In D3D11, force block compressed textures to have dimensions divisible by 4

Fixes #17745 (crash when loading certain texture packs in D3D11)

This is an old unfortunate limitation. Only applies to the top mip
level, which makes it obvious that it's kinda unnecessary for the
hardware and indeed, Vulkan and OpenGL don't have this limitation.
This commit is contained in:
Henrik Rydgård
2023-07-20 19:44:00 +02:00
parent 2985faa828
commit ace217008a
4 changed files with 22 additions and 0 deletions
+10
View File
@@ -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) {
+3
View File
@@ -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;
}
+8
View File
@@ -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);
+1
View File
@@ -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