From 1ec8d2123d3cca013178827e059641f8989b5af4 Mon Sep 17 00:00:00 2001 From: Subv Date: Wed, 28 Mar 2018 15:14:47 -0500 Subject: GPU: Implemented a gpu macro interpreter. The Ryujinx macro interpreter and envydis were used as reference. Macros are programs that are uploaded by the games during boot and can later be called by writing to their method id in a GPU command buffer. --- src/video_core/engines/maxwell_3d.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/video_core/engines/maxwell_3d.cpp') diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index 5359d21a2..85255d0a5 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp @@ -386,5 +386,10 @@ std::vector Maxwell3D::GetStageTextures(Regs::ShaderSt return textures; } +u32 Maxwell3D::GetRegisterValue(u32 method) const { + ASSERT_MSG(method < Regs::NUM_REGS, "Invalid Maxwell3D register"); + return regs.reg_array[method]; +} + } // namespace Engines } // namespace Tegra -- cgit v1.2.3 From 11b4ab96858296ad46016edb1d00ca22ab81a356 Mon Sep 17 00:00:00 2001 From: Subv Date: Wed, 28 Mar 2018 15:20:18 -0500 Subject: GPU: Use the MacroInterpreter class to execute the GPU macros instead of HLEing them. --- src/video_core/engines/maxwell_3d.cpp | 108 +++------------------------------- 1 file changed, 8 insertions(+), 100 deletions(-) (limited to 'src/video_core/engines/maxwell_3d.cpp') 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 { /// First register id that is actually a Macro call. constexpr u32 MacroRegistersStart = 0xE00; -const std::unordered_map Maxwell3D::method_handlers = { - {0xE1A, {"BindTextureInfoBuffer", 1, &Maxwell3D::BindTextureInfoBuffer}}, - {0xE24, {"SetShader", 5, &Maxwell3D::SetShader}}, - {0xE2A, {"BindStorageBuffer", 1, &Maxwell3D::BindStorageBuffer}}, -}; - -Maxwell3D::Maxwell3D(MemoryManager& memory_manager) : memory_manager(memory_manager) {} +Maxwell3D::Maxwell3D(MemoryManager& memory_manager) + : memory_manager(memory_manager), macro_interpreter(*this) {} void Maxwell3D::SubmitMacroCode(u32 entry, std::vector code) { uploaded_macros[entry * 2 + MacroRegistersStart] = std::move(code); } -void Maxwell3D::CallMacroMethod(u32 method, const std::vector& parameters) { - // TODO(Subv): Write an interpreter for the macros uploaded via registers 0x45 and 0x47 - +void Maxwell3D::CallMacroMethod(u32 method, std::vector parameters) { + auto macro_code = uploaded_macros.find(method); // The requested macro must have been uploaded already. - ASSERT_MSG(uploaded_macros.find(method) != uploaded_macros.end(), "Macro %08X was not uploaded", - method); - - auto itr = method_handlers.find(method); - ASSERT_MSG(itr != method_handlers.end(), "Unhandled method call %08X", method); - - ASSERT(itr->second.arguments == parameters.size()); - - (this->*itr->second.handler)(parameters); + ASSERT_MSG(macro_code != uploaded_macros.end(), "Macro %08X was not uploaded", method); - // Reset the current macro and its parameters. + // Reset the current macro and execute it. executing_macro = 0; - macro_params.clear(); + macro_interpreter.Execute(macro_code->second, std::move(parameters)); } void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) { @@ -77,7 +63,7 @@ void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) { // Call the macro when there are no more parameters in the command buffer if (remaining_params == 0) { - CallMacroMethod(executing_macro, macro_params); + CallMacroMethod(executing_macro, std::move(macro_params)); } return; } @@ -193,84 +179,6 @@ void Maxwell3D::DrawArrays() { VideoCore::g_renderer->Rasterizer()->AccelerateDrawBatch(false /*is_indexed*/); } -void Maxwell3D::BindTextureInfoBuffer(const std::vector& parameters) { - /** - * Parameters description: - * [0] = Shader stage, usually 4 for FragmentShader - */ - - u32 stage = parameters[0]; - - // Perform the same operations as the real macro code. - GPUVAddr address = static_cast(regs.tex_info_buffers.address[stage]) << 8; - u32 size = regs.tex_info_buffers.size[stage]; - - regs.const_buffer.cb_size = size; - regs.const_buffer.cb_address_high = address >> 32; - regs.const_buffer.cb_address_low = address & 0xFFFFFFFF; -} - -void Maxwell3D::SetShader(const std::vector& parameters) { - /** - * Parameters description: - * [0] = Shader Program. - * [1] = Unknown, presumably the shader id. - * [2] = Offset to the start of the shader, after the 0x30 bytes header. - * [3] = Shader Stage. - * [4] = Const Buffer Address >> 8. - */ - auto shader_program = static_cast(parameters[0]); - // TODO(Subv): This address is probably an offset from the CODE_ADDRESS register. - GPUVAddr address = parameters[2]; - auto shader_stage = static_cast(parameters[3]); - GPUVAddr cb_address = parameters[4] << 8; - - auto& shader = state.shader_programs[static_cast(shader_program)]; - shader.program = shader_program; - shader.stage = shader_stage; - shader.address = address; - - // Perform the same operations as the real macro code. - // TODO(Subv): Early exit if register 0xD1C + shader_program contains the same as params[1]. - auto& shader_regs = regs.shader_config[static_cast(shader_program)]; - shader_regs.start_id = address; - // TODO(Subv): Write params[1] to register 0xD1C + shader_program. - // TODO(Subv): Write params[2] to register 0xD22 + shader_program. - - // Note: This value is hardcoded in the macro's code. - static constexpr u32 DefaultCBSize = 0x10000; - regs.const_buffer.cb_size = DefaultCBSize; - regs.const_buffer.cb_address_high = cb_address >> 32; - regs.const_buffer.cb_address_low = cb_address & 0xFFFFFFFF; - - // Write a hardcoded 0x11 to CB_BIND, this binds the current const buffer to buffer c1[] in the - // shader. It's likely that these are the constants for the shader. - regs.cb_bind[static_cast(shader_stage)].valid.Assign(1); - regs.cb_bind[static_cast(shader_stage)].index.Assign(1); - - ProcessCBBind(shader_stage); -} - -void Maxwell3D::BindStorageBuffer(const std::vector& parameters) { - /** - * Parameters description: - * [0] = Buffer offset >> 2 - */ - - u32 buffer_offset = parameters[0] << 2; - - // Perform the same operations as the real macro code. - // Note: This value is hardcoded in the macro's code. - static constexpr u32 DefaultCBSize = 0x5F00; - regs.const_buffer.cb_size = DefaultCBSize; - - GPUVAddr address = regs.ssbo_info.BufferAddress(); - regs.const_buffer.cb_address_high = address >> 32; - regs.const_buffer.cb_address_low = address & 0xFFFFFFFF; - - regs.const_buffer.cb_pos = buffer_offset; -} - void Maxwell3D::ProcessCBBind(Regs::ShaderStage stage) { // Bind the buffer currently in CB_ADDRESS to the specified index in the desired shader stage. auto& shader = state.shader_stages[static_cast(stage)]; -- cgit v1.2.3