vkd3d-shader/hlsl: Support stores to raw groupshared variables.

This commit is contained in:
Shaun Ren
2025-07-17 13:57:08 -04:00
committed by Henri Verbeet
parent c8d2d40b91
commit 8d0d8d106b
Notes: Henri Verbeet 2025-08-05 16:40:26 +02:00
Approved-by: Elizabeth Figura (@zfigura)
Approved-by: Henri Verbeet (@hverbeet)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1605
5 changed files with 71 additions and 28 deletions

View File

@@ -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:

View File

@@ -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,

View File

@@ -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;

View File

@@ -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)
{

View File

@@ -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)