From 21742403a439414112d387e0f7640c8564268bf0 Mon Sep 17 00:00:00 2001 From: XxJSONDeruloxX Date: Thu, 15 Oct 2026 19:16:11 -0400 Subject: [PATCH] fix: preserve OpenVR shared image layouts --- docs/quest.md | 5 +++-- tools/vr/src/vk_layer_droiddeck_vr.c | 7 ++++--- tools/vr/tests/test_semaphore_layer.c | 3 +++ 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/docs/quest.md b/docs/quest.md index bce85b1ac..86d420cdc 100644 --- a/docs/quest.md +++ b/docs/quest.md @@ -136,8 +136,9 @@ immersive scenes. SUPERHOT's Windows OpenXR build initially showed shared-image corruption: DXVK supplied a restricted mutable-image format list while SteamVR created its corresponding opaque shared images without one. Turnip can select different memory layouts for those descriptions. On the Quest bridge, the layer -normalizes the known opaque-FD creation chains to SteamVR's unrestricted list, -without changing DMA-BUF/modifier images or other targets. A headset capture then +normalizes the known opaque-FD stereo-array creation chains to SteamVR's unrestricted list, +without changing application-owned single-layer OpenVR images, DMA-BUF/modifier +images or other targets. A headset capture then showed clean SUPERHOT scene geometry; interactive gameplay remains unverified. A subsequent 60-second shared-buffer dashboard run delivered about 43 new stereo images per second. Reusing Android pixel buffers raised the next diff --git a/tools/vr/src/vk_layer_droiddeck_vr.c b/tools/vr/src/vk_layer_droiddeck_vr.c index bde81f4a7..c66157491 100644 --- a/tools/vr/src/vk_layer_droiddeck_vr.c +++ b/tools/vr/src/vk_layer_droiddeck_vr.c @@ -980,8 +980,9 @@ static VkResult VKAPI_CALL CreateImage(VkDevice d, const VkImageCreateInfo *ci, VkImageCreateInfo compatible = *ci; VkExternalMemoryImageCreateInfo shared; const VkBaseInStructure *first = ci->pNext; - // SteamVR omits a format list, but DXVK adds one; Turnip can choose a different shared-memory layout. - if (dev_for(d)->quest_images && (ci->flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) && ci->tiling == VK_IMAGE_TILING_OPTIMAL + // SteamVR's OpenXR stereo arrays omit a format list, while DXVK adds one on import. + // Leave single-layer OpenVR images alone: the application owns their export layout. + if (dev_for(d)->quest_images && ci->arrayLayers > 1 && (ci->flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) && ci->tiling == VK_IMAGE_TILING_OPTIMAL && first && first->sType == VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO) { const VkBaseInStructure *second = first->pNext; if (second && second->sType == VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO @@ -990,7 +991,7 @@ static VkResult VKAPI_CALL CreateImage(VkDevice d, const VkImageCreateInfo *ci, say("%s", "matching opaque shared image layout to SteamVR's unrestricted format list"); } } - if (dev_for(d)->quest_images && (ci->flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) && ci->tiling == VK_IMAGE_TILING_OPTIMAL + if (dev_for(d)->quest_images && ci->arrayLayers > 1 && (ci->flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) && ci->tiling == VK_IMAGE_TILING_OPTIMAL && first && first->sType == VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO) { const VkExternalMemoryImageCreateInfo *external = (const void *)first; const VkBaseInStructure *second = external->pNext; diff --git a/tools/vr/tests/test_semaphore_layer.c b/tools/vr/tests/test_semaphore_layer.c index dc265e4a9..575d64e92 100644 --- a/tools/vr/tests/test_semaphore_layer.c +++ b/tools/vr/tests/test_semaphore_layer.c @@ -42,6 +42,9 @@ static void check_shared_images(VkDevice device) { expected_image_chain = &list; assert(CreateImage(device, &image, NULL, &output) == VK_ERROR_FORMAT_NOT_SUPPORTED); g_dev[0].quest_images = 1; + image.arrayLayers = 1; + assert(CreateImage(device, &image, NULL, &output) == VK_ERROR_FORMAT_NOT_SUPPORTED); + image.arrayLayers = 2; image.flags = 0; assert(CreateImage(device, &image, NULL, &output) == VK_ERROR_FORMAT_NOT_SUPPORTED); image.flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;