From 8775abacc6776fe2f8b65e04402d783b19da79fa Mon Sep 17 00:00:00 2001 From: skidau Date: Sat, 6 Nov 2010 04:46:44 +0000 Subject: [PATCH] Optimised EFB copy to RAM. The finding was that 99% of the time, textures are static in memory. However, Dolphin would pessimistically continue to decode and copy the same texture every time. The optimisation is to check if the texture matches what is in the cache, and if it does, Dolphin should early exit. The result is the speed in New Super Mario Bros Wii increased 35% with spinning coins. Still not as fast as EFB copy to texture though. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6352 8ced0084-cf51-0410-be5f-012b33b47a6e --- .../Core/VideoCommon/Src/TextureCacheBase.cpp | 20 +++++++++++++++++-- .../Core/VideoCommon/Src/TextureCacheBase.h | 1 + .../Plugin_VideoDX9/Src/TextureConverter.cpp | 8 +++++++- .../Plugin_VideoOGL/Src/TextureConverter.cpp | 8 +++++++- 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index a3d6c62740..ba54adbac5 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -119,8 +119,12 @@ void TextureCache::InvalidateRange(u32 start_address, u32 size) void TextureCache::MakeRangeDynamic(u32 start_address, u32 size) { TexCache::iterator - iter = textures.begin(), - tcend = textures.end(); + iter = textures.lower_bound(start_address), + tcend = textures.upper_bound(start_address + size); + + if (iter != textures.begin()) + iter--; + for (; iter != tcend; ++iter) { const int rangePosition = iter->second->IntersectsMemoryRange(start_address, size); @@ -131,6 +135,18 @@ void TextureCache::MakeRangeDynamic(u32 start_address, u32 size) } } +bool TextureCache::Find(u32 start_address, u64 hash) +{ + TexCache::iterator + iter = textures.lower_bound(start_address), + tcend = textures.upper_bound(start_address); + + if (iter->second->hash == hash) + return true; + + return false; +} + int TextureCache::TCacheEntryBase::IntersectsMemoryRange(u32 range_address, u32 range_size) const { if (addr + size_in_bytes < range_address) diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.h b/Source/Core/VideoCommon/Src/TextureCacheBase.h index 24ca3dd761..d434bec5f6 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.h +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.h @@ -77,6 +77,7 @@ public: static void InvalidateRange(u32 start_address, u32 size); static void MakeRangeDynamic(u32 start_address, u32 size); static void ClearRenderTargets(); // currently only used by OGL + static bool Find(u32 start_address, u64 hash); virtual TCacheEntryBase* CreateTexture(unsigned int width, unsigned int height, unsigned int expanded_width, unsigned int tex_levels, PC_TexFormat pcfmt) = 0; diff --git a/Source/Plugins/Plugin_VideoDX9/Src/TextureConverter.cpp b/Source/Plugins/Plugin_VideoDX9/Src/TextureConverter.cpp index 3e9d25c476..05514d1919 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/TextureConverter.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/TextureConverter.cpp @@ -406,6 +406,12 @@ u64 EncodeToRamFromTexture(u32 address,LPDIRECT3DTEXTURE9 source_texture,u32 Sou int size_in_bytes = TexDecoder_GetTextureSizeInBytes(width, height, format); + u64 hash = GetHash64(dest_ptr,size_in_bytes,g_ActiveConfig.iSafeTextureCache_ColorSamples); + + // If the texture in RAM is already in the texture cache, do not copy it again as it has not changed. + if (TextureCache::Find(address, hash)) + return hash; + u16 blkW = TexDecoder_GetBlockWidthInTexels(format) - 1; u16 blkH = TexDecoder_GetBlockHeightInTexels(format) - 1; u16 samples = TextureConversionShader::GetEncodedSampleCount(format); @@ -439,7 +445,7 @@ u64 EncodeToRamFromTexture(u32 address,LPDIRECT3DTEXTURE9 source_texture,u32 Sou int readStride = (expandedWidth * cacheBytes) / TexDecoder_GetBlockWidthInTexels(format); EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource, dest_ptr, expandedWidth / samples, expandedHeight, readStride, true, bScaleByHalf > 0); TextureCache::MakeRangeDynamic(address,size_in_bytes); - return GetHash64(dest_ptr,size_in_bytes,g_ActiveConfig.iSafeTextureCache_ColorSamples); + return hash; } void EncodeToRamYUYV(LPDIRECT3DTEXTURE9 srcTexture, const TargetRectangle& sourceRc, u8* destAddr, int dstWidth, int dstHeight) diff --git a/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp b/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp index 9236f2a627..ee1236b8d1 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp @@ -345,6 +345,12 @@ u64 EncodeToRamFromTexture(u32 address,GLuint source_texture,float MValueX,float int size_in_bytes = TexDecoder_GetTextureSizeInBytes(width, height, format); + u64 hash = GetHash64(dest_ptr,size_in_bytes,g_ActiveConfig.iSafeTextureCache_ColorSamples); + + // If the texture in RAM is already in the texture cache, do not copy it again as it has not changed. + if (TextureCache::Find(address, hash)) + return hash; + u16 blkW = TexDecoder_GetBlockWidthInTexels(format) - 1; u16 blkH = TexDecoder_GetBlockHeightInTexels(format) - 1; u16 samples = TextureConversionShader::GetEncodedSampleCount(format); @@ -375,7 +381,7 @@ u64 EncodeToRamFromTexture(u32 address,GLuint source_texture,float MValueX,float int readStride = (expandedWidth * cacheBytes) / TexDecoder_GetBlockWidthInTexels(format); EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource, dest_ptr, expandedWidth / samples, expandedHeight, readStride, true, bScaleByHalf > 0 && !bFromZBuffer); TextureCache::MakeRangeDynamic(address,size_in_bytes); - return GetHash64(dest_ptr,size_in_bytes,g_ActiveConfig.iSafeTextureCache_ColorSamples); + return hash; } void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc, u8* destAddr, int dstWidth, int dstHeight)