GPU: Use texel fetch for creating page textures

This commit is contained in:
Connor McLaughlin 2019-09-14 23:18:39 +10:00
parent 19d9322e67
commit b5d51f47cd
3 changed files with 30 additions and 53 deletions

View file

@ -409,8 +409,8 @@ bool GPU::HandleRenderCommand()
ZeroExtend32(words_per_vertex)); ZeroExtend32(words_per_vertex));
DispatchRenderCommand(rc, num_vertices); DispatchRenderCommand(rc, num_vertices);
FlushRender(); //FlushRender();
UpdateDisplay(); //UpdateDisplay();
return true; return true;
} }
@ -535,7 +535,7 @@ void GPU::TextureConfig::SetFromPageAttribute(u16 value)
if (page_attribute == value) if (page_attribute == value)
return; return;
base_x = static_cast<s32>(ZeroExtend32(value & UINT16_C(0x1FF)) * UINT32_C(64)); base_x = static_cast<s32>(ZeroExtend32(value & UINT16_C(0x0F)) * UINT32_C(64));
base_y = static_cast<s32>(ZeroExtend32((value >> 11) & UINT16_C(1)) * UINT32_C(512)); base_y = static_cast<s32>(ZeroExtend32((value >> 11) & UINT16_C(1)) * UINT32_C(512));
page_attribute = value; page_attribute = value;
page_changed = true; page_changed = true;

View file

@ -123,13 +123,19 @@ static void DefineMacro(std::stringstream& ss, const char* name, bool enabled)
void GPU_HW::GenerateShaderHeader(std::stringstream& ss) void GPU_HW::GenerateShaderHeader(std::stringstream& ss)
{ {
ss << "#version 330 core\n\n"; ss << "#version 330 core\n\n";
ss << "const vec2 vram_size = vec2(float(" << VRAM_WIDTH << "), float(" << VRAM_HEIGHT << "));\n"; ss << "const ivec2 VRAM_SIZE = ivec2(" << VRAM_WIDTH << ", " << VRAM_HEIGHT << ");\n";
ss << "const vec2 rcp_vram_size = vec2(1.0, 1.0) / vram_size;\n"; ss << "const ivec2 VRAM_COORD_MASK = ivec2(" << (VRAM_WIDTH - 1) << ", " << (VRAM_HEIGHT - 1) << ");\n";
ss << "const vec2 RCP_VRAM_SIZE = vec2(1.0, 1.0) / vec2(VRAM_SIZE);\n";
ss << R"( ss << R"(
float fixYCoord(float y) float fixYCoord(float y)
{ {
return 1.0 - rcp_vram_size.y - y; return 1.0 - RCP_VRAM_SIZE.y - y;
}
int fixYCoord(int y)
{
return VRAM_SIZE.y - y - 1;
} }
uint RGBA8ToRGBA5551(vec4 v) uint RGBA8ToRGBA5551(vec4 v)
@ -179,7 +185,7 @@ void main()
v_col0 = a_col0; v_col0 = a_col0;
#if TEXTURED #if TEXTURED
v_tex0 = vec2(a_tex0 * u_tex_scale); v_tex0 = a_tex0;
#endif #endif
} }
)"; )";
@ -255,10 +261,10 @@ std::string GPU_HW::GenerateTexturePageFragmentShader(TextureColorMode mode)
ss << R"( ss << R"(
uniform sampler2D samp0; uniform sampler2D samp0;
uniform vec2 base_offset; uniform ivec2 base_offset;
#if PALETTE #if PALETTE
uniform vec2 palette_offset; uniform ivec2 palette_offset;
#endif #endif
in vec2 v_tex0; in vec2 v_tex0;
@ -266,33 +272,32 @@ out vec4 o_col0;
void main() void main()
{ {
ivec2 local_coords = ivec2(gl_FragCoord.xy);
#if PALETTE_4_BIT #if PALETTE_4_BIT
vec2 local_coords = vec2(v_tex0.x / 4.0, v_tex0.y); local_coords.x /= 4;
#elif PALETTE_8_BIT #elif PALETTE_8_BIT
vec2 local_coords = vec2(v_tex0.x / 2.0, v_tex0.y); local_coords.x /= 2;
#else
vec2 local_coords = v_tex0;
#endif #endif
// fixup coords // fixup coords
vec2 coords = vec2(local_coords.x + base_offset.x, fixYCoord(local_coords.y + base_offset.y)); ivec2 coords = ivec2(base_offset.x + local_coords.x, fixYCoord(base_offset.y + local_coords.y));
// load colour/palette // load colour/palette
vec4 color = texture(samp0, coords); vec4 color = texelFetch(samp0, coords & VRAM_COORD_MASK, 0);
// apply palette // apply palette
#if PALETTE #if PALETTE
#if PALETTE_4_BIT #if PALETTE_4_BIT
uint subpixel = uint(gl_FragCoord.x) & 3u; int subpixel = int(gl_FragCoord.x) & 3;
uint vram_value = RGBA8ToRGBA5551(color); uint vram_value = RGBA8ToRGBA5551(color);
float palette_index = float((vram_value >> (subpixel * 4u)) & 0x0Fu) * rcp_vram_size.x; int palette_index = int((vram_value >> (subpixel * 4)) & 0x0Fu);
#elif PALETTE_8_BIT #elif PALETTE_8_BIT
// TODO: Still has precision issues here int subpixel = int(gl_FragCoord.x) & 1;
uint subpixel = uint(gl_FragCoord.x) & 1u; uint vram_value = RGBA8ToRGBA5551(color);
float palette_index = ((subpixel == 0u) ? color.x : color.y) * (255.0 * rcp_vram_size.x); int palette_index = int((vram_value >> (subpixel * 8)) & 0xFFu);
#endif #endif
vec2 palette_coords = vec2(palette_offset.x + palette_index, fixYCoord(palette_offset.y)); ivec2 palette_coords = ivec2(palette_offset.x + palette_index, fixYCoord(palette_offset.y));
color = texture(samp0, palette_coords); color = texelFetch(samp0, palette_coords & VRAM_COORD_MASK, 0);
#endif #endif
o_col0 = color; o_col0 = color;

View file

@ -151,9 +151,8 @@ bool GPU_HW_OpenGL::CompileProgram(GL::Program& prog, bool textured, bool blendi
if (textured) if (textured)
{ {
prog.Bind(); prog.Bind();
prog.RegisterUniform("u_tex_scale");
prog.RegisterUniform("samp0"); prog.RegisterUniform("samp0");
prog.Uniform1i(1, 0); prog.Uniform1i(0, 0);
} }
return true; return true;
@ -165,28 +164,8 @@ void GPU_HW_OpenGL::SetProgram(bool textured, bool blending)
prog.Bind(); prog.Bind();
if (textured) if (textured)
{
switch (m_texture_config.color_mode)
{
case GPU::TextureColorMode::Palette4Bit:
prog.Uniform2f(0, 1.0f / 4, 1.0f);
break;
case GPU::TextureColorMode::Palette8Bit:
prog.Uniform2f(0, 1.0f / 2, 1.0f);
break;
case GPU::TextureColorMode::Direct16Bit:
prog.Uniform2f(0, 1.0f, 1.0f);
break;
default:
break;
}
m_texture_page_texture->Bind(); m_texture_page_texture->Bind();
} }
}
void GPU_HW_OpenGL::SetViewport() void GPU_HW_OpenGL::SetViewport()
{ {
@ -334,16 +313,9 @@ void GPU_HW_OpenGL::UpdateTexturePageTexture()
const GL::Program& prog = m_texture_page_programs[static_cast<u8>(m_texture_config.color_mode)]; const GL::Program& prog = m_texture_page_programs[static_cast<u8>(m_texture_config.color_mode)];
prog.Bind(); prog.Bind();
const float base_x = static_cast<float>(m_texture_config.base_x) * (1.0f / static_cast<float>(VRAM_WIDTH)); prog.Uniform2i(1, m_texture_config.base_x, m_texture_config.base_y);
const float base_y = static_cast<float>(m_texture_config.base_y) * (1.0f / static_cast<float>(VRAM_HEIGHT));
prog.Uniform2f(1, base_x, base_y);
if (m_texture_config.color_mode >= GPU::TextureColorMode::Palette4Bit) if (m_texture_config.color_mode >= GPU::TextureColorMode::Palette4Bit)
{ prog.Uniform2i(2, m_texture_config.palette_x, m_texture_config.palette_y);
const float palette_x = static_cast<float>(m_texture_config.palette_x) * (1.0f / static_cast<float>(VRAM_WIDTH));
const float palette_y = static_cast<float>(m_texture_config.palette_y) * (1.0f / static_cast<float>(VRAM_HEIGHT));
prog.Uniform2f(2, palette_x, palette_y);
}
glDrawArrays(GL_TRIANGLES, 0, 3); glDrawArrays(GL_TRIANGLES, 0, 3);