Zebediah Figura : vkd3d-shader: Create a separate variable for input varyings.

Alexandre Julliard julliard at winehq.org
Tue Mar 30 14:57:57 CDT 2021


Module: vkd3d
Branch: master
Commit: a6e47e155217741212955897f1b00bbfefce2d9d
URL:    https://source.winehq.org/git/vkd3d.git/?a=commit;h=a6e47e155217741212955897f1b00bbfefce2d9d

Author: Zebediah Figura <zfigura at codeweavers.com>
Date:   Sun Mar 28 21:46:57 2021 +0200

vkd3d-shader: Create a separate variable for input varyings.

Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
Signed-off-by: Matteo Bruni <mbruni at codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 libs/vkd3d-shader/hlsl_codegen.c | 83 ++++++++++++++++++++++++++++++++++++++--
 tests/hlsl-invalid.shader_test   | 11 ++++++
 2 files changed, 91 insertions(+), 3 deletions(-)

diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c
index e9f3699..ca38fe7 100644
--- a/libs/vkd3d-shader/hlsl_codegen.c
+++ b/libs/vkd3d-shader/hlsl_codegen.c
@@ -63,6 +63,83 @@ static void prepend_uniform_copy(struct hlsl_ctx *ctx, struct list *instrs, stru
     list_add_after(&load->node.entry, &store->node.entry);
 }
 
+static void prepend_input_copy(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_var *var,
+        struct hlsl_type *type, unsigned int field_offset, const char *semantic)
+{
+    struct vkd3d_string_buffer *name;
+    struct hlsl_ir_assignment *store;
+    struct hlsl_ir_constant *offset;
+    struct hlsl_ir_var *varying;
+    struct hlsl_ir_load *load;
+
+    if (!(name = vkd3d_string_buffer_get(&ctx->string_buffers)))
+    {
+        ctx->failed = true;
+        return;
+    }
+    vkd3d_string_buffer_printf(name, "<input-%s>", semantic);
+    if (!(varying = hlsl_new_var(vkd3d_strdup(name->buffer), type, var->loc, vkd3d_strdup(semantic), NULL)))
+    {
+        vkd3d_string_buffer_release(&ctx->string_buffers, name);
+        ctx->failed = true;
+        return;
+    }
+    vkd3d_string_buffer_release(&ctx->string_buffers, name);
+    varying->is_input_varying = 1;
+    list_add_head(&ctx->globals->vars, &varying->scope_entry);
+
+    if (!(load = hlsl_new_var_load(varying, var->loc)))
+    {
+        ctx->failed = true;
+        return;
+    }
+    list_add_head(instrs, &load->node.entry);
+
+    if (!(offset = hlsl_new_uint_constant(ctx, field_offset * 4, var->loc)))
+    {
+        ctx->failed = true;
+        return;
+    }
+    list_add_after(&load->node.entry, &offset->node.entry);
+
+    if (!(store = hlsl_new_assignment(var, &offset->node, &load->node, 0, var->loc)))
+    {
+        ctx->failed = true;
+        return;
+    }
+    list_add_after(&offset->node.entry, &store->node.entry);
+}
+
+static void prepend_input_struct_copy(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_var *var,
+        struct hlsl_type *type, unsigned int field_offset)
+{
+    struct hlsl_struct_field *field;
+
+    LIST_FOR_EACH_ENTRY(field, type->e.elements, struct hlsl_struct_field, entry)
+    {
+        if (field->type->type == HLSL_CLASS_STRUCT)
+            prepend_input_struct_copy(ctx, instrs, var, field->type, field_offset + field->reg_offset);
+        else if (field->semantic)
+            prepend_input_copy(ctx, instrs, var, field->type, field_offset + field->reg_offset, field->semantic);
+        else
+            hlsl_error(ctx, field->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_SEMANTIC,
+                    "Field '%s' is missing a semantic.", field->name);
+    }
+}
+
+/* Split input varyings into two variables representing the varying and temp
+ * registers, and copy the former to the latter, so that writes to input
+ * varyings work. */
+static void prepend_input_var_copy(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_var *var)
+{
+    if (var->data_type->type == HLSL_CLASS_STRUCT)
+        prepend_input_struct_copy(ctx, instrs, var, var->data_type, 0);
+    else if (var->semantic)
+        prepend_input_copy(ctx, instrs, var, var->data_type, 0, var->semantic);
+
+    var->is_input_varying = 0;
+}
+
 static bool transform_ir(struct hlsl_ctx *ctx, bool (*func)(struct hlsl_ctx *ctx, struct hlsl_ir_node *, void *),
         struct list *instrs, void *context)
 {
@@ -441,14 +518,12 @@ static void compute_liveness(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl
 
     LIST_FOR_EACH_ENTRY(var, &ctx->globals->vars, struct hlsl_ir_var, scope_entry)
     {
-        if (var->is_uniform)
+        if (var->is_uniform || var->is_input_varying)
             var->first_write = 1;
     }
 
     LIST_FOR_EACH_ENTRY(var, entry_func->parameters, struct hlsl_ir_var, param_entry)
     {
-        if (var->is_input_varying)
-            var->first_write = 1;
         if (var->is_output_varying)
             var->last_read = UINT_MAX;
     }
@@ -475,6 +550,8 @@ int hlsl_emit_dxbc(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_fun
     {
         if (var->is_uniform)
             prepend_uniform_copy(ctx, entry_func->body, var);
+        if (var->is_input_varying)
+            prepend_input_var_copy(ctx, entry_func->body, var);
     }
 
     while (transform_ir(ctx, fold_redundant_casts, entry_func->body, NULL));
diff --git a/tests/hlsl-invalid.shader_test b/tests/hlsl-invalid.shader_test
index b30ff3d..59a0dbe 100644
--- a/tests/hlsl-invalid.shader_test
+++ b/tests/hlsl-invalid.shader_test
@@ -135,3 +135,14 @@ float4 main() : sv_target
     const float4 x;
     return x;
 }
+
+[pixel shader fail]
+struct input
+{
+    float4 a;
+};
+
+float4 main(struct input i) : sv_target
+{
+    return i.a;
+}




More information about the wine-cvs mailing list