mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
2216 lines
100 KiB
Diff
2216 lines
100 KiB
Diff
From c5c1605d8c3efac75f051defd5167bde20dfc36e Mon Sep 17 00:00:00 2001
|
|
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
|
|
Date: Wed, 13 Mar 2024 15:58:53 +1100
|
|
Subject: [PATCH] Updated vkd3d to 9b0d304f8fe4e6f0d065e4561af9e372e1643c2d.
|
|
|
|
---
|
|
libs/vkd3d/include/vkd3d_shader.h | 28 +-
|
|
libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 22 +-
|
|
libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 16 +-
|
|
libs/vkd3d/libs/vkd3d-shader/dxbc.c | 39 +--
|
|
libs/vkd3d/libs/vkd3d-shader/dxil.c | 145 +++++++++--
|
|
libs/vkd3d/libs/vkd3d-shader/fx.c | 128 +++++++---
|
|
libs/vkd3d/libs/vkd3d-shader/glsl.c | 49 ++--
|
|
libs/vkd3d/libs/vkd3d-shader/hlsl.c | 4 +
|
|
libs/vkd3d/libs/vkd3d-shader/hlsl.h | 2 +
|
|
libs/vkd3d/libs/vkd3d-shader/hlsl.l | 1 -
|
|
libs/vkd3d/libs/vkd3d-shader/hlsl.y | 24 +-
|
|
libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 8 +-
|
|
libs/vkd3d/libs/vkd3d-shader/ir.c | 239 ++++++++++++++++--
|
|
libs/vkd3d/libs/vkd3d-shader/spirv.c | 166 ++++++++++--
|
|
libs/vkd3d/libs/vkd3d-shader/tpf.c | 45 ++--
|
|
.../libs/vkd3d-shader/vkd3d_shader_main.c | 22 +-
|
|
.../libs/vkd3d-shader/vkd3d_shader_private.h | 35 ++-
|
|
libs/vkd3d/libs/vkd3d/device.c | 29 ++-
|
|
libs/vkd3d/libs/vkd3d/vkd3d_private.h | 3 +-
|
|
19 files changed, 781 insertions(+), 224 deletions(-)
|
|
|
|
diff --git a/libs/vkd3d/include/vkd3d_shader.h b/libs/vkd3d/include/vkd3d_shader.h
|
|
index 1a62f093d6b..83b90474af4 100644
|
|
--- a/libs/vkd3d/include/vkd3d_shader.h
|
|
+++ b/libs/vkd3d/include/vkd3d_shader.h
|
|
@@ -218,6 +218,20 @@ enum vkd3d_shader_compile_option_feature_flags
|
|
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPILE_OPTION_FEATURE_FLAGS),
|
|
};
|
|
|
|
+/**
|
|
+ * Flags for vkd3d_shader_parse_dxbc().
|
|
+ *
|
|
+ * \since 1.12
|
|
+ */
|
|
+enum vkd3d_shader_parse_dxbc_flags
|
|
+{
|
|
+ /** Ignore the checksum and continue parsing even if it is
|
|
+ * incorrect. */
|
|
+ VKD3D_SHADER_PARSE_DXBC_IGNORE_CHECKSUM = 0x00000001,
|
|
+
|
|
+ VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_PARSE_DXBC_FLAGS),
|
|
+};
|
|
+
|
|
enum vkd3d_shader_compile_option_name
|
|
{
|
|
/**
|
|
@@ -285,6 +299,15 @@ enum vkd3d_shader_compile_option_name
|
|
* \since 1.11
|
|
*/
|
|
VKD3D_SHADER_COMPILE_OPTION_FEATURE = 0x0000000a,
|
|
+ /**
|
|
+ * If \a value is non-zero compilation will produce a child effect using
|
|
+ * shared object descriptions, as instructed by the "shared" modifier.
|
|
+ * Child effects are supported with fx_2_0, fx_4_0, and fx_4_1. This option
|
|
+ * and "shared" modifiers are ignored for fx_5_0 profile, and non-fx profiles.
|
|
+ *
|
|
+ * \since 1.12
|
|
+ */
|
|
+ VKD3D_SHADER_COMPILE_OPTION_CHILD_EFFECT = 0x0000000b,
|
|
|
|
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPILE_OPTION_NAME),
|
|
};
|
|
@@ -2385,9 +2408,8 @@ VKD3D_SHADER_API void vkd3d_shader_free_dxbc(struct vkd3d_shader_dxbc_desc *dxbc
|
|
*
|
|
* \param dxbc A vkd3d_shader_code structure containing the DXBC blob to parse.
|
|
*
|
|
- * \param flags A set of flags modifying the behaviour of the function. No
|
|
- * flags are defined for this version of vkd3d-shader, and this parameter
|
|
- * should be set to 0.
|
|
+ * \param flags A combination of zero or more elements of enum
|
|
+ * vkd3d_shader_parse_dxbc_flags.
|
|
*
|
|
* \param desc A vkd3d_shader_dxbc_desc structure describing the contents of
|
|
* the DXBC blob. Its vkd3d_shader_dxbc_section_desc structures will contain
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c
|
|
index b8dcfd011b6..fcbb321edd1 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c
|
|
@@ -649,6 +649,8 @@ static void shader_dump_data_type(struct vkd3d_d3d_asm_compiler *compiler, enum
|
|
[VKD3D_DATA_UINT8 ] = "uint8",
|
|
[VKD3D_DATA_UINT64 ] = "uint64",
|
|
[VKD3D_DATA_BOOL ] = "bool",
|
|
+ [VKD3D_DATA_UINT16 ] = "uint16",
|
|
+ [VKD3D_DATA_HALF ] = "half",
|
|
};
|
|
|
|
const char *name;
|
|
@@ -2196,22 +2198,22 @@ static enum vkd3d_result dump_signature(struct vkd3d_d3d_asm_compiler *compiler,
|
|
}
|
|
|
|
static enum vkd3d_result dump_signatures(struct vkd3d_d3d_asm_compiler *compiler,
|
|
- const struct vkd3d_shader_desc *shader_desc, enum vkd3d_shader_type shader_type)
|
|
+ const struct vsir_program *program)
|
|
{
|
|
enum vkd3d_result ret;
|
|
|
|
if ((ret = dump_signature(compiler, ".input",
|
|
- shader_type == VKD3D_SHADER_TYPE_DOMAIN ? "vicp" : "v",
|
|
- &shader_desc->input_signature)) < 0)
|
|
+ program->shader_version.type == VKD3D_SHADER_TYPE_DOMAIN ? "vicp" : "v",
|
|
+ &program->input_signature)) < 0)
|
|
return ret;
|
|
|
|
if ((ret = dump_signature(compiler, ".output", "o",
|
|
- &shader_desc->output_signature)) < 0)
|
|
+ &program->output_signature)) < 0)
|
|
return ret;
|
|
|
|
if ((ret = dump_signature(compiler, ".patch_constant",
|
|
- shader_type == VKD3D_SHADER_TYPE_DOMAIN ? "vpc" : "o",
|
|
- &shader_desc->patch_constant_signature)) < 0)
|
|
+ program->shader_version.type == VKD3D_SHADER_TYPE_DOMAIN ? "vpc" : "o",
|
|
+ &program->patch_constant_signature)) < 0)
|
|
return ret;
|
|
|
|
vkd3d_string_buffer_printf(&compiler->buffer, "%s.text%s\n",
|
|
@@ -2220,8 +2222,8 @@ static enum vkd3d_result dump_signatures(struct vkd3d_d3d_asm_compiler *compiler
|
|
return VKD3D_OK;
|
|
}
|
|
|
|
-enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vsir_program *program,
|
|
- const struct vkd3d_shader_desc *shader_desc, const struct vkd3d_shader_compile_info *compile_info,
|
|
+enum vkd3d_result d3d_asm_compile(const struct vsir_program *program,
|
|
+ const struct vkd3d_shader_compile_info *compile_info,
|
|
struct vkd3d_shader_code *out, enum vsir_asm_flags flags)
|
|
{
|
|
const struct vkd3d_shader_version *shader_version = &program->shader_version;
|
|
@@ -2297,7 +2299,7 @@ enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vsir_program *program,
|
|
* doesn't even have an explicit concept of signature. */
|
|
if (formatting & VKD3D_SHADER_COMPILE_OPTION_FORMATTING_IO_SIGNATURES && shader_version->major >= 4)
|
|
{
|
|
- if ((result = dump_signatures(&compiler, shader_desc, shader_version->type)) < 0)
|
|
+ if ((result = dump_signatures(&compiler, program)) < 0)
|
|
{
|
|
vkd3d_string_buffer_cleanup(buffer);
|
|
return result;
|
|
@@ -2355,7 +2357,7 @@ void vkd3d_shader_trace(const struct vsir_program *program)
|
|
const char *p, *q, *end;
|
|
struct vkd3d_shader_code code;
|
|
|
|
- if (vkd3d_dxbc_binary_to_text(program, NULL, NULL, &code, VSIR_ASM_FLAG_DUMP_TYPES) != VKD3D_OK)
|
|
+ if (d3d_asm_compile(program, NULL, &code, VSIR_ASM_FLAG_DUMP_TYPES) != VKD3D_OK)
|
|
return;
|
|
|
|
end = (const char *)code.code + code.size;
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
|
|
index a8cca17faa3..57dd0258aef 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
|
|
@@ -541,9 +541,9 @@ static bool add_signature_element(struct vkd3d_shader_sm1_parser *sm1, bool outp
|
|
struct signature_element *element;
|
|
|
|
if (output)
|
|
- signature = &sm1->p.shader_desc.output_signature;
|
|
+ signature = &sm1->p.program.output_signature;
|
|
else
|
|
- signature = &sm1->p.shader_desc.input_signature;
|
|
+ signature = &sm1->p.program.input_signature;
|
|
|
|
if ((element = find_signature_element(signature, name, index)))
|
|
{
|
|
@@ -581,9 +581,9 @@ static void add_signature_mask(struct vkd3d_shader_sm1_parser *sm1, bool output,
|
|
struct signature_element *element;
|
|
|
|
if (output)
|
|
- signature = &sm1->p.shader_desc.output_signature;
|
|
+ signature = &sm1->p.program.output_signature;
|
|
else
|
|
- signature = &sm1->p.shader_desc.input_signature;
|
|
+ signature = &sm1->p.program.input_signature;
|
|
|
|
if (!(element = find_signature_element_by_register_index(signature, register_index)))
|
|
{
|
|
@@ -886,7 +886,6 @@ static void shader_sm1_destroy(struct vkd3d_shader_parser *parser)
|
|
struct vkd3d_shader_sm1_parser *sm1 = vkd3d_shader_sm1_parser(parser);
|
|
|
|
vsir_program_cleanup(&parser->program);
|
|
- free_shader_desc(&sm1->p.shader_desc);
|
|
vkd3d_free(sm1);
|
|
}
|
|
|
|
@@ -1237,7 +1236,6 @@ static enum vkd3d_result shader_sm1_init(struct vkd3d_shader_sm1_parser *sm1,
|
|
const struct vkd3d_shader_location location = {.source_name = compile_info->source_name};
|
|
const uint32_t *code = compile_info->source.code;
|
|
size_t code_size = compile_info->source.size;
|
|
- struct vkd3d_shader_desc *shader_desc;
|
|
struct vkd3d_shader_version version;
|
|
uint16_t shader_type;
|
|
size_t token_count;
|
|
@@ -1290,9 +1288,6 @@ static enum vkd3d_result shader_sm1_init(struct vkd3d_shader_sm1_parser *sm1,
|
|
if (!vkd3d_shader_parser_init(&sm1->p, message_context, compile_info->source_name, &version, &shader_sm1_parser_ops,
|
|
code_size != ~(size_t)0 ? token_count / 4u + 4 : 16))
|
|
return VKD3D_ERROR_OUT_OF_MEMORY;
|
|
- shader_desc = &sm1->p.shader_desc;
|
|
- shader_desc->byte_code = code;
|
|
- shader_desc->byte_code_size = code_size;
|
|
sm1->ptr = sm1->start;
|
|
|
|
return VKD3D_OK;
|
|
@@ -2067,6 +2062,9 @@ static void write_sm1_semantic_dcl(struct hlsl_ctx *ctx, struct vkd3d_bytecode_b
|
|
D3DDECLUSAGE usage;
|
|
bool ret;
|
|
|
|
+ if ((!output && !var->last_read) || (output && !var->first_write))
|
|
+ return;
|
|
+
|
|
if (hlsl_sm1_register_from_semantic(ctx, &var->semantic, output, ®.type, ®.reg))
|
|
{
|
|
usage = 0;
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/dxbc.c b/libs/vkd3d/libs/vkd3d-shader/dxbc.c
|
|
index 37ebc73c099..8a1012d909b 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/dxbc.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/dxbc.c
|
|
@@ -150,7 +150,7 @@ static const char *shader_get_string(const char *data, size_t data_size, size_t
|
|
}
|
|
|
|
static int parse_dxbc(const struct vkd3d_shader_code *dxbc, struct vkd3d_shader_message_context *message_context,
|
|
- const char *source_name, struct vkd3d_shader_dxbc_desc *desc)
|
|
+ const char *source_name, uint32_t flags, struct vkd3d_shader_dxbc_desc *desc)
|
|
{
|
|
const struct vkd3d_shader_location location = {.source_name = source_name};
|
|
struct vkd3d_shader_dxbc_section_desc *sections, *section;
|
|
@@ -186,17 +186,20 @@ static int parse_dxbc(const struct vkd3d_shader_code *dxbc, struct vkd3d_shader_
|
|
checksum[1] = read_u32(&ptr);
|
|
checksum[2] = read_u32(&ptr);
|
|
checksum[3] = read_u32(&ptr);
|
|
- vkd3d_compute_dxbc_checksum(data, data_size, calculated_checksum);
|
|
- if (memcmp(checksum, calculated_checksum, sizeof(checksum)))
|
|
- {
|
|
- WARN("Checksum {0x%08x, 0x%08x, 0x%08x, 0x%08x} does not match "
|
|
- "calculated checksum {0x%08x, 0x%08x, 0x%08x, 0x%08x}.\n",
|
|
- checksum[0], checksum[1], checksum[2], checksum[3],
|
|
- calculated_checksum[0], calculated_checksum[1],
|
|
- calculated_checksum[2], calculated_checksum[3]);
|
|
- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXBC_INVALID_CHECKSUM,
|
|
- "Invalid DXBC checksum.");
|
|
- return VKD3D_ERROR_INVALID_ARGUMENT;
|
|
+ if (!(flags & VKD3D_SHADER_PARSE_DXBC_IGNORE_CHECKSUM))
|
|
+ {
|
|
+ vkd3d_compute_dxbc_checksum(data, data_size, calculated_checksum);
|
|
+ if (memcmp(checksum, calculated_checksum, sizeof(checksum)))
|
|
+ {
|
|
+ WARN("Checksum {0x%08x, 0x%08x, 0x%08x, 0x%08x} does not match "
|
|
+ "calculated checksum {0x%08x, 0x%08x, 0x%08x, 0x%08x}.\n",
|
|
+ checksum[0], checksum[1], checksum[2], checksum[3],
|
|
+ calculated_checksum[0], calculated_checksum[1],
|
|
+ calculated_checksum[2], calculated_checksum[3]);
|
|
+ vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXBC_INVALID_CHECKSUM,
|
|
+ "Invalid DXBC checksum.");
|
|
+ return VKD3D_ERROR_INVALID_ARGUMENT;
|
|
+ }
|
|
}
|
|
|
|
version = read_u32(&ptr);
|
|
@@ -287,7 +290,7 @@ static int for_each_dxbc_section(const struct vkd3d_shader_code *dxbc,
|
|
unsigned int i;
|
|
int ret;
|
|
|
|
- if ((ret = parse_dxbc(dxbc, message_context, source_name, &desc)) < 0)
|
|
+ if ((ret = parse_dxbc(dxbc, message_context, source_name, 0, &desc)) < 0)
|
|
return ret;
|
|
|
|
for (i = 0; i < desc.section_count; ++i)
|
|
@@ -313,7 +316,7 @@ int vkd3d_shader_parse_dxbc(const struct vkd3d_shader_code *dxbc,
|
|
*messages = NULL;
|
|
vkd3d_shader_message_context_init(&message_context, VKD3D_SHADER_LOG_INFO);
|
|
|
|
- ret = parse_dxbc(dxbc, &message_context, NULL, desc);
|
|
+ ret = parse_dxbc(dxbc, &message_context, NULL, flags, desc);
|
|
|
|
vkd3d_shader_message_context_trace_messages(&message_context);
|
|
if (!vkd3d_shader_message_context_copy_messages(&message_context, messages) && ret >= 0)
|
|
@@ -485,7 +488,7 @@ int shader_parse_input_signature(const struct vkd3d_shader_code *dxbc,
|
|
static int shdr_handler(const struct vkd3d_shader_dxbc_section_desc *section,
|
|
struct vkd3d_shader_message_context *message_context, void *context)
|
|
{
|
|
- struct vkd3d_shader_desc *desc = context;
|
|
+ struct dxbc_shader_desc *desc = context;
|
|
int ret;
|
|
|
|
switch (section->tag)
|
|
@@ -550,7 +553,7 @@ static int shdr_handler(const struct vkd3d_shader_dxbc_section_desc *section,
|
|
return VKD3D_OK;
|
|
}
|
|
|
|
-void free_shader_desc(struct vkd3d_shader_desc *desc)
|
|
+void free_dxbc_shader_desc(struct dxbc_shader_desc *desc)
|
|
{
|
|
shader_signature_cleanup(&desc->input_signature);
|
|
shader_signature_cleanup(&desc->output_signature);
|
|
@@ -558,7 +561,7 @@ void free_shader_desc(struct vkd3d_shader_desc *desc)
|
|
}
|
|
|
|
int shader_extract_from_dxbc(const struct vkd3d_shader_code *dxbc,
|
|
- struct vkd3d_shader_message_context *message_context, const char *source_name, struct vkd3d_shader_desc *desc)
|
|
+ struct vkd3d_shader_message_context *message_context, const char *source_name, struct dxbc_shader_desc *desc)
|
|
{
|
|
int ret;
|
|
|
|
@@ -569,7 +572,7 @@ int shader_extract_from_dxbc(const struct vkd3d_shader_code *dxbc,
|
|
if (ret < 0)
|
|
{
|
|
WARN("Failed to parse shader, vkd3d result %d.\n", ret);
|
|
- free_shader_desc(desc);
|
|
+ free_dxbc_shader_desc(desc);
|
|
}
|
|
|
|
return ret;
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c
|
|
index a202d208f9d..de51588b513 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/dxil.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c
|
|
@@ -389,6 +389,8 @@ enum dx_intrinsic_opcode
|
|
DX_BUFFER_LOAD = 68,
|
|
DX_BUFFER_STORE = 69,
|
|
DX_GET_DIMENSIONS = 72,
|
|
+ DX_TEXTURE_GATHER = 73,
|
|
+ DX_TEXTURE_GATHER_CMP = 74,
|
|
DX_ATOMIC_BINOP = 78,
|
|
DX_ATOMIC_CMP_XCHG = 79,
|
|
DX_DERIV_COARSEX = 83,
|
|
@@ -2110,6 +2112,15 @@ static inline bool sm6_value_is_undef(const struct sm6_value *value)
|
|
return sm6_value_is_register(value) && value->u.reg.type == VKD3DSPR_UNDEF;
|
|
}
|
|
|
|
+static bool sm6_value_vector_is_constant_or_undef(const struct sm6_value **values, unsigned int count)
|
|
+{
|
|
+ unsigned int i;
|
|
+ for (i = 0; i < count; ++i)
|
|
+ if (!sm6_value_is_constant(values[i]) && !sm6_value_is_undef(values[i]))
|
|
+ return false;
|
|
+ return true;
|
|
+}
|
|
+
|
|
static bool sm6_value_is_icb(const struct sm6_value *value)
|
|
{
|
|
return value->value_type == VALUE_TYPE_ICB;
|
|
@@ -2199,6 +2210,8 @@ static enum vkd3d_data_type vkd3d_data_type_from_sm6_type(const struct sm6_type
|
|
return VKD3D_DATA_BOOL;
|
|
case 8:
|
|
return VKD3D_DATA_UINT8;
|
|
+ case 16:
|
|
+ return VKD3D_DATA_UINT16;
|
|
case 32:
|
|
return VKD3D_DATA_UINT;
|
|
case 64:
|
|
@@ -2212,6 +2225,8 @@ static enum vkd3d_data_type vkd3d_data_type_from_sm6_type(const struct sm6_type
|
|
{
|
|
switch (type->u.width)
|
|
{
|
|
+ case 16:
|
|
+ return VKD3D_DATA_HALF;
|
|
case 32:
|
|
return VKD3D_DATA_FLOAT;
|
|
case 64:
|
|
@@ -2876,7 +2891,7 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const
|
|
}
|
|
|
|
if (type->u.width == 16)
|
|
- FIXME("Half float type is not supported yet.\n");
|
|
+ dst->u.reg.u.immconst_u32[0] = record->operands[0];
|
|
else if (type->u.width == 32)
|
|
dst->u.reg.u.immconst_f32[0] = bitcast_uint64_to_float(record->operands[0]);
|
|
else if (type->u.width == 64)
|
|
@@ -4182,7 +4197,7 @@ static void sm6_parser_emit_dx_load_input(struct sm6_parser *sm6, enum dx_intrin
|
|
|
|
vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_MOV);
|
|
|
|
- signature = &sm6->p.shader_desc.input_signature;
|
|
+ signature = &sm6->p.program.input_signature;
|
|
if (row_index >= signature->element_count)
|
|
{
|
|
WARN("Invalid row index %u.\n", row_index);
|
|
@@ -4572,7 +4587,7 @@ static void sm6_parser_emit_dx_store_output(struct sm6_parser *sm6, enum dx_intr
|
|
row_index = sm6_value_get_constant_uint(operands[0]);
|
|
column_index = sm6_value_get_constant_uint(operands[2]);
|
|
|
|
- signature = &sm6->p.shader_desc.output_signature;
|
|
+ signature = &sm6->p.program.output_signature;
|
|
if (row_index >= signature->element_count)
|
|
{
|
|
WARN("Invalid row index %u.\n", row_index);
|
|
@@ -4612,6 +4627,68 @@ static void sm6_parser_emit_dx_store_output(struct sm6_parser *sm6, enum dx_intr
|
|
src_param_init_from_value(src_param, value);
|
|
}
|
|
|
|
+static void sm6_parser_emit_dx_texture_gather(struct sm6_parser *sm6, enum dx_intrinsic_opcode op,
|
|
+ const struct sm6_value **operands, struct function_emission_state *state)
|
|
+{
|
|
+ struct vkd3d_shader_register coord, offset;
|
|
+ const struct sm6_value *resource, *sampler;
|
|
+ struct vkd3d_shader_src_param *src_params;
|
|
+ struct vkd3d_shader_instruction *ins;
|
|
+ unsigned int swizzle;
|
|
+ bool extended_offset;
|
|
+
|
|
+ resource = operands[0];
|
|
+ sampler = operands[1];
|
|
+ if (!sm6_value_validate_is_texture_handle(resource, op, sm6)
|
|
+ || !sm6_value_validate_is_sampler_handle(sampler, op, sm6))
|
|
+ {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (!sm6_parser_emit_coordinate_construct(sm6, &operands[2], VKD3D_VEC4_SIZE, NULL, state, &coord))
|
|
+ return;
|
|
+
|
|
+ if ((extended_offset = !sm6_value_vector_is_constant_or_undef(&operands[6], 2))
|
|
+ && !sm6_parser_emit_coordinate_construct(sm6, &operands[6], 2, NULL, state, &offset))
|
|
+ {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ ins = state->ins;
|
|
+ if (op == DX_TEXTURE_GATHER)
|
|
+ {
|
|
+ instruction_init_with_resource(ins, extended_offset ? VKD3DSIH_GATHER4_PO : VKD3DSIH_GATHER4, resource, sm6);
|
|
+ if (!(src_params = instruction_src_params_alloc(ins, 3 + extended_offset, sm6)))
|
|
+ return;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ instruction_init_with_resource(ins, extended_offset ? VKD3DSIH_GATHER4_PO_C : VKD3DSIH_GATHER4_C, resource, sm6);
|
|
+ if (!(src_params = instruction_src_params_alloc(ins, 4 + extended_offset, sm6)))
|
|
+ return;
|
|
+ src_param_init_from_value(&src_params[3 + extended_offset], operands[9]);
|
|
+ }
|
|
+
|
|
+ src_param_init_vector_from_reg(&src_params[0], &coord);
|
|
+ if (extended_offset)
|
|
+ src_param_init_vector_from_reg(&src_params[1], &offset);
|
|
+ else
|
|
+ instruction_set_texel_offset(ins, &operands[6], sm6);
|
|
+ src_param_init_vector_from_reg(&src_params[1 + extended_offset], &resource->u.handle.reg);
|
|
+ src_param_init_vector_from_reg(&src_params[2 + extended_offset], &sampler->u.handle.reg);
|
|
+ /* Swizzle stored in the sampler parameter is the scalar component index to be gathered. */
|
|
+ swizzle = sm6_value_get_constant_uint(operands[8]);
|
|
+ if (swizzle >= VKD3D_VEC4_SIZE)
|
|
+ {
|
|
+ WARN("Invalid swizzle %#x.\n", swizzle);
|
|
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND,
|
|
+ "Swizzle %#x for a texture gather operation is invalid.", swizzle);
|
|
+ }
|
|
+ src_params[2 + extended_offset].swizzle = swizzle;
|
|
+
|
|
+ instruction_dst_param_init_ssa_vector(ins, VKD3D_VEC4_SIZE, sm6);
|
|
+}
|
|
+
|
|
static void sm6_parser_emit_dx_texture_load(struct sm6_parser *sm6, enum dx_intrinsic_opcode op,
|
|
const struct sm6_value **operands, struct function_emission_state *state)
|
|
{
|
|
@@ -4791,6 +4868,8 @@ static const struct sm6_dx_opcode_info sm6_dx_op_table[] =
|
|
[DX_SQRT ] = {"g", "R", sm6_parser_emit_dx_unary},
|
|
[DX_STORE_OUTPUT ] = {"v", "ii8o", sm6_parser_emit_dx_store_output},
|
|
[DX_TAN ] = {"g", "R", sm6_parser_emit_dx_unary},
|
|
+ [DX_TEXTURE_GATHER ] = {"o", "HHffffiic", sm6_parser_emit_dx_texture_gather},
|
|
+ [DX_TEXTURE_GATHER_CMP ] = {"o", "HHffffiicf", sm6_parser_emit_dx_texture_gather},
|
|
[DX_TEXTURE_LOAD ] = {"o", "HiiiiCCC", sm6_parser_emit_dx_texture_load},
|
|
[DX_TEXTURE_STORE ] = {"v", "Hiiiooooc", sm6_parser_emit_dx_texture_store},
|
|
[DX_UBFE ] = {"m", "iiR", sm6_parser_emit_dx_tertiary},
|
|
@@ -5055,7 +5134,10 @@ static enum vkd3d_shader_opcode sm6_map_cast_op(uint64_t code, const struct sm6_
|
|
break;
|
|
case CAST_ZEXT:
|
|
case CAST_SEXT:
|
|
- /* nop or min precision. TODO: native 16-bit */
|
|
+ /* nop or min precision. TODO: native 16-bit.
|
|
+ * Extension instructions could be emitted for min precision, but in Windows
|
|
+ * the AMD RX 580 simply drops such instructions, which makes sense as no
|
|
+ * assumptions should be made about any behaviour which depends on bit width. */
|
|
if (to->u.width == from->u.width || (to->u.width == 32 && from->u.width == 16))
|
|
{
|
|
op = VKD3DSIH_NOP;
|
|
@@ -7752,19 +7834,19 @@ static enum vkd3d_result sm6_parser_signatures_init(struct sm6_parser *sm6, cons
|
|
}
|
|
|
|
if (m->u.node->operand_count && (ret = sm6_parser_read_signature(sm6, m->u.node->operands[0],
|
|
- &sm6->p.shader_desc.input_signature)) < 0)
|
|
+ &sm6->p.program.input_signature)) < 0)
|
|
{
|
|
return ret;
|
|
}
|
|
if (m->u.node->operand_count > 1 && (ret = sm6_parser_read_signature(sm6, m->u.node->operands[1],
|
|
- &sm6->p.shader_desc.output_signature)) < 0)
|
|
+ &sm6->p.program.output_signature)) < 0)
|
|
{
|
|
return ret;
|
|
}
|
|
/* TODO: patch constant signature in operand 2. */
|
|
|
|
- sm6_parser_init_input_signature(sm6, &sm6->p.shader_desc.input_signature);
|
|
- sm6_parser_init_output_signature(sm6, &sm6->p.shader_desc.output_signature);
|
|
+ sm6_parser_init_input_signature(sm6, &sm6->p.program.input_signature);
|
|
+ sm6_parser_init_output_signature(sm6, &sm6->p.program.output_signature);
|
|
|
|
return VKD3D_OK;
|
|
}
|
|
@@ -8062,7 +8144,6 @@ static void sm6_parser_destroy(struct vkd3d_shader_parser *parser)
|
|
sm6_parser_metadata_cleanup(sm6);
|
|
vkd3d_free(sm6->descriptors);
|
|
vkd3d_free(sm6->values);
|
|
- free_shader_desc(&parser->shader_desc);
|
|
vkd3d_free(sm6);
|
|
}
|
|
|
|
@@ -8080,15 +8161,16 @@ static struct sm6_function *sm6_parser_get_function(const struct sm6_parser *sm6
|
|
return NULL;
|
|
}
|
|
|
|
-static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t *byte_code, size_t byte_code_size,
|
|
- const char *source_name, struct vkd3d_shader_message_context *message_context)
|
|
+static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const char *source_name,
|
|
+ struct vkd3d_shader_message_context *message_context, struct dxbc_shader_desc *dxbc_desc)
|
|
{
|
|
- const struct shader_signature *output_signature = &sm6->p.shader_desc.output_signature;
|
|
- const struct shader_signature *input_signature = &sm6->p.shader_desc.input_signature;
|
|
+ const struct shader_signature *output_signature = &sm6->p.program.output_signature;
|
|
+ const struct shader_signature *input_signature = &sm6->p.program.input_signature;
|
|
+ size_t count, length, function_count, byte_code_size = dxbc_desc->byte_code_size;
|
|
const struct vkd3d_shader_location location = {.source_name = source_name};
|
|
uint32_t version_token, dxil_version, token_count, magic;
|
|
+ const uint32_t *byte_code = dxbc_desc->byte_code;
|
|
unsigned int chunk_offset, chunk_size;
|
|
- size_t count, length, function_count;
|
|
enum bitcode_block_abbreviation abbr;
|
|
struct vkd3d_shader_version version;
|
|
struct dxil_block *block;
|
|
@@ -8181,6 +8263,11 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t
|
|
sm6->ptr = &sm6->start[1];
|
|
sm6->bitpos = 2;
|
|
|
|
+ sm6->p.program.input_signature = dxbc_desc->input_signature;
|
|
+ sm6->p.program.output_signature = dxbc_desc->output_signature;
|
|
+ sm6->p.program.patch_constant_signature = dxbc_desc->patch_constant_signature;
|
|
+ memset(dxbc_desc, 0, sizeof(*dxbc_desc));
|
|
+
|
|
block = &sm6->root_block;
|
|
if ((ret = dxil_block_init(block, NULL, sm6)) < 0)
|
|
{
|
|
@@ -8351,7 +8438,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t
|
|
int vkd3d_shader_sm6_parser_create(const struct vkd3d_shader_compile_info *compile_info,
|
|
struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_parser **parser)
|
|
{
|
|
- struct vkd3d_shader_desc *shader_desc;
|
|
+ struct dxbc_shader_desc dxbc_desc = {0};
|
|
uint32_t *byte_code = NULL;
|
|
struct sm6_parser *sm6;
|
|
int ret;
|
|
@@ -8364,31 +8451,33 @@ int vkd3d_shader_sm6_parser_create(const struct vkd3d_shader_compile_info *compi
|
|
return VKD3D_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
- shader_desc = &sm6->p.shader_desc;
|
|
- shader_desc->is_dxil = true;
|
|
+ dxbc_desc.is_dxil = true;
|
|
if ((ret = shader_extract_from_dxbc(&compile_info->source, message_context, compile_info->source_name,
|
|
- shader_desc)) < 0)
|
|
+ &dxbc_desc)) < 0)
|
|
{
|
|
WARN("Failed to extract shader, vkd3d result %d.\n", ret);
|
|
vkd3d_free(sm6);
|
|
return ret;
|
|
}
|
|
|
|
- sm6->p.shader_desc = *shader_desc;
|
|
- shader_desc = &sm6->p.shader_desc;
|
|
-
|
|
- if (((uintptr_t)shader_desc->byte_code & (VKD3D_DXBC_CHUNK_ALIGNMENT - 1)))
|
|
+ if (((uintptr_t)dxbc_desc.byte_code & (VKD3D_DXBC_CHUNK_ALIGNMENT - 1)))
|
|
{
|
|
/* LLVM bitcode should be 32-bit aligned, but before dxc v1.7.2207 this was not always the case in the DXBC
|
|
* container due to missing padding after signature names. Get an aligned copy to prevent unaligned access. */
|
|
- if (!(byte_code = vkd3d_malloc(align(shader_desc->byte_code_size, VKD3D_DXBC_CHUNK_ALIGNMENT))))
|
|
- ERR("Failed to allocate aligned chunk. Unaligned access will occur.\n");
|
|
- else
|
|
- memcpy(byte_code, shader_desc->byte_code, shader_desc->byte_code_size);
|
|
+ if (!(byte_code = vkd3d_malloc(align(dxbc_desc.byte_code_size, VKD3D_DXBC_CHUNK_ALIGNMENT))))
|
|
+ {
|
|
+ ERR("Failed to allocate aligned chunk.\n");
|
|
+ free_dxbc_shader_desc(&dxbc_desc);
|
|
+ vkd3d_free(sm6);
|
|
+ return VKD3D_ERROR_OUT_OF_MEMORY;
|
|
+ }
|
|
+
|
|
+ memcpy(byte_code, dxbc_desc.byte_code, dxbc_desc.byte_code_size);
|
|
+ dxbc_desc.byte_code = byte_code;
|
|
}
|
|
|
|
- ret = sm6_parser_init(sm6, byte_code ? byte_code : shader_desc->byte_code, shader_desc->byte_code_size,
|
|
- compile_info->source_name, message_context);
|
|
+ ret = sm6_parser_init(sm6, compile_info->source_name, message_context, &dxbc_desc);
|
|
+ free_dxbc_shader_desc(&dxbc_desc);
|
|
vkd3d_free(byte_code);
|
|
|
|
if (!sm6->p.failed && ret >= 0)
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/fx.c b/libs/vkd3d/libs/vkd3d-shader/fx.c
|
|
index fd5c8443221..fdf132e9ed4 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/fx.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/fx.c
|
|
@@ -64,6 +64,7 @@ struct fx_write_context_ops
|
|
uint32_t (*write_type)(const struct hlsl_type *type, 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);
|
|
+ bool are_child_effects_supported;
|
|
};
|
|
|
|
struct fx_write_context
|
|
@@ -84,8 +85,12 @@ struct fx_write_context
|
|
uint32_t buffer_count;
|
|
uint32_t numeric_variable_count;
|
|
uint32_t object_variable_count;
|
|
+ uint32_t shared_object_count;
|
|
+ uint32_t shader_variable_count;
|
|
int status;
|
|
|
|
+ bool child_effect;
|
|
+
|
|
const struct fx_write_context_ops *ops;
|
|
};
|
|
|
|
@@ -174,6 +179,8 @@ static void fx_write_context_init(struct hlsl_ctx *ctx, const struct fx_write_co
|
|
|
|
rb_init(&fx->strings, string_storage_compare);
|
|
list_init(&fx->types);
|
|
+
|
|
+ fx->child_effect = fx->ops->are_child_effects_supported && ctx->child_effect;
|
|
}
|
|
|
|
static int fx_write_context_cleanup(struct fx_write_context *fx)
|
|
@@ -320,19 +327,14 @@ static uint32_t get_fx_4_numeric_type_description(const struct hlsl_type *type,
|
|
return value;
|
|
}
|
|
|
|
-static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_context *fx)
|
|
+static const char * get_fx_4_type_name(const struct hlsl_type *type)
|
|
{
|
|
- struct vkd3d_bytecode_buffer *buffer = &fx->unstructured;
|
|
- uint32_t name_offset, offset, size, stride, numeric_desc;
|
|
- uint32_t elements_count = 0;
|
|
- const char *name;
|
|
- static const uint32_t variable_type[] =
|
|
+ static const char * const object_type_names[] =
|
|
{
|
|
- [HLSL_CLASS_SCALAR] = 1,
|
|
- [HLSL_CLASS_VECTOR] = 1,
|
|
- [HLSL_CLASS_MATRIX] = 1,
|
|
- [HLSL_CLASS_OBJECT] = 2,
|
|
- [HLSL_CLASS_STRUCT] = 3,
|
|
+ [HLSL_TYPE_PIXELSHADER] = "PixelShader",
|
|
+ [HLSL_TYPE_VERTEXSHADER] = "VertexShader",
|
|
+ [HLSL_TYPE_RENDERTARGETVIEW] = "RenderTargetView",
|
|
+ [HLSL_TYPE_DEPTHSTENCILVIEW] = "DepthStencilView",
|
|
};
|
|
static const char * const texture_type_names[] =
|
|
{
|
|
@@ -357,6 +359,39 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co
|
|
[HLSL_SAMPLER_DIM_BUFFER] = "RWBuffer",
|
|
[HLSL_SAMPLER_DIM_STRUCTURED_BUFFER] = "RWStructuredBuffer",
|
|
};
|
|
+
|
|
+ if (type->base_type == HLSL_TYPE_TEXTURE)
|
|
+ return texture_type_names[type->sampler_dim];
|
|
+
|
|
+ if (type->base_type == HLSL_TYPE_UAV)
|
|
+ return uav_type_names[type->sampler_dim];
|
|
+
|
|
+ switch (type->base_type)
|
|
+ {
|
|
+ case HLSL_TYPE_PIXELSHADER:
|
|
+ case HLSL_TYPE_VERTEXSHADER:
|
|
+ case HLSL_TYPE_RENDERTARGETVIEW:
|
|
+ case HLSL_TYPE_DEPTHSTENCILVIEW:
|
|
+ return object_type_names[type->base_type];
|
|
+ default:
|
|
+ return type->name;
|
|
+ }
|
|
+}
|
|
+
|
|
+static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_context *fx)
|
|
+{
|
|
+ struct vkd3d_bytecode_buffer *buffer = &fx->unstructured;
|
|
+ uint32_t name_offset, offset, size, stride, numeric_desc;
|
|
+ uint32_t elements_count = 0;
|
|
+ const char *name;
|
|
+ static const uint32_t variable_type[] =
|
|
+ {
|
|
+ [HLSL_CLASS_SCALAR] = 1,
|
|
+ [HLSL_CLASS_VECTOR] = 1,
|
|
+ [HLSL_CLASS_MATRIX] = 1,
|
|
+ [HLSL_CLASS_OBJECT] = 2,
|
|
+ [HLSL_CLASS_STRUCT] = 3,
|
|
+ };
|
|
struct hlsl_ctx *ctx = fx->ctx;
|
|
|
|
/* Resolve arrays to element type and number of elements. */
|
|
@@ -366,12 +401,7 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co
|
|
type = hlsl_get_multiarray_element_type(type);
|
|
}
|
|
|
|
- if (type->base_type == HLSL_TYPE_TEXTURE)
|
|
- name = texture_type_names[type->sampler_dim];
|
|
- else if (type->base_type == HLSL_TYPE_UAV)
|
|
- name = uav_type_names[type->sampler_dim];
|
|
- else
|
|
- name = type->name;
|
|
+ name = get_fx_4_type_name(type);
|
|
|
|
name_offset = write_string(name, fx);
|
|
offset = put_u32_unaligned(buffer, name_offset);
|
|
@@ -424,6 +454,8 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co
|
|
{
|
|
static const uint32_t object_type[] =
|
|
{
|
|
+ [HLSL_TYPE_PIXELSHADER] = 5,
|
|
+ [HLSL_TYPE_VERTEXSHADER] = 6,
|
|
[HLSL_TYPE_RENDERTARGETVIEW] = 19,
|
|
[HLSL_TYPE_DEPTHSTENCILVIEW] = 20,
|
|
};
|
|
@@ -454,7 +486,9 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co
|
|
switch (type->base_type)
|
|
{
|
|
case HLSL_TYPE_DEPTHSTENCILVIEW:
|
|
+ case HLSL_TYPE_PIXELSHADER:
|
|
case HLSL_TYPE_RENDERTARGETVIEW:
|
|
+ case HLSL_TYPE_VERTEXSHADER:
|
|
put_u32_unaligned(buffer, object_type[type->base_type]);
|
|
break;
|
|
case HLSL_TYPE_TEXTURE:
|
|
@@ -661,6 +695,7 @@ static const struct fx_write_context_ops fx_4_ops =
|
|
.write_type = write_fx_4_type,
|
|
.write_technique = write_fx_4_technique,
|
|
.write_pass = write_fx_4_pass,
|
|
+ .are_child_effects_supported = true,
|
|
};
|
|
|
|
static void write_fx_4_numeric_variable(struct hlsl_ir_var *var, struct fx_write_context *fx)
|
|
@@ -695,9 +730,12 @@ static void write_fx_4_numeric_variable(struct hlsl_ir_var *var, struct fx_write
|
|
|
|
static void write_fx_4_object_variable(struct hlsl_ir_var *var, struct fx_write_context *fx)
|
|
{
|
|
+ const struct hlsl_type *type = hlsl_get_multiarray_element_type(var->data_type);
|
|
+ uint32_t elements_count = hlsl_get_multiarray_size(var->data_type);
|
|
struct vkd3d_bytecode_buffer *buffer = &fx->structured;
|
|
uint32_t semantic_offset, bind_point = ~0u;
|
|
- uint32_t name_offset, type_offset;
|
|
+ uint32_t name_offset, type_offset, i;
|
|
+ struct hlsl_ctx *ctx = fx->ctx;
|
|
|
|
if (var->reg_reservation.reg_type)
|
|
bind_point = var->reg_reservation.reg_index;
|
|
@@ -712,8 +750,35 @@ static void write_fx_4_object_variable(struct hlsl_ir_var *var, struct fx_write_
|
|
semantic_offset = put_u32(buffer, semantic_offset); /* Semantic */
|
|
put_u32(buffer, bind_point); /* Explicit bind point */
|
|
|
|
+ if (fx->child_effect && var->storage_modifiers & HLSL_STORAGE_SHARED)
|
|
+ {
|
|
+ ++fx->shared_object_count;
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ /* Initializer */
|
|
+ switch (type->base_type)
|
|
+ {
|
|
+ case HLSL_TYPE_TEXTURE:
|
|
+ case HLSL_TYPE_UAV:
|
|
+ case HLSL_TYPE_RENDERTARGETVIEW:
|
|
+ break;
|
|
+ case HLSL_TYPE_PIXELSHADER:
|
|
+ case HLSL_TYPE_VERTEXSHADER:
|
|
+ /* FIXME: write shader blobs, once parser support works. */
|
|
+ for (i = 0; i < elements_count; ++i)
|
|
+ put_u32(buffer, 0);
|
|
+ ++fx->shader_variable_count;
|
|
+ break;
|
|
+ default:
|
|
+ hlsl_fixme(ctx, &ctx->location, "Writing initializer for object type %u is not implemented.\n",
|
|
+ type->base_type);
|
|
+ }
|
|
+
|
|
put_u32(buffer, 0); /* Annotations count */
|
|
/* FIXME: write annotations */
|
|
+
|
|
+ ++fx->object_variable_count;
|
|
}
|
|
|
|
static void write_fx_4_buffer(struct hlsl_buffer *b, struct fx_write_context *fx)
|
|
@@ -734,7 +799,8 @@ static void write_fx_4_buffer(struct hlsl_buffer *b, struct fx_write_context *fx
|
|
bind_point = b->reservation.reg_index;
|
|
if (b->type == HLSL_BUFFER_TEXTURE)
|
|
flags |= IS_TBUFFER;
|
|
- /* FIXME: set 'single' flag for fx_5_0 */
|
|
+ if (ctx->profile->major_version == 5 && b->modifiers & HLSL_MODIFIER_SINGLE)
|
|
+ flags |= IS_SINGLE;
|
|
|
|
name_offset = write_string(b->name, fx);
|
|
|
|
@@ -806,21 +872,23 @@ static bool is_object_variable(const struct hlsl_ir_var *var)
|
|
}
|
|
}
|
|
|
|
-static void write_objects(struct fx_write_context *fx)
|
|
+static void write_objects(struct fx_write_context *fx, bool shared)
|
|
{
|
|
struct hlsl_ir_var *var;
|
|
- uint32_t count = 0;
|
|
+
|
|
+ if (shared && !fx->child_effect)
|
|
+ return;
|
|
|
|
LIST_FOR_EACH_ENTRY(var, &fx->ctx->extern_vars, struct hlsl_ir_var, extern_entry)
|
|
{
|
|
if (!is_object_variable(var))
|
|
continue;
|
|
|
|
+ if (fx->child_effect && (shared != !!(var->storage_modifiers & HLSL_STORAGE_SHARED)))
|
|
+ continue;
|
|
+
|
|
write_fx_4_object_variable(var, fx);
|
|
- ++count;
|
|
}
|
|
-
|
|
- fx->object_variable_count += count;
|
|
}
|
|
|
|
static int hlsl_fx_4_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out)
|
|
@@ -834,9 +902,9 @@ static int hlsl_fx_4_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out)
|
|
put_u32(&fx.unstructured, 0); /* Empty string placeholder. */
|
|
|
|
write_buffers(&fx);
|
|
- write_objects(&fx);
|
|
+ write_objects(&fx, false);
|
|
/* TODO: shared buffers */
|
|
- /* TODO: shared objects */
|
|
+ write_objects(&fx, true);
|
|
|
|
write_techniques(ctx->globals, &fx);
|
|
|
|
@@ -846,7 +914,7 @@ static int hlsl_fx_4_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out)
|
|
put_u32(&buffer, fx.object_variable_count); /* Object variable count. */
|
|
put_u32(&buffer, 0); /* Pool buffer count. */
|
|
put_u32(&buffer, 0); /* Pool variable count. */
|
|
- put_u32(&buffer, 0); /* Pool object count. */
|
|
+ put_u32(&buffer, fx.shared_object_count); /* Shared object count. */
|
|
put_u32(&buffer, fx.technique_count);
|
|
size_offset = put_u32(&buffer, 0); /* Unstructured size. */
|
|
put_u32(&buffer, 0); /* String count. */
|
|
@@ -857,7 +925,7 @@ static int hlsl_fx_4_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out)
|
|
put_u32(&buffer, 0); /* Sampler state count. */
|
|
put_u32(&buffer, 0); /* Rendertarget view count. */
|
|
put_u32(&buffer, 0); /* Depth stencil view count. */
|
|
- put_u32(&buffer, 0); /* Shader count. */
|
|
+ put_u32(&buffer, fx.shader_variable_count); /* Shader count. */
|
|
put_u32(&buffer, 0); /* Inline shader count. */
|
|
|
|
set_u32(&buffer, size_offset, fx.unstructured.size);
|
|
@@ -893,7 +961,7 @@ static int hlsl_fx_5_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out)
|
|
put_u32(&fx.unstructured, 0); /* Empty string placeholder. */
|
|
|
|
write_buffers(&fx);
|
|
- write_objects(&fx);
|
|
+ write_objects(&fx, false);
|
|
/* TODO: interface variables */
|
|
|
|
write_groups(&fx);
|
|
@@ -915,7 +983,7 @@ static int hlsl_fx_5_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out)
|
|
put_u32(&buffer, 0); /* Sampler state count. */
|
|
put_u32(&buffer, 0); /* Rendertarget view count. */
|
|
put_u32(&buffer, 0); /* Depth stencil view count. */
|
|
- put_u32(&buffer, 0); /* Shader count. */
|
|
+ put_u32(&buffer, fx.shader_variable_count); /* Shader count. */
|
|
put_u32(&buffer, 0); /* Inline shader count. */
|
|
put_u32(&buffer, fx.group_count); /* Group count. */
|
|
put_u32(&buffer, 0); /* UAV count. */
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/glsl.c b/libs/vkd3d/libs/vkd3d-shader/glsl.c
|
|
index c234caf8275..7c630d181ef 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/glsl.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/glsl.c
|
|
@@ -27,22 +27,6 @@ struct vkd3d_glsl_generator
|
|
bool failed;
|
|
};
|
|
|
|
-struct vkd3d_glsl_generator *vkd3d_glsl_generator_create(const struct vkd3d_shader_version *version,
|
|
- struct vkd3d_shader_message_context *message_context, const struct vkd3d_shader_location *location)
|
|
-{
|
|
- struct vkd3d_glsl_generator *generator;
|
|
-
|
|
- if (!(generator = vkd3d_malloc(sizeof(*generator))))
|
|
- return NULL;
|
|
-
|
|
- memset(generator, 0, sizeof(*generator));
|
|
- generator->version = *version;
|
|
- vkd3d_string_buffer_init(&generator->buffer);
|
|
- generator->location = *location;
|
|
- generator->message_context = message_context;
|
|
- return generator;
|
|
-}
|
|
-
|
|
static void VKD3D_PRINTF_FUNC(3, 4) vkd3d_glsl_compiler_error(
|
|
struct vkd3d_glsl_generator *generator,
|
|
enum vkd3d_shader_error error, const char *fmt, ...)
|
|
@@ -73,6 +57,8 @@ static void shader_glsl_ret(struct vkd3d_glsl_generator *generator,
|
|
static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *generator,
|
|
const struct vkd3d_shader_instruction *instruction)
|
|
{
|
|
+ generator->location = instruction->location;
|
|
+
|
|
switch (instruction->handler_idx)
|
|
{
|
|
case VKD3DSIH_DCL_INPUT:
|
|
@@ -90,7 +76,7 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *generator
|
|
}
|
|
}
|
|
|
|
-int vkd3d_glsl_generator_generate(struct vkd3d_glsl_generator *generator,
|
|
+static int vkd3d_glsl_generator_generate(struct vkd3d_glsl_generator *generator,
|
|
struct vsir_program *program, struct vkd3d_shader_code *out)
|
|
{
|
|
unsigned int i;
|
|
@@ -101,10 +87,8 @@ int vkd3d_glsl_generator_generate(struct vkd3d_glsl_generator *generator,
|
|
vkd3d_string_buffer_printf(&generator->buffer, "#version 440\n\n");
|
|
vkd3d_string_buffer_printf(&generator->buffer, "void main()\n{\n");
|
|
|
|
- generator->location.column = 0;
|
|
for (i = 0; i < program->instructions.count; ++i)
|
|
{
|
|
- generator->location.line = i + 1;
|
|
vkd3d_glsl_handle_instruction(generator, &program->instructions.elements[i]);
|
|
}
|
|
|
|
@@ -124,8 +108,29 @@ int vkd3d_glsl_generator_generate(struct vkd3d_glsl_generator *generator,
|
|
return VKD3D_OK;
|
|
}
|
|
|
|
-void vkd3d_glsl_generator_destroy(struct vkd3d_glsl_generator *generator)
|
|
+static void vkd3d_glsl_generator_cleanup(struct vkd3d_glsl_generator *gen)
|
|
+{
|
|
+ vkd3d_string_buffer_cleanup(&gen->buffer);
|
|
+}
|
|
+
|
|
+static void vkd3d_glsl_generator_init(struct vkd3d_glsl_generator *gen,
|
|
+ const struct vkd3d_shader_version *version, struct vkd3d_shader_message_context *message_context)
|
|
{
|
|
- vkd3d_string_buffer_cleanup(&generator->buffer);
|
|
- vkd3d_free(generator);
|
|
+ memset(gen, 0, sizeof(*gen));
|
|
+ gen->version = *version;
|
|
+ vkd3d_string_buffer_init(&gen->buffer);
|
|
+ gen->message_context = message_context;
|
|
+}
|
|
+
|
|
+int glsl_compile(struct vsir_program *program, struct vkd3d_shader_code *out,
|
|
+ struct vkd3d_shader_message_context *message_context)
|
|
+{
|
|
+ struct vkd3d_glsl_generator generator;
|
|
+ int ret;
|
|
+
|
|
+ vkd3d_glsl_generator_init(&generator, &program->shader_version, message_context);
|
|
+ ret = vkd3d_glsl_generator_generate(&generator, program, out);
|
|
+ vkd3d_glsl_generator_cleanup(&generator);
|
|
+
|
|
+ return ret;
|
|
}
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c
|
|
index c315000a6e9..2820b9abf67 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c
|
|
@@ -3597,6 +3597,10 @@ static bool hlsl_ctx_init(struct hlsl_ctx *ctx, const struct vkd3d_shader_compil
|
|
{
|
|
ctx->semantic_compat_mapping = option->value & VKD3D_SHADER_COMPILE_OPTION_BACKCOMPAT_MAP_SEMANTIC_NAMES;
|
|
}
|
|
+ else if (option->name == VKD3D_SHADER_COMPILE_OPTION_CHILD_EFFECT)
|
|
+ {
|
|
+ ctx->child_effect = !!option->value;
|
|
+ }
|
|
}
|
|
|
|
return true;
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h
|
|
index 49858869e7d..681f2edce31 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h
|
|
@@ -374,6 +374,7 @@ struct hlsl_attribute
|
|
#define HLSL_STORAGE_CENTROID 0x00004000
|
|
#define HLSL_STORAGE_NOPERSPECTIVE 0x00008000
|
|
#define HLSL_STORAGE_LINEAR 0x00010000
|
|
+#define HLSL_MODIFIER_SINGLE 0x00020000
|
|
|
|
#define HLSL_TYPE_MODIFIERS_MASK (HLSL_MODIFIER_PRECISE | HLSL_MODIFIER_VOLATILE | \
|
|
HLSL_MODIFIER_CONST | HLSL_MODIFIER_ROW_MAJOR | \
|
|
@@ -922,6 +923,7 @@ struct hlsl_ctx
|
|
uint32_t found_numthreads : 1;
|
|
|
|
bool semantic_compat_mapping;
|
|
+ bool child_effect;
|
|
};
|
|
|
|
struct hlsl_resource_load_params
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.l b/libs/vkd3d/libs/vkd3d-shader/hlsl.l
|
|
index 8dcceb94c1c..600e2cf2c6a 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.l
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.l
|
|
@@ -109,7 +109,6 @@ packoffset {return KW_PACKOFFSET; }
|
|
pass {return KW_PASS; }
|
|
PixelShader {return KW_PIXELSHADER; }
|
|
pixelshader {return KW_PIXELSHADER; }
|
|
-precise {return KW_PRECISE; }
|
|
RasterizerOrderedBuffer {return KW_RASTERIZERORDEREDBUFFER; }
|
|
RasterizerOrderedStructuredBuffer {return KW_RASTERIZERORDEREDSTRUCTUREDBUFFER; }
|
|
RasterizerOrderedTexture1D {return KW_RASTERIZERORDEREDTEXTURE1D; }
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y
|
|
index b484a952497..ec8b3d22af2 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y
|
|
@@ -5363,7 +5363,6 @@ static void validate_uav_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim dim,
|
|
%token KW_PACKOFFSET
|
|
%token KW_PASS
|
|
%token KW_PIXELSHADER
|
|
-%token KW_PRECISE
|
|
%token KW_RASTERIZERORDEREDBUFFER
|
|
%token KW_RASTERIZERORDEREDSTRUCTUREDBUFFER
|
|
%token KW_RASTERIZERORDEREDTEXTURE1D
|
|
@@ -6542,6 +6541,14 @@ type_no_void:
|
|
{
|
|
$$ = hlsl_get_type(ctx->cur_scope, "DepthStencilView", true, true);
|
|
}
|
|
+ | KW_VERTEXSHADER
|
|
+ {
|
|
+ $$ = hlsl_get_type(ctx->cur_scope, "VertexShader", true, true);
|
|
+ }
|
|
+ | KW_PIXELSHADER
|
|
+ {
|
|
+ $$ = hlsl_get_type(ctx->cur_scope, "PixelShader", true, true);
|
|
+ }
|
|
|
|
type:
|
|
type_no_void
|
|
@@ -6815,10 +6822,6 @@ var_modifiers:
|
|
{
|
|
$$ = add_modifiers(ctx, $2, HLSL_STORAGE_NOPERSPECTIVE, &@1);
|
|
}
|
|
- | KW_PRECISE var_modifiers
|
|
- {
|
|
- $$ = add_modifiers(ctx, $2, HLSL_MODIFIER_PRECISE, &@1);
|
|
- }
|
|
| KW_SHARED var_modifiers
|
|
{
|
|
$$ = add_modifiers(ctx, $2, HLSL_STORAGE_SHARED, &@1);
|
|
@@ -6867,7 +6870,16 @@ var_modifiers:
|
|
{
|
|
$$ = add_modifiers(ctx, $2, HLSL_MODIFIER_INLINE, &@1);
|
|
}
|
|
-
|
|
+ | var_identifier var_modifiers
|
|
+ {
|
|
+ if (!strcmp($1, "precise"))
|
|
+ $$ = add_modifiers(ctx, $2, HLSL_MODIFIER_PRECISE, &@1);
|
|
+ else if (!strcmp($1, "single"))
|
|
+ $$ = add_modifiers(ctx, $2, HLSL_MODIFIER_SINGLE, &@1);
|
|
+ else
|
|
+ hlsl_error(ctx, &@1, VKD3D_SHADER_ERROR_HLSL_UNKNOWN_MODIFIER,
|
|
+ "Unknown modifier %s.", debugstr_a($1));
|
|
+ }
|
|
|
|
complex_initializer:
|
|
initializer_expr
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c
|
|
index 8434a921a62..9eb65dc0170 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c
|
|
@@ -2948,7 +2948,7 @@ static bool lower_ternary(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, stru
|
|
}
|
|
else if (ctx->profile->major_version < 4 && ctx->profile->type == VKD3D_SHADER_TYPE_VERTEX)
|
|
{
|
|
- struct hlsl_ir_node *neg, *slt, *sum, *mul, *cond2;
|
|
+ struct hlsl_ir_node *neg, *slt, *sum, *cond2, *slt_cast, *mul;
|
|
|
|
/* Expression used here is "slt(<cond>) * (first - second) + second". */
|
|
|
|
@@ -2980,7 +2980,11 @@ static bool lower_ternary(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, stru
|
|
return false;
|
|
hlsl_block_add_instr(block, sum);
|
|
|
|
- if (!(mul = hlsl_new_binary_expr(ctx, HLSL_OP2_MUL, slt, sum)))
|
|
+ if (!(slt_cast = hlsl_new_cast(ctx, slt, sum->data_type, &instr->loc)))
|
|
+ return false;
|
|
+ hlsl_block_add_instr(block, slt_cast);
|
|
+
|
|
+ if (!(mul = hlsl_new_binary_expr(ctx, HLSL_OP2_MUL, slt_cast, sum)))
|
|
return false;
|
|
hlsl_block_add_instr(block, mul);
|
|
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c
|
|
index 3c862f33ef1..759c89957d6 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/ir.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c
|
|
@@ -32,6 +32,9 @@ void vsir_program_cleanup(struct vsir_program *program)
|
|
vkd3d_free((void *)program->block_names[i]);
|
|
vkd3d_free(program->block_names);
|
|
shader_instruction_array_destroy(&program->instructions);
|
|
+ shader_signature_cleanup(&program->input_signature);
|
|
+ shader_signature_cleanup(&program->output_signature);
|
|
+ shader_signature_cleanup(&program->patch_constant_signature);
|
|
}
|
|
|
|
static inline bool shader_register_is_phase_instance_id(const struct vkd3d_shader_register *reg)
|
|
@@ -230,7 +233,7 @@ static const struct vkd3d_shader_varying_map *find_varying_map(
|
|
static enum vkd3d_result remap_output_signature(struct vkd3d_shader_parser *parser,
|
|
const struct vkd3d_shader_compile_info *compile_info)
|
|
{
|
|
- struct shader_signature *signature = &parser->shader_desc.output_signature;
|
|
+ struct shader_signature *signature = &parser->program.output_signature;
|
|
const struct vkd3d_shader_varying_map_info *varying_map;
|
|
unsigned int i;
|
|
|
|
@@ -1394,9 +1397,9 @@ static enum vkd3d_result shader_normalise_io_registers(struct vkd3d_shader_parse
|
|
normaliser.phase = VKD3DSIH_INVALID;
|
|
normaliser.shader_type = program->shader_version.type;
|
|
normaliser.major = program->shader_version.major;
|
|
- normaliser.input_signature = &parser->shader_desc.input_signature;
|
|
- normaliser.output_signature = &parser->shader_desc.output_signature;
|
|
- normaliser.patch_constant_signature = &parser->shader_desc.patch_constant_signature;
|
|
+ normaliser.input_signature = &program->input_signature;
|
|
+ normaliser.output_signature = &program->output_signature;
|
|
+ normaliser.patch_constant_signature = &program->patch_constant_signature;
|
|
|
|
for (i = 0, has_control_point_phase = false; i < program->instructions.count; ++i)
|
|
{
|
|
@@ -1439,9 +1442,9 @@ static enum vkd3d_result shader_normalise_io_registers(struct vkd3d_shader_parse
|
|
}
|
|
}
|
|
|
|
- if (!shader_signature_merge(&parser->shader_desc.input_signature, normaliser.input_range_map, false)
|
|
- || !shader_signature_merge(&parser->shader_desc.output_signature, normaliser.output_range_map, false)
|
|
- || !shader_signature_merge(&parser->shader_desc.patch_constant_signature, normaliser.pc_range_map, true))
|
|
+ if (!shader_signature_merge(&program->input_signature, normaliser.input_range_map, false)
|
|
+ || !shader_signature_merge(&program->output_signature, normaliser.output_range_map, false)
|
|
+ || !shader_signature_merge(&program->patch_constant_signature, normaliser.pc_range_map, true))
|
|
{
|
|
program->instructions = normaliser.instructions;
|
|
return VKD3D_ERROR_OUT_OF_MEMORY;
|
|
@@ -3065,7 +3068,7 @@ static void vsir_block_list_remove_index(struct vsir_block_list *list, size_t id
|
|
|
|
struct vsir_block
|
|
{
|
|
- unsigned int label;
|
|
+ unsigned int label, order_pos;
|
|
/* `begin' points to the instruction immediately following the
|
|
* LABEL that introduces the block. `end' points to the terminator
|
|
* instruction (either BRANCH or RET). They can coincide, meaning
|
|
@@ -3140,6 +3143,37 @@ struct vsir_cfg
|
|
size_t *loops_by_header;
|
|
|
|
struct vsir_block_list order;
|
|
+ struct cfg_loop_interval
|
|
+ {
|
|
+ /* `begin' is the position of the first block of the loop in
|
|
+ * the topological sort; `end' is the position of the first
|
|
+ * block after the loop. In other words, `begin' is where a
|
|
+ * `continue' instruction would jump and `end' is where a
|
|
+ * `break' instruction would jump. */
|
|
+ unsigned int begin, end;
|
|
+ /* Each loop interval can be natural or synthetic. Natural
|
|
+ * intervals are added to represent loops given by CFG back
|
|
+ * edges. Synthetic intervals do not correspond to loops in
|
|
+ * the input CFG, but are added to leverage their `break'
|
|
+ * instruction in order to execute forward edges.
|
|
+ *
|
|
+ * For a synthetic loop interval it's not really important
|
|
+ * which one is the `begin' block, since we don't need to
|
|
+ * execute `continue' for them. So we have some leeway for
|
|
+ * moving it provided that these conditions are met: 1. the
|
|
+ * interval must contain all `break' instructions that target
|
|
+ * it, which in practice means that `begin' can be moved
|
|
+ * backward and not forward; 2. intervals must remain properly
|
|
+ * nested (for each pair of intervals, either one contains the
|
|
+ * other or they are disjoint).
|
|
+ *
|
|
+ * Subject to these conditions, we try to reuse the same loop
|
|
+ * as much as possible (if many forward edges target the same
|
|
+ * block), but we still try to keep `begin' as forward as
|
|
+ * possible, to keep the loop scope as small as possible. */
|
|
+ bool synthetic;
|
|
+ } *loop_intervals;
|
|
+ size_t loop_interval_count, loop_interval_capacity;
|
|
};
|
|
|
|
static void vsir_cfg_cleanup(struct vsir_cfg *cfg)
|
|
@@ -3157,11 +3191,30 @@ static void vsir_cfg_cleanup(struct vsir_cfg *cfg)
|
|
vkd3d_free(cfg->blocks);
|
|
vkd3d_free(cfg->loops);
|
|
vkd3d_free(cfg->loops_by_header);
|
|
+ vkd3d_free(cfg->loop_intervals);
|
|
|
|
if (TRACE_ON())
|
|
vkd3d_string_buffer_cleanup(&cfg->debug_buffer);
|
|
}
|
|
|
|
+static enum vkd3d_result vsir_cfg_add_loop_interval(struct vsir_cfg *cfg, unsigned int begin,
|
|
+ unsigned int end, bool synthetic)
|
|
+{
|
|
+ struct cfg_loop_interval *interval;
|
|
+
|
|
+ if (!vkd3d_array_reserve((void **)&cfg->loop_intervals, &cfg->loop_interval_capacity,
|
|
+ cfg->loop_interval_count + 1, sizeof(*cfg->loop_intervals)))
|
|
+ return VKD3D_ERROR_OUT_OF_MEMORY;
|
|
+
|
|
+ interval = &cfg->loop_intervals[cfg->loop_interval_count++];
|
|
+
|
|
+ interval->begin = begin;
|
|
+ interval->end = end;
|
|
+ interval->synthetic = synthetic;
|
|
+
|
|
+ return VKD3D_OK;
|
|
+}
|
|
+
|
|
static bool vsir_block_dominates(struct vsir_block *b1, struct vsir_block *b2)
|
|
{
|
|
return bitmap_is_set(b1->dominates, b2->label - 1);
|
|
@@ -3396,14 +3449,14 @@ static void vsir_cfg_compute_dominators(struct vsir_cfg *cfg)
|
|
* block without passing through the header block) belong to the same
|
|
* loop.
|
|
*
|
|
- * If the input CFG is reducible, each two loops are either disjoint
|
|
- * or one is a strict subset of the other, provided that each block
|
|
- * has at most one incoming back edge. If this condition does not
|
|
- * hold, a synthetic block can be introduced as the only back edge
|
|
- * block for the given header block, with all the previous back edge
|
|
- * now being forward edges to the synthetic block. This is not
|
|
- * currently implemented (but it is rarely found in practice
|
|
- * anyway). */
|
|
+ * If the input CFG is reducible its loops are properly nested (i.e.,
|
|
+ * each two loops are either disjoint or one is contained in the
|
|
+ * other), provided that each block has at most one incoming back
|
|
+ * edge. If this condition does not hold, a synthetic block can be
|
|
+ * introduced as the only back edge block for the given header block,
|
|
+ * with all the previous back edge now being forward edges to the
|
|
+ * synthetic block. This is not currently implemented (but it is
|
|
+ * rarely found in practice anyway). */
|
|
static enum vkd3d_result vsir_cfg_scan_loop(struct vsir_block_list *loop, struct vsir_block *block,
|
|
struct vsir_block *header)
|
|
{
|
|
@@ -3496,6 +3549,7 @@ struct vsir_cfg_node_sorter
|
|
{
|
|
struct vsir_block_list *loop;
|
|
unsigned int seen_count;
|
|
+ unsigned int begin;
|
|
} *stack;
|
|
size_t stack_count, stack_capacity;
|
|
struct vsir_block_list available_blocks;
|
|
@@ -3522,6 +3576,7 @@ static enum vkd3d_result vsir_cfg_node_sorter_make_node_available(struct vsir_cf
|
|
item = &sorter->stack[sorter->stack_count++];
|
|
item->loop = loop;
|
|
item->seen_count = 0;
|
|
+ item->begin = sorter->cfg->order.count;
|
|
|
|
return VKD3D_OK;
|
|
}
|
|
@@ -3628,6 +3683,7 @@ static enum vkd3d_result vsir_cfg_sort_nodes(struct vsir_cfg *cfg)
|
|
}
|
|
|
|
vsir_block_list_remove_index(&sorter.available_blocks, i);
|
|
+ block->order_pos = cfg->order.count;
|
|
if ((ret = vsir_block_list_add_checked(&cfg->order, block)) < 0)
|
|
goto fail;
|
|
|
|
@@ -3646,6 +3702,10 @@ static enum vkd3d_result vsir_cfg_sort_nodes(struct vsir_cfg *cfg)
|
|
if (inner_stack_item->seen_count != inner_stack_item->loop->count)
|
|
break;
|
|
|
|
+ if ((ret = vsir_cfg_add_loop_interval(cfg, inner_stack_item->begin,
|
|
+ cfg->order.count, false)) < 0)
|
|
+ goto fail;
|
|
+
|
|
new_seen_count = inner_stack_item->loop->count;
|
|
--sorter.stack_count;
|
|
}
|
|
@@ -3706,6 +3766,143 @@ fail:
|
|
return ret;
|
|
}
|
|
|
|
+/* Sort loop intervals first by ascending begin time and then by
|
|
+ * descending end time, so that inner intervals appear after outer
|
|
+ * ones and disjoint intervals appear in their proper order. */
|
|
+static int compare_loop_intervals(const void *ptr1, const void *ptr2)
|
|
+{
|
|
+ const struct cfg_loop_interval *interval1 = ptr1;
|
|
+ const struct cfg_loop_interval *interval2 = ptr2;
|
|
+
|
|
+ if (interval1->begin != interval2->begin)
|
|
+ return vkd3d_u32_compare(interval1->begin, interval2->begin);
|
|
+
|
|
+ return -vkd3d_u32_compare(interval1->end, interval2->end);
|
|
+}
|
|
+
|
|
+static enum vkd3d_result vsir_cfg_generate_synthetic_loop_intervals(struct vsir_cfg *cfg)
|
|
+{
|
|
+ enum vkd3d_result ret;
|
|
+ size_t i, j, k;
|
|
+
|
|
+ for (i = 0; i < cfg->block_count; ++i)
|
|
+ {
|
|
+ struct vsir_block *block = &cfg->blocks[i];
|
|
+
|
|
+ if (block->label == 0)
|
|
+ continue;
|
|
+
|
|
+ for (j = 0; j < block->successors.count; ++j)
|
|
+ {
|
|
+ struct vsir_block *successor = block->successors.blocks[j];
|
|
+ struct cfg_loop_interval *extend = NULL;
|
|
+ unsigned int begin;
|
|
+ enum
|
|
+ {
|
|
+ ACTION_DO_NOTHING,
|
|
+ ACTION_CREATE_NEW,
|
|
+ ACTION_EXTEND,
|
|
+ } action = ACTION_CREATE_NEW;
|
|
+
|
|
+ /* We've already contructed loop intervals for the back
|
|
+ * edges, there's nothing more to do. */
|
|
+ if (vsir_block_dominates(successor, block))
|
|
+ continue;
|
|
+
|
|
+ assert(block->order_pos < successor->order_pos);
|
|
+
|
|
+ /* Jumping from a block to the following one is always
|
|
+ * possible, so nothing to do. */
|
|
+ if (block->order_pos + 1 == successor->order_pos)
|
|
+ continue;
|
|
+
|
|
+ /* Let's look for a loop interval that already breaks at
|
|
+ * `successor' and either contains or can be extended to
|
|
+ * contain `block'. */
|
|
+ for (k = 0; k < cfg->loop_interval_count; ++k)
|
|
+ {
|
|
+ struct cfg_loop_interval *interval = &cfg->loop_intervals[k];
|
|
+
|
|
+ if (interval->end != successor->order_pos)
|
|
+ continue;
|
|
+
|
|
+ if (interval->begin <= block->order_pos)
|
|
+ {
|
|
+ action = ACTION_DO_NOTHING;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (interval->synthetic)
|
|
+ {
|
|
+ action = ACTION_EXTEND;
|
|
+ extend = interval;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (action == ACTION_DO_NOTHING)
|
|
+ continue;
|
|
+
|
|
+ /* Ok, we have to decide where the new or replacing
|
|
+ * interval has to begin. These are the rules: 1. it must
|
|
+ * begin before `block'; 2. intervals must be properly
|
|
+ * nested; 3. the new interval should begin as late as
|
|
+ * possible, to limit control flow depth and extension. */
|
|
+ begin = block->order_pos;
|
|
+
|
|
+ /* Our candidate interval is always [begin,
|
|
+ * successor->order_pos), and we move `begin' backward
|
|
+ * until the candidate interval contains all the intervals
|
|
+ * whose endpoint lies in the candidate interval
|
|
+ * itself. */
|
|
+ for (k = 0; k < cfg->loop_interval_count; ++k)
|
|
+ {
|
|
+ struct cfg_loop_interval *interval = &cfg->loop_intervals[k];
|
|
+
|
|
+ if (begin < interval->end && interval->end < successor->order_pos)
|
|
+ begin = min(begin, interval->begin);
|
|
+ }
|
|
+
|
|
+ /* New we have to care about the intervals whose begin
|
|
+ * point lies in the candidate interval. We cannot move
|
|
+ * the candidate interval endpoint, because it is
|
|
+ * important that the loop break target matches
|
|
+ * `successor'. So we have to move that interval's begin
|
|
+ * point to the begin point of the candidate interval,
|
|
+ * i.e. `begin'. But what if the interval we should extend
|
|
+ * backward is not synthetic? This cannot happen,
|
|
+ * fortunately, because it would mean that there is a jump
|
|
+ * entering a loop via a block which is not the loop
|
|
+ * header, so the CFG would not be reducible. */
|
|
+ for (k = 0; k < cfg->loop_interval_count; ++k)
|
|
+ {
|
|
+ struct cfg_loop_interval *interval = &cfg->loop_intervals[k];
|
|
+
|
|
+ if (interval->begin < successor->order_pos && successor->order_pos < interval->end)
|
|
+ {
|
|
+ if (interval->synthetic)
|
|
+ interval->begin = min(begin, interval->begin);
|
|
+ assert(begin >= interval->begin);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (action == ACTION_EXTEND)
|
|
+ extend->begin = begin;
|
|
+ else if ((ret = vsir_cfg_add_loop_interval(cfg, begin, successor->order_pos, true)) < 0)
|
|
+ return ret;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ qsort(cfg->loop_intervals, cfg->loop_interval_count, sizeof(*cfg->loop_intervals), compare_loop_intervals);
|
|
+
|
|
+ if (TRACE_ON())
|
|
+ for (i = 0; i < cfg->loop_interval_count; ++i)
|
|
+ TRACE("%s loop interval %u - %u\n", cfg->loop_intervals[i].synthetic ? "Synthetic" : "Natural",
|
|
+ cfg->loop_intervals[i].begin, cfg->loop_intervals[i].end);
|
|
+
|
|
+ return VKD3D_OK;
|
|
+}
|
|
+
|
|
enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser,
|
|
const struct vkd3d_shader_compile_info *compile_info)
|
|
{
|
|
@@ -3717,7 +3914,7 @@ enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser,
|
|
if ((result = instruction_array_lower_texkills(parser)) < 0)
|
|
return result;
|
|
|
|
- if (parser->shader_desc.is_dxil)
|
|
+ if (parser->program.shader_version.major >= 6)
|
|
{
|
|
struct vsir_cfg cfg;
|
|
|
|
@@ -3744,6 +3941,12 @@ enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser,
|
|
return result;
|
|
}
|
|
|
|
+ if ((result = vsir_cfg_generate_synthetic_loop_intervals(&cfg)) < 0)
|
|
+ {
|
|
+ vsir_cfg_cleanup(&cfg);
|
|
+ return result;
|
|
+ }
|
|
+
|
|
if ((result = simple_structurizer_run(parser)) < 0)
|
|
{
|
|
vsir_cfg_cleanup(&cfg);
|
|
@@ -3766,7 +3969,7 @@ enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser,
|
|
return result;
|
|
|
|
if ((result = instruction_array_normalise_hull_shader_control_point_io(instructions,
|
|
- &parser->shader_desc.input_signature)) < 0)
|
|
+ &parser->program.input_signature)) < 0)
|
|
return result;
|
|
}
|
|
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c
|
|
index 5856f2f04ba..0568407f997 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/spirv.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c
|
|
@@ -223,6 +223,11 @@ enum vkd3d_shader_input_sysval_semantic vkd3d_siv_from_sysval_indexed(enum vkd3d
|
|
}
|
|
}
|
|
|
|
+static bool data_type_is_floating_point(enum vkd3d_data_type data_type)
|
|
+{
|
|
+ return data_type == VKD3D_DATA_HALF || data_type == VKD3D_DATA_FLOAT || data_type == VKD3D_DATA_DOUBLE;
|
|
+}
|
|
+
|
|
#define VKD3D_SPIRV_VERSION 0x00010000
|
|
#define VKD3D_SPIRV_GENERATOR_ID 18
|
|
#define VKD3D_SPIRV_GENERATOR_VERSION 11
|
|
@@ -1838,6 +1843,7 @@ static uint32_t vkd3d_spirv_get_type_id_for_data_type(struct vkd3d_spirv_builder
|
|
{
|
|
switch (data_type)
|
|
{
|
|
+ case VKD3D_DATA_HALF: /* Minimum precision. TODO: native 16-bit */
|
|
case VKD3D_DATA_FLOAT:
|
|
case VKD3D_DATA_SNORM:
|
|
case VKD3D_DATA_UNORM:
|
|
@@ -1845,6 +1851,7 @@ static uint32_t vkd3d_spirv_get_type_id_for_data_type(struct vkd3d_spirv_builder
|
|
break;
|
|
case VKD3D_DATA_INT:
|
|
case VKD3D_DATA_UINT:
|
|
+ case VKD3D_DATA_UINT16: /* Minimum precision. TODO: native 16-bit */
|
|
return vkd3d_spirv_get_op_type_int(builder, 32, data_type == VKD3D_DATA_INT);
|
|
break;
|
|
case VKD3D_DATA_DOUBLE:
|
|
@@ -2444,14 +2451,14 @@ static void spirv_compiler_destroy(struct spirv_compiler *compiler)
|
|
vkd3d_free(compiler);
|
|
}
|
|
|
|
-static struct spirv_compiler *spirv_compiler_create(const struct vkd3d_shader_version *shader_version,
|
|
- struct vkd3d_shader_desc *shader_desc, const struct vkd3d_shader_compile_info *compile_info,
|
|
+static struct spirv_compiler *spirv_compiler_create(const struct vsir_program *program,
|
|
+ const struct vkd3d_shader_compile_info *compile_info,
|
|
const struct vkd3d_shader_scan_descriptor_info1 *scan_descriptor_info,
|
|
struct vkd3d_shader_message_context *message_context, const struct vkd3d_shader_location *location,
|
|
uint64_t config_flags)
|
|
{
|
|
- const struct shader_signature *patch_constant_signature = &shader_desc->patch_constant_signature;
|
|
- const struct shader_signature *output_signature = &shader_desc->output_signature;
|
|
+ const struct shader_signature *patch_constant_signature = &program->patch_constant_signature;
|
|
+ const struct shader_signature *output_signature = &program->output_signature;
|
|
const struct vkd3d_shader_interface_info *shader_interface;
|
|
const struct vkd3d_shader_descriptor_offset_info *offset_info;
|
|
const struct vkd3d_shader_spirv_target_info *target_info;
|
|
@@ -2562,7 +2569,7 @@ static struct spirv_compiler *spirv_compiler_create(const struct vkd3d_shader_ve
|
|
|
|
rb_init(&compiler->symbol_table, vkd3d_symbol_compare);
|
|
|
|
- compiler->shader_type = shader_version->type;
|
|
+ compiler->shader_type = program->shader_version.type;
|
|
|
|
if ((shader_interface = vkd3d_find_struct(compile_info->next, INTERFACE_INFO)))
|
|
{
|
|
@@ -3753,6 +3760,70 @@ static uint32_t spirv_compiler_emit_bool_to_double(struct spirv_compiler *compil
|
|
return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id);
|
|
}
|
|
|
|
+/* Based on the implementation in the OpenGL Mathematics library. */
|
|
+static uint32_t half_to_float(uint16_t value)
|
|
+{
|
|
+ uint32_t s = (value & 0x8000u) << 16;
|
|
+ uint32_t e = (value >> 10) & 0x1fu;
|
|
+ uint32_t m = value & 0x3ffu;
|
|
+
|
|
+ if (!e)
|
|
+ {
|
|
+ if (!m)
|
|
+ {
|
|
+ /* Plus or minus zero */
|
|
+ return s;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ /* Denormalized number -- renormalize it */
|
|
+
|
|
+ while (!(m & 0x400u))
|
|
+ {
|
|
+ m <<= 1;
|
|
+ --e;
|
|
+ }
|
|
+
|
|
+ ++e;
|
|
+ m &= ~0x400u;
|
|
+ }
|
|
+ }
|
|
+ else if (e == 31u)
|
|
+ {
|
|
+ /* Positive or negative infinity for zero 'm'.
|
|
+ * Nan for non-zero 'm' -- preserve sign and significand bits */
|
|
+ return s | 0x7f800000u | (m << 13);
|
|
+ }
|
|
+
|
|
+ /* Normalized number */
|
|
+ e += 127u - 15u;
|
|
+ m <<= 13;
|
|
+
|
|
+ /* Assemble s, e and m. */
|
|
+ return s | (e << 23) | m;
|
|
+}
|
|
+
|
|
+static uint32_t convert_raw_constant32(enum vkd3d_data_type data_type, unsigned int uint_value)
|
|
+{
|
|
+ int16_t i;
|
|
+
|
|
+ /* TODO: native 16-bit support. */
|
|
+ if (data_type != VKD3D_DATA_UINT16 && data_type != VKD3D_DATA_HALF)
|
|
+ return uint_value;
|
|
+
|
|
+ if (data_type == VKD3D_DATA_HALF)
|
|
+ return half_to_float(uint_value);
|
|
+
|
|
+ /* Values in DXIL have no signedness, so it is ambiguous whether 16-bit constants should or
|
|
+ * should not be sign-extended when 16-bit execution is not supported. The AMD RX 580 Windows
|
|
+ * driver has no 16-bit support, and sign-extends all 16-bit constant ints to 32 bits. These
|
|
+ * results differ from SM 5. The RX 6750 XT supports 16-bit execution, so constants are not
|
|
+ * extended, and results match SM 5. It seems best to replicate the sign-extension, and if
|
|
+ * execution is 16-bit, the values will be truncated. */
|
|
+ i = uint_value;
|
|
+ return (int32_t)i;
|
|
+}
|
|
+
|
|
static uint32_t spirv_compiler_emit_load_constant(struct spirv_compiler *compiler,
|
|
const struct vkd3d_shader_register *reg, uint32_t swizzle, uint32_t write_mask)
|
|
{
|
|
@@ -3765,14 +3836,15 @@ static uint32_t spirv_compiler_emit_load_constant(struct spirv_compiler *compile
|
|
if (reg->dimension == VSIR_DIMENSION_SCALAR)
|
|
{
|
|
for (i = 0; i < component_count; ++i)
|
|
- values[i] = *reg->u.immconst_u32;
|
|
+ values[i] = convert_raw_constant32(reg->data_type, reg->u.immconst_u32[0]);
|
|
}
|
|
else
|
|
{
|
|
for (i = 0, j = 0; i < VKD3D_VEC4_SIZE; ++i)
|
|
{
|
|
if (write_mask & (VKD3DSP_WRITEMASK_0 << i))
|
|
- values[j++] = reg->u.immconst_u32[vsir_swizzle_get_component(swizzle, i)];
|
|
+ values[j++] = convert_raw_constant32(reg->data_type,
|
|
+ reg->u.immconst_u32[vsir_swizzle_get_component(swizzle, i)]);
|
|
}
|
|
}
|
|
|
|
@@ -3916,6 +3988,13 @@ static uint32_t spirv_compiler_emit_constant_array(struct spirv_compiler *compil
|
|
|
|
switch (icb->data_type)
|
|
{
|
|
+ case VKD3D_DATA_HALF:
|
|
+ case VKD3D_DATA_UINT16:
|
|
+ /* Scalar only. */
|
|
+ for (i = 0; i < element_count; ++i)
|
|
+ elements[i] = vkd3d_spirv_get_op_constant(builder, elem_type_id,
|
|
+ convert_raw_constant32(icb->data_type, icb->data[i]));
|
|
+ break;
|
|
case VKD3D_DATA_FLOAT:
|
|
case VKD3D_DATA_INT:
|
|
case VKD3D_DATA_UINT:
|
|
@@ -4104,7 +4183,7 @@ static uint32_t spirv_compiler_emit_abs(struct spirv_compiler *compiler,
|
|
uint32_t type_id;
|
|
|
|
type_id = spirv_compiler_get_type_id_for_reg(compiler, reg, write_mask);
|
|
- if (reg->data_type == VKD3D_DATA_FLOAT || reg->data_type == VKD3D_DATA_DOUBLE)
|
|
+ if (data_type_is_floating_point(reg->data_type))
|
|
return vkd3d_spirv_build_op_glsl_std450_fabs(builder, type_id, val_id);
|
|
|
|
FIXME("Unhandled data type %#x.\n", reg->data_type);
|
|
@@ -4118,7 +4197,7 @@ static uint32_t spirv_compiler_emit_neg(struct spirv_compiler *compiler,
|
|
uint32_t type_id;
|
|
|
|
type_id = spirv_compiler_get_type_id_for_reg(compiler, reg, write_mask);
|
|
- if (reg->data_type == VKD3D_DATA_FLOAT || reg->data_type == VKD3D_DATA_DOUBLE)
|
|
+ if (data_type_is_floating_point(reg->data_type))
|
|
return vkd3d_spirv_build_op_fnegate(builder, type_id, val_id);
|
|
else if (data_type_is_integer(reg->data_type))
|
|
return vkd3d_spirv_build_op_snegate(builder, type_id, val_id);
|
|
@@ -4302,7 +4381,7 @@ static uint32_t spirv_compiler_emit_sat(struct spirv_compiler *compiler,
|
|
}
|
|
|
|
type_id = spirv_compiler_get_type_id_for_reg(compiler, reg, write_mask);
|
|
- if (reg->data_type == VKD3D_DATA_FLOAT || reg->data_type == VKD3D_DATA_DOUBLE)
|
|
+ if (data_type_is_floating_point(reg->data_type))
|
|
return vkd3d_spirv_build_op_glsl_std450_nclamp(builder, type_id, val_id, zero_id, one_id);
|
|
|
|
FIXME("Unhandled data type %#x.\n", reg->data_type);
|
|
@@ -6903,7 +6982,7 @@ static void spirv_compiler_emit_bool_cast(struct spirv_compiler *compiler,
|
|
assert(src->reg.data_type == VKD3D_DATA_BOOL && dst->reg.data_type != VKD3D_DATA_BOOL);
|
|
|
|
val_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask);
|
|
- if (dst->reg.data_type == VKD3D_DATA_FLOAT)
|
|
+ if (dst->reg.data_type == VKD3D_DATA_HALF || dst->reg.data_type == VKD3D_DATA_FLOAT)
|
|
{
|
|
val_id = spirv_compiler_emit_bool_to_float(compiler, 1, val_id, instruction->handler_idx == VKD3DSIH_ITOF);
|
|
}
|
|
@@ -6912,7 +6991,7 @@ static void spirv_compiler_emit_bool_cast(struct spirv_compiler *compiler,
|
|
/* ITOD is not supported. Frontends which emit bool casts must use ITOF for double. */
|
|
val_id = spirv_compiler_emit_bool_to_double(compiler, 1, val_id, instruction->handler_idx == VKD3DSIH_ITOF);
|
|
}
|
|
- else if (dst->reg.data_type == VKD3D_DATA_UINT)
|
|
+ else if (dst->reg.data_type == VKD3D_DATA_UINT16 || dst->reg.data_type == VKD3D_DATA_UINT)
|
|
{
|
|
val_id = spirv_compiler_emit_bool_to_int(compiler, 1, val_id, instruction->handler_idx == VKD3DSIH_ITOI);
|
|
}
|
|
@@ -7205,8 +7284,15 @@ static void spirv_compiler_emit_movc(struct spirv_compiler *compiler,
|
|
type_id = spirv_compiler_get_type_id_for_dst(compiler, dst);
|
|
|
|
if (src[0].reg.data_type != VKD3D_DATA_BOOL)
|
|
- condition_id = spirv_compiler_emit_int_to_bool(compiler,
|
|
- VKD3D_SHADER_CONDITIONAL_OP_NZ, src[0].reg.data_type, component_count, condition_id);
|
|
+ {
|
|
+ if (instruction->handler_idx == VKD3DSIH_CMP)
|
|
+ condition_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, SpvOpFOrdGreaterThanEqual,
|
|
+ vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_BOOL, component_count), condition_id,
|
|
+ spirv_compiler_get_constant_float_vector(compiler, 0.0f, component_count));
|
|
+ else
|
|
+ condition_id = spirv_compiler_emit_int_to_bool(compiler,
|
|
+ VKD3D_SHADER_CONDITIONAL_OP_NZ, src[0].reg.data_type, component_count, condition_id);
|
|
+ }
|
|
val_id = vkd3d_spirv_build_op_select(builder, type_id, condition_id, src1_id, src2_id);
|
|
|
|
spirv_compiler_emit_store_dst(compiler, dst, val_id);
|
|
@@ -7738,6 +7824,36 @@ static void spirv_compiler_emit_orderedness_instruction(struct spirv_compiler *c
|
|
spirv_compiler_emit_store_dst(compiler, dst, val_id);
|
|
}
|
|
|
|
+static void spirv_compiler_emit_float_comparison_instruction(struct spirv_compiler *compiler,
|
|
+ const struct vkd3d_shader_instruction *instruction)
|
|
+{
|
|
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
|
|
+ const struct vkd3d_shader_dst_param *dst = instruction->dst;
|
|
+ const struct vkd3d_shader_src_param *src = instruction->src;
|
|
+ uint32_t src0_id, src1_id, type_id, result_id;
|
|
+ unsigned int component_count;
|
|
+ SpvOp op;
|
|
+
|
|
+ switch (instruction->handler_idx)
|
|
+ {
|
|
+ case VKD3DSIH_SLT: op = SpvOpFOrdLessThan; break;
|
|
+ case VKD3DSIH_SGE: op = SpvOpFOrdGreaterThanEqual; break;
|
|
+ default:
|
|
+ vkd3d_unreachable();
|
|
+ }
|
|
+
|
|
+ component_count = vsir_write_mask_component_count(dst->write_mask);
|
|
+
|
|
+ src0_id = spirv_compiler_emit_load_src(compiler, &src[0], dst->write_mask);
|
|
+ src1_id = spirv_compiler_emit_load_src(compiler, &src[1], dst->write_mask);
|
|
+
|
|
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_BOOL, component_count);
|
|
+ result_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, op, type_id, src0_id, src1_id);
|
|
+
|
|
+ result_id = spirv_compiler_emit_bool_to_float(compiler, component_count, result_id, false);
|
|
+ spirv_compiler_emit_store_reg(compiler, &dst->reg, dst->write_mask, result_id);
|
|
+}
|
|
+
|
|
static uint32_t spirv_compiler_emit_conditional_branch(struct spirv_compiler *compiler,
|
|
const struct vkd3d_shader_instruction *instruction, uint32_t target_block_id)
|
|
{
|
|
@@ -9628,6 +9744,7 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler,
|
|
break;
|
|
case VKD3DSIH_DMOVC:
|
|
case VKD3DSIH_MOVC:
|
|
+ case VKD3DSIH_CMP:
|
|
spirv_compiler_emit_movc(compiler, instruction);
|
|
break;
|
|
case VKD3DSIH_SWAPC:
|
|
@@ -9752,6 +9869,10 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler,
|
|
case VKD3DSIH_UNO:
|
|
spirv_compiler_emit_orderedness_instruction(compiler, instruction);
|
|
break;
|
|
+ case VKD3DSIH_SLT:
|
|
+ case VKD3DSIH_SGE:
|
|
+ spirv_compiler_emit_float_comparison_instruction(compiler, instruction);
|
|
+ break;
|
|
case VKD3DSIH_BFI:
|
|
case VKD3DSIH_IBFE:
|
|
case VKD3DSIH_UBFE:
|
|
@@ -9982,7 +10103,6 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler,
|
|
const struct vkd3d_shader_spirv_target_info *info = compiler->spirv_target_info;
|
|
const struct vkd3d_shader_spirv_domain_shader_target_info *ds_info;
|
|
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
|
|
- struct vkd3d_shader_desc *shader_desc = &parser->shader_desc;
|
|
struct vkd3d_shader_instruction_array instructions;
|
|
struct vsir_program *program = &parser->program;
|
|
enum vkd3d_result result = VKD3D_OK;
|
|
@@ -10007,12 +10127,12 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler,
|
|
instructions = program->instructions;
|
|
memset(&program->instructions, 0, sizeof(program->instructions));
|
|
|
|
- compiler->input_signature = shader_desc->input_signature;
|
|
- compiler->output_signature = shader_desc->output_signature;
|
|
- compiler->patch_constant_signature = shader_desc->patch_constant_signature;
|
|
- memset(&shader_desc->input_signature, 0, sizeof(shader_desc->input_signature));
|
|
- 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->input_signature = program->input_signature;
|
|
+ compiler->output_signature = program->output_signature;
|
|
+ compiler->patch_constant_signature = program->patch_constant_signature;
|
|
+ memset(&program->input_signature, 0, sizeof(program->input_signature));
|
|
+ memset(&program->output_signature, 0, sizeof(program->output_signature));
|
|
+ memset(&program->patch_constant_signature, 0, sizeof(program->patch_constant_signature));
|
|
compiler->use_vocp = program->use_vocp;
|
|
compiler->block_names = program->block_names;
|
|
compiler->block_name_count = program->block_name_count;
|
|
@@ -10119,8 +10239,8 @@ int spirv_compile(struct vkd3d_shader_parser *parser,
|
|
struct spirv_compiler *spirv_compiler;
|
|
int ret;
|
|
|
|
- if (!(spirv_compiler = spirv_compiler_create(&parser->program.shader_version, &parser->shader_desc,
|
|
- compile_info, scan_descriptor_info, message_context, &parser->location, parser->config_flags)))
|
|
+ if (!(spirv_compiler = spirv_compiler_create(&parser->program, compile_info,
|
|
+ scan_descriptor_info, message_context, &parser->location, parser->config_flags)))
|
|
{
|
|
ERR("Failed to create SPIR-V compiler.\n");
|
|
return VKD3D_ERROR;
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c
|
|
index 3be4e40ab0c..bd558693b07 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/tpf.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c
|
|
@@ -954,32 +954,32 @@ static void shader_sm4_read_dcl_index_range(struct vkd3d_shader_instruction *ins
|
|
case VKD3DSPR_INCONTROLPOINT:
|
|
io_masks = priv->input_register_masks;
|
|
ranges = &priv->input_index_ranges;
|
|
- signature = &priv->p.shader_desc.input_signature;
|
|
+ signature = &priv->p.program.input_signature;
|
|
break;
|
|
case VKD3DSPR_OUTPUT:
|
|
if (sm4_parser_is_in_fork_or_join_phase(priv))
|
|
{
|
|
io_masks = priv->patch_constant_register_masks;
|
|
ranges = &priv->patch_constant_index_ranges;
|
|
- signature = &priv->p.shader_desc.patch_constant_signature;
|
|
+ signature = &priv->p.program.patch_constant_signature;
|
|
}
|
|
else
|
|
{
|
|
io_masks = priv->output_register_masks;
|
|
ranges = &priv->output_index_ranges;
|
|
- signature = &priv->p.shader_desc.output_signature;
|
|
+ signature = &priv->p.program.output_signature;
|
|
}
|
|
break;
|
|
case VKD3DSPR_COLOROUT:
|
|
case VKD3DSPR_OUTCONTROLPOINT:
|
|
io_masks = priv->output_register_masks;
|
|
ranges = &priv->output_index_ranges;
|
|
- signature = &priv->p.shader_desc.output_signature;
|
|
+ signature = &priv->p.program.output_signature;
|
|
break;
|
|
case VKD3DSPR_PATCHCONST:
|
|
io_masks = priv->patch_constant_register_masks;
|
|
ranges = &priv->patch_constant_index_ranges;
|
|
- signature = &priv->p.shader_desc.patch_constant_signature;
|
|
+ signature = &priv->p.program.patch_constant_signature;
|
|
break;
|
|
|
|
default:
|
|
@@ -1113,7 +1113,7 @@ static void shader_sm4_read_dcl_input_ps(struct vkd3d_shader_instruction *ins, u
|
|
if (shader_sm4_read_dst_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_FLOAT, dst))
|
|
{
|
|
struct signature_element *e = vsir_signature_find_element_for_reg(
|
|
- &priv->p.shader_desc.input_signature, dst->reg.idx[dst->reg.idx_count - 1].offset, dst->write_mask);
|
|
+ &priv->p.program.input_signature, dst->reg.idx[dst->reg.idx_count - 1].offset, dst->write_mask);
|
|
|
|
e->interpolation_mode = ins->flags;
|
|
}
|
|
@@ -1128,7 +1128,7 @@ static void shader_sm4_read_dcl_input_ps_siv(struct vkd3d_shader_instruction *in
|
|
if (shader_sm4_read_dst_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_FLOAT, dst))
|
|
{
|
|
struct signature_element *e = vsir_signature_find_element_for_reg(
|
|
- &priv->p.shader_desc.input_signature, dst->reg.idx[dst->reg.idx_count - 1].offset, dst->write_mask);
|
|
+ &priv->p.program.input_signature, dst->reg.idx[dst->reg.idx_count - 1].offset, dst->write_mask);
|
|
|
|
e->interpolation_mode = ins->flags;
|
|
}
|
|
@@ -1748,7 +1748,6 @@ static void shader_sm4_destroy(struct vkd3d_shader_parser *parser)
|
|
struct vkd3d_shader_sm4_parser *sm4 = vkd3d_shader_sm4_parser(parser);
|
|
|
|
vsir_program_cleanup(&parser->program);
|
|
- free_shader_desc(&parser->shader_desc);
|
|
vkd3d_free(sm4);
|
|
}
|
|
|
|
@@ -2504,7 +2503,7 @@ static const struct vkd3d_shader_parser_ops shader_sm4_parser_ops =
|
|
};
|
|
|
|
static bool shader_sm4_init(struct vkd3d_shader_sm4_parser *sm4, const uint32_t *byte_code,
|
|
- size_t byte_code_size, const char *source_name, const struct shader_signature *output_signature,
|
|
+ size_t byte_code_size, const char *source_name,
|
|
struct vkd3d_shader_message_context *message_context)
|
|
{
|
|
struct vkd3d_shader_version version;
|
|
@@ -2648,9 +2647,9 @@ int vkd3d_shader_sm4_parser_create(const struct vkd3d_shader_compile_info *compi
|
|
struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_parser **parser)
|
|
{
|
|
struct vkd3d_shader_instruction_array *instructions;
|
|
- struct vkd3d_shader_desc *shader_desc;
|
|
struct vkd3d_shader_instruction *ins;
|
|
struct vkd3d_shader_sm4_parser *sm4;
|
|
+ struct dxbc_shader_desc dxbc_desc = {0};
|
|
int ret;
|
|
|
|
if (!(sm4 = vkd3d_calloc(1, sizeof(*sm4))))
|
|
@@ -2659,36 +2658,40 @@ int vkd3d_shader_sm4_parser_create(const struct vkd3d_shader_compile_info *compi
|
|
return VKD3D_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
- shader_desc = &sm4->p.shader_desc;
|
|
- shader_desc->is_dxil = false;
|
|
+ dxbc_desc.is_dxil = false;
|
|
if ((ret = shader_extract_from_dxbc(&compile_info->source,
|
|
- message_context, compile_info->source_name, shader_desc)) < 0)
|
|
+ message_context, compile_info->source_name, &dxbc_desc)) < 0)
|
|
{
|
|
WARN("Failed to extract shader, vkd3d result %d.\n", ret);
|
|
vkd3d_free(sm4);
|
|
return ret;
|
|
}
|
|
|
|
- if (!shader_sm4_init(sm4, shader_desc->byte_code, shader_desc->byte_code_size,
|
|
- compile_info->source_name, &shader_desc->output_signature, message_context))
|
|
+ if (!shader_sm4_init(sm4, dxbc_desc.byte_code, dxbc_desc.byte_code_size,
|
|
+ compile_info->source_name, message_context))
|
|
{
|
|
WARN("Failed to initialise shader parser.\n");
|
|
- free_shader_desc(shader_desc);
|
|
+ free_dxbc_shader_desc(&dxbc_desc);
|
|
vkd3d_free(sm4);
|
|
return VKD3D_ERROR_INVALID_ARGUMENT;
|
|
}
|
|
|
|
+ sm4->p.program.input_signature = dxbc_desc.input_signature;
|
|
+ sm4->p.program.output_signature = dxbc_desc.output_signature;
|
|
+ sm4->p.program.patch_constant_signature = dxbc_desc.patch_constant_signature;
|
|
+ memset(&dxbc_desc, 0, sizeof(dxbc_desc));
|
|
+
|
|
/* DXBC stores used masks inverted for output signatures, for some reason.
|
|
* We return them un-inverted. */
|
|
- uninvert_used_masks(&shader_desc->output_signature);
|
|
+ uninvert_used_masks(&sm4->p.program.output_signature);
|
|
if (sm4->p.program.shader_version.type == VKD3D_SHADER_TYPE_HULL)
|
|
- uninvert_used_masks(&shader_desc->patch_constant_signature);
|
|
+ uninvert_used_masks(&sm4->p.program.patch_constant_signature);
|
|
|
|
- if (!shader_sm4_parser_validate_signature(sm4, &shader_desc->input_signature,
|
|
+ if (!shader_sm4_parser_validate_signature(sm4, &sm4->p.program.input_signature,
|
|
sm4->input_register_masks, "Input")
|
|
- || !shader_sm4_parser_validate_signature(sm4, &shader_desc->output_signature,
|
|
+ || !shader_sm4_parser_validate_signature(sm4, &sm4->p.program.output_signature,
|
|
sm4->output_register_masks, "Output")
|
|
- || !shader_sm4_parser_validate_signature(sm4, &shader_desc->patch_constant_signature,
|
|
+ || !shader_sm4_parser_validate_signature(sm4, &sm4->p.program.patch_constant_signature,
|
|
sm4->patch_constant_register_masks, "Patch constant"))
|
|
{
|
|
shader_sm4_destroy(&sm4->p);
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c
|
|
index d128d84d6ea..1ac372f163c 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c
|
|
@@ -1450,11 +1450,11 @@ static int scan_with_parser(const struct vkd3d_shader_compile_info *compile_info
|
|
|
|
if (!ret && signature_info)
|
|
{
|
|
- if (!vkd3d_shader_signature_from_shader_signature(&signature_info->input, &parser->shader_desc.input_signature)
|
|
+ if (!vkd3d_shader_signature_from_shader_signature(&signature_info->input, &parser->program.input_signature)
|
|
|| !vkd3d_shader_signature_from_shader_signature(&signature_info->output,
|
|
- &parser->shader_desc.output_signature)
|
|
+ &parser->program.output_signature)
|
|
|| !vkd3d_shader_signature_from_shader_signature(&signature_info->patch_constant,
|
|
- &parser->shader_desc.patch_constant_signature))
|
|
+ &parser->program.patch_constant_signature))
|
|
{
|
|
ret = VKD3D_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
@@ -1553,7 +1553,7 @@ static int vkd3d_shader_parser_compile(struct vkd3d_shader_parser *parser,
|
|
struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context)
|
|
{
|
|
struct vkd3d_shader_scan_descriptor_info1 scan_descriptor_info;
|
|
- struct vkd3d_glsl_generator *glsl_generator;
|
|
+ struct vsir_program *program = &parser->program;
|
|
struct vkd3d_shader_compile_info scan_info;
|
|
int ret;
|
|
|
|
@@ -1562,23 +1562,13 @@ static int vkd3d_shader_parser_compile(struct vkd3d_shader_parser *parser,
|
|
switch (compile_info->target_type)
|
|
{
|
|
case VKD3D_SHADER_TARGET_D3D_ASM:
|
|
- ret = vkd3d_dxbc_binary_to_text(&parser->program, &parser->shader_desc,
|
|
- compile_info, out, VSIR_ASM_FLAG_NONE);
|
|
+ ret = d3d_asm_compile(program, compile_info, out, VSIR_ASM_FLAG_NONE);
|
|
break;
|
|
|
|
case VKD3D_SHADER_TARGET_GLSL:
|
|
if ((ret = scan_with_parser(&scan_info, message_context, &scan_descriptor_info, parser)) < 0)
|
|
return ret;
|
|
- if (!(glsl_generator = vkd3d_glsl_generator_create(&parser->program.shader_version,
|
|
- message_context, &parser->location)))
|
|
- {
|
|
- ERR("Failed to create GLSL generator.\n");
|
|
- vkd3d_shader_free_scan_descriptor_info1(&scan_descriptor_info);
|
|
- return VKD3D_ERROR;
|
|
- }
|
|
-
|
|
- ret = vkd3d_glsl_generator_generate(glsl_generator, &parser->program, out);
|
|
- vkd3d_glsl_generator_destroy(glsl_generator);
|
|
+ ret = glsl_compile(program, out, message_context);
|
|
vkd3d_shader_free_scan_descriptor_info1(&scan_descriptor_info);
|
|
break;
|
|
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
|
|
index d257d953dd5..98c311b3655 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
|
|
@@ -149,6 +149,7 @@ enum vkd3d_shader_error
|
|
VKD3D_SHADER_ERROR_HLSL_NON_FINITE_RESULT = 5027,
|
|
VKD3D_SHADER_ERROR_HLSL_DUPLICATE_SWITCH_CASE = 5028,
|
|
VKD3D_SHADER_ERROR_HLSL_MISSING_TECHNIQUE = 5029,
|
|
+ VKD3D_SHADER_ERROR_HLSL_UNKNOWN_MODIFIER = 5030,
|
|
|
|
VKD3D_SHADER_WARNING_HLSL_IMPLICIT_TRUNCATION = 5300,
|
|
VKD3D_SHADER_WARNING_HLSL_DIVISION_BY_ZERO = 5301,
|
|
@@ -623,14 +624,16 @@ enum vkd3d_data_type
|
|
VKD3D_DATA_UINT8,
|
|
VKD3D_DATA_UINT64,
|
|
VKD3D_DATA_BOOL,
|
|
+ VKD3D_DATA_UINT16,
|
|
+ VKD3D_DATA_HALF,
|
|
|
|
VKD3D_DATA_COUNT,
|
|
};
|
|
|
|
static inline bool data_type_is_integer(enum vkd3d_data_type data_type)
|
|
{
|
|
- return data_type == VKD3D_DATA_INT || data_type == VKD3D_DATA_UINT8 || data_type == VKD3D_DATA_UINT
|
|
- || data_type == VKD3D_DATA_UINT64;
|
|
+ return data_type == VKD3D_DATA_INT || data_type == VKD3D_DATA_UINT8 || data_type == VKD3D_DATA_UINT16
|
|
+ || data_type == VKD3D_DATA_UINT || data_type == VKD3D_DATA_UINT64;
|
|
}
|
|
|
|
static inline bool data_type_is_bool(enum vkd3d_data_type data_type)
|
|
@@ -1028,7 +1031,7 @@ struct signature_element *vsir_signature_find_element_for_reg(const struct shade
|
|
unsigned int reg_idx, unsigned int write_mask);
|
|
void shader_signature_cleanup(struct shader_signature *signature);
|
|
|
|
-struct vkd3d_shader_desc
|
|
+struct dxbc_shader_desc
|
|
{
|
|
const uint32_t *byte_code;
|
|
size_t byte_code_size;
|
|
@@ -1036,7 +1039,10 @@ struct vkd3d_shader_desc
|
|
struct shader_signature input_signature;
|
|
struct shader_signature output_signature;
|
|
struct shader_signature patch_constant_signature;
|
|
+};
|
|
|
|
+struct vkd3d_shader_desc
|
|
+{
|
|
struct
|
|
{
|
|
uint32_t used, external;
|
|
@@ -1293,6 +1299,10 @@ struct vsir_program
|
|
struct vkd3d_shader_version shader_version;
|
|
struct vkd3d_shader_instruction_array instructions;
|
|
|
|
+ struct shader_signature input_signature;
|
|
+ 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;
|
|
unsigned int temp_count;
|
|
@@ -1394,8 +1404,8 @@ enum vsir_asm_flags
|
|
VSIR_ASM_FLAG_DUMP_TYPES = 0x1,
|
|
};
|
|
|
|
-enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vsir_program *program,
|
|
- const struct vkd3d_shader_desc *shader_desc, const struct vkd3d_shader_compile_info *compile_info,
|
|
+enum vkd3d_result d3d_asm_compile(const struct vsir_program *program,
|
|
+ const struct vkd3d_shader_compile_info *compile_info,
|
|
struct vkd3d_shader_code *out, enum vsir_asm_flags flags);
|
|
void vkd3d_string_buffer_cleanup(struct vkd3d_string_buffer *buffer);
|
|
struct vkd3d_string_buffer *vkd3d_string_buffer_get(struct vkd3d_string_buffer_cache *list);
|
|
@@ -1487,20 +1497,15 @@ int vkd3d_shader_sm4_parser_create(const struct vkd3d_shader_compile_info *compi
|
|
int vkd3d_shader_sm6_parser_create(const struct vkd3d_shader_compile_info *compile_info,
|
|
struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_parser **parser);
|
|
|
|
-void free_shader_desc(struct vkd3d_shader_desc *desc);
|
|
+void free_dxbc_shader_desc(struct dxbc_shader_desc *desc);
|
|
|
|
int shader_extract_from_dxbc(const struct vkd3d_shader_code *dxbc,
|
|
- struct vkd3d_shader_message_context *message_context, const char *source_name, struct vkd3d_shader_desc *desc);
|
|
+ struct vkd3d_shader_message_context *message_context, const char *source_name, struct dxbc_shader_desc *desc);
|
|
int shader_parse_input_signature(const struct vkd3d_shader_code *dxbc,
|
|
struct vkd3d_shader_message_context *message_context, struct shader_signature *signature);
|
|
|
|
-struct vkd3d_glsl_generator;
|
|
-
|
|
-struct vkd3d_glsl_generator *vkd3d_glsl_generator_create(const struct vkd3d_shader_version *version,
|
|
- struct vkd3d_shader_message_context *message_context, const struct vkd3d_shader_location *location);
|
|
-int vkd3d_glsl_generator_generate(struct vkd3d_glsl_generator *generator,
|
|
- struct vsir_program *program, struct vkd3d_shader_code *out);
|
|
-void vkd3d_glsl_generator_destroy(struct vkd3d_glsl_generator *generator);
|
|
+int glsl_compile(struct vsir_program *program, struct vkd3d_shader_code *out,
|
|
+ struct vkd3d_shader_message_context *message_context);
|
|
|
|
#define SPIRV_MAX_SRC_COUNT 6
|
|
|
|
@@ -1524,10 +1529,12 @@ static inline enum vkd3d_shader_component_type vkd3d_component_type_from_data_ty
|
|
{
|
|
switch (data_type)
|
|
{
|
|
+ case VKD3D_DATA_HALF: /* Minimum precision. TODO: native 16-bit */
|
|
case VKD3D_DATA_FLOAT:
|
|
case VKD3D_DATA_UNORM:
|
|
case VKD3D_DATA_SNORM:
|
|
return VKD3D_SHADER_COMPONENT_FLOAT;
|
|
+ case VKD3D_DATA_UINT16: /* Minimum precision. TODO: native 16-bit */
|
|
case VKD3D_DATA_UINT:
|
|
return VKD3D_SHADER_COMPONENT_UINT;
|
|
case VKD3D_DATA_INT:
|
|
diff --git a/libs/vkd3d/libs/vkd3d/device.c b/libs/vkd3d/libs/vkd3d/device.c
|
|
index da9c1d964d4..7841a811bf7 100644
|
|
--- a/libs/vkd3d/libs/vkd3d/device.c
|
|
+++ b/libs/vkd3d/libs/vkd3d/device.c
|
|
@@ -94,6 +94,7 @@ static const struct vkd3d_optional_extension_info optional_device_extensions[] =
|
|
VK_EXTENSION(EXT_DEBUG_MARKER, EXT_debug_marker),
|
|
VK_EXTENSION(EXT_DEPTH_CLIP_ENABLE, EXT_depth_clip_enable),
|
|
VK_EXTENSION(EXT_DESCRIPTOR_INDEXING, EXT_descriptor_indexing),
|
|
+ VK_EXTENSION(EXT_FRAGMENT_SHADER_INTERLOCK, EXT_fragment_shader_interlock),
|
|
VK_EXTENSION(EXT_MUTABLE_DESCRIPTOR_TYPE, EXT_mutable_descriptor_type),
|
|
VK_EXTENSION(EXT_ROBUSTNESS_2, EXT_robustness2),
|
|
VK_EXTENSION(EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION, EXT_shader_demote_to_helper_invocation),
|
|
@@ -789,6 +790,7 @@ struct vkd3d_physical_device_info
|
|
VkPhysicalDeviceConditionalRenderingFeaturesEXT conditional_rendering_features;
|
|
VkPhysicalDeviceDepthClipEnableFeaturesEXT depth_clip_features;
|
|
VkPhysicalDeviceDescriptorIndexingFeaturesEXT descriptor_indexing_features;
|
|
+ VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT fragment_shader_interlock_features;
|
|
VkPhysicalDeviceRobustness2FeaturesEXT robustness2_features;
|
|
VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT demote_features;
|
|
VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT texel_buffer_alignment_features;
|
|
@@ -808,6 +810,7 @@ static void vkd3d_physical_device_info_init(struct vkd3d_physical_device_info *i
|
|
VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT *vertex_divisor_properties;
|
|
VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT *buffer_alignment_properties;
|
|
VkPhysicalDeviceDescriptorIndexingFeaturesEXT *descriptor_indexing_features;
|
|
+ VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT *fragment_shader_interlock_features;
|
|
VkPhysicalDeviceRobustness2FeaturesEXT *robustness2_features;
|
|
VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *vertex_divisor_features;
|
|
VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT *buffer_alignment_features;
|
|
@@ -825,6 +828,7 @@ static void vkd3d_physical_device_info_init(struct vkd3d_physical_device_info *i
|
|
conditional_rendering_features = &info->conditional_rendering_features;
|
|
depth_clip_features = &info->depth_clip_features;
|
|
descriptor_indexing_features = &info->descriptor_indexing_features;
|
|
+ fragment_shader_interlock_features = &info->fragment_shader_interlock_features;
|
|
robustness2_features = &info->robustness2_features;
|
|
descriptor_indexing_properties = &info->descriptor_indexing_properties;
|
|
maintenance3_properties = &info->maintenance3_properties;
|
|
@@ -846,6 +850,8 @@ static void vkd3d_physical_device_info_init(struct vkd3d_physical_device_info *i
|
|
vk_prepend_struct(&info->features2, depth_clip_features);
|
|
descriptor_indexing_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT;
|
|
vk_prepend_struct(&info->features2, descriptor_indexing_features);
|
|
+ fragment_shader_interlock_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT;
|
|
+ vk_prepend_struct(&info->features2, fragment_shader_interlock_features);
|
|
robustness2_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT;
|
|
vk_prepend_struct(&info->features2, robustness2_features);
|
|
demote_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT;
|
|
@@ -1158,6 +1164,7 @@ static void vkd3d_trace_physical_device_limits(const struct vkd3d_physical_devic
|
|
|
|
static void vkd3d_trace_physical_device_features(const struct vkd3d_physical_device_info *info)
|
|
{
|
|
+ const VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT *fragment_shader_interlock_features;
|
|
const VkPhysicalDeviceConditionalRenderingFeaturesEXT *conditional_rendering_features;
|
|
const VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT *demote_features;
|
|
const VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT *buffer_alignment_features;
|
|
@@ -1279,6 +1286,15 @@ static void vkd3d_trace_physical_device_features(const struct vkd3d_physical_dev
|
|
TRACE(" VkPhysicalDeviceDepthClipEnableFeaturesEXT:\n");
|
|
TRACE(" depthClipEnable: %#x.\n", depth_clip_features->depthClipEnable);
|
|
|
|
+ fragment_shader_interlock_features = &info->fragment_shader_interlock_features;
|
|
+ TRACE(" VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT:\n");
|
|
+ TRACE(" fragmentShaderSampleInterlock: %#x.\n.",
|
|
+ fragment_shader_interlock_features->fragmentShaderSampleInterlock);
|
|
+ TRACE(" fragmentShaderPixelInterlock: %#x\n.",
|
|
+ fragment_shader_interlock_features->fragmentShaderPixelInterlock);
|
|
+ TRACE(" fragmentShaderShadingRateInterlock: %#x\n.",
|
|
+ fragment_shader_interlock_features->fragmentShaderShadingRateInterlock);
|
|
+
|
|
demote_features = &info->demote_features;
|
|
TRACE(" VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT:\n");
|
|
TRACE(" shaderDemoteToHelperInvocation: %#x.\n", demote_features->shaderDemoteToHelperInvocation);
|
|
@@ -1476,6 +1492,7 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device,
|
|
uint32_t *device_extension_count, bool **user_extension_supported)
|
|
{
|
|
const struct vkd3d_vk_instance_procs *vk_procs = &device->vkd3d_instance->vk_procs;
|
|
+ VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT *fragment_shader_interlock;
|
|
const struct vkd3d_optional_device_extensions_info *optional_extensions;
|
|
VkPhysicalDeviceDescriptorIndexingFeaturesEXT *descriptor_indexing;
|
|
VkPhysicalDevice physical_device = device->vk_physical_device;
|
|
@@ -1539,8 +1556,6 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device,
|
|
|
|
device->feature_options.TypedUAVLoadAdditionalFormats = features->shaderStorageImageReadWithoutFormat
|
|
&& d3d12_device_supports_typed_uav_load_additional_formats(device);
|
|
- /* GL_INTEL_fragment_shader_ordering, no Vulkan equivalent. */
|
|
- device->feature_options.ROVsSupported = FALSE;
|
|
/* GL_INTEL_conservative_rasterization, no Vulkan equivalent. */
|
|
device->feature_options.ConservativeRasterizationTier = D3D12_CONSERVATIVE_RASTERIZATION_TIER_NOT_SUPPORTED;
|
|
device->feature_options.MaxGPUVirtualAddressBitsPerResource = 40; /* FIXME */
|
|
@@ -1619,6 +1634,12 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device,
|
|
*user_extension_supported, vulkan_info, "device",
|
|
device->vkd3d_instance->config_flags & VKD3D_CONFIG_FLAG_VULKAN_DEBUG);
|
|
|
|
+ fragment_shader_interlock = &physical_device_info->fragment_shader_interlock_features;
|
|
+ if (!fragment_shader_interlock->fragmentShaderSampleInterlock
|
|
+ || !fragment_shader_interlock->fragmentShaderPixelInterlock)
|
|
+ vulkan_info->EXT_fragment_shader_interlock = false;
|
|
+ device->feature_options.ROVsSupported = vulkan_info->EXT_fragment_shader_interlock;
|
|
+
|
|
if (!physical_device_info->conditional_rendering_features.conditionalRendering)
|
|
vulkan_info->EXT_conditional_rendering = false;
|
|
if (!physical_device_info->depth_clip_features.depthClipEnable)
|
|
@@ -1675,6 +1696,10 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device,
|
|
vulkan_info->shader_extensions[vulkan_info->shader_extension_count++]
|
|
= VKD3D_SHADER_SPIRV_EXTENSION_EXT_DESCRIPTOR_INDEXING;
|
|
|
|
+ if (vulkan_info->EXT_fragment_shader_interlock)
|
|
+ vulkan_info->shader_extensions[vulkan_info->shader_extension_count++]
|
|
+ = VKD3D_SHADER_SPIRV_EXTENSION_EXT_FRAGMENT_SHADER_INTERLOCK;
|
|
+
|
|
if (vulkan_info->EXT_shader_stencil_export)
|
|
vulkan_info->shader_extensions[vulkan_info->shader_extension_count++]
|
|
= VKD3D_SHADER_SPIRV_EXTENSION_EXT_STENCIL_EXPORT;
|
|
diff --git a/libs/vkd3d/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/libs/vkd3d/vkd3d_private.h
|
|
index 1f47ddd5023..34a98c4fc3d 100644
|
|
--- a/libs/vkd3d/libs/vkd3d/vkd3d_private.h
|
|
+++ b/libs/vkd3d/libs/vkd3d/vkd3d_private.h
|
|
@@ -55,7 +55,7 @@
|
|
|
|
#define VKD3D_MAX_COMPATIBLE_FORMAT_COUNT 6u
|
|
#define VKD3D_MAX_QUEUE_FAMILY_COUNT 3u
|
|
-#define VKD3D_MAX_SHADER_EXTENSIONS 4u
|
|
+#define VKD3D_MAX_SHADER_EXTENSIONS 5u
|
|
#define VKD3D_MAX_SHADER_STAGES 5u
|
|
#define VKD3D_MAX_VK_SYNC_OBJECTS 4u
|
|
#define VKD3D_MAX_DEVICE_BLOCKED_QUEUES 16u
|
|
@@ -133,6 +133,7 @@ struct vkd3d_vulkan_info
|
|
bool EXT_debug_marker;
|
|
bool EXT_depth_clip_enable;
|
|
bool EXT_descriptor_indexing;
|
|
+ bool EXT_fragment_shader_interlock;
|
|
bool EXT_mutable_descriptor_type;
|
|
bool EXT_robustness2;
|
|
bool EXT_shader_demote_to_helper_invocation;
|
|
--
|
|
2.43.0
|
|
|