mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2025-09-12 18:50:22 -07:00
vkd3d-shader/hlsl: Parse the shader 'compile' syntax.
The hlsl_ir_compile node is introduced to represent the "compile" syntax, and later the CompileShader() and ConstructGSWithSO() constructs. It basically represents a function call that remembers its arguments using hlsl_srcs and keeps its own instruction block, which is discarded when working on non-effect shaders. For shader compilations it can be asserted that args_count is 1, and that this argument (and the last node in hlsl_ir_effect_call.instrs) is a regular hlsl_ir_call pointing to the declaration of the function to be compiled.
This commit is contained in:
committed by
Henri Verbeet
parent
379cd9b7b5
commit
45f18a7838
Notes:
Henri Verbeet
2024-09-04 18:48:35 +02:00
Approved-by: Elizabeth Figura (@zfigura) Approved-by: Henri Verbeet (@hverbeet) Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/943
@@ -628,6 +628,7 @@ static struct hlsl_default_value evaluate_static_expression(struct hlsl_ctx *ctx
|
||||
case HLSL_IR_RESOURCE_LOAD:
|
||||
case HLSL_IR_RESOURCE_STORE:
|
||||
case HLSL_IR_SWITCH:
|
||||
case HLSL_IR_COMPILE:
|
||||
case HLSL_IR_STATEBLOCK_CONSTANT:
|
||||
hlsl_error(ctx, &node->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX,
|
||||
"Expected literal expression.");
|
||||
@@ -2735,13 +2736,15 @@ static struct hlsl_block *initialize_vars(struct hlsl_ctx *ctx, struct list *var
|
||||
|
||||
if (v->initializer.args_count)
|
||||
{
|
||||
unsigned int store_index = 0;
|
||||
bool is_default_values_initializer;
|
||||
unsigned int store_index = 0;
|
||||
unsigned int size, k;
|
||||
|
||||
is_default_values_initializer = (ctx->cur_buffer != ctx->globals_buffer)
|
||||
|| (var->storage_modifiers & HLSL_STORAGE_UNIFORM)
|
||||
|| ctx->cur_scope->annotations;
|
||||
if (hlsl_type_is_shader(type))
|
||||
is_default_values_initializer = false;
|
||||
|
||||
if (is_default_values_initializer)
|
||||
{
|
||||
@@ -2837,28 +2840,36 @@ static struct hlsl_block *initialize_vars(struct hlsl_ctx *ctx, struct list *var
|
||||
return initializers;
|
||||
}
|
||||
|
||||
static bool func_is_compatible_match(struct hlsl_ctx *ctx,
|
||||
const struct hlsl_ir_function_decl *decl, const struct parse_initializer *args)
|
||||
static bool func_is_compatible_match(struct hlsl_ctx *ctx, const struct hlsl_ir_function_decl *decl,
|
||||
bool is_compile, const struct parse_initializer *args)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int i, k;
|
||||
|
||||
if (decl->parameters.count < args->args_count)
|
||||
return false;
|
||||
|
||||
for (i = 0; i < args->args_count; ++i)
|
||||
k = 0;
|
||||
for (i = 0; i < decl->parameters.count; ++i)
|
||||
{
|
||||
if (!implicit_compatible_data_types(ctx, args->args[i]->data_type, decl->parameters.vars[i]->data_type))
|
||||
if (is_compile && !(decl->parameters.vars[i]->storage_modifiers & HLSL_STORAGE_UNIFORM))
|
||||
continue;
|
||||
|
||||
if (k >= args->args_count)
|
||||
{
|
||||
if (!decl->parameters.vars[i]->default_values)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!implicit_compatible_data_types(ctx, args->args[k]->data_type, decl->parameters.vars[i]->data_type))
|
||||
return false;
|
||||
|
||||
++k;
|
||||
}
|
||||
|
||||
if (args->args_count < decl->parameters.count && !decl->parameters.vars[args->args_count]->default_values)
|
||||
if (k < args->args_count)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static struct hlsl_ir_function_decl *find_function_call(struct hlsl_ctx *ctx,
|
||||
const char *name, const struct parse_initializer *args,
|
||||
const char *name, const struct parse_initializer *args, bool is_compile,
|
||||
const struct vkd3d_shader_location *loc)
|
||||
{
|
||||
struct hlsl_ir_function_decl *decl, *compatible_match = NULL;
|
||||
@@ -2871,7 +2882,7 @@ static struct hlsl_ir_function_decl *find_function_call(struct hlsl_ctx *ctx,
|
||||
|
||||
LIST_FOR_EACH_ENTRY(decl, &func->overloads, struct hlsl_ir_function_decl, entry)
|
||||
{
|
||||
if (func_is_compatible_match(ctx, decl, args))
|
||||
if (func_is_compatible_match(ctx, decl, is_compile, args))
|
||||
{
|
||||
if (compatible_match)
|
||||
{
|
||||
@@ -2892,26 +2903,35 @@ static struct hlsl_ir_node *hlsl_new_void_expr(struct hlsl_ctx *ctx, const struc
|
||||
return hlsl_new_expr(ctx, HLSL_OP0_VOID, operands, ctx->builtin_types.Void, loc);
|
||||
}
|
||||
|
||||
static bool add_user_call(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *func,
|
||||
const struct parse_initializer *args, const struct vkd3d_shader_location *loc)
|
||||
static struct hlsl_ir_node *add_user_call(struct hlsl_ctx *ctx,
|
||||
struct hlsl_ir_function_decl *func, const struct parse_initializer *args,
|
||||
bool is_compile, const struct vkd3d_shader_location *loc)
|
||||
{
|
||||
struct hlsl_ir_node *call;
|
||||
unsigned int i, j;
|
||||
unsigned int i, j, k;
|
||||
|
||||
VKD3D_ASSERT(args->args_count <= func->parameters.count);
|
||||
|
||||
for (i = 0; i < args->args_count; ++i)
|
||||
k = 0;
|
||||
for (i = 0; i < func->parameters.count; ++i)
|
||||
{
|
||||
struct hlsl_ir_var *param = func->parameters.vars[i];
|
||||
struct hlsl_ir_node *arg = args->args[i];
|
||||
struct hlsl_ir_node *arg;
|
||||
|
||||
if (is_compile && !(param->storage_modifiers & HLSL_STORAGE_UNIFORM))
|
||||
continue;
|
||||
|
||||
if (k >= args->args_count)
|
||||
break;
|
||||
arg = args->args[k];
|
||||
|
||||
if (!hlsl_types_are_equal(arg->data_type, param->data_type))
|
||||
{
|
||||
struct hlsl_ir_node *cast;
|
||||
|
||||
if (!(cast = add_cast(ctx, args->instrs, arg, param->data_type, &arg->loc)))
|
||||
return false;
|
||||
args->args[i] = cast;
|
||||
return NULL;
|
||||
args->args[k] = cast;
|
||||
arg = cast;
|
||||
}
|
||||
|
||||
@@ -2920,13 +2940,15 @@ static bool add_user_call(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *fu
|
||||
struct hlsl_ir_node *store;
|
||||
|
||||
if (!(store = hlsl_new_simple_store(ctx, param, arg)))
|
||||
return false;
|
||||
return NULL;
|
||||
hlsl_block_add_instr(args->instrs, store);
|
||||
}
|
||||
|
||||
++k;
|
||||
}
|
||||
|
||||
/* Add default values for the remaining parameters. */
|
||||
for (i = args->args_count; i < func->parameters.count; ++i)
|
||||
for (; i < func->parameters.count; ++i)
|
||||
{
|
||||
struct hlsl_ir_var *param = func->parameters.vars[i];
|
||||
unsigned int comp_count = hlsl_type_component_count(param->data_type);
|
||||
@@ -2934,6 +2956,9 @@ static bool add_user_call(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *fu
|
||||
|
||||
VKD3D_ASSERT(param->default_values);
|
||||
|
||||
if (is_compile && !(param->storage_modifiers & HLSL_STORAGE_UNIFORM))
|
||||
continue;
|
||||
|
||||
hlsl_init_simple_deref_from_var(¶m_deref, param);
|
||||
|
||||
for (j = 0; j < comp_count; ++j)
|
||||
@@ -2947,20 +2972,23 @@ static bool add_user_call(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *fu
|
||||
{
|
||||
value.u[0] = param->default_values[j].number;
|
||||
if (!(comp = hlsl_new_constant(ctx, type, &value, loc)))
|
||||
return false;
|
||||
return NULL;
|
||||
hlsl_block_add_instr(args->instrs, comp);
|
||||
|
||||
if (!hlsl_new_store_component(ctx, &store_block, ¶m_deref, j, comp))
|
||||
return false;
|
||||
return NULL;
|
||||
hlsl_block_add_block(args->instrs, &store_block);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!(call = hlsl_new_call(ctx, func, loc)))
|
||||
return false;
|
||||
return NULL;
|
||||
hlsl_block_add_instr(args->instrs, call);
|
||||
|
||||
if (is_compile)
|
||||
return call;
|
||||
|
||||
for (i = 0; i < args->args_count; ++i)
|
||||
{
|
||||
struct hlsl_ir_var *param = func->parameters.vars[i];
|
||||
@@ -2975,11 +3003,11 @@ static bool add_user_call(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *fu
|
||||
"Output argument to \"%s\" is const.", func->func->name);
|
||||
|
||||
if (!(load = hlsl_new_var_load(ctx, param, &arg->loc)))
|
||||
return false;
|
||||
return NULL;
|
||||
hlsl_block_add_instr(args->instrs, &load->node);
|
||||
|
||||
if (!add_assignment(ctx, args->instrs, arg, ASSIGN_OP_ASSIGN, &load->node))
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3000,7 +3028,7 @@ static bool add_user_call(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *fu
|
||||
hlsl_block_add_instr(args->instrs, expr);
|
||||
}
|
||||
|
||||
return true;
|
||||
return call;
|
||||
}
|
||||
|
||||
static struct hlsl_ir_node *intrinsic_float_convert_arg(struct hlsl_ctx *ctx,
|
||||
@@ -3167,7 +3195,7 @@ static bool write_acos_or_asin(struct hlsl_ctx *ctx,
|
||||
if (!func)
|
||||
return false;
|
||||
|
||||
return add_user_call(ctx, func, params, loc);
|
||||
return !!add_user_call(ctx, func, params, false, loc);
|
||||
}
|
||||
|
||||
static bool intrinsic_acos(struct hlsl_ctx *ctx,
|
||||
@@ -3316,7 +3344,7 @@ static bool write_atan_or_atan2(struct hlsl_ctx *ctx,
|
||||
if (!func)
|
||||
return false;
|
||||
|
||||
return add_user_call(ctx, func, params, loc);
|
||||
return !!add_user_call(ctx, func, params, false, loc);
|
||||
}
|
||||
|
||||
static bool intrinsic_atan(struct hlsl_ctx *ctx,
|
||||
@@ -3509,7 +3537,7 @@ static bool write_cosh_or_sinh(struct hlsl_ctx *ctx,
|
||||
if (!func)
|
||||
return false;
|
||||
|
||||
return add_user_call(ctx, func, params, loc);
|
||||
return !!add_user_call(ctx, func, params, false, loc);
|
||||
}
|
||||
|
||||
static bool intrinsic_cosh(struct hlsl_ctx *ctx,
|
||||
@@ -3736,7 +3764,7 @@ static bool intrinsic_determinant(struct hlsl_ctx *ctx,
|
||||
if (!func)
|
||||
return false;
|
||||
|
||||
return add_user_call(ctx, func, params, loc);
|
||||
return !!add_user_call(ctx, func, params, false, loc);
|
||||
}
|
||||
|
||||
static bool intrinsic_distance(struct hlsl_ctx *ctx,
|
||||
@@ -3823,7 +3851,7 @@ static bool intrinsic_faceforward(struct hlsl_ctx *ctx,
|
||||
if (!func)
|
||||
return false;
|
||||
|
||||
return add_user_call(ctx, func, params, loc);
|
||||
return !!add_user_call(ctx, func, params, false, loc);
|
||||
}
|
||||
|
||||
static bool intrinsic_f16tof32(struct hlsl_ctx *ctx,
|
||||
@@ -3928,7 +3956,7 @@ static bool intrinsic_fwidth(struct hlsl_ctx *ctx,
|
||||
if (!func)
|
||||
return false;
|
||||
|
||||
return add_user_call(ctx, func, params, loc);
|
||||
return !!add_user_call(ctx, func, params, false, loc);
|
||||
}
|
||||
|
||||
static bool intrinsic_ldexp(struct hlsl_ctx *ctx,
|
||||
@@ -4031,7 +4059,7 @@ static bool intrinsic_lit(struct hlsl_ctx *ctx,
|
||||
if (!(func = hlsl_compile_internal_function(ctx, "lit", body)))
|
||||
return false;
|
||||
|
||||
return add_user_call(ctx, func, params, loc);
|
||||
return !!add_user_call(ctx, func, params, false, loc);
|
||||
}
|
||||
|
||||
static bool intrinsic_log(struct hlsl_ctx *ctx,
|
||||
@@ -4334,7 +4362,7 @@ static bool intrinsic_refract(struct hlsl_ctx *ctx,
|
||||
if (!func)
|
||||
return false;
|
||||
|
||||
return add_user_call(ctx, func, params, loc);
|
||||
return !!add_user_call(ctx, func, params, false, loc);
|
||||
}
|
||||
|
||||
static bool intrinsic_round(struct hlsl_ctx *ctx,
|
||||
@@ -4449,7 +4477,7 @@ static bool intrinsic_smoothstep(struct hlsl_ctx *ctx,
|
||||
if (!func)
|
||||
return false;
|
||||
|
||||
return add_user_call(ctx, func, params, loc);
|
||||
return !!add_user_call(ctx, func, params, false, loc);
|
||||
}
|
||||
|
||||
static bool intrinsic_sqrt(struct hlsl_ctx *ctx,
|
||||
@@ -4525,7 +4553,7 @@ static bool intrinsic_tanh(struct hlsl_ctx *ctx,
|
||||
if (!func)
|
||||
return false;
|
||||
|
||||
return add_user_call(ctx, func, params, loc);
|
||||
return !!add_user_call(ctx, func, params, false, loc);
|
||||
}
|
||||
|
||||
static bool intrinsic_tex(struct hlsl_ctx *ctx, const struct parse_initializer *params,
|
||||
@@ -5004,9 +5032,9 @@ static struct hlsl_block *add_call(struct hlsl_ctx *ctx, const char *name,
|
||||
struct intrinsic_function *intrinsic;
|
||||
struct hlsl_ir_function_decl *decl;
|
||||
|
||||
if ((decl = find_function_call(ctx, name, args, loc)))
|
||||
if ((decl = find_function_call(ctx, name, args, false, loc)))
|
||||
{
|
||||
if (!add_user_call(ctx, decl, args, loc))
|
||||
if (!add_user_call(ctx, decl, args, false, loc))
|
||||
goto fail;
|
||||
}
|
||||
else if ((intrinsic = bsearch(name, intrinsic_functions, ARRAY_SIZE(intrinsic_functions),
|
||||
@@ -5062,6 +5090,53 @@ fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct hlsl_block *add_shader_compilation(struct hlsl_ctx *ctx, const char *profile_name,
|
||||
const char *function_name, struct parse_initializer *args, const struct vkd3d_shader_location *loc)
|
||||
{
|
||||
struct hlsl_ir_node *compile, *call_to_compile = NULL;
|
||||
struct hlsl_ir_function_decl *decl;
|
||||
|
||||
if (!ctx->in_state_block && ctx->cur_scope != ctx->globals)
|
||||
{
|
||||
hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_MISPLACED_COMPILE,
|
||||
"Shader compilation statements must be in global scope or a state block.");
|
||||
free_parse_initializer(args);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(decl = find_function_call(ctx, function_name, args, true, loc)))
|
||||
{
|
||||
if (rb_get(&ctx->functions, function_name))
|
||||
{
|
||||
hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_NOT_DEFINED,
|
||||
"No compatible \"%s\" declaration with %u uniform parameters found.",
|
||||
function_name, args->args_count);
|
||||
}
|
||||
else
|
||||
{
|
||||
hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_NOT_DEFINED,
|
||||
"Function \"%s\" is not defined.", function_name);
|
||||
}
|
||||
free_parse_initializer(args);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(call_to_compile = add_user_call(ctx, decl, args, true, loc)))
|
||||
{
|
||||
free_parse_initializer(args);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(compile = hlsl_new_compile(ctx, profile_name, &call_to_compile, 1, args->instrs, loc)))
|
||||
{
|
||||
free_parse_initializer(args);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
free_parse_initializer(args);
|
||||
return make_block(ctx, compile);
|
||||
}
|
||||
|
||||
static struct hlsl_block *add_constructor(struct hlsl_ctx *ctx, struct hlsl_type *type,
|
||||
struct parse_initializer *params, const struct vkd3d_shader_location *loc)
|
||||
{
|
||||
@@ -8393,6 +8468,18 @@ primary_expr:
|
||||
{
|
||||
$$ = $2;
|
||||
}
|
||||
|
||||
| KW_COMPILE any_identifier var_identifier '(' func_arguments ')'
|
||||
{
|
||||
if (!($$ = add_shader_compilation(ctx, $2, $3, &$5, &@1)))
|
||||
{
|
||||
vkd3d_free($2);
|
||||
vkd3d_free($3);
|
||||
YYABORT;
|
||||
}
|
||||
vkd3d_free($2);
|
||||
vkd3d_free($3);
|
||||
}
|
||||
| var_identifier '(' func_arguments ')'
|
||||
{
|
||||
if (!($$ = add_call(ctx, $1, &$3, &@1)))
|
||||
|
||||
Reference in New Issue
Block a user