diff options
| author | bunnei <bunneidev@gmail.com> | 2018-03-16 22:28:22 -0400 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-03-16 22:28:22 -0400 | 
| commit | cd4e8a989cb01eb9cd10c523d8adbea7ca3cd02c (patch) | |
| tree | 51c9d4b007d0e4ddcb0e6833c4908c7a13998680 | |
| parent | 0eff7752648473a1672df1d1ef9fdefd4dbde580 (diff) | |
| parent | 29feece4b849bd40cc6dcef6c60f4bc58707557a (diff) | |
Merge pull request #241 from Subv/gpu_method_call
GPU: Process command mode 5 (IncreaseOnce) differently from other commands
| -rw-r--r-- | src/video_core/command_processor.cpp | 43 | ||||
| -rw-r--r-- | src/video_core/command_processor.h | 2 | ||||
| -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 | 17 | ||||
| -rw-r--r-- | src/video_core/engines/maxwell_3d.h | 22 | ||||
| -rw-r--r-- | src/video_core/engines/maxwell_compute.cpp | 1 | ||||
| -rw-r--r-- | src/video_core/engines/maxwell_compute.h | 8 | ||||
| -rw-r--r-- | src/video_core/gpu.h | 3 | 
9 files changed, 97 insertions, 8 deletions
| diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp index 21d672085..26ba8c40b 100644 --- a/src/video_core/command_processor.cpp +++ b/src/video_core/command_processor.cpp @@ -64,6 +64,35 @@ void GPU::WriteReg(u32 method, u32 subchannel, u32 value) {      }  } +void GPU::CallMethod(u32 method, u32 subchannel, const std::vector<u32>& parameters) { +    LOG_WARNING(HW_GPU, "Processing method %08X on subchannel %u num params %zu", method, +                subchannel, parameters.size()); + +    if (method < static_cast<u32>(BufferMethods::CountBufferMethods)) { +        // TODO(Subv): Research and implement these methods. +        LOG_ERROR(HW_GPU, "Special buffer methods other than Bind are not implemented"); +        return; +    } + +    ASSERT(bound_engines.find(subchannel) != bound_engines.end()); + +    const EngineID engine = bound_engines[subchannel]; + +    switch (engine) { +    case EngineID::FERMI_TWOD_A: +        fermi_2d->CallMethod(method, parameters); +        break; +    case EngineID::MAXWELL_B: +        maxwell_3d->CallMethod(method, parameters); +        break; +    case EngineID::MAXWELL_COMPUTE_B: +        maxwell_compute->CallMethod(method, parameters); +        break; +    default: +        UNIMPLEMENTED(); +    } +} +  void GPU::ProcessCommandList(GPUVAddr address, u32 size) {      // TODO(Subv): PhysicalToVirtualAddress is a misnomer, it converts a GPU VAddr into an      // application VAddr. @@ -96,13 +125,17 @@ void GPU::ProcessCommandList(GPUVAddr address, u32 size) {              ASSERT(header.arg_count.Value() >= 1);              // Use the original method for the first argument and then the next method for all other              // arguments. -            WriteReg(header.method, header.subchannel, Memory::Read32(current_addr)); -            current_addr += sizeof(u32); -            // Use the same method value for all arguments. -            for (unsigned i = 1; i < header.arg_count; ++i) { -                WriteReg(header.method + 1, header.subchannel, Memory::Read32(current_addr)); + +            // Process this command as a method call instead of a register write. Gather +            // all the parameters first and then pass them at once to the CallMethod function. +            std::vector<u32> parameters(header.arg_count); + +            for (unsigned i = 0; i < header.arg_count; ++i) { +                parameters[i] = Memory::Read32(current_addr);                  current_addr += sizeof(u32);              } + +            CallMethod(header.method, header.subchannel, parameters);              break;          }          case SubmissionMode::Inline: { diff --git a/src/video_core/command_processor.h b/src/video_core/command_processor.h index b511bfcf7..f7214ffec 100644 --- a/src/video_core/command_processor.h +++ b/src/video_core/command_processor.h @@ -34,6 +34,4 @@ static_assert(std::is_standard_layout<CommandHeader>::value == true,                "CommandHeader does not use standard layout");  static_assert(sizeof(CommandHeader) == sizeof(u32), "CommandHeader has incorrect size!"); -void ProcessCommandList(VAddr address, u32 size); -  } // namespace Tegra diff --git a/src/video_core/engines/fermi_2d.cpp b/src/video_core/engines/fermi_2d.cpp index 7aab163dc..6c6162cf3 100644 --- a/src/video_core/engines/fermi_2d.cpp +++ b/src/video_core/engines/fermi_2d.cpp @@ -8,6 +8,7 @@ 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 8967ddede..ce8920cee 100644 --- a/src/video_core/engines/fermi_2d.h +++ b/src/video_core/engines/fermi_2d.h @@ -4,6 +4,7 @@  #pragma once +#include <vector>  #include "common/common_types.h"  namespace Tegra { @@ -16,6 +17,13 @@ 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 8c6d1172c..1b963e87e 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp @@ -8,8 +8,23 @@  namespace Tegra {  namespace Engines { +const std::unordered_map<u32, Maxwell3D::MethodInfo> Maxwell3D::method_handlers = { +    {0xE24, {"PrepareShader", 5, &Maxwell3D::PrepareShader}}, +}; +  Maxwell3D::Maxwell3D(MemoryManager& memory_manager) : memory_manager(memory_manager) {} +void Maxwell3D::CallMethod(u32 method, const std::vector<u32>& parameters) { +    auto itr = method_handlers.find(method); +    if (itr == method_handlers.end()) { +        LOG_ERROR(HW_GPU, "Unhandled method call %08X", method); +        return; +    } + +    ASSERT(itr->second.arguments == parameters.size()); +    (this->*itr->second.handler)(parameters); +} +  void Maxwell3D::WriteReg(u32 method, u32 value) {      ASSERT_MSG(method < Regs::NUM_REGS,                 "Invalid Maxwell3D register, increase the size of the Regs structure"); @@ -64,5 +79,7 @@ void Maxwell3D::DrawArrays() {      LOG_WARNING(HW_GPU, "Game requested a DrawArrays, ignoring");  } +void Maxwell3D::PrepareShader(const std::vector<u32>& parameters) {} +  } // namespace Engines  } // namespace Tegra diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index a2ad28732..8870ef119 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h @@ -4,6 +4,8 @@  #pragma once +#include <unordered_map> +#include <vector>  #include "common/bit_field.h"  #include "common/common_funcs.h"  #include "common/common_types.h" @@ -20,6 +22,13 @@ 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); +      /// Register structure of the Maxwell3D engine.      /// TODO(Subv): This structure will need to be made bigger as more registers are discovered.      struct Regs { @@ -112,13 +121,24 @@ public:      static_assert(sizeof(Regs) == Regs::NUM_REGS * sizeof(u32), "Maxwell3D Regs has wrong size");  private: +    MemoryManager& memory_manager; +      /// Handles a write to the QUERY_GET register.      void ProcessQueryGet();      /// Handles a write to the VERTEX_END_GL register, triggering a draw.      void DrawArrays(); -    MemoryManager& memory_manager; +    /// Method call handlers +    void PrepareShader(const std::vector<u32>& parameters); + +    struct MethodInfo { +        const char* name; +        u32 arguments; +        void (Maxwell3D::*handler)(const std::vector<u32>& parameters); +    }; + +    static const std::unordered_map<u32, MethodInfo> method_handlers;  };  #define ASSERT_REG_POSITION(field_name, position)                                                  \ diff --git a/src/video_core/engines/maxwell_compute.cpp b/src/video_core/engines/maxwell_compute.cpp index e4e5f9e5e..3bef7fe86 100644 --- a/src/video_core/engines/maxwell_compute.cpp +++ b/src/video_core/engines/maxwell_compute.cpp @@ -8,6 +8,7 @@ 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 7262e1bcb..5fc7ed635 100644 --- a/src/video_core/engines/maxwell_compute.h +++ b/src/video_core/engines/maxwell_compute.h @@ -4,6 +4,7 @@  #pragma once +#include <vector>  #include "common/common_types.h"  namespace Tegra { @@ -16,6 +17,13 @@ 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/gpu.h b/src/video_core/gpu.h index ba7781756..c5ec6fdef 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h @@ -41,6 +41,9 @@ private:      /// Writes a single register in the engine bound to the specified subchannel      void WriteReg(u32 method, u32 subchannel, u32 value); +    /// Calls a method in the engine bound to the specified subchannel with the input parameters. +    void CallMethod(u32 method, u32 subchannel, const std::vector<u32>& parameters); +      /// Mapping of command subchannels to their bound engine ids.      std::unordered_map<u32, EngineID> bound_engines; | 
