diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index f4d33de4e..3e26fc0dc 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -2112,9 +2112,9 @@ struct hlsl_ir_node *hlsl_block_add_resource_load(struct hlsl_ctx *ctx, struct h return append_new_instr(ctx, block, &load->node); } -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) +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, uint32_t writemask, const struct vkd3d_shader_location *loc) { struct hlsl_ir_resource_store *store; @@ -2122,6 +2122,7 @@ static struct hlsl_ir_node *hlsl_new_resource_store(struct hlsl_ctx *ctx, enum h return NULL; init_node(&store->node, HLSL_IR_RESOURCE_STORE, NULL, loc); store->store_type = type; + store->writemask = writemask; hlsl_copy_deref(ctx, &store->resource, resource); hlsl_src_from_node(&store->coords, coords); @@ -2131,9 +2132,9 @@ static struct hlsl_ir_node *hlsl_new_resource_store(struct hlsl_ctx *ctx, enum h 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 *value, uint32_t writemask, const struct vkd3d_shader_location *loc) { - append_new_instr(ctx, block, hlsl_new_resource_store(ctx, type, resource, coords, value, loc)); + append_new_instr(ctx, block, hlsl_new_resource_store(ctx, type, resource, coords, value, writemask, loc)); } struct hlsl_ir_node *hlsl_new_swizzle(struct hlsl_ctx *ctx, uint32_t s, unsigned int component_count, @@ -2674,6 +2675,7 @@ static struct hlsl_ir_node *clone_resource_store(struct hlsl_ctx *ctx, return NULL; init_node(&dst->node, HLSL_IR_RESOURCE_STORE, NULL, &src->node.loc); dst->store_type = src->store_type; + dst->writemask = src->writemask; if (!clone_deref(ctx, map, &dst->resource, &src->resource)) { vkd3d_free(dst); @@ -3824,7 +3826,8 @@ 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) +static void dump_ir_resource_store(struct hlsl_ctx *ctx, + struct vkd3d_string_buffer *buffer, const struct hlsl_ir_resource_store *store) { static const char *const type_names[] = { @@ -3836,6 +3839,8 @@ static void dump_ir_resource_store(struct vkd3d_string_buffer *buffer, const str 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); + if (store->writemask != VKD3DSP_WRITEMASK_ALL && type_is_single_reg(hlsl_deref_get_type(ctx, &store->resource))) + vkd3d_string_buffer_printf(buffer, "%s", debug_hlsl_writemask(store->writemask)); if (store->coords.node) { vkd3d_string_buffer_printf(buffer, ", coords = "); @@ -4048,7 +4053,7 @@ static void dump_instr(struct hlsl_ctx *ctx, struct vkd3d_string_buffer *buffer, break; case HLSL_IR_RESOURCE_STORE: - dump_ir_resource_store(buffer, hlsl_ir_resource_store(instr)); + dump_ir_resource_store(ctx, buffer, hlsl_ir_resource_store(instr)); break; case HLSL_IR_STRING_CONSTANT: diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 2a7523ac7..199329039 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -911,6 +911,7 @@ struct hlsl_ir_resource_store enum hlsl_resource_store_type store_type; struct hlsl_deref resource; struct hlsl_src coords, value; + uint8_t writemask; }; struct hlsl_ir_store @@ -1587,7 +1588,7 @@ struct hlsl_ir_node *hlsl_block_add_resource_load(struct hlsl_ctx *ctx, struct h 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, 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 *value, uint32_t writemask, 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 5d364d66d..2de7e81f6 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -2117,7 +2117,8 @@ 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, HLSL_RESOURCE_STORE, &resource_deref, coords, rhs, &lhs->loc); + hlsl_block_add_resource_store(ctx, block, HLSL_RESOURCE_STORE, + &resource_deref, coords, rhs, writemask, &lhs->loc); hlsl_cleanup_deref(&resource_deref); } else if (matrix_writemask) @@ -6300,6 +6301,7 @@ static bool add_store_method_call(struct hlsl_ctx *ctx, struct hlsl_block *block struct hlsl_ir_node *offset, *rhs; struct hlsl_deref resource_deref; unsigned int value_dim; + uint32_t writemask; if (params->args_count != 2) { @@ -6321,11 +6323,12 @@ static bool add_store_method_call(struct hlsl_ctx *ctx, struct hlsl_block *block hlsl_get_scalar_type(ctx, HLSL_TYPE_UINT), loc); rhs = add_implicit_conversion(ctx, block, params->args[1], hlsl_get_vector_type(ctx, HLSL_TYPE_UINT, value_dim), loc); + writemask = vkd3d_write_mask_from_component_count(value_dim); if (!hlsl_init_deref_from_index_chain(ctx, &resource_deref, object)) return false; - hlsl_block_add_resource_store(ctx, block, HLSL_RESOURCE_STORE, &resource_deref, offset, rhs, loc); + hlsl_block_add_resource_store(ctx, block, HLSL_RESOURCE_STORE, &resource_deref, offset, rhs, writemask, loc); hlsl_cleanup_deref(&resource_deref); return true; @@ -6350,7 +6353,7 @@ static bool add_so_append_method_call(struct hlsl_ctx *ctx, struct hlsl_block *b 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_block_add_resource_store(ctx, block, HLSL_RESOURCE_STREAM_APPEND, &so_deref, NULL, rhs, 0, loc); hlsl_cleanup_deref(&so_deref); return true; @@ -6371,7 +6374,7 @@ static bool add_so_restartstrip_method_call(struct hlsl_ctx *ctx, struct hlsl_bl if (!hlsl_init_deref_from_index_chain(ctx, &so_deref, object)) return false; - hlsl_block_add_resource_store(ctx, block, HLSL_RESOURCE_STREAM_RESTART, &so_deref, NULL, NULL, loc); + hlsl_block_add_resource_store(ctx, block, HLSL_RESOURCE_STREAM_RESTART, &so_deref, NULL, NULL, 0, loc); hlsl_cleanup_deref(&so_deref); return true; diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 19e2fc6e9..1fbf96cdf 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -1610,6 +1610,38 @@ static bool lower_tgsm_loads(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, s return true; } + +/* Lowers stores to TGSMs to resource stores. */ +static bool lower_tgsm_stores(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) +{ + struct hlsl_ir_store *store; + struct hlsl_ir_node *coords; + struct hlsl_deref res_deref; + struct hlsl_deref *deref; + + if (instr->type != HLSL_IR_STORE) + return false; + store = hlsl_ir_store(instr); + deref = &store->lhs; + + if (!deref->var->is_tgsm) + return false; + + if (deref->path_len) + { + hlsl_fixme(ctx, &instr->loc, "Store to indexed TGSM."); + return false; + } + + hlsl_init_simple_deref_from_var(&res_deref, deref->var); + coords = hlsl_block_add_uint_constant(ctx, block, 0, &instr->loc); + + hlsl_block_add_resource_store(ctx, block, HLSL_RESOURCE_STORE, &res_deref, + coords, store->rhs.node, store->writemask, &instr->loc); + + return true; +} + /* Allocate a unique, ordered index to each instruction, which will be used for * copy propagation and computing liveness ranges. * Index 0 means unused, so start at 1. */ @@ -3475,10 +3507,10 @@ static bool validate_dereferences(struct hlsl_ctx *ctx, struct hlsl_ir_node *ins { struct hlsl_ir_resource_store *store = hlsl_ir_resource_store(instr); - if (!store->resource.var->is_uniform) + if (!store->resource.var->is_uniform && !store->resource.var->is_tgsm) { hlsl_error(ctx, &instr->loc, VKD3D_SHADER_ERROR_HLSL_NON_STATIC_OBJECT_REF, - "Accessed resource must have a single uniform source."); + "Accessed resource must have a single uniform or groupshared source."); } else if (validate_component_index_range_from_deref(ctx, &store->resource) == DEREF_VALIDATION_NOT_CONSTANT) { @@ -11204,11 +11236,7 @@ static bool sm4_generate_vsir_instr_store(struct hlsl_ctx *ctx, struct vkd3d_shader_src_param *src_param; struct vkd3d_shader_instruction *ins; - if (store->lhs.var->is_tgsm) - { - hlsl_fixme(ctx, &instr->loc, "Store to groupshared variable."); - return false; - } + VKD3D_ASSERT(!store->lhs.var->is_tgsm); if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VSIR_OP_MOV, 1, 1))) return false; @@ -11289,8 +11317,8 @@ static bool sm4_generate_vsir_instr_resource_store(struct hlsl_ctx *ctx, struct hlsl_type *resource_type = hlsl_deref_get_type(ctx, &store->resource); struct hlsl_ir_node *coords = store->coords.node, *value = store->value.node; struct hlsl_ir_node *instr = &store->node; + bool tgsm = store->resource.var->is_tgsm; struct vkd3d_shader_instruction *ins; - unsigned int writemask; if (store->store_type != HLSL_RESOURCE_STORE) { @@ -11317,9 +11345,9 @@ static bool sm4_generate_vsir_instr_resource_store(struct hlsl_ctx *ctx, return true; } - if (!store->resource.var->is_uniform) + if (!store->resource.var->is_uniform && !tgsm) { - hlsl_fixme(ctx, &store->node.loc, "Store to non-uniform resource variable."); + hlsl_fixme(ctx, &store->node.loc, "Store to non-uniform non-groupshared resource variable."); return false; } @@ -11329,14 +11357,19 @@ static bool sm4_generate_vsir_instr_resource_store(struct hlsl_ctx *ctx, return false; } - if (resource_type->sampler_dim == HLSL_SAMPLER_DIM_RAW_BUFFER) + if (tgsm && !hlsl_is_numeric_type(resource_type)) + { + hlsl_fixme(ctx, &store->node.loc, "Store to structured TGSM."); + return false; + } + + if (tgsm || resource_type->sampler_dim == HLSL_SAMPLER_DIM_RAW_BUFFER) { if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VSIR_OP_STORE_RAW, 1, 2))) return false; - writemask = vkd3d_write_mask_from_component_count(value->data_type->e.numeric.dimx); - if (!sm4_generate_vsir_init_dst_param_from_deref(ctx, program, - &ins->dst[0], &store->resource, &instr->loc, writemask)) + if (!sm4_generate_vsir_init_dst_param_from_deref(ctx, program, &ins->dst[0], + &store->resource, &instr->loc, store->writemask)) return false; } else @@ -13955,6 +13988,7 @@ static void process_entry_function(struct hlsl_ctx *ctx, struct list *semantic_v lower_ir(ctx, lower_index_loads, body); lower_ir(ctx, lower_tgsm_loads, body); + lower_ir(ctx, lower_tgsm_stores, body); if (entry_func->return_var) { diff --git a/tests/hlsl/tgsm.shader_test b/tests/hlsl/tgsm.shader_test index cecbbafa7..e1f6284d6 100644 --- a/tests/hlsl/tgsm.shader_test +++ b/tests/hlsl/tgsm.shader_test @@ -280,7 +280,7 @@ size (raw_buffer, 8) 0xf000f 0xf000f 0xf000f 0xf000f 0xf000f 0xf000f 0xf000f 0xf000f -[compute shader todo] +[compute shader] RWByteAddressBuffer u : register(u0); groupshared min16uint m; @@ -305,7 +305,7 @@ void main(uint local_idx : SV_GroupIndex, uint group_id : SV_GroupID) } [test] -todo(sm<6 | msl) dispatch 2 1 1 +todo(glsl | msl) dispatch 2 1 1 probe uav 0 (0) u32(0x14321) probe uav 0 (1) u32(0x14321) probe uav 0 (2) u32(0x14321)