diff --git a/rpcs3/Emu/RSX/Common/bitfield.hpp b/rpcs3/Emu/RSX/Common/bitfield.hpp index f0e7f704b3..c9e1fcdce3 100644 --- a/rpcs3/Emu/RSX/Common/bitfield.hpp +++ b/rpcs3/Emu/RSX/Common/bitfield.hpp @@ -133,7 +133,7 @@ namespace rsx m_data |= mask; } - bool test(T mask) + bool test(T mask) const { return !!(m_data & static_cast(mask)); } diff --git a/rpcs3/Emu/RSX/Core/RSXDriverState.h b/rpcs3/Emu/RSX/Core/RSXDriverState.h index b95bafb7d2..2af5785734 100644 --- a/rpcs3/Emu/RSX/Core/RSXDriverState.h +++ b/rpcs3/Emu/RSX/Core/RSXDriverState.h @@ -36,14 +36,15 @@ namespace rsx rtt_config_dirty = (1 << 21), // Render target configuration changed rtt_config_contested = (1 << 22), // Render target configuration is indeterminate rtt_config_valid = (1 << 23), // Render target configuration is valid - rtt_cache_state_dirty = (1 << 24), // Texture cache state is indeterminate + rtt_config_no_attachments = (1 << 24), // Render target configuration has no attachments + rtt_cache_state_dirty = (1 << 25), // Texture cache state is indeterminate - xform_instancing_state_dirty = (1 << 25), // Transform instancing state has changed + xform_instancing_state_dirty = (1 << 26), // Transform instancing state has changed - zeta_address_is_cyclic = (1 << 26), // The currently bound Z buffer is active for R/W in a cyclic manner - zeta_address_cyclic_barrier = (1 << 27), // A memory barrier is required to "end" the Z buffer cyclic state + zeta_address_is_cyclic = (1 << 27), // The currently bound Z buffer is active for R/W in a cyclic manner + zeta_address_cyclic_barrier = (1 << 28), // A memory barrier is required to "end" the Z buffer cyclic state - blend_config_dirty = (1 << 28), // Blending configuration has been updated. Only matters when programmable blending is in use. + blend_config_dirty = (1 << 29), // Blending configuration has been updated. Only matters when programmable blending is in use. // TODO - Should signal that we simply need to do a FP compare before the next draw call and invalidate the ucode if the content has changed. // Marking as dirty to invalidate hot cache also works, it's not like there's tons of barriers per frame anyway. diff --git a/rpcs3/Emu/RSX/GL/GLDraw.cpp b/rpcs3/Emu/RSX/GL/GLDraw.cpp index da6492e8ca..555a44e763 100644 --- a/rpcs3/Emu/RSX/GL/GLDraw.cpp +++ b/rpcs3/Emu/RSX/GL/GLDraw.cpp @@ -929,7 +929,7 @@ void GLGSRender::end() { m_profiler.start(); - if (skip_current_frame || !m_graphics_state.test(rsx::rtt_config_valid) || cond_render_ctrl.disable_rendering()) + if (should_skip_draw()) { execute_nop_draw(); rsx::thread::end(); diff --git a/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp b/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp index 74fd523a42..eac8463968 100644 --- a/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp +++ b/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp @@ -268,8 +268,7 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool /* ensure(m_draw_fbo); - if (!depth_stencil_target && - std::all_of(color_targets.begin(), color_targets.end(), FN(x == GL_NONE))) + if (m_graphics_state.test(rsx::rtt_config_no_attachments)) { // Framebufferless rendering. Raster dimensions must be supplied explicitly and match what real surfaces would have used. const auto [raster_width, raster_height] = rsx::apply_resolution_scale( diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 302a95bc83..2e03962921 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -1005,6 +1005,22 @@ namespace rsx while (method_registers.current_draw_clause.next()); } + bool thread::should_skip_draw() const + { + if (skip_current_frame || !m_graphics_state.test(rsx::rtt_config_valid) || cond_render_ctrl.disable_rendering()) + { + return true; + } + + if (m_graphics_state.test(rsx::rtt_config_no_attachments) && + (g_cfg.video.disable_zcull_queries || !zcull_ctrl->has_active_queries())) + { + return true; + } + + return false; + } + void thread::cpu_task() { while (Emu.IsReady()) @@ -1461,7 +1477,7 @@ namespace rsx layout.width = rsx::method_registers.surface_clip_width(); layout.height = rsx::method_registers.surface_clip_height(); - m_graphics_state.clear(rsx::rtt_config_contested | rsx::rtt_config_valid); + m_graphics_state.clear(rsx::rtt_config_contested | rsx::rtt_config_valid | rsx::rtt_config_no_attachments); m_current_framebuffer_context = context; if (layout.width == 0 || layout.height == 0) @@ -1785,7 +1801,7 @@ namespace rsx } // Context must be draw now... - // TODO: Also disable rendering if ZPASS stat counting is not enabled (side-effect) + m_graphics_state.set(rsx::rtt_config_no_attachments); } // At least one attachment exists diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index 7c6042abf5..6b016582bc 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -365,6 +365,7 @@ namespace rsx virtual void begin(); virtual void end(); virtual void execute_nop_draw(); + bool should_skip_draw() const; virtual void on_init_thread() = 0; virtual void on_frame_end(u32 buffer, bool forced = false); diff --git a/rpcs3/Emu/RSX/RSXZCULL.h b/rpcs3/Emu/RSX/RSXZCULL.h index 8823905a9d..3c5f4b6500 100644 --- a/rpcs3/Emu/RSX/RSXZCULL.h +++ b/rpcs3/Emu/RSX/RSXZCULL.h @@ -187,6 +187,15 @@ namespace rsx // Check for pending writes bool has_pending() const { return !m_pending_writes.empty(); } + // Check if queries are currently active + bool has_active_queries() const { return host_queries_active; } + + // Check if ZPASS_COUNT stats are running + bool is_zpass_count_active() const { return zpass_count_enabled; } + + // Grab the currently active query block + occlusion_query_info* get_current_query_task() const { return m_current_task; } + // Search for query synchronized at address query_search_result find_query(vm::addr_t sink_address, bool all);