From 8d8132b2c72afded16eeb897b2f162ed54af35cf Mon Sep 17 00:00:00 2001 From: Elizabeth Figura Date: Thu, 9 Oct 2025 14:52:30 -0500 Subject: [PATCH] vkd3d-shader/d3dbc: Create vsir descriptor information in the parser. --- libs/vkd3d-shader/d3dbc.c | 77 +++++++++++++++++++++++- libs/vkd3d-shader/ir.c | 32 ++++++++++ libs/vkd3d-shader/vkd3d_shader_main.c | 26 +++++--- libs/vkd3d-shader/vkd3d_shader_private.h | 5 ++ 4 files changed, 129 insertions(+), 11 deletions(-) diff --git a/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d-shader/d3dbc.c index 2379efd3a..dd8fb62d8 100644 --- a/libs/vkd3d-shader/d3dbc.c +++ b/libs/vkd3d-shader/d3dbc.c @@ -248,6 +248,8 @@ struct vkd3d_shader_sm1_parser struct vkd3d_shader_parser p; struct vsir_program *program; + uint16_t texture_descriptors; + struct { #define MAX_CONSTANT_COUNT 8192 @@ -938,6 +940,23 @@ static void shader_sm1_scan_register(struct vkd3d_shader_sm1_parser *sm1, add_signature_element_from_register(sm1, reg, false, mask, 0); } +static void d3dbc_add_combined_sampler_descriptor(struct vkd3d_shader_sm1_parser *d3dbc, + unsigned int sampler_idx, enum vkd3d_shader_resource_type resource_type) +{ + struct vkd3d_shader_register_range range = {.first = sampler_idx, .last = sampler_idx}; + struct vsir_program *program = d3dbc->program; + + if (!vsir_program_add_descriptor(program, VKD3D_SHADER_DESCRIPTOR_TYPE_SRV, + sampler_idx, &range, resource_type, VSIR_DATA_F32)) + vkd3d_shader_parser_error(&d3dbc->p, VKD3D_SHADER_ERROR_D3DBC_OUT_OF_MEMORY, + "Failed to create SRV descriptor for combined sampler %u.", sampler_idx); + + if (!vsir_program_add_descriptor(program, VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, + sampler_idx, &range, VKD3D_SHADER_RESOURCE_NONE, VSIR_DATA_UNUSED)) + vkd3d_shader_parser_error(&d3dbc->p, VKD3D_SHADER_ERROR_D3DBC_OUT_OF_MEMORY, + "Failed to create sampler descriptor for combined sampler %u.", sampler_idx); +} + /* Read a parameter token from the input stream, and possibly a relative * addressing token. */ static void shader_sm1_read_param(struct vkd3d_shader_sm1_parser *sm1, @@ -1102,6 +1121,11 @@ static void shader_sm1_read_semantic(struct vkd3d_shader_sm1_parser *sm1, range->first = range->last = semantic->resource.reg.reg.idx[0].offset; add_signature_element_from_semantic(sm1, semantic); + if (semantic->resource_type) + { + d3dbc_add_combined_sampler_descriptor(sm1, range->first, semantic->resource_type); + sm1->texture_descriptors |= (1u << range->first); + } } static void shader_sm1_read_immconst(struct vkd3d_shader_sm1_parser *sm1, const uint32_t **ptr, @@ -1196,6 +1220,38 @@ static void shader_sm1_read_comment(struct vkd3d_shader_sm1_parser *sm1) } } +static void d3dbc_update_descriptors(struct vkd3d_shader_sm1_parser *d3dbc, + const struct vkd3d_shader_instruction *ins) +{ + unsigned int sampler_idx; + + switch (ins->opcode) + { + case VSIR_OP_TEX: + case VSIR_OP_TEXBEM: + case VSIR_OP_TEXBEML: + case VSIR_OP_TEXDP3TEX: + case VSIR_OP_TEXLD: + case VSIR_OP_TEXM3x2TEX: + case VSIR_OP_TEXM3x3SPEC: + case VSIR_OP_TEXM3x3TEX: + case VSIR_OP_TEXM3x3VSPEC: + case VSIR_OP_TEXREG2AR: + case VSIR_OP_TEXREG2GB: + case VSIR_OP_TEXREG2RGB: + sampler_idx = ins->dst[0].reg.idx[0].offset; + if ((d3dbc->texture_descriptors & (1u << sampler_idx))) + break; + + d3dbc_add_combined_sampler_descriptor(d3dbc, sampler_idx, VKD3D_SHADER_RESOURCE_TEXTURE_2D); + d3dbc->texture_descriptors |= (1u << sampler_idx); + break; + + default: + break; + } +} + static void shader_sm1_validate_instruction(struct vkd3d_shader_sm1_parser *sm1, struct vkd3d_shader_instruction *ins) { if ((ins->opcode == VSIR_OP_BREAKP || ins->opcode == VSIR_OP_IF) && ins->flags) @@ -1360,6 +1416,9 @@ static void shader_sm1_read_instruction(struct vkd3d_shader_sm1_parser *sm1, str goto fail; } + if (program->shader_version.major == 1) + d3dbc_update_descriptors(sm1, ins); + shader_sm1_validate_instruction(sm1, ins); return; @@ -1478,6 +1537,7 @@ int d3dbc_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t c struct vkd3d_shader_message_context *message_context, struct vsir_program *program) { struct vkd3d_shader_sm1_parser sm1 = {0}; + struct vkd3d_shader_descriptor_info1 *d; struct vkd3d_shader_instruction *ins; unsigned int i; int ret; @@ -1507,7 +1567,22 @@ int d3dbc_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t c } for (i = 0; i < ARRAY_SIZE(program->flat_constant_count); ++i) - program->flat_constant_count[i] = get_external_constant_count(&sm1, i); + { + struct vkd3d_shader_register_range range = {.space = 0, .first = i, .last = i}; + unsigned int size = get_external_constant_count(&sm1, i); + + if ((program->flat_constant_count[i] = size)) + { + if (!(d = vsir_program_add_descriptor(program, VKD3D_SHADER_DESCRIPTOR_TYPE_CBV, + i, &range, VKD3D_SHADER_RESOURCE_BUFFER, VSIR_DATA_U32))) + vkd3d_shader_parser_error(&sm1.p, VKD3D_SHADER_ERROR_D3DBC_OUT_OF_MEMORY, + "Failed to create CBV descriptor."); + else + d->buffer_size = size * 16; + } + } + + program->has_descriptor_info = true; if (ret >= 0 && sm1.p.status < 0) ret = sm1.p.status; diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index 53516e520..a5e209ffa 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -747,6 +747,38 @@ bool vsir_signature_find_sysval(const struct shader_signature *signature, return false; } +struct vkd3d_shader_descriptor_info1 *vsir_program_add_descriptor(struct vsir_program *program, + enum vkd3d_shader_descriptor_type type, unsigned int register_id, + const struct vkd3d_shader_register_range *range, + enum vkd3d_shader_resource_type resource_type, enum vsir_data_type resource_data_type) +{ + struct vkd3d_shader_scan_descriptor_info1 *info = &program->descriptors; + struct vkd3d_shader_descriptor_info1 *d; + + if (!info) + return NULL; + + if (!vkd3d_array_reserve((void **)&info->descriptors, &program->descriptors_size, + info->descriptor_count + 1, sizeof(*info->descriptors))) + { + ERR("Failed to allocate descriptor info.\n"); + return NULL; + } + + d = &info->descriptors[info->descriptor_count]; + memset(d, 0, sizeof(*d)); + d->type = type; + d->register_id = register_id; + d->register_space = range->space; + d->register_index = range->first; + d->resource_type = resource_type; + d->resource_data_type = resource_data_type; + d->count = (range->last == ~0u) ? ~0u : range->last - range->first + 1; + ++info->descriptor_count; + + return d; +} + const char *debug_vsir_writemask(unsigned int writemask) { static const char components[] = {'x', 'y', 'z', 'w'}; diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c index 8237fc3af..f07841c3d 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -1729,6 +1729,9 @@ static int vsir_program_scan(struct vsir_program *program, const struct vkd3d_sh add_descriptor_info = true; } + if (program->has_descriptor_info) + add_descriptor_info = false; + tessellation_info = vkd3d_find_struct(compile_info->next, SCAN_HULL_SHADER_TESSELLATION_INFO); thread_group_size_info = vkd3d_find_struct(compile_info->next, SCAN_THREAD_GROUP_SIZE_INFO); @@ -1747,18 +1750,21 @@ static int vsir_program_scan(struct vsir_program *program, const struct vkd3d_sh break; } - for (i = 0; i < ARRAY_SIZE(program->flat_constant_count); ++i) + if (add_descriptor_info) { - struct vkd3d_shader_register_range range = {.space = 0, .first = i, .last = i}; - struct vkd3d_shader_register reg = {.idx[0].offset = i, .idx_count = 1}; - unsigned int size = program->flat_constant_count[i]; - struct vkd3d_shader_descriptor_info1 *d; - - if (size) + for (i = 0; i < ARRAY_SIZE(program->flat_constant_count); ++i) { - if ((d = vkd3d_shader_scan_add_descriptor(&context, VKD3D_SHADER_DESCRIPTOR_TYPE_CBV, - ®, &range, VKD3D_SHADER_RESOURCE_BUFFER, VSIR_DATA_U32))) - d->buffer_size = size * 16; + struct vkd3d_shader_register_range range = {.space = 0, .first = i, .last = i}; + struct vkd3d_shader_register reg = {.idx[0].offset = i, .idx_count = 1}; + unsigned int size = program->flat_constant_count[i]; + struct vkd3d_shader_descriptor_info1 *d; + + if (size) + { + if ((d = vkd3d_shader_scan_add_descriptor(&context, VKD3D_SHADER_DESCRIPTOR_TYPE_CBV, + ®, &range, VKD3D_SHADER_RESOURCE_BUFFER, VSIR_DATA_U32))) + d->buffer_size = size * 16; + } } } diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 77bb26f19..d54644429 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -1589,6 +1589,7 @@ struct vsir_program struct vkd3d_shader_scan_descriptor_info1 descriptors; bool has_descriptor_info; + size_t descriptors_size; unsigned int parameter_count; const struct vkd3d_shader_parameter1 *parameters; @@ -1635,6 +1636,10 @@ enum vkd3d_result vsir_allocate_temp_registers(struct vsir_program *program, enum vkd3d_result vsir_update_dcl_temps(struct vsir_program *program, struct vkd3d_shader_message_context *message_context); +struct vkd3d_shader_descriptor_info1 *vsir_program_add_descriptor(struct vsir_program *program, + enum vkd3d_shader_descriptor_type type, unsigned int register_id, + const struct vkd3d_shader_register_range *range, + enum vkd3d_shader_resource_type resource_type, enum vsir_data_type resource_data_type); bool vsir_program_add_icb(struct vsir_program *program, struct vkd3d_shader_immediate_constant_buffer *icb); void vsir_program_cleanup(struct vsir_program *program); const struct vkd3d_shader_parameter1 *vsir_program_get_parameter(