shader: Better interpolation and disabled attributes support
This commit is contained in:
		| @@ -76,6 +76,8 @@ Id GetAttributeType(EmitContext& ctx, AttributeType type) { | ||||
|         return ctx.TypeVector(ctx.TypeInt(32, true), 4); | ||||
|     case AttributeType::UnsignedInt: | ||||
|         return ctx.U32[4]; | ||||
|     case AttributeType::Disabled: | ||||
|         break; | ||||
|     } | ||||
|     throw InvalidArgument("Invalid attribute type {}", type); | ||||
| } | ||||
| @@ -305,15 +307,36 @@ void EmitContext::DefineInputs(const Info& info) { | ||||
|     if (info.loads_front_face) { | ||||
|         front_face = DefineInput(*this, U1, spv::BuiltIn::FrontFacing); | ||||
|     } | ||||
|     for (size_t index = 0; index < info.loads_generics.size(); ++index) { | ||||
|         if (!info.loads_generics[index]) { | ||||
|     for (size_t index = 0; index < info.input_generics.size(); ++index) { | ||||
|         const InputVarying generic{info.input_generics[index]}; | ||||
|         if (!generic.used) { | ||||
|             continue; | ||||
|         } | ||||
|         const Id type{GetAttributeType(*this, profile.generic_input_types[index])}; | ||||
|         const AttributeType input_type{profile.generic_input_types[index]}; | ||||
|         if (input_type == AttributeType::Disabled) { | ||||
|             continue; | ||||
|         } | ||||
|         const Id type{GetAttributeType(*this, input_type)}; | ||||
|         const Id id{DefineInput(*this, type)}; | ||||
|         Decorate(id, spv::Decoration::Location, static_cast<u32>(index)); | ||||
|         Name(id, fmt::format("in_attr{}", index)); | ||||
|         input_generics[index] = id; | ||||
|  | ||||
|         if (stage != Stage::Fragment) { | ||||
|             continue; | ||||
|         } | ||||
|         switch (generic.interpolation) { | ||||
|         case Interpolation::Smooth: | ||||
|             // Default | ||||
|             // Decorate(id, spv::Decoration::Smooth); | ||||
|             break; | ||||
|         case Interpolation::NoPerspective: | ||||
|             Decorate(id, spv::Decoration::NoPerspective); | ||||
|             break; | ||||
|         case Interpolation::Flat: | ||||
|             Decorate(id, spv::Decoration::Flat); | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -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: | ||||
|   | ||||
		Reference in New Issue
	
	Block a user