maxwell_dma.h 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  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 <cstddef>
  7. #include <vector>
  8. #include "common/bit_field.h"
  9. #include "common/common_funcs.h"
  10. #include "common/common_types.h"
  11. #include "video_core/engines/engine_interface.h"
  12. #include "video_core/gpu.h"
  13. namespace Core {
  14. class System;
  15. }
  16. namespace Tegra {
  17. class MemoryManager;
  18. }
  19. namespace Tegra::Engines {
  20. /**
  21. * This engine is known as gk104_copy. Documentation can be found in:
  22. * https://github.com/NVIDIA/open-gpu-doc/blob/master/classes/dma-copy/clb0b5.h
  23. * https://github.com/envytools/envytools/blob/master/rnndb/fifo/gk104_copy.xml
  24. */
  25. class MaxwellDMA final : public EngineInterface {
  26. public:
  27. struct PackedGPUVAddr {
  28. u32 upper;
  29. u32 lower;
  30. constexpr operator GPUVAddr() const noexcept {
  31. return (static_cast<GPUVAddr>(upper & 0xff) << 32) | lower;
  32. }
  33. };
  34. union BlockSize {
  35. BitField<0, 4, u32> width;
  36. BitField<4, 4, u32> height;
  37. BitField<8, 4, u32> depth;
  38. BitField<12, 4, u32> gob_height;
  39. };
  40. static_assert(sizeof(BlockSize) == 4);
  41. union Origin {
  42. BitField<0, 16, u32> x;
  43. BitField<16, 16, u32> y;
  44. };
  45. static_assert(sizeof(Origin) == 4);
  46. struct Parameters {
  47. BlockSize block_size;
  48. u32 width;
  49. u32 height;
  50. u32 depth;
  51. u32 layer;
  52. Origin origin;
  53. };
  54. static_assert(sizeof(Parameters) == 24);
  55. struct Semaphore {
  56. PackedGPUVAddr address;
  57. u32 payload;
  58. };
  59. static_assert(sizeof(Semaphore) == 12);
  60. struct RenderEnable {
  61. enum class Mode : u32 {
  62. FALSE = 0,
  63. TRUE = 1,
  64. CONDITIONAL = 2,
  65. RENDER_IF_EQUAL = 3,
  66. RENDER_IF_NOT_EQUAL = 4,
  67. };
  68. PackedGPUVAddr address;
  69. BitField<0, 3, Mode> mode;
  70. };
  71. static_assert(sizeof(RenderEnable) == 12);
  72. enum class PhysModeTarget : u32 {
  73. LOCAL_FB = 0,
  74. COHERENT_SYSMEM = 1,
  75. NONCOHERENT_SYSMEM = 2,
  76. };
  77. using PhysMode = BitField<0, 2, PhysModeTarget>;
  78. union LaunchDMA {
  79. enum class DataTransferType : u32 {
  80. NONE = 0,
  81. PIPELINED = 1,
  82. NON_PIPELINED = 2,
  83. };
  84. enum class SemaphoreType : u32 {
  85. NONE = 0,
  86. RELEASE_ONE_WORD_SEMAPHORE = 1,
  87. RELEASE_FOUR_WORD_SEMAPHORE = 2,
  88. };
  89. enum class InterruptType : u32 {
  90. NONE = 0,
  91. BLOCKING = 1,
  92. NON_BLOCKING = 2,
  93. };
  94. enum class MemoryLayout : u32 {
  95. BLOCKLINEAR = 0,
  96. PITCH = 1,
  97. };
  98. enum class Type : u32 {
  99. VIRTUAL = 0,
  100. PHYSICAL = 1,
  101. };
  102. enum class SemaphoreReduction : u32 {
  103. IMIN = 0,
  104. IMAX = 1,
  105. IXOR = 2,
  106. IAND = 3,
  107. IOR = 4,
  108. IADD = 5,
  109. INC = 6,
  110. DEC = 7,
  111. FADD = 0xA,
  112. };
  113. enum class SemaphoreReductionSign : u32 {
  114. SIGNED = 0,
  115. UNSIGNED = 1,
  116. };
  117. enum class BypassL2 : u32 {
  118. USE_PTE_SETTING = 0,
  119. FORCE_VOLATILE = 1,
  120. };
  121. BitField<0, 2, DataTransferType> data_transfer_type;
  122. BitField<2, 1, u32> flush_enable;
  123. BitField<3, 2, SemaphoreType> semaphore_type;
  124. BitField<5, 2, InterruptType> interrupt_type;
  125. BitField<7, 1, MemoryLayout> src_memory_layout;
  126. BitField<8, 1, MemoryLayout> dst_memory_layout;
  127. BitField<9, 1, u32> multi_line_enable;
  128. BitField<10, 1, u32> remap_enable;
  129. BitField<11, 1, u32> rmwdisable;
  130. BitField<12, 1, Type> src_type;
  131. BitField<13, 1, Type> dst_type;
  132. BitField<14, 4, SemaphoreReduction> semaphore_reduction;
  133. BitField<18, 1, SemaphoreReductionSign> semaphore_reduction_sign;
  134. BitField<19, 1, u32> reduction_enable;
  135. BitField<20, 1, BypassL2> bypass_l2;
  136. };
  137. static_assert(sizeof(LaunchDMA) == 4);
  138. struct RemapConst {
  139. enum Swizzle : u32 {
  140. SRC_X = 0,
  141. SRC_Y = 1,
  142. SRC_Z = 2,
  143. SRC_W = 3,
  144. CONST_A = 4,
  145. CONST_B = 5,
  146. NO_WRITE = 6,
  147. };
  148. PackedGPUVAddr address;
  149. union {
  150. BitField<0, 3, Swizzle> dst_x;
  151. BitField<4, 3, Swizzle> dst_y;
  152. BitField<8, 3, Swizzle> dst_z;
  153. BitField<12, 3, Swizzle> dst_w;
  154. BitField<16, 2, u32> component_size_minus_one;
  155. BitField<20, 2, u32> num_src_components_minus_one;
  156. BitField<24, 2, u32> num_dst_components_minus_one;
  157. };
  158. };
  159. static_assert(sizeof(RemapConst) == 12);
  160. explicit MaxwellDMA(Core::System& system, MemoryManager& memory_manager);
  161. ~MaxwellDMA() = default;
  162. /// Write the value to the register identified by method.
  163. void CallMethod(u32 method, u32 method_argument, bool is_last_call) override;
  164. /// Write multiple values to the register identified by method.
  165. void CallMultiMethod(u32 method, const u32* base_start, u32 amount,
  166. u32 methods_pending) override;
  167. private:
  168. /// Performs the copy from the source buffer to the destination buffer as configured in the
  169. /// registers.
  170. void Launch();
  171. void CopyPitchToPitch();
  172. void CopyBlockLinearToPitch();
  173. void CopyPitchToBlockLinear();
  174. void FastCopyBlockLinearToPitch();
  175. Core::System& system;
  176. MemoryManager& memory_manager;
  177. std::vector<u8> read_buffer;
  178. std::vector<u8> write_buffer;
  179. static constexpr std::size_t NUM_REGS = 0x800;
  180. struct Regs {
  181. union {
  182. struct {
  183. u32 reserved[0x40];
  184. u32 nop;
  185. u32 reserved01[0xf];
  186. u32 pm_trigger;
  187. u32 reserved02[0x3f];
  188. Semaphore semaphore;
  189. u32 reserved03[0x2];
  190. RenderEnable render_enable;
  191. PhysMode src_phys_mode;
  192. PhysMode dst_phys_mode;
  193. u32 reserved04[0x26];
  194. LaunchDMA launch_dma;
  195. u32 reserved05[0x3f];
  196. PackedGPUVAddr offset_in;
  197. PackedGPUVAddr offset_out;
  198. u32 pitch_in;
  199. u32 pitch_out;
  200. u32 line_length_in;
  201. u32 line_count;
  202. u32 reserved06[0xb8];
  203. RemapConst remap_const;
  204. Parameters dst_params;
  205. u32 reserved07[0x1];
  206. Parameters src_params;
  207. u32 reserved08[0x275];
  208. u32 pm_trigger_end;
  209. u32 reserved09[0x3ba];
  210. };
  211. std::array<u32, NUM_REGS> reg_array;
  212. };
  213. } regs{};
  214. #define ASSERT_REG_POSITION(field_name, position) \
  215. static_assert(offsetof(MaxwellDMA::Regs, field_name) == position * 4, \
  216. "Field " #field_name " has invalid position")
  217. ASSERT_REG_POSITION(launch_dma, 0xC0);
  218. ASSERT_REG_POSITION(offset_in, 0x100);
  219. ASSERT_REG_POSITION(offset_out, 0x102);
  220. ASSERT_REG_POSITION(pitch_in, 0x104);
  221. ASSERT_REG_POSITION(pitch_out, 0x105);
  222. ASSERT_REG_POSITION(line_length_in, 0x106);
  223. ASSERT_REG_POSITION(line_count, 0x107);
  224. ASSERT_REG_POSITION(remap_const, 0x1C0);
  225. ASSERT_REG_POSITION(dst_params, 0x1C3);
  226. ASSERT_REG_POSITION(src_params, 0x1CA);
  227. #undef ASSERT_REG_POSITION
  228. };
  229. } // namespace Tegra::Engines