wine-staging/patches/vkd3d-latest/0005-Updated-vkd3d-to-62a512c4f8c4070f0f4f3ed8e70b6f0bc88.patch

1498 lines
66 KiB
Diff
Raw Normal View History

2024-05-15 18:58:46 -07:00
From a10a5f6d7f227464e7b594421cda94412460d7dc Mon Sep 17 00:00:00 2001
2024-05-02 14:37:38 -07:00
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
Date: Fri, 3 May 2024 07:31:39 +1000
Subject: [PATCH] Updated vkd3d to 62a512c4f8c4070f0f4f3ed8e70b6f0bc885da30.
---
libs/vkd3d/include/vkd3d.h | 91 +++++++++-
libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 11 ++
libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 22 +--
libs/vkd3d/libs/vkd3d-shader/dxil.c | 155 +++++++++++++++++-
libs/vkd3d/libs/vkd3d-shader/hlsl.c | 39 +++--
libs/vkd3d/libs/vkd3d-shader/hlsl.h | 1 +
libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 1 +
.../libs/vkd3d-shader/hlsl_constant_ops.c | 130 +++++++++++++++
libs/vkd3d/libs/vkd3d-shader/spirv.c | 113 +++++++++++--
.../libs/vkd3d-shader/vkd3d_shader_main.c | 44 ++---
.../libs/vkd3d-shader/vkd3d_shader_private.h | 31 ++--
libs/vkd3d/libs/vkd3d/command.c | 21 +--
libs/vkd3d/libs/vkd3d/device.c | 36 +++-
libs/vkd3d/libs/vkd3d/state.c | 2 +
14 files changed, 595 insertions(+), 102 deletions(-)
diff --git a/libs/vkd3d/include/vkd3d.h b/libs/vkd3d/include/vkd3d.h
index 71c56331d86..38249f0bf5c 100644
--- a/libs/vkd3d/include/vkd3d.h
+++ b/libs/vkd3d/include/vkd3d.h
@@ -237,47 +237,134 @@ struct vkd3d_host_time_domain_info
uint64_t ticks_per_second;
};
+/**
+ * A chained structure containing device creation parameters.
+ */
struct vkd3d_device_create_info
{
+ /** Must be set to VKD3D_STRUCTURE_TYPE_DEVICE_CREATE_INFO. */
enum vkd3d_structure_type type;
+ /** Optional pointer to a structure containing further parameters. */
const void *next;
+ /** The minimum feature level to request. Device creation will fail with E_INVALIDARG if the
+ * Vulkan device doesn't have the features needed to fulfill the request. */
D3D_FEATURE_LEVEL minimum_feature_level;
+ /**
+ * The vkd3d instance to use to create a device. Either this or instance_create_info must be
+ * set.
+ */
struct vkd3d_instance *instance;
+ /**
+ * The parameters used to create an instance, which is then used to create a device. Either
+ * this or instance must be set.
+ */
const struct vkd3d_instance_create_info *instance_create_info;
+ /**
+ * The Vulkan physical device to use. If it is NULL, the first physical device found is used,
+ * prioritizing discrete GPUs over integrated GPUs and integrated GPUs over all the others.
+ *
+ * This parameter can be overridden by setting environment variable VKD3D_VULKAN_DEVICE.
+ */
VkPhysicalDevice vk_physical_device;
+ /**
+ * A list of Vulkan device extensions to request. They are intended as required, so device
+ * creation will fail if any of them is not available.
+ */
const char * const *device_extensions;
+ /** The number of elements in the device_extensions array. */
uint32_t device_extension_count;
+ /**
+ * An object to be set as the device parent. This is not used by vkd3d except for being
+ * returned by vkd3d_get_device_parent.
+ */
IUnknown *parent;
+ /**
+ * The adapter LUID to be set for the device. This is not used by vkd3d except for being
+ * returned by GetAdapterLuid.
+ */
LUID adapter_luid;
};
-/* Extends vkd3d_device_create_info. Available since 1.2. */
+/**
+ * A chained structure to specify optional device extensions.
+ *
+ * This structure extends vkd3d_device_create_info.
+ *
+ * \since 1.2
+ */
struct vkd3d_optional_device_extensions_info
{
+ /** Must be set to VKD3D_STRUCTURE_TYPE_OPTIONAL_DEVICE_EXTENSIONS_INFO. */
enum vkd3d_structure_type type;
+ /** Optional pointer to a structure containing further parameters. */
const void *next;
+ /**
+ * A list of optional Vulkan device extensions to request. Device creation does not fail if
+ * they are not available.
+ */
const char * const *extensions;
+ /** The number of elements in the extensions array. */
uint32_t extension_count;
};
-/* vkd3d_image_resource_create_info flags */
+/**
+ * When specified as a flag of vkd3d_image_resource_create_info, it means that vkd3d will do the
+ * initial transition operation on the image from VK_IMAGE_LAYOUT_UNDEFINED to its appropriate
+ * Vulkan layout (depending on its D3D12 resource state). If this flag is not specified the caller
+ * is responsible for transitioning the Vulkan image to the appropriate layout.
+ */
#define VKD3D_RESOURCE_INITIAL_STATE_TRANSITION 0x00000001
+/**
+ * When specified as a flag of vkd3d_image_resource_create_info, it means that field present_state
+ * is honored.
+ */
#define VKD3D_RESOURCE_PRESENT_STATE_TRANSITION 0x00000002
+/**
+ * A chained structure containing the parameters to create a D3D12 resource backed by a Vulkan
+ * image.
+ */
struct vkd3d_image_resource_create_info
{
+ /** Must be set to VKD3D_STRUCTURE_TYPE_IMAGE_RESOURCE_CREATE_INFO. */
enum vkd3d_structure_type type;
+ /** Optional pointer to a structure containing further parameters. */
const void *next;
+ /** The Vulkan image that backs the resource. */
VkImage vk_image;
+ /** The resource description. */
D3D12_RESOURCE_DESC desc;
+ /**
+ * A combination of zero or more flags. The valid flags are
+ * VKD3D_RESOURCE_INITIAL_STATE_TRANSITION and VKD3D_RESOURCE_PRESENT_STATE_TRANSITION.
+ */
unsigned int flags;
+ /**
+ * This field specifies how to handle resource state D3D12_RESOURCE_STATE_PRESENT for
+ * the resource. Notice that on D3D12 there is no difference between
+ * D3D12_RESOURCE_STATE_COMMON and D3D12_RESOURCE_STATE_PRESENT (they have the same value),
+ * while on Vulkan two different layouts are used (VK_IMAGE_LAYOUT_GENERAL and
+ * VK_IMAGE_LAYOUT_PRESENT_SRC_KHR).
+ *
+ * * When flag VKD3D_RESOURCE_PRESENT_STATE_TRANSITION is not specified, field
+ * present_state is ignored and resource state D3D12_RESOURCE_STATE_COMMON/_PRESENT is
+ * mapped to VK_IMAGE_LAYOUT_GENERAL; this is useful for non-swapchain resources.
+ * * Otherwise, when present_state is D3D12_RESOURCE_STATE_PRESENT/_COMMON, resource state
+ * D3D12_RESOURCE_STATE_COMMON/_PRESENT is mapped to VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
+ * this is useful for swapchain resources that are directly backed by a Vulkan swapchain
+ * image.
+ * * Otherwise, resource state D3D12_RESOURCE_STATE_COMMON/_PRESENT is treated as resource
+ * state present_state; this is useful for swapchain resources that backed by a Vulkan
+ * non-swapchain image, which the client will likely consume with a copy or drawing
+ * operation at presentation time.
+ */
D3D12_RESOURCE_STATES present_state;
};
diff --git a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c
index cd8ba0a7d2b..b2f329cd199 100644
--- a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c
+++ b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c
@@ -327,6 +327,9 @@ static const char * const shader_opcode_names[] =
[VKD3DSIH_UTOD ] = "utod",
[VKD3DSIH_UTOF ] = "utof",
[VKD3DSIH_UTOU ] = "utou",
+ [VKD3DSIH_WAVE_ACTIVE_ALL_EQUAL ] = "wave_active_all_equal",
+ [VKD3DSIH_WAVE_ALL_TRUE ] = "wave_all_true",
+ [VKD3DSIH_WAVE_ANY_TRUE ] = "wave_any_true",
[VKD3DSIH_XOR ] = "xor",
};
@@ -1161,6 +1164,14 @@ static void shader_print_register(struct vkd3d_d3d_asm_compiler *compiler, const
vkd3d_string_buffer_printf(buffer, "sr");
break;
+ case VKD3DSPR_WAVELANECOUNT:
+ vkd3d_string_buffer_printf(buffer, "vWaveLaneCount");
+ break;
+
+ case VKD3DSPR_WAVELANEINDEX:
+ vkd3d_string_buffer_printf(buffer, "vWaveLaneIndex");
+ break;
+
default:
vkd3d_string_buffer_printf(buffer, "%s<unhandled register type %#x>%s",
compiler->colours.error, reg->type, compiler->colours.reset);
diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
index 09e4f596241..aa2358440e5 100644
--- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
+++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
@@ -215,8 +215,12 @@ struct vkd3d_shader_sm1_parser
struct vkd3d_shader_parser p;
+ struct
+ {
#define MAX_CONSTANT_COUNT 8192
- uint32_t constant_def_mask[3][VKD3D_BITMAP_SIZE(MAX_CONSTANT_COUNT)];
+ uint32_t def_mask[VKD3D_BITMAP_SIZE(MAX_CONSTANT_COUNT)];
+ uint32_t count;
+ } constants[3];
};
/* This table is not order or position dependent. */
@@ -750,15 +754,13 @@ static bool add_signature_element_from_semantic(struct vkd3d_shader_sm1_parser *
static void record_constant_register(struct vkd3d_shader_sm1_parser *sm1,
enum vkd3d_shader_d3dbc_constant_register set, uint32_t index, bool from_def)
{
- struct vkd3d_shader_desc *desc = &sm1->p.shader_desc;
-
- desc->flat_constant_count[set].used = max(desc->flat_constant_count[set].used, index + 1);
+ sm1->constants[set].count = max(sm1->constants[set].count, index + 1);
if (from_def)
{
/* d3d shaders have a maximum of 8192 constants; we should not overrun
* this array. */
- assert((index / 32) <= ARRAY_SIZE(sm1->constant_def_mask[set]));
- bitmap_set(sm1->constant_def_mask[set], index);
+ assert((index / 32) <= ARRAY_SIZE(sm1->constants[set].def_mask));
+ bitmap_set(sm1->constants[set].def_mask, index);
}
}
@@ -1301,9 +1303,9 @@ static uint32_t get_external_constant_count(struct vkd3d_shader_sm1_parser *sm1,
/* Find the highest constant index which is not written by a DEF
* instruction. We can't (easily) use an FFZ function for this since it
* needs to be limited by the highest used register index. */
- for (j = sm1->p.shader_desc.flat_constant_count[set].used; j > 0; --j)
+ for (j = sm1->constants[set].count; j > 0; --j)
{
- if (!bitmap_is_set(sm1->constant_def_mask[set], j - 1))
+ if (!bitmap_is_set(sm1->constants[set].def_mask, j - 1))
return j;
}
@@ -1354,8 +1356,8 @@ int vkd3d_shader_sm1_parser_create(const struct vkd3d_shader_compile_info *compi
++instructions->count;
}
- for (i = 0; i < ARRAY_SIZE(sm1->p.shader_desc.flat_constant_count); ++i)
- sm1->p.shader_desc.flat_constant_count[i].external = get_external_constant_count(sm1, i);
+ for (i = 0; i < ARRAY_SIZE(sm1->p.program.flat_constant_count); ++i)
+ sm1->p.program.flat_constant_count[i] = get_external_constant_count(sm1, i);
if (!sm1->p.failed)
ret = vkd3d_shader_parser_validate(&sm1->p);
diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c
index 6a1fb6bddb7..e636ad917db 100644
--- a/libs/vkd3d/libs/vkd3d-shader/dxil.c
+++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c
@@ -31,7 +31,7 @@ static const uint64_t GLOBALVAR_FLAG_EXPLICIT_TYPE = 2;
static const unsigned int GLOBALVAR_ADDRESS_SPACE_SHIFT = 2;
static const uint64_t ALLOCA_FLAG_IN_ALLOCA = 0x20;
static const uint64_t ALLOCA_FLAG_EXPLICIT_TYPE = 0x40;
-static const uint64_t ALLOCA_ALIGNMENT_MASK = ALLOCA_FLAG_IN_ALLOCA - 1;
+static const uint64_t ALLOCA_ALIGNMENT_MASK = 0x1f;
static const unsigned int SHADER_DESCRIPTOR_TYPE_COUNT = 4;
static const size_t MAX_IR_INSTRUCTIONS_PER_DXIL_INSTRUCTION = 11;
@@ -103,6 +103,7 @@ enum bitcode_constant_code
CST_CODE_INTEGER = 4,
CST_CODE_FLOAT = 6,
CST_CODE_STRING = 8,
+ CST_CODE_CE_CAST = 11,
CST_CODE_CE_GEP = 12,
CST_CODE_CE_INBOUNDS_GEP = 20,
CST_CODE_DATA = 22,
@@ -413,6 +414,7 @@ enum dx_intrinsic_opcode
DX_DERIV_COARSEY = 84,
DX_DERIV_FINEX = 85,
DX_DERIV_FINEY = 86,
+ DX_COVERAGE = 91,
DX_THREAD_ID = 93,
DX_GROUP_ID = 94,
DX_THREAD_ID_IN_GROUP = 95,
@@ -425,6 +427,11 @@ enum dx_intrinsic_opcode
DX_STORE_PATCH_CONSTANT = 106,
DX_OUTPUT_CONTROL_POINT_ID = 107,
DX_PRIMITIVE_ID = 108,
+ DX_WAVE_GET_LANE_INDEX = 111,
+ DX_WAVE_GET_LANE_COUNT = 112,
+ DX_WAVE_ANY_TRUE = 113,
+ DX_WAVE_ALL_TRUE = 114,
+ DX_WAVE_ACTIVE_ALL_EQUAL = 115,
DX_LEGACY_F32TOF16 = 130,
DX_LEGACY_F16TOF32 = 131,
DX_RAW_BUFFER_LOAD = 139,
@@ -606,6 +613,7 @@ struct sm6_value
enum sm6_value_type value_type;
unsigned int structure_stride;
bool is_undefined;
+ bool is_back_ref;
union
{
struct sm6_function_data function;
@@ -2216,6 +2224,11 @@ static bool sm6_value_is_ssa(const struct sm6_value *value)
return sm6_value_is_register(value) && register_is_ssa(&value->u.reg);
}
+static bool sm6_value_is_numeric_array(const struct sm6_value *value)
+{
+ return sm6_value_is_register(value) && register_is_numeric_array(&value->u.reg);
+}
+
static inline unsigned int sm6_value_get_constant_uint(const struct sm6_value *value)
{
if (!sm6_value_is_constant(value))
@@ -2658,6 +2671,18 @@ static bool sm6_value_validate_is_pointer(const struct sm6_value *value, struct
return true;
}
+static bool sm6_value_validate_is_backward_ref(const struct sm6_value *value, struct sm6_parser *sm6)
+{
+ if (!value->is_back_ref)
+ {
+ FIXME("Forward-referenced pointers are not supported.\n");
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND,
+ "Forward-referenced pointer declarations are not supported.");
+ return false;
+ }
+ return true;
+}
+
static bool sm6_value_validate_is_numeric(const struct sm6_value *value, struct sm6_parser *sm6)
{
if (!sm6_type_is_numeric(value->type))
@@ -3086,15 +3111,16 @@ static enum vkd3d_result sm6_parser_init_constexpr_gep(struct sm6_parser *sm6, c
static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const struct dxil_block *block)
{
enum vkd3d_shader_register_type reg_type = VKD3DSPR_INVALID;
- const struct sm6_type *type, *elem_type;
+ const struct sm6_type *type, *elem_type, *ptr_type;
+ size_t i, base_value_idx, value_idx;
enum vkd3d_data_type reg_data_type;
const struct dxil_record *record;
+ const struct sm6_value *src;
enum vkd3d_result ret;
struct sm6_value *dst;
- size_t i, value_idx;
uint64_t value;
- for (i = 0, type = NULL; i < block->record_count; ++i)
+ for (i = 0, type = NULL, base_value_idx = sm6->value_count; i < block->record_count; ++i)
{
sm6->p.location.column = i;
record = block->records[i];
@@ -3135,6 +3161,7 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const
dst = sm6_parser_get_current_value(sm6);
dst->type = type;
dst->value_type = VALUE_TYPE_REG;
+ dst->is_back_ref = true;
vsir_register_init(&dst->u.reg, reg_type, reg_data_type, 0);
switch (record->code)
@@ -3209,6 +3236,48 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const
return ret;
break;
+ case CST_CODE_CE_CAST:
+ if (!dxil_record_validate_operand_count(record, 3, 3, sm6))
+ return VKD3D_ERROR_INVALID_SHADER;
+
+ if ((value = record->operands[0]) != CAST_BITCAST)
+ {
+ WARN("Unhandled constexpr cast op %"PRIu64".\n", value);
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND,
+ "Constexpr cast op %"PRIu64" is unhandled.", value);
+ return VKD3D_ERROR_INVALID_SHADER;
+ }
+
+ ptr_type = sm6_parser_get_type(sm6, record->operands[1]);
+ if (!sm6_type_is_pointer(ptr_type))
+ {
+ WARN("Constexpr cast at constant idx %zu is not a pointer.\n", value_idx);
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND,
+ "Constexpr cast source operand is not a pointer.");
+ return VKD3D_ERROR_INVALID_SHADER;
+ }
+
+ if ((value = record->operands[2]) >= sm6->cur_max_value)
+ {
+ WARN("Invalid value index %"PRIu64".\n", value);
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND,
+ "Invalid value index %"PRIu64".", value);
+ return VKD3D_ERROR_INVALID_SHADER;
+ }
+ else if (value == value_idx)
+ {
+ WARN("Invalid value self-reference at %"PRIu64".\n", value);
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND,
+ "Invalid value self-reference for a constexpr cast.");
+ return VKD3D_ERROR_INVALID_SHADER;
+ }
+
+ /* Resolve later in case forward refs exist. */
+ dst->type = type;
+ dst->u.reg.type = VKD3DSPR_COUNT;
+ dst->u.reg.idx[0].offset = value;
+ break;
+
case CST_CODE_UNDEF:
dxil_record_validate_operand_max_count(record, 0, sm6);
dst->u.reg.type = VKD3DSPR_UNDEF;
@@ -3234,6 +3303,29 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const
++sm6->value_count;
}
+ /* Resolve cast forward refs. */
+ for (i = base_value_idx; i < sm6->value_count; ++i)
+ {
+ dst = &sm6->values[i];
+ if (dst->u.reg.type != VKD3DSPR_COUNT)
+ continue;
+
+ type = dst->type;
+
+ src = &sm6->values[dst->u.reg.idx[0].offset];
+ if (!sm6_value_is_numeric_array(src))
+ {
+ WARN("Value is not an array.\n");
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND,
+ "Constexpr cast source value is not a global array element.");
+ return VKD3D_ERROR_INVALID_SHADER;
+ }
+
+ *dst = *src;
+ dst->type = type;
+ dst->u.reg.data_type = vkd3d_data_type_from_sm6_type(type->u.pointer.type);
+ }
+
return VKD3D_OK;
}
@@ -3462,6 +3554,7 @@ static bool sm6_parser_declare_global(struct sm6_parser *sm6, const struct dxil_
dst = sm6_parser_get_current_value(sm6);
dst->type = type;
dst->value_type = VALUE_TYPE_REG;
+ dst->is_back_ref = true;
if (is_constant && !init)
{
@@ -3946,7 +4039,8 @@ static void sm6_parser_emit_atomicrmw(struct sm6_parser *sm6, const struct dxil_
uint64_t code;
if (!(ptr = sm6_parser_get_value_by_ref(sm6, record, NULL, &i))
- || !sm6_value_validate_is_pointer_to_i32(ptr, sm6))
+ || !sm6_value_validate_is_pointer_to_i32(ptr, sm6)
+ || !sm6_value_validate_is_backward_ref(ptr, sm6))
return;
if (ptr->u.reg.type != VKD3DSPR_GROUPSHAREDMEM)
@@ -4421,6 +4515,12 @@ static enum vkd3d_shader_opcode map_dx_unary_op(enum dx_intrinsic_opcode op)
return VKD3DSIH_F32TOF16;
case DX_LEGACY_F16TOF32:
return VKD3DSIH_F16TOF32;
+ case DX_WAVE_ACTIVE_ALL_EQUAL:
+ return VKD3DSIH_WAVE_ACTIVE_ALL_EQUAL;
+ case DX_WAVE_ALL_TRUE:
+ return VKD3DSIH_WAVE_ALL_TRUE;
+ case DX_WAVE_ANY_TRUE:
+ return VKD3DSIH_WAVE_ANY_TRUE;
default:
vkd3d_unreachable();
}
@@ -4729,6 +4829,12 @@ static void sm6_parser_emit_dx_input_register_mov(struct sm6_parser *sm6,
instruction_dst_param_init_ssa_scalar(ins, sm6);
}
+static void sm6_parser_emit_dx_coverage(struct sm6_parser *sm6, enum dx_intrinsic_opcode op,
+ const struct sm6_value **operands, struct function_emission_state *state)
+{
+ sm6_parser_emit_dx_input_register_mov(sm6, state->ins, VKD3DSPR_COVERAGE, VKD3D_DATA_UINT);
+}
+
static const struct sm6_descriptor_info *sm6_parser_get_descriptor(struct sm6_parser *sm6,
enum vkd3d_shader_descriptor_type type, unsigned int id, const struct sm6_value *address)
{
@@ -5804,6 +5910,26 @@ static void sm6_parser_emit_dx_texture_store(struct sm6_parser *sm6, enum dx_int
dst_param_init_with_mask(dst_param, write_mask);
}
+static void sm6_parser_emit_dx_wave_builtin(struct sm6_parser *sm6, enum dx_intrinsic_opcode op,
+ const struct sm6_value **operands, struct function_emission_state *state)
+{
+ enum vkd3d_shader_register_type type;
+
+ switch (op)
+ {
+ case DX_WAVE_GET_LANE_COUNT:
+ type = VKD3DSPR_WAVELANECOUNT;
+ break;
+ case DX_WAVE_GET_LANE_INDEX:
+ type = VKD3DSPR_WAVELANEINDEX;
+ break;
+ default:
+ vkd3d_unreachable();
+ }
+
+ sm6_parser_emit_dx_input_register_mov(sm6, state->ins, type, VKD3D_DATA_UINT);
+}
+
struct sm6_dx_opcode_info
{
const char *ret_type;
@@ -5820,6 +5946,7 @@ struct sm6_dx_opcode_info
C -> constant or undefined int8/16/32
i -> int32
m -> int16/32/64
+ n -> any numeric
f -> float
d -> double
e -> half/float
@@ -5847,6 +5974,7 @@ static const struct sm6_dx_opcode_info sm6_dx_op_table[] =
[DX_CBUFFER_LOAD_LEGACY ] = {"o", "Hi", sm6_parser_emit_dx_cbuffer_load},
[DX_COS ] = {"g", "R", sm6_parser_emit_dx_sincos},
[DX_COUNT_BITS ] = {"i", "m", sm6_parser_emit_dx_unary},
+ [DX_COVERAGE ] = {"i", "", sm6_parser_emit_dx_coverage},
[DX_CREATE_HANDLE ] = {"H", "ccib", sm6_parser_emit_dx_create_handle},
[DX_DERIV_COARSEX ] = {"e", "R", sm6_parser_emit_dx_unary},
[DX_DERIV_COARSEY ] = {"e", "R", sm6_parser_emit_dx_unary},
@@ -5922,6 +6050,11 @@ static const struct sm6_dx_opcode_info sm6_dx_op_table[] =
[DX_UMAD ] = {"m", "RRR", sm6_parser_emit_dx_ma},
[DX_UMAX ] = {"m", "RR", sm6_parser_emit_dx_binary},
[DX_UMIN ] = {"m", "RR", sm6_parser_emit_dx_binary},
+ [DX_WAVE_ACTIVE_ALL_EQUAL ] = {"1", "n", sm6_parser_emit_dx_unary},
+ [DX_WAVE_ALL_TRUE ] = {"1", "1", sm6_parser_emit_dx_unary},
+ [DX_WAVE_ANY_TRUE ] = {"1", "1", sm6_parser_emit_dx_unary},
+ [DX_WAVE_GET_LANE_COUNT ] = {"i", "", sm6_parser_emit_dx_wave_builtin},
+ [DX_WAVE_GET_LANE_INDEX ] = {"i", "", sm6_parser_emit_dx_wave_builtin},
};
static bool sm6_parser_validate_operand_type(struct sm6_parser *sm6, const struct sm6_value *value, char info_type,
@@ -5953,6 +6086,8 @@ static bool sm6_parser_validate_operand_type(struct sm6_parser *sm6, const struc
return sm6_type_is_i32(type);
case 'm':
return sm6_type_is_i16_i32_i64(type);
+ case 'n':
+ return sm6_type_is_numeric(type);
case 'f':
return sm6_type_is_float(type);
case 'd':
@@ -6446,7 +6581,8 @@ static void sm6_parser_emit_cmpxchg(struct sm6_parser *sm6, const struct dxil_re
uint64_t code;
if (!(ptr = sm6_parser_get_value_by_ref(sm6, record, NULL, &i))
- || !sm6_value_validate_is_pointer_to_i32(ptr, sm6))
+ || !sm6_value_validate_is_pointer_to_i32(ptr, sm6)
+ || !sm6_value_validate_is_backward_ref(ptr, sm6))
return;
if (ptr->u.reg.type != VKD3DSPR_GROUPSHAREDMEM)
@@ -6687,6 +6823,7 @@ static void sm6_parser_emit_load(struct sm6_parser *sm6, const struct dxil_recor
return;
if (!sm6_value_validate_is_register(ptr, sm6)
|| !sm6_value_validate_is_pointer(ptr, sm6)
+ || !sm6_value_validate_is_backward_ref(ptr, sm6)
|| !dxil_record_validate_operand_count(record, i + 2, i + 3, sm6))
return;
@@ -6870,7 +7007,8 @@ static void sm6_parser_emit_store(struct sm6_parser *sm6, const struct dxil_reco
if (!(ptr = sm6_parser_get_value_by_ref(sm6, record, NULL, &i))
|| !sm6_value_validate_is_register(ptr, sm6)
- || !sm6_value_validate_is_pointer(ptr, sm6))
+ || !sm6_value_validate_is_pointer(ptr, sm6)
+ || !sm6_value_validate_is_backward_ref(ptr, sm6))
{
return;
}
@@ -7478,6 +7616,7 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const
fwd_type = dst->type;
dst->type = NULL;
dst->value_type = VALUE_TYPE_REG;
+ dst->is_back_ref = true;
is_terminator = false;
record = block->records[i];
@@ -8081,7 +8220,9 @@ static const enum vkd3d_shader_sysval_semantic sysval_semantic_table[] =
{
[SEMANTIC_KIND_ARBITRARY] = VKD3D_SHADER_SV_NONE,
[SEMANTIC_KIND_VERTEXID] = VKD3D_SHADER_SV_VERTEX_ID,
+ [SEMANTIC_KIND_INSTANCEID] = VKD3D_SHADER_SV_INSTANCE_ID,
[SEMANTIC_KIND_POSITION] = VKD3D_SHADER_SV_POSITION,
+ [SEMANTIC_KIND_PRIMITIVEID] = VKD3D_SHADER_SV_PRIMITIVE_ID,
[SEMANTIC_KIND_ISFRONTFACE] = VKD3D_SHADER_SV_IS_FRONT_FACE,
[SEMANTIC_KIND_TARGET] = VKD3D_SHADER_SV_TARGET,
[SEMANTIC_KIND_DEPTH] = VKD3D_SHADER_SV_DEPTH,
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c
index 4fc1493bdce..0b48b17d21c 100644
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c
@@ -3517,6 +3517,7 @@ static int compare_function_rb(const void *key, const struct rb_entry *entry)
static void declare_predefined_types(struct hlsl_ctx *ctx)
{
+ struct vkd3d_string_buffer *name;
unsigned int x, y, bt, i, v;
struct hlsl_type *type;
@@ -3529,7 +3530,6 @@ static void declare_predefined_types(struct hlsl_ctx *ctx)
"uint",
"bool",
};
- char name[15];
static const char *const variants_float[] = {"min10float", "min16float"};
static const char *const variants_int[] = {"min12int", "min16int"};
@@ -3573,28 +3573,34 @@ static void declare_predefined_types(struct hlsl_ctx *ctx)
{"technique11", 11},
};
+ if (!(name = hlsl_get_string_buffer(ctx)))
+ return;
+
for (bt = 0; bt <= HLSL_TYPE_LAST_SCALAR; ++bt)
{
for (y = 1; y <= 4; ++y)
{
for (x = 1; x <= 4; ++x)
{
- sprintf(name, "%s%ux%u", names[bt], y, x);
- type = hlsl_new_type(ctx, name, HLSL_CLASS_MATRIX, bt, x, y);
+ vkd3d_string_buffer_clear(name);
+ vkd3d_string_buffer_printf(name, "%s%ux%u", names[bt], y, x);
+ type = hlsl_new_type(ctx, name->buffer, HLSL_CLASS_MATRIX, bt, x, y);
hlsl_scope_add_type(ctx->globals, type);
ctx->builtin_types.matrix[bt][x - 1][y - 1] = type;
if (y == 1)
{
- sprintf(name, "%s%u", names[bt], x);
- type = hlsl_new_type(ctx, name, HLSL_CLASS_VECTOR, bt, x, y);
+ vkd3d_string_buffer_clear(name);
+ vkd3d_string_buffer_printf(name, "%s%u", names[bt], x);
+ type = hlsl_new_type(ctx, name->buffer, HLSL_CLASS_VECTOR, bt, x, y);
hlsl_scope_add_type(ctx->globals, type);
ctx->builtin_types.vector[bt][x - 1] = type;
if (x == 1)
{
- sprintf(name, "%s", names[bt]);
- type = hlsl_new_type(ctx, name, HLSL_CLASS_SCALAR, bt, x, y);
+ vkd3d_string_buffer_clear(name);
+ vkd3d_string_buffer_printf(name, "%s", names[bt]);
+ type = hlsl_new_type(ctx, name->buffer, HLSL_CLASS_SCALAR, bt, x, y);
hlsl_scope_add_type(ctx->globals, type);
ctx->builtin_types.scalar[bt] = type;
}
@@ -3637,22 +3643,25 @@ static void declare_predefined_types(struct hlsl_ctx *ctx)
{
for (x = 1; x <= 4; ++x)
{
- sprintf(name, "%s%ux%u", variants[v], y, x);
- type = hlsl_new_type(ctx, name, HLSL_CLASS_MATRIX, bt, x, y);
+ vkd3d_string_buffer_clear(name);
+ vkd3d_string_buffer_printf(name, "%s%ux%u", variants[v], y, x);
+ type = hlsl_new_type(ctx, name->buffer, HLSL_CLASS_MATRIX, bt, x, y);
type->is_minimum_precision = 1;
hlsl_scope_add_type(ctx->globals, type);
if (y == 1)
{
- sprintf(name, "%s%u", variants[v], x);
- type = hlsl_new_type(ctx, name, HLSL_CLASS_VECTOR, bt, x, y);
+ vkd3d_string_buffer_clear(name);
+ vkd3d_string_buffer_printf(name, "%s%u", variants[v], x);
+ type = hlsl_new_type(ctx, name->buffer, HLSL_CLASS_VECTOR, bt, x, y);
type->is_minimum_precision = 1;
hlsl_scope_add_type(ctx->globals, type);
if (x == 1)
{
- sprintf(name, "%s", variants[v]);
- type = hlsl_new_type(ctx, name, HLSL_CLASS_SCALAR, bt, x, y);
+ vkd3d_string_buffer_clear(name);
+ vkd3d_string_buffer_printf(name, "%s", variants[v]);
+ type = hlsl_new_type(ctx, name->buffer, HLSL_CLASS_SCALAR, bt, x, y);
type->is_minimum_precision = 1;
hlsl_scope_add_type(ctx->globals, type);
}
@@ -3690,6 +3699,8 @@ static void declare_predefined_types(struct hlsl_ctx *ctx)
type->e.version = technique_types[i].version;
hlsl_scope_add_type(ctx->globals, type);
}
+
+ hlsl_release_string_buffer(ctx, name);
}
static bool hlsl_ctx_init(struct hlsl_ctx *ctx, const struct vkd3d_shader_compile_info *compile_info,
@@ -3965,7 +3976,7 @@ int hlsl_compile_shader(const struct vkd3d_shader_code *hlsl, const struct vkd3d
}
if (ret >= 0)
{
- ret = vkd3d_shader_parser_compile(parser, &info, out, message_context);
+ ret = vsir_program_compile(&parser->program, parser->config_flags, &info, out, message_context);
vkd3d_shader_parser_destroy(parser);
}
vkd3d_shader_free_shader_code(&info.source);
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h
index 1e5f0805152..c3a4c6bd291 100644
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h
@@ -1422,6 +1422,7 @@ struct hlsl_reg hlsl_reg_from_deref(struct hlsl_ctx *ctx, const struct hlsl_dere
bool hlsl_copy_propagation_execute(struct hlsl_ctx *ctx, struct hlsl_block *block);
bool hlsl_fold_constant_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context);
+bool hlsl_fold_constant_identities(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context);
bool hlsl_fold_constant_swizzles(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context);
bool hlsl_transform_ir(struct hlsl_ctx *ctx, bool (*func)(struct hlsl_ctx *ctx, struct hlsl_ir_node *, void *),
struct hlsl_block *block, void *context);
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c
index a6d6b336b40..94acb70fff9 100644
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c
@@ -5427,6 +5427,7 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry
do
{
progress = hlsl_transform_ir(ctx, hlsl_fold_constant_exprs, body, NULL);
+ progress |= hlsl_transform_ir(ctx, hlsl_fold_constant_identities, body, NULL);
progress |= hlsl_transform_ir(ctx, hlsl_fold_constant_swizzles, body, NULL);
progress |= hlsl_copy_propagation_execute(ctx, body);
progress |= hlsl_transform_ir(ctx, fold_swizzle_chains, body, NULL);
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_constant_ops.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_constant_ops.c
index 4cea98e9286..51f2f9cc050 100644
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl_constant_ops.c
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_constant_ops.c
@@ -1396,6 +1396,136 @@ bool hlsl_fold_constant_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr,
return success;
}
+static bool constant_is_zero(struct hlsl_ir_constant *const_arg)
+{
+ struct hlsl_type *data_type = const_arg->node.data_type;
+ unsigned int k;
+
+ for (k = 0; k < data_type->dimx; ++k)
+ {
+ switch (data_type->base_type)
+ {
+ case HLSL_TYPE_FLOAT:
+ case HLSL_TYPE_HALF:
+ if (const_arg->value.u[k].f != 0.0f)
+ return false;
+ break;
+
+ case HLSL_TYPE_DOUBLE:
+ if (const_arg->value.u[k].d != 0.0)
+ return false;
+ break;
+
+ case HLSL_TYPE_UINT:
+ case HLSL_TYPE_INT:
+ case HLSL_TYPE_BOOL:
+ if (const_arg->value.u[k].u != 0)
+ return false;
+ break;
+
+ default:
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool constant_is_one(struct hlsl_ir_constant *const_arg)
+{
+ struct hlsl_type *data_type = const_arg->node.data_type;
+ unsigned int k;
+
+ for (k = 0; k < data_type->dimx; ++k)
+ {
+ switch (data_type->base_type)
+ {
+ case HLSL_TYPE_FLOAT:
+ case HLSL_TYPE_HALF:
+ if (const_arg->value.u[k].f != 1.0f)
+ return false;
+ break;
+
+ case HLSL_TYPE_DOUBLE:
+ if (const_arg->value.u[k].d != 1.0)
+ return false;
+ break;
+
+ case HLSL_TYPE_UINT:
+ case HLSL_TYPE_INT:
+ case HLSL_TYPE_BOOL:
+ if (const_arg->value.u[k].u != 1)
+ return false;
+ break;
+
+ default:
+ return false;
+ }
+ }
+ return true;
+}
+
+bool hlsl_fold_constant_identities(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
+{
+ struct hlsl_ir_constant *const_arg = NULL;
+ struct hlsl_ir_node *mut_arg = NULL;
+ struct hlsl_ir_node *res_node;
+ struct hlsl_ir_expr *expr;
+ unsigned int i;
+
+ if (instr->type != HLSL_IR_EXPR)
+ return false;
+ expr = hlsl_ir_expr(instr);
+
+ if (instr->data_type->class > HLSL_CLASS_VECTOR)
+ return false;
+
+ /* Verify that the expression has two operands. */
+ for (i = 0; i < ARRAY_SIZE(expr->operands); ++i)
+ {
+ if (!!expr->operands[i].node != (i < 2))
+ return false;
+ }
+
+ if (expr->operands[0].node->type == HLSL_IR_CONSTANT)
+ {
+ const_arg = hlsl_ir_constant(expr->operands[0].node);
+ mut_arg = expr->operands[1].node;
+ }
+ else if (expr->operands[1].node->type == HLSL_IR_CONSTANT)
+ {
+ mut_arg = expr->operands[0].node;
+ const_arg = hlsl_ir_constant(expr->operands[1].node);
+ }
+ else
+ {
+ return false;
+ }
+
+ res_node = NULL;
+ switch (expr->op)
+ {
+ case HLSL_OP2_ADD:
+ if (constant_is_zero(const_arg))
+ res_node = mut_arg;
+ break;
+
+ case HLSL_OP2_MUL:
+ if (constant_is_one(const_arg))
+ res_node = mut_arg;
+ break;
+
+ default:
+ break;
+ }
+
+ if (res_node)
+ {
+ hlsl_replace_node(&expr->node, res_node);
+ return true;
+ }
+ return false;
+}
+
bool hlsl_fold_constant_swizzles(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
{
struct hlsl_constant_value value;
diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c
index c4e712b8471..dc9e8c06a5e 100644
--- a/libs/vkd3d/libs/vkd3d-shader/spirv.c
+++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c
@@ -361,6 +361,7 @@ struct vkd3d_spirv_builder
uint32_t type_sampler_id;
uint32_t type_bool_id;
uint32_t type_void_id;
+ uint32_t scope_subgroup_id;
struct vkd3d_spirv_stream debug_stream; /* debug instructions */
struct vkd3d_spirv_stream annotation_stream; /* decoration instructions */
@@ -1741,6 +1742,16 @@ static void vkd3d_spirv_build_op_memory_barrier(struct vkd3d_spirv_builder *buil
SpvOpMemoryBarrier, memory_id, memory_semantics_id);
}
+static uint32_t vkd3d_spirv_build_op_scope_subgroup(struct vkd3d_spirv_builder *builder)
+{
+ return vkd3d_spirv_get_op_constant(builder, vkd3d_spirv_get_op_type_int(builder, 32, 0), SpvScopeSubgroup);
+}
+
+static uint32_t vkd3d_spirv_get_op_scope_subgroup(struct vkd3d_spirv_builder *builder)
+{
+ return vkd3d_spirv_build_once(builder, &builder->scope_subgroup_id, vkd3d_spirv_build_op_scope_subgroup);
+}
+
static uint32_t vkd3d_spirv_build_op_glsl_std450_tr1(struct vkd3d_spirv_builder *builder,
enum GLSLstd450 op, uint32_t result_type, uint32_t operand)
{
@@ -2453,8 +2464,7 @@ static void spirv_compiler_destroy(struct spirv_compiler *compiler)
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)
+ struct vkd3d_shader_message_context *message_context, uint64_t config_flags)
{
const struct shader_signature *patch_constant_signature = &program->patch_constant_signature;
const struct shader_signature *output_signature = &program->output_signature;
@@ -2470,7 +2480,7 @@ static struct spirv_compiler *spirv_compiler_create(const struct vsir_program *p
memset(compiler, 0, sizeof(*compiler));
compiler->message_context = message_context;
- compiler->location = *location;
+ compiler->location.source_name = compile_info->source_name;
compiler->config_flags = config_flags;
if ((target_info = vkd3d_find_struct(compile_info->next, SPIRV_TARGET_INFO)))
@@ -2632,6 +2642,11 @@ static bool spirv_compiler_is_opengl_target(const struct spirv_compiler *compile
return spirv_compiler_get_target_environment(compiler) == VKD3D_SHADER_SPIRV_ENVIRONMENT_OPENGL_4_5;
}
+static bool spirv_compiler_is_spirv_min_1_3_target(const struct spirv_compiler *compiler)
+{
+ return spirv_compiler_get_target_environment(compiler) == VKD3D_SHADER_SPIRV_ENVIRONMENT_VULKAN_1_1;
+}
+
static bool spirv_compiler_is_target_extension_supported(const struct spirv_compiler *compiler,
enum vkd3d_shader_spirv_extension extension)
{
@@ -3150,6 +3165,12 @@ static bool spirv_compiler_get_register_name(char *buffer, unsigned int buffer_s
case VKD3DSPR_OUTSTENCILREF:
snprintf(buffer, buffer_size, "oStencilRef");
break;
+ case VKD3DSPR_WAVELANECOUNT:
+ snprintf(buffer, buffer_size, "vWaveLaneCount");
+ break;
+ case VKD3DSPR_WAVELANEINDEX:
+ snprintf(buffer, buffer_size, "vWaveLaneIndex");
+ break;
default:
FIXME("Unhandled register %#x.\n", reg->type);
snprintf(buffer, buffer_size, "unrecognized_%#x", reg->type);
@@ -4535,6 +4556,10 @@ static void spirv_compiler_decorate_builtin(struct spirv_compiler *compiler,
case SpvBuiltInCullDistance:
vkd3d_spirv_enable_capability(builder, SpvCapabilityCullDistance);
break;
+ case SpvBuiltInSubgroupSize:
+ case SpvBuiltInSubgroupLocalInvocationId:
+ vkd3d_spirv_enable_capability(builder, SpvCapabilityGroupNonUniform);
+ break;
default:
break;
}
@@ -4724,6 +4749,9 @@ vkd3d_register_builtins[] =
{VKD3DSPR_DEPTHOUTLE, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInFragDepth}},
{VKD3DSPR_OUTSTENCILREF, {VKD3D_SHADER_COMPONENT_UINT, 1, SpvBuiltInFragStencilRefEXT}},
+
+ {VKD3DSPR_WAVELANECOUNT, {VKD3D_SHADER_COMPONENT_UINT, 1, SpvBuiltInSubgroupSize}},
+ {VKD3DSPR_WAVELANEINDEX, {VKD3D_SHADER_COMPONENT_UINT, 1, SpvBuiltInSubgroupLocalInvocationId}},
};
static void spirv_compiler_emit_register_execution_mode(struct spirv_compiler *compiler,
@@ -5772,6 +5800,23 @@ static void spirv_compiler_emit_dcl_global_flags(struct spirv_compiler *compiler
flags &= ~VKD3DSGF_ENABLE_INT64;
}
+ if (flags & VKD3DSGF_ENABLE_WAVE_INTRINSICS)
+ {
+ if (!(compiler->features & VKD3D_SHADER_COMPILE_OPTION_FEATURE_WAVE_OPS))
+ {
+ WARN("Unsupported wave ops.\n");
+ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_UNSUPPORTED_FEATURE,
+ "The target environment does not support wave ops.");
+ }
+ else if (!spirv_compiler_is_spirv_min_1_3_target(compiler))
+ {
+ WARN("Wave ops enabled but environment does not support SPIR-V 1.3 or greater.\n");
+ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_UNSUPPORTED_FEATURE,
+ "The target environment uses wave ops but does not support SPIR-V 1.3 or greater.");
+ }
+ flags &= ~VKD3DSGF_ENABLE_WAVE_INTRINSICS;
+ }
+
if (flags & ~(VKD3DSGF_REFACTORING_ALLOWED | VKD3DSGF_ENABLE_RAW_AND_STRUCTURED_BUFFERS))
FIXME("Unhandled global flags %#"PRIx64".\n", (uint64_t)flags);
else
@@ -9713,6 +9758,41 @@ static void spirv_compiler_emit_cut_stream(struct spirv_compiler *compiler,
vkd3d_spirv_build_op_end_primitive(builder);
}
+static SpvOp map_wave_bool_op(enum vkd3d_shader_opcode handler_idx)
+{
+ switch (handler_idx)
+ {
+ case VKD3DSIH_WAVE_ACTIVE_ALL_EQUAL:
+ return SpvOpGroupNonUniformAllEqual;
+ case VKD3DSIH_WAVE_ALL_TRUE:
+ return SpvOpGroupNonUniformAll;
+ case VKD3DSIH_WAVE_ANY_TRUE:
+ return SpvOpGroupNonUniformAny;
+ default:
+ vkd3d_unreachable();
+ }
+}
+
+static void spirv_compiler_emit_wave_bool_op(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 type_id, val_id;
+ SpvOp op;
+
+ vkd3d_spirv_enable_capability(builder, SpvCapabilityGroupNonUniformVote);
+
+ op = map_wave_bool_op(instruction->handler_idx);
+ type_id = vkd3d_spirv_get_op_type_bool(builder);
+ val_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask);
+ val_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, op,
+ type_id, vkd3d_spirv_get_op_scope_subgroup(builder), val_id);
+
+ spirv_compiler_emit_store_dst(compiler, dst, val_id);
+}
+
/* This function is called after declarations are processed. */
static void spirv_compiler_emit_main_prolog(struct spirv_compiler *compiler)
{
@@ -9732,6 +9812,8 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler,
{
int ret = VKD3D_OK;
+ compiler->location = instruction->location;
+
switch (instruction->handler_idx)
{
case VKD3DSIH_DCL_GLOBAL_FLAGS:
@@ -10055,6 +10137,11 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler,
case VKD3DSIH_CUT_STREAM:
spirv_compiler_emit_cut_stream(compiler, instruction);
break;
+ case VKD3DSIH_WAVE_ACTIVE_ALL_EQUAL:
+ case VKD3DSIH_WAVE_ALL_TRUE:
+ case VKD3DSIH_WAVE_ANY_TRUE:
+ spirv_compiler_emit_wave_bool_op(compiler, instruction);
+ break;
case VKD3DSIH_DCL:
case VKD3DSIH_DCL_HS_MAX_TESSFACTOR:
case VKD3DSIH_DCL_INPUT_CONTROL_POINT_COUNT:
@@ -10151,15 +10238,13 @@ static void spirv_compiler_emit_descriptor_declarations(struct spirv_compiler *c
}
}
-static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler,
- const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_parser *parser,
- struct vkd3d_shader_code *spirv)
+static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, struct vsir_program *program,
+ const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_code *spirv)
{
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_instruction_array instructions;
- struct vsir_program *program = &parser->program;
enum vkd3d_shader_spirv_environment environment;
enum vkd3d_result result = VKD3D_OK;
unsigned int i;
@@ -10175,9 +10260,6 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler,
spirv_compiler_emit_descriptor_declarations(compiler);
- compiler->location.column = 0;
- compiler->location.line = 1;
-
if (program->block_count && !spirv_compiler_init_blocks(compiler, program->block_count))
return VKD3D_ERROR_OUT_OF_MEMORY;
@@ -10202,7 +10284,6 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler,
for (i = 0; i < instructions.count && result >= 0; ++i)
{
- compiler->location.line = i + 1;
result = spirv_compiler_handle_instruction(compiler, &instructions.elements[i]);
}
@@ -10249,7 +10330,7 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler,
if (!vkd3d_spirv_compile_module(builder, spirv, spirv_compiler_get_entry_point_name(compiler), environment))
return VKD3D_ERROR;
- if (TRACE_ON() || parser->config_flags & VKD3D_SHADER_CONFIG_FLAG_FORCE_VALIDATION)
+ if (TRACE_ON() || compiler->config_flags & VKD3D_SHADER_CONFIG_FLAG_FORCE_VALIDATION)
{
struct vkd3d_string_buffer buffer;
@@ -10287,7 +10368,7 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler,
return VKD3D_OK;
}
-int spirv_compile(struct vkd3d_shader_parser *parser,
+int spirv_compile(struct vsir_program *program, uint64_t config_flags,
const struct vkd3d_shader_scan_descriptor_info1 *scan_descriptor_info,
const struct vkd3d_shader_compile_info *compile_info,
struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context)
@@ -10295,14 +10376,14 @@ int spirv_compile(struct vkd3d_shader_parser *parser,
struct spirv_compiler *spirv_compiler;
int ret;
- if (!(spirv_compiler = spirv_compiler_create(&parser->program, compile_info,
- scan_descriptor_info, message_context, &parser->location, parser->config_flags)))
+ if (!(spirv_compiler = spirv_compiler_create(program, compile_info,
+ scan_descriptor_info, message_context, config_flags)))
{
ERR("Failed to create SPIR-V compiler.\n");
return VKD3D_ERROR;
}
- ret = spirv_compiler_generate_spirv(spirv_compiler, compile_info, parser, out);
+ ret = spirv_compiler_generate_spirv(spirv_compiler, program, compile_info, out);
spirv_compiler_destroy(spirv_compiler);
return ret;
diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c
index cb37efb53f7..29b2c1482a9 100644
--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c
+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c
@@ -1395,9 +1395,9 @@ static void vkd3d_shader_free_scan_descriptor_info1(struct vkd3d_shader_scan_des
vkd3d_free(scan_descriptor_info->descriptors);
}
-static int scan_with_parser(const struct vkd3d_shader_compile_info *compile_info,
+static int vsir_program_scan(struct vsir_program *program, const struct vkd3d_shader_compile_info *compile_info,
struct vkd3d_shader_message_context *message_context,
- struct vkd3d_shader_scan_descriptor_info1 *descriptor_info1, struct vkd3d_shader_parser *parser)
+ struct vkd3d_shader_scan_descriptor_info1 *descriptor_info1)
{
struct vkd3d_shader_scan_combined_resource_sampler_info *combined_sampler_info;
struct vkd3d_shader_scan_descriptor_info1 local_descriptor_info1 = {0};
@@ -1428,27 +1428,27 @@ static int scan_with_parser(const struct vkd3d_shader_compile_info *compile_info
descriptor_info1 = &local_descriptor_info1;
}
- vkd3d_shader_scan_context_init(&context, &parser->program.shader_version, compile_info,
+ vkd3d_shader_scan_context_init(&context, &program->shader_version, compile_info,
descriptor_info1, combined_sampler_info, message_context);
if (TRACE_ON())
- vkd3d_shader_trace(&parser->program);
+ vkd3d_shader_trace(program);
- for (i = 0; i < parser->program.instructions.count; ++i)
+ for (i = 0; i < program->instructions.count; ++i)
{
- instruction = &parser->program.instructions.elements[i];
+ instruction = &program->instructions.elements[i];
if ((ret = vkd3d_shader_scan_instruction(&context, instruction)) < 0)
break;
}
- for (i = 0; i < ARRAY_SIZE(parser->shader_desc.flat_constant_count); ++i)
+ for (i = 0; i < ARRAY_SIZE(program->flat_constant_count); ++i)
{
- unsigned int size = parser->shader_desc.flat_constant_count[i].external;
struct vkd3d_shader_register_range range = {.space = 0, .first = i, .last = i};
struct vkd3d_shader_register reg = {.idx[0].offset = i, .idx_count = 1};
+ unsigned int size = program->flat_constant_count[i];
struct vkd3d_shader_descriptor_info1 *d;
- if (parser->shader_desc.flat_constant_count[i].external)
+ if (size)
{
if ((d = vkd3d_shader_scan_add_descriptor(&context, VKD3D_SHADER_DESCRIPTOR_TYPE_CBV, &reg,
&range, VKD3D_SHADER_RESOURCE_BUFFER, VKD3D_SHADER_RESOURCE_DATA_UINT)))
@@ -1458,11 +1458,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->program.input_signature)
+ if (!vkd3d_shader_signature_from_shader_signature(&signature_info->input, &program->input_signature)
|| !vkd3d_shader_signature_from_shader_signature(&signature_info->output,
- &parser->program.output_signature)
+ &program->output_signature)
|| !vkd3d_shader_signature_from_shader_signature(&signature_info->patch_constant,
- &parser->program.patch_constant_signature))
+ &program->patch_constant_signature))
{
ret = VKD3D_ERROR_OUT_OF_MEMORY;
}
@@ -1544,7 +1544,7 @@ int vkd3d_shader_scan(const struct vkd3d_shader_compile_info *compile_info, char
}
else
{
- ret = scan_with_parser(compile_info, &message_context, NULL, parser);
+ ret = vsir_program_scan(&parser->program, compile_info, &message_context, NULL);
vkd3d_shader_parser_destroy(parser);
}
}
@@ -1556,12 +1556,11 @@ int vkd3d_shader_scan(const struct vkd3d_shader_compile_info *compile_info, char
return ret;
}
-int vkd3d_shader_parser_compile(struct vkd3d_shader_parser *parser,
- const struct vkd3d_shader_compile_info *compile_info,
- struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context)
+int vsir_program_compile(struct vsir_program *program, uint64_t config_flags,
+ const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_code *out,
+ struct vkd3d_shader_message_context *message_context)
{
struct vkd3d_shader_scan_descriptor_info1 scan_descriptor_info;
- struct vsir_program *program = &parser->program;
struct vkd3d_shader_compile_info scan_info;
int ret;
@@ -1574,17 +1573,18 @@ int vkd3d_shader_parser_compile(struct vkd3d_shader_parser *parser,
break;
case VKD3D_SHADER_TARGET_GLSL:
- if ((ret = scan_with_parser(&scan_info, message_context, &scan_descriptor_info, parser)) < 0)
+ if ((ret = vsir_program_scan(program, &scan_info, message_context, &scan_descriptor_info)) < 0)
return ret;
- ret = glsl_compile(program, parser->config_flags, compile_info, out, message_context);
+ ret = glsl_compile(program, config_flags, compile_info, out, message_context);
vkd3d_shader_free_scan_descriptor_info1(&scan_descriptor_info);
break;
case VKD3D_SHADER_TARGET_SPIRV_BINARY:
case VKD3D_SHADER_TARGET_SPIRV_TEXT:
- if ((ret = scan_with_parser(&scan_info, message_context, &scan_descriptor_info, parser)) < 0)
+ if ((ret = vsir_program_scan(program, &scan_info, message_context, &scan_descriptor_info)) < 0)
return ret;
- ret = spirv_compile(parser, &scan_descriptor_info, compile_info, out, message_context);
+ ret = spirv_compile(program, config_flags, &scan_descriptor_info,
+ compile_info, out, message_context);
vkd3d_shader_free_scan_descriptor_info1(&scan_descriptor_info);
break;
@@ -1665,7 +1665,7 @@ int vkd3d_shader_compile(const struct vkd3d_shader_compile_info *compile_info,
}
else
{
- ret = vkd3d_shader_parser_compile(parser, compile_info, out, &message_context);
+ ret = vsir_program_compile(&parser->program, parser->config_flags, compile_info, out, &message_context);
vkd3d_shader_parser_destroy(parser);
}
}
diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
index 4434e6e98f2..07b5818cba9 100644
--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
@@ -527,6 +527,9 @@ enum vkd3d_shader_opcode
VKD3DSIH_UTOD,
VKD3DSIH_UTOF,
VKD3DSIH_UTOU,
+ VKD3DSIH_WAVE_ACTIVE_ALL_EQUAL,
+ VKD3DSIH_WAVE_ALL_TRUE,
+ VKD3DSIH_WAVE_ANY_TRUE,
VKD3DSIH_XOR,
VKD3DSIH_INVALID,
@@ -590,6 +593,8 @@ enum vkd3d_shader_register_type
VKD3DSPR_OUTSTENCILREF,
VKD3DSPR_UNDEF,
VKD3DSPR_SSA,
+ VKD3DSPR_WAVELANECOUNT,
+ VKD3DSPR_WAVELANEINDEX,
VKD3DSPR_COUNT,
@@ -1061,14 +1066,6 @@ struct dxbc_shader_desc
struct shader_signature patch_constant_signature;
};
-struct vkd3d_shader_desc
-{
- struct
- {
- uint32_t used, external;
- } flat_constant_count[3];
-};
-
struct vkd3d_shader_register_semantic
{
struct vkd3d_shader_dst_param reg;
@@ -1249,6 +1246,12 @@ static inline bool register_is_scalar_constant_zero(const struct vkd3d_shader_re
&& (data_type_is_64_bit(reg->data_type) ? !reg->u.immconst_u64[0] : !reg->u.immconst_u32[0]);
}
+static inline bool register_is_numeric_array(const struct vkd3d_shader_register *reg)
+{
+ return (reg->type == VKD3DSPR_IMMCONSTBUFFER || reg->type == VKD3DSPR_IDXTEMP
+ || reg->type == VKD3DSPR_GROUPSHAREDMEM);
+}
+
static inline bool vsir_register_is_label(const struct vkd3d_shader_register *reg)
{
return reg->type == VKD3DSPR_LABEL;
@@ -1332,6 +1335,7 @@ struct vsir_program
struct shader_signature patch_constant_signature;
unsigned int input_control_point_count, output_control_point_count;
+ unsigned int flat_constant_count[3];
unsigned int block_count;
unsigned int temp_count;
unsigned int ssa_count;
@@ -1341,8 +1345,11 @@ struct vsir_program
size_t block_name_count;
};
-bool vsir_program_init(struct vsir_program *program, const struct vkd3d_shader_version *version, unsigned int reserve);
void vsir_program_cleanup(struct vsir_program *program);
+int vsir_program_compile(struct vsir_program *program, uint64_t config_flags,
+ const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_code *out,
+ struct vkd3d_shader_message_context *message_context);
+bool vsir_program_init(struct vsir_program *program, const struct vkd3d_shader_version *version, unsigned int reserve);
enum vkd3d_result vsir_program_normalise(struct vsir_program *program, uint64_t config_flags,
const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_message_context *message_context);
enum vkd3d_result vsir_program_validate(struct vsir_program *program, uint64_t config_flags,
@@ -1366,7 +1373,6 @@ struct vkd3d_shader_parser
struct vkd3d_shader_location location;
bool failed;
- struct vkd3d_shader_desc shader_desc;
const struct vkd3d_shader_parser_ops *ops;
struct vsir_program program;
@@ -1378,9 +1384,6 @@ struct vkd3d_shader_parser_ops
void (*parser_destroy)(struct vkd3d_shader_parser *parser);
};
-int vkd3d_shader_parser_compile(struct vkd3d_shader_parser *parser,
- const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_code *out,
- struct vkd3d_shader_message_context *message_context);
void vkd3d_shader_parser_error(struct vkd3d_shader_parser *parser,
enum vkd3d_shader_error error, const char *format, ...) VKD3D_PRINTF_FUNC(3, 4);
bool vkd3d_shader_parser_init(struct vkd3d_shader_parser *parser,
@@ -1552,7 +1555,7 @@ int glsl_compile(struct vsir_program *program, uint64_t config_flags,
#define SPIRV_MAX_SRC_COUNT 6
-int spirv_compile(struct vkd3d_shader_parser *parser,
+int spirv_compile(struct vsir_program *program, uint64_t config_flags,
const struct vkd3d_shader_scan_descriptor_info1 *scan_descriptor_info,
const struct vkd3d_shader_compile_info *compile_info,
struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context);
diff --git a/libs/vkd3d/libs/vkd3d/command.c b/libs/vkd3d/libs/vkd3d/command.c
index 4a69ff530da..95366d3441b 100644
--- a/libs/vkd3d/libs/vkd3d/command.c
+++ b/libs/vkd3d/libs/vkd3d/command.c
@@ -2052,20 +2052,15 @@ static bool vk_barrier_parameters_from_d3d12_resource_state(unsigned int state,
* state when GPU finishes execution of a command list. */
if (is_swapchain_image)
{
- if (resource->present_state == D3D12_RESOURCE_STATE_PRESENT)
- {
- *access_mask = VK_ACCESS_MEMORY_READ_BIT;
- *stage_flags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
- if (image_layout)
- *image_layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
- return true;
- }
- else if (resource->present_state != D3D12_RESOURCE_STATE_COMMON)
- {
- vk_barrier_parameters_from_d3d12_resource_state(resource->present_state, 0,
+ if (resource->present_state != D3D12_RESOURCE_STATE_PRESENT)
+ return vk_barrier_parameters_from_d3d12_resource_state(resource->present_state, 0,
resource, vk_queue_flags, vk_info, access_mask, stage_flags, image_layout);
- return true;
- }
+
+ *access_mask = VK_ACCESS_MEMORY_READ_BIT;
+ *stage_flags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ if (image_layout)
+ *image_layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
+ return true;
}
*access_mask = VK_ACCESS_HOST_READ_BIT | VK_ACCESS_HOST_WRITE_BIT;
diff --git a/libs/vkd3d/libs/vkd3d/device.c b/libs/vkd3d/libs/vkd3d/device.c
index cb2b6ad0364..3f3332dd3e3 100644
--- a/libs/vkd3d/libs/vkd3d/device.c
+++ b/libs/vkd3d/libs/vkd3d/device.c
@@ -788,6 +788,11 @@ VkInstance vkd3d_instance_get_vk_instance(struct vkd3d_instance *instance)
return instance->vk_instance;
}
+static bool d3d12_device_environment_is_vulkan_min_1_1(struct d3d12_device *device)
+{
+ return device->environment == VKD3D_SHADER_SPIRV_ENVIRONMENT_VULKAN_1_1;
+}
+
struct vkd3d_physical_device_info
{
/* properties */
@@ -796,6 +801,7 @@ struct vkd3d_physical_device_info
VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT texel_buffer_alignment_properties;
VkPhysicalDeviceTransformFeedbackPropertiesEXT xfb_properties;
VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT vertex_divisor_properties;
+ VkPhysicalDeviceSubgroupProperties subgroup_properties;
VkPhysicalDeviceProperties2KHR properties2;
@@ -838,6 +844,7 @@ static void vkd3d_physical_device_info_init(struct vkd3d_physical_device_info *i
VkPhysicalDevice4444FormatsFeaturesEXT *formats4444_features;
VkPhysicalDeviceTransformFeedbackFeaturesEXT *xfb_features;
struct vkd3d_vulkan_info *vulkan_info = &device->vk_info;
+ VkPhysicalDeviceSubgroupProperties *subgroup_properties;
memset(info, 0, sizeof(*info));
conditional_rendering_features = &info->conditional_rendering_features;
@@ -857,6 +864,7 @@ static void vkd3d_physical_device_info_init(struct vkd3d_physical_device_info *i
formats4444_features = &info->formats4444_features;
xfb_features = &info->xfb_features;
xfb_properties = &info->xfb_properties;
+ subgroup_properties = &info->subgroup_properties;
info->features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
@@ -902,6 +910,9 @@ static void vkd3d_physical_device_info_init(struct vkd3d_physical_device_info *i
vk_prepend_struct(&info->properties2, xfb_properties);
vertex_divisor_properties->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT;
vk_prepend_struct(&info->properties2, vertex_divisor_properties);
+ subgroup_properties->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES;
+ if (d3d12_device_environment_is_vulkan_min_1_1(device))
+ vk_prepend_struct(&info->properties2, subgroup_properties);
if (vulkan_info->KHR_get_physical_device_properties2)
VK_CALL(vkGetPhysicalDeviceProperties2KHR(physical_device, &info->properties2));
@@ -1509,6 +1520,7 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device,
struct vkd3d_physical_device_info *physical_device_info,
uint32_t *device_extension_count, bool **user_extension_supported)
{
+ const VkPhysicalDeviceSubgroupProperties *subgroup_properties = &physical_device_info->subgroup_properties;
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;
@@ -1520,6 +1532,16 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device,
uint32_t count;
VkResult vr;
+ /* SHUFFLE is required to implement WaveReadLaneAt with dynamically uniform index before SPIR-V 1.5 / Vulkan 1.2. */
+ static const VkSubgroupFeatureFlags required_subgroup_features = VK_SUBGROUP_FEATURE_ARITHMETIC_BIT
+ | VK_SUBGROUP_FEATURE_BASIC_BIT
+ | VK_SUBGROUP_FEATURE_BALLOT_BIT
+ | VK_SUBGROUP_FEATURE_SHUFFLE_BIT
+ | VK_SUBGROUP_FEATURE_QUAD_BIT
+ | VK_SUBGROUP_FEATURE_VOTE_BIT;
+
+ static const VkSubgroupFeatureFlags required_stages = VK_SHADER_STAGE_COMPUTE_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
+
*device_extension_count = 0;
vkd3d_trace_physical_device(physical_device, physical_device_info, vk_procs);
@@ -1583,10 +1605,12 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device,
device->feature_options.ResourceHeapTier = D3D12_RESOURCE_HEAP_TIER_2;
/* Shader Model 6 support. */
- device->feature_options1.WaveOps = FALSE;
- device->feature_options1.WaveLaneCountMin = 0;
- device->feature_options1.WaveLaneCountMax = 0;
- device->feature_options1.TotalLaneCount = 0;
+ device->feature_options1.WaveOps = subgroup_properties->subgroupSize >= 4
+ && (subgroup_properties->supportedOperations & required_subgroup_features) == required_subgroup_features
+ && (subgroup_properties->supportedStages & required_stages) == required_stages;
+ device->feature_options1.WaveLaneCountMin = subgroup_properties->subgroupSize;
+ device->feature_options1.WaveLaneCountMax = subgroup_properties->subgroupSize;
+ device->feature_options1.TotalLaneCount = 32 * subgroup_properties->subgroupSize; /* approx. */
device->feature_options1.ExpandedComputeResourceStates = TRUE;
device->feature_options1.Int64ShaderOps = features->shaderInt64;
@@ -3434,7 +3458,11 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CheckFeatureSupport(ID3D12Device9
TRACE("Request shader model %#x.\n", data->HighestShaderModel);
+#ifdef VKD3D_SHADER_UNSUPPORTED_DXIL
+ data->HighestShaderModel = D3D_SHADER_MODEL_6_0;
+#else
data->HighestShaderModel = D3D_SHADER_MODEL_5_1;
+#endif
TRACE("Shader model %#x.\n", data->HighestShaderModel);
return S_OK;
diff --git a/libs/vkd3d/libs/vkd3d/state.c b/libs/vkd3d/libs/vkd3d/state.c
index 6ba29c18004..199d8043ffe 100644
--- a/libs/vkd3d/libs/vkd3d/state.c
+++ b/libs/vkd3d/libs/vkd3d/state.c
@@ -2159,6 +2159,8 @@ static unsigned int feature_flags_compile_option(const struct d3d12_device *devi
flags |= VKD3D_SHADER_COMPILE_OPTION_FEATURE_INT64;
if (device->feature_options.DoublePrecisionFloatShaderOps)
flags |= VKD3D_SHADER_COMPILE_OPTION_FEATURE_FLOAT64;
+ if (device->feature_options1.WaveOps)
+ flags |= VKD3D_SHADER_COMPILE_OPTION_FEATURE_WAVE_OPS;
return flags;
}
--
2.43.0