From 9525eb2f0c996490b17362e27247a2c5cb79b9cf Mon Sep 17 00:00:00 2001 From: Shaun Ren Date: Fri, 11 Apr 2025 11:36:44 -0400 Subject: [PATCH] vkd3d-shader/hlsl: Parse the Append() method for stream outputs. --- libs/vkd3d-shader/hlsl.c | 38 ++++++++++++++----- libs/vkd3d-shader/hlsl.h | 12 +++++- libs/vkd3d-shader/hlsl.y | 65 ++++++++++++++++++++++++-------- libs/vkd3d-shader/hlsl_codegen.c | 12 +++++- 4 files changed, 97 insertions(+), 30 deletions(-) diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index 8915ca5df..8fdf972f3 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -2057,24 +2057,28 @@ struct hlsl_ir_node *hlsl_block_add_resource_load(struct hlsl_ctx *ctx, struct h return append_new_instr(ctx, block, hlsl_new_resource_load(ctx, params, loc)); } -static struct hlsl_ir_node *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) +static struct hlsl_ir_node *hlsl_new_resource_store(struct hlsl_ctx *ctx, enum hlsl_resource_store_type type, + 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); + store->store_type = type; + hlsl_copy_deref(ctx, &store->resource, resource); hlsl_src_from_node(&store->coords, coords); hlsl_src_from_node(&store->value, value); return &store->node; } -void hlsl_block_add_resource_store(struct hlsl_ctx *ctx, struct hlsl_block *block, const struct hlsl_deref *resource, - struct hlsl_ir_node *coords, struct hlsl_ir_node *value, const struct vkd3d_shader_location *loc) +void hlsl_block_add_resource_store(struct hlsl_ctx *ctx, struct hlsl_block *block, + enum hlsl_resource_store_type type, const struct hlsl_deref *resource, struct hlsl_ir_node *coords, + struct hlsl_ir_node *value, const struct vkd3d_shader_location *loc) { - append_new_instr(ctx, block, hlsl_new_resource_store(ctx, resource, coords, value, loc)); + append_new_instr(ctx, block, hlsl_new_resource_store(ctx, type, resource, coords, value, loc)); } struct hlsl_ir_node *hlsl_new_swizzle(struct hlsl_ctx *ctx, uint32_t s, unsigned int component_count, @@ -2593,6 +2597,7 @@ static struct hlsl_ir_node *clone_resource_store(struct hlsl_ctx *ctx, if (!(dst = hlsl_alloc(ctx, sizeof(*dst)))) return NULL; init_node(&dst->node, HLSL_IR_RESOURCE_STORE, NULL, &src->node.loc); + dst->store_type = src->store_type; if (!clone_deref(ctx, map, &dst->resource, &src->resource)) { vkd3d_free(dst); @@ -3724,12 +3729,25 @@ static void dump_ir_resource_load(struct vkd3d_string_buffer *buffer, const stru 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 = "); + static const char *const type_names[] = + { + [HLSL_RESOURCE_STORE] = "store_resource", + [HLSL_RESOURCE_STREAM_APPEND] = "stream_append", + }; + + VKD3D_ASSERT(store->store_type < ARRAY_SIZE(type_names)); + vkd3d_string_buffer_printf(buffer, "%s(resource = ", type_names[store->store_type]); 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); + if (store->coords.node) + { + vkd3d_string_buffer_printf(buffer, ", coords = "); + dump_src(buffer, &store->coords); + } + if (store->value.node) + { + vkd3d_string_buffer_printf(buffer, ", value = "); + dump_src(buffer, &store->value); + } vkd3d_string_buffer_printf(buffer, ")"); } diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 92f26cdb8..e3e436e3a 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -894,9 +894,16 @@ struct hlsl_ir_resource_load enum hlsl_sampler_dim sampling_dim; }; +enum hlsl_resource_store_type +{ + HLSL_RESOURCE_STORE, + HLSL_RESOURCE_STREAM_APPEND, +}; + struct hlsl_ir_resource_store { struct hlsl_ir_node node; + enum hlsl_resource_store_type store_type; struct hlsl_deref resource; struct hlsl_src coords, value; }; @@ -1554,8 +1561,9 @@ void hlsl_block_add_loop(struct hlsl_ctx *ctx, struct hlsl_block *block, unsigned int unroll_limit, const struct vkd3d_shader_location *loc); struct hlsl_ir_node *hlsl_block_add_resource_load(struct hlsl_ctx *ctx, struct hlsl_block *block, const struct hlsl_resource_load_params *params, const struct vkd3d_shader_location *loc); -void hlsl_block_add_resource_store(struct hlsl_ctx *ctx, struct hlsl_block *block, const struct hlsl_deref *resource, - struct hlsl_ir_node *coords, struct hlsl_ir_node *value, const struct vkd3d_shader_location *loc); +void hlsl_block_add_resource_store(struct hlsl_ctx *ctx, struct hlsl_block *block, + enum hlsl_resource_store_type type, const struct hlsl_deref *resource, struct hlsl_ir_node *coords, + struct hlsl_ir_node *value, const struct vkd3d_shader_location *loc); struct hlsl_ir_node *hlsl_block_add_simple_load(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_ir_var *var, const struct vkd3d_shader_location *loc); void hlsl_block_add_simple_store(struct hlsl_ctx *ctx, struct hlsl_block *block, diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 40fd142f5..d1fffd3ca 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -2115,7 +2115,7 @@ static bool add_assignment(struct hlsl_ctx *ctx, struct hlsl_block *block, struc VKD3D_ASSERT(coords->data_type->e.numeric.type == HLSL_TYPE_UINT); VKD3D_ASSERT(coords->data_type->e.numeric.dimx == dim_count); - hlsl_block_add_resource_store(ctx, block, &resource_deref, coords, rhs, &lhs->loc); + hlsl_block_add_resource_store(ctx, block, HLSL_RESOURCE_STORE, &resource_deref, coords, rhs, &lhs->loc); hlsl_cleanup_deref(&resource_deref); } else if (matrix_writemask) @@ -6220,12 +6220,37 @@ static bool add_store_method_call(struct hlsl_ctx *ctx, struct hlsl_block *block if (!hlsl_init_deref_from_index_chain(ctx, &resource_deref, object)) return false; - hlsl_block_add_resource_store(ctx, block, &resource_deref, offset, rhs, loc); + hlsl_block_add_resource_store(ctx, block, HLSL_RESOURCE_STORE, &resource_deref, offset, rhs, loc); hlsl_cleanup_deref(&resource_deref); return true; } +static bool add_so_append_method_call(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_ir_node *object, + const char *name, const struct parse_initializer *params, const struct vkd3d_shader_location *loc) +{ + struct hlsl_deref so_deref; + struct hlsl_ir_node *rhs; + + if (params->args_count != 1) + { + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT, + "Wrong number of arguments to method '%s': expected 1.", name); + return false; + } + + if (!hlsl_init_deref_from_index_chain(ctx, &so_deref, object)) + return false; + + if (!(rhs = add_implicit_conversion(ctx, block, params->args[0], object->data_type->e.so.type, loc))) + return false; + + hlsl_block_add_resource_store(ctx, block, HLSL_RESOURCE_STREAM_APPEND, &so_deref, NULL, rhs, loc); + hlsl_cleanup_deref(&so_deref); + + return true; +} + static const struct method_function { const char *name; @@ -6269,6 +6294,11 @@ static const struct method_function uav_methods[] = { "Store4", add_store_method_call, "00000000000001" }, }; +static const struct method_function so_methods[] = +{ + { "Append", add_so_append_method_call, "" }, +}; + static int object_method_function_name_compare(const void *a, const void *b) { const struct method_function *func = b; @@ -6280,8 +6310,7 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct hlsl_block *block, stru const char *name, const struct parse_initializer *params, const struct vkd3d_shader_location *loc) { const struct hlsl_type *object_type = object->data_type; - const struct method_function *method, *methods; - unsigned int count; + const struct method_function *method; if (object_type->class == HLSL_CLASS_ERROR) { @@ -6300,13 +6329,24 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct hlsl_block *block, stru if (object_type->class == HLSL_CLASS_TEXTURE) { - count = ARRAY_SIZE(texture_methods); - methods = texture_methods; + method = bsearch(name, texture_methods, ARRAY_SIZE(texture_methods), sizeof(*method), + object_method_function_name_compare); + + if (method && method->valid_dims[object_type->sampler_dim] != '1') + method = NULL; } else if (object_type->class == HLSL_CLASS_UAV) { - count = ARRAY_SIZE(uav_methods); - methods = uav_methods; + method = bsearch(name, uav_methods, ARRAY_SIZE(uav_methods), sizeof(*method), + object_method_function_name_compare); + + if (method && method->valid_dims[object_type->sampler_dim] != '1') + method = NULL; + } + else if (object_type->class == HLSL_CLASS_STREAM_OUTPUT) + { + method = bsearch(name, so_methods, ARRAY_SIZE(so_methods), sizeof(*method), + object_method_function_name_compare); } else { @@ -6319,17 +6359,10 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct hlsl_block *block, stru return false; } - method = bsearch(name, methods, count, sizeof(*method), - object_method_function_name_compare); - - if (method && method->valid_dims[object_type->sampler_dim] == '1') - { + if (method) return method->handler(ctx, block, object, name, params, loc); - } else - { return raise_invalid_method_object_type(ctx, object_type, name, loc); - } } static bool add_object_property_access(struct hlsl_ctx *ctx, diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 792da9086..f8fbcfc81 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -5359,8 +5359,10 @@ static void compute_liveness_recurse(struct hlsl_block *block, unsigned int loop var = store->resource.var; var->last_read = max(var->last_read, last_read); deref_mark_last_read(&store->resource, last_read); - store->coords.node->last_read = last_read; - store->value.node->last_read = last_read; + if (store->coords.node) + store->coords.node->last_read = last_read; + if (store->value.node) + store->value.node->last_read = last_read; break; } case HLSL_IR_SWIZZLE: @@ -10632,6 +10634,12 @@ static bool sm4_generate_vsir_instr_resource_store(struct hlsl_ctx *ctx, struct vkd3d_shader_instruction *ins; unsigned int writemask; + if (store->store_type != HLSL_RESOURCE_STORE) + { + hlsl_fixme(ctx, &instr->loc, "Stream output operations."); + return false; + } + if (!store->resource.var->is_uniform) { hlsl_fixme(ctx, &store->node.loc, "Store to non-uniform resource variable.");