Fix image format when dumping textures.

Fixes #15831
This commit is contained in:
Henrik Rydgård 2022-09-01 15:02:51 +02:00
parent 11d4f9acb6
commit 2bf0c86ac7
6 changed files with 33 additions and 25 deletions

View File

@ -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);

View File

@ -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) {

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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<uint8_t> 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);
}
}