Signed-off-by: Zebediah Figura zfigura@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 49aece201..b8c0d7e53 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) { @@ -984,6 +1000,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", }; @@ -1206,6 +1223,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, "= ("); @@ -1272,6 +1303,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; @@ -1370,6 +1405,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); @@ -1413,6 +1455,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); }