diff options
| author | 2018-11-23 23:20:56 -0500 | |
|---|---|---|
| committer | 2018-11-26 23:14:01 -0500 | |
| commit | abea6fa90c901d0b47487ed38d44511b18f0addf (patch) | |
| tree | 65ba9fc6ff7609ea569ea1e3d05f91caa56ffa14 /src/video_core/engines | |
| parent | Merge pull request #1805 from lioncash/resource (diff) | |
| download | yuzu-abea6fa90c901d0b47487ed38d44511b18f0addf.tar.gz yuzu-abea6fa90c901d0b47487ed38d44511b18f0addf.tar.xz yuzu-abea6fa90c901d0b47487ed38d44511b18f0addf.zip | |
gpu: Rewrite GPU command list processing with DmaPusher class.
- More accurate impl., fixes Undertale (among other games).
Diffstat (limited to 'src/video_core/engines')
| -rw-r--r-- | src/video_core/engines/fermi_2d.cpp | 8 | ||||
| -rw-r--r-- | src/video_core/engines/fermi_2d.h | 2 | ||||
| -rw-r--r-- | src/video_core/engines/kepler_memory.cpp | 10 | ||||
| -rw-r--r-- | src/video_core/engines/kepler_memory.h | 3 | ||||
| -rw-r--r-- | src/video_core/engines/maxwell_3d.cpp | 53 | ||||
| -rw-r--r-- | src/video_core/engines/maxwell_3d.h | 2 | ||||
| -rw-r--r-- | src/video_core/engines/maxwell_compute.cpp | 8 | ||||
| -rw-r--r-- | src/video_core/engines/maxwell_compute.h | 3 | ||||
| -rw-r--r-- | src/video_core/engines/maxwell_dma.cpp | 8 | ||||
| -rw-r--r-- | src/video_core/engines/maxwell_dma.h | 2 |
10 files changed, 52 insertions, 47 deletions
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 { | |||
| 14 | Fermi2D::Fermi2D(VideoCore::RasterizerInterface& rasterizer, MemoryManager& memory_manager) | 14 | Fermi2D::Fermi2D(VideoCore::RasterizerInterface& rasterizer, MemoryManager& memory_manager) |
| 15 | : memory_manager(memory_manager), rasterizer{rasterizer} {} | 15 | : memory_manager(memory_manager), rasterizer{rasterizer} {} |
| 16 | 16 | ||
| 17 | void Fermi2D::WriteReg(u32 method, u32 value) { | 17 | void Fermi2D::CallMethod(const GPU::MethodCall& method_call) { |
| 18 | ASSERT_MSG(method < Regs::NUM_REGS, | 18 | ASSERT_MSG(method_call.method < Regs::NUM_REGS, |
| 19 | "Invalid Fermi2D register, increase the size of the Regs structure"); | 19 | "Invalid Fermi2D register, increase the size of the Regs structure"); |
| 20 | 20 | ||
| 21 | regs.reg_array[method] = value; | 21 | regs.reg_array[method_call.method] = method_call.argument; |
| 22 | 22 | ||
| 23 | switch (method) { | 23 | switch (method_call.method) { |
| 24 | case FERMI2D_REG_INDEX(trigger): { | 24 | case FERMI2D_REG_INDEX(trigger): { |
| 25 | HandleSurfaceCopy(); | 25 | HandleSurfaceCopy(); |
| 26 | break; | 26 | 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: | |||
| 27 | ~Fermi2D() = default; | 27 | ~Fermi2D() = default; |
| 28 | 28 | ||
| 29 | /// Write the value to the register identified by method. | 29 | /// Write the value to the register identified by method. |
| 30 | void WriteReg(u32 method, u32 value); | 30 | void CallMethod(const GPU::MethodCall& method_call); |
| 31 | 31 | ||
| 32 | struct Regs { | 32 | struct Regs { |
| 33 | static constexpr std::size_t NUM_REGS = 0x258; | 33 | 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, | |||
| 17 | 17 | ||
| 18 | KeplerMemory::~KeplerMemory() = default; | 18 | KeplerMemory::~KeplerMemory() = default; |
| 19 | 19 | ||
| 20 | void KeplerMemory::WriteReg(u32 method, u32 value) { | 20 | void KeplerMemory::CallMethod(const GPU::MethodCall& method_call) { |
| 21 | ASSERT_MSG(method < Regs::NUM_REGS, | 21 | ASSERT_MSG(method_call.method < Regs::NUM_REGS, |
| 22 | "Invalid KeplerMemory register, increase the size of the Regs structure"); | 22 | "Invalid KeplerMemory register, increase the size of the Regs structure"); |
| 23 | 23 | ||
| 24 | regs.reg_array[method] = value; | 24 | regs.reg_array[method_call.method] = method_call.argument; |
| 25 | 25 | ||
| 26 | switch (method) { | 26 | switch (method_call.method) { |
| 27 | case KEPLERMEMORY_REG_INDEX(exec): { | 27 | case KEPLERMEMORY_REG_INDEX(exec): { |
| 28 | state.write_offset = 0; | 28 | state.write_offset = 0; |
| 29 | break; | 29 | break; |
| 30 | } | 30 | } |
| 31 | case KEPLERMEMORY_REG_INDEX(data): { | 31 | case KEPLERMEMORY_REG_INDEX(data): { |
| 32 | ProcessData(value); | 32 | ProcessData(method_call.argument); |
| 33 | break; | 33 | break; |
| 34 | } | 34 | } |
| 35 | } | 35 | } |
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 @@ | |||
| 9 | #include "common/bit_field.h" | 9 | #include "common/bit_field.h" |
| 10 | #include "common/common_funcs.h" | 10 | #include "common/common_funcs.h" |
| 11 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
| 12 | #include "video_core/gpu.h" | ||
| 12 | #include "video_core/memory_manager.h" | 13 | #include "video_core/memory_manager.h" |
| 13 | 14 | ||
| 14 | namespace VideoCore { | 15 | namespace VideoCore { |
| @@ -26,7 +27,7 @@ public: | |||
| 26 | ~KeplerMemory(); | 27 | ~KeplerMemory(); |
| 27 | 28 | ||
| 28 | /// Write the value to the register identified by method. | 29 | /// Write the value to the register identified by method. |
| 29 | void WriteReg(u32 method, u32 value); | 30 | void CallMethod(const GPU::MethodCall& method_call); |
| 30 | 31 | ||
| 31 | struct Regs { | 32 | struct Regs { |
| 32 | static constexpr size_t NUM_REGS = 0x7F; | 33 | 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<u32> parameters) { | |||
| 97 | macro_interpreter.Execute(search->second, std::move(parameters)); | 97 | macro_interpreter.Execute(search->second, std::move(parameters)); |
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) { | 100 | void Maxwell3D::CallMethod(const GPU::MethodCall& method_call) { |
| 101 | auto debug_context = Core::System::GetInstance().GetGPUDebugContext(); | 101 | auto debug_context = Core::System::GetInstance().GetGPUDebugContext(); |
| 102 | 102 | ||
| 103 | // It is an error to write to a register other than the current macro's ARG register before it | 103 | // It is an error to write to a register other than the current macro's ARG register before it |
| 104 | // has finished execution. | 104 | // has finished execution. |
| 105 | if (executing_macro != 0) { | 105 | if (executing_macro != 0) { |
| 106 | ASSERT(method == executing_macro + 1); | 106 | ASSERT(method_call.method == executing_macro + 1); |
| 107 | } | 107 | } |
| 108 | 108 | ||
| 109 | // Methods after 0xE00 are special, they're actually triggers for some microcode that was | 109 | // Methods after 0xE00 are special, they're actually triggers for some microcode that was |
| 110 | // uploaded to the GPU during initialization. | 110 | // uploaded to the GPU during initialization. |
| 111 | if (method >= MacroRegistersStart) { | 111 | if (method_call.method >= MacroRegistersStart) { |
| 112 | // We're trying to execute a macro | 112 | // We're trying to execute a macro |
| 113 | if (executing_macro == 0) { | 113 | if (executing_macro == 0) { |
| 114 | // A macro call must begin by writing the macro method's register, not its argument. | 114 | // A macro call must begin by writing the macro method's register, not its argument. |
| 115 | ASSERT_MSG((method % 2) == 0, | 115 | ASSERT_MSG((method_call.method % 2) == 0, |
| 116 | "Can't start macro execution by writing to the ARGS register"); | 116 | "Can't start macro execution by writing to the ARGS register"); |
| 117 | executing_macro = method; | 117 | executing_macro = method_call.method; |
| 118 | } | 118 | } |
| 119 | 119 | ||
| 120 | macro_params.push_back(value); | 120 | macro_params.push_back(method_call.argument); |
| 121 | 121 | ||
| 122 | // Call the macro when there are no more parameters in the command buffer | 122 | // Call the macro when there are no more parameters in the command buffer |
| 123 | if (remaining_params == 0) { | 123 | if (method_call.IsLastCall()) { |
| 124 | CallMacroMethod(executing_macro, std::move(macro_params)); | 124 | CallMacroMethod(executing_macro, std::move(macro_params)); |
| 125 | } | 125 | } |
| 126 | return; | 126 | return; |
| 127 | } | 127 | } |
| 128 | 128 | ||
| 129 | ASSERT_MSG(method < Regs::NUM_REGS, | 129 | ASSERT_MSG(method_call.method < Regs::NUM_REGS, |
| 130 | "Invalid Maxwell3D register, increase the size of the Regs structure"); | 130 | "Invalid Maxwell3D register, increase the size of the Regs structure"); |
| 131 | 131 | ||
| 132 | if (debug_context) { | 132 | if (debug_context) { |
| 133 | debug_context->OnEvent(Tegra::DebugContext::Event::MaxwellCommandLoaded, nullptr); | 133 | debug_context->OnEvent(Tegra::DebugContext::Event::MaxwellCommandLoaded, nullptr); |
| 134 | } | 134 | } |
| 135 | 135 | ||
| 136 | if (regs.reg_array[method] != value) { | 136 | if (regs.reg_array[method_call.method] != method_call.argument) { |
| 137 | regs.reg_array[method] = value; | 137 | regs.reg_array[method_call.method] = method_call.argument; |
| 138 | // Vertex format | 138 | // Vertex format |
| 139 | if (method >= MAXWELL3D_REG_INDEX(vertex_attrib_format) && | 139 | if (method_call.method >= MAXWELL3D_REG_INDEX(vertex_attrib_format) && |
| 140 | method < MAXWELL3D_REG_INDEX(vertex_attrib_format) + regs.vertex_attrib_format.size()) { | 140 | method_call.method < |
| 141 | MAXWELL3D_REG_INDEX(vertex_attrib_format) + regs.vertex_attrib_format.size()) { | ||
| 141 | dirty_flags.vertex_attrib_format = true; | 142 | dirty_flags.vertex_attrib_format = true; |
| 142 | } | 143 | } |
| 143 | 144 | ||
| 144 | // Vertex buffer | 145 | // Vertex buffer |
| 145 | if (method >= MAXWELL3D_REG_INDEX(vertex_array) && | 146 | if (method_call.method >= MAXWELL3D_REG_INDEX(vertex_array) && |
| 146 | method < MAXWELL3D_REG_INDEX(vertex_array) + 4 * 32) { | 147 | method_call.method < MAXWELL3D_REG_INDEX(vertex_array) + 4 * 32) { |
| 147 | dirty_flags.vertex_array |= 1u << ((method - MAXWELL3D_REG_INDEX(vertex_array)) >> 2); | ||
| 148 | } else if (method >= MAXWELL3D_REG_INDEX(vertex_array_limit) && | ||
| 149 | method < MAXWELL3D_REG_INDEX(vertex_array_limit) + 2 * 32) { | ||
| 150 | dirty_flags.vertex_array |= | 148 | dirty_flags.vertex_array |= |
| 151 | 1u << ((method - MAXWELL3D_REG_INDEX(vertex_array_limit)) >> 1); | 149 | 1u << ((method_call.method - MAXWELL3D_REG_INDEX(vertex_array)) >> 2); |
| 152 | } else if (method >= MAXWELL3D_REG_INDEX(instanced_arrays) && | 150 | } else if (method_call.method >= MAXWELL3D_REG_INDEX(vertex_array_limit) && |
| 153 | method < MAXWELL3D_REG_INDEX(instanced_arrays) + 32) { | 151 | method_call.method < MAXWELL3D_REG_INDEX(vertex_array_limit) + 2 * 32) { |
| 154 | dirty_flags.vertex_array |= 1u << (method - MAXWELL3D_REG_INDEX(instanced_arrays)); | 152 | dirty_flags.vertex_array |= |
| 153 | 1u << ((method_call.method - MAXWELL3D_REG_INDEX(vertex_array_limit)) >> 1); | ||
| 154 | } else if (method_call.method >= MAXWELL3D_REG_INDEX(instanced_arrays) && | ||
| 155 | method_call.method < MAXWELL3D_REG_INDEX(instanced_arrays) + 32) { | ||
| 156 | dirty_flags.vertex_array |= | ||
| 157 | 1u << (method_call.method - MAXWELL3D_REG_INDEX(instanced_arrays)); | ||
| 155 | } | 158 | } |
| 156 | } | 159 | } |
| 157 | 160 | ||
| 158 | switch (method) { | 161 | switch (method_call.method) { |
| 159 | case MAXWELL3D_REG_INDEX(macros.data): { | 162 | case MAXWELL3D_REG_INDEX(macros.data): { |
| 160 | ProcessMacroUpload(value); | 163 | ProcessMacroUpload(method_call.argument); |
| 161 | break; | 164 | break; |
| 162 | } | 165 | } |
| 163 | case MAXWELL3D_REG_INDEX(macros.bind): { | 166 | case MAXWELL3D_REG_INDEX(macros.bind): { |
| 164 | ProcessMacroBind(value); | 167 | ProcessMacroBind(method_call.argument); |
| 165 | break; | 168 | break; |
| 166 | } | 169 | } |
| 167 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[0]): | 170 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[0]): |
| @@ -180,7 +183,7 @@ void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) { | |||
| 180 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[13]): | 183 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[13]): |
| 181 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[14]): | 184 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[14]): |
| 182 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[15]): { | 185 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[15]): { |
| 183 | ProcessCBData(value); | 186 | ProcessCBData(method_call.argument); |
| 184 | break; | 187 | break; |
| 185 | } | 188 | } |
| 186 | case MAXWELL3D_REG_INDEX(cb_bind[0].raw_config): { | 189 | 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: | |||
| 1080 | u32 GetRegisterValue(u32 method) const; | 1080 | u32 GetRegisterValue(u32 method) const; |
| 1081 | 1081 | ||
| 1082 | /// Write the value to the register identified by method. | 1082 | /// Write the value to the register identified by method. |
| 1083 | void WriteReg(u32 method, u32 value, u32 remaining_params); | 1083 | void CallMethod(const GPU::MethodCall& method_call); |
| 1084 | 1084 | ||
| 1085 | /// Returns a list of enabled textures for the specified shader stage. | 1085 | /// Returns a list of enabled textures for the specified shader stage. |
| 1086 | std::vector<Texture::FullTextureInfo> GetStageTextures(Regs::ShaderStage stage) const; | 1086 | std::vector<Texture::FullTextureInfo> 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 @@ | |||
| 8 | 8 | ||
| 9 | namespace Tegra::Engines { | 9 | namespace Tegra::Engines { |
| 10 | 10 | ||
| 11 | void MaxwellCompute::WriteReg(u32 method, u32 value) { | 11 | void MaxwellCompute::CallMethod(const GPU::MethodCall& method_call) { |
| 12 | ASSERT_MSG(method < Regs::NUM_REGS, | 12 | ASSERT_MSG(method_call.method < Regs::NUM_REGS, |
| 13 | "Invalid MaxwellCompute register, increase the size of the Regs structure"); | 13 | "Invalid MaxwellCompute register, increase the size of the Regs structure"); |
| 14 | 14 | ||
| 15 | regs.reg_array[method] = value; | 15 | regs.reg_array[method_call.method] = method_call.argument; |
| 16 | 16 | ||
| 17 | switch (method) { | 17 | switch (method_call.method) { |
| 18 | case MAXWELL_COMPUTE_REG_INDEX(compute): { | 18 | case MAXWELL_COMPUTE_REG_INDEX(compute): { |
| 19 | LOG_CRITICAL(HW_GPU, "Compute shaders are not implemented"); | 19 | LOG_CRITICAL(HW_GPU, "Compute shaders are not implemented"); |
| 20 | UNREACHABLE(); | 20 | 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 @@ | |||
| 9 | #include "common/bit_field.h" | 9 | #include "common/bit_field.h" |
| 10 | #include "common/common_funcs.h" | 10 | #include "common/common_funcs.h" |
| 11 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
| 12 | #include "video_core/gpu.h" | ||
| 12 | 13 | ||
| 13 | namespace Tegra::Engines { | 14 | namespace Tegra::Engines { |
| 14 | 15 | ||
| @@ -42,7 +43,7 @@ public: | |||
| 42 | "MaxwellCompute Regs has wrong size"); | 43 | "MaxwellCompute Regs has wrong size"); |
| 43 | 44 | ||
| 44 | /// Write the value to the register identified by method. | 45 | /// Write the value to the register identified by method. |
| 45 | void WriteReg(u32 method, u32 value); | 46 | void CallMethod(const GPU::MethodCall& method_call); |
| 46 | }; | 47 | }; |
| 47 | 48 | ||
| 48 | #define ASSERT_REG_POSITION(field_name, position) \ | 49 | #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 { | |||
| 14 | MaxwellDMA::MaxwellDMA(VideoCore::RasterizerInterface& rasterizer, MemoryManager& memory_manager) | 14 | MaxwellDMA::MaxwellDMA(VideoCore::RasterizerInterface& rasterizer, MemoryManager& memory_manager) |
| 15 | : memory_manager(memory_manager), rasterizer{rasterizer} {} | 15 | : memory_manager(memory_manager), rasterizer{rasterizer} {} |
| 16 | 16 | ||
| 17 | void MaxwellDMA::WriteReg(u32 method, u32 value) { | 17 | void MaxwellDMA::CallMethod(const GPU::MethodCall& method_call) { |
| 18 | ASSERT_MSG(method < Regs::NUM_REGS, | 18 | ASSERT_MSG(method_call.method < Regs::NUM_REGS, |
| 19 | "Invalid MaxwellDMA register, increase the size of the Regs structure"); | 19 | "Invalid MaxwellDMA register, increase the size of the Regs structure"); |
| 20 | 20 | ||
| 21 | regs.reg_array[method] = value; | 21 | regs.reg_array[method_call.method] = method_call.argument; |
| 22 | 22 | ||
| 23 | #define MAXWELLDMA_REG_INDEX(field_name) \ | 23 | #define MAXWELLDMA_REG_INDEX(field_name) \ |
| 24 | (offsetof(Tegra::Engines::MaxwellDMA::Regs, field_name) / sizeof(u32)) | 24 | (offsetof(Tegra::Engines::MaxwellDMA::Regs, field_name) / sizeof(u32)) |
| 25 | 25 | ||
| 26 | switch (method) { | 26 | switch (method_call.method) { |
| 27 | case MAXWELLDMA_REG_INDEX(exec): { | 27 | case MAXWELLDMA_REG_INDEX(exec): { |
| 28 | HandleCopy(); | 28 | HandleCopy(); |
| 29 | break; | 29 | 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: | |||
| 24 | ~MaxwellDMA() = default; | 24 | ~MaxwellDMA() = default; |
| 25 | 25 | ||
| 26 | /// Write the value to the register identified by method. | 26 | /// Write the value to the register identified by method. |
| 27 | void WriteReg(u32 method, u32 value); | 27 | void CallMethod(const GPU::MethodCall& method_call); |
| 28 | 28 | ||
| 29 | struct Regs { | 29 | struct Regs { |
| 30 | static constexpr std::size_t NUM_REGS = 0x1D6; | 30 | static constexpr std::size_t NUM_REGS = 0x1D6; |