diff options
| author | 2018-03-28 15:20:18 -0500 | |
|---|---|---|
| committer | 2018-04-01 12:07:26 -0500 | |
| commit | 11b4ab96858296ad46016edb1d00ca22ab81a356 (patch) | |
| tree | 350b64ebd6b96bd9338f63865480180a864c3012 /src | |
| parent | GPU: Implemented a gpu macro interpreter. (diff) | |
| download | yuzu-11b4ab96858296ad46016edb1d00ca22ab81a356.tar.gz yuzu-11b4ab96858296ad46016edb1d00ca22ab81a356.tar.xz yuzu-11b4ab96858296ad46016edb1d00ca22ab81a356.zip | |
GPU: Use the MacroInterpreter class to execute the GPU macros instead of HLEing them.
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/engines/maxwell_3d.cpp | 108 | ||||
| -rw-r--r-- | src/video_core/engines/maxwell_3d.h | 26 |
2 files changed, 13 insertions, 121 deletions
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index 85255d0a5..124753032 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp | |||
| @@ -19,35 +19,21 @@ namespace Engines { | |||
| 19 | /// First register id that is actually a Macro call. | 19 | /// First register id that is actually a Macro call. |
| 20 | constexpr u32 MacroRegistersStart = 0xE00; | 20 | constexpr u32 MacroRegistersStart = 0xE00; |
| 21 | 21 | ||
| 22 | const std::unordered_map<u32, Maxwell3D::MethodInfo> Maxwell3D::method_handlers = { | 22 | Maxwell3D::Maxwell3D(MemoryManager& memory_manager) |
| 23 | {0xE1A, {"BindTextureInfoBuffer", 1, &Maxwell3D::BindTextureInfoBuffer}}, | 23 | : memory_manager(memory_manager), macro_interpreter(*this) {} |
| 24 | {0xE24, {"SetShader", 5, &Maxwell3D::SetShader}}, | ||
| 25 | {0xE2A, {"BindStorageBuffer", 1, &Maxwell3D::BindStorageBuffer}}, | ||
| 26 | }; | ||
| 27 | |||
| 28 | Maxwell3D::Maxwell3D(MemoryManager& memory_manager) : memory_manager(memory_manager) {} | ||
| 29 | 24 | ||
| 30 | void Maxwell3D::SubmitMacroCode(u32 entry, std::vector<u32> code) { | 25 | void Maxwell3D::SubmitMacroCode(u32 entry, std::vector<u32> code) { |
| 31 | uploaded_macros[entry * 2 + MacroRegistersStart] = std::move(code); | 26 | uploaded_macros[entry * 2 + MacroRegistersStart] = std::move(code); |
| 32 | } | 27 | } |
| 33 | 28 | ||
| 34 | void Maxwell3D::CallMacroMethod(u32 method, const std::vector<u32>& parameters) { | 29 | void Maxwell3D::CallMacroMethod(u32 method, std::vector<u32> parameters) { |
| 35 | // TODO(Subv): Write an interpreter for the macros uploaded via registers 0x45 and 0x47 | 30 | auto macro_code = uploaded_macros.find(method); |
| 36 | |||
| 37 | // The requested macro must have been uploaded already. | 31 | // The requested macro must have been uploaded already. |
| 38 | ASSERT_MSG(uploaded_macros.find(method) != uploaded_macros.end(), "Macro %08X was not uploaded", | 32 | ASSERT_MSG(macro_code != uploaded_macros.end(), "Macro %08X was not uploaded", method); |
| 39 | method); | ||
| 40 | |||
| 41 | auto itr = method_handlers.find(method); | ||
| 42 | ASSERT_MSG(itr != method_handlers.end(), "Unhandled method call %08X", method); | ||
| 43 | |||
| 44 | ASSERT(itr->second.arguments == parameters.size()); | ||
| 45 | |||
| 46 | (this->*itr->second.handler)(parameters); | ||
| 47 | 33 | ||
| 48 | // Reset the current macro and its parameters. | 34 | // Reset the current macro and execute it. |
| 49 | executing_macro = 0; | 35 | executing_macro = 0; |
| 50 | macro_params.clear(); | 36 | macro_interpreter.Execute(macro_code->second, std::move(parameters)); |
| 51 | } | 37 | } |
| 52 | 38 | ||
| 53 | void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) { | 39 | void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) { |
| @@ -77,7 +63,7 @@ void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) { | |||
| 77 | 63 | ||
| 78 | // Call the macro when there are no more parameters in the command buffer | 64 | // Call the macro when there are no more parameters in the command buffer |
| 79 | if (remaining_params == 0) { | 65 | if (remaining_params == 0) { |
| 80 | CallMacroMethod(executing_macro, macro_params); | 66 | CallMacroMethod(executing_macro, std::move(macro_params)); |
| 81 | } | 67 | } |
| 82 | return; | 68 | return; |
| 83 | } | 69 | } |
| @@ -193,84 +179,6 @@ void Maxwell3D::DrawArrays() { | |||
| 193 | VideoCore::g_renderer->Rasterizer()->AccelerateDrawBatch(false /*is_indexed*/); | 179 | VideoCore::g_renderer->Rasterizer()->AccelerateDrawBatch(false /*is_indexed*/); |
| 194 | } | 180 | } |
| 195 | 181 | ||
| 196 | void Maxwell3D::BindTextureInfoBuffer(const std::vector<u32>& parameters) { | ||
| 197 | /** | ||
| 198 | * Parameters description: | ||
| 199 | * [0] = Shader stage, usually 4 for FragmentShader | ||
| 200 | */ | ||
| 201 | |||
| 202 | u32 stage = parameters[0]; | ||
| 203 | |||
| 204 | // Perform the same operations as the real macro code. | ||
| 205 | GPUVAddr address = static_cast<GPUVAddr>(regs.tex_info_buffers.address[stage]) << 8; | ||
| 206 | u32 size = regs.tex_info_buffers.size[stage]; | ||
| 207 | |||
| 208 | regs.const_buffer.cb_size = size; | ||
| 209 | regs.const_buffer.cb_address_high = address >> 32; | ||
| 210 | regs.const_buffer.cb_address_low = address & 0xFFFFFFFF; | ||
| 211 | } | ||
| 212 | |||
| 213 | void Maxwell3D::SetShader(const std::vector<u32>& parameters) { | ||
| 214 | /** | ||
| 215 | * Parameters description: | ||
| 216 | * [0] = Shader Program. | ||
| 217 | * [1] = Unknown, presumably the shader id. | ||
| 218 | * [2] = Offset to the start of the shader, after the 0x30 bytes header. | ||
| 219 | * [3] = Shader Stage. | ||
| 220 | * [4] = Const Buffer Address >> 8. | ||
| 221 | */ | ||
| 222 | auto shader_program = static_cast<Regs::ShaderProgram>(parameters[0]); | ||
| 223 | // TODO(Subv): This address is probably an offset from the CODE_ADDRESS register. | ||
| 224 | GPUVAddr address = parameters[2]; | ||
| 225 | auto shader_stage = static_cast<Regs::ShaderStage>(parameters[3]); | ||
| 226 | GPUVAddr cb_address = parameters[4] << 8; | ||
| 227 | |||
| 228 | auto& shader = state.shader_programs[static_cast<size_t>(shader_program)]; | ||
| 229 | shader.program = shader_program; | ||
| 230 | shader.stage = shader_stage; | ||
| 231 | shader.address = address; | ||
| 232 | |||
| 233 | // Perform the same operations as the real macro code. | ||
| 234 | // TODO(Subv): Early exit if register 0xD1C + shader_program contains the same as params[1]. | ||
| 235 | auto& shader_regs = regs.shader_config[static_cast<size_t>(shader_program)]; | ||
| 236 | shader_regs.start_id = address; | ||
| 237 | // TODO(Subv): Write params[1] to register 0xD1C + shader_program. | ||
| 238 | // TODO(Subv): Write params[2] to register 0xD22 + shader_program. | ||
| 239 | |||
| 240 | // Note: This value is hardcoded in the macro's code. | ||
| 241 | static constexpr u32 DefaultCBSize = 0x10000; | ||
| 242 | regs.const_buffer.cb_size = DefaultCBSize; | ||
| 243 | regs.const_buffer.cb_address_high = cb_address >> 32; | ||
| 244 | regs.const_buffer.cb_address_low = cb_address & 0xFFFFFFFF; | ||
| 245 | |||
| 246 | // Write a hardcoded 0x11 to CB_BIND, this binds the current const buffer to buffer c1[] in the | ||
| 247 | // shader. It's likely that these are the constants for the shader. | ||
| 248 | regs.cb_bind[static_cast<size_t>(shader_stage)].valid.Assign(1); | ||
| 249 | regs.cb_bind[static_cast<size_t>(shader_stage)].index.Assign(1); | ||
| 250 | |||
| 251 | ProcessCBBind(shader_stage); | ||
| 252 | } | ||
| 253 | |||
| 254 | void Maxwell3D::BindStorageBuffer(const std::vector<u32>& parameters) { | ||
| 255 | /** | ||
| 256 | * Parameters description: | ||
| 257 | * [0] = Buffer offset >> 2 | ||
| 258 | */ | ||
| 259 | |||
| 260 | u32 buffer_offset = parameters[0] << 2; | ||
| 261 | |||
| 262 | // Perform the same operations as the real macro code. | ||
| 263 | // Note: This value is hardcoded in the macro's code. | ||
| 264 | static constexpr u32 DefaultCBSize = 0x5F00; | ||
| 265 | regs.const_buffer.cb_size = DefaultCBSize; | ||
| 266 | |||
| 267 | GPUVAddr address = regs.ssbo_info.BufferAddress(); | ||
| 268 | regs.const_buffer.cb_address_high = address >> 32; | ||
| 269 | regs.const_buffer.cb_address_low = address & 0xFFFFFFFF; | ||
| 270 | |||
| 271 | regs.const_buffer.cb_pos = buffer_offset; | ||
| 272 | } | ||
| 273 | |||
| 274 | void Maxwell3D::ProcessCBBind(Regs::ShaderStage stage) { | 182 | void Maxwell3D::ProcessCBBind(Regs::ShaderStage stage) { |
| 275 | // Bind the buffer currently in CB_ADDRESS to the specified index in the desired shader stage. | 183 | // Bind the buffer currently in CB_ADDRESS to the specified index in the desired shader stage. |
| 276 | auto& shader = state.shader_stages[static_cast<size_t>(stage)]; | 184 | auto& shader = state.shader_stages[static_cast<size_t>(stage)]; |
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index 086ffeb6a..98b39b2ff 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include "common/common_types.h" | 13 | #include "common/common_types.h" |
| 14 | #include "common/math_util.h" | 14 | #include "common/math_util.h" |
| 15 | #include "video_core/gpu.h" | 15 | #include "video_core/gpu.h" |
| 16 | #include "video_core/macro_interpreter.h" | ||
| 16 | #include "video_core/memory_manager.h" | 17 | #include "video_core/memory_manager.h" |
| 17 | #include "video_core/textures/texture.h" | 18 | #include "video_core/textures/texture.h" |
| 18 | 19 | ||
| @@ -498,18 +499,11 @@ public: | |||
| 498 | bool enabled; | 499 | bool enabled; |
| 499 | }; | 500 | }; |
| 500 | 501 | ||
| 501 | struct ShaderProgramInfo { | ||
| 502 | Regs::ShaderStage stage; | ||
| 503 | Regs::ShaderProgram program; | ||
| 504 | GPUVAddr address; | ||
| 505 | }; | ||
| 506 | |||
| 507 | struct ShaderStageInfo { | 502 | struct ShaderStageInfo { |
| 508 | std::array<ConstBufferInfo, Regs::MaxConstBuffers> const_buffers; | 503 | std::array<ConstBufferInfo, Regs::MaxConstBuffers> const_buffers; |
| 509 | }; | 504 | }; |
| 510 | 505 | ||
| 511 | std::array<ShaderStageInfo, Regs::MaxShaderStage> shader_stages; | 506 | std::array<ShaderStageInfo, Regs::MaxShaderStage> shader_stages; |
| 512 | std::array<ShaderProgramInfo, Regs::MaxShaderProgram> shader_programs; | ||
| 513 | }; | 507 | }; |
| 514 | 508 | ||
| 515 | State state{}; | 509 | State state{}; |
| @@ -536,6 +530,9 @@ private: | |||
| 536 | /// Parameters that have been submitted to the macro call so far. | 530 | /// Parameters that have been submitted to the macro call so far. |
| 537 | std::vector<u32> macro_params; | 531 | std::vector<u32> macro_params; |
| 538 | 532 | ||
| 533 | /// Interpreter for the macro codes uploaded to the GPU. | ||
| 534 | MacroInterpreter macro_interpreter; | ||
| 535 | |||
| 539 | /// Retrieves information about a specific TIC entry from the TIC buffer. | 536 | /// Retrieves information about a specific TIC entry from the TIC buffer. |
| 540 | Texture::TICEntry GetTICEntry(u32 tic_index) const; | 537 | Texture::TICEntry GetTICEntry(u32 tic_index) const; |
| 541 | 538 | ||
| @@ -547,7 +544,7 @@ private: | |||
| 547 | * @param method Method to call | 544 | * @param method Method to call |
| 548 | * @param parameters Arguments to the method call | 545 | * @param parameters Arguments to the method call |
| 549 | */ | 546 | */ |
| 550 | void CallMacroMethod(u32 method, const std::vector<u32>& parameters); | 547 | void CallMacroMethod(u32 method, std::vector<u32> parameters); |
| 551 | 548 | ||
| 552 | /// Handles a write to the QUERY_GET register. | 549 | /// Handles a write to the QUERY_GET register. |
| 553 | void ProcessQueryGet(); | 550 | void ProcessQueryGet(); |
| @@ -560,19 +557,6 @@ private: | |||
| 560 | 557 | ||
| 561 | /// Handles a write to the VERTEX_END_GL register, triggering a draw. | 558 | /// Handles a write to the VERTEX_END_GL register, triggering a draw. |
| 562 | void DrawArrays(); | 559 | void DrawArrays(); |
| 563 | |||
| 564 | /// Method call handlers | ||
| 565 | void BindTextureInfoBuffer(const std::vector<u32>& parameters); | ||
| 566 | void SetShader(const std::vector<u32>& parameters); | ||
| 567 | void BindStorageBuffer(const std::vector<u32>& parameters); | ||
| 568 | |||
| 569 | struct MethodInfo { | ||
| 570 | const char* name; | ||
| 571 | u32 arguments; | ||
| 572 | void (Maxwell3D::*handler)(const std::vector<u32>& parameters); | ||
| 573 | }; | ||
| 574 | |||
| 575 | static const std::unordered_map<u32, MethodInfo> method_handlers; | ||
| 576 | }; | 560 | }; |
| 577 | 561 | ||
| 578 | #define ASSERT_REG_POSITION(field_name, position) \ | 562 | #define ASSERT_REG_POSITION(field_name, position) \ |