wine-staging/patches/vkd3d-latest/0005-Updated-vkd3d-to-bf628f0c74ae839bb20266cd10e07d1504e.patch
2024-01-27 12:58:57 +11:00

1545 lines
64 KiB
Diff

From 9a5b8e1dc86435ee994f9c960ede88767f5da27f Mon Sep 17 00:00:00 2001
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
Date: Wed, 24 Jan 2024 12:27:59 +1100
Subject: [PATCH] Updated vkd3d to bf628f0c74ae839bb20266cd10e07d1504ebc1bf.
---
libs/vkd3d/libs/vkd3d-shader/dxbc.c | 5 -
libs/vkd3d/libs/vkd3d-shader/dxil.c | 104 +++++--
libs/vkd3d/libs/vkd3d-shader/fx.c | 168 ++++++++++-
libs/vkd3d/libs/vkd3d-shader/hlsl.c | 7 +-
libs/vkd3d/libs/vkd3d-shader/hlsl.h | 3 +
libs/vkd3d/libs/vkd3d-shader/hlsl.y | 113 +++++--
libs/vkd3d/libs/vkd3d-shader/ir.c | 284 ++++++++++++------
libs/vkd3d/libs/vkd3d-shader/spirv.c | 72 ++++-
libs/vkd3d/libs/vkd3d-shader/tpf.c | 8 +-
.../libs/vkd3d-shader/vkd3d_shader_private.h | 12 +-
libs/vkd3d/libs/vkd3d/device.c | 12 +-
libs/vkd3d/libs/vkd3d/resource.c | 2 +-
12 files changed, 595 insertions(+), 195 deletions(-)
diff --git a/libs/vkd3d/libs/vkd3d-shader/dxbc.c b/libs/vkd3d/libs/vkd3d-shader/dxbc.c
index edb65d2e92f..37ebc73c099 100644
--- a/libs/vkd3d/libs/vkd3d-shader/dxbc.c
+++ b/libs/vkd3d/libs/vkd3d-shader/dxbc.c
@@ -552,14 +552,9 @@ static int shdr_handler(const struct vkd3d_shader_dxbc_section_desc *section,
void free_shader_desc(struct vkd3d_shader_desc *desc)
{
- size_t i;
-
shader_signature_cleanup(&desc->input_signature);
shader_signature_cleanup(&desc->output_signature);
shader_signature_cleanup(&desc->patch_constant_signature);
- for (i = 0; i < desc->block_name_count; ++i)
- vkd3d_free((void *)desc->block_names[i]);
- vkd3d_free(desc->block_names);
}
int shader_extract_from_dxbc(const struct vkd3d_shader_code *dxbc,
diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c
index 15cc380f5f2..2a0ff61cfeb 100644
--- a/libs/vkd3d/libs/vkd3d-shader/dxil.c
+++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c
@@ -342,6 +342,12 @@ enum dx_intrinsic_opcode
DX_FIRST_BIT_LO = 32,
DX_FIRST_BIT_HI = 33,
DX_FIRST_BIT_SHI = 34,
+ DX_FMAX = 35,
+ DX_FMIN = 36,
+ DX_IMAX = 37,
+ DX_IMIN = 38,
+ DX_UMAX = 39,
+ DX_UMIN = 40,
DX_CREATE_HANDLE = 57,
DX_CBUFFER_LOAD_LEGACY = 59,
DX_BUFFER_LOAD = 68,
@@ -1628,7 +1634,7 @@ static enum vkd3d_result sm6_parser_type_table_init(struct sm6_parser *sm6)
break;
}
- if (!ascii_strcasecmp(struct_name, "dx.types.Handle"))
+ if (!strcmp(struct_name, "dx.types.Handle"))
sm6->handle_type = type;
type->u.struc->name = struct_name;
@@ -3546,6 +3552,41 @@ static void sm6_parser_emit_dx_unary(struct sm6_parser *sm6, enum dx_intrinsic_o
instruction_dst_param_init_ssa_scalar(ins, sm6);
}
+static enum vkd3d_shader_opcode map_dx_binary_op(enum dx_intrinsic_opcode op, const struct sm6_type *type)
+{
+ switch (op)
+ {
+ case DX_FMAX:
+ return type->u.width == 64 ? VKD3DSIH_DMAX : VKD3DSIH_MAX;
+ case DX_FMIN:
+ return type->u.width == 64 ? VKD3DSIH_DMIN : VKD3DSIH_MIN;
+ case DX_IMAX:
+ return VKD3DSIH_IMAX;
+ case DX_IMIN:
+ return VKD3DSIH_IMIN;
+ case DX_UMAX:
+ return VKD3DSIH_UMAX;
+ case DX_UMIN:
+ return VKD3DSIH_UMIN;
+ default:
+ vkd3d_unreachable();
+ }
+}
+
+static void sm6_parser_emit_dx_binary(struct sm6_parser *sm6, enum dx_intrinsic_opcode op,
+ const struct sm6_value **operands, struct function_emission_state *state)
+{
+ struct vkd3d_shader_instruction *ins = state->ins;
+ struct vkd3d_shader_src_param *src_params;
+
+ vsir_instruction_init(ins, &sm6->p.location, map_dx_binary_op(op, operands[0]->type));
+ src_params = instruction_src_params_alloc(ins, 2, sm6);
+ src_param_init_from_value(&src_params[0], operands[0]);
+ src_param_init_from_value(&src_params[1], operands[1]);
+
+ instruction_dst_param_init_ssa_scalar(ins, sm6);
+}
+
static void sm6_parser_emit_dx_cbuffer_load(struct sm6_parser *sm6, enum dx_intrinsic_opcode op,
const struct sm6_value **operands, struct function_emission_state *state)
{
@@ -3776,38 +3817,45 @@ struct sm6_dx_opcode_info
H -> handle
v -> void
o -> overloaded
+ R -> matches the return type
*/
static const struct sm6_dx_opcode_info sm6_dx_op_table[] =
{
- [DX_BFREV ] = {"m0", "m", sm6_parser_emit_dx_unary},
+ [DX_BFREV ] = {"m", "R", sm6_parser_emit_dx_unary},
[DX_BUFFER_LOAD ] = {"o", "Hii", sm6_parser_emit_dx_buffer_load},
[DX_CBUFFER_LOAD_LEGACY ] = {"o", "Hi", sm6_parser_emit_dx_cbuffer_load},
[DX_COUNT_BITS ] = {"i", "m", sm6_parser_emit_dx_unary},
[DX_CREATE_HANDLE ] = {"H", "ccib", sm6_parser_emit_dx_create_handle},
- [DX_DERIV_COARSEX ] = {"e0", "e", sm6_parser_emit_dx_unary},
- [DX_DERIV_COARSEY ] = {"e0", "e", sm6_parser_emit_dx_unary},
- [DX_DERIV_FINEX ] = {"e0", "e", sm6_parser_emit_dx_unary},
- [DX_DERIV_FINEY ] = {"e0", "e", sm6_parser_emit_dx_unary},
- [DX_EXP ] = {"g0", "g", sm6_parser_emit_dx_unary},
+ [DX_DERIV_COARSEX ] = {"e", "R", sm6_parser_emit_dx_unary},
+ [DX_DERIV_COARSEY ] = {"e", "R", sm6_parser_emit_dx_unary},
+ [DX_DERIV_FINEX ] = {"e", "R", sm6_parser_emit_dx_unary},
+ [DX_DERIV_FINEY ] = {"e", "R", sm6_parser_emit_dx_unary},
+ [DX_EXP ] = {"g", "R", sm6_parser_emit_dx_unary},
[DX_FIRST_BIT_HI ] = {"i", "m", sm6_parser_emit_dx_unary},
[DX_FIRST_BIT_LO ] = {"i", "m", sm6_parser_emit_dx_unary},
[DX_FIRST_BIT_SHI ] = {"i", "m", sm6_parser_emit_dx_unary},
- [DX_FRC ] = {"g0", "g", sm6_parser_emit_dx_unary},
+ [DX_FMAX ] = {"g", "RR", sm6_parser_emit_dx_binary},
+ [DX_FMIN ] = {"g", "RR", sm6_parser_emit_dx_binary},
+ [DX_FRC ] = {"g", "R", sm6_parser_emit_dx_unary},
+ [DX_IMAX ] = {"m", "RR", sm6_parser_emit_dx_binary},
+ [DX_IMIN ] = {"m", "RR", sm6_parser_emit_dx_binary},
[DX_LEGACY_F16TOF32 ] = {"f", "i", sm6_parser_emit_dx_unary},
[DX_LEGACY_F32TOF16 ] = {"i", "f", sm6_parser_emit_dx_unary},
[DX_LOAD_INPUT ] = {"o", "ii8i", sm6_parser_emit_dx_load_input},
- [DX_LOG ] = {"g0", "g", sm6_parser_emit_dx_unary},
- [DX_ROUND_NE ] = {"g0", "g", sm6_parser_emit_dx_unary},
- [DX_ROUND_NI ] = {"g0", "g", sm6_parser_emit_dx_unary},
- [DX_ROUND_PI ] = {"g0", "g", sm6_parser_emit_dx_unary},
- [DX_ROUND_Z ] = {"g0", "g", sm6_parser_emit_dx_unary},
- [DX_RSQRT ] = {"g0", "g", sm6_parser_emit_dx_unary},
- [DX_SQRT ] = {"g0", "g", sm6_parser_emit_dx_unary},
+ [DX_LOG ] = {"g", "R", sm6_parser_emit_dx_unary},
+ [DX_ROUND_NE ] = {"g", "R", sm6_parser_emit_dx_unary},
+ [DX_ROUND_NI ] = {"g", "R", sm6_parser_emit_dx_unary},
+ [DX_ROUND_PI ] = {"g", "R", sm6_parser_emit_dx_unary},
+ [DX_ROUND_Z ] = {"g", "R", sm6_parser_emit_dx_unary},
+ [DX_RSQRT ] = {"g", "R", sm6_parser_emit_dx_unary},
+ [DX_SQRT ] = {"g", "R", sm6_parser_emit_dx_unary},
[DX_STORE_OUTPUT ] = {"v", "ii8o", sm6_parser_emit_dx_store_output},
+ [DX_UMAX ] = {"m", "RR", sm6_parser_emit_dx_binary},
+ [DX_UMIN ] = {"m", "RR", sm6_parser_emit_dx_binary},
};
static bool sm6_parser_validate_operand_type(struct sm6_parser *sm6, const struct sm6_value *value, char info_type,
- bool is_return)
+ const struct sm6_type *ret_type, bool is_return)
{
const struct sm6_type *type = value->type;
@@ -3843,23 +3891,14 @@ static bool sm6_parser_validate_operand_type(struct sm6_parser *sm6, const struc
case 'o':
/* TODO: some type checking may be possible */
return true;
+ case 'R':
+ return type == ret_type;
default:
FIXME("Unhandled operand code '%c'.\n", info_type);
return false;
}
}
-static bool operand_types_match(struct sm6_value *dst, const struct sm6_value **operands, unsigned int operand_count,
- char index_char)
-{
- unsigned int i = index_char - '0';
-
- assert(i < 10);
- if (i >= operand_count)
- return false;
- return dst->type == operands[i]->type;
-}
-
static bool sm6_parser_validate_dx_op(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, const char *name,
const struct sm6_value **operands, unsigned int operand_count, struct sm6_value *dst)
{
@@ -3869,8 +3908,7 @@ static bool sm6_parser_validate_dx_op(struct sm6_parser *sm6, enum dx_intrinsic_
info = &sm6_dx_op_table[op];
assert(info->ret_type[0]);
- if (!sm6_parser_validate_operand_type(sm6, dst, info->ret_type[0], true)
- || (info->ret_type[1] && !operand_types_match(dst, operands, operand_count, info->ret_type[1])))
+ if (!sm6_parser_validate_operand_type(sm6, dst, info->ret_type[0], NULL, true))
{
WARN("Failed to validate return type for dx intrinsic id %u, '%s'.\n", op, name);
/* Return type validation failure is not so critical. We only need to set
@@ -3880,7 +3918,7 @@ static bool sm6_parser_validate_dx_op(struct sm6_parser *sm6, enum dx_intrinsic_
for (i = 0; i < operand_count; ++i)
{
const struct sm6_value *value = operands[i];
- if (!sm6_parser_validate_operand_type(sm6, value, info->operand_info[i], false))
+ if (!sm6_parser_validate_operand_type(sm6, value, info->operand_info[i], dst->type, false))
{
WARN("Failed to validate operand %u for dx intrinsic id %u, '%s'.\n", i + 1, op, name);
vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND,
@@ -5489,7 +5527,7 @@ static enum vkd3d_result sm6_function_emit_blocks(const struct sm6_function *fun
{
unsigned int i;
- sm6->p.shader_desc.block_count = function->block_count;
+ sm6->p.program.block_count = function->block_count;
for (i = 0; i < function->block_count; ++i)
{
@@ -6726,7 +6764,7 @@ static enum vkd3d_result sm6_parser_entry_point_init(struct sm6_parser *sm6)
sm6->entry_point = value->u.function.name;
if (!sm6_metadata_value_is_string(entry_node->operands[1])
- || ascii_strcasecmp(sm6->entry_point, entry_node->operands[1]->u.string_value))
+ || strcmp(sm6->entry_point, entry_node->operands[1]->u.string_value))
{
WARN("Entry point function name %s mismatch.\n", sm6->entry_point);
vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_ENTRY_POINT_MISMATCH,
@@ -6916,7 +6954,7 @@ static struct sm6_function *sm6_parser_get_function(const struct sm6_parser *sm6
{
size_t i;
for (i = 0; i < sm6->function_count; ++i)
- if (!ascii_strcasecmp(sm6->functions[i].declaration->u.function.name, name))
+ if (!strcmp(sm6->functions[i].declaration->u.function.name, name))
return &sm6->functions[i];
return NULL;
}
diff --git a/libs/vkd3d/libs/vkd3d-shader/fx.c b/libs/vkd3d/libs/vkd3d-shader/fx.c
index 17b9627b6bd..e1459f76c14 100644
--- a/libs/vkd3d/libs/vkd3d-shader/fx.c
+++ b/libs/vkd3d/libs/vkd3d-shader/fx.c
@@ -43,6 +43,15 @@ static void string_storage_destroy(struct rb_entry *entry, void *context)
vkd3d_free(string_entry);
}
+struct fx_write_context;
+
+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);
+};
+
struct fx_write_context
{
struct hlsl_ctx *ctx;
@@ -58,15 +67,29 @@ struct fx_write_context
uint32_t technique_count;
uint32_t group_count;
int status;
+
+ const struct fx_write_context_ops *ops;
};
-static void fx_write_context_init(struct hlsl_ctx *ctx, struct fx_write_context *fx)
+static uint32_t write_string(const char *string, struct fx_write_context *fx)
+{
+ return fx->ops->write_string(string, fx);
+}
+
+static void write_pass(struct hlsl_ir_var *var, struct fx_write_context *fx)
+{
+ fx->ops->write_pass(var, fx);
+}
+
+static void fx_write_context_init(struct hlsl_ctx *ctx, const struct fx_write_context_ops *ops,
+ struct fx_write_context *fx)
{
unsigned int version = ctx->profile->major_version;
memset(fx, 0, sizeof(*fx));
fx->ctx = ctx;
+ fx->ops = ops;
if (version == 2)
{
fx->min_technique_version = 9;
@@ -104,7 +127,7 @@ static bool technique_matches_version(const struct hlsl_ir_var *var, const struc
return type->e.version >= fx->min_technique_version && type->e.version <= fx->max_technique_version;
}
-static uint32_t fx_put_raw_string(struct fx_write_context *fx, const char *string)
+static uint32_t write_fx_4_string(const char *string, struct fx_write_context *fx)
{
struct string_entry *string_entry;
struct rb_entry *entry;
@@ -130,25 +153,42 @@ static uint32_t fx_put_raw_string(struct fx_write_context *fx, const char *strin
return string_entry->offset;
}
-static void write_pass(struct hlsl_ir_var *var, struct fx_write_context *fx)
+static void write_fx_4_pass(struct hlsl_ir_var *var, struct fx_write_context *fx)
{
struct vkd3d_bytecode_buffer *buffer = &fx->structured;
uint32_t name_offset;
- name_offset = fx_put_raw_string(fx, var->name);
+ 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 */
+ /* TODO: assignments */
+}
+
+static void write_fx_2_pass(struct hlsl_ir_var *var, struct fx_write_context *fx)
+{
+ struct vkd3d_bytecode_buffer *buffer = &fx->structured;
+ uint32_t name_offset;
+
+ name_offset = write_string(var->name, fx);
put_u32(buffer, name_offset);
put_u32(buffer, 0); /* Annotation count. */
put_u32(buffer, 0); /* Assignment count. */
+
+ /* TODO: annotations */
+ /* TODO: assignments */
}
-static void write_technique(struct hlsl_ir_var *var, struct fx_write_context *fx)
+static void write_fx_4_technique(struct hlsl_ir_var *var, struct fx_write_context *fx)
{
struct vkd3d_bytecode_buffer *buffer = &fx->structured;
uint32_t name_offset, count = 0;
struct hlsl_ir_var *pass;
uint32_t count_offset;
- name_offset = fx_put_raw_string(fx, var->name);
+ name_offset = write_string(var->name, fx);
put_u32(buffer, name_offset);
count_offset = put_u32(buffer, 0);
put_u32(buffer, 0); /* Annotation count. */
@@ -176,11 +216,9 @@ static void write_techniques(struct hlsl_scope *scope, struct fx_write_context *
LIST_FOR_EACH_ENTRY(var, &scope->vars, struct hlsl_ir_var, scope_entry)
{
- const struct hlsl_type *type = var->data_type;
-
- if (type->base_type == HLSL_TYPE_TECHNIQUE && type->e.version == 10)
+ if (technique_matches_version(var, fx))
{
- write_technique(var, fx);
+ fx->ops->write_technique(var, fx);
++fx->technique_count;
}
}
@@ -192,7 +230,7 @@ static void write_techniques(struct hlsl_scope *scope, struct fx_write_context *
static void write_group(struct hlsl_scope *scope, const char *name, struct fx_write_context *fx)
{
struct vkd3d_bytecode_buffer *buffer = &fx->structured;
- uint32_t name_offset = fx_put_raw_string(fx, name);
+ uint32_t name_offset = write_string(name, fx);
uint32_t count_offset, count;
put_u32(buffer, name_offset);
@@ -231,13 +269,114 @@ static void write_groups(struct hlsl_scope *scope, struct fx_write_context *fx)
}
}
+static uint32_t write_fx_2_string(const char *string, struct fx_write_context *fx)
+{
+ struct vkd3d_bytecode_buffer *buffer = &fx->unstructured;
+ const char *s = string ? string : "";
+ uint32_t size, offset;
+
+ size = strlen(s) + 1;
+ offset = put_u32(buffer, size);
+ bytecode_put_bytes(buffer, s, size);
+ return offset;
+}
+
+static void write_fx_2_technique(struct hlsl_ir_var *var, struct fx_write_context *fx)
+{
+ struct vkd3d_bytecode_buffer *buffer = &fx->structured;
+ uint32_t name_offset, count_offset, count = 0;
+ struct hlsl_ir_var *pass;
+
+ name_offset = write_string(var->name, fx);
+ put_u32(buffer, name_offset);
+ put_u32(buffer, 0); /* Annotation count. */
+ count_offset = put_u32(buffer, 0); /* Pass count. */
+
+ /* FIXME: annotations */
+
+ LIST_FOR_EACH_ENTRY(pass, &var->scope->vars, struct hlsl_ir_var, scope_entry)
+ {
+ write_pass(pass, fx);
+ ++count;
+ }
+
+ set_u32(buffer, count_offset, count);
+}
+
+static const struct fx_write_context_ops fx_2_ops =
+{
+ .write_string = write_fx_2_string,
+ .write_technique = write_fx_2_technique,
+ .write_pass = write_fx_2_pass,
+};
+
+static int hlsl_fx_2_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out)
+{
+ struct vkd3d_bytecode_buffer buffer = { 0 };
+ struct vkd3d_bytecode_buffer *structured;
+ uint32_t offset, size, technique_count;
+ struct fx_write_context fx;
+
+ fx_write_context_init(ctx, &fx_2_ops, &fx);
+ structured = &fx.structured;
+
+ /* First entry is always zeroed and skipped. */
+ put_u32(&fx.unstructured, 0);
+
+ put_u32(&buffer, 0xfeff0901); /* Version. */
+ offset = put_u32(&buffer, 0);
+
+ put_u32(structured, 0); /* Parameter count */
+ technique_count = put_u32(structured, 0);
+ put_u32(structured, 0); /* Unknown */
+ put_u32(structured, 0); /* Object count */
+
+ /* TODO: parameters */
+
+ write_techniques(ctx->globals, &fx);
+ set_u32(structured, technique_count, fx.technique_count);
+
+ put_u32(structured, 0); /* String count */
+ put_u32(structured, 0); /* Resource count */
+
+ /* TODO: strings */
+ /* TODO: resources */
+
+ size = align(fx.unstructured.size, 4);
+ set_u32(&buffer, offset, size);
+
+ bytecode_put_bytes(&buffer, fx.unstructured.data, fx.unstructured.size);
+ bytecode_put_bytes(&buffer, fx.structured.data, fx.structured.size);
+
+ vkd3d_free(fx.unstructured.data);
+ vkd3d_free(fx.structured.data);
+
+ if (!fx.status)
+ {
+ out->code = buffer.data;
+ out->size = buffer.size;
+ }
+
+ if (fx.status < 0)
+ ctx->result = fx.status;
+
+ return fx_write_context_cleanup(&fx);
+}
+
+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,
+};
+
static int hlsl_fx_4_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out)
{
struct vkd3d_bytecode_buffer buffer = { 0 };
struct fx_write_context fx;
uint32_t size_offset, size;
- fx_write_context_init(ctx, &fx);
+ fx_write_context_init(ctx, &fx_4_ops, &fx);
put_u32(&fx.unstructured, 0); /* Empty string placeholder. */
@@ -297,7 +436,7 @@ static int hlsl_fx_5_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out)
struct fx_write_context fx;
uint32_t size_offset, size;
- fx_write_context_init(ctx, &fx);
+ fx_write_context_init(ctx, &fx_4_ops, &fx);
put_u32(&fx.unstructured, 0); /* Empty string placeholder. */
@@ -359,8 +498,7 @@ int hlsl_emit_effect_binary(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out)
{
if (ctx->profile->major_version == 2)
{
- hlsl_fixme(ctx, &ctx->location, "Writing fx_2_0 binaries is not implemented.");
- return VKD3D_ERROR_NOT_IMPLEMENTED;
+ return hlsl_fx_2_write(ctx, out);
}
else if (ctx->profile->major_version == 4)
{
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c
index 6a5a6d0e3c1..04c37498d84 100644
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c
@@ -953,6 +953,8 @@ struct hlsl_type *hlsl_type_clone(struct hlsl_ctx *ctx, struct hlsl_type *old,
type->modifiers |= default_majority;
type->sampler_dim = old->sampler_dim;
type->is_minimum_precision = old->is_minimum_precision;
+ type->sample_count = old->sample_count;
+
switch (old->class)
{
case HLSL_CLASS_ARRAY:
@@ -1002,11 +1004,11 @@ struct hlsl_type *hlsl_type_clone(struct hlsl_ctx *ctx, struct hlsl_type *old,
}
case HLSL_CLASS_OBJECT:
- {
if (type->base_type == HLSL_TYPE_TECHNIQUE)
type->e.version = old->e.version;
+ if (old->base_type == HLSL_TYPE_TEXTURE || old->base_type == HLSL_TYPE_UAV)
+ type->e.resource_format = old->e.resource_format;
break;
- }
default:
break;
@@ -3366,6 +3368,7 @@ static void declare_predefined_types(struct hlsl_ctx *ctx)
{"vector", HLSL_CLASS_VECTOR, HLSL_TYPE_FLOAT, 4, 1},
{"matrix", HLSL_CLASS_MATRIX, HLSL_TYPE_FLOAT, 4, 4},
{"fxgroup", HLSL_CLASS_OBJECT, HLSL_TYPE_EFFECT_GROUP, 1, 1},
+ {"pass", HLSL_CLASS_OBJECT, HLSL_TYPE_PASS, 1, 1},
{"STRING", HLSL_CLASS_OBJECT, HLSL_TYPE_STRING, 1, 1},
{"TEXTURE", HLSL_CLASS_OBJECT, HLSL_TYPE_TEXTURE, 1, 1},
{"PIXELSHADER", HLSL_CLASS_OBJECT, HLSL_TYPE_PIXELSHADER, 1, 1},
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h
index 8bc98b99e8a..984ac7e4883 100644
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h
@@ -95,6 +95,7 @@ enum hlsl_base_type
HLSL_TYPE_UAV,
HLSL_TYPE_PIXELSHADER,
HLSL_TYPE_VERTEXSHADER,
+ HLSL_TYPE_PASS,
HLSL_TYPE_TECHNIQUE,
HLSL_TYPE_EFFECT_GROUP,
HLSL_TYPE_STRING,
@@ -408,6 +409,8 @@ struct hlsl_ir_var
struct list extern_entry;
/* Scope that variable itself defines, used to provide a container for techniques and passes. */
struct hlsl_scope *scope;
+ /* Scope that contains annotations for this variable. */
+ struct hlsl_scope *annotations;
/* Indexes of the IR instructions where the variable is first written and last read (liveness
* range). The IR instructions are numerated starting from 2, because 0 means unused, and 1
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y
index c308916e07e..8dc353e11c0 100644
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y
@@ -292,6 +292,21 @@ static bool implicit_compatible_data_types(struct hlsl_ctx *ctx, struct hlsl_typ
return hlsl_types_are_componentwise_equal(ctx, src, dst);
}
+static void check_condition_type(struct hlsl_ctx *ctx, const struct hlsl_ir_node *cond)
+{
+ const struct hlsl_type *type = cond->data_type;
+
+ if (type->class > HLSL_CLASS_LAST_NUMERIC || type->dimx > 1 || type->dimy > 1)
+ {
+ struct vkd3d_string_buffer *string;
+
+ if ((string = hlsl_type_to_string(ctx, type)))
+ hlsl_error(ctx, &cond->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
+ "Condition type '%s' is not a scalar numeric type.", string->buffer);
+ hlsl_release_string_buffer(ctx, string);
+ }
+}
+
static struct hlsl_ir_node *add_cast(struct hlsl_ctx *ctx, struct hlsl_block *block,
struct hlsl_ir_node *node, struct hlsl_type *dst_type, const struct vkd3d_shader_location *loc)
{
@@ -431,6 +446,9 @@ static bool append_conditional_break(struct hlsl_ctx *ctx, struct hlsl_block *co
return true;
condition = node_from_block(cond_block);
+
+ check_condition_type(ctx, condition);
+
if (!(not = hlsl_new_unary_expr(ctx, HLSL_OP1_LOGIC_NOT, condition, &condition->loc)))
return false;
hlsl_block_add_instr(cond_block, not);
@@ -1096,8 +1114,33 @@ static bool add_func_parameter(struct hlsl_ctx *ctx, struct hlsl_func_parameters
return true;
}
+static bool add_pass(struct hlsl_ctx *ctx, const char *name, struct hlsl_scope *annotations,
+ const struct vkd3d_shader_location *loc)
+{
+ struct hlsl_ir_var *var;
+ struct hlsl_type *type;
+
+ type = hlsl_get_type(ctx->globals, "pass", false, false);
+ if (!(var = hlsl_new_var(ctx, name, type, loc, NULL, 0, NULL)))
+ return false;
+ var->annotations = annotations;
+
+ if (!hlsl_add_var(ctx, var, false))
+ {
+ struct hlsl_ir_var *old = hlsl_get_var(ctx->cur_scope, var->name);
+
+ hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_REDEFINED,
+ "Identifier \"%s\" was already declared in this scope.", var->name);
+ hlsl_note(ctx, &old->loc, VKD3D_SHADER_LOG_ERROR, "\"%s\" was previously declared here.", old->name);
+ hlsl_free_var(var);
+ return false;
+ }
+
+ return true;
+}
+
static bool add_technique(struct hlsl_ctx *ctx, const char *name, struct hlsl_scope *scope,
- const char *typename, const struct vkd3d_shader_location *loc)
+ struct hlsl_scope *annotations, const char *typename, const struct vkd3d_shader_location *loc)
{
struct hlsl_ir_var *var;
struct hlsl_type *type;
@@ -1106,6 +1149,7 @@ static bool add_technique(struct hlsl_ctx *ctx, const char *name, struct hlsl_sc
if (!(var = hlsl_new_var(ctx, name, type, loc, NULL, 0, NULL)))
return false;
var->scope = scope;
+ var->annotations = annotations;
if (!hlsl_add_var(ctx, var, false))
{
@@ -1122,7 +1166,7 @@ static bool add_technique(struct hlsl_ctx *ctx, const char *name, struct hlsl_sc
}
static bool add_effect_group(struct hlsl_ctx *ctx, const char *name, struct hlsl_scope *scope,
- const struct vkd3d_shader_location *loc)
+ struct hlsl_scope *annotations, const struct vkd3d_shader_location *loc)
{
struct hlsl_ir_var *var;
struct hlsl_type *type;
@@ -1131,6 +1175,7 @@ static bool add_effect_group(struct hlsl_ctx *ctx, const char *name, struct hlsl
if (!(var = hlsl_new_var(ctx, name, type, loc, NULL, 0, NULL)))
return false;
var->scope = scope;
+ var->annotations = annotations;
if (!hlsl_add_var(ctx, var, false))
{
@@ -4999,6 +5044,7 @@ static void check_duplicated_switch_cases(struct hlsl_ctx *ctx, const struct hls
struct hlsl_attribute *attr;
struct parse_attribute_list attr_list;
struct hlsl_ir_switch_case *switch_case;
+ struct hlsl_scope *scope;
}
%token KW_BLENDSTATE
@@ -5124,6 +5170,8 @@ static void check_duplicated_switch_cases(struct hlsl_ctx *ctx, const struct hls
%token <name> STRING
%token <name> TYPE_IDENTIFIER
+%type <scope> annotations_opt
+
%type <arrays> arrays
%type <assign_op> assign_op
@@ -5240,7 +5288,33 @@ name_opt:
| any_identifier
pass:
- KW_PASS name_opt '{' '}'
+ KW_PASS name_opt annotations_opt '{' '}'
+ {
+ if (!add_pass(ctx, $2, $3, &@1))
+ YYABORT;
+ }
+
+annotations_list:
+ variables_def_typed ';'
+ | annotations_list variables_def_typed ';'
+
+annotations_opt:
+ %empty
+ {
+ $$ = NULL;
+ }
+ | '<' scope_start '>'
+ {
+ hlsl_pop_scope(ctx);
+ $$ = NULL;
+ }
+ | '<' scope_start annotations_list '>'
+ {
+ struct hlsl_scope *scope = ctx->cur_scope;
+
+ hlsl_pop_scope(ctx);
+ $$ = scope;
+ }
pass_list:
pass
@@ -5251,17 +5325,17 @@ passes:
| scope_start pass_list
technique9:
- KW_TECHNIQUE name_opt '{' passes '}'
+ KW_TECHNIQUE name_opt annotations_opt '{' passes '}'
{
struct hlsl_scope *scope = ctx->cur_scope;
hlsl_pop_scope(ctx);
- if (!add_technique(ctx, $2, scope, "technique", &@1))
+ if (!add_technique(ctx, $2, scope, $3, "technique", &@1))
YYABORT;
}
technique10:
- KW_TECHNIQUE10 name_opt '{' passes '}'
+ KW_TECHNIQUE10 name_opt annotations_opt '{' passes '}'
{
struct hlsl_scope *scope = ctx->cur_scope;
hlsl_pop_scope(ctx);
@@ -5270,12 +5344,12 @@ technique10:
hlsl_error(ctx, &@1, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX,
"The 'technique10' keyword is invalid for this profile.");
- if (!add_technique(ctx, $2, scope, "technique10", &@1))
+ if (!add_technique(ctx, $2, scope, $3, "technique10", &@1))
YYABORT;
}
technique11:
- KW_TECHNIQUE11 name_opt '{' passes '}'
+ KW_TECHNIQUE11 name_opt annotations_opt '{' passes '}'
{
struct hlsl_scope *scope = ctx->cur_scope;
hlsl_pop_scope(ctx);
@@ -5284,7 +5358,7 @@ technique11:
hlsl_error(ctx, &@1, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX,
"The 'technique11' keyword is invalid for this profile.");
- if (!add_technique(ctx, $2, scope, "technique11", &@1))
+ if (!add_technique(ctx, $2, scope, $3, "technique11", &@1))
YYABORT;
}
@@ -5302,11 +5376,11 @@ group_techniques:
| group_techniques group_technique
effect_group:
- KW_FXGROUP any_identifier '{' scope_start group_techniques '}'
+ KW_FXGROUP any_identifier annotations_opt '{' scope_start group_techniques '}'
{
struct hlsl_scope *scope = ctx->cur_scope;
hlsl_pop_scope(ctx);
- if (!(add_effect_group(ctx, $2, scope, &@2)))
+ if (!(add_effect_group(ctx, $2, scope, $3, &@2)))
YYABORT;
}
@@ -6689,6 +6763,15 @@ selection_statement:
}
}
+ check_condition_type(ctx, condition);
+
+ if (!(condition = add_cast(ctx, $4, condition, hlsl_get_scalar_type(ctx, HLSL_TYPE_BOOL), &@4)))
+ {
+ destroy_block($6.then_block);
+ destroy_block($6.else_block);
+ YYABORT;
+ }
+
if (!(instr = hlsl_new_if(ctx, condition, $6.then_block, $6.else_block, &@2)))
{
destroy_block($6.then_block);
@@ -6697,15 +6780,7 @@ selection_statement:
}
destroy_block($6.then_block);
destroy_block($6.else_block);
- if (condition->data_type->dimx > 1 || condition->data_type->dimy > 1)
- {
- struct vkd3d_string_buffer *string;
- if ((string = hlsl_type_to_string(ctx, condition->data_type)))
- hlsl_error(ctx, &instr->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
- "if condition type %s is not scalar.", string->buffer);
- hlsl_release_string_buffer(ctx, string);
- }
$$ = $4;
hlsl_block_add_instr($$, instr);
}
diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c
index a797e49308a..865a292cd62 100644
--- a/libs/vkd3d/libs/vkd3d-shader/ir.c
+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c
@@ -26,6 +26,11 @@ bool vsir_program_init(struct vsir_program *program, const struct vkd3d_shader_v
void vsir_program_cleanup(struct vsir_program *program)
{
+ size_t i;
+
+ for (i = 0; i < program->block_name_count; ++i)
+ vkd3d_free((void *)program->block_names[i]);
+ vkd3d_free(program->block_names);
shader_instruction_array_destroy(&program->instructions);
}
@@ -47,6 +52,19 @@ static void vkd3d_shader_instruction_make_nop(struct vkd3d_shader_instruction *i
vsir_instruction_init(ins, &location, VKD3DSIH_NOP);
}
+static void remove_dcl_temps(struct vsir_program *program)
+{
+ unsigned int i;
+
+ for (i = 0; i < program->instructions.count; ++i)
+ {
+ struct vkd3d_shader_instruction *ins = &program->instructions.elements[i];
+
+ if (ins->handler_idx == VKD3DSIH_DCL_TEMPS)
+ vkd3d_shader_instruction_make_nop(ins);
+ }
+}
+
static void shader_register_eliminate_phase_addressing(struct vkd3d_shader_register *reg,
unsigned int instance_id)
{
@@ -154,9 +172,6 @@ struct hull_flattener
{
struct vkd3d_shader_instruction_array instructions;
- unsigned int max_temp_count;
- unsigned int temp_dcl_idx;
-
unsigned int instance_count;
unsigned int phase_body_idx;
enum vkd3d_shader_opcode phase;
@@ -214,21 +229,6 @@ static void flattener_eliminate_phase_related_dcls(struct hull_flattener *normal
vkd3d_shader_instruction_make_nop(ins);
return;
}
- else if (ins->handler_idx == VKD3DSIH_DCL_TEMPS && normaliser->phase != VKD3DSIH_INVALID)
- {
- /* Leave only the first temp declaration and set it to the max count later. */
- if (!normaliser->max_temp_count)
- {
- normaliser->max_temp_count = ins->declaration.count;
- normaliser->temp_dcl_idx = index;
- }
- else
- {
- normaliser->max_temp_count = max(normaliser->max_temp_count, ins->declaration.count);
- vkd3d_shader_instruction_make_nop(ins);
- }
- return;
- }
if (normaliser->phase == VKD3DSIH_INVALID || shader_instruction_is_dcl(ins))
return;
@@ -382,9 +382,6 @@ static enum vkd3d_result instruction_array_flatten_hull_shader_phases(struct vkd
if (flattener.phase != VKD3DSIH_INVALID)
{
- if (flattener.temp_dcl_idx)
- instructions->elements[flattener.temp_dcl_idx].declaration.count = flattener.max_temp_count;
-
if (!shader_instruction_array_reserve(&flattener.instructions, flattener.instructions.count + 1))
return VKD3D_ERROR_OUT_OF_MEMORY;
vsir_instruction_init(&instructions->elements[instructions->count++], &flattener.last_ret_location, VKD3DSIH_RET);
@@ -581,9 +578,6 @@ struct io_normaliser
struct shader_signature *output_signature;
struct shader_signature *patch_constant_signature;
- unsigned int max_temp_count;
- unsigned int temp_dcl_idx;
-
unsigned int instance_count;
unsigned int phase_body_idx;
enum vkd3d_shader_opcode phase;
@@ -2224,6 +2218,7 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte
static enum vkd3d_result flatten_control_flow_constructs(struct vkd3d_shader_parser *parser)
{
+ struct vsir_program *program = &parser->program;
struct cf_flattener flattener = {0};
enum vkd3d_result result;
@@ -2233,10 +2228,10 @@ static enum vkd3d_result flatten_control_flow_constructs(struct vkd3d_shader_par
if (result >= 0)
{
vkd3d_free(parser->program.instructions.elements);
- parser->program.instructions.elements = flattener.instructions;
- parser->program.instructions.capacity = flattener.instruction_capacity;
- parser->program.instructions.count = flattener.instruction_count;
- parser->shader_desc.block_count = flattener.block_id;
+ program->instructions.elements = flattener.instructions;
+ program->instructions.capacity = flattener.instruction_capacity;
+ program->instructions.count = flattener.instruction_count;
+ program->block_count = flattener.block_id;
}
else
{
@@ -2245,8 +2240,8 @@ static enum vkd3d_result flatten_control_flow_constructs(struct vkd3d_shader_par
vkd3d_free(flattener.control_flow_info);
/* Simpler to always free these in free_shader_desc(). */
- parser->shader_desc.block_names = flattener.block_names;
- parser->shader_desc.block_name_count = flattener.block_name_count;
+ program->block_names = flattener.block_names;
+ program->block_name_count = flattener.block_name_count;
return result;
}
@@ -2257,41 +2252,48 @@ enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser,
struct vkd3d_shader_instruction_array *instructions = &parser->program.instructions;
enum vkd3d_result result = VKD3D_OK;
- if (parser->shader_desc.is_dxil)
- return result;
+ remove_dcl_temps(&parser->program);
- if (parser->program.shader_version.type != VKD3D_SHADER_TYPE_PIXEL
- && (result = remap_output_signature(parser, compile_info)) < 0)
- return result;
-
- if (parser->program.shader_version.type == VKD3D_SHADER_TYPE_HULL
- && (result = instruction_array_flatten_hull_shader_phases(instructions)) >= 0)
+ if (!parser->shader_desc.is_dxil)
{
- result = instruction_array_normalise_hull_shader_control_point_io(instructions,
- &parser->shader_desc.input_signature);
- }
- if (result >= 0)
- result = shader_normalise_io_registers(parser);
+ if (parser->program.shader_version.type != VKD3D_SHADER_TYPE_PIXEL)
+ {
+ if ((result = remap_output_signature(parser, compile_info)) < 0)
+ return result;
+ }
- if (result >= 0)
- result = instruction_array_normalise_flat_constants(&parser->program);
+ if (parser->program.shader_version.type == VKD3D_SHADER_TYPE_HULL)
+ {
+ if ((result = instruction_array_flatten_hull_shader_phases(instructions)) < 0)
+ return result;
+
+ if ((result = instruction_array_normalise_hull_shader_control_point_io(instructions,
+ &parser->shader_desc.input_signature)) < 0)
+ return result;
+ }
+
+ if ((result = shader_normalise_io_registers(parser)) < 0)
+ return result;
+
+ if ((result = instruction_array_normalise_flat_constants(&parser->program)) < 0)
+ return result;
- if (result >= 0)
remove_dead_code(&parser->program);
- if (result >= 0)
- result = flatten_control_flow_constructs(parser);
+ if ((result = flatten_control_flow_constructs(parser)) < 0)
+ return result;
- if (result >= 0)
- result = normalise_combined_samplers(parser);
+ if ((result = normalise_combined_samplers(parser)) < 0)
+ return result;
+ }
- if (result >= 0 && TRACE_ON())
+ if (TRACE_ON())
vkd3d_shader_trace(&parser->program);
- if (result >= 0 && !parser->failed)
- result = vsir_validate(parser);
+ if (!parser->failed && (result = vsir_validate(parser)) < 0)
+ return result;
- if (result >= 0 && parser->failed)
+ if (parser->failed)
result = VKD3D_ERROR_INVALID_SHADER;
return result;
@@ -2304,7 +2306,6 @@ struct validation_context
size_t instruction_idx;
bool invalid_instruction_idx;
bool dcl_temps_found;
- unsigned int temp_count;
enum vkd3d_shader_opcode phase;
enum cf_type
{
@@ -2312,6 +2313,7 @@ struct validation_context
CF_TYPE_STRUCTURED,
CF_TYPE_BLOCKS,
} cf_type;
+ bool inside_block;
struct validation_context_temp_data
{
@@ -2365,11 +2367,7 @@ static void vsir_validate_src_param(struct validation_context *ctx,
static void vsir_validate_register(struct validation_context *ctx,
const struct vkd3d_shader_register *reg)
{
- unsigned int i, temp_count = ctx->temp_count;
-
- /* SM1-3 shaders do not include a DCL_TEMPS instruction. */
- if (ctx->program->shader_version.major <= 3)
- temp_count = ctx->program->temp_count;
+ unsigned int i;
if (reg->type >= VKD3DSPR_COUNT)
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, "Invalid register type %#x.",
@@ -2414,18 +2412,13 @@ static void vsir_validate_register(struct validation_context *ctx,
if (reg->idx[0].rel_addr)
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, "Non-NULL relative address for a TEMP register.");
- if (reg->idx[0].offset >= temp_count)
+ if (reg->idx[0].offset >= ctx->parser->program.temp_count)
{
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, "TEMP register index %u exceeds the maximum count %u.",
- reg->idx[0].offset, temp_count);
+ reg->idx[0].offset, ctx->parser->program.temp_count);
break;
}
- /* program->temp_count might be smaller then temp_count if the
- * parser made a mistake; we still don't want to overflow the
- * array. */
- if (reg->idx[0].offset >= ctx->program->temp_count)
- break;
data = &ctx->temps[reg->idx[0].offset];
if (reg->dimension == VSIR_DIMENSION_NONE)
@@ -2524,9 +2517,10 @@ static void vsir_validate_register(struct validation_context *ctx,
/* Index == 0 is invalid, but it is temporarily allowed
* for intermediate stages. Once we support validation
* dialects we can selectively check for that. */
- if (reg->idx[0].offset > ctx->parser->shader_desc.block_count)
- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, "LABEL register index %u exceeds the maximum count %u.",
- reg->idx[0].offset, ctx->parser->shader_desc.block_count);
+ if (reg->idx[0].offset > ctx->program->block_count)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX,
+ "LABEL register index %u exceeds the maximum count %u.",
+ reg->idx[0].offset, ctx->program->block_count);
break;
case VKD3DSPR_NULL:
@@ -2601,21 +2595,39 @@ static void vsir_validate_dst_param(struct validation_context *ctx,
dst->shift);
}
- if (dst->reg.type == VKD3DSPR_SSA && dst->reg.idx[0].offset < ctx->program->ssa_count)
+ switch (dst->reg.type)
{
- struct validation_context_ssa_data *data = &ctx->ssas[dst->reg.idx[0].offset];
+ case VKD3DSPR_SSA:
+ if (dst->reg.idx[0].offset < ctx->parser->program.ssa_count)
+ {
+ struct validation_context_ssa_data *data = &ctx->ssas[dst->reg.idx[0].offset];
- if (data->write_mask == 0)
- {
- data->write_mask = dst->write_mask;
- data->first_assigned = ctx->instruction_idx;
- }
- else
- {
- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SSA_USAGE,
- "SSA register is already assigned at instruction %zu.",
- data->first_assigned);
- }
+ if (data->write_mask == 0)
+ {
+ data->write_mask = dst->write_mask;
+ data->first_assigned = ctx->instruction_idx;
+ }
+ else
+ {
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SSA_USAGE,
+ "SSA register is already assigned at instruction %zu.",
+ data->first_assigned);
+ }
+ }
+ break;
+
+ case VKD3DSPR_IMMCONST:
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE,
+ "Invalid IMMCONST register used as destination parameter.");
+ break;
+
+ case VKD3DSPR_IMMCONST64:
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE,
+ "Invalid IMMCONST64 register used as destination parameter.");
+ break;
+
+ default:
+ break;
}
}
@@ -2636,13 +2648,21 @@ static void vsir_validate_src_param(struct validation_context *ctx,
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_MODIFIERS, "Source has invalid modifiers %#x.",
src->modifiers);
- if (src->reg.type == VKD3DSPR_SSA && src->reg.idx[0].offset < ctx->program->ssa_count)
+ switch (src->reg.type)
{
- struct validation_context_ssa_data *data = &ctx->ssas[src->reg.idx[0].offset];
- unsigned int i;
+ case VKD3DSPR_SSA:
+ if (src->reg.idx[0].offset < ctx->parser->program.ssa_count)
+ {
+ struct validation_context_ssa_data *data = &ctx->ssas[src->reg.idx[0].offset];
+ unsigned int i;
- for (i = 0; i < VKD3D_VEC4_SIZE; ++i)
- data->read_mask |= (1u << vsir_swizzle_get_component(src->swizzle, i));
+ for (i = 0; i < VKD3D_VEC4_SIZE; ++i)
+ data->read_mask |= (1u << vsir_swizzle_get_component(src->swizzle, i));
+ }
+ break;
+
+ default:
+ break;
}
}
@@ -2752,7 +2772,6 @@ static void vsir_validate_instruction(struct validation_context *ctx)
instruction->handler_idx);
ctx->phase = instruction->handler_idx;
ctx->dcl_temps_found = false;
- ctx->temp_count = 0;
return;
default:
@@ -2781,6 +2800,33 @@ static void vsir_validate_instruction(struct validation_context *ctx)
ctx->cf_type = CF_TYPE_STRUCTURED;
}
+ if (ctx->cf_type == CF_TYPE_BLOCKS && !vsir_instruction_is_dcl(instruction))
+ {
+ switch (instruction->handler_idx)
+ {
+ case VKD3DSIH_LABEL:
+ if (ctx->inside_block)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, "Invalid LABEL instruction inside a block.");
+ ctx->inside_block = true;
+ break;
+
+ case VKD3DSIH_RET:
+ case VKD3DSIH_BRANCH:
+ case VKD3DSIH_SWITCH_MONOLITHIC:
+ if (!ctx->inside_block)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, "Invalid instruction %#x outside any block.",
+ instruction->handler_idx);
+ ctx->inside_block = false;
+ break;
+
+ default:
+ if (!ctx->inside_block)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, "Invalid instruction %#x outside any block.",
+ instruction->handler_idx);
+ break;
+ }
+ }
+
switch (instruction->handler_idx)
{
case VKD3DSIH_DCL_TEMPS:
@@ -2793,7 +2839,6 @@ static void vsir_validate_instruction(struct validation_context *ctx)
"Invalid DCL_TEMPS count %u, expected at most %u.",
instruction->declaration.count, ctx->program->temp_count);
ctx->dcl_temps_found = true;
- ctx->temp_count = instruction->declaration.count;
break;
case VKD3DSIH_IF:
@@ -2988,6 +3033,62 @@ static void vsir_validate_instruction(struct validation_context *ctx)
break;
}
+ case VKD3DSIH_PHI:
+ {
+ unsigned int incoming_count;
+
+ vsir_validate_cf_type(ctx, instruction, CF_TYPE_BLOCKS);
+ vsir_validate_dst_count(ctx, instruction, 1);
+ vsir_validate_src_min_count(ctx, instruction, 2);
+ if (instruction->src_count % 2 != 0)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SOURCE_COUNT,
+ "Invalid source count %u for a PHI instruction, it must be an even number.",
+ instruction->src_count);
+ incoming_count = instruction->src_count / 2;
+
+ if (!register_is_ssa(&instruction->dst[0].reg))
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE,
+ "Invalid destination of type %#x in PHI instruction, expected SSA.",
+ instruction->dst[0].reg.type);
+
+ if (instruction->dst[0].reg.dimension != VSIR_DIMENSION_SCALAR)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION,
+ "Invalid destination dimension %#x in PHI instruction, expected scalar.",
+ instruction->dst[0].reg.dimension);
+
+ if (instruction->dst[0].modifiers != VKD3DSPDM_NONE)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_MODIFIERS,
+ "Invalid modifiers %#x for the destination of a PHI instruction, expected none.",
+ instruction->dst[0].modifiers);
+
+ if (instruction->dst[0].shift != 0)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SHIFT,
+ "Invalid shift %#x for the destination of a PHI instruction, expected none.",
+ instruction->dst[0].shift);
+
+ for (i = 0; i < incoming_count; ++i)
+ {
+ unsigned int value_idx = 2 * i;
+ unsigned int label_idx = 2 * i + 1;
+
+ if (!register_is_constant(&instruction->src[value_idx].reg) && !register_is_ssa(&instruction->src[value_idx].reg))
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE,
+ "Invalid value register for incoming %zu of type %#x in PHI instruction, "
+ "expected SSA, IMMCONST or IMMCONST64.", i, instruction->src[value_idx].reg.type);
+
+ if (instruction->src[value_idx].reg.dimension != VSIR_DIMENSION_SCALAR)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION,
+ "Invalid value dimension %#x for incoming %zu in PHI instruction, expected scalar.",
+ instruction->src[value_idx].reg.dimension, i);
+
+ if (!vsir_register_is_label(&instruction->src[label_idx].reg))
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE,
+ "Invalid label register for case %zu of type %#x in PHI instruction, "
+ "expected LABEL.", i, instruction->src[value_idx].reg.type);
+ }
+ break;
+ }
+
default:
break;
}
@@ -3020,6 +3121,9 @@ enum vkd3d_result vsir_validate(struct vkd3d_shader_parser *parser)
if (ctx.depth != 0)
validator_error(&ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, "%zu nested blocks were not closed.", ctx.depth);
+ if (ctx.inside_block)
+ validator_error(&ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, "Last block was not closed.");
+
for (i = 0; i < ctx.program->ssa_count; ++i)
{
struct validation_context_ssa_data *data = &ctx.ssas[i];
diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c
index e99724ca21c..3b2e45829fd 100644
--- a/libs/vkd3d/libs/vkd3d-shader/spirv.c
+++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c
@@ -2328,6 +2328,7 @@ struct spirv_compiler
uint32_t private_output_variable[MAX_REG_OUTPUT + 1]; /* 1 entry for oDepth */
uint32_t private_output_variable_write_mask[MAX_REG_OUTPUT + 1]; /* 1 entry for oDepth */
uint32_t epilogue_function_id;
+ uint32_t discard_function_id;
uint32_t binding_idx;
@@ -7626,16 +7627,39 @@ static void spirv_compiler_emit_retc(struct spirv_compiler *compiler,
vkd3d_spirv_build_op_label(builder, merge_block_id);
}
-static void spirv_compiler_emit_kill(struct spirv_compiler *compiler,
- const struct vkd3d_shader_instruction *instruction)
+static uint32_t spirv_compiler_get_discard_function_id(struct spirv_compiler *compiler)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
- uint32_t target_id, merge_block_id;
- target_id = vkd3d_spirv_alloc_id(builder);
- merge_block_id = spirv_compiler_emit_conditional_branch(compiler, instruction, target_id);
+ if (!compiler->discard_function_id)
+ compiler->discard_function_id = vkd3d_spirv_alloc_id(builder);
- vkd3d_spirv_build_op_label(builder, target_id);
+ return compiler->discard_function_id;
+}
+
+static void spirv_compiler_emit_discard_function(struct spirv_compiler *compiler)
+{
+ uint32_t void_id, bool_id, function_type_id, condition_id, target_block_id, merge_block_id;
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+
+ vkd3d_spirv_build_op_name(builder, compiler->discard_function_id, "discard");
+
+ void_id = vkd3d_spirv_get_op_type_void(builder);
+ bool_id = vkd3d_spirv_get_op_type_bool(builder);
+ function_type_id = vkd3d_spirv_get_op_type_function(builder, void_id, &bool_id, 1);
+
+ vkd3d_spirv_build_op_function(builder, void_id, compiler->discard_function_id,
+ SpvFunctionControlMaskNone, function_type_id);
+ condition_id = vkd3d_spirv_build_op_function_parameter(builder, bool_id);
+
+ vkd3d_spirv_build_op_label(builder, vkd3d_spirv_alloc_id(builder));
+
+ target_block_id = vkd3d_spirv_alloc_id(builder);
+ merge_block_id = vkd3d_spirv_alloc_id(builder);
+ vkd3d_spirv_build_op_selection_merge(builder, merge_block_id, SpvSelectionControlMaskNone);
+ vkd3d_spirv_build_op_branch_conditional(builder, condition_id, target_block_id, merge_block_id);
+
+ vkd3d_spirv_build_op_label(builder, target_block_id);
if (spirv_compiler_is_target_extension_supported(compiler,
VKD3D_SHADER_SPIRV_EXTENSION_EXT_DEMOTE_TO_HELPER_INVOCATION))
@@ -7650,6 +7674,26 @@ static void spirv_compiler_emit_kill(struct spirv_compiler *compiler,
}
vkd3d_spirv_build_op_label(builder, merge_block_id);
+ vkd3d_spirv_build_op_return(builder);
+ vkd3d_spirv_build_op_function_end(builder);
+}
+
+static void spirv_compiler_emit_discard(struct spirv_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_src_param *src = instruction->src;
+ uint32_t condition_id, void_id;
+
+ /* discard is not a block terminator in VSIR, and emitting it as such in SPIR-V would cause
+ * a mismatch between the VSIR structure and the SPIR-V one, which would cause problems if
+ * structurisation is necessary. Therefore we emit it as a function call. */
+ condition_id = spirv_compiler_emit_load_src(compiler, src, VKD3DSP_WRITEMASK_0);
+ condition_id = spirv_compiler_emit_int_to_bool(compiler,
+ instruction->flags, src->reg.data_type, 1, condition_id);
+ void_id = vkd3d_spirv_get_op_type_void(builder);
+ vkd3d_spirv_build_op_function_call(builder, void_id, spirv_compiler_get_discard_function_id(compiler),
+ &condition_id, 1);
}
static bool spirv_compiler_init_blocks(struct spirv_compiler *compiler, unsigned int block_count)
@@ -9515,7 +9559,7 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler,
break;
case VKD3DSIH_DISCARD:
case VKD3DSIH_TEXKILL:
- spirv_compiler_emit_kill(compiler, instruction);
+ spirv_compiler_emit_discard(compiler, instruction);
break;
case VKD3DSIH_LABEL:
spirv_compiler_emit_label(compiler, instruction);
@@ -9635,7 +9679,6 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler,
case VKD3DSIH_DCL_RESOURCE_RAW:
case VKD3DSIH_DCL_RESOURCE_STRUCTURED:
case VKD3DSIH_DCL_SAMPLER:
- case VKD3DSIH_DCL_TEMPS:
case VKD3DSIH_DCL_UAV_RAW:
case VKD3DSIH_DCL_UAV_STRUCTURED:
case VKD3DSIH_DCL_UAV_TYPED:
@@ -9747,7 +9790,7 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler,
compiler->location.column = 0;
compiler->location.line = 1;
- if (parser->shader_desc.block_count && !spirv_compiler_init_blocks(compiler, parser->shader_desc.block_count))
+ if (program->block_count && !spirv_compiler_init_blocks(compiler, program->block_count))
return VKD3D_ERROR_OUT_OF_MEMORY;
instructions = program->instructions;
@@ -9760,11 +9803,11 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler,
memset(&shader_desc->output_signature, 0, sizeof(shader_desc->output_signature));
memset(&shader_desc->patch_constant_signature, 0, sizeof(shader_desc->patch_constant_signature));
compiler->use_vocp = program->use_vocp;
- compiler->block_names = parser->shader_desc.block_names;
- compiler->block_name_count = parser->shader_desc.block_name_count;
+ compiler->block_names = program->block_names;
+ compiler->block_name_count = program->block_name_count;
- compiler->input_control_point_count = shader_desc->input_control_point_count;
- compiler->output_control_point_count = shader_desc->output_control_point_count;
+ compiler->input_control_point_count = program->input_control_point_count;
+ compiler->output_control_point_count = program->output_control_point_count;
if (compiler->shader_type != VKD3D_SHADER_TYPE_HULL)
spirv_compiler_emit_shader_signature_outputs(compiler);
@@ -9802,6 +9845,9 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler,
}
}
+ if (compiler->discard_function_id)
+ spirv_compiler_emit_discard_function(compiler);
+
if (compiler->epilogue_function_id)
{
vkd3d_spirv_build_op_name(builder, compiler->epilogue_function_id, "epilogue");
diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c
index df10cd254d6..50146c2c7c9 100644
--- a/libs/vkd3d/libs/vkd3d-shader/tpf.c
+++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c
@@ -1051,7 +1051,7 @@ static void shader_sm4_read_dcl_input_primitive(struct vkd3d_shader_instruction
{
ins->declaration.primitive_type.type = VKD3D_PT_PATCH;
ins->declaration.primitive_type.patch_vertex_count = primitive_type - VKD3D_SM5_INPUT_PT_PATCH1 + 1;
- priv->p.shader_desc.input_control_point_count = ins->declaration.primitive_type.patch_vertex_count;
+ priv->p.program.input_control_point_count = ins->declaration.primitive_type.patch_vertex_count;
}
else if (primitive_type >= ARRAY_SIZE(input_primitive_type_table))
{
@@ -1060,7 +1060,7 @@ static void shader_sm4_read_dcl_input_primitive(struct vkd3d_shader_instruction
else
{
ins->declaration.primitive_type.type = input_primitive_type_table[primitive_type].vkd3d_type;
- priv->p.shader_desc.input_control_point_count = input_primitive_type_table[primitive_type].control_point_count;
+ priv->p.program.input_control_point_count = input_primitive_type_table[primitive_type].control_point_count;
}
if (ins->declaration.primitive_type.type == VKD3D_PT_UNDEFINED)
@@ -1174,9 +1174,9 @@ static void shader_sm5_read_control_point_count(struct vkd3d_shader_instruction
>> VKD3D_SM5_CONTROL_POINT_COUNT_SHIFT;
if (opcode == VKD3D_SM5_OP_DCL_INPUT_CONTROL_POINT_COUNT)
- priv->p.shader_desc.input_control_point_count = ins->declaration.count;
+ priv->p.program.input_control_point_count = ins->declaration.count;
else
- priv->p.shader_desc.output_control_point_count = ins->declaration.count;
+ priv->p.program.output_control_point_count = ins->declaration.count;
}
static void shader_sm5_read_dcl_tessellator_domain(struct vkd3d_shader_instruction *ins, uint32_t opcode,
diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
index 2d5e25d7f05..115a7d8c83b 100644
--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
@@ -1020,17 +1020,10 @@ struct vkd3d_shader_desc
struct shader_signature output_signature;
struct shader_signature patch_constant_signature;
- unsigned int input_control_point_count, output_control_point_count;
-
- unsigned int block_count;
-
struct
{
uint32_t used, external;
} flat_constant_count[3];
-
- const char **block_names;
- size_t block_name_count;
};
struct vkd3d_shader_register_semantic
@@ -1271,9 +1264,14 @@ struct vsir_program
struct vkd3d_shader_version shader_version;
struct vkd3d_shader_instruction_array instructions;
+ unsigned int input_control_point_count, output_control_point_count;
+ unsigned int block_count;
unsigned int temp_count;
unsigned int ssa_count;
bool use_vocp;
+
+ const char **block_names;
+ size_t block_name_count;
};
bool vsir_program_init(struct vsir_program *program, const struct vkd3d_shader_version *version, unsigned int reserve);
diff --git a/libs/vkd3d/libs/vkd3d/device.c b/libs/vkd3d/libs/vkd3d/device.c
index 75efa41fd32..2b8558175e0 100644
--- a/libs/vkd3d/libs/vkd3d/device.c
+++ b/libs/vkd3d/libs/vkd3d/device.c
@@ -594,7 +594,7 @@ static HRESULT vkd3d_instance_init(struct vkd3d_instance *instance,
if (FAILED(hr = vkd3d_init_vk_global_procs(instance, create_info->pfn_vkGetInstanceProcAddr)))
{
- ERR("Failed to initialize Vulkan global procs, hr %#x.\n", hr);
+ ERR("Failed to initialise Vulkan global procs, hr %s.\n", debugstr_hresult(hr));
return hr;
}
@@ -674,7 +674,7 @@ static HRESULT vkd3d_instance_init(struct vkd3d_instance *instance,
if (FAILED(hr = vkd3d_load_vk_instance_procs(&instance->vk_procs, vk_global_procs, vk_instance)))
{
- ERR("Failed to load instance procs, hr %#x.\n", hr);
+ ERR("Failed to load instance procs, hr %s.\n", debugstr_hresult(hr));
if (instance->vk_procs.vkDestroyInstance)
instance->vk_procs.vkDestroyInstance(vk_instance, NULL);
if (instance->libvulkan)
@@ -2071,7 +2071,7 @@ static HRESULT vkd3d_create_vk_device(struct d3d12_device *device,
if (FAILED(hr = vkd3d_load_vk_device_procs(&device->vk_procs, vk_procs, vk_device)))
{
- ERR("Failed to load device procs, hr %#x.\n", hr);
+ ERR("Failed to load device procs, hr %s.\n", debugstr_hresult(hr));
if (device->vk_procs.vkDestroyDevice)
device->vk_procs.vkDestroyDevice(vk_device, NULL);
return hr;
@@ -2081,7 +2081,7 @@ static HRESULT vkd3d_create_vk_device(struct d3d12_device *device,
if (FAILED(hr = d3d12_device_create_vkd3d_queues(device, &device_queue_info)))
{
- ERR("Failed to create queues, hr %#x.\n", hr);
+ ERR("Failed to create queues, hr %s.\n", debugstr_hresult(hr));
device->vk_procs.vkDestroyDevice(vk_device, NULL);
return hr;
}
@@ -4404,7 +4404,7 @@ static HRESULT d3d12_device_init(struct d3d12_device *device,
if (device->use_vk_heaps && FAILED(hr = vkd3d_create_thread(device->vkd3d_instance,
device_worker_main, device, &device->worker_thread)))
{
- WARN("Failed to create worker thread, hr %#x.\n", hr);
+ WARN("Failed to create worker thread, hr %s.\n", debugstr_hresult(hr));
goto out_cleanup_descriptor_heap_layouts;
}
@@ -4582,7 +4582,7 @@ HRESULT vkd3d_join_thread(struct vkd3d_instance *instance, union vkd3d_thread_ha
if (instance->join_thread)
{
if (FAILED(hr = instance->join_thread(thread->handle)))
- ERR("Failed to join thread, hr %#x.\n", hr);
+ ERR("Failed to join thread, hr %s.\n", debugstr_hresult(hr));
}
else
{
diff --git a/libs/vkd3d/libs/vkd3d/resource.c b/libs/vkd3d/libs/vkd3d/resource.c
index f9e50335fa8..a360b0ef4dd 100644
--- a/libs/vkd3d/libs/vkd3d/resource.c
+++ b/libs/vkd3d/libs/vkd3d/resource.c
@@ -4923,7 +4923,7 @@ HRESULT vkd3d_init_null_resources(struct vkd3d_null_resources *null_resources,
return vkd3d_init_null_resources_data(null_resources, device);
fail:
- ERR("Failed to initialize NULL resources, hr %#x.\n", hr);
+ ERR("Failed to initialise NULL resources, hr %s.\n", debugstr_hresult(hr));
vkd3d_destroy_null_resources(null_resources, device);
return hr;
}
--
2.43.0