Skip to content
Permalink
Browse files
Merge pull request #5849 from beholdnec/tex-format-bookkeeping
Video: Clearly separate Texture and EFB Copy formats
  • Loading branch information
Helios747 committed Aug 5, 2017
2 parents 20d7180 + c3a57bb commit 737e045
Show file tree
Hide file tree
Showing 27 changed files with 1,279 additions and 1,323 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,19 +32,19 @@ class PSTextureEncoder final

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;

ID3D11Texture2D* m_out;
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, &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");
@@ -28,12 +28,12 @@ class TextureCache : public TextureCacheBase
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 @@ class TextureCache : public TextureCacheBase
~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);

0 comments on commit 737e045

Please sign in to comment.