From 8de3a6475f21e12fc05532ddc836e14c9abc4f4f Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Tue, 4 Feb 2025 06:59:46 +1100 Subject: [PATCH] Updated vkd3d to 2f77d56b7748f89ae85fd08bba956fbb60387bd2. --- libs/vkd3d/libs/vkd3d-shader/hlsl.c | 62 ++- libs/vkd3d/libs/vkd3d-shader/hlsl.h | 37 +- libs/vkd3d/libs/vkd3d-shader/hlsl.l | 2 + libs/vkd3d/libs/vkd3d-shader/hlsl.y | 157 +++---- libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 426 ++++++++++++++---- libs/vkd3d/libs/vkd3d-shader/tpf.c | 22 +- .../libs/vkd3d-shader/vkd3d_shader_private.h | 3 +- 7 files changed, 519 insertions(+), 190 deletions(-) diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c index 48d9d4e0023..41586550203 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c @@ -93,7 +93,7 @@ char *hlsl_sprintf_alloc(struct hlsl_ctx *ctx, const char *fmt, ...) return ret; } -bool hlsl_add_var(struct hlsl_ctx *ctx, struct hlsl_ir_var *decl, bool local_var) +void hlsl_add_var(struct hlsl_ctx *ctx, struct hlsl_ir_var *decl) { struct hlsl_scope *scope = ctx->cur_scope; struct hlsl_ir_var *var; @@ -103,21 +103,16 @@ bool hlsl_add_var(struct hlsl_ctx *ctx, struct hlsl_ir_var *decl, bool local_var LIST_FOR_EACH_ENTRY(var, &scope->vars, struct hlsl_ir_var, scope_entry) { if (var->name && !strcmp(decl->name, var->name)) - return false; - } - if (local_var && scope->upper->upper == ctx->globals) - { - /* Check whether the variable redefines a function parameter. */ - LIST_FOR_EACH_ENTRY(var, &scope->upper->vars, struct hlsl_ir_var, scope_entry) { - if (var->name && !strcmp(decl->name, var->name)) - return false; + hlsl_error(ctx, &decl->loc, VKD3D_SHADER_ERROR_HLSL_REDEFINED, + "Identifier \"%s\" was already declared in this scope.", var->name); + hlsl_note(ctx, &var->loc, VKD3D_SHADER_LOG_ERROR, "\"%s\" was previously declared here.", var->name); + break; } } } list_add_tail(&scope->vars, &decl->scope_entry); - return true; } struct hlsl_ir_var *hlsl_get_var(struct hlsl_scope *scope, const char *name) @@ -297,6 +292,12 @@ bool hlsl_type_is_shader(const struct hlsl_type *type) return false; } +bool hlsl_type_is_patch_array(const struct hlsl_type *type) +{ + return type->class == HLSL_CLASS_ARRAY && (type->e.array.array_type == HLSL_ARRAY_PATCH_INPUT + || type->e.array.array_type == HLSL_ARRAY_PATCH_OUTPUT); +} + /* Only intended to be used for derefs (after copies have been lowered to components or vectors) or * resources, since for both their data types span across a single regset. */ static enum hlsl_regset type_get_regset(const struct hlsl_type *type) @@ -891,7 +892,8 @@ struct hlsl_type *hlsl_get_element_type_from_path_index(struct hlsl_ctx *ctx, co } } -struct hlsl_type *hlsl_new_array_type(struct hlsl_ctx *ctx, struct hlsl_type *basic_type, unsigned int array_size) +struct hlsl_type *hlsl_new_array_type(struct hlsl_ctx *ctx, struct hlsl_type *basic_type, + unsigned int array_size, enum hlsl_array_type array_type) { struct hlsl_type *type; @@ -902,6 +904,7 @@ struct hlsl_type *hlsl_new_array_type(struct hlsl_ctx *ctx, struct hlsl_type *ba type->modifiers = basic_type->modifiers; type->e.array.elements_count = array_size; type->e.array.type = basic_type; + type->e.array.array_type = array_type; type->sampler_dim = basic_type->sampler_dim; hlsl_type_calculate_reg_size(ctx, type); @@ -1172,6 +1175,7 @@ bool hlsl_types_are_equal(const struct hlsl_type *t1, const struct hlsl_type *t2 case HLSL_CLASS_ARRAY: return t1->e.array.elements_count == t2->e.array.elements_count + && t1->e.array.array_type == t2->e.array.array_type && hlsl_types_are_equal(t1->e.array.type, t2->e.array.type); case HLSL_CLASS_TECHNIQUE: @@ -1251,6 +1255,7 @@ struct hlsl_type *hlsl_type_clone(struct hlsl_ctx *ctx, struct hlsl_type *old, return NULL; } type->e.array.elements_count = old->e.array.elements_count; + type->e.array.array_type = old->e.array.array_type; break; case HLSL_CLASS_STRUCT: @@ -2833,22 +2838,32 @@ static void hlsl_dump_type(struct vkd3d_string_buffer *buffer, const struct hlsl return; case HLSL_CLASS_ARRAY: - { - const struct hlsl_type *t; - - for (t = type; t->class == HLSL_CLASS_ARRAY; t = t->e.array.type) - ; - - hlsl_dump_type(buffer, t); - for (t = type; t->class == HLSL_CLASS_ARRAY; t = t->e.array.type) + if (hlsl_type_is_patch_array(type)) { - if (t->e.array.elements_count == HLSL_ARRAY_ELEMENTS_COUNT_IMPLICIT) - vkd3d_string_buffer_printf(buffer, "[]"); + if (type->e.array.array_type == HLSL_ARRAY_PATCH_INPUT) + vkd3d_string_buffer_printf(buffer, "InputPatch<"); else - vkd3d_string_buffer_printf(buffer, "[%u]", t->e.array.elements_count); + vkd3d_string_buffer_printf(buffer, "OutputPatch<"); + hlsl_dump_type(buffer, type->e.array.type); + vkd3d_string_buffer_printf(buffer, ", %u>", type->e.array.elements_count); + } + else + { + const struct hlsl_type *t; + + for (t = type; t->class == HLSL_CLASS_ARRAY; t = t->e.array.type) + ; + + hlsl_dump_type(buffer, t); + for (t = type; t->class == HLSL_CLASS_ARRAY; t = t->e.array.type) + { + if (t->e.array.elements_count == HLSL_ARRAY_ELEMENTS_COUNT_IMPLICIT) + vkd3d_string_buffer_printf(buffer, "[]"); + else + vkd3d_string_buffer_printf(buffer, "[%u]", t->e.array.elements_count); + } } return; - } case HLSL_CLASS_STRUCT: vkd3d_string_buffer_printf(buffer, ""); @@ -4561,6 +4576,7 @@ static bool hlsl_ctx_init(struct hlsl_ctx *ctx, const struct vkd3d_shader_compil ctx->output_control_point_count = UINT_MAX; ctx->output_primitive = 0; ctx->partitioning = 0; + ctx->input_control_point_count = UINT_MAX; return true; } diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h index e9845f8f887..f614e12036e 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h @@ -145,6 +145,13 @@ enum hlsl_regset HLSL_REGSET_LAST = HLSL_REGSET_NUMERIC, }; +enum hlsl_array_type +{ + HLSL_ARRAY_GENERIC, + HLSL_ARRAY_PATCH_INPUT, + HLSL_ARRAY_PATCH_OUTPUT, +}; + /* An HLSL source-level data type, including anonymous structs and typedefs. */ struct hlsl_type { @@ -195,6 +202,7 @@ struct hlsl_type struct hlsl_type *type; /* Array length, or HLSL_ARRAY_ELEMENTS_COUNT_IMPLICIT if it is not known yet at parse time. */ unsigned int elements_count; + enum hlsl_array_type array_type; } array; /* Additional information if the class is HLSL_CLASS_TEXTURE or * HLSL_CLASS_UAV. */ @@ -1147,11 +1155,34 @@ struct hlsl_ctx * compute shader profiles. It is set using the numthreads() attribute in the entry point. */ uint32_t thread_count[3]; + /* Declared information in tessellation shaders. + * + * The following fields are specific to hull shaders: output_control_point_count, + * output_control_point_type, output_primitive, partitioning, and patch_constant_func. + * + * The output_control_point_count and output_control_point_type fields correspond to the return + * type and the "outputcontrolpoints" attribute of a hull shader's control point function, + * respectively. Moreover, if an OutputPatch parameter is declared in the hull shader's patch + * constant function, its type and element count must match these fields. + * + * The input_control_point_count and input_control_point_type fields are specified by the + * InputPatch parameter in hull shaders, or by the _OutputPatch_ parameter in domain + * shaders. + * + * For input_ and output_control_point_count, the value UINT_MAX indicates that the value is + * unknown or not set by the shader. */ enum vkd3d_tessellator_domain domain; unsigned int output_control_point_count; + struct hlsl_type *output_control_point_type; enum vkd3d_shader_tessellator_output_primitive output_primitive; enum vkd3d_shader_tessellator_partitioning partitioning; struct hlsl_ir_function_decl *patch_constant_func; + unsigned int input_control_point_count; + struct hlsl_type *input_control_point_type; + + /* Whether the current function being processed during HLSL codegen is + * the patch constant function in a hull shader. */ + bool is_patch_constant_func; /* In some cases we generate opcodes by parsing an HLSL function and then * invoking it. If not NULL, this field is the name of the function that we @@ -1469,7 +1500,7 @@ const char *hlsl_node_type_to_string(enum hlsl_ir_node_type type); struct hlsl_ir_node *hlsl_add_conditional(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_ir_node *condition, struct hlsl_ir_node *if_true, struct hlsl_ir_node *if_false); void hlsl_add_function(struct hlsl_ctx *ctx, char *name, struct hlsl_ir_function_decl *decl); -bool hlsl_add_var(struct hlsl_ctx *ctx, struct hlsl_ir_var *decl, bool local_var); +void hlsl_add_var(struct hlsl_ctx *ctx, struct hlsl_ir_var *decl); void hlsl_block_cleanup(struct hlsl_block *block); bool hlsl_clone_block(struct hlsl_ctx *ctx, struct hlsl_block *dst_block, const struct hlsl_block *src_block); @@ -1527,7 +1558,8 @@ struct hlsl_type *hlsl_get_element_type_from_path_index(struct hlsl_ctx *ctx, co const char *hlsl_jump_type_to_string(enum hlsl_ir_jump_type type); -struct hlsl_type *hlsl_new_array_type(struct hlsl_ctx *ctx, struct hlsl_type *basic_type, unsigned int array_size); +struct hlsl_type *hlsl_new_array_type(struct hlsl_ctx *ctx, struct hlsl_type *basic_type, + unsigned int array_size, enum hlsl_array_type array_type); struct hlsl_ir_node *hlsl_new_binary_expr(struct hlsl_ctx *ctx, enum hlsl_ir_expr_op op, struct hlsl_ir_node *arg1, struct hlsl_ir_node *arg2); struct hlsl_ir_node *hlsl_new_bool_constant(struct hlsl_ctx *ctx, bool b, const struct vkd3d_shader_location *loc); @@ -1659,6 +1691,7 @@ unsigned int hlsl_type_major_size(const struct hlsl_type *type); unsigned int hlsl_type_element_count(const struct hlsl_type *type); bool hlsl_type_is_resource(const struct hlsl_type *type); bool hlsl_type_is_shader(const struct hlsl_type *type); +bool hlsl_type_is_patch_array(const struct hlsl_type *type); unsigned int hlsl_type_get_sm4_offset(const struct hlsl_type *type, unsigned int offset); bool hlsl_types_are_equal(const struct hlsl_type *t1, const struct hlsl_type *t2); diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.l b/libs/vkd3d/libs/vkd3d-shader/hlsl.l index 31fb30521e9..605a9abaa93 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.l +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.l @@ -104,6 +104,7 @@ if {return KW_IF; } in {return KW_IN; } inline {return KW_INLINE; } inout {return KW_INOUT; } +InputPatch {return KW_INPUTPATCH; } LineStream {return KW_LINESTREAM; } linear {return KW_LINEAR; } matrix {return KW_MATRIX; } @@ -112,6 +113,7 @@ nointerpolation {return KW_NOINTERPOLATION; } noperspective {return KW_NOPERSPECTIVE; } NULL {return KW_NULL; } out {return KW_OUT; } +OutputPatch {return KW_OUTPUTPATCH; } packoffset {return KW_PACKOFFSET; } pass {return KW_PASS; } PixelShader {return KW_PIXELSHADER; } diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y index 7dbb051f913..4813940e89c 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y @@ -415,7 +415,7 @@ static bool add_explicit_conversion(struct hlsl_ctx *ctx, struct hlsl_block *blo dst_type = ctx->builtin_types.error; break; } - dst_type = hlsl_new_array_type(ctx, dst_type, arrays->sizes[i]); + dst_type = hlsl_new_array_type(ctx, dst_type, arrays->sizes[i], HLSL_ARRAY_GENERIC); } if (instr->data_type->class == HLSL_CLASS_ERROR) @@ -1118,7 +1118,7 @@ static bool gen_struct_fields(struct hlsl_ctx *ctx, struct parse_fields *fields, break; } - field->type = hlsl_new_array_type(ctx, field->type, v->arrays.sizes[k]); + field->type = hlsl_new_array_type(ctx, field->type, v->arrays.sizes[k], HLSL_ARRAY_GENERIC); } } @@ -1214,7 +1214,7 @@ static bool add_typedef(struct hlsl_ctx *ctx, struct hlsl_type *const orig_type, break; } - if (!(type = hlsl_new_array_type(ctx, type, v->arrays.sizes[i]))) + if (!(type = hlsl_new_array_type(ctx, type, v->arrays.sizes[i], HLSL_ARRAY_GENERIC))) { free_parse_variable_def(v); ret = false; @@ -1311,11 +1311,7 @@ static bool add_func_parameter(struct hlsl_ctx *ctx, struct hlsl_func_parameters free_parse_initializer(¶m->initializer); } - if (!hlsl_add_var(ctx, var, false)) - { - hlsl_free_var(var); - return false; - } + hlsl_add_var(ctx, var); if (!hlsl_array_reserve(ctx, (void **)¶meters->vars, ¶meters->capacity, parameters->count + 1, sizeof(*parameters->vars))) @@ -1324,7 +1320,7 @@ static bool add_func_parameter(struct hlsl_ctx *ctx, struct hlsl_func_parameters return true; } -static bool add_pass(struct hlsl_ctx *ctx, const char *name, struct hlsl_scope *annotations, +static void add_pass(struct hlsl_ctx *ctx, const char *name, struct hlsl_scope *annotations, struct hlsl_state_block *state_block, const struct vkd3d_shader_location *loc) { struct hlsl_ir_var *var; @@ -1332,7 +1328,7 @@ static bool add_pass(struct hlsl_ctx *ctx, const char *name, struct hlsl_scope * type = hlsl_get_type(ctx->globals, "pass", false, false); if (!(var = hlsl_new_var(ctx, name, type, loc, NULL, 0, NULL))) - return false; + return; var->annotations = annotations; var->state_blocks = hlsl_alloc(ctx, sizeof(*var->state_blocks)); @@ -1340,21 +1336,10 @@ static bool add_pass(struct hlsl_ctx *ctx, const char *name, struct hlsl_scope * var->state_block_count = 1; var->state_block_capacity = 1; - if (!hlsl_add_var(ctx, var, false)) - { - struct hlsl_ir_var *old = hlsl_get_var(ctx->cur_scope, var->name); - - hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_REDEFINED, - "Identifier \"%s\" was already declared in this scope.", var->name); - hlsl_note(ctx, &old->loc, VKD3D_SHADER_LOG_ERROR, "\"%s\" was previously declared here.", old->name); - hlsl_free_var(var); - return false; - } - - return true; + hlsl_add_var(ctx, var); } -static bool add_technique(struct hlsl_ctx *ctx, const char *name, struct hlsl_scope *scope, +static void add_technique(struct hlsl_ctx *ctx, const char *name, struct hlsl_scope *scope, struct hlsl_scope *annotations, const char *typename, const struct vkd3d_shader_location *loc) { struct hlsl_ir_var *var; @@ -1362,25 +1347,14 @@ static bool add_technique(struct hlsl_ctx *ctx, const char *name, struct hlsl_sc type = hlsl_get_type(ctx->globals, typename, false, false); if (!(var = hlsl_new_var(ctx, name, type, loc, NULL, 0, NULL))) - return false; + return; var->scope = scope; var->annotations = annotations; - if (!hlsl_add_var(ctx, var, false)) - { - struct hlsl_ir_var *old = hlsl_get_var(ctx->cur_scope, var->name); - - hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_REDEFINED, - "Identifier \"%s\" was already declared in this scope.", var->name); - hlsl_note(ctx, &old->loc, VKD3D_SHADER_LOG_ERROR, "\"%s\" was previously declared here.", old->name); - hlsl_free_var(var); - return false; - } - - return true; + hlsl_add_var(ctx, var); } -static bool add_effect_group(struct hlsl_ctx *ctx, const char *name, struct hlsl_scope *scope, +static void add_effect_group(struct hlsl_ctx *ctx, const char *name, struct hlsl_scope *scope, struct hlsl_scope *annotations, const struct vkd3d_shader_location *loc) { struct hlsl_ir_var *var; @@ -1388,22 +1362,11 @@ static bool add_effect_group(struct hlsl_ctx *ctx, const char *name, struct hlsl type = hlsl_get_type(ctx->globals, "fxgroup", false, false); if (!(var = hlsl_new_var(ctx, name, type, loc, NULL, 0, NULL))) - return false; + return; var->scope = scope; var->annotations = annotations; - if (!hlsl_add_var(ctx, var, false)) - { - struct hlsl_ir_var *old = hlsl_get_var(ctx->cur_scope, var->name); - - hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_REDEFINED, - "Identifier \"%s\" was already declared in this scope.", var->name); - hlsl_note(ctx, &old->loc, VKD3D_SHADER_LOG_ERROR, "\"%s\" was previously declared here.", old->name); - hlsl_free_var(var); - return false; - } - - return true; + hlsl_add_var(ctx, var); } static bool parse_reservation_index(struct hlsl_ctx *ctx, const char *string, unsigned int bracket_offset, @@ -2590,7 +2553,6 @@ static void declare_var(struct hlsl_ctx *ctx, struct parse_variable_def *v) bool constant_buffer = false; struct hlsl_ir_var *var; struct hlsl_type *type; - bool local = true; char *var_name; unsigned int i; @@ -2669,7 +2631,7 @@ static void declare_var(struct hlsl_ctx *ctx, struct parse_variable_def *v) v->arrays.sizes[i] = size / elem_components; } } - type = hlsl_new_array_type(ctx, type, v->arrays.sizes[i]); + type = hlsl_new_array_type(ctx, type, v->arrays.sizes[i], HLSL_ARRAY_GENERIC); } } @@ -2717,11 +2679,15 @@ static void declare_var(struct hlsl_ctx *ctx, struct parse_variable_def *v) hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, "packoffset() is only allowed inside constant buffer declarations."); } + else + { + if ((type->modifiers & HLSL_MODIFIER_CONST) && !v->initializer.args_count) + hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_INITIALIZER, + "Const variable \"%s\" is missing an initializer.", var->name); + } if (ctx->cur_scope == ctx->globals) { - local = false; - if ((modifiers & HLSL_STORAGE_UNIFORM) && (modifiers & HLSL_STORAGE_STATIC)) hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER, "Variable '%s' is declared as both \"uniform\" and \"static\".", var->name); @@ -2784,16 +2750,7 @@ static void declare_var(struct hlsl_ctx *ctx, struct parse_variable_def *v) "Static variables cannot have both numeric and resource components."); } - if (!hlsl_add_var(ctx, var, local)) - { - struct hlsl_ir_var *old = hlsl_get_var(ctx->cur_scope, var->name); - - hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_REDEFINED, - "Variable \"%s\" was already declared in this scope.", var->name); - hlsl_note(ctx, &old->loc, VKD3D_SHADER_LOG_ERROR, "\"%s\" was previously declared here.", old->name); - hlsl_free_var(var); - return; - } + hlsl_add_var(ctx, var); } static struct hlsl_block *initialize_vars(struct hlsl_ctx *ctx, struct list *var_list) @@ -4120,7 +4077,7 @@ static bool intrinsic_exp(struct hlsl_ctx *ctx, return false; hlsl_block_add_instr(params->instrs, coeff); - if (!(mul = add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_MUL, coeff, params->args[0], loc))) + if (!(mul = add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_MUL, coeff, arg, loc))) return false; return !!add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_EXP2, mul, loc); @@ -5742,6 +5699,16 @@ static struct hlsl_block *add_shader_compilation(struct hlsl_ctx *ctx, const cha return NULL; } + for (unsigned int i = 0; i < args->args_count; ++i) + { + if (args->args[i]->data_type->class == HLSL_CLASS_ERROR) + { + args->instrs->value = ctx->error_instr; + free(args->args); + return args->instrs; + } + } + if (!(call_to_compile = add_user_call(ctx, decl, args, true, loc))) { free_parse_initializer(args); @@ -7001,6 +6968,7 @@ static void validate_uav_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim dim, enum hlsl_buffer_type buffer_type; enum hlsl_sampler_dim sampler_dim; enum hlsl_so_object_type so_type; + enum hlsl_array_type patch_type; struct hlsl_attribute *attr; struct parse_attribute_list attr_list; struct hlsl_ir_switch_case *switch_case; @@ -7043,6 +7011,7 @@ static void validate_uav_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim dim, %token KW_IN %token KW_INLINE %token KW_INOUT +%token KW_INPUTPATCH %token KW_LINEAR %token KW_LINESTREAM %token KW_MATRIX @@ -7051,6 +7020,7 @@ static void validate_uav_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim dim, %token KW_NOPERSPECTIVE %token KW_NULL %token KW_OUT +%token KW_OUTPUTPATCH %token KW_PACKOFFSET %token KW_PASS %token KW_PIXELSHADER @@ -7232,6 +7202,7 @@ static void validate_uav_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim dim, %type packoffset_reservation %type texture_type texture_ms_type uav_type rov_type +%type patch_type %type semantic @@ -7285,8 +7256,7 @@ name_opt: pass: KW_PASS name_opt annotations_opt '{' state_block_start state_block '}' { - if (!add_pass(ctx, $2, $3, $6, &@1)) - YYABORT; + add_pass(ctx, $2, $3, $6, &@1); } annotations_list: @@ -7337,8 +7307,7 @@ technique9: struct hlsl_scope *scope = ctx->cur_scope; hlsl_pop_scope(ctx); - if (!add_technique(ctx, $2, scope, $3, "technique", &@1)) - YYABORT; + add_technique(ctx, $2, scope, $3, "technique", &@1); } technique10: @@ -7347,8 +7316,7 @@ technique10: struct hlsl_scope *scope = ctx->cur_scope; hlsl_pop_scope(ctx); - if (!add_technique(ctx, $2, scope, $3, "technique10", &@1)) - YYABORT; + add_technique(ctx, $2, scope, $3, "technique10", &@1); } technique11: @@ -7361,8 +7329,7 @@ technique11: hlsl_error(ctx, &@1, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, "The 'technique11' keyword is invalid for this profile."); - if (!add_technique(ctx, $2, scope, $3, "technique11", &@1)) - YYABORT; + add_technique(ctx, $2, scope, $3, "technique11", &@1); } global_technique: @@ -7383,8 +7350,7 @@ effect_group: { struct hlsl_scope *scope = ctx->cur_scope; hlsl_pop_scope(ctx); - if (!(add_effect_group(ctx, $2, scope, $3, &@2))) - YYABORT; + add_effect_group(ctx, $2, scope, $3, &@2); } buffer_declaration: @@ -7853,10 +7819,9 @@ compound_statement: if (!($$ = make_empty_block(ctx))) YYABORT; } - | '{' scope_start statement_list '}' + | '{' statement_list '}' { - hlsl_pop_scope(ctx); - $$ = $3; + $$ = $2; } scope_start: @@ -8102,11 +8067,7 @@ param_list: { $$ = $1; if (!add_func_parameter(ctx, &$$, &$3, &@3)) - { - hlsl_error(ctx, &@3, VKD3D_SHADER_ERROR_HLSL_REDEFINED, - "Parameter \"%s\" is already declared.", $3.name); YYABORT; - } } parameter: @@ -8141,7 +8102,7 @@ parameter_decl: break; } - type = hlsl_new_array_type(ctx, type, $4.sizes[i]); + type = hlsl_new_array_type(ctx, type, $4.sizes[i], HLSL_ARRAY_GENERIC); } vkd3d_free($4.sizes); @@ -8284,6 +8245,16 @@ resource_format: YYABORT; } +patch_type: + KW_INPUTPATCH + { + $$ = HLSL_ARRAY_PATCH_INPUT; + } + | KW_OUTPUTPATCH + { + $$ = HLSL_ARRAY_PATCH_OUTPUT; + } + type_no_void: KW_VECTOR '<' type ',' C_INTEGER '>' { @@ -8422,6 +8393,20 @@ type_no_void: { $$ = hlsl_new_stream_output_type(ctx, $1, $3); } + | patch_type '<' type ',' C_INTEGER '>' + { + struct hlsl_type *type; + + if ($5 < 1) + { + hlsl_error(ctx, &@5, VKD3D_SHADER_ERROR_HLSL_INVALID_SIZE, + "Control point size %d is not positive.", $5); + YYABORT; + } + + type = hlsl_new_array_type(ctx, $3, $5, $1); + $$ = hlsl_type_clone(ctx, type, 0, HLSL_MODIFIER_CONST); + } | KW_RWBYTEADDRESSBUFFER { $$ = hlsl_new_uav_type(ctx, HLSL_SAMPLER_DIM_RAW_BUFFER, hlsl_get_scalar_type(ctx, HLSL_TYPE_UINT), false); @@ -9092,7 +9077,11 @@ statement_list: statement: declaration_statement | expr_statement - | compound_statement + | scope_start compound_statement + { + hlsl_pop_scope(ctx); + $$ = $2; + } | jump_statement | selection_statement | loop_statement diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c index 20a4a3eaff5..a7798bf8e9f 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c @@ -274,6 +274,14 @@ static bool types_are_semantic_equivalent(struct hlsl_ctx *ctx, const struct hls if (ctx->profile->major_version < 4) return true; + if (hlsl_type_is_patch_array(type1)) + { + return hlsl_type_is_patch_array(type2) + && type1->e.array.array_type == type2->e.array.array_type + && type1->e.array.elements_count == type2->e.array.elements_count + && types_are_semantic_equivalent(ctx, type1->e.array.type, type2->e.array.type); + } + if (type1->e.numeric.dimx != type2->e.numeric.dimx) return false; @@ -287,17 +295,24 @@ static struct hlsl_ir_var *add_semantic_var(struct hlsl_ctx *ctx, struct hlsl_ir { struct hlsl_semantic new_semantic; struct hlsl_ir_var *ext_var; + const char *prefix; char *new_name; - if (!(new_name = hlsl_sprintf_alloc(ctx, "<%s-%s%u>", output ? "output" : "input", semantic->name, index))) + if (hlsl_type_is_patch_array(type)) + prefix = type->e.array.array_type == HLSL_ARRAY_PATCH_INPUT ? "inputpatch" : "outputpatch"; + else + prefix = output ? "output" : "input"; + + if (!(new_name = hlsl_sprintf_alloc(ctx, "<%s-%s%u>", prefix, semantic->name, index))) return NULL; LIST_FOR_EACH_ENTRY(ext_var, &func->extern_vars, struct hlsl_ir_var, extern_entry) { if (!ascii_strcasecmp(ext_var->name, new_name)) { - VKD3D_ASSERT(ext_var->data_type->class <= HLSL_CLASS_VECTOR); - VKD3D_ASSERT(type->class <= HLSL_CLASS_VECTOR); + VKD3D_ASSERT(hlsl_type_is_patch_array(ext_var->data_type) + || ext_var->data_type->class <= HLSL_CLASS_VECTOR); + VKD3D_ASSERT(hlsl_type_is_patch_array(type) || type->class <= HLSL_CLASS_VECTOR); if (output) { @@ -370,7 +385,8 @@ static uint32_t combine_field_storage_modifiers(uint32_t modifiers, uint32_t fie return field_modifiers; } -static void prepend_input_copy(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *func, struct hlsl_ir_load *lhs, +static void prepend_input_copy(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *func, + struct hlsl_ir_var *top_var, uint32_t patch_index, struct hlsl_ir_load *lhs, uint32_t modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index, bool force_align) { struct hlsl_type *type = lhs->node.data_type, *vector_type_src, *vector_type_dst; @@ -404,13 +420,40 @@ static void prepend_input_copy(struct hlsl_ctx *ctx, struct hlsl_ir_function_dec struct hlsl_ir_var *input; struct hlsl_ir_load *load; - if (!(input = add_semantic_var(ctx, func, var, vector_type_src, - modifiers, semantic, semantic_index + i, false, force_align, loc))) - return; + if (hlsl_type_is_patch_array(top_var->data_type)) + { + struct hlsl_type *top_type = top_var->data_type; + struct hlsl_type *patch_type; + struct hlsl_deref patch_deref; + struct hlsl_ir_node *idx; - if (!(load = hlsl_new_var_load(ctx, input, &var->loc))) - return; - list_add_after(&lhs->node.entry, &load->node.entry); + if (!(patch_type = hlsl_new_array_type(ctx, vector_type_src, top_type->e.array.elements_count, + top_type->e.array.array_type))) + return; + + if (!(input = add_semantic_var(ctx, func, var, patch_type, + modifiers, semantic, semantic_index + i, false, force_align, loc))) + return; + hlsl_init_simple_deref_from_var(&patch_deref, input); + + if (!(idx = hlsl_new_uint_constant(ctx, patch_index, &var->loc))) + return; + list_add_after(&lhs->node.entry, &idx->entry); + + if (!(load = hlsl_new_load_index(ctx, &patch_deref, idx, loc))) + return; + list_add_after(&idx->entry, &load->node.entry); + } + else + { + if (!(input = add_semantic_var(ctx, func, var, vector_type_src, + modifiers, semantic, semantic_index + i, false, force_align, loc))) + return; + + if (!(load = hlsl_new_var_load(ctx, input, &var->loc))) + return; + list_add_after(&lhs->node.entry, &load->node.entry); + } if (!(cast = hlsl_new_cast(ctx, &load->node, vector_type_dst, &var->loc))) return; @@ -437,8 +480,8 @@ static void prepend_input_copy(struct hlsl_ctx *ctx, struct hlsl_ir_function_dec } } -static void prepend_input_copy_recurse(struct hlsl_ctx *ctx, - struct hlsl_ir_function_decl *func, struct hlsl_ir_load *lhs, uint32_t modifiers, +static void prepend_input_copy_recurse(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *func, + struct hlsl_ir_var *top_var, uint32_t patch_index, struct hlsl_ir_load *lhs, uint32_t modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index, bool force_align) { struct vkd3d_shader_location *loc = &lhs->node.loc; @@ -463,6 +506,9 @@ static void prepend_input_copy_recurse(struct hlsl_ctx *ctx, + i * hlsl_type_get_array_element_reg_size(type->e.array.type, HLSL_REGSET_NUMERIC) / 4; element_modifiers = modifiers; force_align = true; + + if (hlsl_type_is_patch_array(type)) + patch_index = i; } else { @@ -489,13 +535,13 @@ static void prepend_input_copy_recurse(struct hlsl_ctx *ctx, return; list_add_after(&c->entry, &element_load->node.entry); - prepend_input_copy_recurse(ctx, func, element_load, element_modifiers, + prepend_input_copy_recurse(ctx, func, top_var, patch_index, element_load, element_modifiers, semantic, elem_semantic_index, force_align); } } else { - prepend_input_copy(ctx, func, lhs, modifiers, semantic, semantic_index, force_align); + prepend_input_copy(ctx, func, var, patch_index, lhs, modifiers, semantic, semantic_index, force_align); } } @@ -510,7 +556,8 @@ static void prepend_input_var_copy(struct hlsl_ctx *ctx, struct hlsl_ir_function return; list_add_head(&func->body.instrs, &load->node.entry); - prepend_input_copy_recurse(ctx, func, load, var->storage_modifiers, &var->semantic, var->semantic.index, false); + prepend_input_copy_recurse(ctx, func, var, 0, load, var->storage_modifiers, &var->semantic, + var->semantic.index, false); } static void append_output_copy(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *func, @@ -2968,7 +3015,7 @@ static struct hlsl_type *clone_texture_array_as_combined_sampler_array(struct hl if (!(sampler_type = clone_texture_array_as_combined_sampler_array(ctx, type->e.array.type))) return NULL; - return hlsl_new_array_type(ctx, sampler_type, type->e.array.elements_count); + return hlsl_new_array_type(ctx, sampler_type, type->e.array.elements_count, HLSL_ARRAY_GENERIC); } return ctx->builtin_types.sampler[type->sampler_dim]; @@ -3132,7 +3179,8 @@ static bool lower_combined_samples(struct hlsl_ctx *ctx, struct hlsl_ir_node *in for (i = 0; i < load->resource.path_len; ++i) { VKD3D_ASSERT(arr_type->class == HLSL_CLASS_ARRAY); - texture_array_type = hlsl_new_array_type(ctx, texture_array_type, arr_type->e.array.elements_count); + texture_array_type = hlsl_new_array_type(ctx, texture_array_type, + arr_type->e.array.elements_count, HLSL_ARRAY_GENERIC); arr_type = arr_type->e.array.type; } @@ -5764,7 +5812,7 @@ static enum vkd3d_shader_interpolation_mode sm4_get_interpolation_mode(struct hl } static void allocate_semantic_register(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, - struct register_allocator *allocator, bool output, bool optimize, bool is_patch_constant_func) + struct register_allocator *allocator, bool output, bool optimize) { static const char *const shader_names[] = { @@ -5776,6 +5824,7 @@ static void allocate_semantic_register(struct hlsl_ctx *ctx, struct hlsl_ir_var [VKD3D_SHADER_TYPE_COMPUTE] = "Compute", }; + bool is_patch = hlsl_type_is_patch_array(var->data_type); enum vkd3d_shader_register_type type; struct vkd3d_shader_version version; bool special_interpolation = false; @@ -5815,8 +5864,8 @@ static void allocate_semantic_register(struct hlsl_ctx *ctx, struct hlsl_ir_var enum vkd3d_shader_sysval_semantic semantic; bool has_idx; - if (!sm4_sysval_semantic_from_semantic_name(&semantic, &version, ctx->semantic_compat_mapping, - ctx->domain, var->semantic.name, var->semantic.index, output, is_patch_constant_func)) + if (!sm4_sysval_semantic_from_semantic_name(&semantic, &version, ctx->semantic_compat_mapping, ctx->domain, + var->semantic.name, var->semantic.index, output, ctx->is_patch_constant_func, is_patch)) { hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SEMANTIC, "Invalid semantic '%s'.", var->semantic.name); @@ -5849,15 +5898,17 @@ static void allocate_semantic_register(struct hlsl_ctx *ctx, struct hlsl_ir_var } else { + unsigned int component_count = is_patch + ? var->data_type->e.array.type->e.numeric.dimx : var->data_type->e.numeric.dimx; int mode = (ctx->profile->major_version < 4) ? 0 : sm4_get_interpolation_mode(var->data_type, var->storage_modifiers); - unsigned int reg_size = optimize ? var->data_type->e.numeric.dimx : 4; + unsigned int reg_size = optimize ? component_count : 4; if (special_interpolation) mode = VKD3DSIM_NONE; var->regs[HLSL_REGSET_NUMERIC] = allocate_register(ctx, allocator, 1, UINT_MAX, - reg_size, var->data_type->e.numeric.dimx, mode, var->force_align, vip_allocation); + reg_size, component_count, mode, var->force_align, vip_allocation); TRACE("Allocated %s to %s (mode %d).\n", var->name, debug_register(output ? 'o' : 'v', var->regs[HLSL_REGSET_NUMERIC], var->data_type), mode); @@ -5866,10 +5917,10 @@ static void allocate_semantic_register(struct hlsl_ctx *ctx, struct hlsl_ir_var static void allocate_semantic_registers(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func) { + struct register_allocator in_patch_allocator = {0}, patch_constant_out_patch_allocator = {0}; struct register_allocator input_allocator = {0}, output_allocator = {0}; bool is_vertex_shader = ctx->profile->type == VKD3D_SHADER_TYPE_VERTEX; bool is_pixel_shader = ctx->profile->type == VKD3D_SHADER_TYPE_PIXEL; - bool is_patch_constant_func = entry_func == ctx->patch_constant_func; struct hlsl_ir_var *var; input_allocator.prioritize_smaller_writemasks = true; @@ -5878,9 +5929,25 @@ static void allocate_semantic_registers(struct hlsl_ctx *ctx, struct hlsl_ir_fun LIST_FOR_EACH_ENTRY(var, &entry_func->extern_vars, struct hlsl_ir_var, extern_entry) { if (var->is_input_semantic) - allocate_semantic_register(ctx, var, &input_allocator, false, !is_vertex_shader, is_patch_constant_func); + { + if (hlsl_type_is_patch_array(var->data_type)) + { + bool is_patch_constant_output_patch = ctx->is_patch_constant_func && + var->data_type->e.array.array_type == HLSL_ARRAY_PATCH_OUTPUT; + + if (is_patch_constant_output_patch) + allocate_semantic_register(ctx, var, &patch_constant_out_patch_allocator, false, + !is_vertex_shader); + else + allocate_semantic_register(ctx, var, &in_patch_allocator, false, + !is_vertex_shader); + } + else + allocate_semantic_register(ctx, var, &input_allocator, false, !is_vertex_shader); + } + if (var->is_output_semantic) - allocate_semantic_register(ctx, var, &output_allocator, true, !is_pixel_shader, is_patch_constant_func); + allocate_semantic_register(ctx, var, &output_allocator, true, !is_pixel_shader); } vkd3d_free(input_allocator.allocations); @@ -6430,6 +6497,9 @@ bool hlsl_offset_from_deref(struct hlsl_ctx *ctx, const struct hlsl_deref *deref *offset = deref->const_offset; + if (hlsl_type_is_patch_array(deref->var->data_type)) + return false; + if (offset_node) { /* We should always have generated a cast to UINT. */ @@ -6809,6 +6879,77 @@ static void validate_hull_shader_attributes(struct hlsl_ctx *ctx, const struct h } } +static void validate_and_record_patch_type(struct hlsl_ctx *ctx, struct hlsl_ir_var *var) +{ + unsigned int control_point_count = var->data_type->e.array.elements_count; + enum hlsl_array_type array_type = var->data_type->e.array.array_type; + struct hlsl_type *control_point_type = var->data_type->e.array.type; + const struct hlsl_profile_info *profile = ctx->profile; + + if (array_type == HLSL_ARRAY_PATCH_INPUT) + { + if (profile->type != VKD3D_SHADER_TYPE_HULL + && !(profile->type == VKD3D_SHADER_TYPE_GEOMETRY && hlsl_version_ge(ctx, 5, 0))) + { + hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE, + "InputPatch parameters can only be used in hull shaders, " + "and geometry shaders with shader model 5.0 or higher."); + return; + } + } + else + { + if (!ctx->is_patch_constant_func && profile->type != VKD3D_SHADER_TYPE_DOMAIN) + { + hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE, + "OutputPatch parameters can only be used in " + "hull shader patch constant functions and domain shaders."); + return; + } + } + + if (control_point_count > 32) + { + hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_CONTROL_POINT_COUNT, + "Control point count %u exceeds 32.", control_point_count); + return; + } + VKD3D_ASSERT(control_point_count > 0); + + if (ctx->is_patch_constant_func && array_type == HLSL_ARRAY_PATCH_OUTPUT) + { + if (control_point_count != ctx->output_control_point_count) + hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_CONTROL_POINT_COUNT, + "Output control point count %u does not match the count %u specified in the control point function.", + control_point_count, ctx->output_control_point_count); + + if (!hlsl_types_are_equal(control_point_type, ctx->output_control_point_type)) + hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "Output control point type does not match the output type of the control point function."); + + return; + } + + if (ctx->input_control_point_count != UINT_MAX) + { + VKD3D_ASSERT(ctx->is_patch_constant_func); + + if (control_point_count != ctx->input_control_point_count) + hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_CONTROL_POINT_COUNT, + "Input control point count %u does not match the count %u specified in the control point function.", + control_point_count, ctx->input_control_point_count); + + if (!hlsl_types_are_equal(control_point_type, ctx->input_control_point_type)) + hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "Input control point type does not match the input type specified in the control point function."); + + return; + } + + ctx->input_control_point_count = control_point_count; + ctx->input_control_point_type = control_point_type; +} + static void remove_unreachable_code(struct hlsl_ctx *ctx, struct hlsl_block *body) { struct hlsl_ir_node *instr, *next; @@ -6910,10 +7051,11 @@ void hlsl_run_const_passes(struct hlsl_ctx *ctx, struct hlsl_block *body) } static void generate_vsir_signature_entry(struct hlsl_ctx *ctx, struct vsir_program *program, - struct shader_signature *signature, bool output, bool is_patch_constant_func, struct hlsl_ir_var *var) + struct shader_signature *signature, bool output, struct hlsl_ir_var *var) { enum vkd3d_shader_component_type component_type = VKD3D_SHADER_COMPONENT_VOID; enum vkd3d_shader_sysval_semantic sysval = VKD3D_SHADER_SV_NONE; + bool is_patch = hlsl_type_is_patch_array(var->data_type); unsigned int register_index, mask, use_mask; const char *name = var->semantic.name; enum vkd3d_shader_register_type type; @@ -6922,10 +7064,11 @@ static void generate_vsir_signature_entry(struct hlsl_ctx *ctx, struct vsir_prog if (hlsl_version_ge(ctx, 4, 0)) { struct vkd3d_string_buffer *string; + enum hlsl_base_type numeric_type; bool has_idx, ret; ret = sm4_sysval_semantic_from_semantic_name(&sysval, &program->shader_version, ctx->semantic_compat_mapping, - ctx->domain, var->semantic.name, var->semantic.index, output, is_patch_constant_func); + ctx->domain, var->semantic.name, var->semantic.index, output, ctx->is_patch_constant_func, is_patch); VKD3D_ASSERT(ret); if (sysval == ~0u) return; @@ -6944,7 +7087,12 @@ static void generate_vsir_signature_entry(struct hlsl_ctx *ctx, struct vsir_prog use_mask = mask; /* FIXME: retrieve use mask accurately. */ - switch (var->data_type->e.numeric.type) + if (var->data_type->class == HLSL_CLASS_ARRAY) + numeric_type = var->data_type->e.array.type->e.numeric.type; + else + numeric_type = var->data_type->e.numeric.type; + + switch (numeric_type) { case HLSL_TYPE_FLOAT: case HLSL_TYPE_HALF: @@ -7051,26 +7199,40 @@ static void generate_vsir_signature(struct hlsl_ctx *ctx, struct vsir_program *program, struct hlsl_ir_function_decl *func) { bool is_domain = program->shader_version.type == VKD3D_SHADER_TYPE_DOMAIN; - bool is_patch_constant_func = func == ctx->patch_constant_func; struct hlsl_ir_var *var; + ctx->is_patch_constant_func = func == ctx->patch_constant_func; + LIST_FOR_EACH_ENTRY(var, &func->extern_vars, struct hlsl_ir_var, extern_entry) { if (var->is_input_semantic) { - if (is_patch_constant_func) - generate_vsir_signature_entry(ctx, program, &program->patch_constant_signature, false, true, var); + bool is_patch = hlsl_type_is_patch_array(var->data_type); + + if (ctx->is_patch_constant_func) + { + if (!is_patch) + generate_vsir_signature_entry(ctx, program, &program->patch_constant_signature, false, var); + } else if (is_domain) - generate_vsir_signature_entry(ctx, program, &program->patch_constant_signature, false, false, var); + { + if (is_patch) + generate_vsir_signature_entry(ctx, program, &program->input_signature, false, var); + else + generate_vsir_signature_entry(ctx, program, &program->patch_constant_signature, false, var); + } else - generate_vsir_signature_entry(ctx, program, &program->input_signature, false, false, var); + { + generate_vsir_signature_entry(ctx, program, &program->input_signature, false, var); + } } + if (var->is_output_semantic) { - if (is_patch_constant_func) - generate_vsir_signature_entry(ctx, program, &program->patch_constant_signature, true, true, var); + if (ctx->is_patch_constant_func) + generate_vsir_signature_entry(ctx, program, &program->patch_constant_signature, true, var); else - generate_vsir_signature_entry(ctx, program, &program->output_signature, true, false, var); + generate_vsir_signature_entry(ctx, program, &program->output_signature, true, var); } } } @@ -7246,6 +7408,39 @@ static void sm1_generate_vsir_sampler_dcls(struct hlsl_ctx *ctx, } } +static enum vkd3d_shader_register_type sm4_get_semantic_register_type(enum vkd3d_shader_type shader_type, + bool is_patch_constant_func, const struct hlsl_ir_var *var) +{ + if (hlsl_type_is_patch_array(var->data_type)) + { + VKD3D_ASSERT(var->is_input_semantic); + + switch (shader_type) + { + case VKD3D_SHADER_TYPE_HULL: + if (is_patch_constant_func) + { + bool is_inputpatch = var->data_type->e.array.array_type == HLSL_ARRAY_PATCH_INPUT; + + return is_inputpatch ? VKD3DSPR_INCONTROLPOINT : VKD3DSPR_OUTCONTROLPOINT; + } + return VKD3DSPR_INPUT; + + case VKD3D_SHADER_TYPE_DOMAIN: + return VKD3DSPR_INCONTROLPOINT; + + default: + return VKD3DSPR_INPUT; + } + } + + if (var->is_output_semantic) + return VKD3DSPR_OUTPUT; + if (shader_type == VKD3D_SHADER_TYPE_DOMAIN) + return VKD3DSPR_PATCHCONST; + return VKD3DSPR_INPUT; +} + static struct vkd3d_shader_instruction *generate_vsir_add_program_instruction( struct hlsl_ctx *ctx, struct vsir_program *program, const struct vkd3d_shader_location *loc, enum vkd3d_shader_opcode opcode, @@ -7313,6 +7508,22 @@ static void vsir_src_from_hlsl_node(struct vkd3d_shader_src_param *src, } } +static struct vkd3d_shader_src_param *sm4_generate_vsir_new_idx_src(struct hlsl_ctx *ctx, + struct vsir_program *program, const struct hlsl_ir_node *rel_offset) +{ + struct vkd3d_shader_src_param *idx_src; + + if (!(idx_src = vsir_program_get_src_params(program, 1))) + { + ctx->result = VKD3D_ERROR_OUT_OF_MEMORY; + return NULL; + } + + memset(idx_src, 0, sizeof(*idx_src)); + vsir_src_from_hlsl_node(idx_src, ctx, rel_offset, VKD3DSP_WRITEMASK_ALL); + return idx_src; +} + static bool sm4_generate_vsir_numeric_reg_from_deref(struct hlsl_ctx *ctx, struct vsir_program *program, struct vkd3d_shader_register *reg, uint32_t *writemask, const struct hlsl_deref *deref) { @@ -7339,17 +7550,8 @@ static bool sm4_generate_vsir_numeric_reg_from_deref(struct hlsl_ctx *ctx, struc if (deref->rel_offset.node) { - struct vkd3d_shader_src_param *idx_src; - - if (!(idx_src = vsir_program_get_src_params(program, 1))) - { - ctx->result = VKD3D_ERROR_OUT_OF_MEMORY; + if (!(reg->idx[1].rel_addr = sm4_generate_vsir_new_idx_src(ctx, program, deref->rel_offset.node))) return false; - } - memset(idx_src, 0, sizeof(*idx_src)); - reg->idx[1].rel_addr = idx_src; - - vsir_src_from_hlsl_node(idx_src, ctx, deref->rel_offset.node, VKD3DSP_WRITEMASK_ALL); } } @@ -7452,12 +7654,15 @@ static bool sm4_generate_vsir_reg_from_deref(struct hlsl_ctx *ctx, struct vsir_p } else if (var->is_input_semantic) { + bool is_patch = hlsl_type_is_patch_array(var->data_type); bool has_idx; if (sm4_register_from_semantic_name(version, var->semantic.name, false, ®->type, &has_idx)) { unsigned int offset = hlsl_offset_from_deref_safe(ctx, deref); + VKD3D_ASSERT(!is_patch); + if (has_idx) { reg->idx[0].offset = var->semantic.index + offset / 4; @@ -7476,15 +7681,22 @@ static bool sm4_generate_vsir_reg_from_deref(struct hlsl_ctx *ctx, struct vsir_p VKD3D_ASSERT(hlsl_reg.allocated); - if (version->type == VKD3D_SHADER_TYPE_DOMAIN) - reg->type = VKD3DSPR_PATCHCONST; - else - reg->type = VKD3DSPR_INPUT; + reg->type = sm4_get_semantic_register_type(version->type, ctx->is_patch_constant_func, var); reg->dimension = VSIR_DIMENSION_VEC4; - reg->idx[0].offset = hlsl_reg.id; - reg->idx_count = 1; + reg->idx[is_patch ? 1 : 0].offset = hlsl_reg.id; + reg->idx_count = is_patch ? 2 : 1; *writemask = hlsl_reg.writemask; } + + if (is_patch) + { + reg->idx[0].offset = deref->const_offset / 4; + if (deref->rel_offset.node) + { + if (!(reg->idx[0].rel_addr = sm4_generate_vsir_new_idx_src(ctx, program, deref->rel_offset.node))) + return false; + } + } } else if (var->is_output_semantic) { @@ -8757,10 +8969,10 @@ static void sm1_generate_ctab(struct hlsl_ctx *ctx, struct vkd3d_shader_code *ct } static void sm4_generate_vsir_instr_dcl_semantic(struct hlsl_ctx *ctx, struct vsir_program *program, - const struct hlsl_ir_var *var, bool is_patch_constant_func, struct hlsl_block *block, - const struct vkd3d_shader_location *loc) + const struct hlsl_ir_var *var, struct hlsl_block *block, const struct vkd3d_shader_location *loc) { const struct vkd3d_shader_version *version = &program->shader_version; + const bool is_patch = hlsl_type_is_patch_array(var->data_type); const bool output = var->is_output_semantic; enum vkd3d_shader_sysval_semantic semantic; struct vkd3d_shader_dst_param *dst_param; @@ -8771,8 +8983,8 @@ static void sm4_generate_vsir_instr_dcl_semantic(struct hlsl_ctx *ctx, struct vs uint32_t write_mask; bool has_idx; - sm4_sysval_semantic_from_semantic_name(&semantic, version, ctx->semantic_compat_mapping, - ctx->domain, var->semantic.name, var->semantic.index, output, is_patch_constant_func); + sm4_sysval_semantic_from_semantic_name(&semantic, version, ctx->semantic_compat_mapping, ctx->domain, + var->semantic.name, var->semantic.index, output, ctx->is_patch_constant_func, is_patch); if (semantic == ~0u) semantic = VKD3D_SHADER_SV_NONE; @@ -8795,14 +9007,19 @@ static void sm4_generate_vsir_instr_dcl_semantic(struct hlsl_ctx *ctx, struct vs break; default: - opcode = (version->type == VKD3D_SHADER_TYPE_PIXEL) - ? VKD3DSIH_DCL_INPUT_PS_SIV : VKD3DSIH_DCL_INPUT_SIV; + if (version->type == VKD3D_SHADER_TYPE_PIXEL) + opcode = VKD3DSIH_DCL_INPUT_PS_SIV; + else if (is_patch) + opcode = VKD3DSIH_DCL_INPUT; + else + opcode = VKD3DSIH_DCL_INPUT_SIV; break; } } else { - if (semantic == VKD3D_SHADER_SV_NONE || version->type == VKD3D_SHADER_TYPE_PIXEL) + if (semantic == VKD3D_SHADER_SV_NONE || version->type == VKD3D_SHADER_TYPE_PIXEL + || version->type == VKD3D_SHADER_TYPE_HULL) opcode = VKD3DSIH_DCL_OUTPUT; else opcode = VKD3DSIH_DCL_OUTPUT_SIV; @@ -8816,13 +9033,7 @@ static void sm4_generate_vsir_instr_dcl_semantic(struct hlsl_ctx *ctx, struct vs } else { - if (output) - type = VKD3DSPR_OUTPUT; - else if (version->type == VKD3D_SHADER_TYPE_DOMAIN) - type = VKD3DSPR_PATCHCONST; - else - type = VKD3DSPR_INPUT; - + type = sm4_get_semantic_register_type(version->type, ctx->is_patch_constant_func, var); has_idx = true; idx = var->regs[HLSL_REGSET_NUMERIC].id; write_mask = var->regs[HLSL_REGSET_NUMERIC].writemask; @@ -8833,13 +9044,13 @@ static void sm4_generate_vsir_instr_dcl_semantic(struct hlsl_ctx *ctx, struct vs if (opcode == VKD3DSIH_DCL_OUTPUT) { - VKD3D_ASSERT(semantic == VKD3D_SHADER_SV_NONE - || semantic == VKD3D_SHADER_SV_TARGET || type != VKD3DSPR_OUTPUT); + VKD3D_ASSERT(semantic == VKD3D_SHADER_SV_NONE || semantic == VKD3D_SHADER_SV_TARGET + || version->type == VKD3D_SHADER_TYPE_HULL || type != VKD3DSPR_OUTPUT); dst_param = &ins->declaration.dst; } else if (opcode == VKD3DSIH_DCL_INPUT || opcode == VKD3DSIH_DCL_INPUT_PS) { - VKD3D_ASSERT(semantic == VKD3D_SHADER_SV_NONE); + VKD3D_ASSERT(semantic == VKD3D_SHADER_SV_NONE || is_patch); dst_param = &ins->declaration.dst; } else @@ -8850,7 +9061,14 @@ static void sm4_generate_vsir_instr_dcl_semantic(struct hlsl_ctx *ctx, struct vs dst_param = &ins->declaration.register_semantic.reg; } - if (has_idx) + if (is_patch) + { + VKD3D_ASSERT(has_idx); + vsir_register_init(&dst_param->reg, type, VKD3D_DATA_FLOAT, 2); + dst_param->reg.idx[0].offset = var->data_type->e.array.elements_count; + dst_param->reg.idx[1].offset = idx; + } + else if (has_idx) { vsir_register_init(&dst_param->reg, type, VKD3D_DATA_FLOAT, 1); dst_param->reg.idx[0].offset = idx; @@ -10344,12 +10562,13 @@ static void sm4_generate_vsir_block(struct hlsl_ctx *ctx, struct hlsl_block *blo static void sm4_generate_vsir_add_function(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *func, uint64_t config_flags, struct vsir_program *program) { - bool is_patch_constant_func = func == ctx->patch_constant_func; struct hlsl_block block = {0}; struct hlsl_scope *scope; struct hlsl_ir_var *var; uint32_t temp_count; + ctx->is_patch_constant_func = func == ctx->patch_constant_func; + compute_liveness(ctx, func); mark_indexable_vars(ctx, func); temp_count = allocate_temp_registers(ctx, func); @@ -10363,7 +10582,7 @@ static void sm4_generate_vsir_add_function(struct hlsl_ctx *ctx, { if ((var->is_input_semantic && var->last_read) || (var->is_output_semantic && var->first_write)) - sm4_generate_vsir_instr_dcl_semantic(ctx, program, var, is_patch_constant_func, &block, &var->loc); + sm4_generate_vsir_instr_dcl_semantic(ctx, program, var, &block, &var->loc); } if (temp_count) @@ -10916,7 +11135,8 @@ static void sm4_generate_vsir(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl } else if (version.type == VKD3D_SHADER_TYPE_HULL) { - program->input_control_point_count = 1; /* TODO: Obtain from InputPatch */ + program->input_control_point_count = ctx->input_control_point_count == UINT_MAX + ? 1 : ctx->input_control_point_count; program->output_control_point_count = ctx->output_control_point_count; program->tess_domain = ctx->domain; program->tess_partitioning = ctx->partitioning; @@ -10924,7 +11144,8 @@ static void sm4_generate_vsir(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl } else if (version.type == VKD3D_SHADER_TYPE_DOMAIN) { - program->input_control_point_count = 0; /* TODO: Obtain from OutputPatch */ + program->input_control_point_count = ctx->input_control_point_count == UINT_MAX + ? 0 : ctx->input_control_point_count; program->tess_domain = ctx->domain; } @@ -12133,6 +12354,7 @@ static bool lower_isinf(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, struct static void process_entry_function(struct hlsl_ctx *ctx, const struct hlsl_block *global_uniform_block, struct hlsl_ir_function_decl *entry_func) { + const struct hlsl_ir_var *input_patch = NULL, *output_patch = NULL; const struct hlsl_profile_info *profile = ctx->profile; struct hlsl_block static_initializers, global_uniforms; struct hlsl_block *const body = &entry_func->body; @@ -12140,6 +12362,8 @@ static void process_entry_function(struct hlsl_ctx *ctx, struct hlsl_ir_var *var; unsigned int i; + ctx->is_patch_constant_func = entry_func == ctx->patch_constant_func; + if (!hlsl_clone_block(ctx, &static_initializers, &ctx->static_initializers)) return; list_move_head(&body->instrs, &static_initializers.instrs); @@ -12183,12 +12407,48 @@ static void process_entry_function(struct hlsl_ctx *ctx, } else if ((var->storage_modifiers & HLSL_STORAGE_UNIFORM)) { - if (ctx->profile->type == VKD3D_SHADER_TYPE_HULL && entry_func == ctx->patch_constant_func) + if (ctx->profile->type == VKD3D_SHADER_TYPE_HULL && ctx->is_patch_constant_func) hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER, "Patch constant function parameter \"%s\" cannot be uniform.", var->name); else prepend_uniform_copy(ctx, body, var); } + else if (hlsl_type_is_patch_array(var->data_type)) + { + if (var->data_type->e.array.array_type == HLSL_ARRAY_PATCH_INPUT) + { + if (input_patch) + { + hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_DUPLICATE_PATCH, + "Found multiple InputPatch parameters."); + hlsl_note(ctx, &input_patch->loc, VKD3D_SHADER_LOG_ERROR, + "The InputPatch parameter was previously declared here."); + continue; + } + input_patch = var; + } + else + { + if (output_patch) + { + hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_DUPLICATE_PATCH, + "Found multiple OutputPatch parameters."); + hlsl_note(ctx, &output_patch->loc, VKD3D_SHADER_LOG_ERROR, + "The OutputPatch parameter was previously declared here."); + continue; + } + output_patch = var; + } + + validate_and_record_patch_type(ctx, var); + if (profile->type == VKD3D_SHADER_TYPE_GEOMETRY) + { + hlsl_fixme(ctx, &var->loc, "InputPatch/OutputPatch parameters in geometry shaders."); + continue; + } + + prepend_input_var_copy(ctx, entry_func, var); + } else { if (hlsl_get_multiarray_element_type(var->data_type)->class != HLSL_CLASS_STRUCT @@ -12202,7 +12462,13 @@ static void process_entry_function(struct hlsl_ctx *ctx, if (var->storage_modifiers & HLSL_STORAGE_IN) prepend_input_var_copy(ctx, entry_func, var); if (var->storage_modifiers & HLSL_STORAGE_OUT) - append_output_var_copy(ctx, entry_func, var); + { + if (profile->type == VKD3D_SHADER_TYPE_HULL && !ctx->is_patch_constant_func) + hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER, + "Output parameters are not supported in hull shader control point functions."); + else + append_output_var_copy(ctx, entry_func, var); + } } } if (entry_func->return_var) @@ -12212,6 +12478,14 @@ static void process_entry_function(struct hlsl_ctx *ctx, "Entry point \"%s\" is missing a return value semantic.", entry_func->func->name); append_output_var_copy(ctx, entry_func, entry_func->return_var); + + if (profile->type == VKD3D_SHADER_TYPE_HULL && !ctx->is_patch_constant_func) + ctx->output_control_point_type = entry_func->return_var->data_type; + } + else + { + if (profile->type == VKD3D_SHADER_TYPE_HULL && !ctx->is_patch_constant_func) + hlsl_fixme(ctx, &entry_func->loc, "Passthrough hull shader control point function."); } if (hlsl_version_ge(ctx, 4, 0)) diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c index 1ecfe32de45..82302aac666 100644 --- a/libs/vkd3d/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c @@ -3070,7 +3070,7 @@ static bool get_insidetessfactor_sysval_semantic(enum vkd3d_shader_sysval_semant bool sm4_sysval_semantic_from_semantic_name(enum vkd3d_shader_sysval_semantic *sysval_semantic, const struct vkd3d_shader_version *version, bool semantic_compat_mapping, enum vkd3d_tessellator_domain domain, - const char *semantic_name, unsigned int semantic_idx, bool output, bool is_patch_constant_func) + const char *semantic_name, unsigned int semantic_idx, bool output, bool is_patch_constant_func, bool is_patch) { unsigned int i; @@ -3131,7 +3131,21 @@ bool sm4_sysval_semantic_from_semantic_name(enum vkd3d_shader_sysval_semantic *s {"sv_rendertargetarrayindex", true, VKD3D_SHADER_TYPE_VERTEX, VKD3D_SHADER_SV_RENDER_TARGET_ARRAY_INDEX}, {"sv_viewportarrayindex", true, VKD3D_SHADER_TYPE_VERTEX, VKD3D_SHADER_SV_VIEWPORT_ARRAY_INDEX}, }; - bool needs_compat_mapping = ascii_strncasecmp(semantic_name, "sv_", 3); + bool has_sv_prefix = !ascii_strncasecmp(semantic_name, "sv_", 3); + + if (is_patch) + { + VKD3D_ASSERT(!output); + + if (!ascii_strcasecmp(semantic_name, "sv_position") + || (semantic_compat_mapping && !ascii_strcasecmp(semantic_name, "position"))) + *sysval_semantic = VKD3D_SHADER_SV_POSITION; + else if (has_sv_prefix) + return false; + else + *sysval_semantic = VKD3D_SHADER_SV_NONE; + return true; + } if (is_patch_constant_func) { @@ -3173,7 +3187,7 @@ bool sm4_sysval_semantic_from_semantic_name(enum vkd3d_shader_sysval_semantic *s { if (!ascii_strcasecmp(semantic_name, semantics[i].name) && output == semantics[i].output - && (semantic_compat_mapping == needs_compat_mapping || !needs_compat_mapping) + && (semantic_compat_mapping || has_sv_prefix) && version->type == semantics[i].shader_type) { *sysval_semantic = semantics[i].semantic; @@ -3181,7 +3195,7 @@ bool sm4_sysval_semantic_from_semantic_name(enum vkd3d_shader_sysval_semantic *s } } - if (!needs_compat_mapping) + if (has_sv_prefix) return false; *sysval_semantic = VKD3D_SHADER_SV_NONE; diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h index 7e8ec156aad..03643acff3c 100644 --- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h @@ -166,6 +166,7 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_HLSL_INVALID_PARTITIONING = 5038, VKD3D_SHADER_ERROR_HLSL_MISPLACED_SAMPLER_STATE = 5039, VKD3D_SHADER_ERROR_HLSL_AMBIGUOUS_CALL = 5040, + VKD3D_SHADER_ERROR_HLSL_DUPLICATE_PATCH = 5041, VKD3D_SHADER_WARNING_HLSL_IMPLICIT_TRUNCATION = 5300, VKD3D_SHADER_WARNING_HLSL_DIVISION_BY_ZERO = 5301, @@ -1641,7 +1642,7 @@ bool sm4_register_from_semantic_name(const struct vkd3d_shader_version *version, bool shader_sm4_is_scalar_register(const struct vkd3d_shader_register *reg); bool sm4_sysval_semantic_from_semantic_name(enum vkd3d_shader_sysval_semantic *sysval_semantic, const struct vkd3d_shader_version *version, bool semantic_compat_mapping, enum vkd3d_tessellator_domain domain, - const char *semantic_name, unsigned int semantic_idx, bool output, bool is_patch_constant_func); + const char *semantic_name, unsigned int semantic_idx, bool output, bool is_patch_constant_func, bool is_patch); int d3dbc_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t config_flags, struct vkd3d_shader_message_context *message_context, struct vsir_program *program); -- 2.47.2