Merge pull request #2085 from degasus/ogl_paletted
OGL: support palette texture decoding
This commit is contained in:
commit
5fc62ac563
|
@ -528,6 +528,7 @@ void ProgramShaderCache::CreateHeader()
|
|||
"%s\n" // storage buffer
|
||||
"%s\n" // shader5
|
||||
"%s\n" // AEP
|
||||
"%s\n" // texture buffer
|
||||
|
||||
// Precision defines for GLSL ES
|
||||
"%s\n"
|
||||
|
@ -563,6 +564,7 @@ void ProgramShaderCache::CreateHeader()
|
|||
, g_ActiveConfig.backend_info.bSupportsBBox ? "#extension GL_ARB_shader_storage_buffer_object : enable" : ""
|
||||
, g_ActiveConfig.backend_info.bSupportsGSInstancing ? "#extension GL_ARB_gpu_shader5 : enable" : ""
|
||||
, g_ogl_config.bSupportsAEP ? "#extension GL_ANDROID_extension_pack_es31a : enable" : ""
|
||||
, v<GLSL_140 && g_ActiveConfig.backend_info.bSupportsPaletteConversion ? "#extension GL_ARB_texture_buffer_object : enable" : ""
|
||||
|
||||
, v>=GLSLES_300 ? "precision highp float;" : ""
|
||||
, v>=GLSLES_300 ? "precision highp int;" : ""
|
||||
|
|
|
@ -465,6 +465,7 @@ Renderer::Renderer()
|
|||
g_Config.backend_info.bSupportsBBox = GLExtensions::Supports("GL_ARB_shader_storage_buffer_object");
|
||||
g_Config.backend_info.bSupportsGSInstancing = GLExtensions::Supports("GL_ARB_gpu_shader5");
|
||||
g_Config.backend_info.bSupportsGeometryShaders = GLExtensions::Version() >= 320;
|
||||
g_Config.backend_info.bSupportsPaletteConversion = GLExtensions::Supports("GL_ARB_texture_buffer_object");
|
||||
|
||||
// Desktop OpenGL supports the binding layout if it supports 420pack
|
||||
// OpenGL ES 3.1 supports it implicitly without an extension
|
||||
|
@ -499,6 +500,7 @@ Renderer::Renderer()
|
|||
g_Config.backend_info.bSupportsBindingLayout = true;
|
||||
g_Config.backend_info.bSupportsEarlyZ = true;
|
||||
g_Config.backend_info.bSupportsGeometryShaders = g_ogl_config.bSupportsAEP;
|
||||
//g_Config.backend_info.bSupportsPaletteConversion = GLExtensions::Supports("GL_EXT_texture_buffer");
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "VideoBackends/OGL/GLInterfaceBase.h"
|
||||
#include "VideoBackends/OGL/ProgramShaderCache.h"
|
||||
#include "VideoBackends/OGL/Render.h"
|
||||
#include "VideoBackends/OGL/StreamBuffer.h"
|
||||
#include "VideoBackends/OGL/TextureCache.h"
|
||||
#include "VideoBackends/OGL/TextureConverter.h"
|
||||
|
||||
|
@ -43,6 +44,13 @@ static u32 s_DepthCbufid;
|
|||
static u32 s_Textures[8];
|
||||
static u32 s_ActiveTexture;
|
||||
|
||||
static SHADER s_palette_pixel_shader[3];
|
||||
static StreamBuffer* s_palette_stream_buffer = nullptr;
|
||||
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];
|
||||
|
||||
bool SaveTexture(const std::string& filename, u32 textarget, u32 tex, int virtual_width, int virtual_height, unsigned int level)
|
||||
{
|
||||
if (GLInterface->GetMode() != GLInterfaceMode::MODE_OPENGL)
|
||||
|
@ -237,12 +245,27 @@ TextureCache::TextureCache()
|
|||
s_ActiveTexture = -1;
|
||||
for (auto& gtex : s_Textures)
|
||||
gtex = -1;
|
||||
|
||||
if (g_ActiveConfig.backend_info.bSupportsPaletteConversion)
|
||||
{
|
||||
s_palette_stream_buffer = StreamBuffer::Create(GL_TEXTURE_BUFFER, 1024*1024);
|
||||
glGenTextures(1, &s_palette_resolv_texture);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, s_palette_resolv_texture);
|
||||
glTexBuffer(GL_TEXTURE_BUFFER, GL_R16UI, s_palette_stream_buffer->m_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TextureCache::~TextureCache()
|
||||
{
|
||||
DeleteShaders();
|
||||
|
||||
if (g_ActiveConfig.backend_info.bSupportsPaletteConversion)
|
||||
{
|
||||
delete s_palette_stream_buffer;
|
||||
s_palette_stream_buffer = nullptr;
|
||||
glDeleteTextures(1, &s_palette_resolv_texture);
|
||||
}
|
||||
}
|
||||
|
||||
void TextureCache::DisableStage(unsigned int stage)
|
||||
|
@ -347,18 +370,161 @@ void TextureCache::CompileShaders()
|
|||
|
||||
s_ColorCopyPositionUniform = glGetUniformLocation(s_ColorMatrixProgram.glprogid, "copy_position");
|
||||
s_DepthCopyPositionUniform = glGetUniformLocation(s_DepthMatrixProgram.glprogid, "copy_position");
|
||||
|
||||
std::string palette_shader =
|
||||
R"GLSL(
|
||||
uniform int texture_buffer_offset;
|
||||
uniform float multiplier;
|
||||
SAMPLER_BINDING(9) uniform sampler2DArray samp9;
|
||||
SAMPLER_BINDING(10) uniform usamplerBuffer samp10;
|
||||
|
||||
in vec3 f_uv0;
|
||||
out vec4 ocol0;
|
||||
|
||||
int Convert3To8(int v)
|
||||
{
|
||||
// Swizzle bits: 00000123 -> 12312312
|
||||
return (v << 5) | (v << 2) | (v >> 1);
|
||||
}
|
||||
|
||||
int Convert4To8(int v)
|
||||
{
|
||||
// Swizzle bits: 00001234 -> 12341234
|
||||
return (v << 4) | v;
|
||||
}
|
||||
|
||||
int Convert5To8(int v)
|
||||
{
|
||||
// Swizzle bits: 00012345 -> 12345123
|
||||
return (v << 3) | (v >> 2);
|
||||
}
|
||||
|
||||
int Convert6To8(int v)
|
||||
{
|
||||
// Swizzle bits: 00123456 -> 12345612
|
||||
return (v << 2) | (v >> 4);
|
||||
}
|
||||
|
||||
float4 DecodePixel_RGB5A3(int val)
|
||||
{
|
||||
int r,g,b,a;
|
||||
if ((val&0x8000) > 0)
|
||||
{
|
||||
r=Convert5To8((val>>10) & 0x1f);
|
||||
g=Convert5To8((val>>5 ) & 0x1f);
|
||||
b=Convert5To8((val ) & 0x1f);
|
||||
a=0xFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
a=Convert3To8((val>>12) & 0x7);
|
||||
r=Convert4To8((val>>8 ) & 0xf);
|
||||
g=Convert4To8((val>>4 ) & 0xf);
|
||||
b=Convert4To8((val ) & 0xf);
|
||||
}
|
||||
return float4(r, g, b, a) / 255.0;
|
||||
}
|
||||
|
||||
float4 DecodePixel_RGB565(int val)
|
||||
{
|
||||
int r, g, b, a;
|
||||
r = Convert5To8((val >> 11) & 0x1f);
|
||||
g = Convert6To8((val >> 5) & 0x3f);
|
||||
b = Convert5To8((val) & 0x1f);
|
||||
a = 0xFF;
|
||||
return float4(r, g, b, a) / 255.0;
|
||||
}
|
||||
|
||||
float4 DecodePixel_IA8(int val)
|
||||
{
|
||||
int i = val & 0xFF;
|
||||
int a = val >> 8;
|
||||
return float4(i, i, i, a) / 255.0;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
int src = int(round(texture(samp9, f_uv0).r * multiplier));
|
||||
src = int(texelFetch(samp10, src + texture_buffer_offset).r);
|
||||
src = ((src << 8) & 0xFF00) | (src >> 8);
|
||||
ocol0 = DECODE(src);
|
||||
}
|
||||
)GLSL";
|
||||
|
||||
if (g_ActiveConfig.backend_info.bSupportsPaletteConversion)
|
||||
{
|
||||
ProgramShaderCache::CompileShader(
|
||||
s_palette_pixel_shader[GX_TL_IA8],
|
||||
StringFromFormat(VProgram, prefix, prefix).c_str(),
|
||||
("#define DECODE DecodePixel_IA8" + palette_shader).c_str(),
|
||||
GProgram);
|
||||
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");
|
||||
|
||||
ProgramShaderCache::CompileShader(
|
||||
s_palette_pixel_shader[GX_TL_RGB565],
|
||||
StringFromFormat(VProgram, prefix, prefix).c_str(),
|
||||
("#define DECODE DecodePixel_RGB565" + palette_shader).c_str(),
|
||||
GProgram);
|
||||
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");
|
||||
|
||||
ProgramShaderCache::CompileShader(
|
||||
s_palette_pixel_shader[GX_TL_RGB5A3],
|
||||
StringFromFormat(VProgram, prefix, prefix).c_str(),
|
||||
("#define DECODE DecodePixel_RGB5A3" + palette_shader).c_str(),
|
||||
GProgram);
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
void TextureCache::DeleteShaders()
|
||||
{
|
||||
s_ColorMatrixProgram.Destroy();
|
||||
s_DepthMatrixProgram.Destroy();
|
||||
|
||||
if (g_ActiveConfig.backend_info.bSupportsPaletteConversion)
|
||||
for (auto& shader : s_palette_pixel_shader)
|
||||
shader.Destroy();
|
||||
}
|
||||
|
||||
void TextureCache::ConvertTexture(TextureCache::TCacheEntryBase* entry, TCacheEntryBase* unconverted, void* palette, TlutFormat format)
|
||||
void TextureCache::ConvertTexture(TCacheEntryBase* _entry, TCacheEntryBase* _unconverted, void* palette, TlutFormat format)
|
||||
{
|
||||
// TODO: Implement.
|
||||
return;
|
||||
if (!g_ActiveConfig.backend_info.bSupportsPaletteConversion)
|
||||
return;
|
||||
|
||||
g_renderer->ResetAPIState();
|
||||
|
||||
TCacheEntry* entry = (TCacheEntry*) _entry;
|
||||
TCacheEntry* unconverted = (TCacheEntry*) _unconverted;
|
||||
|
||||
glActiveTexture(GL_TEXTURE0 + 9);
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, unconverted->texture);
|
||||
|
||||
FramebufferManager::SetFramebuffer(entry->framebuffer);
|
||||
glViewport(0, 0, entry->config.width, entry->config.height);
|
||||
s_palette_pixel_shader[format].Bind();
|
||||
|
||||
int size = unconverted->format == 0 ? 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], unconverted->format == 0 ? 15.0f : 255.0f);
|
||||
glUniform4f(s_palette_copy_position_uniform[format], 0.0f, 0.0f, (float)unconverted->config.width, (float)unconverted->config.height);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0 + 10);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, s_palette_resolv_texture);
|
||||
|
||||
OpenGL_BindAttributelessVAO();
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
FramebufferManager::SetFramebuffer(0);
|
||||
g_renderer->RestoreAPIState();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -134,13 +134,10 @@ static void InitBackendInfo()
|
|||
{
|
||||
g_Config.backend_info.APIType = API_OPENGL;
|
||||
g_Config.backend_info.bSupportsExclusiveFullscreen = false;
|
||||
//g_Config.backend_info.bSupportsDualSourceBlend = true; // is GPU dependent and must be set in renderer
|
||||
//g_Config.backend_info.bSupportsEarlyZ = true; // is GPU dependent and must be set in renderer
|
||||
g_Config.backend_info.bSupportsOversizedViewports = true;
|
||||
g_Config.backend_info.bSupportsGeometryShaders = true;
|
||||
g_Config.backend_info.bSupports3DVision = false;
|
||||
g_Config.backend_info.bSupportsPostProcessing = true;
|
||||
g_Config.backend_info.bSupportsPaletteConversion = false;
|
||||
|
||||
g_Config.backend_info.Adapters.clear();
|
||||
|
||||
|
|
Loading…
Reference in New Issue