From 434ffc982852c75b557ffbd053594c84de6d9214 Mon Sep 17 00:00:00 2001 From: Samuliak Date: Tue, 10 Dec 2024 08:11:10 +0100 Subject: [PATCH] clamp texture mip count --- src/Cafe/HW/Latte/Core/LatteTexture.cpp | 34 ++++++++++++++++ src/Cafe/HW/Latte/Core/LatteTextureLegacy.cpp | 40 +++---------------- .../Latte/Renderer/Metal/LatteTextureMtl.cpp | 4 ++ .../Renderer/Metal/LatteTextureViewMtl.cpp | 4 ++ 4 files changed, 47 insertions(+), 35 deletions(-) diff --git a/src/Cafe/HW/Latte/Core/LatteTexture.cpp b/src/Cafe/HW/Latte/Core/LatteTexture.cpp index 3c561000..4445fb26 100644 --- a/src/Cafe/HW/Latte/Core/LatteTexture.cpp +++ b/src/Cafe/HW/Latte/Core/LatteTexture.cpp @@ -1308,6 +1308,40 @@ LatteTexture::LatteTexture(Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddre { this->enableReadback = true; } + + // calculate number of potential mip levels (from effective size) + sint32 effectiveWidth = width; + sint32 effectiveHeight = height; + sint32 effectiveDepth = depth; + if (this->overwriteInfo.hasResolutionOverwrite) + { + effectiveWidth = this->overwriteInfo.width; + effectiveHeight = this->overwriteInfo.height; + effectiveDepth = this->overwriteInfo.depth; + } + this->maxPossibleMipLevels = 1; + if (dim != Latte::E_DIM::DIM_3D) + { + for (sint32 i = 0; i < 20; i++) + { + if ((effectiveWidth >> i) <= 1 && (effectiveHeight >> i) <= 1) + { + this->maxPossibleMipLevels = i + 1; + break; + } + } + } + else + { + for (sint32 i = 0; i < 20; i++) + { + if ((effectiveWidth >> i) <= 1 && (effectiveHeight >> i) <= 1 && (effectiveDepth >> i) <= 1) + { + this->maxPossibleMipLevels = i + 1; + break; + } + } + } } LatteTexture::~LatteTexture() diff --git a/src/Cafe/HW/Latte/Core/LatteTextureLegacy.cpp b/src/Cafe/HW/Latte/Core/LatteTextureLegacy.cpp index 50aa4d87..25c9f54b 100644 --- a/src/Cafe/HW/Latte/Core/LatteTextureLegacy.cpp +++ b/src/Cafe/HW/Latte/Core/LatteTextureLegacy.cpp @@ -13,7 +13,7 @@ struct TexScaleXY float xy[2]; }; -struct +struct { TexScaleXY perUnit[Latte::GPU_LIMITS::NUM_TEXTURES_PER_STAGE]; // stores actualResolution/effectiveResolution ratio for each texture }LatteTextureScale[static_cast(LatteConst::ShaderType::TotalCount)] = { }; @@ -73,46 +73,16 @@ void LatteTexture_ReloadData(LatteTexture* tex) LatteTextureView* LatteTexture_CreateTexture(Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth) { const auto tex = g_renderer->texture_createTextureEx(dim, physAddress, physMipAddress, format, width, height, depth, pitch, mipLevels, swizzle, tileMode, isDepth); + // init slice/mip info array LatteTexture_InitSliceAndMipInfo(tex); LatteTexture_RegisterTextureMemoryOccupancy(tex); cemu_assert_debug(mipLevels != 0); - // calculate number of potential mip levels (from effective size) - sint32 effectiveWidth = width; - sint32 effectiveHeight = height; - sint32 effectiveDepth = depth; - if (tex->overwriteInfo.hasResolutionOverwrite) - { - effectiveWidth = tex->overwriteInfo.width; - effectiveHeight = tex->overwriteInfo.height; - effectiveDepth = tex->overwriteInfo.depth; - } - tex->maxPossibleMipLevels = 1; - if (dim != Latte::E_DIM::DIM_3D) - { - for (sint32 i = 0; i < 20; i++) - { - if ((effectiveWidth >> i) <= 1 && (effectiveHeight >> i) <= 1) - { - tex->maxPossibleMipLevels = i + 1; - break; - } - } - } - else - { - for (sint32 i = 0; i < 20; i++) - { - if ((effectiveWidth >> i) <= 1 && (effectiveHeight >> i) <= 1 && (effectiveDepth >> i) <= 1) - { - tex->maxPossibleMipLevels = i + 1; - break; - } - } - } + LatteTexture_ReloadData(tex); LatteTC_MarkTextureStillInUse(tex); LatteTC_RegisterTexture(tex); + // create initial view that maps to the whole texture tex->baseView = tex->GetOrCreateView(0, tex->mipLevels, 0, tex->depth); return tex->baseView; @@ -371,4 +341,4 @@ uint64 LatteTexture_getNextUpdateEventCounter() void LatteTexture_init() { -} \ No newline at end of file +} diff --git a/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureMtl.cpp b/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureMtl.cpp index da00d7ec..aedd5a3e 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureMtl.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureMtl.cpp @@ -56,6 +56,10 @@ LatteTextureMtl::LatteTextureMtl(class MetalRenderer* mtlRenderer, Latte::E_DIM } desc->setTextureType(textureType); + // Clamp mip levels + mipLevels = std::min(mipLevels, (uint32)maxPossibleMipLevels); + mipLevels = std::max(mipLevels, (uint32)1); + desc->setWidth(effectiveBaseWidth); desc->setHeight(effectiveBaseHeight); desc->setMipmapLevelCount(mipLevels); diff --git a/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureViewMtl.cpp b/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureViewMtl.cpp index 5374126a..3b157bf4 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureViewMtl.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureViewMtl.cpp @@ -180,6 +180,10 @@ MTL::Texture* LatteTextureViewMtl::CreateSwizzledView(uint32 gpuSamplerSwizzle) swizzle.blue = GetMtlTextureSwizzle(compSelB); swizzle.alpha = GetMtlTextureSwizzle(compSelA); + // Clamp mip levels + levelCount = std::min(levelCount, m_baseTexture->maxPossibleMipLevels - baseLevel); + levelCount = std::max(levelCount, (uint32)1); + auto pixelFormat = GetMtlPixelFormat(format, m_baseTexture->IsDepth()); MTL::Texture* texture = m_baseTexture->GetTexture()->newTextureView(pixelFormat, textureType, NS::Range::Make(baseLevel, levelCount), NS::Range::Make(baseLayer, layerCount), swizzle);