mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2025-09-12 18:50:22 -07:00
vkd3d-shader/hlsl: Validate and record stream output objects.
Validation should only be done for stream outputs that are used.
This commit is contained in:
Notes:
Henri Verbeet
2025-04-23 18:18:33 +02:00
Approved-by: Elizabeth Figura (@zfigura) Approved-by: Henri Verbeet (@hverbeet) Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1458
@@ -4859,6 +4859,7 @@ static bool hlsl_ctx_init(struct hlsl_ctx *ctx, const struct vkd3d_shader_compil
|
||||
ctx->input_control_point_count = UINT_MAX;
|
||||
ctx->max_vertex_count = 0;
|
||||
ctx->input_primitive_type = VKD3D_PT_UNDEFINED;
|
||||
ctx->output_topology_type = VKD3D_PT_UNDEFINED;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@@ -1213,6 +1213,8 @@ struct hlsl_ctx
|
||||
unsigned int max_vertex_count;
|
||||
/* The input primitive type of a geometry shader. */
|
||||
enum vkd3d_primitive_type input_primitive_type;
|
||||
/* The output topology type of a geometry shader. */
|
||||
enum vkd3d_primitive_type output_topology_type;
|
||||
|
||||
/* 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
|
||||
|
@@ -7583,6 +7583,64 @@ static void validate_and_record_prim_type(struct hlsl_ctx *ctx, struct hlsl_ir_v
|
||||
ctx->input_primitive_param = var;
|
||||
}
|
||||
|
||||
static void validate_and_record_stream_outputs(struct hlsl_ctx *ctx)
|
||||
{
|
||||
static const enum vkd3d_primitive_type prim_types[] =
|
||||
{
|
||||
[HLSL_STREAM_OUTPUT_POINT_STREAM] = VKD3D_PT_POINTLIST,
|
||||
[HLSL_STREAM_OUTPUT_LINE_STREAM] = VKD3D_PT_LINESTRIP,
|
||||
[HLSL_STREAM_OUTPUT_TRIANGLE_STREAM] = VKD3D_PT_TRIANGLESTRIP,
|
||||
};
|
||||
|
||||
bool reported_non_point_multistream = false, reported_nonzero_index = false, reported_invalid_index = false;
|
||||
enum hlsl_so_object_type so_type;
|
||||
const struct hlsl_type *type;
|
||||
struct hlsl_ir_var *var;
|
||||
|
||||
LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
|
||||
{
|
||||
if (!var->bind_count[HLSL_REGSET_STREAM_OUTPUTS])
|
||||
continue;
|
||||
|
||||
type = hlsl_get_stream_output_type(var->data_type);
|
||||
so_type = type->e.so.so_type;
|
||||
|
||||
VKD3D_ASSERT(so_type < ARRAY_SIZE(prim_types));
|
||||
|
||||
if (ctx->output_topology_type == VKD3D_PT_UNDEFINED)
|
||||
{
|
||||
ctx->output_topology_type = prim_types[so_type];
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((so_type != HLSL_STREAM_OUTPUT_POINT_STREAM || ctx->output_topology_type != VKD3D_PT_POINTLIST)
|
||||
&& !reported_non_point_multistream)
|
||||
{
|
||||
hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
|
||||
"Multiple output streams are only allowed with PointStream objects.");
|
||||
reported_non_point_multistream = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (var->regs[HLSL_REGSET_STREAM_OUTPUTS].index && hlsl_version_lt(ctx, 5, 0) && !reported_nonzero_index)
|
||||
{
|
||||
hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE,
|
||||
"Multiple output streams are only supported in shader model 5.0 or higher.");
|
||||
reported_nonzero_index = true;
|
||||
}
|
||||
|
||||
if (var->regs[HLSL_REGSET_STREAM_OUTPUTS].index >= VKD3D_MAX_STREAM_COUNT && !reported_invalid_index)
|
||||
{
|
||||
hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SIZE,
|
||||
"Output stream index %u exceeds the maximum index %u.",
|
||||
var->regs[HLSL_REGSET_STREAM_OUTPUTS].index, VKD3D_MAX_STREAM_COUNT - 1);
|
||||
reported_invalid_index = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: check that maxvertexcount * outputdatasize <= 1024. */
|
||||
}
|
||||
|
||||
static void remove_unreachable_code(struct hlsl_ctx *ctx, struct hlsl_block *body)
|
||||
{
|
||||
struct hlsl_ir_node *instr, *next;
|
||||
@@ -11995,7 +12053,7 @@ static void sm4_generate_vsir(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl
|
||||
{
|
||||
program->input_control_point_count = ctx->input_control_point_count;
|
||||
program->input_primitive = ctx->input_primitive_type;
|
||||
program->output_topology = VKD3D_PT_UNDEFINED; /* TODO: obtain from stream output parameters. */
|
||||
program->output_topology = ctx->output_topology_type;
|
||||
program->vertices_out_count = ctx->max_vertex_count;
|
||||
}
|
||||
|
||||
@@ -13285,8 +13343,6 @@ static void process_entry_function(struct hlsl_ctx *ctx,
|
||||
hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER,
|
||||
"Stream output parameter \"%s\" must be declared as \"inout\".", var->name);
|
||||
|
||||
/* TODO: check that maxvertexcount * component_count(element_type) <= 1024. */
|
||||
|
||||
prepend_uniform_copy(ctx, body, var);
|
||||
}
|
||||
else
|
||||
@@ -13402,7 +13458,10 @@ static void process_entry_function(struct hlsl_ctx *ctx,
|
||||
sort_synthetic_separated_samplers_first(ctx);
|
||||
|
||||
if (profile->type == VKD3D_SHADER_TYPE_GEOMETRY)
|
||||
{
|
||||
allocate_stream_outputs(ctx);
|
||||
validate_and_record_stream_outputs(ctx);
|
||||
}
|
||||
|
||||
if (profile->major_version < 4)
|
||||
{
|
||||
|
Reference in New Issue
Block a user