diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index 53668c89c189..d95ee297fbe4 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -513,6 +513,10 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference bool bc = Draw::DataFormatIsBlockCompressed(*pixelFormat, &blockSize); _dbg_assert_(bc || *pixelFormat == Draw::DataFormat::R8G8B8A8_UNORM); + if (bc && (level.w & 3) != 0 || (level.h & 3) != 0) { + WARN_LOG(G3D, "Block compressed replacement texture '%s' not divisible by 4x4 (%dx%d). In D3D11 (only!) we will have to expand (potentially causing glitches).", filename.c_str(), level.w, level.h); + } + data_.resize(numMips); basist::ktx2_transcoder_state transcodeState; // Each thread needs one of these. @@ -546,6 +550,7 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference } transcoder.clear(); vfs_->CloseFile(openFile); + return LoadLevelResult::DONE; // don't read more levels } else if (imageType == ReplacedImageType::DDS) { // TODO: Do better with alphaStatus, it's possible. @@ -562,6 +567,10 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference bool bc = Draw::DataFormatIsBlockCompressed(*pixelFormat, &blockSize); _dbg_assert_(bc); + if (bc && (level.w & 3) != 0 || (level.h & 3) != 0) { + WARN_LOG(G3D, "Block compressed replacement texture '%s' not divisible by 4x4 (%dx%d). In D3D11 (only!) we will have to expand (potentially causing glitches).", filename.c_str(), level.w, level.h); + } + data_.resize(numMips); // A DDS File can contain multiple mipmaps. @@ -583,6 +592,7 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference level.fileRef = nullptr; // We only provide a fileref on level 0 if we have mipmaps. } vfs_->CloseFile(openFile); + return LoadLevelResult::DONE; // don't read more levels } else if (imageType == ReplacedImageType::ZIM) { diff --git a/GPU/Common/TextureReplacer.cpp b/GPU/Common/TextureReplacer.cpp index da0f94401c17..5e7b471c62ff 100644 --- a/GPU/Common/TextureReplacer.cpp +++ b/GPU/Common/TextureReplacer.cpp @@ -337,6 +337,9 @@ bool TextureReplacer::LoadIniValues(IniFile &ini, VFSBackend *dir, bool isOverri } } + auto gr = GetI18NCategory(I18NCat::GRAPHICS); + + g_OSD.Show(OSDType::MESSAGE_SUCCESS, gr->T("Texture replacement pack activated")); return true; } diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index d658d19a0106..465981e67379 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -348,6 +348,14 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry) { if (th > 16384) th = 16384; + // NOTE: For block-compressed textures, we'll force the size up to the closest 4x4. This is due to an + // unfortunate restriction in D3D11 (and early D3D12). We'll warn about it in the log to give texture pack + // authors notice to fix it. + if (plan.doReplace && Draw::DataFormatIsBlockCompressed(plan.replaced->Format(), nullptr)) { + tw = (tw + 3) & ~3; + th = (th + 3) & ~3; + } + if (plan.depth == 1) { // We don't yet have mip generation, so clamp the number of levels to the ones we can load directly. levels = std::min(plan.levelsToCreate, plan.levelsToLoad); diff --git a/assets/lang/en_US.ini b/assets/lang/en_US.ini index 3462f24c2f0e..7c0999fe1dd3 100644 --- a/assets/lang/en_US.ini +++ b/assets/lang/en_US.ini @@ -630,6 +630,7 @@ Stereo rendering = Stereo rendering Stretch = Stretch Texture Filter = Texture filtering Texture Filtering = Texture filtering +Texture replacement pack activated = Texture replacement pack activated Texture Scaling = Texture scaling Texture Shader = Texture shader Turn off Hardware Tessellation - unsupported = Turn off "hardware tessellation": unsupported