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>
This commit is contained in:
Zebediah Figura 2021-03-28 21:46:57 +02:00 committed by Alexandre Julliard
parent 9a70d57690
commit a6e47e1552
2 changed files with 91 additions and 3 deletions

View File

@ -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));

View File

@ -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;
}