mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2025-09-12 18:50:22 -07:00
vkd3d-shader/hlsl: Validate maximum output size in geometry shaders.
This commit is contained in:
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
@@ -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,
|
||||||
|
@@ -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;
|
||||||
|
Reference in New Issue
Block a user