maxwell_dma.h 8.3 KB

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