From d0d53091a832fe0cf474b9780637d855c3d9aacb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 29 Jul 2022 12:59:43 +0200 Subject: [PATCH] Change from maxLevel to levelsToLoad, for better readability. Cleanup. --- Common/GPU/OpenGL/GLQueueRunner.cpp | 4 +-- Common/GPU/OpenGL/GLQueueRunner.h | 2 +- Common/GPU/OpenGL/GLRenderManager.h | 4 +-- Core/TextureReplacer.cpp | 4 +-- Core/TextureReplacer.h | 18 +++++----- GPU/Common/TextureCacheCommon.cpp | 22 +++++------- GPU/Common/TextureCacheCommon.h | 12 +++---- GPU/D3D11/TextureCacheD3D11.cpp | 13 +++++-- GPU/Directx9/TextureCacheDX9.cpp | 7 ++-- GPU/GLES/TextureCacheGLES.cpp | 53 +++++++++++------------------ GPU/Vulkan/TextureCacheVulkan.cpp | 2 +- 11 files changed, 66 insertions(+), 75 deletions(-) diff --git a/Common/GPU/OpenGL/GLQueueRunner.cpp b/Common/GPU/OpenGL/GLQueueRunner.cpp index 328605d1e2..f4cd16737f 100644 --- a/Common/GPU/OpenGL/GLQueueRunner.cpp +++ b/Common/GPU/OpenGL/GLQueueRunner.cpp @@ -376,9 +376,9 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps, bool ski boundTexture = tex->texture; } if (!gl_extensions.IsGLES || gl_extensions.GLES3) { - glTexParameteri(tex->target, GL_TEXTURE_MAX_LEVEL, step.texture_finalize.maxLevel); + glTexParameteri(tex->target, GL_TEXTURE_MAX_LEVEL, step.texture_finalize.loadedLevels - 1); } - tex->maxLod = (float)step.texture_finalize.maxLevel; + tex->maxLod = (float)step.texture_finalize.loadedLevels - 1; if (step.texture_finalize.genMips) { glGenerateMipmap(tex->target); } diff --git a/Common/GPU/OpenGL/GLQueueRunner.h b/Common/GPU/OpenGL/GLQueueRunner.h index 8dec753949..715bc3382a 100644 --- a/Common/GPU/OpenGL/GLQueueRunner.h +++ b/Common/GPU/OpenGL/GLQueueRunner.h @@ -267,7 +267,7 @@ struct GLRInitStep { } texture_image; struct { GLRTexture *texture; - int maxLevel; + int loadedLevels; bool genMips; } texture_finalize; }; diff --git a/Common/GPU/OpenGL/GLRenderManager.h b/Common/GPU/OpenGL/GLRenderManager.h index 835034defc..bb5f49a92a 100644 --- a/Common/GPU/OpenGL/GLRenderManager.h +++ b/Common/GPU/OpenGL/GLRenderManager.h @@ -565,10 +565,10 @@ public: curRenderStep_->commands.push_back(_data); } - void FinalizeTexture(GLRTexture *texture, int maxLevels, bool genMips) { + void FinalizeTexture(GLRTexture *texture, int loadedLevels, bool genMips) { GLRInitStep step{ GLRInitStepType::TEXTURE_FINALIZE }; step.texture_finalize.texture = texture; - step.texture_finalize.maxLevel = maxLevels; + step.texture_finalize.loadedLevels = loadedLevels; step.texture_finalize.genMips = genMips; initSteps_.push_back(step); } diff --git a/Core/TextureReplacer.cpp b/Core/TextureReplacer.cpp index c38ef1fe44..48c9905e38 100644 --- a/Core/TextureReplacer.cpp +++ b/Core/TextureReplacer.cpp @@ -845,8 +845,8 @@ void ReplacedTexture::Prepare() { if (cancelPrepare_) return; - levelData_.resize(MaxLevel() + 1); - for (int i = 0; i <= MaxLevel(); ++i) { + levelData_.resize(NumLevels()); + for (int i = 0; i < NumLevels(); ++i) { if (cancelPrepare_) break; PrepareData(i); diff --git a/Core/TextureReplacer.h b/Core/TextureReplacer.h index 1daaa1e30f..e01a03d2a4 100644 --- a/Core/TextureReplacer.h +++ b/Core/TextureReplacer.h @@ -60,8 +60,7 @@ struct ReplacementCacheKey { u64 cachekey; u32 hash; - ReplacementCacheKey(u64 c, u32 h) : cachekey(c), hash(h) { - } + ReplacementCacheKey(u64 c, u32 h) : cachekey(c), hash(h) { } bool operator ==(const ReplacementCacheKey &k) const { return k.cachekey == cachekey && k.hash == hash; @@ -85,8 +84,7 @@ struct ReplacementAliasKey { }; }; - ReplacementAliasKey(u64 c, u32 h, u32 l) : cachekey(c), level(l), hash(h) { - } + ReplacementAliasKey(u64 c, u32 h, u32 l) : cachekey(c), level(l), hash(h) { } bool operator ==(const ReplacementAliasKey &k) const { return k.cachekey == cachekey && k.hashAndLevel == hashAndLevel; @@ -119,11 +117,11 @@ namespace std { struct ReplacedTexture { ~ReplacedTexture(); - inline bool Valid() { + inline bool Valid() const { return !levels_.empty(); } - bool GetSize(int level, int &w, int &h) { + bool GetSize(int level, int &w, int &h) const { if ((size_t)level < levels_.size()) { w = levels_[level].w; h = levels_[level].h; @@ -132,18 +130,18 @@ struct ReplacedTexture { return false; } - int MaxLevel() { - return (int)levels_.size() - 1; + int NumLevels() const { + return (int)levels_.size(); } - Draw::DataFormat Format(int level) { + Draw::DataFormat Format(int level) const { if ((size_t)level < levels_.size()) { return levels_[level].fmt; } return Draw::DataFormat::R8G8B8A8_UNORM; } - u8 AlphaStatus() { + u8 AlphaStatus() const { return (u8)alphaStatus_; } diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 331507745d..dcef0a69a7 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -2020,13 +2020,12 @@ bool TextureCacheCommon::PrepareBuildTexture(BuildTexturePlan &plan, TexCacheEnt plan.badMipSizes = false; // maxLevel here is the max level to upload. Not the count. - plan.canAutoGen = false; - plan.maxLevelToLoad = entry->maxLevel; - for (int i = 0; i <= plan.maxLevelToLoad; i++) { + plan.levelsToLoad = entry->maxLevel + 1; + for (int i = 0; i < plan.levelsToLoad; i++) { // If encountering levels pointing to nothing, adjust max level. u32 levelTexaddr = gstate.getTextureAddress(i); if (!Memory::IsValidAddress(levelTexaddr)) { - plan.maxLevelToLoad = i - 1; + plan.levelsToLoad = i; break; } @@ -2034,7 +2033,7 @@ bool TextureCacheCommon::PrepareBuildTexture(BuildTexturePlan &plan, TexCacheEnt int tw = gstate.getTextureWidth(i); int th = gstate.getTextureHeight(i); if (tw == 1 || th == 1) { - plan.maxLevelToLoad = i; + plan.levelsToLoad = i + 1; // next level is assumed to be invalid break; } @@ -2048,9 +2047,6 @@ bool TextureCacheCommon::PrepareBuildTexture(BuildTexturePlan &plan, TexCacheEnt else if (th != 1 && th != (lastH >> 1)) plan.badMipSizes = true; } - - if (lastW > tw || lastH > th) - plan.canAutoGen = true; } } @@ -2064,7 +2060,7 @@ bool TextureCacheCommon::PrepareBuildTexture(BuildTexturePlan &plan, TexCacheEnt } if (plan.badMipSizes) { - plan.maxLevelToLoad = 0; + plan.levelsToLoad = 1; } if (plan.hardwareScaling) { @@ -2074,7 +2070,7 @@ bool TextureCacheCommon::PrepareBuildTexture(BuildTexturePlan &plan, TexCacheEnt // We generate missing mipmaps from maxLevel+1 up to this level. maxLevel can get overwritten below // such as when using replacement textures - but let's keep the same amount of levels for generation. // Not all backends will generate mipmaps, and in GL we can't really control the number of levels. - plan.levelsToCreate = plan.maxLevelToLoad + 1; + plan.levelsToCreate = plan.levelsToLoad; plan.w = gstate.getTextureWidth(0); plan.h = gstate.getTextureHeight(0); @@ -2083,7 +2079,7 @@ bool TextureCacheCommon::PrepareBuildTexture(BuildTexturePlan &plan, TexCacheEnt if (plan.replaced->Valid()) { // We're replacing, so we won't scale. plan.scaleFactor = 1; - plan.maxLevelToLoad = plan.replaced->MaxLevel(); + plan.levelsToLoad = plan.replaced->NumLevels(); plan.badMipSizes = false; } @@ -2113,7 +2109,7 @@ bool TextureCacheCommon::PrepareBuildTexture(BuildTexturePlan &plan, TexCacheEnt // TODO: Support reading actual mip levels for upscaled images, instead of just generating them. // Maybe can just remove this check? if (plan.scaleFactor > 1) { - plan.maxLevelToLoad = 0; + plan.levelsToLoad = 1; bool enableVideoUpscaling = false; @@ -2129,7 +2125,7 @@ bool TextureCacheCommon::PrepareBuildTexture(BuildTexturePlan &plan, TexCacheEnt // NOTE: Since the level is not part of the cache key, we assume it never changes. plan.baseLevelSrc = std::max(0, gstate.getTexLevelOffset16() / 16); plan.levelsToCreate = 1; - plan.maxLevelToLoad = 0; + plan.levelsToLoad = 1; } if (plan.levelsToCreate == 1) { diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index 753eac18ac..dc650ddaaf 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -240,14 +240,12 @@ struct BuildTexturePlan { // However, we still respect baseLevelSrc. bool badMipSizes; - // Set if we can autogenerate mipmaps. Probably redundant. - bool canAutoGen; + // Number of mip levels to load from PSP memory (or replacement). + int levelsToLoad; - // Highest index of a level to load. - int maxLevelToLoad; - - // The number of levels in total to create. If more than maxLevelToLoad, - // the backend is expected to either generate the levels, or limit itself to maxLevelToLoad. + // The number of levels in total to create. + // If greater than maxLevelToLoad, the backend is expected to either generate + // the missing levels, or limit itself to levelsToLoad levels. int levelsToCreate; // Load the 0-mip from this PSP texture level instead of 0. diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index 9324263530..1544bb028c 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -472,6 +472,9 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry) { } } + // We don't yet have mip generation, so clamp the number of levels to the ones we can load directly. + int levels = std::min(plan.levelsToCreate, plan.levelsToLoad); + D3D11_TEXTURE2D_DESC desc{}; desc.CPUAccessFlags = 0; desc.Usage = D3D11_USAGE_DEFAULT; @@ -480,7 +483,7 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry) { desc.Width = tw; desc.Height = th; desc.Format = tfmt; - desc.MipLevels = plan.levelsToCreate; + desc.MipLevels = levels; desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; ASSERT_SUCCESS(device_->CreateTexture2D(&desc, nullptr, &texture)); @@ -489,10 +492,16 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry) { entry->textureView = view; // Mipmapping is only enabled when texture scaling is disabled. - for (int i = 0; i < plan.levelsToCreate; i++) { + for (int i = 0; i < levels; i++) { LoadTextureLevel(*entry, *plan.replaced, (i == 0) ? plan.baseLevelSrc : i, i, plan.scaleFactor, dstFmt); } + if (levels == 1) { + entry->status |= TexCacheEntry::STATUS_NO_MIPS; + } else { + entry->status &= ~TexCacheEntry::STATUS_NO_MIPS; + } + if (plan.replaced->Valid()) { entry->SetAlphaStatus(TexCacheEntry::TexStatus(plan.replaced->AlphaStatus())); } diff --git a/GPU/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index c0ff2f25a2..001bb571be 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -428,7 +428,10 @@ void TextureCacheDX9::BuildTexture(TexCacheEntry *const entry) { } } - HRESULT hr = device_->CreateTexture(tw, th, plan.levelsToCreate, usage, tfmt, pool, &texture, NULL); + // We don't yet have mip generation, so clamp the number of levels to the ones we can load directly. + int levels = std::min(plan.levelsToCreate, plan.levelsToLoad); + + HRESULT hr = device_->CreateTexture(tw, th, levels, usage, tfmt, pool, &texture, NULL); if (FAILED(hr)) { INFO_LOG(G3D, "Failed to create D3D texture: %dx%d", tw, th); @@ -442,7 +445,7 @@ void TextureCacheDX9::BuildTexture(TexCacheEntry *const entry) { } // Mipmapping is only enabled when texture scaling is disabled. - for (int i = 0; i < plan.levelsToCreate; i++) { + for (int i = 0; i < levels; i++) { int dstLevel = i; HRESULT result; uint32_t lockFlag = dstLevel == 0 ? D3DLOCK_DISCARD : 0; // Can only discard the top level diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index c1fd549518..38a7858e5c 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -443,47 +443,34 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry) { // than determining if we can wrap this texture size, that is, it's pow2 or not on very old hardware, else true. // This will be easy after .. well, yet another refactoring, where I hoist the size calculation out of LoadTextureLevel // and unify BuildTexture. - entry->textureName = render_->CreateTexture(GL_TEXTURE_2D, 16, 16, 1); + entry->textureName = render_->CreateTexture(GL_TEXTURE_2D, plan.w, plan.h, plan.levelsToCreate); Draw::DataFormat dstFmt = GetDestFormat(GETextureFormat(entry->format), gstate.getClutPaletteFormat()); - LoadTextureLevel(*entry, *plan.replaced, plan.baseLevelSrc, 0, plan.scaleFactor, dstFmt); - - // Mipmapping is only enabled when texture scaling is disabled. - int texMaxLevel = 0; - bool genMips = false; - if (plan.maxLevelToLoad > 0 && plan.scaleFactor == 1) { - if (gstate_c.Supports(GPU_SUPPORTS_TEXTURE_LOD_CONTROL)) { - if (plan.badMipSizes) { - // WARN_LOG(G3D, "Bad mipmap for texture sized %dx%dx%d - autogenerating", w, h, (int)format); - if (plan.canAutoGen) { - genMips = true; - } else { - texMaxLevel = 0; - plan.maxLevelToLoad = 0; - } - } else { - for (int i = 1; i <= plan.maxLevelToLoad; i++) { - LoadTextureLevel(*entry, *plan.replaced, i, i, plan.scaleFactor, dstFmt); - } - texMaxLevel = plan.maxLevelToLoad; - } + // Apply some additional compatibility checks. + if (plan.levelsToLoad > 1) { + // Avoid PowerVR driver bug + if (plan.w > 1 && plan.h > 1 && !(plan.h > plan.w && draw_->GetBugs().Has(Draw::Bugs::PVR_GENMIPMAP_HEIGHT_GREATER))) { // Really! only seems to fail if height > width + // It's ok to generate mipmaps beyond the loaded levels. } else { - // Avoid PowerVR driver bug - if (plan.canAutoGen && plan.w > 1 && plan.h > 1 && !(plan.h > plan.w && draw_->GetBugs().Has(Draw::Bugs::PVR_GENMIPMAP_HEIGHT_GREATER))) { // Really! only seems to fail if height > width - // NOTICE_LOG(G3D, "Generating mipmap for texture sized %dx%d%d", w, h, (int)format); - genMips = true; - } else { - plan.maxLevelToLoad = 0; - } + plan.levelsToCreate = plan.levelsToLoad; } - } else if (gstate_c.Supports(GPU_SUPPORTS_TEXTURE_LOD_CONTROL)) { - texMaxLevel = 0; + } + + if (!gstate_c.Supports(GPU_SUPPORTS_TEXTURE_LOD_CONTROL)) { + // Force no additional mipmaps. + plan.levelsToCreate = plan.levelsToLoad; } - render_->FinalizeTexture(entry->textureName, texMaxLevel, genMips); + for (int i = 0; i < plan.levelsToLoad; i++) { + LoadTextureLevel(*entry, *plan.replaced, i == 0 ? plan.baseLevelSrc : i, i, plan.scaleFactor, dstFmt); + } - if (plan.maxLevelToLoad == 0) { + bool genMips = plan.levelsToCreate > plan.levelsToLoad; + + render_->FinalizeTexture(entry->textureName, plan.levelsToLoad, genMips); + + if (plan.levelsToLoad == 1) { entry->status |= TexCacheEntry::STATUS_NO_MIPS; } else { entry->status &= ~TexCacheEntry::STATUS_NO_MIPS; diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index fd562bc48a..b204a8a54c 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -649,7 +649,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { if (replaced.Valid()) { // We're replacing, so we won't scale. scaleFactor = 1; - maxLevel = replaced.MaxLevel(); + maxLevel = replaced.NumLevels() - 1; badMipSizes = false; }