diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp index 5efce9292..4c323b012 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp @@ -307,10 +307,14 @@ void SetupCapabilities(const Info& info, const Profile& profile, const RuntimeIn } else if (profile.supports_fragment_shader_barycentric) { ctx.AddExtension("SPV_KHR_fragment_shader_barycentric"); ctx.AddCapability(spv::Capability::FragmentBarycentricKHR); + ctx.AddCapability(spv::Capability::InterpolationFunction); } if (info.loads.Get(IR::Attribute::SampleIndex) || runtime_info.fs_info.addr_flags.linear_sample_ena || - runtime_info.fs_info.addr_flags.persp_sample_ena) { + runtime_info.fs_info.addr_flags.persp_sample_ena || + (!profile.supports_amd_shader_explicit_vertex_parameter && + profile.supports_fragment_shader_barycentric && + info.loads.Get(IR::Attribute::BaryCoordSmoothSample))) { ctx.AddCapability(spv::Capability::SampleRateShading); } if (info.loads.GetAny(IR::Attribute::RenderTargetIndex)) { 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 0d7da9067..277e7ff84 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 @@ -128,15 +128,33 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, u32 comp, u32 index) { return ctx.OpLoad(ctx.F32[1], ctx.OpAccessChain(ctx.input_f32, ctx.tess_coord, ctx.ConstU32(1U))); case IR::Attribute::BaryCoordSmooth: - return ctx.OpLoad(ctx.F32[1], ctx.OpAccessChain(ctx.input_f32, ctx.bary_coord_smooth, - ctx.ConstU32(comp))); + if (ctx.profile.supports_amd_shader_explicit_vertex_parameter) { + return ctx.OpLoad(ctx.F32[1], ctx.OpAccessChain(ctx.input_f32, ctx.bary_coord_smooth, + ctx.ConstU32(comp))); + } else { + return ctx.OpCompositeExtract(ctx.F32[1], ctx.OpLoad(ctx.F32[3], ctx.bary_coord), comp); + } case IR::Attribute::BaryCoordSmoothCentroid: - return ctx.OpLoad( - ctx.F32[1], - ctx.OpAccessChain(ctx.input_f32, ctx.bary_coord_smooth_centroid, ctx.ConstU32(comp))); + if (ctx.profile.supports_amd_shader_explicit_vertex_parameter) { + return ctx.OpLoad(ctx.F32[1], + ctx.OpAccessChain(ctx.input_f32, ctx.bary_coord_smooth_centroid, + ctx.ConstU32(comp))); + } else { + return ctx.OpCompositeExtract( + ctx.F32[1], ctx.OpInterpolateAtCentroid(ctx.F32[3], ctx.bary_coord), comp); + } case IR::Attribute::BaryCoordSmoothSample: - return ctx.OpLoad(ctx.F32[1], ctx.OpAccessChain(ctx.input_f32, ctx.bary_coord_smooth_sample, - ctx.ConstU32(comp))); + if (ctx.profile.supports_amd_shader_explicit_vertex_parameter) { + return ctx.OpLoad( + ctx.F32[1], + ctx.OpAccessChain(ctx.input_f32, ctx.bary_coord_smooth_sample, ctx.ConstU32(comp))); + } else { + return ctx.OpCompositeExtract( + ctx.F32[1], + ctx.OpInterpolateAtSample(ctx.F32[3], ctx.bary_coord, + ctx.OpLoad(ctx.U32[1], ctx.sample_index)), + comp); + } case IR::Attribute::BaryCoordNoPersp: return ctx.OpLoad(ctx.F32[1], ctx.OpAccessChain(ctx.input_f32, ctx.bary_coord_nopersp, 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 6ceef062c..8e564de5d 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp @@ -356,8 +356,8 @@ void EmitContext::DefineInputs() { if (profile.supports_amd_shader_explicit_vertex_parameter) { bary_coord_smooth = DefineVariable(F32[2], spv::BuiltIn::BaryCoordSmoothAMD, spv::StorageClass::Input); - } else if (profile.supports_fragment_shader_barycentric) { - bary_coord_smooth = + } else if (profile.supports_fragment_shader_barycentric && !ValidId(bary_coord)) { + bary_coord = DefineVariable(F32[3], spv::BuiltIn::BaryCoordKHR, spv::StorageClass::Input); } } @@ -365,20 +365,24 @@ void EmitContext::DefineInputs() { 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 = + } else if (profile.supports_fragment_shader_barycentric && !ValidId(bary_coord)) { + bary_coord = DefineVariable(F32[3], spv::BuiltIn::BaryCoordKHR, spv::StorageClass::Input); - // Decorate(bary_coord_smooth_centroid, spv::Decoration::Centroid); } } if (info.loads.GetAny(IR::Attribute::BaryCoordSmoothSample)) { if (profile.supports_amd_shader_explicit_vertex_parameter) { bary_coord_smooth_sample = DefineVariable( F32[2], spv::BuiltIn::BaryCoordSmoothSampleAMD, spv::StorageClass::Input); - } else if (profile.supports_fragment_shader_barycentric) { - bary_coord_smooth_sample = + } else if (profile.supports_fragment_shader_barycentric && !ValidId(bary_coord)) { + bary_coord = DefineVariable(F32[3], spv::BuiltIn::BaryCoordKHR, spv::StorageClass::Input); - // Decorate(bary_coord_smooth_sample, spv::Decoration::Sample); + // we would need sample_index to interpolate the bary_coord later + if (!ValidId(sample_index)) { + sample_index = + DefineVariable(U32[1], spv::BuiltIn::SampleId, spv::StorageClass::Input); + Decorate(sample_index, spv::Decoration::Flat); + } } } if (info.loads.GetAny(IR::Attribute::BaryCoordNoPersp)) { diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.h b/src/shader_recompiler/backend/spirv/spirv_emit_context.h index 9236be6a0..cb84a719c 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.h +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.h @@ -285,6 +285,7 @@ public: Id shared_memory_u32_type{}; Id shared_memory_u64_type{}; + Id bary_coord{}; Id bary_coord_smooth{}; Id bary_coord_smooth_centroid{}; Id bary_coord_smooth_sample{};