mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2025-04-13 05:43:18 -07:00
vkd3d-shader/hlsl: Validate stream output object declarations.
Valid stream output objects must be single-element containing a PointStream/LineStream/TriangleStream object. Moreover, stream output objects cannot be declared globally.
This commit is contained in:
Notes:
Henri Verbeet
2025-03-12 22:20:50 +01:00
Approved-by: Elizabeth Figura (@zfigura) Approved-by: Henri Verbeet (@hverbeet) Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1405
@@ -234,6 +234,33 @@ unsigned int hlsl_get_multiarray_size(const struct hlsl_type *type)
|
||||
return 1;
|
||||
}
|
||||
|
||||
const struct hlsl_type *hlsl_get_stream_output_type(const struct hlsl_type *type)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
switch (type->class)
|
||||
{
|
||||
case HLSL_CLASS_ARRAY:
|
||||
return hlsl_get_stream_output_type(type->e.array.type);
|
||||
|
||||
case HLSL_CLASS_STRUCT:
|
||||
for (i = 0; i < type->e.record.field_count; ++i)
|
||||
{
|
||||
const struct hlsl_type *field_type = hlsl_get_stream_output_type(type->e.record.fields[i].type);
|
||||
|
||||
if (field_type)
|
||||
return field_type;
|
||||
}
|
||||
return NULL;
|
||||
|
||||
case HLSL_CLASS_STREAM_OUTPUT:
|
||||
return type;
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool hlsl_type_is_resource(const struct hlsl_type *type)
|
||||
{
|
||||
switch (type->class)
|
||||
@@ -1138,6 +1165,7 @@ unsigned int hlsl_type_component_count(const struct hlsl_type *type)
|
||||
case HLSL_CLASS_HULL_SHADER:
|
||||
case HLSL_CLASS_GEOMETRY_SHADER:
|
||||
case HLSL_CLASS_BLEND_STATE:
|
||||
case HLSL_CLASS_STREAM_OUTPUT:
|
||||
case HLSL_CLASS_NULL:
|
||||
return 1;
|
||||
|
||||
@@ -1145,7 +1173,6 @@ unsigned int hlsl_type_component_count(const struct hlsl_type *type)
|
||||
case HLSL_CLASS_PASS:
|
||||
case HLSL_CLASS_TECHNIQUE:
|
||||
case HLSL_CLASS_VOID:
|
||||
case HLSL_CLASS_STREAM_OUTPUT:
|
||||
break;
|
||||
}
|
||||
|
||||
|
@@ -1751,6 +1751,8 @@ void hlsl_calculate_buffer_offsets(struct hlsl_ctx *ctx);
|
||||
const struct hlsl_type *hlsl_get_multiarray_element_type(const struct hlsl_type *type);
|
||||
unsigned int hlsl_get_multiarray_size(const struct hlsl_type *type);
|
||||
|
||||
const struct hlsl_type *hlsl_get_stream_output_type(const struct hlsl_type *type);
|
||||
|
||||
uint32_t hlsl_combine_swizzles(uint32_t first, uint32_t second, unsigned int dim);
|
||||
unsigned int hlsl_combine_writemasks(unsigned int first, unsigned int second);
|
||||
uint32_t hlsl_map_swizzle(uint32_t swizzle, unsigned int writemask);
|
||||
|
@@ -1196,6 +1196,14 @@ static bool add_typedef(struct hlsl_ctx *ctx, struct hlsl_type *const orig_type,
|
||||
return true;
|
||||
}
|
||||
|
||||
static void check_invalid_stream_output_object(struct hlsl_ctx *ctx, const struct hlsl_type *type,
|
||||
const char *name, const struct vkd3d_shader_location* loc)
|
||||
{
|
||||
if (hlsl_type_component_count(type) != 1)
|
||||
hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
|
||||
"Stream output object '%s' is not single-element.", name);
|
||||
}
|
||||
|
||||
static void initialize_var_components(struct hlsl_ctx *ctx, struct hlsl_block *instrs,
|
||||
struct hlsl_ir_var *dst, unsigned int *store_index, struct hlsl_ir_node *src,
|
||||
bool is_default_values_initializer);
|
||||
@@ -1230,6 +1238,9 @@ static bool add_func_parameter(struct hlsl_ctx *ctx, struct hlsl_func_parameters
|
||||
hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER,
|
||||
"Output parameter '%s' has a default value.", param->name);
|
||||
|
||||
if (hlsl_get_stream_output_type(param->type))
|
||||
check_invalid_stream_output_object(ctx, param->type, param->name, loc);
|
||||
|
||||
if (!(var = hlsl_new_var(ctx, param->name, param->type, loc, ¶m->semantic, param->modifiers,
|
||||
¶m->reg_reservation)))
|
||||
return false;
|
||||
@@ -2438,6 +2449,7 @@ 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 stream_output;
|
||||
char *var_name;
|
||||
unsigned int i;
|
||||
|
||||
@@ -2529,6 +2541,10 @@ static void declare_var(struct hlsl_ctx *ctx, struct parse_variable_def *v)
|
||||
hlsl_fixme(ctx, &v->loc, "Shader model 5.1+ resource array.");
|
||||
}
|
||||
|
||||
stream_output = !!hlsl_get_stream_output_type(type);
|
||||
if (stream_output)
|
||||
check_invalid_stream_output_object(ctx, type, v->name, &v->loc);
|
||||
|
||||
if (!(var_name = vkd3d_strdup(v->name)))
|
||||
return;
|
||||
|
||||
@@ -2583,6 +2599,10 @@ static void declare_var(struct hlsl_ctx *ctx, struct parse_variable_def *v)
|
||||
if (!(modifiers & HLSL_STORAGE_STATIC))
|
||||
var->storage_modifiers |= HLSL_STORAGE_UNIFORM;
|
||||
|
||||
if (stream_output)
|
||||
hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_MISPLACED_STREAM_OUTPUT,
|
||||
"Stream output object '%s' is not allowed in the global scope.", var->name);
|
||||
|
||||
if ((ctx->profile->major_version < 5 || ctx->profile->type == VKD3D_SHADER_TYPE_EFFECT)
|
||||
&& (var->storage_modifiers & HLSL_STORAGE_UNIFORM))
|
||||
{
|
||||
|
@@ -171,6 +171,7 @@ enum vkd3d_shader_error
|
||||
VKD3D_SHADER_ERROR_HLSL_DUPLICATE_PATCH = 5041,
|
||||
VKD3D_SHADER_ERROR_HLSL_INVALID_MAX_VERTEX_COUNT = 5042,
|
||||
VKD3D_SHADER_ERROR_HLSL_MISSING_PRIMITIVE_TYPE = 5043,
|
||||
VKD3D_SHADER_ERROR_HLSL_MISPLACED_STREAM_OUTPUT = 5044,
|
||||
|
||||
VKD3D_SHADER_WARNING_HLSL_IMPLICIT_TRUNCATION = 5300,
|
||||
VKD3D_SHADER_WARNING_HLSL_DIVISION_BY_ZERO = 5301,
|
||||
|
Reference in New Issue
Block a user