diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index 48d9d4e0..d15532f4 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -297,6 +297,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 +897,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 +909,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 +1180,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 +1260,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 +2843,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, ""); diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index cf15ac1e..53560a89 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/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. */ @@ -1527,7 +1535,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 +1668,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-shader/hlsl.l b/libs/vkd3d-shader/hlsl.l index 31fb3052..605a9aba 100644 --- a/libs/vkd3d-shader/hlsl.l +++ b/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-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 9d14d051..85c11782 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/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; @@ -2669,7 +2669,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); } } @@ -7007,6 +7007,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; @@ -7049,6 +7050,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 @@ -7057,6 +7059,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 @@ -7238,6 +7241,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 @@ -8147,7 +8151,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); @@ -8290,6 +8294,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 '>' { @@ -8428,6 +8442,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); diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 0c75f6a1..4b744bf8 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -2968,7 +2968,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 +3132,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; } @@ -12189,6 +12190,10 @@ static void process_entry_function(struct hlsl_ctx *ctx, else prepend_uniform_copy(ctx, body, var); } + else if (hlsl_type_is_patch_array(var->data_type)) + { + hlsl_fixme(ctx, &var->loc, "InputPatch/OutputPatch function parameters."); + } else { if (hlsl_get_multiarray_element_type(var->data_type)->class != HLSL_CLASS_STRUCT