From 8ca20e28caa8751ed2513e7550fd77c38a99ecbe Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Thu, 30 Jul 2026 02:43:32 -0400 Subject: [PATCH] [Fix] (DirectVulkan): size texture backings by their defined mip level count - every non-MSAA texture was allocated with a full mip chain regardless of how many levels the GL texture actually defines, so MC's 3044x1440 main colour and depth render targets each carried 12 levels where ANGLE allocates one; a level-0-only texture now gets a single-level backing and upgrades to the full chain exactly once when a second level is first defined, through the existing preserve-copy recreation path - saves a third of the memory of every mip-less texture and keeps single-level render targets off the multi-mip image layout entirely, which also removes the surface the Adreno 650 implicit-LOD overread workaround (ForceExplicitLod0SamplePass) exists to defend - measured perf-neutral on Adreno 650 / MC 26.2 (the driver keeps full UBWC on multi-mip render targets), so this is a memory/robustness fix, not a speed one --- .../DirectVulkan/Renderer/VkTextureManager.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.cpp index 2972f9b8..d5f238c8 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.cpp @@ -1436,8 +1436,17 @@ namespace MobileGL::MG_Backend::DirectVulkan { return false; } const Bool isMultisampleTexture = IsMultisampleTextureUploadTarget(uploadTarget); + // A texture that has only ever defined level 0 gets a single-level backing + // (ANGLE's model). Preallocating the full chain put every render target + // onto Adreno's multi-mip image layout and grew each texture by a third + // for levels most textures never define. Once a second level is defined + // the backing is recreated ONE time with the full chain (the + // preserve-copy path below carries the pixels over), so sequentially- + // defined atlas mips do not recreate per level, and glGenerateMipmap - + // which defines every level before syncing - works unchanged. const Uint32 backingMipLevels = - isMultisampleTexture ? 1u : std::max(mipLevels, ComputeFullMipLevelCount(texelSize)); + isMultisampleTexture ? 1u + : (mipLevels > 1 ? std::max(mipLevels, ComputeFullMipLevelCount(texelSize)) : 1u); TextureShapeInfo shapeInfo{}; const Bool supportedShape = TryResolveTextureShapeInfo(texture, uploadTarget, texelSize, shapeInfo); MOBILEGL_ASSERT(supportedShape,