From 8b36a15fb31d35e19e38ff746b47c84ef71c38e3 Mon Sep 17 00:00:00 2001 From: BZLZHH Date: Fri, 31 Jul 2026 18:21:28 -0400 Subject: [PATCH] [Fix] (DirectVulkan): repair VK_VERIFY varargs and soften image-creation OOM VK_VERIFY appended the caller's context format string to the base format while the context ARGUMENTS expanded before the base arguments, so any failing VK_VERIFY with context args formatted every conversion from the wrong slot - the %s for VkResultToString dereferenced an integer arg and crashed inside the logger. The context line is now its own log call (XXHASH_VERIFY had the same defect). vmaCreateImage failure in SyncTextureResource is now a soft failure like the unsupported-sample-count path: a driver may pass the vkGetPhysicalDeviceImageFormatProperties pre-check yet still refuse creation (a 4-sample 16K depth texture on lavapipe is 4 GiB), and a GL implementation must not abort on that. --- .../Renderer/VkTextureManager.cpp | 20 ++++++++++++++----- MobileGL/MG_Backend/DirectVulkan/VkIncludes.h | 16 ++++++++++++--- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.cpp index 07182761..4784b0ae 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.cpp @@ -1693,11 +1693,21 @@ namespace MobileGL::MG_Backend::DirectVulkan { VmaAllocationCreateInfo allocationInfo{}; allocationInfo.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE; allocationInfo.requiredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; - VK_VERIFY(vmaCreateImage(m_allocator, &imageInfo, &allocationInfo, &resource.image, &resource.allocation, nullptr), - "vmaCreateImage(texture) textureId=%d extent=%ux%u depth=%u layers=%u mips=%u samples=%d format=%d", - texture.GetExternalIndex(), imageInfo.extent.width, imageInfo.extent.height, - imageInfo.extent.depth, imageInfo.arrayLayers, imageInfo.mipLevels, - static_cast(imageInfo.samples), static_cast(imageInfo.format)); + // Soft failure like the unsupported-sample-count path above: a driver can pass the + // vkGetPhysicalDeviceImageFormatProperties pre-check yet still refuse the creation + // (e.g. multisampled depth on lavapipe); the texture simply stays unbacked. + const VkResult createImageResult = + vmaCreateImage(m_allocator, &imageInfo, &allocationInfo, &resource.image, &resource.allocation, nullptr); + if (createImageResult != VK_SUCCESS) { + MGLOG_F("SyncTextureResource: vmaCreateImage failed (%d) textureId=%d extent=%ux%u depth=%u layers=%u " + "mips=%u samples=%d format=%d", + createImageResult, texture.GetExternalIndex(), imageInfo.extent.width, imageInfo.extent.height, + imageInfo.extent.depth, imageInfo.arrayLayers, imageInfo.mipLevels, + static_cast(imageInfo.samples), static_cast(imageInfo.format)); + resource.image = VK_NULL_HANDLE; + resource.allocation = nullptr; + return false; + } ++m_textureImageEpoch; // a new attachment image invalidates cached render passes resource.layout = VK_IMAGE_LAYOUT_UNDEFINED; diff --git a/MobileGL/MG_Backend/DirectVulkan/VkIncludes.h b/MobileGL/MG_Backend/DirectVulkan/VkIncludes.h index b6bd9141..9048764b 100644 --- a/MobileGL/MG_Backend/DirectVulkan/VkIncludes.h +++ b/MobileGL/MG_Backend/DirectVulkan/VkIncludes.h @@ -52,19 +52,29 @@ namespace MobileGL::MG_Backend::DirectVulkan { } } // namespace MobileGL::MG_Backend::DirectVulkan +// The context line (__VA_ARGS__ = its own format string + args) must be a SEPARATE log +// call: appending its format to the base format while its arguments precede the base +// arguments makes every conversion read the wrong slot (a %s pulling an int crashes). #define VK_VERIFY(expr, ...) \ do { \ VkResult _vk_verify_result = (expr); \ if (_vk_verify_result != VK_SUCCESS) { \ - MGLOG_F("Vulkan error %s (%d) at %s:%d" __VA_OPT__(" - ") __VA_ARGS__, \ + __VA_OPT__(MGLOG_F(__VA_ARGS__);) \ + MGLOG_F("Vulkan error %s (%d) at %s:%d", \ MobileGL::MG_Backend::DirectVulkan::VkResultToString(_vk_verify_result), \ _vk_verify_result, __FILE__, __LINE__); \ } \ - MOBILEGL_ASSERT(_vk_verify_result == VK_SUCCESS, "Vulkan error %s (%d) at %s:%d" __VA_OPT__(" - ") __VA_ARGS__, MobileGL::MG_Backend::DirectVulkan::VkResultToString(_vk_verify_result), _vk_verify_result, __FILE__, __LINE__); \ + MOBILEGL_ASSERT(_vk_verify_result == VK_SUCCESS, "Vulkan error %s (%d) at %s:%d", \ + MobileGL::MG_Backend::DirectVulkan::VkResultToString(_vk_verify_result), \ + _vk_verify_result, __FILE__, __LINE__); \ } while (0) #define XXHASH_VERIFY(expr, ...) \ do { \ XXH_errorcode _xxh_verify_result = (expr); \ - MOBILEGL_ASSERT(_xxh_verify_result == XXH_OK, "XXHash error %d at %s:%d" __VA_OPT__(" - ") __VA_ARGS__, _xxh_verify_result, __FILE__, __LINE__); \ + if (_xxh_verify_result != XXH_OK) { \ + __VA_OPT__(MGLOG_F(__VA_ARGS__);) \ + } \ + MOBILEGL_ASSERT(_xxh_verify_result == XXH_OK, "XXHash error %d at %s:%d", _xxh_verify_result, __FILE__, \ + __LINE__); \ } while (0)