|
@@ -52,7 +52,15 @@ Id OutputAccessChain(EmitContext& ctx, Id result_type, Id base, Args&&... args)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-std::optional<Id> OutputAttrPointer(EmitContext& ctx, IR::Attribute attr) {
|
|
|
|
|
|
|
+struct OutAttr {
|
|
|
|
|
+ OutAttr(Id pointer_) : pointer{pointer_} {}
|
|
|
|
|
+ OutAttr(Id pointer_, Id type_) : pointer{pointer_}, type{type_} {}
|
|
|
|
|
+
|
|
|
|
|
+ Id pointer{};
|
|
|
|
|
+ Id type{};
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+std::optional<OutAttr> OutputAttrPointer(EmitContext& ctx, IR::Attribute attr) {
|
|
|
if (IR::IsGeneric(attr)) {
|
|
if (IR::IsGeneric(attr)) {
|
|
|
const u32 index{IR::GenericAttributeIndex(attr)};
|
|
const u32 index{IR::GenericAttributeIndex(attr)};
|
|
|
const u32 element{IR::GenericAttributeElement(attr)};
|
|
const u32 element{IR::GenericAttributeElement(attr)};
|
|
@@ -90,20 +98,23 @@ std::optional<Id> OutputAttrPointer(EmitContext& ctx, IR::Attribute attr) {
|
|
|
return OutputAccessChain(ctx, ctx.output_f32, ctx.clip_distances, clip_num);
|
|
return OutputAccessChain(ctx, ctx.output_f32, ctx.clip_distances, clip_num);
|
|
|
}
|
|
}
|
|
|
case IR::Attribute::Layer:
|
|
case IR::Attribute::Layer:
|
|
|
- return ctx.profile.support_viewport_index_layer_non_geometry ||
|
|
|
|
|
- ctx.stage == Shader::Stage::Geometry
|
|
|
|
|
- ? std::optional<Id>{ctx.layer}
|
|
|
|
|
- : std::nullopt;
|
|
|
|
|
|
|
+ if (ctx.profile.support_viewport_index_layer_non_geometry ||
|
|
|
|
|
+ ctx.stage == Shader::Stage::Geometry) {
|
|
|
|
|
+ return OutAttr{ctx.layer, ctx.U32[1]};
|
|
|
|
|
+ }
|
|
|
|
|
+ return std::nullopt;
|
|
|
case IR::Attribute::ViewportIndex:
|
|
case IR::Attribute::ViewportIndex:
|
|
|
- return ctx.profile.support_viewport_index_layer_non_geometry ||
|
|
|
|
|
- ctx.stage == Shader::Stage::Geometry
|
|
|
|
|
- ? std::optional<Id>{ctx.viewport_index}
|
|
|
|
|
- : std::nullopt;
|
|
|
|
|
|
|
+ if (ctx.profile.support_viewport_index_layer_non_geometry ||
|
|
|
|
|
+ ctx.stage == Shader::Stage::Geometry) {
|
|
|
|
|
+ return OutAttr{ctx.viewport_index, ctx.U32[1]};
|
|
|
|
|
+ }
|
|
|
|
|
+ return std::nullopt;
|
|
|
case IR::Attribute::ViewportMask:
|
|
case IR::Attribute::ViewportMask:
|
|
|
if (!ctx.profile.support_viewport_mask) {
|
|
if (!ctx.profile.support_viewport_mask) {
|
|
|
return std::nullopt;
|
|
return std::nullopt;
|
|
|
}
|
|
}
|
|
|
- return ctx.OpAccessChain(ctx.output_u32, ctx.viewport_mask, ctx.u32_zero_value);
|
|
|
|
|
|
|
+ return OutAttr{ctx.OpAccessChain(ctx.output_u32, ctx.viewport_mask, ctx.u32_zero_value),
|
|
|
|
|
+ ctx.U32[1]};
|
|
|
default:
|
|
default:
|
|
|
throw NotImplementedException("Read attribute {}", attr);
|
|
throw NotImplementedException("Read attribute {}", attr);
|
|
|
}
|
|
}
|
|
@@ -262,10 +273,14 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, Id vertex) {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, Id value, [[maybe_unused]] Id vertex) {
|
|
void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, Id value, [[maybe_unused]] Id vertex) {
|
|
|
- const std::optional<Id> output{OutputAttrPointer(ctx, attr)};
|
|
|
|
|
- if (output) {
|
|
|
|
|
- ctx.OpStore(*output, value);
|
|
|
|
|
|
|
+ const std::optional<OutAttr> output{OutputAttrPointer(ctx, attr)};
|
|
|
|
|
+ if (!output) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (Sirit::ValidId(output->type)) {
|
|
|
|
|
+ value = ctx.OpBitcast(output->type, value);
|
|
|
}
|
|
}
|
|
|
|
|
+ ctx.OpStore(output->pointer, value);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
Id EmitGetAttributeIndexed(EmitContext& ctx, Id offset, Id vertex) {
|
|
Id EmitGetAttributeIndexed(EmitContext& ctx, Id offset, Id vertex) {
|