From abea6fa90c901d0b47487ed38d44511b18f0addf Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 23 Nov 2018 23:20:56 -0500 Subject: gpu: Rewrite GPU command list processing with DmaPusher class. - More accurate impl., fixes Undertale (among other games). --- src/video_core/engines/fermi_2d.cpp | 8 ++--- src/video_core/engines/fermi_2d.h | 2 +- src/video_core/engines/kepler_memory.cpp | 10 +++--- src/video_core/engines/kepler_memory.h | 3 +- src/video_core/engines/maxwell_3d.cpp | 53 ++++++++++++++++-------------- src/video_core/engines/maxwell_3d.h | 2 +- src/video_core/engines/maxwell_compute.cpp | 8 ++--- src/video_core/engines/maxwell_compute.h | 3 +- src/video_core/engines/maxwell_dma.cpp | 8 ++--- src/video_core/engines/maxwell_dma.h | 2 +- 10 files changed, 52 insertions(+), 47 deletions(-) (limited to 'src/video_core/engines') diff --git a/src/video_core/engines/fermi_2d.cpp b/src/video_core/engines/fermi_2d.cpp index 8d0700d13..dbea5bb5e 100644 --- a/src/video_core/engines/fermi_2d.cpp +++ b/src/video_core/engines/fermi_2d.cpp @@ -14,13 +14,13 @@ namespace Tegra::Engines { Fermi2D::Fermi2D(VideoCore::RasterizerInterface& rasterizer, MemoryManager& memory_manager) : memory_manager(memory_manager), rasterizer{rasterizer} {} -void Fermi2D::WriteReg(u32 method, u32 value) { - ASSERT_MSG(method < Regs::NUM_REGS, +void Fermi2D::CallMethod(const GPU::MethodCall& method_call) { + ASSERT_MSG(method_call.method < Regs::NUM_REGS, "Invalid Fermi2D register, increase the size of the Regs structure"); - regs.reg_array[method] = value; + regs.reg_array[method_call.method] = method_call.argument; - switch (method) { + switch (method_call.method) { case FERMI2D_REG_INDEX(trigger): { HandleSurfaceCopy(); break; diff --git a/src/video_core/engines/fermi_2d.h b/src/video_core/engines/fermi_2d.h index 2a6e8bbbb..50009bf75 100644 --- a/src/video_core/engines/fermi_2d.h +++ b/src/video_core/engines/fermi_2d.h @@ -27,7 +27,7 @@ public: ~Fermi2D() = default; /// Write the value to the register identified by method. - void WriteReg(u32 method, u32 value); + void CallMethod(const GPU::MethodCall& method_call); struct Regs { static constexpr std::size_t NUM_REGS = 0x258; diff --git a/src/video_core/engines/kepler_memory.cpp b/src/video_core/engines/kepler_memory.cpp index 2adbc9eaf..4880191fc 100644 --- a/src/video_core/engines/kepler_memory.cpp +++ b/src/video_core/engines/kepler_memory.cpp @@ -17,19 +17,19 @@ KeplerMemory::KeplerMemory(VideoCore::RasterizerInterface& rasterizer, KeplerMemory::~KeplerMemory() = default; -void KeplerMemory::WriteReg(u32 method, u32 value) { - ASSERT_MSG(method < Regs::NUM_REGS, +void KeplerMemory::CallMethod(const GPU::MethodCall& method_call) { + ASSERT_MSG(method_call.method < Regs::NUM_REGS, "Invalid KeplerMemory register, increase the size of the Regs structure"); - regs.reg_array[method] = value; + regs.reg_array[method_call.method] = method_call.argument; - switch (method) { + switch (method_call.method) { case KEPLERMEMORY_REG_INDEX(exec): { state.write_offset = 0; break; } case KEPLERMEMORY_REG_INDEX(data): { - ProcessData(value); + ProcessData(method_call.argument); break; } } diff --git a/src/video_core/engines/kepler_memory.h b/src/video_core/engines/kepler_memory.h index bf4a13cff..fe9ebc5b9 100644 --- a/src/video_core/engines/kepler_memory.h +++ b/src/video_core/engines/kepler_memory.h @@ -9,6 +9,7 @@ #include "common/bit_field.h" #include "common/common_funcs.h" #include "common/common_types.h" +#include "video_core/gpu.h" #include "video_core/memory_manager.h" namespace VideoCore { @@ -26,7 +27,7 @@ public: ~KeplerMemory(); /// Write the value to the register identified by method. - void WriteReg(u32 method, u32 value); + void CallMethod(const GPU::MethodCall& method_call); struct Regs { static constexpr size_t NUM_REGS = 0x7F; diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index f0a5470b9..b19b3a75a 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp @@ -97,71 +97,74 @@ void Maxwell3D::CallMacroMethod(u32 method, std::vector parameters) { macro_interpreter.Execute(search->second, std::move(parameters)); } -void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) { +void Maxwell3D::CallMethod(const GPU::MethodCall& method_call) { auto debug_context = Core::System::GetInstance().GetGPUDebugContext(); // It is an error to write to a register other than the current macro's ARG register before it // has finished execution. if (executing_macro != 0) { - ASSERT(method == executing_macro + 1); + ASSERT(method_call.method == executing_macro + 1); } // Methods after 0xE00 are special, they're actually triggers for some microcode that was // uploaded to the GPU during initialization. - if (method >= MacroRegistersStart) { + if (method_call.method >= MacroRegistersStart) { // We're trying to execute a macro if (executing_macro == 0) { // A macro call must begin by writing the macro method's register, not its argument. - ASSERT_MSG((method % 2) == 0, + ASSERT_MSG((method_call.method % 2) == 0, "Can't start macro execution by writing to the ARGS register"); - executing_macro = method; + executing_macro = method_call.method; } - macro_params.push_back(value); + macro_params.push_back(method_call.argument); // Call the macro when there are no more parameters in the command buffer - if (remaining_params == 0) { + if (method_call.IsLastCall()) { CallMacroMethod(executing_macro, std::move(macro_params)); } return; } - ASSERT_MSG(method < Regs::NUM_REGS, + ASSERT_MSG(method_call.method < Regs::NUM_REGS, "Invalid Maxwell3D register, increase the size of the Regs structure"); if (debug_context) { debug_context->OnEvent(Tegra::DebugContext::Event::MaxwellCommandLoaded, nullptr); } - if (regs.reg_array[method] != value) { - regs.reg_array[method] = value; + if (regs.reg_array[method_call.method] != method_call.argument) { + regs.reg_array[method_call.method] = method_call.argument; // Vertex format - if (method >= MAXWELL3D_REG_INDEX(vertex_attrib_format) && - method < MAXWELL3D_REG_INDEX(vertex_attrib_format) + regs.vertex_attrib_format.size()) { + if (method_call.method >= MAXWELL3D_REG_INDEX(vertex_attrib_format) && + method_call.method < + MAXWELL3D_REG_INDEX(vertex_attrib_format) + regs.vertex_attrib_format.size()) { dirty_flags.vertex_attrib_format = true; } // Vertex buffer - if (method >= MAXWELL3D_REG_INDEX(vertex_array) && - method < MAXWELL3D_REG_INDEX(vertex_array) + 4 * 32) { - dirty_flags.vertex_array |= 1u << ((method - MAXWELL3D_REG_INDEX(vertex_array)) >> 2); - } else if (method >= MAXWELL3D_REG_INDEX(vertex_array_limit) && - method < MAXWELL3D_REG_INDEX(vertex_array_limit) + 2 * 32) { + if (method_call.method >= MAXWELL3D_REG_INDEX(vertex_array) && + method_call.method < MAXWELL3D_REG_INDEX(vertex_array) + 4 * 32) { dirty_flags.vertex_array |= - 1u << ((method - MAXWELL3D_REG_INDEX(vertex_array_limit)) >> 1); - } else if (method >= MAXWELL3D_REG_INDEX(instanced_arrays) && - method < MAXWELL3D_REG_INDEX(instanced_arrays) + 32) { - dirty_flags.vertex_array |= 1u << (method - MAXWELL3D_REG_INDEX(instanced_arrays)); + 1u << ((method_call.method - MAXWELL3D_REG_INDEX(vertex_array)) >> 2); + } else if (method_call.method >= MAXWELL3D_REG_INDEX(vertex_array_limit) && + method_call.method < MAXWELL3D_REG_INDEX(vertex_array_limit) + 2 * 32) { + dirty_flags.vertex_array |= + 1u << ((method_call.method - MAXWELL3D_REG_INDEX(vertex_array_limit)) >> 1); + } else if (method_call.method >= MAXWELL3D_REG_INDEX(instanced_arrays) && + method_call.method < MAXWELL3D_REG_INDEX(instanced_arrays) + 32) { + dirty_flags.vertex_array |= + 1u << (method_call.method - MAXWELL3D_REG_INDEX(instanced_arrays)); } } - switch (method) { + switch (method_call.method) { case MAXWELL3D_REG_INDEX(macros.data): { - ProcessMacroUpload(value); + ProcessMacroUpload(method_call.argument); break; } case MAXWELL3D_REG_INDEX(macros.bind): { - ProcessMacroBind(value); + ProcessMacroBind(method_call.argument); break; } case MAXWELL3D_REG_INDEX(const_buffer.cb_data[0]): @@ -180,7 +183,7 @@ void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) { case MAXWELL3D_REG_INDEX(const_buffer.cb_data[13]): case MAXWELL3D_REG_INDEX(const_buffer.cb_data[14]): case MAXWELL3D_REG_INDEX(const_buffer.cb_data[15]): { - ProcessCBData(value); + ProcessCBData(method_call.argument); break; } case MAXWELL3D_REG_INDEX(cb_bind[0].raw_config): { diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index 9324d9710..84471f181 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h @@ -1080,7 +1080,7 @@ public: u32 GetRegisterValue(u32 method) const; /// Write the value to the register identified by method. - void WriteReg(u32 method, u32 value, u32 remaining_params); + void CallMethod(const GPU::MethodCall& method_call); /// Returns a list of enabled textures for the specified shader stage. std::vector GetStageTextures(Regs::ShaderStage stage) const; diff --git a/src/video_core/engines/maxwell_compute.cpp b/src/video_core/engines/maxwell_compute.cpp index 8b5f08351..656db6a61 100644 --- a/src/video_core/engines/maxwell_compute.cpp +++ b/src/video_core/engines/maxwell_compute.cpp @@ -8,13 +8,13 @@ namespace Tegra::Engines { -void MaxwellCompute::WriteReg(u32 method, u32 value) { - ASSERT_MSG(method < Regs::NUM_REGS, +void MaxwellCompute::CallMethod(const GPU::MethodCall& method_call) { + ASSERT_MSG(method_call.method < Regs::NUM_REGS, "Invalid MaxwellCompute register, increase the size of the Regs structure"); - regs.reg_array[method] = value; + regs.reg_array[method_call.method] = method_call.argument; - switch (method) { + switch (method_call.method) { case MAXWELL_COMPUTE_REG_INDEX(compute): { LOG_CRITICAL(HW_GPU, "Compute shaders are not implemented"); UNREACHABLE(); diff --git a/src/video_core/engines/maxwell_compute.h b/src/video_core/engines/maxwell_compute.h index 6ea934fb9..1d71f11bd 100644 --- a/src/video_core/engines/maxwell_compute.h +++ b/src/video_core/engines/maxwell_compute.h @@ -9,6 +9,7 @@ #include "common/bit_field.h" #include "common/common_funcs.h" #include "common/common_types.h" +#include "video_core/gpu.h" namespace Tegra::Engines { @@ -42,7 +43,7 @@ public: "MaxwellCompute Regs has wrong size"); /// Write the value to the register identified by method. - void WriteReg(u32 method, u32 value); + void CallMethod(const GPU::MethodCall& method_call); }; #define ASSERT_REG_POSITION(field_name, position) \ diff --git a/src/video_core/engines/maxwell_dma.cpp b/src/video_core/engines/maxwell_dma.cpp index a34e884fe..06462f570 100644 --- a/src/video_core/engines/maxwell_dma.cpp +++ b/src/video_core/engines/maxwell_dma.cpp @@ -14,16 +14,16 @@ namespace Tegra::Engines { MaxwellDMA::MaxwellDMA(VideoCore::RasterizerInterface& rasterizer, MemoryManager& memory_manager) : memory_manager(memory_manager), rasterizer{rasterizer} {} -void MaxwellDMA::WriteReg(u32 method, u32 value) { - ASSERT_MSG(method < Regs::NUM_REGS, +void MaxwellDMA::CallMethod(const GPU::MethodCall& method_call) { + ASSERT_MSG(method_call.method < Regs::NUM_REGS, "Invalid MaxwellDMA register, increase the size of the Regs structure"); - regs.reg_array[method] = value; + regs.reg_array[method_call.method] = method_call.argument; #define MAXWELLDMA_REG_INDEX(field_name) \ (offsetof(Tegra::Engines::MaxwellDMA::Regs, field_name) / sizeof(u32)) - switch (method) { + switch (method_call.method) { case MAXWELLDMA_REG_INDEX(exec): { HandleCopy(); break; diff --git a/src/video_core/engines/maxwell_dma.h b/src/video_core/engines/maxwell_dma.h index 5f3704f05..1f8cd65d2 100644 --- a/src/video_core/engines/maxwell_dma.h +++ b/src/video_core/engines/maxwell_dma.h @@ -24,7 +24,7 @@ public: ~MaxwellDMA() = default; /// Write the value to the register identified by method. - void WriteReg(u32 method, u32 value); + void CallMethod(const GPU::MethodCall& method_call); struct Regs { static constexpr std::size_t NUM_REGS = 0x1D6; -- cgit v1.2.3