|
|
|
@ -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: |
|
|
|
|