From 6e21fd9a356c7e8c2ffd6ff042c458ddc6d649e8 Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Thu, 5 Mar 2026 23:17:27 +0800 Subject: [PATCH] [Chore] (MG_Backend/DirectVulkan): a lotta assertions & transition uploaded texture directly to `VK_ACCESS_SHADER_READ_BIT` --- .../Renderer/UniformDescriptorBinder.cpp | 16 ++++++++++++++++ .../Renderer/VkRenderPassManager.cpp | 13 ++++++++++++- .../DirectVulkan/Renderer/VkTextureManager.cpp | 7 ++++++- 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/UniformDescriptorBinder.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/UniformDescriptorBinder.cpp index 37adefcb..71c52f1e 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/UniformDescriptorBinder.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/UniformDescriptorBinder.cpp @@ -14,6 +14,19 @@ #include namespace MobileGL::MG_Backend::DirectVulkan { + static Bool IsValidSampledImageLayout(VkImageLayout layout) { + switch (layout) { + case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: + case VK_IMAGE_LAYOUT_GENERAL: + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: + case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL: + case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL: + return true; + default: + return false; + } + } + VkDeviceSize UniformDescriptorBinder::AlignUp(VkDeviceSize value, VkDeviceSize alignment) { if (alignment == 0) { return value; @@ -480,6 +493,9 @@ namespace MobileGL::MG_Backend::DirectVulkan { if (resource == nullptr) { return false; } + MOBILEGL_ASSERT(IsValidSampledImageLayout(resource->layout), + "ResolveSamplerDescriptor: invalid sampled image layout=%d for textureId=%d, binding=%u", + static_cast(resource->layout), texture->GetExternalIndex(), binding); outImageInfo = { .sampler = m_samplerManager->GetOrCreateSampler(*samplerToUse), .imageView = resource->view, diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkRenderPassManager.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkRenderPassManager.cpp index 411eac6e..78aa05c0 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkRenderPassManager.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkRenderPassManager.cpp @@ -177,6 +177,9 @@ namespace MobileGL::MG_Backend::DirectVulkan { textureResources[i] = m_textureManager.SyncTextureAndGetDescriptor(*texture); MOBILEGL_ASSERT(textureResources[i], "GetOrCreateRenderPass: SyncTextureAndGetDescriptor failed at color attachment %d", i); + MOBILEGL_ASSERT(hasClear || textureResources[i]->layout != VK_IMAGE_LAYOUT_UNDEFINED, + "GetOrCreateRenderPass: color attachment textureId=%d has undefined tracked layout with LOAD_OP_LOAD (attachment=%d)", + texture->GetExternalIndex(), i); attachmentViews[i] = textureResources[i]->view; } @@ -218,10 +221,15 @@ namespace MobileGL::MG_Backend::DirectVulkan { VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD; depthAttachmentDescription.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; - depthAttachmentDescription.initialLayout = hasClear ? + // UNDEFINED is only valid when both depth and stencil are discarded/cleared. + depthAttachmentDescription.initialLayout = (clearDepth && clearStencil) ? VK_IMAGE_LAYOUT_UNDEFINED : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; depthAttachmentDescription.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + MOBILEGL_ASSERT(!(depthAttachmentDescription.stencilLoadOp == VK_ATTACHMENT_LOAD_OP_LOAD && + depthAttachmentDescription.initialLayout == VK_IMAGE_LAYOUT_UNDEFINED), + "GetOrCreateRenderPass: invalid depth-stencil state (stencil LOAD + initialLayout UNDEFINED), textureId=%d", + texture.GetExternalIndex()); if (hasClear) { pendingClearAttachments.emplace_back(PendingClearAttachmentInfo { .attachmentIndex = depthAttachmentIndex, @@ -234,6 +242,9 @@ namespace MobileGL::MG_Backend::DirectVulkan { depthTextureResource = m_textureManager.SyncTextureAndGetDescriptor(texture); MOBILEGL_ASSERT(depthTextureResource, "GetOrCreateRenderPass: SyncTextureAndGetDescriptor failed at depth attachment"); + MOBILEGL_ASSERT(clearDepth || clearStencil || depthTextureResource->layout != VK_IMAGE_LAYOUT_UNDEFINED, + "GetOrCreateRenderPass: depth attachment textureId=%d has undefined tracked layout with LOAD_OP_LOAD", + texture.GetExternalIndex()); textureResources.emplace_back(depthTextureResource); attachmentViews.emplace_back(depthTextureResource->view); if (width == 0 || height == 0) { diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.cpp index d7cfa9be..d5d4c2f2 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.cpp @@ -64,6 +64,11 @@ namespace MobileGL::MG_Backend::DirectVulkan { VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageAspectFlags aspectMask) { MOBILEGL_ASSERT(image != VK_NULL_HANDLE, "TransitionImageLayout: m_image == VK_NULL_HANDLE"); + MOBILEGL_ASSERT(!((dstAccessMask & VK_ACCESS_TRANSFER_READ_BIT) != 0 && + (dstStageMask & VK_PIPELINE_STAGE_TRANSFER_BIT) == 0), + "TransitionImageLayout: invalid dstAccess/dstStage pair (dstAccess=0x%x, dstStage=0x%x, oldLayout=%d, newLayout=%d)", + static_cast(dstAccessMask), static_cast(dstStageMask), static_cast(trackedLayout), + static_cast(newLayout)); if (trackedLayout == newLayout) { return true; @@ -333,7 +338,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, - VK_ACCESS_TRANSFER_READ_BIT, + VK_ACCESS_SHADER_READ_BIT, aspectMask); MOBILEGL_ASSERT(ok, "TransitionImageLayout to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL failed"); outResource.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;