Vulkan: Add a workaround for input_position on Adreno drivers
Adreno drivers will crash compiling geometry shaders if the input position is not wrapped in a gl_in struct.
This commit is contained in:
parent
1428451722
commit
bbfad79c89
5 changed files with 42 additions and 11 deletions
|
@ -321,8 +321,11 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, Id vertex) {
|
||||||
case IR::Attribute::PositionY:
|
case IR::Attribute::PositionY:
|
||||||
case IR::Attribute::PositionZ:
|
case IR::Attribute::PositionZ:
|
||||||
case IR::Attribute::PositionW:
|
case IR::Attribute::PositionW:
|
||||||
return ctx.OpLoad(ctx.F32[1], AttrPointer(ctx, ctx.input_f32, vertex, ctx.input_position,
|
return ctx.OpLoad(ctx.F32[1], ctx.need_input_position_indirect ?
|
||||||
ctx.Const(element)));
|
AttrPointer(ctx, ctx.input_f32, vertex, ctx.input_position,
|
||||||
|
ctx.u32_zero_value, ctx.Const(element))
|
||||||
|
: AttrPointer(ctx, ctx.input_f32, vertex, ctx.input_position,
|
||||||
|
ctx.Const(element)));
|
||||||
case IR::Attribute::InstanceId:
|
case IR::Attribute::InstanceId:
|
||||||
if (ctx.profile.support_vertex_instance_id) {
|
if (ctx.profile.support_vertex_instance_id) {
|
||||||
return ctx.OpBitcast(ctx.F32[1], ctx.OpLoad(ctx.U32[1], ctx.instance_id));
|
return ctx.OpBitcast(ctx.F32[1], ctx.OpLoad(ctx.U32[1], ctx.instance_id));
|
||||||
|
|
|
@ -721,9 +721,21 @@ void EmitContext::DefineAttributeMemAccess(const Info& info) {
|
||||||
size_t label_index{0};
|
size_t label_index{0};
|
||||||
if (info.loads.AnyComponent(IR::Attribute::PositionX)) {
|
if (info.loads.AnyComponent(IR::Attribute::PositionX)) {
|
||||||
AddLabel(labels[label_index]);
|
AddLabel(labels[label_index]);
|
||||||
const Id pointer{is_array
|
const Id pointer{[&]() {
|
||||||
? OpAccessChain(input_f32, input_position, vertex, masked_index)
|
if (need_input_position_indirect) {
|
||||||
: OpAccessChain(input_f32, input_position, masked_index)};
|
if (is_array)
|
||||||
|
return OpAccessChain(input_f32, input_position, vertex, u32_zero_value,
|
||||||
|
masked_index);
|
||||||
|
else
|
||||||
|
return OpAccessChain(input_f32, input_position, u32_zero_value,
|
||||||
|
masked_index);
|
||||||
|
} else {
|
||||||
|
if (is_array)
|
||||||
|
return OpAccessChain(input_f32, input_position, vertex, masked_index);
|
||||||
|
else
|
||||||
|
return OpAccessChain(input_f32, input_position, masked_index);
|
||||||
|
}
|
||||||
|
}()};
|
||||||
const Id result{OpLoad(F32[1], pointer)};
|
const Id result{OpLoad(F32[1], pointer)};
|
||||||
OpReturnValue(result);
|
OpReturnValue(result);
|
||||||
++label_index;
|
++label_index;
|
||||||
|
@ -1367,12 +1379,24 @@ void EmitContext::DefineInputs(const IR::Program& program) {
|
||||||
Decorate(layer, spv::Decoration::Flat);
|
Decorate(layer, spv::Decoration::Flat);
|
||||||
}
|
}
|
||||||
if (loads.AnyComponent(IR::Attribute::PositionX)) {
|
if (loads.AnyComponent(IR::Attribute::PositionX)) {
|
||||||
const bool is_fragment{stage != Stage::Fragment};
|
const bool is_fragment{stage == Stage::Fragment};
|
||||||
const spv::BuiltIn built_in{is_fragment ? spv::BuiltIn::Position : spv::BuiltIn::FragCoord};
|
if (!is_fragment && profile.has_broken_spirv_position_input) {
|
||||||
input_position = DefineInput(*this, F32[4], true, built_in);
|
need_input_position_indirect = true;
|
||||||
if (profile.support_geometry_shader_passthrough) {
|
|
||||||
if (info.passthrough.AnyComponent(IR::Attribute::PositionX)) {
|
const Id input_position_struct = TypeStruct(F32[4]);
|
||||||
Decorate(input_position, spv::Decoration::PassthroughNV);
|
input_position = DefineInput(*this, input_position_struct, true);
|
||||||
|
|
||||||
|
MemberDecorate(input_position_struct, 0, spv::Decoration::BuiltIn,
|
||||||
|
static_cast<unsigned>(spv::BuiltIn::Position));
|
||||||
|
Decorate(input_position_struct, spv::Decoration::Block);
|
||||||
|
} else {
|
||||||
|
const spv::BuiltIn built_in{is_fragment ? spv::BuiltIn::FragCoord : spv::BuiltIn::Position};
|
||||||
|
input_position = DefineInput(*this, F32[4], true, built_in);
|
||||||
|
|
||||||
|
if (profile.support_geometry_shader_passthrough) {
|
||||||
|
if (info.passthrough.AnyComponent(IR::Attribute::PositionX)) {
|
||||||
|
Decorate(input_position, spv::Decoration::PassthroughNV);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -280,6 +280,7 @@ public:
|
||||||
Id write_global_func_u32x2{};
|
Id write_global_func_u32x2{};
|
||||||
Id write_global_func_u32x4{};
|
Id write_global_func_u32x4{};
|
||||||
|
|
||||||
|
bool need_input_position_indirect{};
|
||||||
Id input_position{};
|
Id input_position{};
|
||||||
std::array<Id, 32> input_generics{};
|
std::array<Id, 32> input_generics{};
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,8 @@ struct Profile {
|
||||||
|
|
||||||
/// OpFClamp is broken and OpFMax + OpFMin should be used instead
|
/// OpFClamp is broken and OpFMax + OpFMin should be used instead
|
||||||
bool has_broken_spirv_clamp{};
|
bool has_broken_spirv_clamp{};
|
||||||
|
/// The Position builtin needs to be wrapped in a struct when used as an input
|
||||||
|
bool has_broken_spirv_position_input{};
|
||||||
/// Offset image operands with an unsigned type do not work
|
/// Offset image operands with an unsigned type do not work
|
||||||
bool has_broken_unsigned_image_offsets{};
|
bool has_broken_unsigned_image_offsets{};
|
||||||
/// Signed instructions with unsigned data types are misinterpreted
|
/// Signed instructions with unsigned data types are misinterpreted
|
||||||
|
|
|
@ -331,6 +331,7 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device
|
||||||
.need_declared_frag_colors = false,
|
.need_declared_frag_colors = false,
|
||||||
|
|
||||||
.has_broken_spirv_clamp = driver_id == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS,
|
.has_broken_spirv_clamp = driver_id == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS,
|
||||||
|
.has_broken_spirv_position_input = driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY,
|
||||||
.has_broken_unsigned_image_offsets = false,
|
.has_broken_unsigned_image_offsets = false,
|
||||||
.has_broken_signed_operations = false,
|
.has_broken_signed_operations = false,
|
||||||
.has_broken_fp16_float_controls = driver_id == VK_DRIVER_ID_NVIDIA_PROPRIETARY,
|
.has_broken_fp16_float_controls = driver_id == VK_DRIVER_ID_NVIDIA_PROPRIETARY,
|
||||||
|
|
Loading…
Reference in a new issue