gpu.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. // Copyright 2018 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #pragma once
  5. #include <array>
  6. #include <atomic>
  7. #include <condition_variable>
  8. #include <list>
  9. #include <memory>
  10. #include <mutex>
  11. #include "common/common_types.h"
  12. #include "core/hle/service/nvdrv/nvdata.h"
  13. #include "core/hle/service/nvflinger/buffer_queue.h"
  14. #include "video_core/cdma_pusher.h"
  15. #include "video_core/dma_pusher.h"
  16. #include "video_core/framebuffer_config.h"
  17. #include "video_core/gpu_thread.h"
  18. using CacheAddr = std::uintptr_t;
  19. [[nodiscard]] inline CacheAddr ToCacheAddr(const void* host_ptr) {
  20. return reinterpret_cast<CacheAddr>(host_ptr);
  21. }
  22. [[nodiscard]] inline u8* FromCacheAddr(CacheAddr cache_addr) {
  23. return reinterpret_cast<u8*>(cache_addr);
  24. }
  25. namespace Core {
  26. namespace Frontend {
  27. class EmuWindow;
  28. }
  29. class System;
  30. } // namespace Core
  31. namespace VideoCore {
  32. class RendererBase;
  33. class ShaderNotify;
  34. } // namespace VideoCore
  35. namespace Tegra {
  36. enum class RenderTargetFormat : u32 {
  37. NONE = 0x0,
  38. R32B32G32A32_FLOAT = 0xC0,
  39. R32G32B32A32_SINT = 0xC1,
  40. R32G32B32A32_UINT = 0xC2,
  41. R16G16B16A16_UNORM = 0xC6,
  42. R16G16B16A16_SNORM = 0xC7,
  43. R16G16B16A16_SINT = 0xC8,
  44. R16G16B16A16_UINT = 0xC9,
  45. R16G16B16A16_FLOAT = 0xCA,
  46. R32G32_FLOAT = 0xCB,
  47. R32G32_SINT = 0xCC,
  48. R32G32_UINT = 0xCD,
  49. R16G16B16X16_FLOAT = 0xCE,
  50. B8G8R8A8_UNORM = 0xCF,
  51. B8G8R8A8_SRGB = 0xD0,
  52. A2B10G10R10_UNORM = 0xD1,
  53. A2B10G10R10_UINT = 0xD2,
  54. A8B8G8R8_UNORM = 0xD5,
  55. A8B8G8R8_SRGB = 0xD6,
  56. A8B8G8R8_SNORM = 0xD7,
  57. A8B8G8R8_SINT = 0xD8,
  58. A8B8G8R8_UINT = 0xD9,
  59. R16G16_UNORM = 0xDA,
  60. R16G16_SNORM = 0xDB,
  61. R16G16_SINT = 0xDC,
  62. R16G16_UINT = 0xDD,
  63. R16G16_FLOAT = 0xDE,
  64. B10G11R11_FLOAT = 0xE0,
  65. R32_SINT = 0xE3,
  66. R32_UINT = 0xE4,
  67. R32_FLOAT = 0xE5,
  68. R5G6B5_UNORM = 0xE8,
  69. A1R5G5B5_UNORM = 0xE9,
  70. R8G8_UNORM = 0xEA,
  71. R8G8_SNORM = 0xEB,
  72. R8G8_SINT = 0xEC,
  73. R8G8_UINT = 0xED,
  74. R16_UNORM = 0xEE,
  75. R16_SNORM = 0xEF,
  76. R16_SINT = 0xF0,
  77. R16_UINT = 0xF1,
  78. R16_FLOAT = 0xF2,
  79. R8_UNORM = 0xF3,
  80. R8_SNORM = 0xF4,
  81. R8_SINT = 0xF5,
  82. R8_UINT = 0xF6,
  83. };
  84. enum class DepthFormat : u32 {
  85. D32_FLOAT = 0xA,
  86. D16_UNORM = 0x13,
  87. S8_UINT_Z24_UNORM = 0x14,
  88. D24X8_UNORM = 0x15,
  89. D24S8_UNORM = 0x16,
  90. D24C8_UNORM = 0x18,
  91. D32_FLOAT_S8X24_UINT = 0x19,
  92. };
  93. struct CommandListHeader;
  94. class DebugContext;
  95. namespace Engines {
  96. class Fermi2D;
  97. class Maxwell3D;
  98. class MaxwellDMA;
  99. class KeplerCompute;
  100. class KeplerMemory;
  101. } // namespace Engines
  102. enum class EngineID {
  103. FERMI_TWOD_A = 0x902D, // 2D Engine
  104. MAXWELL_B = 0xB197, // 3D Engine
  105. KEPLER_COMPUTE_B = 0xB1C0,
  106. KEPLER_INLINE_TO_MEMORY_B = 0xA140,
  107. MAXWELL_DMA_COPY_A = 0xB0B5,
  108. };
  109. class MemoryManager;
  110. class GPU final {
  111. public:
  112. struct MethodCall {
  113. u32 method{};
  114. u32 argument{};
  115. u32 subchannel{};
  116. u32 method_count{};
  117. explicit MethodCall(u32 method_, u32 argument_, u32 subchannel_ = 0, u32 method_count_ = 0)
  118. : method(method_), argument(argument_), subchannel(subchannel_),
  119. method_count(method_count_) {}
  120. [[nodiscard]] bool IsLastCall() const {
  121. return method_count <= 1;
  122. }
  123. };
  124. explicit GPU(Core::System& system_, bool is_async_, bool use_nvdec_);
  125. ~GPU();
  126. /// Binds a renderer to the GPU.
  127. void BindRenderer(std::unique_ptr<VideoCore::RendererBase> renderer);
  128. /// Calls a GPU method.
  129. void CallMethod(const MethodCall& method_call);
  130. /// Calls a GPU multivalue method.
  131. void CallMultiMethod(u32 method, u32 subchannel, const u32* base_start, u32 amount,
  132. u32 methods_pending);
  133. /// Flush all current written commands into the host GPU for execution.
  134. void FlushCommands();
  135. /// Synchronizes CPU writes with Host GPU memory.
  136. void SyncGuestHost();
  137. /// Signal the ending of command list.
  138. void OnCommandListEnd();
  139. /// Request a host GPU memory flush from the CPU.
  140. [[nodiscard]] u64 RequestFlush(VAddr addr, std::size_t size);
  141. /// Obtains current flush request fence id.
  142. [[nodiscard]] u64 CurrentFlushRequestFence() const {
  143. return current_flush_fence.load(std::memory_order_relaxed);
  144. }
  145. /// Tick pending requests within the GPU.
  146. void TickWork();
  147. /// Returns a reference to the Maxwell3D GPU engine.
  148. [[nodiscard]] Engines::Maxwell3D& Maxwell3D();
  149. /// Returns a const reference to the Maxwell3D GPU engine.
  150. [[nodiscard]] const Engines::Maxwell3D& Maxwell3D() const;
  151. /// Returns a reference to the KeplerCompute GPU engine.
  152. [[nodiscard]] Engines::KeplerCompute& KeplerCompute();
  153. /// Returns a reference to the KeplerCompute GPU engine.
  154. [[nodiscard]] const Engines::KeplerCompute& KeplerCompute() const;
  155. /// Returns a reference to the GPU memory manager.
  156. [[nodiscard]] Tegra::MemoryManager& MemoryManager();
  157. /// Returns a const reference to the GPU memory manager.
  158. [[nodiscard]] const Tegra::MemoryManager& MemoryManager() const;
  159. /// Returns a reference to the GPU DMA pusher.
  160. [[nodiscard]] Tegra::DmaPusher& DmaPusher();
  161. /// Returns a const reference to the GPU DMA pusher.
  162. [[nodiscard]] const Tegra::DmaPusher& DmaPusher() const;
  163. /// Returns a reference to the GPU CDMA pusher.
  164. [[nodiscard]] Tegra::CDmaPusher& CDmaPusher();
  165. /// Returns a const reference to the GPU CDMA pusher.
  166. [[nodiscard]] const Tegra::CDmaPusher& CDmaPusher() const;
  167. /// Returns a reference to the underlying renderer.
  168. [[nodiscard]] VideoCore::RendererBase& Renderer() {
  169. return *renderer;
  170. }
  171. /// Returns a const reference to the underlying renderer.
  172. [[nodiscard]] const VideoCore::RendererBase& Renderer() const {
  173. return *renderer;
  174. }
  175. /// Returns a reference to the shader notifier.
  176. [[nodiscard]] VideoCore::ShaderNotify& ShaderNotify() {
  177. return *shader_notify;
  178. }
  179. /// Returns a const reference to the shader notifier.
  180. [[nodiscard]] const VideoCore::ShaderNotify& ShaderNotify() const {
  181. return *shader_notify;
  182. }
  183. // Waits for the GPU to finish working
  184. void WaitIdle() const;
  185. /// Allows the CPU/NvFlinger to wait on the GPU before presenting a frame.
  186. void WaitFence(u32 syncpoint_id, u32 value);
  187. void IncrementSyncPoint(u32 syncpoint_id);
  188. [[nodiscard]] u32 GetSyncpointValue(u32 syncpoint_id) const;
  189. void RegisterSyncptInterrupt(u32 syncpoint_id, u32 value);
  190. [[nodiscard]] bool CancelSyncptInterrupt(u32 syncpoint_id, u32 value);
  191. [[nodiscard]] u64 GetTicks() const;
  192. [[nodiscard]] std::unique_lock<std::mutex> LockSync() {
  193. return std::unique_lock{sync_mutex};
  194. }
  195. [[nodiscard]] bool IsAsync() const {
  196. return is_async;
  197. }
  198. [[nodiscard]] bool UseNvdec() const {
  199. return use_nvdec;
  200. }
  201. enum class FenceOperation : u32 {
  202. Acquire = 0,
  203. Increment = 1,
  204. };
  205. union FenceAction {
  206. u32 raw;
  207. BitField<0, 1, FenceOperation> op;
  208. BitField<8, 24, u32> syncpoint_id;
  209. [[nodiscard]] static CommandHeader Build(FenceOperation op, u32 syncpoint_id) {
  210. FenceAction result{};
  211. result.op.Assign(op);
  212. result.syncpoint_id.Assign(syncpoint_id);
  213. return {result.raw};
  214. }
  215. };
  216. struct Regs {
  217. static constexpr size_t NUM_REGS = 0x40;
  218. union {
  219. struct {
  220. INSERT_UNION_PADDING_WORDS(0x4);
  221. struct {
  222. u32 address_high;
  223. u32 address_low;
  224. [[nodiscard]] GPUVAddr SemaphoreAddress() const {
  225. return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
  226. address_low);
  227. }
  228. } semaphore_address;
  229. u32 semaphore_sequence;
  230. u32 semaphore_trigger;
  231. INSERT_UNION_PADDING_WORDS(0xC);
  232. // The pusher and the puller share the reference counter, the pusher only has read
  233. // access
  234. u32 reference_count;
  235. INSERT_UNION_PADDING_WORDS(0x5);
  236. u32 semaphore_acquire;
  237. u32 semaphore_release;
  238. u32 fence_value;
  239. FenceAction fence_action;
  240. INSERT_UNION_PADDING_WORDS(0xE2);
  241. // Puller state
  242. u32 acquire_mode;
  243. u32 acquire_source;
  244. u32 acquire_active;
  245. u32 acquire_timeout;
  246. u32 acquire_value;
  247. };
  248. std::array<u32, NUM_REGS> reg_array;
  249. };
  250. } regs{};
  251. /// Performs any additional setup necessary in order to begin GPU emulation.
  252. /// This can be used to launch any necessary threads and register any necessary
  253. /// core timing events.
  254. void Start();
  255. /// Obtain the CPU Context
  256. void ObtainContext();
  257. /// Release the CPU Context
  258. void ReleaseContext();
  259. /// Push GPU command entries to be processed
  260. void PushGPUEntries(Tegra::CommandList&& entries);
  261. /// Push GPU command buffer entries to be processed
  262. void PushCommandBuffer(Tegra::ChCommandHeaderList& entries);
  263. /// Swap buffers (render frame)
  264. void SwapBuffers(const Tegra::FramebufferConfig* framebuffer);
  265. /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory
  266. void FlushRegion(VAddr addr, u64 size);
  267. /// Notify rasterizer that any caches of the specified region should be invalidated
  268. void InvalidateRegion(VAddr addr, u64 size);
  269. /// Notify rasterizer that any caches of the specified region should be flushed and invalidated
  270. void FlushAndInvalidateRegion(VAddr addr, u64 size);
  271. protected:
  272. void TriggerCpuInterrupt(u32 syncpoint_id, u32 value) const;
  273. private:
  274. void ProcessBindMethod(const MethodCall& method_call);
  275. void ProcessFenceActionMethod();
  276. void ProcessWaitForInterruptMethod();
  277. void ProcessSemaphoreTriggerMethod();
  278. void ProcessSemaphoreRelease();
  279. void ProcessSemaphoreAcquire();
  280. /// Calls a GPU puller method.
  281. void CallPullerMethod(const MethodCall& method_call);
  282. /// Calls a GPU engine method.
  283. void CallEngineMethod(const MethodCall& method_call);
  284. /// Calls a GPU engine multivalue method.
  285. void CallEngineMultiMethod(u32 method, u32 subchannel, const u32* base_start, u32 amount,
  286. u32 methods_pending);
  287. /// Determines where the method should be executed.
  288. [[nodiscard]] bool ExecuteMethodOnEngine(u32 method);
  289. protected:
  290. Core::System& system;
  291. std::unique_ptr<Tegra::MemoryManager> memory_manager;
  292. std::unique_ptr<Tegra::DmaPusher> dma_pusher;
  293. std::unique_ptr<Tegra::CDmaPusher> cdma_pusher;
  294. std::unique_ptr<VideoCore::RendererBase> renderer;
  295. const bool use_nvdec;
  296. private:
  297. /// Mapping of command subchannels to their bound engine ids
  298. std::array<EngineID, 8> bound_engines = {};
  299. /// 3D engine
  300. std::unique_ptr<Engines::Maxwell3D> maxwell_3d;
  301. /// 2D engine
  302. std::unique_ptr<Engines::Fermi2D> fermi_2d;
  303. /// Compute engine
  304. std::unique_ptr<Engines::KeplerCompute> kepler_compute;
  305. /// DMA engine
  306. std::unique_ptr<Engines::MaxwellDMA> maxwell_dma;
  307. /// Inline memory engine
  308. std::unique_ptr<Engines::KeplerMemory> kepler_memory;
  309. /// Shader build notifier
  310. std::unique_ptr<VideoCore::ShaderNotify> shader_notify;
  311. std::array<std::atomic<u32>, Service::Nvidia::MaxSyncPoints> syncpoints{};
  312. std::array<std::list<u32>, Service::Nvidia::MaxSyncPoints> syncpt_interrupts;
  313. std::mutex sync_mutex;
  314. std::mutex device_mutex;
  315. std::condition_variable sync_cv;
  316. struct FlushRequest {
  317. explicit FlushRequest(u64 fence_, VAddr addr_, std::size_t size_)
  318. : fence{fence_}, addr{addr_}, size{size_} {}
  319. u64 fence;
  320. VAddr addr;
  321. std::size_t size;
  322. };
  323. std::list<FlushRequest> flush_requests;
  324. std::atomic<u64> current_flush_fence{};
  325. u64 last_flush_fence{};
  326. std::mutex flush_request_mutex;
  327. VideoCommon::GPUThread::ThreadManager gpu_thread;
  328. std::unique_ptr<Core::Frontend::GraphicsContext> cpu_context;
  329. const bool is_async;
  330. };
  331. #define ASSERT_REG_POSITION(field_name, position) \
  332. static_assert(offsetof(GPU::Regs, field_name) == position * 4, \
  333. "Field " #field_name " has invalid position")
  334. ASSERT_REG_POSITION(semaphore_address, 0x4);
  335. ASSERT_REG_POSITION(semaphore_sequence, 0x6);
  336. ASSERT_REG_POSITION(semaphore_trigger, 0x7);
  337. ASSERT_REG_POSITION(reference_count, 0x14);
  338. ASSERT_REG_POSITION(semaphore_acquire, 0x1A);
  339. ASSERT_REG_POSITION(semaphore_release, 0x1B);
  340. ASSERT_REG_POSITION(fence_value, 0x1C);
  341. ASSERT_REG_POSITION(fence_action, 0x1D);
  342. ASSERT_REG_POSITION(acquire_mode, 0x100);
  343. ASSERT_REG_POSITION(acquire_source, 0x101);
  344. ASSERT_REG_POSITION(acquire_active, 0x102);
  345. ASSERT_REG_POSITION(acquire_timeout, 0x103);
  346. ASSERT_REG_POSITION(acquire_value, 0x104);
  347. #undef ASSERT_REG_POSITION
  348. } // namespace Tegra