diff --git a/src/android/app/src/main/jniLibs/arm64-v8a/libVkLayer_khronos_timeline_semaphore.so b/src/android/app/src/main/jniLibs/arm64-v8a/libVkLayer_khronos_timeline_semaphore.so deleted file mode 100644 index 06545335e..000000000 Binary files a/src/android/app/src/main/jniLibs/arm64-v8a/libVkLayer_khronos_timeline_semaphore.so and /dev/null differ diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index dd9d1bc40..0cdb362fe 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -95,8 +95,6 @@ add_library(common STATIC misc.cpp param_package.cpp param_package.h - polyfill_ranges.h - polyfill_thread.h precompiled_headers.h quaternion.h ring_buffer.h diff --git a/src/common/polyfill_ranges.h b/src/common/polyfill_ranges.h deleted file mode 100644 index ca44bfaef..000000000 --- a/src/common/polyfill_ranges.h +++ /dev/null @@ -1,530 +0,0 @@ -// SPDX-FileCopyrightText: 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -// -// TODO: remove this file when ranges are supported by all compilation targets -// - -#pragma once - -#include -#include -#include - -#ifndef __cpp_lib_ranges - -namespace std { -namespace ranges { - -template -concept range = requires(T& t) { - begin(t); - end(t); -}; - -template -concept input_range = range; - -template -concept output_range = range; - -template -using range_difference_t = ptrdiff_t; - -// -// find, find_if, find_if_not -// - -struct find_fn { - template - constexpr Iterator operator()(Iterator first, Iterator last, const T& value, - Proj proj = {}) const { - for (; first != last; ++first) { - if (std::invoke(proj, *first) == value) { - return first; - } - } - return first; - } - - template - constexpr ranges::iterator_t operator()(R&& r, const T& value, Proj proj = {}) const { - return operator()(ranges::begin(r), ranges::end(r), value, std::ref(proj)); - } -}; - -struct find_if_fn { - template - constexpr Iterator operator()(Iterator first, Iterator last, Pred pred, Proj proj = {}) const { - for (; first != last; ++first) { - if (std::invoke(pred, std::invoke(proj, *first))) { - return first; - } - } - return first; - } - - template - constexpr ranges::iterator_t operator()(R&& r, Pred pred, Proj proj = {}) const { - return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj)); - } -}; - -struct find_if_not_fn { - template - constexpr Iterator operator()(Iterator first, Iterator last, Pred pred, Proj proj = {}) const { - for (; first != last; ++first) { - if (!std::invoke(pred, std::invoke(proj, *first))) { - return first; - } - } - return first; - } - - template - constexpr ranges::iterator_t operator()(R&& r, Pred pred, Proj proj = {}) const { - return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj)); - } -}; - -inline constexpr find_fn find; -inline constexpr find_if_fn find_if; -inline constexpr find_if_not_fn find_if_not; - -// -// any_of, all_of, none_of -// - -struct all_of_fn { - template - constexpr bool operator()(Iterator first, Iterator last, Pred pred, Proj proj = {}) const { - return ranges::find_if_not(first, last, std::ref(pred), std::ref(proj)) == last; - } - - template - constexpr bool operator()(R&& r, Pred pred, Proj proj = {}) const { - return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj)); - } -}; - -struct any_of_fn { - template - constexpr bool operator()(Iterator first, Iterator last, Pred pred, Proj proj = {}) const { - return ranges::find_if(first, last, std::ref(pred), std::ref(proj)) != last; - } - - template - constexpr bool operator()(R&& r, Pred pred, Proj proj = {}) const { - return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj)); - } -}; - -struct none_of_fn { - template - constexpr bool operator()(Iterator first, Iterator last, Pred pred, Proj proj = {}) const { - return ranges::find_if(first, last, std::ref(pred), std::ref(proj)) == last; - } - - template - constexpr bool operator()(R&& r, Pred pred, Proj proj = {}) const { - return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj)); - } -}; - -inline constexpr any_of_fn any_of; -inline constexpr all_of_fn all_of; -inline constexpr none_of_fn none_of; - -// -// count, count_if -// - -struct count_fn { - template - constexpr ptrdiff_t operator()(Iterator first, Iterator last, const T& value, - Proj proj = {}) const { - ptrdiff_t counter = 0; - for (; first != last; ++first) - if (std::invoke(proj, *first) == value) - ++counter; - return counter; - } - - template - constexpr ptrdiff_t operator()(R&& r, const T& value, Proj proj = {}) const { - return operator()(ranges::begin(r), ranges::end(r), value, std::ref(proj)); - } -}; - -struct count_if_fn { - template - constexpr ptrdiff_t operator()(Iterator first, Iterator last, Pred pred, Proj proj = {}) const { - ptrdiff_t counter = 0; - for (; first != last; ++first) - if (std::invoke(pred, std::invoke(proj, *first))) - ++counter; - return counter; - } - - template - constexpr ptrdiff_t operator()(R&& r, Pred pred, Proj proj = {}) const { - return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj)); - } -}; - -inline constexpr count_fn count; -inline constexpr count_if_fn count_if; - -// -// transform -// - -struct transform_fn { - template - constexpr void operator()(InputIterator first1, InputIterator last1, OutputIterator result, - F op, Proj proj = {}) const { - for (; first1 != last1; ++first1, (void)++result) { - *result = std::invoke(op, std::invoke(proj, *first1)); - } - } - - template - constexpr void operator()(R&& r, OutputIterator result, F op, Proj proj = {}) const { - return operator()(ranges::begin(r), ranges::end(r), result, std::ref(op), std::ref(proj)); - } -}; - -inline constexpr transform_fn transform; - -// -// sort -// - -struct sort_fn { - template - constexpr void operator()(Iterator first, Iterator last, Comp comp = {}, Proj proj = {}) const { - if (first == last) - return; - - Iterator last_iter = ranges::next(first, last); - std::sort(first, last_iter, - [&](auto& lhs, auto& rhs) { return comp(proj(lhs), proj(rhs)); }); - } - - template - constexpr void operator()(R&& r, Comp comp = {}, Proj proj = {}) const { - return operator()(ranges::begin(r), ranges::end(r), std::move(comp), std::move(proj)); - } -}; - -inline constexpr sort_fn sort; - -// -// fill -// - -struct fill_fn { - template - constexpr OutputIterator operator()(OutputIterator first, OutputIterator last, - const T& value) const { - while (first != last) { - *first++ = value; - } - - return first; - } - - template - constexpr ranges::iterator_t operator()(R&& r, const T& value) const { - return operator()(ranges::begin(r), ranges::end(r), value); - } -}; - -inline constexpr fill_fn fill; - -// -// for_each -// - -struct for_each_fn { - template - constexpr void operator()(Iterator first, Iterator last, Fun f, Proj proj = {}) const { - for (; first != last; ++first) { - std::invoke(f, std::invoke(proj, *first)); - } - } - - template - constexpr void operator()(R&& r, Fun f, Proj proj = {}) const { - return operator()(ranges::begin(r), ranges::end(r), std::move(f), std::ref(proj)); - } -}; - -inline constexpr for_each_fn for_each; - -// -// min_element, max_element -// - -struct min_element_fn { - template - constexpr Iterator operator()(Iterator first, Iterator last, Comp comp = {}, - Proj proj = {}) const { - if (first == last) { - return last; - } - - auto smallest = first; - ++first; - for (; first != last; ++first) { - if (!std::invoke(comp, std::invoke(proj, *smallest), std::invoke(proj, *first))) { - smallest = first; - } - } - return smallest; - } - - template - constexpr ranges::iterator_t operator()(R&& r, Comp comp = {}, Proj proj = {}) const { - return operator()(ranges::begin(r), ranges::end(r), std::ref(comp), std::ref(proj)); - } -}; - -struct max_element_fn { - template - constexpr Iterator operator()(Iterator first, Iterator last, Comp comp = {}, - Proj proj = {}) const { - if (first == last) { - return last; - } - - auto largest = first; - ++first; - for (; first != last; ++first) { - if (std::invoke(comp, std::invoke(proj, *largest), std::invoke(proj, *first))) { - largest = first; - } - } - return largest; - } - - template - constexpr ranges::iterator_t operator()(R&& r, Comp comp = {}, Proj proj = {}) const { - return operator()(ranges::begin(r), ranges::end(r), std::ref(comp), std::ref(proj)); - } -}; - -inline constexpr min_element_fn min_element; -inline constexpr max_element_fn max_element; - -// -// replace, replace_if -// - -struct replace_fn { - template - constexpr Iterator operator()(Iterator first, Iterator last, const T1& old_value, - const T2& new_value, Proj proj = {}) const { - for (; first != last; ++first) { - if (old_value == std::invoke(proj, *first)) { - *first = new_value; - } - } - return first; - } - - template - constexpr ranges::iterator_t operator()(R&& r, const T1& old_value, const T2& new_value, - Proj proj = {}) const { - return operator()(ranges::begin(r), ranges::end(r), old_value, new_value, std::move(proj)); - } -}; - -struct replace_if_fn { - template - constexpr Iterator operator()(Iterator first, Iterator last, Pred pred, const T& new_value, - Proj proj = {}) const { - for (; first != last; ++first) { - if (!!std::invoke(pred, std::invoke(proj, *first))) { - *first = new_value; - } - } - return std::move(first); - } - - template - constexpr ranges::iterator_t operator()(R&& r, Pred pred, const T& new_value, - Proj proj = {}) const { - return operator()(ranges::begin(r), ranges::end(r), std::move(pred), new_value, - std::move(proj)); - } -}; - -inline constexpr replace_fn replace; -inline constexpr replace_if_fn replace_if; - -// -// copy, copy_if -// - -struct copy_fn { - template - constexpr void operator()(InputIterator first, InputIterator last, - OutputIterator result) const { - for (; first != last; ++first, (void)++result) { - *result = *first; - } - } - - template - constexpr void operator()(R&& r, OutputIterator result) const { - return operator()(ranges::begin(r), ranges::end(r), std::move(result)); - } -}; - -struct copy_if_fn { - template - constexpr void operator()(InputIterator first, InputIterator last, OutputIterator result, - Pred pred, Proj proj = {}) const { - for (; first != last; ++first) { - if (std::invoke(pred, std::invoke(proj, *first))) { - *result = *first; - ++result; - } - } - } - - template - constexpr void operator()(R&& r, OutputIterator result, Pred pred, Proj proj = {}) const { - return operator()(ranges::begin(r), ranges::end(r), std::move(result), std::ref(pred), - std::ref(proj)); - } -}; - -inline constexpr copy_fn copy; -inline constexpr copy_if_fn copy_if; - -// -// generate -// - -struct generate_fn { - template - constexpr Iterator operator()(Iterator first, Iterator last, F gen) const { - for (; first != last; *first = std::invoke(gen), ++first) - ; - return first; - } - - template - requires std::invocable && ranges::output_range - constexpr ranges::iterator_t operator()(R&& r, F gen) const { - return operator()(ranges::begin(r), ranges::end(r), std::move(gen)); - } -}; - -inline constexpr generate_fn generate; - -// -// lower_bound, upper_bound -// - -struct lower_bound_fn { - template - constexpr Iterator operator()(Iterator first, Iterator last, const T& value, Comp comp = {}, - Proj proj = {}) const { - Iterator it; - std::ptrdiff_t _count, _step; - _count = std::distance(first, last); - - while (_count > 0) { - it = first; - _step = _count / 2; - ranges::advance(it, _step, last); - if (comp(std::invoke(proj, *it), value)) { - first = ++it; - _count -= _step + 1; - } else { - _count = _step; - } - } - return first; - } - - template - constexpr ranges::iterator_t operator()(R&& r, const T& value, Comp comp = {}, - Proj proj = {}) const { - return operator()(ranges::begin(r), ranges::end(r), value, std::ref(comp), std::ref(proj)); - } -}; - -struct upper_bound_fn { - template - constexpr Iterator operator()(Iterator first, Iterator last, const T& value, Comp comp = {}, - Proj proj = {}) const { - Iterator it; - std::ptrdiff_t _count, _step; - _count = std::distance(first, last); - - while (_count > 0) { - it = first; - _step = _count / 2; - ranges::advance(it, _step, last); - if (!comp(value, std::invoke(proj, *it))) { - first = ++it; - _count -= _step + 1; - } else { - _count = _step; - } - } - return first; - } - - template - constexpr ranges::iterator_t operator()(R&& r, const T& value, Comp comp = {}, - Proj proj = {}) const { - return operator()(ranges::begin(r), ranges::end(r), value, std::ref(comp), std::ref(proj)); - } -}; - -inline constexpr lower_bound_fn lower_bound; -inline constexpr upper_bound_fn upper_bound; - -// -// adjacent_find -// - -struct adjacent_find_fn { - template - constexpr Iterator operator()(Iterator first, Iterator last, Pred pred = {}, - Proj proj = {}) const { - if (first == last) - return first; - auto _next = ranges::next(first); - for (; _next != last; ++_next, ++first) - if (std::invoke(pred, std::invoke(proj, *first), std::invoke(proj, *_next))) - return first; - return _next; - } - - template - constexpr ranges::iterator_t operator()(R&& r, Pred pred = {}, Proj proj = {}) const { - return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj)); - } -}; - -inline constexpr adjacent_find_fn adjacent_find; - -} // namespace ranges -} // namespace std - -#endif diff --git a/src/common/polyfill_thread.h b/src/common/polyfill_thread.h deleted file mode 100644 index 5a8d1ce08..000000000 --- a/src/common/polyfill_thread.h +++ /dev/null @@ -1,323 +0,0 @@ -// SPDX-FileCopyrightText: 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -// -// TODO: remove this file when jthread is supported by all compilation targets -// - -#pragma once - -#include - -#ifdef __cpp_lib_jthread - -#include -#include - -namespace Common { - -template -void CondvarWait(Condvar& cv, Lock& lock, std::stop_token token, Pred&& pred) { - cv.wait(lock, token, std::move(pred)); -} - -} // namespace Common - -#else - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace std { -namespace polyfill { - -using stop_state_callbacks = list>; - -class stop_state { -public: - stop_state() = default; - ~stop_state() = default; - - bool request_stop() { - stop_state_callbacks callbacks; - - { - scoped_lock lk{m_lock}; - - if (m_stop_requested.load()) { - // Already set, nothing to do - return false; - } - - // Set as requested - m_stop_requested = true; - - // Copy callback list - callbacks = m_callbacks; - } - - for (auto callback : callbacks) { - callback(); - } - - return true; - } - - bool stop_requested() const { - return m_stop_requested.load(); - } - - stop_state_callbacks::const_iterator insert_callback(function f) { - stop_state_callbacks::const_iterator ret{}; - bool should_run{}; - - { - scoped_lock lk{m_lock}; - should_run = m_stop_requested.load(); - m_callbacks.push_front(f); - ret = m_callbacks.begin(); - } - - if (should_run) { - f(); - } - - return ret; - } - - void remove_callback(stop_state_callbacks::const_iterator it) { - scoped_lock lk{m_lock}; - m_callbacks.erase(it); - } - -private: - mutex m_lock; - atomic m_stop_requested; - stop_state_callbacks m_callbacks; -}; - -} // namespace polyfill - -class stop_token; -class stop_source; -struct nostopstate_t { - explicit nostopstate_t() = default; -}; -inline constexpr nostopstate_t nostopstate{}; - -template -class stop_callback; - -class stop_token { -public: - stop_token() noexcept = default; - - stop_token(const stop_token&) noexcept = default; - stop_token(stop_token&&) noexcept = default; - stop_token& operator=(const stop_token&) noexcept = default; - stop_token& operator=(stop_token&&) noexcept = default; - ~stop_token() = default; - - void swap(stop_token& other) noexcept { - m_stop_state.swap(other.m_stop_state); - } - - [[nodiscard]] bool stop_requested() const noexcept { - return m_stop_state && m_stop_state->stop_requested(); - } - [[nodiscard]] bool stop_possible() const noexcept { - return m_stop_state != nullptr; - } - -private: - friend class stop_source; - template - friend class stop_callback; - stop_token(shared_ptr stop_state) : m_stop_state(move(stop_state)) {} - -private: - shared_ptr m_stop_state; -}; - -class stop_source { -public: - stop_source() : m_stop_state(make_shared()) {} - explicit stop_source(nostopstate_t) noexcept {} - - stop_source(const stop_source&) noexcept = default; - stop_source(stop_source&&) noexcept = default; - stop_source& operator=(const stop_source&) noexcept = default; - stop_source& operator=(stop_source&&) noexcept = default; - ~stop_source() = default; - void swap(stop_source& other) noexcept { - m_stop_state.swap(other.m_stop_state); - } - - [[nodiscard]] stop_token get_token() const noexcept { - return stop_token(m_stop_state); - } - [[nodiscard]] bool stop_possible() const noexcept { - return m_stop_state != nullptr; - } - [[nodiscard]] bool stop_requested() const noexcept { - return m_stop_state && m_stop_state->stop_requested(); - } - bool request_stop() noexcept { - return m_stop_state && m_stop_state->request_stop(); - } - -private: - friend class jthread; - explicit stop_source(shared_ptr stop_state) - : m_stop_state(move(stop_state)) {} - -private: - shared_ptr m_stop_state; -}; - -template -class stop_callback { - static_assert(is_nothrow_destructible_v); - static_assert(is_invocable_v); - -public: - using callback_type = Callback; - - template - requires constructible_from - explicit stop_callback(const stop_token& st, - C&& cb) noexcept(is_nothrow_constructible_v) - : m_stop_state(st.m_stop_state) { - if (m_stop_state) { - m_callback = m_stop_state->insert_callback(move(cb)); - } - } - template - requires constructible_from - explicit stop_callback(stop_token&& st, - C&& cb) noexcept(is_nothrow_constructible_v) - : m_stop_state(move(st.m_stop_state)) { - if (m_stop_state) { - m_callback = m_stop_state->insert_callback(move(cb)); - } - } - ~stop_callback() { - if (m_stop_state && m_callback) { - m_stop_state->remove_callback(*m_callback); - } - } - - stop_callback(const stop_callback&) = delete; - stop_callback(stop_callback&&) = delete; - stop_callback& operator=(const stop_callback&) = delete; - stop_callback& operator=(stop_callback&&) = delete; - -private: - shared_ptr m_stop_state; - optional m_callback; -}; - -template -stop_callback(stop_token, Callback) -> stop_callback; - -class jthread { -public: - using id = thread::id; - using native_handle_type = thread::native_handle_type; - - jthread() noexcept = default; - - template , jthread>>> - explicit jthread(F&& f, Args&&... args) - : m_stop_state(make_shared()), - m_thread(make_thread(move(f), move(args)...)) {} - - ~jthread() { - if (joinable()) { - request_stop(); - join(); - } - } - - jthread(const jthread&) = delete; - jthread(jthread&&) noexcept = default; - jthread& operator=(const jthread&) = delete; - - jthread& operator=(jthread&& other) noexcept { - m_thread.swap(other.m_thread); - m_stop_state.swap(other.m_stop_state); - return *this; - } - - void swap(jthread& other) noexcept { - m_thread.swap(other.m_thread); - m_stop_state.swap(other.m_stop_state); - } - [[nodiscard]] bool joinable() const noexcept { - return m_thread.joinable(); - } - void join() { - m_thread.join(); - } - void detach() { - m_thread.detach(); - m_stop_state.reset(); - } - - [[nodiscard]] id get_id() const noexcept { - return m_thread.get_id(); - } - [[nodiscard]] native_handle_type native_handle() { - return m_thread.native_handle(); - } - [[nodiscard]] stop_source get_stop_source() noexcept { - return stop_source(m_stop_state); - } - [[nodiscard]] stop_token get_stop_token() const noexcept { - return stop_source(m_stop_state).get_token(); - } - bool request_stop() noexcept { - return get_stop_source().request_stop(); - } - [[nodiscard]] static unsigned int hardware_concurrency() noexcept { - return thread::hardware_concurrency(); - } - -private: - template - thread make_thread(F&& f, Args&&... args) { - if constexpr (is_invocable_v, stop_token, decay_t...>) { - return thread(move(f), get_stop_token(), move(args)...); - } else { - return thread(move(f), move(args)...); - } - } - - shared_ptr m_stop_state; - thread m_thread; -}; - -} // namespace std - -namespace Common { - -template -void CondvarWait(Condvar& cv, Lock& lock, std::stop_token token, Pred pred) { - if (token.stop_requested()) { - return; - } - - std::stop_callback callback(token, [&] { cv.notify_all(); }); - cv.wait(lock, [&] { return pred() || token.stop_requested(); }); -} - -} // namespace Common - -#endif diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 3aebab662..5a6a4f9e7 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -401,19 +401,19 @@ bool RasterizerVulkan::AccelerateDrawBatchInternal(bool is_indexed) { regs.pipeline.vertex_attributes.GetPhysicalBaseAddress() + regs.pipeline.index_array.offset); + // Upload index buffer data to the GPU auto [index_ptr, index_offset, _] = index_buffer.Map(index_buffer_size); std::memcpy(index_ptr, index_data, index_buffer_size); index_buffer.Commit(index_buffer_size); - scheduler.Record( - [this, offset = index_offset, index_u16, num_vertices = regs.pipeline.num_vertices, - vertex_offset = static_cast(vs_input_index_min)](vk::CommandBuffer render_cmdbuf, - vk::CommandBuffer) { - const vk::IndexType index_type = - index_u16 ? vk::IndexType::eUint16 : vk::IndexType::eUint8EXT; - render_cmdbuf.bindIndexBuffer(index_buffer.GetHandle(), offset, index_type); - render_cmdbuf.drawIndexed(num_vertices, 1, 0, -vertex_offset, 0); - }); + scheduler.Record([this, offset = index_offset, num_vertices = regs.pipeline.num_vertices, + index_u16, vertex_offset = vs_input_index_min]( + vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) { + const vk::IndexType index_type = + index_u16 ? vk::IndexType::eUint16 : vk::IndexType::eUint8EXT; + render_cmdbuf.bindIndexBuffer(index_buffer.GetHandle(), offset, index_type); + render_cmdbuf.drawIndexed(num_vertices, 1, 0, -vertex_offset, 0); + }); } else { scheduler.Record([num_vertices = regs.pipeline.num_vertices]( vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) { diff --git a/src/video_core/renderer_vulkan/vk_scheduler.cpp b/src/video_core/renderer_vulkan/vk_scheduler.cpp index 19ee3eb7a..f1003cbb4 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.cpp +++ b/src/video_core/renderer_vulkan/vk_scheduler.cpp @@ -29,16 +29,31 @@ void Scheduler::CommandChunk::ExecuteAll(vk::CommandBuffer render_cmdbuf, Scheduler::Scheduler(const Instance& instance, RenderpassCache& renderpass_cache, RendererVulkan& renderer) : instance{instance}, renderpass_cache{renderpass_cache}, renderer{renderer}, - master_semaphore{instance}, command_pool{instance, master_semaphore}, + master_semaphore{instance}, command_pool{instance, master_semaphore}, stop_requested{false}, use_worker_thread{Settings::values.async_command_recording} { AllocateWorkerCommandBuffers(); if (use_worker_thread) { AcquireNewChunk(); - worker_thread = std::jthread([this](std::stop_token token) { WorkerThread(token); }); + worker_thread = std::thread([this]() { WorkerThread(); }); } } -Scheduler::~Scheduler() = default; +Scheduler::~Scheduler() { + if (!use_worker_thread) { + return; + } + + stop_requested = true; + + // Push a dummy chunk to unblock the thread + { + std::scoped_lock lock{work_mutex}; + work_queue.push(std::move(chunk)); + } + + work_cv.notify_one(); + worker_thread.join(); +} void Scheduler::Flush(vk::Semaphore signal, vk::Semaphore wait) { SubmitExecution(signal, wait); @@ -78,7 +93,7 @@ void Scheduler::DispatchWork() { AcquireNewChunk(); } -void Scheduler::WorkerThread(std::stop_token stop_token) { +void Scheduler::WorkerThread() { do { std::unique_ptr work; bool has_submit{false}; @@ -87,8 +102,8 @@ void Scheduler::WorkerThread(std::stop_token stop_token) { if (work_queue.empty()) { wait_cv.notify_all(); } - Common::CondvarWait(work_cv, lock, stop_token, [&] { return !work_queue.empty(); }); - if (stop_token.stop_requested()) { + work_cv.wait(lock, [this] { return !work_queue.empty() || stop_requested; }); + if (stop_requested) { continue; } work = std::move(work_queue.front()); @@ -102,7 +117,7 @@ void Scheduler::WorkerThread(std::stop_token stop_token) { } std::scoped_lock reserve_lock{reserve_mutex}; chunk_reserve.push_back(std::move(work)); - } while (!stop_token.stop_requested()); + } while (!stop_requested); } void Scheduler::AllocateWorkerCommandBuffers() { diff --git a/src/video_core/renderer_vulkan/vk_scheduler.h b/src/video_core/renderer_vulkan/vk_scheduler.h index c3b4f7ee9..13357ca34 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.h +++ b/src/video_core/renderer_vulkan/vk_scheduler.h @@ -6,12 +6,12 @@ #include #include #include +#include #include #include #include "common/alignment.h" #include "common/common_funcs.h" #include "common/common_types.h" -#include "common/polyfill_thread.h" #include "video_core/renderer_vulkan/vk_master_semaphore.h" #include "video_core/renderer_vulkan/vk_resource_pool.h" @@ -187,7 +187,7 @@ private: }; private: - void WorkerThread(std::stop_token stop_token); + void WorkerThread(); void AllocateWorkerCommandBuffers(); @@ -211,7 +211,8 @@ private: std::mutex work_mutex; std::condition_variable_any work_cv; std::condition_variable wait_cv; - std::jthread worker_thread; + std::thread worker_thread; + std::atomic_bool stop_requested; bool use_worker_thread; }; diff --git a/src/video_core/renderer_vulkan/vk_shader_util.h b/src/video_core/renderer_vulkan/vk_shader_util.h index 1e4975b48..7a19cd1d9 100644 --- a/src/video_core/renderer_vulkan/vk_shader_util.h +++ b/src/video_core/renderer_vulkan/vk_shader_util.h @@ -4,7 +4,6 @@ #pragma once -#include #include "video_core/renderer_vulkan/vk_common.h" namespace Vulkan { diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp index ce7c7a5aa..55ce5a497 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.cpp +++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp @@ -2,9 +2,9 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include #include "common/logging/log.h" #include "common/microprofile.h" -#include "common/polyfill_ranges.h" #include "common/settings.h" #include "video_core/renderer_vulkan/vk_instance.h" #include "video_core/renderer_vulkan/vk_renderpass_cache.h" @@ -134,8 +134,8 @@ void Swapchain::FindPresentFormat() { const std::vector formats = instance.GetPhysicalDevice().getSurfaceFormatsKHR(surface); - // If there is a single undefined surface format, the device doesn't care, so we'll just use - // RGBA + // If there is a single undefined surface format, the device doesn't care, so we'll just use + // RGBA if (formats[0].format == vk::Format::eUndefined) { surface_format.format = vk::Format::eR8G8B8A8Unorm; surface_format.colorSpace = vk::ColorSpaceKHR::eSrgbNonlinear; @@ -165,8 +165,9 @@ void Swapchain::SetPresentMode() { instance.GetPhysicalDevice().getSurfacePresentModesKHR(surface); const auto FindMode = [&modes](vk::PresentModeKHR requested) { - auto it = std::ranges::find_if( - modes, [&requested](vk::PresentModeKHR mode) { return mode == requested; }); + auto it = + std::find_if(modes.begin(), modes.end(), + [&requested](vk::PresentModeKHR mode) { return mode == requested; }); return it != modes.end(); };