diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index a78087f03b..5e5fc7c098 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -219,7 +219,6 @@ void TextureCacheCommon::SetTexture(bool force) { if (!Memory::IsValidAddress(texaddr)) { // Bind a null texture and return. Unbind(); - InvalidateLastTexture(); return; } @@ -482,7 +481,7 @@ bool TextureCacheCommon::HandleTextureChange(TexCacheEntry *const entry, const c // Instead, let's use glTexSubImage to replace the images. replaceImages = true; } else { - InvalidateLastTexture(entry); + InvalidateLastTexture(); ReleaseTexture(entry, true); entry->status &= ~TexCacheEntry::STATUS_IS_SCALED; } @@ -1498,16 +1497,28 @@ bool TextureCacheCommon::CheckFullHash(TexCacheEntry *entry, bool &doDelete) { } void TextureCacheCommon::Invalidate(u32 addr, int size, GPUInvalidationType type) { + // They could invalidate inside the texture, let's just give a bit of leeway. + const int LARGEST_TEXTURE_SIZE = 512 * 512 * 4; + + addr &= 0x3FFFFFFF; + const u32 addr_end = addr + size; + + if (type == GPU_INVALIDATE_ALL) { + // This is an active signal from the game that something in the texture cache may have changed. + gstate_c.Dirty(DIRTY_TEXTURE_IMAGE); + } else { + // Do a quick check to see if the current texture is in range. + const u32 currentAddr = gstate.getTextureAddress(0); + if (addr_end >= currentAddr && addr < currentAddr + LARGEST_TEXTURE_SIZE) { + gstate_c.Dirty(DIRTY_TEXTURE_IMAGE); + } + } + // If we're hashing every use, without backoff, then this isn't needed. if (!g_Config.bTextureBackoffCache) { return; } - addr &= 0x3FFFFFFF; - const u32 addr_end = addr + size; - - // They could invalidate inside the texture, let's just give a bit of leeway. - const int LARGEST_TEXTURE_SIZE = 512 * 512 * 4; const u64 startKey = (u64)(addr - LARGEST_TEXTURE_SIZE) << 32; u64 endKey = (u64)(addr + size + LARGEST_TEXTURE_SIZE) << 32; if (endKey < startKey) { diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index b508639506..ac3643e99e 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -143,7 +143,7 @@ void TextureCacheD3D11::ReleaseTexture(TexCacheEntry *entry, bool delete_them) { } void TextureCacheD3D11::ForgetLastTexture() { - lastBoundTexture = INVALID_TEX; + InvalidateLastTexture(); gstate_c.Dirty(DIRTY_TEXTURE_PARAMS); ID3D11ShaderResourceView *nullTex = nullptr; context_->PSSetShaderResources(0, 1, &nullTex); @@ -201,7 +201,7 @@ void TextureCacheD3D11::SetFramebufferSamplingParams(u16 bufferWidth, u16 buffer } void TextureCacheD3D11::StartFrame() { - lastBoundTexture = INVALID_TEX; + InvalidateLastTexture(); timesInvalidatedAllThisFrame_ = 0; if (texelsScaledThisFrame_) { @@ -264,6 +264,7 @@ void TextureCacheD3D11::BindTexture(TexCacheEntry *entry) { void TextureCacheD3D11::Unbind() { ID3D11ShaderResourceView *nullView = nullptr; context_->PSSetShaderResources(0, 1, &nullView); + InvalidateLastTexture(); } class TextureShaderApplierD3D11 { @@ -438,7 +439,7 @@ void TextureCacheD3D11::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFra SetFramebufferSamplingParams(framebuffer->bufferWidth, framebuffer->bufferHeight, samplerKey); ID3D11SamplerState *state = samplerCache_.GetOrCreateSampler(device_, samplerKey); context_->PSSetSamplers(0, 1, &state); - lastBoundTexture = INVALID_TEX; + InvalidateLastTexture(); } diff --git a/GPU/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index 1188ac58bf..c7b229c1b8 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -96,7 +96,7 @@ void TextureCacheDX9::ReleaseTexture(TexCacheEntry *entry, bool delete_them) { } void TextureCacheDX9::ForgetLastTexture() { - lastBoundTexture = INVALID_TEX; + InvalidateLastTexture(); gstate_c.Dirty(DIRTY_TEXTURE_PARAMS); } @@ -213,7 +213,7 @@ void TextureCacheDX9::SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHe } void TextureCacheDX9::StartFrame() { - lastBoundTexture = INVALID_TEX; + InvalidateLastTexture(); timesInvalidatedAllThisFrame_ = 0; if (texelsScaledThisFrame_) { @@ -279,6 +279,7 @@ void TextureCacheDX9::BindTexture(TexCacheEntry *entry) { void TextureCacheDX9::Unbind() { device_->SetTexture(0, NULL); + InvalidateLastTexture(); } class TextureShaderApplierDX9 { @@ -458,7 +459,7 @@ void TextureCacheDX9::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFrame framebufferManagerDX9_->RebindFramebuffer(); SetFramebufferSamplingParams(framebuffer->bufferWidth, framebuffer->bufferHeight); - lastBoundTexture = INVALID_TEX; + InvalidateLastTexture(); } void TextureCacheDX9::BuildTexture(TexCacheEntry *const entry, bool replaceImages) { diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index a43fe020f1..0af31d5925 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -340,6 +340,7 @@ void TextureCacheGLES::BindTexture(TexCacheEntry *entry) { void TextureCacheGLES::Unbind() { glBindTexture(GL_TEXTURE_2D, 0); + InvalidateLastTexture(); } class TextureShaderApplier { @@ -522,7 +523,7 @@ void TextureCacheGLES::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFram CHECK_GL_ERROR_IF_DEBUG(); - lastBoundTexture = INVALID_TEX; + InvalidateLastTexture(); } ReplacedTextureFormat FromGLESFormat(GLenum fmt, bool useBGRA = false) { diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 4e28d5f1d9..021a5ee016 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -1542,13 +1542,9 @@ void GPUCommon::Execute_BoundingBox(u32 op, u32 diff) { } void GPUCommon::Execute_BlockTransferStart(u32 op, u32 diff) { - // TODO: Here we should check if the transfer overlaps a framebuffer or any textures, // and take appropriate action. This is a block transfer between RAM and VRAM, or vice versa. // Can we skip this on SkipDraw? DoBlockTransfer(gstate_c.skipDrawReason); - - // Fixes Gran Turismo's funky text issue, since it overwrites the current texture. - gstate_c.Dirty(DIRTY_TEXTURE_IMAGE); } void GPUCommon::Execute_WorldMtxNum(u32 op, u32 diff) { @@ -2285,6 +2281,7 @@ void GPUCommon::DoBlockTransfer(u32 skipDrawReason) { } } + // Fixes Gran Turismo's funky text issue, since it overwrites the current texture. textureCache_->Invalidate(dstBasePtr + (dstY * dstStride + dstX) * bpp, height * dstStride * bpp, GPU_INVALIDATE_HINT); framebufferManager_->NotifyBlockTransferAfter(dstBasePtr, dstStride, dstX, dstY, srcBasePtr, srcStride, srcX, srcY, width, height, bpp, skipDrawReason); } diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index 3d424c6ced..1a265b6866 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -271,7 +271,7 @@ void TextureCacheVulkan::SetFramebufferSamplingParams(u16 bufferWidth, u16 buffe } void TextureCacheVulkan::StartFrame() { - lastBoundTexture = nullptr; + InvalidateLastTexture(); timesInvalidatedAllThisFrame_ = 0; texelsScaledThisFrame_ = 0; @@ -342,6 +342,7 @@ void TextureCacheVulkan::BindTexture(TexCacheEntry *entry) { void TextureCacheVulkan::Unbind() { imageView_ = VK_NULL_HANDLE; sampler_ = VK_NULL_HANDLE; + InvalidateLastTexture(); } void TextureCacheVulkan::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer) { @@ -452,7 +453,7 @@ void TextureCacheVulkan::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFr key.mipEnable = false; sampler_ = samplerCache_.GetOrCreateSampler(key); - lastBoundTexture = nullptr; + InvalidateLastTexture(); } }