From e696d9b3244cde9b18929acb240a301d2e28b653 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Wed, 25 Dec 2024 22:06:46 +0300 Subject: [PATCH] rsx: Add code to detect instanced draw commands --- rpcs3/Emu/RSX/NV47/FW/draw_call.cpp | 40 +++++++++++++++++++++++++++++ rpcs3/Emu/RSX/NV47/FW/draw_call.hpp | 7 +++-- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/rpcs3/Emu/RSX/NV47/FW/draw_call.cpp b/rpcs3/Emu/RSX/NV47/FW/draw_call.cpp index 39c8aa01e7..2d41a0ed75 100644 --- a/rpcs3/Emu/RSX/NV47/FW/draw_call.cpp +++ b/rpcs3/Emu/RSX/NV47/FW/draw_call.cpp @@ -89,6 +89,45 @@ namespace rsx } } + bool draw_clause::check_trivially_instanced() const + { + if (draw_command_ranges.size() <= 1) + { + // Cannot instance one draw call or less + return false; + } + + // For instancing all draw calls must be identical + const auto& ref = draw_command_ranges.front(); + for (const auto& range : draw_command_ranges) + { + if (range.first != ref.first || range.count != ref.count) + { + return false; + } + } + + if (draw_command_barriers.empty()) + { + // Raise alarm here for investigation, we may be missing a corner case. + rsx_log.error("Instanced draw detected, but no command barriers found!"); + return false; + } + + // Barriers must exist, but can only involve updating transform constants (for now) + for (const auto& barrier : draw_command_barriers) + { + if (barrier.type != rsx::transform_constant_load_modifier_barrier && + barrier.type != rsx::transform_constant_update_barrier) + { + // Only transform constant instancing is supported at the moment. + return false; + } + } + + return true; + } + void draw_clause::reset(primitive_type type) { current_range_index = ~0u; @@ -97,6 +136,7 @@ namespace rsx command = draw_command::none; primitive = type; primitive_barrier_enable = false; + is_trivial_instanced_draw = false; draw_command_ranges.clear(); draw_command_barriers.clear(); diff --git a/rpcs3/Emu/RSX/NV47/FW/draw_call.hpp b/rpcs3/Emu/RSX/NV47/FW/draw_call.hpp index 323504ac91..fed734f025 100644 --- a/rpcs3/Emu/RSX/NV47/FW/draw_call.hpp +++ b/rpcs3/Emu/RSX/NV47/FW/draw_call.hpp @@ -51,6 +51,8 @@ namespace rsx } } + bool check_trivially_instanced() const; + public: primitive_type primitive{}; draw_command command{}; @@ -59,6 +61,7 @@ namespace rsx bool is_disjoint_primitive{}; // Set if primitive type does not rely on adjacency information bool primitive_barrier_enable{}; // Set once to signal that a primitive restart barrier can be inserted bool is_rendering{}; // Set while we're actually pushing the draw calls to host GPU + bool is_trivial_instanced_draw{}; // Set if the draw call can be executed on the host GPU as a single instanced draw. simple_array inline_vertex_array{}; @@ -73,8 +76,8 @@ namespace rsx { // End draw call append mode current_range_index = ~0u; - - // TODO + // Check if we can instance on host + is_trivial_instanced_draw = check_trivially_instanced(); } /**