From df3b961d5dfa84ad54add2270fb111e6fe7058a8 Mon Sep 17 00:00:00 2001 From: PixelyIon Date: Mon, 30 Jan 2023 21:05:58 +0530 Subject: [PATCH] Fix mipmapped GOB dimensions calculation When calculating mip-level dimensions in terms of GOBs, they need to be divided by 2 while rounding upwards rather than downwards. This fixes corrupted textures and OOB access on lower mip levels across a substantial amount of titles, reducing arbitrary crashes as a result. --- app/src/main/cpp/skyline/gpu/texture/layout.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/src/main/cpp/skyline/gpu/texture/layout.cpp b/app/src/main/cpp/skyline/gpu/texture/layout.cpp index 58360993..01d8f0fa 100644 --- a/app/src/main/cpp/skyline/gpu/texture/layout.cpp +++ b/app/src/main/cpp/skyline/gpu/texture/layout.cpp @@ -42,10 +42,10 @@ namespace skyline::gpu::texture { // Iterate over every level, adding the size of the current level to the total size totalSize += (GobWidth * gobsWidth) * (GobHeight * util::AlignUp(gobsHeight, gobBlockHeight)) * util::AlignUp(gobsDepth, gobBlockDepth); - // Successively divide every dimension by 2 until the final level is reached - gobsWidth = std::max(gobsWidth / 2, 1UL); - gobsHeight = std::max(gobsHeight / 2, 1UL); - gobsDepth = std::max(gobsDepth / 2, 1UL); + // Successively divide every dimension by 2 until the final level is reached, the division is rounded up to contain the padding GOBs + gobsWidth = std::max(util::DivideCeil(gobsWidth, 2UL), 1UL); + gobsHeight = std::max(util::DivideCeil(gobsHeight, 2UL), 1UL); + gobsDepth = std::max(gobsDepth / 2, 1UL); // The GOB depth is the same as the depth dimension and needs to be rounded down during the division gobBlockHeight = CalculateBlockGobs(gobBlockHeight, gobsHeight); gobBlockDepth = CalculateBlockGobs(gobBlockDepth, gobsDepth); @@ -74,8 +74,8 @@ namespace skyline::gpu::texture { gobBlockHeight, gobBlockDepth ); - gobsWidth = std::max(gobsWidth / 2, 1UL); - gobsHeight = std::max(gobsHeight / 2, 1UL); + gobsWidth = std::max(util::DivideCeil(gobsWidth, 2UL), 1UL); + gobsHeight = std::max(util::DivideCeil(gobsHeight, 2UL), 1UL); dimensions.width = std::max(dimensions.width / 2, 1U); dimensions.height = std::max(dimensions.height / 2, 1U);