Module: vkd3d Branch: master Commit: a6e47e155217741212955897f1b00bbfefce2d9d URL: https://source.winehq.org/git/vkd3d.git/?a=commit;h=a6e47e155217741212955897...
Author: Zebediah Figura zfigura@codeweavers.com Date: Sun Mar 28 21:46:57 2021 +0200
vkd3d-shader: Create a separate variable for input varyings.
Signed-off-by: Zebediah Figura zfigura@codeweavers.com Signed-off-by: Matteo Bruni mbruni@codeweavers.com Signed-off-by: Henri Verbeet hverbeet@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
libs/vkd3d-shader/hlsl_codegen.c | 83 ++++++++++++++++++++++++++++++++++++++-- tests/hlsl-invalid.shader_test | 11 ++++++ 2 files changed, 91 insertions(+), 3 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index e9f3699..ca38fe7 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -63,6 +63,83 @@ static void prepend_uniform_copy(struct hlsl_ctx *ctx, struct list *instrs, stru list_add_after(&load->node.entry, &store->node.entry); }
+static void prepend_input_copy(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_var *var, + struct hlsl_type *type, unsigned int field_offset, const char *semantic) +{ + struct vkd3d_string_buffer *name; + struct hlsl_ir_assignment *store; + struct hlsl_ir_constant *offset; + struct hlsl_ir_var *varying; + struct hlsl_ir_load *load; + + if (!(name = vkd3d_string_buffer_get(&ctx->string_buffers))) + { + ctx->failed = true; + return; + } + vkd3d_string_buffer_printf(name, "<input-%s>", semantic); + if (!(varying = hlsl_new_var(vkd3d_strdup(name->buffer), type, var->loc, vkd3d_strdup(semantic), NULL))) + { + vkd3d_string_buffer_release(&ctx->string_buffers, name); + ctx->failed = true; + return; + } + vkd3d_string_buffer_release(&ctx->string_buffers, name); + varying->is_input_varying = 1; + list_add_head(&ctx->globals->vars, &varying->scope_entry); + + if (!(load = hlsl_new_var_load(varying, var->loc))) + { + ctx->failed = true; + return; + } + list_add_head(instrs, &load->node.entry); + + if (!(offset = hlsl_new_uint_constant(ctx, field_offset * 4, var->loc))) + { + ctx->failed = true; + return; + } + list_add_after(&load->node.entry, &offset->node.entry); + + if (!(store = hlsl_new_assignment(var, &offset->node, &load->node, 0, var->loc))) + { + ctx->failed = true; + return; + } + list_add_after(&offset->node.entry, &store->node.entry); +} + +static void prepend_input_struct_copy(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_var *var, + struct hlsl_type *type, unsigned int field_offset) +{ + struct hlsl_struct_field *field; + + LIST_FOR_EACH_ENTRY(field, type->e.elements, struct hlsl_struct_field, entry) + { + if (field->type->type == HLSL_CLASS_STRUCT) + prepend_input_struct_copy(ctx, instrs, var, field->type, field_offset + field->reg_offset); + else if (field->semantic) + prepend_input_copy(ctx, instrs, var, field->type, field_offset + field->reg_offset, field->semantic); + else + hlsl_error(ctx, field->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_SEMANTIC, + "Field '%s' is missing a semantic.", field->name); + } +} + +/* Split input varyings into two variables representing the varying and temp + * registers, and copy the former to the latter, so that writes to input + * varyings work. */ +static void prepend_input_var_copy(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_var *var) +{ + if (var->data_type->type == HLSL_CLASS_STRUCT) + prepend_input_struct_copy(ctx, instrs, var, var->data_type, 0); + else if (var->semantic) + prepend_input_copy(ctx, instrs, var, var->data_type, 0, var->semantic); + + var->is_input_varying = 0; +} + static bool transform_ir(struct hlsl_ctx *ctx, bool (*func)(struct hlsl_ctx *ctx, struct hlsl_ir_node *, void *), struct list *instrs, void *context) { @@ -441,14 +518,12 @@ static void compute_liveness(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl
LIST_FOR_EACH_ENTRY(var, &ctx->globals->vars, struct hlsl_ir_var, scope_entry) { - if (var->is_uniform) + if (var->is_uniform || var->is_input_varying) var->first_write = 1; }
LIST_FOR_EACH_ENTRY(var, entry_func->parameters, struct hlsl_ir_var, param_entry) { - if (var->is_input_varying) - var->first_write = 1; if (var->is_output_varying) var->last_read = UINT_MAX; } @@ -475,6 +550,8 @@ int hlsl_emit_dxbc(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_fun { if (var->is_uniform) prepend_uniform_copy(ctx, entry_func->body, var); + if (var->is_input_varying) + prepend_input_var_copy(ctx, entry_func->body, var); }
while (transform_ir(ctx, fold_redundant_casts, entry_func->body, NULL)); diff --git a/tests/hlsl-invalid.shader_test b/tests/hlsl-invalid.shader_test index b30ff3d..59a0dbe 100644 --- a/tests/hlsl-invalid.shader_test +++ b/tests/hlsl-invalid.shader_test @@ -135,3 +135,14 @@ float4 main() : sv_target const float4 x; return x; } + +[pixel shader fail] +struct input +{ + float4 a; +}; + +float4 main(struct input i) : sv_target +{ + return i.a; +}