diff --git a/rpcs3/Emu/RSX/Common/bitfield.hpp b/rpcs3/Emu/RSX/Common/bitfield.hpp index c1b8af5f8e..c2bfed7b4c 100644 --- a/rpcs3/Emu/RSX/Common/bitfield.hpp +++ b/rpcs3/Emu/RSX/Common/bitfield.hpp @@ -89,5 +89,10 @@ namespace rsx { m_data.release(0); } + + operator bool () const + { + return m_data.observe() != 0; + } }; } diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index cf7bf3d31a..db27d87056 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -967,7 +967,7 @@ bool GLGSRender::on_access_violation(u32 address, bool is_writing) { auto &task = post_flush_request(address, result); - m_graphics_state |= rsx::pipeline_state::backend_interrupt; + m_eng_interrupt_mask |= rsx::backend_interrupt; vm::temporary_unlock(); task.producer_wait(); } diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index f0066f57dd..17b518bee0 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -521,6 +521,7 @@ namespace rsx method_registers.current_draw_clause.post_execute_cleanup(); m_graphics_state |= rsx::pipeline_state::framebuffer_reads_dirty; + m_eng_interrupt_mask |= rsx::backend_interrupt; ROP_sync_timestamp = rsx::get_shared_tag(); if (m_graphics_state & rsx::pipeline_state::push_buffer_arrays_dirty) @@ -766,8 +767,7 @@ namespace rsx // Update sub-units every 64 cycles. The local handler is invoked for other functions externally on-demand anyway. // This avoids expensive calls to check timestamps which involves reading some values from TLS storage on windows. // If something is going on in the backend that requires an update, set the interrupt bit explicitly. - if ((m_cycles_counter++ & 63) == 0 || - m_graphics_state & rsx::pipeline_state::backend_interrupt_bits) + if ((m_cycles_counter++ & 63) == 0 || m_eng_interrupt_mask) { // Execute backend-local tasks first do_local_task(performance_counters.state); @@ -1049,7 +1049,7 @@ namespace rsx void thread::do_local_task(FIFO_state state) { - m_graphics_state &= ~rsx::pipeline_state::backend_interrupt; + m_eng_interrupt_mask.clear(rsx::backend_interrupt); if (async_flip_requested & flip_request::emu_requested) { @@ -2480,6 +2480,8 @@ namespace rsx void thread::flip(const display_flip_info_t& info) { + m_eng_interrupt_mask.clear(rsx::display_interrupt); + if (async_flip_requested & flip_request::any) { // Deferred flip @@ -2965,14 +2967,14 @@ namespace rsx m_invalidated_memory_range = unmap_range; } - m_graphics_state |= rsx::pipeline_state::memory_config_interrupt; + m_eng_interrupt_mask |= rsx::memory_config_interrupt; } } // NOTE: m_mtx_task lock must be acquired before calling this method void thread::handle_invalidated_memory_range() { - m_graphics_state &= ~rsx::pipeline_state::memory_config_interrupt; + m_eng_interrupt_mask.clear(rsx::memory_config_interrupt); if (!m_invalidated_memory_range.valid()) return; @@ -3159,7 +3161,7 @@ namespace rsx async_flip_buffer = buffer; async_flip_requested |= flip_request::emu_requested; - m_graphics_state |= rsx::pipeline_state::backend_interrupt; + m_eng_interrupt_mask |= rsx::display_interrupt; } } diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index c02b1bb7a7..452631aa97 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -132,19 +132,24 @@ namespace rsx push_buffer_arrays_dirty = 0x20000, // Push buffers have data written to them (immediate mode vertex buffers) - backend_interrupt = 0x80000000, // Backend interrupt, must serve immediately - memory_config_interrupt = 0x40000000, // Memory configuration changed - 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, invalidate_zclip_bits = vertex_state_dirty | zclip_config_state_dirty, memory_barrier_bits = framebuffer_reads_dirty, - backend_interrupt_bits = memory_barrier_bits | memory_config_interrupt | backend_interrupt, all_dirty = ~0u }; + enum eng_interrupt_reason : u32 + { + backend_interrupt = 0x0001, // Backend-related interrupt + memory_config_interrupt = 0x0002, // Memory configuration changed + display_interrupt = 0x0004, // Display handling + + all_interrupt_bits = memory_config_interrupt | backend_interrupt | display_interrupt + }; + enum FIFO_state : u8 { running = 0, @@ -565,6 +570,7 @@ namespace rsx 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; u64 ROP_sync_timestamp = 0; diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index 15a145d31a..43da3996db 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -804,7 +804,7 @@ bool VKGSRender::on_access_violation(u32 address, bool is_writing) g_fxo->get().set_mem_fault_flag(); m_queue_status |= flush_queue_state::deadlock; - m_graphics_state |= rsx::pipeline_state::backend_interrupt; + m_eng_interrupt_mask |= rsx::backend_interrupt; // Wait for deadlock to clear while (m_queue_status & flush_queue_state::deadlock) @@ -825,7 +825,7 @@ bool VKGSRender::on_access_violation(u32 address, bool is_writing) std::lock_guard lock(m_flush_queue_mutex); m_flush_requests.post(false); - m_graphics_state |= rsx::pipeline_state::backend_interrupt; + m_eng_interrupt_mask |= rsx::backend_interrupt; has_queue_ref = true; } else