Răsfoiți Sursa

video_core: Implement maxwell inline_index method

FengChen 3 ani în urmă
părinte
comite
2f90694797

+ 94 - 66
src/video_core/engines/maxwell_3d.cpp

@@ -126,6 +126,9 @@ void Maxwell3D::InitializeRegisterDefaults() {
     draw_command[MAXWELL3D_REG_INDEX(index_buffer32_first)] = true;
     draw_command[MAXWELL3D_REG_INDEX(index_buffer32_first)] = true;
     draw_command[MAXWELL3D_REG_INDEX(index_buffer16_first)] = true;
     draw_command[MAXWELL3D_REG_INDEX(index_buffer16_first)] = true;
     draw_command[MAXWELL3D_REG_INDEX(index_buffer8_first)] = true;
     draw_command[MAXWELL3D_REG_INDEX(index_buffer8_first)] = true;
+    draw_command[MAXWELL3D_REG_INDEX(draw_inline_index)] = true;
+    draw_command[MAXWELL3D_REG_INDEX(inline_index_2x16.even)] = true;
+    draw_command[MAXWELL3D_REG_INDEX(inline_index_4x8.index0)] = true;
 }
 }
 
 
 void Maxwell3D::ProcessMacro(u32 method, const u32* base_start, u32 amount, bool is_last_call) {
 void Maxwell3D::ProcessMacro(u32 method, const u32* base_start, u32 amount, bool is_last_call) {
@@ -271,6 +274,23 @@ void Maxwell3D::CallMethod(u32 method, u32 method_argument, bool is_last_call) {
     if (draw_command[method]) {
     if (draw_command[method]) {
         regs.reg_array[method] = method_argument;
         regs.reg_array[method] = method_argument;
         deferred_draw_method.push_back(method);
         deferred_draw_method.push_back(method);
+        auto u32_to_u8 = [&](const u32 argument) {
+            inline_index_draw_indexes.push_back(static_cast<u8>(argument & 0x000000ff));
+            inline_index_draw_indexes.push_back(static_cast<u8>((argument & 0x0000ff00) >> 8));
+            inline_index_draw_indexes.push_back(static_cast<u8>((argument & 0x00ff0000) >> 16));
+            inline_index_draw_indexes.push_back(static_cast<u8>((argument & 0xff000000) >> 24));
+        };
+        if (MAXWELL3D_REG_INDEX(draw_inline_index) == method) {
+            u32_to_u8(method_argument);
+        } else if (MAXWELL3D_REG_INDEX(inline_index_2x16.even) == method) {
+            u32_to_u8(regs.inline_index_2x16.even);
+            u32_to_u8(regs.inline_index_2x16.odd);
+        } else if (MAXWELL3D_REG_INDEX(inline_index_4x8.index0) == method) {
+            u32_to_u8(regs.inline_index_4x8.index0);
+            u32_to_u8(regs.inline_index_4x8.index1);
+            u32_to_u8(regs.inline_index_4x8.index2);
+            u32_to_u8(regs.inline_index_4x8.index3);
+        }
     } else {
     } else {
         ProcessDeferredDraw();
         ProcessDeferredDraw();
 
 
@@ -567,86 +587,94 @@ void Maxwell3D::ProcessClearBuffers() {
 }
 }
 
 
 void Maxwell3D::ProcessDeferredDraw() {
 void Maxwell3D::ProcessDeferredDraw() {
-    auto method_count = deferred_draw_method.size();
-    if (method_count) {
-        enum class DrawMode {
-            Undefined,
-            General,
-            Instance,
-        };
-        DrawMode draw_mode{DrawMode::Undefined};
-        u32 instance_count = 1;
-
-        auto first_method = deferred_draw_method[0];
-        if (MAXWELL3D_REG_INDEX(draw.begin) == first_method) {
-            // The minimum number of methods for drawing must be greater than or equal to
-            // 3[draw.begin->vertex(index)count->draw.end] to avoid errors in index mode drawing
-            if (method_count < 3) {
-                return;
-            }
-            draw_mode =
-                (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Subsequent) ||
-                        (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Unchanged)
-                    ? DrawMode::Instance
-                    : DrawMode::General;
-        } else if (MAXWELL3D_REG_INDEX(index_buffer32_first) == first_method ||
-                   MAXWELL3D_REG_INDEX(index_buffer16_first) == first_method ||
-                   MAXWELL3D_REG_INDEX(index_buffer8_first) == first_method) {
-            draw_mode = DrawMode::General;
-        }
+    if (deferred_draw_method.empty()) {
+        return;
+    }
+
+    enum class DrawMode {
+        Undefined,
+        General,
+        Instance,
+    };
+    DrawMode draw_mode{DrawMode::Undefined};
+    u32 instance_count = 1;
 
 
-        // Drawing will only begin with draw.begin or index_buffer method, other methods directly
-        // clear
-        if (draw_mode == DrawMode::Undefined) {
-            deferred_draw_method.clear();
+    auto first_method = deferred_draw_method[0];
+    if (MAXWELL3D_REG_INDEX(draw.begin) == first_method) {
+        // The minimum number of methods for drawing must be greater than or equal to
+        // 3[draw.begin->vertex(index)count->draw.end] to avoid errors in index mode drawing
+        if (deferred_draw_method.size() < 3) {
             return;
             return;
         }
         }
+        draw_mode = (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Subsequent) ||
+                            (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Unchanged)
+                        ? DrawMode::Instance
+                        : DrawMode::General;
+    } else if (MAXWELL3D_REG_INDEX(index_buffer32_first) == first_method ||
+               MAXWELL3D_REG_INDEX(index_buffer16_first) == first_method ||
+               MAXWELL3D_REG_INDEX(index_buffer8_first) == first_method) {
+        draw_mode = DrawMode::General;
+    }
+
+    // Drawing will only begin with draw.begin or index_buffer method, other methods directly
+    // clear
+    if (draw_mode == DrawMode::Undefined) {
+        deferred_draw_method.clear();
+        return;
+    }
 
 
-        if (draw_mode == DrawMode::Instance) {
-            ASSERT_MSG(deferred_draw_method.size() % 4 == 0, "Instance mode method size error");
-            instance_count = static_cast<u32>(deferred_draw_method.size()) / 4;
+    if (draw_mode == DrawMode::Instance) {
+        ASSERT_MSG(deferred_draw_method.size() % 4 == 0, "Instance mode method size error");
+        instance_count = static_cast<u32>(deferred_draw_method.size()) / 4;
+    } else {
+        if (MAXWELL3D_REG_INDEX(index_buffer32_first) == first_method) {
+            regs.index_buffer.count = regs.index_buffer32_first.count;
+            regs.index_buffer.first = regs.index_buffer32_first.first;
+            dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
+        } else if (MAXWELL3D_REG_INDEX(index_buffer32_first) == first_method) {
+            regs.index_buffer.count = regs.index_buffer16_first.count;
+            regs.index_buffer.first = regs.index_buffer16_first.first;
+            dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
+        } else if (MAXWELL3D_REG_INDEX(index_buffer32_first) == first_method) {
+            regs.index_buffer.count = regs.index_buffer8_first.count;
+            regs.index_buffer.first = regs.index_buffer8_first.first;
+            dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
         } else {
         } else {
-            if (MAXWELL3D_REG_INDEX(index_buffer32_first) == first_method) {
-                regs.index_buffer.count = regs.index_buffer32_first.count;
-                regs.index_buffer.first = regs.index_buffer32_first.first;
-                dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
-            } else if (MAXWELL3D_REG_INDEX(index_buffer32_first) == first_method) {
-                regs.index_buffer.count = regs.index_buffer16_first.count;
-                regs.index_buffer.first = regs.index_buffer16_first.first;
-                dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
-            } else if (MAXWELL3D_REG_INDEX(index_buffer32_first) == first_method) {
-                regs.index_buffer.count = regs.index_buffer8_first.count;
-                regs.index_buffer.first = regs.index_buffer8_first.first;
-                dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
+            auto second_method = deferred_draw_method[1];
+            if (MAXWELL3D_REG_INDEX(draw_inline_index) == second_method ||
+                MAXWELL3D_REG_INDEX(inline_index_2x16.even) == second_method ||
+                MAXWELL3D_REG_INDEX(inline_index_4x8.index0) == second_method) {
+                regs.index_buffer.count = static_cast<u32>(inline_index_draw_indexes.size() / 4);
+                regs.index_buffer.format = Regs::IndexFormat::UnsignedInt;
             }
             }
         }
         }
+    }
 
 
-        LOG_TRACE(HW_GPU, "called, topology={}, count={}", regs.draw.topology.Value(),
-                  regs.vertex_buffer.count);
+    LOG_TRACE(HW_GPU, "called, topology={}, count={}", regs.draw.topology.Value(),
+              regs.vertex_buffer.count);
 
 
-        ASSERT_MSG(!(regs.index_buffer.count && regs.vertex_buffer.count),
-                   "Both indexed and direct?");
+    ASSERT_MSG(!(regs.index_buffer.count && regs.vertex_buffer.count), "Both indexed and direct?");
 
 
-        // Both instance configuration registers can not be set at the same time.
-        ASSERT_MSG(regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::First ||
-                       regs.draw.instance_id != Maxwell3D::Regs::Draw::InstanceId::Unchanged,
-                   "Illegal combination of instancing parameters");
+    // Both instance configuration registers can not be set at the same time.
+    ASSERT_MSG(regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::First ||
+                   regs.draw.instance_id != Maxwell3D::Regs::Draw::InstanceId::Unchanged,
+               "Illegal combination of instancing parameters");
 
 
-        ProcessTopologyOverride();
+    ProcessTopologyOverride();
 
 
-        const bool is_indexed = regs.index_buffer.count && !regs.vertex_buffer.count;
-        if (ShouldExecute()) {
-            rasterizer->Draw(is_indexed, instance_count);
-        }
-
-        if (is_indexed) {
-            regs.index_buffer.count = 0;
-        } else {
-            regs.vertex_buffer.count = 0;
-        }
+    const bool is_indexed = regs.index_buffer.count && !regs.vertex_buffer.count;
+    if (ShouldExecute()) {
+        rasterizer->Draw(is_indexed, instance_count);
+    }
 
 
-        deferred_draw_method.clear();
+    if (is_indexed) {
+        regs.index_buffer.count = 0;
+    } else {
+        regs.vertex_buffer.count = 0;
     }
     }
+
+    deferred_draw_method.clear();
+    inline_index_draw_indexes.clear();
 }
 }
 
 
 } // namespace Tegra::Engines
 } // namespace Tegra::Engines

+ 5 - 8
src/video_core/engines/maxwell_3d.h

@@ -1739,14 +1739,11 @@ public:
             Footprint_1x1_Virtual = 2,
             Footprint_1x1_Virtual = 2,
         };
         };
 
 
-        struct InlineIndex4x8Align {
+        struct InlineIndex4x8 {
             union {
             union {
                 BitField<0, 30, u32> count;
                 BitField<0, 30, u32> count;
                 BitField<30, 2, u32> start;
                 BitField<30, 2, u32> start;
             };
             };
-        };
-
-        struct InlineIndex4x8Index {
             union {
             union {
                 BitField<0, 8, u32> index0;
                 BitField<0, 8, u32> index0;
                 BitField<8, 8, u32> index1;
                 BitField<8, 8, u32> index1;
@@ -2836,8 +2833,7 @@ public:
                 u32 depth_write_enabled;                                               ///< 0x12E8
                 u32 depth_write_enabled;                                               ///< 0x12E8
                 u32 alpha_test_enabled;                                                ///< 0x12EC
                 u32 alpha_test_enabled;                                                ///< 0x12EC
                 INSERT_PADDING_BYTES_NOINIT(0x10);
                 INSERT_PADDING_BYTES_NOINIT(0x10);
-                InlineIndex4x8Align inline_index_4x8_align;                            ///< 0x1300
-                InlineIndex4x8Index inline_index_4x8_index;                            ///< 0x1304
+                InlineIndex4x8 inline_index_4x8;                                       ///< 0x1300
                 D3DCullMode d3d_cull_mode;                                             ///< 0x1308
                 D3DCullMode d3d_cull_mode;                                             ///< 0x1308
                 ComparisonOp depth_test_func;                                          ///< 0x130C
                 ComparisonOp depth_test_func;                                          ///< 0x130C
                 f32 alpha_test_ref;                                                    ///< 0x1310
                 f32 alpha_test_ref;                                                    ///< 0x1310
@@ -3083,6 +3079,8 @@ public:
         Tables tables{};
         Tables tables{};
     } dirty;
     } dirty;
 
 
+    std::vector<u8> inline_index_draw_indexes;
+
 private:
 private:
     void InitializeRegisterDefaults();
     void InitializeRegisterDefaults();
 
 
@@ -3377,8 +3375,7 @@ ASSERT_REG_POSITION(alpha_to_coverage_dither, 0x12E0);
 ASSERT_REG_POSITION(blend_per_target_enabled, 0x12E4);
 ASSERT_REG_POSITION(blend_per_target_enabled, 0x12E4);
 ASSERT_REG_POSITION(depth_write_enabled, 0x12E8);
 ASSERT_REG_POSITION(depth_write_enabled, 0x12E8);
 ASSERT_REG_POSITION(alpha_test_enabled, 0x12EC);
 ASSERT_REG_POSITION(alpha_test_enabled, 0x12EC);
-ASSERT_REG_POSITION(inline_index_4x8_align, 0x1300);
-ASSERT_REG_POSITION(inline_index_4x8_index, 0x1304);
+ASSERT_REG_POSITION(inline_index_4x8, 0x1300);
 ASSERT_REG_POSITION(d3d_cull_mode, 0x1308);
 ASSERT_REG_POSITION(d3d_cull_mode, 0x1308);
 ASSERT_REG_POSITION(depth_test_func, 0x130C);
 ASSERT_REG_POSITION(depth_test_func, 0x130C);
 ASSERT_REG_POSITION(alpha_test_ref, 0x1310);
 ASSERT_REG_POSITION(alpha_test_ref, 0x1310);

+ 12 - 0
src/video_core/renderer_opengl/gl_rasterizer.cpp

@@ -222,6 +222,8 @@ void RasterizerOpenGL::Draw(bool is_indexed, u32 instance_count) {
     pipeline->SetEngine(maxwell3d, gpu_memory);
     pipeline->SetEngine(maxwell3d, gpu_memory);
     pipeline->Configure(is_indexed);
     pipeline->Configure(is_indexed);
 
 
+    BindInlineIndexBuffer();
+
     SyncState();
     SyncState();
 
 
     const GLenum primitive_mode = MaxwellToGL::PrimitiveTopology(maxwell3d->regs.draw.topology);
     const GLenum primitive_mode = MaxwellToGL::PrimitiveTopology(maxwell3d->regs.draw.topology);
@@ -1128,6 +1130,16 @@ void RasterizerOpenGL::ReleaseChannel(s32 channel_id) {
     query_cache.EraseChannel(channel_id);
     query_cache.EraseChannel(channel_id);
 }
 }
 
 
+void RasterizerOpenGL::BindInlineIndexBuffer() {
+    if (maxwell3d->inline_index_draw_indexes.empty()) {
+        return;
+    }
+    const auto data_count = static_cast<u32>(maxwell3d->inline_index_draw_indexes.size());
+    auto buffer = Buffer(buffer_cache_runtime, *this, 0, data_count);
+    buffer.ImmediateUpload(0, maxwell3d->inline_index_draw_indexes);
+    buffer_cache_runtime.BindIndexBuffer(buffer, 0, data_count);
+}
+
 AccelerateDMA::AccelerateDMA(BufferCache& buffer_cache_) : buffer_cache{buffer_cache_} {}
 AccelerateDMA::AccelerateDMA(BufferCache& buffer_cache_) : buffer_cache{buffer_cache_} {}
 
 
 bool AccelerateDMA::BufferCopy(GPUVAddr src_address, GPUVAddr dest_address, u64 amount) {
 bool AccelerateDMA::BufferCopy(GPUVAddr src_address, GPUVAddr dest_address, u64 amount) {

+ 2 - 0
src/video_core/renderer_opengl/gl_rasterizer.h

@@ -199,6 +199,8 @@ private:
     /// End a transform feedback
     /// End a transform feedback
     void EndTransformFeedback();
     void EndTransformFeedback();
 
 
+    void BindInlineIndexBuffer();
+
     Tegra::GPU& gpu;
     Tegra::GPU& gpu;
 
 
     const Device& device;
     const Device& device;

+ 15 - 0
src/video_core/renderer_vulkan/vk_rasterizer.cpp

@@ -193,6 +193,8 @@ void RasterizerVulkan::Draw(bool is_indexed, u32 instance_count) {
     pipeline->SetEngine(maxwell3d, gpu_memory);
     pipeline->SetEngine(maxwell3d, gpu_memory);
     pipeline->Configure(is_indexed);
     pipeline->Configure(is_indexed);
 
 
+    BindInlineIndexBuffer();
+
     BeginTransformFeedback();
     BeginTransformFeedback();
 
 
     UpdateDynamicStates();
     UpdateDynamicStates();
@@ -1008,4 +1010,17 @@ void RasterizerVulkan::ReleaseChannel(s32 channel_id) {
     query_cache.EraseChannel(channel_id);
     query_cache.EraseChannel(channel_id);
 }
 }
 
 
+void RasterizerVulkan::BindInlineIndexBuffer() {
+    if (maxwell3d->inline_index_draw_indexes.empty()) {
+        return;
+    }
+    const auto data_count = static_cast<u32>(maxwell3d->inline_index_draw_indexes.size());
+    auto buffer = buffer_cache_runtime.UploadStagingBuffer(data_count);
+    std::memcpy(buffer.mapped_span.data(), maxwell3d->inline_index_draw_indexes.data(), data_count);
+    buffer_cache_runtime.BindIndexBuffer(
+        maxwell3d->regs.draw.topology, maxwell3d->regs.index_buffer.format,
+        maxwell3d->regs.index_buffer.first, maxwell3d->regs.index_buffer.count, buffer.buffer,
+        static_cast<u32>(buffer.offset), data_count);
+}
+
 } // namespace Vulkan
 } // namespace Vulkan

+ 2 - 0
src/video_core/renderer_vulkan/vk_rasterizer.h

@@ -141,6 +141,8 @@ private:
 
 
     void UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs);
     void UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs);
 
 
+    void BindInlineIndexBuffer();
+
     Tegra::GPU& gpu;
     Tegra::GPU& gpu;
 
 
     ScreenInfo& screen_info;
     ScreenInfo& screen_info;