vkd3d-shader/hlsl: Validate maximum output size in geometry shaders.

This commit is contained in:
Shaun Ren
2025-03-25 18:49:21 -04:00
committed by Henri Verbeet
parent 729a3ac089
commit c8c1e270e0
Notes: Henri Verbeet 2025-05-05 15:28:21 +02:00
Approved-by: Elizabeth Figura (@zfigura)
Approved-by: Henri Verbeet (@hverbeet)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1473
2 changed files with 46 additions and 3 deletions

View File

@@ -6515,7 +6515,8 @@ 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) static void allocate_semantic_registers(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func,
uint32_t *output_reg_count)
{ {
struct register_allocator in_prim_allocator = {0}, patch_constant_out_patch_allocator = {0}; struct register_allocator in_prim_allocator = {0}, patch_constant_out_patch_allocator = {0};
struct register_allocator input_allocator = {0}, output_allocator = {0}; struct register_allocator input_allocator = {0}, output_allocator = {0};
@@ -6552,6 +6553,8 @@ static void allocate_semantic_registers(struct hlsl_ctx *ctx, struct hlsl_ir_fun
allocate_semantic_register(ctx, var, &output_allocator, true, !is_pixel_shader); allocate_semantic_register(ctx, var, &output_allocator, true, !is_pixel_shader);
} }
*output_reg_count = output_allocator.reg_count;
vkd3d_free(in_prim_allocator.allocations); vkd3d_free(in_prim_allocator.allocations);
vkd3d_free(patch_constant_out_patch_allocator.allocations); vkd3d_free(patch_constant_out_patch_allocator.allocations);
vkd3d_free(input_allocator.allocations); vkd3d_free(input_allocator.allocations);
@@ -7715,6 +7718,42 @@ static void validate_and_record_stream_outputs(struct hlsl_ctx *ctx)
/* TODO: check that maxvertexcount * outputdatasize <= 1024. */ /* TODO: check that maxvertexcount * outputdatasize <= 1024. */
} }
static void validate_max_output_size(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func,
uint32_t output_reg_count)
{
unsigned int max_output_size, comp_count = 0;
unsigned int *reg_comp_count;
struct hlsl_ir_var *var;
uint32_t id;
if (ctx->result)
return;
if (!(reg_comp_count = hlsl_calloc(ctx, output_reg_count, sizeof(*reg_comp_count))))
return;
LIST_FOR_EACH_ENTRY(var, &entry_func->extern_vars, struct hlsl_ir_var, extern_entry)
{
if (!var->is_output_semantic)
continue;
VKD3D_ASSERT(var->regs[HLSL_REGSET_NUMERIC].allocated);
id = var->regs[HLSL_REGSET_NUMERIC].id;
reg_comp_count[id] = max(reg_comp_count[id], vkd3d_log2i(var->regs[HLSL_REGSET_NUMERIC].writemask) + 1);
}
for (id = 0; id < output_reg_count; ++id)
comp_count += reg_comp_count[id];
max_output_size = ctx->max_vertex_count * comp_count;
if (max_output_size > 1024)
hlsl_error(ctx, &entry_func->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_MAX_VERTEX_COUNT,
"Max vertex count (%u) * output data component count (%u) = %u, which is greater than 1024.",
ctx->max_vertex_count, comp_count, max_output_size);
vkd3d_free(reg_comp_count);
}
static void remove_unreachable_code(struct hlsl_ctx *ctx, struct hlsl_block *body) static void remove_unreachable_code(struct hlsl_ctx *ctx, struct hlsl_block *body)
{ {
struct hlsl_ir_node *instr, *next; struct hlsl_ir_node *instr, *next;
@@ -13328,6 +13367,7 @@ static void process_entry_function(struct hlsl_ctx *ctx,
struct hlsl_block *const body = &entry_func->body; struct hlsl_block *const body = &entry_func->body;
struct recursive_call_ctx recursive_call_ctx; struct recursive_call_ctx recursive_call_ctx;
struct stream_append_ctx stream_append_ctx; struct stream_append_ctx stream_append_ctx;
uint32_t output_reg_count;
struct hlsl_ir_var *var; struct hlsl_ir_var *var;
unsigned int i; unsigned int i;
bool progress; bool progress;
@@ -13615,7 +13655,10 @@ static void process_entry_function(struct hlsl_ctx *ctx,
allocate_register_reservations(ctx, &ctx->extern_vars); allocate_register_reservations(ctx, &ctx->extern_vars);
allocate_register_reservations(ctx, &entry_func->extern_vars); allocate_register_reservations(ctx, &entry_func->extern_vars);
allocate_semantic_registers(ctx, entry_func); allocate_semantic_registers(ctx, entry_func, &output_reg_count);
if (profile->type == VKD3D_SHADER_TYPE_GEOMETRY)
validate_max_output_size(ctx, entry_func, output_reg_count);
} }
int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func,

View File

@@ -662,7 +662,7 @@ void main(point gs_data vin[1], inout PointStream<gs_data> vout)
vout.Append(vin[0]); vout.Append(vin[0]);
} }
[geometry shader fail todo] [geometry shader fail]
struct gs_data struct gs_data
{ {
float2 x : X; float2 x : X;