mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
1545 lines
64 KiB
Diff
1545 lines
64 KiB
Diff
|
From 9384c8b24d08cfdbbb913b8a6b229a8315123af6 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
|
||
|
|