diff --git a/pcsx2/GS/Renderers/Common/GSDevice.cpp b/pcsx2/GS/Renderers/Common/GSDevice.cpp index 96c9c58867..7fc883bafc 100644 --- a/pcsx2/GS/Renderers/Common/GSDevice.cpp +++ b/pcsx2/GS/Renderers/Common/GSDevice.cpp @@ -74,11 +74,6 @@ const char* shaderName(PresentShader value) } } -static int MipmapLevelsForSize(int width, int height) -{ - return std::min(static_cast(std::log2(std::max(width, height))) + 1, MAXIMUM_TEXTURE_MIPMAP_LEVELS); -} - #ifdef PCSX2_DEVBUILD enum class TextureLabel @@ -285,6 +280,11 @@ std::optional GSDevice::ReadShaderSource(const char* filename) return FileSystem::ReadFileToString(Path::Combine(EmuFolders::Resources, filename).c_str()); } +int GSDevice::GetMipmapLevelsForSize(int width, int height) +{ + return std::min(static_cast(std::log2(std::max(width, height))) + 1, MAXIMUM_TEXTURE_MIPMAP_LEVELS); +} + bool GSDevice::Create() { m_vsync_mode = Host::GetEffectiveVSyncMode(); @@ -546,7 +546,8 @@ GSTexture* GSDevice::CreateDepthStencil(int w, int h, GSTexture::Format format, GSTexture* GSDevice::CreateTexture(int w, int h, int mipmap_levels, GSTexture::Format format, bool prefer_reuse /* = false */) { - const int levels = mipmap_levels < 0 ? MipmapLevelsForSize(w, h) : mipmap_levels; + pxAssert(mipmap_levels != 0 && (mipmap_levels < 0 || mipmap_levels <= GetMipmapLevelsForSize(w, h))); + const int levels = mipmap_levels < 0 ? GetMipmapLevelsForSize(w, h) : mipmap_levels; return FetchSurface(GSTexture::Type::Texture, w, h, levels, format, false, m_features.prefer_new_textures && !prefer_reuse); } diff --git a/pcsx2/GS/Renderers/Common/GSDevice.h b/pcsx2/GS/Renderers/Common/GSDevice.h index c29c617279..bc6b626588 100644 --- a/pcsx2/GS/Renderers/Common/GSDevice.h +++ b/pcsx2/GS/Renderers/Common/GSDevice.h @@ -815,6 +815,9 @@ public: /// Reads the specified shader source file. static std::optional ReadShaderSource(const char* filename); + /// Returns the maximum number of mipmap levels for a given texture size. + static int GetMipmapLevelsForSize(int width, int height); + __fi u64 GetPoolMemoryUsage() const { return m_pool_memory_usage; } __fi FeatureSupport Features() const { return m_features; } diff --git a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp index 780cc85923..c40c0007da 100644 --- a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp +++ b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp @@ -4166,7 +4166,7 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con { // lod won't contain the full range when using basic mipmapping, only that // which is hashed, so we just allocate the full thing. - tlevels = (GSConfig.HWMipmap != HWMipmapLevel::Full) ? -1 : (lod->y - lod->x + 1); + tlevels = (GSConfig.HWMipmap != HWMipmapLevel::Full) ? -1 : std::min(lod->y - lod->x + 1, GSDevice::GetMipmapLevelsForSize(tw, th)); src->m_lod = *lod; } @@ -5069,7 +5069,7 @@ GSTextureCache::HashCacheEntry* GSTextureCache::LookupHashCache(const GIFRegTEX0 // expand/upload texture const int tw = region.HasX() ? region.GetWidth() : (1 << TEX0.TW); const int th = region.HasY() ? region.GetHeight() : (1 << TEX0.TH); - const int tlevels = lod ? ((GSConfig.HWMipmap != HWMipmapLevel::Full) ? -1 : (lod->y - lod->x + 1)) : 1; + const int tlevels = lod ? ((GSConfig.HWMipmap != HWMipmapLevel::Full) ? -1 : std::min(lod->y - lod->x + 1, GSDevice::GetMipmapLevelsForSize(tw, th))) : 1; GSTexture* tex = g_gs_device->CreateTexture(tw, th, tlevels, paltex ? GSTexture::Format::UNorm8 : GSTexture::Format::Color); if (!tex) {