From 2aecb570c16e373d46dd802e3067c66131b5d865 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Sat, 4 Apr 2020 00:11:33 +1000 Subject: [PATCH] GPU: Implement interlaced rendering in hardware backends --- src/core/gpu.cpp | 13 +++++--- src/core/gpu.h | 6 ++-- src/core/gpu_hw.cpp | 8 +++++ src/core/gpu_hw.h | 3 +- src/core/gpu_hw_d3d11.cpp | 29 ++++++++-------- src/core/gpu_hw_d3d11.h | 4 +-- src/core/gpu_hw_opengl.cpp | 54 +++++++++++++++--------------- src/core/gpu_hw_opengl.h | 7 ++-- src/core/gpu_hw_opengl_es.cpp | 62 +++++++++++++++++++---------------- src/core/gpu_hw_opengl_es.h | 7 ++-- src/core/gpu_hw_shadergen.cpp | 12 +++++-- src/core/gpu_hw_shadergen.h | 2 +- src/core/gpu_sw.cpp | 5 ++- 13 files changed, 123 insertions(+), 89 deletions(-) diff --git a/src/core/gpu.cpp b/src/core/gpu.cpp index 1069f980a..911fa6e3e 100644 --- a/src/core/gpu.cpp +++ b/src/core/gpu.cpp @@ -627,12 +627,12 @@ void GPU::Execute(TickCount ticks) // alternating even line bit in 240-line mode if (m_GPUSTAT.In480iMode()) { - m_GPUSTAT.drawing_even_line = - ConvertToBoolUnchecked((m_crtc_state.regs.Y + BoolToUInt32(!m_GPUSTAT.interlaced_field)) & u32(1)); + m_GPUSTAT.displaying_odd_line = + ConvertToBoolUnchecked((m_crtc_state.regs.Y + BoolToUInt32(m_GPUSTAT.interlaced_field)) & u32(1)); } else { - m_GPUSTAT.drawing_even_line = + m_GPUSTAT.displaying_odd_line = ConvertToBoolUnchecked((m_crtc_state.regs.Y + m_crtc_state.current_scanline) & u32(1)); } @@ -995,6 +995,9 @@ void GPU::SetDrawMode(u16 value) m_draw_mode.mode_reg.bits = new_mode_reg.bits; + if (m_GPUSTAT.draw_to_displayed_field != new_mode_reg.draw_to_displayed_field) + FlushRender(); + // Bits 0..10 are returned in the GPU status register. m_GPUSTAT.bits = (m_GPUSTAT.bits & ~(DrawMode::Reg::GPUSTAT_MASK)) | (ZeroExtend32(new_mode_reg.bits) & DrawMode::Reg::GPUSTAT_MASK); @@ -1124,7 +1127,7 @@ void GPU::DrawDebugStateWindow() ImGui::Text("Vertical Interlace: %s (%s field)", m_GPUSTAT.vertical_interlace ? "Yes" : "No", m_GPUSTAT.interlaced_field ? "odd" : "even"); ImGui::Text("Display Disable: %s", m_GPUSTAT.display_disable ? "Yes" : "No"); - ImGui::Text("Drawing Even Line: %s", m_GPUSTAT.drawing_even_line ? "Yes" : "No"); + ImGui::Text("Displaying Odd Line/Field: %s", m_GPUSTAT.displaying_odd_line ? "Yes" : "No"); ImGui::Text("Color Depth: %u-bit", m_GPUSTAT.display_area_color_depth_24 ? 24 : 15); ImGui::Text("Start Offset: (%u, %u)", cs.regs.X.GetValue(), cs.regs.Y.GetValue()); ImGui::Text("Display Total: %u (%u) horizontal, %u vertical", cs.horizontal_total, @@ -1145,7 +1148,7 @@ void GPU::DrawDebugStateWindow() if (ImGui::CollapsingHeader("GPU", ImGuiTreeNodeFlags_DefaultOpen)) { ImGui::Text("Dither: %s", m_GPUSTAT.dither_enable ? "Enabled" : "Disabled"); - ImGui::Text("Draw To Display Area: %s", m_GPUSTAT.draw_to_display_area ? "Enabled" : "Disabled"); + ImGui::Text("Draw To Displayed Field: %s", m_GPUSTAT.draw_to_displayed_field ? "Enabled" : "Disabled"); ImGui::Text("Draw Set Mask Bit: %s", m_GPUSTAT.set_mask_while_drawing ? "Yes" : "No"); ImGui::Text("Draw To Masked Pixels: %s", m_GPUSTAT.check_mask_before_draw ? "Yes" : "No"); ImGui::Text("Reverse Flag: %s", m_GPUSTAT.reverse_flag ? "Yes" : "No"); diff --git a/src/core/gpu.h b/src/core/gpu.h index 165dfc1eb..af5ad0e2d 100644 --- a/src/core/gpu.h +++ b/src/core/gpu.h @@ -377,7 +377,7 @@ protected: BitField semi_transparency_mode; BitField texture_color_mode; BitField dither_enable; - BitField draw_to_display_area; + BitField draw_to_displayed_field; BitField set_mask_while_drawing; BitField check_mask_before_draw; BitField interlaced_field; @@ -396,7 +396,7 @@ protected: BitField ready_to_send_vram; BitField ready_to_recieve_dma; BitField dma_direction; - BitField drawing_even_line; + BitField displaying_odd_line; bool IsMaskingEnabled() const { @@ -452,7 +452,7 @@ protected: BitField transparency_mode; BitField texture_mode; BitField dither_enable; - BitField draw_to_display_area; + BitField draw_to_displayed_field; BitField texture_disable; BitField texture_x_flip; BitField texture_y_flip; diff --git a/src/core/gpu_hw.cpp b/src/core/gpu_hw.cpp index c3fe639d5..4833bce9e 100644 --- a/src/core/gpu_hw.cpp +++ b/src/core/gpu_hw.cpp @@ -541,6 +541,14 @@ void GPU_HW::DispatchRenderCommand(RenderCommand rc, u32 num_vertices, const u32 m_batch_ubo_dirty = true; } + m_batch.interlacing = m_GPUSTAT.SkipDrawingToActiveField(); + if (m_batch.interlacing) + { + const u32 displayed_field = BoolToUInt32(m_GPUSTAT.displaying_odd_line); + m_batch_ubo_dirty |= (m_batch_ubo_data.u_interlaced_displayed_field != displayed_field); + m_batch_ubo_data.u_interlaced_displayed_field = displayed_field; + } + // update state m_batch.primitive = rc_primitive; m_batch.texture_mode = texture_mode; diff --git a/src/core/gpu_hw.h b/src/core/gpu_hw.h index 649229386..1d5f2f4da 100644 --- a/src/core/gpu_hw.h +++ b/src/core/gpu_hw.h @@ -76,6 +76,7 @@ protected: TextureMode texture_mode; TransparencyMode transparency_mode; bool dithering; + bool interlacing; bool set_mask_while_drawing; bool check_mask_before_draw; @@ -102,7 +103,7 @@ protected: float u_src_alpha_factor; float u_dst_alpha_factor; u32 u_set_mask_while_drawing; - u32 padding[1]; + u32 u_interlaced_displayed_field; }; struct RendererStats diff --git a/src/core/gpu_hw_d3d11.cpp b/src/core/gpu_hw_d3d11.cpp index da9a9c2ef..c0599a2c1 100644 --- a/src/core/gpu_hw_d3d11.cpp +++ b/src/core/gpu_hw_d3d11.cpp @@ -349,13 +349,17 @@ bool GPU_HW_D3D11::CompileShaders() { for (u8 dithering = 0; dithering < 2; dithering++) { - const std::string ps = shadergen.GenerateBatchFragmentShader(static_cast(render_mode), - static_cast(texture_mode), - ConvertToBoolUnchecked(dithering)); + for (u8 interlacing = 0; interlacing < 2; interlacing++) + { + const std::string ps = shadergen.GenerateBatchFragmentShader( + static_cast(render_mode), static_cast(texture_mode), + ConvertToBoolUnchecked(dithering), ConvertToBoolUnchecked(interlacing)); - m_batch_pixel_shaders[render_mode][texture_mode][dithering] = m_shader_cache.GetPixelShader(m_device.Get(), ps); - if (!m_batch_pixel_shaders[render_mode][texture_mode][dithering]) - return false; + m_batch_pixel_shaders[render_mode][texture_mode][dithering][interlacing] = + m_shader_cache.GetPixelShader(m_device.Get(), ps); + if (!m_batch_pixel_shaders[render_mode][texture_mode][dithering][interlacing]) + return false; + } } } } @@ -388,12 +392,12 @@ bool GPU_HW_D3D11::CompileShaders() for (u8 depth_24bit = 0; depth_24bit < 2; depth_24bit++) { - for (u8 interlaced = 0; interlaced < 2; interlaced++) + for (u8 interlacing = 0; interlacing < 2; interlacing++) { const std::string ps = shadergen.GenerateDisplayFragmentShader(ConvertToBoolUnchecked(depth_24bit), - ConvertToBoolUnchecked(interlaced)); - m_display_pixel_shaders[depth_24bit][interlaced] = m_shader_cache.GetPixelShader(m_device.Get(), ps); - if (!m_display_pixel_shaders[depth_24bit][interlaced]) + ConvertToBoolUnchecked(interlacing)); + m_display_pixel_shaders[depth_24bit][interlacing] = m_shader_cache.GetPixelShader(m_device.Get(), ps); + if (!m_display_pixel_shaders[depth_24bit][interlacing]) return false; } } @@ -486,7 +490,7 @@ void GPU_HW_D3D11::SetDrawState(BatchRenderMode render_mode) nullptr, 0); m_context->PSSetShader(m_batch_pixel_shaders[static_cast(render_mode)][static_cast(m_batch.texture_mode)] - [BoolToUInt8(m_batch.dithering)] + [BoolToUInt8(m_batch.dithering)][BoolToUInt8(m_batch.interlacing)] .Get(), nullptr, 0); @@ -555,8 +559,7 @@ void GPU_HW_D3D11::UpdateDisplay() m_context->OMSetRenderTargets(1, m_display_texture.GetD3DRTVArray(), nullptr); m_context->PSSetShaderResources(0, 1, m_vram_texture.GetD3DSRVArray()); - const u32 reinterpret_field_offset = - (m_crtc_state.regs.Y + BoolToUInt8(interlaced && m_GPUSTAT.interlaced_field)) & 1u; + const u32 reinterpret_field_offset = BoolToUInt32(m_GPUSTAT.displaying_odd_line); const u32 reinterpret_start_x = m_crtc_state.regs.X * m_resolution_scale; const u32 reinterpret_width = scaled_display_width + (m_crtc_state.display_vram_left - m_crtc_state.regs.X); const u32 uniforms[4] = {reinterpret_field_offset, reinterpret_start_x}; diff --git a/src/core/gpu_hw_d3d11.h b/src/core/gpu_hw_d3d11.h index 5eceb0350..759c1ae3b 100644 --- a/src/core/gpu_hw_d3d11.h +++ b/src/core/gpu_hw_d3d11.h @@ -103,8 +103,8 @@ private: std::array, 5> m_batch_blend_states; // [transparency_mode] ComPtr m_batch_input_layout; std::array, 2> m_batch_vertex_shaders; // [textured] - std::array, 2>, 9>, 4> - m_batch_pixel_shaders; // [render_mode][texture_mode][dithering] + std::array, 2>, 2>, 9>, 4> + m_batch_pixel_shaders; // [render_mode][texture_mode][dithering][interlacing] ComPtr m_batch_line_expand_geometry_shader; ComPtr m_screen_quad_vertex_shader; diff --git a/src/core/gpu_hw_opengl.cpp b/src/core/gpu_hw_opengl.cpp index 5c18393fa..909f2c3e2 100644 --- a/src/core/gpu_hw_opengl.cpp +++ b/src/core/gpu_hw_opengl.cpp @@ -302,35 +302,38 @@ bool GPU_HW_OpenGL::CompilePrograms() { for (u8 dithering = 0; dithering < 2; dithering++) { - const bool textured = (static_cast(texture_mode) != TextureMode::Disabled); - const std::string vs = shadergen.GenerateBatchVertexShader(textured); - const std::string fs = shadergen.GenerateBatchFragmentShader(static_cast(render_mode), - static_cast(texture_mode), - ConvertToBoolUnchecked(dithering)); + for (u8 interlacing = 0; interlacing < 2; interlacing++) + { + const bool textured = (static_cast(texture_mode) != TextureMode::Disabled); + const std::string vs = shadergen.GenerateBatchVertexShader(textured); + const std::string fs = shadergen.GenerateBatchFragmentShader( + static_cast(render_mode), static_cast(texture_mode), + ConvertToBoolUnchecked(dithering), ConvertToBoolUnchecked(interlacing)); - std::optional prog = m_shader_cache.GetProgram(vs, fs, [this, textured](GL::Program& prog) { - prog.BindAttribute(0, "a_pos"); - prog.BindAttribute(1, "a_col0"); + std::optional prog = m_shader_cache.GetProgram(vs, fs, [this, textured](GL::Program& prog) { + prog.BindAttribute(0, "a_pos"); + prog.BindAttribute(1, "a_col0"); + if (textured) + { + prog.BindAttribute(2, "a_texcoord"); + prog.BindAttribute(3, "a_texpage"); + } + + if (!m_is_gles) + prog.BindFragData(0, "o_col0"); + }); + if (!prog) + return false; + + prog->BindUniformBlock("UBOBlock", 1); if (textured) { - prog.BindAttribute(2, "a_texcoord"); - prog.BindAttribute(3, "a_texpage"); + prog->Bind(); + prog->Uniform1i("samp0", 0); } - if (!m_is_gles) - prog.BindFragData(0, "o_col0"); - }); - if (!prog) - return false; - - prog->BindUniformBlock("UBOBlock", 1); - if (textured) - { - prog->Bind(); - prog->Uniform1i("samp0", 0); + m_render_programs[render_mode][texture_mode][dithering][interlacing] = std::move(*prog); } - - m_render_programs[render_mode][texture_mode][dithering] = std::move(*prog); } } } @@ -406,7 +409,7 @@ bool GPU_HW_OpenGL::CompilePrograms() void GPU_HW_OpenGL::SetDrawState(BatchRenderMode render_mode) { const GL::Program& prog = m_render_programs[static_cast(render_mode)][static_cast(m_batch.texture_mode)] - [BoolToUInt8(m_batch.dithering)]; + [BoolToUInt8(m_batch.dithering)][BoolToUInt8(m_batch.interlacing)]; prog.Bind(); if (m_batch.texture_mode != TextureMode::Disabled) @@ -513,8 +516,7 @@ void GPU_HW_OpenGL::UpdateDisplay() const u32 scaled_flipped_vram_offset_y = m_vram_texture.GetHeight() - scaled_vram_offset_y - scaled_display_height; - const u32 reinterpret_field_offset = - (m_crtc_state.regs.Y + BoolToUInt8(interlaced && m_GPUSTAT.interlaced_field)) & 1u; + const u32 reinterpret_field_offset = BoolToUInt32(m_GPUSTAT.displaying_odd_line); const u32 reinterpret_start_x = m_crtc_state.regs.X * m_resolution_scale; const u32 reinterpret_width = scaled_display_width + (m_crtc_state.display_vram_left - m_crtc_state.regs.X); const u32 uniforms[4] = {reinterpret_field_offset, reinterpret_start_x}; diff --git a/src/core/gpu_hw_opengl.h b/src/core/gpu_hw_opengl.h index 18e7bd847..df68fd46d 100644 --- a/src/core/gpu_hw_opengl.h +++ b/src/core/gpu_hw_opengl.h @@ -1,8 +1,8 @@ #pragma once #include "common/gl/program.h" +#include "common/gl/shader_cache.h" #include "common/gl/stream_buffer.h" #include "common/gl/texture.h" -#include "common/gl/shader_cache.h" #include "glad.h" #include "gpu_hw.h" #include @@ -76,8 +76,9 @@ private: std::unique_ptr m_texture_stream_buffer; GLuint m_texture_buffer_r16ui_texture = 0; - std::array, 9>, 4> m_render_programs; // [render_mode][texture_mode][dithering] - std::array, 2> m_display_programs; // [depth_24][interlaced] + std::array, 2>, 9>, 4> + m_render_programs; // [render_mode][texture_mode][dithering][interlacing] + std::array, 2> m_display_programs; // [depth_24][interlaced] GL::Program m_vram_read_program; GL::Program m_vram_write_program; diff --git a/src/core/gpu_hw_opengl_es.cpp b/src/core/gpu_hw_opengl_es.cpp index 22398c479..32380862b 100644 --- a/src/core/gpu_hw_opengl_es.cpp +++ b/src/core/gpu_hw_opengl_es.cpp @@ -197,35 +197,39 @@ bool GPU_HW_OpenGL_ES::CompilePrograms() { for (u8 dithering = 0; dithering < 2; dithering++) { - const bool textured = (static_cast(texture_mode) != TextureMode::Disabled); - const std::string vs = shadergen.GenerateBatchVertexShader(textured); - const std::string fs = shadergen.GenerateBatchFragmentShader(static_cast(render_mode), - static_cast(texture_mode), - ConvertToBoolUnchecked(dithering)); + for (u8 interlacing = 0; interlacing < 2; interlacing++) + { + const bool textured = (static_cast(texture_mode) != TextureMode::Disabled); + const std::string vs = shadergen.GenerateBatchVertexShader(textured); + const std::string fs = shadergen.GenerateBatchFragmentShader( + static_cast(render_mode), static_cast(texture_mode), + ConvertToBoolUnchecked(dithering), ConvertToBoolUnchecked(interlacing)); + + std::optional prog = m_shader_cache.GetProgram(vs, fs, [this, textured](GL::Program& prog) { + prog.BindAttribute(0, "a_pos"); + prog.BindAttribute(1, "a_col0"); + if (textured) + { + prog.BindAttribute(2, "a_texcoord"); + prog.BindAttribute(3, "a_texpage"); + } + }); + if (!prog) + return false; + + prog->Bind(); + prog->RegisterUniform("u_texture_window_mask"); + prog->RegisterUniform("u_texture_window_offset"); + prog->RegisterUniform("u_src_alpha_factor"); + prog->RegisterUniform("u_dst_alpha_factor"); + prog->RegisterUniform("u_set_mask_while_drawing"); + prog->RegisterUniform("u_interlaced_displayed_field"); - std::optional prog = m_shader_cache.GetProgram(vs, fs, [this, textured](GL::Program& prog) { - prog.BindAttribute(0, "a_pos"); - prog.BindAttribute(1, "a_col0"); if (textured) - { - prog.BindAttribute(2, "a_texcoord"); - prog.BindAttribute(3, "a_texpage"); - } - }); - if (!prog) - return false; + prog->Uniform1i("samp0", 0); - prog->Bind(); - prog->RegisterUniform("u_texture_window_mask"); - prog->RegisterUniform("u_texture_window_offset"); - prog->RegisterUniform("u_src_alpha_factor"); - prog->RegisterUniform("u_dst_alpha_factor"); - prog->RegisterUniform("u_set_mask_while_drawing"); - - if (textured) - prog->Uniform1i("samp0", 0); - - m_render_programs[render_mode][texture_mode][dithering] = std::move(*prog); + m_render_programs[render_mode][texture_mode][dithering][interlacing] = std::move(*prog); + } } } } @@ -277,7 +281,7 @@ void GPU_HW_OpenGL_ES::SetVertexPointers() void GPU_HW_OpenGL_ES::SetDrawState(BatchRenderMode render_mode) { const GL::Program& prog = m_render_programs[static_cast(render_mode)][static_cast(m_batch.texture_mode)] - [BoolToUInt8(m_batch.dithering)]; + [BoolToUInt8(m_batch.dithering)][BoolToUInt8(m_batch.interlacing)]; m_batch_ubo_dirty |= !prog.IsBound(); prog.Bind(); @@ -311,6 +315,7 @@ void GPU_HW_OpenGL_ES::SetDrawState(BatchRenderMode render_mode) prog.Uniform1f(2, m_batch_ubo_data.u_src_alpha_factor); prog.Uniform1f(3, m_batch_ubo_data.u_dst_alpha_factor); prog.Uniform1i(4, static_cast(m_batch_ubo_data.u_set_mask_while_drawing)); + prog.Uniform1i(5, static_cast(m_batch_ubo_data.u_interlaced_displayed_field)); m_batch_ubo_dirty = false; } } @@ -380,8 +385,7 @@ void GPU_HW_OpenGL_ES::UpdateDisplay() const u32 scaled_flipped_vram_offset_y = m_vram_texture.GetHeight() - scaled_vram_offset_y - scaled_display_height; - const u32 reinterpret_field_offset = - (m_crtc_state.regs.Y + BoolToUInt8(interlaced && m_GPUSTAT.interlaced_field)) & 1u; + const u32 reinterpret_field_offset = BoolToUInt32(m_GPUSTAT.displaying_odd_line); const u32 reinterpret_start_x = m_crtc_state.regs.X * m_resolution_scale; const u32 reinterpret_width = scaled_display_width + (m_crtc_state.display_vram_left - m_crtc_state.regs.X); diff --git a/src/core/gpu_hw_opengl_es.h b/src/core/gpu_hw_opengl_es.h index ede68ae59..d931abdd7 100644 --- a/src/core/gpu_hw_opengl_es.h +++ b/src/core/gpu_hw_opengl_es.h @@ -1,8 +1,8 @@ #pragma once #include "common/gl/program.h" +#include "common/gl/shader_cache.h" #include "common/gl/stream_buffer.h" #include "common/gl/texture.h" -#include "common/gl/shader_cache.h" #include "glad.h" #include "gpu_hw.h" #include @@ -64,7 +64,8 @@ private: std::vector m_vertex_buffer; - std::array, 9>, 4> m_render_programs; // [render_mode][texture_mode][dithering] - std::array, 2> m_display_programs; // [depth_24][interlaced] + std::array, 2>, 9>, 4> + m_render_programs; // [render_mode][texture_mode][dithering][interlacing] + std::array, 2> m_display_programs; // [depth_24][interlaced] GL::Program m_vram_read_program; }; diff --git a/src/core/gpu_hw_shadergen.cpp b/src/core/gpu_hw_shadergen.cpp index 7189ba8fd..41b07af20 100644 --- a/src/core/gpu_hw_shadergen.cpp +++ b/src/core/gpu_hw_shadergen.cpp @@ -345,7 +345,8 @@ void GPU_HW_ShaderGen::DeclareFragmentEntryPoint(std::stringstream& ss, u32 num_ void GPU_HW_ShaderGen::WriteBatchUniformBuffer(std::stringstream& ss) { DeclareUniformBuffer(ss, {"uint2 u_texture_window_mask", "uint2 u_texture_window_offset", "float u_src_alpha_factor", - "float u_dst_alpha_factor", "bool u_set_mask_while_drawing"}); + "float u_dst_alpha_factor", "bool u_set_mask_while_drawing", + "int u_interlaced_displayed_field"}); } std::string GPU_HW_ShaderGen::GenerateBatchVertexShader(bool textured) @@ -394,7 +395,8 @@ std::string GPU_HW_ShaderGen::GenerateBatchVertexShader(bool textured) } std::string GPU_HW_ShaderGen::GenerateBatchFragmentShader(GPU_HW::BatchRenderMode transparency, - GPU::TextureMode texture_mode, bool dithering) + GPU::TextureMode texture_mode, bool dithering, + bool interlacing) { const GPU::TextureMode actual_texture_mode = texture_mode & ~GPU::TextureMode::RawTextureBit; const bool raw_texture = (texture_mode & GPU::TextureMode::RawTextureBit) == GPU::TextureMode::RawTextureBit; @@ -416,6 +418,7 @@ std::string GPU_HW_ShaderGen::GenerateBatchFragmentShader(GPU_HW::BatchRenderMod DefineMacro(ss, "RAW_TEXTURE", raw_texture); DefineMacro(ss, "DITHERING", dithering); DefineMacro(ss, "DITHERING_SCALED", m_scaled_dithering); + DefineMacro(ss, "INTERLACING", interlacing); DefineMacro(ss, "TRUE_COLOR", m_true_color); DefineMacro(ss, "TEXTURE_FILTERING", m_texture_filering); DefineMacro(ss, "USE_DUAL_SOURCE", use_dual_source); @@ -519,6 +522,11 @@ float4 SampleFromVRAM(int4 texpage, int2 icoord) float ialpha; float oalpha; + #if INTERLACING + if (((int(v_pos.y) / RESOLUTION_SCALE) & 1) == u_interlaced_displayed_field) + discard; + #endif + #if TEXTURED #if TEXTURE_FILTERING int2 icoord = int2(v_tex0); diff --git a/src/core/gpu_hw_shadergen.h b/src/core/gpu_hw_shadergen.h index a4d788e63..0f396c137 100644 --- a/src/core/gpu_hw_shadergen.h +++ b/src/core/gpu_hw_shadergen.h @@ -13,7 +13,7 @@ public: std::string GenerateBatchVertexShader(bool textured); std::string GenerateBatchFragmentShader(GPU_HW::BatchRenderMode transparency, GPU::TextureMode texture_mode, - bool dithering); + bool dithering, bool interlacing); std::string GenerateBatchLineExpandGeometryShader(); std::string GenerateScreenQuadVertexShader(); std::string GenerateFillFragmentShader(); diff --git a/src/core/gpu_sw.cpp b/src/core/gpu_sw.cpp index 5b574a012..f31d44dba 100644 --- a/src/core/gpu_sw.cpp +++ b/src/core/gpu_sw.cpp @@ -574,8 +574,11 @@ void GPU_SW::ShadePixel(u32 x, u32 y, u8 color_r, u8 color_g, u8 color_b, u8 tex if ((bg_color.bits & mask_and) != 0) return; - if (m_GPUSTAT.SkipDrawingToActiveField() && BoolToUInt32(m_GPUSTAT.drawing_even_line) != (static_cast(y) & 1u)) + if (m_GPUSTAT.SkipDrawingToActiveField() && + BoolToUInt32(m_GPUSTAT.displaying_odd_line) == (static_cast(y) & 1u)) + { return; + } SetPixel(static_cast(x), static_cast(y), color.bits | m_GPUSTAT.GetMaskOR()); }