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..1bc173d4ee 100644 --- a/Source/Core/VideoBackends/Vulkan/TextureConverter.cpp +++ b/Source/Core/VideoBackends/Vulkan/TextureConverter.cpp @@ -27,6 +27,7 @@ #include "VideoCommon/TextureConversionShader.h" #include "VideoCommon/TextureDecoder.h" +#include "VideoCommon/VideoConfig.h" namespace Vulkan { @@ -57,11 +58,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 +87,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 +213,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,17 +236,19 @@ 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), scale_by_half ? 2 : 1}; draw.SetPushConstants(position_uniform, sizeof(position_uniform)); - // Doesn't make sense to linear filter depth values - draw.SetPSSampler(0, src_texture, (scale_by_half && !is_depth_copy) ? - g_object_cache->GetLinearSampler() : - g_object_cache->GetPointSampler()); + // We also linear filtering for both box filtering and downsampling higher resolutions to 1x + // 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. + bool linear_filter = (scale_by_half && !is_depth_copy) || g_ActiveConfig.iEFBScale != SCALE_1X; + draw.SetPSSampler(0, src_texture, linear_filter ? g_object_cache->GetLinearSampler() : + g_object_cache->GetPointSampler()); u32 render_width = bytes_per_row / sizeof(u32); u32 render_height = num_blocks_y; @@ -681,24 +677,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; diff --git a/Source/Core/VideoCommon/TextureConversionShader.cpp b/Source/Core/VideoCommon/TextureConversionShader.cpp index 833d2a7840..d22ade97c7 100644 --- a/Source/Core/VideoCommon/TextureConversionShader.cpp +++ b/Source/Core/VideoCommon/TextureConversionShader.cpp @@ -14,7 +14,6 @@ #include "Common/MsgHandler.h" #include "VideoCommon/RenderBase.h" #include "VideoCommon/TextureConversionShader.h" -#include "VideoCommon/TextureDecoder.h" #include "VideoCommon/VideoCommon.h" #define WRITE p += sprintf @@ -79,6 +78,11 @@ u16 GetEncodedSampleCount(u32 format) } } +static bool EFBFormatHasAlpha(u32 format) +{ + return format == PEControl::RGBA6_Z24; +} + // block dimensions : widthStride, heightStride // texture dims : width, height, x offset, y offset static void WriteSwizzler(char*& p, u32 format, APIType ApiType) @@ -162,7 +166,7 @@ static void WriteSwizzler(char*& p, u32 format, APIType ApiType) } static void WriteSampleColor(char*& p, const char* colorComp, const char* dest, int xoffset, - APIType ApiType, bool depth = false) + APIType ApiType, const EFBCopyFormat& format, bool depth) { if (ApiType == APIType::OpenGL || ApiType == APIType::Vulkan) { @@ -181,6 +185,25 @@ static void WriteSampleColor(char*& p, const char* colorComp, const char* dest, if (depth) WRITE(p, " %s = 1.0 - %s;\n", dest, dest); } + + // Truncate 8-bits to 5/6-bits per channel. + switch (format.efb_format) + { + case PEControl::RGBA6_Z24: + WRITE(p, " %s = floor(%s * 63.0) / 63.0;\n", dest, dest); + break; + + case PEControl::RGB565_Z16: + WRITE( + p, + " %s = floor(%s * float4(31.0, 63.0, 31.0, 1.0).%s) / float4(31.0, 63.0, 31.0, 1.0).%s;\n", + dest, dest, colorComp, colorComp); + break; + } + + // Alpha channel is set to 1 in the copy if the EFB does not have an alpha channel. + if (std::strchr(colorComp, 'a') && !EFBFormatHasAlpha(format.efb_format)) + WRITE(p, " %s.a = 1.0;\n", dest); } static void WriteColorToIntensity(char*& p, const char* src, const char* dest) @@ -206,21 +229,21 @@ static void WriteEncoderEnd(char*& p) IntensityConstantAdded = false; } -static void WriteI8Encoder(char*& p, APIType ApiType) +static void WriteI8Encoder(char*& p, APIType ApiType, const EFBCopyFormat& format) { WriteSwizzler(p, GX_TF_I8, ApiType); WRITE(p, " float3 texSample;\n"); - WriteSampleColor(p, "rgb", "texSample", 0, ApiType); + WriteSampleColor(p, "rgb", "texSample", 0, ApiType, format, false); WriteColorToIntensity(p, "texSample", "ocol0.b"); - WriteSampleColor(p, "rgb", "texSample", 1, ApiType); + WriteSampleColor(p, "rgb", "texSample", 1, ApiType, format, false); WriteColorToIntensity(p, "texSample", "ocol0.g"); - WriteSampleColor(p, "rgb", "texSample", 2, ApiType); + WriteSampleColor(p, "rgb", "texSample", 2, ApiType, format, false); WriteColorToIntensity(p, "texSample", "ocol0.r"); - WriteSampleColor(p, "rgb", "texSample", 3, ApiType); + WriteSampleColor(p, "rgb", "texSample", 3, ApiType, format, false); WriteColorToIntensity(p, "texSample", "ocol0.a"); WRITE(p, " ocol0.rgba += IntensityConst.aaaa;\n"); // see WriteColorToIntensity @@ -228,35 +251,35 @@ static void WriteI8Encoder(char*& p, APIType ApiType) WriteEncoderEnd(p); } -static void WriteI4Encoder(char*& p, APIType ApiType) +static void WriteI4Encoder(char*& p, APIType ApiType, const EFBCopyFormat& format) { WriteSwizzler(p, GX_TF_I4, ApiType); WRITE(p, " float3 texSample;\n"); WRITE(p, " float4 color0;\n"); WRITE(p, " float4 color1;\n"); - WriteSampleColor(p, "rgb", "texSample", 0, ApiType); + WriteSampleColor(p, "rgb", "texSample", 0, ApiType, format, false); WriteColorToIntensity(p, "texSample", "color0.b"); - WriteSampleColor(p, "rgb", "texSample", 1, ApiType); + WriteSampleColor(p, "rgb", "texSample", 1, ApiType, format, false); WriteColorToIntensity(p, "texSample", "color1.b"); - WriteSampleColor(p, "rgb", "texSample", 2, ApiType); + WriteSampleColor(p, "rgb", "texSample", 2, ApiType, format, false); WriteColorToIntensity(p, "texSample", "color0.g"); - WriteSampleColor(p, "rgb", "texSample", 3, ApiType); + WriteSampleColor(p, "rgb", "texSample", 3, ApiType, format, false); WriteColorToIntensity(p, "texSample", "color1.g"); - WriteSampleColor(p, "rgb", "texSample", 4, ApiType); + WriteSampleColor(p, "rgb", "texSample", 4, ApiType, format, false); WriteColorToIntensity(p, "texSample", "color0.r"); - WriteSampleColor(p, "rgb", "texSample", 5, ApiType); + WriteSampleColor(p, "rgb", "texSample", 5, ApiType, format, false); WriteColorToIntensity(p, "texSample", "color1.r"); - WriteSampleColor(p, "rgb", "texSample", 6, ApiType); + WriteSampleColor(p, "rgb", "texSample", 6, ApiType, format, false); WriteColorToIntensity(p, "texSample", "color0.a"); - WriteSampleColor(p, "rgb", "texSample", 7, ApiType); + WriteSampleColor(p, "rgb", "texSample", 7, ApiType, format, false); WriteColorToIntensity(p, "texSample", "color1.a"); WRITE(p, " color0.rgba += IntensityConst.aaaa;\n"); @@ -269,16 +292,16 @@ static void WriteI4Encoder(char*& p, APIType ApiType) WriteEncoderEnd(p); } -static void WriteIA8Encoder(char*& p, APIType ApiType) +static void WriteIA8Encoder(char*& p, APIType ApiType, const EFBCopyFormat& format) { WriteSwizzler(p, GX_TF_IA8, ApiType); WRITE(p, " float4 texSample;\n"); - WriteSampleColor(p, "rgba", "texSample", 0, ApiType); + WriteSampleColor(p, "rgba", "texSample", 0, ApiType, format, false); WRITE(p, " ocol0.b = texSample.a;\n"); WriteColorToIntensity(p, "texSample", "ocol0.g"); - WriteSampleColor(p, "rgba", "texSample", 1, ApiType); + WriteSampleColor(p, "rgba", "texSample", 1, ApiType, format, false); WRITE(p, " ocol0.r = texSample.a;\n"); WriteColorToIntensity(p, "texSample", "ocol0.a"); @@ -287,26 +310,26 @@ static void WriteIA8Encoder(char*& p, APIType ApiType) WriteEncoderEnd(p); } -static void WriteIA4Encoder(char*& p, APIType ApiType) +static void WriteIA4Encoder(char*& p, APIType ApiType, const EFBCopyFormat& format) { WriteSwizzler(p, GX_TF_IA4, ApiType); WRITE(p, " float4 texSample;\n"); WRITE(p, " float4 color0;\n"); WRITE(p, " float4 color1;\n"); - WriteSampleColor(p, "rgba", "texSample", 0, ApiType); + WriteSampleColor(p, "rgba", "texSample", 0, ApiType, format, false); WRITE(p, " color0.b = texSample.a;\n"); WriteColorToIntensity(p, "texSample", "color1.b"); - WriteSampleColor(p, "rgba", "texSample", 1, ApiType); + WriteSampleColor(p, "rgba", "texSample", 1, ApiType, format, false); WRITE(p, " color0.g = texSample.a;\n"); WriteColorToIntensity(p, "texSample", "color1.g"); - WriteSampleColor(p, "rgba", "texSample", 2, ApiType); + WriteSampleColor(p, "rgba", "texSample", 2, ApiType, format, false); WRITE(p, " color0.r = texSample.a;\n"); WriteColorToIntensity(p, "texSample", "color1.r"); - WriteSampleColor(p, "rgba", "texSample", 3, ApiType); + WriteSampleColor(p, "rgba", "texSample", 3, ApiType, format, false); WRITE(p, " color0.a = texSample.a;\n"); WriteColorToIntensity(p, "texSample", "color1.a"); @@ -319,12 +342,12 @@ static void WriteIA4Encoder(char*& p, APIType ApiType) WriteEncoderEnd(p); } -static void WriteRGB565Encoder(char*& p, APIType ApiType) +static void WriteRGB565Encoder(char*& p, APIType ApiType, const EFBCopyFormat& format) { WriteSwizzler(p, GX_TF_RGB565, ApiType); - WriteSampleColor(p, "rgb", "float3 texSample0", 0, ApiType); - WriteSampleColor(p, "rgb", "float3 texSample1", 1, ApiType); + WriteSampleColor(p, "rgb", "float3 texSample0", 0, ApiType, format, false); + WriteSampleColor(p, "rgb", "float3 texSample1", 1, ApiType, format, false); WRITE(p, " float2 texRs = float2(texSample0.r, texSample1.r);\n"); WRITE(p, " float2 texGs = float2(texSample0.g, texSample1.g);\n"); WRITE(p, " float2 texBs = float2(texSample0.b, texSample1.b);\n"); @@ -342,7 +365,7 @@ static void WriteRGB565Encoder(char*& p, APIType ApiType) WriteEncoderEnd(p); } -static void WriteRGB5A3Encoder(char*& p, APIType ApiType) +static void WriteRGB5A3Encoder(char*& p, APIType ApiType, const EFBCopyFormat& format) { WriteSwizzler(p, GX_TF_RGB5A3, ApiType); @@ -351,7 +374,7 @@ static void WriteRGB5A3Encoder(char*& p, APIType ApiType) WRITE(p, " float gUpper;\n"); WRITE(p, " float gLower;\n"); - WriteSampleColor(p, "rgba", "texSample", 0, ApiType); + WriteSampleColor(p, "rgba", "texSample", 0, ApiType, format, false); // 0.8784 = 224 / 255 which is the maximum alpha value that can be represented in 3 bits WRITE(p, "if(texSample.a > 0.878f) {\n"); @@ -377,7 +400,8 @@ static void WriteRGB5A3Encoder(char*& p, APIType ApiType) WRITE(p, "}\n"); - WriteSampleColor(p, "rgba", "texSample", 1, ApiType); + WriteSampleColor(p, "rgba", "texSample", 1, ApiType, format, false); + WRITE(p, " texSample.a = 1.0;\n"); WRITE(p, "if(texSample.a > 0.878f) {\n"); @@ -406,7 +430,7 @@ static void WriteRGB5A3Encoder(char*& p, APIType ApiType) WriteEncoderEnd(p); } -static void WriteRGBA8Encoder(char*& p, APIType ApiType) +static void WriteRGBA8Encoder(char*& p, APIType ApiType, const EFBCopyFormat& format) { WriteSwizzler(p, GX_TF_RGBA8, ApiType); @@ -414,13 +438,13 @@ static void WriteRGBA8Encoder(char*& p, APIType ApiType) WRITE(p, " float4 color0;\n"); WRITE(p, " float4 color1;\n"); - WriteSampleColor(p, "rgba", "texSample", 0, ApiType); + WriteSampleColor(p, "rgba", "texSample", 0, ApiType, format, false); WRITE(p, " color0.b = texSample.a;\n"); WRITE(p, " color0.g = texSample.r;\n"); WRITE(p, " color1.b = texSample.g;\n"); WRITE(p, " color1.g = texSample.b;\n"); - WriteSampleColor(p, "rgba", "texSample", 1, ApiType); + WriteSampleColor(p, "rgba", "texSample", 1, ApiType, format, false); WRITE(p, " color0.r = texSample.a;\n"); WRITE(p, " color0.a = texSample.r;\n"); WRITE(p, " color1.r = texSample.g;\n"); @@ -431,20 +455,21 @@ static void WriteRGBA8Encoder(char*& p, APIType ApiType) WriteEncoderEnd(p); } -static void WriteC4Encoder(char*& p, const char* comp, APIType ApiType, bool depth = false) +static void WriteC4Encoder(char*& p, const char* comp, APIType ApiType, const EFBCopyFormat& format, + bool depth) { WriteSwizzler(p, GX_CTF_R4, ApiType); WRITE(p, " float4 color0;\n"); WRITE(p, " float4 color1;\n"); - WriteSampleColor(p, comp, "color0.b", 0, ApiType, depth); - WriteSampleColor(p, comp, "color1.b", 1, ApiType, depth); - WriteSampleColor(p, comp, "color0.g", 2, ApiType, depth); - WriteSampleColor(p, comp, "color1.g", 3, ApiType, depth); - WriteSampleColor(p, comp, "color0.r", 4, ApiType, depth); - WriteSampleColor(p, comp, "color1.r", 5, ApiType, depth); - WriteSampleColor(p, comp, "color0.a", 6, ApiType, depth); - WriteSampleColor(p, comp, "color1.a", 7, ApiType, depth); + WriteSampleColor(p, comp, "color0.b", 0, ApiType, format, depth); + WriteSampleColor(p, comp, "color1.b", 1, ApiType, format, depth); + WriteSampleColor(p, comp, "color0.g", 2, ApiType, format, depth); + WriteSampleColor(p, comp, "color1.g", 3, ApiType, format, depth); + WriteSampleColor(p, comp, "color0.r", 4, ApiType, format, depth); + WriteSampleColor(p, comp, "color1.r", 5, ApiType, format, depth); + WriteSampleColor(p, comp, "color0.a", 6, ApiType, format, depth); + WriteSampleColor(p, comp, "color1.a", 7, ApiType, format, depth); WriteToBitDepth(p, 4, "color0", "color0"); WriteToBitDepth(p, 4, "color1", "color1"); @@ -453,38 +478,40 @@ static void WriteC4Encoder(char*& p, const char* comp, APIType ApiType, bool dep WriteEncoderEnd(p); } -static void WriteC8Encoder(char*& p, const char* comp, APIType ApiType, bool depth = false) +static void WriteC8Encoder(char*& p, const char* comp, APIType ApiType, const EFBCopyFormat& format, + bool depth) { WriteSwizzler(p, GX_CTF_R8, ApiType); - WriteSampleColor(p, comp, "ocol0.b", 0, ApiType, depth); - WriteSampleColor(p, comp, "ocol0.g", 1, ApiType, depth); - WriteSampleColor(p, comp, "ocol0.r", 2, ApiType, depth); - WriteSampleColor(p, comp, "ocol0.a", 3, ApiType, depth); + WriteSampleColor(p, comp, "ocol0.b", 0, ApiType, format, depth); + WriteSampleColor(p, comp, "ocol0.g", 1, ApiType, format, depth); + WriteSampleColor(p, comp, "ocol0.r", 2, ApiType, format, depth); + WriteSampleColor(p, comp, "ocol0.a", 3, ApiType, format, depth); WriteEncoderEnd(p); } -static void WriteCC4Encoder(char*& p, const char* comp, APIType ApiType) +static void WriteCC4Encoder(char*& p, const char* comp, APIType ApiType, + const EFBCopyFormat& format) { WriteSwizzler(p, GX_CTF_RA4, ApiType); WRITE(p, " float2 texSample;\n"); WRITE(p, " float4 color0;\n"); WRITE(p, " float4 color1;\n"); - WriteSampleColor(p, comp, "texSample", 0, ApiType); + WriteSampleColor(p, comp, "texSample", 0, ApiType, format, false); WRITE(p, " color0.b = texSample.x;\n"); WRITE(p, " color1.b = texSample.y;\n"); - WriteSampleColor(p, comp, "texSample", 1, ApiType); + WriteSampleColor(p, comp, "texSample", 1, ApiType, format, false); WRITE(p, " color0.g = texSample.x;\n"); WRITE(p, " color1.g = texSample.y;\n"); - WriteSampleColor(p, comp, "texSample", 2, ApiType); + WriteSampleColor(p, comp, "texSample", 2, ApiType, format, false); WRITE(p, " color0.r = texSample.x;\n"); WRITE(p, " color1.r = texSample.y;\n"); - WriteSampleColor(p, comp, "texSample", 3, ApiType); + WriteSampleColor(p, comp, "texSample", 3, ApiType, format, false); WRITE(p, " color0.a = texSample.x;\n"); WRITE(p, " color1.a = texSample.y;\n"); @@ -495,38 +522,40 @@ static void WriteCC4Encoder(char*& p, const char* comp, APIType ApiType) WriteEncoderEnd(p); } -static void WriteCC8Encoder(char*& p, const char* comp, APIType ApiType) +static void WriteCC8Encoder(char*& p, const char* comp, APIType ApiType, + const EFBCopyFormat& format) { WriteSwizzler(p, GX_CTF_RA8, ApiType); - WriteSampleColor(p, comp, "ocol0.bg", 0, ApiType); - WriteSampleColor(p, comp, "ocol0.ra", 1, ApiType); + WriteSampleColor(p, comp, "ocol0.bg", 0, ApiType, format, false); + WriteSampleColor(p, comp, "ocol0.ra", 1, ApiType, format, false); WriteEncoderEnd(p); } -static void WriteZ8Encoder(char*& p, const char* multiplier, APIType ApiType) +static void WriteZ8Encoder(char*& p, const char* multiplier, APIType ApiType, + const EFBCopyFormat& format) { WriteSwizzler(p, GX_CTF_Z8M, ApiType); WRITE(p, " float depth;\n"); - WriteSampleColor(p, "r", "depth", 0, ApiType, true); + WriteSampleColor(p, "r", "depth", 0, ApiType, format, true); WRITE(p, "ocol0.b = frac(depth * %s);\n", multiplier); - WriteSampleColor(p, "r", "depth", 1, ApiType, true); + WriteSampleColor(p, "r", "depth", 1, ApiType, format, true); WRITE(p, "ocol0.g = frac(depth * %s);\n", multiplier); - WriteSampleColor(p, "r", "depth", 2, ApiType, true); + WriteSampleColor(p, "r", "depth", 2, ApiType, format, true); WRITE(p, "ocol0.r = frac(depth * %s);\n", multiplier); - WriteSampleColor(p, "r", "depth", 3, ApiType, true); + WriteSampleColor(p, "r", "depth", 3, ApiType, format, true); WRITE(p, "ocol0.a = frac(depth * %s);\n", multiplier); WriteEncoderEnd(p); } -static void WriteZ16Encoder(char*& p, APIType ApiType) +static void WriteZ16Encoder(char*& p, APIType ApiType, const EFBCopyFormat& format) { WriteSwizzler(p, GX_TF_Z16, ApiType); @@ -535,7 +564,7 @@ static void WriteZ16Encoder(char*& p, APIType ApiType) // byte order is reversed - WriteSampleColor(p, "r", "depth", 0, ApiType, true); + WriteSampleColor(p, "r", "depth", 0, ApiType, format, true); WRITE(p, " depth *= 16777216.0;\n"); WRITE(p, " expanded.r = floor(depth / (256.0 * 256.0));\n"); @@ -545,7 +574,7 @@ static void WriteZ16Encoder(char*& p, APIType ApiType) WRITE(p, " ocol0.b = expanded.g / 255.0;\n"); WRITE(p, " ocol0.g = expanded.r / 255.0;\n"); - WriteSampleColor(p, "r", "depth", 1, ApiType, true); + WriteSampleColor(p, "r", "depth", 1, ApiType, format, true); WRITE(p, " depth *= 16777216.0;\n"); WRITE(p, " expanded.r = floor(depth / (256.0 * 256.0));\n"); @@ -558,7 +587,7 @@ static void WriteZ16Encoder(char*& p, APIType ApiType) WriteEncoderEnd(p); } -static void WriteZ16LEncoder(char*& p, APIType ApiType) +static void WriteZ16LEncoder(char*& p, APIType ApiType, const EFBCopyFormat& format) { WriteSwizzler(p, GX_CTF_Z16L, ApiType); @@ -567,7 +596,7 @@ static void WriteZ16LEncoder(char*& p, APIType ApiType) // byte order is reversed - WriteSampleColor(p, "r", "depth", 0, ApiType, true); + WriteSampleColor(p, "r", "depth", 0, ApiType, format, true); WRITE(p, " depth *= 16777216.0;\n"); WRITE(p, " expanded.r = floor(depth / (256.0 * 256.0));\n"); @@ -579,7 +608,7 @@ static void WriteZ16LEncoder(char*& p, APIType ApiType) WRITE(p, " ocol0.b = expanded.b / 255.0;\n"); WRITE(p, " ocol0.g = expanded.g / 255.0;\n"); - WriteSampleColor(p, "r", "depth", 1, ApiType, true); + WriteSampleColor(p, "r", "depth", 1, ApiType, format, true); WRITE(p, " depth *= 16777216.0;\n"); WRITE(p, " expanded.r = floor(depth / (256.0 * 256.0));\n"); @@ -594,7 +623,7 @@ static void WriteZ16LEncoder(char*& p, APIType ApiType) WriteEncoderEnd(p); } -static void WriteZ24Encoder(char*& p, APIType ApiType) +static void WriteZ24Encoder(char*& p, APIType ApiType, const EFBCopyFormat& format) { WriteSwizzler(p, GX_TF_Z24X8, ApiType); @@ -603,8 +632,8 @@ static void WriteZ24Encoder(char*& p, APIType ApiType) WRITE(p, " float3 expanded0;\n"); WRITE(p, " float3 expanded1;\n"); - WriteSampleColor(p, "r", "depth0", 0, ApiType, true); - WriteSampleColor(p, "r", "depth1", 1, ApiType, true); + WriteSampleColor(p, "r", "depth0", 0, ApiType, format, true); + WriteSampleColor(p, "r", "depth1", 1, ApiType, format, true); for (int i = 0; i < 2; i++) { @@ -634,87 +663,87 @@ static void WriteZ24Encoder(char*& p, APIType ApiType) WriteEncoderEnd(p); } -const char* GenerateEncodingShader(u32 format, APIType ApiType) +const char* GenerateEncodingShader(const EFBCopyFormat& format, APIType api_type) { text[sizeof(text) - 1] = 0x7C; // canary char* p = text; - switch (format) + switch (format.copy_format) { case GX_TF_I4: - WriteI4Encoder(p, ApiType); + WriteI4Encoder(p, api_type, format); break; case GX_TF_I8: - WriteI8Encoder(p, ApiType); + WriteI8Encoder(p, api_type, format); break; case GX_TF_IA4: - WriteIA4Encoder(p, ApiType); + WriteIA4Encoder(p, api_type, format); break; case GX_TF_IA8: - WriteIA8Encoder(p, ApiType); + WriteIA8Encoder(p, api_type, format); break; case GX_TF_RGB565: - WriteRGB565Encoder(p, ApiType); + WriteRGB565Encoder(p, api_type, format); break; case GX_TF_RGB5A3: - WriteRGB5A3Encoder(p, ApiType); + WriteRGB5A3Encoder(p, api_type, format); break; case GX_TF_RGBA8: - WriteRGBA8Encoder(p, ApiType); + WriteRGBA8Encoder(p, api_type, format); break; case GX_CTF_R4: - WriteC4Encoder(p, "r", ApiType); + WriteC4Encoder(p, "r", api_type, format, false); break; case GX_CTF_RA4: - WriteCC4Encoder(p, "ar", ApiType); + WriteCC4Encoder(p, "ar", api_type, format); break; case GX_CTF_RA8: - WriteCC8Encoder(p, "ar", ApiType); + WriteCC8Encoder(p, "ar", api_type, format); break; case GX_CTF_A8: - WriteC8Encoder(p, "a", ApiType); + WriteC8Encoder(p, "a", api_type, format, false); break; case GX_CTF_R8: - WriteC8Encoder(p, "r", ApiType); + WriteC8Encoder(p, "r", api_type, format, false); break; case GX_CTF_G8: - WriteC8Encoder(p, "g", ApiType); + WriteC8Encoder(p, "g", api_type, format, false); break; case GX_CTF_B8: - WriteC8Encoder(p, "b", ApiType); + WriteC8Encoder(p, "b", api_type, format, false); break; case GX_CTF_RG8: - WriteCC8Encoder(p, "rg", ApiType); + WriteCC8Encoder(p, "rg", api_type, format); break; case GX_CTF_GB8: - WriteCC8Encoder(p, "gb", ApiType); + WriteCC8Encoder(p, "gb", api_type, format); break; case GX_CTF_Z8H: case GX_TF_Z8: - WriteC8Encoder(p, "r", ApiType, true); + WriteC8Encoder(p, "r", api_type, format, true); break; case GX_CTF_Z16R: case GX_TF_Z16: - WriteZ16Encoder(p, ApiType); + WriteZ16Encoder(p, api_type, format); break; case GX_TF_Z24X8: - WriteZ24Encoder(p, ApiType); + WriteZ24Encoder(p, api_type, format); break; case GX_CTF_Z4: - WriteC4Encoder(p, "r", ApiType, true); + WriteC4Encoder(p, "r", api_type, format, true); break; case GX_CTF_Z8M: - WriteZ8Encoder(p, "256.0", ApiType); + WriteZ8Encoder(p, "256.0", api_type, format); break; case GX_CTF_Z8L: - WriteZ8Encoder(p, "65536.0", ApiType); + WriteZ8Encoder(p, "65536.0", api_type, format); break; case GX_CTF_Z16L: - WriteZ16LEncoder(p, ApiType); + WriteZ16LEncoder(p, api_type, format); break; default: - PanicAlert("Unknown texture copy format: 0x%x\n", format); + PanicAlert("Unknown texture copy format: 0x%x\n", static_cast(format.copy_format)); break; } @@ -1219,9 +1248,9 @@ static const std::array s_buffer_bytes_per_texel = {{ 8, // BUFFER_FORMAT_R32G32_UINT }}; -const DecodingShaderInfo* GetDecodingShaderInfo(u32 format) +const DecodingShaderInfo* GetDecodingShaderInfo(TextureFormat format) { - auto iter = s_decoding_shader_info.find(static_cast(format)); + auto iter = s_decoding_shader_info.find(format); return iter != s_decoding_shader_info.end() ? &iter->second : nullptr; } @@ -1240,7 +1269,8 @@ std::pair GetDispatchCount(const DecodingShaderInfo* info, u32 width, (height + (info->group_size_y - 1)) / info->group_size_y}; } -std::string GenerateDecodingShader(u32 format, u32 palette_format, APIType api_type) +std::string GenerateDecodingShader(TextureFormat format, TlutFormat palette_format, + APIType api_type) { const DecodingShaderInfo* info = GetDecodingShaderInfo(format); if (!info) diff --git a/Source/Core/VideoCommon/TextureConversionShader.h b/Source/Core/VideoCommon/TextureConversionShader.h index cc65a2d201..abcd765245 100644 --- a/Source/Core/VideoCommon/TextureConversionShader.h +++ b/Source/Core/VideoCommon/TextureConversionShader.h @@ -8,6 +8,7 @@ #include #include "Common/CommonTypes.h" +#include "VideoCommon/TextureDecoder.h" enum class APIType; @@ -15,7 +16,7 @@ namespace TextureConversionShader { u16 GetEncodedSampleCount(u32 format); -const char* GenerateEncodingShader(u32 format, APIType ApiType); +const char* GenerateEncodingShader(const EFBCopyFormat& format, APIType ApiType); // View format of the input data to the texture decoding shader. enum BufferFormat @@ -39,7 +40,7 @@ struct DecodingShaderInfo // Obtain shader information for the specified texture format. // If this format does not have a shader written for it, returns nullptr. -const DecodingShaderInfo* GetDecodingShaderInfo(u32 format); +const DecodingShaderInfo* GetDecodingShaderInfo(TextureFormat format); // Determine how many bytes there are in each element of the texel buffer. // Needed for alignment and stride calculations. @@ -50,6 +51,7 @@ u32 GetBytesPerBufferElement(BufferFormat buffer_format); std::pair GetDispatchCount(const DecodingShaderInfo* info, u32 width, u32 height); // Returns the GLSL string containing the texture decoding shader for the specified format. -std::string GenerateDecodingShader(u32 format, u32 palette_format, APIType api_type); +std::string GenerateDecodingShader(TextureFormat format, TlutFormat palette_format, + APIType api_type); } // namespace TextureConversionShader diff --git a/Source/Core/VideoCommon/TextureDecoder.h b/Source/Core/VideoCommon/TextureDecoder.h index 44834c0623..b424dd324f 100644 --- a/Source/Core/VideoCommon/TextureDecoder.h +++ b/Source/Core/VideoCommon/TextureDecoder.h @@ -4,6 +4,7 @@ #pragma once +#include #include "Common/CommonTypes.h" enum @@ -67,6 +68,22 @@ enum TlutFormat GX_TL_RGB5A3 = 0x2, }; +struct EFBCopyFormat +{ + EFBCopyFormat(u32 efb_format_, TextureFormat copy_format_) + : efb_format(efb_format_), copy_format(copy_format_) + { + } + + bool operator<(const EFBCopyFormat& rhs) const + { + return std::tie(efb_format, copy_format) < std::tie(rhs.efb_format, rhs.copy_format); + } + + u32 efb_format; + TextureFormat copy_format; +}; + int TexDecoder_GetTexelSizeInNibbles(int format); int TexDecoder_GetTextureSizeInBytes(int width, int height, int format); int TexDecoder_GetBlockWidthInTexels(u32 format);