|
|
|
@ -25,12 +25,6 @@ enum class Operation { |
|
|
|
FPMax, |
|
|
|
}; |
|
|
|
|
|
|
|
struct AttrInfo { |
|
|
|
Id pointer; |
|
|
|
Id id; |
|
|
|
bool needs_cast; |
|
|
|
}; |
|
|
|
|
|
|
|
Id ImageType(EmitContext& ctx, const TextureDescriptor& desc) { |
|
|
|
const spv::ImageFormat format{spv::ImageFormat::Unknown}; |
|
|
|
const Id type{ctx.F32[1]}; |
|
|
|
@ -206,23 +200,37 @@ Id GetAttributeType(EmitContext& ctx, AttributeType type) { |
|
|
|
return ctx.TypeVector(ctx.TypeInt(32, true), 4); |
|
|
|
case AttributeType::UnsignedInt: |
|
|
|
return ctx.U32[4]; |
|
|
|
case AttributeType::SignedScaled: |
|
|
|
return ctx.profile.support_scaled_attributes ? ctx.F32[4] |
|
|
|
: ctx.TypeVector(ctx.TypeInt(32, true), 4); |
|
|
|
case AttributeType::UnsignedScaled: |
|
|
|
return ctx.profile.support_scaled_attributes ? ctx.F32[4] : ctx.U32[4]; |
|
|
|
case AttributeType::Disabled: |
|
|
|
break; |
|
|
|
} |
|
|
|
throw InvalidArgument("Invalid attribute type {}", type); |
|
|
|
} |
|
|
|
|
|
|
|
std::optional<AttrInfo> AttrTypes(EmitContext& ctx, u32 index) { |
|
|
|
const AttributeType type{ctx.runtime_info.generic_input_types.at(index)}; |
|
|
|
InputGenericInfo GetAttributeInfo(EmitContext& ctx, AttributeType type, Id id) { |
|
|
|
switch (type) { |
|
|
|
case AttributeType::Float: |
|
|
|
return AttrInfo{ctx.input_f32, ctx.F32[1], false}; |
|
|
|
return InputGenericInfo{id, ctx.input_f32, ctx.F32[1], InputGenericLoadOp::None}; |
|
|
|
case AttributeType::UnsignedInt: |
|
|
|
return AttrInfo{ctx.input_u32, ctx.U32[1], true}; |
|
|
|
return InputGenericInfo{id, ctx.input_u32, ctx.U32[1], InputGenericLoadOp::Bitcast}; |
|
|
|
case AttributeType::SignedInt: |
|
|
|
return AttrInfo{ctx.input_s32, ctx.TypeInt(32, true), true}; |
|
|
|
return InputGenericInfo{id, ctx.input_s32, ctx.TypeInt(32, true), |
|
|
|
InputGenericLoadOp::Bitcast}; |
|
|
|
case AttributeType::SignedScaled: |
|
|
|
return ctx.profile.support_scaled_attributes |
|
|
|
? InputGenericInfo{id, ctx.input_f32, ctx.F32[1], InputGenericLoadOp::None} |
|
|
|
: InputGenericInfo{id, ctx.input_s32, ctx.TypeInt(32, true), |
|
|
|
InputGenericLoadOp::SToF}; |
|
|
|
case AttributeType::UnsignedScaled: |
|
|
|
return ctx.profile.support_scaled_attributes |
|
|
|
? InputGenericInfo{id, ctx.input_f32, ctx.F32[1], InputGenericLoadOp::None} |
|
|
|
: InputGenericInfo{id, ctx.input_u32, ctx.U32[1], InputGenericLoadOp::UToF}; |
|
|
|
case AttributeType::Disabled: |
|
|
|
return std::nullopt; |
|
|
|
return InputGenericInfo{}; |
|
|
|
} |
|
|
|
throw InvalidArgument("Invalid attribute type {}", type); |
|
|
|
} |
|
|
|
@ -746,18 +754,29 @@ void EmitContext::DefineAttributeMemAccess(const Info& info) { |
|
|
|
continue; |
|
|
|
} |
|
|
|
AddLabel(labels[label_index]); |
|
|
|
const auto type{AttrTypes(*this, static_cast<u32>(index))}; |
|
|
|
if (!type) { |
|
|
|
const auto& generic{input_generics.at(index)}; |
|
|
|
const Id generic_id{generic.id}; |
|
|
|
if (!ValidId(generic_id)) { |
|
|
|
OpReturnValue(Const(0.0f)); |
|
|
|
++label_index; |
|
|
|
continue; |
|
|
|
} |
|
|
|
const Id generic_id{input_generics.at(index)}; |
|
|
|
const Id pointer{is_array |
|
|
|
? OpAccessChain(type->pointer, generic_id, vertex, masked_index) |
|
|
|
: OpAccessChain(type->pointer, generic_id, masked_index)}; |
|
|
|
const Id value{OpLoad(type->id, pointer)}; |
|
|
|
const Id result{type->needs_cast ? OpBitcast(F32[1], value) : value}; |
|
|
|
const Id pointer{ |
|
|
|
is_array ? OpAccessChain(generic.pointer_type, generic_id, vertex, masked_index) |
|
|
|
: OpAccessChain(generic.pointer_type, generic_id, masked_index)}; |
|
|
|
const Id value{OpLoad(generic.component_type, pointer)}; |
|
|
|
const Id result{[this, generic, value]() { |
|
|
|
switch (generic.load_op) { |
|
|
|
case InputGenericLoadOp::Bitcast: |
|
|
|
return OpBitcast(F32[1], value); |
|
|
|
case InputGenericLoadOp::SToF: |
|
|
|
return OpConvertSToF(F32[1], value); |
|
|
|
case InputGenericLoadOp::UToF: |
|
|
|
return OpConvertUToF(F32[1], value); |
|
|
|
default: |
|
|
|
return value; |
|
|
|
}; |
|
|
|
}()}; |
|
|
|
OpReturnValue(result); |
|
|
|
++label_index; |
|
|
|
} |
|
|
|
@ -1457,7 +1476,7 @@ void EmitContext::DefineInputs(const IR::Program& program) { |
|
|
|
const Id id{DefineInput(*this, type, true)}; |
|
|
|
Decorate(id, spv::Decoration::Location, static_cast<u32>(index)); |
|
|
|
Name(id, fmt::format("in_attr{}", index)); |
|
|
|
input_generics[index] = id; |
|
|
|
input_generics[index] = GetAttributeInfo(*this, input_type, id); |
|
|
|
|
|
|
|
if (info.passthrough.Generic(index) && profile.support_geometry_shader_passthrough) { |
|
|
|
Decorate(id, spv::Decoration::PassthroughNV); |
|
|
|
|