diff --git a/rpcs3/Emu/RSX/Common/bitfield.hpp b/rpcs3/Emu/RSX/Common/bitfield.hpp index c2bfed7b4c..d3c1f9d2ca 100644 --- a/rpcs3/Emu/RSX/Common/bitfield.hpp +++ b/rpcs3/Emu/RSX/Common/bitfield.hpp @@ -35,6 +35,7 @@ namespace rsx } template + requires std::is_integral_v&& std::is_enum_v class atomic_bitmask_t { private: @@ -95,4 +96,70 @@ namespace rsx return m_data.observe() != 0; } }; + + template + requires std::is_integral_v && std::is_enum_v + class bitmask_t + { + private: + bitmask_type m_data = 0; + + public: + bitmask_t() = default; + + bool operator & (bitmask_type mask) const + { + return !!(m_data & mask); + } + + bitmask_type operator | (bitmask_type mask) const + { + return m_data | mask; + } + + void operator &= (bitmask_type mask) + { + m_data &= mask; + } + + void operator |= (bitmask_type mask) + { + m_data |= mask; + } + + bool test(T mask) + { + return !!(m_data & static_cast(mask)); + } + + void set(T mask) + { + m_data |= static_cast(mask); + } + + bool test_and_set(T mask) + { + const auto old = m_data; + m_data |= static_cast(mask); + return !!(old & mask); + } + + template + requires std::is_same_v || std::is_same_v + void clear(U mask) + { + const bitmask_type clear_mask = ~(static_cast(mask)); + m_data &= clear_mask; + } + + void clear() + { + m_data = 0; + } + + operator bool() const + { + return !!m_data; + } + }; } diff --git a/rpcs3/Emu/RSX/GL/GLDraw.cpp b/rpcs3/Emu/RSX/GL/GLDraw.cpp index 4a6a747f4d..b4e67328a6 100644 --- a/rpcs3/Emu/RSX/GL/GLDraw.cpp +++ b/rpcs3/Emu/RSX/GL/GLDraw.cpp @@ -320,7 +320,7 @@ void GLGSRender::update_draw_state() //NV4097_SET_CLIP_ID_TEST_ENABLE // For OGL Z range is updated every draw as it is separate from viewport config - m_graphics_state &= ~(rsx::pipeline_state::zclip_config_state_dirty); + m_graphics_state.clear(rsx::pipeline_state::zclip_config_state_dirty); m_frame_stats.setup_time += m_profiler.duration(); } diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 09633c7c5d..b7eafb1c56 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -799,13 +799,13 @@ void GLGSRender::load_program_env() const u32 fragment_constants_size = current_fp_metadata.program_constants_buffer_length; - const bool update_transform_constants = !!(m_graphics_state & rsx::pipeline_state::transform_constants_dirty); - const bool update_fragment_constants = !!(m_graphics_state & rsx::pipeline_state::fragment_constants_dirty) && fragment_constants_size; - const bool update_vertex_env = !!(m_graphics_state & rsx::pipeline_state::vertex_state_dirty); - const bool update_fragment_env = !!(m_graphics_state & rsx::pipeline_state::fragment_state_dirty); - const bool update_fragment_texture_env = !!(m_graphics_state & rsx::pipeline_state::fragment_texture_state_dirty); - const bool update_instruction_buffers = (!!m_interpreter_state && m_shader_interpreter.is_interpreter(m_program)); - const bool update_raster_env = (rsx::method_registers.polygon_stipple_enabled() && !!(m_graphics_state & rsx::pipeline_state::polygon_stipple_pattern_dirty)); + const bool update_transform_constants = m_graphics_state & rsx::pipeline_state::transform_constants_dirty; + const bool update_fragment_constants = (m_graphics_state & rsx::pipeline_state::fragment_constants_dirty) && fragment_constants_size; + const bool update_vertex_env = m_graphics_state & rsx::pipeline_state::vertex_state_dirty; + const bool update_fragment_env = m_graphics_state & rsx::pipeline_state::fragment_state_dirty; + const bool update_fragment_texture_env = m_graphics_state & rsx::pipeline_state::fragment_texture_state_dirty; + const bool update_instruction_buffers = !!m_interpreter_state && m_shader_interpreter.is_interpreter(m_program); + const bool update_raster_env = rsx::method_registers.polygon_stipple_enabled() && (m_graphics_state & rsx::pipeline_state::polygon_stipple_pattern_dirty); if (manually_flush_ring_buffers) { @@ -892,7 +892,7 @@ void GLGSRender::load_program_env() std::memcpy(mapping.first, rsx::method_registers.polygon_stipple_pattern(), 128); m_raster_env_ring_buffer->bind_range(GL_RASTERIZER_STATE_BIND_SLOT, mapping.second, 128); - m_graphics_state &= ~(rsx::pipeline_state::polygon_stipple_pattern_dirty); + m_graphics_state.clear(rsx::pipeline_state::polygon_stipple_pattern_dirty); } if (update_instruction_buffers) @@ -954,8 +954,12 @@ void GLGSRender::load_program_env() } } - const u32 handled_flags = (rsx::pipeline_state::fragment_state_dirty | rsx::pipeline_state::vertex_state_dirty | rsx::pipeline_state::transform_constants_dirty | rsx::pipeline_state::fragment_constants_dirty | rsx::pipeline_state::fragment_texture_state_dirty); - m_graphics_state &= ~handled_flags; + m_graphics_state.clear( + rsx::pipeline_state::fragment_state_dirty | + rsx::pipeline_state::vertex_state_dirty | + rsx::pipeline_state::transform_constants_dirty | + rsx::pipeline_state::fragment_constants_dirty | + rsx::pipeline_state::fragment_texture_state_dirty); } void GLGSRender::update_vertex_env(const gl::vertex_upload_info& upload_info) @@ -1065,7 +1069,7 @@ void GLGSRender::do_local_task(rsx::FIFO::state state) //This will re-engage locks and break the texture cache if another thread is waiting in access violation handler! //Only call when there are no waiters m_gl_texture_cache.do_update(); - m_graphics_state &= ~rsx::pipeline_state::framebuffer_reads_dirty; + m_graphics_state.clear(rsx::pipeline_state::framebuffer_reads_dirty); } } diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.h b/rpcs3/Emu/RSX/GL/GLGSRender.h index 0950124634..0d22366760 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.h +++ b/rpcs3/Emu/RSX/GL/GLGSRender.h @@ -78,7 +78,7 @@ class GLGSRender : public GSRender, public ::rsx::reports::ZCULL_control const GLFragmentProgram *m_fragment_prog = nullptr; const GLVertexProgram *m_vertex_prog = nullptr; - u32 m_interpreter_state = 0; + rsx::flags32_t m_interpreter_state = 0; gl::shader_interpreter m_shader_interpreter; gl_render_targets m_rtts; diff --git a/rpcs3/Emu/RSX/GL/GLPresent.cpp b/rpcs3/Emu/RSX/GL/GLPresent.cpp index 1d93256456..2b26413013 100644 --- a/rpcs3/Emu/RSX/GL/GLPresent.cpp +++ b/rpcs3/Emu/RSX/GL/GLPresent.cpp @@ -409,11 +409,11 @@ void GLGSRender::flip(const rsx::display_flip_info_t& info) return false; }); - if (m_draw_fbo && !m_rtts_dirty) + if (m_draw_fbo && !m_graphics_state.test(rsx::rtt_config_dirty)) { // Always restore the active framebuffer m_draw_fbo->bind(); set_viewport(); - set_scissor(!!(m_graphics_state & rsx::pipeline_state::scissor_setup_clipped)); + set_scissor(m_graphics_state & rsx::pipeline_state::scissor_setup_clipped); } } diff --git a/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp b/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp index 7874c0a536..93e0b17aa3 100644 --- a/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp +++ b/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp @@ -103,7 +103,7 @@ u8 rsx::internals::get_pixel_size(rsx::surface_depth_format format) 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) + if (m_current_framebuffer_context == context && !m_graphics_state.test(rsx::rtt_config_dirty) && m_draw_fbo) { // Fast path // Framebuffer usage has not changed, framebuffer exists and config regs have not changed @@ -111,9 +111,8 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool /* return; } - m_rtts_dirty = false; + m_graphics_state.clear(rsx::rtt_config_dirty | rsx::rtt_config_contested); framebuffer_status_valid = false; - m_framebuffer_state_contested = false; get_framebuffer_layout(context, m_framebuffer_layout); if (!framebuffer_status_valid) diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 3a8aa0d87d..842bd119d8 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -524,11 +524,10 @@ namespace rsx return on_access_violation(address, is_writing); }; - m_rtts_dirty = true; m_textures_dirty.fill(true); m_vertex_textures_dirty.fill(true); - m_graphics_state = pipeline_state::all_dirty; + m_graphics_state |= pipeline_state::all_dirty; g_user_asked_for_frame_capture = false; @@ -685,7 +684,7 @@ namespace rsx push_buf.clear(); } - m_graphics_state &= ~rsx::pipeline_state::push_buffer_arrays_dirty; + m_graphics_state.clear(rsx::pipeline_state::push_buffer_arrays_dirty); } element_push_buffer.clear(); @@ -1359,8 +1358,8 @@ 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); framebuffer_status_valid = false; - m_framebuffer_state_contested = false; m_current_framebuffer_context = context; if (layout.width == 0 || layout.height == 0) @@ -1481,7 +1480,10 @@ namespace rsx } color_buffer_unused = !color_write_enabled || layout.target == rsx::surface_target::none; - m_framebuffer_state_contested = color_buffer_unused || depth_buffer_unused; + if (color_buffer_unused || depth_buffer_unused) + { + m_graphics_state.set(rsx::rtt_config_contested); + } break; default: fmt::throw_exception("Unknown framebuffer context 0x%x", static_cast(context)); @@ -1686,7 +1688,7 @@ namespace rsx void thread::on_framebuffer_options_changed(u32 opt) { - if (m_rtts_dirty) + if (m_graphics_state & rsx::rtt_config_dirty) { // Nothing to do return; @@ -1773,9 +1775,9 @@ namespace rsx { evaluate_depth_buffer_state(); - if (m_framebuffer_state_contested) + if (m_graphics_state.test(rsx::rtt_config_contested) && evaluate_depth_buffer_contested()) { - m_rtts_dirty |= evaluate_depth_buffer_contested(); + m_graphics_state.set(rsx::rtt_config_dirty); } break; } @@ -1798,16 +1800,16 @@ namespace rsx evaluate_stencil_buffer_state(); } - if (m_framebuffer_state_contested) + if (m_graphics_state.test(rsx::rtt_config_contested) && evaluate_depth_buffer_contested()) { - m_rtts_dirty |= evaluate_depth_buffer_contested(); + m_graphics_state.set(rsx::rtt_config_dirty); } break; } case NV4097_SET_COLOR_MASK: case NV4097_SET_COLOR_MASK_MRT: { - if (!m_framebuffer_state_contested) [[likely]] + if (!m_graphics_state.test(rsx::rtt_config_contested)) [[likely]] { // Update write masks and continue evaluate_color_buffer_state(); @@ -1824,7 +1826,7 @@ namespace rsx if (!old_state && new_state) { // Color buffers now in use - m_rtts_dirty = true; + m_graphics_state.set(rsx::rtt_config_dirty); } } break; @@ -1836,16 +1838,16 @@ namespace rsx bool thread::get_scissor(areau& region, bool clip_viewport) { - if (!(m_graphics_state & rsx::pipeline_state::scissor_config_state_dirty)) + if (!m_graphics_state.test(rsx::pipeline_state::scissor_config_state_dirty)) { - if (clip_viewport == !!(m_graphics_state & rsx::pipeline_state::scissor_setup_clipped)) + if (clip_viewport == m_graphics_state.test(rsx::pipeline_state::scissor_setup_clipped)) { // Nothing to do return false; } } - m_graphics_state &= ~(rsx::pipeline_state::scissor_config_state_dirty | rsx::pipeline_state::scissor_setup_clipped); + m_graphics_state.clear(rsx::pipeline_state::scissor_config_state_dirty | rsx::pipeline_state::scissor_setup_clipped); u16 x1, x2, y1, y2; @@ -1889,7 +1891,7 @@ namespace rsx if (m_graphics_state & rsx::pipeline_state::scissor_setup_invalid) { - m_graphics_state &= ~rsx::pipeline_state::scissor_setup_invalid; + m_graphics_state.clear(rsx::pipeline_state::scissor_setup_invalid); framebuffer_status_valid = true; } @@ -1901,10 +1903,12 @@ namespace rsx void thread::prefetch_fragment_program() { - if (!(m_graphics_state & rsx::pipeline_state::fragment_program_ucode_dirty)) + if (!m_graphics_state.test(rsx::pipeline_state::fragment_program_ucode_dirty)) + { return; + } - m_graphics_state &= ~rsx::pipeline_state::fragment_program_ucode_dirty; + m_graphics_state.clear(rsx::pipeline_state::fragment_program_ucode_dirty); // Request for update of fragment constants if the program block is invalidated m_graphics_state |= rsx::pipeline_state::fragment_constants_dirty; @@ -1922,7 +1926,7 @@ namespace rsx current_fragment_program.texture_state.import(current_fp_texture_state, current_fp_metadata.referenced_textures_mask); current_fragment_program.valid = true; - if (!(m_graphics_state & rsx::pipeline_state::fragment_program_state_dirty)) + if (!m_graphics_state.test(rsx::pipeline_state::fragment_program_state_dirty)) { // Verify current texture state is valid for (u32 textures_ref = current_fp_metadata.referenced_textures_mask, i = 0; textures_ref; textures_ref >>= 1, ++i) @@ -1937,7 +1941,7 @@ namespace rsx } } - if (!(m_graphics_state & rsx::pipeline_state::fragment_program_state_dirty) && + if (!m_graphics_state.test(rsx::pipeline_state::fragment_program_state_dirty) && (prev_textures_reference_mask != current_fp_metadata.referenced_textures_mask)) { // If different textures are used, upload their coefficients. @@ -1948,10 +1952,12 @@ namespace rsx void thread::prefetch_vertex_program() { - if (!(m_graphics_state & rsx::pipeline_state::vertex_program_ucode_dirty)) + if (!m_graphics_state.test(rsx::pipeline_state::vertex_program_ucode_dirty)) + { return; + } - m_graphics_state &= ~rsx::pipeline_state::vertex_program_ucode_dirty; + m_graphics_state.clear(rsx::pipeline_state::vertex_program_ucode_dirty); // Reload transform constants unconditionally for now m_graphics_state |= rsx::pipeline_state::transform_constants_dirty; @@ -1969,7 +1975,7 @@ namespace rsx current_vertex_program.texture_state.import(current_vp_texture_state, current_vp_metadata.referenced_textures_mask); - if (!(m_graphics_state & rsx::pipeline_state::vertex_program_state_dirty)) + if (!m_graphics_state.test(rsx::pipeline_state::vertex_program_state_dirty)) { // Verify current texture state is valid for (u32 textures_ref = current_vp_metadata.referenced_textures_mask, i = 0; textures_ref; textures_ref >>= 1, ++i) @@ -1993,10 +1999,12 @@ namespace rsx void thread::get_current_vertex_program(const std::array, rsx::limits::vertex_textures_count>& sampler_descriptors) { - if (!(m_graphics_state & rsx::pipeline_state::vertex_program_dirty)) + if (!m_graphics_state.test(rsx::pipeline_state::vertex_program_dirty)) + { return; + } - ensure(!(m_graphics_state & rsx::pipeline_state::vertex_program_ucode_dirty)); + ensure(!m_graphics_state.test(rsx::pipeline_state::vertex_program_ucode_dirty)); current_vertex_program.output_mask = rsx::method_registers.vertex_attrib_output_mask(); current_vertex_program.ctrl = 0; // Reserved @@ -2195,12 +2203,14 @@ namespace rsx void thread::get_current_fragment_program(const std::array, rsx::limits::fragment_textures_count>& sampler_descriptors) { - if (!(m_graphics_state & rsx::pipeline_state::fragment_program_dirty)) + if (!m_graphics_state.test(rsx::pipeline_state::fragment_program_dirty)) + { return; + } - ensure(!(m_graphics_state & rsx::pipeline_state::fragment_program_ucode_dirty)); + ensure(!m_graphics_state.test(rsx::pipeline_state::fragment_program_ucode_dirty)); - m_graphics_state &= ~(rsx::pipeline_state::fragment_program_dirty); + m_graphics_state.clear(rsx::pipeline_state::fragment_program_dirty); current_fragment_program.ctrl = rsx::method_registers.shader_control() & (CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS | CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT); current_fragment_program.texcoord_control_mask = rsx::method_registers.texcoord_control_mask(); @@ -2428,9 +2438,7 @@ namespace rsx rsx::method_registers.reset(); check_zcull_status(false); nv4097::set_render_mode(this, 0, method_registers.registers[NV4097_SET_RENDER_ENABLE]); - m_graphics_state = pipeline_state::all_dirty; - m_rtts_dirty = true; - m_framebuffer_state_contested = false; + m_graphics_state |= pipeline_state::all_dirty; } void thread::init(u32 ctrlAddress) diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index dd2d14dd8b..4ab98f41ad 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -82,6 +82,10 @@ namespace rsx pipeline_config_dirty = 0x100000, // Generic pipeline configuration changes. Shader peek hint. + rtt_config_dirty = 0x200000, // Render target configuration changed + rtt_config_contested = 0x400000, // Render target configuration is indeterminate + texture_cache_state_dirty = 0x800000, // Texture cache state is indeterminate + fragment_program_dirty = fragment_program_ucode_dirty | fragment_program_state_dirty, vertex_program_dirty = vertex_program_ucode_dirty | vertex_program_state_dirty, invalidate_pipeline_bits = fragment_program_dirty | vertex_program_dirty, @@ -288,14 +292,12 @@ namespace rsx bool send_event(u64, u64, u64); - bool m_rtts_dirty = true; std::array m_textures_dirty; std::array m_vertex_textures_dirty; - bool m_framebuffer_state_contested = false; rsx::framebuffer_creation_context m_current_framebuffer_context = rsx::framebuffer_creation_context::context_draw; rsx::atomic_bitmask_t m_eng_interrupt_mask; - u32 m_graphics_state = 0; + rsx::bitmask_t m_graphics_state; u64 ROP_sync_timestamp = 0; program_hash_util::fragment_program_utils::fragment_program_metadata current_fp_metadata = {}; diff --git a/rpcs3/Emu/RSX/VK/VKDraw.cpp b/rpcs3/Emu/RSX/VK/VKDraw.cpp index d93fc3c651..2e6c6f17b2 100644 --- a/rpcs3/Emu/RSX/VK/VKDraw.cpp +++ b/rpcs3/Emu/RSX/VK/VKDraw.cpp @@ -225,7 +225,7 @@ void VKGSRender::update_draw_state() bind_viewport(); m_current_command_buffer->flags &= ~vk::command_buffer::cb_reload_dynamic_state; - m_graphics_state &= ~(rsx::pipeline_state::polygon_offset_state_dirty | rsx::pipeline_state::depth_bounds_state_dirty); + m_graphics_state.clear(rsx::pipeline_state::polygon_offset_state_dirty | rsx::pipeline_state::depth_bounds_state_dirty); m_frame_stats.setup_time += m_profiler.duration(); } diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index d72a7872a2..4ff90dac76 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -1355,7 +1355,7 @@ void VKGSRender::set_viewport() } m_current_command_buffer->flags |= vk::command_buffer::cb_reload_dynamic_state; - m_graphics_state &= ~(rsx::pipeline_state::zclip_config_state_dirty); + m_graphics_state.clear(rsx::pipeline_state::zclip_config_state_dirty); } void VKGSRender::set_scissor(bool clip_viewport) @@ -1382,7 +1382,7 @@ void VKGSRender::bind_viewport() m_viewport.maxDepth = rsx::method_registers.clip_max(); } - m_graphics_state &= ~(rsx::pipeline_state::zclip_config_state_dirty); + m_graphics_state.clear(rsx::pipeline_state::zclip_config_state_dirty); } vkCmdSetViewport(*m_current_command_buffer, 0, 1, &m_viewport); @@ -1888,7 +1888,7 @@ void VKGSRender::do_local_task(rsx::FIFO::state state) //This will re-engage locks and break the texture cache if another thread is waiting in access violation handler! //Only call when there are no waiters m_texture_cache.do_update(); - m_graphics_state &= ~rsx::pipeline_state::framebuffer_reads_dirty; + m_graphics_state.clear(rsx::pipeline_state::framebuffer_reads_dirty); } } @@ -1934,7 +1934,7 @@ bool VKGSRender::load_program() get_current_vertex_program(vs_sampler_state); - m_graphics_state &= ~rsx::pipeline_state::invalidate_pipeline_bits; + m_graphics_state.clear(rsx::pipeline_state::invalidate_pipeline_bits); } else if (!(m_graphics_state & rsx::pipeline_state::pipeline_config_dirty) && m_program && @@ -1978,7 +1978,7 @@ bool VKGSRender::load_program() // Fallthrough m_pipeline_properties = properties; - m_graphics_state &= ~rsx::pipeline_state::pipeline_config_dirty; + m_graphics_state.clear(rsx::pipeline_state::pipeline_config_dirty); } else { @@ -2152,7 +2152,7 @@ void VKGSRender::load_program_env() m_raster_env_ring_info.unmap(); m_raster_env_buffer_info = { m_raster_env_ring_info.heap->value, mem, 128 }; - m_graphics_state &= ~(rsx::pipeline_state::polygon_stipple_pattern_dirty); + m_graphics_state.clear(rsx::pipeline_state::polygon_stipple_pattern_dirty); } if (update_instruction_buffers) @@ -2219,9 +2219,13 @@ void VKGSRender::load_program_env() m_program->bind_buffer({ predicate, 0, 4 }, binding_table.conditional_render_predicate_slot, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, m_current_frame->descriptor_set); } - //Clear flags - const u32 handled_flags = (rsx::pipeline_state::fragment_state_dirty | rsx::pipeline_state::vertex_state_dirty | rsx::pipeline_state::transform_constants_dirty | rsx::pipeline_state::fragment_constants_dirty | rsx::pipeline_state::fragment_texture_state_dirty); - m_graphics_state &= ~handled_flags; + // Clear flags + m_graphics_state.clear( + rsx::pipeline_state::fragment_state_dirty | + rsx::pipeline_state::vertex_state_dirty | + rsx::pipeline_state::transform_constants_dirty | + rsx::pipeline_state::fragment_constants_dirty | + rsx::pipeline_state::fragment_texture_state_dirty); } void VKGSRender::update_vertex_env(u32 id, const vk::vertex_upload_info& vertex_info) @@ -2394,7 +2398,7 @@ void VKGSRender::close_and_submit_command_buffer(vk::fence* pFence, VkSemaphore 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) + if (m_current_framebuffer_context == context && !m_graphics_state.test(rsx::rtt_config_dirty) && m_draw_fbo) { // Fast path // Framebuffer usage has not changed, framebuffer exists and config regs have not changed @@ -2402,9 +2406,8 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context) return; } - m_rtts_dirty = false; + m_graphics_state.clear(rsx::rtt_config_dirty | rsx::rtt_config_contested); framebuffer_status_valid = false; - m_framebuffer_state_contested = false; get_framebuffer_layout(context, m_framebuffer_layout); if (!framebuffer_status_valid) diff --git a/rpcs3/Emu/RSX/rsx_methods.cpp b/rpcs3/Emu/RSX/rsx_methods.cpp index cbf7076298..f535c578ff 100644 --- a/rpcs3/Emu/RSX/rsx_methods.cpp +++ b/rpcs3/Emu/RSX/rsx_methods.cpp @@ -801,8 +801,8 @@ namespace rsx break; } - rsx->m_rtts_dirty = true; - rsx->m_framebuffer_state_contested = false; + rsx->m_graphics_state.set(rtt_config_dirty); + rsx->m_graphics_state.clear(rtt_config_contested); } void set_surface_format(thread* rsx, u32 reg, u32 arg)