|
@@ -25,12 +25,6 @@ enum class Operation {
|
|
|
FPMax,
|
|
FPMax,
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-struct AttrInfo {
|
|
|
|
|
- Id pointer;
|
|
|
|
|
- Id id;
|
|
|
|
|
- bool needs_cast;
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
Id ImageType(EmitContext& ctx, const TextureDescriptor& desc) {
|
|
Id ImageType(EmitContext& ctx, const TextureDescriptor& desc) {
|
|
|
const spv::ImageFormat format{spv::ImageFormat::Unknown};
|
|
const spv::ImageFormat format{spv::ImageFormat::Unknown};
|
|
|
const Id type{ctx.F32[1]};
|
|
const Id type{ctx.F32[1]};
|
|
@@ -206,23 +200,37 @@ Id GetAttributeType(EmitContext& ctx, AttributeType type) {
|
|
|
return ctx.TypeVector(ctx.TypeInt(32, true), 4);
|
|
return ctx.TypeVector(ctx.TypeInt(32, true), 4);
|
|
|
case AttributeType::UnsignedInt:
|
|
case AttributeType::UnsignedInt:
|
|
|
return ctx.U32[4];
|
|
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:
|
|
case AttributeType::Disabled:
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
throw InvalidArgument("Invalid attribute type {}", type);
|
|
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) {
|
|
switch (type) {
|
|
|
case AttributeType::Float:
|
|
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:
|
|
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:
|
|
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:
|
|
case AttributeType::Disabled:
|
|
|
- return std::nullopt;
|
|
|
|
|
|
|
+ return InputGenericInfo{};
|
|
|
}
|
|
}
|
|
|
throw InvalidArgument("Invalid attribute type {}", type);
|
|
throw InvalidArgument("Invalid attribute type {}", type);
|
|
|
}
|
|
}
|
|
@@ -746,18 +754,29 @@ void EmitContext::DefineAttributeMemAccess(const Info& info) {
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
AddLabel(labels[label_index]);
|
|
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));
|
|
OpReturnValue(Const(0.0f));
|
|
|
++label_index;
|
|
++label_index;
|
|
|
continue;
|
|
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);
|
|
OpReturnValue(result);
|
|
|
++label_index;
|
|
++label_index;
|
|
|
}
|
|
}
|
|
@@ -1457,7 +1476,7 @@ void EmitContext::DefineInputs(const IR::Program& program) {
|
|
|
const Id id{DefineInput(*this, type, true)};
|
|
const Id id{DefineInput(*this, type, true)};
|
|
|
Decorate(id, spv::Decoration::Location, static_cast<u32>(index));
|
|
Decorate(id, spv::Decoration::Location, static_cast<u32>(index));
|
|
|
Name(id, fmt::format("in_attr{}", 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) {
|
|
if (info.passthrough.Generic(index) && profile.support_geometry_shader_passthrough) {
|
|
|
Decorate(id, spv::Decoration::PassthroughNV);
|
|
Decorate(id, spv::Decoration::PassthroughNV);
|