From 7b86a47867a2484e148994115b3ed2d6c711d9a2 Mon Sep 17 00:00:00 2001 From: Steven Li Date: Fri, 15 Nov 2024 16:30:45 -0800 Subject: [PATCH] Fix vulkan error per VUID-VkMemoryAllocateInfo-pNext-00639 Per https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkMemoryAllocateInfo.html#VUID-VkMemoryAllocateInfo-pNext-00639, dedicated allocation is required by certain externalMemoryFeatures. This change is to keep dedicated allocation in those scenarios for capture mode, while being assured no dedicated allocation for reading and replaying mode. --- renderdoc/driver/vulkan/vk_resources.h | 4 +- .../vulkan/wrappers/vk_resource_funcs.cpp | 54 ++++++++++++++++++- 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/renderdoc/driver/vulkan/vk_resources.h b/renderdoc/driver/vulkan/vk_resources.h index 5dbdab073c..007817647a 100644 --- a/renderdoc/driver/vulkan/vk_resources.h +++ b/renderdoc/driver/vulkan/vk_resources.h @@ -1027,8 +1027,10 @@ struct ResourceInfo rdcarray altSparseAspects; // for external images if we query both external and non-external and the sizes are different, we - // can't allow dedicated memory as it is required to precisely match in size. + // can't allow dedicated memory as it is required to precisely match in size, + // unless it is required by certain VkExportMemoryAllocateInfo::handleTypes. bool banDedicated = false; + VkExternalMemoryFeatureFlags externalMemoryFeatures = 0; VkImageAspectFlags sparseAspect; diff --git a/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp index 3a808940dd..cbb9936bf3 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp @@ -522,7 +522,19 @@ VkResult WrappedVulkan::vkAllocateMemory(VkDevice device, const VkMemoryAllocate VkResourceRecord *imageRecord = GetRecord(dedicated->image); if(imageRecord->resInfo->banDedicated) - RemoveNextStruct(&unwrapped, VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO); + { + VkExportMemoryAllocateInfo *exportMem = (VkExportMemoryAllocateInfo *)FindNextStruct( + pAllocateInfo, VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO); + if(exportMem && exportMem->handleTypes & imageRecord->resInfo->externalMemoryFeatures) + { + RDCWARN( + "Can't ban dedicated memory per Vulkan spec VUID-VkMemoryAllocateInfo-pNext-00639."); + } + else + { + RemoveNextStruct(&unwrapped, VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO); + } + } } } @@ -2509,6 +2521,7 @@ VkResult WrappedVulkan::vkCreateImage(VkDevice device, const VkImageCreateInfo * bool isLinear = (pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR); bool isExternal = false; + VkExternalMemoryHandleTypeFlags externalHandleTypes = 0; const VkBaseInStructure *next = (const VkBaseInStructure *)pCreateInfo->pNext; @@ -2528,6 +2541,7 @@ VkResult WrappedVulkan::vkCreateImage(VkDevice device, const VkImageCreateInfo * resInfo.imageInfo.isAHB = (extCreateInfo->handleTypes & VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) != 0; + externalHandleTypes = extCreateInfo->handleTypes; break; } } @@ -2617,6 +2631,44 @@ VkResult WrappedVulkan::vkCreateImage(VkDevice device, const VkImageCreateInfo * "Required size changed on image between external/non-external, banning " "dedicated memory"); resInfo.banDedicated = true; + + // Per Vulkan spec VUID-VkMemoryAllocateInfo-pNext-00639, + // we need to make sure the dedicated memory is not required. + // We query the externalMemoryFeatures here based on the image's properties. + // Then check the memory's handleType upon vkAllocateMemory(). + // externalMemoryFeatures need to be checked bit by bit. + for(VkFlags handleType = 0x01; externalHandleTypes; + externalHandleTypes &= ~handleType, handleType <<= 1) + { + if(!(externalHandleTypes & handleType)) + continue; + + VkPhysicalDeviceExternalImageFormatInfo extImageFormatInfo = { + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO}; + extImageFormatInfo.handleType = (VkExternalMemoryHandleTypeFlagBits)handleType; + + VkPhysicalDeviceImageFormatInfo2 imageFormatInfo = { + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2}; + imageFormatInfo.pNext = &extImageFormatInfo; + imageFormatInfo.format = createInfo_adjusted.format; + imageFormatInfo.type = createInfo_adjusted.imageType; + imageFormatInfo.tiling = createInfo_adjusted.tiling; + imageFormatInfo.usage = createInfo_adjusted.usage; + imageFormatInfo.flags = createInfo_adjusted.flags; + + VkExternalImageFormatProperties extImageFormatProperties = { + VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES}; + VkImageFormatProperties2 imageFormatProperties = { + VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2}; + imageFormatProperties.pNext = &extImageFormatProperties; + + if(VK_SUCCESS == + ObjDisp(m_PhysicalDevice) + ->GetPhysicalDeviceImageFormatProperties2( + Unwrap(m_PhysicalDevice), &imageFormatInfo, &imageFormatProperties)) + resInfo.externalMemoryFeatures |= + extImageFormatProperties.externalMemoryProperties.externalMemoryFeatures; + } } resInfo.memreqs.size = RDCMAX(resInfo.memreqs.size, mrq.size);