From cf899781f980ecf7dbe373a36c78a2a302e3951d Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Tue, 24 Jan 2012 16:38:27 +0100 Subject: [PATCH] TextureCacheBase: Update and improve documentation for EFB copies --- .../Core/VideoCommon/Src/TextureCacheBase.cpp | 40 +++++++++++-------- .../Core/VideoCommon/Src/TextureCacheBase.h | 6 +-- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index 6f2c9ebd0c..0a59aeefa4 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -377,30 +377,36 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat // Disadvantage: Encoding+decoding steps often are redundant because only some games read or modify EFB copies before using them as textures. // - EFB to texture: // Copies the requested EFB data to a texture object in VRAM, performing any color conversion using shaders. - // Advantage: Works for many games, since in most cases EFB copies aren't read or modified at all before being used as a texture again. + // Advantage: Works for many games, since in most cases EFB copies aren't read or modified at all before being used as a texture again. // Since we don't do any further encoding or decoding here, this method is much faster. // It also allows enhancing the visual quality by doing scaled EFB copies. // - hybrid EFB copies: - // 1) Whenever this function gets called, encode the requested EFB data to RAM (like EFB to RAM) - // 2a) If we haven't copied to the specified dstAddr yet, copy the requested EFB data to a texture object in VRAM as well (like EFB to texture) - // Create a texture cache entry for the render target (isRenderTarget = true, isDynamic = false) - // Store a hash of the encoded RAM data in the texcache entry. - // 2b) If we already have created a texcache entry for dstAddr (i.e. if we copied to dstAddr before) AND isDynamic is false: - // Do the same like above, but reuse the old texcache entry instead of creating a new one. - // 2c) If we already have created a texcache entry for dstAddr AND isDynamic is true (isRenderTarget will be false then) - // Only encode the texture to RAM (like EFB to RAM) and store a hash of the encoded data in the existing texcache entry. - // Do NOT copy the requested EFB data to a VRAM object. Reason: the texture is dynamic, i.e. the CPU is modifying it. Storing a VRAM copy is useless, because we'd end up deleting it and reloading the data from RAM again anyway. + // 1a) Whenever this function gets called, encode the requested EFB data to RAM (like EFB to RAM) + // 1b) Set efbcopy_state to EC_VRAM_DYNAMIC for all texture cache entries in the destination address range. + // If EFB copy caching is enabled, further checks will (try to) prevent redundant EFB copies. + // 2) Check if a texture cache entry for the specified dstAddr already exists (i.e. if an EFB copy was triggered to that address before): + // 2a) Entry doesn't exist: + // - Also copy the requested EFB data to a texture object in VRAM (like EFB to texture) + // - Create a texture cache entry for the target (efbcopy_state = EC_VRAM_READY) + // - Store a hash of the encoded RAM data in the texcache entry. + // 2b) Entry exists AND efbcopy_state is EC_VRAM_READY: + // - Like case 2a, but reuse the old texcache entry instead of creating a new one. + // 2c) Entry exists AND efbcopy_state is EC_VRAM_DYNAMIC: + // - Only encode the texture to RAM (like EFB to RAM) and store a hash of the encoded data in the existing texcache entry. + // - Do NOT copy the requested EFB data to a VRAM object. Reason: the texture is dynamic, i.e. the CPU is modifying it. Storing a VRAM copy is useless, because we'd always end up deleting it and reloading the data from RAM anyway. // 3) If the EFB copy gets used as a texture, compare the source RAM hash with the hash you stored when encoding the EFB data to RAM. - // 3a) If the two hashes match AND isDynamic is still false, reuse the VRAM copy you created - // 3b) If the two hashes differ AND isDynamic is still false, screw your existing VRAM copy. Set isRenderTarget to false and isDynamic to true. + // 3a) If the two hashes match AND efbcopy_state is EC_VRAM_READY, reuse the VRAM copy you created + // 3b) If the two hashes differ AND efbcopy_state is EC_VRAM_READY, screw your existing VRAM copy. Set efbcopy_state to EC_VRAM_DYNAMIC. // Redecode the source RAM data to a VRAM object. The entry basically behaves like a normal texture now. - // 3c) If isDynamic is true, treat the EFB copy like a normal texture. - // Advantage: Neither as fast as EFB to texture nor as slow as EFB to RAM, so it's a good compromise. - // Non-dynamic EFB copies can be visually enhanced like with EFB to texture. - // Compatibility ideally is as good as with EFB to RAM. - // Disadvantage: Depends on accurate texture hashing being enabled. However, with accurate hashing you end up being as slow as EFB to RAM anyway. + // 3c) If efbcopy_state is EC_VRAM_DYNAMIC, treat the EFB copy like a normal texture. + // Advantage: Non-dynamic EFB copies can be visually enhanced like with EFB to texture. + // Compatibility is as good as EFB to RAM. + // Disadvantage: Slower than EFB to texture and often even slower than EFB to RAM. + // EFB copy cache depends on accurate texture hashing being enabled. However, with accurate hashing you end up being as slow as without a copy cache anyway. // // Disadvantage of all methods: Calling this function requires the GPU to perform a pipeline flush which stalls any further CPU processing. + // + // For historical reasons, Dolphin doesn't actually implement "pure" EFB to RAM emulation, but only EFB to texture and hybrid EFB copies. float colmat[28] = {0}; float *const fConstAdd = colmat + 16; diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.h b/Source/Core/VideoCommon/Src/TextureCacheBase.h index 88a76776df..59960c7fb8 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.h +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.h @@ -16,9 +16,9 @@ class TextureCache public: enum EFBCopyState { - EC_NO_COPY, - EC_VRAM_READY, - EC_VRAM_DYNAMIC, + EC_NO_COPY, // regular texture + EC_VRAM_READY, // EFB copy sits in VRAM and is ready to use + EC_VRAM_DYNAMIC, // EFB copy sits in RAM and needs to be decoded before using it as a texture }; struct TCacheEntryBase