diff --git a/patches/vkd3d-latest/0001-Updated-vkd3d-to-d3ba810c98b4d2df260a527f74586a0b314.patch b/patches/vkd3d-latest/0001-Updated-vkd3d-to-d3ba810c98b4d2df260a527f74586a0b314.patch index 1a909074..50eaba15 100644 --- a/patches/vkd3d-latest/0001-Updated-vkd3d-to-d3ba810c98b4d2df260a527f74586a0b314.patch +++ b/patches/vkd3d-latest/0001-Updated-vkd3d-to-d3ba810c98b4d2df260a527f74586a0b314.patch @@ -1,4 +1,4 @@ -From 7c4de384b1162aeec25c97a679ce749ea9c40bc1 Mon Sep 17 00:00:00 2001 +From aba492b0cf6cda5452b16a2688de012b7908a762 Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Thu, 7 Mar 2024 10:40:41 +1100 Subject: [PATCH] Updated vkd3d to d3ba810c98b4d2df260a527f74586a0b31408510. diff --git a/patches/vkd3d-latest/0002-Updated-vkd3d-to-ccb6150aabc7cce9e26a39366c611f5a7da.patch b/patches/vkd3d-latest/0002-Updated-vkd3d-to-ccb6150aabc7cce9e26a39366c611f5a7da.patch index 261cc048..30c94926 100644 --- a/patches/vkd3d-latest/0002-Updated-vkd3d-to-ccb6150aabc7cce9e26a39366c611f5a7da.patch +++ b/patches/vkd3d-latest/0002-Updated-vkd3d-to-ccb6150aabc7cce9e26a39366c611f5a7da.patch @@ -1,4 +1,4 @@ -From 0b6ce29e931e2b02b75a4d76c3810a1049e56d67 Mon Sep 17 00:00:00 2001 +From aaeb96da1ada9e18e982a17444e13305506aa097 Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Sun, 23 Jun 2024 15:40:43 +1000 Subject: [PATCH] Updated vkd3d to ccb6150aabc7cce9e26a39366c611f5a7da789e4. diff --git a/patches/vkd3d-latest/0003-Updated-vkd3d-to-3dc43e8945f68c42268b8d5e43525b9e108.patch b/patches/vkd3d-latest/0003-Updated-vkd3d-to-3dc43e8945f68c42268b8d5e43525b9e108.patch new file mode 100644 index 00000000..aa83716d --- /dev/null +++ b/patches/vkd3d-latest/0003-Updated-vkd3d-to-3dc43e8945f68c42268b8d5e43525b9e108.patch @@ -0,0 +1,1883 @@ +From 15652871b2e9951be700c7baf1988ae5db09ccad Mon Sep 17 00:00:00 2001 +From: Alistair Leslie-Hughes +Date: Tue, 9 Jul 2024 07:22:05 +1000 +Subject: [PATCH] Updated vkd3d to 3dc43e8945f68c42268b8d5e43525b9e10806f77. + +--- + libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 24 +- + libs/vkd3d/libs/vkd3d-shader/fx.c | 454 +++++++++++++++++--- + libs/vkd3d/libs/vkd3d-shader/hlsl.c | 52 +++ + libs/vkd3d/libs/vkd3d-shader/hlsl.h | 7 + + libs/vkd3d/libs/vkd3d-shader/hlsl.l | 4 +- + libs/vkd3d/libs/vkd3d-shader/hlsl.y | 306 ++++++++++--- + libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 41 +- + libs/vkd3d/libs/vkd3d-shader/ir.c | 31 +- + libs/vkd3d/libs/vkd3d-shader/tpf.c | 3 + + libs/vkd3d/libs/vkd3d/command.c | 5 +- + libs/vkd3d/libs/vkd3d/device.c | 1 + + libs/vkd3d/libs/vkd3d/vkd3d_private.h | 1 + + 12 files changed, 793 insertions(+), 136 deletions(-) + +diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c +index 3665b99aed7..2482efc55d2 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c ++++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c +@@ -1497,13 +1497,16 @@ D3DXPARAMETER_CLASS hlsl_sm1_class(const struct hlsl_type *type) + case HLSL_CLASS_TEXTURE: + case HLSL_CLASS_VERTEX_SHADER: + return D3DXPC_OBJECT; ++ 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_TECHNIQUE: + case HLSL_CLASS_UAV: + case HLSL_CLASS_VOID: ++ case HLSL_CLASS_CONSTANT_BUFFER: + break; + } + +@@ -1593,13 +1596,16 @@ D3DXPARAMETER_TYPE hlsl_sm1_base_type(const struct hlsl_type *type) + case HLSL_CLASS_VERTEX_SHADER: + return D3DXPT_VERTEXSHADER; + ++ 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_TECHNIQUE: + case HLSL_CLASS_UAV: + case HLSL_CLASS_VOID: ++ case HLSL_CLASS_CONSTANT_BUFFER: + break; + } + +@@ -1859,7 +1865,7 @@ struct sm1_instruction + D3DSHADER_PARAM_SRCMOD_TYPE mod; + unsigned int swizzle; + uint32_t reg; +- } srcs[3]; ++ } srcs[4]; + unsigned int src_count; + + unsigned int has_dst; +@@ -2567,6 +2573,8 @@ static void write_sm1_resource_load(struct hlsl_ctx *ctx, struct vkd3d_bytecode_ + { + const struct hlsl_ir_resource_load *load = hlsl_ir_resource_load(instr); + struct hlsl_ir_node *coords = load->coords.node; ++ struct hlsl_ir_node *ddx = load->ddx.node; ++ struct hlsl_ir_node *ddy = load->ddy.node; + unsigned int sampler_offset, reg_id; + struct sm1_instruction sm1_instr; + +@@ -2607,6 +2615,20 @@ static void write_sm1_resource_load(struct hlsl_ctx *ctx, struct vkd3d_bytecode_ + sm1_instr.opcode |= VKD3DSI_TEXLD_BIAS << VKD3D_SM1_INSTRUCTION_FLAGS_SHIFT; + break; + ++ case HLSL_RESOURCE_SAMPLE_GRAD: ++ sm1_instr.opcode = D3DSIO_TEXLDD; ++ ++ sm1_instr.srcs[2].type = D3DSPR_TEMP; ++ sm1_instr.srcs[2].reg = ddx->reg.id; ++ sm1_instr.srcs[2].swizzle = hlsl_swizzle_from_writemask(ddx->reg.writemask); ++ ++ sm1_instr.srcs[3].type = D3DSPR_TEMP; ++ sm1_instr.srcs[3].reg = ddy->reg.id; ++ sm1_instr.srcs[3].swizzle = hlsl_swizzle_from_writemask(ddy->reg.writemask); ++ ++ sm1_instr.src_count += 2; ++ break; ++ + default: + hlsl_fixme(ctx, &instr->loc, "Resource load type %u.", load->load_type); + return; +diff --git a/libs/vkd3d/libs/vkd3d-shader/fx.c b/libs/vkd3d/libs/vkd3d-shader/fx.c +index 3ba0a9ba994..75f10a18253 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/fx.c ++++ b/libs/vkd3d/libs/vkd3d-shader/fx.c +@@ -63,6 +63,7 @@ struct fx_write_context_ops + uint32_t (*write_string)(const char *string, struct fx_write_context *fx); + void (*write_technique)(struct hlsl_ir_var *var, struct fx_write_context *fx); + void (*write_pass)(struct hlsl_ir_var *var, struct fx_write_context *fx); ++ void (*write_annotation)(struct hlsl_ir_var *var, struct fx_write_context *fx); + bool are_child_effects_supported; + }; + +@@ -94,6 +95,8 @@ struct fx_write_context + uint32_t texture_count; + uint32_t uav_count; + uint32_t sampler_state_count; ++ uint32_t depth_stencil_state_count; ++ uint32_t rasterizer_state_count; + int status; + + bool child_effect; +@@ -128,8 +131,41 @@ static void write_pass(struct hlsl_ir_var *var, struct fx_write_context *fx) + fx->ops->write_pass(var, fx); + } + ++static uint32_t write_annotations(struct hlsl_scope *scope, struct fx_write_context *fx) ++{ ++ struct hlsl_ctx *ctx = fx->ctx; ++ struct hlsl_ir_var *v; ++ uint32_t count = 0; ++ ++ if (!scope) ++ return 0; ++ ++ LIST_FOR_EACH_ENTRY(v, &scope->vars, struct hlsl_ir_var, scope_entry) ++ { ++ if (!v->default_values) ++ hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, ++ "Annotation variable is missing default value."); ++ ++ fx->ops->write_annotation(v, fx); ++ ++count; ++ } ++ ++ return count; ++} ++ ++static void write_fx_4_annotations(struct hlsl_scope *scope, struct fx_write_context *fx) ++{ ++ struct vkd3d_bytecode_buffer *buffer = &fx->structured; ++ uint32_t count_offset, count; ++ ++ count_offset = put_u32(buffer, 0); ++ count = write_annotations(scope, fx); ++ set_u32(buffer, count_offset, count); ++} ++ + static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_context *fx); + static const char * get_fx_4_type_name(const struct hlsl_type *type); ++static void write_fx_4_annotation(struct hlsl_ir_var *var, struct fx_write_context *fx); + + static uint32_t write_type(const struct hlsl_type *type, struct fx_write_context *fx) + { +@@ -279,9 +315,9 @@ static void write_fx_4_pass(struct hlsl_ir_var *var, struct fx_write_context *fx + name_offset = write_string(var->name, fx); + put_u32(buffer, name_offset); + put_u32(buffer, 0); /* Assignment count. */ +- put_u32(buffer, 0); /* Annotation count. */ + +- /* TODO: annotations */ ++ write_fx_4_annotations(var->annotations, fx); ++ + /* TODO: assignments */ + } + +@@ -402,6 +438,9 @@ static const char * get_fx_4_type_name(const struct hlsl_type *type) + case HLSL_CLASS_UAV: + return uav_type_names[type->sampler_dim]; + ++ case HLSL_CLASS_DEPTH_STENCIL_STATE: ++ return "DepthStencilState"; ++ + case HLSL_CLASS_DEPTH_STENCIL_VIEW: + return "DepthStencilView"; + +@@ -421,10 +460,20 @@ static const char * get_fx_4_type_name(const struct hlsl_type *type) + + static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_context *fx) + { ++ struct field_offsets ++ { ++ uint32_t name; ++ uint32_t semantic; ++ uint32_t offset; ++ uint32_t type; ++ }; ++ uint32_t name_offset, offset, total_size, packed_size, stride, numeric_desc; + struct vkd3d_bytecode_buffer *buffer = &fx->unstructured; +- uint32_t name_offset, offset, size, stride, numeric_desc; ++ struct field_offsets *field_offsets = NULL; ++ struct hlsl_ctx *ctx = fx->ctx; + uint32_t elements_count = 0; + const char *name; ++ size_t i; + + /* Resolve arrays to element type and number of elements. */ + if (type->class == HLSL_CLASS_ARRAY) +@@ -436,6 +485,22 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co + name = get_fx_4_type_name(type); + + name_offset = write_string(name, fx); ++ if (type->class == HLSL_CLASS_STRUCT) ++ { ++ if (!(field_offsets = hlsl_calloc(ctx, type->e.record.field_count, sizeof(*field_offsets)))) ++ return 0; ++ ++ for (i = 0; i < type->e.record.field_count; ++i) ++ { ++ const struct hlsl_struct_field *field = &type->e.record.fields[i]; ++ ++ field_offsets[i].name = write_string(field->name, fx); ++ field_offsets[i].semantic = write_string(field->semantic.raw_name, fx); ++ field_offsets[i].offset = field->reg_offset[HLSL_REGSET_NUMERIC]; ++ field_offsets[i].type = write_type(field->type, fx); ++ } ++ } ++ + offset = put_u32_unaligned(buffer, name_offset); + + switch (type->class) +@@ -446,8 +511,10 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co + put_u32_unaligned(buffer, 1); + break; + ++ case HLSL_CLASS_DEPTH_STENCIL_STATE: + case HLSL_CLASS_DEPTH_STENCIL_VIEW: + case HLSL_CLASS_PIXEL_SHADER: ++ case HLSL_CLASS_RASTERIZER_STATE: + case HLSL_CLASS_RENDER_TARGET_VIEW: + case HLSL_CLASS_SAMPLER: + case HLSL_CLASS_TEXTURE: +@@ -464,6 +531,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: +@@ -473,34 +541,40 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co + return 0; + } + +- size = stride = type->reg_size[HLSL_REGSET_NUMERIC] * sizeof(float); ++ /* Structures can only contain numeric fields, this is validated during variable declaration. */ ++ total_size = stride = type->reg_size[HLSL_REGSET_NUMERIC] * sizeof(float); ++ packed_size = 0; ++ if (type->class == HLSL_CLASS_STRUCT || hlsl_is_numeric_type(type)) ++ packed_size = hlsl_type_component_count(type) * sizeof(float); + if (elements_count) +- size *= elements_count; ++ { ++ total_size *= elements_count; ++ packed_size *= elements_count; ++ } + stride = align(stride, 4 * sizeof(float)); + + put_u32_unaligned(buffer, elements_count); +- put_u32_unaligned(buffer, size); /* Total size. */ +- put_u32_unaligned(buffer, stride); /* Stride. */ +- put_u32_unaligned(buffer, size); ++ put_u32_unaligned(buffer, total_size); ++ put_u32_unaligned(buffer, stride); ++ put_u32_unaligned(buffer, packed_size); + + if (type->class == HLSL_CLASS_STRUCT) + { +- size_t i; +- + put_u32_unaligned(buffer, type->e.record.field_count); + for (i = 0; i < type->e.record.field_count; ++i) + { +- const struct hlsl_struct_field *field = &type->e.record.fields[i]; +- uint32_t semantic_offset, field_type_offset; ++ const struct field_offsets *field = &field_offsets[i]; + +- name_offset = write_string(field->name, fx); +- semantic_offset = write_string(field->semantic.raw_name, fx); +- field_type_offset = write_type(field->type, fx); ++ put_u32_unaligned(buffer, field->name); ++ put_u32_unaligned(buffer, field->semantic); ++ put_u32_unaligned(buffer, field->offset); ++ put_u32_unaligned(buffer, field->type); ++ } + +- put_u32_unaligned(buffer, name_offset); +- put_u32_unaligned(buffer, semantic_offset); +- put_u32_unaligned(buffer, field->reg_offset[HLSL_REGSET_NUMERIC]); +- put_u32_unaligned(buffer, field_type_offset); ++ if (ctx->profile->major_version == 5) ++ { ++ put_u32_unaligned(buffer, 0); /* Base class type */ ++ put_u32_unaligned(buffer, 0); /* Interface count */ + } + } + else if (type->class == HLSL_CLASS_TEXTURE) +@@ -556,6 +630,14 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co + { + put_u32_unaligned(buffer, 6); + } ++ else if (type->class == HLSL_CLASS_RASTERIZER_STATE) ++ { ++ put_u32_unaligned(buffer, 4); ++ } ++ else if (type->class == HLSL_CLASS_DEPTH_STENCIL_STATE) ++ { ++ put_u32_unaligned(buffer, 3); ++ } + else if (hlsl_is_numeric_type(type)) + { + numeric_desc = get_fx_4_numeric_type_description(type, fx); +@@ -565,9 +647,9 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co + { + FIXME("Type %u is not supported.\n", type->class); + set_status(fx, VKD3D_ERROR_NOT_IMPLEMENTED); +- return 0; + } + ++ vkd3d_free(field_offsets); + return offset; + } + +@@ -581,8 +663,9 @@ static void write_fx_4_technique(struct hlsl_ir_var *var, struct fx_write_contex + name_offset = write_string(var->name, fx); + put_u32(buffer, name_offset); + count_offset = put_u32(buffer, 0); +- put_u32(buffer, 0); /* Annotation count. */ ++ write_fx_4_annotations(var->annotations, fx); + ++ count = 0; + LIST_FOR_EACH_ENTRY(pass, &var->scope->vars, struct hlsl_ir_var, scope_entry) + { + write_pass(pass, fx); +@@ -617,7 +700,7 @@ static void write_group(struct hlsl_ir_var *var, struct fx_write_context *fx) + + put_u32(buffer, name_offset); + count_offset = put_u32(buffer, 0); /* Technique count */ +- put_u32(buffer, 0); /* Annotation count */ ++ write_fx_4_annotations(var ? var->annotations : NULL, fx); + + count = fx->technique_count; + write_techniques(var ? var->scope : fx->ctx->globals, fx); +@@ -853,8 +936,10 @@ static bool is_type_supported_fx_2(struct hlsl_ctx *ctx, const struct hlsl_type + hlsl_fixme(ctx, loc, "Write fx 2.0 parameter class %#x.", type->class); + return false; + ++ case HLSL_CLASS_DEPTH_STENCIL_STATE: + case HLSL_CLASS_DEPTH_STENCIL_VIEW: + case HLSL_CLASS_UAV: ++ case HLSL_CLASS_RASTERIZER_STATE: + case HLSL_CLASS_RENDER_TARGET_VIEW: + case HLSL_CLASS_VOID: + return false; +@@ -862,6 +947,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; + } +@@ -975,9 +1061,72 @@ static const struct fx_write_context_ops fx_4_ops = + .write_string = write_fx_4_string, + .write_technique = write_fx_4_technique, + .write_pass = write_fx_4_pass, ++ .write_annotation = write_fx_4_annotation, + .are_child_effects_supported = true, + }; + ++static uint32_t write_fx_4_default_value(struct hlsl_type *value_type, struct hlsl_default_value *value, ++ struct fx_write_context *fx) ++{ ++ const struct hlsl_type *type = hlsl_get_multiarray_element_type(value_type); ++ uint32_t elements_count = hlsl_get_multiarray_size(value_type), i, j; ++ struct vkd3d_bytecode_buffer *buffer = &fx->unstructured; ++ struct hlsl_ctx *ctx = fx->ctx; ++ uint32_t offset = buffer->size; ++ unsigned int comp_count; ++ ++ if (!value) ++ return 0; ++ ++ comp_count = hlsl_type_component_count(type); ++ ++ for (i = 0; i < elements_count; ++i) ++ { ++ switch (type->class) ++ { ++ case HLSL_CLASS_SCALAR: ++ case HLSL_CLASS_VECTOR: ++ case HLSL_CLASS_MATRIX: ++ { ++ switch (type->e.numeric.type) ++ { ++ case HLSL_TYPE_FLOAT: ++ case HLSL_TYPE_INT: ++ case HLSL_TYPE_UINT: ++ case HLSL_TYPE_BOOL: ++ ++ for (j = 0; j < comp_count; ++j) ++ { ++ put_u32_unaligned(buffer, value->value.u); ++ value++; ++ } ++ break; ++ default: ++ hlsl_fixme(ctx, &ctx->location, "Writing default values for numeric type %u is not implemented.", ++ type->e.numeric.type); ++ } ++ ++ break; ++ } ++ case HLSL_CLASS_STRUCT: ++ { ++ struct hlsl_struct_field *fields = type->e.record.fields; ++ ++ for (j = 0; j < type->e.record.field_count; ++j) ++ { ++ write_fx_4_default_value(fields[i].type, value, fx); ++ value += hlsl_type_component_count(fields[i].type); ++ } ++ break; ++ } ++ default: ++ hlsl_fixme(ctx, &ctx->location, "Writing default values for class %u is not implemented.", type->class); ++ } ++ } ++ ++ return offset; ++} ++ + static void write_fx_4_numeric_variable(struct hlsl_ir_var *var, bool shared, struct fx_write_context *fx) + { + struct vkd3d_bytecode_buffer *buffer = &fx->structured; +@@ -987,7 +1136,6 @@ static void write_fx_4_numeric_variable(struct hlsl_ir_var *var, bool shared, st + { + HAS_EXPLICIT_BIND_POINT = 0x4, + }; +- struct hlsl_ctx *ctx = fx->ctx; + + if (var->has_explicit_bind_point) + flags |= HAS_EXPLICIT_BIND_POINT; +@@ -1001,7 +1149,7 @@ static void write_fx_4_numeric_variable(struct hlsl_ir_var *var, bool shared, st + + semantic_offset = put_u32(buffer, semantic_offset); /* Semantic */ + put_u32(buffer, var->buffer_offset * 4); /* Offset in the constant buffer, in bytes. */ +- value_offset = put_u32(buffer, 0); /* Default value offset */ ++ value_offset = put_u32(buffer, 0); + put_u32(buffer, flags); /* Flags */ + + if (shared) +@@ -1010,19 +1158,39 @@ static void write_fx_4_numeric_variable(struct hlsl_ir_var *var, bool shared, st + } + else + { +- /* FIXME: write default value */ +- set_u32(buffer, value_offset, 0); +- if (var->default_values) +- hlsl_fixme(fx->ctx, &var->loc, "Write default values.\n"); ++ uint32_t offset = write_fx_4_default_value(var->data_type, var->default_values, fx); ++ set_u32(buffer, value_offset, offset); + +- put_u32(buffer, 0); /* Annotations count */ +- if (has_annotations(var)) +- hlsl_fixme(ctx, &ctx->location, "Writing annotations for numeric variables is not implemented."); ++ write_fx_4_annotations(var->annotations, fx); + + fx->numeric_variable_count++; + } + } + ++static void write_fx_4_annotation(struct hlsl_ir_var *var, struct fx_write_context *fx) ++{ ++ const struct hlsl_type *type = hlsl_get_multiarray_element_type(var->data_type); ++ struct vkd3d_bytecode_buffer *buffer = &fx->structured; ++ uint32_t name_offset, type_offset, offset; ++ struct hlsl_ctx *ctx = fx->ctx; ++ ++ name_offset = write_string(var->name, fx); ++ type_offset = write_type(var->data_type, fx); ++ ++ put_u32(buffer, name_offset); ++ put_u32(buffer, type_offset); ++ ++ if (hlsl_is_numeric_type(type)) ++ { ++ offset = write_fx_4_default_value(var->data_type, var->default_values, fx); ++ put_u32(buffer, offset); ++ } ++ else ++ { ++ hlsl_fixme(ctx, &var->loc, "Writing annotations for type class %u is not implemented.", type->class); ++ } ++} ++ + struct rhs_named_value + { + const char *name; +@@ -1164,6 +1332,41 @@ static bool replace_state_block_constant(struct hlsl_ctx *ctx, struct hlsl_ir_no + return true; + } + ++static void fold_state_value(struct hlsl_ctx *ctx, struct hlsl_state_block_entry *entry) ++{ ++ bool progress; ++ ++ do ++ { ++ progress = hlsl_transform_ir(ctx, hlsl_fold_constant_exprs, entry->instrs, NULL); ++ progress |= hlsl_copy_propagation_execute(ctx, entry->instrs); ++ } while (progress); ++} ++ ++enum state_property_component_type ++{ ++ FX_BOOL, ++ FX_FLOAT, ++ FX_UINT, ++ FX_UINT8, ++}; ++ ++static inline enum hlsl_base_type hlsl_type_from_fx_type(enum state_property_component_type type) ++{ ++ switch (type) ++ { ++ case FX_BOOL: ++ return HLSL_TYPE_BOOL; ++ case FX_FLOAT: ++ return HLSL_TYPE_FLOAT; ++ case FX_UINT: ++ case FX_UINT8: ++ return HLSL_TYPE_UINT; ++ default: ++ vkd3d_unreachable(); ++ } ++} ++ + static void resolve_fx_4_state_block_values(struct hlsl_ir_var *var, struct hlsl_state_block_entry *entry, + struct fx_write_context *fx) + { +@@ -1213,37 +1416,112 @@ static void resolve_fx_4_state_block_values(struct hlsl_ir_var *var, struct hlsl + { NULL } + }; + ++ static const struct rhs_named_value depth_write_mask_values[] = ++ { ++ { "ZERO", 0 }, ++ { "ALL", 1 }, ++ { NULL } ++ }; ++ ++ static const struct rhs_named_value comparison_values[] = ++ { ++ { "NEVER", 1 }, ++ { "LESS", 2 }, ++ { "EQUAL", 3 }, ++ { "LESS_EQUAL", 4 }, ++ { "GREATER", 5 }, ++ { "NOT_EQUAL", 6 }, ++ { "GREATER_EQUAL", 7 }, ++ { "ALWAYS", 8 }, ++ { NULL } ++ }; ++ ++ static const struct rhs_named_value stencil_op_values[] = ++ { ++ { "KEEP", 1 }, ++ { "ZERO", 2 }, ++ { "REPLACE", 3 }, ++ { "INCR_SAT", 4 }, ++ { "DECR_SAT", 5 }, ++ { "INVERT", 6 }, ++ { "INCR", 7 }, ++ { "DECR", 8 }, ++ { NULL } ++ }; ++ ++ static const struct rhs_named_value fill_values[] = ++ { ++ { "WIREFRAME", 2 }, ++ { "SOLID", 3 }, ++ { NULL } ++ }; ++ ++ static const struct rhs_named_value cull_values[] = ++ { ++ { "NONE", 1 }, ++ { "FRONT", 2 }, ++ { "BACK", 3 }, ++ { NULL } ++ }; ++ + static const struct state + { + const char *name; + enum hlsl_type_class container; +- enum hlsl_base_type type; ++ enum hlsl_type_class class; ++ enum state_property_component_type type; + unsigned int dimx; + uint32_t id; + const struct rhs_named_value *values; + } + states[] = + { +- { "Filter", HLSL_CLASS_SAMPLER, HLSL_TYPE_UINT, 1, 45, filter_values }, +- { "AddressU", HLSL_CLASS_SAMPLER, HLSL_TYPE_UINT, 1, 46, address_values }, +- { "AddressV", HLSL_CLASS_SAMPLER, HLSL_TYPE_UINT, 1, 47, address_values }, +- { "AddressW", HLSL_CLASS_SAMPLER, HLSL_TYPE_UINT, 1, 48, address_values }, +- { "MipLODBias", HLSL_CLASS_SAMPLER, HLSL_TYPE_FLOAT, 1, 49 }, +- { "MaxAnisotropy", HLSL_CLASS_SAMPLER, HLSL_TYPE_UINT, 1, 50 }, +- { "ComparisonFunc", HLSL_CLASS_SAMPLER, HLSL_TYPE_UINT, 1, 51, compare_func_values }, +- { "BorderColor", HLSL_CLASS_SAMPLER, HLSL_TYPE_FLOAT, 4, 52 }, +- { "MinLOD", HLSL_CLASS_SAMPLER, HLSL_TYPE_FLOAT, 1, 53 }, +- { "MaxLOD", HLSL_CLASS_SAMPLER, HLSL_TYPE_FLOAT, 1, 54 }, ++ { "FillMode", HLSL_CLASS_RASTERIZER_STATE, HLSL_CLASS_SCALAR, FX_UINT, 1, 12, fill_values }, ++ { "CullMode", HLSL_CLASS_RASTERIZER_STATE, HLSL_CLASS_SCALAR, FX_UINT, 1, 13, cull_values }, ++ { "FrontCounterClockwise", HLSL_CLASS_RASTERIZER_STATE, HLSL_CLASS_SCALAR, FX_BOOL, 1, 14 }, ++ { "DepthBias", HLSL_CLASS_RASTERIZER_STATE, HLSL_CLASS_SCALAR, FX_UINT, 1, 15 }, ++ { "DepthBiasClamp", HLSL_CLASS_RASTERIZER_STATE, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 16 }, ++ { "SlopeScaledDepthBias", HLSL_CLASS_RASTERIZER_STATE, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 17 }, ++ { "DepthClipEnable", HLSL_CLASS_RASTERIZER_STATE, HLSL_CLASS_SCALAR, FX_BOOL, 1, 18 }, ++ { "ScissorEnable", HLSL_CLASS_RASTERIZER_STATE, HLSL_CLASS_SCALAR, FX_BOOL, 1, 19 }, ++ { "MultisampleEnable", HLSL_CLASS_RASTERIZER_STATE, HLSL_CLASS_SCALAR, FX_BOOL, 1, 20 }, ++ { "AntializedLineEnable", HLSL_CLASS_RASTERIZER_STATE, HLSL_CLASS_SCALAR, FX_BOOL, 1, 21 }, ++ ++ { "DepthEnable", HLSL_CLASS_DEPTH_STENCIL_STATE, HLSL_CLASS_SCALAR, FX_BOOL, 1, 22 }, ++ { "DepthWriteMask", HLSL_CLASS_DEPTH_STENCIL_STATE, HLSL_CLASS_SCALAR, FX_UINT, 1, 23, depth_write_mask_values }, ++ { "DepthFunc", HLSL_CLASS_DEPTH_STENCIL_STATE, HLSL_CLASS_SCALAR, FX_UINT, 1, 24, comparison_values }, ++ { "StencilEnable", HLSL_CLASS_DEPTH_STENCIL_STATE, HLSL_CLASS_SCALAR, FX_BOOL, 1, 25 }, ++ { "StencilReadMask", HLSL_CLASS_DEPTH_STENCIL_STATE, HLSL_CLASS_SCALAR, FX_UINT8, 1, 26 }, ++ { "StencilWriteMask", HLSL_CLASS_DEPTH_STENCIL_STATE, HLSL_CLASS_SCALAR, FX_UINT8, 1, 27 }, ++ { "FrontFaceStencilFail", HLSL_CLASS_DEPTH_STENCIL_STATE, HLSL_CLASS_SCALAR, FX_UINT, 1, 28, stencil_op_values }, ++ { "FrontFaceStencilDepthFail", HLSL_CLASS_DEPTH_STENCIL_STATE, HLSL_CLASS_SCALAR, FX_UINT, 1, 29, stencil_op_values }, ++ { "FrontFaceStencilPass", HLSL_CLASS_DEPTH_STENCIL_STATE, HLSL_CLASS_SCALAR, FX_UINT, 1, 30, stencil_op_values }, ++ { "FrontFaceStencilFunc", HLSL_CLASS_DEPTH_STENCIL_STATE, HLSL_CLASS_SCALAR, FX_UINT, 1, 31, comparison_values }, ++ { "BackFaceStencilFail", HLSL_CLASS_DEPTH_STENCIL_STATE, HLSL_CLASS_SCALAR, FX_UINT, 1, 32, stencil_op_values }, ++ { "BackFaceStencilDepthFail", HLSL_CLASS_DEPTH_STENCIL_STATE, HLSL_CLASS_SCALAR, FX_UINT, 1, 33, stencil_op_values }, ++ { "BackFaceStencilPass", HLSL_CLASS_DEPTH_STENCIL_STATE, HLSL_CLASS_SCALAR, FX_UINT, 1, 34, stencil_op_values }, ++ { "BackFaceStencilFunc", HLSL_CLASS_DEPTH_STENCIL_STATE, HLSL_CLASS_SCALAR, FX_UINT, 1, 35, comparison_values }, ++ ++ { "Filter", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_UINT, 1, 45, filter_values }, ++ { "AddressU", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_UINT, 1, 46, address_values }, ++ { "AddressV", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_UINT, 1, 47, address_values }, ++ { "AddressW", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_UINT, 1, 48, address_values }, ++ { "MipLODBias", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 49 }, ++ { "MaxAnisotropy", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_UINT, 1, 50 }, ++ { "ComparisonFunc", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_UINT, 1, 51, compare_func_values }, ++ { "BorderColor", HLSL_CLASS_SAMPLER, HLSL_CLASS_VECTOR, FX_FLOAT, 4, 52 }, ++ { "MinLOD", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 53 }, ++ { "MaxLOD", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 54 }, + /* TODO: "Texture" field */ + }; + const struct hlsl_type *type = hlsl_get_multiarray_element_type(var->data_type); + struct replace_state_context replace_context; ++ struct hlsl_type *state_type = NULL; + struct hlsl_ir_node *node, *cast; + const struct state *state = NULL; + struct hlsl_ctx *ctx = fx->ctx; +- struct hlsl_type *state_type; ++ enum hlsl_base_type base_type; + unsigned int i; +- bool progress; + + for (i = 0; i < ARRAY_SIZE(states); ++i) + { +@@ -1273,28 +1551,54 @@ static void resolve_fx_4_state_block_values(struct hlsl_ir_var *var, struct hlsl + replace_context.values = state->values; + replace_context.var = var; + +- /* Turned named constants to actual constants. */ ++ /* Turn named constants to actual constants. */ + hlsl_transform_ir(ctx, replace_state_block_constant, entry->instrs, &replace_context); ++ fold_state_value(ctx, entry); + +- if (state->dimx) +- state_type = hlsl_get_vector_type(ctx, state->type, state->dimx); +- else +- state_type = hlsl_get_scalar_type(ctx, state->type); ++ /* Now cast and run folding again. */ + +- /* Cast to expected property type. */ +- node = entry->args->node; +- if (!(cast = hlsl_new_cast(ctx, node, state_type, &var->loc))) +- return; +- list_add_after(&node->entry, &cast->entry); +- +- hlsl_src_remove(entry->args); +- hlsl_src_from_node(entry->args, cast); ++ base_type = hlsl_type_from_fx_type(state->type); ++ switch (state->class) ++ { ++ case HLSL_CLASS_VECTOR: ++ state_type = hlsl_get_vector_type(ctx, base_type, state->dimx); ++ break; ++ case HLSL_CLASS_SCALAR: ++ state_type = hlsl_get_scalar_type(ctx, base_type); ++ break; ++ case HLSL_CLASS_TEXTURE: ++ hlsl_fixme(ctx, &ctx->location, "Object type fields are not supported."); ++ break; ++ default: ++ ; ++ } + +- do ++ if (state_type) + { +- progress = hlsl_transform_ir(ctx, hlsl_fold_constant_exprs, entry->instrs, NULL); +- progress |= hlsl_copy_propagation_execute(ctx, entry->instrs); +- } while (progress); ++ node = entry->args->node; ++ if (!(cast = hlsl_new_cast(ctx, node, state_type, &var->loc))) ++ return; ++ list_add_after(&node->entry, &cast->entry); ++ ++ /* FX_UINT8 values are using 32-bits in the binary. Mask higher 24 bits for those. */ ++ if (state->type == FX_UINT8) ++ { ++ struct hlsl_ir_node *mask; ++ ++ if (!(mask = hlsl_new_uint_constant(ctx, 0xff, &var->loc))) ++ return; ++ list_add_after(&cast->entry, &mask->entry); ++ ++ if (!(cast = hlsl_new_binary_expr(ctx, HLSL_OP2_BIT_AND, cast, mask))) ++ return; ++ list_add_after(&mask->entry, &cast->entry); ++ } ++ ++ hlsl_src_remove(entry->args); ++ hlsl_src_from_node(entry->args, cast); ++ ++ fold_state_value(ctx, entry); ++ } + } + + static void write_fx_4_state_object_initializer(struct hlsl_ir_var *var, struct fx_write_context *fx) +@@ -1387,19 +1691,27 @@ static void write_fx_4_object_variable(struct hlsl_ir_var *var, struct fx_write_ + fx->dsv_count += elements_count; + break; + ++ case HLSL_CLASS_DEPTH_STENCIL_STATE: ++ write_fx_4_state_object_initializer(var, fx); ++ fx->depth_stencil_state_count += elements_count; ++ break; ++ + case HLSL_CLASS_SAMPLER: + write_fx_4_state_object_initializer(var, fx); + fx->sampler_state_count += elements_count; + break; + ++ case HLSL_CLASS_RASTERIZER_STATE: ++ write_fx_4_state_object_initializer(var, fx); ++ fx->rasterizer_state_count += elements_count; ++ break; ++ + default: + hlsl_fixme(ctx, &ctx->location, "Writing initializer for object type %u is not implemented.", + type->e.numeric.type); + } + +- put_u32(buffer, 0); /* Annotations count */ +- if (has_annotations(var)) +- hlsl_fixme(ctx, &ctx->location, "Writing annotations for object variables is not implemented."); ++ write_fx_4_annotations(var->annotations, fx); + + ++fx->object_variable_count; + } +@@ -1442,9 +1754,7 @@ static void write_fx_4_buffer(struct hlsl_buffer *b, struct fx_write_context *fx + } + else + { +- put_u32(buffer, 0); /* Annotations count */ +- if (b->annotations) +- hlsl_fixme(ctx, &b->loc, "Writing annotations for buffers is not implemented."); ++ write_fx_4_annotations(b->annotations, fx); + ++fx->buffer_count; + } + +@@ -1490,8 +1800,10 @@ static bool is_supported_object_variable(const struct hlsl_ctx *ctx, const struc + + switch (type->class) + { ++ case HLSL_CLASS_DEPTH_STENCIL_STATE: + case HLSL_CLASS_DEPTH_STENCIL_VIEW: + case HLSL_CLASS_PIXEL_SHADER: ++ case HLSL_CLASS_RASTERIZER_STATE: + case HLSL_CLASS_RENDER_TARGET_VIEW: + case HLSL_CLASS_SAMPLER: + case HLSL_CLASS_TEXTURE: +@@ -1558,9 +1870,9 @@ static int hlsl_fx_4_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) + size_offset = put_u32(&buffer, 0); /* Unstructured size. */ + put_u32(&buffer, 0); /* String count. */ + put_u32(&buffer, fx.texture_count); +- put_u32(&buffer, 0); /* Depth stencil state count. */ ++ put_u32(&buffer, fx.depth_stencil_state_count); + put_u32(&buffer, 0); /* Blend state count. */ +- put_u32(&buffer, 0); /* Rasterizer state count. */ ++ put_u32(&buffer, fx.rasterizer_state_count); + put_u32(&buffer, fx.sampler_state_count); + put_u32(&buffer, fx.rtv_count); + put_u32(&buffer, fx.dsv_count); +@@ -1616,9 +1928,9 @@ static int hlsl_fx_5_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) + size_offset = put_u32(&buffer, 0); /* Unstructured size. */ + put_u32(&buffer, 0); /* String count. */ + put_u32(&buffer, fx.texture_count); +- put_u32(&buffer, 0); /* Depth stencil state count. */ ++ put_u32(&buffer, fx.depth_stencil_state_count); + put_u32(&buffer, 0); /* Blend state count. */ +- put_u32(&buffer, 0); /* Rasterizer state count. */ ++ put_u32(&buffer, fx.rasterizer_state_count); + put_u32(&buffer, fx.sampler_state_count); + put_u32(&buffer, fx.rtv_count); + put_u32(&buffer, fx.dsv_count); +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c +index c69af4e94bb..a157590c97a 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c +@@ -369,15 +369,18 @@ static void hlsl_type_calculate_reg_size(struct hlsl_ctx *ctx, struct hlsl_type + type->reg_size[HLSL_REGSET_UAVS] = 1; + break; + ++ case HLSL_CLASS_DEPTH_STENCIL_STATE: + case HLSL_CLASS_DEPTH_STENCIL_VIEW: + case HLSL_CLASS_EFFECT_GROUP: + case HLSL_CLASS_PASS: + case HLSL_CLASS_PIXEL_SHADER: ++ case HLSL_CLASS_RASTERIZER_STATE: + case HLSL_CLASS_RENDER_TARGET_VIEW: + case HLSL_CLASS_STRING: + case HLSL_CLASS_TECHNIQUE: + case HLSL_CLASS_VERTEX_SHADER: + case HLSL_CLASS_VOID: ++ case HLSL_CLASS_CONSTANT_BUFFER: + break; + } + } +@@ -437,11 +440,13 @@ static bool type_is_single_component(const struct hlsl_type *type) + { + switch (type->class) + { ++ case HLSL_CLASS_DEPTH_STENCIL_STATE: + case HLSL_CLASS_DEPTH_STENCIL_VIEW: + case HLSL_CLASS_PIXEL_SHADER: + case HLSL_CLASS_SCALAR: + case HLSL_CLASS_SAMPLER: + case HLSL_CLASS_STRING: ++ case HLSL_CLASS_RASTERIZER_STATE: + case HLSL_CLASS_RENDER_TARGET_VIEW: + case HLSL_CLASS_TEXTURE: + case HLSL_CLASS_UAV: +@@ -452,6 +457,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 +536,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(); + } +@@ -581,8 +593,10 @@ unsigned int hlsl_type_get_component_offset(struct hlsl_ctx *ctx, struct hlsl_ty + } + break; + ++ case HLSL_CLASS_DEPTH_STENCIL_STATE: + case HLSL_CLASS_DEPTH_STENCIL_VIEW: + case HLSL_CLASS_PIXEL_SHADER: ++ case HLSL_CLASS_RASTERIZER_STATE: + case HLSL_CLASS_RENDER_TARGET_VIEW: + case HLSL_CLASS_SAMPLER: + case HLSL_CLASS_STRING: +@@ -597,6 +611,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 +885,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,8 +990,13 @@ 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_STATE: + case HLSL_CLASS_DEPTH_STENCIL_VIEW: + case HLSL_CLASS_PIXEL_SHADER: ++ case HLSL_CLASS_RASTERIZER_STATE: + case HLSL_CLASS_RENDER_TARGET_VIEW: + case HLSL_CLASS_SAMPLER: + case HLSL_CLASS_STRING: +@@ -1043,10 +1077,15 @@ 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_STATE: + case HLSL_CLASS_DEPTH_STENCIL_VIEW: + case HLSL_CLASS_EFFECT_GROUP: + case HLSL_CLASS_PASS: + case HLSL_CLASS_PIXEL_SHADER: ++ case HLSL_CLASS_RASTERIZER_STATE: + case HLSL_CLASS_RENDER_TARGET_VIEW: + case HLSL_CLASS_STRING: + case HLSL_CLASS_VERTEX_SHADER: +@@ -2413,10 +2452,21 @@ 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_STATE: + case HLSL_CLASS_DEPTH_STENCIL_VIEW: + case HLSL_CLASS_EFFECT_GROUP: + case HLSL_CLASS_PASS: + case HLSL_CLASS_PIXEL_SHADER: ++ case HLSL_CLASS_RASTERIZER_STATE: + case HLSL_CLASS_RENDER_TARGET_VIEW: + case HLSL_CLASS_SAMPLER: + case HLSL_CLASS_STRING: +@@ -3761,9 +3811,11 @@ static void declare_predefined_types(struct hlsl_ctx *ctx) + + 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)); + hlsl_scope_add_type(ctx->globals, hlsl_new_simple_type(ctx, "fxgroup", HLSL_CLASS_EFFECT_GROUP)); + hlsl_scope_add_type(ctx->globals, hlsl_new_simple_type(ctx, "pass", HLSL_CLASS_PASS)); + 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)); +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h +index 179cc219e68..3e0d55a7f7d 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h +@@ -78,10 +78,12 @@ enum hlsl_type_class + HLSL_CLASS_LAST_NUMERIC = HLSL_CLASS_MATRIX, + HLSL_CLASS_STRUCT, + HLSL_CLASS_ARRAY, ++ HLSL_CLASS_DEPTH_STENCIL_STATE, + HLSL_CLASS_DEPTH_STENCIL_VIEW, + HLSL_CLASS_EFFECT_GROUP, + HLSL_CLASS_PASS, + HLSL_CLASS_PIXEL_SHADER, ++ HLSL_CLASS_RASTERIZER_STATE, + HLSL_CLASS_RENDER_TARGET_VIEW, + HLSL_CLASS_SAMPLER, + HLSL_CLASS_STRING, +@@ -89,6 +91,7 @@ enum hlsl_type_class + HLSL_CLASS_TEXTURE, + HLSL_CLASS_UAV, + HLSL_CLASS_VERTEX_SHADER, ++ HLSL_CLASS_CONSTANT_BUFFER, + HLSL_CLASS_VOID, + }; + +@@ -385,6 +388,7 @@ struct hlsl_attribute + #define HLSL_STORAGE_LINEAR 0x00010000 + #define HLSL_MODIFIER_SINGLE 0x00020000 + #define HLSL_MODIFIER_EXPORT 0x00040000 ++#define HLSL_STORAGE_ANNOTATION 0x00080000 + + #define HLSL_TYPE_MODIFIERS_MASK (HLSL_MODIFIER_PRECISE | HLSL_MODIFIER_VOLATILE | \ + HLSL_MODIFIER_CONST | HLSL_MODIFIER_ROW_MAJOR | \ +@@ -838,6 +842,8 @@ struct hlsl_scope + bool loop; + /* The scope was created for the switch statement. */ + bool _switch; ++ /* The scope contains annotation variables. */ ++ bool annotations; + }; + + struct hlsl_profile_info +@@ -1391,6 +1397,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/libs/vkd3d-shader/hlsl.l b/libs/vkd3d/libs/vkd3d-shader/hlsl.l +index 91418775e1b..55993dac2b4 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.l ++++ b/libs/vkd3d/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/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y +index 9c75c87d36e..a02692399f7 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y +@@ -1214,12 +1214,42 @@ static bool add_effect_group(struct hlsl_ctx *ctx, const char *name, struct hlsl + return true; + } + +-static bool parse_reservation_index(const char *string, char *type, uint32_t *index) ++static bool parse_reservation_index(struct hlsl_ctx *ctx, const char *string, unsigned int bracket_offset, ++ struct hlsl_reg_reservation *reservation) + { +- if (!sscanf(string + 1, "%u", index)) +- return false; ++ char *endptr; ++ ++ reservation->reg_type = ascii_tolower(string[0]); ++ ++ /* Prior to SM5.1, fxc simply ignored bracket offsets for 'b' types. */ ++ if (reservation->reg_type == 'b' && hlsl_version_lt(ctx, 5, 1)) ++ { ++ bracket_offset = 0; ++ } ++ ++ if (string[1] == '\0') ++ { ++ reservation->reg_index = bracket_offset; ++ return true; ++ } ++ ++ reservation->reg_index = strtoul(string + 1, &endptr, 10) + bracket_offset; ++ ++ if (*endptr) ++ { ++ /* fxc for SM >= 4 treats all parse failures for 'b' types as successes, ++ * setting index to -1. It will later fail while validating slot limits. */ ++ if (reservation->reg_type == 'b' && hlsl_version_ge(ctx, 4, 0)) ++ { ++ reservation->reg_index = -1; ++ return true; ++ } ++ ++ /* All other types tolerate leftover characters. */ ++ if (endptr == string + 1) ++ return false; ++ } + +- *type = ascii_tolower(string[0]); + return true; + } + +@@ -2194,6 +2224,9 @@ static unsigned int get_component_index_from_default_initializer_index(struct hl + if (ctx->profile->major_version < 4) + return index; + ++ if (ctx->profile->type == VKD3D_SHADER_TYPE_EFFECT) ++ return index; ++ + switch (type->class) + { + case HLSL_CLASS_MATRIX: +@@ -2346,6 +2379,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; +@@ -2365,6 +2399,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) +@@ -2446,7 +2486,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) + { +@@ -2469,8 +2518,11 @@ static void declare_var(struct hlsl_ctx *ctx, struct parse_variable_def *v) + if (!(modifiers & HLSL_STORAGE_STATIC)) + var->storage_modifiers |= HLSL_STORAGE_UNIFORM; + +- if (ctx->profile->major_version < 5 && (var->storage_modifiers & HLSL_STORAGE_UNIFORM)) ++ if ((ctx->profile->major_version < 5 || ctx->profile->type == VKD3D_SHADER_TYPE_EFFECT) ++ && (var->storage_modifiers & HLSL_STORAGE_UNIFORM)) ++ { + check_invalid_object_fields(ctx, var); ++ } + + if ((func = hlsl_get_first_func_decl(ctx, var->name))) + { +@@ -2576,11 +2628,19 @@ static struct hlsl_block *initialize_vars(struct hlsl_ctx *ctx, struct list *var + unsigned int size, k; + + is_default_values_initializer = (ctx->cur_buffer != ctx->globals_buffer) +- || (var->storage_modifiers & HLSL_STORAGE_UNIFORM); ++ || (var->storage_modifiers & HLSL_STORAGE_UNIFORM) ++ || ctx->cur_scope->annotations; + + if (is_default_values_initializer) + { +- assert(!var->default_values); ++ /* Default values might have been allocated already for another variable of the same name, ++ in the same scope. */ ++ if (var->default_values) ++ { ++ free_parse_variable_def(v); ++ continue; ++ } ++ + if (!(var->default_values = hlsl_calloc(ctx, component_count, sizeof(*var->default_values)))) + { + free_parse_variable_def(v); +@@ -4233,6 +4293,7 @@ static bool intrinsic_tanh(struct hlsl_ctx *ctx, + static bool intrinsic_tex(struct hlsl_ctx *ctx, const struct parse_initializer *params, + const struct vkd3d_shader_location *loc, const char *name, enum hlsl_sampler_dim dim) + { ++ unsigned int sampler_dim = hlsl_sampler_dim_count(dim); + struct hlsl_resource_load_params load_params = { 0 }; + const struct hlsl_type *sampler_type; + struct hlsl_ir_node *coords, *sample; +@@ -4244,11 +4305,6 @@ static bool intrinsic_tex(struct hlsl_ctx *ctx, const struct parse_initializer * + return false; + } + +- if (params->args_count == 4) +- { +- hlsl_fixme(ctx, loc, "Samples with gradients are not implemented."); +- } +- + sampler_type = params->args[0]->data_type; + if (sampler_type->class != HLSL_CLASS_SAMPLER + || (sampler_type->sampler_dim != dim && sampler_type->sampler_dim != HLSL_SAMPLER_DIM_GENERIC)) +@@ -4272,12 +4328,12 @@ static bool intrinsic_tex(struct hlsl_ctx *ctx, const struct parse_initializer * + else + load_params.type = HLSL_RESOURCE_SAMPLE_LOD_BIAS; + +- if (!(c = hlsl_new_swizzle(ctx, HLSL_SWIZZLE(X, Y, Z, W), hlsl_sampler_dim_count(dim), params->args[1], loc))) ++ if (!(c = hlsl_new_swizzle(ctx, HLSL_SWIZZLE(X, Y, Z, W), sampler_dim, params->args[1], loc))) + return false; + hlsl_block_add_instr(params->instrs, c); + +- if (!(coords = add_implicit_conversion(ctx, params->instrs, c, hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, +- hlsl_sampler_dim_count(dim)), loc))) ++ if (!(coords = add_implicit_conversion(ctx, params->instrs, c, ++ hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, sampler_dim), loc))) + { + return false; + } +@@ -4304,14 +4360,13 @@ static bool intrinsic_tex(struct hlsl_ctx *ctx, const struct parse_initializer * + + if (hlsl_version_ge(ctx, 4, 0)) + { +- unsigned int count = hlsl_sampler_dim_count(dim); + struct hlsl_ir_node *divisor; + +- if (!(divisor = hlsl_new_swizzle(ctx, HLSL_SWIZZLE(W, W, W, W), count, coords, loc))) ++ if (!(divisor = hlsl_new_swizzle(ctx, HLSL_SWIZZLE(W, W, W, W), sampler_dim, coords, loc))) + return false; + hlsl_block_add_instr(params->instrs, divisor); + +- if (!(coords = hlsl_new_swizzle(ctx, HLSL_SWIZZLE(X, Y, Z, W), count, coords, loc))) ++ if (!(coords = hlsl_new_swizzle(ctx, HLSL_SWIZZLE(X, Y, Z, W), sampler_dim, coords, loc))) + return false; + hlsl_block_add_instr(params->instrs, coords); + +@@ -4325,12 +4380,34 @@ static bool intrinsic_tex(struct hlsl_ctx *ctx, const struct parse_initializer * + load_params.type = HLSL_RESOURCE_SAMPLE_PROJ; + } + } ++ else if (params->args_count == 4) /* Gradient sampling. */ ++ { ++ if (!(coords = add_implicit_conversion(ctx, params->instrs, params->args[1], ++ hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, sampler_dim), loc))) ++ { ++ return false; ++ } ++ ++ if (!(load_params.ddx = add_implicit_conversion(ctx, params->instrs, params->args[2], ++ hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, sampler_dim), loc))) ++ { ++ return false; ++ } ++ ++ if (!(load_params.ddy = add_implicit_conversion(ctx, params->instrs, params->args[3], ++ hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, sampler_dim), loc))) ++ { ++ return false; ++ } ++ ++ load_params.type = HLSL_RESOURCE_SAMPLE_GRAD; ++ } + else + { + load_params.type = HLSL_RESOURCE_SAMPLE; + + if (!(coords = add_implicit_conversion(ctx, params->instrs, params->args[1], +- hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, hlsl_sampler_dim_count(dim)), loc))) ++ hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, sampler_dim), loc))) + { + return false; + } +@@ -4386,6 +4463,12 @@ static bool intrinsic_tex1D(struct hlsl_ctx *ctx, + return intrinsic_tex(ctx, params, loc, "tex1D", HLSL_SAMPLER_DIM_1D); + } + ++static bool intrinsic_tex1Dgrad(struct hlsl_ctx *ctx, ++ const struct parse_initializer *params, const struct vkd3d_shader_location *loc) ++{ ++ return intrinsic_tex(ctx, params, loc, "tex1Dgrad", HLSL_SAMPLER_DIM_1D); ++} ++ + static bool intrinsic_tex2D(struct hlsl_ctx *ctx, + const struct parse_initializer *params, const struct vkd3d_shader_location *loc) + { +@@ -4398,6 +4481,12 @@ static bool intrinsic_tex2Dbias(struct hlsl_ctx *ctx, + return intrinsic_tex(ctx, params, loc, "tex2Dbias", HLSL_SAMPLER_DIM_2D); + } + ++static bool intrinsic_tex2Dgrad(struct hlsl_ctx *ctx, ++ const struct parse_initializer *params, const struct vkd3d_shader_location *loc) ++{ ++ return intrinsic_tex(ctx, params, loc, "tex2Dgrad", HLSL_SAMPLER_DIM_2D); ++} ++ + static bool intrinsic_tex2Dlod(struct hlsl_ctx *ctx, + const struct parse_initializer *params, const struct vkd3d_shader_location *loc) + { +@@ -4416,6 +4505,12 @@ static bool intrinsic_tex3D(struct hlsl_ctx *ctx, + return intrinsic_tex(ctx, params, loc, "tex3D", HLSL_SAMPLER_DIM_3D); + } + ++static bool intrinsic_tex3Dgrad(struct hlsl_ctx *ctx, ++ const struct parse_initializer *params, const struct vkd3d_shader_location *loc) ++{ ++ return intrinsic_tex(ctx, params, loc, "tex3Dgrad", HLSL_SAMPLER_DIM_3D); ++} ++ + static bool intrinsic_tex3Dproj(struct hlsl_ctx *ctx, + const struct parse_initializer *params, const struct vkd3d_shader_location *loc) + { +@@ -4428,6 +4523,12 @@ static bool intrinsic_texCUBE(struct hlsl_ctx *ctx, + return intrinsic_tex(ctx, params, loc, "texCUBE", HLSL_SAMPLER_DIM_CUBE); + } + ++static bool intrinsic_texCUBEgrad(struct hlsl_ctx *ctx, ++ const struct parse_initializer *params, const struct vkd3d_shader_location *loc) ++{ ++ return intrinsic_tex(ctx, params, loc, "texCUBEgrad", HLSL_SAMPLER_DIM_CUBE); ++} ++ + static bool intrinsic_texCUBEproj(struct hlsl_ctx *ctx, + const struct parse_initializer *params, const struct vkd3d_shader_location *loc) + { +@@ -4617,13 +4718,17 @@ intrinsic_functions[] = + {"tan", 1, true, intrinsic_tan}, + {"tanh", 1, true, intrinsic_tanh}, + {"tex1D", -1, false, intrinsic_tex1D}, ++ {"tex1Dgrad", 4, false, intrinsic_tex1Dgrad}, + {"tex2D", -1, false, intrinsic_tex2D}, + {"tex2Dbias", 2, false, intrinsic_tex2Dbias}, ++ {"tex2Dgrad", 4, false, intrinsic_tex2Dgrad}, + {"tex2Dlod", 2, false, intrinsic_tex2Dlod}, + {"tex2Dproj", 2, false, intrinsic_tex2Dproj}, + {"tex3D", -1, false, intrinsic_tex3D}, ++ {"tex3Dgrad", 4, false, intrinsic_tex3Dgrad}, + {"tex3Dproj", 2, false, intrinsic_tex3Dproj}, + {"texCUBE", -1, false, intrinsic_texCUBE}, ++ {"texCUBEgrad", 4, false, intrinsic_texCUBEgrad}, + {"texCUBEproj", 2, false, intrinsic_texCUBEproj}, + {"transpose", 1, true, intrinsic_transpose}, + {"trunc", 1, true, intrinsic_trunc}, +@@ -5693,6 +5798,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 +@@ -5883,6 +5989,8 @@ static bool state_block_add_entry(struct hlsl_state_block *state_block, struct h + + %type if_body + ++%type array ++ + %type var_modifiers + + %type any_identifier +@@ -5954,19 +6062,31 @@ pass: + + annotations_list: + variables_def_typed ';' ++ { ++ struct hlsl_block *block; ++ ++ block = initialize_vars(ctx, $1); ++ destroy_block(block); ++ } + | annotations_list variables_def_typed ';' ++ { ++ struct hlsl_block *block; ++ ++ block = initialize_vars(ctx, $2); ++ destroy_block(block); ++ } + + annotations_opt: + %empty + { + $$ = NULL; + } +- | '<' scope_start '>' ++ | '<' annotations_scope_start '>' + { + hlsl_pop_scope(ctx); + $$ = NULL; + } +- | '<' scope_start annotations_list '>' ++ | '<' annotations_scope_start annotations_list '>' + { + struct hlsl_scope *scope = ctx->cur_scope; + +@@ -6494,6 +6614,13 @@ switch_scope_start: + ctx->cur_scope->_switch = true; + } + ++annotations_scope_start: ++ %empty ++ { ++ hlsl_push_scope(ctx); ++ ctx->cur_scope->annotations = true; ++ } ++ + var_identifier: + VAR_IDENTIFIER + | NEW_IDENTIFIER +@@ -6545,22 +6672,34 @@ register_reservation: + ':' KW_REGISTER '(' any_identifier ')' + { + memset(&$$, 0, sizeof($$)); +- if (!parse_reservation_index($4, &$$.reg_type, &$$.reg_index)) ++ if (!parse_reservation_index(ctx, $4, 0, &$$)) + hlsl_error(ctx, &@4, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, + "Invalid register reservation '%s'.", $4); + + vkd3d_free($4); + } ++ | ':' KW_REGISTER '(' any_identifier '[' expr ']' ')' ++ { ++ memset(&$$, 0, sizeof($$)); ++ if (!parse_reservation_index(ctx, $4, evaluate_static_expression_as_uint(ctx, $6, &@6), &$$)) ++ { ++ hlsl_error(ctx, &@4, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, ++ "Invalid register reservation '%s'.", $4); ++ } ++ ++ vkd3d_free($4); ++ vkd3d_free($6); ++ } + | ':' KW_REGISTER '(' any_identifier ',' any_identifier ')' + { + memset(&$$, 0, sizeof($$)); +- if (parse_reservation_index($6, &$$.reg_type, &$$.reg_index)) ++ if (parse_reservation_index(ctx, $6, 0, &$$)) + { + hlsl_fixme(ctx, &@4, "Reservation shader target %s.", $4); + } + else if (parse_reservation_space($6, &$$.reg_space)) + { +- if (!parse_reservation_index($4, &$$.reg_type, &$$.reg_index)) ++ if (!parse_reservation_index(ctx, $4, 0, &$$)) + hlsl_error(ctx, &@4, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, + "Invalid register reservation '%s'.", $4); + } +@@ -6573,12 +6712,45 @@ register_reservation: + vkd3d_free($4); + vkd3d_free($6); + } ++ | ':' KW_REGISTER '(' any_identifier '[' expr ']' ',' any_identifier ')' ++ { ++ memset(&$$, 0, sizeof($$)); ++ ++ if (!parse_reservation_space($9, &$$.reg_space)) ++ hlsl_error(ctx, &@9, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, ++ "Invalid register space reservation '%s'.", $9); ++ ++ if (!parse_reservation_index(ctx, $4, evaluate_static_expression_as_uint(ctx, $6, &@6), &$$)) ++ { ++ hlsl_error(ctx, &@4, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, ++ "Invalid register reservation '%s'.", $4); ++ } ++ ++ vkd3d_free($4); ++ vkd3d_free($6); ++ vkd3d_free($9); ++ } ++ | ':' KW_REGISTER '(' any_identifier ',' any_identifier '[' expr ']' ')' ++ { ++ hlsl_fixme(ctx, &@4, "Reservation shader target %s.", $4); ++ ++ memset(&$$, 0, sizeof($$)); ++ if (!parse_reservation_index(ctx, $6, evaluate_static_expression_as_uint(ctx, $8, &@8), &$$)) ++ { ++ hlsl_error(ctx, &@6, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, ++ "Invalid register reservation '%s'.", $6); ++ } ++ ++ vkd3d_free($4); ++ vkd3d_free($6); ++ vkd3d_free($8); ++ } + | ':' KW_REGISTER '(' any_identifier ',' any_identifier ',' any_identifier ')' + { + hlsl_fixme(ctx, &@4, "Reservation shader target %s.", $4); + + memset(&$$, 0, sizeof($$)); +- if (!parse_reservation_index($6, &$$.reg_type, &$$.reg_index)) ++ if (!parse_reservation_index(ctx, $6, 0, &$$)) + hlsl_error(ctx, &@6, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, + "Invalid register reservation '%s'.", $6); + +@@ -6590,6 +6762,26 @@ register_reservation: + vkd3d_free($6); + vkd3d_free($8); + } ++ | ':' KW_REGISTER '(' any_identifier ',' any_identifier '[' expr ']' ',' any_identifier ')' ++ { ++ hlsl_fixme(ctx, &@4, "Reservation shader target %s.", $4); ++ ++ memset(&$$, 0, sizeof($$)); ++ if (!parse_reservation_index(ctx, $6, evaluate_static_expression_as_uint(ctx, $8, &@8), &$$)) ++ { ++ hlsl_error(ctx, &@6, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, ++ "Invalid register reservation '%s'.", $6); ++ } ++ ++ if (!parse_reservation_space($11, &$$.reg_space)) ++ hlsl_error(ctx, &@11, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, ++ "Invalid register space reservation '%s'.", $11); ++ ++ vkd3d_free($4); ++ vkd3d_free($6); ++ vkd3d_free($8); ++ vkd3d_free($11); ++ } + + packoffset_reservation: + ':' KW_PACKOFFSET '(' any_identifier ')' +@@ -6962,6 +7154,10 @@ type_no_void: + { + $$ = hlsl_get_type(ctx->cur_scope, "RenderTargetView", true, true); + } ++ | KW_DEPTHSTENCILSTATE ++ { ++ $$ = hlsl_get_type(ctx->cur_scope, "DepthStencilState", true, true); ++ } + | KW_DEPTHSTENCILVIEW + { + $$ = hlsl_get_type(ctx->cur_scope, "DepthStencilView", true, true); +@@ -6974,6 +7170,17 @@ 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); ++ } ++ | KW_RASTERIZERSTATE ++ { ++ $$ = hlsl_get_type(ctx->cur_scope, "RasterizerState", true, true); ++ } + + type: + type_no_void +@@ -7258,52 +7465,43 @@ variable_def_typed: + $$->modifiers_loc = @1; + } + +-arrays: +- %empty ++array: ++ '[' ']' + { +- $$.sizes = NULL; +- $$.count = 0; ++ $$ = HLSL_ARRAY_ELEMENTS_COUNT_IMPLICIT; + } +- | '[' expr ']' arrays ++ | '[' expr ']' + { +- uint32_t *new_array; +- unsigned int size; +- +- size = evaluate_static_expression_as_uint(ctx, $2, &@2); +- +- destroy_block($2); +- +- $$ = $4; ++ $$ = evaluate_static_expression_as_uint(ctx, $2, &@2); + +- if (!size) ++ if (!$$) + { + hlsl_error(ctx, &@2, VKD3D_SHADER_ERROR_HLSL_INVALID_SIZE, + "Array size is not a positive integer constant."); +- vkd3d_free($$.sizes); + YYABORT; + } + +- if (size > 65536) ++ if ($$ > 65536) + { + hlsl_error(ctx, &@2, VKD3D_SHADER_ERROR_HLSL_INVALID_SIZE, +- "Array size %u is not between 1 and 65536.", size); +- vkd3d_free($$.sizes); ++ "Array size %u is not between 1 and 65536.", $$); + YYABORT; + } + +- if (!(new_array = hlsl_realloc(ctx, $$.sizes, ($$.count + 1) * sizeof(*new_array)))) +- { +- vkd3d_free($$.sizes); +- YYABORT; +- } +- $$.sizes = new_array; +- $$.sizes[$$.count++] = size; ++ destroy_block($2); ++ } ++ ++arrays: ++ %empty ++ { ++ $$.sizes = NULL; ++ $$.count = 0; + } +- | '[' ']' arrays ++ | array arrays + { + uint32_t *new_array; + +- $$ = $3; ++ $$ = $2; + + if (!(new_array = hlsl_realloc(ctx, $$.sizes, ($$.count + 1) * sizeof(*new_array)))) + { +@@ -7312,7 +7510,7 @@ arrays: + } + + $$.sizes = new_array; +- $$.sizes[$$.count++] = HLSL_ARRAY_ELEMENTS_COUNT_IMPLICIT; ++ $$.sizes[$$.count++] = $1; + } + + var_modifiers: +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +index 36270b159a5..33845b0d4bf 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +@@ -1631,9 +1631,11 @@ static bool copy_propagation_transform_load(struct hlsl_ctx *ctx, + + switch (type->class) + { ++ case HLSL_CLASS_DEPTH_STENCIL_STATE: + case HLSL_CLASS_SCALAR: + case HLSL_CLASS_VECTOR: + case HLSL_CLASS_PIXEL_SHADER: ++ case HLSL_CLASS_RASTERIZER_STATE: + case HLSL_CLASS_SAMPLER: + case HLSL_CLASS_TEXTURE: + case HLSL_CLASS_UAV: +@@ -1643,6 +1645,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; +@@ -2562,11 +2565,11 @@ static bool lower_combined_samples(struct hlsl_ctx *ctx, struct hlsl_ir_node *in + case HLSL_RESOURCE_RESINFO: + case HLSL_RESOURCE_SAMPLE_CMP: + case HLSL_RESOURCE_SAMPLE_CMP_LZ: +- case HLSL_RESOURCE_SAMPLE_GRAD: + case HLSL_RESOURCE_SAMPLE_INFO: + return false; + + case HLSL_RESOURCE_SAMPLE: ++ case HLSL_RESOURCE_SAMPLE_GRAD: + case HLSL_RESOURCE_SAMPLE_LOD: + case HLSL_RESOURCE_SAMPLE_LOD_BIAS: + case HLSL_RESOURCE_SAMPLE_PROJ: +@@ -4598,6 +4601,7 @@ static void sort_uniforms_by_numeric_bind_count(struct hlsl_ctx *ctx) + + static void allocate_const_registers(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func) + { ++ struct register_allocator allocator_used = {0}; + struct register_allocator allocator = {0}; + struct hlsl_ir_var *var; + +@@ -4606,6 +4610,7 @@ static void allocate_const_registers(struct hlsl_ctx *ctx, struct hlsl_ir_functi + LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) + { + unsigned int reg_size = var->data_type->reg_size[HLSL_REGSET_NUMERIC]; ++ unsigned int bind_count = var->bind_count[HLSL_REGSET_NUMERIC]; + + if (!var->is_uniform || reg_size == 0) + continue; +@@ -4618,12 +4623,15 @@ static void allocate_const_registers(struct hlsl_ctx *ctx, struct hlsl_ir_functi + assert(reg_size % 4 == 0); + for (i = 0; i < reg_size / 4; ++i) + { +- if (get_available_writemask(&allocator, 1, UINT_MAX, reg_idx + i) != VKD3DSP_WRITEMASK_ALL) ++ if (i < bind_count) + { +- hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, +- "Overlapping register() reservations on 'c%u'.", reg_idx + i); ++ if (get_available_writemask(&allocator_used, 1, UINT_MAX, reg_idx + i) != VKD3DSP_WRITEMASK_ALL) ++ { ++ hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, ++ "Overlapping register() reservations on 'c%u'.", reg_idx + i); ++ } ++ record_allocation(ctx, &allocator_used, reg_idx + i, VKD3DSP_WRITEMASK_ALL, 1, UINT_MAX); + } +- + record_allocation(ctx, &allocator, reg_idx + i, VKD3DSP_WRITEMASK_ALL, 1, UINT_MAX); + } + +@@ -4636,6 +4644,8 @@ static void allocate_const_registers(struct hlsl_ctx *ctx, struct hlsl_ir_functi + } + } + ++ vkd3d_free(allocator_used.allocations); ++ + LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) + { + unsigned int alloc_size = 4 * var->bind_count[HLSL_REGSET_NUMERIC]; +@@ -4777,7 +4787,7 @@ static const struct hlsl_buffer *get_reserved_buffer(struct hlsl_ctx *ctx, uint3 + + LIST_FOR_EACH_ENTRY(buffer, &ctx->buffers, const struct hlsl_buffer, entry) + { +- if (buffer->used_size && buffer->reservation.reg_type == 'b' ++ if (buffer->reservation.reg_type == 'b' + && buffer->reservation.reg_space == space && buffer->reservation.reg_index == index) + return buffer; + } +@@ -4925,6 +4935,14 @@ void hlsl_calculate_buffer_offsets(struct hlsl_ctx *ctx) + } + } + ++static unsigned int get_max_cbuffer_reg_index(struct hlsl_ctx *ctx) ++{ ++ if (hlsl_version_ge(ctx, 5, 1)) ++ return UINT_MAX; ++ ++ return 13; ++} ++ + static void allocate_buffers(struct hlsl_ctx *ctx) + { + struct hlsl_buffer *buffer; +@@ -4956,6 +4974,12 @@ static void allocate_buffers(struct hlsl_ctx *ctx) + { + const struct hlsl_buffer *reserved_buffer = get_reserved_buffer(ctx, + reservation->reg_space, reservation->reg_index); ++ unsigned int max_index = get_max_cbuffer_reg_index(ctx); ++ ++ if (buffer->reservation.reg_index > max_index) ++ hlsl_error(ctx, &buffer->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, ++ "Buffer reservation cb%u exceeds target's maximum (cb%u).", ++ buffer->reservation.reg_index, max_index); + + if (reserved_buffer && reserved_buffer != buffer) + { +@@ -4980,9 +5004,14 @@ static void allocate_buffers(struct hlsl_ctx *ctx) + } + else if (!reservation->reg_type) + { ++ unsigned int max_index = get_max_cbuffer_reg_index(ctx); + while (get_reserved_buffer(ctx, 0, index)) + ++index; + ++ if (index > max_index) ++ hlsl_error(ctx, &buffer->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, ++ "Too many buffers allocated, target's maximum is %u.", max_index); ++ + buffer->reg.space = 0; + buffer->reg.index = index; + if (hlsl_version_ge(ctx, 5, 1)) +diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c +index 5f99be632f2..e5432cb35ce 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/ir.c ++++ b/libs/vkd3d/libs/vkd3d-shader/ir.c +@@ -1899,13 +1899,42 @@ static enum vkd3d_result vsir_program_normalise_combined_samplers(struct vsir_pr + ins->src_count = 3; + break; + ++ case VKD3DSIH_TEXLDD: ++ if (!(srcs = shader_src_param_allocator_get(&program->instructions.src_params, 5))) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ memset(srcs, 0, sizeof(*srcs) * 5); ++ ++ ins->opcode = VKD3DSIH_SAMPLE_GRAD; ++ ++ srcs[0] = ins->src[0]; ++ ++ srcs[1].reg.type = VKD3DSPR_RESOURCE; ++ srcs[1].reg.idx[0] = ins->src[1].reg.idx[0]; ++ srcs[1].reg.idx[1] = ins->src[1].reg.idx[0]; ++ srcs[1].reg.idx_count = 2; ++ srcs[1].reg.data_type = VKD3D_DATA_RESOURCE; ++ srcs[1].reg.dimension = VSIR_DIMENSION_VEC4; ++ srcs[1].swizzle = VKD3D_SHADER_NO_SWIZZLE; ++ ++ srcs[2].reg.type = VKD3DSPR_SAMPLER; ++ srcs[2].reg.idx[0] = ins->src[1].reg.idx[0]; ++ srcs[2].reg.idx[1] = ins->src[1].reg.idx[0]; ++ srcs[2].reg.idx_count = 2; ++ srcs[2].reg.data_type = VKD3D_DATA_SAMPLER; ++ ++ srcs[3] = ins->src[2]; ++ srcs[4] = ins->src[3]; ++ ++ ins->src = srcs; ++ ins->src_count = 5; ++ break; ++ + case VKD3DSIH_TEXBEM: + case VKD3DSIH_TEXBEML: + case VKD3DSIH_TEXCOORD: + case VKD3DSIH_TEXDEPTH: + case VKD3DSIH_TEXDP3: + case VKD3DSIH_TEXDP3TEX: +- case VKD3DSIH_TEXLDD: + case VKD3DSIH_TEXLDL: + case VKD3DSIH_TEXM3x2PAD: + case VKD3DSIH_TEXM3x2TEX: +diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c +index 24206ae9a4d..ca7cdfd5217 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/tpf.c ++++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c +@@ -2984,11 +2984,13 @@ static D3D_SHADER_VARIABLE_CLASS sm4_class(const struct hlsl_type *type) + return D3D_SVC_VECTOR; + + case HLSL_CLASS_ARRAY: ++ case HLSL_CLASS_DEPTH_STENCIL_STATE: + case HLSL_CLASS_DEPTH_STENCIL_VIEW: + case HLSL_CLASS_EFFECT_GROUP: + case HLSL_CLASS_STRUCT: + case HLSL_CLASS_PASS: + case HLSL_CLASS_PIXEL_SHADER: ++ case HLSL_CLASS_RASTERIZER_STATE: + case HLSL_CLASS_RENDER_TARGET_VIEW: + case HLSL_CLASS_SAMPLER: + case HLSL_CLASS_STRING: +@@ -2997,6 +2999,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/libs/vkd3d/libs/vkd3d/command.c b/libs/vkd3d/libs/vkd3d/command.c +index 6c463be8d60..2354938c08d 100644 +--- a/libs/vkd3d/libs/vkd3d/command.c ++++ b/libs/vkd3d/libs/vkd3d/command.c +@@ -2034,11 +2034,12 @@ static bool vk_barrier_parameters_from_d3d12_resource_state(unsigned int state, + if (vk_queue_flags & VK_QUEUE_GRAPHICS_BIT) + { + queue_shader_stages |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT +- | VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT +- | VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT + | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + if (device->vk_info.geometry_shaders) + queue_shader_stages |= VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT; ++ if (device->vk_info.tessellation_shaders) ++ queue_shader_stages |= VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT ++ | VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT; + } + if (vk_queue_flags & VK_QUEUE_COMPUTE_BIT) + queue_shader_stages |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; +diff --git a/libs/vkd3d/libs/vkd3d/device.c b/libs/vkd3d/libs/vkd3d/device.c +index 674e46fe5c5..2bbc170504e 100644 +--- a/libs/vkd3d/libs/vkd3d/device.c ++++ b/libs/vkd3d/libs/vkd3d/device.c +@@ -1644,6 +1644,7 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device, + vulkan_info->device_limits = physical_device_info->properties2.properties.limits; + vulkan_info->sparse_properties = physical_device_info->properties2.properties.sparseProperties; + vulkan_info->geometry_shaders = physical_device_info->features2.features.geometryShader; ++ vulkan_info->tessellation_shaders = physical_device_info->features2.features.tessellationShader; + vulkan_info->sparse_binding = features->sparseBinding; + vulkan_info->sparse_residency_3d = features->sparseResidencyImage3D; + vulkan_info->rasterization_stream = physical_device_info->xfb_properties.transformFeedbackRasterizationStreamSelect; +diff --git a/libs/vkd3d/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/libs/vkd3d/vkd3d_private.h +index a55e967cdfc..7acd39d65be 100644 +--- a/libs/vkd3d/libs/vkd3d/vkd3d_private.h ++++ b/libs/vkd3d/libs/vkd3d/vkd3d_private.h +@@ -147,6 +147,7 @@ struct vkd3d_vulkan_info + bool rasterization_stream; + bool transform_feedback_queries; + bool geometry_shaders; ++ bool tessellation_shaders; + + bool uav_read_without_format; + +-- +2.43.0 +