wineopenxr: Don't recreate swapchain images for subsequent calls to EnumerateSwapchainImages.

This commit is contained in:
Yuxuan Shui 2024-05-08 15:11:24 +01:00 committed by Arkadiusz Hiler
parent 0181ecc872
commit 2cf4673153
2 changed files with 54 additions and 22 deletions

View file

@ -1663,12 +1663,22 @@ XrResult WINAPI wine_xrDestroySwapchain(XrSwapchain swapchain)
WINE_TRACE("%p\n", swapchain); WINE_TRACE("%p\n", swapchain);
if (wine_swapchain->image_count){
UINT i;
if (wine_swapchain->wine_session->session_type == SESSION_TYPE_D3D11){
XrSwapchainImageD3D11KHR *d3d11_images = (XrSwapchainImageD3D11KHR *)wine_swapchain->images;
for (i = 0; i < wine_swapchain->image_count; i++)
d3d11_images[i].texture->lpVtbl->Release(d3d11_images[i].texture);
}
heap_free(wine_swapchain->images);
wine_swapchain->image_count = 0;
}
res = xrDestroySwapchain(wine_swapchain->swapchain); res = xrDestroySwapchain(wine_swapchain->swapchain);
if(res != XR_SUCCESS){ if(res != XR_SUCCESS){
WINE_WARN("xrDestroySwapchain failed: %d\n", res); WINE_WARN("xrDestroySwapchain failed: %d\n", res);
return res; return res;
} }
heap_free(wine_swapchain); heap_free(wine_swapchain);
return XR_SUCCESS; return XR_SUCCESS;
@ -1700,28 +1710,34 @@ XrResult WINAPI wine_xrEnumerateSwapchainImages(XrSwapchain swapchain, uint32_t
wine_XrSwapchain *wine_swapchain = (wine_XrSwapchain *)swapchain; wine_XrSwapchain *wine_swapchain = (wine_XrSwapchain *)swapchain;
wine_XrInstance *wine_instance = wine_swapchain->wine_session->wine_instance; wine_XrInstance *wine_instance = wine_swapchain->wine_session->wine_instance;
XrResult res; XrResult res;
XrSwapchainImageVulkanKHR *our_images = NULL; XrSwapchainImageVulkanKHR *our_vk = NULL;
XrSwapchainImageBaseHeader *their_images = images;
HRESULT hr; HRESULT hr;
uint32_t i; size_t image_size = 0;
uint32_t i, to_copy;
WINE_TRACE("%p, %u, %p, %p\n", swapchain, imageCapacityInput, imageCountOutput, images); WINE_TRACE("%p, %u, %p, %p\n", swapchain, imageCapacityInput, imageCountOutput, images);
if (wine_swapchain->wine_session->session_type != SESSION_TYPE_D3D11)
return xrEnumerateSwapchainImages(wine_swapchain->swapchain, imageCapacityInput, imageCountOutput, images);
if(images){ if (!wine_swapchain->image_count) {
if(wine_swapchain->wine_session->session_type == SESSION_TYPE_D3D11){ uint32_t image_count;
our_images = heap_alloc(sizeof(*our_images) * imageCapacityInput); res = xrEnumerateSwapchainImages(wine_swapchain->swapchain, 0, &image_count, NULL);
for(i = 0; i < imageCapacityInput; ++i){ if (res != XR_SUCCESS)
our_images[i].type = XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR; return res;
}
images = (XrSwapchainImageBaseHeader *)our_images; our_vk = heap_alloc(sizeof(*our_vk) * image_count);
for(i = 0; i < image_count; ++i){
our_vk[i].type = XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR;
} }
}
res = xrEnumerateSwapchainImages(wine_swapchain->swapchain, imageCapacityInput, imageCountOutput, images); res = xrEnumerateSwapchainImages(wine_swapchain->swapchain, image_count, &image_count, (XrSwapchainImageBaseHeader *)our_vk);
if (res != XR_SUCCESS){
heap_free(our_vk);
return res;
}
if(images && res == XR_SUCCESS){
if(wine_swapchain->wine_session->session_type == SESSION_TYPE_D3D11){ if(wine_swapchain->wine_session->session_type == SESSION_TYPE_D3D11){
XrSwapchainImageD3D11KHR *their_d3d11; XrSwapchainImageD3D11KHR *our_d3d11;
D3D11_TEXTURE2D_DESC1 desc; D3D11_TEXTURE2D_DESC1 desc;
desc.Width = wine_swapchain->create_info.width; desc.Width = wine_swapchain->create_info.width;
@ -1739,21 +1755,35 @@ XrResult WINAPI wine_xrEnumerateSwapchainImages(XrSwapchain swapchain, uint32_t
desc.MiscFlags = 0; desc.MiscFlags = 0;
desc.TextureLayout = D3D11_TEXTURE_LAYOUT_UNDEFINED; desc.TextureLayout = D3D11_TEXTURE_LAYOUT_UNDEFINED;
their_d3d11 = (XrSwapchainImageD3D11KHR *)their_images; our_d3d11 = heap_alloc(sizeof(XrSwapchainImageD3D11KHR) * image_count);
for(i = 0; i < *imageCountOutput; ++i){ for(i = 0; i < image_count; ++i){
hr = wine_instance->dxvk_device->lpVtbl->CreateTexture2DFromVkImage(wine_instance->dxvk_device, hr = wine_instance->dxvk_device->lpVtbl->CreateTexture2DFromVkImage(wine_instance->dxvk_device,
&desc, our_images[i].image, &their_d3d11[i].texture); &desc, our_vk[i].image, &our_d3d11[i].texture);
if(FAILED(hr)){ if(FAILED(hr)){
UINT j;
for (j = 0; j < i; ++j){
our_d3d11[i].texture->lpVtbl->Release(our_d3d11[i].texture);
}
heap_free(our_d3d11);
heap_free(our_vk);
WINE_WARN("Failed to create DXVK texture from VkImage: %08x\n", hr); WINE_WARN("Failed to create DXVK texture from VkImage: %08x\n", hr);
return XR_ERROR_INSTANCE_LOST; return XR_ERROR_RUNTIME_FAILURE;
} }
WINE_TRACE("Successfully allocated texture %p\n", their_d3d11[i].texture); WINE_TRACE("Successfully allocated texture %p\n", our_d3d11[i].texture);
} }
wine_swapchain->images = (XrSwapchainImageBaseHeader *)our_d3d11;
} }
heap_free(our_vk);
wine_swapchain->image_count = image_count;
} }
heap_free(our_images);
return res; to_copy = min(wine_swapchain->image_count, imageCapacityInput);
*imageCountOutput = wine_swapchain->image_count;
if (wine_swapchain->wine_session->session_type == SESSION_TYPE_D3D11){
image_size = sizeof(XrSwapchainImageD3D11KHR);
}
memcpy(images, wine_swapchain->images, image_size * to_copy);
return XR_SUCCESS;
} }
static XrCompositionLayerBaseHeader *convert_XrCompositionLayer(wine_XrSession *wine_session, static XrCompositionLayerBaseHeader *convert_XrCompositionLayer(wine_XrSession *wine_session,

View file

@ -49,6 +49,8 @@ typedef struct wine_XrSession {
typedef struct wine_XrSwapchain{ typedef struct wine_XrSwapchain{
XrSwapchain swapchain; XrSwapchain swapchain;
XrSwapchainImageBaseHeader *images;
uint32_t image_count;
struct wine_XrSession *wine_session; struct wine_XrSession *wine_session;
XrSwapchainCreateInfo create_info; XrSwapchainCreateInfo create_info;