diff options
Diffstat (limited to 'src/video_core/engines')
-rw-r--r-- | src/video_core/engines/fermi_2d.cpp | 1 | ||||
-rw-r--r-- | src/video_core/engines/fermi_2d.h | 8 | ||||
-rw-r--r-- | src/video_core/engines/maxwell_3d.cpp | 52 | ||||
-rw-r--r-- | src/video_core/engines/maxwell_3d.h | 31 | ||||
-rw-r--r-- | src/video_core/engines/maxwell_compute.cpp | 1 | ||||
-rw-r--r-- | src/video_core/engines/maxwell_compute.h | 8 |
6 files changed, 69 insertions, 32 deletions
diff --git a/src/video_core/engines/fermi_2d.cpp b/src/video_core/engines/fermi_2d.cpp index 6c6162cf3..7aab163dc 100644 --- a/src/video_core/engines/fermi_2d.cpp +++ b/src/video_core/engines/fermi_2d.cpp @@ -8,7 +8,6 @@ namespace Tegra { namespace Engines { void Fermi2D::WriteReg(u32 method, u32 value) {} -void Fermi2D::CallMethod(u32 method, const std::vector<u32>& parameters) {} } // namespace Engines } // namespace Tegra diff --git a/src/video_core/engines/fermi_2d.h b/src/video_core/engines/fermi_2d.h index ce8920cee..8967ddede 100644 --- a/src/video_core/engines/fermi_2d.h +++ b/src/video_core/engines/fermi_2d.h @@ -4,7 +4,6 @@ #pragma once -#include <vector> #include "common/common_types.h" namespace Tegra { @@ -17,13 +16,6 @@ public: /// Write the value to the register identified by method. void WriteReg(u32 method, u32 value); - - /** - * Handles a method call to this engine. - * @param method Method to call - * @param parameters Arguments to the method call - */ - void CallMethod(u32 method, const std::vector<u32>& parameters); }; } // namespace Engines diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index db12fc702..49a138c1d 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp @@ -8,28 +8,68 @@ namespace Tegra { namespace Engines { +/// First register id that is actually a Macro call. +constexpr u32 MacroRegistersStart = 0xE00; + const std::unordered_map<u32, Maxwell3D::MethodInfo> Maxwell3D::method_handlers = { {0xE24, {"SetShader", 5, &Maxwell3D::SetShader}}, }; Maxwell3D::Maxwell3D(MemoryManager& memory_manager) : memory_manager(memory_manager) {} -void Maxwell3D::CallMethod(u32 method, const std::vector<u32>& parameters) { +void Maxwell3D::SubmitMacroCode(u32 entry, std::vector<u32> code) { + uploaded_macros[entry * 2 + MacroRegistersStart] = std::move(code); +} + +void Maxwell3D::CallMacroMethod(u32 method, const std::vector<u32>& parameters) { // TODO(Subv): Write an interpreter for the macros uploaded via registers 0x45 and 0x47 + + // 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); - if (itr == method_handlers.end()) { - LOG_ERROR(HW_GPU, "Unhandled method call %08X", method); - return; - } + ASSERT_MSG(itr != method_handlers.end(), "Unhandled method call %08X", method); ASSERT(itr->second.arguments == parameters.size()); + (this->*itr->second.handler)(parameters); + + // Reset the current macro and its parameters. + executing_macro = 0; + macro_params.clear(); } -void Maxwell3D::WriteReg(u32 method, u32 value) { +void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) { ASSERT_MSG(method < Regs::NUM_REGS, "Invalid Maxwell3D register, increase the size of the Regs structure"); + // 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); + } + + // Methods after 0xE00 are special, they're actually triggers for some microcode that was + // uploaded to the GPU during initialization. + if (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, + "Can't start macro execution by writing to the ARGS register"); + executing_macro = method; + } + + macro_params.push_back(value); + + // Call the macro when there are no more parameters in the command buffer + if (remaining_params == 0) { + CallMacroMethod(executing_macro, macro_params); + } + return; + } + regs.reg_array[method] = value; #define MAXWELL3D_REG_INDEX(field_name) (offsetof(Regs, field_name) / sizeof(u32)) diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index 98137f94b..05820a21e 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h @@ -21,14 +21,10 @@ public: ~Maxwell3D() = default; /// Write the value to the register identified by method. - void WriteReg(u32 method, u32 value); + void WriteReg(u32 method, u32 value, u32 remaining_params); - /** - * Handles a method call to this engine. - * @param method Method to call - * @param parameters Arguments to the method call - */ - void CallMethod(u32 method, const std::vector<u32>& parameters); + /// Uploads the code for a GPU macro program associated with the specified entry. + void SubmitMacroCode(u32 entry, std::vector<u32> code); /// Register structure of the Maxwell3D engine. /// TODO(Subv): This structure will need to be made bigger as more registers are discovered. @@ -166,7 +162,11 @@ public: INSERT_PADDING_WORDS(7); } cb_bind[MaxShaderStage]; - INSERT_PADDING_WORDS(0x50A); + INSERT_PADDING_WORDS(0x56); + + u32 tex_cb_index; + + INSERT_PADDING_WORDS(0x4B3); }; std::array<u32, NUM_REGS> reg_array; }; @@ -201,6 +201,20 @@ public: private: MemoryManager& memory_manager; + std::unordered_map<u32, std::vector<u32>> uploaded_macros; + + /// Macro method that is currently being executed / being fed parameters. + u32 executing_macro = 0; + /// Parameters that have been submitted to the macro call so far. + std::vector<u32> macro_params; + + /** + * Call a macro on this engine. + * @param method Method to call + * @param parameters Arguments to the method call + */ + void CallMacroMethod(u32 method, const std::vector<u32>& parameters); + /// Handles a write to the QUERY_GET register. void ProcessQueryGet(); @@ -234,6 +248,7 @@ ASSERT_REG_POSITION(vertex_array_limit[0], 0x7C0); ASSERT_REG_POSITION(shader_config[0], 0x800); ASSERT_REG_POSITION(const_buffer, 0x8E0); ASSERT_REG_POSITION(cb_bind[0], 0x904); +ASSERT_REG_POSITION(tex_cb_index, 0x982); #undef ASSERT_REG_POSITION diff --git a/src/video_core/engines/maxwell_compute.cpp b/src/video_core/engines/maxwell_compute.cpp index 3bef7fe86..e4e5f9e5e 100644 --- a/src/video_core/engines/maxwell_compute.cpp +++ b/src/video_core/engines/maxwell_compute.cpp @@ -8,7 +8,6 @@ namespace Tegra { namespace Engines { void MaxwellCompute::WriteReg(u32 method, u32 value) {} -void MaxwellCompute::CallMethod(u32 method, const std::vector<u32>& parameters) {} } // namespace Engines } // namespace Tegra diff --git a/src/video_core/engines/maxwell_compute.h b/src/video_core/engines/maxwell_compute.h index 5fc7ed635..7262e1bcb 100644 --- a/src/video_core/engines/maxwell_compute.h +++ b/src/video_core/engines/maxwell_compute.h @@ -4,7 +4,6 @@ #pragma once -#include <vector> #include "common/common_types.h" namespace Tegra { @@ -17,13 +16,6 @@ public: /// Write the value to the register identified by method. void WriteReg(u32 method, u32 value); - - /** - * Handles a method call to this engine. - * @param method Method to call - * @param parameters Arguments to the method call - */ - void CallMethod(u32 method, const std::vector<u32>& parameters); }; } // namespace Engines |