From d1487bedf089df15fa1cd5b35d6984b31fa549b8 Mon Sep 17 00:00:00 2001 From: BZLZHH Date: Fri, 31 Jul 2026 16:01:41 -0400 Subject: [PATCH] [Fix] (DirectVulkan): address array layers in mip upload copies UploadDirtyMipLevels encoded a texture's GL depth into VkBufferImageCopy imageExtent.depth with layerCount = 1. For array textures the layers live in the image's arrayLayers, and extent.depth > 1 is invalid for 2D images - in practice every layer past the first never received its data. Route the third dimension into layerCount for 1D/2D/cube array images and keep imageExtent.depth for genuine 3D images. Fixes the KHR-GL33.pixelstoragemodes.teximage3d.* failures (110 cases) on lavapipe. --- .../DirectVulkan/Renderer/VkTextureManager.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.cpp index 14abdcab..2a0dab92 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.cpp @@ -2020,7 +2020,14 @@ namespace MobileGL::MG_Backend::DirectVulkan { aspectMask, 0, outResource.mipLevels, outResource.arrayLayers); MOBILEGL_ASSERT(ok, "TransitionImageLayout to VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL failed"); + // Array textures keep their GL "depth" in VkImage array layers, so the + // copy must address layerCount, not imageExtent.depth (which is invalid + // for 2D images and silently dropped every layer past the first). + const Bool depthSelectsArrayLayer = outResource.viewType == VK_IMAGE_VIEW_TYPE_1D_ARRAY || + outResource.viewType == VK_IMAGE_VIEW_TYPE_2D_ARRAY || + outResource.viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY; for (const auto& item : uploadItems) { + const Uint32 depthOrLayers = item.texelSize.z() > 0 ? static_cast(item.texelSize.z()) : 1u; VkBufferImageCopy copy{}; copy.bufferOffset = item.offset; copy.bufferRowLength = 0; @@ -2028,10 +2035,10 @@ namespace MobileGL::MG_Backend::DirectVulkan { copy.imageSubresource.aspectMask = aspectMask; copy.imageSubresource.mipLevel = item.level; copy.imageSubresource.baseArrayLayer = item.baseArrayLayer; - copy.imageSubresource.layerCount = 1; + copy.imageSubresource.layerCount = depthSelectsArrayLayer ? depthOrLayers : 1; copy.imageOffset = {0, 0, 0}; copy.imageExtent = {static_cast(item.texelSize.x()), static_cast(item.texelSize.y()), - item.texelSize.z() > 0 ? static_cast(item.texelSize.z()) : 1u}; + depthSelectsArrayLayer ? 1u : depthOrLayers}; vkCmdCopyBufferToImage(commandBuffer, stagingBuffer, outResource.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©); }