Browse Source

VideoCore/GPU: Delegate subchannel engines to the dma pusher.

Fernando Sahmkow 6 years ago
parent
commit
b87422a86f
3 changed files with 49 additions and 4 deletions
  1. 17 3
      src/video_core/dma_pusher.cpp
  2. 11 0
      src/video_core/dma_pusher.h
  3. 21 1
      src/video_core/gpu.cpp

+ 17 - 3
src/video_core/dma_pusher.cpp

@@ -27,6 +27,8 @@ void DmaPusher::DispatchCalls() {
 
     dma_pushbuffer_subindex = 0;
 
+    dma_state.is_last_call = true;
+
     while (system.IsPoweredOn()) {
         if (!Step()) {
             break;
@@ -82,9 +84,11 @@ bool DmaPusher::Step() {
                     index);
                 CallMultiMethod(&command_header.argument, max_write);
                 dma_state.method_count -= max_write;
+                dma_state.is_last_call = true;
                 index += max_write;
                 continue;
             } else {
+                dma_state.is_last_call = dma_state.method_count <= 1;
                 CallMethod(command_header.argument);
             }
 
@@ -144,12 +148,22 @@ void DmaPusher::SetState(const CommandHeader& command_header) {
 }
 
 void DmaPusher::CallMethod(u32 argument) const {
-    gpu.CallMethod({dma_state.method, argument, dma_state.subchannel, dma_state.method_count});
+    if (dma_state.method < non_puller_methods) {
+        gpu.CallMethod({dma_state.method, argument, dma_state.subchannel, dma_state.method_count});
+    } else {
+        subchannels[dma_state.subchannel]->CallMethod(dma_state.method, argument,
+                                                      dma_state.is_last_call);
+    }
 }
 
 void DmaPusher::CallMultiMethod(const u32* base_start, u32 num_methods) const {
-    gpu.CallMultiMethod(dma_state.method, dma_state.subchannel, base_start, num_methods,
-                        dma_state.method_count);
+    if (dma_state.method < non_puller_methods) {
+        gpu.CallMultiMethod(dma_state.method, dma_state.subchannel, base_start, num_methods,
+                            dma_state.method_count);
+    } else {
+        subchannels[dma_state.subchannel]->CallMultiMethod(dma_state.method, base_start,
+                                                           num_methods, dma_state.method_count);
+    }
 }
 
 } // namespace Tegra

+ 11 - 0
src/video_core/dma_pusher.h

@@ -4,11 +4,13 @@
 
 #pragma once
 
+#include <array>
 #include <vector>
 #include <queue>
 
 #include "common/bit_field.h"
 #include "common/common_types.h"
+#include "video_core/engines/engine_interface.h"
 
 namespace Core {
 class System;
@@ -69,7 +71,13 @@ public:
 
     void DispatchCalls();
 
+    void BindSubchannel(Tegra::Engines::EngineInterface* engine, u32 subchannel_id) {
+        subchannels[subchannel_id] = engine;
+    }
+
 private:
+    static constexpr u32 non_puller_methods = 0x40;
+    static constexpr u32 max_subchannels = 8;
     bool Step();
 
     void SetState(const CommandHeader& command_header);
@@ -88,6 +96,7 @@ private:
         u32 method_count;      ///< Current method count
         u32 length_pending;    ///< Large NI command length pending
         bool non_incrementing; ///< Current command's NI flag
+        bool is_last_call;
     };
 
     DmaState dma_state{};
@@ -96,6 +105,8 @@ private:
     GPUVAddr dma_mget{};  ///< main pushbuffer last read address
     bool ib_enable{true}; ///< IB mode enabled
 
+    std::array<Tegra::Engines::EngineInterface*, max_subchannels> subchannels{};
+
     GPU& gpu;
     Core::System& system;
 };

+ 21 - 1
src/video_core/gpu.cpp

@@ -347,7 +347,27 @@ void GPU::ProcessBindMethod(const MethodCall& method_call) {
     // Bind the current subchannel to the desired engine id.
     LOG_DEBUG(HW_GPU, "Binding subchannel {} to engine {}", method_call.subchannel,
               method_call.argument);
-    bound_engines[method_call.subchannel] = static_cast<EngineID>(method_call.argument);
+    auto engine_id = static_cast<EngineID>(method_call.argument);
+    bound_engines[method_call.subchannel] = static_cast<EngineID>(engine_id);
+    switch (engine_id) {
+    case EngineID::FERMI_TWOD_A:
+        dma_pusher->BindSubchannel(fermi_2d.get(), method_call.subchannel);
+        break;
+    case EngineID::MAXWELL_B:
+        dma_pusher->BindSubchannel(maxwell_3d.get(), method_call.subchannel);
+        break;
+    case EngineID::KEPLER_COMPUTE_B:
+        dma_pusher->BindSubchannel(kepler_compute.get(), method_call.subchannel);
+        break;
+    case EngineID::MAXWELL_DMA_COPY_A:
+        dma_pusher->BindSubchannel(maxwell_dma.get(), method_call.subchannel);
+        break;
+    case EngineID::KEPLER_INLINE_TO_MEMORY_B:
+        dma_pusher->BindSubchannel(kepler_memory.get(), method_call.subchannel);
+        break;
+    default:
+        UNIMPLEMENTED_MSG("Unimplemented engine");
+    }
 }
 
 void GPU::ProcessSemaphoreTriggerMethod() {