From: Francisco Casas fcasas@codeweavers.com
Errors lose precision on which part of the variable is missing the semantics, but this will be fixed in a couple of commits ahead. --- libs/vkd3d-shader/hlsl.h | 1 + libs/vkd3d-shader/hlsl_codegen.c | 169 ++++++++++++------------ tests/entry-point-semantics.shader_test | 36 ++--- 3 files changed, 102 insertions(+), 104 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..479abc1d 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -257,12 +257,42 @@ 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; + struct hlsl_ir_constant *c; unsigned int i;
+ if (type->class == HLSL_CLASS_ARRAY || type->class == HLSL_CLASS_STRUCT) + { + struct hlsl_semantic field_semantic_copy; + struct hlsl_ir_load *element_load; + struct hlsl_struct_field *field; + + for (i = 0; i < hlsl_type_element_count(type); ++i) + { + if (type->class == HLSL_CLASS_STRUCT) + { + field = &type->e.record.fields[i]; + field_semantic_copy = field->semantic; + semantic = &field_semantic_copy; + } + + if (!(c = hlsl_new_uint_constant(ctx, i, &var->loc))) + return; + 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))) + return; + list_add_after(&c->node.entry, &element_load->node.entry); + + prepend_input_copy(ctx, instrs, element_load, modifiers, semantic); + } + return; + } + if (type->class > HLSL_CLASS_LAST_NUMERIC) { struct vkd3d_string_buffer *string; @@ -270,6 +300,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 +311,13 @@ 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,41 +344,11 @@ 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) -{ - struct hlsl_type *type = lhs->node.data_type; - struct hlsl_ir_var *var = lhs->src.var; - size_t i; - - for (i = 0; i < type->e.record.field_count; ++i) - { - const struct hlsl_struct_field *field = &type->e.record.fields[i]; - struct hlsl_ir_load *field_load; - struct hlsl_ir_constant *c; - - if (!(c = hlsl_new_uint_constant(ctx, i, &var->loc))) - return; - list_add_after(&lhs->node.entry, &c->node.entry); - - /* This redundant load is expected to be deleted later by DCE. */ - if (!(field_load = hlsl_new_load_index(ctx, &lhs->src, &c->node, &var->loc))) - return; - list_add_after(&c->node.entry, &field_load->node.entry); - - 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 - hlsl_error(ctx, &field->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_SEMANTIC, - "Field '%s' is missing a semantic.", field->name); - } -} - /* Split inputs into two variables representing the semantic and temp registers, * 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. */ @@ -355,19 +356,45 @@ static void prepend_input_var_copy(struct hlsl_ctx *ctx, struct list *instrs, st return; list_add_head(instrs, &load->node.entry);
- 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); + 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; + struct hlsl_ir_constant *c; unsigned int i;
+ if (type->class == HLSL_CLASS_ARRAY || type->class == HLSL_CLASS_STRUCT) + { + struct hlsl_semantic field_semantic_copy; + struct hlsl_ir_load *element_load; + struct hlsl_struct_field *field; + + for (i = 0; i < hlsl_type_element_count(type); ++i) + { + if (type->class == HLSL_CLASS_STRUCT) + { + field = &type->e.record.fields[i]; + field_semantic_copy = field->semantic; + semantic = &field_semantic_copy; + } + + 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))) + return; + list_add_tail(instrs, &element_load->node.entry); + + append_output_copy(ctx, instrs, element_load, modifiers, semantic); + } + return; + } + if (type->class > HLSL_CLASS_LAST_NUMERIC) { struct vkd3d_string_buffer *string; @@ -375,6 +402,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 +413,13 @@ 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,42 +446,12 @@ 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) -{ - struct hlsl_type *type = rhs->node.data_type; - struct hlsl_ir_var *var = rhs->src.var; - size_t i; - - for (i = 0; i < type->e.record.field_count; ++i) - { - const struct hlsl_struct_field *field = &type->e.record.fields[i]; - struct hlsl_ir_load *field_load; - struct hlsl_ir_constant *c; - - if (!(c = hlsl_new_uint_constant(ctx, i, &var->loc))) - return; - list_add_tail(instrs, &c->node.entry); - - /* This redundant load is expected to be deleted later by DCE. */ - if (!(field_load = hlsl_new_load_index(ctx, &rhs->src, &c->node, &var->loc))) - return; - list_add_tail(instrs, &field_load->node.entry); - - 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 - hlsl_error(ctx, &field->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_SEMANTIC, - "Field '%s' is missing a semantic.", field->name); - } -} - /* Split outputs into two variables representing the temp and semantic * registers, and copy the former to the latter, so that reads from output * 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. */ @@ -461,10 +459,7 @@ static void append_output_var_copy(struct hlsl_ctx *ctx, struct list *instrs, st return; list_add_tail(instrs, &load->node.entry);
- 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); + 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 +3397,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 e1080955..460e64b2 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 (1.0, 3.0, 5.0, 7.0) +draw quad +probe (0, 0) rgba (1.0, 3.0, 5.0, 7.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 (1.0, 2.0, 5.0, 6.0) +draw quad +probe (0, 0) rgba (1.0, 2.0, 5.0, 6.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)
@@ -150,7 +150,7 @@ float4 main(in float2 t1 : TEXCOORD0, in float2 t2 : TEXCOORD0) : sv_target }
[test] -todo draw quad +draw quad todo probe (0, 0) rgba (10.0, 20.0, 1.0, 2.0)
@@ -178,8 +178,8 @@ float4 main(in float2 a : TEXCOORD0, in float b : TEXCOORD1) : sv_target }
[test] -todo draw quad -todo probe (0, 0) rgba (1.0, 2.0, 3.0, 0.0) +draw quad +probe (0, 0) rgba (1.0, 2.0, 3.0, 0.0)
% Duplicated input semantics can only have different types if they have the same layout and register types. @@ -249,7 +249,7 @@ void main(out banana bans[2])
% Output semantics cannot be mapped to more than one value. -[vertex shader fail] +[vertex shader fail todo] struct apple { float2 tex : TEXCOORD0; }; @@ -270,7 +270,7 @@ void main(out float2 a : sem0, out float2 b : SEM, inout float4 pos : sv_positio }
-[vertex shader todo] +[vertex shader] struct apple { float2 tex[2] : TEXCOORD0; }; @@ -288,5 +288,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)