From: Francisco Casas fcasas@codeweavers.com
--- tests/shader_runner.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/tests/shader_runner.c b/tests/shader_runner.c index 9922496b..680a2856 100644 --- a/tests/shader_runner.c +++ b/tests/shader_runner.c @@ -1026,6 +1026,7 @@ void run_shader_tests(struct shader_runner *runner, const struct shader_runner_o else if (!strcmp(line, "[vertex shader]\n")) { state = STATE_SHADER_VERTEX; + expect_hr = S_OK; } else if (!strcmp(line, "[input layout]\n")) {
From: Francisco Casas fcasas@codeweavers.com
--- tests/shader_runner.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/tests/shader_runner.c b/tests/shader_runner.c index 680a2856..da5548bc 100644 --- a/tests/shader_runner.c +++ b/tests/shader_runner.c @@ -87,6 +87,7 @@ enum parse_state STATE_SHADER_PIXEL, STATE_SHADER_PIXEL_TODO, STATE_SHADER_VERTEX, + STATE_SHADER_VERTEX_TODO, STATE_TEST, };
@@ -824,7 +825,9 @@ void run_shader_tests(struct shader_runner *runner, const struct shader_runner_o break;
case STATE_SHADER_VERTEX: - compile_shader(runner, shader_source, shader_source_len, "vs", expect_hr); + case STATE_SHADER_VERTEX_TODO: + todo_if (state == STATE_SHADER_VERTEX_TODO) + compile_shader(runner, shader_source, shader_source_len, "vs", expect_hr); free(runner->vs_source); runner->vs_source = shader_source; shader_source = NULL; @@ -1028,6 +1031,21 @@ void run_shader_tests(struct shader_runner *runner, const struct shader_runner_o state = STATE_SHADER_VERTEX; expect_hr = S_OK; } + else if (!strcmp(line, "[vertex shader todo]\n")) + { + state = STATE_SHADER_VERTEX_TODO; + expect_hr = S_OK; + } + else if (!strcmp(line, "[vertex shader fail]\n")) + { + state = STATE_SHADER_VERTEX; + expect_hr = E_FAIL; + } + else if (!strcmp(line, "[vertex shader fail todo]\n")) + { + state = STATE_SHADER_VERTEX_TODO; + expect_hr = E_FAIL; + } else if (!strcmp(line, "[input layout]\n")) { state = STATE_INPUT_LAYOUT; @@ -1058,6 +1076,7 @@ void run_shader_tests(struct shader_runner *runner, const struct shader_runner_o case STATE_SHADER_PIXEL: case STATE_SHADER_PIXEL_TODO: case STATE_SHADER_VERTEX: + case STATE_SHADER_VERTEX_TODO: { size_t len = strlen(line);
From: Francisco Casas fcasas@codeweavers.com
--- libs/vkd3d-shader/hlsl_codegen.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 5d7e426f..e250dd0b 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -263,6 +263,16 @@ static void prepend_input_copy(struct hlsl_ctx *ctx, struct list *instrs, struct struct hlsl_ir_var *var = lhs->src.var; unsigned int i;
+ if (type->class > HLSL_CLASS_LAST_NUMERIC) + { + struct vkd3d_string_buffer *string; + if (!(string = hlsl_type_to_string(ctx, type))) + return; + hlsl_fixme(ctx, &var->loc, "Input semantics for type %s.", string->buffer); + hlsl_release_string_buffer(ctx, string); + return; + } + vector_type = hlsl_get_vector_type(ctx, type->base_type, hlsl_type_minor_size(type));
for (i = 0; i < hlsl_type_major_size(type); ++i) @@ -358,6 +368,16 @@ static void append_output_copy(struct hlsl_ctx *ctx, struct list *instrs, struct struct hlsl_ir_var *var = rhs->src.var; unsigned int i;
+ if (type->class > HLSL_CLASS_LAST_NUMERIC) + { + struct vkd3d_string_buffer *string; + if (!(string = hlsl_type_to_string(ctx, type))) + return; + hlsl_fixme(ctx, &var->loc, "Output semantics for type %s.", string->buffer); + hlsl_release_string_buffer(ctx, string); + return; + } + vector_type = hlsl_get_vector_type(ctx, type->base_type, hlsl_type_minor_size(type));
for (i = 0; i < hlsl_type_major_size(type); ++i)
From: Francisco Casas fcasas@codeweavers.com
--- tests/entry-point-semantics.shader_test | 156 ++++++++++++++++++++++++ 1 file changed, 156 insertions(+)
diff --git a/tests/entry-point-semantics.shader_test b/tests/entry-point-semantics.shader_test index a32a0e7b..8c5fed58 100644 --- a/tests/entry-point-semantics.shader_test +++ b/tests/entry-point-semantics.shader_test @@ -50,3 +50,159 @@ float4 main(float tex : bogus) : bogus; [test] draw quad probe (0, 0) rgba (0.2, 0.2, 0.2, 0.2) + +[vertex shader todo] +void main(out float2 tex[4] : texcoord, inout float4 pos : sv_position) +{ + tex[0] = float2(1.0, 2.0); + tex[1] = float2(3.0, 4.0); + tex[2] = float2(5.0, 6.0); + tex[3] = float2(7.0, 8.0); +} + + +% Array parameters of non-struct elements must have a semantic. +[pixel shader fail] +float4 main(in float2 arr[2]) : sv_target +{ + return 0.0; +} + + +% Array elements with a semantic get successive indexes +[pixel shader todo] +struct apple +{ + float2 tp[4] : TEXCOORD0; +}; + +float4 main(in apple a) : sv_target +{ + return float4(10 * a.tp[0] + a.tp[1], 10 * a.tp[2] + a.tp[3]); +} + +[test] +todo draw quad +todo probe (0, 0) rgba (13.0, 24.0, 57.0, 68.0) + + +% Arrays of matrices get successive indexes +[pixel shader todo] +struct apple +{ + float2x2 tp[2] : TEXCOORD0; +}; + +float4 main(in apple a) : sv_target +{ + return float4(10 * a.tp[0][0] + a.tp[0][1], 10 * a.tp[1][0] + a.tp[1][1]); +} + +[test] +todo draw quad +todo probe (0, 0) rgba (12.0, 34.0, 56.0, 78.0) + + +% Arrays (even multi-dimensional) of struct elements are allowed. The fields in the different struct +% elements get the same indexes. +[pixel shader todo] +struct apple { + float2 texcoord : TEXCOORD0; + float4 arb : UNUSED; +}; + +float4 main(in apple aps[2][2]) : sv_target +{ + return float4(aps[0][0].texcoord, aps[1][1].texcoord); +} + +[test] +todo draw quad +todo probe (0, 0) rgba (1.0, 2.0, 1.0, 2.0) + + +[pixel shader todo] +struct apple { + float2 texcoord : TEXCOORD0; +}; + +struct banana { + apple apl; + float4 arb : UNUSED; +}; + +float4 main(in banana bans[2]) : sv_target +{ + return float4(bans[0].apl.texcoord, bans[1].apl.texcoord); +} + +[test] +todo draw quad +todo probe (0, 0) rgba (1.0, 2.0, 1.0, 2.0) + + +[pixel shader fail] +struct apple { + float2 miss; // missing semantic. +}; + +struct banana { + apple apl[2]; + float4 arb : UNUSED; +}; + +float4 main(in banana bans[2]) : sv_target +{ + return 0.0; +} + + +[vertex shader fail] +struct apple { + float2 miss; // missing semantic. +}; + +struct banana { + apple apl[2]; + float4 arb : UNUSED; +}; + +void main(out banana bans[2]) +{ + return 0.0; +} + + +% Output semmantics cannot be mapped to more than one value +[vertex shader fail] +struct apple { + float2 tex : TEXCOORD0; +}; + +void main(out apple apls[2], inout float4 pos : sv_position) +{ + apls[0].tex = float2(1, 2); + apls[1].tex = float2(3, 4); +} + + +[vertex shader todo] +struct apple { + float2 tex[2] : TEXCOORD0; +}; + +void main(out apple apl, inout float4 pos : sv_position) +{ + apl.tex[0] = float2(1, 2); + apl.tex[1] = float2(10, 20); +} + +[pixel shader] +float4 main(in float2 tex0 : TEXCOORD0, in float2 tex1 : TEXCOORD1) : sv_target +{ + return float4(tex0, tex1); +} + +[test] +todo draw quad +todo probe (0, 0) rgba (1.0, 2.0, 10.0, 20.0)
From: Francisco Casas fcasas@codeweavers.com
Errors lose precision on which part of the variable is missing the semantics, but this is necessary in order to avoid printing the same error many times, when arrays are involved. It seems that the native compiler also makes this compromise. --- libs/vkd3d-shader/hlsl.h | 1 + libs/vkd3d-shader/hlsl_codegen.c | 126 +++++++++++++++++++----- tests/entry-point-semantics.shader_test | 30 +++--- 3 files changed, 116 insertions(+), 41 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 38a7715e..1b8a2f55 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -392,6 +392,7 @@ struct hlsl_ir_var uint32_t is_output_semantic : 1; uint32_t is_uniform : 1; uint32_t is_param : 1; + uint32_t is_missing_semantics : 1; };
/* Sized array of variables representing a function's parameters. */ diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index e250dd0b..03430069 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -257,7 +257,7 @@ 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) + unsigned int modifiers, struct hlsl_semantic *semantic) { struct hlsl_type *type = lhs->node.data_type, *vector_type; struct hlsl_ir_var *var = lhs->src.var; @@ -270,6 +270,10 @@ static void prepend_input_copy(struct hlsl_ctx *ctx, struct list *instrs, struct return; hlsl_fixme(ctx, &var->loc, "Input semantics for type %s.", string->buffer); hlsl_release_string_buffer(ctx, string); + } + if (!semantic->name) + { + var->is_missing_semantics = 1; return; }
@@ -277,16 +281,14 @@ static void prepend_input_copy(struct hlsl_ctx *ctx, struct list *instrs, struct
for (i = 0; i < hlsl_type_major_size(type); ++i) { - struct hlsl_semantic semantic_copy = *semantic; struct hlsl_ir_store *store; struct hlsl_ir_constant *c; struct hlsl_ir_var *input; struct hlsl_ir_load *load;
- semantic_copy.index = semantic->index + i; - - if (!(input = add_semantic_var(ctx, var, vector_type, modifiers, &semantic_copy, false))) + if (!(input = add_semantic_var(ctx, var, vector_type, modifiers, semantic, false))) return; + semantic->index += 1;
if (!(load = hlsl_new_var_load(ctx, input, var->loc))) return; @@ -313,6 +315,37 @@ static void prepend_input_copy(struct hlsl_ctx *ctx, struct list *instrs, struct } }
+static void prepend_input_struct_copy(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_load *lhs); + +static void prepend_input_array_copy(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_load *lhs, + unsigned int modifiers, struct hlsl_semantic *semantic) +{ + struct hlsl_type *type = lhs->node.data_type; + struct hlsl_type *element_type = type->e.array.type; + struct hlsl_ir_var *var = lhs->src.var; + struct hlsl_ir_constant *c; + struct hlsl_ir_load *load; + unsigned int i; + + for (i = 0; i < hlsl_type_element_count(type); ++i) + { + if (!(c = hlsl_new_uint_constant(ctx, i, &var->loc))) + return; + list_add_after(&lhs->node.entry, &c->node.entry); + + if (!(load = hlsl_new_load_index(ctx, &lhs->src, &c->node, &var->loc))) + return; + list_add_after(&c->node.entry, &load->node.entry); + + if (element_type->class == HLSL_CLASS_STRUCT) + prepend_input_struct_copy(ctx, instrs, load); + else if (element_type->class == HLSL_CLASS_ARRAY) + prepend_input_array_copy(ctx, instrs, load, modifiers, semantic); + else + prepend_input_copy(ctx, instrs, load, modifiers, semantic); + } +} + static void prepend_input_struct_copy(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_load *lhs) { struct hlsl_type *type = lhs->node.data_type; @@ -322,6 +355,7 @@ static void prepend_input_struct_copy(struct hlsl_ctx *ctx, struct list *instrs, for (i = 0; i < type->e.record.field_count; ++i) { const struct hlsl_struct_field *field = &type->e.record.fields[i]; + struct hlsl_semantic semantic_copy = field->semantic; struct hlsl_ir_load *field_load; struct hlsl_ir_constant *c;
@@ -336,11 +370,10 @@ static void prepend_input_struct_copy(struct hlsl_ctx *ctx, struct list *instrs,
if (field->type->class == HLSL_CLASS_STRUCT) prepend_input_struct_copy(ctx, instrs, field_load); - else if (field->semantic.name) - prepend_input_copy(ctx, instrs, field_load, field->storage_modifiers, &field->semantic); + else if (field->type->class == HLSL_CLASS_ARRAY) + prepend_input_array_copy(ctx, instrs, field_load, field->storage_modifiers, &semantic_copy); else - hlsl_error(ctx, &field->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_SEMANTIC, - "Field '%s' is missing a semantic.", field->name); + prepend_input_copy(ctx, instrs, field_load, field->storage_modifiers, &semantic_copy); } }
@@ -348,6 +381,7 @@ static void prepend_input_struct_copy(struct hlsl_ctx *ctx, struct list *instrs, * and copy the former to the latter, so that writes to input variables work. */ static void prepend_input_var_copy(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_var *var) { + struct hlsl_semantic semantic_copy = var->semantic; struct hlsl_ir_load *load;
/* This redundant load is expected to be deleted later by DCE. */ @@ -357,12 +391,14 @@ static void prepend_input_var_copy(struct hlsl_ctx *ctx, struct list *instrs, st
if (var->data_type->class == HLSL_CLASS_STRUCT) prepend_input_struct_copy(ctx, instrs, load); - else if (var->semantic.name) - prepend_input_copy(ctx, instrs, load, var->storage_modifiers, &var->semantic); + else if (var->data_type->class == HLSL_CLASS_ARRAY) + prepend_input_array_copy(ctx, instrs, load, var->storage_modifiers, &semantic_copy); + else + prepend_input_copy(ctx, instrs, load, var->storage_modifiers, &semantic_copy); }
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) + unsigned int modifiers, struct hlsl_semantic *semantic) { struct hlsl_type *type = rhs->node.data_type, *vector_type; struct hlsl_ir_var *var = rhs->src.var; @@ -375,6 +411,10 @@ static void append_output_copy(struct hlsl_ctx *ctx, struct list *instrs, struct return; hlsl_fixme(ctx, &var->loc, "Output semantics for type %s.", string->buffer); hlsl_release_string_buffer(ctx, string); + } + if (!semantic->name) + { + var->is_missing_semantics = 1; return; }
@@ -382,16 +422,14 @@ static void append_output_copy(struct hlsl_ctx *ctx, struct list *instrs, struct
for (i = 0; i < hlsl_type_major_size(type); ++i) { - struct hlsl_semantic semantic_copy = *semantic; struct hlsl_ir_store *store; struct hlsl_ir_constant *c; struct hlsl_ir_var *output; struct hlsl_ir_load *load;
- semantic_copy.index = semantic->index + i; - - if (!(output = add_semantic_var(ctx, var, vector_type, modifiers, &semantic_copy, true))) + if (!(output = add_semantic_var(ctx, var, vector_type, modifiers, semantic, true))) return; + semantic->index += 1;
if (type->class == HLSL_CLASS_MATRIX) { @@ -418,6 +456,37 @@ static void append_output_copy(struct hlsl_ctx *ctx, struct list *instrs, struct } }
+static void append_output_struct_copy(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_load *rhs); + +static void append_output_array_copy(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_load *rhs, + unsigned int modifiers, struct hlsl_semantic *semantic) +{ + struct hlsl_type *type = rhs->node.data_type; + struct hlsl_type *element_type = type->e.array.type; + struct hlsl_ir_var *var = rhs->src.var; + struct hlsl_ir_constant *c; + struct hlsl_ir_load *load; + unsigned int i; + + for (i = 0; i < hlsl_type_element_count(type); ++i) + { + if (!(c = hlsl_new_uint_constant(ctx, i, &var->loc))) + return; + list_add_tail(instrs, &c->node.entry); + + if (!(load = hlsl_new_load_index(ctx, &rhs->src, &c->node, &var->loc))) + return; + list_add_tail(instrs, &load->node.entry); + + if (element_type->class == HLSL_CLASS_STRUCT) + append_output_struct_copy(ctx, instrs, load); + else if (element_type->class == HLSL_CLASS_ARRAY) + append_output_array_copy(ctx, instrs, load, modifiers, semantic); + else + append_output_copy(ctx, instrs, load, modifiers, semantic); + } +} + static void append_output_struct_copy(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_load *rhs) { struct hlsl_type *type = rhs->node.data_type; @@ -427,6 +496,7 @@ static void append_output_struct_copy(struct hlsl_ctx *ctx, struct list *instrs, for (i = 0; i < type->e.record.field_count; ++i) { const struct hlsl_struct_field *field = &type->e.record.fields[i]; + struct hlsl_semantic semantic_copy = field->semantic; struct hlsl_ir_load *field_load; struct hlsl_ir_constant *c;
@@ -441,11 +511,10 @@ static void append_output_struct_copy(struct hlsl_ctx *ctx, struct list *instrs,
if (field->type->class == HLSL_CLASS_STRUCT) append_output_struct_copy(ctx, instrs, field_load); - else if (field->semantic.name) - append_output_copy(ctx, instrs, field_load, field->storage_modifiers, &field->semantic); + else if (field->type->class == HLSL_CLASS_ARRAY) + append_output_array_copy(ctx, instrs, field_load, field->storage_modifiers, &semantic_copy); else - hlsl_error(ctx, &field->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_SEMANTIC, - "Field '%s' is missing a semantic.", field->name); + append_output_copy(ctx, instrs, field_load, field->storage_modifiers, &semantic_copy); } }
@@ -454,6 +523,7 @@ static void append_output_struct_copy(struct hlsl_ctx *ctx, struct list *instrs, * variables work. */ static void append_output_var_copy(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_var *var) { + struct hlsl_semantic semantic_copy = var->semantic; struct hlsl_ir_load *load;
/* This redundant load is expected to be deleted later by DCE. */ @@ -463,8 +533,10 @@ static void append_output_var_copy(struct hlsl_ctx *ctx, struct list *instrs, st
if (var->data_type->class == HLSL_CLASS_STRUCT) append_output_struct_copy(ctx, instrs, load); - else if (var->semantic.name) - append_output_copy(ctx, instrs, load, var->storage_modifiers, &var->semantic); + else if (var->data_type->class == HLSL_CLASS_ARRAY) + append_output_array_copy(ctx, instrs, load, var->storage_modifiers, &semantic_copy); + else + append_output_copy(ctx, instrs, load, var->storage_modifiers, &semantic_copy); }
static bool transform_ir(struct hlsl_ctx *ctx, bool (*func)(struct hlsl_ctx *ctx, struct hlsl_ir_node *, void *), @@ -3402,14 +3474,16 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry } else { - if (var->data_type->class != HLSL_CLASS_STRUCT && !var->semantic.name) - hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_SEMANTIC, - "Parameter "%s" is missing a semantic.", var->name); - if (var->storage_modifiers & HLSL_STORAGE_IN) prepend_input_var_copy(ctx, &body->instrs, var); if (var->storage_modifiers & HLSL_STORAGE_OUT) append_output_var_copy(ctx, &body->instrs, var); + + if (var->is_missing_semantics) + { + hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_SEMANTIC, + "Parameter "%s" is missing semantics.", var->name); + } } } if (entry_func->return_var) diff --git a/tests/entry-point-semantics.shader_test b/tests/entry-point-semantics.shader_test index 8c5fed58..a1dc2283 100644 --- a/tests/entry-point-semantics.shader_test +++ b/tests/entry-point-semantics.shader_test @@ -51,7 +51,7 @@ float4 main(float tex : bogus) : bogus; draw quad probe (0, 0) rgba (0.2, 0.2, 0.2, 0.2)
-[vertex shader todo] +[vertex shader] void main(out float2 tex[4] : texcoord, inout float4 pos : sv_position) { tex[0] = float2(1.0, 2.0); @@ -70,7 +70,7 @@ float4 main(in float2 arr[2]) : sv_target
% Array elements with a semantic get successive indexes -[pixel shader todo] +[pixel shader] struct apple { float2 tp[4] : TEXCOORD0; @@ -82,12 +82,12 @@ float4 main(in apple a) : sv_target }
[test] -todo draw quad -todo probe (0, 0) rgba (13.0, 24.0, 57.0, 68.0) +draw quad +probe (0, 0) rgba (13.0, 24.0, 57.0, 68.0)
% Arrays of matrices get successive indexes -[pixel shader todo] +[pixel shader] struct apple { float2x2 tp[2] : TEXCOORD0; @@ -99,13 +99,13 @@ float4 main(in apple a) : sv_target }
[test] -todo draw quad -todo probe (0, 0) rgba (12.0, 34.0, 56.0, 78.0) +draw quad +probe (0, 0) rgba (12.0, 34.0, 56.0, 78.0)
% Arrays (even multi-dimensional) of struct elements are allowed. The fields in the different struct % elements get the same indexes. -[pixel shader todo] +[pixel shader] struct apple { float2 texcoord : TEXCOORD0; float4 arb : UNUSED; @@ -117,11 +117,11 @@ float4 main(in apple aps[2][2]) : sv_target }
[test] -todo draw quad +draw quad todo probe (0, 0) rgba (1.0, 2.0, 1.0, 2.0)
-[pixel shader todo] +[pixel shader] struct apple { float2 texcoord : TEXCOORD0; }; @@ -137,7 +137,7 @@ float4 main(in banana bans[2]) : sv_target }
[test] -todo draw quad +draw quad todo probe (0, 0) rgba (1.0, 2.0, 1.0, 2.0)
@@ -174,7 +174,7 @@ void main(out banana bans[2])
% Output semmantics cannot be mapped to more than one value -[vertex shader fail] +[vertex shader fail todo] struct apple { float2 tex : TEXCOORD0; }; @@ -186,7 +186,7 @@ void main(out apple apls[2], inout float4 pos : sv_position) }
-[vertex shader todo] +[vertex shader] struct apple { float2 tex[2] : TEXCOORD0; }; @@ -204,5 +204,5 @@ float4 main(in float2 tex0 : TEXCOORD0, in float2 tex1 : TEXCOORD1) : sv_target }
[test] -todo draw quad -todo probe (0, 0) rgba (1.0, 2.0, 10.0, 20.0) +draw quad +probe (0, 0) rgba (1.0, 2.0, 10.0, 20.0)
From: Francisco Casas fcasas@codeweavers.com
--- libs/vkd3d-shader/hlsl_codegen.c | 10 ++++++++++ tests/entry-point-semantics.shader_test | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 03430069..bd129bb0 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -231,6 +231,16 @@ static struct hlsl_ir_var *add_semantic_var(struct hlsl_ctx *ctx, struct hlsl_ir if (!(name = hlsl_get_string_buffer(ctx))) return NULL; vkd3d_string_buffer_printf(name, "<%s-%s%u>", output ? "output" : "input", semantic->name, semantic->index); + + LIST_FOR_EACH_ENTRY(ext_var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) + { + if (!strcmp(ext_var->name, name->buffer)) + { + hlsl_release_string_buffer(ctx, name); + return ext_var; + } + } + if (!(new_semantic.name = hlsl_strdup(ctx, semantic->name))) { hlsl_release_string_buffer(ctx, name); diff --git a/tests/entry-point-semantics.shader_test b/tests/entry-point-semantics.shader_test index a1dc2283..b92a84d2 100644 --- a/tests/entry-point-semantics.shader_test +++ b/tests/entry-point-semantics.shader_test @@ -118,7 +118,7 @@ float4 main(in apple aps[2][2]) : sv_target
[test] draw quad -todo probe (0, 0) rgba (1.0, 2.0, 1.0, 2.0) +probe (0, 0) rgba (1.0, 2.0, 1.0, 2.0)
[pixel shader] @@ -138,7 +138,7 @@ float4 main(in banana bans[2]) : sv_target
[test] draw quad -todo probe (0, 0) rgba (1.0, 2.0, 1.0, 2.0) +probe (0, 0) rgba (1.0, 2.0, 1.0, 2.0)
[pixel shader fail]
From: Francisco Casas fcasas@codeweavers.com
--- libs/vkd3d-shader/hlsl_codegen.c | 4 ++++ tests/entry-point-semantics.shader_test | 2 +- tests/matrix-semantics.shader_test | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index bd129bb0..2dc11c57 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -236,6 +236,10 @@ static struct hlsl_ir_var *add_semantic_var(struct hlsl_ctx *ctx, struct hlsl_ir { if (!strcmp(ext_var->name, name->buffer)) { + if (output) + hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SEMANTIC, + "Output semantic "%s%u" is used multiple times.", semantic->name, semantic->index); + hlsl_release_string_buffer(ctx, name); return ext_var; } diff --git a/tests/entry-point-semantics.shader_test b/tests/entry-point-semantics.shader_test index b92a84d2..1a8ff074 100644 --- a/tests/entry-point-semantics.shader_test +++ b/tests/entry-point-semantics.shader_test @@ -174,7 +174,7 @@ void main(out banana bans[2])
% Output semmantics cannot be mapped to more than one value -[vertex shader fail todo] +[vertex shader fail] struct apple { float2 tex : TEXCOORD0; }; 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);
Errors lose precision on which part of the variable is missing the semantics, but this is necessary in order to avoid printing the same error many times, when arrays are involved. It seems that the native compiler also makes this compromise.
I think we can do better, though. We could add a bool field to struct hlsl_field denoting whether the missing-semantic warning has been reported yet, and then just do it in prepend_input_var_copy() / append_output_var_copy(). [Side note: we may want to add a helper, even though it's a one-liner, just to make sure the error messages are always in sync.]
Zebediah Figura (@zfigura) commented about libs/vkd3d-shader/hlsl_codegen.c:
- for (i = 0; i < hlsl_type_element_count(type); ++i)
- {
if (!(c = hlsl_new_uint_constant(ctx, i, &var->loc)))
return;
list_add_after(&lhs->node.entry, &c->node.entry);
if (!(load = hlsl_new_load_index(ctx, &lhs->src, &c->node, &var->loc)))
return;
list_add_after(&c->node.entry, &load->node.entry);
if (element_type->class == HLSL_CLASS_STRUCT)
prepend_input_struct_copy(ctx, instrs, load);
else if (element_type->class == HLSL_CLASS_ARRAY)
prepend_input_array_copy(ctx, instrs, load, modifiers, semantic);
else
prepend_input_copy(ctx, instrs, load, modifiers, semantic);
This pattern appears I think three times now, we should be able to use a helper. Or just fold this into the prologue of prepend_input_copy(), maybe?
Zebediah Figura (@zfigura) commented about tests/entry-point-semantics.shader_test:
+{
- return 0.0;
+}
+% Array elements with a semantic get successive indexes +[pixel shader todo] +struct apple +{
- float2 tp[4] : TEXCOORD0;
+};
+float4 main(in apple a) : sv_target +{
- return float4(10 * a.tp[0] + a.tp[1], 10 * a.tp[2] + a.tp[3]);
+}
Not a big deal (the test works either way), but it might be clearer just to take the first component of each, and then there's no math necessary?
Zebediah Figura (@zfigura) commented about tests/entry-point-semantics.shader_test:
+todo draw quad +todo probe (0, 0) rgba (12.0, 34.0, 56.0, 78.0)
+% Arrays (even multi-dimensional) of struct elements are allowed. The fields in the different struct +% elements get the same indexes. +[pixel shader todo] +struct apple {
- float2 texcoord : TEXCOORD0;
- float4 arb : UNUSED;
+};
+float4 main(in apple aps[2][2]) : sv_target +{
- return float4(aps[0][0].texcoord, aps[1][1].texcoord);
+}
Wow, okay, I was not expecting that to be legal.
It's also legal even without using arrays, *but* only if the types match—otherwise there's an error. We could probably add some extra tests for that.
Also a test that the variables don't really alias each other might be warranted. (I.e. assigning to one only affects that one.)
Zebediah Figura (@zfigura) commented about tests/entry-point-semantics.shader_test:
+struct apple {
- float2 miss; // missing semantic.
+};
+struct banana {
- apple apl[2];
- float4 arb : UNUSED;
+};
+void main(out banana bans[2]) +{
- return 0.0;
+}
+% Output semmantics cannot be mapped to more than one value
Spelling error, "semmantics".
Zebediah Figura (@zfigura) commented about libs/vkd3d-shader/hlsl_codegen.c:
{ if (!strcmp(ext_var->name, name->buffer)) {
if (output)
hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SEMANTIC,
"Output semantic \"%s%u\" is used multiple times.", semantic->name, semantic->index);
Can we hlsl_note() with the previous variable's location?