From e9850aa0f270a1f735562db72d84860611ad7226 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Tue, 4 Apr 2017 23:55:36 +1000 Subject: [PATCH] VideoBackends: Support updated texture encoding shader generators --- .../VideoBackends/D3D/PSTextureEncoder.cpp | 94 ++++++------------- .../Core/VideoBackends/D3D/PSTextureEncoder.h | 26 ++--- .../Core/VideoBackends/D3D/TextureCache.cpp | 8 +- Source/Core/VideoBackends/D3D/TextureCache.h | 6 +- .../VideoBackends/D3D12/PSTextureEncoder.cpp | 75 +++++---------- .../VideoBackends/D3D12/PSTextureEncoder.h | 25 ++--- .../Core/VideoBackends/D3D12/TextureCache.cpp | 8 +- .../Core/VideoBackends/D3D12/TextureCache.h | 6 +- Source/Core/VideoBackends/Null/TextureCache.h | 6 +- .../Core/VideoBackends/OGL/TextureCache.cpp | 9 +- Source/Core/VideoBackends/OGL/TextureCache.h | 6 +- .../VideoBackends/OGL/TextureConverter.cpp | 84 ++++++++--------- .../Core/VideoBackends/OGL/TextureConverter.h | 7 +- Source/Core/VideoBackends/Software/SWmain.cpp | 6 +- .../VideoBackends/Vulkan/TextureCache.cpp | 8 +- .../Core/VideoBackends/Vulkan/TextureCache.h | 6 +- .../VideoBackends/Vulkan/TextureConverter.cpp | 64 ++++++------- .../VideoBackends/Vulkan/TextureConverter.h | 15 +-- Source/Core/VideoCommon/TextureCacheBase.cpp | 8 +- Source/Core/VideoCommon/TextureCacheBase.h | 6 +- 20 files changed, 194 insertions(+), 279 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp b/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp index 7b9bfaeaa3..403e768599 100644 --- a/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp +++ b/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp @@ -75,11 +75,11 @@ void PSTextureEncoder::Shutdown() { m_ready = false; - for (auto& it : m_staticShaders) + for (auto& it : m_encoding_shaders) { SAFE_RELEASE(it.second); } - m_staticShaders.clear(); + m_encoding_shaders.clear(); SAFE_RELEASE(m_encodeParams); SAFE_RELEASE(m_outStage); @@ -87,9 +87,9 @@ void PSTextureEncoder::Shutdown() SAFE_RELEASE(m_out); } -void PSTextureEncoder::Encode(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, - u32 num_blocks_y, u32 memory_stride, bool is_depth_copy, - const EFBRectangle& srcRect, bool isIntensity, bool scaleByHalf) +void PSTextureEncoder::Encode(u8* dst, const EFBCopyFormat& format, u32 native_width, + u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, + bool is_depth_copy, const EFBRectangle& src_rect, bool scale_by_half) { if (!m_ready) // Make sure we initialized OK return; @@ -120,10 +120,10 @@ void PSTextureEncoder::Encode(u8* dst, u32 format, u32 native_width, u32 bytes_p D3D::context->OMSetRenderTargets(1, &m_outRTV, nullptr); EFBEncodeParams params; - params.SrcLeft = srcRect.left; - params.SrcTop = srcRect.top; + params.SrcLeft = src_rect.left; + params.SrcTop = src_rect.top; params.DestWidth = native_width; - params.ScaleFactor = scaleByHalf ? 2 : 1; + params.ScaleFactor = scale_by_half ? 2 : 1; D3D::context->UpdateSubresource(m_encodeParams, 0, nullptr, ¶ms, 0, 0); D3D::stateman->SetPixelConstants(m_encodeParams); @@ -131,15 +131,15 @@ void PSTextureEncoder::Encode(u8* dst, u32 format, u32 native_width, u32 bytes_p // TODO: This only produces perfect downsampling for 1.5x and 2x IR, other resolution will // need more complex down filtering to average all pixels and produce the correct result. // Also, box filtering won't be correct for anything other than 1x IR - if (scaleByHalf || g_ActiveConfig.iEFBScale != SCALE_1X) + if (scale_by_half || g_ActiveConfig.iEFBScale != SCALE_1X) D3D::SetLinearCopySampler(); else D3D::SetPointCopySampler(); - D3D::drawShadedTexQuad( - pEFB, targetRect.AsRECT(), g_renderer->GetTargetWidth(), g_renderer->GetTargetHeight(), - SetStaticShader(format, is_depth_copy, isIntensity, scaleByHalf), - VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout()); + D3D::drawShadedTexQuad(pEFB, targetRect.AsRECT(), g_renderer->GetTargetWidth(), + g_renderer->GetTargetHeight(), GetEncodingPixelShader(format), + VertexShaderCache::GetSimpleVertexShader(), + VertexShaderCache::GetSimpleInputLayout()); // Copy to staging buffer D3D11_BOX srcBox = CD3D11_BOX(0, 0, 0, words_per_row, num_blocks_y, 1); @@ -168,61 +168,27 @@ void PSTextureEncoder::Encode(u8* dst, u32 format, u32 native_width, u32 bytes_p FramebufferManager::GetEFBDepthTexture()->GetDSV()); } -ID3D11PixelShader* PSTextureEncoder::SetStaticShader(unsigned int dstFormat, bool is_depth_copy, - bool isIntensity, bool scaleByHalf) +ID3D11PixelShader* PSTextureEncoder::GetEncodingPixelShader(const EFBCopyFormat& format) { - ComboKey key = MakeComboKey(dstFormat, is_depth_copy, isIntensity, scaleByHalf); + auto iter = m_encoding_shaders.find(format); + if (iter != m_encoding_shaders.end()) + return iter->second; - ComboMap::iterator it = m_staticShaders.find(key); - if (it == m_staticShaders.end()) + D3DBlob* bytecode = nullptr; + const char* shader = TextureConversionShader::GenerateEncodingShader(format, APIType::D3D); + if (!D3D::CompilePixelShader(shader, &bytecode)) { - INFO_LOG(VIDEO, - "Compiling efb encoding shader for dstFormat 0x%X, is_depth_copy %d, isIntensity " - "%d, scaleByHalf %d", - dstFormat, is_depth_copy, isIntensity ? 1 : 0, scaleByHalf ? 1 : 0); - - u32 format = dstFormat; - - if (is_depth_copy) - { - format |= _GX_TF_ZTF; - if (dstFormat == 11) - format = GX_TF_Z16; - else if (format < GX_TF_Z8 || format > GX_TF_Z24X8) - format |= _GX_TF_CTF; - } - else - { - if (dstFormat > GX_TF_RGBA8 || (dstFormat < GX_TF_RGB565 && !isIntensity)) - format |= _GX_TF_CTF; - } - - D3DBlob* bytecode = nullptr; - const char* shader = TextureConversionShader::GenerateEncodingShader(format, APIType::D3D); - if (!D3D::CompilePixelShader(shader, &bytecode)) - { - WARN_LOG(VIDEO, "EFB encoder shader for dstFormat 0x%X, is_depth_copy %d, isIntensity %d, " - "scaleByHalf %d failed to compile", - dstFormat, is_depth_copy, isIntensity ? 1 : 0, scaleByHalf ? 1 : 0); - m_staticShaders[key] = nullptr; - return nullptr; - } - - ID3D11PixelShader* newShader; - HRESULT hr = - D3D::device->CreatePixelShader(bytecode->Data(), bytecode->Size(), nullptr, &newShader); - CHECK(SUCCEEDED(hr), "create efb encoder pixel shader"); - - char debugName[255] = {}; - sprintf_s(debugName, - "efb encoder pixel shader (dst:%d, is_depth_copy:%d, intensity:%d, scale:%d)", - dstFormat, is_depth_copy, isIntensity, scaleByHalf); - D3D::SetDebugObjectName(newShader, debugName); - - it = m_staticShaders.emplace(key, newShader).first; - bytecode->Release(); + PanicAlert("Failed to compile texture encoding shader."); + m_encoding_shaders[format] = nullptr; + return nullptr; } - return it->second; + ID3D11PixelShader* newShader; + HRESULT hr = + D3D::device->CreatePixelShader(bytecode->Data(), bytecode->Size(), nullptr, &newShader); + CHECK(SUCCEEDED(hr), "create efb encoder pixel shader"); + + m_encoding_shaders.emplace(format, newShader); + return newShader; } } diff --git a/Source/Core/VideoBackends/D3D/PSTextureEncoder.h b/Source/Core/VideoBackends/D3D/PSTextureEncoder.h index eee3f63cc5..c000777591 100644 --- a/Source/Core/VideoBackends/D3D/PSTextureEncoder.h +++ b/Source/Core/VideoBackends/D3D/PSTextureEncoder.h @@ -7,6 +7,7 @@ #include #include "Common/CommonTypes.h" +#include "VideoCommon/TextureConversionShader.h" #include "VideoCommon/VideoCommon.h" struct ID3D11Texture2D; @@ -31,32 +32,19 @@ 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, bool is_depth_copy, const EFBRectangle& srcRect, bool isIntensity, - bool scaleByHalf); + void Encode(u8* dst, const EFBCopyFormat& format, u32 native_width, u32 bytes_per_row, + u32 num_blocks_y, u32 memory_stride, bool is_depth_copy, const EFBRectangle& src_rect, + bool scale_by_half); private: + ID3D11PixelShader* GetEncodingPixelShader(const EFBCopyFormat& format); + bool m_ready; ID3D11Texture2D* m_out; ID3D11RenderTargetView* m_outRTV; ID3D11Texture2D* m_outStage; ID3D11Buffer* m_encodeParams; - - ID3D11PixelShader* SetStaticShader(unsigned int dstFormat, bool is_depth_copy, bool isIntensity, - bool scaleByHalf); - - typedef unsigned int ComboKey; // Key for a shader combination - - ComboKey MakeComboKey(unsigned int dstFormat, bool is_depth_copy, bool isIntensity, - bool scaleByHalf) - { - return (dstFormat << 4) | (static_cast(is_depth_copy) << 2) | - (isIntensity ? (1 << 1) : 0) | (scaleByHalf ? (1 << 0) : 0); - } - - typedef std::map ComboMap; - - ComboMap m_staticShaders; + std::map m_encoding_shaders; }; } diff --git a/Source/Core/VideoBackends/D3D/TextureCache.cpp b/Source/Core/VideoBackends/D3D/TextureCache.cpp index e3edf79695..d6369f290f 100644 --- a/Source/Core/VideoBackends/D3D/TextureCache.cpp +++ b/Source/Core/VideoBackends/D3D/TextureCache.cpp @@ -241,12 +241,12 @@ void TextureCache::TCacheEntry::FromRenderTarget(bool is_depth_copy, const EFBRe g_renderer->RestoreAPIState(); } -void TextureCache::CopyEFB(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, - u32 num_blocks_y, u32 memory_stride, bool is_depth_copy, - const EFBRectangle& srcRect, bool isIntensity, bool scaleByHalf) +void TextureCache::CopyEFB(u8* dst, const EFBCopyFormat& format, u32 native_width, + u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, + bool is_depth_copy, const EFBRectangle& src_rect, bool scale_by_half) { g_encoder->Encode(dst, format, native_width, bytes_per_row, num_blocks_y, memory_stride, - is_depth_copy, srcRect, isIntensity, scaleByHalf); + is_depth_copy, src_rect, scale_by_half); } const char palette_shader[] = diff --git a/Source/Core/VideoBackends/D3D/TextureCache.h b/Source/Core/VideoBackends/D3D/TextureCache.h index bf82418208..01b229cf72 100644 --- a/Source/Core/VideoBackends/D3D/TextureCache.h +++ b/Source/Core/VideoBackends/D3D/TextureCache.h @@ -51,9 +51,9 @@ 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, bool is_depth_copy, const EFBRectangle& srcRect, bool isIntensity, - bool scaleByHalf) override; + void CopyEFB(u8* dst, const EFBCopyFormat& format, u32 native_width, u32 bytes_per_row, + u32 num_blocks_y, u32 memory_stride, bool is_depth_copy, + const EFBRectangle& src_rect, bool scale_by_half) override; bool CompileShaders() override { return true; } void DeleteShaders() override {} diff --git a/Source/Core/VideoBackends/D3D12/PSTextureEncoder.cpp b/Source/Core/VideoBackends/D3D12/PSTextureEncoder.cpp index 8e70540d94..ce56588669 100644 --- a/Source/Core/VideoBackends/D3D12/PSTextureEncoder.cpp +++ b/Source/Core/VideoBackends/D3D12/PSTextureEncoder.cpp @@ -101,18 +101,18 @@ void PSTextureEncoder::Shutdown() D3D::command_list_mgr->DestroyResourceAfterCurrentCommandListExecuted(m_out_readback_buffer); D3D::command_list_mgr->DestroyResourceAfterCurrentCommandListExecuted(m_encode_params_buffer); - for (auto& it : m_static_shaders_blobs) + for (auto& it : m_shader_blobs) { SAFE_RELEASE(it); } - m_static_shaders_blobs.clear(); - m_static_shaders_map.clear(); + m_shader_blobs.clear(); + m_encoding_shaders.clear(); } -void PSTextureEncoder::Encode(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, - u32 num_blocks_y, u32 memory_stride, bool is_depth_copy, - const EFBRectangle& src_rect, bool is_intensity, bool scale_by_half) +void PSTextureEncoder::Encode(u8* dst, const EFBCopyFormat& format, u32 native_width, + u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, + bool is_depth_copy, const EFBRectangle& src_rect, bool scale_by_half) { if (!m_ready) // Make sure we initialized OK return; @@ -167,8 +167,7 @@ void PSTextureEncoder::Encode(u8* dst, u32 format, u32 native_width, u32 bytes_p D3D::DrawShadedTexQuad( efb_source, target_rect.AsRECT(), g_renderer->GetTargetWidth(), g_renderer->GetTargetHeight(), - SetStaticShader(format, is_depth_copy, is_intensity, scale_by_half), - StaticShaderCache::GetSimpleVertexShader(), + GetEncodingPixelShader(format), StaticShaderCache::GetSimpleVertexShader(), StaticShaderCache::GetSimpleVertexShaderInputLayout(), D3D12_SHADER_BYTECODE(), 1.0f, 0, DXGI_FORMAT_B8G8R8A8_UNORM, false, false /* Render target is not multisampled */ ); @@ -223,53 +222,27 @@ void PSTextureEncoder::Encode(u8* dst, u32 format, u32 native_width, u32 bytes_p m_out_readback_buffer->Unmap(0, &write_range); } -D3D12_SHADER_BYTECODE PSTextureEncoder::SetStaticShader(unsigned int dst_format, bool is_depth_copy, - bool is_intensity, bool scale_by_half) +D3D12_SHADER_BYTECODE PSTextureEncoder::GetEncodingPixelShader(const EFBCopyFormat& format) { - ComboKey key = MakeComboKey(dst_format, is_depth_copy, is_intensity, scale_by_half); + auto iter = m_encoding_shaders.find(format); + if (iter != m_encoding_shaders.end()) + return iter->second; - ComboMap::iterator it = m_static_shaders_map.find(key); - if (it == m_static_shaders_map.end()) + ID3DBlob* bytecode = nullptr; + const char* shader = TextureConversionShader::GenerateEncodingShader(format, APIType::D3D); + if (!D3D::CompilePixelShader(shader, &bytecode)) { - INFO_LOG(VIDEO, "Compiling efb encoding shader for dst_format 0x%X, is_depth_copy %d, " - "is_intensity %d, scale_by_half %d", - dst_format, is_depth_copy, is_intensity ? 1 : 0, scale_by_half ? 1 : 0); - - u32 format = dst_format; - - if (is_depth_copy) - { - format |= _GX_TF_ZTF; - if (dst_format == 11) - format = GX_TF_Z16; - else if (format < GX_TF_Z8 || format > GX_TF_Z24X8) - format |= _GX_TF_CTF; - } - else - { - if (dst_format > GX_TF_RGBA8 || (dst_format < GX_TF_RGB565 && !is_intensity)) - format |= _GX_TF_CTF; - } - - ID3DBlob* bytecode = nullptr; - const char* shader = TextureConversionShader::GenerateEncodingShader(format, APIType::D3D); - if (!D3D::CompilePixelShader(shader, &bytecode)) - { - WARN_LOG(VIDEO, "EFB encoder shader for dst_format 0x%X, is_depth_copy %d, is_intensity %d, " - "scale_by_half %d failed to compile", - dst_format, is_depth_copy, is_intensity ? 1 : 0, scale_by_half ? 1 : 0); - m_static_shaders_blobs[key] = {}; - return {}; - } - - D3D12_SHADER_BYTECODE new_shader = {bytecode->GetBufferPointer(), bytecode->GetBufferSize()}; - - it = m_static_shaders_map.emplace(key, new_shader).first; - - // Keep track of the ID3DBlobs, so we can free them upon shutdown. - m_static_shaders_blobs.push_back(bytecode); + PanicAlert("Failed to compile texture encoding shader."); + m_encoding_shaders[format] = {}; + return {}; } - return it->second; + D3D12_SHADER_BYTECODE new_shader = {bytecode->GetBufferPointer(), bytecode->GetBufferSize()}; + m_encoding_shaders.emplace(format, new_shader); + + // Keep track of the ID3DBlobs, so we can free them upon shutdown. + m_shader_blobs.push_back(bytecode); + + return new_shader; } } diff --git a/Source/Core/VideoBackends/D3D12/PSTextureEncoder.h b/Source/Core/VideoBackends/D3D12/PSTextureEncoder.h index 8f7f11b229..b3f984277c 100644 --- a/Source/Core/VideoBackends/D3D12/PSTextureEncoder.h +++ b/Source/Core/VideoBackends/D3D12/PSTextureEncoder.h @@ -9,6 +9,7 @@ #include "Common/CommonTypes.h" #include "VideoBackends/D3D12/D3DBase.h" +#include "VideoCommon/TextureConversionShader.h" #include "VideoCommon/VideoCommon.h" namespace DX12 @@ -20,11 +21,13 @@ 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, bool is_depth_copy, const EFBRectangle& src_rect, - bool is_intensity, bool scale_by_half); + void Encode(u8* dst, const EFBCopyFormat& format, u32 native_width, u32 bytes_per_row, + u32 num_blocks_y, u32 memory_stride, bool is_depth_copy, const EFBRectangle& src_rect, + bool scale_by_half); private: + D3D12_SHADER_BYTECODE GetEncodingPixelShader(const EFBCopyFormat& format); + bool m_ready = false; ID3D12Resource* m_out = nullptr; @@ -35,19 +38,7 @@ private: ID3D12Resource* m_encode_params_buffer = nullptr; void* m_encode_params_buffer_data = nullptr; - D3D12_SHADER_BYTECODE SetStaticShader(unsigned int dst_format, bool is_depth_copy, - bool is_intensity, bool scale_by_half); - - using ComboKey = unsigned int; // Key for a shader combination - static ComboKey MakeComboKey(unsigned int dst_format, bool is_depth_copy, bool is_intensity, - bool scale_by_half) - { - return (dst_format << 4) | (is_depth_copy << 2) | (is_intensity ? (1 << 1) : 0) | - (scale_by_half ? (1 << 0) : 0); - } - - using ComboMap = std::map; - ComboMap m_static_shaders_map; - std::vector m_static_shaders_blobs; + std::map m_encoding_shaders; + std::vector m_shader_blobs; }; } diff --git a/Source/Core/VideoBackends/D3D12/TextureCache.cpp b/Source/Core/VideoBackends/D3D12/TextureCache.cpp index 8ae4d54d74..d626cb7732 100644 --- a/Source/Core/VideoBackends/D3D12/TextureCache.cpp +++ b/Source/Core/VideoBackends/D3D12/TextureCache.cpp @@ -306,12 +306,12 @@ void TextureCache::TCacheEntry::FromRenderTarget(bool is_depth_copy, const EFBRe g_renderer->RestoreAPIState(); } -void TextureCache::CopyEFB(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, - u32 num_blocks_y, u32 memory_stride, bool is_depth_copy, - const EFBRectangle& srcRect, bool isIntensity, bool scaleByHalf) +void TextureCache::CopyEFB(u8* dst, const EFBCopyFormat& format, u32 native_width, + u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, + bool is_depth_copy, const EFBRectangle& src_rect, bool scale_by_half) { s_encoder->Encode(dst, format, native_width, bytes_per_row, num_blocks_y, memory_stride, - is_depth_copy, srcRect, isIntensity, scaleByHalf); + is_depth_copy, src_rect, scale_by_half); } static const constexpr char s_palette_shader_hlsl[] = diff --git a/Source/Core/VideoBackends/D3D12/TextureCache.h b/Source/Core/VideoBackends/D3D12/TextureCache.h index 87c3107960..f6921afe5b 100644 --- a/Source/Core/VideoBackends/D3D12/TextureCache.h +++ b/Source/Core/VideoBackends/D3D12/TextureCache.h @@ -60,9 +60,9 @@ 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, bool is_depth_copy, const EFBRectangle& src_rect, - bool is_intensity, bool scale_by_half) override; + void CopyEFB(u8* dst, const EFBCopyFormat& format, u32 native_width, u32 bytes_per_row, + u32 num_blocks_y, u32 memory_stride, bool is_depth_copy, + const EFBRectangle& src_rect, bool scale_by_half) override; bool CompileShaders() override { return true; } void DeleteShaders() override {} diff --git a/Source/Core/VideoBackends/Null/TextureCache.h b/Source/Core/VideoBackends/Null/TextureCache.h index ff21422e69..48d111dce6 100644 --- a/Source/Core/VideoBackends/Null/TextureCache.h +++ b/Source/Core/VideoBackends/Null/TextureCache.h @@ -20,9 +20,9 @@ public: { } - void CopyEFB(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, - u32 memory_stride, bool is_depth_copy, const EFBRectangle& src_rect, - bool is_intensity, bool scale_by_half) override + void CopyEFB(u8* dst, const EFBCopyFormat& format, u32 native_width, u32 bytes_per_row, + u32 num_blocks_y, u32 memory_stride, bool is_depth_copy, + const EFBRectangle& src_rect, bool scale_by_half) override { } diff --git a/Source/Core/VideoBackends/OGL/TextureCache.cpp b/Source/Core/VideoBackends/OGL/TextureCache.cpp index 33130da5c8..3bf1342809 100644 --- a/Source/Core/VideoBackends/OGL/TextureCache.cpp +++ b/Source/Core/VideoBackends/OGL/TextureCache.cpp @@ -288,13 +288,12 @@ void TextureCache::TCacheEntry::FromRenderTarget(bool is_depth_copy, const EFBRe g_renderer->RestoreAPIState(); } -void TextureCache::CopyEFB(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, - u32 num_blocks_y, u32 memory_stride, bool is_depth_copy, - const EFBRectangle& srcRect, bool isIntensity, bool scaleByHalf) +void TextureCache::CopyEFB(u8* dst, const EFBCopyFormat& format, u32 native_width, + u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, + bool is_depth_copy, const EFBRectangle& src_rect, bool scale_by_half) { TextureConverter::EncodeToRamFromTexture(dst, format, native_width, bytes_per_row, num_blocks_y, - memory_stride, is_depth_copy, isIntensity, scaleByHalf, - srcRect); + memory_stride, is_depth_copy, src_rect, scale_by_half); } TextureCache::TextureCache() diff --git a/Source/Core/VideoBackends/OGL/TextureCache.h b/Source/Core/VideoBackends/OGL/TextureCache.h index cfd267caae..aece35cd6c 100644 --- a/Source/Core/VideoBackends/OGL/TextureCache.h +++ b/Source/Core/VideoBackends/OGL/TextureCache.h @@ -58,9 +58,9 @@ 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, bool is_depth_copy, const EFBRectangle& srcRect, bool isIntensity, - bool scaleByHalf) override; + void CopyEFB(u8* dst, const EFBCopyFormat& format, u32 native_width, u32 bytes_per_row, + u32 num_blocks_y, u32 memory_stride, bool is_depth_copy, + const EFBRectangle& src_rect, bool scale_by_half) override; bool CompileShaders() override; void DeleteShaders() override; diff --git a/Source/Core/VideoBackends/OGL/TextureConverter.cpp b/Source/Core/VideoBackends/OGL/TextureConverter.cpp index b54234710b..1a51d8fb09 100644 --- a/Source/Core/VideoBackends/OGL/TextureConverter.cpp +++ b/Source/Core/VideoBackends/OGL/TextureConverter.cpp @@ -45,10 +45,12 @@ static int s_rgbToYuyvUniform_loc; static SHADER s_yuyvToRgbProgram; -// Not all slots are taken - but who cares. -const u32 NUM_ENCODING_PROGRAMS = 64; -static SHADER s_encodingPrograms[NUM_ENCODING_PROGRAMS]; -static int s_encodingUniforms[NUM_ENCODING_PROGRAMS]; +struct EncodingProgram +{ + SHADER program; + GLint copy_position_uniform; +}; +static std::map s_encoding_programs; static GLuint s_PBO = 0; // for readback with different strides @@ -133,41 +135,37 @@ static void CreatePrograms() ProgramShaderCache::CompileShader(s_yuyvToRgbProgram, VProgramYuyvToRgb, FProgramYuyvToRgb); } -static SHADER& GetOrCreateEncodingShader(u32 format) +static EncodingProgram& GetOrCreateEncodingShader(const EFBCopyFormat& format) { - if (format >= NUM_ENCODING_PROGRAMS) - { - PanicAlert("Unknown texture copy format: 0x%x\n", format); - return s_encodingPrograms[0]; - } + auto iter = s_encoding_programs.find(format); + if (iter != s_encoding_programs.end()) + return iter->second; - if (s_encodingPrograms[format].glprogid == 0) - { - const char* shader = TextureConversionShader::GenerateEncodingShader(format, APIType::OpenGL); + const char* shader = TextureConversionShader::GenerateEncodingShader(format, APIType::OpenGL); #if defined(_DEBUG) || defined(DEBUGFAST) - if (g_ActiveConfig.iLog & CONF_SAVESHADERS && shader) - { - static int counter = 0; - std::string filename = - StringFromFormat("%senc_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), counter++); + if (g_ActiveConfig.iLog & CONF_SAVESHADERS && shader) + { + static int counter = 0; + std::string filename = + StringFromFormat("%senc_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), counter++); - SaveData(filename, shader); - } + SaveData(filename, shader); + } #endif - const char* VProgram = "void main()\n" - "{\n" - " vec2 rawpos = vec2(gl_VertexID&1, gl_VertexID&2);\n" - " gl_Position = vec4(rawpos*2.0-1.0, 0.0, 1.0);\n" - "}\n"; + const char* VProgram = "void main()\n" + "{\n" + " vec2 rawpos = vec2(gl_VertexID&1, gl_VertexID&2);\n" + " gl_Position = vec4(rawpos*2.0-1.0, 0.0, 1.0);\n" + "}\n"; - ProgramShaderCache::CompileShader(s_encodingPrograms[format], VProgram, shader); + EncodingProgram program; + if (!ProgramShaderCache::CompileShader(program.program, VProgram, shader)) + PanicAlert("Failed to compile texture encoding shader."); - s_encodingUniforms[format] = - glGetUniformLocation(s_encodingPrograms[format].glprogid, "position"); - } - return s_encodingPrograms[format]; + program.copy_position_uniform = glGetUniformLocation(program.program.glprogid, "position"); + return s_encoding_programs.emplace(format, program).first->second; } void Init() @@ -204,8 +202,9 @@ void Shutdown() s_rgbToYuyvProgram.Destroy(); s_yuyvToRgbProgram.Destroy(); - for (auto& program : s_encodingPrograms) - program.Destroy(); + for (auto& program : s_encoding_programs) + program.second.program.Destroy(); + s_encoding_programs.clear(); s_srcTexture = 0; s_dstTexture = 0; @@ -271,23 +270,24 @@ static void EncodeToRamUsingShader(GLuint srcTexture, u8* destAddr, u32 dst_line glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); } -void EncodeToRamFromTexture(u8* dest_ptr, u32 format, u32 native_width, u32 bytes_per_row, - u32 num_blocks_y, u32 memory_stride, bool is_depth_copy, - bool bIsIntensityFmt, int bScaleByHalf, const EFBRectangle& source) +void EncodeToRamFromTexture(u8* dest_ptr, const EFBCopyFormat& format, u32 native_width, + u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, + bool is_depth_copy, const EFBRectangle& src_rect, bool scale_by_half) { g_renderer->ResetAPIState(); - SHADER& texconv_shader = GetOrCreateEncodingShader(format); + EncodingProgram& texconv_shader = GetOrCreateEncodingShader(format); - texconv_shader.Bind(); - glUniform4i(s_encodingUniforms[format], source.left, source.top, native_width, - bScaleByHalf ? 2 : 1); + texconv_shader.program.Bind(); + glUniform4i(texconv_shader.copy_position_uniform, src_rect.left, src_rect.top, native_width, + scale_by_half ? 2 : 1); - const GLuint read_texture = is_depth_copy ? FramebufferManager::ResolveAndGetDepthTarget(source) : - FramebufferManager::ResolveAndGetRenderTarget(source); + const GLuint read_texture = is_depth_copy ? + FramebufferManager::ResolveAndGetDepthTarget(src_rect) : + FramebufferManager::ResolveAndGetRenderTarget(src_rect); EncodeToRamUsingShader(read_texture, dest_ptr, bytes_per_row, num_blocks_y, memory_stride, - bScaleByHalf > 0 && !is_depth_copy); + scale_by_half && !is_depth_copy); FramebufferManager::SetFramebuffer(0); g_renderer->RestoreAPIState(); diff --git a/Source/Core/VideoBackends/OGL/TextureConverter.h b/Source/Core/VideoBackends/OGL/TextureConverter.h index 8893ef1e52..11576f9aa1 100644 --- a/Source/Core/VideoBackends/OGL/TextureConverter.h +++ b/Source/Core/VideoBackends/OGL/TextureConverter.h @@ -7,6 +7,7 @@ #include "Common/CommonTypes.h" #include "Common/GL/GLUtil.h" +#include "VideoCommon/TextureDecoder.h" #include "VideoCommon/VideoCommon.h" namespace OGL @@ -24,9 +25,9 @@ void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc, u8* des 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, bool is_depth_copy, - bool bIsIntensityFmt, int bScaleByHalf, const EFBRectangle& source); +void EncodeToRamFromTexture(u8* dest_ptr, const EFBCopyFormat& format, u32 native_width, + u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, + bool is_depth_copy, const EFBRectangle& src_rect, bool scale_by_half); } } // namespace OGL diff --git a/Source/Core/VideoBackends/Software/SWmain.cpp b/Source/Core/VideoBackends/Software/SWmain.cpp index eb70f4059f..0f67c0e6fd 100644 --- a/Source/Core/VideoBackends/Software/SWmain.cpp +++ b/Source/Core/VideoBackends/Software/SWmain.cpp @@ -53,9 +53,9 @@ public: TlutFormat format) override { } - void CopyEFB(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, - u32 memory_stride, bool is_depth_copy, const EFBRectangle& srcRect, bool isIntensity, - bool scaleByHalf) override + void CopyEFB(u8* dst, const EFBCopyFormat& format, u32 native_width, u32 bytes_per_row, + u32 num_blocks_y, u32 memory_stride, bool is_depth_copy, + const EFBRectangle& src_rect, bool scale_by_half) override { EfbCopy::CopyEfb(); } diff --git a/Source/Core/VideoBackends/Vulkan/TextureCache.cpp b/Source/Core/VideoBackends/Vulkan/TextureCache.cpp index b951b78aa2..23cc06abff 100644 --- a/Source/Core/VideoBackends/Vulkan/TextureCache.cpp +++ b/Source/Core/VideoBackends/Vulkan/TextureCache.cpp @@ -88,9 +88,9 @@ void TextureCache::ConvertTexture(TCacheEntryBase* base_entry, TCacheEntryBase* m_texture_converter->ConvertTexture(entry, unconverted, m_render_pass, palette, format); } -void TextureCache::CopyEFB(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, - u32 num_blocks_y, u32 memory_stride, bool is_depth_copy, - const EFBRectangle& src_rect, bool is_intensity, bool scale_by_half) +void TextureCache::CopyEFB(u8* dst, const EFBCopyFormat& format, u32 native_width, + u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, + bool is_depth_copy, const EFBRectangle& src_rect, bool scale_by_half) { // Flush EFB pokes first, as they're expected to be included. FramebufferManager::GetInstance()->FlushEFBPokes(); @@ -120,7 +120,7 @@ void TextureCache::CopyEFB(u8* dst, u32 format, u32 native_width, u32 bytes_per_ m_texture_converter->EncodeTextureToMemory(src_texture->GetView(), dst, format, native_width, bytes_per_row, num_blocks_y, memory_stride, - is_depth_copy, is_intensity, scale_by_half, src_rect); + is_depth_copy, src_rect, scale_by_half); // Transition back to original state src_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), original_layout); diff --git a/Source/Core/VideoBackends/Vulkan/TextureCache.h b/Source/Core/VideoBackends/Vulkan/TextureCache.h index b433d7d9e0..5fd25c23d8 100644 --- a/Source/Core/VideoBackends/Vulkan/TextureCache.h +++ b/Source/Core/VideoBackends/Vulkan/TextureCache.h @@ -59,9 +59,9 @@ public: void ConvertTexture(TCacheEntryBase* base_entry, TCacheEntryBase* base_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, bool is_depth_copy, const EFBRectangle& src_rect, - bool is_intensity, bool scale_by_half) override; + void CopyEFB(u8* dst, const EFBCopyFormat& format, u32 native_width, u32 bytes_per_row, + u32 num_blocks_y, u32 memory_stride, bool is_depth_copy, + const EFBRectangle& src_rect, bool scale_by_half) override; void CopyRectangleFromTexture(TCacheEntry* dst_texture, const MathUtil::Rectangle& dst_rect, Texture2D* src_texture, const MathUtil::Rectangle& src_rect); diff --git a/Source/Core/VideoBackends/Vulkan/TextureConverter.cpp b/Source/Core/VideoBackends/Vulkan/TextureConverter.cpp index 7765647b1f..ca5ebe94bc 100644 --- a/Source/Core/VideoBackends/Vulkan/TextureConverter.cpp +++ b/Source/Core/VideoBackends/Vulkan/TextureConverter.cpp @@ -57,11 +57,8 @@ TextureConverter::~TextureConverter() if (m_encoding_render_framebuffer != VK_NULL_HANDLE) vkDestroyFramebuffer(g_vulkan_context->GetDevice(), m_encoding_render_framebuffer, nullptr); - for (VkShaderModule shader : m_encoding_shaders) - { - if (shader != VK_NULL_HANDLE) - vkDestroyShaderModule(g_vulkan_context->GetDevice(), shader, nullptr); - } + for (auto& it : m_encoding_shaders) + vkDestroyShaderModule(g_vulkan_context->GetDevice(), it.second, nullptr); for (const auto& it : m_decoding_pipelines) { @@ -89,12 +86,6 @@ bool TextureConverter::Initialize() return false; } - if (!CompileEncodingShaders()) - { - PanicAlert("Failed to compile texture encoding shaders"); - return false; - } - if (!CreateEncodingRenderPass()) { PanicAlert("Failed to create encode render pass"); @@ -221,15 +212,17 @@ void TextureConverter::ConvertTexture(TextureCache::TCacheEntry* dst_entry, draw.EndRenderPass(); } -void TextureConverter::EncodeTextureToMemory(VkImageView src_texture, u8* dest_ptr, u32 format, - u32 native_width, u32 bytes_per_row, u32 num_blocks_y, - u32 memory_stride, bool is_depth_copy, - bool is_intensity, int scale_by_half, - const EFBRectangle& src_rect) +void TextureConverter::EncodeTextureToMemory(VkImageView src_texture, u8* dest_ptr, + const EFBCopyFormat& format, u32 native_width, + u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, + bool is_depth_copy, const EFBRectangle& src_rect, + bool scale_by_half) { - if (m_encoding_shaders[format] == VK_NULL_HANDLE) + VkShaderModule shader = GetEncodingShader(format); + if (shader == VK_NULL_HANDLE) { - ERROR_LOG(VIDEO, "Missing encoding fragment shader for format %u", format); + ERROR_LOG(VIDEO, "Missing encoding fragment shader for format %u->%u", format.efb_format, + static_cast(format.copy_format)); return; } @@ -242,7 +235,7 @@ void TextureConverter::EncodeTextureToMemory(VkImageView src_texture, u8* dest_p UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentCommandBuffer(), g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_PUSH_CONSTANT), m_encoding_render_pass, g_object_cache->GetScreenQuadVertexShader(), - VK_NULL_HANDLE, m_encoding_shaders[format]); + VK_NULL_HANDLE, shader); // Uniform - int4 of left,top,native_width,scale s32 position_uniform[4] = {src_rect.left, src_rect.top, static_cast(native_width), @@ -681,24 +674,25 @@ bool TextureConverter::CompilePaletteConversionShaders() m_palette_conversion_shaders[GX_TL_RGB5A3] != VK_NULL_HANDLE; } -bool TextureConverter::CompileEncodingShaders() +VkShaderModule TextureConverter::CompileEncodingShader(const EFBCopyFormat& format) { - // Texture encoding shaders - static const u32 texture_encoding_shader_formats[] = { - GX_TF_I4, GX_TF_I8, GX_TF_IA4, GX_TF_IA8, GX_TF_RGB565, GX_TF_RGB5A3, GX_TF_RGBA8, - GX_CTF_R4, GX_CTF_RA4, GX_CTF_RA8, GX_CTF_A8, GX_CTF_R8, GX_CTF_G8, GX_CTF_B8, - GX_CTF_RG8, GX_CTF_GB8, GX_CTF_Z8H, GX_TF_Z8, GX_CTF_Z16R, GX_TF_Z16, GX_TF_Z24X8, - GX_CTF_Z4, GX_CTF_Z8M, GX_CTF_Z8L, GX_CTF_Z16L}; - for (u32 format : texture_encoding_shader_formats) - { - const char* shader_source = - TextureConversionShader::GenerateEncodingShader(format, APIType::Vulkan); - m_encoding_shaders[format] = Util::CompileAndCreateFragmentShader(shader_source); - if (m_encoding_shaders[format] == VK_NULL_HANDLE) - return false; - } + const char* shader = TextureConversionShader::GenerateEncodingShader(format, APIType::Vulkan); + VkShaderModule module = Util::CompileAndCreateFragmentShader(shader); + if (module == VK_NULL_HANDLE) + PanicAlert("Failed to compile texture encoding shader."); - return true; + return module; +} + +VkShaderModule TextureConverter::GetEncodingShader(const EFBCopyFormat& format) +{ + auto iter = m_encoding_shaders.find(format); + if (iter != m_encoding_shaders.end()) + return iter->second; + + VkShaderModule shader = CompileEncodingShader(format); + m_encoding_shaders.emplace(format, shader); + return shader; } bool TextureConverter::CreateEncodingRenderPass() diff --git a/Source/Core/VideoBackends/Vulkan/TextureConverter.h b/Source/Core/VideoBackends/Vulkan/TextureConverter.h index 39543e0f17..a139f1eab9 100644 --- a/Source/Core/VideoBackends/Vulkan/TextureConverter.h +++ b/Source/Core/VideoBackends/Vulkan/TextureConverter.h @@ -35,10 +35,10 @@ public: // Uses an encoding shader to copy src_texture to dest_ptr. // NOTE: Executes the current command buffer. - void EncodeTextureToMemory(VkImageView src_texture, u8* dest_ptr, u32 format, u32 native_width, - u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, - bool is_depth_copy, bool is_intensity, int scale_by_half, - const EFBRectangle& source); + void EncodeTextureToMemory(VkImageView src_texture, u8* dest_ptr, const EFBCopyFormat& format, + u32 native_width, u32 bytes_per_row, u32 num_blocks_y, + u32 memory_stride, bool is_depth_copy, const EFBRectangle& src_rect, + bool scale_by_half); // Encodes texture to guest memory in XFB (YUYV) format. void EncodeTextureToMemoryYUYV(void* dst_ptr, u32 dst_width, u32 dst_stride, u32 dst_height, @@ -55,7 +55,6 @@ public: TlutFormat palette_format); private: - static const u32 NUM_TEXTURE_ENCODING_SHADERS = 64; static const u32 ENCODING_TEXTURE_WIDTH = EFB_WIDTH * 4; static const u32 ENCODING_TEXTURE_HEIGHT = 1024; static const VkFormat ENCODING_TEXTURE_FORMAT = VK_FORMAT_B8G8R8A8_UNORM; @@ -70,7 +69,9 @@ private: bool CompilePaletteConversionShaders(); - bool CompileEncodingShaders(); + VkShaderModule CompileEncodingShader(const EFBCopyFormat& format); + VkShaderModule GetEncodingShader(const EFBCopyFormat& format); + bool CreateEncodingRenderPass(); bool CreateEncodingTexture(); bool CreateEncodingDownloadTexture(); @@ -102,7 +103,7 @@ private: std::array m_palette_conversion_shaders = {}; // Texture encoding - RGBA8->GX format in memory - std::array m_encoding_shaders = {}; + std::map m_encoding_shaders; VkRenderPass m_encoding_render_pass = VK_NULL_HANDLE; std::unique_ptr m_encoding_render_texture; VkFramebuffer m_encoding_render_framebuffer = VK_NULL_HANDLE; diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index c12c53be27..89d473cfec 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -969,7 +969,8 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFo ColorMask[0] = ColorMask[1] = ColorMask[2] = ColorMask[3] = 255.0f; ColorMask[4] = ColorMask[5] = ColorMask[6] = ColorMask[7] = 1.0f / 255.0f; unsigned int cbufid = -1; - bool efbHasAlpha = bpmem.zcontrol.pixel_format == PEControl::RGBA6_Z24; + u32 srcFormat = bpmem.zcontrol.pixel_format; + bool efbHasAlpha = srcFormat == PEControl::RGBA6_Z24; if (is_depth_copy) { @@ -1278,8 +1279,9 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFo if (copy_to_ram) { - CopyEFB(dst, dstFormat, tex_w, bytes_per_row, num_blocks_y, dstStride, is_depth_copy, srcRect, - isIntensity, scaleByHalf); + EFBCopyFormat format(srcFormat, static_cast(dstFormat)); + CopyEFB(dst, format, tex_w, bytes_per_row, num_blocks_y, dstStride, is_depth_copy, srcRect, + scaleByHalf); } else { diff --git a/Source/Core/VideoCommon/TextureCacheBase.h b/Source/Core/VideoCommon/TextureCacheBase.h index 3000491924..4c9582079b 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.h +++ b/Source/Core/VideoCommon/TextureCacheBase.h @@ -154,9 +154,9 @@ 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, bool is_depth_copy, const EFBRectangle& srcRect, - bool isIntensity, bool scaleByHalf) = 0; + virtual void CopyEFB(u8* dst, const EFBCopyFormat& format, u32 native_width, u32 bytes_per_row, + u32 num_blocks_y, u32 memory_stride, bool is_depth_copy, + const EFBRectangle& src_rect, bool scale_by_half) = 0; virtual bool CompileShaders() = 0; virtual void DeleteShaders() = 0;