regs.h 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. // Copyright 2017 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/common_funcs.h"
  12. #include "common/common_types.h"
  13. #include "video_core/regs_framebuffer.h"
  14. #include "video_core/regs_lighting.h"
  15. #include "video_core/regs_pipeline.h"
  16. #include "video_core/regs_rasterizer.h"
  17. #include "video_core/regs_shader.h"
  18. #include "video_core/regs_texturing.h"
  19. namespace Pica {
  20. // Returns index corresponding to the Regs member labeled by field_name
  21. // TODO: Due to Visual studio bug 209229, offsetof does not return constant expressions
  22. // when used with array elements (e.g. PICA_REG_INDEX(vs_uniform_setup.set_value[1])).
  23. // For details cf.
  24. // https://connect.microsoft.com/VisualStudio/feedback/details/209229/offsetof-does-not-produce-a-constant-expression-for-array-members
  25. // Hopefully, this will be fixed sometime in the future.
  26. // For lack of better alternatives, we currently hardcode the offsets when constant
  27. // expressions are needed via PICA_REG_INDEX_WORKAROUND (on sane compilers, static_asserts
  28. // will then make sure the offsets indeed match the automatically calculated ones).
  29. #define PICA_REG_INDEX(field_name) (offsetof(Pica::Regs, field_name) / sizeof(u32))
  30. #if defined(_MSC_VER)
  31. #define PICA_REG_INDEX_WORKAROUND(field_name, backup_workaround_index) (backup_workaround_index)
  32. #else
  33. // NOTE: Yeah, hacking in a static_assert here just to workaround the lacking MSVC compiler
  34. // really is this annoying. This macro just forwards its first argument to PICA_REG_INDEX
  35. // and then performs a (no-op) cast to size_t iff the second argument matches the expected
  36. // field offset. Otherwise, the compiler will fail to compile this code.
  37. #define PICA_REG_INDEX_WORKAROUND(field_name, backup_workaround_index) \
  38. ((typename std::enable_if<backup_workaround_index == PICA_REG_INDEX(field_name), \
  39. size_t>::type)PICA_REG_INDEX(field_name))
  40. #endif // _MSC_VER
  41. struct Regs {
  42. static constexpr size_t NUM_REGS = 0x300;
  43. union {
  44. struct {
  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. ShaderRegs gs;
  54. ShaderRegs vs;
  55. INSERT_PADDING_WORDS(0x20);
  56. };
  57. std::array<u32, NUM_REGS> reg_array;
  58. };
  59. /// Map register indices to names readable by humans
  60. static const char* GetRegisterName(u16 index);
  61. };
  62. static_assert(sizeof(Regs) == Regs::NUM_REGS * sizeof(u32), "Regs struct has wrong size");
  63. // TODO: MSVC does not support using offsetof() on non-static data members even though this
  64. // is technically allowed since C++11. This macro should be enabled once MSVC adds
  65. // support for that.
  66. #ifndef _MSC_VER
  67. #define ASSERT_REG_POSITION(field_name, position) \
  68. static_assert(offsetof(Regs, field_name) == position * 4, \
  69. "Field " #field_name " has invalid position")
  70. ASSERT_REG_POSITION(trigger_irq, 0x10);
  71. ASSERT_REG_POSITION(rasterizer, 0x40);
  72. ASSERT_REG_POSITION(rasterizer.cull_mode, 0x40);
  73. ASSERT_REG_POSITION(rasterizer.viewport_size_x, 0x41);
  74. ASSERT_REG_POSITION(rasterizer.viewport_size_y, 0x43);
  75. ASSERT_REG_POSITION(rasterizer.viewport_depth_range, 0x4d);
  76. ASSERT_REG_POSITION(rasterizer.viewport_depth_near_plane, 0x4e);
  77. ASSERT_REG_POSITION(rasterizer.vs_output_attributes[0], 0x50);
  78. ASSERT_REG_POSITION(rasterizer.vs_output_attributes[1], 0x51);
  79. ASSERT_REG_POSITION(rasterizer.scissor_test, 0x65);
  80. ASSERT_REG_POSITION(rasterizer.viewport_corner, 0x68);
  81. ASSERT_REG_POSITION(rasterizer.depthmap_enable, 0x6D);
  82. ASSERT_REG_POSITION(texturing, 0x80);
  83. ASSERT_REG_POSITION(texturing.texture0_enable, 0x80);
  84. ASSERT_REG_POSITION(texturing.texture0, 0x81);
  85. ASSERT_REG_POSITION(texturing.texture0_format, 0x8e);
  86. ASSERT_REG_POSITION(texturing.fragment_lighting_enable, 0x8f);
  87. ASSERT_REG_POSITION(texturing.texture1, 0x91);
  88. ASSERT_REG_POSITION(texturing.texture1_format, 0x96);
  89. ASSERT_REG_POSITION(texturing.texture2, 0x99);
  90. ASSERT_REG_POSITION(texturing.texture2_format, 0x9e);
  91. ASSERT_REG_POSITION(texturing.tev_stage0, 0xc0);
  92. ASSERT_REG_POSITION(texturing.tev_stage1, 0xc8);
  93. ASSERT_REG_POSITION(texturing.tev_stage2, 0xd0);
  94. ASSERT_REG_POSITION(texturing.tev_stage3, 0xd8);
  95. ASSERT_REG_POSITION(texturing.tev_combiner_buffer_input, 0xe0);
  96. ASSERT_REG_POSITION(texturing.fog_mode, 0xe0);
  97. ASSERT_REG_POSITION(texturing.fog_color, 0xe1);
  98. ASSERT_REG_POSITION(texturing.fog_lut_offset, 0xe6);
  99. ASSERT_REG_POSITION(texturing.fog_lut_data, 0xe8);
  100. ASSERT_REG_POSITION(texturing.tev_stage4, 0xf0);
  101. ASSERT_REG_POSITION(texturing.tev_stage5, 0xf8);
  102. ASSERT_REG_POSITION(texturing.tev_combiner_buffer_color, 0xfd);
  103. ASSERT_REG_POSITION(framebuffer, 0x100);
  104. ASSERT_REG_POSITION(framebuffer.output_merger, 0x100);
  105. ASSERT_REG_POSITION(framebuffer.framebuffer, 0x110);
  106. ASSERT_REG_POSITION(lighting, 0x140);
  107. ASSERT_REG_POSITION(pipeline, 0x200);
  108. ASSERT_REG_POSITION(pipeline.vertex_attributes, 0x200);
  109. ASSERT_REG_POSITION(pipeline.index_array, 0x227);
  110. ASSERT_REG_POSITION(pipeline.num_vertices, 0x228);
  111. ASSERT_REG_POSITION(pipeline.vertex_offset, 0x22a);
  112. ASSERT_REG_POSITION(pipeline.trigger_draw, 0x22e);
  113. ASSERT_REG_POSITION(pipeline.trigger_draw_indexed, 0x22f);
  114. ASSERT_REG_POSITION(pipeline.vs_default_attributes_setup, 0x232);
  115. ASSERT_REG_POSITION(pipeline.command_buffer, 0x238);
  116. ASSERT_REG_POSITION(pipeline.gpu_mode, 0x245);
  117. ASSERT_REG_POSITION(pipeline.triangle_topology, 0x25e);
  118. ASSERT_REG_POSITION(pipeline.restart_primitive, 0x25f);
  119. ASSERT_REG_POSITION(gs, 0x280);
  120. ASSERT_REG_POSITION(vs, 0x2b0);
  121. #undef ASSERT_REG_POSITION
  122. #endif // !defined(_MSC_VER)
  123. } // namespace Pica