mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-24 06:39:46 -06:00
Video: Clearly separate Texture and EFB Copy formats
Improve bookkeeping around formats. Hopefully make code less confusing. - Rename TlutFormat -> TLUTFormat to follow conventions. - Use enum classes to prevent using a Texture format where an EFB Copy format is expected or vice-versa. - Use common EFBCopyFormat names regardless of depth and YUV configurations.
This commit is contained in:
@ -87,9 +87,9 @@ void PSTextureEncoder::Shutdown()
|
||||
SAFE_RELEASE(m_out);
|
||||
}
|
||||
|
||||
void PSTextureEncoder::Encode(u8* dst, const EFBCopyFormat& format, u32 native_width,
|
||||
void PSTextureEncoder::Encode(u8* dst, const EFBCopyParams& params, 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)
|
||||
const EFBRectangle& src_rect, bool scale_by_half)
|
||||
{
|
||||
if (!m_ready) // Make sure we initialized OK
|
||||
return;
|
||||
@ -100,7 +100,7 @@ void PSTextureEncoder::Encode(u8* dst, const EFBCopyFormat& format, u32 native_w
|
||||
// FIXME: Instead of resolving EFB, it would be better to pick out a
|
||||
// single sample from each pixel. The game may break if it isn't
|
||||
// expecting the blurred edges around multisampled shapes.
|
||||
ID3D11ShaderResourceView* pEFB = is_depth_copy ?
|
||||
ID3D11ShaderResourceView* pEFB = params.depth ?
|
||||
FramebufferManager::GetResolvedEFBDepthTexture()->GetSRV() :
|
||||
FramebufferManager::GetResolvedEFBColorTexture()->GetSRV();
|
||||
|
||||
@ -119,12 +119,12 @@ void PSTextureEncoder::Encode(u8* dst, const EFBCopyFormat& format, u32 native_w
|
||||
|
||||
D3D::context->OMSetRenderTargets(1, &m_outRTV, nullptr);
|
||||
|
||||
EFBEncodeParams params;
|
||||
params.SrcLeft = src_rect.left;
|
||||
params.SrcTop = src_rect.top;
|
||||
params.DestWidth = native_width;
|
||||
params.ScaleFactor = scale_by_half ? 2 : 1;
|
||||
D3D::context->UpdateSubresource(m_encodeParams, 0, nullptr, ¶ms, 0, 0);
|
||||
EFBEncodeParams encode_params;
|
||||
encode_params.SrcLeft = src_rect.left;
|
||||
encode_params.SrcTop = src_rect.top;
|
||||
encode_params.DestWidth = native_width;
|
||||
encode_params.ScaleFactor = scale_by_half ? 2 : 1;
|
||||
D3D::context->UpdateSubresource(m_encodeParams, 0, nullptr, &encode_params, 0, 0);
|
||||
D3D::stateman->SetPixelConstants(m_encodeParams);
|
||||
|
||||
// We also linear filtering for both box filtering and downsampling higher resolutions to 1x
|
||||
@ -137,7 +137,7 @@ void PSTextureEncoder::Encode(u8* dst, const EFBCopyFormat& format, u32 native_w
|
||||
D3D::SetPointCopySampler();
|
||||
|
||||
D3D::drawShadedTexQuad(pEFB, targetRect.AsRECT(), g_renderer->GetTargetWidth(),
|
||||
g_renderer->GetTargetHeight(), GetEncodingPixelShader(format),
|
||||
g_renderer->GetTargetHeight(), GetEncodingPixelShader(params),
|
||||
VertexShaderCache::GetSimpleVertexShader(),
|
||||
VertexShaderCache::GetSimpleInputLayout());
|
||||
|
||||
@ -168,18 +168,18 @@ void PSTextureEncoder::Encode(u8* dst, const EFBCopyFormat& format, u32 native_w
|
||||
FramebufferManager::GetEFBDepthTexture()->GetDSV());
|
||||
}
|
||||
|
||||
ID3D11PixelShader* PSTextureEncoder::GetEncodingPixelShader(const EFBCopyFormat& format)
|
||||
ID3D11PixelShader* PSTextureEncoder::GetEncodingPixelShader(const EFBCopyParams& params)
|
||||
{
|
||||
auto iter = m_encoding_shaders.find(format);
|
||||
auto iter = m_encoding_shaders.find(params);
|
||||
if (iter != m_encoding_shaders.end())
|
||||
return iter->second;
|
||||
|
||||
D3DBlob* bytecode = nullptr;
|
||||
const char* shader = TextureConversionShader::GenerateEncodingShader(format, APIType::D3D);
|
||||
const char* shader = TextureConversionShader::GenerateEncodingShader(params, APIType::D3D);
|
||||
if (!D3D::CompilePixelShader(shader, &bytecode))
|
||||
{
|
||||
PanicAlert("Failed to compile texture encoding shader.");
|
||||
m_encoding_shaders[format] = nullptr;
|
||||
m_encoding_shaders[params] = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -188,7 +188,7 @@ ID3D11PixelShader* PSTextureEncoder::GetEncodingPixelShader(const EFBCopyFormat&
|
||||
D3D::device->CreatePixelShader(bytecode->Data(), bytecode->Size(), nullptr, &newShader);
|
||||
CHECK(SUCCEEDED(hr), "create efb encoder pixel shader");
|
||||
|
||||
m_encoding_shaders.emplace(format, newShader);
|
||||
m_encoding_shaders.emplace(params, newShader);
|
||||
return newShader;
|
||||
}
|
||||
}
|
||||
|
@ -32,12 +32,12 @@ public:
|
||||
|
||||
void Init();
|
||||
void Shutdown();
|
||||
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,
|
||||
void Encode(u8* dst, const EFBCopyParams& params, u32 native_width, u32 bytes_per_row,
|
||||
u32 num_blocks_y, u32 memory_stride, const EFBRectangle& src_rect,
|
||||
bool scale_by_half);
|
||||
|
||||
private:
|
||||
ID3D11PixelShader* GetEncodingPixelShader(const EFBCopyFormat& format);
|
||||
ID3D11PixelShader* GetEncodingPixelShader(const EFBCopyParams& params);
|
||||
|
||||
bool m_ready;
|
||||
|
||||
@ -45,6 +45,6 @@ private:
|
||||
ID3D11RenderTargetView* m_outRTV;
|
||||
ID3D11Texture2D* m_outStage;
|
||||
ID3D11Buffer* m_encodeParams;
|
||||
std::map<EFBCopyFormat, ID3D11PixelShader*> m_encoding_shaders;
|
||||
std::map<EFBCopyParams, ID3D11PixelShader*> m_encoding_shaders;
|
||||
};
|
||||
}
|
||||
|
@ -38,12 +38,12 @@ std::unique_ptr<AbstractTexture> TextureCache::CreateTexture(const TextureConfig
|
||||
return std::make_unique<DXTexture>(config);
|
||||
}
|
||||
|
||||
void TextureCache::CopyEFB(u8* dst, const EFBCopyFormat& format, u32 native_width,
|
||||
void TextureCache::CopyEFB(u8* dst, const EFBCopyParams& params, 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)
|
||||
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, src_rect, scale_by_half);
|
||||
g_encoder->Encode(dst, params, native_width, bytes_per_row, num_blocks_y, memory_stride, src_rect,
|
||||
scale_by_half);
|
||||
}
|
||||
|
||||
const char palette_shader[] =
|
||||
@ -126,8 +126,8 @@ void main(
|
||||
}
|
||||
)HLSL";
|
||||
|
||||
void TextureCache::ConvertTexture(TCacheEntry* destination, TCacheEntry* source, void* palette,
|
||||
TlutFormat format)
|
||||
void TextureCache::ConvertTexture(TCacheEntry* destination, TCacheEntry* source,
|
||||
const void* palette, TLUTFormat format)
|
||||
{
|
||||
DXTexture* source_texture = static_cast<DXTexture*>(source->texture.get());
|
||||
DXTexture* destination_texture = static_cast<DXTexture*>(destination->texture.get());
|
||||
@ -144,7 +144,7 @@ void TextureCache::ConvertTexture(TCacheEntry* destination, TCacheEntry* source,
|
||||
D3D::stateman->SetTexture(1, palette_buf_srv);
|
||||
|
||||
// TODO: Add support for C14X2 format. (Different multiplier, more palette entries.)
|
||||
float params[4] = {(source->format & 0xf) == GX_TF_I4 ? 15.f : 255.f};
|
||||
float params[4] = {source->format == TextureFormat::I4 ? 15.f : 255.f};
|
||||
D3D::context->UpdateSubresource(palette_uniform, 0, nullptr, ¶ms, 0, 0);
|
||||
D3D::stateman->SetPixelConstants(palette_uniform);
|
||||
|
||||
@ -163,8 +163,9 @@ void TextureCache::ConvertTexture(TCacheEntry* destination, TCacheEntry* source,
|
||||
// Create texture copy
|
||||
D3D::drawShadedTexQuad(
|
||||
source_texture->GetRawTexIdentifier()->GetSRV(), &sourcerect, source->GetWidth(),
|
||||
source->GetHeight(), palette_pixel_shader[format], VertexShaderCache::GetSimpleVertexShader(),
|
||||
VertexShaderCache::GetSimpleInputLayout(), GeometryShaderCache::GetCopyGeometryShader());
|
||||
source->GetHeight(), palette_pixel_shader[static_cast<int>(format)],
|
||||
VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout(),
|
||||
GeometryShaderCache::GetCopyGeometryShader());
|
||||
|
||||
D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(),
|
||||
FramebufferManager::GetEFBDepthTexture()->GetDSV());
|
||||
@ -190,9 +191,9 @@ TextureCache::TextureCache()
|
||||
palette_buf = nullptr;
|
||||
palette_buf_srv = nullptr;
|
||||
palette_uniform = nullptr;
|
||||
palette_pixel_shader[GX_TL_IA8] = GetConvertShader("IA8");
|
||||
palette_pixel_shader[GX_TL_RGB565] = GetConvertShader("RGB565");
|
||||
palette_pixel_shader[GX_TL_RGB5A3] = GetConvertShader("RGB5A3");
|
||||
palette_pixel_shader[static_cast<int>(TLUTFormat::IA8)] = GetConvertShader("IA8");
|
||||
palette_pixel_shader[static_cast<int>(TLUTFormat::RGB565)] = GetConvertShader("RGB565");
|
||||
palette_pixel_shader[static_cast<int>(TLUTFormat::RGB5A3)] = GetConvertShader("RGB5A3");
|
||||
auto lutBd = CD3D11_BUFFER_DESC(sizeof(u16) * 256, D3D11_BIND_SHADER_RESOURCE);
|
||||
HRESULT hr = D3D::device->CreateBuffer(&lutBd, nullptr, &palette_buf);
|
||||
CHECK(SUCCEEDED(hr), "create palette decoder lut buffer");
|
||||
|
@ -28,12 +28,12 @@ private:
|
||||
return 0;
|
||||
};
|
||||
|
||||
void ConvertTexture(TCacheEntry* destination, TCacheEntry* source, void* palette,
|
||||
TlutFormat format) override;
|
||||
void ConvertTexture(TCacheEntry* destination, TCacheEntry* source, const void* palette,
|
||||
TLUTFormat format) 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 CopyEFB(u8* dst, const EFBCopyParams& params, u32 native_width, u32 bytes_per_row,
|
||||
u32 num_blocks_y, u32 memory_stride, const EFBRectangle& src_rect,
|
||||
bool scale_by_half) override;
|
||||
|
||||
void CopyEFBToCacheEntry(TCacheEntry* entry, bool is_depth_copy, const EFBRectangle& src_rect,
|
||||
bool scale_by_half, unsigned int cbuf_id, const float* colmat) override;
|
||||
|
@ -20,14 +20,14 @@ public:
|
||||
~TextureCache() {}
|
||||
bool CompileShaders() override { return true; }
|
||||
void DeleteShaders() override {}
|
||||
void ConvertTexture(TCacheEntry* entry, TCacheEntry* unconverted, void* palette,
|
||||
TlutFormat format) override
|
||||
void ConvertTexture(TCacheEntry* entry, TCacheEntry* unconverted, const void* palette,
|
||||
TLUTFormat format) 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 CopyEFB(u8* dst, const EFBCopyParams& params, u32 native_width, u32 bytes_per_row,
|
||||
u32 num_blocks_y, u32 memory_stride, const EFBRectangle& src_rect,
|
||||
bool scale_by_half) override
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "Common/Assert.h"
|
||||
#include "Common/GL/GLInterfaceBase.h"
|
||||
#include "Common/MsgHandler.h"
|
||||
#include "Common/StringUtil.h"
|
||||
@ -32,12 +33,18 @@ namespace OGL
|
||||
{
|
||||
static u32 s_ColorCbufid;
|
||||
static u32 s_DepthCbufid;
|
||||
static SHADER s_palette_pixel_shader[3];
|
||||
|
||||
struct PaletteShader
|
||||
{
|
||||
SHADER shader;
|
||||
GLuint buffer_offset_uniform;
|
||||
GLuint multiplier_uniform;
|
||||
GLuint copy_position_uniform;
|
||||
};
|
||||
|
||||
static PaletteShader s_palette_shader[3];
|
||||
static std::unique_ptr<StreamBuffer> s_palette_stream_buffer;
|
||||
static GLuint s_palette_resolv_texture;
|
||||
static GLuint s_palette_buffer_offset_uniform[3];
|
||||
static GLuint s_palette_multiplier_uniform[3];
|
||||
static GLuint s_palette_copy_position_uniform[3];
|
||||
static GLuint s_palette_resolv_texture = 0;
|
||||
|
||||
struct TextureDecodingProgramInfo
|
||||
{
|
||||
@ -64,12 +71,12 @@ std::unique_ptr<AbstractTexture> TextureCache::CreateTexture(const TextureConfig
|
||||
return std::make_unique<OGLTexture>(config);
|
||||
}
|
||||
|
||||
void TextureCache::CopyEFB(u8* dst, const EFBCopyFormat& format, u32 native_width,
|
||||
void TextureCache::CopyEFB(u8* dst, const EFBCopyParams& params, 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)
|
||||
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, src_rect, scale_by_half);
|
||||
TextureConverter::EncodeToRamFromTexture(dst, params, native_width, bytes_per_row, num_blocks_y,
|
||||
memory_stride, src_rect, scale_by_half);
|
||||
}
|
||||
|
||||
TextureCache::TextureCache()
|
||||
@ -126,6 +133,23 @@ GLuint TextureCache::GetColorCopyPositionUniform() const
|
||||
return m_colorCopyPositionUniform;
|
||||
}
|
||||
|
||||
static bool CompilePaletteShader(TLUTFormat tlutfmt, const std::string& vcode,
|
||||
const std::string& pcode, const std::string& gcode)
|
||||
{
|
||||
_assert_(IsValidTLUTFormat(tlutfmt));
|
||||
PaletteShader& shader = s_palette_shader[static_cast<int>(tlutfmt)];
|
||||
|
||||
if (!ProgramShaderCache::CompileShader(shader.shader, vcode, pcode, gcode))
|
||||
return false;
|
||||
|
||||
shader.buffer_offset_uniform =
|
||||
glGetUniformLocation(shader.shader.glprogid, "texture_buffer_offset");
|
||||
shader.multiplier_uniform = glGetUniformLocation(shader.shader.glprogid, "multiplier");
|
||||
shader.copy_position_uniform = glGetUniformLocation(shader.shader.glprogid, "copy_position");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TextureCache::CompileShaders()
|
||||
{
|
||||
constexpr const char* color_copy_program = "SAMPLER_BINDING(9) uniform sampler2DArray samp9;\n"
|
||||
@ -315,44 +339,17 @@ bool TextureCache::CompileShaders()
|
||||
|
||||
if (g_ActiveConfig.backend_info.bSupportsPaletteConversion)
|
||||
{
|
||||
if (!ProgramShaderCache::CompileShader(
|
||||
s_palette_pixel_shader[GX_TL_IA8], StringFromFormat(vertex_program, prefix, prefix),
|
||||
"#define DECODE DecodePixel_IA8" + palette_shader, geo_program))
|
||||
{
|
||||
if (!CompilePaletteShader(TLUTFormat::IA8, StringFromFormat(vertex_program, prefix, prefix),
|
||||
"#define DECODE DecodePixel_IA8" + palette_shader, geo_program))
|
||||
return false;
|
||||
}
|
||||
s_palette_buffer_offset_uniform[GX_TL_IA8] =
|
||||
glGetUniformLocation(s_palette_pixel_shader[GX_TL_IA8].glprogid, "texture_buffer_offset");
|
||||
s_palette_multiplier_uniform[GX_TL_IA8] =
|
||||
glGetUniformLocation(s_palette_pixel_shader[GX_TL_IA8].glprogid, "multiplier");
|
||||
s_palette_copy_position_uniform[GX_TL_IA8] =
|
||||
glGetUniformLocation(s_palette_pixel_shader[GX_TL_IA8].glprogid, "copy_position");
|
||||
|
||||
if (!ProgramShaderCache::CompileShader(
|
||||
s_palette_pixel_shader[GX_TL_RGB565], StringFromFormat(vertex_program, prefix, prefix),
|
||||
"#define DECODE DecodePixel_RGB565" + palette_shader, geo_program))
|
||||
{
|
||||
if (!CompilePaletteShader(TLUTFormat::RGB565, StringFromFormat(vertex_program, prefix, prefix),
|
||||
"#define DECODE DecodePixel_RGB565" + palette_shader, geo_program))
|
||||
return false;
|
||||
}
|
||||
s_palette_buffer_offset_uniform[GX_TL_RGB565] = glGetUniformLocation(
|
||||
s_palette_pixel_shader[GX_TL_RGB565].glprogid, "texture_buffer_offset");
|
||||
s_palette_multiplier_uniform[GX_TL_RGB565] =
|
||||
glGetUniformLocation(s_palette_pixel_shader[GX_TL_RGB565].glprogid, "multiplier");
|
||||
s_palette_copy_position_uniform[GX_TL_RGB565] =
|
||||
glGetUniformLocation(s_palette_pixel_shader[GX_TL_RGB565].glprogid, "copy_position");
|
||||
|
||||
if (!ProgramShaderCache::CompileShader(
|
||||
s_palette_pixel_shader[GX_TL_RGB5A3], StringFromFormat(vertex_program, prefix, prefix),
|
||||
"#define DECODE DecodePixel_RGB5A3" + palette_shader, geo_program))
|
||||
{
|
||||
if (!CompilePaletteShader(TLUTFormat::RGB5A3, StringFromFormat(vertex_program, prefix, prefix),
|
||||
"#define DECODE DecodePixel_RGB5A3" + palette_shader, geo_program))
|
||||
return false;
|
||||
}
|
||||
s_palette_buffer_offset_uniform[GX_TL_RGB5A3] = glGetUniformLocation(
|
||||
s_palette_pixel_shader[GX_TL_RGB5A3].glprogid, "texture_buffer_offset");
|
||||
s_palette_multiplier_uniform[GX_TL_RGB5A3] =
|
||||
glGetUniformLocation(s_palette_pixel_shader[GX_TL_RGB5A3].glprogid, "multiplier");
|
||||
s_palette_copy_position_uniform[GX_TL_RGB5A3] =
|
||||
glGetUniformLocation(s_palette_pixel_shader[GX_TL_RGB5A3].glprogid, "copy_position");
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -364,16 +361,19 @@ void TextureCache::DeleteShaders()
|
||||
m_depthMatrixProgram.Destroy();
|
||||
|
||||
if (g_ActiveConfig.backend_info.bSupportsPaletteConversion)
|
||||
for (auto& shader : s_palette_pixel_shader)
|
||||
shader.Destroy();
|
||||
for (auto& shader : s_palette_shader)
|
||||
shader.shader.Destroy();
|
||||
}
|
||||
|
||||
void TextureCache::ConvertTexture(TCacheEntry* destination, TCacheEntry* source, void* palette,
|
||||
TlutFormat format)
|
||||
void TextureCache::ConvertTexture(TCacheEntry* destination, TCacheEntry* source,
|
||||
const void* palette, TLUTFormat tlutfmt)
|
||||
{
|
||||
if (!g_ActiveConfig.backend_info.bSupportsPaletteConversion)
|
||||
return;
|
||||
|
||||
_assert_(IsValidTLUTFormat(tlutfmt));
|
||||
const PaletteShader& palette_shader = s_palette_shader[static_cast<int>(tlutfmt)];
|
||||
|
||||
g_renderer->ResetAPIState();
|
||||
|
||||
OGLTexture* source_texture = static_cast<OGLTexture*>(source->texture.get());
|
||||
@ -385,16 +385,17 @@ void TextureCache::ConvertTexture(TCacheEntry* destination, TCacheEntry* source,
|
||||
|
||||
FramebufferManager::SetFramebuffer(destination_texture->GetFramebuffer());
|
||||
glViewport(0, 0, destination->GetWidth(), destination->GetHeight());
|
||||
s_palette_pixel_shader[format].Bind();
|
||||
palette_shader.shader.Bind();
|
||||
|
||||
// C14 textures are currently unsupported
|
||||
int size = (source->format & 0xf) == GX_TF_I4 ? 32 : 512;
|
||||
int size = source->format == TextureFormat::I4 ? 32 : 512;
|
||||
auto buffer = s_palette_stream_buffer->Map(size);
|
||||
memcpy(buffer.first, palette, size);
|
||||
s_palette_stream_buffer->Unmap(size);
|
||||
glUniform1i(s_palette_buffer_offset_uniform[format], buffer.second / 2);
|
||||
glUniform1f(s_palette_multiplier_uniform[format], (source->format & 0xf) == 0 ? 15.0f : 255.0f);
|
||||
glUniform4f(s_palette_copy_position_uniform[format], 0.0f, 0.0f,
|
||||
glUniform1i(palette_shader.buffer_offset_uniform, buffer.second / 2);
|
||||
glUniform1f(palette_shader.multiplier_uniform,
|
||||
source->format == TextureFormat::I4 ? 15.0f : 255.0f);
|
||||
glUniform4f(palette_shader.copy_position_uniform, 0.0f, 0.0f,
|
||||
static_cast<float>(source->GetWidth()), static_cast<float>(source->GetHeight()));
|
||||
|
||||
glActiveTexture(GL_TEXTURE10);
|
||||
@ -441,7 +442,7 @@ void DestroyTextureDecodingResources()
|
||||
s_texture_decoding_program_info.clear();
|
||||
}
|
||||
|
||||
bool TextureCache::SupportsGPUTextureDecode(TextureFormat format, TlutFormat palette_format)
|
||||
bool TextureCache::SupportsGPUTextureDecode(TextureFormat format, TLUTFormat palette_format)
|
||||
{
|
||||
auto key = std::make_pair(static_cast<u32>(format), static_cast<u32>(palette_format));
|
||||
auto iter = s_texture_decoding_program_info.find(key);
|
||||
@ -483,7 +484,7 @@ bool TextureCache::SupportsGPUTextureDecode(TextureFormat format, TlutFormat pal
|
||||
void TextureCache::DecodeTextureOnGPU(TCacheEntry* entry, u32 dst_level, const u8* data,
|
||||
size_t data_size, TextureFormat format, u32 width, u32 height,
|
||||
u32 aligned_width, u32 aligned_height, u32 row_stride,
|
||||
const u8* palette, TlutFormat palette_format)
|
||||
const u8* palette, TLUTFormat palette_format)
|
||||
{
|
||||
auto key = std::make_pair(static_cast<u32>(format), static_cast<u32>(palette_format));
|
||||
auto iter = s_texture_decoding_program_info.find(key);
|
||||
|
@ -26,23 +26,23 @@ public:
|
||||
|
||||
static TextureCache* GetInstance();
|
||||
|
||||
bool SupportsGPUTextureDecode(TextureFormat format, TlutFormat palette_format) override;
|
||||
bool SupportsGPUTextureDecode(TextureFormat format, TLUTFormat palette_format) override;
|
||||
void DecodeTextureOnGPU(TCacheEntry* entry, u32 dst_level, const u8* data, size_t data_size,
|
||||
TextureFormat format, u32 width, u32 height, u32 aligned_width,
|
||||
u32 aligned_height, u32 row_stride, const u8* palette,
|
||||
TlutFormat palette_format) override;
|
||||
TLUTFormat palette_format) override;
|
||||
|
||||
const SHADER& GetColorCopyProgram() const;
|
||||
GLuint GetColorCopyPositionUniform() const;
|
||||
|
||||
private:
|
||||
std::unique_ptr<AbstractTexture> CreateTexture(const TextureConfig& config) override;
|
||||
void ConvertTexture(TCacheEntry* destination, TCacheEntry* source, void* palette,
|
||||
TlutFormat format) override;
|
||||
void ConvertTexture(TCacheEntry* destination, TCacheEntry* source, const void* palette,
|
||||
TLUTFormat format) 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 CopyEFB(u8* dst, const EFBCopyParams& params, u32 native_width, u32 bytes_per_row,
|
||||
u32 num_blocks_y, u32 memory_stride, const EFBRectangle& src_rect,
|
||||
bool scale_by_half) override;
|
||||
|
||||
void CopyEFBToCacheEntry(TCacheEntry* entry, bool is_depth_copy, const EFBRectangle& src_rect,
|
||||
bool scale_by_half, unsigned int cbuf_id, const float* colmat) override;
|
||||
|
@ -51,7 +51,7 @@ struct EncodingProgram
|
||||
SHADER program;
|
||||
GLint copy_position_uniform;
|
||||
};
|
||||
static std::map<EFBCopyFormat, EncodingProgram> s_encoding_programs;
|
||||
static std::map<EFBCopyParams, EncodingProgram> s_encoding_programs;
|
||||
|
||||
static GLuint s_PBO = 0; // for readback with different strides
|
||||
|
||||
@ -136,13 +136,13 @@ static void CreatePrograms()
|
||||
ProgramShaderCache::CompileShader(s_yuyvToRgbProgram, VProgramYuyvToRgb, FProgramYuyvToRgb);
|
||||
}
|
||||
|
||||
static EncodingProgram& GetOrCreateEncodingShader(const EFBCopyFormat& format)
|
||||
static EncodingProgram& GetOrCreateEncodingShader(const EFBCopyParams& params)
|
||||
{
|
||||
auto iter = s_encoding_programs.find(format);
|
||||
auto iter = s_encoding_programs.find(params);
|
||||
if (iter != s_encoding_programs.end())
|
||||
return iter->second;
|
||||
|
||||
const char* shader = TextureConversionShader::GenerateEncodingShader(format, APIType::OpenGL);
|
||||
const char* shader = TextureConversionShader::GenerateEncodingShader(params, APIType::OpenGL);
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
if (g_ActiveConfig.iLog & CONF_SAVESHADERS && shader)
|
||||
@ -166,7 +166,7 @@ static EncodingProgram& GetOrCreateEncodingShader(const EFBCopyFormat& format)
|
||||
PanicAlert("Failed to compile texture encoding shader.");
|
||||
|
||||
program.copy_position_uniform = glGetUniformLocation(program.program.glprogid, "position");
|
||||
return s_encoding_programs.emplace(format, program).first->second;
|
||||
return s_encoding_programs.emplace(params, program).first->second;
|
||||
}
|
||||
|
||||
void Init()
|
||||
@ -271,24 +271,24 @@ static void EncodeToRamUsingShader(GLuint srcTexture, u8* destAddr, u32 dst_line
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||
}
|
||||
|
||||
void EncodeToRamFromTexture(u8* dest_ptr, const EFBCopyFormat& format, u32 native_width,
|
||||
void EncodeToRamFromTexture(u8* dest_ptr, const EFBCopyParams& params, 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)
|
||||
const EFBRectangle& src_rect, bool scale_by_half)
|
||||
{
|
||||
g_renderer->ResetAPIState();
|
||||
|
||||
EncodingProgram& texconv_shader = GetOrCreateEncodingShader(format);
|
||||
EncodingProgram& texconv_shader = GetOrCreateEncodingShader(params);
|
||||
|
||||
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 ?
|
||||
const GLuint read_texture = params.depth ?
|
||||
FramebufferManager::ResolveAndGetDepthTarget(src_rect) :
|
||||
FramebufferManager::ResolveAndGetRenderTarget(src_rect);
|
||||
|
||||
EncodeToRamUsingShader(read_texture, dest_ptr, bytes_per_row, num_blocks_y, memory_stride,
|
||||
scale_by_half && !is_depth_copy);
|
||||
scale_by_half && !params.depth);
|
||||
|
||||
FramebufferManager::SetFramebuffer(0);
|
||||
g_renderer->RestoreAPIState();
|
||||
|
@ -7,9 +7,10 @@
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/GL/GLUtil.h"
|
||||
|
||||
#include "VideoCommon/TextureDecoder.h"
|
||||
#include "VideoCommon/VideoCommon.h"
|
||||
|
||||
struct EFBCopyParams;
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
// Converts textures between formats using shaders
|
||||
@ -25,9 +26,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, const EFBCopyFormat& format, u32 native_width,
|
||||
void EncodeToRamFromTexture(u8* dest_ptr, const EFBCopyParams& params, 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);
|
||||
const EFBRectangle& src_rect, bool scale_by_half);
|
||||
}
|
||||
|
||||
} // namespace OGL
|
||||
|
@ -50,13 +50,13 @@ class TextureCache : public TextureCacheBase
|
||||
public:
|
||||
bool CompileShaders() override { return true; }
|
||||
void DeleteShaders() override {}
|
||||
void ConvertTexture(TCacheEntry* entry, TCacheEntry* unconverted, void* palette,
|
||||
TlutFormat format) override
|
||||
void ConvertTexture(TCacheEntry* entry, TCacheEntry* unconverted, const void* palette,
|
||||
TLUTFormat format) 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 CopyEFB(u8* dst, const EFBCopyParams& params, u32 native_width, u32 bytes_per_row,
|
||||
u32 num_blocks_y, u32 memory_stride, const EFBRectangle& src_rect,
|
||||
bool scale_by_half) override
|
||||
{
|
||||
EfbCopy::CopyEfb();
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -111,13 +111,14 @@ void SampleMip(s32 s, s32 t, s32 mip, bool linear, u8 texmap, u8* sample)
|
||||
TexMode0& tm0 = texUnit.texMode0[subTexmap];
|
||||
TexImage0& ti0 = texUnit.texImage0[subTexmap];
|
||||
TexTLUT& texTlut = texUnit.texTlut[subTexmap];
|
||||
TlutFormat tlutfmt = (TlutFormat)texTlut.tlut_format;
|
||||
TextureFormat texfmt = static_cast<TextureFormat>(ti0.format);
|
||||
TLUTFormat tlutfmt = static_cast<TLUTFormat>(texTlut.tlut_format);
|
||||
|
||||
u8 *imageSrc, *imageSrcOdd = nullptr;
|
||||
if (texUnit.texImage1[subTexmap].image_type)
|
||||
{
|
||||
imageSrc = &texMem[texUnit.texImage1[subTexmap].tmem_even * TMEM_LINE_SIZE];
|
||||
if (ti0.format == GX_TF_RGBA8)
|
||||
if (texfmt == TextureFormat::RGBA8)
|
||||
imageSrcOdd = &texMem[texUnit.texImage2[subTexmap].tmem_odd * TMEM_LINE_SIZE];
|
||||
}
|
||||
else
|
||||
@ -139,9 +140,9 @@ void SampleMip(s32 s, s32 t, s32 mip, bool linear, u8 texmap, u8* sample)
|
||||
int mipWidth = imageWidth + 1;
|
||||
int mipHeight = imageHeight + 1;
|
||||
|
||||
int fmtWidth = TexDecoder_GetBlockWidthInTexels(ti0.format);
|
||||
int fmtHeight = TexDecoder_GetBlockHeightInTexels(ti0.format);
|
||||
int fmtDepth = TexDecoder_GetTexelSizeInNibbles(ti0.format);
|
||||
int fmtWidth = TexDecoder_GetBlockWidthInTexels(texfmt);
|
||||
int fmtHeight = TexDecoder_GetBlockHeightInTexels(texfmt);
|
||||
int fmtDepth = TexDecoder_GetTexelSizeInNibbles(texfmt);
|
||||
|
||||
imageWidth >>= mip;
|
||||
imageHeight >>= mip;
|
||||
@ -186,21 +187,21 @@ void SampleMip(s32 s, s32 t, s32 mip, bool linear, u8 texmap, u8* sample)
|
||||
WrapCoord(&imageSPlus1, tm0.wrap_s, imageWidth);
|
||||
WrapCoord(&imageTPlus1, tm0.wrap_t, imageHeight);
|
||||
|
||||
if (!(ti0.format == GX_TF_RGBA8 && texUnit.texImage1[subTexmap].image_type))
|
||||
if (!(texfmt == TextureFormat::RGBA8 && texUnit.texImage1[subTexmap].image_type))
|
||||
{
|
||||
TexDecoder_DecodeTexel(sampledTex, imageSrc, imageS, imageT, imageWidth, ti0.format, tlut,
|
||||
TexDecoder_DecodeTexel(sampledTex, imageSrc, imageS, imageT, imageWidth, texfmt, tlut,
|
||||
tlutfmt);
|
||||
SetTexel(sampledTex, texel, (128 - fractS) * (128 - fractT));
|
||||
|
||||
TexDecoder_DecodeTexel(sampledTex, imageSrc, imageSPlus1, imageT, imageWidth, ti0.format,
|
||||
tlut, tlutfmt);
|
||||
TexDecoder_DecodeTexel(sampledTex, imageSrc, imageSPlus1, imageT, imageWidth, texfmt, tlut,
|
||||
tlutfmt);
|
||||
AddTexel(sampledTex, texel, (fractS) * (128 - fractT));
|
||||
|
||||
TexDecoder_DecodeTexel(sampledTex, imageSrc, imageS, imageTPlus1, imageWidth, ti0.format,
|
||||
tlut, tlutfmt);
|
||||
TexDecoder_DecodeTexel(sampledTex, imageSrc, imageS, imageTPlus1, imageWidth, texfmt, tlut,
|
||||
tlutfmt);
|
||||
AddTexel(sampledTex, texel, (128 - fractS) * (fractT));
|
||||
|
||||
TexDecoder_DecodeTexel(sampledTex, imageSrc, imageSPlus1, imageTPlus1, imageWidth, ti0.format,
|
||||
TexDecoder_DecodeTexel(sampledTex, imageSrc, imageSPlus1, imageTPlus1, imageWidth, texfmt,
|
||||
tlut, tlutfmt);
|
||||
AddTexel(sampledTex, texel, (fractS) * (fractT));
|
||||
}
|
||||
@ -238,9 +239,8 @@ void SampleMip(s32 s, s32 t, s32 mip, bool linear, u8 texmap, u8* sample)
|
||||
WrapCoord(&imageS, tm0.wrap_s, imageWidth);
|
||||
WrapCoord(&imageT, tm0.wrap_t, imageHeight);
|
||||
|
||||
if (!(ti0.format == GX_TF_RGBA8 && texUnit.texImage1[subTexmap].image_type))
|
||||
TexDecoder_DecodeTexel(sample, imageSrc, imageS, imageT, imageWidth, ti0.format, tlut,
|
||||
tlutfmt);
|
||||
if (!(texfmt == TextureFormat::RGBA8 && texUnit.texImage1[subTexmap].image_type))
|
||||
TexDecoder_DecodeTexel(sample, imageSrc, imageS, imageT, imageWidth, texfmt, tlut, tlutfmt);
|
||||
else
|
||||
TexDecoder_DecodeTexelRGBA8FromTmem(sample, imageSrc, imageSrcOdd, imageS, imageT,
|
||||
imageWidth);
|
||||
|
@ -95,8 +95,8 @@ bool TextureCache::Initialize()
|
||||
return true;
|
||||
}
|
||||
|
||||
void TextureCache::ConvertTexture(TCacheEntry* destination, TCacheEntry* source, void* palette,
|
||||
TlutFormat format)
|
||||
void TextureCache::ConvertTexture(TCacheEntry* destination, TCacheEntry* source,
|
||||
const void* palette, TLUTFormat format)
|
||||
{
|
||||
m_texture_converter->ConvertTexture(destination, source, m_render_pass, palette, format);
|
||||
|
||||
@ -111,9 +111,9 @@ void TextureCache::ConvertTexture(TCacheEntry* destination, TCacheEntry* source,
|
||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
}
|
||||
|
||||
void TextureCache::CopyEFB(u8* dst, const EFBCopyFormat& format, u32 native_width,
|
||||
void TextureCache::CopyEFB(u8* dst, const EFBCopyParams& params, 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)
|
||||
const EFBRectangle& src_rect, bool scale_by_half)
|
||||
{
|
||||
// Flush EFB pokes first, as they're expected to be included.
|
||||
FramebufferManager::GetInstance()->FlushEFBPokes();
|
||||
@ -128,7 +128,7 @@ void TextureCache::CopyEFB(u8* dst, const EFBCopyFormat& format, u32 native_widt
|
||||
region = Util::ClampRect2D(region, FramebufferManager::GetInstance()->GetEFBWidth(),
|
||||
FramebufferManager::GetInstance()->GetEFBHeight());
|
||||
Texture2D* src_texture;
|
||||
if (is_depth_copy)
|
||||
if (params.depth)
|
||||
src_texture = FramebufferManager::GetInstance()->ResolveEFBDepthTexture(region);
|
||||
else
|
||||
src_texture = FramebufferManager::GetInstance()->ResolveEFBColorTexture(region);
|
||||
@ -144,15 +144,15 @@ void TextureCache::CopyEFB(u8* dst, const EFBCopyFormat& format, u32 native_widt
|
||||
src_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
|
||||
m_texture_converter->EncodeTextureToMemory(src_texture->GetView(), dst, format, native_width,
|
||||
bytes_per_row, num_blocks_y, memory_stride,
|
||||
is_depth_copy, src_rect, scale_by_half);
|
||||
m_texture_converter->EncodeTextureToMemory(src_texture->GetView(), dst, params, native_width,
|
||||
bytes_per_row, num_blocks_y, memory_stride, src_rect,
|
||||
scale_by_half);
|
||||
|
||||
// Transition back to original state
|
||||
src_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), original_layout);
|
||||
}
|
||||
|
||||
bool TextureCache::SupportsGPUTextureDecode(TextureFormat format, TlutFormat palette_format)
|
||||
bool TextureCache::SupportsGPUTextureDecode(TextureFormat format, TLUTFormat palette_format)
|
||||
{
|
||||
return m_texture_converter->SupportsTextureDecoding(format, palette_format);
|
||||
}
|
||||
@ -160,7 +160,7 @@ bool TextureCache::SupportsGPUTextureDecode(TextureFormat format, TlutFormat pal
|
||||
void TextureCache::DecodeTextureOnGPU(TCacheEntry* entry, u32 dst_level, const u8* data,
|
||||
size_t data_size, TextureFormat format, u32 width, u32 height,
|
||||
u32 aligned_width, u32 aligned_height, u32 row_stride,
|
||||
const u8* palette, TlutFormat palette_format)
|
||||
const u8* palette, TLUTFormat palette_format)
|
||||
{
|
||||
// Group compute shader dispatches together in the init command buffer. That way we don't have to
|
||||
// pay a penalty for switching from graphics->compute, or end/restart our render pass.
|
||||
|
@ -33,19 +33,19 @@ public:
|
||||
|
||||
std::unique_ptr<AbstractTexture> CreateTexture(const TextureConfig& config) override;
|
||||
|
||||
void ConvertTexture(TCacheEntry* destination, TCacheEntry* source, void* palette,
|
||||
TlutFormat format) override;
|
||||
void ConvertTexture(TCacheEntry* destination, TCacheEntry* source, const void* palette,
|
||||
TLUTFormat format) 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 CopyEFB(u8* dst, const EFBCopyParams& params, u32 native_width, u32 bytes_per_row,
|
||||
u32 num_blocks_y, u32 memory_stride, const EFBRectangle& src_rect,
|
||||
bool scale_by_half) override;
|
||||
|
||||
bool SupportsGPUTextureDecode(TextureFormat format, TlutFormat palette_format) override;
|
||||
bool SupportsGPUTextureDecode(TextureFormat format, TLUTFormat palette_format) override;
|
||||
|
||||
void DecodeTextureOnGPU(TCacheEntry* entry, u32 dst_level, const u8* data, size_t data_size,
|
||||
TextureFormat format, u32 width, u32 height, u32 aligned_width,
|
||||
u32 aligned_height, u32 row_stride, const u8* palette,
|
||||
TlutFormat palette_format) override;
|
||||
TLUTFormat palette_format) override;
|
||||
|
||||
VkShaderModule GetCopyShader() const;
|
||||
VkRenderPass GetTextureCopyRenderPass() const;
|
||||
|
@ -166,7 +166,7 @@ TextureConverter::GetCommandBufferForTextureConversion(const TextureCache::TCach
|
||||
void TextureConverter::ConvertTexture(TextureCacheBase::TCacheEntry* dst_entry,
|
||||
TextureCacheBase::TCacheEntry* src_entry,
|
||||
VkRenderPass render_pass, const void* palette,
|
||||
TlutFormat palette_format)
|
||||
TLUTFormat palette_format)
|
||||
{
|
||||
struct PSUniformBlock
|
||||
{
|
||||
@ -182,7 +182,7 @@ void TextureConverter::ConvertTexture(TextureCacheBase::TCacheEntry* dst_entry,
|
||||
_assert_(destination_texture->GetConfig().rendertarget);
|
||||
|
||||
// We want to align to 2 bytes (R16) or the device's texel buffer alignment, whichever is greater.
|
||||
size_t palette_size = (src_entry->format & 0xF) == GX_TF_I4 ? 32 : 512;
|
||||
size_t palette_size = src_entry->format == TextureFormat::I4 ? 32 : 512;
|
||||
if (!ReserveTexelBufferStorage(palette_size, sizeof(u16)))
|
||||
return;
|
||||
|
||||
@ -201,13 +201,13 @@ void TextureConverter::ConvertTexture(TextureCacheBase::TCacheEntry* dst_entry,
|
||||
UtilityShaderDraw draw(command_buffer,
|
||||
g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_TEXTURE_CONVERSION),
|
||||
render_pass, g_shader_cache->GetScreenQuadVertexShader(), VK_NULL_HANDLE,
|
||||
m_palette_conversion_shaders[palette_format]);
|
||||
m_palette_conversion_shaders[static_cast<int>(palette_format)]);
|
||||
|
||||
VkRect2D region = {{0, 0}, {dst_entry->GetWidth(), dst_entry->GetHeight()}};
|
||||
draw.BeginRenderPass(destination_texture->GetFramebuffer(), region);
|
||||
|
||||
PSUniformBlock uniforms = {};
|
||||
uniforms.multiplier = (src_entry->format & 0xF) == GX_TF_I4 ? 15.0f : 255.0f;
|
||||
uniforms.multiplier = src_entry->format == TextureFormat::I4 ? 15.0f : 255.0f;
|
||||
uniforms.texel_buffer_offset = static_cast<int>(palette_offset / sizeof(u16));
|
||||
draw.SetPushConstants(&uniforms, sizeof(uniforms));
|
||||
draw.SetPSSampler(0, source_texture->GetRawTexIdentifier()->GetView(),
|
||||
@ -219,16 +219,15 @@ void TextureConverter::ConvertTexture(TextureCacheBase::TCacheEntry* dst_entry,
|
||||
}
|
||||
|
||||
void TextureConverter::EncodeTextureToMemory(VkImageView src_texture, u8* dest_ptr,
|
||||
const EFBCopyFormat& format, u32 native_width,
|
||||
const EFBCopyParams& params, 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)
|
||||
const EFBRectangle& src_rect, bool scale_by_half)
|
||||
{
|
||||
VkShaderModule shader = GetEncodingShader(format);
|
||||
VkShaderModule shader = GetEncodingShader(params);
|
||||
if (shader == VK_NULL_HANDLE)
|
||||
{
|
||||
ERROR_LOG(VIDEO, "Missing encoding fragment shader for format %u->%u", format.efb_format,
|
||||
static_cast<u32>(format.copy_format));
|
||||
ERROR_LOG(VIDEO, "Missing encoding fragment shader for format %u->%u",
|
||||
static_cast<unsigned>(params.efb_format), static_cast<unsigned>(params.copy_format));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -251,7 +250,7 @@ void TextureConverter::EncodeTextureToMemory(VkImageView src_texture, u8* dest_p
|
||||
// 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;
|
||||
bool linear_filter = (scale_by_half && !params.depth) || g_ActiveConfig.iEFBScale != SCALE_1X;
|
||||
draw.SetPSSampler(0, src_texture, linear_filter ? g_object_cache->GetLinearSampler() :
|
||||
g_object_cache->GetPointSampler());
|
||||
|
||||
@ -387,7 +386,7 @@ void TextureConverter::DecodeYUYVTextureFromMemory(VKTexture* dst_texture, const
|
||||
draw.EndRenderPass();
|
||||
}
|
||||
|
||||
bool TextureConverter::SupportsTextureDecoding(TextureFormat format, TlutFormat palette_format)
|
||||
bool TextureConverter::SupportsTextureDecoding(TextureFormat format, TLUTFormat palette_format)
|
||||
{
|
||||
auto key = std::make_pair(format, palette_format);
|
||||
auto iter = m_decoding_pipelines.find(key);
|
||||
@ -424,7 +423,7 @@ void TextureConverter::DecodeTexture(VkCommandBuffer command_buffer,
|
||||
TextureCache::TCacheEntry* entry, u32 dst_level,
|
||||
const u8* data, size_t data_size, TextureFormat format,
|
||||
u32 width, u32 height, u32 aligned_width, u32 aligned_height,
|
||||
u32 row_stride, const u8* palette, TlutFormat palette_format)
|
||||
u32 row_stride, const u8* palette, TLUTFormat palette_format)
|
||||
{
|
||||
VKTexture* destination_texture = static_cast<VKTexture*>(entry->texture.get());
|
||||
auto key = std::make_pair(format, palette_format);
|
||||
@ -667,21 +666,21 @@ bool TextureConverter::CompilePaletteConversionShaders()
|
||||
std::string palette_rgb5a3_program = StringFromFormat(
|
||||
"%s\n%s", "#define DECODE DecodePixel_RGB5A3", PALETTE_CONVERSION_FRAGMENT_SHADER_SOURCE);
|
||||
|
||||
m_palette_conversion_shaders[GX_TL_IA8] =
|
||||
m_palette_conversion_shaders[static_cast<int>(TLUTFormat::IA8)] =
|
||||
Util::CompileAndCreateFragmentShader(palette_ia8_program);
|
||||
m_palette_conversion_shaders[GX_TL_RGB565] =
|
||||
m_palette_conversion_shaders[static_cast<int>(TLUTFormat::RGB565)] =
|
||||
Util::CompileAndCreateFragmentShader(palette_rgb565_program);
|
||||
m_palette_conversion_shaders[GX_TL_RGB5A3] =
|
||||
m_palette_conversion_shaders[static_cast<int>(TLUTFormat::RGB5A3)] =
|
||||
Util::CompileAndCreateFragmentShader(palette_rgb5a3_program);
|
||||
|
||||
return m_palette_conversion_shaders[GX_TL_IA8] != VK_NULL_HANDLE &&
|
||||
m_palette_conversion_shaders[GX_TL_RGB565] != VK_NULL_HANDLE &&
|
||||
m_palette_conversion_shaders[GX_TL_RGB5A3] != VK_NULL_HANDLE;
|
||||
return m_palette_conversion_shaders[static_cast<int>(TLUTFormat::IA8)] != VK_NULL_HANDLE &&
|
||||
m_palette_conversion_shaders[static_cast<int>(TLUTFormat::RGB565)] != VK_NULL_HANDLE &&
|
||||
m_palette_conversion_shaders[static_cast<int>(TLUTFormat::RGB5A3)] != VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
VkShaderModule TextureConverter::CompileEncodingShader(const EFBCopyFormat& format)
|
||||
VkShaderModule TextureConverter::CompileEncodingShader(const EFBCopyParams& params)
|
||||
{
|
||||
const char* shader = TextureConversionShader::GenerateEncodingShader(format, APIType::Vulkan);
|
||||
const char* shader = TextureConversionShader::GenerateEncodingShader(params, APIType::Vulkan);
|
||||
VkShaderModule module = Util::CompileAndCreateFragmentShader(shader);
|
||||
if (module == VK_NULL_HANDLE)
|
||||
PanicAlert("Failed to compile texture encoding shader.");
|
||||
@ -689,14 +688,14 @@ VkShaderModule TextureConverter::CompileEncodingShader(const EFBCopyFormat& form
|
||||
return module;
|
||||
}
|
||||
|
||||
VkShaderModule TextureConverter::GetEncodingShader(const EFBCopyFormat& format)
|
||||
VkShaderModule TextureConverter::GetEncodingShader(const EFBCopyParams& params)
|
||||
{
|
||||
auto iter = m_encoding_shaders.find(format);
|
||||
auto iter = m_encoding_shaders.find(params);
|
||||
if (iter != m_encoding_shaders.end())
|
||||
return iter->second;
|
||||
|
||||
VkShaderModule shader = CompileEncodingShader(format);
|
||||
m_encoding_shaders.emplace(format, shader);
|
||||
VkShaderModule shader = CompileEncodingShader(params);
|
||||
m_encoding_shaders.emplace(params, shader);
|
||||
return shader;
|
||||
}
|
||||
|
||||
|
@ -33,14 +33,13 @@ public:
|
||||
// Applies palette to dst_entry, using indices from src_entry.
|
||||
void ConvertTexture(TextureCacheBase::TCacheEntry* dst_entry,
|
||||
TextureCache::TCacheEntry* src_entry, VkRenderPass render_pass,
|
||||
const void* palette, TlutFormat palette_format);
|
||||
const void* palette, TLUTFormat palette_format);
|
||||
|
||||
// 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, const EFBCopyFormat& format,
|
||||
void EncodeTextureToMemory(VkImageView src_texture, u8* dest_ptr, const EFBCopyParams& params,
|
||||
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);
|
||||
u32 memory_stride, 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,
|
||||
@ -50,11 +49,11 @@ public:
|
||||
void DecodeYUYVTextureFromMemory(VKTexture* dst_texture, const void* src_ptr, u32 src_width,
|
||||
u32 src_stride, u32 src_height);
|
||||
|
||||
bool SupportsTextureDecoding(TextureFormat format, TlutFormat palette_format);
|
||||
bool SupportsTextureDecoding(TextureFormat format, TLUTFormat palette_format);
|
||||
void DecodeTexture(VkCommandBuffer command_buffer, TextureCache::TCacheEntry* entry,
|
||||
u32 dst_level, const u8* data, size_t data_size, TextureFormat format,
|
||||
u32 width, u32 height, u32 aligned_width, u32 aligned_height, u32 row_stride,
|
||||
const u8* palette, TlutFormat palette_format);
|
||||
const u8* palette, TLUTFormat palette_format);
|
||||
|
||||
private:
|
||||
static const u32 ENCODING_TEXTURE_WIDTH = EFB_WIDTH * 4;
|
||||
@ -71,8 +70,8 @@ private:
|
||||
|
||||
bool CompilePaletteConversionShaders();
|
||||
|
||||
VkShaderModule CompileEncodingShader(const EFBCopyFormat& format);
|
||||
VkShaderModule GetEncodingShader(const EFBCopyFormat& format);
|
||||
VkShaderModule CompileEncodingShader(const EFBCopyParams& params);
|
||||
VkShaderModule GetEncodingShader(const EFBCopyParams& params);
|
||||
|
||||
bool CreateEncodingRenderPass();
|
||||
bool CreateEncodingTexture();
|
||||
@ -105,7 +104,7 @@ private:
|
||||
std::array<VkShaderModule, NUM_PALETTE_CONVERSION_SHADERS> m_palette_conversion_shaders = {};
|
||||
|
||||
// Texture encoding - RGBA8->GX format in memory
|
||||
std::map<EFBCopyFormat, VkShaderModule> m_encoding_shaders;
|
||||
std::map<EFBCopyParams, VkShaderModule> m_encoding_shaders;
|
||||
VkRenderPass m_encoding_render_pass = VK_NULL_HANDLE;
|
||||
std::unique_ptr<Texture2D> m_encoding_render_texture;
|
||||
VkFramebuffer m_encoding_render_framebuffer = VK_NULL_HANDLE;
|
||||
@ -118,7 +117,7 @@ private:
|
||||
VkShaderModule compute_shader;
|
||||
bool valid;
|
||||
};
|
||||
std::map<std::pair<TextureFormat, TlutFormat>, TextureDecodingPipeline> m_decoding_pipelines;
|
||||
std::map<std::pair<TextureFormat, TLUTFormat>, TextureDecodingPipeline> m_decoding_pipelines;
|
||||
std::unique_ptr<Texture2D> m_decoding_texture;
|
||||
|
||||
// XFB encoding/decoding shaders
|
||||
|
Reference in New Issue
Block a user