wine-staging/patches/vkd3d-latest/0003-Updated-vkd3d-to-9b0d304f8fe4e6f0d065e4561af9e372e16.patch
2024-03-22 17:43:13 +11:00

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, &reg.type, &reg.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