GPU: Enable batching of polygons with the different texture pages
This commit is contained in:
parent
69f6788f9f
commit
c0a3a4176d
|
@ -39,7 +39,8 @@ void GPU::SoftReset()
|
|||
m_crtc_state.regs.horizontal_display_range = 0xC60260;
|
||||
m_crtc_state.regs.vertical_display_range = 0x3FC10;
|
||||
m_render_state = {};
|
||||
m_render_state.texture_changed = true;
|
||||
m_render_state.texture_page_changed = true;
|
||||
m_render_state.texture_color_mode_changed = true;
|
||||
m_render_state.transparency_mode_changed = true;
|
||||
UpdateGPUSTAT();
|
||||
UpdateCRTCConfig();
|
||||
|
@ -66,7 +67,8 @@ bool GPU::DoState(StateWrapper& sw)
|
|||
sw.Do(&m_render_state.texture_y_flip);
|
||||
sw.Do(&m_render_state.texpage_attribute);
|
||||
sw.Do(&m_render_state.texlut_attribute);
|
||||
sw.Do(&m_render_state.texture_changed);
|
||||
sw.Do(&m_render_state.texture_page_changed);
|
||||
sw.Do(&m_render_state.texture_color_mode_changed);
|
||||
sw.Do(&m_render_state.transparency_mode_changed);
|
||||
|
||||
sw.Do(&m_drawing_area.left);
|
||||
|
@ -102,7 +104,8 @@ bool GPU::DoState(StateWrapper& sw)
|
|||
|
||||
if (sw.IsReading())
|
||||
{
|
||||
m_render_state.texture_changed = true;
|
||||
m_render_state.texture_page_changed = true;
|
||||
m_render_state.texture_color_mode_changed = true;
|
||||
m_render_state.transparency_mode_changed = true;
|
||||
UpdateGPUSTAT();
|
||||
}
|
||||
|
@ -326,8 +329,6 @@ void GPU::Execute(TickCount ticks)
|
|||
m_timers->SetGate(HBLANK_TIMER_INDEX, new_vblank);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// alternating even line bit in 240-line mode
|
||||
if (!m_crtc_state.vertical_resolution)
|
||||
m_GPUSTAT.drawing_even_line = ConvertToBoolUnchecked(m_crtc_state.current_scanline & u32(1));
|
||||
|
@ -439,8 +440,7 @@ void GPU::WriteGP0(u32 value)
|
|||
{
|
||||
m_drawing_area.right = param & UINT32_C(0x3FF);
|
||||
m_drawing_area.bottom = (param >> 10) & UINT32_C(0x1FF);
|
||||
Log_DebugPrintf("Set drawing area bottom-right: (%u, %u)", m_drawing_area.right,
|
||||
m_drawing_area.bottom);
|
||||
Log_DebugPrintf("Set drawing area bottom-right: (%u, %u)", m_drawing_area.right, m_drawing_area.bottom);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -785,14 +785,17 @@ void GPU::RenderState::SetFromPageAttribute(u16 value)
|
|||
if (texpage_attribute == value)
|
||||
return;
|
||||
|
||||
texpage_attribute = value;
|
||||
texture_page_x = static_cast<s32>(ZeroExtend32(value & UINT16_C(0x0F)) * UINT32_C(64));
|
||||
texture_page_y = static_cast<s32>(ZeroExtend32((value >> 4) & UINT16_C(1)) * UINT32_C(256));
|
||||
texture_page_changed |=
|
||||
(old_page_attribute & PAGE_ATTRIBUTE_TEXTURE_PAGE_MASK) != (value & PAGE_ATTRIBUTE_TEXTURE_PAGE_MASK);
|
||||
|
||||
const TextureColorMode old_color_mode = texture_color_mode;
|
||||
texture_color_mode = (static_cast<TextureColorMode>((value >> 7) & UINT16_C(0x03)));
|
||||
if (texture_color_mode == TextureColorMode::Reserved_Direct16Bit)
|
||||
texture_color_mode = TextureColorMode::Direct16Bit;
|
||||
|
||||
texpage_attribute = value;
|
||||
texture_changed |= (old_page_attribute & PAGE_ATTRIBUTE_TEXTURE_MASK) != (value & PAGE_ATTRIBUTE_TEXTURE_MASK);
|
||||
texture_color_mode_changed |= old_color_mode != texture_color_mode;
|
||||
|
||||
const TransparencyMode old_transparency_mode = transparency_mode;
|
||||
transparency_mode = (static_cast<TransparencyMode>((value >> 5) & UINT16_C(0x03)));
|
||||
|
@ -808,7 +811,7 @@ void GPU::RenderState::SetFromPaletteAttribute(u16 value)
|
|||
texture_palette_x = static_cast<s32>(ZeroExtend32(value & UINT16_C(0x3F)) * UINT32_C(16));
|
||||
texture_palette_y = static_cast<s32>(ZeroExtend32((value >> 6) & UINT16_C(0x1FF)));
|
||||
texlut_attribute = value;
|
||||
texture_changed = true;
|
||||
texture_page_changed = true;
|
||||
}
|
||||
|
||||
bool GPU::DumpVRAMToFile(const char* filename, u32 width, u32 height, u32 stride, const void* buffer, bool remove_alpha)
|
||||
|
|
|
@ -223,7 +223,7 @@ protected:
|
|||
|
||||
struct RenderState
|
||||
{
|
||||
static constexpr u16 PAGE_ATTRIBUTE_TEXTURE_MASK = UINT16_C(0b0000000110011111);
|
||||
static constexpr u16 PAGE_ATTRIBUTE_TEXTURE_PAGE_MASK = UINT16_C(0b0000000000011111);
|
||||
static constexpr u16 PAGE_ATTRIBUTE_MASK = UINT16_C(0b0000000111111111);
|
||||
static constexpr u16 PALETTE_ATTRIBUTE_MASK = UINT16_C(0b0111111111111111);
|
||||
|
||||
|
@ -245,13 +245,17 @@ protected:
|
|||
u16 texpage_attribute; // from register in rectangle modes/vertex in polygon modes
|
||||
u16 texlut_attribute; // from vertex
|
||||
|
||||
bool texture_changed = false;
|
||||
bool texture_page_changed = false;
|
||||
bool texture_color_mode_changed = false;
|
||||
bool transparency_mode_changed = false;
|
||||
|
||||
bool IsChanged() const { return texture_changed || transparency_mode_changed; }
|
||||
bool IsChanged() const { return texture_page_changed || texture_color_mode_changed || transparency_mode_changed; }
|
||||
|
||||
bool IsTextureChanged() const { return texture_changed; }
|
||||
void ClearTextureChangedFlag() { texture_changed = false; }
|
||||
bool IsTexturePageChanged() const { return texture_page_changed; }
|
||||
void ClearTexturePageChangedFlag() { texture_page_changed = false; }
|
||||
|
||||
bool IsTextureColorModeChanged() const { return texture_color_mode_changed; }
|
||||
void ClearTextureColorModeChangedFlag() { texture_color_mode_changed = false; }
|
||||
|
||||
bool IsTransparencyModeChanged() const { return transparency_mode_changed; }
|
||||
void ClearTransparencyModeChangedFlag() { transparency_mode_changed = false; }
|
||||
|
|
|
@ -10,6 +10,9 @@ GPU_HW::~GPU_HW() = default;
|
|||
|
||||
void GPU_HW::LoadVertices(RenderCommand rc, u32 num_vertices)
|
||||
{
|
||||
const u32 texpage =
|
||||
ZeroExtend32(m_render_state.texpage_attribute) | (ZeroExtend32(m_render_state.texlut_attribute) << 16);
|
||||
|
||||
// TODO: Move this to the GPU..
|
||||
switch (rc.primitive)
|
||||
{
|
||||
|
@ -33,6 +36,7 @@ void GPU_HW::LoadVertices(RenderCommand rc, u32 num_vertices)
|
|||
const VertexPosition vp{m_GP0_command[buffer_pos++]};
|
||||
hw_vert.x = vp.x();
|
||||
hw_vert.y = vp.y();
|
||||
hw_vert.texpage = texpage;
|
||||
|
||||
if (textured)
|
||||
hw_vert.texcoord = Truncate16(m_GP0_command[buffer_pos++]);
|
||||
|
@ -94,13 +98,16 @@ void GPU_HW::LoadVertices(RenderCommand rc, u32 num_vertices)
|
|||
const u8 tex_right = static_cast<u8>(tex_left + (rectangle_width - 1));
|
||||
const u8 tex_bottom = static_cast<u8>(tex_top + (rectangle_height - 1));
|
||||
|
||||
m_batch.vertices.push_back(HWVertex{pos_left, pos_top, color, HWVertex::EncodeTexcoord(tex_left, tex_top)});
|
||||
m_batch.vertices.push_back(
|
||||
HWVertex{pos_left, pos_top, color, texpage, HWVertex::EncodeTexcoord(tex_left, tex_top)});
|
||||
if (restart_strip)
|
||||
m_batch.vertices.push_back(m_batch.vertices.back());
|
||||
m_batch.vertices.push_back(HWVertex{pos_right, pos_top, color, HWVertex::EncodeTexcoord(tex_right, tex_top)});
|
||||
m_batch.vertices.push_back(HWVertex{pos_left, pos_bottom, color, HWVertex::EncodeTexcoord(tex_left, tex_bottom)});
|
||||
m_batch.vertices.push_back(
|
||||
HWVertex{pos_right, pos_bottom, color, HWVertex::EncodeTexcoord(tex_right, tex_bottom)});
|
||||
HWVertex{pos_right, pos_top, color, texpage, HWVertex::EncodeTexcoord(tex_right, tex_top)});
|
||||
m_batch.vertices.push_back(
|
||||
HWVertex{pos_left, pos_bottom, color, texpage, HWVertex::EncodeTexcoord(tex_left, tex_bottom)});
|
||||
m_batch.vertices.push_back(
|
||||
HWVertex{pos_right, pos_bottom, color, texpage, HWVertex::EncodeTexcoord(tex_right, tex_bottom)});
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -175,10 +182,12 @@ std::string GPU_HW::GenerateVertexShader(bool textured)
|
|||
in ivec2 a_pos;
|
||||
in vec4 a_col0;
|
||||
in vec2 a_tex0;
|
||||
in int a_texpage;
|
||||
|
||||
out vec3 v_col0;
|
||||
#if TEXTURED
|
||||
out vec2 v_tex0;
|
||||
flat out ivec4 v_texpage;
|
||||
#endif
|
||||
|
||||
uniform ivec2 u_pos_offset;
|
||||
|
@ -193,6 +202,12 @@ void main()
|
|||
v_col0 = a_col0.rgb;
|
||||
#if TEXTURED
|
||||
v_tex0 = a_tex0;
|
||||
|
||||
// base_x,base_y,palette_x,palette_y
|
||||
v_texpage.x = (a_texpage & 15) * 64;
|
||||
v_texpage.y = ((a_texpage >> 4) & 1) * 256;
|
||||
v_texpage.z = ((a_texpage >> 16) & 63) * 16;
|
||||
v_texpage.w = ((a_texpage >> 22) & 511);
|
||||
#endif
|
||||
}
|
||||
)";
|
||||
|
@ -218,11 +233,8 @@ in vec3 v_col0;
|
|||
uniform vec2 u_transparent_alpha;
|
||||
#if TEXTURED
|
||||
in vec2 v_tex0;
|
||||
flat in ivec4 v_texpage;
|
||||
uniform sampler2D samp0;
|
||||
uniform ivec2 u_texture_page_base;
|
||||
#if PALETTE
|
||||
uniform ivec2 u_texture_palette_base;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
out vec4 o_col0;
|
||||
|
@ -242,8 +254,8 @@ vec4 SampleFromVRAM(vec2 coord)
|
|||
#endif
|
||||
|
||||
// fixup coords
|
||||
ivec2 vicoord = ivec2(u_texture_page_base.x + index_coord.x,
|
||||
fixYCoord(u_texture_page_base.y + index_coord.y));
|
||||
ivec2 vicoord = ivec2(v_texpage.x + index_coord.x,
|
||||
fixYCoord(v_texpage.y + index_coord.y));
|
||||
|
||||
// load colour/palette
|
||||
vec4 color = texelFetch(samp0, vicoord & VRAM_COORD_MASK, 0);
|
||||
|
@ -259,7 +271,7 @@ vec4 SampleFromVRAM(vec2 coord)
|
|||
uint vram_value = RGBA8ToRGBA5551(color);
|
||||
int palette_index = int((vram_value >> (subpixel * 8)) & 0xFFu);
|
||||
#endif
|
||||
ivec2 palette_icoord = ivec2(u_texture_palette_base.x + palette_index, fixYCoord(u_texture_palette_base.y));
|
||||
ivec2 palette_icoord = ivec2(v_texpage.z + palette_index, fixYCoord(v_texpage.w));
|
||||
color = texelFetch(samp0, palette_icoord & VRAM_COORD_MASK, 0);
|
||||
#endif
|
||||
|
||||
|
@ -393,7 +405,9 @@ void GPU_HW::DispatchRenderCommand(RenderCommand rc, u32 num_vertices)
|
|||
m_batch.render_command_bits != rc.bits && m_batch.transparency_enable != rc_transparency_enable ||
|
||||
m_batch.texture_enable != rc_texture_enable || m_batch.texture_blending_enable != rc_texture_blend_enable ||
|
||||
m_batch.primitive != rc_primitive;
|
||||
const bool needs_flush = !IsFlushed() && (m_render_state.IsChanged() || buffer_overflow || rc_changed);
|
||||
const bool needs_flush =
|
||||
!IsFlushed() && (m_render_state.IsTextureColorModeChanged() || m_render_state.IsTransparencyModeChanged() ||
|
||||
buffer_overflow || rc_changed);
|
||||
if (needs_flush)
|
||||
FlushRender();
|
||||
|
||||
|
@ -407,7 +421,7 @@ void GPU_HW::DispatchRenderCommand(RenderCommand rc, u32 num_vertices)
|
|||
m_batch.texture_blending_enable = rc_texture_blend_enable;
|
||||
}
|
||||
|
||||
if (m_render_state.IsTextureChanged())
|
||||
if (m_render_state.IsTexturePageChanged())
|
||||
{
|
||||
// we only need to update the copy texture if the render area intersects with the texture page
|
||||
const u32 texture_page_left = m_render_state.texture_page_x;
|
||||
|
@ -425,12 +439,17 @@ void GPU_HW::DispatchRenderCommand(RenderCommand rc, u32 num_vertices)
|
|||
InvalidateVRAMReadCache();
|
||||
}
|
||||
|
||||
m_batch.texture_color_mode = m_render_state.texture_color_mode;
|
||||
m_batch.texture_page_x = m_render_state.texture_page_x;
|
||||
m_batch.texture_page_y = m_render_state.texture_page_y;
|
||||
m_batch.texture_palette_x = m_render_state.texture_palette_x;
|
||||
m_batch.texture_palette_y = m_render_state.texture_palette_y;
|
||||
m_render_state.ClearTextureChangedFlag();
|
||||
m_render_state.ClearTexturePageChangedFlag();
|
||||
}
|
||||
|
||||
if (m_render_state.IsTextureColorModeChanged())
|
||||
{
|
||||
m_batch.texture_color_mode = m_render_state.texture_color_mode;
|
||||
m_render_state.ClearTextureColorModeChangedFlag();
|
||||
}
|
||||
|
||||
if (m_render_state.IsTransparencyModeChanged())
|
||||
|
|
|
@ -16,9 +16,9 @@ protected:
|
|||
s32 x;
|
||||
s32 y;
|
||||
u32 color;
|
||||
u32 texpage;
|
||||
u16 texcoord;
|
||||
u16 padding;
|
||||
u32 texpage;
|
||||
|
||||
static constexpr std::tuple<u8, u8> DecodeTexcoord(u16 texcoord)
|
||||
{
|
||||
|
|
|
@ -138,11 +138,13 @@ void GPU_HW_OpenGL::CreateVertexBuffer()
|
|||
glEnableVertexAttribArray(0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glEnableVertexAttribArray(2);
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribIPointer(0, 2, GL_INT, sizeof(HWVertex), reinterpret_cast<void*>(offsetof(HWVertex, x)));
|
||||
glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, true, sizeof(HWVertex),
|
||||
reinterpret_cast<void*>(offsetof(HWVertex, color)));
|
||||
glVertexAttribPointer(2, 2, GL_UNSIGNED_BYTE, true, sizeof(HWVertex),
|
||||
reinterpret_cast<void*>(offsetof(HWVertex, texcoord)));
|
||||
glVertexAttribIPointer(3, 1, GL_INT, sizeof(HWVertex), reinterpret_cast<void*>(offsetof(HWVertex, texpage)));
|
||||
glBindVertexArray(0);
|
||||
|
||||
glGenVertexArrays(1, &m_attributeless_vao_id);
|
||||
|
@ -184,7 +186,10 @@ bool GPU_HW_OpenGL::CompileProgram(GL::Program& prog, bool textured, bool blendi
|
|||
prog.BindAttribute(0, "a_pos");
|
||||
prog.BindAttribute(1, "a_col0");
|
||||
if (textured)
|
||||
{
|
||||
prog.BindAttribute(2, "a_tex0");
|
||||
prog.BindAttribute(3, "a_texpage");
|
||||
}
|
||||
|
||||
prog.BindFragData(0, "o_col0");
|
||||
|
||||
|
@ -200,8 +205,6 @@ bool GPU_HW_OpenGL::CompileProgram(GL::Program& prog, bool textured, bool blendi
|
|||
if (textured)
|
||||
{
|
||||
prog.RegisterUniform("samp0");
|
||||
prog.RegisterUniform("u_texture_page_base");
|
||||
prog.RegisterUniform("u_texture_palette_base");
|
||||
prog.Uniform1i(2, 0);
|
||||
}
|
||||
|
||||
|
@ -228,11 +231,7 @@ void GPU_HW_OpenGL::SetProgram()
|
|||
}
|
||||
|
||||
if (m_batch.texture_enable)
|
||||
{
|
||||
m_vram_read_texture->Bind();
|
||||
prog.Uniform2i(3, m_batch.texture_page_x, m_batch.texture_page_y);
|
||||
prog.Uniform2i(4, m_batch.texture_palette_x, m_batch.texture_palette_y);
|
||||
}
|
||||
}
|
||||
|
||||
void GPU_HW_OpenGL::SetViewport()
|
||||
|
|
Loading…
Reference in New Issue