diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index de2775aad9..49bea7c2f6 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -1451,13 +1451,17 @@ void CopyAndSumMask32(u32 *dst, const u32 *src, int width, u32 *outMask) { *outMask &= (u32)mask; } -void TextureCacheCommon::DecodeTextureLevel(u8 *out, int outPitch, GETextureFormat format, GEPaletteFormat clutformat, uint32_t texaddr, int level, int bufw, bool reverseColors, bool useBGRA, bool expandTo32bit, u32 *alphaSum, u32 *fullAlphaMask) { +CheckAlphaResult TextureCacheCommon::DecodeTextureLevel(u8 *out, int outPitch, GETextureFormat format, GEPaletteFormat clutformat, uint32_t texaddr, int level, int bufw, bool reverseColors, bool useBGRA, bool expandTo32bit) { + u32 alphaSum = 0xFFFFFFFF; + u32 fullAlphaMask = 0x0; + bool swizzled = gstate.isTextureSwizzled(); if ((texaddr & 0x00600000) != 0 && Memory::IsVRAMAddress(texaddr)) { // This means it's in a mirror, possibly a swizzled mirror. Let's report. WARN_LOG_REPORT_ONCE(texmirror, G3D, "Decoding texture from VRAM mirror at %08x swizzle=%d", texaddr, swizzled ? 1 : 0); if ((texaddr & 0x00200000) == 0x00200000) { // Technically 2 and 6 are slightly different, but this is better than nothing probably. + // We should only see this with depth textures anyway which we don't support uploading (yet). swizzled = !swizzled; } // Note that (texaddr & 0x00600000) == 0x00600000 is very likely to be depth texturing. @@ -1506,14 +1510,14 @@ void TextureCacheCommon::DecodeTextureLevel(u8 *out, int outPitch, GETextureForm if (expandTo32bit && !reverseColors) { // We simply expand the CLUT to 32-bit, then we deindex as usual. Probably the fastest way. ConvertFormatToRGBA8888(clutformat, expandClut_, clut, 16); - *fullAlphaMask = 0xFF000000; + fullAlphaMask = 0xFF000000; for (int y = 0; y < h; ++y) { - DeIndexTexture4((u32 *)(out + outPitch * y), texptr + (bufw * y) / 2, w, expandClut_, alphaSum); + DeIndexTexture4((u32 *)(out + outPitch * y), texptr + (bufw * y) / 2, w, expandClut_, &alphaSum); } } else { - *fullAlphaMask = ClutFormatToFullAlpha(clutformat); + fullAlphaMask = ClutFormatToFullAlpha(clutformat); for (int y = 0; y < h; ++y) { - DeIndexTexture4((u16 *)(out + outPitch * y), texptr + (bufw * y) / 2, w, clut, alphaSum); + DeIndexTexture4((u16 *)(out + outPitch * y), texptr + (bufw * y) / 2, w, clut, &alphaSum); } } } @@ -1523,30 +1527,30 @@ void TextureCacheCommon::DecodeTextureLevel(u8 *out, int outPitch, GETextureForm case GE_CMODE_32BIT_ABGR8888: { const u32 *clut = GetCurrentClut() + clutSharingOffset; - *fullAlphaMask = 0xFF000000; + fullAlphaMask = 0xFF000000; for (int y = 0; y < h; ++y) { - DeIndexTexture4((u32 *)(out + outPitch * y), texptr + (bufw * y) / 2, w, clut, alphaSum); + DeIndexTexture4((u32 *)(out + outPitch * y), texptr + (bufw * y) / 2, w, clut, &alphaSum); } } break; default: ERROR_LOG_REPORT(G3D, "Unknown CLUT4 texture mode %d", gstate.getClutPaletteFormat()); - return; + return CHECKALPHA_ANY; } } break; case GE_TFMT_CLUT8: - ReadIndexedTex(out, outPitch, level, texptr, 1, bufw, expandTo32bit, alphaSum, fullAlphaMask); + ReadIndexedTex(out, outPitch, level, texptr, 1, bufw, expandTo32bit, &alphaSum, &fullAlphaMask); break; case GE_TFMT_CLUT16: - ReadIndexedTex(out, outPitch, level, texptr, 2, bufw, expandTo32bit, alphaSum, fullAlphaMask); + ReadIndexedTex(out, outPitch, level, texptr, 2, bufw, expandTo32bit, &alphaSum, &fullAlphaMask); break; case GE_TFMT_CLUT32: - ReadIndexedTex(out, outPitch, level, texptr, 4, bufw, expandTo32bit, alphaSum, fullAlphaMask); + ReadIndexedTex(out, outPitch, level, texptr, 4, bufw, expandTo32bit, &alphaSum, &fullAlphaMask); break; case GE_TFMT_4444: @@ -1565,9 +1569,9 @@ void TextureCacheCommon::DecodeTextureLevel(u8 *out, int outPitch, GETextureForm ConvertFormatToRGBA8888(format, (u32 *)(out + outPitch * y), (const u16 *)texptr + bufw * y, w); } } else { - *fullAlphaMask = TfmtRawToFullAlpha(format); + fullAlphaMask = TfmtRawToFullAlpha(format); for (int y = 0; y < h; ++y) { - CopyAndSumMask16((u16 *)(out + outPitch * y), (u16 *)(texptr + bufw * sizeof(u16) * y), w, alphaSum); + CopyAndSumMask16((u16 *)(out + outPitch * y), (u16 *)(texptr + bufw * sizeof(u16) * y), w, &alphaSum); } } } /* else if (h >= 8 && bufw <= w && !expandTo32bit) { @@ -1594,9 +1598,9 @@ void TextureCacheCommon::DecodeTextureLevel(u8 *out, int outPitch, GETextureForm ConvertFormatToRGBA8888(format, (u32 *)(out + outPitch * y), (const u16 *)unswizzled + bufw * y, w); } } else { - *fullAlphaMask = TfmtRawToFullAlpha(format); + fullAlphaMask = TfmtRawToFullAlpha(format); for (int y = 0; y < h; ++y) { - CopyAndSumMask16((u16 *)(out + outPitch * y), (const u16 *)(unswizzled + bufw * sizeof(u16) * y), w, alphaSum); + CopyAndSumMask16((u16 *)(out + outPitch * y), (const u16 *)(unswizzled + bufw * sizeof(u16) * y), w, &alphaSum); } } } @@ -1605,14 +1609,14 @@ void TextureCacheCommon::DecodeTextureLevel(u8 *out, int outPitch, GETextureForm case GE_TFMT_8888: if (!swizzled) { if (reverseColors) { - *fullAlphaMask = 0; // ignore alpha optimization for now + fullAlphaMask = 0; // ignore alpha optimization for now for (int y = 0; y < h; ++y) { ReverseColors(out + outPitch * y, texptr + bufw * sizeof(u32) * y, format, w, useBGRA); } } else { - *fullAlphaMask = TfmtRawToFullAlpha(format); + fullAlphaMask = TfmtRawToFullAlpha(format); for (int y = 0; y < h; ++y) { - CopyAndSumMask32((u32 *)(out + outPitch * y), (const u32 *)(texptr + bufw * sizeof(u32) * y), w * sizeof(u32), alphaSum); + CopyAndSumMask32((u32 *)(out + outPitch * y), (const u32 *)(texptr + bufw * sizeof(u32) * y), w * sizeof(u32), &alphaSum); } } } /* else if (h >= 8 && bufw <= w) { @@ -1632,30 +1636,32 @@ void TextureCacheCommon::DecodeTextureLevel(u8 *out, int outPitch, GETextureForm ReverseColors(out + outPitch * y, unswizzled + bufw * sizeof(u32) * y, format, w, useBGRA); } } else { - *fullAlphaMask = TfmtRawToFullAlpha(format); + fullAlphaMask = TfmtRawToFullAlpha(format); for (int y = 0; y < h; ++y) { - CopyAndSumMask32((u32 *)(out + outPitch * y), (const u32 *)(unswizzled + bufw * sizeof(u32) * y), w * sizeof(u32), alphaSum); + CopyAndSumMask32((u32 *)(out + outPitch * y), (const u32 *)(unswizzled + bufw * sizeof(u32) * y), w * sizeof(u32), &alphaSum); } } } break; case GE_TFMT_DXT1: - DecodeDXTBlocks(out, outPitch, texaddr, texptr, w, h, bufw, reverseColors, useBGRA, alphaSum, fullAlphaMask); + DecodeDXTBlocks(out, outPitch, texaddr, texptr, w, h, bufw, reverseColors, useBGRA, &alphaSum, &fullAlphaMask); break; case GE_TFMT_DXT3: - DecodeDXTBlocks(out, outPitch, texaddr, texptr, w, h, bufw, reverseColors, useBGRA, alphaSum, fullAlphaMask); + DecodeDXTBlocks(out, outPitch, texaddr, texptr, w, h, bufw, reverseColors, useBGRA, &alphaSum, &fullAlphaMask); break; case GE_TFMT_DXT5: - DecodeDXTBlocks(out, outPitch, texaddr, texptr, w, h, bufw, reverseColors, useBGRA, alphaSum, fullAlphaMask); + DecodeDXTBlocks(out, outPitch, texaddr, texptr, w, h, bufw, reverseColors, useBGRA, &alphaSum, &fullAlphaMask); break; default: ERROR_LOG_REPORT(G3D, "Unknown Texture Format %d!!!", format); break; } + + return AlphaSumIsFull(alphaSum, fullAlphaMask) ? CHECKALPHA_FULL : CHECKALPHA_ANY; } void TextureCacheCommon::ReadIndexedTex(u8 *out, int outPitch, int level, const u8 *texptr, int bytesPerIndex, int bufw, bool expandTo32Bit, u32 *alphaSum, u32 *fullAlphaMask) { diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index caaea2fcf9..debefa1b3a 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -181,6 +181,13 @@ struct TexCacheEntry { SetAlphaStatus(newStatus); } } + void SetAlphaStatus(CheckAlphaResult alphaResult, int level) { + TexStatus newStatus = (TexStatus)alphaResult; + // For non-level zero, only set more restrictive. + if (newStatus == STATUS_ALPHA_UNKNOWN || level == 0) { + SetAlphaStatus(newStatus); + } + } bool Matches(u16 dim2, u8 format2, u8 maxLevel2) const; u64 CacheKey() const; @@ -275,7 +282,7 @@ protected: virtual void UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple) = 0; bool CheckFullHash(TexCacheEntry *entry, bool &doDelete); - void DecodeTextureLevel(u8 *out, int outPitch, GETextureFormat format, GEPaletteFormat clutformat, uint32_t texaddr, int level, int bufw, bool reverseColors, bool useBGRA, bool expandTo32Bit, u32 *alphaSum, u32 *fullAlphaMask); + CheckAlphaResult DecodeTextureLevel(u8 *out, int outPitch, GETextureFormat format, GEPaletteFormat clutformat, uint32_t texaddr, int level, int bufw, bool reverseColors, bool useBGRA, bool expandTo32Bit); void UnswizzleFromMem(u32 *dest, u32 destPitch, const u8 *texptr, u32 bufw, u32 height, u32 bytesPerPixel); void ReadIndexedTex(u8 *out, int outPitch, int level, const u8 *texptr, int bytesPerIndex, int bufw, bool expandTo32Bit, u32 *alphaSum, u32 *fullAlphaMask); ReplacedTexture &FindReplacement(TexCacheEntry *entry, int &w, int &h); diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index c34bb96871..ee428c0ab6 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -708,17 +708,9 @@ void TextureCacheD3D11::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture & } bool expand32 = !gstate_c.Supports(GPU_SUPPORTS_16BIT_FORMATS); - u32 fullAlphaMask = 0; - u32 alphaSum = 0xFFFFFFFF; - DecodeTextureLevel((u8 *)pixelData, decPitch, tfmt, clutformat, texaddr, level, bufw, false, false, expand32, &alphaSum, &fullAlphaMask); - - // We check before scaling since scaling shouldn't invent alpha from a full alpha texture. - if (AlphaSumIsFull(alphaSum, fullAlphaMask)) { - entry.SetAlphaStatus(TexCacheEntry::STATUS_ALPHA_FULL, level); - } else { - entry.SetAlphaStatus(TexCacheEntry::STATUS_ALPHA_UNKNOWN, level); - } + CheckAlphaResult alphaResult = DecodeTextureLevel((u8 *)pixelData, decPitch, tfmt, clutformat, texaddr, level, bufw, false, false, expand32); + entry.SetAlphaStatus(alphaResult, level); if (scaleFactor > 1) { u32 scaleFmt = (u32)dstFmt; diff --git a/GPU/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index 37d3392102..fb2efaa8e8 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -634,16 +634,8 @@ void TextureCacheDX9::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &re decPitch = w * bpp; } - u32 fullAlphaMask = 0; - u32 alphaSum = 0xFFFFFFFF; - DecodeTextureLevel((u8 *)pixelData, decPitch, tfmt, clutformat, texaddr, level, bufw, false, false, false, &alphaSum, &fullAlphaMask); - - // We check before scaling since scaling shouldn't invent alpha from a full alpha texture. - if (AlphaSumIsFull(alphaSum, fullAlphaMask)) { - entry.SetAlphaStatus(TexCacheEntry::STATUS_ALPHA_FULL, level); - } else { - entry.SetAlphaStatus(TexCacheEntry::STATUS_ALPHA_UNKNOWN, level); - } + CheckAlphaResult alphaResult = DecodeTextureLevel((u8 *)pixelData, decPitch, tfmt, clutformat, texaddr, level, bufw, false, false, false); + entry.SetAlphaStatus(alphaResult, level); if (scaleFactor > 1) { scaler.ScaleAlways((u32 *)rect.pBits, pixelData, dstFmt, w, h, scaleFactor); diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 0e53525689..7ec34e6711 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -675,16 +675,9 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r decPitch = std::max(w * pixelSize, 4); pixelData = (uint8_t *)AllocateAlignedMemory(decPitch * h * pixelSize, 16); - u32 fullAlphaMask = 0; - u32 alphaSum = 0xFFFFFFFF; - DecodeTextureLevel(pixelData, decPitch, GETextureFormat(entry.format), clutformat, texaddr, level, bufw, true, false, false, &alphaSum, &fullAlphaMask); - // We check before scaling since scaling shouldn't invent alpha from a full alpha texture. - if (AlphaSumIsFull(alphaSum, fullAlphaMask)) { - entry.SetAlphaStatus(TexCacheEntry::STATUS_ALPHA_FULL, level); - } else { - entry.SetAlphaStatus(TexCacheEntry::STATUS_ALPHA_UNKNOWN, level); - } + CheckAlphaResult alphaStatus = DecodeTextureLevel(pixelData, decPitch, GETextureFormat(entry.format), clutformat, texaddr, level, bufw, true, false, false); + entry.SetAlphaStatus(alphaStatus, level); if (scaleFactor > 1) { uint8_t *rearrange = (uint8_t *)AllocateAlignedMemory(w * scaleFactor * h * scaleFactor * 4, 16); diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index cc0c95499c..815758cd60 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -249,7 +249,7 @@ static std::string ReadShaderSrc(const Path &filename) { size_t sz = 0; char *data = (char *)VFSReadFile(filename.c_str(), &sz); if (!data) - return ""; + return std::string(); std::string src(data, sz); delete[] data; @@ -961,6 +961,8 @@ void TextureCacheVulkan::LoadTextureLevel(TexCacheEntry &entry, uint8_t *writePt int w = gstate.getTextureWidth(level); int h = gstate.getTextureHeight(level); + gpuStats.numTexturesDecoded++; + { PROFILE_THIS_SCOPE("decodetex"); @@ -981,17 +983,8 @@ void TextureCacheVulkan::LoadTextureLevel(TexCacheEntry &entry, uint8_t *writePt bool expand32 = !gstate_c.Supports(GPU_SUPPORTS_16BIT_FORMATS) || dstFmt == VK_FORMAT_R8G8B8A8_UNORM; - u32 alphaSum = 0xFFFFFFFF; - u32 fullAlphaMask = 0x0; - - DecodeTextureLevel((u8 *)pixelData, decPitch, tfmt, clutformat, texaddr, level, bufw, false, false, expand32, &alphaSum, &fullAlphaMask); - gpuStats.numTexturesDecoded++; - - if (AlphaSumIsFull(alphaSum, fullAlphaMask)) { - entry.SetAlphaStatus(TexCacheEntry::STATUS_ALPHA_FULL, level); - } else { - entry.SetAlphaStatus(TexCacheEntry::STATUS_ALPHA_UNKNOWN, level); - } + CheckAlphaResult alphaResult = DecodeTextureLevel((u8 *)pixelData, decPitch, tfmt, clutformat, texaddr, level, bufw, false, false, expand32); + entry.SetAlphaStatus(alphaResult, level); if (scaleFactor > 1) { u32 fmt = dstFmt;