From 495902787c74612c870547c21dbdb61bc53fecf8 Mon Sep 17 00:00:00 2001 From: degasus Date: Thu, 29 Oct 2015 08:42:30 +0100 Subject: [PATCH 1/5] OGL: Remove TCache::Entry usage in TextureConverter --- Source/Core/VideoBackends/OGL/TextureCache.cpp | 6 +++++- Source/Core/VideoBackends/OGL/TextureConverter.cpp | 12 ++++++------ Source/Core/VideoBackends/OGL/TextureConverter.h | 2 +- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/Source/Core/VideoBackends/OGL/TextureCache.cpp b/Source/Core/VideoBackends/OGL/TextureCache.cpp index 2cd1f3942a..287e9b2188 100644 --- a/Source/Core/VideoBackends/OGL/TextureCache.cpp +++ b/Source/Core/VideoBackends/OGL/TextureCache.cpp @@ -272,7 +272,11 @@ void TextureCache::TCacheEntry::FromRenderTarget(u8* dstPointer, unsigned int ds { TextureConverter::EncodeToRamFromTexture( dstPointer, - this, + format, + native_width, + BytesPerRow(), + NumBlocksY(), + memory_stride, read_texture, srcFormat == PEControl::Z24, isIntensity, diff --git a/Source/Core/VideoBackends/OGL/TextureConverter.cpp b/Source/Core/VideoBackends/OGL/TextureConverter.cpp index b780594101..ba2046d9a3 100644 --- a/Source/Core/VideoBackends/OGL/TextureConverter.cpp +++ b/Source/Core/VideoBackends/OGL/TextureConverter.cpp @@ -269,18 +269,18 @@ static void EncodeToRamUsingShader(GLuint srcTexture, } } -void EncodeToRamFromTexture(u8 *dest_ptr, const TextureCache::TCacheEntryBase *texture_entry, +void EncodeToRamFromTexture(u8 *dest_ptr, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, GLuint source_texture, bool bFromZBuffer, bool bIsIntensityFmt, int bScaleByHalf, const EFBRectangle& source) { - SHADER& texconv_shader = GetOrCreateEncodingShader(texture_entry->format); + SHADER& texconv_shader = GetOrCreateEncodingShader(format); texconv_shader.Bind(); - glUniform4i(s_encodingUniforms[texture_entry->format], - source.left, source.top, texture_entry->native_width, bScaleByHalf ? 2 : 1); + glUniform4i(s_encodingUniforms[format], + source.left, source.top, native_width, bScaleByHalf ? 2 : 1); EncodeToRamUsingShader(source_texture, - dest_ptr, texture_entry->BytesPerRow(), texture_entry->NumBlocksY(), - texture_entry->memory_stride, bScaleByHalf > 0 && !bFromZBuffer); + dest_ptr, bytes_per_row, num_blocks_y, + memory_stride, bScaleByHalf > 0 && !bFromZBuffer); } void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc, u8* destAddr, u32 dstWidth, u32 dstStride, u32 dstHeight) diff --git a/Source/Core/VideoBackends/OGL/TextureConverter.h b/Source/Core/VideoBackends/OGL/TextureConverter.h index b13bbc57f2..7a9fbca53e 100644 --- a/Source/Core/VideoBackends/OGL/TextureConverter.h +++ b/Source/Core/VideoBackends/OGL/TextureConverter.h @@ -26,7 +26,7 @@ void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc, void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTexture); // returns size of the encoded data (in bytes) -void EncodeToRamFromTexture(u8* dest_ptr, const TextureCacheBase::TCacheEntryBase* texture_entry, +void EncodeToRamFromTexture(u8 *dest_ptr, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, GLuint source_texture, bool bFromZBuffer, bool bIsIntensityFmt, int bScaleByHalf, const EFBRectangle& source); } From 71b22702a1b65d024311d6a92069ab76a3b48c96 Mon Sep 17 00:00:00 2001 From: degasus Date: Thu, 29 Oct 2015 08:45:17 +0100 Subject: [PATCH 2/5] OGL-TextureConverter: Keep care about the global state ifself --- Source/Core/VideoBackends/OGL/TextureCache.cpp | 10 ++++------ .../Core/VideoBackends/OGL/TextureConverter.cpp | 15 ++++++++++++--- Source/Core/VideoBackends/OGL/TextureConverter.h | 2 +- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/Source/Core/VideoBackends/OGL/TextureCache.cpp b/Source/Core/VideoBackends/OGL/TextureCache.cpp index 287e9b2188..24fcb81e82 100644 --- a/Source/Core/VideoBackends/OGL/TextureCache.cpp +++ b/Source/Core/VideoBackends/OGL/TextureCache.cpp @@ -264,6 +264,9 @@ void TextureCache::TCacheEntry::FromRenderTarget(u8* dstPointer, unsigned int ds glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + FramebufferManager::SetFramebuffer(0); + g_renderer->RestoreAPIState(); + if (g_ActiveConfig.bSkipEFBCopyToRam) { this->Zero(dstPointer); @@ -277,16 +280,11 @@ void TextureCache::TCacheEntry::FromRenderTarget(u8* dstPointer, unsigned int ds BytesPerRow(), NumBlocksY(), memory_stride, - read_texture, - srcFormat == PEControl::Z24, + srcFormat, isIntensity, scaleByHalf, srcRect); } - - FramebufferManager::SetFramebuffer(0); - - g_renderer->RestoreAPIState(); } TextureCache::TextureCache() diff --git a/Source/Core/VideoBackends/OGL/TextureConverter.cpp b/Source/Core/VideoBackends/OGL/TextureConverter.cpp index ba2046d9a3..bd51ca745f 100644 --- a/Source/Core/VideoBackends/OGL/TextureConverter.cpp +++ b/Source/Core/VideoBackends/OGL/TextureConverter.cpp @@ -270,17 +270,26 @@ static void EncodeToRamUsingShader(GLuint srcTexture, } void EncodeToRamFromTexture(u8 *dest_ptr, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, - GLuint source_texture, bool bFromZBuffer, bool bIsIntensityFmt, int bScaleByHalf, const EFBRectangle& source) + PEControl::PixelFormat srcFormat, bool bIsIntensityFmt, int bScaleByHalf, const EFBRectangle& source) { + g_renderer->ResetAPIState(); + SHADER& texconv_shader = GetOrCreateEncodingShader(format); texconv_shader.Bind(); glUniform4i(s_encodingUniforms[format], source.left, source.top, native_width, bScaleByHalf ? 2 : 1); - EncodeToRamUsingShader(source_texture, + const GLuint read_texture = (srcFormat == PEControl::Z24) ? + FramebufferManager::ResolveAndGetDepthTarget(source) : + FramebufferManager::ResolveAndGetRenderTarget(source); + + EncodeToRamUsingShader(read_texture, dest_ptr, bytes_per_row, num_blocks_y, - memory_stride, bScaleByHalf > 0 && !bFromZBuffer); + memory_stride, bScaleByHalf > 0 && srcFormat != PEControl::Z24); + + FramebufferManager::SetFramebuffer(0); + g_renderer->RestoreAPIState(); } void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc, u8* destAddr, u32 dstWidth, u32 dstStride, u32 dstHeight) diff --git a/Source/Core/VideoBackends/OGL/TextureConverter.h b/Source/Core/VideoBackends/OGL/TextureConverter.h index 7a9fbca53e..e417e431a4 100644 --- a/Source/Core/VideoBackends/OGL/TextureConverter.h +++ b/Source/Core/VideoBackends/OGL/TextureConverter.h @@ -27,7 +27,7 @@ void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTextur // returns size of the encoded data (in bytes) void EncodeToRamFromTexture(u8 *dest_ptr, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, - GLuint source_texture, bool bFromZBuffer, bool bIsIntensityFmt, int bScaleByHalf, const EFBRectangle& source); + PEControl::PixelFormat srcFormat, bool bIsIntensityFmt, int bScaleByHalf, const EFBRectangle& source); } From d7d870435367b2a9eb2f5153c954b354efd98202 Mon Sep 17 00:00:00 2001 From: degasus Date: Thu, 29 Oct 2015 08:55:50 +0100 Subject: [PATCH 3/5] D3D-TextureEncoder: Remove TCache::Entry usage --- .../VideoBackends/D3D/PSTextureEncoder.cpp | 18 +++++++++--------- .../Core/VideoBackends/D3D/PSTextureEncoder.h | 6 +++--- Source/Core/VideoBackends/D3D/TextureCache.cpp | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp b/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp index c337927ac9..b3209bef48 100644 --- a/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp +++ b/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp @@ -87,7 +87,7 @@ void PSTextureEncoder::Shutdown() SAFE_RELEASE(m_out); } -void PSTextureEncoder::Encode(u8* dst, const TextureCache::TCacheEntryBase *texture_entry, +void PSTextureEncoder::Encode(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect, bool isIntensity, bool scaleByHalf) { @@ -101,9 +101,9 @@ void PSTextureEncoder::Encode(u8* dst, const TextureCache::TCacheEntryBase *text // Set up all the state for EFB encoding { - const u32 words_per_row = texture_entry->BytesPerRow() / sizeof(u32); + const u32 words_per_row = bytes_per_row / sizeof(u32); - D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, FLOAT(words_per_row), FLOAT(texture_entry->NumBlocksY())); + D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, FLOAT(words_per_row), FLOAT(num_blocks_y)); D3D::context->RSSetViewports(1, &vp); EFBRectangle fullSrcRect; @@ -125,7 +125,7 @@ void PSTextureEncoder::Encode(u8* dst, const TextureCache::TCacheEntryBase *text EFBEncodeParams params; params.SrcLeft = srcRect.left; params.SrcTop = srcRect.top; - params.DestWidth = texture_entry->native_width; + params.DestWidth = native_width; params.ScaleFactor = scaleByHalf ? 2 : 1; D3D::context->UpdateSubresource(m_encodeParams, 0, nullptr, ¶ms, 0, 0); D3D::stateman->SetPixelConstants(m_encodeParams); @@ -140,12 +140,12 @@ void PSTextureEncoder::Encode(u8* dst, const TextureCache::TCacheEntryBase *text targetRect.AsRECT(), Renderer::GetTargetWidth(), Renderer::GetTargetHeight(), - SetStaticShader(texture_entry->format, srcFormat, isIntensity, scaleByHalf), + SetStaticShader(format, srcFormat, isIntensity, scaleByHalf), VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout()); // Copy to staging buffer - D3D11_BOX srcBox = CD3D11_BOX(0, 0, 0, words_per_row, texture_entry->NumBlocksY(), 1); + D3D11_BOX srcBox = CD3D11_BOX(0, 0, 0, words_per_row, num_blocks_y, 1); D3D::context->CopySubresourceRegion(m_outStage, 0, 0, 0, 0, m_out, 0, &srcBox); // Transfer staging buffer to GameCube/Wii RAM @@ -154,11 +154,11 @@ void PSTextureEncoder::Encode(u8* dst, const TextureCache::TCacheEntryBase *text CHECK(SUCCEEDED(hr), "map staging buffer (0x%x)", hr); u8* src = (u8*)map.pData; - u32 readStride = std::min(texture_entry->BytesPerRow(), map.RowPitch); - for (unsigned int y = 0; y < texture_entry->NumBlocksY(); ++y) + u32 readStride = std::min(bytes_per_row, map.RowPitch); + for (unsigned int y = 0; y < num_blocks_y; ++y) { memcpy(dst, src, readStride); - dst += texture_entry->memory_stride; + dst += memory_stride; src += map.RowPitch; } diff --git a/Source/Core/VideoBackends/D3D/PSTextureEncoder.h b/Source/Core/VideoBackends/D3D/PSTextureEncoder.h index 40f49a0728..e82db8779e 100644 --- a/Source/Core/VideoBackends/D3D/PSTextureEncoder.h +++ b/Source/Core/VideoBackends/D3D/PSTextureEncoder.h @@ -31,9 +31,9 @@ public: void Init(); void Shutdown(); - void Encode(u8* dst, const TextureCacheBase::TCacheEntryBase* texture_entry, - PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect, - bool isIntensity, bool scaleByHalf); + void Encode(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, + PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect, + bool isIntensity, bool scaleByHalf); private: bool m_ready; diff --git a/Source/Core/VideoBackends/D3D/TextureCache.cpp b/Source/Core/VideoBackends/D3D/TextureCache.cpp index 1738a1f4d5..eab591c7ee 100644 --- a/Source/Core/VideoBackends/D3D/TextureCache.cpp +++ b/Source/Core/VideoBackends/D3D/TextureCache.cpp @@ -240,7 +240,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u8* dst, unsigned int dstFormat if (g_ActiveConfig.bSkipEFBCopyToRam) this->Zero(dst); else - g_encoder->Encode(dst, this, srcFormat, srcRect, isIntensity, scaleByHalf); + g_encoder->Encode(dst, format, native_width, BytesPerRow(), NumBlocksY(), memory_stride, srcFormat, srcRect, isIntensity, scaleByHalf); } const char palette_shader[] = From dcdf8fd3ced5e5d2b94299bc710a69ee06bab0d6 Mon Sep 17 00:00:00 2001 From: degasus Date: Thu, 29 Oct 2015 17:48:35 +0100 Subject: [PATCH 4/5] TextureCache: Split efb2ram from efb2tex --- .../Core/VideoBackends/D3D/TextureCache.cpp | 10 +++--- Source/Core/VideoBackends/D3D/TextureCache.h | 4 +++ .../Core/VideoBackends/D3D/TextureEncoder.h | 2 +- .../Core/VideoBackends/OGL/TextureCache.cpp | 34 +++++++++---------- Source/Core/VideoBackends/OGL/TextureCache.h | 4 +++ Source/Core/VideoCommon/TextureCacheBase.cpp | 19 +++++++++++ Source/Core/VideoCommon/TextureCacheBase.h | 4 +++ 7 files changed, 54 insertions(+), 23 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/TextureCache.cpp b/Source/Core/VideoBackends/D3D/TextureCache.cpp index eab591c7ee..f2f5ae96b4 100644 --- a/Source/Core/VideoBackends/D3D/TextureCache.cpp +++ b/Source/Core/VideoBackends/D3D/TextureCache.cpp @@ -236,11 +236,13 @@ void TextureCache::TCacheEntry::FromRenderTarget(u8* dst, unsigned int dstFormat D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV()); g_renderer->RestoreAPIState(); +} - if (g_ActiveConfig.bSkipEFBCopyToRam) - this->Zero(dst); - else - g_encoder->Encode(dst, format, native_width, BytesPerRow(), NumBlocksY(), memory_stride, srcFormat, srcRect, isIntensity, scaleByHalf); +void TextureCache::CopyEFB(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, + PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect, + bool isIntensity, bool scaleByHalf) +{ + g_encoder->Encode(dst, format, native_width, bytes_per_row, num_blocks_y, memory_stride, srcFormat, srcRect, isIntensity, scaleByHalf); } const char palette_shader[] = diff --git a/Source/Core/VideoBackends/D3D/TextureCache.h b/Source/Core/VideoBackends/D3D/TextureCache.h index fa6aeafc3b..c852d2469c 100644 --- a/Source/Core/VideoBackends/D3D/TextureCache.h +++ b/Source/Core/VideoBackends/D3D/TextureCache.h @@ -49,6 +49,10 @@ private: void ConvertTexture(TCacheEntryBase* entry, TCacheEntryBase* unconverted, void* palette, TlutFormat format) override; + void CopyEFB(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, + PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect, + bool isIntensity, bool scaleByHalf) override; + void CompileShaders() override { } void DeleteShaders() override { } diff --git a/Source/Core/VideoBackends/D3D/TextureEncoder.h b/Source/Core/VideoBackends/D3D/TextureEncoder.h index 2e3eef99ad..52ac6ba25e 100644 --- a/Source/Core/VideoBackends/D3D/TextureEncoder.h +++ b/Source/Core/VideoBackends/D3D/TextureEncoder.h @@ -26,7 +26,7 @@ public: virtual void Init() = 0; virtual void Shutdown() = 0; // Returns size in bytes of encoded block of memory - virtual void Encode(u8* dst, const TextureCacheBase::TCacheEntryBase* texture_entry, + virtual void Encode(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect, bool isIntensity, bool scaleByHalf) = 0; diff --git a/Source/Core/VideoBackends/OGL/TextureCache.cpp b/Source/Core/VideoBackends/OGL/TextureCache.cpp index 24fcb81e82..e733cd8d87 100644 --- a/Source/Core/VideoBackends/OGL/TextureCache.cpp +++ b/Source/Core/VideoBackends/OGL/TextureCache.cpp @@ -266,25 +266,23 @@ void TextureCache::TCacheEntry::FromRenderTarget(u8* dstPointer, unsigned int ds FramebufferManager::SetFramebuffer(0); g_renderer->RestoreAPIState(); +} - if (g_ActiveConfig.bSkipEFBCopyToRam) - { - this->Zero(dstPointer); - } - else - { - TextureConverter::EncodeToRamFromTexture( - dstPointer, - format, - native_width, - BytesPerRow(), - NumBlocksY(), - memory_stride, - srcFormat, - isIntensity, - scaleByHalf, - srcRect); - } +void TextureCache::CopyEFB(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, + PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect, + bool isIntensity, bool scaleByHalf) +{ + TextureConverter::EncodeToRamFromTexture( + dst, + format, + native_width, + bytes_per_row, + num_blocks_y, + memory_stride, + srcFormat, + isIntensity, + scaleByHalf, + srcRect); } TextureCache::TextureCache() diff --git a/Source/Core/VideoBackends/OGL/TextureCache.h b/Source/Core/VideoBackends/OGL/TextureCache.h index 10c4a57378..3028a25d38 100644 --- a/Source/Core/VideoBackends/OGL/TextureCache.h +++ b/Source/Core/VideoBackends/OGL/TextureCache.h @@ -56,6 +56,10 @@ private: TCacheEntryBase* CreateTexture(const TCacheEntryConfig& config) override; void ConvertTexture(TCacheEntryBase* entry, TCacheEntryBase* unconverted, void* palette, TlutFormat format) override; + void CopyEFB(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, + PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect, + bool isIntensity, bool scaleByHalf) override; + void CompileShaders() override; void DeleteShaders() override; }; diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 8f1d700dfd..44fdf9fe48 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -1050,6 +1050,25 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFo entry->FromRenderTarget(dst, dstFormat, dstStride, srcFormat, srcRect, isIntensity, scaleByHalf, cbufid, colmat); + if (g_ActiveConfig.bSkipEFBCopyToRam) + { + entry->Zero(dst); + } + else + { + g_texture_cache->CopyEFB( + dst, + entry->format, + entry->native_width, + entry->BytesPerRow(), + entry->NumBlocksY(), + entry->memory_stride, + srcFormat, + srcRect, + isIntensity, + scaleByHalf); + } + u64 hash = entry->CalculateHash(); entry->SetHashes(hash, hash); diff --git a/Source/Core/VideoCommon/TextureCacheBase.h b/Source/Core/VideoCommon/TextureCacheBase.h index 9e7b4a7c71..1dbddd253f 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.h +++ b/Source/Core/VideoCommon/TextureCacheBase.h @@ -130,6 +130,10 @@ public: virtual TCacheEntryBase* CreateTexture(const TCacheEntryConfig& config) = 0; + virtual void CopyEFB(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, + PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect, + bool isIntensity, bool scaleByHalf) = 0; + virtual void CompileShaders() = 0; // currently only implemented by OGL virtual void DeleteShaders() = 0; // currently only implemented by OGL From 087ba5268a5512e95783ad69bc743a5aeb0bb0b9 Mon Sep 17 00:00:00 2001 From: degasus Date: Thu, 29 Oct 2015 18:08:04 +0100 Subject: [PATCH 5/5] TextureCache: Rewrite EFB Copy control flow --- .../Core/VideoBackends/D3D/PSTextureEncoder.h | 4 +- .../Core/VideoBackends/D3D/TextureCache.cpp | 6 +- Source/Core/VideoBackends/D3D/TextureCache.h | 6 +- .../Core/VideoBackends/OGL/TextureCache.cpp | 6 +- Source/Core/VideoBackends/OGL/TextureCache.h | 6 +- .../VideoBackends/OGL/TextureConverter.cpp | 2 +- .../Core/VideoBackends/OGL/TextureConverter.h | 2 +- Source/Core/VideoCommon/TextureCacheBase.cpp | 135 ++++++++++-------- Source/Core/VideoCommon/TextureCacheBase.h | 8 +- 9 files changed, 91 insertions(+), 84 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/PSTextureEncoder.h b/Source/Core/VideoBackends/D3D/PSTextureEncoder.h index e82db8779e..b12030ec66 100644 --- a/Source/Core/VideoBackends/D3D/PSTextureEncoder.h +++ b/Source/Core/VideoBackends/D3D/PSTextureEncoder.h @@ -32,8 +32,8 @@ public: void Init(); void Shutdown(); void Encode(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, - PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect, - bool isIntensity, bool scaleByHalf); + PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect, + bool isIntensity, bool scaleByHalf); private: bool m_ready; diff --git a/Source/Core/VideoBackends/D3D/TextureCache.cpp b/Source/Core/VideoBackends/D3D/TextureCache.cpp index f2f5ae96b4..1d5141ce0e 100644 --- a/Source/Core/VideoBackends/D3D/TextureCache.cpp +++ b/Source/Core/VideoBackends/D3D/TextureCache.cpp @@ -184,10 +184,8 @@ TextureCacheBase::TCacheEntryBase* TextureCache::CreateTexture(const TCacheEntry } } -void TextureCache::TCacheEntry::FromRenderTarget(u8* dst, unsigned int dstFormat, u32 dstStride, - PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect, - bool isIntensity, bool scaleByHalf, unsigned int cbufid, - const float *colmat) +void TextureCache::TCacheEntry::FromRenderTarget(u8* dst, PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect, + bool scaleByHalf, unsigned int cbufid, const float *colmat) { g_renderer->ResetAPIState(); diff --git a/Source/Core/VideoBackends/D3D/TextureCache.h b/Source/Core/VideoBackends/D3D/TextureCache.h index c852d2469c..37f0dcc6c7 100644 --- a/Source/Core/VideoBackends/D3D/TextureCache.h +++ b/Source/Core/VideoBackends/D3D/TextureCache.h @@ -34,10 +34,8 @@ private: void Load(unsigned int width, unsigned int height, unsigned int expanded_width, unsigned int levels) override; - void FromRenderTarget(u8* dst, unsigned int dstFormat, u32 dstStride, - PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect, - bool isIntensity, bool scaleByHalf, unsigned int cbufid, - const float *colmat) override; + void FromRenderTarget(u8* dst, PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect, + bool scaleByHalf, unsigned int cbufid, const float *colmat) override; void Bind(unsigned int stage) override; bool Save(const std::string& filename, unsigned int level) override; diff --git a/Source/Core/VideoBackends/OGL/TextureCache.cpp b/Source/Core/VideoBackends/OGL/TextureCache.cpp index e733cd8d87..5ffd87699b 100644 --- a/Source/Core/VideoBackends/OGL/TextureCache.cpp +++ b/Source/Core/VideoBackends/OGL/TextureCache.cpp @@ -215,10 +215,8 @@ void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height, TextureCache::SetStage(); } -void TextureCache::TCacheEntry::FromRenderTarget(u8* dstPointer, unsigned int dstFormat, u32 dstStride, - PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect, - bool isIntensity, bool scaleByHalf, unsigned int cbufid, - const float *colmat) +void TextureCache::TCacheEntry::FromRenderTarget(u8* dstPointer, PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect, + bool scaleByHalf, unsigned int cbufid, const float *colmat) { g_renderer->ResetAPIState(); // reset any game specific settings diff --git a/Source/Core/VideoBackends/OGL/TextureCache.h b/Source/Core/VideoBackends/OGL/TextureCache.h index 3028a25d38..5460e1be09 100644 --- a/Source/Core/VideoBackends/OGL/TextureCache.h +++ b/Source/Core/VideoBackends/OGL/TextureCache.h @@ -42,10 +42,8 @@ private: void Load(unsigned int width, unsigned int height, unsigned int expanded_width, unsigned int level) override; - void FromRenderTarget(u8 *dst, unsigned int dstFormat, u32 dstStride, - PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect, - bool isIntensity, bool scaleByHalf, unsigned int cbufid, - const float *colmat) override; + void FromRenderTarget(u8 *dst, PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect, + bool scaleByHalf, unsigned int cbufid, const float *colmat) override; void Bind(unsigned int stage) override; bool Save(const std::string& filename, unsigned int level) override; diff --git a/Source/Core/VideoBackends/OGL/TextureConverter.cpp b/Source/Core/VideoBackends/OGL/TextureConverter.cpp index bd51ca745f..b56b08ab4f 100644 --- a/Source/Core/VideoBackends/OGL/TextureConverter.cpp +++ b/Source/Core/VideoBackends/OGL/TextureConverter.cpp @@ -269,7 +269,7 @@ static void EncodeToRamUsingShader(GLuint srcTexture, } } -void EncodeToRamFromTexture(u8 *dest_ptr, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, +void EncodeToRamFromTexture(u8* dest_ptr, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, PEControl::PixelFormat srcFormat, bool bIsIntensityFmt, int bScaleByHalf, const EFBRectangle& source) { g_renderer->ResetAPIState(); diff --git a/Source/Core/VideoBackends/OGL/TextureConverter.h b/Source/Core/VideoBackends/OGL/TextureConverter.h index e417e431a4..5fdb46e92f 100644 --- a/Source/Core/VideoBackends/OGL/TextureConverter.h +++ b/Source/Core/VideoBackends/OGL/TextureConverter.h @@ -26,7 +26,7 @@ void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc, void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTexture); // returns size of the encoded data (in bytes) -void EncodeToRamFromTexture(u8 *dest_ptr, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, +void EncodeToRamFromTexture(u8* dest_ptr, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, PEControl::PixelFormat srcFormat, bool bIsIntensityFmt, int bScaleByHalf, const EFBRectangle& source); } diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 44fdf9fe48..693b4b5ba1 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -1032,80 +1032,109 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFo } } - // create the texture - TCacheEntryConfig config; - config.rendertarget = true; - config.width = scaled_tex_w; - config.height = scaled_tex_h; - config.layers = FramebufferManagerBase::GetEFBLayers(); + u32 blockH = TexDecoder_GetBlockHeightInTexels(dstFormat); + const u32 blockW = TexDecoder_GetBlockWidthInTexels(dstFormat); - TCacheEntryBase* entry = AllocateTexture(config); + // Round up source height to multiple of block size + u32 actualHeight = ROUND_UP(tex_h, blockH); + const u32 actualWidth = ROUND_UP(tex_w, blockW); - entry->SetGeneralParameters(dstAddr, 0, dstFormat); - entry->SetDimensions(tex_w, tex_h, 1); + u32 num_blocks_y = actualHeight / blockH; + const u32 num_blocks_x = actualWidth / blockW; - entry->frameCount = FRAMECOUNT_INVALID; - entry->SetEfbCopy(dstStride); - entry->is_custom_tex = false; + // RGBA takes two cache lines per block; all others take one + const u32 bytes_per_block = dstFormat == GX_TF_RGBA8 ? 64 : 32; - entry->FromRenderTarget(dst, dstFormat, dstStride, srcFormat, srcRect, isIntensity, scaleByHalf, cbufid, colmat); + u32 bytes_per_row = num_blocks_x * bytes_per_block; - if (g_ActiveConfig.bSkipEFBCopyToRam) - { - entry->Zero(dst); - } - else + bool copy_to_ram = !g_ActiveConfig.bSkipEFBCopyToRam; + bool copy_to_vram = true; + + if (copy_to_ram) { g_texture_cache->CopyEFB( dst, - entry->format, - entry->native_width, - entry->BytesPerRow(), - entry->NumBlocksY(), - entry->memory_stride, + dstFormat, + tex_w, + bytes_per_row, + num_blocks_y, + dstStride, srcFormat, srcRect, isIntensity, scaleByHalf); } - - u64 hash = entry->CalculateHash(); - entry->SetHashes(hash, hash); - - // Invalidate all textures that overlap the range of our efb copy. - // Unless our efb copy has a weird stride, then we want avoid invalidating textures which - // we might be able to do a partial texture update on. - if (entry->memory_stride == entry->BytesPerRow()) + else { - TexCache::iterator iter = textures_by_address.begin(); - while (iter != textures_by_address.end()) + // Hack: Most games don't actually need the correct texture data in RAM + // and we can just keep a copy in VRAM. We zero the memory so we + // can check it hasn't changed before using our copy in VRAM. + u8* ptr = dst; + for (u32 i = 0; i < num_blocks_y; i++) { - if (iter->second->OverlapsMemoryRange(dstAddr, entry->size_in_bytes)) - iter = FreeTexture(iter); - else - ++iter; + memset(ptr, 0, bytes_per_row); + ptr += dstStride; } } - if (g_ActiveConfig.bDumpEFBTarget) - { - static int count = 0; - entry->Save(StringFromFormat("%sefb_frame_%i.png", File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(), - count++), 0); - } - if (g_bRecordFifoData) { // Mark the memory behind this efb copy as dynamicly generated for the Fifo log u32 address = dstAddr; - for (u32 i = 0; i < entry->NumBlocksY(); i++) + for (u32 i = 0; i < num_blocks_y; i++) { - FifoRecorder::GetInstance().UseMemory(address, entry->BytesPerRow(), MemoryUpdate::TEXTURE_MAP, true); - address += entry->memory_stride; + FifoRecorder::GetInstance().UseMemory(address, bytes_per_row, MemoryUpdate::TEXTURE_MAP, true); + address += dstStride; } } - textures_by_address.emplace((u64)dstAddr, entry); + // Invalidate all textures that overlap the range of our efb copy. + // Unless our efb copy has a weird stride, then we want avoid invalidating textures which + // we might be able to do a partial texture update on. + if (dstStride == bytes_per_row || !copy_to_vram) + { + TexCache::iterator iter = textures_by_address.begin(); + while (iter != textures_by_address.end()) + { + if (iter->second->addr + iter->second->size_in_bytes <= dstAddr || iter->second->addr >= dstAddr + num_blocks_y * dstStride) + ++iter; + else + iter = FreeTexture(iter); + } + } + + if (copy_to_vram) + { + // create the texture + TCacheEntryConfig config; + config.rendertarget = true; + config.width = scaled_tex_w; + config.height = scaled_tex_h; + config.layers = FramebufferManagerBase::GetEFBLayers(); + + TCacheEntryBase* entry = AllocateTexture(config); + + entry->SetGeneralParameters(dstAddr, 0, dstFormat); + entry->SetDimensions(tex_w, tex_h, 1); + + entry->frameCount = FRAMECOUNT_INVALID; + entry->SetEfbCopy(dstStride); + entry->is_custom_tex = false; + + entry->FromRenderTarget(dst, srcFormat, srcRect, scaleByHalf, cbufid, colmat); + + u64 hash = entry->CalculateHash(); + entry->SetHashes(hash, hash); + + if (g_ActiveConfig.bDumpEFBTarget) + { + static int count = 0; + entry->Save(StringFromFormat("%sefb_frame_%i.png", File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(), + count++), 0); + } + + textures_by_address.emplace((u64)dstAddr, entry); + } } TextureCacheBase::TCacheEntryBase* TextureCacheBase::AllocateTexture(const TCacheEntryConfig& config) @@ -1177,16 +1206,6 @@ void TextureCacheBase::TCacheEntryBase::SetEfbCopy(u32 stride) size_in_bytes = memory_stride * NumBlocksY(); } -// Fill gamecube memory backing this texture with zeros. -void TextureCacheBase::TCacheEntryBase::Zero(u8* ptr) -{ - for (u32 i = 0; i < NumBlocksY(); i++) - { - memset(ptr, 0, BytesPerRow()); - ptr += memory_stride; - } -} - u64 TextureCacheBase::TCacheEntryBase::CalculateHash() const { u8* ptr = Memory::GetPointer(addr); diff --git a/Source/Core/VideoCommon/TextureCacheBase.h b/Source/Core/VideoCommon/TextureCacheBase.h index 1dbddd253f..00db6e46a3 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.h +++ b/Source/Core/VideoCommon/TextureCacheBase.h @@ -101,10 +101,8 @@ public: virtual void Load(unsigned int width, unsigned int height, unsigned int expanded_width, unsigned int level) = 0; - virtual void FromRenderTarget(u8* dst, unsigned int dstFormat, u32 dstStride, - PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect, - bool isIntensity, bool scaleByHalf, unsigned int cbufid, - const float *colmat) = 0; + virtual void FromRenderTarget(u8* dst, PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect, + bool scaleByHalf, unsigned int cbufid, const float *colmat) = 0; bool OverlapsMemoryRange(u32 range_address, u32 range_size) const; @@ -113,8 +111,6 @@ public: u32 NumBlocksY() const; u32 BytesPerRow() const; - void Zero(u8* ptr); - u64 CalculateHash() const; };