From 4d3578edbe35acc343d04ed91be6f9391bbd8dc6 Mon Sep 17 00:00:00 2001 From: TheTurtle Date: Wed, 23 Jul 2025 19:46:06 +0300 Subject: [PATCH] shader_recompiler: Fix incorrect bary coord loads when unsupported (#3303) * shader_recompiler: Fix incorrect bary coord loads when unsupported Also properly set sample rate shading * emit_spirv: Implement BaryCoordSmoothCentroid --- .../backend/spirv/emit_spirv.cpp | 9 +++++---- .../backend/spirv/emit_spirv_context_get_set.cpp | 4 ++++ .../backend/spirv/spirv_emit_context.cpp | 16 ++++++++++------ .../backend/spirv/spirv_emit_context.h | 1 + .../frontend/translate/translate.cpp | 5 ++++- 5 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp index baf9ced25..0e58b8f58 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp @@ -241,7 +241,8 @@ spv::ExecutionMode ExecutionMode(AmdGpu::TessellationPartitioning spacing) { UNREACHABLE_MSG("Tessellation spacing {}", spacing); } -void SetupCapabilities(const Info& info, const Profile& profile, EmitContext& ctx) { +void SetupCapabilities(const Info& info, const Profile& profile, const RuntimeInfo& runtime_info, + EmitContext& ctx) { ctx.AddCapability(spv::Capability::Image1D); ctx.AddCapability(spv::Capability::Sampled1D); ctx.AddCapability(spv::Capability::ImageQuery); @@ -300,8 +301,8 @@ void SetupCapabilities(const Info& info, const Profile& profile, EmitContext& ct ctx.AddExtension("SPV_KHR_fragment_shader_barycentric"); ctx.AddCapability(spv::Capability::FragmentBarycentricKHR); } - if (info.loads.GetAny(IR::Attribute::BaryCoordSmoothSample) || - info.loads.GetAny(IR::Attribute::BaryCoordNoPerspSample)) { + if (runtime_info.fs_info.addr_flags.linear_sample_ena || + runtime_info.fs_info.addr_flags.persp_sample_ena) { ctx.AddCapability(spv::Capability::SampleRateShading); } } @@ -443,7 +444,7 @@ std::vector EmitSPIRV(const Profile& profile, const RuntimeInfo& runtime_in EmitContext ctx{profile, runtime_info, program.info, binding}; const Id main{DefineMain(ctx, program)}; DefineEntryPoint(program.info, ctx, main); - SetupCapabilities(program.info, profile, ctx); + SetupCapabilities(program.info, profile, runtime_info, ctx); SetupFloatMode(ctx, profile, runtime_info, main); PatchPhiNodes(program, ctx); binding.user_data += program.info.ud_mask.NumRegs(); 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 ead2a2825..330516d07 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 @@ -208,6 +208,10 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, u32 comp, u32 index) { case IR::Attribute::BaryCoordSmooth: return ctx.OpLoad(ctx.F32[1], ctx.OpAccessChain(ctx.input_f32, ctx.bary_coord_smooth, ctx.ConstU32(comp))); + case IR::Attribute::BaryCoordSmoothCentroid: + return ctx.OpLoad( + ctx.F32[1], + ctx.OpAccessChain(ctx.input_f32, ctx.bary_coord_smooth_centroid, ctx.ConstU32(comp))); case IR::Attribute::BaryCoordSmoothSample: return ctx.OpLoad(ctx.F32[1], ctx.OpAccessChain(ctx.input_f32, ctx.bary_coord_smooth_sample, ctx.ConstU32(comp))); diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index a8ffe6ae5..def1ff8ce 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp @@ -384,8 +384,16 @@ void EmitContext::DefineInputs() { } else if (profile.supports_fragment_shader_barycentric) { bary_coord_smooth = DefineVariable(F32[3], spv::BuiltIn::BaryCoordKHR, spv::StorageClass::Input); - } else { - bary_coord_smooth = ConstF32(0.f, 0.f); + } + } + if (info.loads.GetAny(IR::Attribute::BaryCoordSmoothCentroid)) { + if (profile.supports_amd_shader_explicit_vertex_parameter) { + bary_coord_smooth_centroid = DefineVariable( + F32[2], spv::BuiltIn::BaryCoordSmoothCentroidAMD, spv::StorageClass::Input); + } else if (profile.supports_fragment_shader_barycentric) { + bary_coord_smooth_centroid = + DefineVariable(F32[3], spv::BuiltIn::BaryCoordKHR, spv::StorageClass::Input); + // Decorate(bary_coord_smooth_centroid, spv::Decoration::Centroid); } } if (info.loads.GetAny(IR::Attribute::BaryCoordSmoothSample)) { @@ -396,8 +404,6 @@ void EmitContext::DefineInputs() { bary_coord_smooth_sample = DefineVariable(F32[3], spv::BuiltIn::BaryCoordKHR, spv::StorageClass::Input); // Decorate(bary_coord_smooth_sample, spv::Decoration::Sample); - } else { - bary_coord_smooth_sample = ConstF32(0.f, 0.f); } } if (info.loads.GetAny(IR::Attribute::BaryCoordNoPersp)) { @@ -407,8 +413,6 @@ void EmitContext::DefineInputs() { } else if (profile.supports_fragment_shader_barycentric) { bary_coord_nopersp = DefineVariable(F32[3], spv::BuiltIn::BaryCoordNoPerspKHR, spv::StorageClass::Input); - } else { - bary_coord_nopersp = ConstF32(0.f, 0.f); } } for (s32 i = 0; i < runtime_info.fs_info.num_inputs; i++) { diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.h b/src/shader_recompiler/backend/spirv/spirv_emit_context.h index f57dbebd8..b73b2b67d 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.h +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.h @@ -280,6 +280,7 @@ public: Id shared_memory_u64_type{}; Id bary_coord_smooth{}; + Id bary_coord_smooth_centroid{}; Id bary_coord_smooth_sample{}; Id bary_coord_nopersp{}; diff --git a/src/shader_recompiler/frontend/translate/translate.cpp b/src/shader_recompiler/frontend/translate/translate.cpp index 578c1f96a..21b0ffb52 100644 --- a/src/shader_recompiler/frontend/translate/translate.cpp +++ b/src/shader_recompiler/frontend/translate/translate.cpp @@ -126,7 +126,10 @@ void Translator::EmitPrologue(IR::Block* first_block) { case LogicalStage::Fragment: dst_vreg = IterateBarycentrics(runtime_info, [this](u32 vreg, IR::Attribute attrib, u32 comp) { - ir.SetVectorReg(IR::VectorReg(vreg), ir.GetAttribute(attrib, comp)); + if (profile.supports_amd_shader_explicit_vertex_parameter || + profile.supports_fragment_shader_barycentric) { + ir.SetVectorReg(IR::VectorReg(vreg), ir.GetAttribute(attrib, comp)); + } }); if (runtime_info.fs_info.addr_flags.pos_x_float_ena) { if (runtime_info.fs_info.en_flags.pos_x_float_ena) {