From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- libs/vkd3d-shader/hlsl_codegen.c | 52 +++++++++++++++------ tests/register-reservations.shader_test | 61 +++++++++++++++++++++++++ 2 files changed, 100 insertions(+), 13 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 96b4cb660..f8511a1f9 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -2688,6 +2688,7 @@ static char get_regset_name(enum hlsl_regset regset)
static void allocate_register_reservations(struct hlsl_ctx *ctx) { + struct vkd3d_string_buffer *type_string; struct hlsl_ir_var *var;
LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) @@ -2696,29 +2697,49 @@ static void allocate_register_reservations(struct hlsl_ctx *ctx)
if (!hlsl_type_is_resource(var->data_type)) continue; + if (!var->reg_reservation.reg_type) + continue; + regset = hlsl_type_get_regset(var->data_type);
- if (var->reg_reservation.reg_type) + if (var->reg_reservation.reg_type != get_regset_name(regset)) { - if (var->reg_reservation.reg_type != get_regset_name(regset)) + if (var->last_read) { - struct vkd3d_string_buffer *type_string; - type_string = hlsl_type_to_string(ctx, var->data_type); hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, "Object of type '%s' must be bound to register type '%c'.", type_string->buffer, get_regset_name(regset)); hlsl_release_string_buffer(ctx, type_string); } - else - { - var->regs[regset].allocated = true; - var->regs[regset].id = var->reg_reservation.reg_index; - var->regs[regset].bind_count = var->data_type->reg_size[regset]; - TRACE("Allocated reserved %s to %c%u-%c%u.\n", var->name, var->reg_reservation.reg_type, - var->reg_reservation.reg_index, var->reg_reservation.reg_type, - var->reg_reservation.reg_index + var->regs[regset].bind_count); - } + continue; + } + + var->regs[regset].allocated = true; + var->regs[regset].id = var->reg_reservation.reg_index; + var->regs[regset].bind_count = var->data_type->reg_size[regset]; + TRACE("Allocated reserved %s to %c%u-%c%u.\n", var->name, var->reg_reservation.reg_type, + var->reg_reservation.reg_index, var->reg_reservation.reg_type, + var->reg_reservation.reg_index + var->regs[regset].bind_count); + } +} + +static void deallocate_unused_register_reservations(struct hlsl_ctx *ctx) +{ + struct hlsl_ir_var *var; + + LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) + { + enum hlsl_regset regset; + + if (!hlsl_type_is_resource(var->data_type)) + continue; + if (!var->reg_reservation.reg_type) + continue; + regset = hlsl_type_get_regset(var->data_type); + if (var->regs[regset].allocated && !var->last_read) + { + var->regs[regset].allocated = false; } } } @@ -3666,6 +3687,9 @@ static void allocate_objects(struct hlsl_ctx *ctx, enum hlsl_regset regset) const struct hlsl_ir_var *reserved_object, *last_reported = NULL; unsigned int index, i;
+ if (!var->last_read) + continue; + if (var->regs[regset].id < min_index) { assert(regset == HLSL_REGSET_UAVS); @@ -4130,6 +4154,8 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry allocate_semantic_registers(ctx); allocate_objects(ctx, HLSL_REGSET_SAMPLERS);
+ deallocate_unused_register_reservations(ctx); + if (ctx->result) return ctx->result;
diff --git a/tests/register-reservations.shader_test b/tests/register-reservations.shader_test index 72f68c1e0..26f4381d0 100644 --- a/tests/register-reservations.shader_test +++ b/tests/register-reservations.shader_test @@ -69,6 +69,36 @@ draw quad probe all rgba (1.0, 1.0, 1.0, 99.0)
+% Register reservation with incorrect register type. +[pixel shader] +Texture2D unused : register(s0); +Texture2D tex; + +float4 main() : sv_target +{ + return tex.Load(int3(0, 0, 0)); +} + +[test] +draw quad +probe all rgba (0.0, 0.0, 0.0, 99.0) + + +% Register reservation with incorrect register type. +[pixel shader] +sampler2D unused : register(t0); +Texture2D tex; + +float4 main() : sv_target +{ + return tex.Load(int3(0, 0, 0)); +} + + +[test] +draw quad +probe all rgba (0.0, 0.0, 0.0, 99.0) + [pixel shader] Texture2D unused[2][2] : register(t0); Texture2D tex; @@ -81,3 +111,34 @@ float4 main() : sv_target [test] draw quad probe all rgba (4.0, 4.0, 4.0, 99.0) + + +% Overlapping reservations, both overlapping objects are unused. +[pixel shader] +Texture2D tex1 : register(t0); +Texture2D tex2 : register(t0); +Texture2D tex3; + +float4 main() : sv_target +{ + return tex3.Load(int3(0, 0, 0)); +} + +[test] +draw quad +probe all rgba (1.0, 1.0, 1.0, 99.0) + + +% Overlapping reservations +[pixel shader] +Texture2D tex1 : register(t2); +Texture2D tex2 : register(t2); + +float4 main() : sv_target +{ + return tex1.Load(int3(0, 0, 0)); +} + +[test] +draw quad +probe all rgba (2.0, 2.0, 2.0, 99.0)