diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index 220ba773..0e3ce50c 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -799,6 +799,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 io_regs_declared[(VKD3DSPR_COUNT + 0x1f) / 0x20]; struct sm6_function *functions; @@ -2515,7 +2516,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; @@ -3689,12 +3690,35 @@ static enum vkd3d_shader_register_type register_type_from_dxil_semantic_kind( } 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 = false; + if (!is_patch_constant) + { + switch (shader_type) + { + case VKD3D_SHADER_TYPE_DOMAIN: + case VKD3D_SHADER_TYPE_GEOMETRY: + is_control_point = is_input; + break; + + case VKD3D_SHADER_TYPE_HULL: + is_control_point = true; + break; + + default: + break; + } + } + for (i = 0; i < s->element_count; ++i) { e = &s->elements[i]; @@ -3709,8 +3733,18 @@ static void sm6_parser_init_signature(struct sm6_parser *sm6, const struct shade 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 && vsir_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; } @@ -3718,12 +3752,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) @@ -7286,11 +7329,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"); @@ -8976,10 +9014,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; } @@ -9509,9 +9552,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; @@ -9674,7 +9718,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, @@ -9705,6 +9751,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) @@ -9754,7 +9801,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."); @@ -9771,9 +9819,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 eca18f4e..1f8d60c6 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -636,11 +636,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; @@ -648,6 +651,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; } @@ -3344,6 +3348,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 302d4f08..447f4ebb 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -1300,6 +1300,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); @@ -1310,6 +1312,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