maxwell_dma.h 9.4 KB

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