wine-staging/patches/vkd3d-latest/0004-Updated-vkd3d-to-13e1491941a1af32ddfc1019fa304231fd1.patch

954 lines
33 KiB
Diff
Raw Normal View History

2024-05-02 14:37:38 -07:00
From 669446d32104b9a4b879f5cb2ad46a964606fa70 Mon Sep 17 00:00:00 2001
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
Date: Sun, 28 Apr 2024 09:46:44 +1000
Subject: [PATCH] Updated vkd3d to 13e1491941a1af32ddfc1019fa304231fd121c4d.
---
libs/vkd3d/include/private/vkd3d_common.h | 63 +++++++
libs/vkd3d/include/vkd3d_types.h | 6 +
libs/vkd3d/libs/vkd3d-common/blob.c | 3 +
libs/vkd3d/libs/vkd3d-common/error.c | 6 +
libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 61 ++++++-
libs/vkd3d/libs/vkd3d-shader/ir.c | 122 +++++++++++++-
libs/vkd3d/libs/vkd3d/cache.c | 195 ++++++++++++++++++++++
libs/vkd3d/libs/vkd3d/device.c | 36 +++-
libs/vkd3d/libs/vkd3d/resource.c | 24 +--
libs/vkd3d/libs/vkd3d/vkd3d_main.c | 2 +-
libs/vkd3d/libs/vkd3d/vkd3d_private.h | 92 ++--------
11 files changed, 497 insertions(+), 113 deletions(-)
diff --git a/libs/vkd3d/include/private/vkd3d_common.h b/libs/vkd3d/include/private/vkd3d_common.h
index b0e9230dab6..2d950b4f7aa 100644
--- a/libs/vkd3d/include/private/vkd3d_common.h
+++ b/libs/vkd3d/include/private/vkd3d_common.h
@@ -340,6 +340,11 @@ static inline int vkd3d_u32_compare(uint32_t x, uint32_t y)
return (x > y) - (x < y);
}
+static inline int vkd3d_u64_compare(uint64_t x, uint64_t y)
+{
+ return (x > y) - (x < y);
+}
+
#define VKD3D_BITMAP_SIZE(x) (((x) + 0x1f) >> 5)
static inline bool bitmap_clear(uint32_t *map, unsigned int idx)
@@ -431,6 +436,64 @@ static inline uint32_t vkd3d_atomic_increment_u32(uint32_t volatile *x)
return vkd3d_atomic_add_fetch_u32(x, 1);
}
+static inline bool vkd3d_atomic_compare_exchange_u32(uint32_t volatile *x, uint32_t expected, uint32_t val)
+{
+#if HAVE_SYNC_BOOL_COMPARE_AND_SWAP
+ return __sync_bool_compare_and_swap(x, expected, val);
+#elif defined(_WIN32)
+ return InterlockedCompareExchange((LONG *)x, val, expected) == expected;
+#else
+# error "vkd3d_atomic_compare_exchange_u32() not implemented for this platform"
+#endif
+}
+
+static inline bool vkd3d_atomic_compare_exchange_ptr(void * volatile *x, void *expected, void *val)
+{
+#if HAVE_SYNC_BOOL_COMPARE_AND_SWAP
+ return __sync_bool_compare_and_swap(x, expected, val);
+#elif defined(_WIN32)
+ return InterlockedCompareExchangePointer(x, val, expected) == expected;
+#else
+# error "vkd3d_atomic_compare_exchange_ptr() not implemented for this platform"
+#endif
+}
+
+static inline uint32_t vkd3d_atomic_exchange_u32(uint32_t volatile *x, uint32_t val)
+{
+#if HAVE_ATOMIC_EXCHANGE_N
+ return __atomic_exchange_n(x, val, __ATOMIC_SEQ_CST);
+#elif defined(_WIN32)
+ return InterlockedExchange((LONG *)x, val);
+#else
+ uint32_t expected;
+
+ do
+ {
+ expected = *x;
+ } while (!vkd3d_atomic_compare_exchange_u32(x, expected, val));
+
+ return expected;
+#endif
+}
+
+static inline void *vkd3d_atomic_exchange_ptr(void * volatile *x, void *val)
+{
+#if HAVE_ATOMIC_EXCHANGE_N
+ return __atomic_exchange_n(x, val, __ATOMIC_SEQ_CST);
+#elif defined(_WIN32)
+ return InterlockedExchangePointer(x, val);
+#else
+ void *expected;
+
+ do
+ {
+ expected = *x;
+ } while (!vkd3d_atomic_compare_exchange_ptr(x, expected, val));
+
+ return expected;
+#endif
+}
+
struct vkd3d_mutex
{
#ifdef _WIN32
diff --git a/libs/vkd3d/include/vkd3d_types.h b/libs/vkd3d/include/vkd3d_types.h
index 017eaf11806..dc5a7c064ae 100644
--- a/libs/vkd3d/include/vkd3d_types.h
+++ b/libs/vkd3d/include/vkd3d_types.h
@@ -53,6 +53,12 @@ enum vkd3d_result
VKD3D_ERROR_INVALID_SHADER = -4,
/** The operation is not implemented in this version of vkd3d. */
VKD3D_ERROR_NOT_IMPLEMENTED = -5,
+ /** The object or entry already exists. \since 1.12 */
+ VKD3D_ERROR_KEY_ALREADY_EXISTS = -6,
+ /** The requested object was not found. \since 1.12 */
+ VKD3D_ERROR_NOT_FOUND = -7,
+ /** The output buffer is larger than the requested object \since 1.12. */
+ VKD3D_ERROR_MORE_DATA = -8,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_RESULT),
};
diff --git a/libs/vkd3d/libs/vkd3d-common/blob.c b/libs/vkd3d/libs/vkd3d-common/blob.c
index 6bc95dc55c4..c2c6ad67804 100644
--- a/libs/vkd3d/libs/vkd3d-common/blob.c
+++ b/libs/vkd3d/libs/vkd3d-common/blob.c
@@ -16,6 +16,9 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+#ifndef __MINGW32__
+#define WIDL_C_INLINE_WRAPPERS
+#endif
#define COBJMACROS
#define CONST_VTABLE
diff --git a/libs/vkd3d/libs/vkd3d-common/error.c b/libs/vkd3d/libs/vkd3d-common/error.c
index b8350a5404c..2f978c4977d 100644
--- a/libs/vkd3d/libs/vkd3d-common/error.c
+++ b/libs/vkd3d/libs/vkd3d-common/error.c
@@ -35,6 +35,12 @@ HRESULT hresult_from_vkd3d_result(int vkd3d_result)
return E_INVALIDARG;
case VKD3D_ERROR_NOT_IMPLEMENTED:
return E_NOTIMPL;
+ case VKD3D_ERROR_KEY_ALREADY_EXISTS:
+ return DXGI_ERROR_ALREADY_EXISTS;
+ case VKD3D_ERROR_NOT_FOUND:
+ return DXGI_ERROR_NOT_FOUND;
+ case VKD3D_ERROR_MORE_DATA:
+ return DXGI_ERROR_MORE_DATA;
default:
FIXME("Unhandled vkd3d result %d.\n", vkd3d_result);
return E_FAIL;
diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
index 55d9ecf707d..09e4f596241 100644
--- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
+++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
@@ -1813,6 +1813,7 @@ static uint32_t sm1_encode_register_type(D3DSHADER_PARAM_REGISTER_TYPE type)
struct sm1_instruction
{
D3DSHADER_INSTRUCTION_OPCODE_TYPE opcode;
+ unsigned int flags;
struct sm1_dst_register
{
@@ -1852,6 +1853,8 @@ static void write_sm1_instruction(struct hlsl_ctx *ctx, struct vkd3d_bytecode_bu
uint32_t token = instr->opcode;
unsigned int i;
+ token |= VKD3D_SM1_INSTRUCTION_FLAGS_MASK & (instr->flags << VKD3D_SM1_INSTRUCTION_FLAGS_SHIFT);
+
if (ctx->profile->major_version > 1)
token |= (instr->has_dst + instr->src_count) << D3DSI_INSTLENGTH_SHIFT;
put_u32(buffer, token);
@@ -2414,6 +2417,49 @@ static void write_sm1_expr(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b
}
}
+static void write_sm1_block(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer,
+ const struct hlsl_block *block);
+
+static void write_sm1_if(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer, const struct hlsl_ir_node *instr)
+{
+ const struct hlsl_ir_if *iff = hlsl_ir_if(instr);
+ const struct hlsl_ir_node *condition;
+ struct sm1_instruction sm1_ifc, sm1_else, sm1_endif;
+
+ condition = iff->condition.node;
+ assert(condition->data_type->dimx == 1 && condition->data_type->dimy == 1);
+
+ sm1_ifc = (struct sm1_instruction)
+ {
+ .opcode = D3DSIO_IFC,
+ .flags = VKD3D_SHADER_REL_OP_NE, /* Make it a "if_ne" instruction. */
+
+ .srcs[0].type = D3DSPR_TEMP,
+ .srcs[0].swizzle = hlsl_swizzle_from_writemask(condition->reg.writemask),
+ .srcs[0].reg = condition->reg.id,
+ .srcs[0].mod = 0,
+
+ .srcs[1].type = D3DSPR_TEMP,
+ .srcs[1].swizzle = hlsl_swizzle_from_writemask(condition->reg.writemask),
+ .srcs[1].reg = condition->reg.id,
+ .srcs[1].mod = D3DSPSM_NEG,
+
+ .src_count = 2,
+ };
+ write_sm1_instruction(ctx, buffer, &sm1_ifc);
+ write_sm1_block(ctx, buffer, &iff->then_block);
+
+ if (!list_empty(&iff->else_block.instrs))
+ {
+ sm1_else = (struct sm1_instruction){.opcode = D3DSIO_ELSE};
+ write_sm1_instruction(ctx, buffer, &sm1_else);
+ write_sm1_block(ctx, buffer, &iff->else_block);
+ }
+
+ sm1_endif = (struct sm1_instruction){.opcode = D3DSIO_ENDIF};
+ write_sm1_instruction(ctx, buffer, &sm1_endif);
+}
+
static void write_sm1_jump(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer, const struct hlsl_ir_node *instr)
{
const struct hlsl_ir_jump *jump = hlsl_ir_jump(instr);
@@ -2614,12 +2660,12 @@ static void write_sm1_swizzle(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer
write_sm1_instruction(ctx, buffer, &sm1_instr);
}
-static void write_sm1_instructions(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer,
- const struct hlsl_ir_function_decl *entry_func)
+static void write_sm1_block(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer,
+ const struct hlsl_block *block)
{
const struct hlsl_ir_node *instr;
- LIST_FOR_EACH_ENTRY(instr, &entry_func->body.instrs, struct hlsl_ir_node, entry)
+ LIST_FOR_EACH_ENTRY(instr, &block->instrs, struct hlsl_ir_node, entry)
{
if (instr->data_type)
{
@@ -2643,6 +2689,13 @@ static void write_sm1_instructions(struct hlsl_ctx *ctx, struct vkd3d_bytecode_b
write_sm1_expr(ctx, buffer, instr);
break;
+ case HLSL_IR_IF:
+ if (hlsl_version_ge(ctx, 2, 1))
+ write_sm1_if(ctx, buffer, instr);
+ else
+ hlsl_fixme(ctx, &instr->loc, "Flatten \"if\" conditionals branches.");
+ break;
+
case HLSL_IR_JUMP:
write_sm1_jump(ctx, buffer, instr);
break;
@@ -2680,7 +2733,7 @@ int hlsl_sm1_write(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_fun
write_sm1_constant_defs(ctx, &buffer);
write_sm1_semantic_dcls(ctx, &buffer);
write_sm1_sampler_dcls(ctx, &buffer);
- write_sm1_instructions(ctx, &buffer, entry_func);
+ write_sm1_block(ctx, &buffer, &entry_func->body);
put_u32(&buffer, D3DSIO_END);
diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c
index 59b74c065d8..121b0fe3a6c 100644
--- a/libs/vkd3d/libs/vkd3d-shader/ir.c
+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c
@@ -82,6 +82,106 @@ static bool vsir_instruction_init_with_params(struct vsir_program *program,
return true;
}
+static bool get_opcode_from_rel_op(enum vkd3d_shader_rel_op rel_op, enum vkd3d_data_type data_type,
+ enum vkd3d_shader_opcode *opcode, bool *requires_swap)
+{
+ switch (rel_op)
+ {
+ case VKD3D_SHADER_REL_OP_LT:
+ case VKD3D_SHADER_REL_OP_GT:
+ *requires_swap = (rel_op == VKD3D_SHADER_REL_OP_GT);
+ if (data_type == VKD3D_DATA_FLOAT)
+ {
+ *opcode = VKD3DSIH_LTO;
+ return true;
+ }
+ break;
+
+ case VKD3D_SHADER_REL_OP_GE:
+ case VKD3D_SHADER_REL_OP_LE:
+ *requires_swap = (rel_op == VKD3D_SHADER_REL_OP_LE);
+ if (data_type == VKD3D_DATA_FLOAT)
+ {
+ *opcode = VKD3DSIH_GEO;
+ return true;
+ }
+ break;
+
+ case VKD3D_SHADER_REL_OP_EQ:
+ *requires_swap = false;
+ if (data_type == VKD3D_DATA_FLOAT)
+ {
+ *opcode = VKD3DSIH_EQO;
+ return true;
+ }
+ break;
+
+ case VKD3D_SHADER_REL_OP_NE:
+ *requires_swap = false;
+ if (data_type == VKD3D_DATA_FLOAT)
+ {
+ *opcode = VKD3DSIH_NEO;
+ return true;
+ }
+ break;
+ }
+ return false;
+}
+
+static enum vkd3d_result vsir_program_lower_ifc(struct vsir_program *program,
+ struct vkd3d_shader_instruction *ifc, unsigned int *tmp_idx,
+ struct vkd3d_shader_message_context *message_context)
+{
+ struct vkd3d_shader_instruction_array *instructions = &program->instructions;
+ size_t pos = ifc - instructions->elements;
+ struct vkd3d_shader_instruction *ins;
+ enum vkd3d_shader_opcode opcode;
+ bool swap;
+
+ if (!shader_instruction_array_insert_at(instructions, pos + 1, 2))
+ return VKD3D_ERROR_OUT_OF_MEMORY;
+
+ if (*tmp_idx == ~0u)
+ *tmp_idx = program->temp_count++;
+
+ /* Replace ifc comparison with actual comparison, saving the result in the tmp register. */
+ if (!(get_opcode_from_rel_op(ifc->flags, ifc->src[0].reg.data_type, &opcode, &swap)))
+ {
+ vkd3d_shader_error(message_context, &ifc->location, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED,
+ "Aborting due to not yet implemented feature: opcode for rel_op %u and data type %u.",
+ ifc->flags, ifc->src[0].reg.data_type);
+ return VKD3D_ERROR_NOT_IMPLEMENTED;
+ }
+
+ ins = &instructions->elements[pos + 1];
+ if (!vsir_instruction_init_with_params(program, ins, &ifc->location, opcode, 1, 2))
+ return VKD3D_ERROR_OUT_OF_MEMORY;
+
+ vsir_register_init(&ins->dst[0].reg, VKD3DSPR_TEMP, VKD3D_DATA_UINT, 1);
+ ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4;
+ ins->dst[0].reg.idx[0].offset = *tmp_idx;
+ ins->dst[0].write_mask = VKD3DSP_WRITEMASK_0;
+
+ ins->src[0] = ifc->src[swap];
+ ins->src[1] = ifc->src[!swap];
+
+ /* Create new if instruction using the previous result. */
+ ins = &instructions->elements[pos + 2];
+ if (!vsir_instruction_init_with_params(program, ins, &ifc->location, VKD3DSIH_IF, 0, 1))
+ return VKD3D_ERROR_OUT_OF_MEMORY;
+ ins->flags = VKD3D_SHADER_CONDITIONAL_OP_NZ;
+
+ vsir_register_init(&ins->src[0].reg, VKD3DSPR_TEMP, VKD3D_DATA_UINT, 1);
+ ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4;
+ ins->src[0].reg.idx[0].offset = *tmp_idx;
+ ins->src[0].swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X);
+
+ /* Make the original instruction no-op */
+ vkd3d_shader_instruction_make_nop(ifc);
+
+ return VKD3D_OK;
+}
+
static enum vkd3d_result vsir_program_lower_texkill(struct vsir_program *program,
struct vkd3d_shader_instruction *texkill, unsigned int *tmp_idx)
{
@@ -210,7 +310,8 @@ static enum vkd3d_result vsir_program_lower_precise_mad(struct vsir_program *pro
return VKD3D_OK;
}
-static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *program)
+static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *program,
+ struct vkd3d_shader_message_context *message_context)
{
struct vkd3d_shader_instruction_array *instructions = &program->instructions;
unsigned int tmp_idx = ~0u, i;
@@ -222,6 +323,11 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr
switch (ins->handler_idx)
{
+ case VKD3DSIH_IFC:
+ if ((ret = vsir_program_lower_ifc(program, ins, &tmp_idx, message_context)) < 0)
+ return ret;
+ break;
+
case VKD3DSIH_TEXKILL:
if ((ret = vsir_program_lower_texkill(program, ins, &tmp_idx)) < 0)
return ret;
@@ -4992,12 +5098,12 @@ static void register_map_undominated_use(struct vkd3d_shader_register *reg, stru
{
unsigned int i;
- if (!register_is_ssa(reg))
- return;
-
- i = reg->idx[0].offset;
- if (alloc->table[i] == UINT_MAX && !vsir_block_dominates(origin_blocks[i], block))
- alloc->table[i] = alloc->next_temp_idx++;
+ if (register_is_ssa(reg))
+ {
+ i = reg->idx[0].offset;
+ if (alloc->table[i] == UINT_MAX && !vsir_block_dominates(origin_blocks[i], block))
+ alloc->table[i] = alloc->next_temp_idx++;
+ }
for (i = 0; i < reg->idx_count; ++i)
if (reg->idx[i].rel_addr)
@@ -6056,7 +6162,7 @@ enum vkd3d_result vsir_program_normalise(struct vsir_program *program, uint64_t
{
enum vkd3d_result result = VKD3D_OK;
- if ((result = vsir_program_lower_instructions(program)) < 0)
+ if ((result = vsir_program_lower_instructions(program, message_context)) < 0)
return result;
if (program->shader_version.major >= 6)
diff --git a/libs/vkd3d/libs/vkd3d/cache.c b/libs/vkd3d/libs/vkd3d/cache.c
index 56ba6990420..a0a29ed30cb 100644
--- a/libs/vkd3d/libs/vkd3d/cache.c
+++ b/libs/vkd3d/libs/vkd3d/cache.c
@@ -18,11 +18,60 @@
#include "vkd3d_private.h"
+struct vkd3d_cache_entry_header
+{
+ uint64_t hash;
+ uint64_t key_size;
+ uint64_t value_size;
+};
+
struct vkd3d_shader_cache
{
unsigned int refcount;
+ struct vkd3d_mutex lock;
+
+ struct rb_tree tree;
};
+struct shader_cache_entry
+{
+ struct vkd3d_cache_entry_header h;
+ struct rb_entry entry;
+ uint8_t *payload;
+};
+
+struct shader_cache_key
+{
+ uint64_t hash;
+ const void *key;
+ uint64_t key_size;
+};
+
+static int vkd3d_shader_cache_compare_key(const void *key, const struct rb_entry *entry)
+{
+ const struct shader_cache_entry *e = RB_ENTRY_VALUE(entry, struct shader_cache_entry, entry);
+ const struct shader_cache_key *k = key;
+ int ret;
+
+ if ((ret = vkd3d_u64_compare(k->hash, e->h.hash)))
+ return ret;
+ if ((ret = vkd3d_u64_compare(k->key_size, e->h.key_size)))
+ return ret;
+
+ /* Until now we have not seen an actual hash collision. If the key didn't match it was always
+ * due to a bug in the serialization code or memory corruption. If you see this FIXME please
+ * investigate. */
+ if ((ret = memcmp(k->key, e->payload, k->key_size)))
+ FIXME("Actual case of a hash collision found.\n");
+ return ret;
+}
+
+static void vkd3d_shader_cache_add_entry(struct vkd3d_shader_cache *cache,
+ struct shader_cache_entry *e)
+{
+ rb_put(&cache->tree, &e->h.hash, &e->entry);
+}
+
int vkd3d_shader_open_cache(struct vkd3d_shader_cache **cache)
{
struct vkd3d_shader_cache *object;
@@ -34,6 +83,9 @@ int vkd3d_shader_open_cache(struct vkd3d_shader_cache **cache)
return VKD3D_ERROR_OUT_OF_MEMORY;
object->refcount = 1;
+ rb_init(&object->tree, vkd3d_shader_cache_compare_key);
+ vkd3d_mutex_init(&object->lock);
+
*cache = object;
return VKD3D_OK;
@@ -46,6 +98,13 @@ unsigned int vkd3d_shader_cache_incref(struct vkd3d_shader_cache *cache)
return refcount;
}
+static void vkd3d_shader_cache_destroy_entry(struct rb_entry *entry, void *context)
+{
+ struct shader_cache_entry *e = RB_ENTRY_VALUE(entry, struct shader_cache_entry, entry);
+ vkd3d_free(e->payload);
+ vkd3d_free(e);
+}
+
unsigned int vkd3d_shader_cache_decref(struct vkd3d_shader_cache *cache)
{
unsigned int refcount = vkd3d_atomic_decrement_u32(&cache->refcount);
@@ -54,6 +113,142 @@ unsigned int vkd3d_shader_cache_decref(struct vkd3d_shader_cache *cache)
if (refcount)
return refcount;
+ rb_destroy(&cache->tree, vkd3d_shader_cache_destroy_entry, NULL);
+ vkd3d_mutex_destroy(&cache->lock);
+
vkd3d_free(cache);
return 0;
}
+
+static uint64_t vkd3d_shader_cache_hash_key(const void *key, size_t size)
+{
+ static const uint64_t fnv_prime = 0x00000100000001b3;
+ uint64_t hash = 0xcbf29ce484222325;
+ const uint8_t *k = key;
+ size_t i;
+
+ for (i = 0; i < size; ++i)
+ hash = (hash ^ k[i]) * fnv_prime;
+
+ return hash;
+}
+
+static void vkd3d_shader_cache_lock(struct vkd3d_shader_cache *cache)
+{
+ vkd3d_mutex_lock(&cache->lock);
+}
+
+static void vkd3d_shader_cache_unlock(struct vkd3d_shader_cache *cache)
+{
+ vkd3d_mutex_unlock(&cache->lock);
+}
+
+int vkd3d_shader_cache_put(struct vkd3d_shader_cache *cache,
+ const void *key, size_t key_size, const void *value, size_t value_size)
+{
+ struct shader_cache_entry *e;
+ struct shader_cache_key k;
+ struct rb_entry *entry;
+ enum vkd3d_result ret;
+
+ TRACE("%p, %p, %#zx, %p, %#zx.\n", cache, key, key_size, value, value_size);
+
+ k.hash = vkd3d_shader_cache_hash_key(key, key_size);
+ k.key = key;
+ k.key_size = key_size;
+
+ vkd3d_shader_cache_lock(cache);
+
+ entry = rb_get(&cache->tree, &k);
+ e = entry ? RB_ENTRY_VALUE(entry, struct shader_cache_entry, entry) : NULL;
+
+ if (e)
+ {
+ WARN("Key already exists, returning VKD3D_ERROR_KEY_ALREADY_EXISTS.\n");
+ ret = VKD3D_ERROR_KEY_ALREADY_EXISTS;
+ goto done;
+ }
+
+ e = vkd3d_malloc(sizeof(*e));
+ if (!e)
+ {
+ ret = VKD3D_ERROR_OUT_OF_MEMORY;
+ goto done;
+ }
+ e->payload = vkd3d_malloc(key_size + value_size);
+ if (!e->payload)
+ {
+ vkd3d_free(e);
+ ret = VKD3D_ERROR_OUT_OF_MEMORY;
+ goto done;
+ }
+
+ e->h.key_size = key_size;
+ e->h.value_size = value_size;
+ e->h.hash = k.hash;
+ memcpy(e->payload, key, key_size);
+ memcpy(e->payload + key_size, value, value_size);
+
+ vkd3d_shader_cache_add_entry(cache, e);
+ TRACE("Cache entry %#"PRIx64" stored.\n", k.hash);
+ ret = VKD3D_OK;
+
+done:
+ vkd3d_shader_cache_unlock(cache);
+ return ret;
+}
+
+int vkd3d_shader_cache_get(struct vkd3d_shader_cache *cache,
+ const void *key, size_t key_size, void *value, size_t *value_size)
+{
+ struct shader_cache_entry *e;
+ struct shader_cache_key k;
+ struct rb_entry *entry;
+ enum vkd3d_result ret;
+ size_t size_in;
+
+ TRACE("%p, %p, %#zx, %p, %p.\n", cache, key, key_size, value, value_size);
+
+ size_in = *value_size;
+
+ k.hash = vkd3d_shader_cache_hash_key(key, key_size);
+ k.key = key;
+ k.key_size = key_size;
+
+ vkd3d_shader_cache_lock(cache);
+
+ entry = rb_get(&cache->tree, &k);
+ if (!entry)
+ {
+ WARN("Entry not found.\n");
+ ret = VKD3D_ERROR_NOT_FOUND;
+ goto done;
+ }
+
+ e = RB_ENTRY_VALUE(entry, struct shader_cache_entry, entry);
+
+ *value_size = e->h.value_size;
+ if (!value)
+ {
+ TRACE("Found item %#"PRIx64", returning needed size %#"PRIx64".\n",
+ e->h.hash, e->h.value_size);
+ ret = VKD3D_OK;
+ goto done;
+ }
+
+ if (size_in < e->h.value_size)
+ {
+ WARN("Output buffer is too small for item %#"PRIx64", got %#zx want %#"PRIx64".\n",
+ e->h.hash, size_in, e->h.value_size);
+ ret = VKD3D_ERROR_MORE_DATA;
+ goto done;
+ }
+
+ memcpy(value, e->payload + e->h.key_size, e->h.value_size);
+ ret = VKD3D_OK;
+ TRACE("Returning cached item %#"PRIx64".\n", e->h.hash);
+
+done:
+ vkd3d_shader_cache_unlock(cache);
+ return ret;
+}
diff --git a/libs/vkd3d/libs/vkd3d/device.c b/libs/vkd3d/libs/vkd3d/device.c
index a394e3f7592..cb2b6ad0364 100644
--- a/libs/vkd3d/libs/vkd3d/device.c
+++ b/libs/vkd3d/libs/vkd3d/device.c
@@ -2685,19 +2685,43 @@ static HRESULT STDMETHODCALLTYPE d3d12_cache_session_GetDevice(ID3D12ShaderCache
static HRESULT STDMETHODCALLTYPE d3d12_cache_session_FindValue(ID3D12ShaderCacheSession *iface,
const void *key, UINT key_size, void *value, UINT *value_size)
{
- FIXME("iface %p, key %p, key_size %#x, value %p, value_size %p stub!\n",
+ struct d3d12_cache_session *session = impl_from_ID3D12ShaderCacheSession(iface);
+ enum vkd3d_result ret;
+ size_t size;
+
+ TRACE("iface %p, key %p, key_size %#x, value %p, value_size %p.\n",
iface, key, key_size, value, value_size);
- return DXGI_ERROR_NOT_FOUND;
+ if (!value_size)
+ {
+ WARN("value_size is NULL, returning E_INVALIDARG.\n");
+ return E_INVALIDARG;
+ }
+
+ size = *value_size;
+ ret = vkd3d_shader_cache_get(session->cache, key, key_size, value, &size);
+ *value_size = size;
+
+ return hresult_from_vkd3d_result(ret);
}
static HRESULT STDMETHODCALLTYPE d3d12_cache_session_StoreValue(ID3D12ShaderCacheSession *iface,
const void *key, UINT key_size, const void *value, UINT value_size)
{
- FIXME("iface %p, key %p, key_size %#x, value %p, value_size %u stub!\n", iface, key, key_size,
- value, value_size);
+ struct d3d12_cache_session *session = impl_from_ID3D12ShaderCacheSession(iface);
+ enum vkd3d_result ret;
- return E_NOTIMPL;
+ TRACE("iface %p, key %p, key_size %#x, value %p, value_size %u.\n",
+ iface, key, key_size, value, value_size);
+
+ if (!key || !key_size || !value || !value_size)
+ {
+ WARN("Invalid input parameters, returning E_INVALIDARG.\n");
+ return E_INVALIDARG;
+ }
+
+ ret = vkd3d_shader_cache_put(session->cache, key, key_size, value, value_size);
+ return hresult_from_vkd3d_result(ret);
}
static void STDMETHODCALLTYPE d3d12_cache_session_SetDeleteOnDestroy(ID3D12ShaderCacheSession *iface)
@@ -2833,7 +2857,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_QueryInterface(ID3D12Device9 *ifac
|| IsEqualGUID(riid, &IID_ID3D12Object)
|| IsEqualGUID(riid, &IID_IUnknown))
{
- ID3D12Device_AddRef(iface);
+ ID3D12Device9_AddRef(iface);
*object = iface;
return S_OK;
}
diff --git a/libs/vkd3d/libs/vkd3d/resource.c b/libs/vkd3d/libs/vkd3d/resource.c
index 179999148bc..7a2f464c98e 100644
--- a/libs/vkd3d/libs/vkd3d/resource.c
+++ b/libs/vkd3d/libs/vkd3d/resource.c
@@ -1271,7 +1271,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_resource_QueryInterface(ID3D12Resource2 *
|| IsEqualGUID(riid, &IID_ID3D12Object)
|| IsEqualGUID(riid, &IID_IUnknown))
{
- ID3D12Resource_AddRef(iface);
+ ID3D12Resource2_AddRef(iface);
*object = iface;
return S_OK;
}
@@ -2350,16 +2350,16 @@ static void *vkd3d_desc_object_cache_get(struct vkd3d_desc_object_cache *cache)
i = vkd3d_atomic_increment_u32(&cache->next_index) & HEAD_INDEX_MASK;
for (;;)
{
- if (vkd3d_atomic_compare_exchange(&cache->heads[i].spinlock, 0, 1))
+ if (vkd3d_atomic_compare_exchange_u32(&cache->heads[i].spinlock, 0, 1))
{
if ((u.object = cache->heads[i].head))
{
vkd3d_atomic_decrement_u32(&cache->free_count);
cache->heads[i].head = u.header->next;
- vkd3d_atomic_exchange(&cache->heads[i].spinlock, 0);
+ vkd3d_atomic_exchange_u32(&cache->heads[i].spinlock, 0);
return u.object;
}
- vkd3d_atomic_exchange(&cache->heads[i].spinlock, 0);
+ vkd3d_atomic_exchange_u32(&cache->heads[i].spinlock, 0);
}
/* Keeping a free count avoids uncertainty over when this loop should terminate,
* which could result in excess allocations gradually increasing without limit. */
@@ -2381,7 +2381,7 @@ static void vkd3d_desc_object_cache_push(struct vkd3d_desc_object_cache *cache,
i = vkd3d_atomic_increment_u32(&cache->next_index) & HEAD_INDEX_MASK;
for (;;)
{
- if (vkd3d_atomic_compare_exchange(&cache->heads[i].spinlock, 0, 1))
+ if (vkd3d_atomic_compare_exchange_u32(&cache->heads[i].spinlock, 0, 1))
break;
i = (i + 1) & HEAD_INDEX_MASK;
}
@@ -2389,7 +2389,7 @@ static void vkd3d_desc_object_cache_push(struct vkd3d_desc_object_cache *cache,
head = cache->heads[i].head;
u.header->next = head;
cache->heads[i].head = u.object;
- vkd3d_atomic_exchange(&cache->heads[i].spinlock, 0);
+ vkd3d_atomic_exchange_u32(&cache->heads[i].spinlock, 0);
vkd3d_atomic_increment_u32(&cache->free_count);
}
@@ -2473,7 +2473,7 @@ void vkd3d_view_decref(void *view, struct d3d12_device *device)
static inline void d3d12_desc_replace(struct d3d12_desc *dst, void *view, struct d3d12_device *device)
{
- if ((view = vkd3d_atomic_exchange_pointer(&dst->s.u.object, view)))
+ if ((view = vkd3d_atomic_exchange_ptr(&dst->s.u.object, view)))
vkd3d_view_decref(view, device);
}
@@ -2652,7 +2652,7 @@ void d3d12_desc_flush_vk_heap_updates_locked(struct d3d12_descriptor_heap *descr
union d3d12_desc_object u;
unsigned int i, next;
- if ((i = vkd3d_atomic_exchange(&descriptor_heap->dirty_list_head, UINT_MAX)) == UINT_MAX)
+ if ((i = vkd3d_atomic_exchange_u32(&descriptor_heap->dirty_list_head, UINT_MAX)) == UINT_MAX)
return;
writes.null_vk_cbv_info.buffer = VK_NULL_HANDLE;
@@ -2667,7 +2667,7 @@ void d3d12_desc_flush_vk_heap_updates_locked(struct d3d12_descriptor_heap *descr
for (; i != UINT_MAX; i = next)
{
src = &descriptors[i];
- next = vkd3d_atomic_exchange(&src->next, 0);
+ next = vkd3d_atomic_exchange_u32(&src->next, 0);
next = (int)next >> 1;
/* A race exists here between updating src->next and getting the current object. The best
@@ -2695,13 +2695,13 @@ static void d3d12_desc_mark_as_modified(struct d3d12_desc *dst, struct d3d12_des
head = descriptor_heap->dirty_list_head;
/* Only one thread can swap the value away from zero. */
- if (!vkd3d_atomic_compare_exchange(&dst->next, 0, (head << 1) | 1))
+ if (!vkd3d_atomic_compare_exchange_u32(&dst->next, 0, (head << 1) | 1))
return;
/* Now it is safe to modify 'next' to another nonzero value if necessary. */
- while (!vkd3d_atomic_compare_exchange(&descriptor_heap->dirty_list_head, head, i))
+ while (!vkd3d_atomic_compare_exchange_u32(&descriptor_heap->dirty_list_head, head, i))
{
head = descriptor_heap->dirty_list_head;
- vkd3d_atomic_exchange(&dst->next, (head << 1) | 1);
+ vkd3d_atomic_exchange_u32(&dst->next, (head << 1) | 1);
}
}
diff --git a/libs/vkd3d/libs/vkd3d/vkd3d_main.c b/libs/vkd3d/libs/vkd3d/vkd3d_main.c
index 29305fbdc63..c7431bd821b 100644
--- a/libs/vkd3d/libs/vkd3d/vkd3d_main.c
+++ b/libs/vkd3d/libs/vkd3d/vkd3d_main.c
@@ -71,7 +71,7 @@ HRESULT vkd3d_create_device(const struct vkd3d_device_create_info *create_info,
if (!device)
{
- ID3D12Device_Release(&object->ID3D12Device9_iface);
+ ID3D12Device9_Release(&object->ID3D12Device9_iface);
return S_FALSE;
}
diff --git a/libs/vkd3d/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/libs/vkd3d/vkd3d_private.h
index 5f60c8d90ad..d1fa866d9e3 100644
--- a/libs/vkd3d/libs/vkd3d/vkd3d_private.h
+++ b/libs/vkd3d/libs/vkd3d/vkd3d_private.h
@@ -19,6 +19,9 @@
#ifndef __VKD3D_PRIVATE_H
#define __VKD3D_PRIVATE_H
+#ifndef __MINGW32__
+#define WIDL_C_INLINE_WRAPPERS
+#endif
#define COBJMACROS
#define NONAMELESSUNION
#define VK_NO_PROTOTYPES
@@ -194,93 +197,14 @@ struct vkd3d_instance
unsigned int refcount;
};
-#ifdef _WIN32
-
-union vkd3d_thread_handle
-{
- void *handle;
-};
-
-static inline bool vkd3d_atomic_compare_exchange(unsigned int volatile *x, unsigned int cmp, unsigned int xchg)
-{
- return InterlockedCompareExchange((LONG volatile *)x, xchg, cmp) == cmp;
-}
-
-static inline unsigned int vkd3d_atomic_exchange(unsigned int volatile *x, unsigned int val)
-{
- return InterlockedExchange((LONG volatile *)x, val);
-}
-
-static inline bool vkd3d_atomic_compare_exchange_pointer(void * volatile *x, void *cmp, void *xchg)
-{
- return InterlockedCompareExchangePointer(x, xchg, cmp) == cmp;
-}
-
-static inline void *vkd3d_atomic_exchange_pointer(void * volatile *x, void *val)
-{
- return InterlockedExchangePointer(x, val);
-}
-
-#else /* _WIN32 */
-
-#include <pthread.h>
-
union vkd3d_thread_handle
{
+#ifndef _WIN32
pthread_t pthread;
+#endif
void *handle;
};
-# if HAVE_SYNC_BOOL_COMPARE_AND_SWAP
-static inline bool vkd3d_atomic_compare_exchange(unsigned int volatile *x, unsigned int cmp, unsigned int xchg)
-{
- return __sync_bool_compare_and_swap(x, cmp, xchg);
-}
-
-static inline bool vkd3d_atomic_compare_exchange_pointer(void * volatile *x, void *cmp, void *xchg)
-{
- return __sync_bool_compare_and_swap(x, cmp, xchg);
-}
-# else
-# error "vkd3d_atomic_compare_exchange() not implemented for this platform"
-# endif
-
-# if HAVE_ATOMIC_EXCHANGE_N
-static inline unsigned int vkd3d_atomic_exchange(unsigned int volatile *x, unsigned int val)
-{
- return __atomic_exchange_n(x, val, __ATOMIC_SEQ_CST);
-}
-
-static inline void *vkd3d_atomic_exchange_pointer(void * volatile *x, void *val)
-{
- return __atomic_exchange_n(x, val, __ATOMIC_SEQ_CST);
-}
-# elif HAVE_SYNC_BOOL_COMPARE_AND_SWAP
-static inline unsigned int vkd3d_atomic_exchange(unsigned int volatile *x, unsigned int val)
-{
- unsigned int i;
- do
- {
- i = *x;
- } while (!__sync_bool_compare_and_swap(x, i, val));
- return i;
-}
-
-static inline void *vkd3d_atomic_exchange_pointer(void * volatile *x, void *val)
-{
- void *p;
- do
- {
- p = *x;
- } while (!__sync_bool_compare_and_swap(x, p, val));
- return p;
-}
-# else
-# error "vkd3d_atomic_exchange() not implemented for this platform"
-# endif
-
-#endif /* _WIN32 */
-
HRESULT vkd3d_create_thread(struct vkd3d_instance *instance,
PFN_vkd3d_thread thread_main, void *data, union vkd3d_thread_handle *thread);
HRESULT vkd3d_join_thread(struct vkd3d_instance *instance, union vkd3d_thread_handle *thread);
@@ -742,7 +666,7 @@ static inline bool vkd3d_view_incref(void *desc)
if (refcount <= 0)
return false;
}
- while (!vkd3d_atomic_compare_exchange(&h->refcount, refcount, refcount + 1));
+ while (!vkd3d_atomic_compare_exchange_u32(&h->refcount, refcount, refcount + 1));
return true;
}
@@ -1852,5 +1776,9 @@ struct vkd3d_shader_cache;
int vkd3d_shader_open_cache(struct vkd3d_shader_cache **cache);
unsigned int vkd3d_shader_cache_incref(struct vkd3d_shader_cache *cache);
unsigned int vkd3d_shader_cache_decref(struct vkd3d_shader_cache *cache);
+int vkd3d_shader_cache_put(struct vkd3d_shader_cache *cache,
+ const void *key, size_t key_size, const void *value, size_t value_size);
+int vkd3d_shader_cache_get(struct vkd3d_shader_cache *cache,
+ const void *key, size_t key_size, void *value, size_t *value_size);
#endif /* __VKD3D_PRIVATE_H */
--
2.43.0