diff options
79 files changed, 952 insertions, 37 deletions
| diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index 9740e017c..25ef0c058 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -67,6 +67,9 @@ if (YUZU_USE_EXTERNAL_SDL2)      endif()      set(SDL_STATIC ON)      set(SDL_SHARED OFF) +    if (APPLE) +        set(SDL_FILE ON) +    endif()      add_subdirectory(SDL EXCLUDE_FROM_ALL)  endif() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0ac3d254e..4bd5aa50b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -112,6 +112,8 @@ else()          $<$<CXX_COMPILER_ID:Clang>:-Wno-braced-scalar-init>          $<$<CXX_COMPILER_ID:Clang>:-Wno-unused-private-field> +        $<$<CXX_COMPILER_ID:AppleClang>:-Wno-braced-scalar-init> +        $<$<CXX_COMPILER_ID:AppleClang>:-Wno-unused-private-field>      )      if (ARCHITECTURE_x86_64) diff --git a/src/audio_core/audio_event.cpp b/src/audio_core/audio_event.cpp index 424049c7a..d15568e1f 100644 --- a/src/audio_core/audio_event.cpp +++ b/src/audio_core/audio_event.cpp @@ -3,6 +3,7 @@  #include "audio_core/audio_event.h"  #include "common/assert.h" +#include "common/polyfill_ranges.h"  namespace AudioCore { diff --git a/src/audio_core/audio_manager.h b/src/audio_core/audio_manager.h index abf077de4..02270242a 100644 --- a/src/audio_core/audio_manager.h +++ b/src/audio_core/audio_manager.h @@ -9,6 +9,8 @@  #include <mutex>  #include <thread> +#include "common/polyfill_thread.h" +  #include "audio_core/audio_event.h"  union Result; diff --git a/src/audio_core/audio_render_manager.h b/src/audio_core/audio_render_manager.h index bf4837190..fffa5944d 100644 --- a/src/audio_core/audio_render_manager.h +++ b/src/audio_core/audio_render_manager.h @@ -7,6 +7,8 @@  #include <memory>  #include <mutex> +#include "common/polyfill_thread.h" +  #include "audio_core/common/common.h"  #include "audio_core/renderer/system_manager.h"  #include "core/hle/service/audio/errors.h" diff --git a/src/audio_core/common/feature_support.h b/src/audio_core/common/feature_support.h index 55c9e690d..e71905ae8 100644 --- a/src/audio_core/common/feature_support.h +++ b/src/audio_core/common/feature_support.h @@ -10,6 +10,7 @@  #include "common/assert.h"  #include "common/common_funcs.h"  #include "common/common_types.h" +#include "common/polyfill_ranges.h"  namespace AudioCore {  constexpr u32 CurrentRevision = 11; diff --git a/src/audio_core/renderer/command/effect/i3dl2_reverb.cpp b/src/audio_core/renderer/command/effect/i3dl2_reverb.cpp index c4bf3943a..2187d8a65 100644 --- a/src/audio_core/renderer/command/effect/i3dl2_reverb.cpp +++ b/src/audio_core/renderer/command/effect/i3dl2_reverb.cpp @@ -5,6 +5,7 @@  #include "audio_core/renderer/adsp/command_list_processor.h"  #include "audio_core/renderer/command/effect/i3dl2_reverb.h" +#include "common/polyfill_ranges.h"  namespace AudioCore::AudioRenderer { diff --git a/src/audio_core/renderer/command/effect/reverb.cpp b/src/audio_core/renderer/command/effect/reverb.cpp index fe2b1eb43..427489214 100644 --- a/src/audio_core/renderer/command/effect/reverb.cpp +++ b/src/audio_core/renderer/command/effect/reverb.cpp @@ -6,6 +6,7 @@  #include "audio_core/renderer/adsp/command_list_processor.h"  #include "audio_core/renderer/command/effect/reverb.h" +#include "common/polyfill_ranges.h"  namespace AudioCore::AudioRenderer { diff --git a/src/audio_core/renderer/mix/mix_context.cpp b/src/audio_core/renderer/mix/mix_context.cpp index 2427c83ed..35b748ede 100644 --- a/src/audio_core/renderer/mix/mix_context.cpp +++ b/src/audio_core/renderer/mix/mix_context.cpp @@ -5,6 +5,7 @@  #include "audio_core/renderer/mix/mix_context.h"  #include "audio_core/renderer/splitter/splitter_context.h" +#include "common/polyfill_ranges.h"  namespace AudioCore::AudioRenderer { diff --git a/src/audio_core/renderer/voice/voice_context.cpp b/src/audio_core/renderer/voice/voice_context.cpp index a501a677d..16a3e839d 100644 --- a/src/audio_core/renderer/voice/voice_context.cpp +++ b/src/audio_core/renderer/voice/voice_context.cpp @@ -4,6 +4,7 @@  #include <ranges>  #include "audio_core/renderer/voice/voice_context.h" +#include "common/polyfill_ranges.h"  namespace AudioCore::AudioRenderer { diff --git a/src/audio_core/sink/sink_stream.cpp b/src/audio_core/sink/sink_stream.cpp index 67e194e3c..06c2a876e 100644 --- a/src/audio_core/sink/sink_stream.cpp +++ b/src/audio_core/sink/sink_stream.cpp @@ -170,8 +170,8 @@ void SinkStream::ProcessAudioIn(std::span<const s16> input_buffer, std::size_t n          // Get the minimum frames available between the currently playing buffer, and the          // amount we have left to fill -        size_t frames_available{std::min(playing_buffer.frames - playing_buffer.frames_played, -                                         num_frames - frames_written)}; +        size_t frames_available{std::min<u64>(playing_buffer.frames - playing_buffer.frames_played, +                                              num_frames - frames_written)};          samples_buffer.Push(&input_buffer[frames_written * frame_size],                              frames_available * frame_size); @@ -241,8 +241,8 @@ void SinkStream::ProcessAudioOutAndRender(std::span<s16> output_buffer, std::siz          // Get the minimum frames available between the currently playing buffer, and the          // amount we have left to fill -        size_t frames_available{std::min(playing_buffer.frames - playing_buffer.frames_played, -                                         num_frames - frames_written)}; +        size_t frames_available{std::min<u64>(playing_buffer.frames - playing_buffer.frames_played, +                                              num_frames - frames_written)};          samples_buffer.Pop(&output_buffer[frames_written * frame_size],                             frames_available * frame_size); diff --git a/src/common/fs/file.cpp b/src/common/fs/file.cpp index fa8422c41..656b03cc5 100644 --- a/src/common/fs/file.cpp +++ b/src/common/fs/file.cpp @@ -1,6 +1,8 @@  // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project  // SPDX-License-Identifier: GPL-2.0-or-later +#include <vector> +  #include "common/fs/file.h"  #include "common/fs/fs.h"  #include "common/logging/log.h" diff --git a/src/common/fs/fs_util.cpp b/src/common/fs/fs_util.cpp index eb4ac1deb..813a713c3 100644 --- a/src/common/fs/fs_util.cpp +++ b/src/common/fs/fs_util.cpp @@ -4,6 +4,7 @@  #include <algorithm>  #include "common/fs/fs_util.h" +#include "common/polyfill_ranges.h"  namespace Common::FS { diff --git a/src/common/fs/path_util.cpp b/src/common/fs/path_util.cpp index 1074f2421..defa3e918 100644 --- a/src/common/fs/path_util.cpp +++ b/src/common/fs/path_util.cpp @@ -2,6 +2,7 @@  // SPDX-License-Identifier: GPL-2.0-or-later  #include <algorithm> +#include <sstream>  #include <unordered_map>  #include "common/fs/fs.h" diff --git a/src/common/input.h b/src/common/input.h index 449e0193f..fc14fd7bf 100644 --- a/src/common/input.h +++ b/src/common/input.h @@ -8,6 +8,7 @@  #include <string>  #include <unordered_map>  #include <utility> +#include <vector>  #include "common/logging/log.h"  #include "common/param_package.h"  #include "common/uuid.h" diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index 15d92505e..2a3bded40 100644 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp @@ -4,7 +4,6 @@  #include <atomic>  #include <chrono>  #include <climits> -#include <stop_token>  #include <thread>  #include <fmt/format.h> @@ -18,6 +17,7 @@  #include "common/fs/fs_paths.h"  #include "common/fs/path_util.h"  #include "common/literals.h" +#include "common/polyfill_thread.h"  #include "common/thread.h"  #include "common/logging/backend.h" diff --git a/src/common/polyfill_ranges.h b/src/common/polyfill_ranges.h new file mode 100644 index 000000000..ca44bfaef --- /dev/null +++ b/src/common/polyfill_ranges.h @@ -0,0 +1,530 @@ +// 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 <algorithm> +#include <utility> +#include <version> + +#ifndef __cpp_lib_ranges + +namespace std { +namespace ranges { + +template <typename T> +concept range = requires(T& t) { +    begin(t); +    end(t); +}; + +template <typename T> +concept input_range = range<T>; + +template <typename T> +concept output_range = range<T>; + +template <range R> +using range_difference_t = ptrdiff_t; + +// +// find, find_if, find_if_not +// + +struct find_fn { +    template <typename Iterator, typename T, typename Proj = std::identity> +    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 <ranges::input_range R, typename T, typename Proj = std::identity> +    constexpr ranges::iterator_t<R> 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 <typename Iterator, typename Proj = std::identity, typename Pred> +    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 <ranges::input_range R, typename Proj = std::identity, typename Pred> +    constexpr ranges::iterator_t<R> 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 <typename Iterator, typename Proj = std::identity, typename Pred> +    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 <ranges::input_range R, typename Proj = std::identity, typename Pred> +    constexpr ranges::iterator_t<R> 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 <typename Iterator, typename Proj = std::identity, typename Pred> +    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 <ranges::input_range R, typename Proj = std::identity, typename Pred> +    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 <typename Iterator, typename Proj = std::identity, typename Pred> +    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 <ranges::input_range R, typename Proj = std::identity, typename Pred> +    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 <typename Iterator, typename Proj = std::identity, typename Pred> +    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 <ranges::input_range R, typename Proj = std::identity, typename Pred> +    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 <typename Iterator, typename T, typename Proj = std::identity> +    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 <ranges::input_range R, typename T, typename Proj = std::identity> +    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 <typename Iterator, typename Proj = std::identity, typename Pred> +    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 <ranges::input_range R, typename Proj = std::identity, typename Pred> +    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 <typename InputIterator, typename OutputIterator, typename F, +              typename Proj = std::identity> +    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 <ranges::input_range R, typename OutputIterator, typename F, +              typename Proj = std::identity> +    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 <typename Iterator, typename Comp = ranges::less, typename Proj = std::identity> +    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 <ranges::input_range R, typename Comp = ranges::less, typename Proj = std::identity> +    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 <typename T, typename OutputIterator> +    constexpr OutputIterator operator()(OutputIterator first, OutputIterator last, +                                        const T& value) const { +        while (first != last) { +            *first++ = value; +        } + +        return first; +    } + +    template <typename T, ranges::output_range R> +    constexpr ranges::iterator_t<R> 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 <typename Iterator, typename Proj = std::identity, typename Fun> +    constexpr void operator()(Iterator first, Iterator last, Fun f, Proj proj = {}) const { +        for (; first != last; ++first) { +            std::invoke(f, std::invoke(proj, *first)); +        } +    } + +    template <ranges::input_range R, typename Proj = std::identity, typename Fun> +    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 <typename Iterator, typename Proj = std::identity, typename Comp = ranges::less> +    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 <ranges::input_range R, typename Proj = std::identity, typename Comp = ranges::less> +    constexpr ranges::iterator_t<R> 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 <typename Iterator, typename Proj = std::identity, typename Comp = ranges::less> +    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 <ranges::input_range R, typename Proj = std::identity, typename Comp = ranges::less> +    constexpr ranges::iterator_t<R> 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 <typename Iterator, typename T1, typename T2, typename Proj = std::identity> +    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 <ranges::input_range R, typename T1, typename T2, typename Proj = std::identity> +    constexpr ranges::iterator_t<R> 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 <typename Iterator, typename T, typename Proj = std::identity, typename Pred> +    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 <ranges::input_range R, typename T, typename Proj = std::identity, typename Pred> +    constexpr ranges::iterator_t<R> 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 <typename InputIterator, typename OutputIterator> +    constexpr void operator()(InputIterator first, InputIterator last, +                              OutputIterator result) const { +        for (; first != last; ++first, (void)++result) { +            *result = *first; +        } +    } + +    template <ranges::input_range R, typename OutputIterator> +    constexpr void operator()(R&& r, OutputIterator result) const { +        return operator()(ranges::begin(r), ranges::end(r), std::move(result)); +    } +}; + +struct copy_if_fn { +    template <typename InputIterator, typename OutputIterator, typename Proj = std::identity, +              typename Pred> +    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 <ranges::input_range R, typename OutputIterator, typename Proj = std::identity, +              typename Pred> +    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 <typename Iterator, typename F> +    constexpr Iterator operator()(Iterator first, Iterator last, F gen) const { +        for (; first != last; *first = std::invoke(gen), ++first) +            ; +        return first; +    } + +    template <typename R, std::copy_constructible F> +    requires std::invocable<F&> && ranges::output_range<R> +    constexpr ranges::iterator_t<R> 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 <typename Iterator, typename T, typename Proj = std::identity, +              typename Comp = ranges::less> +    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 <ranges::input_range R, typename T, typename Proj = std::identity, +              typename Comp = ranges::less> +    constexpr ranges::iterator_t<R> 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 <typename Iterator, typename T, typename Proj = std::identity, +              typename Comp = ranges::less> +    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 <ranges::input_range R, typename T, typename Proj = std::identity, +              typename Comp = ranges::less> +    constexpr ranges::iterator_t<R> 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 <typename Iterator, typename Proj = std::identity, typename Pred = ranges::equal_to> +    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 <ranges::input_range R, typename Proj = std::identity, +              typename Pred = ranges::equal_to> +    constexpr ranges::iterator_t<R> 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 new file mode 100644 index 000000000..5a8d1ce08 --- /dev/null +++ b/src/common/polyfill_thread.h @@ -0,0 +1,323 @@ +// 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 <version> + +#ifdef __cpp_lib_jthread + +#include <stop_token> +#include <thread> + +namespace Common { + +template <typename Condvar, typename Lock, typename Pred> +void CondvarWait(Condvar& cv, Lock& lock, std::stop_token token, Pred&& pred) { +    cv.wait(lock, token, std::move(pred)); +} + +} // namespace Common + +#else + +#include <atomic> +#include <functional> +#include <list> +#include <memory> +#include <mutex> +#include <optional> +#include <thread> +#include <type_traits> + +namespace std { +namespace polyfill { + +using stop_state_callbacks = list<function<void()>>; + +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<void()> 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<bool> 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 Callback> +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 <typename Callback> +    friend class stop_callback; +    stop_token(shared_ptr<polyfill::stop_state> stop_state) : m_stop_state(move(stop_state)) {} + +private: +    shared_ptr<polyfill::stop_state> m_stop_state; +}; + +class stop_source { +public: +    stop_source() : m_stop_state(make_shared<polyfill::stop_state>()) {} +    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<polyfill::stop_state> stop_state) +        : m_stop_state(move(stop_state)) {} + +private: +    shared_ptr<polyfill::stop_state> m_stop_state; +}; + +template <typename Callback> +class stop_callback { +    static_assert(is_nothrow_destructible_v<Callback>); +    static_assert(is_invocable_v<Callback>); + +public: +    using callback_type = Callback; + +    template <typename C> +    requires constructible_from<Callback, C> +    explicit stop_callback(const stop_token& st, +                           C&& cb) noexcept(is_nothrow_constructible_v<Callback, C>) +        : m_stop_state(st.m_stop_state) { +        if (m_stop_state) { +            m_callback = m_stop_state->insert_callback(move(cb)); +        } +    } +    template <typename C> +    requires constructible_from<Callback, C> +    explicit stop_callback(stop_token&& st, +                           C&& cb) noexcept(is_nothrow_constructible_v<Callback, C>) +        : 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<polyfill::stop_state> m_stop_state; +    optional<polyfill::stop_state_callbacks::const_iterator> m_callback; +}; + +template <typename Callback> +stop_callback(stop_token, Callback) -> stop_callback<Callback>; + +class jthread { +public: +    using id = thread::id; +    using native_handle_type = thread::native_handle_type; + +    jthread() noexcept = default; + +    template <typename F, typename... Args, +              typename = enable_if_t<!is_same_v<remove_cvref_t<F>, jthread>>> +    explicit jthread(F&& f, Args&&... args) +        : m_stop_state(make_shared<polyfill::stop_state>()), +          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 <typename F, typename... Args> +    thread make_thread(F&& f, Args&&... args) { +        if constexpr (is_invocable_v<decay_t<F>, stop_token, decay_t<Args>...>) { +            return thread(move(f), get_stop_token(), move(args)...); +        } else { +            return thread(move(f), move(args)...); +        } +    } + +    shared_ptr<polyfill::stop_state> m_stop_state; +    thread m_thread; +}; + +} // namespace std + +namespace Common { + +template <typename Condvar, typename Lock, typename Pred> +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/common/thread_worker.h b/src/common/thread_worker.h index 62c60f724..260ad44e4 100644 --- a/src/common/thread_worker.h +++ b/src/common/thread_worker.h @@ -7,13 +7,13 @@  #include <condition_variable>  #include <functional>  #include <mutex> -#include <stop_token>  #include <string>  #include <thread>  #include <type_traits>  #include <vector>  #include <queue> +#include "common/polyfill_thread.h"  #include "common/thread.h"  #include "common/unique_function.h" @@ -47,7 +47,8 @@ public:                          if (requests.empty()) {                              wait_condition.notify_all();                          } -                        condition.wait(lock, stop_token, [this] { return !requests.empty(); }); +                        Common::CondvarWait(condition, lock, stop_token, +                                            [this] { return !requests.empty(); });                          if (stop_token.stop_requested()) {                              break;                          } diff --git a/src/common/threadsafe_queue.h b/src/common/threadsafe_queue.h index 053798e79..2ef1da064 100644 --- a/src/common/threadsafe_queue.h +++ b/src/common/threadsafe_queue.h @@ -12,6 +12,8 @@  #include <mutex>  #include <utility> +#include "common/polyfill_thread.h" +  namespace Common {  template <typename T, bool with_stop_token = false>  class SPSCQueue { @@ -97,7 +99,7 @@ public:      T PopWait(std::stop_token stop_token) {          if (Empty()) {              std::unique_lock lock{cv_mutex}; -            cv.wait(lock, stop_token, [this] { return !Empty(); }); +            Common::CondvarWait(cv, lock, stop_token, [this] { return !Empty(); });          }          if (stop_token.stop_requested()) {              return T{}; diff --git a/src/core/cpu_manager.h b/src/core/cpu_manager.h index 95ea3ef39..374367468 100644 --- a/src/core/cpu_manager.h +++ b/src/core/cpu_manager.h @@ -10,6 +10,7 @@  #include <thread>  #include "common/fiber.h" +#include "common/polyfill_thread.h"  #include "common/thread.h"  #include "core/hardware_properties.h" diff --git a/src/core/debugger/debugger.cpp b/src/core/debugger/debugger.cpp index 1a8e02e6a..a9675df76 100644 --- a/src/core/debugger/debugger.cpp +++ b/src/core/debugger/debugger.cpp @@ -9,6 +9,7 @@  #include <boost/process/async_pipe.hpp>  #include "common/logging/log.h" +#include "common/polyfill_thread.h"  #include "common/thread.h"  #include "core/core.h"  #include "core/debugger/debugger.h" diff --git a/src/core/file_sys/content_archive.cpp b/src/core/file_sys/content_archive.cpp index 78e56bbbd..50303fe42 100644 --- a/src/core/file_sys/content_archive.cpp +++ b/src/core/file_sys/content_archive.cpp @@ -7,6 +7,7 @@  #include <utility>  #include "common/logging/log.h" +#include "common/polyfill_ranges.h"  #include "core/crypto/aes_util.h"  #include "core/crypto/ctr_encryption_layer.h"  #include "core/crypto/key_manager.h" diff --git a/src/core/frontend/applets/controller.h b/src/core/frontend/applets/controller.h index 1d2850ad5..71698df74 100644 --- a/src/core/frontend/applets/controller.h +++ b/src/core/frontend/applets/controller.h @@ -4,6 +4,7 @@  #pragma once  #include <functional> +#include <vector>  #include "common/common_types.h" diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h index d004ca56a..3f83108d3 100644 --- a/src/core/hid/emulated_controller.h +++ b/src/core/hid/emulated_controller.h @@ -8,6 +8,7 @@  #include <memory>  #include <mutex>  #include <unordered_map> +#include <vector>  #include "common/common_types.h"  #include "common/input.h" diff --git a/src/core/hid/emulated_devices.h b/src/core/hid/emulated_devices.h index 4149eeced..4cdbf9dc6 100644 --- a/src/core/hid/emulated_devices.h +++ b/src/core/hid/emulated_devices.h @@ -8,6 +8,7 @@  #include <memory>  #include <mutex>  #include <unordered_map> +#include <vector>  #include "common/common_types.h"  #include "common/input.h" diff --git a/src/core/hle/kernel/k_memory_manager.cpp b/src/core/hle/kernel/k_memory_manager.cpp index c4bf306e8..bd33571da 100644 --- a/src/core/hle/kernel/k_memory_manager.cpp +++ b/src/core/hle/kernel/k_memory_manager.cpp @@ -225,8 +225,8 @@ Result KMemoryManager::AllocatePageGroupImpl(KPageGroup* out, size_t num_pages,      ON_RESULT_FAILURE {          for (const auto& it : out->Nodes()) {              auto& manager = this->GetManager(it.GetAddress()); -            const size_t node_num_pages = -                std::min(it.GetNumPages(), (manager.GetEndAddress() - it.GetAddress()) / PageSize); +            const size_t node_num_pages = std::min<u64>( +                it.GetNumPages(), (manager.GetEndAddress() - it.GetAddress()) / PageSize);              manager.Free(it.GetAddress(), node_num_pages);          }          out->Finalize(); diff --git a/src/core/hle/kernel/k_slab_heap.h b/src/core/hle/kernel/k_slab_heap.h index a8c77a7d4..68469b041 100644 --- a/src/core/hle/kernel/k_slab_heap.h +++ b/src/core/hle/kernel/k_slab_heap.h @@ -6,6 +6,7 @@  #include <atomic>  #include "common/assert.h" +#include "common/atomic_ops.h"  #include "common/common_funcs.h"  #include "common/common_types.h"  #include "common/spin_lock.h" @@ -82,16 +83,13 @@ private:  private:      void UpdatePeakImpl(uintptr_t obj) { -        static_assert(std::atomic_ref<uintptr_t>::is_always_lock_free); -        std::atomic_ref<uintptr_t> peak_ref(m_peak); -          const uintptr_t alloc_peak = obj + this->GetObjectSize();          uintptr_t cur_peak = m_peak;          do {              if (alloc_peak <= cur_peak) {                  break;              } -        } while (!peak_ref.compare_exchange_strong(cur_peak, alloc_peak)); +        } while (!Common::AtomicCompareAndSwap(&m_peak, alloc_peak, cur_peak, cur_peak));      }  public: diff --git a/src/core/hle/kernel/k_thread_local_page.h b/src/core/hle/kernel/k_thread_local_page.h index 5d466ace7..fe0cff084 100644 --- a/src/core/hle/kernel/k_thread_local_page.h +++ b/src/core/hle/kernel/k_thread_local_page.h @@ -10,6 +10,7 @@  #include "common/assert.h"  #include "common/common_types.h"  #include "common/intrusive_red_black_tree.h" +#include "common/polyfill_ranges.h"  #include "core/hle/kernel/memory_types.h"  #include "core/hle/kernel/slab_helpers.h"  #include "core/hle/result.h" diff --git a/src/core/hle/kernel/service_thread.cpp b/src/core/hle/kernel/service_thread.cpp index e6e41ac34..0690f9a1c 100644 --- a/src/core/hle/kernel/service_thread.cpp +++ b/src/core/hle/kernel/service_thread.cpp @@ -7,6 +7,7 @@  #include <thread>  #include <vector> +#include "common/polyfill_thread.h"  #include "common/scope_exit.h"  #include "common/thread.h"  #include "core/hle/ipc_helpers.h" diff --git a/src/core/hle/kernel/svc_wrap.h b/src/core/hle/kernel/svc_wrap.h index 3730937fe..1ea8c7fbc 100644 --- a/src/core/hle/kernel/svc_wrap.h +++ b/src/core/hle/kernel/svc_wrap.h @@ -82,7 +82,7 @@ void SvcWrap64(Core::System& system) {  }  // Used by ControlCodeMemory -template <Result func(Core::System&, Handle, u32, u64, u64, Svc::MemoryPermission)> +template <Result func(Core::System&, Handle, u32, VAddr, size_t, Svc::MemoryPermission)>  void SvcWrap64(Core::System& system) {      FuncReturn(system, func(system, static_cast<Handle>(Param(system, 0)),                              static_cast<u32>(Param(system, 1)), Param(system, 2), Param(system, 3), @@ -327,7 +327,7 @@ void SvcWrap64(Core::System& system) {  }  // Used by CreateCodeMemory -template <Result func(Core::System&, Handle*, u64, u64)> +template <Result func(Core::System&, Handle*, VAddr, size_t)>  void SvcWrap64(Core::System& system) {      u32 param_1 = 0;      const u32 retval = func(system, ¶m_1, Param(system, 1), Param(system, 2)).raw; diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp index 85a3f0802..6d1084fd1 100644 --- a/src/core/hle/service/acc/acc.cpp +++ b/src/core/hle/service/acc/acc.cpp @@ -7,6 +7,7 @@  #include "common/fs/file.h"  #include "common/fs/path_util.h"  #include "common/logging/log.h" +#include "common/polyfill_ranges.h"  #include "common/string_util.h"  #include "common/swap.h"  #include "core/constants.h" diff --git a/src/core/hle/service/acc/profile_manager.cpp b/src/core/hle/service/acc/profile_manager.cpp index 481e0d141..97f7c6688 100644 --- a/src/core/hle/service/acc/profile_manager.cpp +++ b/src/core/hle/service/acc/profile_manager.cpp @@ -9,6 +9,7 @@  #include "common/fs/file.h"  #include "common/fs/fs.h"  #include "common/fs/path_util.h" +#include "common/polyfill_ranges.h"  #include "common/settings.h"  #include "core/hle/service/acc/profile_manager.h" diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 8ea7fd760..22999c942 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -1125,7 +1125,7 @@ void IStorageAccessor::Write(Kernel::HLERequestContext& ctx) {      const u64 offset{rp.Pop<u64>()};      const std::vector<u8> data{ctx.ReadBuffer()}; -    const std::size_t size{std::min(data.size(), backing.GetSize() - offset)}; +    const std::size_t size{std::min<u64>(data.size(), backing.GetSize() - offset)};      LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, size); @@ -1149,7 +1149,7 @@ void IStorageAccessor::Read(Kernel::HLERequestContext& ctx) {      IPC::RequestParser rp{ctx};      const u64 offset{rp.Pop<u64>()}; -    const std::size_t size{std::min(ctx.GetWriteBufferSize(), backing.GetSize() - offset)}; +    const std::size_t size{std::min<u64>(ctx.GetWriteBufferSize(), backing.GetSize() - offset)};      LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, size); diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp index 034ee273f..3a1c231b6 100644 --- a/src/core/hle/service/audio/audren_u.cpp +++ b/src/core/hle/service/audio/audren_u.cpp @@ -14,6 +14,7 @@  #include "common/bit_util.h"  #include "common/common_funcs.h"  #include "common/logging/log.h" +#include "common/polyfill_ranges.h"  #include "common/string_util.h"  #include "core/core.h"  #include "core/hle/ipc_helpers.h" diff --git a/src/core/hle/service/nvflinger/nvflinger.h b/src/core/hle/service/nvflinger/nvflinger.h index 460bef976..9b22397db 100644 --- a/src/core/hle/service/nvflinger/nvflinger.h +++ b/src/core/hle/service/nvflinger/nvflinger.h @@ -11,6 +11,7 @@  #include <vector>  #include "common/common_types.h" +#include "common/polyfill_thread.h"  #include "core/hle/result.h"  #include "core/hle/service/kernel_helpers.h" diff --git a/src/core/internal_network/network_interface.cpp b/src/core/internal_network/network_interface.cpp index 057fd3661..7b8e510a2 100644 --- a/src/core/internal_network/network_interface.cpp +++ b/src/core/internal_network/network_interface.cpp @@ -9,6 +9,7 @@  #include "common/bit_cast.h"  #include "common/common_types.h"  #include "common/logging/log.h" +#include "common/polyfill_ranges.h"  #include "common/settings.h"  #include "common/string_util.h"  #include "core/internal_network/network_interface.h" diff --git a/src/input_common/drivers/gc_adapter.h b/src/input_common/drivers/gc_adapter.h index 7f81767f7..b5270fd0b 100644 --- a/src/input_common/drivers/gc_adapter.h +++ b/src/input_common/drivers/gc_adapter.h @@ -5,10 +5,10 @@  #include <array>  #include <memory> -#include <stop_token>  #include <string>  #include <thread> +#include "common/polyfill_thread.h"  #include "input_common/input_engine.h"  struct libusb_context; diff --git a/src/input_common/drivers/mouse.cpp b/src/input_common/drivers/mouse.cpp index 98c3157a8..faf9cbdc3 100644 --- a/src/input_common/drivers/mouse.cpp +++ b/src/input_common/drivers/mouse.cpp @@ -1,7 +1,6 @@  // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project  // SPDX-License-Identifier: GPL-2.0-or-later -#include <stop_token>  #include <thread>  #include <fmt/format.h> diff --git a/src/input_common/drivers/mouse.h b/src/input_common/drivers/mouse.h index 286ce1cf6..72073cc23 100644 --- a/src/input_common/drivers/mouse.h +++ b/src/input_common/drivers/mouse.h @@ -3,9 +3,9 @@  #pragma once -#include <stop_token>  #include <thread> +#include "common/polyfill_thread.h"  #include "common/vector_math.h"  #include "input_common/input_engine.h" diff --git a/src/input_common/drivers/tas_input.cpp b/src/input_common/drivers/tas_input.cpp index 21c6ed405..f3ade90da 100644 --- a/src/input_common/drivers/tas_input.cpp +++ b/src/input_common/drivers/tas_input.cpp @@ -2,6 +2,7 @@  // SPDX-License-Identifier: GPL-2.0-or-later  #include <cstring> +#include <sstream>  #include <fmt/format.h>  #include "common/fs/file.h" diff --git a/src/shader_recompiler/CMakeLists.txt b/src/shader_recompiler/CMakeLists.txt index 8cd584154..ef09fe2b9 100644 --- a/src/shader_recompiler/CMakeLists.txt +++ b/src/shader_recompiler/CMakeLists.txt @@ -255,6 +255,7 @@ else()          # Bracket depth determines maximum size of a fold expression in Clang since 9c9974c3ccb6.          # And this in turns limits the size of a std::array.          $<$<CXX_COMPILER_ID:Clang>:-fbracket-depth=1024> +        $<$<CXX_COMPILER_ID:AppleClang>:-fbracket-depth=1024>      )  endif() diff --git a/src/shader_recompiler/frontend/ir/opcodes.h b/src/shader_recompiler/frontend/ir/opcodes.h index e70d7745c..d155afd0f 100644 --- a/src/shader_recompiler/frontend/ir/opcodes.h +++ b/src/shader_recompiler/frontend/ir/opcodes.h @@ -8,6 +8,7 @@  #include <fmt/format.h> +#include "common/polyfill_ranges.h"  #include "shader_recompiler/frontend/ir/type.h"  namespace Shader::IR { diff --git a/src/shader_recompiler/frontend/maxwell/control_flow.cpp b/src/shader_recompiler/frontend/maxwell/control_flow.cpp index 6939692cd..dce414cb4 100644 --- a/src/shader_recompiler/frontend/maxwell/control_flow.cpp +++ b/src/shader_recompiler/frontend/maxwell/control_flow.cpp @@ -9,6 +9,7 @@  #include <fmt/format.h> +#include "common/polyfill_ranges.h"  #include "shader_recompiler/exception.h"  #include "shader_recompiler/frontend/maxwell/control_flow.h"  #include "shader_recompiler/frontend/maxwell/decode.h" diff --git a/src/shader_recompiler/frontend/maxwell/decode.cpp b/src/shader_recompiler/frontend/maxwell/decode.cpp index 455c91470..774f65bc5 100644 --- a/src/shader_recompiler/frontend/maxwell/decode.cpp +++ b/src/shader_recompiler/frontend/maxwell/decode.cpp @@ -7,6 +7,7 @@  #include <memory>  #include "common/common_types.h" +#include "common/polyfill_ranges.h"  #include "shader_recompiler/exception.h"  #include "shader_recompiler/frontend/maxwell/decode.h"  #include "shader_recompiler/frontend/maxwell/opcodes.h" diff --git a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp index ce42475d4..80c90fe6a 100644 --- a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp +++ b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp @@ -12,6 +12,7 @@  #include <boost/intrusive/list.hpp> +#include "common/polyfill_ranges.h"  #include "shader_recompiler/environment.h"  #include "shader_recompiler/frontend/ir/basic_block.h"  #include "shader_recompiler/frontend/ir/ir_emitter.h" diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_conversion_integer.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_conversion_integer.cpp index 4942878b9..85c18d942 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_conversion_integer.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_conversion_integer.cpp @@ -176,12 +176,13 @@ void TranslateF2I(TranslatorVisitor& v, u64 insn, const IR::F16F32F64& src_a) {          (f2i.src_format == SrcFormat::F64) != (f2i.dest_format == DestFormat::I64);      if (special_nan_cases) {          if (f2i.dest_format == DestFormat::I32) { +            constexpr u32 nan_value = 0x8000'0000U;              handled_special_case = true; -            result = IR::U32{v.ir.Select(v.ir.FPIsNan(op_a), v.ir.Imm32(0x8000'0000U), result)}; +            result = IR::U32{v.ir.Select(v.ir.FPIsNan(op_a), v.ir.Imm32(nan_value), result)};          } else if (f2i.dest_format == DestFormat::I64) { +            constexpr u64 nan_value = 0x8000'0000'0000'0000ULL;              handled_special_case = true; -            result = IR::U64{ -                v.ir.Select(v.ir.FPIsNan(op_a), v.ir.Imm64(0x8000'0000'0000'0000UL), result)}; +            result = IR::U64{v.ir.Select(v.ir.FPIsNan(op_a), v.ir.Imm64(nan_value), result)};          }      }      if (!handled_special_case && is_signed) { diff --git a/src/video_core/buffer_cache/buffer_base.h b/src/video_core/buffer_cache/buffer_base.h index f9a6472cf..92d77eef2 100644 --- a/src/video_core/buffer_cache/buffer_base.h +++ b/src/video_core/buffer_cache/buffer_base.h @@ -535,7 +535,7 @@ private:          const u64* const state_words = Array<type>();          const u64 num_query_words = size / BYTES_PER_WORD + 1;          const u64 word_begin = offset / BYTES_PER_WORD; -        const u64 word_end = std::min(word_begin + num_query_words, NumWords()); +        const u64 word_end = std::min<u64>(word_begin + num_query_words, NumWords());          const u64 page_limit = Common::DivCeil(offset + size, BYTES_PER_PAGE);          u64 page_index = (offset / BYTES_PER_PAGE) % PAGES_PER_WORD;          for (u64 word_index = word_begin; word_index < word_end; ++word_index, page_index = 0) { diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 5d3a8293b..6881b34c4 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -19,6 +19,7 @@  #include "common/literals.h"  #include "common/lru_cache.h"  #include "common/microprofile.h" +#include "common/polyfill_ranges.h"  #include "common/settings.h"  #include "core/memory.h"  #include "video_core/buffer_cache/buffer_base.h" diff --git a/src/video_core/control/channel_state_cache.h b/src/video_core/control/channel_state_cache.h index 584a0c26c..cdaf4f8d5 100644 --- a/src/video_core/control/channel_state_cache.h +++ b/src/video_core/control/channel_state_cache.h @@ -35,8 +35,6 @@ public:      explicit ChannelInfo(Tegra::Control::ChannelState& state);      ChannelInfo(const ChannelInfo& state) = delete;      ChannelInfo& operator=(const ChannelInfo&) = delete; -    ChannelInfo(ChannelInfo&& other) = default; -    ChannelInfo& operator=(ChannelInfo&& other) = default;      Tegra::Engines::Maxwell3D& maxwell3d;      Tegra::Engines::KeplerCompute& kepler_compute; diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp index 1bd477011..164a5252a 100644 --- a/src/video_core/gpu_thread.cpp +++ b/src/video_core/gpu_thread.cpp @@ -125,7 +125,7 @@ u64 ThreadManager::PushCommand(CommandData&& command_data, bool block) {      state.queue.Push(CommandDataContainer(std::move(command_data), fence, block));      if (block) { -        state.cv.wait(lk, thread.get_stop_token(), [this, fence] { +        Common::CondvarWait(state.cv, lk, thread.get_stop_token(), [this, fence] {              return fence <= state.signaled_fence.load(std::memory_order_relaxed);          });      } diff --git a/src/video_core/gpu_thread.h b/src/video_core/gpu_thread.h index 64628d3e3..c71a419c7 100644 --- a/src/video_core/gpu_thread.h +++ b/src/video_core/gpu_thread.h @@ -10,6 +10,7 @@  #include <thread>  #include <variant> +#include "common/polyfill_thread.h"  #include "common/threadsafe_queue.h"  #include "video_core/framebuffer_config.h" diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h index cfd872a40..b6907463c 100644 --- a/src/video_core/rasterizer_interface.h +++ b/src/video_core/rasterizer_interface.h @@ -6,8 +6,8 @@  #include <functional>  #include <optional>  #include <span> -#include <stop_token>  #include "common/common_types.h" +#include "common/polyfill_thread.h"  #include "video_core/engines/fermi_2d.h"  #include "video_core/gpu.h" diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp index 1663e277d..e2e3dac34 100644 --- a/src/video_core/renderer_opengl/gl_device.cpp +++ b/src/video_core/renderer_opengl/gl_device.cpp @@ -14,6 +14,7 @@  #include "common/literals.h"  #include "common/logging/log.h" +#include "common/polyfill_ranges.h"  #include "common/settings.h"  #include "shader_recompiler/stage.h"  #include "video_core/renderer_opengl/gl_device.h" diff --git a/src/video_core/renderer_opengl/gl_shader_cache.h b/src/video_core/renderer_opengl/gl_shader_cache.h index 89f181fe3..53ffea904 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.h +++ b/src/video_core/renderer_opengl/gl_shader_cache.h @@ -4,7 +4,6 @@  #pragma once  #include <filesystem> -#include <stop_token>  #include <unordered_map>  #include "common/common_types.h" diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp index 98cc26679..f3f08b42c 100644 --- a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp +++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp @@ -7,6 +7,7 @@  #include "common/bit_cast.h"  #include "common/cityhash.h"  #include "common/common_types.h" +#include "common/polyfill_ranges.h"  #include "video_core/renderer_vulkan/fixed_pipeline_state.h"  #include "video_core/renderer_vulkan/vk_state_tracker.h" diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp index 89426121f..6e5abade4 100644 --- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp +++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp @@ -10,6 +10,7 @@  #include "common/assert.h"  #include "common/common_types.h"  #include "common/math_util.h" +#include "common/polyfill_ranges.h"  #include "common/settings.h"  #include "core/core.h"  #include "core/frontend/emu_window.h" diff --git a/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp b/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp index c7196b64e..b5ae6443c 100644 --- a/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp +++ b/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp @@ -7,6 +7,7 @@  #include <vector>  #include "common/common_types.h" +#include "common/polyfill_ranges.h"  #include "video_core/renderer_vulkan/vk_descriptor_pool.h"  #include "video_core/renderer_vulkan/vk_resource_pool.h"  #include "video_core/renderer_vulkan/vk_scheduler.h" diff --git a/src/video_core/renderer_vulkan/vk_master_semaphore.h b/src/video_core/renderer_vulkan/vk_master_semaphore.h index 362ed579a..689f02ea5 100644 --- a/src/video_core/renderer_vulkan/vk_master_semaphore.h +++ b/src/video_core/renderer_vulkan/vk_master_semaphore.h @@ -7,6 +7,7 @@  #include <thread>  #include "common/common_types.h" +#include "common/polyfill_thread.h"  #include "video_core/vulkan_common/vulkan_wrapper.h"  namespace Vulkan { diff --git a/src/video_core/renderer_vulkan/vk_render_pass_cache.h b/src/video_core/renderer_vulkan/vk_render_pass_cache.h index dc21b7e69..91ad4bf57 100644 --- a/src/video_core/renderer_vulkan/vk_render_pass_cache.h +++ b/src/video_core/renderer_vulkan/vk_render_pass_cache.h @@ -12,7 +12,7 @@  namespace Vulkan {  struct RenderPassKey { -    auto operator<=>(const RenderPassKey&) const noexcept = default; +    bool operator==(const RenderPassKey&) const noexcept = default;      std::array<VideoCore::Surface::PixelFormat, 8> color_formats;      VideoCore::Surface::PixelFormat depth_format; diff --git a/src/video_core/renderer_vulkan/vk_scheduler.cpp b/src/video_core/renderer_vulkan/vk_scheduler.cpp index 4a7b633b7..c09fb3e98 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.cpp +++ b/src/video_core/renderer_vulkan/vk_scheduler.cpp @@ -145,7 +145,7 @@ void Scheduler::WorkerThread(std::stop_token stop_token) {              if (work_queue.empty()) {                  wait_cv.notify_all();              } -            work_cv.wait(lock, stop_token, [this] { return !work_queue.empty(); }); +            Common::CondvarWait(work_cv, lock, stop_token, [&] { return !work_queue.empty(); });              if (stop_token.stop_requested()) {                  continue;              } diff --git a/src/video_core/renderer_vulkan/vk_scheduler.h b/src/video_core/renderer_vulkan/vk_scheduler.h index 929216749..3858c506c 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.h +++ b/src/video_core/renderer_vulkan/vk_scheduler.h @@ -12,6 +12,7 @@  #include "common/alignment.h"  #include "common/common_types.h" +#include "common/polyfill_thread.h"  #include "video_core/renderer_vulkan/vk_master_semaphore.h"  #include "video_core/vulkan_common/vulkan_wrapper.h" diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp index 706d9ba74..d7be417f5 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.cpp +++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp @@ -7,6 +7,7 @@  #include <vector>  #include "common/logging/log.h" +#include "common/polyfill_ranges.h"  #include "common/settings.h"  #include "core/core.h"  #include "video_core/renderer_vulkan/vk_scheduler.h" diff --git a/src/video_core/shader_cache.h b/src/video_core/shader_cache.h index a4391202d..f3cc4c70b 100644 --- a/src/video_core/shader_cache.h +++ b/src/video_core/shader_cache.h @@ -12,6 +12,7 @@  #include <vector>  #include "common/common_types.h" +#include "common/polyfill_ranges.h"  #include "video_core/control/channel_state_cache.h"  #include "video_core/rasterizer_interface.h"  #include "video_core/shader_environment.h" diff --git a/src/video_core/shader_environment.cpp b/src/video_core/shader_environment.cpp index f24f320b6..958810747 100644 --- a/src/video_core/shader_environment.cpp +++ b/src/video_core/shader_environment.cpp @@ -15,6 +15,7 @@  #include "common/fs/fs.h"  #include "common/fs/path_util.h"  #include "common/logging/log.h" +#include "common/polyfill_ranges.h"  #include "shader_recompiler/environment.h"  #include "video_core/engines/kepler_compute.h"  #include "video_core/memory_manager.h" diff --git a/src/video_core/shader_environment.h b/src/video_core/shader_environment.h index bb55b029f..1342fab1e 100644 --- a/src/video_core/shader_environment.h +++ b/src/video_core/shader_environment.h @@ -10,12 +10,12 @@  #include <memory>  #include <optional>  #include <span> -#include <stop_token>  #include <type_traits>  #include <unordered_map>  #include <vector>  #include "common/common_types.h" +#include "common/polyfill_thread.h"  #include "common/unique_function.h"  #include "shader_recompiler/environment.h"  #include "video_core/engines/maxwell_3d.h" diff --git a/src/video_core/texture_cache/formatter.cpp b/src/video_core/texture_cache/formatter.cpp index ee4f2d406..418890126 100644 --- a/src/video_core/texture_cache/formatter.cpp +++ b/src/video_core/texture_cache/formatter.cpp @@ -4,6 +4,7 @@  #include <algorithm>  #include <string> +#include "common/polyfill_ranges.h"  #include "video_core/texture_cache/formatter.h"  #include "video_core/texture_cache/image_base.h"  #include "video_core/texture_cache/image_info.h" diff --git a/src/video_core/texture_cache/render_targets.h b/src/video_core/texture_cache/render_targets.h index 1efbd6507..0829d773a 100644 --- a/src/video_core/texture_cache/render_targets.h +++ b/src/video_core/texture_cache/render_targets.h @@ -13,7 +13,7 @@ namespace VideoCommon {  /// Framebuffer properties used to lookup a framebuffer  struct RenderTargets { -    constexpr auto operator<=>(const RenderTargets&) const noexcept = default; +    constexpr bool operator==(const RenderTargets&) const noexcept = default;      constexpr bool Contains(std::span<const ImageViewId> elements) const noexcept {          const auto contains = [elements](ImageViewId item) { diff --git a/src/video_core/texture_cache/slot_vector.h b/src/video_core/texture_cache/slot_vector.h index 46e8a86e6..1e2aad76a 100644 --- a/src/video_core/texture_cache/slot_vector.h +++ b/src/video_core/texture_cache/slot_vector.h @@ -12,6 +12,7 @@  #include "common/assert.h"  #include "common/common_types.h" +#include "common/polyfill_ranges.h"  namespace VideoCommon { diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h index 9db7195bf..587339a31 100644 --- a/src/video_core/texture_cache/texture_cache_base.h +++ b/src/video_core/texture_cache/texture_cache_base.h @@ -16,6 +16,7 @@  #include "common/hash.h"  #include "common/literals.h"  #include "common/lru_cache.h" +#include "common/polyfill_ranges.h"  #include "video_core/compatible_formats.h"  #include "video_core/control/channel_state_cache.h"  #include "video_core/delayed_destruction_ring.h" @@ -60,8 +61,6 @@ public:      TextureCacheChannelInfo(Tegra::Control::ChannelState& state) noexcept;      TextureCacheChannelInfo(const TextureCacheChannelInfo& state) = delete;      TextureCacheChannelInfo& operator=(const TextureCacheChannelInfo&) = delete; -    TextureCacheChannelInfo(TextureCacheChannelInfo&& other) noexcept = default; -    TextureCacheChannelInfo& operator=(TextureCacheChannelInfo&& other) noexcept = default;      DescriptorTable<TICEntry> graphics_image_table{gpu_memory};      DescriptorTable<TSCEntry> graphics_sampler_table{gpu_memory}; diff --git a/src/video_core/textures/astc.cpp b/src/video_core/textures/astc.cpp index 69a32819a..e8d7c7863 100644 --- a/src/video_core/textures/astc.cpp +++ b/src/video_core/textures/astc.cpp @@ -15,6 +15,7 @@  #include "common/alignment.h"  #include "common/common_types.h" +#include "common/polyfill_ranges.h"  #include "common/thread_worker.h"  #include "video_core/textures/astc.h" diff --git a/src/video_core/transform_feedback.cpp b/src/video_core/transform_feedback.cpp index 45071185a..155599316 100644 --- a/src/video_core/transform_feedback.cpp +++ b/src/video_core/transform_feedback.cpp @@ -7,6 +7,7 @@  #include "common/alignment.h"  #include "common/assert.h" +#include "common/polyfill_ranges.h"  #include "shader_recompiler/shader_info.h"  #include "video_core/transform_feedback.h" diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index a16a8275b..652329c38 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp @@ -12,6 +12,7 @@  #include "common/assert.h"  #include "common/literals.h" +#include "common/polyfill_ranges.h"  #include "common/settings.h"  #include "video_core/vulkan_common/nsight_aftermath_tracker.h"  #include "video_core/vulkan_common/vulkan_device.h" diff --git a/src/video_core/vulkan_common/vulkan_instance.cpp b/src/video_core/vulkan_common/vulkan_instance.cpp index 35e073e16..562039b56 100644 --- a/src/video_core/vulkan_common/vulkan_instance.cpp +++ b/src/video_core/vulkan_common/vulkan_instance.cpp @@ -9,6 +9,7 @@  #include "common/common_types.h"  #include "common/dynamic_library.h"  #include "common/logging/log.h" +#include "common/polyfill_ranges.h"  #include "core/frontend/emu_window.h"  #include "video_core/vulkan_common/vulkan_instance.h"  #include "video_core/vulkan_common/vulkan_wrapper.h" diff --git a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp index 6442898bd..1732866e0 100644 --- a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp +++ b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp @@ -12,6 +12,7 @@  #include "common/assert.h"  #include "common/common_types.h"  #include "common/logging/log.h" +#include "common/polyfill_ranges.h"  #include "video_core/vulkan_common/vulkan_device.h"  #include "video_core/vulkan_common/vulkan_memory_allocator.h"  #include "video_core/vulkan_common/vulkan_wrapper.h" diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index ccf1c50f4..a6658a26f 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp @@ -118,7 +118,7 @@ void EmuThread::run() {              }          } else {              std::unique_lock lock{running_mutex}; -            running_cv.wait(lock, stop_token, [this] { return IsRunning(); }); +            Common::CondvarWait(running_cv, lock, stop_token, [&] { return IsRunning(); });          }      } diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h index 4a01481cd..ca4aee088 100644 --- a/src/yuzu/bootmanager.h +++ b/src/yuzu/bootmanager.h @@ -14,6 +14,7 @@  #include <QTouchEvent>  #include <QWidget> +#include "common/polyfill_thread.h"  #include "common/thread.h"  #include "core/frontend/emu_window.h" diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index c21153560..4f693b339 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -2850,6 +2850,7 @@ void GMainWindow::ErrorDisplayDisplayError(QString error_code, QString error_tex  }  void GMainWindow::OnMenuReportCompatibility() { +#if defined(ARCHITECTURE_x86_64) && !defined(__APPLE__)      const auto& caps = Common::GetCPUCaps();      const bool has_fma = caps.fma || caps.fma4;      const auto processor_count = std::thread::hardware_concurrency(); @@ -2876,6 +2877,11 @@ void GMainWindow::OnMenuReportCompatibility() {                 "> "                 "Web."));      } +#else +    QMessageBox::critical(this, tr("Hardware requirements not met"), +                          tr("Your system does not meet the recommended hardware requirements. " +                             "Compatibility reporting has been disabled.")); +#endif  }  void GMainWindow::OpenURL(const QUrl& url) { diff --git a/src/yuzu/multiplayer/chat_room.h b/src/yuzu/multiplayer/chat_room.h index 01c70fad0..dd71ea4cd 100644 --- a/src/yuzu/multiplayer/chat_room.h +++ b/src/yuzu/multiplayer/chat_room.h @@ -4,6 +4,7 @@  #pragma once  #include <memory> +#include <unordered_map>  #include <unordered_set>  #include <QDialog>  #include <QSortFilterProxyModel> | 
