From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/dxil.c | 95 +++++++++++++++++++----- libs/vkd3d-shader/ir.c | 14 +++- libs/vkd3d-shader/vkd3d_shader_private.h | 10 +++ 3 files changed, 101 insertions(+), 18 deletions(-)
diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index f370f6f97..a5ee0570c 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -795,6 +795,7 @@ struct sm6_parser
struct vkd3d_shader_dst_param *output_params; struct vkd3d_shader_dst_param *input_params; + struct vkd3d_shader_dst_param *patch_constant_params; uint32_t input_regs_declared[(VKD3DSPR_COUNT + 0x1f) / 0x20];
struct sm6_function *functions; @@ -2492,7 +2493,7 @@ static size_t sm6_parser_compute_max_value_count(struct sm6_parser *sm6, * overestimate the value count somewhat, but this should be no problem. */ value_count = size_add_with_overflow_check(value_count, max(block->record_count, 1u) - 1); sm6->value_capacity = max(sm6->value_capacity, value_count); - sm6->functions[sm6->function_count].value_count = value_count; + sm6->functions[sm6->function_count++].value_count = value_count; /* The value count returns to its previous value after handling a function. */ if (value_count < SIZE_MAX) value_count = old_value_count; @@ -3496,12 +3497,19 @@ static void src_params_init_from_operands(struct vkd3d_shader_src_param *src_par }
static void sm6_parser_init_signature(struct sm6_parser *sm6, const struct shader_signature *s, - enum vkd3d_shader_register_type reg_type, struct vkd3d_shader_dst_param *params) + bool is_input, enum vkd3d_shader_register_type reg_type, struct vkd3d_shader_dst_param *params) { + enum vkd3d_shader_type shader_type = sm6->p.program.shader_version.type; + bool is_patch_constant, is_control_point; struct vkd3d_shader_dst_param *param; const struct signature_element *e; unsigned int i, count;
+ is_patch_constant = reg_type == VKD3DSPR_PATCHCONST; + is_control_point = !is_patch_constant && ((is_input && (shader_type == VKD3D_SHADER_TYPE_HULL + || shader_type == VKD3D_SHADER_TYPE_DOMAIN || shader_type == VKD3D_SHADER_TYPE_GEOMETRY)) + || (!is_input && !is_patch_constant && shader_type == VKD3D_SHADER_TYPE_HULL)); + for (i = 0; i < s->element_count; ++i) { e = &s->elements[i]; @@ -3509,8 +3517,15 @@ static void sm6_parser_init_signature(struct sm6_parser *sm6, const struct shade param = ¶ms[i]; dst_param_io_init(param, e, reg_type); count = 0; - if (e->register_count > 1) + if (is_control_point) + { + if (reg_type == VKD3DSPR_OUTPUT) + param->reg.idx[count].rel_addr = instruction_array_create_outpointid_param(&sm6->p.program.instructions); param->reg.idx[count++].offset = 0; + } + if (e->register_count > 1 || (is_patch_constant && sysval_semantic_is_tess_factor(e->sysval_semantic))) + param->reg.idx[count++].offset = 0; + assert(count < ARRAY_SIZE(param->reg.idx)); param->reg.idx[count++].offset = i; param->reg.idx_count = count; } @@ -3518,12 +3533,21 @@ static void sm6_parser_init_signature(struct sm6_parser *sm6, const struct shade
static void sm6_parser_init_output_signature(struct sm6_parser *sm6, const struct shader_signature *output_signature) { - sm6_parser_init_signature(sm6, output_signature, VKD3DSPR_OUTPUT, sm6->output_params); + sm6_parser_init_signature(sm6, output_signature, false, VKD3DSPR_OUTPUT, sm6->output_params); }
static void sm6_parser_init_input_signature(struct sm6_parser *sm6, const struct shader_signature *input_signature) { - sm6_parser_init_signature(sm6, input_signature, VKD3DSPR_INPUT, sm6->input_params); + sm6_parser_init_signature(sm6, input_signature, true, VKD3DSPR_INPUT, sm6->input_params); +} + +static void sm6_parser_init_patch_constant_signature(struct sm6_parser *sm6, + const struct shader_signature *patch_constant_signature) +{ + bool is_input = sm6->p.program.shader_version.type == VKD3D_SHADER_TYPE_DOMAIN; + + sm6_parser_init_signature(sm6, patch_constant_signature, is_input, VKD3DSPR_PATCHCONST, + sm6->patch_constant_params); }
static const struct sm6_value *sm6_parser_next_function_definition(struct sm6_parser *sm6) @@ -6908,11 +6932,6 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const struct sm6_block *code_block; struct sm6_value *dst;
- if (sm6->function_count) - { - FIXME("Multiple functions are not supported yet.\n"); - return VKD3D_ERROR_INVALID_SHADER; - } if (!(function->declaration = sm6_parser_next_function_definition(sm6))) { WARN("Failed to find definition to match function body.\n"); @@ -8576,10 +8595,15 @@ static enum vkd3d_result sm6_parser_signatures_init(struct sm6_parser *sm6, cons { return ret; } - /* TODO: patch constant signature in operand 2. */ + if (m->u.node->operand_count > 1 && (ret = sm6_parser_read_signature(sm6, m->u.node->operands[2], + &sm6->p.program.patch_constant_signature, tessellator_domain)) < 0) + { + return ret; + }
sm6_parser_init_input_signature(sm6, &sm6->p.program.input_signature); sm6_parser_init_output_signature(sm6, &sm6->p.program.output_signature); + sm6_parser_init_patch_constant_signature(sm6, &sm6->p.program.patch_constant_signature);
return VKD3D_OK; } @@ -9063,9 +9087,10 @@ static struct sm6_function *sm6_parser_get_function(const struct sm6_parser *sm6 static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const char *source_name, struct vkd3d_shader_message_context *message_context, struct dxbc_shader_desc *dxbc_desc) { + size_t count, length, function_count, expected_function_count, byte_code_size = dxbc_desc->byte_code_size; + const struct shader_signature *patch_constant_signature = &sm6->p.program.patch_constant_signature; const struct shader_signature *output_signature = &sm6->p.program.output_signature; const struct shader_signature *input_signature = &sm6->p.program.input_signature; - size_t count, length, function_count, byte_code_size = dxbc_desc->byte_code_size; const struct vkd3d_shader_location location = {.source_name = source_name}; uint32_t version_token, dxil_version, token_count, magic; const uint32_t *byte_code = dxbc_desc->byte_code; @@ -9228,7 +9253,9 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const char *sou }
if (!(sm6->output_params = vsir_program_get_dst_params(&sm6->p.program, output_signature->element_count)) - || !(sm6->input_params = vsir_program_get_dst_params(&sm6->p.program, input_signature->element_count))) + || !(sm6->input_params = vsir_program_get_dst_params(&sm6->p.program, input_signature->element_count)) + || !(sm6->patch_constant_params = vsir_program_get_dst_params(&sm6->p.program, + patch_constant_signature->element_count))) { ERR("Failed to allocate input/output parameters.\n"); vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, @@ -9259,6 +9286,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const char *sou "Out of memory allocating DXIL value array."); return VKD3D_ERROR_OUT_OF_MEMORY; } + sm6->function_count = 0; sm6->ssa_next_id = 1;
if ((ret = sm6_parser_globals_init(sm6)) < 0) @@ -9308,7 +9336,8 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const char *sou return ret; }
- if (!sm6_parser_require_space(sm6, output_signature->element_count + input_signature->element_count)) + if (!sm6_parser_require_space(sm6, output_signature->element_count + input_signature->element_count + + patch_constant_signature->element_count)) { vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, "Out of memory emitting shader signature declarations."); @@ -9325,9 +9354,41 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const char *sou return VKD3D_ERROR_INVALID_SHADER; }
- assert(sm6->function_count == 1); - if ((ret = sm6_function_emit_blocks(fn, sm6)) < 0) - return ret; + if (version.type == VKD3D_SHADER_TYPE_HULL) + { + sm6_parser_add_instruction(sm6, VKD3DSIH_HS_CONTROL_POINT_PHASE); + + if ((ret = sm6_function_emit_blocks(fn, sm6)) < 0) + return ret; + + if (!(fn = sm6_parser_get_function(sm6, sm6->patch_constant_function))) + { + WARN("Failed to find patch constant function '%s'.\n", sm6->patch_constant_function); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE, + "Failed to find the patch constant function '%s' for a hull shader.", + sm6->patch_constant_function); + return VKD3D_ERROR_INVALID_SHADER; + } + + sm6_parser_add_instruction(sm6, VKD3DSIH_HS_FORK_PHASE); + if ((ret = sm6_function_emit_blocks(fn, sm6)) < 0) + return ret; + + expected_function_count = 2; + } + else + { + if ((ret = sm6_function_emit_blocks(fn, sm6)) < 0) + return ret; + expected_function_count = 1; + } + + if (sm6->function_count > expected_function_count) + { + FIXME("%zu unhandled functions.\n", sm6->function_count - expected_function_count); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE, + "%zu functions were not emitted.", sm6->function_count - expected_function_count); + }
dxil_block_destroy(&sm6->root_block);
diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index 19e16c627..721146ede 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -569,11 +569,14 @@ static bool control_point_normaliser_is_in_control_point_phase(const struct cont return normaliser->phase == VKD3DSIH_HS_CONTROL_POINT_PHASE; }
-static struct vkd3d_shader_src_param *instruction_array_create_outpointid_param( +struct vkd3d_shader_src_param *instruction_array_create_outpointid_param( struct vkd3d_shader_instruction_array *instructions) { struct vkd3d_shader_src_param *rel_addr;
+ if (instructions->outpointid_param) + return instructions->outpointid_param; + if (!(rel_addr = shader_src_param_allocator_get(&instructions->src_params, 1))) return NULL;
@@ -581,6 +584,7 @@ static struct vkd3d_shader_src_param *instruction_array_create_outpointid_param( rel_addr->swizzle = 0; rel_addr->modifiers = 0;
+ instructions->outpointid_param = rel_addr; return rel_addr; }
@@ -3408,6 +3412,14 @@ static enum vkd3d_result vsir_cfg_init(struct vsir_cfg *cfg, struct vsir_program enum vkd3d_result ret; size_t i;
+ if (program->shader_version.type == VKD3D_SHADER_TYPE_HULL) + { + FIXME("Hull shaders are not supported.\n"); + vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED, + "The structurizer does not support hull shaders."); + return VKD3D_ERROR_INVALID_SHADER; + } + memset(cfg, 0, sizeof(*cfg)); cfg->message_context = message_context; cfg->program = program; diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index b9ac46b27..4a1aa76f0 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -1295,6 +1295,8 @@ struct vkd3d_shader_instruction_array struct vkd3d_shader_immediate_constant_buffer **icbs; size_t icb_capacity; size_t icb_count; + + struct vkd3d_shader_src_param *outpointid_param; };
bool shader_instruction_array_init(struct vkd3d_shader_instruction_array *instructions, unsigned int reserve); @@ -1305,6 +1307,8 @@ bool shader_instruction_array_add_icb(struct vkd3d_shader_instruction_array *ins struct vkd3d_shader_immediate_constant_buffer *icb); bool shader_instruction_array_clone_instruction(struct vkd3d_shader_instruction_array *instructions, unsigned int dst, unsigned int src); +struct vkd3d_shader_src_param *instruction_array_create_outpointid_param( + struct vkd3d_shader_instruction_array *instructions); void shader_instruction_array_destroy(struct vkd3d_shader_instruction_array *instructions);
enum vkd3d_shader_config_flags @@ -1628,6 +1632,12 @@ static inline bool component_type_is_64_bit(enum vkd3d_shader_component_type com return component_type == VKD3D_SHADER_COMPONENT_DOUBLE || component_type == VKD3D_SHADER_COMPONENT_UINT64; }
+static inline bool sysval_semantic_is_tess_factor(enum vkd3d_shader_sysval_semantic sysval_semantic) +{ + return sysval_semantic >= VKD3D_SHADER_SV_TESS_FACTOR_QUADEDGE + && sysval_semantic <= VKD3D_SHADER_SV_TESS_FACTOR_LINEDEN; +} + enum vkd3d_shader_input_sysval_semantic vkd3d_siv_from_sysval_indexed(enum vkd3d_shader_sysval_semantic sysval, unsigned int index);