maxwell_dma.h 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #pragma once
  4. #include <array>
  5. #include <cstddef>
  6. #include <vector>
  7. #include "common/bit_field.h"
  8. #include "common/common_types.h"
  9. #include "common/scratch_buffer.h"
  10. #include "video_core/engines/engine_interface.h"
  11. namespace Core {
  12. class System;
  13. }
  14. namespace Tegra {
  15. class MemoryManager;
  16. }
  17. namespace VideoCore {
  18. class RasterizerInterface;
  19. }
  20. namespace Tegra {
  21. namespace DMA {
  22. union Origin {
  23. BitField<0, 16, u32> x;
  24. BitField<16, 16, u32> y;
  25. };
  26. static_assert(sizeof(Origin) == 4);
  27. struct ImageCopy {
  28. u32 length_x{};
  29. u32 length_y{};
  30. };
  31. union BlockSize {
  32. BitField<0, 4, u32> width;
  33. BitField<4, 4, u32> height;
  34. BitField<8, 4, u32> depth;
  35. BitField<12, 4, u32> gob_height;
  36. };
  37. static_assert(sizeof(BlockSize) == 4);
  38. struct Parameters {
  39. BlockSize block_size;
  40. u32 width;
  41. u32 height;
  42. u32 depth;
  43. u32 layer;
  44. Origin origin;
  45. };
  46. static_assert(sizeof(Parameters) == 24);
  47. struct ImageOperand {
  48. u32 bytes_per_pixel;
  49. Parameters params;
  50. GPUVAddr address;
  51. };
  52. struct BufferOperand {
  53. u32 pitch;
  54. u32 width;
  55. u32 height;
  56. GPUVAddr address;
  57. };
  58. } // namespace DMA
  59. } // namespace Tegra
  60. namespace Tegra::Engines {
  61. class AccelerateDMAInterface {
  62. public:
  63. /// Write the value to the register identified by method.
  64. virtual bool BufferCopy(GPUVAddr src_address, GPUVAddr dest_address, u64 amount) = 0;
  65. virtual bool BufferClear(GPUVAddr src_address, u64 amount, u32 value) = 0;
  66. virtual bool ImageToBuffer(const DMA::ImageCopy& copy_info, const DMA::ImageOperand& src,
  67. const DMA::BufferOperand& dst) = 0;
  68. virtual bool BufferToImage(const DMA::ImageCopy& copy_info, const DMA::BufferOperand& src,
  69. const DMA::ImageOperand& dst) = 0;
  70. };
  71. /**
  72. * This engine is known as gk104_copy. Documentation can be found in:
  73. * https://github.com/NVIDIA/open-gpu-doc/blob/master/classes/dma-copy/clb0b5.h
  74. * https://github.com/envytools/envytools/blob/master/rnndb/fifo/gk104_copy.xml
  75. */
  76. class MaxwellDMA final : public EngineInterface {
  77. public:
  78. struct PackedGPUVAddr {
  79. u32 upper;
  80. u32 lower;
  81. constexpr operator GPUVAddr() const noexcept {
  82. return (static_cast<GPUVAddr>(upper & 0xff) << 32) | lower;
  83. }
  84. };
  85. struct Semaphore {
  86. PackedGPUVAddr address;
  87. u32 payload;
  88. };
  89. static_assert(sizeof(Semaphore) == 12);
  90. struct RenderEnable {
  91. enum class Mode : u32 {
  92. // Note: This uses Pascal case in order to avoid the identifiers
  93. // FALSE and TRUE, which are reserved on Darwin.
  94. False = 0,
  95. True = 1,
  96. Conditional = 2,
  97. RenderIfEqual = 3,
  98. RenderIfNotEqual = 4,
  99. };
  100. PackedGPUVAddr address;
  101. BitField<0, 3, Mode> mode;
  102. };
  103. static_assert(sizeof(RenderEnable) == 12);
  104. enum class PhysModeTarget : u32 {
  105. LOCAL_FB = 0,
  106. COHERENT_SYSMEM = 1,
  107. NONCOHERENT_SYSMEM = 2,
  108. };
  109. using PhysMode = BitField<0, 2, PhysModeTarget>;
  110. union LaunchDMA {
  111. enum class DataTransferType : u32 {
  112. NONE = 0,
  113. PIPELINED = 1,
  114. NON_PIPELINED = 2,
  115. };
  116. enum class SemaphoreType : u32 {
  117. NONE = 0,
  118. RELEASE_ONE_WORD_SEMAPHORE = 1,
  119. RELEASE_FOUR_WORD_SEMAPHORE = 2,
  120. };
  121. enum class InterruptType : u32 {
  122. NONE = 0,
  123. BLOCKING = 1,
  124. NON_BLOCKING = 2,
  125. };
  126. enum class MemoryLayout : u32 {
  127. BLOCKLINEAR = 0,
  128. PITCH = 1,
  129. };
  130. enum class Type : u32 {
  131. VIRTUAL = 0,
  132. PHYSICAL = 1,
  133. };
  134. enum class SemaphoreReduction : u32 {
  135. IMIN = 0,
  136. IMAX = 1,
  137. IXOR = 2,
  138. IAND = 3,
  139. IOR = 4,
  140. IADD = 5,
  141. INC = 6,
  142. DEC = 7,
  143. FADD = 0xA,
  144. };
  145. enum class SemaphoreReductionSign : u32 {
  146. SIGNED = 0,
  147. UNSIGNED = 1,
  148. };
  149. enum class BypassL2 : u32 {
  150. USE_PTE_SETTING = 0,
  151. FORCE_VOLATILE = 1,
  152. };
  153. BitField<0, 2, DataTransferType> data_transfer_type;
  154. BitField<2, 1, u32> flush_enable;
  155. BitField<3, 2, SemaphoreType> semaphore_type;
  156. BitField<5, 2, InterruptType> interrupt_type;
  157. BitField<7, 1, MemoryLayout> src_memory_layout;
  158. BitField<8, 1, MemoryLayout> dst_memory_layout;
  159. BitField<9, 1, u32> multi_line_enable;
  160. BitField<10, 1, u32> remap_enable;
  161. BitField<11, 1, u32> rmwdisable;
  162. BitField<12, 1, Type> src_type;
  163. BitField<13, 1, Type> dst_type;
  164. BitField<14, 4, SemaphoreReduction> semaphore_reduction;
  165. BitField<18, 1, SemaphoreReductionSign> semaphore_reduction_sign;
  166. BitField<19, 1, u32> reduction_enable;
  167. BitField<20, 1, BypassL2> bypass_l2;
  168. };
  169. static_assert(sizeof(LaunchDMA) == 4);
  170. struct RemapConst {
  171. enum class Swizzle : u32 {
  172. SRC_X = 0,
  173. SRC_Y = 1,
  174. SRC_Z = 2,
  175. SRC_W = 3,
  176. CONST_A = 4,
  177. CONST_B = 5,
  178. NO_WRITE = 6,
  179. };
  180. u32 remap_consta_value;
  181. u32 remap_constb_value;
  182. union {
  183. BitField<0, 12, u32> dst_components_raw;
  184. BitField<0, 3, Swizzle> dst_x;
  185. BitField<4, 3, Swizzle> dst_y;
  186. BitField<8, 3, Swizzle> dst_z;
  187. BitField<12, 3, Swizzle> dst_w;
  188. BitField<16, 2, u32> component_size_minus_one;
  189. BitField<20, 2, u32> num_src_components_minus_one;
  190. BitField<24, 2, u32> num_dst_components_minus_one;
  191. };
  192. Swizzle GetComponent(size_t i) const {
  193. const u32 raw = dst_components_raw;
  194. return static_cast<Swizzle>((raw >> (i * 3)) & 0x7);
  195. }
  196. };
  197. static_assert(sizeof(RemapConst) == 12);
  198. void BindRasterizer(VideoCore::RasterizerInterface* rasterizer);
  199. explicit MaxwellDMA(Core::System& system_, MemoryManager& memory_manager_);
  200. ~MaxwellDMA() override;
  201. /// Write the value to the register identified by method.
  202. void CallMethod(u32 method, u32 method_argument, bool is_last_call) override;
  203. /// Write multiple values to the register identified by method.
  204. void CallMultiMethod(u32 method, const u32* base_start, u32 amount,
  205. u32 methods_pending) override;
  206. private:
  207. /// Performs the copy from the source buffer to the destination buffer as configured in the
  208. /// registers.
  209. void Launch();
  210. void CopyBlockLinearToPitch();
  211. void CopyPitchToBlockLinear();
  212. void CopyBlockLinearToBlockLinear();
  213. void ReleaseSemaphore();
  214. void ConsumeSinkImpl() override;
  215. Core::System& system;
  216. MemoryManager& memory_manager;
  217. VideoCore::RasterizerInterface* rasterizer = nullptr;
  218. Common::ScratchBuffer<u8> read_buffer;
  219. Common::ScratchBuffer<u8> write_buffer;
  220. Common::ScratchBuffer<u8> intermediate_buffer;
  221. static constexpr std::size_t NUM_REGS = 0x800;
  222. struct Regs {
  223. union {
  224. struct {
  225. INSERT_PADDING_BYTES_NOINIT(0x100);
  226. u32 nop;
  227. INSERT_PADDING_BYTES_NOINIT(0x3C);
  228. u32 pm_trigger;
  229. INSERT_PADDING_BYTES_NOINIT(0xFC);
  230. Semaphore semaphore;
  231. INSERT_PADDING_BYTES_NOINIT(0x8);
  232. RenderEnable render_enable;
  233. PhysMode src_phys_mode;
  234. PhysMode dst_phys_mode;
  235. INSERT_PADDING_BYTES_NOINIT(0x98);
  236. LaunchDMA launch_dma;
  237. INSERT_PADDING_BYTES_NOINIT(0xFC);
  238. PackedGPUVAddr offset_in;
  239. PackedGPUVAddr offset_out;
  240. s32 pitch_in;
  241. s32 pitch_out;
  242. u32 line_length_in;
  243. u32 line_count;
  244. INSERT_PADDING_BYTES_NOINIT(0x2E0);
  245. RemapConst remap_const;
  246. DMA::Parameters dst_params;
  247. INSERT_PADDING_BYTES_NOINIT(0x4);
  248. DMA::Parameters src_params;
  249. INSERT_PADDING_BYTES_NOINIT(0x9D4);
  250. u32 pm_trigger_end;
  251. INSERT_PADDING_BYTES_NOINIT(0xEE8);
  252. };
  253. std::array<u32, NUM_REGS> reg_array;
  254. };
  255. } regs{};
  256. static_assert(sizeof(Regs) == NUM_REGS * 4);
  257. #define ASSERT_REG_POSITION(field_name, position) \
  258. static_assert(offsetof(MaxwellDMA::Regs, field_name) == position, \
  259. "Field " #field_name " has invalid position")
  260. ASSERT_REG_POSITION(semaphore, 0x240);
  261. ASSERT_REG_POSITION(render_enable, 0x254);
  262. ASSERT_REG_POSITION(src_phys_mode, 0x260);
  263. ASSERT_REG_POSITION(launch_dma, 0x300);
  264. ASSERT_REG_POSITION(offset_in, 0x400);
  265. ASSERT_REG_POSITION(offset_out, 0x408);
  266. ASSERT_REG_POSITION(pitch_in, 0x410);
  267. ASSERT_REG_POSITION(pitch_out, 0x414);
  268. ASSERT_REG_POSITION(line_length_in, 0x418);
  269. ASSERT_REG_POSITION(line_count, 0x41C);
  270. ASSERT_REG_POSITION(remap_const, 0x700);
  271. ASSERT_REG_POSITION(dst_params, 0x70C);
  272. ASSERT_REG_POSITION(src_params, 0x728);
  273. ASSERT_REG_POSITION(pm_trigger_end, 0x1114);
  274. #undef ASSERT_REG_POSITION
  275. };
  276. } // namespace Tegra::Engines