shader.h 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. // Copyright 2015 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 <type_traits>
  8. #include <nihstro/shader_bytecode.h>
  9. #include "common/assert.h"
  10. #include "common/common_funcs.h"
  11. #include "common/common_types.h"
  12. #include "common/vector_math.h"
  13. #include "video_core/pica_types.h"
  14. #include "video_core/regs_rasterizer.h"
  15. #include "video_core/regs_shader.h"
  16. using nihstro::RegisterType;
  17. using nihstro::SourceRegister;
  18. using nihstro::DestRegister;
  19. namespace Pica {
  20. namespace Shader {
  21. struct AttributeBuffer {
  22. alignas(16) Math::Vec4<float24> attr[16];
  23. };
  24. struct OutputVertex {
  25. Math::Vec4<float24> pos;
  26. Math::Vec4<float24> quat;
  27. Math::Vec4<float24> color;
  28. Math::Vec2<float24> tc0;
  29. Math::Vec2<float24> tc1;
  30. float24 tc0_w;
  31. INSERT_PADDING_WORDS(1);
  32. Math::Vec3<float24> view;
  33. INSERT_PADDING_WORDS(1);
  34. Math::Vec2<float24> tc2;
  35. static OutputVertex FromAttributeBuffer(const RasterizerRegs& regs, AttributeBuffer& output);
  36. };
  37. #define ASSERT_POS(var, pos) \
  38. static_assert(offsetof(OutputVertex, var) == pos * sizeof(float24), "Semantic at wrong " \
  39. "offset.")
  40. ASSERT_POS(pos, RasterizerRegs::VSOutputAttributes::POSITION_X);
  41. ASSERT_POS(quat, RasterizerRegs::VSOutputAttributes::QUATERNION_X);
  42. ASSERT_POS(color, RasterizerRegs::VSOutputAttributes::COLOR_R);
  43. ASSERT_POS(tc0, RasterizerRegs::VSOutputAttributes::TEXCOORD0_U);
  44. ASSERT_POS(tc1, RasterizerRegs::VSOutputAttributes::TEXCOORD1_U);
  45. ASSERT_POS(tc0_w, RasterizerRegs::VSOutputAttributes::TEXCOORD0_W);
  46. ASSERT_POS(view, RasterizerRegs::VSOutputAttributes::VIEW_X);
  47. ASSERT_POS(tc2, RasterizerRegs::VSOutputAttributes::TEXCOORD2_U);
  48. #undef ASSERT_POS
  49. static_assert(std::is_pod<OutputVertex>::value, "Structure is not POD");
  50. static_assert(sizeof(OutputVertex) == 24 * sizeof(float), "OutputVertex has invalid size");
  51. /**
  52. * This structure contains the state information that needs to be unique for a shader unit. The 3DS
  53. * has four shader units that process shaders in parallel. At the present, Citra only implements a
  54. * single shader unit that processes all shaders serially. Putting the state information in a struct
  55. * here will make it easier for us to parallelize the shader processing later.
  56. */
  57. struct UnitState {
  58. struct Registers {
  59. // The registers are accessed by the shader JIT using SSE instructions, and are therefore
  60. // required to be 16-byte aligned.
  61. alignas(16) Math::Vec4<float24> input[16];
  62. alignas(16) Math::Vec4<float24> temporary[16];
  63. alignas(16) Math::Vec4<float24> output[16];
  64. } registers;
  65. static_assert(std::is_pod<Registers>::value, "Structure is not POD");
  66. bool conditional_code[2];
  67. // Two Address registers and one loop counter
  68. // TODO: How many bits do these actually have?
  69. s32 address_registers[3];
  70. static size_t InputOffset(const SourceRegister& reg) {
  71. switch (reg.GetRegisterType()) {
  72. case RegisterType::Input:
  73. return offsetof(UnitState, registers.input) +
  74. reg.GetIndex() * sizeof(Math::Vec4<float24>);
  75. case RegisterType::Temporary:
  76. return offsetof(UnitState, registers.temporary) +
  77. reg.GetIndex() * sizeof(Math::Vec4<float24>);
  78. default:
  79. UNREACHABLE();
  80. return 0;
  81. }
  82. }
  83. static size_t OutputOffset(const DestRegister& reg) {
  84. switch (reg.GetRegisterType()) {
  85. case RegisterType::Output:
  86. return offsetof(UnitState, registers.output) +
  87. reg.GetIndex() * sizeof(Math::Vec4<float24>);
  88. case RegisterType::Temporary:
  89. return offsetof(UnitState, registers.temporary) +
  90. reg.GetIndex() * sizeof(Math::Vec4<float24>);
  91. default:
  92. UNREACHABLE();
  93. return 0;
  94. }
  95. }
  96. /**
  97. * Loads the unit state with an input vertex.
  98. *
  99. * @param config Shader configuration registers corresponding to the unit.
  100. * @param input Attribute buffer to load into the input registers.
  101. */
  102. void LoadInput(const ShaderRegs& config, const AttributeBuffer& input);
  103. void WriteOutput(const ShaderRegs& config, AttributeBuffer& output);
  104. };
  105. struct ShaderSetup {
  106. struct {
  107. // The float uniforms are accessed by the shader JIT using SSE instructions, and are
  108. // therefore required to be 16-byte aligned.
  109. alignas(16) Math::Vec4<float24> f[96];
  110. std::array<bool, 16> b;
  111. std::array<Math::Vec4<u8>, 4> i;
  112. } uniforms;
  113. static size_t GetFloatUniformOffset(unsigned index) {
  114. return offsetof(ShaderSetup, uniforms.f) + index * sizeof(Math::Vec4<float24>);
  115. }
  116. static size_t GetBoolUniformOffset(unsigned index) {
  117. return offsetof(ShaderSetup, uniforms.b) + index * sizeof(bool);
  118. }
  119. static size_t GetIntUniformOffset(unsigned index) {
  120. return offsetof(ShaderSetup, uniforms.i) + index * sizeof(Math::Vec4<u8>);
  121. }
  122. std::array<u32, 1024> program_code;
  123. std::array<u32, 1024> swizzle_data;
  124. /// Data private to ShaderEngines
  125. struct EngineData {
  126. unsigned int entry_point;
  127. /// Used by the JIT, points to a compiled shader object.
  128. const void* cached_shader = nullptr;
  129. } engine_data;
  130. };
  131. class ShaderEngine {
  132. public:
  133. virtual ~ShaderEngine() = default;
  134. /**
  135. * Performs any shader unit setup that only needs to happen once per shader (as opposed to once
  136. * per vertex, which would happen within the `Run` function).
  137. */
  138. virtual void SetupBatch(ShaderSetup& setup, unsigned int entry_point) = 0;
  139. /**
  140. * Runs the currently setup shader.
  141. *
  142. * @param setup Shader engine state, must be setup with SetupBatch on each shader change.
  143. * @param state Shader unit state, must be setup with input data before each shader invocation.
  144. */
  145. virtual void Run(const ShaderSetup& setup, UnitState& state) const = 0;
  146. };
  147. // TODO(yuriks): Remove and make it non-global state somewhere
  148. ShaderEngine* GetEngine();
  149. void Shutdown();
  150. } // namespace Shader
  151. } // namespace Pica