From b560fc14bf2bb3c69f1fecc7991cf362e79653ee Mon Sep 17 00:00:00 2001 From: pineappleEA Date: Mon, 20 Mar 2023 08:00:30 +0100 Subject: [PATCH] early-access version 3467 --- README.md | 2 +- src/common/bounded_threadsafe_queue.h | 203 ++------------------------ src/video_core/gpu_thread.cpp | 3 - 3 files changed, 17 insertions(+), 191 deletions(-) diff --git a/README.md b/README.md index 5c4f3ace7..375956b4f 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ yuzu emulator early access ============= -This is the source code for early-access 3466. +This is the source code for early-access 3467. ## Legal Notice diff --git a/src/common/bounded_threadsafe_queue.h b/src/common/bounded_threadsafe_queue.h index ef491fde2..6e90f59e0 100755 --- a/src/common/bounded_threadsafe_queue.h +++ b/src/common/bounded_threadsafe_queue.h @@ -8,7 +8,6 @@ #include #include #include -#include #include "common/polyfill_thread.h" @@ -23,33 +22,16 @@ class SPSCQueue { static_assert((Capacity & (Capacity - 1)) == 0, "Capacity must be a power of two."); public: - bool TryPush(T&& t) { - return Push(std::move(t)); - } - template bool TryEmplace(Args&&... args) { return Emplace(std::forward(args)...); } - void PushWait(T&& t) { - Push(std::move(t)); - } - template void EmplaceWait(Args&&... args) { Emplace(std::forward(args)...); } - void PushOverwrite(T&& t) { - Push(std::move(t)); - } - - template - void EmplaceOverwrite(Args&&... args) { - Emplace(std::forward(args)...); - } - bool TryPop(T& t) { return Pop(t); } @@ -74,25 +56,10 @@ public: return t; } - void Clear() { - while (!Empty()) { - Pop(); - } - } - - bool Empty() const { - return m_read_index.load() == m_write_index.load(); - } - - size_t Size() const { - return m_write_index.load() - m_read_index.load(); - } - private: enum class PushMode { Try, Wait, - Overwrite, Count, }; @@ -103,68 +70,21 @@ private: Count, }; - template - bool Push(T&& t) { - const size_t write_index = m_write_index.load(); - - if constexpr (Mode == PushMode::Try) { - // Check if we have free slots to write to. - if ((write_index - m_read_index.load()) == Capacity) { - return false; - } - } else if constexpr (Mode == PushMode::Wait) { - // Wait until we have free slots to write to. - std::unique_lock lock{producer_cv_mutex}; - producer_cv.wait(lock, [this, write_index] { - return (write_index - m_read_index.load()) < Capacity; - }); - } else if constexpr (Mode == PushMode::Overwrite) { - // Check if we have free slots to write to. - if ((write_index - m_read_index.load()) == Capacity) { - // If we don't, increment the read index. This is effectively a pop operation. - ++m_read_index; - } - } else { - static_assert(Mode < PushMode::Count, "Invalid PushMode."); - } - - // Determine the position to write to. - const size_t pos = write_index % Capacity; - - // Push into the queue. - m_data[pos] = std::move(t); - - // Increment the write index. - ++m_write_index; - - // Notify the consumer that we have pushed into the queue. - std::scoped_lock lock{consumer_cv_mutex}; - consumer_cv.notify_one(); - - return true; - } - template bool Emplace(Args&&... args) { - const size_t write_index = m_write_index.load(); + const size_t write_index = m_write_index.load(std::memory_order::relaxed); if constexpr (Mode == PushMode::Try) { // Check if we have free slots to write to. - if ((write_index - m_read_index.load()) == Capacity) { + if ((write_index - m_read_index.load(std::memory_order::acquire)) == Capacity) { return false; } } else if constexpr (Mode == PushMode::Wait) { // Wait until we have free slots to write to. std::unique_lock lock{producer_cv_mutex}; producer_cv.wait(lock, [this, write_index] { - return (write_index - m_read_index.load()) < Capacity; + return (write_index - m_read_index.load(std::memory_order::acquire)) < Capacity; }); - } else if constexpr (Mode == PushMode::Overwrite) { - // Check if we have free slots to write to. - if ((write_index - m_read_index.load()) == Capacity) { - // If we don't, increment the read index. This is effectively a pop operation. - ++m_read_index; - } } else { static_assert(Mode < PushMode::Count, "Invalid PushMode."); } @@ -185,47 +105,30 @@ private: return true; } - void Pop() { - const size_t read_index = m_read_index.load(); - - // Check if the queue is empty. - if (read_index == m_write_index.load()) { - return; - } - - // Determine the position to read from. - const size_t pos = read_index % Capacity; - - // Pop the data off the queue, deleting it. - std::destroy_at(std::addressof(m_data[pos])); - - // Increment the read index. - ++m_read_index; - - // Notify the producer that we have popped off the queue. - std::unique_lock lock{producer_cv_mutex}; - producer_cv.notify_one(); - } - template bool Pop(T& t, [[maybe_unused]] std::stop_token stop_token = {}) { - const size_t read_index = m_read_index.load(); + const size_t read_index = m_read_index.load(std::memory_order::relaxed); if constexpr (Mode == PopMode::Try) { // Check if the queue is empty. - if (read_index == m_write_index.load()) { + if (read_index == m_write_index.load(std::memory_order::acquire)) { return false; } } else if constexpr (Mode == PopMode::Wait) { // Wait until the queue is not empty. std::unique_lock lock{consumer_cv_mutex}; - consumer_cv.wait(lock, - [this, read_index] { return read_index != m_write_index.load(); }); + consumer_cv.wait(lock, [this, read_index] { + return read_index != m_write_index.load(std::memory_order::acquire); + }); } else if constexpr (Mode == PopMode::WaitWithStopToken) { // Wait until the queue is not empty. std::unique_lock lock{consumer_cv_mutex}; - Common::CondvarWait(consumer_cv, lock, stop_token, - [this, read_index] { return read_index != m_write_index.load(); }); + Common::CondvarWait(consumer_cv, lock, stop_token, [this, read_index] { + return read_index != m_write_index.load(std::memory_order::acquire); + }); + if (stop_token.stop_requested()) { + return false; + } } else { static_assert(Mode < PopMode::Count, "Invalid PopMode."); } @@ -246,13 +149,8 @@ private: return true; } -#ifdef __cpp_lib_hardware_interference_size - alignas(std::hardware_destructive_interference_size) std::atomic_size_t m_read_index{0}; - alignas(std::hardware_destructive_interference_size) std::atomic_size_t m_write_index{0}; -#else - alignas(64) std::atomic_size_t m_read_index{0}; - alignas(64) std::atomic_size_t m_write_index{0}; -#endif + alignas(128) std::atomic_size_t m_read_index{0}; + alignas(128) std::atomic_size_t m_write_index{0}; std::array m_data; @@ -265,39 +163,18 @@ private: template class MPSCQueue { public: - bool TryPush(T&& t) { - std::scoped_lock lock{write_mutex}; - return spsc_queue.TryPush(std::move(t)); - } - template bool TryEmplace(Args&&... args) { std::scoped_lock lock{write_mutex}; return spsc_queue.TryEmplace(std::forward(args)...); } - void PushWait(T&& t) { - std::scoped_lock lock{write_mutex}; - spsc_queue.PushWait(std::move(t)); - } - template void EmplaceWait(Args&&... args) { std::scoped_lock lock{write_mutex}; spsc_queue.EmplaceWait(std::forward(args)...); } - void PushOverwrite(T&& t) { - std::scoped_lock lock{write_mutex}; - spsc_queue.PushOverwrite(std::move(t)); - } - - template - void EmplaceOverwrite(Args&&... args) { - std::scoped_lock lock{write_mutex}; - spsc_queue.EmplaceOverwrite(std::forward(args)...); - } - bool TryPop(T& t) { return spsc_queue.TryPop(t); } @@ -318,18 +195,6 @@ public: return spsc_queue.PopWait(stop_token); } - void Clear() { - spsc_queue.Clear(); - } - - bool Empty() { - return spsc_queue.Empty(); - } - - size_t Size() { - return spsc_queue.Size(); - } - private: SPSCQueue spsc_queue; std::mutex write_mutex; @@ -338,39 +203,18 @@ private: template class MPMCQueue { public: - bool TryPush(T&& t) { - std::scoped_lock lock{write_mutex}; - return spsc_queue.TryPush(std::move(t)); - } - template bool TryEmplace(Args&&... args) { std::scoped_lock lock{write_mutex}; return spsc_queue.TryEmplace(std::forward(args)...); } - void PushWait(T&& t) { - std::scoped_lock lock{write_mutex}; - spsc_queue.PushWait(std::move(t)); - } - template void EmplaceWait(Args&&... args) { std::scoped_lock lock{write_mutex}; spsc_queue.EmplaceWait(std::forward(args)...); } - void PushOverwrite(T&& t) { - std::scoped_lock lock{write_mutex}; - spsc_queue.PushOverwrite(std::move(t)); - } - - template - void EmplaceOverwrite(Args&&... args) { - std::scoped_lock lock{write_mutex}; - spsc_queue.EmplaceOverwrite(std::forward(args)...); - } - bool TryPop(T& t) { std::scoped_lock lock{read_mutex}; return spsc_queue.TryPop(t); @@ -396,21 +240,6 @@ public: return spsc_queue.PopWait(stop_token); } - void Clear() { - std::scoped_lock lock{read_mutex}; - spsc_queue.Clear(); - } - - bool Empty() { - std::scoped_lock lock{read_mutex}; - return spsc_queue.Empty(); - } - - size_t Size() { - std::scoped_lock lock{read_mutex}; - return spsc_queue.Size(); - } - private: SPSCQueue spsc_queue; std::mutex write_mutex; diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp index 31b09755c..223e76465 100755 --- a/src/video_core/gpu_thread.cpp +++ b/src/video_core/gpu_thread.cpp @@ -59,9 +59,6 @@ static void RunThread(std::stop_token stop_token, Core::System& system, state.cv.notify_all(); } } - - // Drain the queue. - state.queue.Clear(); } ThreadManager::ThreadManager(Core::System& system_, bool is_async_)