From 2bf0c86ac7b3e8c8d98077474eea1aa3f9ada77d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 1 Sep 2022 15:02:51 +0200 Subject: [PATCH] Fix image format when dumping textures. Fixes #15831 --- GPU/Common/TextureCacheCommon.cpp | 15 ++++++++++++++- GPU/Common/TextureCacheCommon.h | 1 + GPU/D3D11/TextureCacheD3D11.cpp | 2 +- GPU/Directx9/TextureCacheDX9.cpp | 2 +- GPU/GLES/TextureCacheGLES.cpp | 8 +++----- GPU/Vulkan/TextureCacheVulkan.cpp | 30 +++++++++++++----------------- 6 files changed, 33 insertions(+), 25 deletions(-) diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index faa03ad261..acce603667 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -2388,6 +2388,7 @@ bool TextureCacheCommon::PrepareBuildTexture(BuildTexturePlan &plan, TexCacheEnt plan.replaceValid = plan.replaced->Valid(); } + plan.saveTexture = false; if (plan.replaceValid) { // We're replacing, so we won't scale. plan.scaleFactor = 1; @@ -2397,6 +2398,18 @@ bool TextureCacheCommon::PrepareBuildTexture(BuildTexturePlan &plan, TexCacheEnt // But, we still need to create the texture at a larger size. plan.replaced->GetSize(0, plan.createW, plan.createH); } else { + if (replacer_.Enabled() && !plan.replaceValid && plan.depth == 1) { + ReplacedTextureDecodeInfo replacedInfo; + // TODO: Do we handle the race where a replacement becomes valid AFTER this but before we save? + replacedInfo.cachekey = entry->CacheKey(); + replacedInfo.hash = entry->fullhash; + replacedInfo.addr = entry->addr; + replacedInfo.isVideo = plan.isVideo; + replacedInfo.isFinal = (entry->status & TexCacheEntry::STATUS_TO_SCALE) == 0; + replacedInfo.scaleFactor = plan.scaleFactor; + replacedInfo.fmt = Draw::DataFormat::R8G8B8A8_UNORM; + plan.saveTexture = replacer_.WillSave(replacedInfo); + } plan.createW = plan.w * plan.scaleFactor; plan.createH = plan.h * plan.scaleFactor; } @@ -2454,7 +2467,7 @@ void TextureCacheCommon::LoadTextureLevel(TexCacheEntry &entry, uint8_t *data, i decPitch = stride; } - bool expand32 = !gstate_c.Supports(GPU_SUPPORTS_16BIT_FORMATS) || scaleFactor > 1; + bool expand32 = !gstate_c.Supports(GPU_SUPPORTS_16BIT_FORMATS) || dstFmt == Draw::DataFormat::R8G8B8A8_UNORM; CheckAlphaResult alphaResult = DecodeTextureLevel((u8 *)pixelData, decPitch, tfmt, clutformat, texaddr, srcLevel, bufw, reverseColors, expand32); entry.SetAlphaStatus(alphaResult, srcLevel); diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index e394923090..7cb79d44ce 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -272,6 +272,7 @@ struct BuildTexturePlan { ReplacedTexture *replaced; // Need to only check once since it can change during the load! bool replaceValid; + bool saveTexture; void GetMipSize(int level, int *w, int *h) const { if (replaceValid) { diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index baa8ee5e04..5cc42adee6 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -279,7 +279,7 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry) { DXGI_FORMAT dstFmt = GetDestFormat(GETextureFormat(entry->format), gstate.getClutPaletteFormat()); if (plan.replaceValid) { dstFmt = ToDXGIFormat(plan.replaced->Format(plan.baseLevelSrc)); - } else if (plan.scaleFactor > 1) { + } else if (plan.scaleFactor > 1 || plan.saveTexture) { dstFmt = DXGI_FORMAT_B8G8R8A8_UNORM; } diff --git a/GPU/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index 0ef616914d..289d52d3b7 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -241,7 +241,7 @@ void TextureCacheDX9::BuildTexture(TexCacheEntry *const entry) { D3DFORMAT dstFmt = GetDestFormat(GETextureFormat(entry->format), gstate.getClutPaletteFormat()); if (plan.replaceValid) { dstFmt = ToD3D9Format(plan.replaced->Format(plan.baseLevelSrc)); - } else if (plan.scaleFactor > 1) { + } else if (plan.scaleFactor > 1 || plan.saveTexture) { dstFmt = D3DFMT_A8R8G8B8; } diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index cf9a8e13af..928854f1e2 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -258,15 +258,13 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry) { // the bottom few levels or rely on OpenGL's autogen mipmaps instead, which might not // be as good quality as the game's own (might even be better in some cases though). - int tw = plan.w; - int th = plan.h; + int tw = plan.createW; + int th = plan.createH; Draw::DataFormat dstFmt = GetDestFormat(GETextureFormat(entry->format), gstate.getClutPaletteFormat()); if (plan.replaced->GetSize(plan.baseLevelSrc, tw, th)) { dstFmt = plan.replaced->Format(plan.baseLevelSrc); - } else if (plan.scaleFactor > 1) { - tw *= plan.scaleFactor; - th *= plan.scaleFactor; + } else if (plan.scaleFactor > 1 || plan.saveTexture) { dstFmt = Draw::DataFormat::R8G8B8A8_UNORM; } diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index 4b4ec639a9..e72464a469 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -499,21 +499,8 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { imageLayout = VK_IMAGE_LAYOUT_GENERAL; } - ReplacedTextureDecodeInfo replacedInfo; - bool willSaveTex = false; - if (replacer_.Enabled() && !plan.replaceValid && plan.depth == 1) { - // TODO: Do we handle the race where a replacement becomes valid AFTER this but before we save? - replacedInfo.cachekey = entry->CacheKey(); - replacedInfo.hash = entry->fullhash; - replacedInfo.addr = entry->addr; - replacedInfo.isVideo = plan.isVideo; - replacedInfo.isFinal = (entry->status & TexCacheEntry::STATUS_TO_SCALE) == 0; - replacedInfo.scaleFactor = plan.scaleFactor; - replacedInfo.fmt = FromVulkanFormat(VULKAN_8888_FORMAT); - willSaveTex = replacer_.WillSave(replacedInfo); - if (willSaveTex) { - actualFmt = VULKAN_8888_FORMAT; - } + if (plan.saveTexture) { + actualFmt = VULKAN_8888_FORMAT; } char texName[128]{}; @@ -588,14 +575,14 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { std::vector saveData; auto loadLevel = [&](int sz, int srcLevel, int lstride, int lfactor) { - if (willSaveTex) { + if (plan.saveTexture) { saveData.resize(sz); data = &saveData[0]; } else { data = drawEngine_->GetPushBufferForTextureData()->PushAligned(sz, &bufferOffset, &texBuf, pushAlignment); } LoadTextureLevel(*entry, (uint8_t *)data, lstride, srcLevel, lfactor, actualFmt); - if (willSaveTex) + if (plan.saveTexture) bufferOffset = drawEngine_->GetPushBufferForTextureData()->PushAligned(&saveData[0], sz, pushAlignment, &texBuf); }; @@ -646,6 +633,15 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { int w = dataScaled ? mipWidth : mipUnscaledWidth; int h = dataScaled ? mipHeight : mipUnscaledHeight; // At this point, data should be saveData, and not slow. + ReplacedTextureDecodeInfo replacedInfo; + replacedInfo.cachekey = entry->CacheKey(); + replacedInfo.hash = entry->fullhash; + replacedInfo.addr = entry->addr; + replacedInfo.isVideo = IsVideo(entry->addr); + replacedInfo.isFinal = (entry->status & TexCacheEntry::STATUS_TO_SCALE) == 0; + replacedInfo.scaleFactor = plan.scaleFactor; + replacedInfo.fmt = FromVulkanFormat(actualFmt); + replacer_.NotifyTextureDecoded(replacedInfo, data, stride, plan.baseLevelSrc + i, w, h); } }