diff --git a/CMakeModules/Findsirit.cmake b/CMakeModules/Findsirit.cmake new file mode 100644 index 0000000000..83b81b09c5 --- /dev/null +++ b/CMakeModules/Findsirit.cmake @@ -0,0 +1,11 @@ +# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +# SPDX-License-Identifier: GPL-3.0-or-later + +include(FindPackageHandleStandardArgs) + +find_package(PkgConfig QUIET) +pkg_search_module(sirit QUIET IMPORTED_TARGET sirit) +find_package_handle_standard_args(sirit + REQUIRED_VARS sirit_LINK_LIBRARIES + VERSION_VAR sirit_VERSION +) diff --git a/externals/cpmfile.json b/externals/cpmfile.json index dcafc8f97d..283da76743 100644 --- a/externals/cpmfile.json +++ b/externals/cpmfile.json @@ -10,7 +10,7 @@ "repo": "eden-emulator/sirit", "sha": "db1f1e8ab5", "hash": "73eb3a042848c63a10656545797e85f40d142009dfb7827384548a385e1e28e1ac72f42b25924ce530d58275f8638554281e884d72f9c7aaf4ed08690a414b05", - "find_args": "CONFIG", + "find_args": "MODULE", "options": [ "SIRIT_USE_SYSTEM_SPIRV_HEADERS ON" ] diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 96ea429e5a..7759ea6a21 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -32,6 +32,7 @@ add_library( atomic_ops.h bit_cast.h bit_field.h + bit_set.h bit_util.h bounded_threadsafe_queue.h cityhash.cpp diff --git a/src/common/bit_set.h b/src/common/bit_set.h new file mode 100644 index 0000000000..74754504be --- /dev/null +++ b/src/common/bit_set.h @@ -0,0 +1,86 @@ +// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include + +#include "common/alignment.h" +#include "common/bit_util.h" +#include "common/common_types.h" + +namespace Common { + +namespace impl { + +template +class BitSet { + +public: + constexpr BitSet() = default; + + constexpr void SetBit(size_t i) { + this->words[i / FlagsPerWord] |= GetBitMask(i % FlagsPerWord); + } + + constexpr void ClearBit(size_t i) { + this->words[i / FlagsPerWord] &= ~GetBitMask(i % FlagsPerWord); + } + + constexpr size_t CountLeadingZero() const { + for (size_t i = 0; i < NumWords; i++) { + if (this->words[i]) { + return FlagsPerWord * i + CountLeadingZeroImpl(this->words[i]); + } + } + return FlagsPerWord * NumWords; + } + + constexpr size_t GetNextSet(size_t n) const { + for (size_t i = (n + 1) / FlagsPerWord; i < NumWords; i++) { + Storage word = this->words[i]; + if (!IsAligned(n + 1, FlagsPerWord)) { + word &= GetBitMask(n % FlagsPerWord) - 1; + } + if (word) { + return FlagsPerWord * i + CountLeadingZeroImpl(word); + } + } + return FlagsPerWord * NumWords; + } + +private: + static_assert(std::is_unsigned_v); + static_assert(sizeof(Storage) <= sizeof(u64)); + + static constexpr size_t FlagsPerWord = BitSize(); + static constexpr size_t NumWords = AlignUp(N, FlagsPerWord) / FlagsPerWord; + + static constexpr auto CountLeadingZeroImpl(Storage word) { + return std::countl_zero(static_cast(word)) - + (BitSize() - FlagsPerWord); + } + + static constexpr Storage GetBitMask(size_t bit) { + return Storage(1) << (FlagsPerWord - 1 - bit); + } + + std::array words{}; +}; + +} // namespace impl + +template +using BitSet8 = impl::BitSet; + +template +using BitSet16 = impl::BitSet; + +template +using BitSet32 = impl::BitSet; + +template +using BitSet64 = impl::BitSet; + +} // namespace Common diff --git a/src/core/hle/kernel/k_priority_queue.h b/src/core/hle/kernel/k_priority_queue.h index 0ef6bcc32c..26677ec65c 100644 --- a/src/core/hle/kernel/k_priority_queue.h +++ b/src/core/hle/kernel/k_priority_queue.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -8,11 +5,10 @@ #include #include -#include #include -#include #include "common/assert.h" +#include "common/bit_set.h" #include "common/common_types.h" #include "common/concepts.h" @@ -163,7 +159,7 @@ public: } if (m_queues[priority].PushBack(core, member)) { - m_available_priorities[core].set(std::size_t(priority)); + m_available_priorities[core].SetBit(priority); } } @@ -176,7 +172,7 @@ public: } if (m_queues[priority].PushFront(core, member)) { - m_available_priorities[core].set(std::size_t(priority)); + m_available_priorities[core].SetBit(priority); } } @@ -189,14 +185,14 @@ public: } if (m_queues[priority].Remove(core, member)) { - m_available_priorities[core].reset(std::size_t(priority)); + m_available_priorities[core].ClearBit(priority); } } constexpr Member* GetFront(s32 core) const { ASSERT(IsValidCore(core)); - const s32 priority = s32((~m_available_priorities[core]).count()); + const s32 priority = static_cast(m_available_priorities[core].CountLeadingZero()); if (priority <= LowestPriority) { return m_queues[priority].GetFront(core); } else { @@ -220,14 +216,11 @@ public: Member* next = member->GetPriorityQueueEntry(core).GetNext(); if (next == nullptr) { - s32 priority = member->GetPriority() + 1; - do { - if (m_available_priorities[core][priority]) { - next = m_queues[priority].GetFront(core); - break; - } - ++priority; - } while (priority <= LowestPriority && priority < s32(m_available_priorities[core].size())); + const s32 priority = static_cast( + m_available_priorities[core].GetNextSet(member->GetPriority())); + if (priority <= LowestPriority) { + next = m_queues[priority].GetFront(core); + } } return next; } @@ -257,7 +250,7 @@ public: private: std::array m_queues{}; - std::array, NumCores> m_available_priorities{}; + std::array, NumCores> m_available_priorities{}; }; private: diff --git a/src/dynarmic/src/dynarmic/CMakeLists.txt b/src/dynarmic/src/dynarmic/CMakeLists.txt index 58efcac747..9e6bd25913 100644 --- a/src/dynarmic/src/dynarmic/CMakeLists.txt +++ b/src/dynarmic/src/dynarmic/CMakeLists.txt @@ -374,7 +374,7 @@ endif() target_compile_options(dynarmic PRIVATE ${DYNARMIC_CXX_FLAGS}) target_link_libraries(dynarmic - PUBLIC + PRIVATE fmt::fmt merry::mcl )