[PATCH vkd3d v3 5/5] vkd3d-shader/hlsl: Parse the Load() method.

Zebediah Figura zfigura at codeweavers.com
Thu Oct 7 11:39:07 CDT 2021


Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
 libs/vkd3d-shader/hlsl.c         |  46 ++++++++++++++
 libs/vkd3d-shader/hlsl.h         |  24 ++++++++
 libs/vkd3d-shader/hlsl.y         | 100 ++++++++++++++++++++++++++++++-
 libs/vkd3d-shader/hlsl_codegen.c |  14 +++++
 libs/vkd3d-shader/hlsl_sm1.c     |   5 ++
 libs/vkd3d-shader/hlsl_sm4.c     |   5 ++
 6 files changed, 193 insertions(+), 1 deletion(-)

diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c
index 6c8fa24e5..58753a919 100644
--- a/libs/vkd3d-shader/hlsl.c
+++ b/libs/vkd3d-shader/hlsl.c
@@ -626,6 +626,22 @@ struct hlsl_ir_load *hlsl_new_var_load(struct hlsl_ctx *ctx, struct hlsl_ir_var
     return hlsl_new_load(ctx, var, NULL, var->data_type, loc);
 }
 
+struct hlsl_ir_resource_load *hlsl_new_resource_load(struct hlsl_ctx *ctx, struct hlsl_type *data_type,
+        enum hlsl_resource_load_type type, struct hlsl_ir_var *resource, struct hlsl_ir_node *offset,
+        struct hlsl_ir_node *coords, struct vkd3d_shader_location loc)
+{
+    struct hlsl_ir_resource_load *load;
+
+    if (!(load = hlsl_alloc(ctx, sizeof(*load))))
+        return NULL;
+    init_node(&load->node, HLSL_IR_RESOURCE_LOAD, data_type, loc);
+    load->load_type = type;
+    load->resource.var = resource;
+    hlsl_src_from_node(&load->resource.offset, offset);
+    hlsl_src_from_node(&load->coords, coords);
+    return load;
+}
+
 struct hlsl_ir_swizzle *hlsl_new_swizzle(struct hlsl_ctx *ctx, DWORD s, unsigned int components,
         struct hlsl_ir_node *val, struct vkd3d_shader_location *loc)
 {
@@ -992,6 +1008,7 @@ const char *hlsl_node_type_to_string(enum hlsl_ir_node_type type)
         "HLSL_IR_LOAD",
         "HLSL_IR_LOOP",
         "HLSL_IR_JUMP",
+        "HLSL_IR_RESOURCE_LOAD",
         "HLSL_IR_STORE",
         "HLSL_IR_SWIZZLE",
     };
@@ -1214,6 +1231,20 @@ static void dump_ir_loop(struct hlsl_ctx *ctx, struct vkd3d_string_buffer *buffe
     vkd3d_string_buffer_printf(buffer, "}\n");
 }
 
+static void dump_ir_resource_load(struct vkd3d_string_buffer *buffer, const struct hlsl_ir_resource_load *load)
+{
+    static const char *const type_names[] =
+    {
+        [HLSL_RESOURCE_LOAD] = "load_resource",
+    };
+
+    vkd3d_string_buffer_printf(buffer, "%s(resource = ", type_names[load->load_type]);
+    dump_deref(buffer, &load->resource);
+    vkd3d_string_buffer_printf(buffer, ", coords = ");
+    dump_src(buffer, &load->coords);
+    vkd3d_string_buffer_printf(buffer, ")");
+}
+
 static void dump_ir_store(struct vkd3d_string_buffer *buffer, const struct hlsl_ir_store *store)
 {
     vkd3d_string_buffer_printf(buffer, "= (");
@@ -1280,6 +1311,10 @@ static void dump_instr(struct hlsl_ctx *ctx, struct vkd3d_string_buffer *buffer,
             dump_ir_loop(ctx, buffer, hlsl_ir_loop(instr));
             break;
 
+        case HLSL_IR_RESOURCE_LOAD:
+            dump_ir_resource_load(buffer, hlsl_ir_resource_load(instr));
+            break;
+
         case HLSL_IR_STORE:
             dump_ir_store(buffer, hlsl_ir_store(instr));
             break;
@@ -1378,6 +1413,13 @@ static void free_ir_loop(struct hlsl_ir_loop *loop)
     vkd3d_free(loop);
 }
 
+static void free_ir_resource_load(struct hlsl_ir_resource_load *load)
+{
+    hlsl_src_remove(&load->coords);
+    hlsl_src_remove(&load->resource.offset);
+    vkd3d_free(load);
+}
+
 static void free_ir_store(struct hlsl_ir_store *store)
 {
     hlsl_src_remove(&store->rhs);
@@ -1421,6 +1463,10 @@ void hlsl_free_instr(struct hlsl_ir_node *node)
             free_ir_loop(hlsl_ir_loop(node));
             break;
 
+        case HLSL_IR_RESOURCE_LOAD:
+            free_ir_resource_load(hlsl_ir_resource_load(node));
+            break;
+
         case HLSL_IR_STORE:
             free_ir_store(hlsl_ir_store(node));
             break;
diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h
index 64a90ffdc..80a8989c1 100644
--- a/libs/vkd3d-shader/hlsl.h
+++ b/libs/vkd3d-shader/hlsl.h
@@ -166,6 +166,7 @@ enum hlsl_ir_node_type
     HLSL_IR_LOAD,
     HLSL_IR_LOOP,
     HLSL_IR_JUMP,
+    HLSL_IR_RESOURCE_LOAD,
     HLSL_IR_STORE,
     HLSL_IR_SWIZZLE,
 };
@@ -239,6 +240,7 @@ struct hlsl_ir_var
     uint32_t is_output_semantic : 1;
     uint32_t is_uniform : 1;
     uint32_t is_param : 1;
+    uint32_t has_resource_access : 1;
 };
 
 struct hlsl_ir_function
@@ -366,6 +368,19 @@ struct hlsl_ir_load
     struct hlsl_deref src;
 };
 
+enum hlsl_resource_load_type
+{
+    HLSL_RESOURCE_LOAD,
+};
+
+struct hlsl_ir_resource_load
+{
+    struct hlsl_ir_node node;
+    enum hlsl_resource_load_type load_type;
+    struct hlsl_deref resource;
+    struct hlsl_src coords;
+};
+
 struct hlsl_ir_store
 {
     struct hlsl_ir_node node;
@@ -521,6 +536,12 @@ static inline struct hlsl_ir_loop *hlsl_ir_loop(const struct hlsl_ir_node *node)
     return CONTAINING_RECORD(node, struct hlsl_ir_loop, node);
 }
 
+static inline struct hlsl_ir_resource_load *hlsl_ir_resource_load(const struct hlsl_ir_node *node)
+{
+    assert(node->type == HLSL_IR_RESOURCE_LOAD);
+    return CONTAINING_RECORD(node, struct hlsl_ir_resource_load, node);
+}
+
 static inline struct hlsl_ir_store *hlsl_ir_store(const struct hlsl_ir_node *node)
 {
     assert(node->type == HLSL_IR_STORE);
@@ -648,6 +669,9 @@ struct hlsl_ir_jump *hlsl_new_jump(struct hlsl_ctx *ctx, enum hlsl_ir_jump_type
 struct hlsl_ir_load *hlsl_new_load(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, struct hlsl_ir_node *offset,
         struct hlsl_type *type, struct vkd3d_shader_location loc);
 struct hlsl_ir_loop *hlsl_new_loop(struct hlsl_ctx *ctx, struct vkd3d_shader_location loc);
+struct hlsl_ir_resource_load *hlsl_new_resource_load(struct hlsl_ctx *ctx, struct hlsl_type *data_type,
+        enum hlsl_resource_load_type type, struct hlsl_ir_var *resource, struct hlsl_ir_node *offset,
+        struct hlsl_ir_node *coords, struct vkd3d_shader_location loc);
 struct hlsl_ir_store *hlsl_new_simple_store(struct hlsl_ctx *ctx, struct hlsl_ir_var *lhs, struct hlsl_ir_node *rhs);
 struct hlsl_ir_store *hlsl_new_store(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, struct hlsl_ir_node *offset,
         struct hlsl_ir_node *rhs, unsigned int writemask, struct vkd3d_shader_location loc);
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y
index 32dd418d1..3bf40563f 100644
--- a/libs/vkd3d-shader/hlsl.y
+++ b/libs/vkd3d-shader/hlsl.y
@@ -843,15 +843,21 @@ static unsigned int evaluate_array_dimension(struct hlsl_ir_node *node)
 
         case HLSL_IR_EXPR:
         case HLSL_IR_LOAD:
+        case HLSL_IR_RESOURCE_LOAD:
         case HLSL_IR_SWIZZLE:
             FIXME("Unhandled type %s.\n", hlsl_node_type_to_string(node->type));
             return 0;
 
+        case HLSL_IR_IF:
+        case HLSL_IR_JUMP:
+        case HLSL_IR_LOOP:
         case HLSL_IR_STORE:
-        default:
             WARN("Invalid node type %s.\n", hlsl_node_type_to_string(node->type));
             return 0;
     }
+
+    assert(0);
+    return 0;
 }
 
 static bool expr_compatible_data_types(struct hlsl_type *t1, struct hlsl_type *t2)
@@ -1513,6 +1519,23 @@ static struct list *declare_vars(struct hlsl_ctx *ctx, struct hlsl_type *basic_t
     return statements_list;
 }
 
+static unsigned int sampler_dim_count(enum hlsl_sampler_dim dim)
+{
+    switch (dim)
+    {
+        case HLSL_SAMPLER_DIM_1D:
+            return 1;
+        case HLSL_SAMPLER_DIM_2D:
+            return 2;
+        case HLSL_SAMPLER_DIM_3D:
+        case HLSL_SAMPLER_DIM_CUBE:
+            return 3;
+        default:
+            assert(0);
+            return 0;
+    }
+}
+
 struct find_function_call_args
 {
     const struct parse_initializer *params;
@@ -1757,6 +1780,65 @@ static struct list *add_constructor(struct hlsl_ctx *ctx, struct hlsl_type *type
     return params->instrs;
 }
 
+static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_node *object,
+        const char *name, const struct parse_initializer *params, struct vkd3d_shader_location loc)
+{
+    const struct hlsl_type *object_type = object->data_type;
+    struct hlsl_ir_load *object_load;
+
+    if (object_type->type != HLSL_CLASS_OBJECT || object_type->base_type != HLSL_TYPE_TEXTURE
+            || object_type->sampler_dim == HLSL_SAMPLER_DIM_GENERIC)
+    {
+        struct vkd3d_string_buffer *string;
+
+        if ((string = hlsl_type_to_string(ctx, object_type)))
+            hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
+                    "Type '%s' does not have methods.", string->buffer);
+        hlsl_release_string_buffer(ctx, string);
+        return false;
+    }
+
+    /* Only HLSL_IR_LOAD can return an object. */
+    object_load = hlsl_ir_load(object);
+
+    if (!strcmp(name, "Load"))
+    {
+        const unsigned int sampler_dim = sampler_dim_count(object_type->sampler_dim);
+        struct hlsl_ir_resource_load *load;
+        struct hlsl_ir_node *coords;
+
+        if (params->args_count < 1 || params->args_count > 3)
+        {
+            hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT,
+                    "Wrong number of arguments to method 'Load': expected 1, 2, or 3, but got %u.", params->args_count);
+            return false;
+        }
+        if (params->args_count >= 2)
+            FIXME("Ignoring index and/or offset parameter(s).\n");
+
+        /* -1 for zero-indexing; +1 for the mipmap level */
+        if (!(coords = add_implicit_conversion(ctx, instrs, params->args[0],
+                ctx->builtin_types.vector[HLSL_TYPE_INT][sampler_dim - 1 + 1], &loc)))
+            return false;
+
+        if (!(load = hlsl_new_resource_load(ctx, object_type->e.resource_format, HLSL_RESOURCE_LOAD,
+                object_load->src.var, object_load->src.offset.node, coords, loc)))
+            return false;
+        list_add_tail(instrs, &load->node.entry);
+        return true;
+    }
+    else
+    {
+        struct vkd3d_string_buffer *string;
+
+        if ((string = hlsl_type_to_string(ctx, object_type)))
+            hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_NOT_DEFINED,
+                    "Method '%s' is not defined on type '%s'.", name, string->buffer);
+        hlsl_release_string_buffer(ctx, string);
+        return false;
+    }
+}
+
 }
 
 %locations
@@ -3085,6 +3167,22 @@ postfix_expr:
                 YYABORT;
             }
         }
+    | postfix_expr '.' any_identifier '(' func_arguments ')'
+        {
+            struct hlsl_ir_node *object = node_from_list($1);
+
+            list_move_tail($1, $5.instrs);
+            vkd3d_free($5.instrs);
+
+            if (!add_method_call(ctx, $1, object, $3, &$5, @3))
+            {
+                hlsl_free_instr_list($1);
+                vkd3d_free($5.args);
+                YYABORT;
+            }
+            vkd3d_free($5.args);
+            $$ = $1;
+        }
 
 unary_expr:
       postfix_expr
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c
index 9c9a38379..00fe76b2f 100644
--- a/libs/vkd3d-shader/hlsl_codegen.c
+++ b/libs/vkd3d-shader/hlsl_codegen.c
@@ -503,6 +503,7 @@ static bool dce(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
         case HLSL_IR_CONSTANT:
         case HLSL_IR_EXPR:
         case HLSL_IR_LOAD:
+        case HLSL_IR_RESOURCE_LOAD:
         case HLSL_IR_SWIZZLE:
             if (list_empty(&instr->uses))
             {
@@ -640,6 +641,16 @@ static void compute_liveness_recurse(struct list *instrs, unsigned int loop_firs
                     loop_last ? loop_last : loop->next_index);
             break;
         }
+        case HLSL_IR_RESOURCE_LOAD:
+        {
+            struct hlsl_ir_resource_load *load = hlsl_ir_resource_load(instr);
+
+            load->resource.var->has_resource_access = 1;
+            if (load->resource.offset.node)
+                load->resource.offset.node->last_read = instr->index;
+            load->coords.node->last_read = instr->index;
+            break;
+        }
         case HLSL_IR_SWIZZLE:
         {
             struct hlsl_ir_swizzle *swizzle = hlsl_ir_swizzle(instr);
@@ -665,7 +676,10 @@ static void compute_liveness(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl
     LIST_FOR_EACH_ENTRY(scope, &ctx->scopes, struct hlsl_scope, entry)
     {
         LIST_FOR_EACH_ENTRY(var, &scope->vars, struct hlsl_ir_var, scope_entry)
+        {
             var->first_write = var->last_read = 0;
+            var->has_resource_access = 0;
+        }
     }
 
     LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
diff --git a/libs/vkd3d-shader/hlsl_sm1.c b/libs/vkd3d-shader/hlsl_sm1.c
index ee2870eca..9fc1b2210 100644
--- a/libs/vkd3d-shader/hlsl_sm1.c
+++ b/libs/vkd3d-shader/hlsl_sm1.c
@@ -778,6 +778,11 @@ static void write_sm1_instructions(struct hlsl_ctx *ctx, struct vkd3d_bytecode_b
                 hlsl_fixme(ctx, instr->loc, "SM1 matrix expression.");
                 continue;
             }
+            else if (instr->data_type->type == HLSL_CLASS_OBJECT)
+            {
+                hlsl_fixme(ctx, instr->loc, "Object copy.\n");
+                break;
+            }
 
             assert(instr->data_type->type == HLSL_CLASS_SCALAR || instr->data_type->type == HLSL_CLASS_VECTOR);
         }
diff --git a/libs/vkd3d-shader/hlsl_sm4.c b/libs/vkd3d-shader/hlsl_sm4.c
index 328a8ba1b..b4fb8f2f7 100644
--- a/libs/vkd3d-shader/hlsl_sm4.c
+++ b/libs/vkd3d-shader/hlsl_sm4.c
@@ -1286,6 +1286,11 @@ static void write_sm4_shdr(struct hlsl_ctx *ctx,
                 FIXME("Matrix operations need to be lowered.\n");
                 break;
             }
+            else if (instr->data_type->type == HLSL_CLASS_OBJECT)
+            {
+                hlsl_fixme(ctx, instr->loc, "Object copy.\n");
+                break;
+            }
 
             assert(instr->data_type->type == HLSL_CLASS_SCALAR || instr->data_type->type == HLSL_CLASS_VECTOR);
         }
-- 
2.33.0




More information about the wine-devel mailing list