Files
wine-staging/patches/vkd3d-latest/0004-Updated-vkd3d-to-2f77d56b7748f89ae85fd08bba956fbb603.patch
Alistair Leslie-Hughes 2b9cd3663b Updated vkd3d-latest patchset
2025-02-18 09:01:06 +11:00

1525 lines
66 KiB
Diff

From 0b997e16483a911049de4382f993a9c267c568b5 Mon Sep 17 00:00:00 2001
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
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, "<anonymous struct>");
@@ -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(&param->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 **)&parameters->vars, &parameters->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 <reg_reservation> packoffset_reservation
%type <sampler_dim> texture_type texture_ms_type uav_type rov_type
+%type <patch_type> patch_type
%type <semantic> 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, &reg->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