From: Zebediah Figura zfigura@codeweavers.com
--- libs/vkd3d-shader/hlsl.c | 52 +++++++++++++++++++++++++++++--- libs/vkd3d-shader/hlsl.h | 17 +++++++++++ libs/vkd3d-shader/hlsl.y | 51 ++++++++++++++++++++++++++++--- libs/vkd3d-shader/hlsl_codegen.c | 17 +++++++++++ 4 files changed, 127 insertions(+), 10 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index 8591fe31..1f35b1ac 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -373,7 +373,7 @@ static bool init_deref(struct hlsl_ctx *ctx, struct hlsl_deref *deref, struct hl return true; }
-static struct hlsl_type *get_type_from_deref(struct hlsl_ctx *ctx, const struct hlsl_deref *deref) +struct hlsl_type *hlsl_deref_get_type(struct hlsl_ctx *ctx, const struct hlsl_deref *deref) { struct hlsl_type *type; unsigned int i; @@ -400,7 +400,7 @@ static bool init_deref_from_component_index(struct hlsl_ctx *ctx, struct hlsl_bl list_init(&block->instrs);
path_len = 0; - path_type = get_type_from_deref(ctx, prefix); + path_type = hlsl_deref_get_type(ctx, prefix); path_index = index; while (!type_is_single_component(path_type)) { @@ -415,7 +415,7 @@ static bool init_deref_from_component_index(struct hlsl_ctx *ctx, struct hlsl_bl for (i = 0; i < prefix->path_len; ++i) hlsl_src_from_node(&deref->path[deref_path_len++], prefix->path[i].node);
- path_type = get_type_from_deref(ctx, prefix); + path_type = hlsl_deref_get_type(ctx, prefix); path_index = index; while (!type_is_single_component(path_type)) { @@ -1045,7 +1045,7 @@ struct hlsl_ir_load *hlsl_new_load_index(struct hlsl_ctx *ctx, const struct hlsl
assert(!deref->offset.node);
- type = get_type_from_deref(ctx, deref); + type = hlsl_deref_get_type(ctx, deref); if (idx) type = hlsl_get_element_type_from_path_index(ctx, type, idx);
@@ -1087,7 +1087,7 @@ struct hlsl_ir_load *hlsl_new_load_component(struct hlsl_ctx *ctx, struct hlsl_b if (!(load = hlsl_alloc(ctx, sizeof(*load)))) return NULL;
- type = get_type_from_deref(ctx, deref); + type = hlsl_deref_get_type(ctx, deref); comp_type = hlsl_type_get_component_type(ctx, type, comp); init_node(&load->node, HLSL_IR_LOAD, comp_type, loc);
@@ -1129,6 +1129,20 @@ struct hlsl_ir_resource_load *hlsl_new_resource_load(struct hlsl_ctx *ctx, return load; }
+struct hlsl_ir_resource_store *hlsl_new_resource_store(struct hlsl_ctx *ctx, const struct hlsl_deref *resource, + struct hlsl_ir_node *coords, struct hlsl_ir_node *value, const struct vkd3d_shader_location *loc) +{ + struct hlsl_ir_resource_store *store; + + if (!(store = hlsl_alloc(ctx, sizeof(*store)))) + return NULL; + init_node(&store->node, HLSL_IR_RESOURCE_STORE, NULL, loc); + hlsl_copy_deref(ctx, &store->resource, resource); + hlsl_src_from_node(&store->coords, coords); + hlsl_src_from_node(&store->value, value); + return store; +} + struct hlsl_ir_swizzle *hlsl_new_swizzle(struct hlsl_ctx *ctx, DWORD s, unsigned int components, struct hlsl_ir_node *val, const struct vkd3d_shader_location *loc) { @@ -1511,6 +1525,7 @@ const char *hlsl_node_type_to_string(enum hlsl_ir_node_type type) "HLSL_IR_LOOP", "HLSL_IR_JUMP", "HLSL_IR_RESOURCE_LOAD", + "HLSL_IR_RESOURCE_STORE", "HLSL_IR_STORE", "HLSL_IR_SWIZZLE", }; @@ -1800,6 +1815,17 @@ static void dump_ir_resource_load(struct vkd3d_string_buffer *buffer, const stru vkd3d_string_buffer_printf(buffer, ")"); }
+static void dump_ir_resource_store(struct vkd3d_string_buffer *buffer, const struct hlsl_ir_resource_store *store) +{ + vkd3d_string_buffer_printf(buffer, "store_resource(resource = "); + dump_deref(buffer, &store->resource); + vkd3d_string_buffer_printf(buffer, ", coords = "); + dump_src(buffer, &store->coords); + vkd3d_string_buffer_printf(buffer, ", value = "); + dump_src(buffer, &store->value); + 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, "= ("); @@ -1867,6 +1893,10 @@ static void dump_instr(struct hlsl_ctx *ctx, struct vkd3d_string_buffer *buffer, dump_ir_resource_load(buffer, hlsl_ir_resource_load(instr)); break;
+ case HLSL_IR_RESOURCE_STORE: + dump_ir_resource_store(buffer, hlsl_ir_resource_store(instr)); + break; + case HLSL_IR_STORE: dump_ir_store(buffer, hlsl_ir_store(instr)); break; @@ -1992,6 +2022,14 @@ static void free_ir_resource_load(struct hlsl_ir_resource_load *load) vkd3d_free(load); }
+static void free_ir_resource_store(struct hlsl_ir_resource_store *store) +{ + hlsl_src_remove(&store->resource.offset); + hlsl_src_remove(&store->coords); + hlsl_src_remove(&store->value); + vkd3d_free(store); +} + static void free_ir_store(struct hlsl_ir_store *store) { hlsl_src_remove(&store->rhs); @@ -2039,6 +2077,10 @@ void hlsl_free_instr(struct hlsl_ir_node *node) free_ir_resource_load(hlsl_ir_resource_load(node)); break;
+ case HLSL_IR_RESOURCE_STORE: + free_ir_resource_store(hlsl_ir_resource_store(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 f237d6c4..26629fcd 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -178,6 +178,7 @@ enum hlsl_ir_node_type HLSL_IR_LOOP, HLSL_IR_JUMP, HLSL_IR_RESOURCE_LOAD, + HLSL_IR_RESOURCE_STORE, HLSL_IR_STORE, HLSL_IR_SWIZZLE, }; @@ -410,6 +411,13 @@ struct hlsl_ir_resource_load struct hlsl_src coords, lod, texel_offset; };
+struct hlsl_ir_resource_store +{ + struct hlsl_ir_node node; + struct hlsl_deref resource; + struct hlsl_src coords, value; +}; + struct hlsl_ir_store { struct hlsl_ir_node node; @@ -578,6 +586,12 @@ static inline struct hlsl_ir_resource_load *hlsl_ir_resource_load(const struct h return CONTAINING_RECORD(node, struct hlsl_ir_resource_load, node); }
+static inline struct hlsl_ir_resource_store *hlsl_ir_resource_store(const struct hlsl_ir_node *node) +{ + assert(node->type == HLSL_IR_RESOURCE_STORE); + return CONTAINING_RECORD(node, struct hlsl_ir_resource_store, node); +} + static inline struct hlsl_ir_store *hlsl_ir_store(const struct hlsl_ir_node *node) { assert(node->type == HLSL_IR_STORE); @@ -781,6 +795,8 @@ struct hlsl_ir_store *hlsl_new_store_component(struct hlsl_ctx *ctx, struct hlsl 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, const struct hlsl_resource_load_params *params, const struct vkd3d_shader_location *loc); +struct hlsl_ir_resource_store *hlsl_new_resource_store(struct hlsl_ctx *ctx, const struct hlsl_deref *resource, + struct hlsl_ir_node *coords, struct hlsl_ir_node *value, const struct vkd3d_shader_location *loc); struct hlsl_type *hlsl_new_struct_type(struct hlsl_ctx *ctx, const char *name, struct hlsl_struct_field *fields, size_t field_count); struct hlsl_ir_swizzle *hlsl_new_swizzle(struct hlsl_ctx *ctx, DWORD s, unsigned int components, @@ -829,6 +845,7 @@ unsigned int hlsl_combine_writemasks(unsigned int first, unsigned int second); unsigned int hlsl_map_swizzle(unsigned int swizzle, unsigned int writemask); unsigned int hlsl_swizzle_from_writemask(unsigned int writemask);
+struct hlsl_type *hlsl_deref_get_type(struct hlsl_ctx *ctx, const struct hlsl_deref *deref); bool hlsl_component_index_range_from_deref(struct hlsl_ctx *ctx, const struct hlsl_deref *deref, unsigned int *start, unsigned int *count); bool hlsl_offset_from_deref(struct hlsl_ctx *ctx, const struct hlsl_deref *deref, unsigned int *offset); diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index d76ea92e..00842195 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -1159,6 +1159,7 @@ static unsigned int evaluate_array_dimension(struct hlsl_ir_node *node) case HLSL_IR_IF: case HLSL_IR_JUMP: case HLSL_IR_LOOP: + case HLSL_IR_RESOURCE_STORE: case HLSL_IR_STORE: WARN("Invalid node type %s.\n", hlsl_node_type_to_string(node->type)); return 0; @@ -1699,7 +1700,6 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct list *in enum parse_assign_op assign_op, struct hlsl_ir_node *rhs) { struct hlsl_type *lhs_type = lhs->data_type; - struct hlsl_ir_store *store; struct hlsl_ir_expr *copy; unsigned int writemask = 0;
@@ -1724,7 +1724,7 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct list *in if (!(rhs = add_implicit_conversion(ctx, instrs, rhs, lhs_type, &rhs->loc))) return NULL;
- while (lhs->type != HLSL_IR_LOAD) + while (lhs->type != HLSL_IR_LOAD && lhs->type != HLSL_IR_RESOURCE_LOAD) { if (lhs->type == HLSL_IR_EXPR && hlsl_ir_expr(lhs)->op == HLSL_OP1_CAST) { @@ -1761,9 +1761,50 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct list *in } }
- if (!(store = hlsl_new_store_index(ctx, &hlsl_ir_load(lhs)->src, NULL, rhs, writemask, &rhs->loc))) - return NULL; - list_add_tail(instrs, &store->node.entry); + if (lhs->type == HLSL_IR_RESOURCE_LOAD) + { + struct hlsl_ir_resource_load *load = hlsl_ir_resource_load(lhs); + struct hlsl_ir_resource_store *store; + struct hlsl_type *resource_type; + struct hlsl_ir_swizzle *coords; + unsigned int dim_count; + + /* Such an lvalue was produced by an index expression. */ + assert(load->load_type == HLSL_RESOURCE_LOAD); + resource_type = hlsl_deref_get_type(ctx, &load->resource); + assert(resource_type->type == HLSL_CLASS_OBJECT); + assert(resource_type->base_type == HLSL_TYPE_TEXTURE || resource_type->base_type == HLSL_TYPE_UAV); + + if (resource_type->base_type != HLSL_TYPE_UAV) + hlsl_error(ctx, &lhs->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "Read-only resources cannot be stored to."); + + dim_count = hlsl_sampler_dim_count(resource_type->sampler_dim); + + if (writemask != ((1u << resource_type->e.resource_format->dimx) - 1)) + hlsl_error(ctx, &lhs->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_WRITEMASK, + "Resource store expressions must write to all components."); + + /* Remove the (implicit) mipmap level from the load expression. */ + assert(load->coords.node->data_type->type == HLSL_CLASS_VECTOR); + assert(load->coords.node->data_type->base_type == HLSL_TYPE_UINT); + assert(load->coords.node->data_type->dimx == dim_count + 1); + if (!(coords = hlsl_new_swizzle(ctx, HLSL_SWIZZLE(X, Y, Z, W), dim_count, load->coords.node, &lhs->loc))) + return NULL; + list_add_tail(instrs, &coords->node.entry); + + if (!(store = hlsl_new_resource_store(ctx, &load->resource, &coords->node, rhs, &lhs->loc))) + return NULL; + list_add_tail(instrs, &store->node.entry); + } + else + { + struct hlsl_ir_store *store; + + if (!(store = hlsl_new_store_index(ctx, &hlsl_ir_load(lhs)->src, NULL, rhs, writemask, &rhs->loc))) + return NULL; + list_add_tail(instrs, &store->node.entry); + }
/* Don't use the instruction itself as a source, as this makes structure * splitting easier. Instead copy it here. Since we retrieve sources from diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 3e36aa05..2ebfa87b 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -160,6 +160,10 @@ static bool transform_deref_paths_into_offsets(struct hlsl_ctx *ctx, struct hlsl replace_deref_path_with_offset(ctx, &hlsl_ir_resource_load(instr)->sampler, instr); return true;
+ case HLSL_IR_RESOURCE_STORE: + replace_deref_path_with_offset(ctx, &hlsl_ir_resource_store(instr)->resource, instr); + return true; + default: return false; } @@ -1588,6 +1592,7 @@ static bool dce(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) case HLSL_IR_IF: case HLSL_IR_JUMP: case HLSL_IR_LOOP: + case HLSL_IR_RESOURCE_STORE: break; }
@@ -1724,6 +1729,18 @@ static void compute_liveness_recurse(struct hlsl_block *block, unsigned int loop load->lod.node->last_read = instr->index; break; } + case HLSL_IR_RESOURCE_STORE: + { + struct hlsl_ir_resource_store *store = hlsl_ir_resource_store(instr); + + var = store->resource.var; + var->last_read = max(var->last_read, var_last_read); + if (store->resource.offset.node) + store->resource.offset.node->last_read = instr->index; + store->coords.node->last_read = instr->index; + store->value.node->last_read = instr->index; + break; + } case HLSL_IR_SWIZZLE: { struct hlsl_ir_swizzle *swizzle = hlsl_ir_swizzle(instr);