From 9a7c2784f06bff485b3aa83ef3b47cfa94580a8d Mon Sep 17 00:00:00 2001 From: kd-11 Date: Sat, 20 Jul 2019 14:58:05 +0300 Subject: [PATCH] rsx: Do not clip scissor to viewport when doing buffer clear --- rpcs3/Emu/RSX/GL/GLGSRender.cpp | 6 ++-- rpcs3/Emu/RSX/GL/GLGSRender.h | 4 +-- rpcs3/Emu/RSX/GL/GLRenderTargets.cpp | 7 +++-- rpcs3/Emu/RSX/RSXThread.cpp | 43 +++++++++++++++++++--------- rpcs3/Emu/RSX/RSXThread.h | 3 +- rpcs3/Emu/RSX/VK/VKGSRender.cpp | 11 +++---- rpcs3/Emu/RSX/VK/VKGSRender.h | 2 +- 7 files changed, 48 insertions(+), 28 deletions(-) diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 90edf94aa6..ef8ea4cdfa 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -650,10 +650,10 @@ void GLGSRender::set_viewport() glViewport(0, 0, clip_width, clip_height); } -void GLGSRender::set_scissor() +void GLGSRender::set_scissor(bool clip_viewport) { areau scissor; - if (get_scissor(scissor)) + if (get_scissor(scissor, clip_viewport)) { // NOTE: window origin does not affect scissor region (probably only affects viewport matrix; already applied) // See LIMBO [NPUB-30373] which uses shader window origin = top @@ -1784,7 +1784,7 @@ void GLGSRender::flip(int buffer, bool emu_flip) // Always restore the active framebuffer m_draw_fbo->bind(); set_viewport(); - set_scissor(); + set_scissor(!!(m_graphics_state & rsx::pipeline_state::scissor_setup_clipped)); } // If we are skipping the next frame, do not reset perf counters diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.h b/rpcs3/Emu/RSX/GL/GLGSRender.h index 6997e5a833..485b4b25f6 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.h +++ b/rpcs3/Emu/RSX/GL/GLGSRender.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include "Emu/RSX/GSRender.h" #include "GLHelpers.h" #include "GLTexture.h" @@ -373,7 +373,7 @@ private: public: void read_buffers(); void set_viewport(); - void set_scissor(); + void set_scissor(bool clip_viewport); work_item& post_flush_request(u32 address, gl::texture_cache::thrashed_set& flush_data); diff --git a/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp b/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp index 3e2b94d989..f0bac5e41f 100644 --- a/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp +++ b/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp @@ -172,11 +172,12 @@ namespace void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool skip_reading) { + const bool clipped_scissor = (context == rsx::framebuffer_creation_context::context_draw); if (m_current_framebuffer_context == context && !m_rtts_dirty && m_draw_fbo) { // Fast path // Framebuffer usage has not changed, framebuffer exists and config regs have not changed - set_scissor(); + set_scissor(clipped_scissor); return; } @@ -196,7 +197,7 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool sk // Update flags to match current m_draw_fbo->bind(); set_viewport(); - set_scissor(); + set_scissor(clipped_scissor); return; } @@ -364,7 +365,7 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool sk check_zcull_status(true); set_viewport(); - set_scissor(); + set_scissor(clipped_scissor); m_gl_texture_cache.clear_ro_tex_invalidate_intr(); diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index d7a547c6b5..30dfbdea7d 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -1302,31 +1302,48 @@ namespace rsx return layout; } - bool thread::get_scissor(areau& region) + bool thread::get_scissor(areau& region, bool clip_viewport) { if (!(m_graphics_state & rsx::pipeline_state::scissor_config_state_dirty)) { - // Nothing to do - return false; + if (clip_viewport == !!(m_graphics_state & rsx::pipeline_state::scissor_setup_clipped)) + { + // Nothing to do + return false; + } } - m_graphics_state &= ~rsx::pipeline_state::scissor_config_state_dirty; + m_graphics_state &= ~(rsx::pipeline_state::scissor_config_state_dirty | rsx::pipeline_state::scissor_setup_clipped); + + u16 x1, x2, y1, y2; u16 scissor_x = rsx::method_registers.scissor_origin_x(); u16 scissor_w = rsx::method_registers.scissor_width(); u16 scissor_y = rsx::method_registers.scissor_origin_y(); u16 scissor_h = rsx::method_registers.scissor_height(); - u16 raster_x = rsx::method_registers.viewport_origin_x(); - u16 raster_w = rsx::method_registers.viewport_width(); - u16 raster_y = rsx::method_registers.viewport_origin_y(); - u16 raster_h = rsx::method_registers.viewport_height(); + if (clip_viewport) + { + u16 raster_x = rsx::method_registers.viewport_origin_x(); + u16 raster_w = rsx::method_registers.viewport_width(); + u16 raster_y = rsx::method_registers.viewport_origin_y(); + u16 raster_h = rsx::method_registers.viewport_height(); - // Get the minimum area between these two - u16 x1 = std::max(scissor_x, raster_x); - u16 y1 = std::max(scissor_y, raster_y); - u16 x2 = std::min(scissor_x + scissor_w, raster_x + raster_w); - u16 y2 = std::min(scissor_y + scissor_h, raster_y + raster_h); + // Get the minimum area between these two + x1 = std::max(scissor_x, raster_x); + y1 = std::max(scissor_y, raster_y); + x2 = std::min(scissor_x + scissor_w, raster_x + raster_w); + y2 = std::min(scissor_y + scissor_h, raster_y + raster_h); + + m_graphics_state |= rsx::pipeline_state::scissor_setup_clipped; + } + else + { + x1 = scissor_x; + x2 = scissor_x + scissor_w; + y1 = scissor_y; + y2 = scissor_y + scissor_h; + } if (x2 <= x1 || y2 <= y1 || diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index 7db22d81cb..a448af475a 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -76,6 +76,7 @@ namespace rsx scissor_config_state_dirty = 0x200, // Scissor region changed scissor_setup_invalid = 0x400, // Scissor configuration is broken + scissor_setup_clipped = 0x800, // Scissor region is cropped by viewport constraint invalidate_pipeline_bits = fragment_program_dirty | vertex_program_dirty, memory_barrier_bits = framebuffer_reads_dirty, @@ -521,7 +522,7 @@ namespace rsx u32 get_zeta_surface_address() const; framebuffer_layout get_framebuffer_layout(rsx::framebuffer_creation_context context); - bool get_scissor(areau& region); + bool get_scissor(areau& region, bool clip_viewport); /** * Analyze vertex inputs and group all interleaved blocks diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index 0cf6090bd1..15693169ed 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -1797,10 +1797,10 @@ void VKGSRender::set_viewport() m_viewport.maxDepth = 1.f; } -void VKGSRender::set_scissor() +void VKGSRender::set_scissor(bool clip_viewport) { areau scissor; - if (get_scissor(scissor)) + if (get_scissor(scissor, clip_viewport)) { m_scissor.extent.height = scissor.height(); m_scissor.extent.width = scissor.width(); @@ -2824,11 +2824,12 @@ void VKGSRender::open_command_buffer() void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context) { + const bool clipped_scissor = (context == rsx::framebuffer_creation_context::context_draw); if (m_current_framebuffer_context == context && !m_rtts_dirty && m_draw_fbo) { // Fast path // Framebuffer usage has not changed, framebuffer exists and config regs have not changed - set_scissor(); + set_scissor(clipped_scissor); return; } @@ -2846,7 +2847,7 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context) { // Nothing has changed, we're still using the same framebuffer // Update flags to match current - set_scissor(); + set_scissor(clipped_scissor); return; } @@ -3022,7 +3023,7 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context) m_draw_fbo->add_ref(); set_viewport(); - set_scissor(); + set_scissor(clipped_scissor); check_zcull_status(true); } diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.h b/rpcs3/Emu/RSX/VK/VKGSRender.h index 6120326636..b19ec8fa3d 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.h +++ b/rpcs3/Emu/RSX/VK/VKGSRender.h @@ -460,7 +460,7 @@ public: void read_buffers(); void write_buffers(); void set_viewport(); - void set_scissor(); + void set_scissor(bool clip_viewport); void bind_viewport(); void sync_hint(rsx::FIFO_hint hint) override;