diff --git a/Common/Thread/ParallelLoop.cpp b/Common/Thread/ParallelLoop.cpp index 2f00664618..0c2cb7db79 100644 --- a/Common/Thread/ParallelLoop.cpp +++ b/Common/Thread/ParallelLoop.cpp @@ -107,7 +107,7 @@ void ParallelRangeLoop(ThreadManager *threadMan, const std::function 1; - CheckAlphaResult alphaResult = DecodeTextureLevel((u8 *)pixelData, decPitch, tfmt, clutformat, texaddr, srcLevel, bufw, false, expand32); + CheckAlphaResult alphaResult = DecodeTextureLevel((u8 *)pixelData, decPitch, tfmt, clutformat, texaddr, srcLevel, bufw, reverseColors, expand32); entry.SetAlphaStatus(alphaResult, srcLevel); if (scaleFactor > 1) { diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index 85187af204..33430d6c97 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -330,7 +330,7 @@ protected: ReplacedTexture &FindReplacement(TexCacheEntry *entry, int &w, int &h); // Return value is mapData normally, but could be another buffer allocated with AllocateAlignedMemory. - void LoadTextureLevel(TexCacheEntry &entry, uint8_t *mapData, int mapRowPitch, ReplacedTexture &replaced, int srcLevel, int scaleFactor, Draw::DataFormat dstFmt); + void LoadTextureLevel(TexCacheEntry &entry, uint8_t *mapData, int mapRowPitch, ReplacedTexture &replaced, int srcLevel, int scaleFactor, Draw::DataFormat dstFmt, bool reverseColors); template inline const T *GetCurrentClut() { diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index e48f523e1f..e2bb7ece02 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -458,17 +458,12 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry) { int th = plan.h; DXGI_FORMAT dstFmt = GetDestFormat(GETextureFormat(entry->format), gstate.getClutPaletteFormat()); - ID3D11ShaderResourceView *view; - ID3D11Texture2D *texture = DxTex(entry); - _assert_(texture == nullptr); if (plan.replaced->GetSize(plan.baseLevelSrc, tw, th)) { dstFmt = ToDXGIFormat(plan.replaced->Format(plan.baseLevelSrc)); - } else { + } else if (plan.scaleFactor > 1) { tw *= plan.scaleFactor; th *= plan.scaleFactor; - if (plan.scaleFactor > 1) { - dstFmt = DXGI_FORMAT_B8G8R8A8_UNORM; - } + dstFmt = DXGI_FORMAT_B8G8R8A8_UNORM; } // We don't yet have mip generation, so clamp the number of levels to the ones we can load directly. @@ -485,6 +480,10 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry) { desc.MipLevels = levels; desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + ID3D11ShaderResourceView *view; + ID3D11Texture2D *texture = DxTex(entry); + _assert_(texture == nullptr); + ASSERT_SUCCESS(device_->CreateTexture2D(&desc, nullptr, &texture)); ASSERT_SUCCESS(device_->CreateShaderResourceView(texture, nullptr, &view)); entry->texturePtr = texture; @@ -524,7 +523,7 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry) { return; } - LoadTextureLevel(*entry, data, stride, *plan.replaced, srcLevel, plan.scaleFactor, texFmt); + LoadTextureLevel(*entry, data, stride, *plan.replaced, srcLevel, plan.scaleFactor, texFmt, false); ID3D11Texture2D *texture = DxTex(entry); context_->UpdateSubresource(texture, i, nullptr, data, stride, 0); diff --git a/GPU/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index 08f1e377f0..85af315d8d 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -413,23 +413,21 @@ void TextureCacheDX9::BuildTexture(TexCacheEntry *const entry) { int tw = plan.w; int th = plan.h; - LPDIRECT3DTEXTURE9 &texture = DxTex(entry); D3DFORMAT dstFmt = GetDestFormat(GETextureFormat(entry->format), gstate.getClutPaletteFormat()); - D3DPOOL pool = D3DPOOL_DEFAULT; - int usage = D3DUSAGE_DYNAMIC; if (plan.replaced->GetSize(plan.baseLevelSrc, tw, th)) { dstFmt = ToD3D9Format(plan.replaced->Format(plan.baseLevelSrc)); - } else { + } else if (plan.scaleFactor > 1) { tw *= plan.scaleFactor; th *= plan.scaleFactor; - if (plan.scaleFactor > 1) { - dstFmt = D3DFMT_A8R8G8B8; - } + dstFmt = D3DFMT_A8R8G8B8; } // We don't yet have mip generation, so clamp the number of levels to the ones we can load directly. int levels = std::min(plan.levelsToCreate, plan.levelsToLoad); + LPDIRECT3DTEXTURE9 &texture = DxTex(entry); + D3DPOOL pool = D3DPOOL_DEFAULT; + int usage = D3DUSAGE_DYNAMIC; HRESULT hr = device_->CreateTexture(tw, th, levels, usage, dstFmt, pool, &texture, NULL); if (FAILED(hr)) { @@ -460,7 +458,7 @@ void TextureCacheDX9::BuildTexture(TexCacheEntry *const entry) { uint8_t *data = (uint8_t *)rect.pBits; int stride = rect.Pitch; - LoadTextureLevel(*entry, data, stride, *plan.replaced, (i == 0) ? plan.baseLevelSrc : i, plan.scaleFactor, texFmt); + LoadTextureLevel(*entry, data, stride, *plan.replaced, (i == 0) ? plan.baseLevelSrc : i, plan.scaleFactor, texFmt, false); texture->UnlockRect(dstLevel); } diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 2c63f40b1b..de4dc36994 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -445,12 +445,10 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry) { Draw::DataFormat dstFmt = GetDestFormat(GETextureFormat(entry->format), gstate.getClutPaletteFormat()); if (plan.replaced->GetSize(plan.baseLevelSrc, tw, th)) { dstFmt = plan.replaced->Format(plan.baseLevelSrc); - } else { + } else if (plan.scaleFactor > 1) { tw *= plan.scaleFactor; th *= plan.scaleFactor; - if (plan.scaleFactor > 1) { - dstFmt = Draw::DataFormat::R8G8B8A8_UNORM; - } + dstFmt = Draw::DataFormat::R8G8B8A8_UNORM; } entry->textureName = render_->CreateTexture(GL_TEXTURE_2D, tw, tw, plan.levelsToCreate); @@ -471,18 +469,45 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry) { } for (int i = 0; i < plan.levelsToLoad; i++) { - LoadTextureLevel(*entry, *plan.replaced, i == 0 ? plan.baseLevelSrc : i, i, plan.scaleFactor, dstFmt); + int srcLevel = i == 0 ? plan.baseLevelSrc : i; + + int w = gstate.getTextureWidth(srcLevel); + int h = gstate.getTextureHeight(srcLevel); + + u8 *data = nullptr; + int stride = 0; + + if (plan.replaced->GetSize(srcLevel, w, h)) { + int bpp = (int)Draw::DataFormatSizeInBytes(plan.replaced->Format(srcLevel)); + stride = w * bpp; + data = (u8 *)AllocateAlignedMemory(stride * h, 16); + } else { + if (plan.scaleFactor > 1) { + data = (u8 *)AllocateAlignedMemory(4 * (w * plan.scaleFactor) * (h * plan.scaleFactor), 16); + stride = w * plan.scaleFactor * 4; + } else { + int bpp = dstFmt == Draw::DataFormat::R8G8B8A8_UNORM ? 4 : 2; + + stride = std::max(w * bpp, 4); + data = (u8 *)AllocateAlignedMemory(stride * h, 16); + } + } + + if (!data) { + ERROR_LOG(G3D, "Ran out of RAM trying to allocate a temporary texture upload buffer (%dx%d)", w, h); + return; + } + + LoadTextureLevel(*entry, data, stride, *plan.replaced, srcLevel, plan.scaleFactor, dstFmt, true); + + // NOTE: TextureImage takes ownership of data, so we don't free it afterwards. + render_->TextureImage(entry->textureName, i, w * plan.scaleFactor, h * plan.scaleFactor, dstFmt, data, GLRAllocType::ALIGNED); } bool genMips = plan.levelsToCreate > plan.levelsToLoad; render_->FinalizeTexture(entry->textureName, plan.levelsToLoad, genMips); - if (plan.levelsToLoad == 1) { - entry->status |= TexCacheEntry::STATUS_NO_MIPS; - } else { - entry->status &= ~TexCacheEntry::STATUS_NO_MIPS; - } if (plan.replaced->Valid()) { entry->SetAlphaStatus(TexCacheEntry::TexStatus(plan.replaced->AlphaStatus())); } @@ -524,65 +549,6 @@ CheckAlphaResult TextureCacheGLES::CheckAlpha(const uint8_t *pixelData, Draw::Da } } -void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int srcLevel, int dstLevel, int scaleFactor, Draw::DataFormat dstFmt) { - int w = gstate.getTextureWidth(srcLevel); - int h = gstate.getTextureHeight(srcLevel); - uint8_t *pixelData; - int decPitch = 0; - - if (replaced.GetSize(srcLevel, w, h)) { - int bpp = (int)DataFormatSizeInBytes(replaced.Format(srcLevel)); - - decPitch = w * bpp; - uint8_t *rearrange = (uint8_t *)AllocateAlignedMemory(decPitch * h, 16); - double replaceStart = time_now_d(); - replaced.Load(srcLevel, rearrange, decPitch); - replacementTimeThisFrame_ += time_now_d() - replaceStart; - pixelData = rearrange; - - dstFmt = replaced.Format(srcLevel); - } else { - GEPaletteFormat clutformat = gstate.getClutPaletteFormat(); - u32 texaddr = gstate.getTextureAddress(srcLevel); - int bufw = GetTextureBufw(srcLevel, texaddr, GETextureFormat(entry.format)); - - int pixelSize = dstFmt == Draw::DataFormat::R8G8B8A8_UNORM ? 4 : 2; - - // We leave GL_UNPACK_ALIGNMENT at 4, so this must be at least 4. - decPitch = std::max(w * pixelSize, 4); - - pixelData = (uint8_t *)AllocateAlignedMemory(decPitch * h * pixelSize, 16); - - bool expand32 = scaleFactor > 1; - - CheckAlphaResult alphaStatus = DecodeTextureLevel(pixelData, decPitch, GETextureFormat(entry.format), clutformat, texaddr, srcLevel, bufw, true, expand32); - entry.SetAlphaStatus(alphaStatus, srcLevel); - - if (scaleFactor > 1) { - uint8_t *rearrange = (uint8_t *)AllocateAlignedMemory(w * scaleFactor * h * scaleFactor * 4, 16); - scaler_.ScaleAlways((u32 *)rearrange, (u32 *)pixelData, w, h, scaleFactor); - FreeAlignedMemory(pixelData); - pixelData = rearrange; - decPitch = w * 4; - } - - if (replacer_.Enabled()) { - 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 = scaleFactor; - replacedInfo.fmt = dstFmt; - - replacer_.NotifyTextureDecoded(replacedInfo, pixelData, decPitch, srcLevel, w, h); - } - } - - render_->TextureImage(entry.textureName, dstLevel, w, h, dstFmt, pixelData, GLRAllocType::ALIGNED); -} - bool TextureCacheGLES::GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level) { GPUgstate saved; if (level != 0) { diff --git a/GPU/GLES/TextureCacheGLES.h b/GPU/GLES/TextureCacheGLES.h index edf0a6b21f..a90001acaa 100644 --- a/GPU/GLES/TextureCacheGLES.h +++ b/GPU/GLES/TextureCacheGLES.h @@ -69,7 +69,6 @@ protected: private: void ApplySamplingParams(const SamplerCacheKey &key); - void LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int srcLevel, int dstLevel, int scaleFactor, Draw::DataFormat dstFmt); Draw::DataFormat GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const; static CheckAlphaResult CheckAlpha(const uint8_t *pixelData, Draw::DataFormat dstFmt, int w); diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index b64851656b..42a74b02d8 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -845,8 +845,6 @@ void TextureCacheVulkan::LoadTextureLevel(TexCacheEntry &entry, uint8_t *writePt int w = gstate.getTextureWidth(level); int h = gstate.getTextureHeight(level); - PROFILE_THIS_SCOPE("decodetex"); - GETextureFormat tfmt = (GETextureFormat)entry.format; GEPaletteFormat clutformat = gstate.getClutPaletteFormat(); u32 texaddr = gstate.getTextureAddress(level);