maxwell_dma.h 8.5 KB

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