|
|
|
@ -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);
|
|
|
|
|