Review comments and some cleanup

This commit is contained in:
IndecisiveTurtle 2025-07-15 13:11:06 +03:00
parent 3b0d08c730
commit f3e2d985f7
9 changed files with 53 additions and 57 deletions

View File

@ -294,11 +294,11 @@ void SetupCapabilities(const Info& info, const Profile& profile, EmitContext& ct
ctx.AddCapability(spv::Capability::Geometry);
}
if (info.stage == Stage::Fragment) {
if (profile.supports_fragment_shader_barycentric) {
if (profile.supports_amd_shader_explicit_vertex_parameter) {
ctx.AddExtension("SPV_AMD_shader_explicit_vertex_parameter");
} else if (profile.supports_fragment_shader_barycentric) {
ctx.AddExtension("SPV_KHR_fragment_shader_barycentric");
ctx.AddCapability(spv::Capability::FragmentBarycentricKHR);
} else if (profile.supports_amd_shader_explicit_vertex_parameter) {
ctx.AddExtension("SPV_AMD_shader_explicit_vertex_parameter");
}
if (info.loads.GetAny(IR::Attribute::BaryCoordSmoothSample) ||
info.loads.GetAny(IR::Attribute::BaryCoordNoPerspSample)) {

View File

@ -68,7 +68,7 @@ Id OutputAttrPointer(EmitContext& ctx, IR::Attribute attr, u32 element) {
}
if (IR::IsMrt(attr)) {
const u32 index{u32(attr) - u32(IR::Attribute::RenderTarget0)};
const auto& info{ctx.output_params.at(index)};
const auto& info{ctx.frag_outputs.at(index)};
if (info.num_components == 1) {
return info.id;
} else {
@ -100,7 +100,7 @@ std::pair<Id, bool> OutputAttrComponentType(EmitContext& ctx, IR::Attribute attr
}
if (IR::IsMrt(attr)) {
const u32 index{u32(attr) - u32(IR::Attribute::RenderTarget0)};
const auto& info{ctx.output_params.at(index)};
const auto& info{ctx.frag_outputs.at(index)};
return {info.component_type, info.is_integer};
}
switch (attr) {
@ -163,7 +163,7 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, u32 comp, u32 index) {
if (IR::IsParam(attr)) {
const u32 param_index{u32(attr) - u32(IR::Attribute::Param0)};
const auto& param{ctx.input_params.at(param_index)};
const Id result = [&] {
const Id value = [&] {
if (param.is_array) {
ASSERT(param.num_components > 1);
if (param.is_loaded) {
@ -185,7 +185,10 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, u32 comp, u32 index) {
}
}
}();
return param.is_integer ? ctx.OpBitcast(ctx.F32[1], result) : result;
return param.is_integer ? ctx.OpBitcast(ctx.F32[1], value) : value;
}
if (IR::IsBarycentricCoord(attr) && ctx.profile.supports_fragment_shader_barycentric) {
++comp;
}
switch (attr) {
case IR::Attribute::Position0:
@ -203,21 +206,12 @@ 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:
if (ctx.profile.supports_fragment_shader_barycentric) {
++comp;
}
return ctx.OpLoad(ctx.F32[1], ctx.OpAccessChain(ctx.input_f32, ctx.bary_coord_smooth,
ctx.ConstU32(comp)));
case IR::Attribute::BaryCoordSmoothSample:
if (ctx.profile.supports_fragment_shader_barycentric) {
++comp;
}
return ctx.OpLoad(ctx.F32[1], ctx.OpAccessChain(ctx.input_f32, ctx.bary_coord_smooth_sample,
ctx.ConstU32(comp)));
case IR::Attribute::BaryCoordNoPersp:
if (ctx.profile.supports_fragment_shader_barycentric) {
++comp;
}
return ctx.OpLoad(ctx.F32[1], ctx.OpAccessChain(ctx.input_f32, ctx.bary_coord_nopersp,
ctx.ConstU32(comp)));
default:

View File

@ -305,7 +305,7 @@ void EmitContext::DefineAmdPerVertexAttribs() {
}
for (s32 i = 0; i < runtime_info.fs_info.num_inputs; i++) {
const auto& input = runtime_info.fs_info.inputs[i];
if (input.IsDefault() || info.fs_interp_qualifiers[i].primary != Qualifier::PerVertex) {
if (input.IsDefault() || info.fs_interpolation[i].primary != Qualifier::PerVertex) {
continue;
}
auto& param = input_params[i];
@ -316,6 +316,7 @@ void EmitContext::DefineAmdPerVertexAttribs() {
OpInterpolateAtVertexAMD(F32[param.num_components], pointer, ConstU32(1U));
param.id_array[2] =
OpInterpolateAtVertexAMD(F32[param.num_components], pointer, ConstU32(2U));
param.is_loaded = true;
}
}
@ -378,28 +379,34 @@ void EmitContext::DefineInputs() {
if (profile.supports_amd_shader_explicit_vertex_parameter) {
bary_coord_smooth = DefineVariable(F32[2], spv::BuiltIn::BaryCoordSmoothAMD,
spv::StorageClass::Input);
} else {
} 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::BaryCoordSmoothSample)) {
if (profile.supports_amd_shader_explicit_vertex_parameter) {
bary_coord_smooth = DefineVariable(F32[2], spv::BuiltIn::BaryCoordSmoothSampleAMD,
spv::StorageClass::Input);
} else {
bary_coord_smooth_sample = DefineVariable(
F32[2], spv::BuiltIn::BaryCoordSmoothSampleAMD, spv::StorageClass::Input);
} else if (profile.supports_fragment_shader_barycentric) {
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)) {
if (profile.supports_amd_shader_explicit_vertex_parameter) {
bary_coord_nopersp = DefineVariable(F32[2], spv::BuiltIn::BaryCoordNoPerspAMD,
spv::StorageClass::Input);
} else {
} 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++) {
@ -409,36 +416,30 @@ void EmitContext::DefineInputs() {
}
const IR::Attribute param = IR::Attribute::Param0 + i;
const u32 num_components = info.loads.NumComponents(param);
const auto [primary, auxiliary] = info.fs_interp_qualifiers[i];
const bool is_array = primary == Qualifier::PerVertex;
const Id type{F32[num_components]};
Id attr_id{};
// Declare primary qualifier (pervertex, smooth, noperspective, flat)
if (is_array) {
if (profile.supports_fragment_shader_barycentric) {
attr_id = DefineInput(TypeArray(type, ConstU32(3U)), input.param_index);
Decorate(attr_id, spv::Decoration::PerVertexKHR);
} else {
attr_id = DefineInput(type, input.param_index);
Decorate(attr_id, spv::Decoration::ExplicitInterpAMD);
}
Name(attr_id, fmt::format("fs_in_attr{}_p", i));
} else {
attr_id = DefineInput(type, input.param_index);
Name(attr_id, fmt::format("fs_in_attr{}", i));
if (primary != Qualifier::Smooth) {
Decorate(attr_id, primary == Qualifier::Flat ? spv::Decoration::Flat
: spv::Decoration::NoPerspective);
const auto [primary, auxiliary] = info.fs_interpolation[i];
const Id type = F32[num_components];
const Id attr_id = [&] {
if (primary == Qualifier::PerVertex &&
profile.supports_fragment_shader_barycentric) {
return Name(DefineInput(TypeArray(type, ConstU32(3U)), input.param_index),
fmt::format("fs_in_attr{}_p", i));
}
return Name(DefineInput(type, input.param_index), fmt::format("fs_in_attr{}", i));
}();
if (primary == Qualifier::PerVertex) {
Decorate(attr_id, profile.supports_amd_shader_explicit_vertex_parameter
? spv::Decoration::ExplicitInterpAMD
: spv::Decoration::PerVertexKHR);
} else if (primary != Qualifier::Smooth) {
Decorate(attr_id, primary == Qualifier::Flat ? spv::Decoration::Flat
: spv::Decoration::NoPerspective);
}
// Declare auxiliary qualifier if present (centroid, sample)
if (auxiliary != Qualifier::None) {
Decorate(attr_id, auxiliary == Qualifier::Centroid ? spv::Decoration::Centroid
: spv::Decoration::Sample);
}
input_params[i] = GetAttributeInfo(
AmdGpu::NumberFormat::Float, attr_id, num_components, false,
is_array && profile.supports_amd_shader_explicit_vertex_parameter, is_array);
input_params[i] = GetAttributeInfo(AmdGpu::NumberFormat::Float, attr_id, num_components,
false, false, primary == Qualifier::PerVertex);
}
break;
case LogicalStage::Compute:
@ -650,7 +651,7 @@ void EmitContext::DefineOutputs() {
id = DefineOutput(type, i);
}
Name(id, fmt::format("frag_color{}", i));
output_params[i] = GetAttributeInfo(num_format, id, num_components, true);
frag_outputs[i] = GetAttributeInfo(num_format, id, num_components, true);
++num_render_targets;
}
ASSERT_MSG(!runtime_info.fs_info.dual_source_blending || num_render_targets == 2,

View File

@ -371,6 +371,7 @@ public:
Id output_attr_array;
std::array<SpirvAttribute, IR::NumParams> input_params{};
std::array<SpirvAttribute, IR::NumParams> output_params{};
std::array<SpirvAttribute, IR::NumRenderTargets> frag_outputs{};
Id uf11_to_f32{};
Id f32_to_uf11{};

View File

@ -60,7 +60,7 @@ void Translator::V_INTERP_P2_F32(const GcnInst& inst) {
const u32 attr_index = inst.control.vintrp.attr;
const IR::Attribute attrib = IR::Attribute::Param0 + attr_index;
const auto& attr = runtime_info.fs_info.inputs[attr_index];
auto& interp = info.fs_interp_qualifiers[attr_index];
auto& interp = info.fs_interpolation[attr_index];
ASSERT(!attr.IsDefault() && !attr.is_flat);
if (!profile.needs_manual_interpolation) {
interp = GetInterpolation(vgpr_to_interp[inst.src[0].code]);
@ -80,10 +80,11 @@ void Translator::V_INTERP_MOV_F32(const GcnInst& inst) {
const u32 attr_index = inst.control.vintrp.attr;
const IR::Attribute attrib = IR::Attribute::Param0 + attr_index;
const auto& attr = runtime_info.fs_info.inputs[attr_index];
auto& interp = info.fs_interp_qualifiers[attr_index];
auto& interp = info.fs_interpolation[attr_index];
ASSERT(attr.is_flat);
if (profile.supports_amd_shader_explicit_vertex_parameter ||
profile.supports_fragment_shader_barycentric) {
(profile.supports_fragment_shader_barycentric &&
!profile.has_incomplete_fragment_shader_barycentric)) {
// VSRC 0=P10, 1=P20, 2=P0
interp.primary = Qualifier::PerVertex;
SetDst(inst.dst[0],

View File

@ -209,7 +209,7 @@ struct Info {
Qualifier primary;
Qualifier auxiliary;
};
std::array<Interpolation, IR::NumParams> fs_interp_qualifiers{};
std::array<Interpolation, IR::NumParams> fs_interpolation{};
IR::ScalarReg tess_consts_ptr_base = IR::ScalarReg::Max;
s32 tess_consts_dword_offset = -1;

View File

@ -109,12 +109,7 @@ constexpr bool IsMrt(Attribute attribute) noexcept {
return attribute >= Attribute::RenderTarget0 && attribute <= Attribute::RenderTarget7;
}
constexpr bool IsLinear(Attribute attribute) noexcept {
return attribute >= Attribute::BaryCoordNoPersp &&
attribute <= Attribute::BaryCoordNoPerspSample;
}
constexpr bool IsPerspective(Attribute attribute) noexcept {
constexpr bool IsBarycentricCoord(Attribute attribute) noexcept {
return attribute >= Attribute::BaryCoordSmooth && attribute <= Attribute::BaryCoordSmoothSample;
}

View File

@ -29,6 +29,7 @@ struct Profile {
bool supports_workgroup_explicit_memory_layout{};
bool supports_amd_shader_explicit_vertex_parameter{};
bool supports_fragment_shader_barycentric{};
bool has_incomplete_fragment_shader_barycentric{};
bool has_broken_spirv_clamp{};
bool lower_left_origin_mode{};
bool needs_manual_interpolation{};

View File

@ -223,6 +223,9 @@ PipelineCache::PipelineCache(const Instance& instance_, Scheduler& scheduler_,
.supports_amd_shader_explicit_vertex_parameter =
instance_.IsAmdShaderExplicitVertexParameterSupported(),
.supports_fragment_shader_barycentric = instance_.IsFragmentShaderBarycentricSupported(),
.has_incomplete_fragment_shader_barycentric =
instance_.IsFragmentShaderBarycentricSupported() &&
instance.GetDriverID() == vk::DriverId::eMoltenvk,
.needs_manual_interpolation = instance.IsFragmentShaderBarycentricSupported() &&
instance.GetDriverID() == vk::DriverId::eNvidiaProprietary,
.needs_lds_barriers = instance.GetDriverID() == vk::DriverId::eNvidiaProprietary ||