Zebediah Figura : vkd3d-shader: Split struct copies.

Alexandre Julliard julliard at winehq.org
Mon Mar 22 16:48:26 CDT 2021


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

Author: Zebediah Figura <zfigura at codeweavers.com>
Date:   Thu Mar 18 00:22:21 2021 -0500

vkd3d-shader: Split struct copies.

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 | 81 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 81 insertions(+)

diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c
index 5b68a46..2382ffe 100644
--- a/libs/vkd3d-shader/hlsl_codegen.c
+++ b/libs/vkd3d-shader/hlsl_codegen.c
@@ -84,6 +84,86 @@ static bool fold_redundant_casts(struct hlsl_ctx *ctx, struct hlsl_ir_node *inst
     return false;
 }
 
+static bool split_struct_copies(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
+{
+    const struct hlsl_struct_field *field;
+    const struct hlsl_ir_load *rhs_load;
+    struct hlsl_ir_assignment *assign;
+    const struct hlsl_ir_node *rhs;
+    const struct hlsl_type *type;
+
+    if (instr->type != HLSL_IR_ASSIGNMENT)
+        return false;
+
+    assign = hlsl_ir_assignment(instr);
+    rhs = assign->rhs.node;
+    type = rhs->data_type;
+    if (type->type != HLSL_CLASS_STRUCT)
+        return false;
+
+    rhs_load = hlsl_ir_load(rhs);
+
+    LIST_FOR_EACH_ENTRY(field, type->e.elements, struct hlsl_struct_field, entry)
+    {
+        struct hlsl_ir_node *offset, *add;
+        struct hlsl_ir_assignment *store;
+        struct hlsl_ir_load *field_load;
+        struct hlsl_ir_constant *c;
+
+        if (!(c = hlsl_new_uint_constant(ctx, field->reg_offset * 4, instr->loc)))
+        {
+            ctx->failed = true;
+            return false;
+        }
+        list_add_before(&instr->entry, &c->node.entry);
+
+        offset = &c->node;
+        if (rhs_load->src.offset.node)
+        {
+            if (!(add = hlsl_new_binary_expr(HLSL_IR_BINOP_ADD, rhs_load->src.offset.node, &c->node)))
+            {
+                ctx->failed = true;
+                return false;
+            }
+            list_add_before(&instr->entry, &add->entry);
+            offset = add;
+        }
+        if (!(field_load = hlsl_new_load(rhs_load->src.var, offset, field->type, instr->loc)))
+        {
+            ctx->failed = true;
+            return false;
+        }
+        list_add_before(&instr->entry, &field_load->node.entry);
+
+        offset = &c->node;
+        if (assign->lhs.offset.node)
+        {
+            if (!(add = hlsl_new_binary_expr(HLSL_IR_BINOP_ADD, assign->lhs.offset.node, &c->node)))
+            {
+                ctx->failed = true;
+                return false;
+            }
+            list_add_before(&instr->entry, &add->entry);
+            offset = add;
+        }
+
+        if (!(store = hlsl_new_assignment(assign->lhs.var, offset, &field_load->node, 0, instr->loc)))
+        {
+            ctx->failed = true;
+            return false;
+        }
+        list_add_before(&instr->entry, &store->node.entry);
+    }
+
+    /* Remove the assignment instruction, so that we can split structs
+     * which contain other structs. Although assignment instructions
+     * produce a value, we don't allow HLSL_IR_ASSIGNMENT to be used as
+     * a source. */
+    list_remove(&assign->node.entry);
+    hlsl_free_instr(&assign->node);
+    return true;
+}
+
 static bool fold_constants(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
 {
     struct hlsl_ir_constant *arg1, *arg2 = NULL, *res;
@@ -317,6 +397,7 @@ int hlsl_emit_dxbc(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_fun
     list_move_head(entry_func->body, &ctx->static_initializers);
 
     while (transform_ir(ctx, fold_redundant_casts, entry_func->body, NULL));
+    while (transform_ir(ctx, split_struct_copies, entry_func->body, NULL));
     while (transform_ir(ctx, fold_constants, entry_func->body, NULL));
     while (transform_ir(ctx, dce, entry_func->body, NULL));
 




More information about the wine-cvs mailing list