From b17923b5ba73b5d217a7a85b78ed0e7d49824544 Mon Sep 17 00:00:00 2001 From: "Anna (navi) Figueiredo Gomes" Date: Thu, 23 Jan 2025 20:27:27 +0100 Subject: [PATCH] vkd3d-shader/hlsl: Store parsed values in hlsl_ir_compile(). Makes emitting shaders from fx.c easier, and brings parsing failures upfront. Non-effect target profiles don't perform any type checks on ConstructGSWithSO(), nor use shader objects in any way, but they do check if the argument count is correct. So we create a GeometryShader object with NULL decl and profile when targeting non-effect profiles, so our type checks still work and implicit conversions aren't attempted. --- libs/vkd3d-shader/hlsl.c | 197 ++++++++++++----------- libs/vkd3d-shader/hlsl.h | 40 +++-- libs/vkd3d-shader/hlsl.y | 170 +++++++++++++++---- tests/hlsl/constructgswithso.shader_test | 2 +- 4 files changed, 256 insertions(+), 153 deletions(-) diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index 641d25539..1f1cf4a8c 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -2289,61 +2289,91 @@ struct hlsl_ir_node *hlsl_new_matrix_swizzle(struct hlsl_ctx *ctx, struct hlsl_m return &swizzle->node; } -struct hlsl_ir_node *hlsl_new_compile(struct hlsl_ctx *ctx, enum hlsl_compile_type compile_type, - const char *profile_name, struct hlsl_ir_node **args, unsigned int args_count, - struct hlsl_block *args_instrs, const struct vkd3d_shader_location *loc) +static struct hlsl_ir_compile *new_compile(struct hlsl_ctx *ctx, const struct hlsl_profile_info *profile, + struct hlsl_ir_function_decl *decl, struct hlsl_block *initializer, struct hlsl_type *type, + uint32_t stream, size_t count, const char *output_decls[4], 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; - - switch (compile_type) - { - case HLSL_COMPILE_TYPE_COMPILE: - 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; - } - - break; - - case HLSL_COMPILE_TYPE_CONSTRUCTGSWITHSO: - type = hlsl_get_type(ctx->cur_scope, "GeometryShader", true, true); - break; - } if (!(compile = hlsl_alloc(ctx, sizeof(*compile)))) return NULL; init_node(&compile->node, HLSL_IR_COMPILE, type, loc); + hlsl_block_init(&compile->initializers); + hlsl_block_add_block(&compile->initializers, initializer); - compile->compile_type = compile_type; - compile->profile = profile_info; + compile->profile = profile; + compile->decl = decl; + compile->output.stream = stream; + compile->output.count = count; - 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))) + for (size_t i = 0; i < count; ++i) { - vkd3d_free(compile); + if (output_decls[i]) + compile->output.decls[i] = hlsl_strdup(ctx, output_decls[i]); + } + + return compile; +} + +struct hlsl_ir_node *hlsl_new_compile(struct hlsl_ctx *ctx, const struct hlsl_profile_info *profile, + struct hlsl_ir_function_decl *decl, struct hlsl_block *initializer, const struct vkd3d_shader_location *loc) +{ + struct hlsl_ir_compile *compile; + struct hlsl_type *type = NULL; + + switch (profile->type) + { + case VKD3D_SHADER_TYPE_PIXEL: + type = hlsl_get_type(ctx->cur_scope, "PixelShader", true, true); + break; + + case VKD3D_SHADER_TYPE_VERTEX: + type = hlsl_get_type(ctx->cur_scope, "VertexShader", true, true); + break; + + case VKD3D_SHADER_TYPE_GEOMETRY: + type = hlsl_get_type(ctx->cur_scope, "GeometryShader", true, true); + break; + + default: + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_PROFILE, "Invalid profile \"%s\".", profile->name); + return NULL; + } + + if (!(compile = new_compile(ctx, profile, decl, initializer, type, 0, 0, NULL, loc))) + return NULL; + + return &compile->node; +} + +struct hlsl_ir_node *hlsl_new_compile_with_so(struct hlsl_ctx *ctx, struct hlsl_ir_compile *shader, + uint32_t stream, size_t count, const char *output_decls[4], const struct vkd3d_shader_location *loc) +{ + struct hlsl_type *type = hlsl_get_type(ctx->cur_scope, "GeometryShader", true, true); + const struct hlsl_profile_info *profile = NULL; + struct hlsl_ir_function_decl *decl = NULL; + struct hlsl_ir_compile *compile; + struct hlsl_block initializers; + + hlsl_block_init(&initializers); + + /* non-fx profiles allow ConstructGSWithSO() but do not use nor type-check + * its arguments, so passing in NULL for "shader" creates a dummy geometry + * shader without any decl or profile. */ + if (shader) + { + decl = shader->decl; + profile = shader->profile; + if (!(hlsl_clone_block(ctx, &initializers, &shader->initializers))) + return NULL; + } + + if (!(compile = new_compile(ctx, profile, decl, &initializers, type, stream, count, output_decls, loc))) + { + hlsl_block_cleanup(&initializers); return NULL; } - for (i = 0; i < compile->args_count; ++i) - hlsl_src_from_node(&compile->args[i], args[i]); return &compile->node; } @@ -2878,43 +2908,17 @@ static struct hlsl_ir_node *clone_sync(struct hlsl_ctx *ctx, struct hlsl_ir_sync return &dst->node; } - 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; + struct hlsl_block initializers; - if (!(clone_block(ctx, &block, &compile->instrs, map))) - return NULL; + hlsl_clone_block(ctx, &initializers, &compile->initializers); + compile = new_compile(ctx, compile->profile, compile->decl, &initializers, compile->node.data_type, + compile->output.stream, compile->output.count, compile->output.decls, &compile->node.loc); + hlsl_block_cleanup(&initializers); - 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, compile->compile_type, profile_name, - args, compile->args_count, &block, &compile->node.loc))) - { - hlsl_block_cleanup(&block); - vkd3d_free(args); - return NULL; - } - - vkd3d_free(args); - return node; + return compile ? &compile->node : NULL; } static struct hlsl_ir_node *clone_sampler_state(struct hlsl_ctx *ctx, @@ -4069,26 +4073,24 @@ static void dump_ir_sync(struct vkd3d_string_buffer *buffer, const struct hlsl_i 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); - switch (compile->compile_type) + dump_block(ctx, buffer, &compile->initializers); + + vkd3d_string_buffer_printf(buffer, " %10s }", ""); + + if (!compile->output.count) + return; + + vkd3d_string_buffer_printf(buffer, "("); + for (size_t i = 0; i < compile->output.count; ++i) { - case HLSL_COMPILE_TYPE_COMPILE: - vkd3d_string_buffer_printf(buffer, "compile %s {\n", compile->profile->name); - break; + const char *output = compile->output.decls[i]; - case HLSL_COMPILE_TYPE_CONSTRUCTGSWITHSO: - vkd3d_string_buffer_printf(buffer, "ConstructGSWithSO {\n"); - break; - } - - 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) + if (!output) + output = "NULL"; + vkd3d_string_buffer_printf(buffer, "%s", output); + if (i + 1 < compile->output.count) vkd3d_string_buffer_printf(buffer, ", "); } vkd3d_string_buffer_printf(buffer, ")"); @@ -4455,12 +4457,11 @@ static void free_ir_sync(struct hlsl_ir_sync *sync) 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); + hlsl_block_cleanup(&compile->initializers); + for (size_t i = 0; i < compile->output.count; ++i) + { + vkd3d_free((void *)compile->output.decls[i]); + } vkd3d_free(compile); } diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 6fa836402..78631531c 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -957,33 +957,28 @@ 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. */ +#define HLSL_STREAM_OUTPUT_MAX 4 + +/* Represents shader compilation call for effects, such as "CompileShader()". */ struct hlsl_ir_compile { struct hlsl_ir_node node; - enum hlsl_compile_type - { - /* A shader compilation through the CompileShader() function or the "compile" syntax. */ - HLSL_COMPILE_TYPE_COMPILE, - /* A call to ConstructGSWithSO(), which receives a geometry shader and retrieves one as well. */ - HLSL_COMPILE_TYPE_CONSTRUCTGSWITHSO, - } compile_type; - - /* Special field to store the profile argument for HLSL_COMPILE_TYPE_COMPILE. */ + /* Special field to store the profile argument. */ const struct hlsl_profile_info *profile; + struct hlsl_ir_function_decl *decl; - /* Block containing the instructions required by the arguments of the + /* Block containing the static initializers passed as arguments of the * compilation call. */ - struct hlsl_block instrs; + struct hlsl_block initializers; - /* Arguments to the compilation call. For HLSL_COMPILE_TYPE_COMPILE - * args[0] is an hlsl_ir_call to the specified function. */ - struct hlsl_src *args; - unsigned int args_count; + /* Stream Output constants, filled by a ConstructGSWithSO() call. */ + struct + { + uint32_t stream; + unsigned count; + const char *decls[HLSL_STREAM_OUTPUT_MAX]; + } output; }; /* Represents a state block initialized with the "sampler_state" keyword. */ @@ -1745,9 +1740,10 @@ bool hlsl_index_is_resource_access(struct hlsl_ir_index *index); bool hlsl_index_chain_has_resource_access(struct hlsl_ir_index *index); bool hlsl_index_chain_has_tgsm_access(struct hlsl_ir_index *index); -struct hlsl_ir_node *hlsl_new_compile(struct hlsl_ctx *ctx, enum hlsl_compile_type compile_type, - 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_compile(struct hlsl_ctx *ctx, const struct hlsl_profile_info *profile, + struct hlsl_ir_function_decl *decl, struct hlsl_block *initializer, const struct vkd3d_shader_location *loc); +struct hlsl_ir_node *hlsl_new_compile_with_so(struct hlsl_ctx *ctx, struct hlsl_ir_compile *shader, + uint32_t stream, size_t count, const char *output_decls[4], const struct vkd3d_shader_location *loc); struct hlsl_ir_node *hlsl_new_interlocked(struct hlsl_ctx *ctx, enum hlsl_interlocked_op op, struct hlsl_type *type, const struct hlsl_deref *dst, struct hlsl_ir_node *coords, struct hlsl_ir_node *cmp_value, struct hlsl_ir_node *value, const struct vkd3d_shader_location *loc); diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 0e0189986..d744498ea 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -3015,11 +3015,9 @@ static void add_void_expr(struct hlsl_ctx *ctx, struct hlsl_block *block, hlsl_block_add_expr(ctx, block, HLSL_OP0_VOID, operands, ctx->builtin_types.Void, 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) +static bool parse_function_call_arguments(struct hlsl_ctx *ctx, const 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, k; VKD3D_ASSERT(args->args_count <= func->parameters.count); @@ -3077,12 +3075,22 @@ static struct hlsl_ir_node *add_user_call(struct hlsl_ctx *ctx, } } + return true; +} + +static struct hlsl_ir_node *add_user_call(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *func, + const struct parse_initializer *args, const struct vkd3d_shader_location *loc) +{ + struct hlsl_ir_node *call; + unsigned int i; + + if (!parse_function_call_arguments(ctx, func, args, false, loc)) + return NULL; + if (!(call = hlsl_new_call(ctx, func, loc))) return NULL; - hlsl_block_add_instr(args->instrs, call); - if (is_compile) - return call; + hlsl_block_add_instr(args->instrs, call); for (i = 0; i < args->args_count; ++i) { @@ -3288,7 +3296,7 @@ static bool write_acos_or_asin(struct hlsl_ctx *ctx, if (!func) return false; - return !!add_user_call(ctx, func, params, false, loc); + return !!add_user_call(ctx, func, params, loc); } static bool intrinsic_acos(struct hlsl_ctx *ctx, @@ -3428,7 +3436,7 @@ static bool write_atan_or_atan2(struct hlsl_ctx *ctx, if (!func) return false; - return !!add_user_call(ctx, func, params, false, loc); + return !!add_user_call(ctx, func, params, loc); } static bool intrinsic_atan(struct hlsl_ctx *ctx, @@ -3611,7 +3619,7 @@ static bool write_cosh_or_sinh(struct hlsl_ctx *ctx, if (!func) return false; - return !!add_user_call(ctx, func, params, false, loc); + return !!add_user_call(ctx, func, params, loc); } static bool intrinsic_cosh(struct hlsl_ctx *ctx, @@ -3823,7 +3831,7 @@ static bool intrinsic_determinant(struct hlsl_ctx *ctx, if (!func) return false; - return !!add_user_call(ctx, func, params, false, loc); + return !!add_user_call(ctx, func, params, loc); } static bool intrinsic_distance(struct hlsl_ctx *ctx, @@ -3893,7 +3901,7 @@ static bool intrinsic_dst(struct hlsl_ctx *ctx, const struct parse_initializer * if (!func) return false; - return !!add_user_call(ctx, func, params, false, loc); + return !!add_user_call(ctx, func, params, loc); } static bool intrinsic_exp(struct hlsl_ctx *ctx, @@ -3947,7 +3955,7 @@ static bool intrinsic_faceforward(struct hlsl_ctx *ctx, if (!func) return false; - return !!add_user_call(ctx, func, params, false, loc); + return !!add_user_call(ctx, func, params, loc); } static bool intrinsic_f16tof32(struct hlsl_ctx *ctx, @@ -4143,7 +4151,7 @@ static bool intrinsic_frexp(struct hlsl_ctx *ctx, if (!func) return false; - return !!add_user_call(ctx, func, params, false, loc); + return !!add_user_call(ctx, func, params, loc); } static bool intrinsic_fwidth(struct hlsl_ctx *ctx, @@ -4170,7 +4178,7 @@ static bool intrinsic_fwidth(struct hlsl_ctx *ctx, if (!func) return false; - return !!add_user_call(ctx, func, params, false, loc); + return !!add_user_call(ctx, func, params, loc); } static bool intrinsic_isinf(struct hlsl_ctx *ctx, @@ -4270,7 +4278,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, false, loc); + return !!add_user_call(ctx, func, params, loc); } static bool intrinsic_log(struct hlsl_ctx *ctx, @@ -4371,7 +4379,7 @@ static bool intrinsic_modf(struct hlsl_ctx *ctx, if (!func) return false; - return !!add_user_call(ctx, func, params, false, loc); + return !!add_user_call(ctx, func, params, loc); } static bool intrinsic_mul(struct hlsl_ctx *ctx, @@ -4620,7 +4628,7 @@ static bool intrinsic_refract(struct hlsl_ctx *ctx, if (!func) return false; - return !!add_user_call(ctx, func, params, false, loc); + return !!add_user_call(ctx, func, params, loc); } static bool intrinsic_round(struct hlsl_ctx *ctx, @@ -4722,7 +4730,7 @@ static bool intrinsic_sincos(struct hlsl_ctx *ctx, if (!func) return false; - return !!add_user_call(ctx, func, params, false, loc); + return !!add_user_call(ctx, func, params, loc); } static bool intrinsic_sinh(struct hlsl_ctx *ctx, @@ -4757,7 +4765,7 @@ static bool intrinsic_smoothstep(struct hlsl_ctx *ctx, if (!func) return false; - return !!add_user_call(ctx, func, params, false, loc); + return !!add_user_call(ctx, func, params, loc); } static bool intrinsic_sqrt(struct hlsl_ctx *ctx, @@ -4831,7 +4839,7 @@ static bool intrinsic_tanh(struct hlsl_ctx *ctx, if (!func) return false; - return !!add_user_call(ctx, func, params, false, loc); + return !!add_user_call(ctx, func, params, loc); } static bool intrinsic_tex(struct hlsl_ctx *ctx, const struct parse_initializer *params, @@ -5356,17 +5364,109 @@ static bool intrinsic_AllMemoryBarrierWithGroupSync(struct hlsl_ctx *ctx, static bool intrinsic_ConstructGSWithSO(struct hlsl_ctx *ctx, const struct parse_initializer *params, const struct vkd3d_shader_location *loc) { - struct hlsl_ir_node *compile; + const char *strings[HLSL_STREAM_OUTPUT_MAX] = {0}; + size_t string_count = params->args_count - 1; + struct hlsl_ir_compile *compile; + struct hlsl_ir_node *node; + uint32_t stream_index = 0; + struct hlsl_ir_var *var; if (params->args_count != 2 && params->args_count != 6) + { hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT, - "Wrong number of arguments to ConstructGSWithSO(): expected 2 or 6, but got %u.", params->args_count); - - if (!(compile = hlsl_new_compile(ctx, HLSL_COMPILE_TYPE_CONSTRUCTGSWITHSO, - NULL, params->args, params->args_count, params->instrs, loc))) + "Unexpected number of arguments to ConstructGSWithSO(): expected 2 or 6, but got %u.", + params->args_count); return false; + } + + if (ctx->profile->type != VKD3D_SHADER_TYPE_EFFECT) + { + if (!(node = hlsl_new_compile_with_so(ctx, NULL, 0, 0, NULL, loc))) + return false; + hlsl_block_add_instr(params->instrs, node); + return true; + } + + node = params->args[0]; + switch (node->type) + { + case HLSL_IR_COMPILE: + compile = hlsl_ir_compile(node); + break; + + case HLSL_IR_LOAD: + var = hlsl_ir_load(node)->src.var; + if (var->data_type->class == HLSL_CLASS_ARRAY || !hlsl_type_is_shader(var->data_type)) + { + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "\"%s\" is not a shader compilation.", var->name); + return false; + } + + hlsl_fixme(ctx, loc, "Unhandled HLSL_IR_LOAD in ConstructGSWithSO()."); + return false; + + case HLSL_IR_INDEX: + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "Stream output shaders can't be constructed with array indexes."); + return false; + + default: + hlsl_fixme(ctx, loc, "Unhandled node type in ConstructGSWithSO()."); + return false; + } + + if (compile->profile->type != VKD3D_SHADER_TYPE_VERTEX && compile->profile->type != VKD3D_SHADER_TYPE_GEOMETRY) + { + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "Stream output shaders can only be constructed with vertex or geometry shaders."); + return false; + } + + if (params->args_count == 6) + { + struct hlsl_block stream_index_block; + + --string_count; + + if (!(node = hlsl_clone_instr(ctx, params->args[5]))) + return false; + + hlsl_block_init(&stream_index_block); + hlsl_block_add_instr(&stream_index_block, node); + + stream_index = evaluate_static_expression_as_uint(ctx, &stream_index_block, loc); + + hlsl_block_cleanup(&stream_index_block); + } + + for (size_t i = 0; i < string_count; ++i) + { + struct hlsl_ir_node *stream_node = params->args[i + 1]; + + switch (stream_node->type) + { + case HLSL_IR_STRING_CONSTANT: + strings[i] = hlsl_ir_string_constant(stream_node)->string; + break; + + case HLSL_IR_CONSTANT: + if (stream_node->data_type->class == HLSL_CLASS_NULL) + continue; + /* fall-through */ + default: + hlsl_error(ctx, &stream_node->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "Stream Output declarations must be a literal string."); + return false; + } + } + + VKD3D_ASSERT(string_count <= ARRAY_SIZE(strings)); + + if (!(node = hlsl_new_compile_with_so(ctx, compile, stream_index, string_count, strings, loc))) + return false; + hlsl_block_add_instr(params->instrs, node); - hlsl_block_add_instr(params->instrs, compile); return true; } @@ -5549,7 +5649,7 @@ static struct hlsl_block *add_call(struct hlsl_ctx *ctx, const char *name, if ((decl = find_function_call(ctx, name, args, false, loc))) { - if (!add_user_call(ctx, decl, args, false, loc)) + if (!add_user_call(ctx, decl, args, loc)) goto fail; } else if ((intrinsic = bsearch(name, intrinsic_functions, ARRAY_SIZE(intrinsic_functions), @@ -5608,9 +5708,10 @@ fail: 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; + const struct hlsl_profile_info *profile_info; struct hlsl_ir_function_decl *decl; struct hlsl_block *block = NULL; + struct hlsl_ir_node *compile; if (!ctx->in_state_block && ctx->cur_scope != ctx->globals) { @@ -5635,6 +5736,12 @@ static struct hlsl_block *add_shader_compilation(struct hlsl_ctx *ctx, const cha goto out; } + if (!(profile_info = hlsl_get_target_info(profile_name))) + { + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_PROFILE, "Unknown profile \"%s\".", profile_name); + goto out; + } + for (unsigned int i = 0; i < args->args_count; ++i) { if (args->args[i]->data_type->class == HLSL_CLASS_ERROR) @@ -5645,11 +5752,10 @@ static struct hlsl_block *add_shader_compilation(struct hlsl_ctx *ctx, const cha } } - if (!(call_to_compile = add_user_call(ctx, decl, args, true, loc))) + if (!parse_function_call_arguments(ctx, decl, args, true, loc)) goto out; - if (!(compile = hlsl_new_compile(ctx, HLSL_COMPILE_TYPE_COMPILE, - profile_name, &call_to_compile, 1, args->instrs, loc))) + if (!(compile = hlsl_new_compile(ctx, profile_info, decl, args->instrs, loc))) goto out; block = make_block(ctx, compile); diff --git a/tests/hlsl/constructgswithso.shader_test b/tests/hlsl/constructgswithso.shader_test index 9b8f03006..b5198be94 100644 --- a/tests/hlsl/constructgswithso.shader_test +++ b/tests/hlsl/constructgswithso.shader_test @@ -1,4 +1,4 @@ -[pixel shader todo] +[pixel shader] float4 main() : sv_target { return 0; } GeometryShader gs1 = CompileShader(gs_5_0, main());