mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2024-09-13 09:16:14 -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:
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
@ -254,6 +254,45 @@ bool hlsl_type_is_resource(const struct hlsl_type *type)
|
||||
}
|
||||
}
|
||||
|
||||
bool hlsl_type_is_shader(const struct hlsl_type *type)
|
||||
{
|
||||
switch (type->class)
|
||||
{
|
||||
case HLSL_CLASS_ARRAY:
|
||||
return hlsl_type_is_shader(type->e.array.type);
|
||||
|
||||
case HLSL_CLASS_COMPUTE_SHADER:
|
||||
case HLSL_CLASS_DOMAIN_SHADER:
|
||||
case HLSL_CLASS_GEOMETRY_SHADER:
|
||||
case HLSL_CLASS_HULL_SHADER:
|
||||
case HLSL_CLASS_PIXEL_SHADER:
|
||||
case HLSL_CLASS_VERTEX_SHADER:
|
||||
return true;
|
||||
|
||||
case HLSL_CLASS_SCALAR:
|
||||
case HLSL_CLASS_VECTOR:
|
||||
case HLSL_CLASS_MATRIX:
|
||||
case HLSL_CLASS_STRUCT:
|
||||
case HLSL_CLASS_DEPTH_STENCIL_STATE:
|
||||
case HLSL_CLASS_DEPTH_STENCIL_VIEW:
|
||||
case HLSL_CLASS_EFFECT_GROUP:
|
||||
case HLSL_CLASS_PASS:
|
||||
case HLSL_CLASS_RASTERIZER_STATE:
|
||||
case HLSL_CLASS_RENDER_TARGET_VIEW:
|
||||
case HLSL_CLASS_SAMPLER:
|
||||
case HLSL_CLASS_STRING:
|
||||
case HLSL_CLASS_TECHNIQUE:
|
||||
case HLSL_CLASS_TEXTURE:
|
||||
case HLSL_CLASS_UAV:
|
||||
case HLSL_CLASS_CONSTANT_BUFFER:
|
||||
case HLSL_CLASS_BLEND_STATE:
|
||||
case HLSL_CLASS_VOID:
|
||||
case HLSL_CLASS_NULL:
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Only intended to be used for derefs (after copies have been lowered to components or vectors) or
|
||||
* resources, since for both their data types span across a single regset. */
|
||||
static enum hlsl_regset type_get_regset(const struct hlsl_type *type)
|
||||
@ -1808,6 +1847,54 @@ struct hlsl_ir_node *hlsl_new_swizzle(struct hlsl_ctx *ctx, uint32_t s, unsigned
|
||||
return &swizzle->node;
|
||||
}
|
||||
|
||||
struct hlsl_ir_node *hlsl_new_compile(struct hlsl_ctx *ctx, const char *profile_name,
|
||||
struct hlsl_ir_node **args, unsigned int args_count, struct hlsl_block *args_instrs,
|
||||
const struct vkd3d_shader_location *loc)
|
||||
{
|
||||
const struct hlsl_profile_info *profile_info = NULL;
|
||||
struct hlsl_ir_compile *compile;
|
||||
struct hlsl_type *type = NULL;
|
||||
unsigned int i;
|
||||
|
||||
if (!(profile_info = hlsl_get_target_info(profile_name)))
|
||||
{
|
||||
hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_PROFILE, "Unknown profile \"%s\".", profile_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (profile_info->type == VKD3D_SHADER_TYPE_PIXEL)
|
||||
type = hlsl_get_type(ctx->cur_scope, "PixelShader", true, true);
|
||||
else if (profile_info->type == VKD3D_SHADER_TYPE_VERTEX)
|
||||
type = hlsl_get_type(ctx->cur_scope, "VertexShader", true, true);
|
||||
|
||||
if (!type)
|
||||
{
|
||||
hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_PROFILE, "Invalid profile \"%s\".", profile_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(compile = hlsl_alloc(ctx, sizeof(*compile))))
|
||||
return NULL;
|
||||
|
||||
init_node(&compile->node, HLSL_IR_COMPILE, type, loc);
|
||||
|
||||
compile->profile = profile_info;
|
||||
|
||||
hlsl_block_init(&compile->instrs);
|
||||
hlsl_block_add_block(&compile->instrs, args_instrs);
|
||||
|
||||
compile->args_count = args_count;
|
||||
if (!(compile->args = hlsl_alloc(ctx, sizeof(*compile->args) * args_count)))
|
||||
{
|
||||
vkd3d_free(compile);
|
||||
return NULL;
|
||||
}
|
||||
for (i = 0; i < compile->args_count; ++i)
|
||||
hlsl_src_from_node(&compile->args[i], args[i]);
|
||||
|
||||
return &compile->node;
|
||||
}
|
||||
|
||||
struct hlsl_ir_node *hlsl_new_stateblock_constant(struct hlsl_ctx *ctx, const char *name,
|
||||
struct vkd3d_shader_location *loc)
|
||||
{
|
||||
@ -2158,6 +2245,43 @@ static struct hlsl_ir_node *clone_index(struct hlsl_ctx *ctx, struct clone_instr
|
||||
return dst;
|
||||
}
|
||||
|
||||
static struct hlsl_ir_node *clone_compile(struct hlsl_ctx *ctx,
|
||||
struct clone_instr_map *map, struct hlsl_ir_compile *compile)
|
||||
{
|
||||
const char *profile_name = NULL;
|
||||
struct hlsl_ir_node **args;
|
||||
struct hlsl_ir_node *node;
|
||||
struct hlsl_block block;
|
||||
unsigned int i;
|
||||
|
||||
if (!(clone_block(ctx, &block, &compile->instrs, map)))
|
||||
return NULL;
|
||||
|
||||
if (!(args = hlsl_alloc(ctx, sizeof(*args) * compile->args_count)))
|
||||
{
|
||||
hlsl_block_cleanup(&block);
|
||||
return NULL;
|
||||
}
|
||||
for (i = 0; i < compile->args_count; ++i)
|
||||
{
|
||||
args[i] = map_instr(map, compile->args[i].node);
|
||||
VKD3D_ASSERT(args[i]);
|
||||
}
|
||||
|
||||
if (compile->profile)
|
||||
profile_name = compile->profile->name;
|
||||
|
||||
if (!(node = hlsl_new_compile(ctx, profile_name, args, compile->args_count, &block, &compile->node.loc)))
|
||||
{
|
||||
hlsl_block_cleanup(&block);
|
||||
vkd3d_free(args);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vkd3d_free(args);
|
||||
return node;
|
||||
}
|
||||
|
||||
static struct hlsl_ir_node *clone_stateblock_constant(struct hlsl_ctx *ctx,
|
||||
struct clone_instr_map *map, struct hlsl_ir_stateblock_constant *constant)
|
||||
{
|
||||
@ -2300,6 +2424,9 @@ static struct hlsl_ir_node *clone_instr(struct hlsl_ctx *ctx,
|
||||
case HLSL_IR_SWIZZLE:
|
||||
return clone_swizzle(ctx, map, hlsl_ir_swizzle(instr));
|
||||
|
||||
case HLSL_IR_COMPILE:
|
||||
return clone_compile(ctx, map, hlsl_ir_compile(instr));
|
||||
|
||||
case HLSL_IR_STATEBLOCK_CONSTANT:
|
||||
return clone_stateblock_constant(ctx, map, hlsl_ir_stateblock_constant(instr));
|
||||
|
||||
@ -2717,6 +2844,8 @@ const char *hlsl_node_type_to_string(enum hlsl_ir_node_type type)
|
||||
[HLSL_IR_STORE ] = "HLSL_IR_STORE",
|
||||
[HLSL_IR_SWITCH ] = "HLSL_IR_SWITCH",
|
||||
[HLSL_IR_SWIZZLE ] = "HLSL_IR_SWIZZLE",
|
||||
|
||||
[HLSL_IR_COMPILE] = "HLSL_IR_COMPILE",
|
||||
[HLSL_IR_STATEBLOCK_CONSTANT] = "HLSL_IR_STATEBLOCK_CONSTANT",
|
||||
[HLSL_IR_VSIR_INSTRUCTION_REF] = "HLSL_IR_VSIR_INSTRUCTION_REF",
|
||||
};
|
||||
@ -3166,6 +3295,25 @@ static void dump_ir_index(struct vkd3d_string_buffer *buffer, const struct hlsl_
|
||||
vkd3d_string_buffer_printf(buffer, "]");
|
||||
}
|
||||
|
||||
static void dump_ir_compile(struct hlsl_ctx *ctx, struct vkd3d_string_buffer *buffer,
|
||||
const struct hlsl_ir_compile *compile)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
vkd3d_string_buffer_printf(buffer, "compile %s {\n", compile->profile->name);
|
||||
|
||||
dump_block(ctx, buffer, &compile->instrs);
|
||||
|
||||
vkd3d_string_buffer_printf(buffer, " %10s } (", "");
|
||||
for (i = 0; i < compile->args_count; ++i)
|
||||
{
|
||||
dump_src(buffer, &compile->args[i]);
|
||||
if (i + 1 < compile->args_count)
|
||||
vkd3d_string_buffer_printf(buffer, ", ");
|
||||
}
|
||||
vkd3d_string_buffer_printf(buffer, ")");
|
||||
}
|
||||
|
||||
static void dump_ir_stateblock_constant(struct vkd3d_string_buffer *buffer,
|
||||
const struct hlsl_ir_stateblock_constant *constant)
|
||||
{
|
||||
@ -3265,6 +3413,10 @@ static void dump_instr(struct hlsl_ctx *ctx, struct vkd3d_string_buffer *buffer,
|
||||
dump_ir_swizzle(buffer, hlsl_ir_swizzle(instr));
|
||||
break;
|
||||
|
||||
case HLSL_IR_COMPILE:
|
||||
dump_ir_compile(ctx, buffer, hlsl_ir_compile(instr));
|
||||
break;
|
||||
|
||||
case HLSL_IR_STATEBLOCK_CONSTANT:
|
||||
dump_ir_stateblock_constant(buffer, hlsl_ir_stateblock_constant(instr));
|
||||
break;
|
||||
@ -3484,6 +3636,17 @@ static void free_ir_index(struct hlsl_ir_index *index)
|
||||
vkd3d_free(index);
|
||||
}
|
||||
|
||||
static void free_ir_compile(struct hlsl_ir_compile *compile)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < compile->args_count; ++i)
|
||||
hlsl_src_remove(&compile->args[i]);
|
||||
|
||||
hlsl_block_cleanup(&compile->instrs);
|
||||
vkd3d_free(compile);
|
||||
}
|
||||
|
||||
static void free_ir_stateblock_constant(struct hlsl_ir_stateblock_constant *constant)
|
||||
{
|
||||
vkd3d_free(constant->name);
|
||||
@ -3552,6 +3715,10 @@ void hlsl_free_instr(struct hlsl_ir_node *node)
|
||||
free_ir_switch(hlsl_ir_switch(node));
|
||||
break;
|
||||
|
||||
case HLSL_IR_COMPILE:
|
||||
free_ir_compile(hlsl_ir_compile(node));
|
||||
break;
|
||||
|
||||
case HLSL_IR_STATEBLOCK_CONSTANT:
|
||||
free_ir_stateblock_constant(hlsl_ir_stateblock_constant(node));
|
||||
break;
|
||||
|
@ -324,6 +324,8 @@ enum hlsl_ir_node_type
|
||||
HLSL_IR_STORE,
|
||||
HLSL_IR_SWIZZLE,
|
||||
HLSL_IR_SWITCH,
|
||||
|
||||
HLSL_IR_COMPILE,
|
||||
HLSL_IR_STATEBLOCK_CONSTANT,
|
||||
|
||||
HLSL_IR_VSIR_INSTRUCTION_REF,
|
||||
@ -864,6 +866,27 @@ struct hlsl_ir_string_constant
|
||||
char *string;
|
||||
};
|
||||
|
||||
/* Represents shader compilation call for effects, such as "CompileShader()".
|
||||
*
|
||||
* Unlike hlsl_ir_call, it is not flattened, thus, it keeps track of its
|
||||
* arguments and maintains its own instruction block. */
|
||||
struct hlsl_ir_compile
|
||||
{
|
||||
struct hlsl_ir_node node;
|
||||
|
||||
/* Special field to store the profile argument. */
|
||||
const struct hlsl_profile_info *profile;
|
||||
|
||||
/* Block containing the instructions required by the arguments of the
|
||||
* compilation call. */
|
||||
struct hlsl_block instrs;
|
||||
|
||||
/* Arguments to the compilation call. For a "compile" or "CompileShader()"
|
||||
* args[0] is an hlsl_ir_call to the specified function. */
|
||||
struct hlsl_src *args;
|
||||
unsigned int args_count;
|
||||
};
|
||||
|
||||
/* Stateblock constants are undeclared values found on state blocks or technique passes descriptions,
|
||||
* that do not concern regular pixel, vertex, or compute shaders, except for parsing. */
|
||||
struct hlsl_ir_stateblock_constant
|
||||
@ -1170,6 +1193,12 @@ static inline struct hlsl_ir_switch *hlsl_ir_switch(const struct hlsl_ir_node *n
|
||||
return CONTAINING_RECORD(node, struct hlsl_ir_switch, node);
|
||||
}
|
||||
|
||||
static inline struct hlsl_ir_compile *hlsl_ir_compile(const struct hlsl_ir_node *node)
|
||||
{
|
||||
VKD3D_ASSERT(node->type == HLSL_IR_COMPILE);
|
||||
return CONTAINING_RECORD(node, struct hlsl_ir_compile, node);
|
||||
}
|
||||
|
||||
static inline struct hlsl_ir_stateblock_constant *hlsl_ir_stateblock_constant(const struct hlsl_ir_node *node)
|
||||
{
|
||||
VKD3D_ASSERT(node->type == HLSL_IR_STATEBLOCK_CONSTANT);
|
||||
@ -1455,6 +1484,9 @@ bool hlsl_index_is_noncontiguous(struct hlsl_ir_index *index);
|
||||
bool hlsl_index_is_resource_access(struct hlsl_ir_index *index);
|
||||
bool hlsl_index_chain_has_resource_access(struct hlsl_ir_index *index);
|
||||
|
||||
struct hlsl_ir_node *hlsl_new_compile(struct hlsl_ctx *ctx, const char *profile_name,
|
||||
struct hlsl_ir_node **args, unsigned int args_count, struct hlsl_block *args_instrs,
|
||||
const struct vkd3d_shader_location *loc);
|
||||
struct hlsl_ir_node *hlsl_new_index(struct hlsl_ctx *ctx, struct hlsl_ir_node *val,
|
||||
struct hlsl_ir_node *idx, const struct vkd3d_shader_location *loc);
|
||||
struct hlsl_ir_node *hlsl_new_loop(struct hlsl_ctx *ctx,
|
||||
@ -1523,6 +1555,7 @@ unsigned int hlsl_type_minor_size(const struct hlsl_type *type);
|
||||
unsigned int hlsl_type_major_size(const struct hlsl_type *type);
|
||||
unsigned int hlsl_type_element_count(const struct hlsl_type *type);
|
||||
bool hlsl_type_is_resource(const struct hlsl_type *type);
|
||||
bool hlsl_type_is_shader(const struct hlsl_type *type);
|
||||
unsigned int hlsl_type_get_sm4_offset(const struct hlsl_type *type, unsigned int offset);
|
||||
bool hlsl_types_are_equal(const struct hlsl_type *t1, const struct hlsl_type *t2);
|
||||
|
||||
|
@ -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)))
|
||||
|
@ -4050,6 +4050,7 @@ static bool dce(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
|
||||
switch (instr->type)
|
||||
{
|
||||
case HLSL_IR_CONSTANT:
|
||||
case HLSL_IR_COMPILE:
|
||||
case HLSL_IR_EXPR:
|
||||
case HLSL_IR_INDEX:
|
||||
case HLSL_IR_LOAD:
|
||||
@ -4343,6 +4344,9 @@ static void compute_liveness_recurse(struct hlsl_block *block, unsigned int loop
|
||||
case HLSL_IR_CONSTANT:
|
||||
case HLSL_IR_STRING_CONSTANT:
|
||||
break;
|
||||
case HLSL_IR_COMPILE:
|
||||
/* Compile calls are skipped as they are only relevent to effects. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -152,6 +152,8 @@ enum vkd3d_shader_error
|
||||
VKD3D_SHADER_ERROR_HLSL_UNKNOWN_MODIFIER = 5030,
|
||||
VKD3D_SHADER_ERROR_HLSL_INVALID_STATE_BLOCK_ENTRY = 5031,
|
||||
VKD3D_SHADER_ERROR_HLSL_FAILED_FORCED_UNROLL = 5032,
|
||||
VKD3D_SHADER_ERROR_HLSL_INVALID_PROFILE = 5033,
|
||||
VKD3D_SHADER_ERROR_HLSL_MISPLACED_COMPILE = 5034,
|
||||
|
||||
VKD3D_SHADER_WARNING_HLSL_IMPLICIT_TRUNCATION = 5300,
|
||||
VKD3D_SHADER_WARNING_HLSL_DIVISION_BY_ZERO = 5301,
|
||||
|
@ -1,5 +1,5 @@
|
||||
% Test special "compile" keyword syntax to compile pixel and vertex shaders
|
||||
[pixel shader todo]
|
||||
[pixel shader]
|
||||
float4 fun() : sv_target
|
||||
{
|
||||
return 0;
|
||||
@ -13,7 +13,7 @@ sampler sam
|
||||
float4 main() : sv_target { return 0; }
|
||||
|
||||
|
||||
[pixel shader todo]
|
||||
[pixel shader]
|
||||
float4 fun() : sv_target
|
||||
{
|
||||
return 0;
|
||||
@ -31,7 +31,7 @@ float4 main() : sv_target { return 0; }
|
||||
|
||||
|
||||
% Only uniform arguments are expected, even if undefined identifiers are used.
|
||||
[pixel shader todo]
|
||||
[pixel shader]
|
||||
float4 fun(uniform float4 a, float4 b, uniform float4 c) : sv_target
|
||||
{
|
||||
return a + b + c;
|
||||
@ -185,7 +185,7 @@ float4 main() : sv_target
|
||||
|
||||
|
||||
% Default values are allowed for uniform variables.
|
||||
[pixel shader todo fail(sm>=6)]
|
||||
[pixel shader fail(sm>=6)]
|
||||
float4 fun(uniform float4 a, uniform float4 b = {1, 2, 3, 4}) : sv_target
|
||||
{
|
||||
return 8*a + b;
|
||||
@ -202,7 +202,7 @@ technique10 T1
|
||||
float4 main() : sv_target { return 0; }
|
||||
|
||||
|
||||
[pixel shader todo fail(sm>=6)]
|
||||
[pixel shader fail(sm>=6)]
|
||||
float4 fun(float4 a : COLOR0 = {-1, -2, -3, -4}, uniform float4 b = {1, 2, 3, 4}) : sv_target
|
||||
{
|
||||
return 8*a + b;
|
||||
|
Loading…
Reference in New Issue
Block a user