Module: vkd3d Branch: master Commit: d96e9665b1f5bd46881d1428379ca82c7466a663 URL: https://gitlab.winehq.org/wine/vkd3d/-/commit/d96e9665b1f5bd46881d1428379ca8...
Author: Francisco Casas fcasas@codeweavers.com Date: Wed Apr 12 15:59:06 2023 -0400
vkd3d-shader/hlsl: Error out when an output semantic is used more than once.
The use of the hlsl_semantic.reported_duplicated_output_next_index field allows reporting multiple overlapping indexes, such as in the following vertex shader:
void main(out float1x3 x : OVERLAP0, out float1x3 y : OVERLAP1) { x = float3(1.0, 2.0, 3.2); y = float3(5.0, 6.0, 5.0); }
apple.hlsl:1:41: E5013: Output semantic "OVERLAP1" is used multiple times. apple.hlsl:1:13: First use of "OVERLAP1" is here. apple.hlsl:1:41: E5013: Output semantic "OVERLAP2" is used multiple times. apple.hlsl:1:13: First use of "OVERLAP2" is here.
While at the same time avoiding reporting overlaps more than once for large arrays:
struct apple { float2 p : sv_position; };
void main(out apple aps[4]) { }
apple.hlsl:3:8: E5013: Output semantic "sv_position0" is used multiple times. apple.hlsl:3:8: First use of "sv_position0" is here.
---
libs/vkd3d-shader/hlsl.h | 3 +++ libs/vkd3d-shader/hlsl.y | 1 + libs/vkd3d-shader/hlsl_codegen.c | 42 +++++++++++++++++++++++---------- tests/entry-point-semantics.shader_test | 6 ++--- tests/matrix-semantics.shader_test | 2 +- 5 files changed, 38 insertions(+), 16 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 4a97404c..ac916163 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -212,6 +212,9 @@ struct hlsl_semantic
/* If the variable or field that stores this hlsl_semantic has already reported that it is missing. */ bool reported_missing; + /* In case the variable or field that stores this semantic has already reported to use a + * duplicated output semantic, this value stores the last reported index + 1. Otherwise it is 0. */ + uint32_t reported_duplicated_output_next_index; };
/* A field within a struct type declaration, used in hlsl_type.e.fields. */ diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 1fc85bd1..71c09029 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -4784,6 +4784,7 @@ semantic: $$.name = $2; $$.index = atoi(p); $$.reported_missing = false; + $$.reported_duplicated_output_next_index = 0; *p = 0; }
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 7b842716..630b217d 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -233,8 +233,8 @@ static void validate_field_semantic(struct hlsl_ctx *ctx, struct hlsl_struct_fie }
static struct hlsl_ir_var *add_semantic_var(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, - struct hlsl_type *type, unsigned int modifiers, const struct hlsl_semantic *semantic, - uint32_t index, bool output) + struct hlsl_type *type, unsigned int modifiers, struct hlsl_semantic *semantic, + uint32_t index, bool output, const struct vkd3d_shader_location *loc) { struct hlsl_semantic new_semantic; struct vkd3d_string_buffer *name; @@ -248,6 +248,18 @@ static struct hlsl_ir_var *add_semantic_var(struct hlsl_ctx *ctx, struct hlsl_ir { if (!ascii_strcasecmp(ext_var->name, name->buffer)) { + if (output) + { + if (index >= semantic->reported_duplicated_output_next_index) + { + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SEMANTIC, + "Output semantic "%s%u" is used multiple times.", semantic->name, index); + hlsl_note(ctx, &ext_var->loc, HLSL_LEVEL_ERROR, + "First use of "%s%u" is here.", semantic->name, index); + semantic->reported_duplicated_output_next_index = index + 1; + } + } + hlsl_release_string_buffer(ctx, name); return ext_var; } @@ -259,8 +271,8 @@ static struct hlsl_ir_var *add_semantic_var(struct hlsl_ctx *ctx, struct hlsl_ir return NULL; } new_semantic.index = index; - if (!(ext_var = hlsl_new_var(ctx, hlsl_strdup(ctx, name->buffer), - type, &var->loc, &new_semantic, modifiers, NULL))) + if (!(ext_var = hlsl_new_var(ctx, hlsl_strdup(ctx, name->buffer), type, loc, &new_semantic, + modifiers, NULL))) { hlsl_release_string_buffer(ctx, name); hlsl_cleanup_semantic(&new_semantic); @@ -279,9 +291,10 @@ static struct hlsl_ir_var *add_semantic_var(struct hlsl_ctx *ctx, struct hlsl_ir }
static void prepend_input_copy(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_load *lhs, - unsigned int modifiers, const struct hlsl_semantic *semantic, uint32_t semantic_index) + unsigned int modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index) { struct hlsl_type *type = lhs->node.data_type, *vector_type; + struct vkd3d_shader_location *loc = &lhs->node.loc; struct hlsl_ir_var *var = lhs->src.var; struct hlsl_ir_constant *c; unsigned int i; @@ -305,7 +318,7 @@ static void prepend_input_copy(struct hlsl_ctx *ctx, struct list *instrs, struct struct hlsl_ir_var *input; struct hlsl_ir_load *load;
- if (!(input = add_semantic_var(ctx, var, vector_type, modifiers, semantic, semantic_index + i, false))) + if (!(input = add_semantic_var(ctx, var, vector_type, modifiers, semantic, semantic_index + i, false, loc))) return;
if (!(load = hlsl_new_var_load(ctx, input, &var->loc))) @@ -334,8 +347,9 @@ static void prepend_input_copy(struct hlsl_ctx *ctx, struct list *instrs, struct }
static void prepend_input_copy_recurse(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_load *lhs, - unsigned int modifiers, const struct hlsl_semantic *semantic, uint32_t semantic_index) + unsigned int modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index) { + struct vkd3d_shader_location *loc = &lhs->node.loc; struct hlsl_type *type = lhs->node.data_type; struct hlsl_ir_var *var = lhs->src.var; struct hlsl_ir_constant *c; @@ -360,6 +374,7 @@ static void prepend_input_copy_recurse(struct hlsl_ctx *ctx, struct list *instrs validate_field_semantic(ctx, field); semantic = &field->semantic; elem_semantic_index = semantic->index; + loc = &field->loc; }
if (!(c = hlsl_new_uint_constant(ctx, i, &var->loc))) @@ -367,7 +382,7 @@ static void prepend_input_copy_recurse(struct hlsl_ctx *ctx, struct list *instrs list_add_after(&lhs->node.entry, &c->node.entry);
/* This redundant load is expected to be deleted later by DCE. */ - if (!(element_load = hlsl_new_load_index(ctx, &lhs->src, &c->node, &var->loc))) + if (!(element_load = hlsl_new_load_index(ctx, &lhs->src, &c->node, loc))) return; list_add_after(&c->node.entry, &element_load->node.entry);
@@ -395,9 +410,10 @@ static void prepend_input_var_copy(struct hlsl_ctx *ctx, struct list *instrs, st }
static void append_output_copy(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_load *rhs, - unsigned int modifiers, const struct hlsl_semantic *semantic, uint32_t semantic_index) + unsigned int modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index) { struct hlsl_type *type = rhs->node.data_type, *vector_type; + struct vkd3d_shader_location *loc = &rhs->node.loc; struct hlsl_ir_var *var = rhs->src.var; struct hlsl_ir_constant *c; unsigned int i; @@ -421,7 +437,7 @@ static void append_output_copy(struct hlsl_ctx *ctx, struct list *instrs, struct struct hlsl_ir_var *output; struct hlsl_ir_load *load;
- if (!(output = add_semantic_var(ctx, var, vector_type, modifiers, semantic, semantic_index + i, true))) + if (!(output = add_semantic_var(ctx, var, vector_type, modifiers, semantic, semantic_index + i, true, loc))) return;
if (type->class == HLSL_CLASS_MATRIX) @@ -450,8 +466,9 @@ static void append_output_copy(struct hlsl_ctx *ctx, struct list *instrs, struct }
static void append_output_copy_recurse(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_load *rhs, - unsigned int modifiers, const struct hlsl_semantic *semantic, uint32_t semantic_index) + unsigned int modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index) { + struct vkd3d_shader_location *loc = &rhs->node.loc; struct hlsl_type *type = rhs->node.data_type; struct hlsl_ir_var *var = rhs->src.var; struct hlsl_ir_constant *c; @@ -476,13 +493,14 @@ static void append_output_copy_recurse(struct hlsl_ctx *ctx, struct list *instrs validate_field_semantic(ctx, field); semantic = &field->semantic; elem_semantic_index = semantic->index; + loc = &field->loc; }
if (!(c = hlsl_new_uint_constant(ctx, i, &var->loc))) return; list_add_tail(instrs, &c->node.entry);
- if (!(element_load = hlsl_new_load_index(ctx, &rhs->src, &c->node, &var->loc))) + if (!(element_load = hlsl_new_load_index(ctx, &rhs->src, &c->node, loc))) return; list_add_tail(instrs, &element_load->node.entry);
diff --git a/tests/entry-point-semantics.shader_test b/tests/entry-point-semantics.shader_test index 7819d3e2..66dcd6ee 100644 --- a/tests/entry-point-semantics.shader_test +++ b/tests/entry-point-semantics.shader_test @@ -205,7 +205,7 @@ probe (0, 0) rgba (1.0, 2.0, 10.0, 20.0)
% Output semantics cannot be mapped to more than one value. -[vertex shader fail todo] +[vertex shader fail] struct apple { float2 tex : TEXCOORD0; @@ -218,7 +218,7 @@ void main(out apple apls[2], inout float4 pos : sv_position) }
-[vertex shader fail todo] +[vertex shader fail] struct apple { float2 f : SEMANTIC; @@ -232,7 +232,7 @@ void main(out apple a, out apple b, inout float4 pos : sv_position)
% Semantic names are case-insensitive. -[vertex shader fail todo] +[vertex shader fail] void main(out float2 a : sem0, out float2 b : SEM, inout float4 pos : sv_position) { a = float2(1, 2); diff --git a/tests/matrix-semantics.shader_test b/tests/matrix-semantics.shader_test index 43f467ec..b704dc1a 100644 --- a/tests/matrix-semantics.shader_test +++ b/tests/matrix-semantics.shader_test @@ -63,7 +63,7 @@ probe render target 1 all r (2.0) probe render target 2 all r (3.0) probe render target 3 all r (4.0)
-[pixel shader fail todo] +[pixel shader fail] void main(out float1x2 x : sv_target0, out float1x2 y : sv_target1) { x = float2(1.0, 2.0);