Module: vkd3d Branch: master Commit: 4448d114ad6b279c8631aa9229fb04dda4d92561 URL: https://gitlab.winehq.org/wine/vkd3d/-/commit/4448d114ad6b279c8631aa9229fb04...
Author: Francisco Casas fcasas@codeweavers.com Date: Tue Feb 21 21:53:32 2023 -0300
vkd3d-shader/hlsl: Detect overlaps in cbuffer offsets.
---
libs/vkd3d-shader/hlsl_codegen.c | 42 ++++++++++++++++++++++++++++++++++++++++ tests/cbuffer.shader_test | 2 +- 2 files changed, 43 insertions(+), 1 deletion(-)
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index eafc06e2..2e10aa55 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -2952,6 +2952,46 @@ static void calculate_buffer_offset(struct hlsl_ctx *ctx, struct hlsl_ir_var *va buffer->used_size = max(buffer->used_size, var->buffer_offset + var_reg_size); }
+static void validate_buffer_offsets(struct hlsl_ctx *ctx) +{ + struct hlsl_ir_var *var1, *var2; + struct hlsl_buffer *buffer; + + LIST_FOR_EACH_ENTRY(var1, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) + { + if (!var1->is_uniform || var1->data_type->class == HLSL_CLASS_OBJECT) + continue; + + buffer = var1->buffer; + if (!buffer->used_size) + continue; + + LIST_FOR_EACH_ENTRY(var2, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) + { + unsigned int var1_reg_size, var2_reg_size; + + if (!var2->is_uniform || var2->data_type->class == HLSL_CLASS_OBJECT) + continue; + + if (var1 == var2 || var1->buffer != var2->buffer) + continue; + + /* This is to avoid reporting the error twice for the same pair of overlapping variables. */ + if (strcmp(var1->name, var2->name) >= 0) + continue; + + var1_reg_size = var1->data_type->reg_size[HLSL_REGSET_NUMERIC]; + var2_reg_size = var2->data_type->reg_size[HLSL_REGSET_NUMERIC]; + + if (var1->buffer_offset < var2->buffer_offset + var2_reg_size + && var2->buffer_offset < var1->buffer_offset + var1_reg_size) + hlsl_error(ctx, &buffer->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, + "Invalid packoffset() reservation: Variables %s and %s overlap.", + var1->name, var2->name); + } + } +} + static void allocate_buffers(struct hlsl_ctx *ctx) { struct hlsl_buffer *buffer; @@ -2969,6 +3009,8 @@ static void allocate_buffers(struct hlsl_ctx *ctx) } }
+ validate_buffer_offsets(ctx); + LIST_FOR_EACH_ENTRY(buffer, &ctx->buffers, struct hlsl_buffer, entry) { if (!buffer->used_size) diff --git a/tests/cbuffer.shader_test b/tests/cbuffer.shader_test index bf711629..d8cfc351 100644 --- a/tests/cbuffer.shader_test +++ b/tests/cbuffer.shader_test @@ -106,7 +106,7 @@ draw quad probe all rgba (0.0, 4.0, 5.0, 6.0)
-[pixel shader fail todo] +[pixel shader fail] // Elements cannot overlap if buffer is used. cbuffer buffer {