maxwell_3d.h 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  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 <unordered_map>
  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/memory_manager.h"
  12. namespace Tegra {
  13. namespace Engines {
  14. class Maxwell3D final {
  15. public:
  16. explicit Maxwell3D(MemoryManager& memory_manager);
  17. ~Maxwell3D() = default;
  18. /// Write the value to the register identified by method.
  19. void WriteReg(u32 method, u32 value, u32 remaining_params);
  20. /// Uploads the code for a GPU macro program associated with the specified entry.
  21. void SubmitMacroCode(u32 entry, std::vector<u32> code);
  22. /// Register structure of the Maxwell3D engine.
  23. /// TODO(Subv): This structure will need to be made bigger as more registers are discovered.
  24. struct Regs {
  25. static constexpr size_t NUM_REGS = 0xE36;
  26. static constexpr size_t NumCBData = 16;
  27. static constexpr size_t NumVertexArrays = 32;
  28. static constexpr size_t MaxShaderProgram = 6;
  29. static constexpr size_t MaxShaderStage = 5;
  30. // Maximum number of const buffers per shader stage.
  31. static constexpr size_t MaxConstBuffers = 16;
  32. enum class QueryMode : u32 {
  33. Write = 0,
  34. Sync = 1,
  35. };
  36. enum class ShaderProgram : u32 {
  37. VertexA = 0,
  38. VertexB = 1,
  39. TesselationControl = 2,
  40. TesselationEval = 3,
  41. Geometry = 4,
  42. Fragment = 5,
  43. };
  44. enum class ShaderStage : u32 {
  45. Vertex = 0,
  46. TesselationControl = 1,
  47. TesselationEval = 2,
  48. Geometry = 3,
  49. Fragment = 4,
  50. };
  51. union {
  52. struct {
  53. INSERT_PADDING_WORDS(0x582);
  54. struct {
  55. u32 code_address_high;
  56. u32 code_address_low;
  57. GPUVAddr CodeAddress() const {
  58. return static_cast<GPUVAddr>(
  59. (static_cast<GPUVAddr>(code_address_high) << 32) | code_address_low);
  60. }
  61. } code_address;
  62. INSERT_PADDING_WORDS(1);
  63. struct {
  64. u32 vertex_end_gl;
  65. u32 vertex_begin_gl;
  66. } draw;
  67. INSERT_PADDING_WORDS(0x139);
  68. struct {
  69. u32 query_address_high;
  70. u32 query_address_low;
  71. u32 query_sequence;
  72. union {
  73. u32 raw;
  74. BitField<0, 2, QueryMode> mode;
  75. BitField<4, 1, u32> fence;
  76. BitField<12, 4, u32> unit;
  77. } query_get;
  78. GPUVAddr QueryAddress() const {
  79. return static_cast<GPUVAddr>(
  80. (static_cast<GPUVAddr>(query_address_high) << 32) | query_address_low);
  81. }
  82. } query;
  83. INSERT_PADDING_WORDS(0x3C);
  84. struct {
  85. union {
  86. BitField<0, 12, u32> stride;
  87. BitField<12, 1, u32> enable;
  88. };
  89. u32 start_high;
  90. u32 start_low;
  91. u32 divisor;
  92. GPUVAddr StartAddress() const {
  93. return static_cast<GPUVAddr>((static_cast<GPUVAddr>(start_high) << 32) |
  94. start_low);
  95. }
  96. } vertex_array[NumVertexArrays];
  97. INSERT_PADDING_WORDS(0x40);
  98. struct {
  99. u32 limit_high;
  100. u32 limit_low;
  101. GPUVAddr LimitAddress() const {
  102. return static_cast<GPUVAddr>((static_cast<GPUVAddr>(limit_high) << 32) |
  103. limit_low);
  104. }
  105. } vertex_array_limit[NumVertexArrays];
  106. struct {
  107. union {
  108. BitField<0, 1, u32> enable;
  109. BitField<4, 4, ShaderProgram> program;
  110. };
  111. u32 start_id;
  112. INSERT_PADDING_WORDS(1);
  113. u32 gpr_alloc;
  114. ShaderStage type;
  115. INSERT_PADDING_WORDS(9);
  116. } shader_config[MaxShaderProgram];
  117. INSERT_PADDING_WORDS(0x8C);
  118. struct {
  119. u32 cb_size;
  120. u32 cb_address_high;
  121. u32 cb_address_low;
  122. u32 cb_pos;
  123. u32 cb_data[NumCBData];
  124. GPUVAddr BufferAddress() const {
  125. return static_cast<GPUVAddr>(
  126. (static_cast<GPUVAddr>(cb_address_high) << 32) | cb_address_low);
  127. }
  128. } const_buffer;
  129. INSERT_PADDING_WORDS(0x10);
  130. struct {
  131. union {
  132. u32 raw_config;
  133. BitField<0, 1, u32> valid;
  134. BitField<4, 5, u32> index;
  135. };
  136. INSERT_PADDING_WORDS(7);
  137. } cb_bind[MaxShaderStage];
  138. INSERT_PADDING_WORDS(0x56);
  139. u32 tex_cb_index;
  140. INSERT_PADDING_WORDS(0x4B3);
  141. };
  142. std::array<u32, NUM_REGS> reg_array;
  143. };
  144. } regs{};
  145. static_assert(sizeof(Regs) == Regs::NUM_REGS * sizeof(u32), "Maxwell3D Regs has wrong size");
  146. struct State {
  147. struct ConstBufferInfo {
  148. GPUVAddr address;
  149. u32 index;
  150. u32 size;
  151. bool enabled;
  152. };
  153. struct ShaderProgramInfo {
  154. Regs::ShaderStage stage;
  155. Regs::ShaderProgram program;
  156. GPUVAddr address;
  157. };
  158. struct ShaderStageInfo {
  159. std::array<ConstBufferInfo, Regs::MaxConstBuffers> const_buffers;
  160. };
  161. std::array<ShaderStageInfo, Regs::MaxShaderStage> shader_stages;
  162. std::array<ShaderProgramInfo, Regs::MaxShaderProgram> shader_programs;
  163. };
  164. State state{};
  165. private:
  166. MemoryManager& memory_manager;
  167. std::unordered_map<u32, std::vector<u32>> uploaded_macros;
  168. /// Macro method that is currently being executed / being fed parameters.
  169. u32 executing_macro = 0;
  170. /// Parameters that have been submitted to the macro call so far.
  171. std::vector<u32> macro_params;
  172. /**
  173. * Call a macro on this engine.
  174. * @param method Method to call
  175. * @param parameters Arguments to the method call
  176. */
  177. void CallMacroMethod(u32 method, const std::vector<u32>& parameters);
  178. /// Handles a write to the QUERY_GET register.
  179. void ProcessQueryGet();
  180. /// Handles a write to the CB_BIND register.
  181. void ProcessCBBind(Regs::ShaderStage stage);
  182. /// Handles a write to the VERTEX_END_GL register, triggering a draw.
  183. void DrawArrays();
  184. /// Method call handlers
  185. void SetShader(const std::vector<u32>& parameters);
  186. struct MethodInfo {
  187. const char* name;
  188. u32 arguments;
  189. void (Maxwell3D::*handler)(const std::vector<u32>& parameters);
  190. };
  191. static const std::unordered_map<u32, MethodInfo> method_handlers;
  192. };
  193. #define ASSERT_REG_POSITION(field_name, position) \
  194. static_assert(offsetof(Maxwell3D::Regs, field_name) == position * 4, \
  195. "Field " #field_name " has invalid position")
  196. ASSERT_REG_POSITION(code_address, 0x582);
  197. ASSERT_REG_POSITION(draw, 0x585);
  198. ASSERT_REG_POSITION(query, 0x6C0);
  199. ASSERT_REG_POSITION(vertex_array[0], 0x700);
  200. ASSERT_REG_POSITION(vertex_array_limit[0], 0x7C0);
  201. ASSERT_REG_POSITION(shader_config[0], 0x800);
  202. ASSERT_REG_POSITION(const_buffer, 0x8E0);
  203. ASSERT_REG_POSITION(cb_bind[0], 0x904);
  204. ASSERT_REG_POSITION(tex_cb_index, 0x982);
  205. #undef ASSERT_REG_POSITION
  206. } // namespace Engines
  207. } // namespace Tegra