diff options
| author | 2018-03-17 21:19:39 -0400 | |
|---|---|---|
| committer | 2018-03-17 21:19:39 -0400 | |
| commit | 29981fa2ebf790a9182c5a8d97084606852d2060 (patch) | |
| tree | 371e67d6f7c303c7ddd9bbbbb090247bdc590a14 /src | |
| parent | Merge pull request #242 from Subv/set_shader (diff) | |
| parent | GPU: Renamed ShaderType to ShaderStage as that is less confusing. (diff) | |
| download | yuzu-29981fa2ebf790a9182c5a8d97084606852d2060.tar.gz yuzu-29981fa2ebf790a9182c5a8d97084606852d2060.tar.xz yuzu-29981fa2ebf790a9182c5a8d97084606852d2060.zip | |
Merge pull request #245 from Subv/set_shader2
GPU: Store shader constbuffer bindings in the GPU state.
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/engines/maxwell_3d.cpp | 73 | ||||
| -rw-r--r-- | src/video_core/engines/maxwell_3d.h | 65 |
2 files changed, 115 insertions, 23 deletions
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index 603a2edaf..db12fc702 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp | |||
| @@ -15,6 +15,7 @@ const std::unordered_map<u32, Maxwell3D::MethodInfo> Maxwell3D::method_handlers | |||
| 15 | Maxwell3D::Maxwell3D(MemoryManager& memory_manager) : memory_manager(memory_manager) {} | 15 | Maxwell3D::Maxwell3D(MemoryManager& memory_manager) : memory_manager(memory_manager) {} |
| 16 | 16 | ||
| 17 | void Maxwell3D::CallMethod(u32 method, const std::vector<u32>& parameters) { | 17 | void Maxwell3D::CallMethod(u32 method, const std::vector<u32>& parameters) { |
| 18 | // TODO(Subv): Write an interpreter for the macros uploaded via registers 0x45 and 0x47 | ||
| 18 | auto itr = method_handlers.find(method); | 19 | auto itr = method_handlers.find(method); |
| 19 | if (itr == method_handlers.end()) { | 20 | if (itr == method_handlers.end()) { |
| 20 | LOG_ERROR(HW_GPU, "Unhandled method call %08X", method); | 21 | LOG_ERROR(HW_GPU, "Unhandled method call %08X", method); |
| @@ -42,6 +43,26 @@ void Maxwell3D::WriteReg(u32 method, u32 value) { | |||
| 42 | ASSERT_MSG(regs.code_address.CodeAddress() == 0, "Unexpected CODE_ADDRESS register value."); | 43 | ASSERT_MSG(regs.code_address.CodeAddress() == 0, "Unexpected CODE_ADDRESS register value."); |
| 43 | break; | 44 | break; |
| 44 | } | 45 | } |
| 46 | case MAXWELL3D_REG_INDEX(cb_bind[0].raw_config): { | ||
| 47 | ProcessCBBind(Regs::ShaderStage::Vertex); | ||
| 48 | break; | ||
| 49 | } | ||
| 50 | case MAXWELL3D_REG_INDEX(cb_bind[1].raw_config): { | ||
| 51 | ProcessCBBind(Regs::ShaderStage::TesselationControl); | ||
| 52 | break; | ||
| 53 | } | ||
| 54 | case MAXWELL3D_REG_INDEX(cb_bind[2].raw_config): { | ||
| 55 | ProcessCBBind(Regs::ShaderStage::TesselationEval); | ||
| 56 | break; | ||
| 57 | } | ||
| 58 | case MAXWELL3D_REG_INDEX(cb_bind[3].raw_config): { | ||
| 59 | ProcessCBBind(Regs::ShaderStage::Geometry); | ||
| 60 | break; | ||
| 61 | } | ||
| 62 | case MAXWELL3D_REG_INDEX(cb_bind[4].raw_config): { | ||
| 63 | ProcessCBBind(Regs::ShaderStage::Fragment); | ||
| 64 | break; | ||
| 65 | } | ||
| 45 | case MAXWELL3D_REG_INDEX(draw.vertex_end_gl): { | 66 | case MAXWELL3D_REG_INDEX(draw.vertex_end_gl): { |
| 46 | DrawArrays(); | 67 | DrawArrays(); |
| 47 | break; | 68 | break; |
| @@ -83,22 +104,54 @@ void Maxwell3D::SetShader(const std::vector<u32>& parameters) { | |||
| 83 | /** | 104 | /** |
| 84 | * Parameters description: | 105 | * Parameters description: |
| 85 | * [0] = Shader Program. | 106 | * [0] = Shader Program. |
| 86 | * [1] = Unknown. | 107 | * [1] = Unknown, presumably the shader id. |
| 87 | * [2] = Offset to the start of the shader, after the 0x30 bytes header. | 108 | * [2] = Offset to the start of the shader, after the 0x30 bytes header. |
| 88 | * [3] = Shader Type. | 109 | * [3] = Shader Stage. |
| 89 | * [4] = Shader End Address >> 8. | 110 | * [4] = Const Buffer Address >> 8. |
| 90 | */ | 111 | */ |
| 91 | auto shader_program = static_cast<Regs::ShaderProgram>(parameters[0]); | 112 | auto shader_program = static_cast<Regs::ShaderProgram>(parameters[0]); |
| 92 | // TODO(Subv): This address is probably an offset from the CODE_ADDRESS register. | 113 | // TODO(Subv): This address is probably an offset from the CODE_ADDRESS register. |
| 93 | GPUVAddr begin_address = parameters[2]; | 114 | GPUVAddr address = parameters[2]; |
| 94 | auto shader_type = static_cast<Regs::ShaderType>(parameters[3]); | 115 | auto shader_stage = static_cast<Regs::ShaderStage>(parameters[3]); |
| 95 | GPUVAddr end_address = parameters[4] << 8; | 116 | GPUVAddr cb_address = parameters[4] << 8; |
| 96 | 117 | ||
| 97 | auto& shader = state.shaders[static_cast<size_t>(shader_program)]; | 118 | auto& shader = state.shader_programs[static_cast<size_t>(shader_program)]; |
| 98 | shader.program = shader_program; | 119 | shader.program = shader_program; |
| 99 | shader.type = shader_type; | 120 | shader.stage = shader_stage; |
| 100 | shader.begin_address = begin_address; | 121 | shader.address = address; |
| 101 | shader.end_address = end_address; | 122 | |
| 123 | // Perform the same operations as the real macro code. | ||
| 124 | // TODO(Subv): Early exit if register 0xD1C + shader_program contains the same as params[1]. | ||
| 125 | auto& shader_regs = regs.shader_config[static_cast<size_t>(shader_program)]; | ||
| 126 | shader_regs.start_id = address; | ||
| 127 | // TODO(Subv): Write params[1] to register 0xD1C + shader_program. | ||
| 128 | // TODO(Subv): Write params[2] to register 0xD22 + shader_program. | ||
| 129 | |||
| 130 | // Note: This value is hardcoded in the macro's code. | ||
| 131 | static constexpr u32 DefaultCBSize = 0x10000; | ||
| 132 | regs.const_buffer.cb_size = DefaultCBSize; | ||
| 133 | regs.const_buffer.cb_address_high = cb_address >> 32; | ||
| 134 | regs.const_buffer.cb_address_low = cb_address & 0xFFFFFFFF; | ||
| 135 | |||
| 136 | // Write a hardcoded 0x11 to CB_BIND, this binds the current const buffer to buffer c1[] in the | ||
| 137 | // shader. It's likely that these are the constants for the shader. | ||
| 138 | regs.cb_bind[static_cast<size_t>(shader_stage)].valid.Assign(1); | ||
| 139 | regs.cb_bind[static_cast<size_t>(shader_stage)].index.Assign(1); | ||
| 140 | |||
| 141 | ProcessCBBind(shader_stage); | ||
| 142 | } | ||
| 143 | |||
| 144 | void Maxwell3D::ProcessCBBind(Regs::ShaderStage stage) { | ||
| 145 | // Bind the buffer currently in CB_ADDRESS to the specified index in the desired shader stage. | ||
| 146 | auto& shader = state.shader_stages[static_cast<size_t>(stage)]; | ||
| 147 | auto& bind_data = regs.cb_bind[static_cast<size_t>(stage)]; | ||
| 148 | |||
| 149 | auto& buffer = shader.const_buffers[bind_data.index]; | ||
| 150 | |||
| 151 | buffer.enabled = bind_data.valid.Value() != 0; | ||
| 152 | buffer.index = bind_data.index; | ||
| 153 | buffer.address = regs.const_buffer.BufferAddress(); | ||
| 154 | buffer.size = regs.const_buffer.cb_size; | ||
| 102 | } | 155 | } |
| 103 | 156 | ||
| 104 | } // namespace Engines | 157 | } // namespace Engines |
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index c979d4e61..98137f94b 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h | |||
| @@ -35,8 +35,12 @@ public: | |||
| 35 | struct Regs { | 35 | struct Regs { |
| 36 | static constexpr size_t NUM_REGS = 0xE36; | 36 | static constexpr size_t NUM_REGS = 0xE36; |
| 37 | 37 | ||
| 38 | static constexpr size_t NumCBData = 16; | ||
| 38 | static constexpr size_t NumVertexArrays = 32; | 39 | static constexpr size_t NumVertexArrays = 32; |
| 39 | static constexpr size_t MaxShaderProgram = 6; | 40 | static constexpr size_t MaxShaderProgram = 6; |
| 41 | static constexpr size_t MaxShaderStage = 5; | ||
| 42 | // Maximum number of const buffers per shader stage. | ||
| 43 | static constexpr size_t MaxConstBuffers = 16; | ||
| 40 | 44 | ||
| 41 | enum class QueryMode : u32 { | 45 | enum class QueryMode : u32 { |
| 42 | Write = 0, | 46 | Write = 0, |
| @@ -52,7 +56,7 @@ public: | |||
| 52 | Fragment = 5, | 56 | Fragment = 5, |
| 53 | }; | 57 | }; |
| 54 | 58 | ||
| 55 | enum class ShaderType : u32 { | 59 | enum class ShaderStage : u32 { |
| 56 | Vertex = 0, | 60 | Vertex = 0, |
| 57 | TesselationControl = 1, | 61 | TesselationControl = 1, |
| 58 | TesselationEval = 2, | 62 | TesselationEval = 2, |
| @@ -132,17 +136,37 @@ public: | |||
| 132 | u32 start_id; | 136 | u32 start_id; |
| 133 | INSERT_PADDING_WORDS(1); | 137 | INSERT_PADDING_WORDS(1); |
| 134 | u32 gpr_alloc; | 138 | u32 gpr_alloc; |
| 135 | ShaderType type; | 139 | ShaderStage type; |
| 136 | INSERT_PADDING_WORDS(9); | 140 | INSERT_PADDING_WORDS(9); |
| 137 | } shader_config[MaxShaderProgram]; | 141 | } shader_config[MaxShaderProgram]; |
| 138 | 142 | ||
| 139 | INSERT_PADDING_WORDS(0x5D0); | 143 | INSERT_PADDING_WORDS(0x8C); |
| 140 | 144 | ||
| 141 | struct { | 145 | struct { |
| 142 | u32 shader_code_call; | 146 | u32 cb_size; |
| 143 | u32 shader_code_args; | 147 | u32 cb_address_high; |
| 144 | } shader_code; | 148 | u32 cb_address_low; |
| 149 | u32 cb_pos; | ||
| 150 | u32 cb_data[NumCBData]; | ||
| 151 | |||
| 152 | GPUVAddr BufferAddress() const { | ||
| 153 | return static_cast<GPUVAddr>( | ||
| 154 | (static_cast<GPUVAddr>(cb_address_high) << 32) | cb_address_low); | ||
| 155 | } | ||
| 156 | } const_buffer; | ||
| 157 | |||
| 145 | INSERT_PADDING_WORDS(0x10); | 158 | INSERT_PADDING_WORDS(0x10); |
| 159 | |||
| 160 | struct { | ||
| 161 | union { | ||
| 162 | u32 raw_config; | ||
| 163 | BitField<0, 1, u32> valid; | ||
| 164 | BitField<4, 5, u32> index; | ||
| 165 | }; | ||
| 166 | INSERT_PADDING_WORDS(7); | ||
| 167 | } cb_bind[MaxShaderStage]; | ||
| 168 | |||
| 169 | INSERT_PADDING_WORDS(0x50A); | ||
| 146 | }; | 170 | }; |
| 147 | std::array<u32, NUM_REGS> reg_array; | 171 | std::array<u32, NUM_REGS> reg_array; |
| 148 | }; | 172 | }; |
| @@ -151,17 +175,28 @@ public: | |||
| 151 | static_assert(sizeof(Regs) == Regs::NUM_REGS * sizeof(u32), "Maxwell3D Regs has wrong size"); | 175 | static_assert(sizeof(Regs) == Regs::NUM_REGS * sizeof(u32), "Maxwell3D Regs has wrong size"); |
| 152 | 176 | ||
| 153 | struct State { | 177 | struct State { |
| 154 | struct ShaderInfo { | 178 | struct ConstBufferInfo { |
| 155 | Regs::ShaderType type; | 179 | GPUVAddr address; |
| 180 | u32 index; | ||
| 181 | u32 size; | ||
| 182 | bool enabled; | ||
| 183 | }; | ||
| 184 | |||
| 185 | struct ShaderProgramInfo { | ||
| 186 | Regs::ShaderStage stage; | ||
| 156 | Regs::ShaderProgram program; | 187 | Regs::ShaderProgram program; |
| 157 | GPUVAddr begin_address; | 188 | GPUVAddr address; |
| 158 | GPUVAddr end_address; | ||
| 159 | }; | 189 | }; |
| 160 | 190 | ||
| 161 | std::array<ShaderInfo, Regs::MaxShaderProgram> shaders; | 191 | struct ShaderStageInfo { |
| 192 | std::array<ConstBufferInfo, Regs::MaxConstBuffers> const_buffers; | ||
| 193 | }; | ||
| 194 | |||
| 195 | std::array<ShaderStageInfo, Regs::MaxShaderStage> shader_stages; | ||
| 196 | std::array<ShaderProgramInfo, Regs::MaxShaderProgram> shader_programs; | ||
| 162 | }; | 197 | }; |
| 163 | 198 | ||
| 164 | State state; | 199 | State state{}; |
| 165 | 200 | ||
| 166 | private: | 201 | private: |
| 167 | MemoryManager& memory_manager; | 202 | MemoryManager& memory_manager; |
| @@ -169,6 +204,9 @@ private: | |||
| 169 | /// Handles a write to the QUERY_GET register. | 204 | /// Handles a write to the QUERY_GET register. |
| 170 | void ProcessQueryGet(); | 205 | void ProcessQueryGet(); |
| 171 | 206 | ||
| 207 | /// Handles a write to the CB_BIND register. | ||
| 208 | void ProcessCBBind(Regs::ShaderStage stage); | ||
| 209 | |||
| 172 | /// Handles a write to the VERTEX_END_GL register, triggering a draw. | 210 | /// Handles a write to the VERTEX_END_GL register, triggering a draw. |
| 173 | void DrawArrays(); | 211 | void DrawArrays(); |
| 174 | 212 | ||
| @@ -194,7 +232,8 @@ ASSERT_REG_POSITION(query, 0x6C0); | |||
| 194 | ASSERT_REG_POSITION(vertex_array[0], 0x700); | 232 | ASSERT_REG_POSITION(vertex_array[0], 0x700); |
| 195 | ASSERT_REG_POSITION(vertex_array_limit[0], 0x7C0); | 233 | ASSERT_REG_POSITION(vertex_array_limit[0], 0x7C0); |
| 196 | ASSERT_REG_POSITION(shader_config[0], 0x800); | 234 | ASSERT_REG_POSITION(shader_config[0], 0x800); |
| 197 | ASSERT_REG_POSITION(shader_code, 0xE24); | 235 | ASSERT_REG_POSITION(const_buffer, 0x8E0); |
| 236 | ASSERT_REG_POSITION(cb_bind[0], 0x904); | ||
| 198 | 237 | ||
| 199 | #undef ASSERT_REG_POSITION | 238 | #undef ASSERT_REG_POSITION |
| 200 | 239 | ||