From 1060207c8e59871433ade5578fd0a215ebebc6e3 Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Fri, 18 Oct 2024 07:31:22 +1100 Subject: [PATCH] Updated vkd3d to 03ad04c89004c7f800c5b1a0ea7ba28622916328. --- libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 21 +- libs/vkd3d/libs/vkd3d-shader/dxil.c | 3 +- libs/vkd3d/libs/vkd3d-shader/fx.c | 220 ++++++---- libs/vkd3d/libs/vkd3d-shader/glsl.c | 3 + libs/vkd3d/libs/vkd3d-shader/hlsl.y | 68 ++-- libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 4 +- libs/vkd3d/libs/vkd3d-shader/ir.c | 185 ++++++++- libs/vkd3d/libs/vkd3d-shader/msl.c | 3 + libs/vkd3d/libs/vkd3d-shader/spirv.c | 3 + libs/vkd3d/libs/vkd3d-shader/tpf.c | 3 +- .../libs/vkd3d-shader/vkd3d_shader_private.h | 6 +- libs/vkd3d/libs/vkd3d/command.c | 41 +- libs/vkd3d/libs/vkd3d/state.c | 376 +++++++++--------- 13 files changed, 607 insertions(+), 329 deletions(-) diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c index 8f7e5cb666b..ae8e864c179 100644 --- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c +++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c @@ -561,6 +561,21 @@ static struct signature_element *find_signature_element_by_register_index( return NULL; } +/* Add missing bits to a mask to make it contiguous. */ +static unsigned int make_mask_contiguous(unsigned int mask) +{ + static const unsigned int table[] = + { + 0x0, 0x1, 0x2, 0x3, + 0x4, 0x7, 0x6, 0x7, + 0x8, 0xf, 0xe, 0xf, + 0xc, 0xf, 0xe, 0xf, + }; + + VKD3D_ASSERT(mask < ARRAY_SIZE(table)); + return table[mask]; +} + static bool add_signature_element(struct vkd3d_shader_sm1_parser *sm1, bool output, const char *name, unsigned int index, enum vkd3d_shader_sysval_semantic sysval, unsigned int register_index, bool is_dcl, unsigned int mask) @@ -576,7 +591,7 @@ static bool add_signature_element(struct vkd3d_shader_sm1_parser *sm1, bool outp if ((element = find_signature_element(signature, name, index))) { - element->mask |= mask; + element->mask = make_mask_contiguous(element->mask | mask); if (!is_dcl) element->used_mask |= mask; return true; @@ -596,7 +611,7 @@ static bool add_signature_element(struct vkd3d_shader_sm1_parser *sm1, bool outp element->register_index = register_index; element->target_location = register_index; element->register_count = 1; - element->mask = mask; + element->mask = make_mask_contiguous(mask); element->used_mask = is_dcl ? 0 : mask; if (program->shader_version.type == VKD3D_SHADER_TYPE_PIXEL && !output) element->interpolation_mode = VKD3DSIM_LINEAR; @@ -1305,7 +1320,7 @@ static enum vkd3d_result shader_sm1_init(struct vkd3d_shader_sm1_parser *sm1, st /* Estimate instruction count to avoid reallocation in most shaders. */ if (!vsir_program_init(program, compile_info, &version, - code_size != ~(size_t)0 ? token_count / 4u + 4 : 16, VSIR_CF_STRUCTURED)) + code_size != ~(size_t)0 ? token_count / 4u + 4 : 16, VSIR_CF_STRUCTURED, false)) return VKD3D_ERROR_OUT_OF_MEMORY; vkd3d_shader_parser_init(&sm1->p, program, message_context, compile_info->source_name); diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c index 59494d2500d..f9f44f34bcf 100644 --- a/libs/vkd3d/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c @@ -10311,7 +10311,8 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, struct vsir_pro /* Estimate instruction count to avoid reallocation in most shaders. */ count = max(token_count, 400) - 400; - if (!vsir_program_init(program, compile_info, &version, (count + (count >> 2)) / 2u + 10, VSIR_CF_BLOCKS)) + if (!vsir_program_init(program, compile_info, &version, + (count + (count >> 2)) / 2u + 10, VSIR_CF_BLOCKS, true)) return VKD3D_ERROR_OUT_OF_MEMORY; vkd3d_shader_parser_init(&sm6->p, program, message_context, compile_info->source_name); sm6->ptr = &sm6->start[1]; diff --git a/libs/vkd3d/libs/vkd3d-shader/fx.c b/libs/vkd3d/libs/vkd3d-shader/fx.c index e98dfcf4f32..f3f7a2c765c 100644 --- a/libs/vkd3d/libs/vkd3d-shader/fx.c +++ b/libs/vkd3d/libs/vkd3d-shader/fx.c @@ -25,6 +25,17 @@ static inline size_t put_u32_unaligned(struct vkd3d_bytecode_buffer *buffer, uin return bytecode_put_bytes_unaligned(buffer, &value, sizeof(value)); } +struct fx_4_binary_type +{ + uint32_t name; + uint32_t class; + uint32_t element_count; + uint32_t unpacked_size; + uint32_t stride; + uint32_t packed_size; + uint32_t typeinfo; +}; + struct string_entry { struct rb_entry entry; @@ -2842,6 +2853,7 @@ struct fx_parser const uint8_t *ptr, *start, *end; struct vkd3d_shader_message_context *message_context; struct vkd3d_string_buffer buffer; + unsigned int indent; struct { const uint8_t *ptr; @@ -2949,6 +2961,131 @@ static const char *fx_4_get_string(struct fx_parser *parser, uint32_t offset) return (const char *)(parser->unstructured.ptr + offset); } +static void parse_fx_start_indent(struct fx_parser *parser) +{ + ++parser->indent; +} + +static void parse_fx_end_indent(struct fx_parser *parser) +{ + --parser->indent; +} + +static void parse_fx_print_indent(struct fx_parser *parser) +{ + vkd3d_string_buffer_printf(&parser->buffer, "%*s", 4 * parser->indent, ""); +} + +static void parse_fx_4_numeric_value(struct fx_parser *parser, uint32_t offset, + const struct fx_4_binary_type *type) +{ + unsigned int base_type, comp_count; + size_t i; + + base_type = (type->typeinfo >> FX_4_NUMERIC_BASE_TYPE_SHIFT) & 0xf; + + comp_count = type->packed_size / sizeof(uint32_t); + for (i = 0; i < comp_count; ++i) + { + union hlsl_constant_value_component value; + + fx_parser_read_unstructured(parser, &value, offset, sizeof(uint32_t)); + + if (base_type == FX_4_NUMERIC_TYPE_FLOAT) + vkd3d_string_buffer_printf(&parser->buffer, "%f", value.f); + else if (base_type == FX_4_NUMERIC_TYPE_INT) + vkd3d_string_buffer_printf(&parser->buffer, "%d", value.i); + else if (base_type == FX_4_NUMERIC_TYPE_UINT) + vkd3d_string_buffer_printf(&parser->buffer, "%u", value.u); + else if (base_type == FX_4_NUMERIC_TYPE_BOOL) + vkd3d_string_buffer_printf(&parser->buffer, "%s", value.u ? "true" : "false" ); + else + vkd3d_string_buffer_printf(&parser->buffer, "%#x", value.u); + + if (i < comp_count - 1) + vkd3d_string_buffer_printf(&parser->buffer, ", "); + + offset += sizeof(uint32_t); + } +} + +static void fx_4_parse_string_initializer(struct fx_parser *parser, uint32_t offset) +{ + const char *str = fx_4_get_string(parser, offset); + vkd3d_string_buffer_printf(&parser->buffer, "\"%s\"", str); +} + +static void fx_parse_fx_4_annotations(struct fx_parser *parser) +{ + struct fx_4_annotation + { + uint32_t name; + uint32_t type; + } var; + struct fx_4_binary_type type; + const char *name, *type_name; + uint32_t count, i, value; + + count = fx_parser_read_u32(parser); + + if (!count) + return; + + vkd3d_string_buffer_printf(&parser->buffer, "\n"); + parse_fx_print_indent(parser); + vkd3d_string_buffer_printf(&parser->buffer, "<\n"); + parse_fx_start_indent(parser); + + for (i = 0; i < count; ++i) + { + fx_parser_read_u32s(parser, &var, sizeof(var)); + fx_parser_read_unstructured(parser, &type, var.type, sizeof(type)); + + name = fx_4_get_string(parser, var.name); + type_name = fx_4_get_string(parser, type.name); + + parse_fx_print_indent(parser); + vkd3d_string_buffer_printf(&parser->buffer, "%s %s", type_name, name); + if (type.element_count) + vkd3d_string_buffer_printf(&parser->buffer, "[%u]", type.element_count); + vkd3d_string_buffer_printf(&parser->buffer, " = "); + if (type.element_count) + vkd3d_string_buffer_printf(&parser->buffer, "{ "); + + if (type.class == FX_4_TYPE_CLASS_NUMERIC) + { + value = fx_parser_read_u32(parser); + parse_fx_4_numeric_value(parser, value, &type); + } + else if (type.class == FX_4_TYPE_CLASS_OBJECT && type.typeinfo == FX_4_OBJECT_TYPE_STRING) + { + uint32_t element_count = max(type.element_count, 1); + + for (uint32_t j = 0; j < element_count; ++j) + { + value = fx_parser_read_u32(parser); + fx_4_parse_string_initializer(parser, value); + if (j < element_count - 1) + vkd3d_string_buffer_printf(&parser->buffer, ", "); + } + } + else + { + fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_INVALID_DATA, + "Only numeric and string types are supported in annotations.\n"); + } + + if (type.element_count) + vkd3d_string_buffer_printf(&parser->buffer, " }"); + vkd3d_string_buffer_printf(&parser->buffer, ";\n"); + } + parse_fx_end_indent(parser); + + parse_fx_print_indent(parser); + vkd3d_string_buffer_printf(&parser->buffer, ">"); +} + + static void fx_parse_fx_4_numeric_variables(struct fx_parser *parser, uint32_t count) { struct fx_4_numeric_variable @@ -2960,17 +3097,8 @@ static void fx_parse_fx_4_numeric_variables(struct fx_parser *parser, uint32_t c uint32_t value; uint32_t flags; } var; - struct fx_4_type - { - uint32_t name; - uint32_t class; - uint32_t element_count; - uint32_t unpacked_size; - uint32_t stride; - uint32_t packed_size; - uint32_t typeinfo; - } type; const char *name, *semantic, *type_name; + struct fx_4_binary_type type; uint32_t i; for (i = 0; i < count; ++i) @@ -2984,54 +3112,21 @@ static void fx_parse_fx_4_numeric_variables(struct fx_parser *parser, uint32_t c vkd3d_string_buffer_printf(&parser->buffer, " %s %s", type_name, name); if (type.element_count) vkd3d_string_buffer_printf(&parser->buffer, "[%u]", type.element_count); + if (var.semantic) { semantic = fx_4_get_string(parser, var.semantic); vkd3d_string_buffer_printf(&parser->buffer, " : %s", semantic); } + fx_parse_fx_4_annotations(parser); + if (var.value) { - unsigned int base_type, comp_count; - size_t j; - - if (type.class == FX_4_TYPE_CLASS_NUMERIC) - base_type = (type.typeinfo >> FX_4_NUMERIC_BASE_TYPE_SHIFT) & 0xf; - else - base_type = 0; - vkd3d_string_buffer_printf(&parser->buffer, " = { "); - - comp_count = type.unpacked_size / sizeof(uint32_t); - for (j = 0; j < comp_count; ++j) - { - union hlsl_constant_value_component value; - - fx_parser_read_unstructured(parser, &value, var.value + j * sizeof(uint32_t), sizeof(uint32_t)); - - if (base_type == FX_4_NUMERIC_TYPE_FLOAT) - vkd3d_string_buffer_printf(&parser->buffer, "%f", value.f); - else if (base_type == FX_4_NUMERIC_TYPE_INT) - vkd3d_string_buffer_printf(&parser->buffer, "%d", value.i); - else if (base_type == FX_4_NUMERIC_TYPE_UINT) - vkd3d_string_buffer_printf(&parser->buffer, "%u", value.u); - else if (base_type == FX_4_NUMERIC_TYPE_BOOL) - vkd3d_string_buffer_printf(&parser->buffer, "%s", value.u ? "true" : "false" ); - else - vkd3d_string_buffer_printf(&parser->buffer, "%#x", value.u); - - if (j < comp_count - 1) - vkd3d_string_buffer_printf(&parser->buffer, ", "); - } - + parse_fx_4_numeric_value(parser, var.value, &type); vkd3d_string_buffer_printf(&parser->buffer, " }"); } vkd3d_string_buffer_printf(&parser->buffer, "; // Offset: %u, size %u.\n", var.offset, type.unpacked_size); - - if (fx_parser_read_u32(parser)) - { - fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_NOT_IMPLEMENTED, "Parsing annotations is not implemented.\n"); - return; - } } } @@ -3057,27 +3152,17 @@ static void fx_parse_buffers(struct fx_parser *parser) name = fx_4_get_string(parser, buffer.name); - vkd3d_string_buffer_printf(&parser->buffer, "cbuffer %s\n", name); - vkd3d_string_buffer_printf(&parser->buffer, "{\n"); - - if (fx_parser_read_u32(parser)) - { - fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_NOT_IMPLEMENTED, "Parsing annotations is not implemented.\n"); - return; - } + vkd3d_string_buffer_printf(&parser->buffer, "cbuffer %s", name); + fx_parse_fx_4_annotations(parser); + vkd3d_string_buffer_printf(&parser->buffer, "\n{\n"); + parse_fx_start_indent(parser); fx_parse_fx_4_numeric_variables(parser, buffer.count); - + parse_fx_end_indent(parser); vkd3d_string_buffer_printf(&parser->buffer, "}\n\n"); } } -static void fx_4_parse_string_initializer(struct fx_parser *parser, uint32_t offset) -{ - const char *str = fx_4_get_string(parser, offset); - vkd3d_string_buffer_printf(&parser->buffer, "\"%s\"", str); -} - static void fx_4_parse_objects(struct fx_parser *parser) { struct fx_4_object_variable @@ -3087,17 +3172,8 @@ static void fx_4_parse_objects(struct fx_parser *parser) uint32_t semantic; uint32_t bind_point; } var; - struct fx_4_type - { - uint32_t name; - uint32_t class; - uint32_t element_count; - uint32_t unpacked_size; - uint32_t stride; - uint32_t packed_size; - uint32_t typeinfo; - } type; uint32_t i, j, value, element_count; + struct fx_4_binary_type type; const char *name, *type_name; if (parser->failed) diff --git a/libs/vkd3d/libs/vkd3d-shader/glsl.c b/libs/vkd3d/libs/vkd3d-shader/glsl.c index 1e17de54ede..46515818d07 100644 --- a/libs/vkd3d/libs/vkd3d-shader/glsl.c +++ b/libs/vkd3d/libs/vkd3d-shader/glsl.c @@ -2213,6 +2213,9 @@ int glsl_compile(struct vsir_program *program, uint64_t config_flags, if ((ret = vsir_program_transform(program, config_flags, compile_info, message_context)) < 0) return ret; + VKD3D_ASSERT(program->normalised_io); + VKD3D_ASSERT(program->normalised_hull_cp_io); + vkd3d_glsl_generator_init(&generator, program, compile_info, descriptor_info, combined_sampler_info, message_context); ret = vkd3d_glsl_generator_generate(&generator, out); diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y index ee13e193d49..213cec79c3d 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y @@ -40,6 +40,7 @@ struct parse_initializer unsigned int args_count; struct hlsl_block *instrs; bool braces; + struct vkd3d_shader_location loc; }; struct parse_parameter @@ -2506,6 +2507,32 @@ static void initialize_var_components(struct hlsl_ctx *ctx, struct hlsl_block *i } } +static void initialize_var(struct hlsl_ctx *ctx, struct hlsl_ir_var *dst, + const struct parse_initializer *initializer, bool is_default_values_initializer) +{ + unsigned int store_index = 0; + + /* If any of the elements has an error type, then initializer_size() is not + * meaningful. */ + for (unsigned int i = 0; i < initializer->args_count; ++i) + { + if (initializer->args[i]->data_type->class == HLSL_CLASS_ERROR) + return; + } + + if (initializer_size(initializer) != hlsl_type_component_count(dst->data_type)) + { + hlsl_error(ctx, &initializer->loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT, + "Expected %u components in initializer, but got %u.", + hlsl_type_component_count(dst->data_type), initializer_size(initializer)); + return; + } + + for (unsigned int i = 0; i < initializer->args_count; ++i) + initialize_var_components(ctx, initializer->instrs, dst, &store_index, + initializer->args[i], is_default_values_initializer); +} + static bool type_has_object_components(const struct hlsl_type *type) { if (type->class == HLSL_CLASS_ARRAY) @@ -2832,8 +2859,6 @@ static struct hlsl_block *initialize_vars(struct hlsl_ctx *ctx, struct list *var if (v->initializer.args_count) { bool is_default_values_initializer; - unsigned int store_index = 0; - unsigned int size, k; is_default_values_initializer = (ctx->cur_buffer != ctx->globals_buffer) || (var->storage_modifiers & HLSL_STORAGE_UNIFORM) @@ -2871,20 +2896,7 @@ static struct hlsl_block *initialize_vars(struct hlsl_ctx *ctx, struct list *var v->initializer.args[0] = node_from_block(v->initializer.instrs); } - size = initializer_size(&v->initializer); - if (component_count != size) - { - hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT, - "Expected %u components in initializer, but got %u.", component_count, size); - free_parse_variable_def(v); - continue; - } - - for (k = 0; k < v->initializer.args_count; ++k) - { - initialize_var_components(ctx, v->initializer.instrs, var, - &store_index, v->initializer.args[k], is_default_values_initializer); - } + initialize_var(ctx, var, &v->initializer, is_default_values_initializer); if (is_default_values_initializer) { @@ -5402,13 +5414,11 @@ static struct hlsl_block *add_constructor(struct hlsl_ctx *ctx, struct hlsl_type { struct hlsl_ir_load *load; struct hlsl_ir_var *var; - unsigned int i, idx = 0; if (!(var = hlsl_new_synthetic_var(ctx, "constructor", type, loc))) return NULL; - for (i = 0; i < params->args_count; ++i) - initialize_var_components(ctx, params->instrs, var, &idx, params->args[i], false); + initialize_var(ctx, var, params, false); if (!(load = hlsl_new_var_load(ctx, var, loc))) return NULL; @@ -5425,6 +5435,14 @@ static bool add_ternary(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_type *cond_type = cond->data_type; struct hlsl_type *common_type; + if (cond->data_type->class == HLSL_CLASS_ERROR + || first->data_type->class == HLSL_CLASS_ERROR + || second->data_type->class == HLSL_CLASS_ERROR) + { + block->value = ctx->error_instr; + return true; + } + if (cond_type->class > HLSL_CLASS_LAST_NUMERIC) { struct vkd3d_string_buffer *string; @@ -8321,6 +8339,7 @@ complex_initializer: $$.args[0] = node_from_block($1); $$.instrs = $1; $$.braces = false; + $$.loc = @$; } | '{' complex_initializer_list '}' { @@ -8352,6 +8371,7 @@ complex_initializer_list: $$.args[$$.args_count++] = $3.args[i]; hlsl_block_add_block($$.instrs, $3.instrs); free_parse_initializer(&$3); + $$.loc = @$; } initializer_expr: @@ -8369,6 +8389,7 @@ initializer_expr_list: $$.args[0] = node_from_block($1); $$.instrs = $1; $$.braces = false; + $$.loc = @$; } | initializer_expr_list ',' initializer_expr { @@ -8687,6 +8708,7 @@ func_arguments: if (!($$.instrs = make_empty_block(ctx))) YYABORT; $$.braces = false; + $$.loc = @$; } | initializer_expr_list @@ -8950,14 +8972,6 @@ postfix_expr: free_parse_initializer(&$4); YYABORT; } - if ($2->dimx * $2->dimy != initializer_size(&$4)) - { - hlsl_error(ctx, &@4, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT, - "Expected %u components in constructor, but got %u.", - $2->dimx * $2->dimy, initializer_size(&$4)); - free_parse_initializer(&$4); - YYABORT; - } if (!($$ = add_constructor(ctx, $2, &$4, &@2))) { diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c index 4cf9d5eb84a..88bec8610cb 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c @@ -7366,7 +7366,7 @@ static void sm1_generate_vsir(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl version.major = ctx->profile->major_version; version.minor = ctx->profile->minor_version; version.type = ctx->profile->type; - if (!vsir_program_init(program, NULL, &version, 0, VSIR_CF_STRUCTURED)) + if (!vsir_program_init(program, NULL, &version, 0, VSIR_CF_STRUCTURED, false)) { ctx->result = VKD3D_ERROR_OUT_OF_MEMORY; return; @@ -7404,7 +7404,7 @@ static void sm4_generate_vsir(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl version.minor = ctx->profile->minor_version; version.type = ctx->profile->type; - if (!vsir_program_init(program, NULL, &version, 0, VSIR_CF_STRUCTURED)) + if (!vsir_program_init(program, NULL, &version, 0, VSIR_CF_STRUCTURED, false)) { ctx->result = VKD3D_ERROR_OUT_OF_MEMORY; return; diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c index c475bf92279..b47f12d2188 100644 --- a/libs/vkd3d/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d/libs/vkd3d-shader/ir.c @@ -74,7 +74,8 @@ static int convert_parameter_info(const struct vkd3d_shader_compile_info *compil } bool vsir_program_init(struct vsir_program *program, const struct vkd3d_shader_compile_info *compile_info, - const struct vkd3d_shader_version *version, unsigned int reserve, enum vsir_control_flow_type cf_type) + const struct vkd3d_shader_version *version, unsigned int reserve, enum vsir_control_flow_type cf_type, + bool normalised_io) { memset(program, 0, sizeof(*program)); @@ -97,6 +98,8 @@ bool vsir_program_init(struct vsir_program *program, const struct vkd3d_shader_c program->shader_version = *version; program->cf_type = cf_type; + program->normalised_io = normalised_io; + program->normalised_hull_cp_io = normalised_io; return shader_instruction_array_init(&program->instructions, reserve); } @@ -1132,6 +1135,14 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i enum vkd3d_result ret; unsigned int i, j; + VKD3D_ASSERT(!program->normalised_hull_cp_io); + + if (program->shader_version.type != VKD3D_SHADER_TYPE_HULL) + { + program->normalised_hull_cp_io = true; + return VKD3D_OK; + } + if (!(normaliser.outpointid_param = vsir_program_create_outpointid_param(program))) { ERR("Failed to allocate src param.\n"); @@ -1175,6 +1186,7 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i break; case VKD3DSIH_HS_CONTROL_POINT_PHASE: program->instructions = normaliser.instructions; + program->normalised_hull_cp_io = true; return VKD3D_OK; case VKD3DSIH_HS_FORK_PHASE: case VKD3DSIH_HS_JOIN_PHASE: @@ -1183,6 +1195,7 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i ret = control_point_normaliser_emit_hs_input(&normaliser, &program->input_signature, input_control_point_count, i, &location); program->instructions = normaliser.instructions; + program->normalised_hull_cp_io = true; return ret; default: break; @@ -1190,6 +1203,7 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i } program->instructions = normaliser.instructions; + program->normalised_hull_cp_io = true; return VKD3D_OK; } @@ -1903,6 +1917,8 @@ static enum vkd3d_result vsir_program_normalise_io_registers(struct vsir_program struct vkd3d_shader_instruction *ins; unsigned int i; + VKD3D_ASSERT(!program->normalised_io); + normaliser.phase = VKD3DSIH_INVALID; normaliser.shader_type = program->shader_version.type; normaliser.major = program->shader_version.major; @@ -1959,6 +1975,7 @@ static enum vkd3d_result vsir_program_normalise_io_registers(struct vsir_program program->instructions = normaliser.instructions; program->use_vocp = normaliser.use_vocp; + program->normalised_io = true; return VKD3D_OK; } @@ -6189,6 +6206,143 @@ static void vsir_validate_register_without_indices(struct validation_context *ct reg->idx_count, reg->type); } +static void vsir_validate_io_register(struct validation_context *ctx, + const struct vkd3d_shader_register *reg) +{ + const struct shader_signature *signature; + bool has_control_point = false; + + switch (reg->type) + { + case VKD3DSPR_INPUT: + signature = &ctx->program->input_signature; + + switch (ctx->program->shader_version.type) + { + case VKD3D_SHADER_TYPE_GEOMETRY: + case VKD3D_SHADER_TYPE_HULL: + case VKD3D_SHADER_TYPE_DOMAIN: + has_control_point = true; + break; + + default: + break; + } + break; + + case VKD3DSPR_OUTPUT: + switch (ctx->program->shader_version.type) + { + case VKD3D_SHADER_TYPE_HULL: + if (ctx->phase == VKD3DSIH_HS_CONTROL_POINT_PHASE) + { + signature = &ctx->program->output_signature; + has_control_point = ctx->program->normalised_hull_cp_io; + } + else if (ctx->program->normalised_io) + { + signature = &ctx->program->output_signature; + has_control_point = true; + } + else + { + signature = &ctx->program->patch_constant_signature; + } + break; + + default: + signature = &ctx->program->output_signature; + break; + } + break; + + case VKD3DSPR_INCONTROLPOINT: + signature = &ctx->program->input_signature; + has_control_point = true; + break; + + case VKD3DSPR_OUTCONTROLPOINT: + signature = &ctx->program->output_signature; + has_control_point = true; + break; + + case VKD3DSPR_PATCHCONST: + signature = &ctx->program->patch_constant_signature; + break; + + default: + vkd3d_unreachable(); + } + + if (!ctx->program->normalised_io) + { + /* Indices are [register] or [control point, register]. Both are + * allowed to have a relative address. */ + unsigned int expected_idx_count = 1 + !!has_control_point; + + if (reg->idx_count != expected_idx_count) + { + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, + "Invalid index count %u for a register of type %#x.", + reg->idx_count, reg->type); + return; + } + } + else + { + struct signature_element *element; + unsigned int expected_idx_count; + unsigned int signature_idx; + bool is_array = false; + + /* If the signature element is not an array, indices are + * [signature] or [control point, signature]. If the signature + * element is an array, indices are [array, signature] or + * [control point, array, signature]. In any case `signature' is + * not allowed to have a relative address, while the others are. + */ + if (reg->idx_count < 1) + { + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, + "Invalid index count %u for a register of type %#x.", + reg->idx_count, reg->type); + return; + } + + if (reg->idx[reg->idx_count - 1].rel_addr) + { + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, + "Non-NULL relative address for the signature index of a register of type %#x.", + reg->type); + return; + } + + signature_idx = reg->idx[reg->idx_count - 1].offset; + + if (signature_idx >= signature->element_count) + { + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, + "Signature index %u exceeds the signature size %u in a register of type %#x.", + signature_idx, signature->element_count, reg->type); + return; + } + + element = &signature->elements[signature_idx]; + if (element->register_count > 1 || vsir_sysval_semantic_is_tess_factor(element->sysval_semantic)) + is_array = true; + + expected_idx_count = 1 + !!has_control_point + !!is_array; + + if (reg->idx_count != expected_idx_count) + { + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, + "Invalid index count %u for a register of type %#x.", + reg->idx_count, reg->type); + return; + } + } +} + static void vsir_validate_temp_register(struct validation_context *ctx, const struct vkd3d_shader_register *reg) { @@ -6502,10 +6656,18 @@ static void vsir_validate_register(struct validation_context *ctx, vsir_validate_temp_register(ctx, reg); break; + case VKD3DSPR_INPUT: + vsir_validate_io_register(ctx, reg); + break; + case VKD3DSPR_RASTOUT: vsir_validate_rastout_register(ctx, reg); break; + case VKD3DSPR_OUTPUT: + vsir_validate_io_register(ctx, reg); + break; + case VKD3DSPR_DEPTHOUT: vsir_validate_register_without_indices(ctx, reg); break; @@ -6542,6 +6704,18 @@ static void vsir_validate_register(struct validation_context *ctx, vsir_validate_uav_register(ctx, reg); break; + case VKD3DSPR_INCONTROLPOINT: + vsir_validate_io_register(ctx, reg); + break; + + case VKD3DSPR_OUTCONTROLPOINT: + vsir_validate_io_register(ctx, reg); + break; + + case VKD3DSPR_PATCHCONST: + vsir_validate_io_register(ctx, reg); + break; + case VKD3DSPR_DEPTHOUTGE: vsir_validate_register_without_indices(ctx, reg); break; @@ -6810,6 +6984,11 @@ static void vsir_validate_signature_element(struct validation_context *ctx, validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, "element %u of %s signature: Invalid mask %#x.", idx, signature_type_name, element->mask); + if (!vkd3d_bitmask_is_contiguous(element->mask)) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, + "element %u of %s signature: Non-contiguous mask %#x.", + idx, signature_type_name, element->mask); + /* Here we'd likely want to validate that the usage mask is a subset of the * signature mask. Unfortunately the D3DBC parser sometimes violates this. * For example I've seen a shader like this: @@ -7649,11 +7828,9 @@ enum vkd3d_result vsir_program_transform(struct vsir_program *program, uint64_t vsir_transform(&ctx, vsir_program_remap_output_signature); if (program->shader_version.type == VKD3D_SHADER_TYPE_HULL) - { vsir_transform(&ctx, vsir_program_flatten_hull_shader_phases); - vsir_transform(&ctx, instruction_array_normalise_hull_shader_control_point_io); - } + vsir_transform(&ctx, instruction_array_normalise_hull_shader_control_point_io); vsir_transform(&ctx, vsir_program_normalise_io_registers); vsir_transform(&ctx, vsir_program_normalise_flat_constants); vsir_transform(&ctx, vsir_program_remove_dead_code); diff --git a/libs/vkd3d/libs/vkd3d-shader/msl.c b/libs/vkd3d/libs/vkd3d-shader/msl.c index 36750de1fd8..5baefbc1f44 100644 --- a/libs/vkd3d/libs/vkd3d-shader/msl.c +++ b/libs/vkd3d/libs/vkd3d-shader/msl.c @@ -869,6 +869,9 @@ int msl_compile(struct vsir_program *program, uint64_t config_flags, if ((ret = vsir_program_transform(program, config_flags, compile_info, message_context)) < 0) return ret; + VKD3D_ASSERT(program->normalised_io); + VKD3D_ASSERT(program->normalised_hull_cp_io); + if ((ret = msl_generator_init(&generator, program, compile_info, descriptor_info, message_context)) < 0) return ret; msl_generator_generate(&generator); diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c index 1efd717e970..6a28e2cd68e 100644 --- a/libs/vkd3d/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c @@ -10650,6 +10650,9 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, struct compile_info, compiler->message_context)) < 0) return result; + VKD3D_ASSERT(program->normalised_io); + VKD3D_ASSERT(program->normalised_hull_cp_io); + max_element_count = max(program->output_signature.element_count, program->patch_constant_signature.element_count); if (!(compiler->output_info = vkd3d_calloc(max_element_count, sizeof(*compiler->output_info)))) return VKD3D_ERROR_OUT_OF_MEMORY; diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c index 54344f2afc0..848e78a34d3 100644 --- a/libs/vkd3d/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c @@ -2792,7 +2792,8 @@ static bool shader_sm4_init(struct vkd3d_shader_sm4_parser *sm4, struct vsir_pro version.minor = VKD3D_SM4_VERSION_MINOR(version_token); /* Estimate instruction count to avoid reallocation in most shaders. */ - if (!vsir_program_init(program, compile_info, &version, token_count / 7u + 20, VSIR_CF_STRUCTURED)) + if (!vsir_program_init(program, compile_info, + &version, token_count / 7u + 20, VSIR_CF_STRUCTURED, false)) return false; vkd3d_shader_parser_init(&sm4->p, program, message_context, compile_info->source_name); sm4->ptr = sm4->start; diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h index d63bfd96121..9df538a0da0 100644 --- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h @@ -255,6 +255,7 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_FX_NOT_IMPLEMENTED = 11000, VKD3D_SHADER_ERROR_FX_INVALID_VERSION = 11001, + VKD3D_SHADER_ERROR_FX_INVALID_DATA = 11002, }; enum vkd3d_shader_opcode @@ -1414,6 +1415,8 @@ struct vsir_program bool use_vocp; bool has_point_size; enum vsir_control_flow_type cf_type; + bool normalised_io; + bool normalised_hull_cp_io; const char **block_names; size_t block_name_count; @@ -1426,7 +1429,8 @@ int vsir_program_compile(struct vsir_program *program, uint64_t config_flags, const struct vkd3d_shader_parameter1 *vsir_program_get_parameter( const struct vsir_program *program, enum vkd3d_shader_parameter_name name); bool vsir_program_init(struct vsir_program *program, const struct vkd3d_shader_compile_info *compile_info, - const struct vkd3d_shader_version *version, unsigned int reserve, enum vsir_control_flow_type cf_type); + const struct vkd3d_shader_version *version, unsigned int reserve, enum vsir_control_flow_type cf_type, + bool normalised_io); enum vkd3d_result vsir_program_transform(struct vsir_program *program, uint64_t config_flags, const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_message_context *message_context); enum vkd3d_result vsir_program_validate(struct vsir_program *program, uint64_t config_flags, diff --git a/libs/vkd3d/libs/vkd3d/command.c b/libs/vkd3d/libs/vkd3d/command.c index eab0436bebd..5495809fcb9 100644 --- a/libs/vkd3d/libs/vkd3d/command.c +++ b/libs/vkd3d/libs/vkd3d/command.c @@ -2795,39 +2795,30 @@ static bool vk_write_descriptor_set_from_d3d12_desc(VkWriteDescriptorSet *vk_des /* We use separate bindings for buffer and texture SRVs/UAVs. * See d3d12_root_signature_init(). For unbounded ranges the * descriptors exist in two consecutive sets, otherwise they occur - * in pairs in one set. */ - if (range->descriptor_count == UINT_MAX) - { - if (vk_descriptor_type != VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER - && vk_descriptor_type != VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER) - { - vk_descriptor_write->dstSet = vk_descriptor_sets[set + 1]; - vk_descriptor_write->dstBinding = 0; - } - } - else - { - if (!use_array) - vk_descriptor_write->dstBinding = vk_binding + 2 * index; - if (vk_descriptor_type != VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER - && vk_descriptor_type != VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER) - ++vk_descriptor_write->dstBinding; - } - + * as consecutive ranges within a set. */ if (vk_descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER || vk_descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER) { vk_descriptor_write->pTexelBufferView = &u.view->v.u.vk_buffer_view; + break; + } + + if (range->descriptor_count == UINT_MAX) + { + vk_descriptor_write->dstSet = vk_descriptor_sets[set + 1]; + vk_descriptor_write->dstBinding = 0; } else { - vk_image_info->sampler = VK_NULL_HANDLE; - vk_image_info->imageView = u.view->v.u.vk_image_view; - vk_image_info->imageLayout = u.header->magic == VKD3D_DESCRIPTOR_MAGIC_SRV - ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_GENERAL; - - vk_descriptor_write->pImageInfo = vk_image_info; + vk_descriptor_write->dstBinding += use_array ? 1 : range->descriptor_count; } + + vk_image_info->sampler = VK_NULL_HANDLE; + vk_image_info->imageView = u.view->v.u.vk_image_view; + vk_image_info->imageLayout = u.header->magic == VKD3D_DESCRIPTOR_MAGIC_SRV + ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_GENERAL; + + vk_descriptor_write->pImageInfo = vk_image_info; break; case VKD3D_DESCRIPTOR_MAGIC_SAMPLER: diff --git a/libs/vkd3d/libs/vkd3d/state.c b/libs/vkd3d/libs/vkd3d/state.c index fb377177403..8e5ec70a577 100644 --- a/libs/vkd3d/libs/vkd3d/state.c +++ b/libs/vkd3d/libs/vkd3d/state.c @@ -219,6 +219,30 @@ static VkShaderStageFlags stage_flags_from_visibility(D3D12_SHADER_VISIBILITY vi } } +static VkShaderStageFlags stage_flags_from_vkd3d_shader_visibility(enum vkd3d_shader_visibility visibility) +{ + switch (visibility) + { + case VKD3D_SHADER_VISIBILITY_ALL: + return VK_SHADER_STAGE_ALL; + case VKD3D_SHADER_VISIBILITY_VERTEX: + return VK_SHADER_STAGE_VERTEX_BIT; + case VKD3D_SHADER_VISIBILITY_HULL: + return VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT; + case VKD3D_SHADER_VISIBILITY_DOMAIN: + return VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT; + case VKD3D_SHADER_VISIBILITY_GEOMETRY: + return VK_SHADER_STAGE_GEOMETRY_BIT; + case VKD3D_SHADER_VISIBILITY_PIXEL: + return VK_SHADER_STAGE_FRAGMENT_BIT; + case VKD3D_SHADER_VISIBILITY_COMPUTE: + return VK_SHADER_STAGE_COMPUTE_BIT; + default: + FIXME("Unhandled visibility %#x.\n", visibility); + return VKD3D_SHADER_VISIBILITY_ALL; + } +} + static enum vkd3d_shader_visibility vkd3d_shader_visibility_from_d3d12(D3D12_SHADER_VISIBILITY visibility) { switch (visibility) @@ -260,23 +284,6 @@ static VkDescriptorType vk_descriptor_type_from_vkd3d_descriptor_type(enum vkd3d } } -static VkDescriptorType vk_descriptor_type_from_d3d12_root_parameter(D3D12_ROOT_PARAMETER_TYPE type) -{ - switch (type) - { - /* SRV and UAV root parameters are buffer views. */ - case D3D12_ROOT_PARAMETER_TYPE_SRV: - return VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; - case D3D12_ROOT_PARAMETER_TYPE_UAV: - return VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; - case D3D12_ROOT_PARAMETER_TYPE_CBV: - return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - default: - FIXME("Unhandled descriptor root parameter type %#x.\n", type); - return VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; - } -} - static enum vkd3d_shader_descriptor_type vkd3d_descriptor_type_from_d3d12_range_type( D3D12_DESCRIPTOR_RANGE_TYPE type) { @@ -313,20 +320,6 @@ static enum vkd3d_shader_descriptor_type vkd3d_descriptor_type_from_d3d12_root_p } } -static bool vk_binding_from_d3d12_descriptor_range(struct VkDescriptorSetLayoutBinding *binding_desc, - enum vkd3d_shader_descriptor_type descriptor_type, D3D12_SHADER_VISIBILITY shader_visibility, - bool is_buffer, uint32_t vk_binding, unsigned int descriptor_count) -{ - binding_desc->binding = vk_binding; - binding_desc->descriptorType - = vk_descriptor_type_from_vkd3d_descriptor_type(descriptor_type, is_buffer); - binding_desc->descriptorCount = descriptor_count; - binding_desc->stageFlags = stage_flags_from_visibility(shader_visibility); - binding_desc->pImmutableSamplers = NULL; - - return true; -} - struct d3d12_root_signature_info { size_t binding_count; @@ -719,18 +712,66 @@ static HRESULT d3d12_root_signature_init_push_constants(struct d3d12_root_signat return S_OK; } +struct vk_binding_array +{ + VkDescriptorSetLayoutBinding *bindings; + size_t capacity, count; + + unsigned int table_index; + unsigned int unbounded_offset; + VkDescriptorSetLayoutCreateFlags flags; +}; + +static void vk_binding_array_cleanup(struct vk_binding_array *array) +{ + vkd3d_free(array->bindings); + array->bindings = NULL; +} + +static bool vk_binding_array_add_binding(struct vk_binding_array *array, + VkDescriptorType descriptor_type, unsigned int descriptor_count, + VkShaderStageFlags stage_flags, const VkSampler *immutable_sampler, unsigned int *binding_idx) +{ + unsigned int binding_count = array->count; + VkDescriptorSetLayoutBinding *binding; + + if (!vkd3d_array_reserve((void **)&array->bindings, &array->capacity, + array->count + 1, sizeof(*array->bindings))) + { + ERR("Failed to reallocate the Vulkan binding array.\n"); + return false; + } + + *binding_idx = binding_count; + binding = &array->bindings[binding_count]; + binding->binding = binding_count; + binding->descriptorType = descriptor_type; + binding->descriptorCount = descriptor_count; + binding->stageFlags = stage_flags; + binding->pImmutableSamplers = immutable_sampler; + ++array->count; + + return true; +} + struct vkd3d_descriptor_set_context { - VkDescriptorSetLayoutBinding *current_binding; - VkDescriptorSetLayoutBinding *first_binding; + struct vk_binding_array vk_bindings[VKD3D_MAX_DESCRIPTOR_SETS]; unsigned int table_index; unsigned int unbounded_offset; unsigned int descriptor_index; unsigned int uav_counter_index; unsigned int push_constant_index; - uint32_t descriptor_binding; }; +static void descriptor_set_context_cleanup(struct vkd3d_descriptor_set_context *context) +{ + size_t i; + + for (i = 0; i < ARRAY_SIZE(context->vk_bindings); ++i) + vk_binding_array_cleanup(&context->vk_bindings[i]); +} + static bool vkd3d_validate_descriptor_set_count(struct d3d12_device *device, unsigned int set_count) { uint32_t max_count = min(VKD3D_MAX_DESCRIPTOR_SETS, device->vk_info.device_limits.maxBoundDescriptorSets); @@ -745,56 +786,56 @@ static bool vkd3d_validate_descriptor_set_count(struct d3d12_device *device, uns return true; } -static HRESULT vkd3d_create_descriptor_set_layout(struct d3d12_device *device, - VkDescriptorSetLayoutCreateFlags flags, unsigned int binding_count, bool unbounded, - const VkDescriptorSetLayoutBinding *bindings, VkDescriptorSetLayout *set_layout); - -static HRESULT d3d12_root_signature_append_descriptor_set_layout(struct d3d12_root_signature *root_signature, - struct vkd3d_descriptor_set_context *context, VkDescriptorSetLayoutCreateFlags flags) +static struct vk_binding_array *d3d12_root_signature_current_vk_binding_array( + struct d3d12_root_signature *root_signature, struct vkd3d_descriptor_set_context *context) { - struct d3d12_descriptor_set_layout *layout; - unsigned int index; - HRESULT hr; - - if (!context->descriptor_binding) - return S_OK; + if (root_signature->vk_set_count >= ARRAY_SIZE(context->vk_bindings)) + return NULL; - index = root_signature->vk_set_count; - layout = &root_signature->descriptor_set_layouts[index]; + return &context->vk_bindings[root_signature->vk_set_count]; +} - if (!vkd3d_validate_descriptor_set_count(root_signature->device, index + 1)) - return E_INVALIDARG; +static void d3d12_root_signature_append_vk_binding_array(struct d3d12_root_signature *root_signature, + VkDescriptorSetLayoutCreateFlags flags, struct vkd3d_descriptor_set_context *context) +{ + struct vk_binding_array *array; - if (FAILED(hr = vkd3d_create_descriptor_set_layout(root_signature->device, flags, context->descriptor_binding, - context->unbounded_offset != UINT_MAX, context->first_binding, &layout->vk_layout))) - return hr; - layout->table_index = context->table_index; - layout->unbounded_offset = context->unbounded_offset; - ++root_signature->vk_set_count; + if (!(array = d3d12_root_signature_current_vk_binding_array(root_signature, context)) || !array->count) + return; - context->current_binding = context->first_binding; - context->descriptor_binding = 0; + array->table_index = context->table_index; + array->unbounded_offset = context->unbounded_offset; + array->flags = flags; - return S_OK; + ++root_signature->vk_set_count; } static HRESULT d3d12_root_signature_append_vk_binding(struct d3d12_root_signature *root_signature, - enum vkd3d_shader_descriptor_type descriptor_type, unsigned int register_space, unsigned int register_idx, - bool buffer_descriptor, enum vkd3d_shader_visibility shader_visibility, - unsigned int descriptor_count, struct vkd3d_descriptor_set_context *context) + enum vkd3d_shader_descriptor_type descriptor_type, unsigned int register_space, + unsigned int register_idx, bool buffer_descriptor, enum vkd3d_shader_visibility shader_visibility, + unsigned int descriptor_count, struct vkd3d_descriptor_set_context *context, + const VkSampler *immutable_sampler, unsigned int *binding_idx) { struct vkd3d_shader_descriptor_offset *offset = root_signature->descriptor_offsets ? &root_signature->descriptor_offsets[context->descriptor_index] : NULL; - struct vkd3d_shader_resource_binding *mapping - = &root_signature->descriptor_mapping[context->descriptor_index++]; + struct vkd3d_shader_resource_binding *mapping; + struct vk_binding_array *array; + unsigned int idx; + + if (!(array = d3d12_root_signature_current_vk_binding_array(root_signature, context)) + || !(vk_binding_array_add_binding(&context->vk_bindings[root_signature->vk_set_count], + vk_descriptor_type_from_vkd3d_descriptor_type(descriptor_type, buffer_descriptor), descriptor_count, + stage_flags_from_vkd3d_shader_visibility(shader_visibility), immutable_sampler, &idx))) + return E_OUTOFMEMORY; + mapping = &root_signature->descriptor_mapping[context->descriptor_index++]; mapping->type = descriptor_type; mapping->register_space = register_space; mapping->register_index = register_idx; mapping->shader_visibility = shader_visibility; mapping->flags = buffer_descriptor ? VKD3D_SHADER_BINDING_FLAG_BUFFER : VKD3D_SHADER_BINDING_FLAG_IMAGE; mapping->binding.set = root_signature->vk_set_count; - mapping->binding.binding = context->descriptor_binding++; + mapping->binding.binding = idx; mapping->binding.count = descriptor_count; if (offset) { @@ -803,37 +844,11 @@ static HRESULT d3d12_root_signature_append_vk_binding(struct d3d12_root_signatur } if (context->unbounded_offset != UINT_MAX) - return d3d12_root_signature_append_descriptor_set_layout(root_signature, context, 0); + d3d12_root_signature_append_vk_binding_array(root_signature, 0, context); - return S_OK; -} + if (binding_idx) + *binding_idx = idx; -static HRESULT d3d12_root_signature_assign_vk_bindings(struct d3d12_root_signature *root_signature, - enum vkd3d_shader_descriptor_type descriptor_type, unsigned int register_space, unsigned int base_register_idx, - unsigned int binding_count, bool is_buffer_descriptor, bool duplicate_descriptors, - enum vkd3d_shader_visibility shader_visibility, struct vkd3d_descriptor_set_context *context, - uint32_t *first_binding) -{ - unsigned int i; - HRESULT hr; - - is_buffer_descriptor |= descriptor_type == VKD3D_SHADER_DESCRIPTOR_TYPE_CBV; - duplicate_descriptors = (descriptor_type == VKD3D_SHADER_DESCRIPTOR_TYPE_SRV - || descriptor_type == VKD3D_SHADER_DESCRIPTOR_TYPE_UAV) - && duplicate_descriptors; - - *first_binding = context->descriptor_binding; - for (i = 0; i < binding_count; ++i) - { - if (duplicate_descriptors - && FAILED(hr = d3d12_root_signature_append_vk_binding(root_signature, descriptor_type, - register_space, base_register_idx + i, true, shader_visibility, 1, context))) - return hr; - - if (FAILED(hr = d3d12_root_signature_append_vk_binding(root_signature, descriptor_type, register_space, - base_register_idx + i, is_buffer_descriptor, shader_visibility, 1, context))) - return hr; - } return S_OK; } @@ -895,38 +910,41 @@ static unsigned int vk_binding_count_from_descriptor_range(const struct d3d12_ro return min(count, VKD3D_MAX_VIRTUAL_HEAP_DESCRIPTORS_PER_TYPE); } -static HRESULT d3d12_root_signature_init_descriptor_array_binding(struct d3d12_root_signature *root_signature, +static HRESULT d3d12_root_signature_init_descriptor_table_binding(struct d3d12_root_signature *root_signature, const struct d3d12_root_descriptor_table_range *range, D3D12_SHADER_VISIBILITY visibility, + unsigned int vk_binding_array_count, unsigned int bindings_per_range, struct vkd3d_descriptor_set_context *context) { enum vkd3d_shader_visibility shader_visibility = vkd3d_shader_visibility_from_d3d12(visibility); - bool is_buffer = range->type == VKD3D_SHADER_DESCRIPTOR_TYPE_CBV; + bool is_buffer = range->type != VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER; enum vkd3d_shader_descriptor_type descriptor_type = range->type; + unsigned int i, register_space = range->register_space; HRESULT hr; if (range->descriptor_count == UINT_MAX) context->unbounded_offset = range->offset; - if (descriptor_type == VKD3D_SHADER_DESCRIPTOR_TYPE_SRV || descriptor_type == VKD3D_SHADER_DESCRIPTOR_TYPE_UAV) + for (i = 0; i < bindings_per_range; ++i) { - if (!vk_binding_from_d3d12_descriptor_range(context->current_binding, - descriptor_type, visibility, true, context->descriptor_binding, range->vk_binding_count)) - return E_NOTIMPL; - ++context->current_binding; - - if (FAILED(hr = d3d12_root_signature_append_vk_binding(root_signature, descriptor_type, range->register_space, - range->base_register_idx, true, shader_visibility, range->vk_binding_count, context))) + if (FAILED(hr = d3d12_root_signature_append_vk_binding(root_signature, descriptor_type, + register_space, range->base_register_idx + i, is_buffer, shader_visibility, + vk_binding_array_count, context, NULL, NULL))) return hr; } - if (!vk_binding_from_d3d12_descriptor_range(context->current_binding, - descriptor_type, visibility, is_buffer, context->descriptor_binding, range->vk_binding_count)) - return E_NOTIMPL; - ++context->current_binding; + if (descriptor_type != VKD3D_SHADER_DESCRIPTOR_TYPE_SRV && descriptor_type != VKD3D_SHADER_DESCRIPTOR_TYPE_UAV) + { + context->unbounded_offset = UINT_MAX; + return S_OK; + } - if (FAILED(hr = d3d12_root_signature_append_vk_binding(root_signature, descriptor_type, range->register_space, - range->base_register_idx, is_buffer, shader_visibility, range->vk_binding_count, context))) - return hr; + for (i = 0; i < bindings_per_range; ++i) + { + if (FAILED(hr = d3d12_root_signature_append_vk_binding(root_signature, descriptor_type, + register_space, range->base_register_idx + i, false, shader_visibility, + vk_binding_array_count, context, NULL, NULL))) + return hr; + } context->unbounded_offset = UINT_MAX; @@ -1116,11 +1134,10 @@ static HRESULT d3d12_root_signature_init_root_descriptor_tables(struct d3d12_roo const D3D12_ROOT_SIGNATURE_DESC *desc, const struct d3d12_root_signature_info *info, struct vkd3d_descriptor_set_context *context) { + unsigned int i, j, range_count, bindings_per_range, vk_binding_array_count; const struct d3d12_device *device = root_signature->device; bool use_vk_heaps = root_signature->device->use_vk_heaps; struct d3d12_root_descriptor_table *table; - unsigned int i, j, k, range_count; - uint32_t vk_binding; HRESULT hr; root_signature->descriptor_table_mask = 0; @@ -1177,7 +1194,6 @@ static HRESULT d3d12_root_signature_init_root_descriptor_tables(struct d3d12_roo for (j = 0; j < range_count; ++j) { struct d3d12_root_descriptor_table_range *range; - VkDescriptorSetLayoutBinding *cur_binding; range = &table->ranges[j]; @@ -1223,53 +1239,23 @@ static HRESULT d3d12_root_signature_init_root_descriptor_tables(struct d3d12_roo base_range = range; } - range->binding = context->descriptor_binding; range->vk_binding_count = vk_binding_count_from_descriptor_range(range, info, &device->vk_info.descriptor_limits); - - if (FAILED(hr = d3d12_root_signature_init_descriptor_array_binding(root_signature, - range, p->ShaderVisibility, context))) - return hr; - - continue; + vk_binding_array_count = range->vk_binding_count; + bindings_per_range = 1; } - - cur_binding = context->current_binding; - - if (FAILED(hr = d3d12_root_signature_assign_vk_bindings(root_signature, - range->type, range->register_space, range->base_register_idx, range->descriptor_count, false, true, - shader_visibility, context, &vk_binding))) - return hr; - - /* Unroll descriptor range. */ - for (k = 0; k < range->descriptor_count; ++k) + else { - uint32_t vk_current_binding = vk_binding + k; - - if (range->type == VKD3D_SHADER_DESCRIPTOR_TYPE_SRV - || range->type == VKD3D_SHADER_DESCRIPTOR_TYPE_UAV) - { - vk_current_binding = vk_binding + 2 * k; - - /* Assign binding for image view. */ - if (!vk_binding_from_d3d12_descriptor_range(cur_binding, - range->type, p->ShaderVisibility, false, vk_current_binding + 1, 1)) - return E_NOTIMPL; - - ++cur_binding; - } - - if (!vk_binding_from_d3d12_descriptor_range(cur_binding, - range->type, p->ShaderVisibility, true, vk_current_binding, 1)) - return E_NOTIMPL; - - ++cur_binding; + range->vk_binding_count = range->descriptor_count; + vk_binding_array_count = 1; + bindings_per_range = range->descriptor_count; } - table->ranges[j].vk_binding_count = table->ranges[j].descriptor_count; - table->ranges[j].binding = vk_binding; + range->binding = context->vk_bindings[root_signature->vk_set_count].count; - context->current_binding = cur_binding; + if (FAILED(hr = d3d12_root_signature_init_descriptor_table_binding(root_signature, range, + p->ShaderVisibility, vk_binding_array_count, bindings_per_range, context))) + return hr; } ++context->push_constant_index; } @@ -1280,8 +1266,7 @@ static HRESULT d3d12_root_signature_init_root_descriptor_tables(struct d3d12_roo static HRESULT d3d12_root_signature_init_root_descriptors(struct d3d12_root_signature *root_signature, const D3D12_ROOT_SIGNATURE_DESC *desc, struct vkd3d_descriptor_set_context *context) { - VkDescriptorSetLayoutBinding *cur_binding = context->current_binding; - unsigned int i; + unsigned int binding, i; HRESULT hr; root_signature->push_descriptor_mask = 0; @@ -1296,23 +1281,16 @@ static HRESULT d3d12_root_signature_init_root_descriptors(struct d3d12_root_sign root_signature->push_descriptor_mask |= 1u << i; - if (FAILED(hr = d3d12_root_signature_assign_vk_bindings(root_signature, + if (FAILED(hr = d3d12_root_signature_append_vk_binding(root_signature, vkd3d_descriptor_type_from_d3d12_root_parameter_type(p->ParameterType), - p->u.Descriptor.RegisterSpace, p->u.Descriptor.ShaderRegister, 1, true, false, - vkd3d_shader_visibility_from_d3d12(p->ShaderVisibility), context, &cur_binding->binding))) + p->u.Descriptor.RegisterSpace, p->u.Descriptor.ShaderRegister, true, + vkd3d_shader_visibility_from_d3d12(p->ShaderVisibility), 1, context, NULL, &binding))) return hr; - cur_binding->descriptorType = vk_descriptor_type_from_d3d12_root_parameter(p->ParameterType); - cur_binding->descriptorCount = 1; - cur_binding->stageFlags = stage_flags_from_visibility(p->ShaderVisibility); - cur_binding->pImmutableSamplers = NULL; root_signature->parameters[i].parameter_type = p->ParameterType; - root_signature->parameters[i].u.descriptor.binding = cur_binding->binding; - - ++cur_binding; + root_signature->parameters[i].u.descriptor.binding = binding; } - context->current_binding = cur_binding; return S_OK; } @@ -1320,7 +1298,6 @@ static HRESULT d3d12_root_signature_init_static_samplers(struct d3d12_root_signa struct d3d12_device *device, const D3D12_ROOT_SIGNATURE_DESC *desc, struct vkd3d_descriptor_set_context *context) { - VkDescriptorSetLayoutBinding *cur_binding = context->current_binding; unsigned int i; HRESULT hr; @@ -1332,21 +1309,15 @@ static HRESULT d3d12_root_signature_init_static_samplers(struct d3d12_root_signa if (FAILED(hr = vkd3d_create_static_sampler(device, s, &root_signature->static_samplers[i]))) return hr; - if (FAILED(hr = d3d12_root_signature_assign_vk_bindings(root_signature, - VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, s->RegisterSpace, s->ShaderRegister, 1, false, false, - vkd3d_shader_visibility_from_d3d12(s->ShaderVisibility), context, &cur_binding->binding))) + if (FAILED(hr = d3d12_root_signature_append_vk_binding(root_signature, + VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, s->RegisterSpace, s->ShaderRegister, false, + vkd3d_shader_visibility_from_d3d12(s->ShaderVisibility), 1, context, + &root_signature->static_samplers[i], NULL))) return hr; - cur_binding->descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER; - cur_binding->descriptorCount = 1; - cur_binding->stageFlags = stage_flags_from_visibility(s->ShaderVisibility); - cur_binding->pImmutableSamplers = &root_signature->static_samplers[i]; - - ++cur_binding; } - context->current_binding = cur_binding; if (device->use_vk_heaps) - return d3d12_root_signature_append_descriptor_set_layout(root_signature, context, 0); + d3d12_root_signature_append_vk_binding_array(root_signature, 0, context); return S_OK; } @@ -1479,6 +1450,34 @@ static HRESULT vkd3d_create_pipeline_layout(struct d3d12_device *device, return S_OK; } +static HRESULT d3d12_root_signature_create_descriptor_set_layouts(struct d3d12_root_signature *root_signature, + struct vkd3d_descriptor_set_context *context) +{ + unsigned int i; + HRESULT hr; + + d3d12_root_signature_append_vk_binding_array(root_signature, 0, context); + + if (!vkd3d_validate_descriptor_set_count(root_signature->device, root_signature->vk_set_count)) + return E_INVALIDARG; + + for (i = 0; i < root_signature->vk_set_count; ++i) + { + struct d3d12_descriptor_set_layout *layout = &root_signature->descriptor_set_layouts[i]; + struct vk_binding_array *array = &context->vk_bindings[i]; + + VKD3D_ASSERT(array->count); + + if (FAILED(hr = vkd3d_create_descriptor_set_layout(root_signature->device, array->flags, array->count, + array->unbounded_offset != UINT_MAX, array->bindings, &layout->vk_layout))) + return hr; + layout->unbounded_offset = array->unbounded_offset; + layout->table_index = array->table_index; + } + + return S_OK; +} + static unsigned int d3d12_root_signature_copy_descriptor_set_layouts(const struct d3d12_root_signature *root_signature, VkDescriptorSetLayout *vk_set_layouts) { @@ -1510,7 +1509,6 @@ static HRESULT d3d12_root_signature_init(struct d3d12_root_signature *root_signa VkDescriptorSetLayout vk_layouts[VKD3D_MAX_DESCRIPTOR_SETS]; const struct vkd3d_vulkan_info *vk_info = &device->vk_info; struct vkd3d_descriptor_set_context context; - VkDescriptorSetLayoutBinding *binding_desc; struct d3d12_root_signature_info info; bool use_vk_heaps; unsigned int i; @@ -1518,7 +1516,6 @@ static HRESULT d3d12_root_signature_init(struct d3d12_root_signature *root_signa memset(&context, 0, sizeof(context)); context.unbounded_offset = UINT_MAX; - binding_desc = NULL; root_signature->ID3D12RootSignature_iface.lpVtbl = &d3d12_root_signature_vtbl; root_signature->refcount = 1; @@ -1580,20 +1577,14 @@ static HRESULT d3d12_root_signature_init(struct d3d12_root_signature *root_signa sizeof(*root_signature->static_samplers)))) goto fail; - if (!(binding_desc = vkd3d_calloc(info.binding_count, sizeof(*binding_desc)))) - goto fail; - context.first_binding = binding_desc; - context.current_binding = binding_desc; - if (FAILED(hr = d3d12_root_signature_init_root_descriptors(root_signature, desc, &context))) goto fail; /* We use KHR_push_descriptor for root descriptor parameters. */ if (vk_info->KHR_push_descriptor) { - if (FAILED(hr = d3d12_root_signature_append_descriptor_set_layout(root_signature, - &context, VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR))) - goto fail; + d3d12_root_signature_append_vk_binding_array(root_signature, + VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR, &context); } root_signature->main_set = root_signature->vk_set_count; @@ -1609,11 +1600,10 @@ static HRESULT d3d12_root_signature_init(struct d3d12_root_signature *root_signa if (use_vk_heaps) d3d12_root_signature_init_descriptor_table_push_constants(root_signature, &context); - if (FAILED(hr = d3d12_root_signature_append_descriptor_set_layout(root_signature, &context, 0))) + if (FAILED(hr = d3d12_root_signature_create_descriptor_set_layouts(root_signature, &context))) goto fail; - vkd3d_free(binding_desc); - binding_desc = NULL; + descriptor_set_context_cleanup(&context); i = d3d12_root_signature_copy_descriptor_set_layouts(root_signature, vk_layouts); if (FAILED(hr = vkd3d_create_pipeline_layout(device, i, @@ -1629,7 +1619,7 @@ static HRESULT d3d12_root_signature_init(struct d3d12_root_signature *root_signa return S_OK; fail: - vkd3d_free(binding_desc); + descriptor_set_context_cleanup(&context); d3d12_root_signature_cleanup(root_signature, device); return hr; } -- 2.45.2