diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp index 31e1cea5a..601453aa0 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp @@ -172,6 +172,10 @@ Id EmitGetAttributeU32(EmitContext& ctx, IR::Attribute attr, u32 comp) { return ctx.OpLoad(ctx.U32[1], ctx.vertex_index); case IR::Attribute::InstanceId: return ctx.OpLoad(ctx.U32[1], ctx.instance_id); + case IR::Attribute::BaseVertex: + return ctx.OpLoad(ctx.U32[1], ctx.base_vertex); + case IR::Attribute::BaseInstance: + return ctx.OpLoad(ctx.U32[1], ctx.base_instance); case IR::Attribute::WorkgroupIndex: return ctx.workgroup_index_id; case IR::Attribute::WorkgroupId: diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index 4e64d5f49..d01a22239 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp @@ -5,6 +5,7 @@ #include "common/div_ceil.h" #include "shader_recompiler/backend/spirv/spirv_emit_context.h" #include "shader_recompiler/frontend/fetch_shader.h" +#include "shader_recompiler/ir/attribute.h" #include "shader_recompiler/ir/microinstruction.h" #include "shader_recompiler/runtime_info.h" #include "video_core/buffer_cache/buffer_cache.h" @@ -322,8 +323,15 @@ void EmitContext::DefineInputs() { switch (sw_stage) { case SwStage::Vertex: { vertex_index = DefineVariable(U32[1], spv::BuiltIn::VertexIndex, spv::StorageClass::Input); - base_vertex = DefineVariable(U32[1], spv::BuiltIn::BaseVertex, spv::StorageClass::Input); instance_id = DefineVariable(U32[1], spv::BuiltIn::InstanceIndex, spv::StorageClass::Input); + if (info.loads.Get(IR::Attribute::BaseVertex)) { + base_vertex = + DefineVariable(U32[1], spv::BuiltIn::BaseVertex, spv::StorageClass::Input); + } + if (info.loads.Get(IR::Attribute::BaseInstance)) { + base_instance = + DefineVariable(U32[1], spv::BuiltIn::BaseInstance, spv::StorageClass::Input); + } const auto fetch_shader = Gcn::ParseFetchShader(info); if (!fetch_shader) { diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.h b/src/shader_recompiler/backend/spirv/spirv_emit_context.h index 4c7d130b3..66a43e941 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.h +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.h @@ -253,6 +253,7 @@ public: Id instance_id{}; Id push_data_block{}; Id base_vertex{}; + Id base_instance{}; Id frag_coord{}; Id front_facing{}; Id frag_depth{}; diff --git a/src/shader_recompiler/frontend/translate/translate.cpp b/src/shader_recompiler/frontend/translate/translate.cpp index 29b19220f..d0ec062a0 100644 --- a/src/shader_recompiler/frontend/translate/translate.cpp +++ b/src/shader_recompiler/frontend/translate/translate.cpp @@ -61,6 +61,16 @@ static IR::VectorReg IterateBarycentrics(const RuntimeInfo& runtime_info, auto&& return IR::VectorReg(dst_vreg); } +static s8 UdRegFromShOffset(u16 sgpr_offset, HwStage hw_stage) { + static constexpr std::array indirect_sgpr_offsets{0u, 0x4cu, 0u, 0xccu, 0u, 0x14cu}; + if (sgpr_offset) { + const u32 ud_reg = sgpr_offset - indirect_sgpr_offsets[u32(hw_stage)]; + ASSERT_MSG(ud_reg < 16, "Out of bounds indirect SGPR copy"); + return ud_reg; + } + return -1; +} + Translator::Translator(Info& info_, const RuntimeInfo& runtime_info_, const Profile& profile_) : info{info_}, runtime_info{runtime_info_}, profile{profile_}, next_vgpr_num{runtime_info.props.num_allocated_vgprs} { @@ -84,9 +94,32 @@ void Translator::EmitPrologue(IR::Block* first_block) { IR::VectorReg dst_vreg = IR::VectorReg::V0; switch (info.sw_stage) { - case SwStage::Vertex: + case SwStage::Vertex: { + const s8 base_vertex_sgpr = + UdRegFromShOffset(runtime_info.sw.vs.vertex_sgpr_offset, info.hw_stage); + if (base_vertex_sgpr != -1) { + ir.SetScalarReg(IR::ScalarReg(base_vertex_sgpr), + ir.GetAttributeU32(IR::Attribute::BaseVertex)); + } + const s8 base_instance_sgpr = + UdRegFromShOffset(runtime_info.sw.vs.instance_sgpr_offset, info.hw_stage); + if (base_instance_sgpr != -1) { + ir.SetScalarReg(IR::ScalarReg(base_instance_sgpr), + ir.GetAttributeU32(IR::Attribute::BaseInstance)); + } + // v0: vertex ID, always present - ir.SetVectorReg(dst_vreg++, ir.GetAttributeU32(IR::Attribute::VertexId)); + IR::U32 vertex_id = ir.GetAttributeU32(IR::Attribute::VertexId); + if (base_vertex_sgpr != -1) { + if (!fetch_data || fetch_data->vertex_offset_sgpr == -1) { + vertex_id = ir.ISub(vertex_id, ir.GetAttributeU32(IR::Attribute::BaseVertex)); + } else { + ASSERT_MSG(fetch_data->vertex_offset_sgpr == base_vertex_sgpr, + "Fetch shader in indirect draw uses wrong base vertex"); + } + } + ir.SetVectorReg(dst_vreg++, vertex_id); + if (info.hw_stage == HwStage::Local) { // v1: rel patch ID if (runtime_info.props.num_input_vgprs > 0) { @@ -96,10 +129,6 @@ void Translator::EmitPrologue(IR::Block* first_block) { if (runtime_info.props.num_input_vgprs > 1) { ++dst_vreg; } - // v3: instance ID, plain - if (runtime_info.props.num_input_vgprs > 2) { - ir.SetVectorReg(dst_vreg++, ir.GetAttributeU32(IR::Attribute::InstanceId)); - } } else { // v1: instance ID, step rate 0 if (runtime_info.props.num_input_vgprs > 0) { @@ -121,12 +150,24 @@ void Translator::EmitPrologue(IR::Block* first_block) { ir.SetVectorReg(dst_vreg++, ir.Imm32(0)); } } - // v3: instance ID, plain - if (runtime_info.props.num_input_vgprs > 2) { - ir.SetVectorReg(dst_vreg++, ir.GetAttributeU32(IR::Attribute::InstanceId)); + } + + // v3: instance ID, plain + if (runtime_info.props.num_input_vgprs > 2) { + IR::U32 instance_id = ir.GetAttributeU32(IR::Attribute::InstanceId); + if (base_instance_sgpr != -1) { + if (!fetch_data || fetch_data->instance_offset_sgpr == -1) { + instance_id = + ir.ISub(instance_id, ir.GetAttributeU32(IR::Attribute::BaseInstance)); + } else { + ASSERT_MSG(fetch_data->instance_offset_sgpr == base_instance_sgpr, + "Fetch shader in indirect draw uses wrong base instance"); + } } + ir.SetVectorReg(dst_vreg++, instance_id); } break; + } case SwStage::Fragment: { dst_vreg = IterateBarycentrics(runtime_info, [this](u32 vreg, IR::Attribute attrib, u32 comp) { @@ -1091,7 +1132,7 @@ void Translator::EmitFetch(const GcnInst& inst) { info.has_fetch_shader = true; info.fetch_shader_sgpr_base = code_sgpr_base; - const auto fetch_data = ParseFetchShader(info); + fetch_data = ParseFetchShader(info); ASSERT(fetch_data.has_value()); if (EmulatorSettings.IsDumpShaders()) { diff --git a/src/shader_recompiler/frontend/translate/translate.h b/src/shader_recompiler/frontend/translate/translate.h index 3ba0a5e5e..6655849d2 100644 --- a/src/shader_recompiler/frontend/translate/translate.h +++ b/src/shader_recompiler/frontend/translate/translate.h @@ -5,6 +5,7 @@ #include #include +#include "shader_recompiler/frontend/fetch_shader.h" #include "shader_recompiler/frontend/instruction.h" #include "shader_recompiler/info.h" #include "shader_recompiler/ir/basic_block.h" @@ -391,6 +392,7 @@ private: u32 next_vgpr_num; std::unordered_map vgpr_map; std::array vgpr_to_interp{}; + std::optional fetch_data{}; bool opcode_missing = false; u32 pc{}; }; diff --git a/src/shader_recompiler/ir/attribute.cpp b/src/shader_recompiler/ir/attribute.cpp index d1d9691d3..14fd11b75 100644 --- a/src/shader_recompiler/ir/attribute.cpp +++ b/src/shader_recompiler/ir/attribute.cpp @@ -168,6 +168,10 @@ std::string NameOf(Attribute attribute) { return "PackedAncillary"; case Attribute::SubgroupLtMask: return "SubgroupLtMask"; + case Attribute::BaseVertex: + return "BaseVertex"; + case Attribute::BaseInstance: + return "BaseInstance"; default: break; } diff --git a/src/shader_recompiler/ir/attribute.h b/src/shader_recompiler/ir/attribute.h index a7e52d54f..658c2048b 100644 --- a/src/shader_recompiler/ir/attribute.h +++ b/src/shader_recompiler/ir/attribute.h @@ -92,6 +92,8 @@ enum class Attribute : u64 { SampleMask = 95, PackedAncillary = 96, SubgroupLtMask = 97, + BaseVertex = 98, + BaseInstance = 99, Max, }; diff --git a/src/shader_recompiler/recompiler.cpp b/src/shader_recompiler/recompiler.cpp index 74005d5e5..73953b00f 100644 --- a/src/shader_recompiler/recompiler.cpp +++ b/src/shader_recompiler/recompiler.cpp @@ -33,7 +33,6 @@ IR::BlockList GenerateBlocks(const IR::AbstractSyntaxList& syntax_list) { void EmitControlFlowGraph(IR::Program& program, Pools& pools, Gcn::CFG& cfg, RuntimeInfo& runtime_info, const Profile& profile) { Gcn::Translator translator{program.info, runtime_info, profile}; - bool emit_prologue = true; for (auto& block : cfg) { const u32 start = block.begin_index; const u32 size = block.end_index - start + 1; @@ -42,12 +41,9 @@ void EmitControlFlowGraph(IR::Program& program, Pools& pools, Gcn::CFG& cfg, block.ir_block = ir_block; translator.Translate(ir_block, block.begin, block.cond, std::span{program.ins_list}.subspan(start, size)); - if (emit_prologue) { - translator.EmitPrologue(ir_block); - emit_prologue = false; - } program.blocks.push_back(ir_block); } + translator.EmitPrologue(program.blocks.front()); ASSERT_MSG(!program.info.translation_failed, "Shader translation has failed"); for (auto& block : cfg) { auto* ir_block = block.ir_block; diff --git a/src/shader_recompiler/runtime_info.h b/src/shader_recompiler/runtime_info.h index e1cb1c65a..5b5712114 100644 --- a/src/shader_recompiler/runtime_info.h +++ b/src/shader_recompiler/runtime_info.h @@ -71,6 +71,8 @@ using OutputMap = std::array; struct SwVertexRuntimeInfo { u32 step_rate_0; u32 step_rate_1; + u16 vertex_sgpr_offset{}; + u16 instance_sgpr_offset{}; bool tess_emulated_primitive{}; bool operator==(const SwVertexRuntimeInfo& other) const noexcept = default; diff --git a/src/video_core/amdgpu/liverpool.cpp b/src/video_core/amdgpu/liverpool.cpp index cc7ce6850..9794aa193 100644 --- a/src/video_core/amdgpu/liverpool.cpp +++ b/src/video_core/amdgpu/liverpool.cpp @@ -65,7 +65,7 @@ static std::span NextPacket(std::span span, size_t offset) return span.subspan(offset); } -Liverpool::Liverpool() { +Liverpool::Liverpool() : guest_markers_enabled{EmulatorSettings.IsVkGuestMarkersEnabled()} { num_counter_pairs = Libraries::Kernel::sceKernelIsNeoMode() ? 16 : 8; process_thread = std::jthread{std::bind_front(&Liverpool::Process, this)}; } @@ -229,8 +229,6 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span dcb, std::span(dcb.data()); while (!dcb.empty()) { @@ -427,16 +425,12 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span dcb, std::span(header), regs); } - if (rasterizer) { - const auto cmd_address = reinterpret_cast(header); - if (host_markers_enabled) { - rasterizer->ScopeMarkerBegin(fmt::format("gfx:{}:DrawIndex2", cmd_address)); - rasterizer->Draw(true); - rasterizer->ScopeMarkerEnd(); - } else { - rasterizer->Draw(true); - } + if (!rasterizer) { + break; } + const auto cmd_address = reinterpret_cast(header); + rasterizer->ScopeMarker("gfx:{}:DrawIndex2", fmt::make_format_args(cmd_address), + [&] { rasterizer->Draw(true); }); break; } case PM4ItOpcode::DrawIndexOffset2: { @@ -448,17 +442,13 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span dcb, std::span(header), regs); } - if (rasterizer) { - const auto cmd_address = reinterpret_cast(header); - if (host_markers_enabled) { - rasterizer->ScopeMarkerBegin( - fmt::format("gfx:{}:DrawIndexOffset2", cmd_address)); - rasterizer->Draw(true, draw_index_off->index_offset); - rasterizer->ScopeMarkerEnd(); - } else { - rasterizer->Draw(true, draw_index_off->index_offset); - } + if (!rasterizer) { + break; } + const auto cmd_address = reinterpret_cast(header); + rasterizer->ScopeMarker( + "gfx:{}:DrawIndexOffset2", fmt::make_format_args(cmd_address), + [&] { rasterizer->Draw(true, draw_index_off->index_offset); }); break; } case PM4ItOpcode::DrawIndexAuto: { @@ -468,17 +458,12 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span dcb, std::span(header), regs); } - if (rasterizer) { - const auto cmd_address = reinterpret_cast(header); - if (host_markers_enabled) { - rasterizer->ScopeMarkerBegin( - fmt::format("gfx:{}:DrawIndexAuto", cmd_address)); - rasterizer->Draw(false); - rasterizer->ScopeMarkerEnd(); - } else { - rasterizer->Draw(false); - } + if (!rasterizer) { + break; } + const auto cmd_address = reinterpret_cast(header); + rasterizer->ScopeMarker("gfx:{}:DrawIndexAuto", fmt::make_format_args(cmd_address), + [&] { rasterizer->Draw(false); }); break; } case PM4ItOpcode::DrawIndirect: { @@ -488,17 +473,16 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span dcb, std::span(header), regs); } - if (rasterizer) { - const auto cmd_address = reinterpret_cast(header); - if (host_markers_enabled) { - rasterizer->ScopeMarkerBegin( - fmt::format("gfx:{}:DrawIndirect", cmd_address)); - rasterizer->DrawIndirect(false, indirect_args_addr, offset, stride, 1, 0); - rasterizer->ScopeMarkerEnd(); - } else { - rasterizer->DrawIndirect(false, indirect_args_addr, offset, stride, 1, 0); - } + if (!rasterizer) { + break; } + const auto cmd_address = reinterpret_cast(header); + rasterizer->ScopeMarker( + "gfx:{}:DrawIndirect", fmt::make_format_args(cmd_address), [&] { + rasterizer->DrawIndirect(false, indirect_args_addr, offset, stride, 1, 0, + draw_indirect->base_vtx_loc, + draw_indirect->start_inst_loc); + }); break; } case PM4ItOpcode::DrawIndirectMulti: { @@ -508,19 +492,17 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span dcb, std::span(header), regs); } - if (rasterizer) { - const auto cmd_address = reinterpret_cast(header); - if (host_markers_enabled) { - rasterizer->ScopeMarkerBegin( - fmt::format("gfx:{}:DrawIndirectMulti", cmd_address)); - rasterizer->DrawIndirect(false, indirect_args_addr, offset, - draw_indirect->stride, draw_indirect->count, 0); - rasterizer->ScopeMarkerEnd(); - } else { - rasterizer->DrawIndirect(false, indirect_args_addr, offset, - draw_indirect->stride, draw_indirect->count, 0); - } + if (!rasterizer) { + break; } + const auto cmd_address = reinterpret_cast(header); + rasterizer->ScopeMarker( + "gfx:{}:DrawIndirectMulti", fmt::make_format_args(cmd_address), [&] { + rasterizer->DrawIndirect(false, indirect_args_addr, offset, + draw_indirect->stride, draw_indirect->count, 0, + draw_indirect->base_vtx_loc, + draw_indirect->start_inst_loc); + }); break; } case PM4ItOpcode::DrawIndexIndirect: { @@ -531,17 +513,16 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span dcb, std::span(header), regs); } - if (rasterizer) { - const auto cmd_address = reinterpret_cast(header); - if (host_markers_enabled) { - rasterizer->ScopeMarkerBegin( - fmt::format("gfx:{}:DrawIndexIndirect", cmd_address)); - rasterizer->DrawIndirect(true, indirect_args_addr, offset, stride, 1, 0); - rasterizer->ScopeMarkerEnd(); - } else { - rasterizer->DrawIndirect(true, indirect_args_addr, offset, stride, 1, 0); - } + if (!rasterizer) { + break; } + const auto cmd_address = reinterpret_cast(header); + rasterizer->ScopeMarker( + "gfx:{}:DrawIndexIndirect", fmt::make_format_args(cmd_address), [&] { + rasterizer->DrawIndirect(true, indirect_args_addr, offset, stride, 1, 0, + draw_index_indirect->base_vtx_loc, + draw_index_indirect->start_inst_loc); + }); break; } case PM4ItOpcode::DrawIndexIndirectMulti: { @@ -551,21 +532,17 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span dcb, std::span(header), regs); } - if (rasterizer) { - const auto cmd_address = reinterpret_cast(header); - if (host_markers_enabled) { - rasterizer->ScopeMarkerBegin( - fmt::format("gfx:{}:DrawIndexIndirectMulti", cmd_address)); - rasterizer->DrawIndirect(true, indirect_args_addr, offset, - draw_index_indirect->stride, - draw_index_indirect->count, 0); - rasterizer->ScopeMarkerEnd(); - } else { - rasterizer->DrawIndirect(true, indirect_args_addr, offset, - draw_index_indirect->stride, - draw_index_indirect->count, 0); - } + if (!rasterizer) { + break; } + const auto cmd_address = reinterpret_cast(header); + rasterizer->ScopeMarker( + "gfx:{}:DrawIndexIndirectMulti", fmt::make_format_args(cmd_address), [&] { + rasterizer->DrawIndirect( + true, indirect_args_addr, offset, draw_index_indirect->stride, + draw_index_indirect->count, 0, draw_index_indirect->base_vtx_loc, + draw_index_indirect->start_inst_loc); + }); break; } case PM4ItOpcode::DrawIndexIndirectCountMulti: { @@ -575,27 +552,20 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span dcb, std::span(header), regs); } - if (rasterizer) { - const auto cmd_address = reinterpret_cast(header); - if (host_markers_enabled) { - rasterizer->ScopeMarkerBegin( - fmt::format("gfx:{}:DrawIndexIndirectCountMulti", cmd_address)); - rasterizer->DrawIndirect(true, indirect_args_addr, offset, - draw_index_indirect->stride, - draw_index_indirect->count, - draw_index_indirect->count_indirect_enable.Value() - ? draw_index_indirect->count_addr - : 0); - rasterizer->ScopeMarkerEnd(); - } else { - rasterizer->DrawIndirect(true, indirect_args_addr, offset, - draw_index_indirect->stride, - draw_index_indirect->count, - draw_index_indirect->count_indirect_enable.Value() - ? draw_index_indirect->count_addr - : 0); - } + if (!rasterizer) { + break; } + const auto cmd_address = reinterpret_cast(header); + rasterizer->ScopeMarker( + "gfx:{}:DrawIndexIndirectCountMulti", fmt::make_format_args(cmd_address), [&] { + rasterizer->DrawIndirect( + true, indirect_args_addr, offset, draw_index_indirect->stride, + draw_index_indirect->count, + draw_index_indirect->count_indirect_enable.Value() + ? draw_index_indirect->count_addr + : 0, + draw_index_indirect->base_vtx_loc, draw_index_indirect->start_inst_loc); + }); break; } case PM4ItOpcode::DispatchDirect: { @@ -609,17 +579,12 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span dcb, std::span(header), cs_program); } - if (rasterizer && (cs_program.dispatch_initiator & 1)) { - const auto cmd_address = reinterpret_cast(header); - if (host_markers_enabled) { - rasterizer->ScopeMarkerBegin( - fmt::format("gfx:{}:DispatchDirect", cmd_address)); - rasterizer->DispatchDirect(); - rasterizer->ScopeMarkerEnd(); - } else { - rasterizer->DispatchDirect(); - } + if (!rasterizer || (cs_program.dispatch_initiator & 1) == 0) { + break; } + const auto cmd_address = reinterpret_cast(header); + rasterizer->ScopeMarker("gfx:{}:DispatchDirect", fmt::make_format_args(cmd_address), + [&] { rasterizer->DispatchDirect(); }); break; } case PM4ItOpcode::DispatchIndirect: { @@ -632,17 +597,13 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span dcb, std::span(header), cs_program); } - if (rasterizer && (cs_program.dispatch_initiator & 1)) { - const auto cmd_address = reinterpret_cast(header); - if (host_markers_enabled) { - rasterizer->ScopeMarkerBegin( - fmt::format("gfx:{}:DispatchIndirect", cmd_address)); - rasterizer->DispatchIndirect(indirect_args_addr, offset, size); - rasterizer->ScopeMarkerEnd(); - } else { - rasterizer->DispatchIndirect(indirect_args_addr, offset, size); - } + if (!rasterizer || (cs_program.dispatch_initiator & 1) == 0) { + break; } + const auto cmd_address = reinterpret_cast(header); + rasterizer->ScopeMarker( + "gfx:{}:DispatchIndirect", fmt::make_format_args(cmd_address), + [&] { rasterizer->DispatchIndirect(indirect_args_addr, offset, size); }); break; } case PM4ItOpcode::NumInstances: { @@ -906,7 +867,6 @@ template Liverpool::Task Liverpool::ProcessCompute(std::span acb, u32 vqid) { FIBER_ENTER(acb_task_name[vqid]); auto& queue = asc_queues[{vqid}]; - const bool host_markers_enabled = rasterizer && EmulatorSettings.IsVkHostMarkersEnabled(); struct IndirectPatch { const PM4Header* header; @@ -1076,17 +1036,13 @@ Liverpool::Task Liverpool::ProcessCompute(std::span acb, u32 vqid) { DebugState.PushRegsDumpCompute(base_addr, reinterpret_cast(header), cs_program); } - if (rasterizer && (cs_program.dispatch_initiator & 1)) { - const auto cmd_address = reinterpret_cast(header); - if (host_markers_enabled) { - rasterizer->ScopeMarkerBegin( - fmt::format("asc[{}]:{}:DispatchDirect", vqid, cmd_address)); - rasterizer->DispatchDirect(); - rasterizer->ScopeMarkerEnd(); - } else { - rasterizer->DispatchDirect(); - } + if (!rasterizer || (cs_program.dispatch_initiator & 1) == 0) { + break; } + const auto cmd_address = reinterpret_cast(header); + rasterizer->ScopeMarker("asc[{}]:{}:DispatchDirect", + fmt::make_format_args(vqid, cmd_address), + [&] { rasterizer->DispatchDirect(); }); break; } case PM4ItOpcode::DispatchIndirect: { @@ -1099,17 +1055,13 @@ Liverpool::Task Liverpool::ProcessCompute(std::span acb, u32 vqid) { DebugState.PushRegsDumpCompute(base_addr, reinterpret_cast(header), cs_program); } - if (rasterizer && (cs_program.dispatch_initiator & 1)) { - const auto cmd_address = reinterpret_cast(header); - if (host_markers_enabled) { - rasterizer->ScopeMarkerBegin( - fmt::format("asc[{}]:{}:DispatchIndirect", vqid, cmd_address)); - rasterizer->DispatchIndirect(ib_address, 0, size); - rasterizer->ScopeMarkerEnd(); - } else { - rasterizer->DispatchIndirect(ib_address, 0, size); - } + if (!rasterizer || (cs_program.dispatch_initiator & 1) == 0) { + break; } + const auto cmd_address = reinterpret_cast(header); + rasterizer->ScopeMarker("asc[{}]:{}:DispatchIndirect", + fmt::make_format_args(vqid, cmd_address), + [&] { rasterizer->DispatchIndirect(ib_address, 0, size); }); break; } case PM4ItOpcode::WriteData: { diff --git a/src/video_core/amdgpu/liverpool.h b/src/video_core/amdgpu/liverpool.h index 249ea2ba6..8ad9d7c0c 100644 --- a/src/video_core/amdgpu/liverpool.h +++ b/src/video_core/amdgpu/liverpool.h @@ -222,6 +222,7 @@ private: Vulkan::Rasterizer* rasterizer{}; Libraries::VideoOut::VideoOutPort* vo_port{}; + const bool guest_markers_enabled; std::jthread process_thread{}; std::atomic num_submits{}; std::atomic num_commands{}; diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index ebb31a6f2..10357ae05 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -231,6 +231,8 @@ const Shader::RuntimeInfo& PipelineCache::BuildRuntimeInfo(HwStage stage, SwStag case SwStage::Vertex: info.sw.vs.step_rate_0 = regs.vgt_instance_step_rate_0; info.sw.vs.step_rate_1 = regs.vgt_instance_step_rate_1; + info.sw.vs.vertex_sgpr_offset = draw_indirect_params.vertex_sgpr_offset; + info.sw.vs.instance_sgpr_offset = draw_indirect_params.instance_sgpr_offset; info.sw.vs.tess_emulated_primitive = regs.primitive_type == AmdGpu::PrimitiveType::RectList || regs.primitive_type == AmdGpu::PrimitiveType::QuadList; @@ -322,7 +324,8 @@ PipelineCache::PipelineCache(const Instance& instance_, Scheduler& scheduler_, PipelineCache::~PipelineCache() = default; -const GraphicsPipeline* PipelineCache::GetGraphicsPipeline() { +const GraphicsPipeline* PipelineCache::GetGraphicsPipeline(const DrawIndirectParams params) { + draw_indirect_params = params; if (!RefreshGraphicsKey()) { return nullptr; } diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.h b/src/video_core/renderer_vulkan/vk_pipeline_cache.h index 34d643de3..03cbc3462 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.h +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.h @@ -63,6 +63,11 @@ struct Program { } }; +struct DrawIndirectParams { + u16 vertex_sgpr_offset; + u32 instance_sgpr_offset; +}; + class PipelineCache { public: explicit PipelineCache(const Instance& instance, Scheduler& scheduler, @@ -76,7 +81,7 @@ public: bool LoadGraphicsPipeline(Serialization::Archive& ar); bool LoadPipelineStage(Serialization::Archive& ar, size_t stage); - const GraphicsPipeline* GetGraphicsPipeline(); + const GraphicsPipeline* GetGraphicsPipeline(const DrawIndirectParams params = {}); const ComputePipeline* GetComputePipeline(); @@ -122,6 +127,7 @@ private: vk::UniquePipelineLayout pipeline_layout; Shader::Profile profile{}; Shader::Pools pools; + DrawIndirectParams draw_indirect_params{}; tsl::robin_map> program_cache; tsl::robin_map> compute_pipelines; tsl::robin_map> graphics_pipelines; diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index e4428cd0f..ee05a2f20 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -9,6 +9,7 @@ #include "video_core/amdgpu/liverpool.h" #include "video_core/renderer_vulkan/liverpool_to_vk.h" #include "video_core/renderer_vulkan/vk_instance.h" +#include "video_core/renderer_vulkan/vk_pipeline_cache.h" #include "video_core/renderer_vulkan/vk_rasterizer.h" #include "video_core/renderer_vulkan/vk_scheduler.h" #include "video_core/renderer_vulkan/vk_shader_hle.h" @@ -38,7 +39,9 @@ Rasterizer::Rasterizer(const Instance& instance_, Scheduler& scheduler_, buffer_cache{instance, scheduler, liverpool_, texture_cache, page_manager}, texture_cache{instance, scheduler, liverpool_, buffer_cache, page_manager}, liverpool{liverpool_}, memory{Core::Memory::Instance()}, - pipeline_cache{instance, scheduler, liverpool} { + pipeline_cache{instance, scheduler, liverpool}, + host_markers_enabled{EmulatorSettings.IsVkHostMarkersEnabled()}, + guest_markers_enabled{EmulatorSettings.IsVkGuestMarkersEnabled()} { if (!EmulatorSettings.IsNullGPU()) { liverpool->BindRasterizer(this); } @@ -236,7 +239,8 @@ void Rasterizer::Draw(bool is_indexed, u32 index_offset) { } void Rasterizer::DrawIndirect(bool is_indexed, VAddr arg_address, u32 offset, u32 stride, - u32 max_count, VAddr count_address) { + u32 max_count, VAddr count_address, u16 vertex_sgpr_offset, + u16 instance_sgpr_offset) { RENDERER_TRACE; scheduler.PopPendingOperations(); @@ -245,7 +249,11 @@ void Rasterizer::DrawIndirect(bool is_indexed, VAddr arg_address, u32 offset, u3 return; } - const GraphicsPipeline* pipeline = pipeline_cache.GetGraphicsPipeline(); + const DrawIndirectParams params = { + .vertex_sgpr_offset = vertex_sgpr_offset, + .instance_sgpr_offset = instance_sgpr_offset, + }; + const GraphicsPipeline* pipeline = pipeline_cache.GetGraphicsPipeline(params); if (!pipeline) { return; } diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index 416588336..ff81db0e5 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h @@ -44,11 +44,21 @@ public: void Draw(bool is_indexed, u32 index_offset = 0); void DrawIndirect(bool is_indexed, VAddr arg_address, u32 offset, u32 size, u32 max_count, - VAddr count_address); + VAddr count_address, u16 vertex_sgpr_offset, u16 instance_sgpr_offset); void DispatchDirect(); void DispatchIndirect(VAddr address, u32 offset, u32 size); + void ScopeMarker(fmt::string_view fmt, fmt::format_args args, auto&& func) { + if (host_markers_enabled) { + ScopeMarkerBegin(fmt::vformat(fmt, args)); + func(); + ScopeMarkerEnd(); + } else { + func(); + } + } + void ScopeMarkerBegin(const std::string_view& str, bool from_guest = false); void ScopeMarkerEnd(bool from_guest = false); void ScopedMarkerInsert(const std::string_view& str, bool from_guest = false); @@ -128,6 +138,8 @@ private: boost::icl::interval_set mapped_ranges; Common::SharedFirstMutex mapped_ranges_mutex; PipelineCache pipeline_cache; + const bool host_markers_enabled; + const bool guest_markers_enabled; using RenderTargetInfo = std::pair; std::array cb_descs;