From c0a3a4176d000de8088af4cbfb4eff8868a48c90 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Fri, 27 Sep 2019 21:20:35 +1000 Subject: [PATCH] GPU: Enable batching of polygons with the different texture pages --- src/pse/gpu.cpp | 25 +++++++++++--------- src/pse/gpu.h | 14 +++++++---- src/pse/gpu_hw.cpp | 49 +++++++++++++++++++++++++++------------ src/pse/gpu_hw.h | 2 +- src/pse/gpu_hw_opengl.cpp | 11 ++++----- 5 files changed, 63 insertions(+), 38 deletions(-) diff --git a/src/pse/gpu.cpp b/src/pse/gpu.cpp index 5861a897f..11ea2520a 100644 --- a/src/pse/gpu.cpp +++ b/src/pse/gpu.cpp @@ -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(ZeroExtend32(value & UINT16_C(0x0F)) * UINT32_C(64)); texture_page_y = static_cast(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((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((value >> 5) & UINT16_C(0x03))); @@ -808,7 +811,7 @@ void GPU::RenderState::SetFromPaletteAttribute(u16 value) texture_palette_x = static_cast(ZeroExtend32(value & UINT16_C(0x3F)) * UINT32_C(16)); texture_palette_y = static_cast(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) diff --git a/src/pse/gpu.h b/src/pse/gpu.h index 10636e29f..ac9d46980 100644 --- a/src/pse/gpu.h +++ b/src/pse/gpu.h @@ -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; } diff --git a/src/pse/gpu_hw.cpp b/src/pse/gpu_hw.cpp index f9bf09744..c6b03116c 100644 --- a/src/pse/gpu_hw.cpp +++ b/src/pse/gpu_hw.cpp @@ -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(tex_left + (rectangle_width - 1)); const u8 tex_bottom = static_cast(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()) diff --git a/src/pse/gpu_hw.h b/src/pse/gpu_hw.h index 44ce1d8ce..4e859a906 100644 --- a/src/pse/gpu_hw.h +++ b/src/pse/gpu_hw.h @@ -16,9 +16,9 @@ protected: s32 x; s32 y; u32 color; + u32 texpage; u16 texcoord; u16 padding; - u32 texpage; static constexpr std::tuple DecodeTexcoord(u16 texcoord) { diff --git a/src/pse/gpu_hw_opengl.cpp b/src/pse/gpu_hw_opengl.cpp index 45a98d52a..12efa73bd 100644 --- a/src/pse/gpu_hw_opengl.cpp +++ b/src/pse/gpu_hw_opengl.cpp @@ -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(offsetof(HWVertex, x))); glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, true, sizeof(HWVertex), reinterpret_cast(offsetof(HWVertex, color))); glVertexAttribPointer(2, 2, GL_UNSIGNED_BYTE, true, sizeof(HWVertex), reinterpret_cast(offsetof(HWVertex, texcoord))); + glVertexAttribIPointer(3, 1, GL_INT, sizeof(HWVertex), reinterpret_cast(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()