diff --git a/Makefile.am b/Makefile.am index c86715108bc51aaa235a0fe4e79975fc2d47ddde..1c8ef1235d316e2df23a6f170f6a35a91eb263a5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -88,6 +88,7 @@ vkd3d_shader_tests = \ tests/hlsl/compute.shader_test \ tests/hlsl/conditional.shader_test \ tests/hlsl/const.shader_test \ + tests/hlsl/constructgswithso.shader_test \ tests/hlsl/coverage.shader_test \ tests/hlsl/cross.shader_test \ tests/hlsl/d3dcolor-to-ubyte4.shader_test \ diff --git a/libs/vkd3d-shader/fx.c b/libs/vkd3d-shader/fx.c index 2c2e486aa0e69a731898fd3bce4038f858168514..1314bc09e73807bc1c54ba6b3ba54987e2a87307 100644 --- a/libs/vkd3d-shader/fx.c +++ b/libs/vkd3d-shader/fx.c @@ -570,6 +570,9 @@ static const char * get_fx_4_type_name(const struct hlsl_type *type) case HLSL_CLASS_VERTEX_SHADER: return "VertexShader"; + case HLSL_CLASS_GEOMETRY_SHADER: + return "GeometryShader"; + case HLSL_CLASS_PIXEL_SHADER: return "PixelShader"; diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index 6f737be2e2ad9f7fad18a1744e87357a0a57f044..895a0265711240d5c04b51c861bff78d86f1302e 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -969,6 +969,7 @@ static const char * get_case_insensitive_typename(const char *name) { "dword", "float", + "geometryshader", "matrix", "pixelshader", "texture", @@ -1847,30 +1848,40 @@ 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) +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) { 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))) + switch (compile_type) { - hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_PROFILE, "Unknown profile \"%s\".", profile_name); - return NULL; - } + 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 (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 (!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)))) @@ -1878,6 +1889,7 @@ struct hlsl_ir_node *hlsl_new_compile(struct hlsl_ctx *ctx, const char *profile_ init_node(&compile->node, HLSL_IR_COMPILE, type, loc); + compile->compile_type = compile_type; compile->profile = profile_info; hlsl_block_init(&compile->instrs); @@ -2271,7 +2283,8 @@ static struct hlsl_ir_node *clone_compile(struct hlsl_ctx *ctx, if (compile->profile) profile_name = compile->profile->name; - if (!(node = hlsl_new_compile(ctx, profile_name, args, compile->args_count, &block, &compile->node.loc))) + 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); @@ -3300,7 +3313,16 @@ static void dump_ir_compile(struct hlsl_ctx *ctx, struct vkd3d_string_buffer *bu { unsigned int i; - vkd3d_string_buffer_printf(buffer, "compile %s {\n", compile->profile->name); + switch (compile->compile_type) + { + case HLSL_COMPILE_TYPE_COMPILE: + vkd3d_string_buffer_printf(buffer, "compile %s {\n", compile->profile->name); + break; + + case HLSL_COMPILE_TYPE_CONSTRUCTGSWITHSO: + vkd3d_string_buffer_printf(buffer, "ConstructGSWithSO {\n"); + break; + } dump_block(ctx, buffer, &compile->instrs); diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 6e61db748b4b208f78e381b046c38bf4956e7ced..51ef19449a89a0ec8dbb5840d31510f2b0705d34 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -875,14 +875,22 @@ struct hlsl_ir_compile { struct hlsl_ir_node node; - /* Special field to store the profile argument. */ + 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. */ 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()" + /* 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; @@ -1491,9 +1499,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_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_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, diff --git a/libs/vkd3d-shader/hlsl.l b/libs/vkd3d-shader/hlsl.l index e5472709a8c08a5025ede58629b2c19aeb30d92a..b7c242661e3088a95a9cd611f204eab770a576b1 100644 --- a/libs/vkd3d-shader/hlsl.l +++ b/libs/vkd3d-shader/hlsl.l @@ -82,6 +82,7 @@ ComputeShader {return KW_COMPUTESHADER; } compile {return KW_COMPILE; } CompileShader {return KW_COMPILESHADER; } const {return KW_CONST; } +ConstructGSWithSO {return KW_CONSTRUCTGSWITHSO; } continue {return KW_CONTINUE; } DepthStencilState {return KW_DEPTHSTENCILSTATE; } DepthStencilView {return KW_DEPTHSTENCILVIEW; } diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 60e196c63ccb50d6466ec30f3c5fe0b28c367b50..489fbd55828d6bbe36708835ce54eed09931ea60 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -609,6 +609,7 @@ static struct hlsl_default_value evaluate_static_expression(struct hlsl_ctx *ctx { switch (node->type) { + case HLSL_IR_COMPILE: case HLSL_IR_CONSTANT: case HLSL_IR_EXPR: case HLSL_IR_STRING_CONSTANT: @@ -627,7 +628,6 @@ 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."); @@ -1227,7 +1227,8 @@ static bool add_typedef(struct hlsl_ctx *ctx, struct hlsl_type *const orig_type, } static void initialize_var_components(struct hlsl_ctx *ctx, struct hlsl_block *instrs, - struct hlsl_ir_var *dst, unsigned int *store_index, struct hlsl_ir_node *src); + struct hlsl_ir_var *dst, unsigned int *store_index, struct hlsl_ir_node *src, + bool is_default_values_initializer); static bool add_func_parameter(struct hlsl_ctx *ctx, struct hlsl_func_parameters *parameters, struct parse_parameter *param, const struct vkd3d_shader_location *loc) @@ -1285,7 +1286,8 @@ static bool add_func_parameter(struct hlsl_ctx *ctx, struct hlsl_func_parameters for (i = 0; i < param->initializer.args_count; ++i) { - initialize_var_components(ctx, param->initializer.instrs, var, &store_index, param->initializer.args[i]); + initialize_var_components(ctx, param->initializer.instrs, var, + &store_index, param->initializer.args[i], true); } free_parse_initializer(¶m->initializer); @@ -2368,7 +2370,8 @@ static unsigned int get_component_index_from_default_initializer_index(struct hl } static void initialize_var_components(struct hlsl_ctx *ctx, struct hlsl_block *instrs, - struct hlsl_ir_var *dst, unsigned int *store_index, struct hlsl_ir_node *src) + struct hlsl_ir_var *dst, unsigned int *store_index, struct hlsl_ir_node *src, + bool is_default_values_initializer) { unsigned int src_comp_count = hlsl_type_component_count(src->data_type); struct hlsl_deref dst_deref; @@ -2387,23 +2390,43 @@ static void initialize_var_components(struct hlsl_ctx *ctx, struct hlsl_block *i dst_comp_type = hlsl_type_get_component_type(ctx, dst->data_type, *store_index); - if (dst->default_values) + if (is_default_values_initializer) { struct hlsl_default_value default_value = {0}; unsigned int dst_index; - if (!hlsl_clone_block(ctx, &block, instrs)) - return; - default_value = evaluate_static_expression(ctx, &block, dst_comp_type, &src->loc); + if (hlsl_is_numeric_type(dst_comp_type)) + { + if (src->type == HLSL_IR_COMPILE) + { + /* Default values are discarded if they contain an object + * literal expression for a numeric component. */ + if (dst->default_values) + { + hlsl_warning(ctx, &src->loc, VKD3D_SHADER_WARNING_HLSL_IGNORED_DEFAULT_VALUE, + "Component %u in variable '%s' initializer is object literal. Default values discarded.", + k, dst->name); + vkd3d_free(dst->default_values); + dst->default_values = NULL; + } + } + else + { + if (!hlsl_clone_block(ctx, &block, instrs)) + return; + default_value = evaluate_static_expression(ctx, &block, dst_comp_type, &src->loc); - if (dst->is_param) - dst_index = *store_index; - else - dst_index = get_component_index_from_default_initializer_index(ctx, dst->data_type, *store_index); + if (dst->is_param) + dst_index = *store_index; + else + dst_index = get_component_index_from_default_initializer_index(ctx, dst->data_type, *store_index); - dst->default_values[dst_index] = default_value; + if (dst->default_values) + dst->default_values[dst_index] = default_value; - hlsl_block_cleanup(&block); + hlsl_block_cleanup(&block); + } + } } else { @@ -2793,7 +2816,8 @@ static struct hlsl_block *initialize_vars(struct hlsl_ctx *ctx, struct list *var for (k = 0; k < v->initializer.args_count; ++k) { - initialize_var_components(ctx, v->initializer.instrs, var, &store_index, v->initializer.args[k]); + initialize_var_components(ctx, v->initializer.instrs, var, + &store_index, v->initializer.args[k], is_default_values_initializer); } if (is_default_values_initializer) @@ -4785,17 +4809,17 @@ static bool intrinsic_tex(struct hlsl_ctx *ctx, const struct parse_initializer * if (!(var = hlsl_new_synthetic_var(ctx, "coords", hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, 2), loc))) return false; - initialize_var_components(ctx, params->instrs, var, &idx, coords); + initialize_var_components(ctx, params->instrs, var, &idx, coords, false); if (hlsl_version_ge(ctx, 4, 0)) { if (!(half = hlsl_new_float_constant(ctx, 0.5f, loc))) return false; hlsl_block_add_instr(params->instrs, half); - initialize_var_components(ctx, params->instrs, var, &idx, half); + initialize_var_components(ctx, params->instrs, var, &idx, half, false); } else - initialize_var_components(ctx, params->instrs, var, &idx, coords); + initialize_var_components(ctx, params->instrs, var, &idx, coords, false); if (!(load = hlsl_new_var_load(ctx, var, loc))) return false; @@ -5224,7 +5248,38 @@ static struct hlsl_block *add_shader_compilation(struct hlsl_ctx *ctx, const cha return NULL; } - if (!(compile = hlsl_new_compile(ctx, profile_name, &call_to_compile, 1, args->instrs, loc))) + if (!(compile = hlsl_new_compile(ctx, HLSL_COMPILE_TYPE_COMPILE, + 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_compile_variant(struct hlsl_ctx *ctx, enum hlsl_compile_type compile_type, + struct parse_initializer *args, const struct vkd3d_shader_location *loc) +{ + struct hlsl_ir_node *compile; + + switch (compile_type) + { + case HLSL_COMPILE_TYPE_COMPILE: + vkd3d_unreachable(); + + case HLSL_COMPILE_TYPE_CONSTRUCTGSWITHSO: + if (args->args_count != 2 && args->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.", + args->args_count); + } + break; + } + + if (!(compile = hlsl_new_compile(ctx, compile_type, NULL, args->args, args->args_count, args->instrs, loc))) { free_parse_initializer(args); return NULL; @@ -5245,7 +5300,7 @@ static struct hlsl_block *add_constructor(struct hlsl_ctx *ctx, struct hlsl_type return NULL; for (i = 0; i < params->args_count; ++i) - initialize_var_components(ctx, params->instrs, var, &idx, params->args[i]); + initialize_var_components(ctx, params->instrs, var, &idx, params->args[i], false); if (!(load = hlsl_new_var_load(ctx, var, loc))) return NULL; @@ -6235,6 +6290,7 @@ static bool state_block_add_entry(struct hlsl_state_block *state_block, struct h %token KW_COMPILESHADER %token KW_COMPUTESHADER %token KW_CONST +%token KW_CONSTRUCTGSWITHSO %token KW_CONTINUE %token KW_DEFAULT %token KW_DEPTHSTENCILSTATE @@ -7796,6 +7852,11 @@ stateblock_lhs_identifier: if (!($$ = hlsl_strdup(ctx, "vertexshader"))) YYABORT; } + | KW_GEOMETRYSHADER + { + if (!($$ = hlsl_strdup(ctx, "geometryshader"))) + YYABORT; + } state_block_index_opt: %empty @@ -8590,6 +8651,11 @@ primary_expr: vkd3d_free($3); vkd3d_free($5); } + | KW_CONSTRUCTGSWITHSO '(' func_arguments ')' + { + if (!($$ = add_compile_variant(ctx, HLSL_COMPILE_TYPE_CONSTRUCTGSWITHSO, &$3, &@1))) + YYABORT; + } | var_identifier '(' func_arguments ')' { if (!($$ = add_call(ctx, $1, &$3, &@1))) diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 6442943225929529141d402d82788e8c3b514f30..205da5c24e8aac52221262501d830450ac9507c4 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -165,6 +165,7 @@ enum vkd3d_shader_error VKD3D_SHADER_WARNING_HLSL_IMAGINARY_NUMERIC_RESULT = 5303, VKD3D_SHADER_WARNING_HLSL_NON_FINITE_RESULT = 5304, VKD3D_SHADER_WARNING_HLSL_IGNORED_ATTRIBUTE = 5305, + VKD3D_SHADER_WARNING_HLSL_IGNORED_DEFAULT_VALUE = 5306, VKD3D_SHADER_ERROR_GLSL_INTERNAL = 6000, diff --git a/tests/hlsl/annotations.shader_test b/tests/hlsl/annotations.shader_test index 4f4f4d670f8e87ef07a1840ce42e1433dabc1e0e..5db5dae32b857cf06f0082c7b7ca03193728aa35 100644 --- a/tests/hlsl/annotations.shader_test +++ b/tests/hlsl/annotations.shader_test @@ -83,7 +83,7 @@ technique10 // Without initializer technique10 < int a; > {} -[effect fail] +[effect fail todo] // Only numeric types and strings are allowed technique10 < DepthStencilState ds = { 0 }; > {} diff --git a/tests/hlsl/array-dimension.shader_test b/tests/hlsl/array-dimension.shader_test index 142fa224326ad75c160aa8e8db2c229be4870fbc..672f035a189f096556ebd998f158fc3b072ed57d 100644 --- a/tests/hlsl/array-dimension.shader_test +++ b/tests/hlsl/array-dimension.shader_test @@ -20,3 +20,11 @@ float4 main() : sv_target [test] todo(sm<6) draw quad probe (0, 0) rgba (0.1, 0.1, 0.2, 0.4) + + +[pixel shader fail] +float4 fun() { return 0; }; + +float a[CompileShader(ps_2_0, main())]; + +float4 main() : sv_target { return 0; } diff --git a/tests/hlsl/constructgswithso.shader_test b/tests/hlsl/constructgswithso.shader_test new file mode 100644 index 0000000000000000000000000000000000000000..50e5cbed0106b0ec1a26f5063f184ad00778fcfb --- /dev/null +++ b/tests/hlsl/constructgswithso.shader_test @@ -0,0 +1,35 @@ +[pixel shader todo] +float4 main() : sv_target { return 0; } + +GeometryShader gs1 = CompileShader(gs_5_0, main()); +GeometryShader gs2 = ConstructGSWithSO(gs1, "random_string", "another_string", NULL, NULL, 1); + +technique11 +{ + pass + { + SetGeometryShader(gs2); + } +} + +% ConstructGSWithSO for pixel shaders parses with either 2 or 6 arguments, without doing type checking. +[pixel shader fail(sm<6)] +float4 main() : sv_target { return 0; } +GeometryShader gs1 = CompileShader(gs_5_0, main()); +GeometryShader gs2 = ConstructGSWithSO(gs1); + +[pixel shader] +float4 main() : sv_target { return 0; } +GeometryShader gs2 = ConstructGSWithSO("foo", "bar"); + +[pixel shader fail(sm<6)] +float4 main() : sv_target { return 0; } +GeometryShader gs2 = ConstructGSWithSO(1, 2, 3); + +[pixel shader] +float4 main() : sv_target { return 0; } +GeometryShader gs2 = ConstructGSWithSO("foo", "bar", float2(42, 42), 3, 4, NULL); + +[pixel shader fail(sm<6)] +float4 main() : sv_target { return 0; } +GeometryShader gs2 = ConstructGSWithSO(1, 2, 3, 4, 5, 6, 7); diff --git a/tests/hlsl/default-values.shader_test b/tests/hlsl/default-values.shader_test index 0d319f4dbd53d8b9eb0f342485d7cee48f401c00..6245ffc648f4f6eee829491d020b85b21a2ec634 100644 --- a/tests/hlsl/default-values.shader_test +++ b/tests/hlsl/default-values.shader_test @@ -294,6 +294,17 @@ float4 main() : sv_target } +% This compiles but default values for 'p' aren't written to the output binary. +[pixel shader fail(sm>=6)] +float4 fun() { return 0; }; +float2 p = {5, CompileShader(ps_2_0, fun())}; + +float4 main() : sv_target +{ + return p.xyxy; +} + + [require] shader model >= 5.0 diff --git a/tests/hlsl/effect-compile.shader_test b/tests/hlsl/effect-compile.shader_test index 7155fc5692186f58303699c729fc077b53de64c3..48a1dd800c00bc8203359e434af4fa46cf10f7a8 100644 --- a/tests/hlsl/effect-compile.shader_test +++ b/tests/hlsl/effect-compile.shader_test @@ -161,13 +161,13 @@ float4 main() : sv_target { return 0; } PixelShader ps1 = {42}; // braces make the type checking more permissive. % This compiles, but the default value of "f" is not written. -[pixel shader todo fail(sm>=6)] +[pixel shader fail(sm>=6)] float4 fun() : sv_target { return 0; } float f = {CompileShader(ps_2_0, fun())}; float4 main() : sv_target { return f; } % This also compiles, but the default value of "f" is not written. -[pixel shader todo fail(sm>=6)] +[pixel shader fail(sm>=6)] float4 fun() : sv_target { return 0; } float4 f = {1, 2, compile ps_2_0 fun(), 4}; float4 main() : sv_target { return f; } @@ -225,7 +225,7 @@ shader model < 6.0 % The following test segfaults on DXC. -[pixel shader todo] +[pixel shader] float f; float4 foo(uniform float r) : sv_target { return r; } @@ -247,7 +247,7 @@ technique float4 main() : sv_target { return 0; } [test] -todo draw quad +todo(glsl) draw quad probe (0, 0) rgba (0, 0, 0, 0)