From 48ff7de8ef0dbdffac9819e936fd8f269b4497ac Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Tue, 28 May 2024 00:31:51 +0200 Subject: [PATCH] vkd3d-shader/hlsl: Add support for ConstantBuffer<> type. Signed-off-by: Nikolay Sivov --- libs/vkd3d-shader/d3dbc.c | 2 ++ libs/vkd3d-shader/fx.c | 2 ++ libs/vkd3d-shader/hlsl.c | 38 +++++++++++++++++++++++++ libs/vkd3d-shader/hlsl.h | 2 ++ libs/vkd3d-shader/hlsl.l | 4 ++- libs/vkd3d-shader/hlsl.y | 26 ++++++++++++++++- libs/vkd3d-shader/hlsl_codegen.c | 1 + libs/vkd3d-shader/tpf.c | 1 + tests/hlsl/cbuffer.shader_test | 48 ++++++++++++++++++++++++++++---- 9 files changed, 117 insertions(+), 7 deletions(-) diff --git a/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d-shader/d3dbc.c index 3665b99a..ea0a7633 100644 --- a/libs/vkd3d-shader/d3dbc.c +++ b/libs/vkd3d-shader/d3dbc.c @@ -1504,6 +1504,7 @@ D3DXPARAMETER_CLASS hlsl_sm1_class(const struct hlsl_type *type) case HLSL_CLASS_TECHNIQUE: case HLSL_CLASS_UAV: case HLSL_CLASS_VOID: + case HLSL_CLASS_CONSTANT_BUFFER: break; } @@ -1600,6 +1601,7 @@ D3DXPARAMETER_TYPE hlsl_sm1_base_type(const struct hlsl_type *type) case HLSL_CLASS_TECHNIQUE: case HLSL_CLASS_UAV: case HLSL_CLASS_VOID: + case HLSL_CLASS_CONSTANT_BUFFER: break; } diff --git a/libs/vkd3d-shader/fx.c b/libs/vkd3d-shader/fx.c index 3ba0a9ba..466733d1 100644 --- a/libs/vkd3d-shader/fx.c +++ b/libs/vkd3d-shader/fx.c @@ -464,6 +464,7 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co case HLSL_CLASS_EFFECT_GROUP: case HLSL_CLASS_PASS: case HLSL_CLASS_TECHNIQUE: + case HLSL_CLASS_CONSTANT_BUFFER: vkd3d_unreachable(); case HLSL_CLASS_STRING: @@ -862,6 +863,7 @@ static bool is_type_supported_fx_2(struct hlsl_ctx *ctx, const struct hlsl_type case HLSL_CLASS_EFFECT_GROUP: case HLSL_CLASS_PASS: case HLSL_CLASS_TECHNIQUE: + case HLSL_CLASS_CONSTANT_BUFFER: /* This cannot appear as an extern variable. */ break; } diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index c69af4e9..ce178a88 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -378,6 +378,7 @@ static void hlsl_type_calculate_reg_size(struct hlsl_ctx *ctx, struct hlsl_type case HLSL_CLASS_TECHNIQUE: case HLSL_CLASS_VERTEX_SHADER: case HLSL_CLASS_VOID: + case HLSL_CLASS_CONSTANT_BUFFER: break; } } @@ -452,6 +453,7 @@ static bool type_is_single_component(const struct hlsl_type *type) case HLSL_CLASS_MATRIX: case HLSL_CLASS_STRUCT: case HLSL_CLASS_ARRAY: + case HLSL_CLASS_CONSTANT_BUFFER: return false; case HLSL_CLASS_EFFECT_GROUP: @@ -530,6 +532,12 @@ static unsigned int traverse_path_from_component_index(struct hlsl_ctx *ctx, vkd3d_unreachable(); } + case HLSL_CLASS_CONSTANT_BUFFER: + { + *type_ptr = type->e.resource.format; + return traverse_path_from_component_index(ctx, type_ptr, index_ptr); + } + default: vkd3d_unreachable(); } @@ -597,6 +605,7 @@ unsigned int hlsl_type_get_component_offset(struct hlsl_ctx *ctx, struct hlsl_ty case HLSL_CLASS_TECHNIQUE: case HLSL_CLASS_VOID: case HLSL_CLASS_SCALAR: + case HLSL_CLASS_CONSTANT_BUFFER: vkd3d_unreachable(); } type = next_type; @@ -870,6 +879,20 @@ struct hlsl_type *hlsl_new_uav_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim return type; } +struct hlsl_type *hlsl_new_cb_type(struct hlsl_ctx *ctx, struct hlsl_type *format) +{ + struct hlsl_type *type; + + if (!(type = hlsl_alloc(ctx, sizeof(*type)))) + return NULL; + type->class = HLSL_CLASS_CONSTANT_BUFFER; + type->dimy = 1; + type->e.resource.format = format; + hlsl_type_calculate_reg_size(ctx, type); + list_add_tail(&ctx->types, &type->entry); + return type; +} + static const char * get_case_insensitive_typename(const char *name) { static const char *const names[] = @@ -961,6 +984,9 @@ unsigned int hlsl_type_component_count(const struct hlsl_type *type) case HLSL_CLASS_ARRAY: return hlsl_type_component_count(type->e.array.type) * type->e.array.elements_count; + case HLSL_CLASS_CONSTANT_BUFFER: + return hlsl_type_component_count(type->e.resource.format); + case HLSL_CLASS_DEPTH_STENCIL_VIEW: case HLSL_CLASS_PIXEL_SHADER: case HLSL_CLASS_RENDER_TARGET_VIEW: @@ -1043,6 +1069,9 @@ bool hlsl_types_are_equal(const struct hlsl_type *t1, const struct hlsl_type *t2 case HLSL_CLASS_TECHNIQUE: return t1->e.version == t2->e.version; + case HLSL_CLASS_CONSTANT_BUFFER: + return hlsl_types_are_equal(t1->e.resource.format, t2->e.resource.format); + case HLSL_CLASS_DEPTH_STENCIL_VIEW: case HLSL_CLASS_EFFECT_GROUP: case HLSL_CLASS_PASS: @@ -2413,6 +2442,15 @@ struct vkd3d_string_buffer *hlsl_type_to_string(struct hlsl_ctx *ctx, const stru } return string; + case HLSL_CLASS_CONSTANT_BUFFER: + vkd3d_string_buffer_printf(string, "ConstantBuffer"); + if ((inner_string = hlsl_type_to_string(ctx, type->e.resource.format))) + { + vkd3d_string_buffer_printf(string, "<%s>", inner_string->buffer); + hlsl_release_string_buffer(ctx, inner_string); + } + return string; + case HLSL_CLASS_DEPTH_STENCIL_VIEW: case HLSL_CLASS_EFFECT_GROUP: case HLSL_CLASS_PASS: diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 5f6ed34f..8c0eccdd 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -89,6 +89,7 @@ enum hlsl_type_class HLSL_CLASS_TEXTURE, HLSL_CLASS_UAV, HLSL_CLASS_VERTEX_SHADER, + HLSL_CLASS_CONSTANT_BUFFER, HLSL_CLASS_VOID, }; @@ -1391,6 +1392,7 @@ struct hlsl_type *hlsl_new_texture_type(struct hlsl_ctx *ctx, enum hlsl_sampler_ unsigned int sample_count); struct hlsl_type *hlsl_new_uav_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim dim, struct hlsl_type *format, bool rasteriser_ordered); +struct hlsl_type *hlsl_new_cb_type(struct hlsl_ctx *ctx, struct hlsl_type *format); struct hlsl_ir_node *hlsl_new_uint_constant(struct hlsl_ctx *ctx, unsigned int n, const struct vkd3d_shader_location *loc); struct hlsl_ir_node *hlsl_new_unary_expr(struct hlsl_ctx *ctx, enum hlsl_ir_expr_op op, struct hlsl_ir_node *arg, diff --git a/libs/vkd3d-shader/hlsl.l b/libs/vkd3d-shader/hlsl.l index 91418775..55993dac 100644 --- a/libs/vkd3d-shader/hlsl.l +++ b/libs/vkd3d-shader/hlsl.l @@ -198,7 +198,9 @@ while {return KW_WHILE; } struct hlsl_ctx *ctx = yyget_extra(yyscanner); yylval->name = hlsl_strdup(ctx, yytext); - if (hlsl_get_var(ctx->cur_scope, yytext) || hlsl_get_function(ctx, yytext)) + if (hlsl_version_ge(ctx, 5, 1) && !strcmp(yytext, "ConstantBuffer")) + return KW_CONSTANTBUFFER; + else if (hlsl_get_var(ctx->cur_scope, yytext) || hlsl_get_function(ctx, yytext)) return VAR_IDENTIFIER; else if (hlsl_get_type(ctx->cur_scope, yytext, true, true)) return TYPE_IDENTIFIER; diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 3b5915a1..16a43ecd 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -2376,6 +2376,7 @@ static void declare_var(struct hlsl_ctx *ctx, struct parse_variable_def *v) struct hlsl_semantic new_semantic; uint32_t modifiers = v->modifiers; bool unbounded_res_array = false; + bool constant_buffer = false; struct hlsl_ir_var *var; struct hlsl_type *type; bool local = true; @@ -2395,6 +2396,12 @@ static void declare_var(struct hlsl_ctx *ctx, struct parse_variable_def *v) unbounded_res_array |= (v->arrays.sizes[i] == HLSL_ARRAY_ELEMENTS_COUNT_IMPLICIT); } + if (type->class == HLSL_CLASS_CONSTANT_BUFFER) + { + type = type->e.resource.format; + constant_buffer = true; + } + if (unbounded_res_array) { if (v->arrays.count == 1) @@ -2476,7 +2483,16 @@ static void declare_var(struct hlsl_ctx *ctx, struct parse_variable_def *v) return; } - var->buffer = ctx->cur_buffer; + if (constant_buffer && ctx->cur_scope == ctx->globals) + { + if (!(var_name = vkd3d_strdup(v->name))) + return; + var->buffer = hlsl_new_buffer(ctx, HLSL_BUFFER_CONSTANT, var_name, modifiers, &v->reg_reservation, NULL, &v->loc); + } + else + { + var->buffer = ctx->cur_buffer; + } if (var->buffer == ctx->globals_buffer) { @@ -5723,6 +5739,7 @@ static bool state_block_add_entry(struct hlsl_state_block *state_block, struct h %token KW_BREAK %token KW_BUFFER %token KW_CASE +%token KW_CONSTANTBUFFER %token KW_CBUFFER %token KW_CENTROID %token KW_COLUMN_MAJOR @@ -7069,6 +7086,13 @@ type_no_void: { $$ = hlsl_get_type(ctx->cur_scope, "PixelShader", true, true); } + | KW_CONSTANTBUFFER '<' type '>' + { + if ($3->class != HLSL_CLASS_STRUCT) + hlsl_error(ctx, &@1, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "ConstantBuffer<...> requires user-defined structure type."); + $$ = hlsl_new_cb_type(ctx, $3); + } type: type_no_void diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index f2367dc5..ee2a9082 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -1643,6 +1643,7 @@ static bool copy_propagation_transform_load(struct hlsl_ctx *ctx, case HLSL_CLASS_MATRIX: case HLSL_CLASS_ARRAY: case HLSL_CLASS_STRUCT: + case HLSL_CLASS_CONSTANT_BUFFER: /* FIXME: Actually we shouldn't even get here, but we don't split * matrices yet. */ return false; diff --git a/libs/vkd3d-shader/tpf.c b/libs/vkd3d-shader/tpf.c index 24206ae9..d7501c00 100644 --- a/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d-shader/tpf.c @@ -2997,6 +2997,7 @@ static D3D_SHADER_VARIABLE_CLASS sm4_class(const struct hlsl_type *type) case HLSL_CLASS_UAV: case HLSL_CLASS_VERTEX_SHADER: case HLSL_CLASS_VOID: + case HLSL_CLASS_CONSTANT_BUFFER: break; } vkd3d_unreachable(); diff --git a/tests/hlsl/cbuffer.shader_test b/tests/hlsl/cbuffer.shader_test index c42c989d..22b7878d 100644 --- a/tests/hlsl/cbuffer.shader_test +++ b/tests/hlsl/cbuffer.shader_test @@ -864,7 +864,7 @@ probe (0, 0) rgba (124.0, 135.0, 146.0, 150.5) [require] shader model >= 5.1 -[pixel shader fail todo] +[pixel shader fail] float4 ConstantBuffer; float4 main() : sv_target @@ -886,7 +886,7 @@ float4 main() : sv_target return 0; } -[pixel shader fail(sm>=6) todo] +[pixel shader fail(sm>=6)] struct s { float4 m; @@ -903,10 +903,32 @@ float4 main() : sv_target } [test] -todo draw quad +todo(glsl) draw quad probe (0, 0) rgba (1.1, 1.1, 1.1, 1.1) -[pixel shader fail] +[pixel shader] +struct s +{ + float4 m; +}; +ConstantBuffer cb; + +float4 func(s arg) +{ + return arg.m; +} + +float4 main() : sv_target +{ + return func(cb); +} + +[test] +uniform 0 float4 1.0 2.0 3.0 4.0 +todo(glsl) draw quad +probe (0, 0) rgba (1.0, 2.0, 3.0, 4.0) + +[pixel shader fail todo] struct s { float4 m; @@ -919,7 +941,7 @@ float4 main() : sv_target return cb.m; } -[pixel shader todo] +[pixel shader] struct s { float4 m; @@ -938,6 +960,22 @@ float4 main() : sv_target return 0; } +[pixel shader fail todo] +struct s +{ + float4 m; +}; + +ConstantBuffer func(s arg) +{ + return arg; +} + +float4 main() : sv_target +{ + return 0; +} + [require] shader model >= 2.0 shader model < 5.1