Greatly improves performance in Control in Proton (but upstream vkd3d/Wine currently only renders the intro screens in DX12 mode).
Based on a vkd3d-proton patch by Philip Rebohle.
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- libs/vkd3d/resource.c | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-)
diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c index cae5b580..2c6c07c7 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -2153,24 +2153,45 @@ static void d3d12_desc_destroy(struct d3d12_desc *descriptor, struct d3d12_devic void d3d12_desc_copy(struct d3d12_desc *dst, const struct d3d12_desc *src, struct d3d12_device *device) { + bool needs_update = true; struct d3d12_desc tmp; pthread_mutex_t *mutex;
assert(dst != src);
/* Shadow of the Tomb Raider and possibly other titles sometimes destroy - * and rewrite a descriptor in another thread while it is being copied. */ - mutex = d3d12_device_get_descriptor_mutex(device, src); - pthread_mutex_lock(mutex); + * and rewrite a descriptor in another thread while it is being copied. + * We don't need to lock either descriptor for the update check. We only care + * about preventing use-after-free of the vkd3d_view caused by a race condiion + * in the calling app. It's not important if needs_update falls out of date as + * it's their race condition, not ours. */ + if (dst->magic == src->magic) + { + if (dst->magic & VKD3D_DESCRIPTOR_MAGIC_HAS_VIEW) + { + needs_update = dst->u.view != src->u.view; + } + else if (dst->magic != VKD3D_DESCRIPTOR_MAGIC_FREE) + { + needs_update = dst->u.vk_cbv_info.buffer != src->u.vk_cbv_info.buffer || + dst->u.vk_cbv_info.offset != src->u.vk_cbv_info.offset || + dst->u.vk_cbv_info.range != src->u.vk_cbv_info.range; + } + }
- if (src->magic & VKD3D_DESCRIPTOR_MAGIC_HAS_VIEW) - vkd3d_view_incref(src->u.view); + if (needs_update) + { + mutex = d3d12_device_get_descriptor_mutex(device, src); + pthread_mutex_lock(mutex);
- tmp = *src; + if (src->magic & VKD3D_DESCRIPTOR_MAGIC_HAS_VIEW) + vkd3d_view_incref(src->u.view); + tmp = *src;
- pthread_mutex_unlock(mutex); + pthread_mutex_unlock(mutex);
- d3d12_desc_write_atomic(dst, &tmp, device); + d3d12_desc_write_atomic(dst, &tmp, device); + } }
static VkDeviceSize vkd3d_get_required_texel_buffer_alignment(const struct d3d12_device *device,