|
|
|
@ -10,16 +10,23 @@
|
|
|
|
|
|
|
|
|
|
namespace Shader::Backend::SPIRV {
|
|
|
|
|
namespace {
|
|
|
|
|
std::tuple<Id, Id, bool> AttrTypes(EmitContext& ctx, u32 index) {
|
|
|
|
|
const bool is_first_reader{ctx.stage == Stage::VertexB};
|
|
|
|
|
struct AttrInfo {
|
|
|
|
|
Id pointer;
|
|
|
|
|
Id id;
|
|
|
|
|
bool needs_cast;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
std::optional<AttrInfo> AttrTypes(EmitContext& ctx, u32 index) {
|
|
|
|
|
const AttributeType type{ctx.profile.generic_input_types.at(index)};
|
|
|
|
|
switch (type) {
|
|
|
|
|
case AttributeType::Float:
|
|
|
|
|
return {ctx.input_f32, ctx.F32[1], false};
|
|
|
|
|
return AttrInfo{ctx.input_f32, ctx.F32[1], false};
|
|
|
|
|
case AttributeType::UnsignedInt:
|
|
|
|
|
return {ctx.input_u32, ctx.U32[1], true};
|
|
|
|
|
return AttrInfo{ctx.input_u32, ctx.U32[1], true};
|
|
|
|
|
case AttributeType::SignedInt:
|
|
|
|
|
return {ctx.input_s32, ctx.TypeInt(32, true), true};
|
|
|
|
|
return AttrInfo{ctx.input_s32, ctx.TypeInt(32, true), true};
|
|
|
|
|
case AttributeType::Disabled:
|
|
|
|
|
return std::nullopt;
|
|
|
|
|
}
|
|
|
|
|
throw InvalidArgument("Invalid attribute type {}", type);
|
|
|
|
|
}
|
|
|
|
@ -129,11 +136,15 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr) {
|
|
|
|
|
const auto element_id{[&] { return ctx.Constant(ctx.U32[1], element); }};
|
|
|
|
|
if (IR::IsGeneric(attr)) {
|
|
|
|
|
const u32 index{IR::GenericAttributeIndex(attr)};
|
|
|
|
|
const auto [pointer_type, type, needs_cast]{AttrTypes(ctx, index)};
|
|
|
|
|
const std::optional<AttrInfo> type{AttrTypes(ctx, index)};
|
|
|
|
|
if (!type) {
|
|
|
|
|
// Attribute is disabled
|
|
|
|
|
return ctx.Constant(ctx.F32[1], 0.0f);
|
|
|
|
|
}
|
|
|
|
|
const Id generic_id{ctx.input_generics.at(index)};
|
|
|
|
|
const Id pointer{ctx.OpAccessChain(pointer_type, generic_id, element_id())};
|
|
|
|
|
const Id value{ctx.OpLoad(type, pointer)};
|
|
|
|
|
return needs_cast ? ctx.OpBitcast(ctx.F32[1], value) : value;
|
|
|
|
|
const Id pointer{ctx.OpAccessChain(type->pointer, generic_id, element_id())};
|
|
|
|
|
const Id value{ctx.OpLoad(type->id, pointer)};
|
|
|
|
|
return type->needs_cast ? ctx.OpBitcast(ctx.F32[1], value) : value;
|
|
|
|
|
}
|
|
|
|
|
switch (attr) {
|
|
|
|
|
case IR::Attribute::PositionX:
|
|
|
|
|