gpu.h 13 KB

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