vkd3d-shader/hlsl: Generate IR for user-defined function calls.

This commit is contained in:
Zebediah Figura 2021-09-09 21:06:38 -05:00 committed by Alexandre Julliard
parent 30550c0831
commit b29d3489de
Notes: Alexandre Julliard 2023-01-13 22:23:38 +01:00
Approved-by: Francisco Casas (@fcasas)
Approved-by: Giovanni Mascellani (@giomasce)
Approved-by: Henri Verbeet (@hverbeet)
Approved-by: Alexandre Julliard (@julliard)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/47
9 changed files with 220 additions and 79 deletions

View File

@ -931,6 +931,19 @@ struct hlsl_ir_store *hlsl_new_store_component(struct hlsl_ctx *ctx, struct hlsl
return store;
}
struct hlsl_ir_node *hlsl_new_call(struct hlsl_ctx *ctx, const struct hlsl_ir_function_decl *decl,
const struct vkd3d_shader_location *loc)
{
struct hlsl_ir_call *call;
if (!(call = hlsl_alloc(ctx, sizeof(*call))))
return NULL;
init_node(&call->node, HLSL_IR_CALL, NULL, loc);
call->decl = decl;
return &call->node;
}
struct hlsl_ir_constant *hlsl_new_constant(struct hlsl_ctx *ctx, struct hlsl_type *type,
const struct vkd3d_shader_location *loc)
{
@ -1516,6 +1529,7 @@ const char *hlsl_node_type_to_string(enum hlsl_ir_node_type type)
{
static const char * const names[] =
{
"HLSL_IR_CALL",
"HLSL_IR_CONSTANT",
"HLSL_IR_EXPR",
"HLSL_IR_IF",
@ -1632,6 +1646,32 @@ const char *debug_hlsl_swizzle(unsigned int swizzle, unsigned int size)
return vkd3d_dbg_sprintf(".%s", string);
}
static void dump_ir_call(struct hlsl_ctx *ctx, struct vkd3d_string_buffer *buffer, const struct hlsl_ir_call *call)
{
const struct hlsl_ir_function_decl *decl = call->decl;
struct vkd3d_string_buffer *string;
const struct hlsl_ir_var *param;
if (!(string = hlsl_type_to_string(ctx, decl->return_type)))
return;
vkd3d_string_buffer_printf(buffer, "call %s %s(", string->buffer, decl->func->name);
hlsl_release_string_buffer(ctx, string);
LIST_FOR_EACH_ENTRY(param, decl->parameters, struct hlsl_ir_var, param_entry)
{
if (!(string = hlsl_type_to_string(ctx, param->data_type)))
return;
vkd3d_string_buffer_printf(buffer, "%s", string->buffer);
if (list_tail(decl->parameters) != &param->param_entry)
vkd3d_string_buffer_printf(buffer, ", ");
hlsl_release_string_buffer(ctx, string);
}
vkd3d_string_buffer_printf(buffer, ")");
}
static void dump_ir_constant(struct vkd3d_string_buffer *buffer, const struct hlsl_ir_constant *constant)
{
struct hlsl_type *type = constant->node.data_type;
@ -1678,6 +1718,8 @@ const char *debug_hlsl_expr_op(enum hlsl_ir_expr_op op)
{
static const char *const op_names[] =
{
[HLSL_OP0_VOID] = "void",
[HLSL_OP1_ABS] = "abs",
[HLSL_OP1_BIT_NOT] = "~",
[HLSL_OP1_CAST] = "cast",
@ -1863,6 +1905,10 @@ static void dump_instr(struct hlsl_ctx *ctx, struct vkd3d_string_buffer *buffer,
switch (instr->type)
{
case HLSL_IR_CALL:
dump_ir_call(ctx, buffer, hlsl_ir_call(instr));
break;
case HLSL_IR_CONSTANT:
dump_ir_constant(buffer, hlsl_ir_constant(instr));
break;
@ -1971,6 +2017,11 @@ void hlsl_free_instr_list(struct list *list)
hlsl_free_instr(node);
}
static void free_ir_call(struct hlsl_ir_call *call)
{
vkd3d_free(call);
}
static void free_ir_constant(struct hlsl_ir_constant *constant)
{
vkd3d_free(constant);
@ -2047,6 +2098,10 @@ void hlsl_free_instr(struct hlsl_ir_node *node)
switch (node->type)
{
case HLSL_IR_CALL:
free_ir_call(hlsl_ir_call(node));
break;
case HLSL_IR_CONSTANT:
free_ir_constant(hlsl_ir_constant(node));
break;

View File

@ -224,6 +224,7 @@ struct hlsl_reg
* types can be casted seamlessly to (struct hlsl_ir_node *) and vice-versa. */
enum hlsl_ir_node_type
{
HLSL_IR_CALL,
HLSL_IR_CONSTANT,
HLSL_IR_EXPR,
HLSL_IR_IF,
@ -390,6 +391,12 @@ struct hlsl_ir_function_decl
const struct hlsl_attribute *const *attrs;
};
struct hlsl_ir_call
{
struct hlsl_ir_node node;
const struct hlsl_ir_function_decl *decl;
};
struct hlsl_ir_if
{
struct hlsl_ir_node node;
@ -408,6 +415,8 @@ struct hlsl_ir_loop
enum hlsl_ir_expr_op
{
HLSL_OP0_VOID,
HLSL_OP1_ABS,
HLSL_OP1_BIT_NOT,
HLSL_OP1_CAST,
@ -696,6 +705,12 @@ struct hlsl_resource_load_params
struct hlsl_ir_node *coords, *lod, *texel_offset;
};
static inline struct hlsl_ir_call *hlsl_ir_call(const struct hlsl_ir_node *node)
{
assert(node->type == HLSL_IR_CALL);
return CONTAINING_RECORD(node, struct hlsl_ir_call, node);
}
static inline struct hlsl_ir_constant *hlsl_ir_constant(const struct hlsl_ir_node *node)
{
assert(node->type == HLSL_IR_CONSTANT);
@ -913,6 +928,8 @@ struct hlsl_ir_node *hlsl_new_binary_expr(struct hlsl_ctx *ctx, enum hlsl_ir_exp
struct hlsl_ir_constant *hlsl_new_bool_constant(struct hlsl_ctx *ctx, bool b, const struct vkd3d_shader_location *loc);
struct hlsl_buffer *hlsl_new_buffer(struct hlsl_ctx *ctx, enum hlsl_buffer_type type, const char *name,
const struct hlsl_reg_reservation *reservation, struct vkd3d_shader_location loc);
struct hlsl_ir_node *hlsl_new_call(struct hlsl_ctx *ctx, const struct hlsl_ir_function_decl *decl,
const struct vkd3d_shader_location *loc);
struct hlsl_ir_expr *hlsl_new_cast(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, struct hlsl_type *type,
const struct vkd3d_shader_location *loc);
struct hlsl_ir_constant *hlsl_new_constant(struct hlsl_ctx *ctx, struct hlsl_type *type,

View File

@ -1162,17 +1162,16 @@ static unsigned int evaluate_array_dimension(struct hlsl_ir_node *node)
FIXME("Unhandled type %s.\n", hlsl_node_type_to_string(node->type));
return 0;
case HLSL_IR_CALL:
case HLSL_IR_IF:
case HLSL_IR_JUMP:
case HLSL_IR_LOOP:
case HLSL_IR_RESOURCE_STORE:
case HLSL_IR_STORE:
WARN("Invalid node type %s.\n", hlsl_node_type_to_string(node->type));
return 0;
default:
vkd3d_unreachable();
}
vkd3d_unreachable();
}
static bool expr_compatible_data_types(struct hlsl_type *t1, struct hlsl_type *t2)
@ -2851,64 +2850,129 @@ static int intrinsic_function_name_compare(const void *a, const void *b)
}
static struct list *add_call(struct hlsl_ctx *ctx, const char *name,
struct parse_initializer *params, struct vkd3d_shader_location loc)
struct parse_initializer *args, const struct vkd3d_shader_location *loc)
{
const struct hlsl_ir_function_decl *decl;
struct intrinsic_function *intrinsic;
if ((decl = find_function_call(ctx, name, params)))
if ((decl = find_function_call(ctx, name, args)))
{
hlsl_fixme(ctx, &loc, "Call to user-defined function \"%s\".", name);
free_parse_initializer(params);
return NULL;
struct hlsl_ir_node *call;
struct hlsl_ir_var *param;
unsigned int i;
assert(args->args_count == list_count(decl->parameters));
i = 0;
LIST_FOR_EACH_ENTRY(param, decl->parameters, struct hlsl_ir_var, param_entry)
{
struct hlsl_ir_node *arg = args->args[i++];
if (!hlsl_types_are_equal(arg->data_type, param->data_type))
{
hlsl_fixme(ctx, &arg->loc, "Implicit cast of a function argument.");
continue;
}
if (param->storage_modifiers & HLSL_STORAGE_IN)
{
struct hlsl_ir_store *store;
if (!(store = hlsl_new_simple_store(ctx, param, arg)))
goto fail;
list_add_tail(args->instrs, &store->node.entry);
}
}
if (!(call = hlsl_new_call(ctx, decl, loc)))
goto fail;
list_add_tail(args->instrs, &call->entry);
i = 0;
LIST_FOR_EACH_ENTRY(param, decl->parameters, struct hlsl_ir_var, param_entry)
{
struct hlsl_ir_node *arg = args->args[i++];
if (param->storage_modifiers & HLSL_STORAGE_OUT)
{
struct hlsl_ir_load *load;
if (arg->data_type->modifiers & HLSL_MODIFIER_CONST)
hlsl_error(ctx, &arg->loc, VKD3D_SHADER_ERROR_HLSL_MODIFIES_CONST,
"Output argument to \"%s\" is const.", decl->func->name);
if (!(load = hlsl_new_var_load(ctx, param, arg->loc)))
goto fail;
list_add_tail(args->instrs, &load->node.entry);
if (!add_assignment(ctx, args->instrs, arg, ASSIGN_OP_ASSIGN, &load->node))
goto fail;
}
}
if (decl->return_var)
{
struct hlsl_ir_load *load;
if (!(load = hlsl_new_var_load(ctx, decl->return_var, *loc)))
goto fail;
list_add_tail(args->instrs, &load->node.entry);
}
else
{
struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS] = {0};
struct hlsl_ir_node *expr;
if (!(expr = hlsl_new_expr(ctx, HLSL_OP0_VOID, operands, ctx->builtin_types.Void, loc)))
goto fail;
list_add_tail(args->instrs, &expr->entry);
}
}
else if ((intrinsic = bsearch(name, intrinsic_functions, ARRAY_SIZE(intrinsic_functions),
sizeof(*intrinsic_functions), intrinsic_function_name_compare)))
{
if (intrinsic->param_count >= 0 && params->args_count != intrinsic->param_count)
if (intrinsic->param_count >= 0 && args->args_count != intrinsic->param_count)
{
hlsl_error(ctx, &loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT,
hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT,
"Wrong number of arguments to function '%s': expected %u, but got %u.",
name, intrinsic->param_count, params->args_count);
free_parse_initializer(params);
return NULL;
name, intrinsic->param_count, args->args_count);
goto fail;
}
if (intrinsic->check_numeric)
{
unsigned int i;
for (i = 0; i < params->args_count; ++i)
for (i = 0; i < args->args_count; ++i)
{
if (params->args[i]->data_type->type > HLSL_CLASS_LAST_NUMERIC)
if (args->args[i]->data_type->type > HLSL_CLASS_LAST_NUMERIC)
{
struct vkd3d_string_buffer *string;
if ((string = hlsl_type_to_string(ctx, params->args[i]->data_type)))
hlsl_error(ctx, &loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
if ((string = hlsl_type_to_string(ctx, args->args[i]->data_type)))
hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
"Wrong type for argument %u of '%s': expected a numeric type, but got '%s'.",
i + 1, name, string->buffer);
hlsl_release_string_buffer(ctx, string);
free_parse_initializer(params);
return NULL;
goto fail;
}
}
}
if (!intrinsic->handler(ctx, params, &loc))
{
free_parse_initializer(params);
return NULL;
}
if (!intrinsic->handler(ctx, args, loc))
goto fail;
}
else
{
hlsl_error(ctx, &loc, VKD3D_SHADER_ERROR_HLSL_NOT_DEFINED, "Function \"%s\" is not defined.", name);
free_parse_initializer(params);
return NULL;
hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_NOT_DEFINED, "Function \"%s\" is not defined.", name);
goto fail;
}
vkd3d_free(params->args);
return params->instrs;
vkd3d_free(args->args);
return args->instrs;
fail:
free_parse_initializer(args);
return NULL;
}
static struct list *add_constructor(struct hlsl_ctx *ctx, struct hlsl_type *type,
@ -4633,7 +4697,7 @@ primary_expr:
}
| var_identifier '(' func_arguments ')'
{
if (!($$ = add_call(ctx, $1, &$3, @1)))
if (!($$ = add_call(ctx, $1, &$3, &@1)))
YYABORT;
}
| NEW_IDENTIFIER

View File

@ -1616,6 +1616,7 @@ static bool dce(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
break;
}
case HLSL_IR_CALL:
case HLSL_IR_IF:
case HLSL_IR_JUMP:
case HLSL_IR_LOOP:
@ -1685,6 +1686,10 @@ static void compute_liveness_recurse(struct hlsl_block *block, unsigned int loop
switch (instr->type)
{
case HLSL_IR_CALL:
FIXME("We should have inlined all calls before computing liveness.\n");
break;
case HLSL_IR_STORE:
{
struct hlsl_ir_store *store = hlsl_ir_store(instr);

View File

@ -9,7 +9,7 @@ float4 main() : sv_target
% It's legal to call an undefined function in unused code, though.
[pixel shader todo]
[pixel shader]
float4 func();
@ -23,7 +23,7 @@ float4 main() : sv_target
return 0;
}
[pixel shader fail todo]
[pixel shader fail]
void func(inout float o)
{
@ -37,7 +37,7 @@ float4 main() : sv_target
return 0;
}
[pixel shader fail todo]
[pixel shader fail]
void func(inout float2 o)
{
@ -51,7 +51,7 @@ float4 main() : sv_target
return 0;
}
[pixel shader fail todo]
[pixel shader fail]
void func(out float o)
{
@ -65,7 +65,7 @@ float4 main() : sv_target
return x;
}
[pixel shader fail todo]
[pixel shader fail]
void func(inout float o)
{
@ -78,7 +78,7 @@ float4 main() : sv_target
return x;
}
[pixel shader fail todo]
[pixel shader fail]
void func()
{
@ -118,7 +118,7 @@ void func()
{
}
[pixel shader todo]
[pixel shader]
float func(in float a, out float b, inout float c)
{
@ -139,10 +139,10 @@ float4 main() : sv_target
}
[test]
todo draw quad
probe all rgba (0.5, 0.6, 0.7, 0)
draw quad
todo probe all rgba (0.5, 0.6, 0.7, 0)
[pixel shader todo]
[pixel shader]
void func(in float a, inout float2 b)
{
@ -160,5 +160,5 @@ float4 main() : sv_target
}
[test]
todo draw quad
probe all rgba (0.6, 0.1, 0.5, 0)
draw quad
todo probe all rgba (0.6, 0.1, 0.5, 0)

View File

@ -153,7 +153,7 @@ static int x = 1;
[numthreads((x = 2), 1, 1)]
void main() {}
[compute shader todo]
[compute shader]
static int x = 1;

View File

@ -38,7 +38,7 @@ float4x1 main() : sv_target
draw quad
probe all rgba (0.4, 0.3, 0.2, 0.1)
[pixel shader todo]
[pixel shader]
float3 func()
{
return float3x1(0.4, 0.3, 0.2);
@ -50,10 +50,10 @@ float4 main() : sv_target
}
[test]
todo draw quad
probe all rgba (0.4, 0.3, 0.2, 0.0)
draw quad
todo probe all rgba (0.4, 0.3, 0.2, 0.0)
[pixel shader todo]
[pixel shader]
float3 func()
{
return float1x3(0.4, 0.3, 0.2);
@ -65,10 +65,10 @@ float4 main() : sv_target
}
[test]
todo draw quad
probe all rgba (0.4, 0.3, 0.2, 0.0)
draw quad
todo probe all rgba (0.4, 0.3, 0.2, 0.0)
[pixel shader todo]
[pixel shader]
float1x3 func()
{
return float3(0.4, 0.3, 0.2);
@ -80,10 +80,10 @@ float4 main() : sv_target
}
[test]
todo draw quad
probe all rgba (0.4, 0.3, 0.2, 0.0)
draw quad
todo probe all rgba (0.4, 0.3, 0.2, 0.0)
[pixel shader todo]
[pixel shader]
float3x1 func()
{
return float3(0.4, 0.3, 0.2);
@ -95,8 +95,8 @@ float4 main() : sv_target
}
[test]
todo draw quad
probe all rgba (0.4, 0.3, 0.2, 0.0)
draw quad
todo probe all rgba (0.4, 0.3, 0.2, 0.0)
[pixel shader fail]
float3x1 func()
@ -120,7 +120,7 @@ float4 main() : sv_target
return float4(func(), 0.0);
}
[pixel shader todo]
[pixel shader]
float3 func()
{
return float4(0.4, 0.3, 0.2, 0.1);
@ -132,10 +132,10 @@ float4 main() : sv_target
}
[test]
todo draw quad
probe all rgba (0.4, 0.3, 0.2, 0.0)
draw quad
todo probe all rgba (0.4, 0.3, 0.2, 0.0)
[pixel shader todo]
[pixel shader]
float3 func()
{
return float4x1(0.4, 0.3, 0.2, 0.1);
@ -147,10 +147,10 @@ float4 main() : sv_target
}
[test]
todo draw quad
probe all rgba (0.4, 0.3, 0.2, 0.0)
draw quad
todo probe all rgba (0.4, 0.3, 0.2, 0.0)
[pixel shader todo]
[pixel shader]
float3 func()
{
return float1x4(0.4, 0.3, 0.2, 0.1);
@ -162,8 +162,8 @@ float4 main() : sv_target
}
[test]
todo draw quad
probe all rgba (0.4, 0.3, 0.2, 0.0)
draw quad
todo probe all rgba (0.4, 0.3, 0.2, 0.0)
[pixel shader fail todo]
float3x1 func()
@ -176,7 +176,7 @@ float4 main() : sv_target
return float4(func(), 0.0);
}
[pixel shader todo]
[pixel shader]
float3x1 func()
{
return float4x1(0.4, 0.3, 0.2, 0.1);
@ -188,8 +188,8 @@ float4 main() : sv_target
}
[test]
todo draw quad
probe all rgba (0.4, 0.3, 0.2, 0.0)
draw quad
todo probe all rgba (0.4, 0.3, 0.2, 0.0)
[pixel shader fail]
float3x1 func()
@ -202,7 +202,7 @@ float4 main() : sv_target
return float4(func(), 0.0);
}
[pixel shader todo]
[pixel shader]
float1x3 func()
{
return float4(0.4, 0.3, 0.2, 0.1);
@ -214,8 +214,8 @@ float4 main() : sv_target
}
[test]
todo draw quad
probe all rgba (0.4, 0.3, 0.2, 0.0)
draw quad
todo probe all rgba (0.4, 0.3, 0.2, 0.0)
[pixel shader fail]
float1x3 func()
@ -228,7 +228,7 @@ float4 main() : sv_target
return float4(func(), 0.0);
}
[pixel shader todo]
[pixel shader]
float1x3 func()
{
return float1x4(0.4, 0.3, 0.2, 0.1);
@ -240,5 +240,5 @@ float4 main() : sv_target
}
[test]
todo draw quad
probe all rgba (0.4, 0.3, 0.2, 0.0)
draw quad
todo probe all rgba (0.4, 0.3, 0.2, 0.0)

View File

@ -1,4 +1,4 @@
[pixel shader todo]
[pixel shader]
float myfunc()
{
return 0.6;
@ -12,5 +12,5 @@ float4 main() : sv_target
}
[test]
todo draw quad
probe all rgba (0.8, 0.0, 0.0, 0.0)
draw quad
todo probe all rgba (0.8, 0.0, 0.0, 0.0)

View File

@ -7,7 +7,7 @@ size (1, 1)
0.1 0.2 0.3 0.4
[compute shader todo]
[compute shader]
RWTexture2D<float4> u;
@ -23,5 +23,5 @@ void main()
}
[test]
todo dispatch 1 1 1
dispatch 1 1 1
todo probe uav 0 (0, 0) rgba (0.1, 0.3, 0.3, 0.5)