Procházet zdrojové kódy

spirv: Bitcast non-F32 output attributes to their type before store

ReinUsesLisp před 5 roky
rodič
revize
f3473c5143

+ 28 - 13
src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp

@@ -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) {