Compare commits
6 Commits
master
...
atomic-cla
Author | SHA1 | Date |
---|---|---|
Joshua Ashton | d2c7e0df29 | |
Joshua Ashton | d2a35008d8 | |
Joshua Ashton | 102c2df4a4 | |
Joshua Ashton | d238653aae | |
Joshua Ashton | 1ab4cab3f4 | |
Joshua Ashton | a0d232c10c |
|
@ -27,50 +27,104 @@
|
|||
|
||||
typedef enum
|
||||
{
|
||||
memory_order_relaxed,
|
||||
memory_order_acquire,
|
||||
memory_order_release,
|
||||
memory_order_acq_rel,
|
||||
} memory_order;
|
||||
vkd3d_memory_order_relaxed,
|
||||
vkd3d_memory_order_consume,
|
||||
vkd3d_memory_order_acquire,
|
||||
vkd3d_memory_order_release,
|
||||
vkd3d_memory_order_acq_rel,
|
||||
vkd3d_memory_order_seq_cst,
|
||||
} vkd3d_memory_order;
|
||||
|
||||
# define vkd3d_atomic_rw_barrier() _ReadWriteBarrier()
|
||||
# define vkd3d_atomic_rw_barrier_acquire(order) { if (order == memory_order_acquire || order == memory_order_acq_rel) { vkd3d_atomic_rw_barrier(); } }
|
||||
# define vkd3d_atomic_rw_barrier_release(order) { if (order == memory_order_release || order == memory_order_acq_rel) { vkd3d_atomic_rw_barrier(); } }
|
||||
|
||||
FORCEINLINE uint32_t vkd3d_uint32_atomic_load_explicit(uint32_t *target, memory_order order)
|
||||
FORCEINLINE void vkd3d_atomic_load_barrier(vkd3d_memory_order order)
|
||||
{
|
||||
switch (order)
|
||||
{
|
||||
case vkd3d_memory_order_consume:
|
||||
case vkd3d_memory_order_acquire:
|
||||
case vkd3d_memory_order_seq_cst:
|
||||
vkd3d_atomic_rw_barrier();
|
||||
break;
|
||||
|
||||
case vkd3d_memory_order_relaxed:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Redefinitions for invalid memory orders...
|
||||
#define InterlockedExchangeRelease InterlockedExchange
|
||||
|
||||
#define vkd3d_atomic_choose_intrinsic(order, result, intrinsic, ...) \
|
||||
switch (order) \
|
||||
{ \
|
||||
case vkd3d_memory_order_relaxed: result = intrinsic##NoFence (__VA_ARGS__); break; \
|
||||
case vkd3d_memory_order_consume: \
|
||||
case vkd3d_memory_order_acquire: result = intrinsic##Acquire (__VA_ARGS__); break; \
|
||||
case vkd3d_memory_order_release: result = intrinsic##Release (__VA_ARGS__); break; \
|
||||
case vkd3d_memory_order_acq_rel: \
|
||||
case vkd3d_memory_order_seq_cst: result = intrinsic (__VA_ARGS__); break; \
|
||||
}
|
||||
|
||||
FORCEINLINE uint32_t vkd3d_atomic_uint32_load_explicit(uint32_t *target, vkd3d_memory_order order)
|
||||
{
|
||||
uint32_t value = *((volatile uint32_t*)target);
|
||||
vkd3d_atomic_rw_barrier_acquire(order);
|
||||
vkd3d_atomic_load_barrier(order);
|
||||
return value;
|
||||
}
|
||||
|
||||
FORCEINLINE void vkd3d_uint32_atomic_store_explicit(uint32_t *target, uint32_t value, memory_order order)
|
||||
FORCEINLINE void vkd3d_atomic_uint32_store_explicit(uint32_t *target, uint32_t value, vkd3d_memory_order order)
|
||||
{
|
||||
vkd3d_atomic_rw_barrier_release(order);
|
||||
*((volatile uint32_t*)target) = value;
|
||||
switch (order)
|
||||
{
|
||||
case vkd3d_memory_order_release: vkd3d_atomic_rw_barrier(); // fallthrough...
|
||||
case vkd3d_memory_order_relaxed: *((volatile uint32_t*)target) = value; break;
|
||||
default:
|
||||
case vkd3d_memory_order_seq_cst:
|
||||
(void) InterlockedExchange((LONG*) target, value);
|
||||
}
|
||||
}
|
||||
|
||||
FORCEINLINE uint32_t vkd3d_uint32_atomic_exchange_explicit(uint32_t *target, uint32_t value, memory_order order)
|
||||
FORCEINLINE uint32_t vkd3d_atomic_uint32_exchange_explicit(uint32_t *target, uint32_t value, vkd3d_memory_order order)
|
||||
{
|
||||
vkd3d_atomic_rw_barrier_release(order);
|
||||
uint32_t oldValue = InterlockedExchange((LONG*)target, value);
|
||||
vkd3d_atomic_rw_barrier_acquire(order);
|
||||
return oldValue;
|
||||
uint32_t result;
|
||||
vkd3d_atomic_choose_intrinsic(order, result, InterlockedExchange, (LONG*)target, value);
|
||||
return result;
|
||||
}
|
||||
|
||||
FORCEINLINE uint32_t vkd3d_atomic_uint32_increment(uint32_t *target, vkd3d_memory_order order)
|
||||
{
|
||||
uint32_t result;
|
||||
vkd3d_atomic_choose_intrinsic(order, result, InterlockedIncrement, (LONG*)target);
|
||||
return result;
|
||||
}
|
||||
|
||||
FORCEINLINE uint32_t vkd3d_atomic_uint32_decrement(uint32_t *target, vkd3d_memory_order order)
|
||||
{
|
||||
uint32_t result;
|
||||
vkd3d_atomic_choose_intrinsic(order, result, InterlockedDecrement, (LONG*)target);
|
||||
return result;
|
||||
}
|
||||
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
|
||||
# include <stdatomic.h>
|
||||
#define vkd3d_memory_order_relaxed __ATOMIC_RELAXED
|
||||
#define vkd3d_memory_order_consume __ATOMIC_CONSUME
|
||||
#define vkd3d_memory_order_acquire __ATOMIC_ACQUIRE
|
||||
#define vkd3d_memory_order_release __ATOMIC_RELEASE
|
||||
#define vkd3d_memory_order_acq_rel __ATOMIC_ACQ_REL
|
||||
#define vkd3d_memory_order_seq_cst __ATOMIC_SEQ_CST
|
||||
|
||||
# define vkd3d_uint32_atomic_load_explicit(target, order) atomic_load_explicit(target, order)
|
||||
# define vkd3d_uint32_atomic_store_explicit(target, value, order) atomic_store_explicit(target, value, order)
|
||||
# define vkd3d_uint32_atomic_exchange_explicit(target, value, order) atomic_exchange_explicit(target, value, order)
|
||||
# define vkd3d_atomic_uint32_load_explicit(target, order) __atomic_load_n(target, order)
|
||||
# define vkd3d_atomic_uint32_store_explicit(target, value, order) __atomic_store_n(target, value, order)
|
||||
# define vkd3d_atomic_uint32_exchange_explicit(target, value, order) __atomic_exchange_n(target, value, order)
|
||||
# define vkd3d_atomic_uint32_increment(target, order) __atomic_add_fetch(target, 1, order)
|
||||
# define vkd3d_atomic_uint32_decrement(target, order) __atomic_sub_fetch(target, 1, order)
|
||||
|
||||
# ifndef __MINGW32__
|
||||
/* Unfortunately only fetch_add is in stdatomic
|
||||
* so use the common GCC extensions for these. */
|
||||
# define InterlockedIncrement(target) __atomic_add_fetch(target, 1, memory_order_seq_cst)
|
||||
# define InterlockedDecrement(target) __atomic_sub_fetch(target, 1, memory_order_seq_cst)
|
||||
# define InterlockedIncrement(target) vkd3d_atomic_uint32_increment(target, vkd3d_memory_order_seq_cst)
|
||||
# define InterlockedDecrement(target) vkd3d_atomic_uint32_decrement(target, vkd3d_memory_order_seq_cst)
|
||||
# endif
|
||||
|
||||
#else
|
||||
|
|
|
@ -29,10 +29,10 @@
|
|||
#endif
|
||||
|
||||
#define vkd3d_spinlock_try_lock(lock) \
|
||||
(!vkd3d_uint32_atomic_load_explicit(lock, memory_order_relaxed) && \
|
||||
!vkd3d_uint32_atomic_exchange_explicit(lock, 1u, memory_order_acquire))
|
||||
(!vkd3d_atomic_uint32_load_explicit(lock, vkd3d_memory_order_relaxed) && \
|
||||
!vkd3d_atomic_uint32_exchange_explicit(lock, 1u, vkd3d_memory_order_acquire))
|
||||
|
||||
#define vkd3d_spinlock_unlock(lock) vkd3d_uint32_atomic_store_explicit(lock, 0u, memory_order_release)
|
||||
#define vkd3d_spinlock_unlock(lock) vkd3d_atomic_uint32_store_explicit(lock, 0u, vkd3d_memory_order_release)
|
||||
|
||||
typedef uint32_t spinlock_t;
|
||||
|
||||
|
|
|
@ -177,7 +177,7 @@ static void vkd3d_fence_worker_remove_fence(struct vkd3d_fence_worker *worker, s
|
|||
LONG count;
|
||||
int rc;
|
||||
|
||||
if (!(count = vkd3d_uint32_atomic_load_explicit(&fence->pending_worker_operation_count, memory_order_acquire)))
|
||||
if (!(count = vkd3d_atomic_uint32_load_explicit(&fence->pending_worker_operation_count, vkd3d_memory_order_acquire)))
|
||||
return;
|
||||
|
||||
WARN("Waiting for %u pending fence operations (fence %p).\n", count, fence);
|
||||
|
@ -188,7 +188,7 @@ static void vkd3d_fence_worker_remove_fence(struct vkd3d_fence_worker *worker, s
|
|||
return;
|
||||
}
|
||||
|
||||
while ((count = vkd3d_uint32_atomic_load_explicit(&fence->pending_worker_operation_count, memory_order_acquire)))
|
||||
while ((count = vkd3d_atomic_uint32_load_explicit(&fence->pending_worker_operation_count, vkd3d_memory_order_acquire)))
|
||||
{
|
||||
TRACE("Still waiting for %u pending fence operations (fence %p).\n", count, fence);
|
||||
|
||||
|
@ -313,7 +313,7 @@ static void *vkd3d_fence_worker_main(void *arg)
|
|||
{
|
||||
vkd3d_wait_for_gpu_timeline_semaphores(worker);
|
||||
|
||||
if (!worker->fence_count || vkd3d_uint32_atomic_load_explicit(&worker->enqueued_fence_count, memory_order_acquire))
|
||||
if (!worker->fence_count || vkd3d_atomic_uint32_load_explicit(&worker->enqueued_fence_count, vkd3d_memory_order_acquire))
|
||||
{
|
||||
if ((rc = pthread_mutex_lock(&worker->mutex)))
|
||||
{
|
||||
|
@ -1603,7 +1603,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_command_allocator_Reset(ID3D12CommandAllo
|
|||
TRACE("Resetting command list %p.\n", list);
|
||||
}
|
||||
|
||||
if ((pending = vkd3d_uint32_atomic_load_explicit(&allocator->outstanding_submissions_count, memory_order_acquire)) != 0)
|
||||
if ((pending = vkd3d_atomic_uint32_load_explicit(&allocator->outstanding_submissions_count, vkd3d_memory_order_acquire)) != 0)
|
||||
{
|
||||
/* HACK: There are currently command lists waiting to be submitted to the queue in the submission threads.
|
||||
* Buggy application, but work around this by not resetting the command pool this time.
|
||||
|
|
|
@ -206,7 +206,7 @@ struct vkd3d_fence_worker
|
|||
bool should_exit;
|
||||
bool pending_fence_destruction;
|
||||
|
||||
size_t enqueued_fence_count;
|
||||
uint32_t enqueued_fence_count;
|
||||
struct vkd3d_enqueued_fence
|
||||
{
|
||||
VkSemaphore vk_semaphore;
|
||||
|
|
Loading…
Reference in New Issue