From 597e55691a818a02353b59015e20d382049befc1 Mon Sep 17 00:00:00 2001 From: Francisco Casas Date: Wed, 5 Jun 2024 19:47:43 -0400 Subject: [PATCH] vkd3d-shader/hlsl: Only error out on bind_count register reservation overlaps for SM1. While on SM1 a register reservation reserves the whole size in registers of the variable's data type, overlapping conflicts are only checked up to the bind_count (used size) for each variable. --- libs/vkd3d-shader/hlsl_codegen.c | 15 +++++++++++---- .../register-reservations-numeric.shader_test | 6 +++--- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index ee2a9082..f33668f6 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -4599,6 +4599,7 @@ static void sort_uniforms_by_numeric_bind_count(struct hlsl_ctx *ctx) static void allocate_const_registers(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func) { + struct register_allocator allocator_used = {0}; struct register_allocator allocator = {0}; struct hlsl_ir_var *var; @@ -4607,6 +4608,7 @@ static void allocate_const_registers(struct hlsl_ctx *ctx, struct hlsl_ir_functi LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) { unsigned int reg_size = var->data_type->reg_size[HLSL_REGSET_NUMERIC]; + unsigned int bind_count = var->bind_count[HLSL_REGSET_NUMERIC]; if (!var->is_uniform || reg_size == 0) continue; @@ -4619,12 +4621,15 @@ static void allocate_const_registers(struct hlsl_ctx *ctx, struct hlsl_ir_functi assert(reg_size % 4 == 0); for (i = 0; i < reg_size / 4; ++i) { - if (get_available_writemask(&allocator, 1, UINT_MAX, reg_idx + i) != VKD3DSP_WRITEMASK_ALL) + if (i < bind_count) { - hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, - "Overlapping register() reservations on 'c%u'.", reg_idx + i); + if (get_available_writemask(&allocator_used, 1, UINT_MAX, reg_idx + i) != VKD3DSP_WRITEMASK_ALL) + { + hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, + "Overlapping register() reservations on 'c%u'.", reg_idx + i); + } + record_allocation(ctx, &allocator_used, reg_idx + i, VKD3DSP_WRITEMASK_ALL, 1, UINT_MAX); } - record_allocation(ctx, &allocator, reg_idx + i, VKD3DSP_WRITEMASK_ALL, 1, UINT_MAX); } @@ -4637,6 +4642,8 @@ static void allocate_const_registers(struct hlsl_ctx *ctx, struct hlsl_ir_functi } } + vkd3d_free(allocator_used.allocations); + LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) { unsigned int alloc_size = 4 * var->bind_count[HLSL_REGSET_NUMERIC]; diff --git a/tests/hlsl/register-reservations-numeric.shader_test b/tests/hlsl/register-reservations-numeric.shader_test index 84752361..778516e7 100644 --- a/tests/hlsl/register-reservations-numeric.shader_test +++ b/tests/hlsl/register-reservations-numeric.shader_test @@ -10,7 +10,7 @@ float4 main() : sv_target } -[pixel shader todo(sm<4)] +[pixel shader] // Overlapping reservations when both variables are unused. float4 a : register(c3); float4 b : register(c3); @@ -20,7 +20,7 @@ float4 main() : sv_target return 42; } -[pixel shader fail(sm>=4 & sm<6) todo(sm<4)] +[pixel shader fail(sm>=4 & sm<6)] // Overlapping reservations when only one variable is used. float4 a : register(c3); float4 b : register(c3); @@ -31,7 +31,7 @@ float4 main() : sv_target } -[pixel shader fail(sm>=4 & sm<6) todo(sm<4)] +[pixel shader fail(sm>=4 & sm<6)] // Overlapping reservations when both variables are used, but their bind_count (used size) doesn't // cause an overlap. float4 a[2] : register(c3); // bind count: 1