pica.h 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. // Copyright 2014 Citra 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 <string>
  8. #ifndef _MSC_VER
  9. #include <type_traits> // for std::enable_if
  10. #endif
  11. #include "common/assert.h"
  12. #include "common/bit_field.h"
  13. #include "common/common_funcs.h"
  14. #include "common/common_types.h"
  15. #include "common/logging/log.h"
  16. #include "common/vector_math.h"
  17. #include "video_core/regs_framebuffer.h"
  18. #include "video_core/regs_lighting.h"
  19. #include "video_core/regs_pipeline.h"
  20. #include "video_core/regs_rasterizer.h"
  21. #include "video_core/regs_texturing.h"
  22. namespace Pica {
  23. // Returns index corresponding to the Regs member labeled by field_name
  24. // TODO: Due to Visual studio bug 209229, offsetof does not return constant expressions
  25. // when used with array elements (e.g. PICA_REG_INDEX(vs_uniform_setup.set_value[1])).
  26. // For details cf.
  27. // https://connect.microsoft.com/VisualStudio/feedback/details/209229/offsetof-does-not-produce-a-constant-expression-for-array-members
  28. // Hopefully, this will be fixed sometime in the future.
  29. // For lack of better alternatives, we currently hardcode the offsets when constant
  30. // expressions are needed via PICA_REG_INDEX_WORKAROUND (on sane compilers, static_asserts
  31. // will then make sure the offsets indeed match the automatically calculated ones).
  32. #define PICA_REG_INDEX(field_name) (offsetof(Pica::Regs, field_name) / sizeof(u32))
  33. #if defined(_MSC_VER)
  34. #define PICA_REG_INDEX_WORKAROUND(field_name, backup_workaround_index) (backup_workaround_index)
  35. #else
  36. // NOTE: Yeah, hacking in a static_assert here just to workaround the lacking MSVC compiler
  37. // really is this annoying. This macro just forwards its first argument to PICA_REG_INDEX
  38. // and then performs a (no-op) cast to size_t iff the second argument matches the expected
  39. // field offset. Otherwise, the compiler will fail to compile this code.
  40. #define PICA_REG_INDEX_WORKAROUND(field_name, backup_workaround_index) \
  41. ((typename std::enable_if<backup_workaround_index == PICA_REG_INDEX(field_name), \
  42. size_t>::type)PICA_REG_INDEX(field_name))
  43. #endif // _MSC_VER
  44. struct Regs {
  45. INSERT_PADDING_WORDS(0x10);
  46. u32 trigger_irq;
  47. INSERT_PADDING_WORDS(0x2f);
  48. RasterizerRegs rasterizer;
  49. TexturingRegs texturing;
  50. FramebufferRegs framebuffer;
  51. LightingRegs lighting;
  52. PipelineRegs pipeline;
  53. struct ShaderConfig {
  54. BitField<0, 16, u32> bool_uniforms;
  55. union {
  56. BitField<0, 8, u32> x;
  57. BitField<8, 8, u32> y;
  58. BitField<16, 8, u32> z;
  59. BitField<24, 8, u32> w;
  60. } int_uniforms[4];
  61. INSERT_PADDING_WORDS(0x4);
  62. union {
  63. // Number of input attributes to shader unit - 1
  64. BitField<0, 4, u32> max_input_attribute_index;
  65. };
  66. // Offset to shader program entry point (in words)
  67. BitField<0, 16, u32> main_offset;
  68. /// Maps input attributes to registers. 4-bits per attribute, specifying a register index
  69. u32 input_attribute_to_register_map_low;
  70. u32 input_attribute_to_register_map_high;
  71. unsigned int GetRegisterForAttribute(unsigned int attribute_index) const {
  72. u64 map = ((u64)input_attribute_to_register_map_high << 32) |
  73. (u64)input_attribute_to_register_map_low;
  74. return (map >> (attribute_index * 4)) & 0b1111;
  75. }
  76. BitField<0, 16, u32> output_mask;
  77. // 0x28E, CODETRANSFER_END
  78. INSERT_PADDING_WORDS(0x2);
  79. struct {
  80. enum Format : u32 {
  81. FLOAT24 = 0,
  82. FLOAT32 = 1,
  83. };
  84. bool IsFloat32() const {
  85. return format == FLOAT32;
  86. }
  87. union {
  88. // Index of the next uniform to write to
  89. // TODO: ctrulib uses 8 bits for this, however that seems to yield lots of invalid
  90. // indices
  91. // TODO: Maybe the uppermost index is for the geometry shader? Investigate!
  92. BitField<0, 7, u32> index;
  93. BitField<31, 1, Format> format;
  94. };
  95. // Writing to these registers sets the current uniform.
  96. u32 set_value[8];
  97. } uniform_setup;
  98. INSERT_PADDING_WORDS(0x2);
  99. struct {
  100. // Offset of the next instruction to write code to.
  101. // Incremented with each instruction write.
  102. u32 offset;
  103. // Writing to these registers sets the "current" word in the shader program.
  104. u32 set_word[8];
  105. } program;
  106. INSERT_PADDING_WORDS(0x1);
  107. // This register group is used to load an internal table of swizzling patterns,
  108. // which are indexed by each shader instruction to specify vector component swizzling.
  109. struct {
  110. // Offset of the next swizzle pattern to write code to.
  111. // Incremented with each instruction write.
  112. u32 offset;
  113. // Writing to these registers sets the current swizzle pattern in the table.
  114. u32 set_word[8];
  115. } swizzle_patterns;
  116. INSERT_PADDING_WORDS(0x2);
  117. };
  118. ShaderConfig gs;
  119. ShaderConfig vs;
  120. INSERT_PADDING_WORDS(0x20);
  121. // Map register indices to names readable by humans
  122. // Used for debugging purposes, so performance is not an issue here
  123. static std::string GetCommandName(int index);
  124. static constexpr size_t NumIds() {
  125. return sizeof(Regs) / sizeof(u32);
  126. }
  127. const u32& operator[](int index) const {
  128. const u32* content = reinterpret_cast<const u32*>(this);
  129. return content[index];
  130. }
  131. u32& operator[](int index) {
  132. u32* content = reinterpret_cast<u32*>(this);
  133. return content[index];
  134. }
  135. private:
  136. /*
  137. * Most physical addresses which Pica registers refer to are 8-byte aligned.
  138. * This function should be used to get the address from a raw register value.
  139. */
  140. static inline u32 DecodeAddressRegister(u32 register_value) {
  141. return register_value * 8;
  142. }
  143. };
  144. // TODO: MSVC does not support using offsetof() on non-static data members even though this
  145. // is technically allowed since C++11. This macro should be enabled once MSVC adds
  146. // support for that.
  147. #ifndef _MSC_VER
  148. #define ASSERT_REG_POSITION(field_name, position) \
  149. static_assert(offsetof(Regs, field_name) == position * 4, \
  150. "Field " #field_name " has invalid position")
  151. ASSERT_REG_POSITION(trigger_irq, 0x10);
  152. ASSERT_REG_POSITION(rasterizer, 0x40);
  153. ASSERT_REG_POSITION(rasterizer.cull_mode, 0x40);
  154. ASSERT_REG_POSITION(rasterizer.viewport_size_x, 0x41);
  155. ASSERT_REG_POSITION(rasterizer.viewport_size_y, 0x43);
  156. ASSERT_REG_POSITION(rasterizer.viewport_depth_range, 0x4d);
  157. ASSERT_REG_POSITION(rasterizer.viewport_depth_near_plane, 0x4e);
  158. ASSERT_REG_POSITION(rasterizer.vs_output_attributes[0], 0x50);
  159. ASSERT_REG_POSITION(rasterizer.vs_output_attributes[1], 0x51);
  160. ASSERT_REG_POSITION(rasterizer.scissor_test, 0x65);
  161. ASSERT_REG_POSITION(rasterizer.viewport_corner, 0x68);
  162. ASSERT_REG_POSITION(rasterizer.depthmap_enable, 0x6D);
  163. ASSERT_REG_POSITION(texturing, 0x80);
  164. ASSERT_REG_POSITION(texturing.texture0_enable, 0x80);
  165. ASSERT_REG_POSITION(texturing.texture0, 0x81);
  166. ASSERT_REG_POSITION(texturing.texture0_format, 0x8e);
  167. ASSERT_REG_POSITION(texturing.fragment_lighting_enable, 0x8f);
  168. ASSERT_REG_POSITION(texturing.texture1, 0x91);
  169. ASSERT_REG_POSITION(texturing.texture1_format, 0x96);
  170. ASSERT_REG_POSITION(texturing.texture2, 0x99);
  171. ASSERT_REG_POSITION(texturing.texture2_format, 0x9e);
  172. ASSERT_REG_POSITION(texturing.tev_stage0, 0xc0);
  173. ASSERT_REG_POSITION(texturing.tev_stage1, 0xc8);
  174. ASSERT_REG_POSITION(texturing.tev_stage2, 0xd0);
  175. ASSERT_REG_POSITION(texturing.tev_stage3, 0xd8);
  176. ASSERT_REG_POSITION(texturing.tev_combiner_buffer_input, 0xe0);
  177. ASSERT_REG_POSITION(texturing.fog_mode, 0xe0);
  178. ASSERT_REG_POSITION(texturing.fog_color, 0xe1);
  179. ASSERT_REG_POSITION(texturing.fog_lut_offset, 0xe6);
  180. ASSERT_REG_POSITION(texturing.fog_lut_data, 0xe8);
  181. ASSERT_REG_POSITION(texturing.tev_stage4, 0xf0);
  182. ASSERT_REG_POSITION(texturing.tev_stage5, 0xf8);
  183. ASSERT_REG_POSITION(texturing.tev_combiner_buffer_color, 0xfd);
  184. ASSERT_REG_POSITION(framebuffer, 0x100);
  185. ASSERT_REG_POSITION(framebuffer.output_merger, 0x100);
  186. ASSERT_REG_POSITION(framebuffer.framebuffer, 0x110);
  187. ASSERT_REG_POSITION(lighting, 0x140);
  188. ASSERT_REG_POSITION(pipeline, 0x200);
  189. ASSERT_REG_POSITION(pipeline.vertex_attributes, 0x200);
  190. ASSERT_REG_POSITION(pipeline.index_array, 0x227);
  191. ASSERT_REG_POSITION(pipeline.num_vertices, 0x228);
  192. ASSERT_REG_POSITION(pipeline.vertex_offset, 0x22a);
  193. ASSERT_REG_POSITION(pipeline.trigger_draw, 0x22e);
  194. ASSERT_REG_POSITION(pipeline.trigger_draw_indexed, 0x22f);
  195. ASSERT_REG_POSITION(pipeline.vs_default_attributes_setup, 0x232);
  196. ASSERT_REG_POSITION(pipeline.command_buffer, 0x238);
  197. ASSERT_REG_POSITION(pipeline.gpu_mode, 0x245);
  198. ASSERT_REG_POSITION(pipeline.triangle_topology, 0x25e);
  199. ASSERT_REG_POSITION(pipeline.restart_primitive, 0x25f);
  200. ASSERT_REG_POSITION(gs, 0x280);
  201. ASSERT_REG_POSITION(vs, 0x2b0);
  202. #undef ASSERT_REG_POSITION
  203. #endif // !defined(_MSC_VER)
  204. static_assert(sizeof(Regs::ShaderConfig) == 0x30 * sizeof(u32),
  205. "ShaderConfig structure has incorrect size");
  206. // The total number of registers is chosen arbitrarily, but let's make sure it's not some odd value
  207. // anyway.
  208. static_assert(sizeof(Regs) <= 0x300 * sizeof(u32),
  209. "Register set structure larger than it should be");
  210. static_assert(sizeof(Regs) >= 0x300 * sizeof(u32),
  211. "Register set structure smaller than it should be");
  212. /// Initialize Pica state
  213. void Init();
  214. /// Shutdown Pica state
  215. void Shutdown();
  216. } // namespace