From 4fb75f4e0064105869798b27f99858254b5624ff Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Mon, 5 Oct 2026 00:19:21 -0400 Subject: [PATCH] [Fix] (DirectVulkan): prepare image copy recording after uploads and share texture usage checks --- .../Renderer/VkTextureManager.cpp | 31 +++++++++++-------- .../DirectVulkan/Renderer/VulkanRenderer.cpp | 19 ++++++------ 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.cpp index 4608ace4..98fcd886 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.cpp @@ -56,6 +56,22 @@ namespace MobileGL::MG_Backend::DirectVulkan { }; static SessionLocal s_sampledReadStagesSlot; + static VkImageUsageFlags ResolveTextureUsage(VkImageAspectFlags aspect, + VkFormatFeatureFlags formatFeatures, + Bool supportsStorageImage) { + VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT; + if (supportsStorageImage) usage |= VK_IMAGE_USAGE_STORAGE_BIT; + // A color aspect does not imply renderability (for example, RGB9_E5). + if ((aspect & VK_IMAGE_ASPECT_COLOR_BIT) && + (formatFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)) { + usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + } + if (aspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { + usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + } + return usage; + } + static Uint32 ComputeFullMipLevelCount(const IntVec3& baseTexelSize) { Int maxDimension = std::max(baseTexelSize.x(), std::max(baseTexelSize.y(), std::max(baseTexelSize.z(), 1))); @@ -2256,13 +2272,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { } VkImageUsageFlags desiredUsage = - VK_IMAGE_USAGE_SAMPLED_BIT | (supportsStorageImage ? VK_IMAGE_USAGE_STORAGE_BIT : 0) | - ((aspect & VK_IMAGE_ASPECT_COLOR_BIT) && - (formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) - ? VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT : 0) | - (((aspect & VK_IMAGE_ASPECT_DEPTH_BIT) || (aspect & VK_IMAGE_ASPECT_STENCIL_BIT)) - ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT - : 0); + ResolveTextureUsage(aspect, formatProperties.optimalTilingFeatures, supportsStorageImage); // Multisample attachments are also transfer sources for vkCmdResolveImage. desiredUsage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; @@ -3513,12 +3523,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { } VkImageUsageFlags desiredUsage = - VK_IMAGE_USAGE_SAMPLED_BIT | - (supportsStorageImage ? VK_IMAGE_USAGE_STORAGE_BIT : 0) | - ((aspect & VK_IMAGE_ASPECT_COLOR_BIT) ? VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT : 0) | - (((aspect & VK_IMAGE_ASPECT_DEPTH_BIT) || (aspect & VK_IMAGE_ASPECT_STENCIL_BIT)) ? - VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT : - 0); + ResolveTextureUsage(aspect, formatProperties.optimalTilingFeatures, supportsStorageImage); if (!isMultisampleTexture) { desiredUsage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; } diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp index a6d97bd3..ecc46b0c 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp @@ -10678,15 +10678,6 @@ void main() { return; } - auto& frame = m_frameContext.GetCurrent(); - if (!frame.isCommandRecording) { - m_frameContext.BeginCommandRecording(); - } - - if (VkRenderPassManager::GetActiveRenderPass() != nullptr) { - VkRenderPassManager::EndRenderPass(frame.commandBuffer); - } - // One resolver for both object kinds. The texture arm is the same // SyncTextureAndGetDescriptor the copy always used; the renderbuffer arm goes through the // render-pass manager, which is where a renderbuffer's VkImage lives. @@ -10938,6 +10929,16 @@ void main() { } #endif + // Syncing either endpoint can flush and retire the current command buffer for + // a texture upload. Prepare recording only after both images and uploads are ready. + auto& frame = m_frameContext.GetCurrent(); + if (!frame.isCommandRecording) { + m_frameContext.BeginCommandRecording(); + } + if (VkRenderPassManager::GetActiveRenderPass() != nullptr) { + VkRenderPassManager::EndRenderPass(frame.commandBuffer); + } + const auto materializeClear = [this, &frame](const CopyImageEndpoint& endpoint) { #if MOBILEGL_BUILD_DISAGGREGATED if (MG_Config::Transport != MG_Config::TransportMode::Monolith) return true;