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));
DispatchRenderCommand(rc, num_vertices);
FlushRender();
UpdateDisplay();
//FlushRender();
//UpdateDisplay();
return true;
}
@ -535,7 +535,7 @@ void GPU::TextureConfig::SetFromPageAttribute(u16 value)
if (page_attribute == value)
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));
page_attribute = value;
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)
{
ss << "#version 330 core\n\n";
ss << "const vec2 vram_size = vec2(float(" << VRAM_WIDTH << "), float(" << VRAM_HEIGHT << "));\n";
ss << "const vec2 rcp_vram_size = vec2(1.0, 1.0) / vram_size;\n";
ss << "const ivec2 VRAM_SIZE = ivec2(" << VRAM_WIDTH << ", " << VRAM_HEIGHT << ");\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"(
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)
@ -179,7 +185,7 @@ void main()
v_col0 = a_col0;
#if TEXTURED
v_tex0 = vec2(a_tex0 * u_tex_scale);
v_tex0 = a_tex0;
#endif
}
)";
@ -255,10 +261,10 @@ std::string GPU_HW::GenerateTexturePageFragmentShader(TextureColorMode mode)
ss << R"(
uniform sampler2D samp0;
uniform vec2 base_offset;
uniform ivec2 base_offset;
#if PALETTE
uniform vec2 palette_offset;
uniform ivec2 palette_offset;
#endif
in vec2 v_tex0;
@ -266,33 +272,32 @@ out vec4 o_col0;
void main()
{
ivec2 local_coords = ivec2(gl_FragCoord.xy);
#if PALETTE_4_BIT
vec2 local_coords = vec2(v_tex0.x / 4.0, v_tex0.y);
local_coords.x /= 4;
#elif PALETTE_8_BIT
vec2 local_coords = vec2(v_tex0.x / 2.0, v_tex0.y);
#else
vec2 local_coords = v_tex0;
local_coords.x /= 2;
#endif
// 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
vec4 color = texture(samp0, coords);
vec4 color = texelFetch(samp0, coords & VRAM_COORD_MASK, 0);
// apply palette
#if PALETTE
#if PALETTE_4_BIT
uint subpixel = uint(gl_FragCoord.x) & 3u;
int subpixel = int(gl_FragCoord.x) & 3;
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
// TODO: Still has precision issues here
uint subpixel = uint(gl_FragCoord.x) & 1u;
float palette_index = ((subpixel == 0u) ? color.x : color.y) * (255.0 * rcp_vram_size.x);
int subpixel = int(gl_FragCoord.x) & 1;
uint vram_value = RGBA8ToRGBA5551(color);
int palette_index = int((vram_value >> (subpixel * 8)) & 0xFFu);
#endif
vec2 palette_coords = vec2(palette_offset.x + palette_index, fixYCoord(palette_offset.y));
color = texture(samp0, palette_coords);
ivec2 palette_coords = ivec2(palette_offset.x + palette_index, fixYCoord(palette_offset.y));
color = texelFetch(samp0, palette_coords & VRAM_COORD_MASK, 0);
#endif
o_col0 = color;

View file

@ -151,9 +151,8 @@ bool GPU_HW_OpenGL::CompileProgram(GL::Program& prog, bool textured, bool blendi
if (textured)
{
prog.Bind();
prog.RegisterUniform("u_tex_scale");
prog.RegisterUniform("samp0");
prog.Uniform1i(1, 0);
prog.Uniform1i(0, 0);
}
return true;
@ -165,28 +164,8 @@ void GPU_HW_OpenGL::SetProgram(bool textured, bool blending)
prog.Bind();
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();
}
}
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)];
prog.Bind();
const float base_x = static_cast<float>(m_texture_config.base_x) * (1.0f / static_cast<float>(VRAM_WIDTH));
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);
prog.Uniform2i(1, m_texture_config.base_x, m_texture_config.base_y);
if (m_texture_config.color_mode >= GPU::TextureColorMode::Palette4Bit)
{
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);
}
prog.Uniform2i(2, m_texture_config.palette_x, m_texture_config.palette_y);
glDrawArrays(GL_TRIANGLES, 0, 3);