HACK: Implement singleton devices

This commit is contained in:
Joshua Ashton 2020-11-15 21:48:51 +00:00
parent b514f03906
commit a9fab2a64d
1 changed files with 87 additions and 0 deletions

View File

@ -2165,6 +2165,70 @@ static void vkd3d_gpu_va_allocator_cleanup(struct vkd3d_gpu_va_allocator *alloca
pthread_mutex_destroy(&allocator->mutex);
}
struct d3d12_device_singleton
{
struct list entry;
LUID adapter_luid;
struct d3d12_device *device;
};
static pthread_once_t d3d12_device_map_mutex_init_once = PTHREAD_ONCE_INIT;
static pthread_mutex_t d3d12_device_map_mutex;
static struct list d3d12_device_map;
static void d3d12_init_device_map_once(void)
{
pthread_mutex_init(&d3d12_device_map_mutex, NULL);
list_init(&d3d12_device_map);
}
static struct d3d12_device *d3d12_find_device_singleton(LUID luid)
{
struct d3d12_device_singleton* current;
struct d3d12_device *device = NULL;
LIST_FOR_EACH_ENTRY(current, &d3d12_device_map, struct d3d12_device_singleton, entry)
{
/* Avoid the bubble of time between no ref and death. */
if (!vkd3d_atomic_uint32_load_explicit(&current->device->refcount, vkd3d_memory_order_seq_cst))
continue;
if (!memcmp(&current->adapter_luid, &luid, sizeof(LUID)))
return current->device;
}
return NULL;
}
static void d3d12_add_device_singleton(struct d3d12_device *device, LUID luid)
{
struct d3d12_device_singleton *e;
if (!(e = vkd3d_malloc(sizeof(*e))))
{
ERR("Failed to register device singleton for adapter.");
return;
}
e->adapter_luid = luid;
e->device = device;
list_add_tail(&d3d12_device_map, &e->entry);
}
static void d3d12_remove_device_singleton(LUID luid)
{
struct d3d12_device_singleton *current;
LIST_FOR_EACH_ENTRY(current, &d3d12_device_map, struct d3d12_device_singleton, entry)
{
if (!memcmp(&current->adapter_luid, &luid, sizeof(LUID)))
{
list_remove(&current->entry);
return;
}
}
}
/* ID3D12Device */
static inline struct d3d12_device *impl_from_ID3D12Device(d3d12_device_iface *iface)
{
@ -2240,6 +2304,9 @@ static ULONG STDMETHODCALLTYPE d3d12_device_Release(d3d12_device_iface *iface)
if (!refcount)
{
pthread_mutex_lock(&d3d12_device_map_mutex);
d3d12_remove_device_singleton(device->adapter_luid);
pthread_mutex_unlock(&d3d12_device_map_mutex);
d3d12_device_destroy(device);
vkd3d_free(device);
}
@ -4662,12 +4729,27 @@ HRESULT d3d12_device_create(struct vkd3d_instance *instance,
struct d3d12_device *object;
HRESULT hr;
pthread_once(&d3d12_device_map_mutex_init_once, d3d12_init_device_map_once);
pthread_mutex_lock(&d3d12_device_map_mutex);
if ((object = d3d12_find_device_singleton(create_info->adapter_luid)))
{
TRACE("Returned existing singleton device %p.\n", object);
d3d12_device_add_ref(*device = object);
pthread_mutex_unlock(&d3d12_device_map_mutex);
return S_OK;
}
if (!(object = vkd3d_malloc(sizeof(*object))))
{
pthread_mutex_unlock(&d3d12_device_map_mutex);
return E_OUTOFMEMORY;
}
if (FAILED(hr = d3d12_device_init(object, instance, create_info)))
{
vkd3d_free(object);
pthread_mutex_unlock(&d3d12_device_map_mutex);
return hr;
}
@ -4676,11 +4758,16 @@ HRESULT d3d12_device_create(struct vkd3d_instance *instance,
WARN("Feature level %#x is not supported.\n", create_info->minimum_feature_level);
d3d12_device_destroy(object);
vkd3d_free(object);
pthread_mutex_unlock(&d3d12_device_map_mutex);
return E_INVALIDARG;
}
TRACE("Created device %p.\n", object);
d3d12_add_device_singleton(object, create_info->adapter_luid);
pthread_mutex_unlock(&d3d12_device_map_mutex);
*device = object;
return S_OK;