From 090df488ba69390920e85b763ddb7a5299f5da84 Mon Sep 17 00:00:00 2001 From: Francisco Casas Date: Fri, 14 Jun 2024 19:59:21 -0400 Subject: [PATCH] vkd3d-shader/hlsl: Parse string constants. --- libs/vkd3d-shader/hlsl.c | 75 +++++++++++++++---- libs/vkd3d-shader/hlsl.h | 16 ++++ libs/vkd3d-shader/hlsl.l | 9 +++ libs/vkd3d-shader/hlsl.y | 22 ++++++ libs/vkd3d-shader/hlsl_codegen.c | 2 + tests/hlsl/attributes.shader_test | 6 +- .../state-block-function-syntax.shader_test | 2 +- tests/hlsl/state-block-syntax.shader_test | 4 +- 8 files changed, 116 insertions(+), 20 deletions(-) diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index 62a3d92d..230c84d2 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -1499,6 +1499,24 @@ struct hlsl_ir_node *hlsl_new_uint_constant(struct hlsl_ctx *ctx, unsigned int n return hlsl_new_constant(ctx, hlsl_get_scalar_type(ctx, HLSL_TYPE_UINT), &value, loc); } +struct hlsl_ir_node *hlsl_new_string_constant(struct hlsl_ctx *ctx, const char *str, + const struct vkd3d_shader_location *loc) +{ + struct hlsl_ir_string_constant *s; + + if (!(s = hlsl_alloc(ctx, sizeof(*s)))) + return NULL; + + init_node(&s->node, HLSL_IR_STRING_CONSTANT, ctx->builtin_types.string, loc); + + if (!(s->string = hlsl_strdup(ctx, str))) + { + hlsl_free_instr(&s->node); + return NULL; + } + return &s->node; +} + struct hlsl_ir_node *hlsl_new_expr(struct hlsl_ctx *ctx, enum hlsl_ir_expr_op op, struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS], struct hlsl_type *data_type, const struct vkd3d_shader_location *loc) @@ -2054,6 +2072,11 @@ static struct hlsl_ir_node *clone_resource_store(struct hlsl_ctx *ctx, return &dst->node; } +static struct hlsl_ir_node *clone_string_constant(struct hlsl_ctx *ctx, struct hlsl_ir_string_constant *src) +{ + return hlsl_new_string_constant(ctx, src->string, &src->node.loc); +} + static struct hlsl_ir_node *clone_store(struct hlsl_ctx *ctx, struct clone_instr_map *map, struct hlsl_ir_store *src) { struct hlsl_ir_store *dst; @@ -2220,6 +2243,9 @@ static struct hlsl_ir_node *clone_instr(struct hlsl_ctx *ctx, case HLSL_IR_RESOURCE_STORE: return clone_resource_store(ctx, map, hlsl_ir_resource_store(instr)); + case HLSL_IR_STRING_CONSTANT: + return clone_string_constant(ctx, hlsl_ir_string_constant(instr)); + case HLSL_IR_STORE: return clone_store(ctx, map, hlsl_ir_store(instr)); @@ -2626,19 +2652,21 @@ const char *hlsl_node_type_to_string(enum hlsl_ir_node_type type) { static const char * const names[] = { - [HLSL_IR_CALL ] = "HLSL_IR_CALL", - [HLSL_IR_CONSTANT ] = "HLSL_IR_CONSTANT", - [HLSL_IR_EXPR ] = "HLSL_IR_EXPR", - [HLSL_IR_IF ] = "HLSL_IR_IF", - [HLSL_IR_INDEX ] = "HLSL_IR_INDEX", - [HLSL_IR_LOAD ] = "HLSL_IR_LOAD", - [HLSL_IR_LOOP ] = "HLSL_IR_LOOP", - [HLSL_IR_JUMP ] = "HLSL_IR_JUMP", - [HLSL_IR_RESOURCE_LOAD ] = "HLSL_IR_RESOURCE_LOAD", - [HLSL_IR_RESOURCE_STORE] = "HLSL_IR_RESOURCE_STORE", - [HLSL_IR_STORE ] = "HLSL_IR_STORE", - [HLSL_IR_SWITCH ] = "HLSL_IR_SWITCH", - [HLSL_IR_SWIZZLE ] = "HLSL_IR_SWIZZLE", + [HLSL_IR_CALL ] = "HLSL_IR_CALL", + [HLSL_IR_CONSTANT ] = "HLSL_IR_CONSTANT", + [HLSL_IR_EXPR ] = "HLSL_IR_EXPR", + [HLSL_IR_IF ] = "HLSL_IR_IF", + [HLSL_IR_INDEX ] = "HLSL_IR_INDEX", + [HLSL_IR_LOAD ] = "HLSL_IR_LOAD", + [HLSL_IR_LOOP ] = "HLSL_IR_LOOP", + [HLSL_IR_JUMP ] = "HLSL_IR_JUMP", + [HLSL_IR_RESOURCE_LOAD ] = "HLSL_IR_RESOURCE_LOAD", + [HLSL_IR_RESOURCE_STORE ] = "HLSL_IR_RESOURCE_STORE", + [HLSL_IR_STRING_CONSTANT] = "HLSL_IR_STRING_CONSTANT", + [HLSL_IR_STORE ] = "HLSL_IR_STORE", + [HLSL_IR_SWITCH ] = "HLSL_IR_SWITCH", + [HLSL_IR_SWIZZLE ] = "HLSL_IR_SWIZZLE", + [HLSL_IR_STATEBLOCK_CONSTANT] = "HLSL_IR_STATEBLOCK_CONSTANT", }; if (type >= ARRAY_SIZE(names)) @@ -3044,6 +3072,11 @@ static void dump_ir_resource_store(struct vkd3d_string_buffer *buffer, const str vkd3d_string_buffer_printf(buffer, ")"); } +static void dump_ir_string(struct vkd3d_string_buffer *buffer, const struct hlsl_ir_string_constant *string) +{ + vkd3d_string_buffer_printf(buffer, "\"%s\"", debugstr_a(string->string)); +} + static void dump_ir_store(struct vkd3d_string_buffer *buffer, const struct hlsl_ir_store *store) { vkd3d_string_buffer_printf(buffer, "= ("); @@ -3163,6 +3196,10 @@ static void dump_instr(struct hlsl_ctx *ctx, struct vkd3d_string_buffer *buffer, dump_ir_resource_store(buffer, hlsl_ir_resource_store(instr)); break; + case HLSL_IR_STRING_CONSTANT: + dump_ir_string(buffer, hlsl_ir_string_constant(instr)); + break; + case HLSL_IR_STORE: dump_ir_store(buffer, hlsl_ir_store(instr)); break; @@ -3341,6 +3378,12 @@ static void free_ir_resource_load(struct hlsl_ir_resource_load *load) vkd3d_free(load); } +static void free_ir_string_constant(struct hlsl_ir_string_constant *string) +{ + vkd3d_free(string->string); + vkd3d_free(string); +} + static void free_ir_resource_store(struct hlsl_ir_resource_store *store) { hlsl_cleanup_deref(&store->resource); @@ -3425,6 +3468,10 @@ void hlsl_free_instr(struct hlsl_ir_node *node) free_ir_resource_load(hlsl_ir_resource_load(node)); break; + case HLSL_IR_STRING_CONSTANT: + free_ir_string_constant(hlsl_ir_string_constant(node)); + break; + case HLSL_IR_RESOURCE_STORE: free_ir_resource_store(hlsl_ir_resource_store(node)); break; @@ -3868,6 +3915,7 @@ static void declare_predefined_types(struct hlsl_ctx *ctx) ctx->builtin_types.sampler[bt] = type; } + ctx->builtin_types.string = hlsl_new_simple_type(ctx, "STRING", HLSL_CLASS_STRING); ctx->builtin_types.Void = hlsl_new_simple_type(ctx, "void", HLSL_CLASS_VOID); hlsl_scope_add_type(ctx->globals, hlsl_new_simple_type(ctx, "DepthStencilView", HLSL_CLASS_DEPTH_STENCIL_VIEW)); hlsl_scope_add_type(ctx->globals, hlsl_new_simple_type(ctx, "DepthStencilState", HLSL_CLASS_DEPTH_STENCIL_STATE)); @@ -3876,7 +3924,6 @@ static void declare_predefined_types(struct hlsl_ctx *ctx) hlsl_scope_add_type(ctx->globals, hlsl_new_simple_type(ctx, "pixelshader", HLSL_CLASS_PIXEL_SHADER)); hlsl_scope_add_type(ctx->globals, hlsl_new_simple_type(ctx, "RasterizerState", HLSL_CLASS_RASTERIZER_STATE)); hlsl_scope_add_type(ctx->globals, hlsl_new_simple_type(ctx, "RenderTargetView", HLSL_CLASS_RENDER_TARGET_VIEW)); - hlsl_scope_add_type(ctx->globals, hlsl_new_simple_type(ctx, "STRING", HLSL_CLASS_STRING)); hlsl_scope_add_type(ctx->globals, hlsl_new_simple_type(ctx, "texture", HLSL_CLASS_TEXTURE)); hlsl_scope_add_type(ctx->globals, hlsl_new_simple_type(ctx, "vertexshader", HLSL_CLASS_VERTEX_SHADER)); hlsl_scope_add_type(ctx->globals, hlsl_new_simple_type(ctx, "ComputeShader", HLSL_CLASS_COMPUTE_SHADER)); diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index a7c04dfc..740e4e78 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -309,6 +309,7 @@ enum hlsl_ir_node_type HLSL_IR_JUMP, HLSL_IR_RESOURCE_LOAD, HLSL_IR_RESOURCE_STORE, + HLSL_IR_STRING_CONSTANT, HLSL_IR_STORE, HLSL_IR_SWIZZLE, HLSL_IR_SWITCH, @@ -841,6 +842,12 @@ struct hlsl_ir_constant struct hlsl_reg reg; }; +struct hlsl_ir_string_constant +{ + struct hlsl_ir_node node; + char *string; +}; + /* 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 @@ -987,6 +994,7 @@ struct hlsl_ctx /* matrix[HLSL_TYPE_FLOAT][1][3] is a float4x2, i.e. dimx = 2, dimy = 4 */ struct hlsl_type *matrix[HLSL_TYPE_LAST_SCALAR + 1][4][4]; struct hlsl_type *sampler[HLSL_SAMPLER_DIM_LAST_SAMPLER + 1]; + struct hlsl_type *string; struct hlsl_type *Void; } builtin_types; @@ -1062,6 +1070,12 @@ static inline struct hlsl_ir_constant *hlsl_ir_constant(const struct hlsl_ir_nod return CONTAINING_RECORD(node, struct hlsl_ir_constant, node); } +static inline struct hlsl_ir_string_constant *hlsl_ir_string_constant(const struct hlsl_ir_node *node) +{ + VKD3D_ASSERT(node->type == HLSL_IR_STRING_CONSTANT); + return CONTAINING_RECORD(node, struct hlsl_ir_string_constant, node); +} + static inline struct hlsl_ir_expr *hlsl_ir_expr(const struct hlsl_ir_node *node) { VKD3D_ASSERT(node->type == HLSL_IR_EXPR); @@ -1421,6 +1435,8 @@ struct hlsl_ir_node *hlsl_new_swizzle(struct hlsl_ctx *ctx, uint32_t s, unsigned struct hlsl_ir_node *val, const struct vkd3d_shader_location *loc); struct hlsl_ir_node *hlsl_new_stateblock_constant(struct hlsl_ctx *ctx, const char *name, struct vkd3d_shader_location *loc); +struct hlsl_ir_node *hlsl_new_string_constant(struct hlsl_ctx *ctx, const char *str, + const struct vkd3d_shader_location *loc); struct hlsl_ir_var *hlsl_new_synthetic_var(struct hlsl_ctx *ctx, const char *template, struct hlsl_type *type, const struct vkd3d_shader_location *loc); struct hlsl_ir_var *hlsl_new_synthetic_var_named(struct hlsl_ctx *ctx, const char *name, diff --git a/libs/vkd3d-shader/hlsl.l b/libs/vkd3d-shader/hlsl.l index 55993dac..5552bbc4 100644 --- a/libs/vkd3d-shader/hlsl.l +++ b/libs/vkd3d-shader/hlsl.l @@ -208,6 +208,15 @@ while {return KW_WHILE; } return NEW_IDENTIFIER; } +{STRING} { + struct hlsl_ctx *ctx = yyget_extra(yyscanner); + char *string = hlsl_strdup(ctx, yytext + 1); + + string[strlen(string) - 1] = 0; + yylval->name = string; + return STRING; + } + [0-9]*\.[0-9]+([eE][+-]?[0-9]+)?[h|H|f|F]? { yylval->floatval = atof(yytext); return C_FLOAT; diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 455f7473..ca0cf76b 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -590,6 +590,7 @@ static union hlsl_constant_value_component evaluate_static_expression(struct hls { case HLSL_IR_CONSTANT: case HLSL_IR_EXPR: + case HLSL_IR_STRING_CONSTANT: case HLSL_IR_SWIZZLE: case HLSL_IR_LOAD: case HLSL_IR_INDEX: @@ -633,6 +634,10 @@ static union hlsl_constant_value_component evaluate_static_expression(struct hls constant = hlsl_ir_constant(node); ret = constant->value.u[0]; } + else if (node->type == HLSL_IR_STRING_CONSTANT) + { + hlsl_fixme(ctx, &node->loc, "Evaluate string constants as static expressions."); + } else { hlsl_error(ctx, &node->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, @@ -8264,6 +8269,23 @@ primary_expr: YYABORT; } } + | STRING + { + struct hlsl_ir_node *c; + + if (!(c = hlsl_new_string_constant(ctx, $1, &@1))) + { + vkd3d_free($1); + YYABORT; + } + vkd3d_free($1); + + if (!($$ = make_block(ctx, c))) + { + hlsl_free_instr(c); + YYABORT; + } + } | VAR_IDENTIFIER { struct hlsl_ir_load *load; diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 2d10a853..f460e10e 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -3933,6 +3933,7 @@ static bool dce(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) case HLSL_IR_INDEX: case HLSL_IR_LOAD: case HLSL_IR_RESOURCE_LOAD: + case HLSL_IR_STRING_CONSTANT: case HLSL_IR_SWIZZLE: if (list_empty(&instr->uses)) { @@ -4213,6 +4214,7 @@ static void compute_liveness_recurse(struct hlsl_block *block, unsigned int loop break; } case HLSL_IR_CONSTANT: + case HLSL_IR_STRING_CONSTANT: break; } } diff --git a/tests/hlsl/attributes.shader_test b/tests/hlsl/attributes.shader_test index fd9c087a..fd26951f 100644 --- a/tests/hlsl/attributes.shader_test +++ b/tests/hlsl/attributes.shader_test @@ -17,17 +17,17 @@ float4 main() : sv_target { return 0; } [numthreads(1)] float4 main() : sv_target { return 0; } -[pixel shader todo fail(sm>=6)] +[pixel shader fail(sm>=6)] [numthreads("")] float4 main() : sv_target { return 0; } -[pixel shader todo fail(sm>=6)] +[pixel shader fail(sm>=6)] [numthreads("one")] float4 main() : sv_target { return 0; } -[pixel shader todo fail(sm>=6)] +[pixel shader fail(sm>=6)] uniform float4 f; diff --git a/tests/hlsl/state-block-function-syntax.shader_test b/tests/hlsl/state-block-function-syntax.shader_test index 6b7d85e3..6bc0cff3 100644 --- a/tests/hlsl/state-block-function-syntax.shader_test +++ b/tests/hlsl/state-block-function-syntax.shader_test @@ -18,7 +18,7 @@ sampler sam float4 main() : sv_target { return 0; } -[pixel shader todo] +[pixel shader] sampler sam { SetComputeShader("random string"); diff --git a/tests/hlsl/state-block-syntax.shader_test b/tests/hlsl/state-block-syntax.shader_test index c5057d91..56bd0a90 100644 --- a/tests/hlsl/state-block-syntax.shader_test +++ b/tests/hlsl/state-block-syntax.shader_test @@ -420,7 +420,7 @@ float4 main() : sv_target { return 0; } % State blocks may have bracket initializers on the rhs. -[pixel shader todo] +[pixel shader] sampler sam { MaxAnisotropy = 3; @@ -475,7 +475,7 @@ float4 main() : sv_target { return 0; } % Same rules apply for technique passes -[pixel shader todo] +[pixel shader] technique { pass