Merge pull request #5849 from beholdnec/tex-format-bookkeeping

Video: Clearly separate Texture and EFB Copy formats
This commit is contained in:
Anthony
2017-08-04 22:34:34 -07:00
committed by GitHub
27 changed files with 1275 additions and 1319 deletions
@@ -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, &params, 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;
};
}
+13 -12
View File
@@ -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, &params, 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");
+5 -5
View File
@@ -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
{
}
+54 -53
View File
@@ -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);
+7 -7
View File
@@ -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
+6 -1
View File
@@ -9,6 +9,8 @@
#include "Common/BitField.h"
#include "Common/CommonTypes.h"
enum class EFBCopyFormat;
#pragma pack(4)
enum
@@ -958,7 +960,10 @@ union UPE_Copy
BitField<16, 1, u32>
auto_conv; // if 0 automatic color conversion by texture format and pixel type
u32 tp_realFormat() const { return target_pixel_format / 2 + (target_pixel_format & 1) * 8; }
EFBCopyFormat tp_realFormat() const
{
return static_cast<EFBCopyFormat>(target_pixel_format / 2 + (target_pixel_format & 1) * 8);
}
};
union BPU_PreloadTileInfo
+3 -2
View File
@@ -215,7 +215,7 @@ void HiresTexture::Prefetch()
}
std::string HiresTexture::GenBaseName(const u8* texture, size_t texture_size, const u8* tlut,
size_t tlut_size, u32 width, u32 height, int format,
size_t tlut_size, u32 width, u32 height, TextureFormat format,
bool has_mipmaps, bool dump)
{
std::string name = "";
@@ -385,7 +385,8 @@ u32 HiresTexture::CalculateMipCount(u32 width, u32 height)
std::shared_ptr<HiresTexture> HiresTexture::Search(const u8* texture, size_t texture_size,
const u8* tlut, size_t tlut_size, u32 width,
u32 height, int format, bool has_mipmaps)
u32 height, TextureFormat format,
bool has_mipmaps)
{
std::string base_filename =
GenBaseName(texture, texture_size, tlut, tlut_size, width, height, format, has_mipmaps);
+4 -2
View File
@@ -11,6 +11,8 @@
#include "Common/CommonTypes.h"
#include "VideoCommon/TextureConfig.h"
enum class TextureFormat;
class HiresTexture
{
public:
@@ -22,10 +24,10 @@ public:
static std::shared_ptr<HiresTexture> Search(const u8* texture, size_t texture_size,
const u8* tlut, size_t tlut_size, u32 width,
u32 height, int format, bool has_mipmaps);
u32 height, TextureFormat format, bool has_mipmaps);
static std::string GenBaseName(const u8* texture, size_t texture_size, const u8* tlut,
size_t tlut_size, u32 width, u32 height, int format,
size_t tlut_size, u32 width, u32 height, TextureFormat format,
bool has_mipmaps, bool dump = false);
static u32 CalculateMipCount(u32 width, u32 height);
+71 -97
View File
@@ -226,8 +226,8 @@ void TextureCacheBase::SetBackupConfig(const VideoConfig& config)
backup_config.gpu_texture_decoding = config.bEnableGPUTextureDecoding;
}
TextureCacheBase::TCacheEntry* TextureCacheBase::ApplyPaletteToEntry(TCacheEntry* entry,
u8* palette, u32 tlutfmt)
TextureCacheBase::TCacheEntry*
TextureCacheBase::ApplyPaletteToEntry(TCacheEntry* entry, u8* palette, TLUTFormat tlutfmt)
{
TextureConfig new_config = entry->texture->GetConfig();
new_config.levels = 1;
@@ -243,7 +243,7 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::ApplyPaletteToEntry(TCacheEntry
decoded_entry->frameCount = FRAMECOUNT_INVALID;
decoded_entry->is_efb_copy = false;
ConvertTexture(decoded_entry, entry, palette, static_cast<TlutFormat>(tlutfmt));
ConvertTexture(decoded_entry, entry, palette, tlutfmt);
textures_by_address.emplace(entry->addr, decoded_entry);
return decoded_entry;
@@ -290,7 +290,8 @@ void TextureCacheBase::ScaleTextureCacheEntryTo(TextureCacheBase::TCacheEntry* e
}
TextureCacheBase::TCacheEntry*
TextureCacheBase::DoPartialTextureUpdates(TCacheEntry* entry_to_update, u8* palette, u32 tlutfmt)
TextureCacheBase::DoPartialTextureUpdates(TCacheEntry* entry_to_update, u8* palette,
TLUTFormat tlutfmt)
{
// If the flag may_have_overlapping_textures is cleared, there are no overlapping EFB copies,
// which aren't applied already. It is set for new textures, and for the affected range
@@ -299,19 +300,17 @@ TextureCacheBase::DoPartialTextureUpdates(TCacheEntry* entry_to_update, u8* pale
return entry_to_update;
entry_to_update->may_have_overlapping_textures = false;
const bool isPaletteTexture =
(entry_to_update->format == GX_TF_C4 || entry_to_update->format == GX_TF_C8 ||
entry_to_update->format == GX_TF_C14X2 || entry_to_update->format >= 0x10000);
const bool isPaletteTexture = IsColorIndexed(entry_to_update->format.texfmt);
// EFB copies are excluded from these updates, until there's an example where a game would
// benefit from updating. This would require more work to be done.
if (entry_to_update->IsEfbCopy())
return entry_to_update;
u32 block_width = TexDecoder_GetBlockWidthInTexels(entry_to_update->format & 0xf);
u32 block_height = TexDecoder_GetBlockHeightInTexels(entry_to_update->format & 0xf);
u32 block_width = TexDecoder_GetBlockWidthInTexels(entry_to_update->format.texfmt);
u32 block_height = TexDecoder_GetBlockHeightInTexels(entry_to_update->format.texfmt);
u32 block_size = block_width * block_height *
TexDecoder_GetTexelSizeInNibbles(entry_to_update->format & 0xf) / 2;
TexDecoder_GetTexelSizeInNibbles(entry_to_update->format.texfmt) / 2;
u32 numBlocksX = (entry_to_update->native_width + block_width - 1) / block_width;
@@ -490,9 +489,9 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::Load(const u32 stage)
const u32 address = (tex.texImage3[id].image_base /* & 0x1FFFFF*/) << 5;
u32 width = tex.texImage0[id].width + 1;
u32 height = tex.texImage0[id].height + 1;
const int texformat = tex.texImage0[id].format;
const TextureFormat texformat = static_cast<TextureFormat>(tex.texImage0[id].format);
const u32 tlutaddr = tex.texTlut[id].tmem_offset << 9;
const u32 tlutfmt = tex.texTlut[id].tlut_format;
const TLUTFormat tlutfmt = static_cast<TLUTFormat>(tex.texTlut[id].tlut_format);
const bool use_mipmaps = SamplerCommon::AreBpTexMode0MipmapsEnabled(tex.texMode0[id]);
u32 tex_levels = use_mipmaps ? ((tex.texMode1[id].max_lod + 0xf) / 0x10 + 1) : 1;
const bool from_tmem = tex.texImage1[id].image_type != 0;
@@ -511,18 +510,14 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::Load(const u32 stage)
u64 base_hash = TEXHASH_INVALID;
u64 full_hash = TEXHASH_INVALID;
u32 full_format = texformat;
TextureAndTLUTFormat full_format(texformat, tlutfmt);
const bool isPaletteTexture =
(texformat == GX_TF_C4 || texformat == GX_TF_C8 || texformat == GX_TF_C14X2);
const bool isPaletteTexture = IsColorIndexed(texformat);
// Reject invalid tlut format.
if (isPaletteTexture && tlutfmt > GX_TL_RGB5A3)
if (isPaletteTexture && !IsValidTLUTFormat(tlutfmt))
return nullptr;
if (isPaletteTexture)
full_format = texformat | (tlutfmt << 16);
const u32 texture_size =
TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, texformat);
u32 bytes_per_block = (bsw * bsh * TexDecoder_GetTexelSizeInNibbles(texformat)) / 2;
@@ -766,11 +761,9 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::Load(const u32 stage)
// banks, and if we're doing an copy we may as well just do the whole thing on the CPU, since
// there's no conversion between formats. In the future this could be extended with a separate
// shader, however.
bool decode_on_gpu =
!hires_tex && g_ActiveConfig.UseGPUTextureDecoding() &&
g_texture_cache->SupportsGPUTextureDecode(static_cast<TextureFormat>(texformat),
static_cast<TlutFormat>(tlutfmt)) &&
!(from_tmem && texformat == GX_TF_RGBA8);
bool decode_on_gpu = !hires_tex && g_ActiveConfig.UseGPUTextureDecoding() &&
g_texture_cache->SupportsGPUTextureDecode(texformat, tlutfmt) &&
!(from_tmem && texformat == TextureFormat::RGBA8);
// create the entry/texture
TextureConfig config;
@@ -796,18 +789,16 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::Load(const u32 stage)
if (!hires_tex && decode_on_gpu)
{
u32 row_stride = bytes_per_block * (expandedWidth / bsw);
g_texture_cache->DecodeTextureOnGPU(
entry, 0, src_data, texture_size, static_cast<TextureFormat>(texformat), width, height,
expandedWidth, expandedHeight, row_stride, tlut, static_cast<TlutFormat>(tlutfmt));
g_texture_cache->DecodeTextureOnGPU(entry, 0, src_data, texture_size, texformat, width, height,
expandedWidth, expandedHeight, row_stride, tlut, tlutfmt);
}
else if (!hires_tex)
{
size_t decoded_texture_size = expandedWidth * sizeof(u32) * expandedHeight;
CheckTempSize(decoded_texture_size);
if (!(texformat == GX_TF_RGBA8 && from_tmem))
if (!(texformat == TextureFormat::RGBA8 && from_tmem))
{
TexDecoder_Decode(temp, src_data, expandedWidth, expandedHeight, texformat, tlut,
(TlutFormat)tlutfmt);
TexDecoder_Decode(temp, src_data, expandedWidth, expandedHeight, texformat, tlut, tlutfmt);
}
else
{
@@ -878,17 +869,16 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::Load(const u32 stage)
if (decode_on_gpu)
{
u32 row_stride = bytes_per_block * (expanded_mip_width / bsw);
g_texture_cache->DecodeTextureOnGPU(entry, level, mip_src_data, mip_size,
static_cast<TextureFormat>(texformat), mip_width,
mip_height, expanded_mip_width, expanded_mip_height,
row_stride, tlut, static_cast<TlutFormat>(tlutfmt));
g_texture_cache->DecodeTextureOnGPU(entry, level, mip_src_data, mip_size, texformat,
mip_width, mip_height, expanded_mip_width,
expanded_mip_height, row_stride, tlut, tlutfmt);
}
else
{
// No need to call CheckTempSize here, as mips will always be smaller than the base level.
size_t decoded_mip_size = expanded_mip_width * sizeof(u32) * expanded_mip_height;
TexDecoder_Decode(temp, mip_src_data, expanded_mip_width, expanded_mip_height, texformat,
tlut, (TlutFormat)tlutfmt);
tlut, tlutfmt);
entry->texture->Load(level, mip_width, mip_height, expanded_mip_width, temp,
decoded_mip_size);
}
@@ -908,9 +898,10 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::Load(const u32 stage)
return ReturnEntry(stage, entry);
}
void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat, u32 dstStride,
bool is_depth_copy, const EFBRectangle& srcRect,
bool isIntensity, bool scaleByHalf)
void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, EFBCopyFormat dstFormat,
u32 dstStride, bool is_depth_copy,
const EFBRectangle& srcRect, bool isIntensity,
bool scaleByHalf)
{
// Emulation methods:
//
@@ -980,81 +971,73 @@ 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 = UINT_MAX;
u32 srcFormat = bpmem.zcontrol.pixel_format;
PEControl::PixelFormat srcFormat = bpmem.zcontrol.pixel_format;
bool efbHasAlpha = srcFormat == PEControl::RGBA6_Z24;
if (is_depth_copy)
{
switch (dstFormat)
{
case 0: // Z4
case EFBCopyFormat::R4: // Z4
colmat[3] = colmat[7] = colmat[11] = colmat[15] = 1.0f;
cbufid = 0;
dstFormat |= _GX_TF_CTF;
break;
case 8: // Z8H
dstFormat |= _GX_TF_CTF;
case 1: // Z8
case EFBCopyFormat::R8_0x1: // Z8
case EFBCopyFormat::R8: // Z8H
colmat[0] = colmat[4] = colmat[8] = colmat[12] = 1.0f;
cbufid = 1;
break;
case 3: // Z16
case EFBCopyFormat::RA8: // Z16
colmat[1] = colmat[5] = colmat[9] = colmat[12] = 1.0f;
cbufid = 2;
break;
case 11: // Z16 (reverse order)
case EFBCopyFormat::RG8: // Z16 (reverse order)
colmat[0] = colmat[4] = colmat[8] = colmat[13] = 1.0f;
cbufid = 3;
dstFormat |= _GX_TF_CTF;
break;
case 6: // Z24X8
case EFBCopyFormat::RGBA8: // Z24X8
colmat[0] = colmat[5] = colmat[10] = 1.0f;
cbufid = 4;
break;
case 9: // Z8M
case EFBCopyFormat::G8: // Z8M
colmat[1] = colmat[5] = colmat[9] = colmat[13] = 1.0f;
cbufid = 5;
dstFormat |= _GX_TF_CTF;
break;
case 10: // Z8L
case EFBCopyFormat::B8: // Z8L
colmat[2] = colmat[6] = colmat[10] = colmat[14] = 1.0f;
cbufid = 6;
dstFormat |= _GX_TF_CTF;
break;
case 12: // Z16L - copy lower 16 depth bits
case EFBCopyFormat::GB8: // Z16L - copy lower 16 depth bits
// expected to be used as an IA8 texture (upper 8 bits stored as intensity, lower 8 bits
// stored as alpha)
// Used e.g. in Zelda: Skyward Sword
colmat[1] = colmat[5] = colmat[9] = colmat[14] = 1.0f;
cbufid = 7;
dstFormat |= _GX_TF_CTF;
break;
default:
ERROR_LOG(VIDEO, "Unknown copy zbuf format: 0x%x", dstFormat);
ERROR_LOG(VIDEO, "Unknown copy zbuf format: 0x%X", static_cast<int>(dstFormat));
colmat[2] = colmat[5] = colmat[8] = 1.0f;
cbufid = 8;
break;
}
dstFormat |= _GX_TF_ZTF;
}
else if (isIntensity)
{
fConstAdd[0] = fConstAdd[1] = fConstAdd[2] = 16.0f / 255.0f;
switch (dstFormat)
{
case 0: // I4
case 1: // I8
case 2: // IA4
case 3: // IA8
case 8: // I8
case EFBCopyFormat::R4: // I4
case EFBCopyFormat::R8_0x1: // I8
case EFBCopyFormat::R8: // IA4
case EFBCopyFormat::RA4: // IA8
case EFBCopyFormat::RA8: // I8
// TODO - verify these coefficients
colmat[0] = 0.257f;
colmat[1] = 0.504f;
@@ -1066,13 +1049,14 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFo
colmat[9] = 0.504f;
colmat[10] = 0.098f;
if (dstFormat < 2 || dstFormat == 8)
if (dstFormat == EFBCopyFormat::R4 || dstFormat == EFBCopyFormat::R8_0x1 ||
dstFormat == EFBCopyFormat::R8)
{
colmat[12] = 0.257f;
colmat[13] = 0.504f;
colmat[14] = 0.098f;
fConstAdd[3] = 16.0f / 255.0f;
if (dstFormat == 0)
if (dstFormat == EFBCopyFormat::R4)
{
ColorMask[0] = ColorMask[1] = ColorMask[2] = 255.0f / 16.0f;
ColorMask[4] = ColorMask[5] = ColorMask[6] = 1.0f / 15.0f;
@@ -1086,7 +1070,7 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFo
else // alpha
{
colmat[15] = 1;
if (dstFormat == 2)
if (dstFormat == EFBCopyFormat::RA4)
{
ColorMask[0] = ColorMask[1] = ColorMask[2] = ColorMask[3] = 255.0f / 16.0f;
ColorMask[4] = ColorMask[5] = ColorMask[6] = ColorMask[7] = 1.0f / 15.0f;
@@ -1100,7 +1084,7 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFo
break;
default:
ERROR_LOG(VIDEO, "Unknown copy intensity format: 0x%x", dstFormat);
ERROR_LOG(VIDEO, "Unknown copy intensity format: 0x%X", static_cast<int>(dstFormat));
colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1.0f;
cbufid = 13;
break;
@@ -1110,21 +1094,19 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFo
{
switch (dstFormat)
{
case 0: // R4
case EFBCopyFormat::R4: // R4
colmat[0] = colmat[4] = colmat[8] = colmat[12] = 1;
ColorMask[0] = 255.0f / 16.0f;
ColorMask[4] = 1.0f / 15.0f;
cbufid = 14;
dstFormat |= _GX_TF_CTF;
break;
case 1: // R8
case 8: // R8
case EFBCopyFormat::R8_0x1: // R8
case EFBCopyFormat::R8: // R8
colmat[0] = colmat[4] = colmat[8] = colmat[12] = 1;
cbufid = 15;
dstFormat = GX_CTF_R8;
break;
case 2: // RA4
case EFBCopyFormat::RA4: // RA4
colmat[0] = colmat[4] = colmat[8] = colmat[15] = 1.0f;
ColorMask[0] = ColorMask[3] = 255.0f / 16.0f;
ColorMask[4] = ColorMask[7] = 1.0f / 15.0f;
@@ -1136,9 +1118,8 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFo
fConstAdd[3] = 1.0f;
cbufid = 17;
}
dstFormat |= _GX_TF_CTF;
break;
case 3: // RA8
case EFBCopyFormat::RA8: // RA8
colmat[0] = colmat[4] = colmat[8] = colmat[15] = 1.0f;
cbufid = 18;
@@ -1148,10 +1129,9 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFo
fConstAdd[3] = 1.0f;
cbufid = 19;
}
dstFormat |= _GX_TF_CTF;
break;
case 7: // A8
case EFBCopyFormat::A8: // A8
colmat[3] = colmat[7] = colmat[11] = colmat[15] = 1.0f;
cbufid = 20;
@@ -1164,33 +1144,28 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFo
fConstAdd[3] = 1.0f;
cbufid = 21;
}
dstFormat |= _GX_TF_CTF;
break;
case 9: // G8
case EFBCopyFormat::G8: // G8
colmat[1] = colmat[5] = colmat[9] = colmat[13] = 1.0f;
cbufid = 22;
dstFormat |= _GX_TF_CTF;
break;
case 10: // B8
case EFBCopyFormat::B8: // B8
colmat[2] = colmat[6] = colmat[10] = colmat[14] = 1.0f;
cbufid = 23;
dstFormat |= _GX_TF_CTF;
break;
case 11: // RG8
case EFBCopyFormat::RG8: // RG8
colmat[0] = colmat[4] = colmat[8] = colmat[13] = 1.0f;
cbufid = 24;
dstFormat |= _GX_TF_CTF;
break;
case 12: // GB8
case EFBCopyFormat::GB8: // GB8
colmat[1] = colmat[5] = colmat[9] = colmat[14] = 1.0f;
cbufid = 25;
dstFormat |= _GX_TF_CTF;
break;
case 4: // RGB565
case EFBCopyFormat::RGB565: // RGB565
colmat[0] = colmat[5] = colmat[10] = 1.0f;
ColorMask[0] = ColorMask[2] = 255.0f / 8.0f;
ColorMask[4] = ColorMask[6] = 1.0f / 31.0f;
@@ -1200,7 +1175,7 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFo
cbufid = 26;
break;
case 5: // RGB5A3
case EFBCopyFormat::RGB5A3: // RGB5A3
colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1.0f;
ColorMask[0] = ColorMask[1] = ColorMask[2] = 255.0f / 8.0f;
ColorMask[4] = ColorMask[5] = ColorMask[6] = 1.0f / 31.0f;
@@ -1215,7 +1190,7 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFo
cbufid = 28;
}
break;
case 6: // RGBA8
case EFBCopyFormat::RGBA8: // RGBA8
colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1.0f;
cbufid = 29;
@@ -1228,7 +1203,7 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFo
break;
default:
ERROR_LOG(VIDEO, "Unknown copy color format: 0x%x", dstFormat);
ERROR_LOG(VIDEO, "Unknown copy color format: 0x%X", static_cast<int>(dstFormat));
colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1.0f;
cbufid = 31;
break;
@@ -1267,7 +1242,7 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFo
}
// Get the base (in memory) format of this efb copy.
int baseFormat = TexDecoder_GetEfbCopyBaseFormat(dstFormat);
TextureFormat baseFormat = TexDecoder_GetEFBCopyBaseFormat(dstFormat);
u32 blockH = TexDecoder_GetBlockHeightInTexels(baseFormat);
const u32 blockW = TexDecoder_GetBlockWidthInTexels(baseFormat);
@@ -1280,7 +1255,7 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFo
const u32 num_blocks_x = actualWidth / blockW;
// RGBA takes two cache lines per block; all others take one
const u32 bytes_per_block = baseFormat == GX_TF_RGBA8 ? 64 : 32;
const u32 bytes_per_block = baseFormat == TextureFormat::RGBA8 ? 64 : 32;
const u32 bytes_per_row = num_blocks_x * bytes_per_block;
const u32 covered_range = num_blocks_y * dstStride;
@@ -1290,9 +1265,8 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFo
if (copy_to_ram)
{
EFBCopyFormat format(srcFormat, static_cast<TextureFormat>(dstFormat));
CopyEFB(dst, format, tex_w, bytes_per_row, num_blocks_y, dstStride, is_depth_copy, srcRect,
scaleByHalf);
EFBCopyParams format(srcFormat, dstFormat, is_depth_copy, isIntensity);
CopyEFB(dst, format, tex_w, bytes_per_row, num_blocks_y, dstStride, srcRect, scaleByHalf);
}
else
{
@@ -1510,7 +1484,7 @@ TextureCacheBase::InvalidateTexture(TexAddrCache::iterator iter)
u32 TextureCacheBase::TCacheEntry::BytesPerRow() const
{
const u32 blockW = TexDecoder_GetBlockWidthInTexels(format);
const u32 blockW = TexDecoder_GetBlockWidthInTexels(format.texfmt);
// Round up source height to multiple of block size
const u32 actualWidth = Common::AlignUp(native_width, blockW);
@@ -1518,14 +1492,14 @@ u32 TextureCacheBase::TCacheEntry::BytesPerRow() const
const u32 numBlocksX = actualWidth / blockW;
// RGBA takes two cache lines per block; all others take one
const u32 bytes_per_block = format == GX_TF_RGBA8 ? 64 : 32;
const u32 bytes_per_block = format == TextureFormat::RGBA8 ? 64 : 32;
return numBlocksX * bytes_per_block;
}
u32 TextureCacheBase::TCacheEntry::NumBlocksY() const
{
u32 blockH = TexDecoder_GetBlockHeightInTexels(format);
u32 blockH = TexDecoder_GetBlockHeightInTexels(format.texfmt);
// Round up source height to multiple of block size
u32 actualHeight = Common::AlignUp(native_height, blockH);

Some files were not shown because too many files have changed in this diff Show More