diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index b3d957c343..c61b4a0bc2 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -2537,7 +2537,7 @@ namespace rsx // Save current state m_queued_flip.stats = m_frame_stats; - m_queued_flip.buffer = buffer; + m_queued_flip.push(buffer); m_queued_flip.skip_frame = skip_current_frame; if (LIKELY(!forced)) @@ -2579,10 +2579,7 @@ namespace rsx void thread::request_emu_flip(u32 buffer) { - const bool is_rsxthr = std::this_thread::get_id() == m_rsx_thread; - - // requested through command buffer - if (is_rsxthr) + if (is_current_thread()) // requested through command buffer { // NOTE: The flip will clear any queued flip requests handle_emu_flip(buffer); @@ -2608,10 +2605,11 @@ namespace rsx return; } - if (m_queued_flip.buffer == ~0u) + if (!m_queued_flip.pop(buffer)) { // Frame was not queued before flipping on_frame_end(buffer, true); + verify(HERE), m_queued_flip.pop(buffer); } double limit = 0.; @@ -2656,16 +2654,14 @@ namespace rsx int_flip_index++; - verify(HERE), m_queued_flip.buffer == buffer; - current_display_buffer = buffer; m_queued_flip.emu_flip = true; m_queued_flip.in_progress = true; + flip(m_queued_flip); last_flip_time = get_system_time() - 1000000; flip_status = CELL_GCM_DISPLAY_FLIP_STATUS_DONE; - m_queued_flip.buffer = ~0u; m_queued_flip.in_progress = false; if (flip_handler) diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index e8013505c5..d6f397d9ad 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -426,11 +426,42 @@ namespace rsx struct display_flip_info_t { + std::deque buffer_queue; u32 buffer; bool skip_frame; bool emu_flip; bool in_progress; frame_statistics_t stats; + + inline void push(u32 _buffer) + { + buffer_queue.push_back(_buffer); + } + + inline bool pop(u32 _buffer) + { + if (buffer_queue.empty()) + { + return false; + } + + do + { + const auto index = buffer_queue.front(); + buffer_queue.pop_front(); + + if (index == _buffer) + { + buffer = _buffer; + return true; + } + } + while (!buffer_queue.empty()); + + // Need to observe this happening in the wild + LOG_ERROR(RSX, "Display queue was discarded while not empty!"); + return false; + } }; struct sampled_image_descriptor_base;