diff options
| author | 2024-02-04 19:16:07 +0100 | |
|---|---|---|
| committer | 2024-02-05 11:06:52 +0100 | |
| commit | 0d5a3abeaefd3a1682c48a59c5a9170cfb0a39d0 (patch) | |
| tree | 850cfea521da30809e93d4ab2ce69f649961a9a1 /src/common/range_sets.inc | |
| parent | NVDRV: Refactor HeapMapper to use RangeSets (diff) | |
| download | yuzu-0d5a3abeaefd3a1682c48a59c5a9170cfb0a39d0.tar.gz yuzu-0d5a3abeaefd3a1682c48a59c5a9170cfb0a39d0.tar.xz yuzu-0d5a3abeaefd3a1682c48a59c5a9170cfb0a39d0.zip | |
Buffer Cache: Refactor to use Range sets instead
Diffstat (limited to '')
| -rw-r--r-- | src/common/range_sets.inc | 184 |
1 files changed, 103 insertions, 81 deletions
diff --git a/src/common/range_sets.inc b/src/common/range_sets.inc index fa55a68fb..705ebd4a1 100644 --- a/src/common/range_sets.inc +++ b/src/common/range_sets.inc | |||
| @@ -6,9 +6,6 @@ | |||
| 6 | #include <limits> | 6 | #include <limits> |
| 7 | #include <utility> | 7 | #include <utility> |
| 8 | 8 | ||
| 9 | #define BOOST_NO_MT | ||
| 10 | #include <boost/pool/detail/mutex.hpp> | ||
| 11 | #undef BOOST_NO_MT | ||
| 12 | #include <boost/icl/interval.hpp> | 9 | #include <boost/icl/interval.hpp> |
| 13 | #include <boost/icl/interval_base_set.hpp> | 10 | #include <boost/icl/interval_base_set.hpp> |
| 14 | #include <boost/icl/interval_map.hpp> | 11 | #include <boost/icl/interval_map.hpp> |
| @@ -20,18 +17,16 @@ | |||
| 20 | 17 | ||
| 21 | #include "common/range_sets.h" | 18 | #include "common/range_sets.h" |
| 22 | 19 | ||
| 23 | namespace boost { | ||
| 24 | template <typename T> | ||
| 25 | class fast_pool_allocator<T, default_user_allocator_new_delete, details::pool::null_mutex, 4096, 0>; | ||
| 26 | } | ||
| 27 | |||
| 28 | namespace Common { | 20 | namespace Common { |
| 29 | 21 | ||
| 30 | template <typename AddressType> | 22 | template <typename AddressType> |
| 31 | struct RangeSet<AddressType>::RangeSetImpl { | 23 | struct RangeSet<AddressType>::RangeSetImpl { |
| 24 | template <class T> | ||
| 25 | using MyAllocator = boost::fast_pool_allocator<T, boost::default_user_allocator_new_delete, | ||
| 26 | boost::details::pool::default_mutex, 1024, 2048>; | ||
| 32 | using IntervalSet = boost::icl::interval_set< | 27 | using IntervalSet = boost::icl::interval_set< |
| 33 | AddressType, std::less, ICL_INTERVAL_INSTANCE(ICL_INTERVAL_DEFAULT, AddressType, std::less), | 28 | AddressType, std::less, ICL_INTERVAL_INSTANCE(ICL_INTERVAL_DEFAULT, AddressType, std::less), |
| 34 | boost::fast_pool_allocator>; | 29 | MyAllocator>; |
| 35 | using IntervalType = typename IntervalSet::interval_type; | 30 | using IntervalType = typename IntervalSet::interval_type; |
| 36 | 31 | ||
| 37 | RangeSetImpl() = default; | 32 | RangeSetImpl() = default; |
| @@ -49,18 +44,58 @@ struct RangeSet<AddressType>::RangeSetImpl { | |||
| 49 | m_ranges_set.subtract(interval); | 44 | m_ranges_set.subtract(interval); |
| 50 | } | 45 | } |
| 51 | 46 | ||
| 47 | template <typename Func> | ||
| 48 | void ForEach(Func&& func) const { | ||
| 49 | if (m_ranges_set.empty()) { | ||
| 50 | return; | ||
| 51 | } | ||
| 52 | auto it = m_ranges_set.begin(); | ||
| 53 | auto end_it = m_ranges_set.end(); | ||
| 54 | for (; it != end_it; it++) { | ||
| 55 | const AddressType inter_addr_end = it->upper(); | ||
| 56 | const AddressType inter_addr = it->lower(); | ||
| 57 | func(inter_addr, inter_addr_end); | ||
| 58 | } | ||
| 59 | } | ||
| 60 | |||
| 61 | template <typename Func> | ||
| 62 | void ForEachInRange(AddressType base_addr, size_t size, Func&& func) const { | ||
| 63 | if (m_ranges_set.empty()) { | ||
| 64 | return; | ||
| 65 | } | ||
| 66 | const AddressType start_address = base_addr; | ||
| 67 | const AddressType end_address = start_address + size; | ||
| 68 | const RangeSetImpl::IntervalType search_interval{start_address, end_address}; | ||
| 69 | auto it = m_ranges_set.lower_bound(search_interval); | ||
| 70 | if (it == m_ranges_set.end()) { | ||
| 71 | return; | ||
| 72 | } | ||
| 73 | auto end_it = m_ranges_set.upper_bound(search_interval); | ||
| 74 | for (; it != end_it; it++) { | ||
| 75 | AddressType inter_addr_end = it->upper(); | ||
| 76 | AddressType inter_addr = it->lower(); | ||
| 77 | if (inter_addr_end > end_address) { | ||
| 78 | inter_addr_end = end_address; | ||
| 79 | } | ||
| 80 | if (inter_addr < start_address) { | ||
| 81 | inter_addr = start_address; | ||
| 82 | } | ||
| 83 | func(inter_addr, inter_addr_end); | ||
| 84 | } | ||
| 85 | } | ||
| 86 | |||
| 52 | IntervalSet m_ranges_set; | 87 | IntervalSet m_ranges_set; |
| 53 | }; | 88 | }; |
| 54 | 89 | ||
| 55 | template <typename AddressType> | 90 | template <typename AddressType> |
| 56 | struct SplitRangeSet<AddressType>::SplitRangeSetImpl { | 91 | struct SplitRangeSet<AddressType>::SplitRangeSetImpl { |
| 57 | 92 | template <class T> | |
| 58 | using IntervalSet = | 93 | using MyAllocator = boost::fast_pool_allocator<T, boost::default_user_allocator_new_delete, |
| 59 | boost::icl::split_interval_map<AddressType, s32, boost::icl::partial_enricher, std::less, | 94 | boost::details::pool::default_mutex, 1024, 2048>; |
| 60 | boost::icl::inplace_plus, boost::icl::inter_section, | 95 | using IntervalSet = boost::icl::split_interval_map< |
| 61 | ICL_INTERVAL_INSTANCE(ICL_INTERVAL_DEFAULT, AddressType, | 96 | AddressType, s32, boost::icl::partial_enricher, std::less, boost::icl::inplace_plus, |
| 62 | std::less), | 97 | boost::icl::inter_section, |
| 63 | boost::fast_pool_allocator>; | 98 | ICL_INTERVAL_INSTANCE(ICL_INTERVAL_DEFAULT, AddressType, std::less), MyAllocator>; |
| 64 | using IntervalType = typename IntervalSet::interval_type; | 99 | using IntervalType = typename IntervalSet::interval_type; |
| 65 | 100 | ||
| 66 | SplitRangeSetImpl() = default; | 101 | SplitRangeSetImpl() = default; |
| @@ -75,6 +110,9 @@ struct SplitRangeSet<AddressType>::SplitRangeSetImpl { | |||
| 75 | template <bool has_on_delete, typename Func> | 110 | template <bool has_on_delete, typename Func> |
| 76 | void Subtract(AddressType base_address, size_t size, s32 amount, | 111 | void Subtract(AddressType base_address, size_t size, s32 amount, |
| 77 | [[maybe_unused]] Func&& on_delete) { | 112 | [[maybe_unused]] Func&& on_delete) { |
| 113 | if (m_split_ranges_set.empty()) { | ||
| 114 | return; | ||
| 115 | } | ||
| 78 | AddressType end_address = base_address + static_cast<AddressType>(size); | 116 | AddressType end_address = base_address + static_cast<AddressType>(size); |
| 79 | IntervalType interval{base_address, end_address}; | 117 | IntervalType interval{base_address, end_address}; |
| 80 | bool any_removals = false; | 118 | bool any_removals = false; |
| @@ -101,6 +139,47 @@ struct SplitRangeSet<AddressType>::SplitRangeSetImpl { | |||
| 101 | } while (any_removals); | 139 | } while (any_removals); |
| 102 | } | 140 | } |
| 103 | 141 | ||
| 142 | template <typename Func> | ||
| 143 | void ForEach(Func&& func) const { | ||
| 144 | if (m_split_ranges_set.empty()) { | ||
| 145 | return; | ||
| 146 | } | ||
| 147 | auto it = m_split_ranges_set.begin(); | ||
| 148 | auto end_it = m_split_ranges_set.end(); | ||
| 149 | for (; it != end_it; it++) { | ||
| 150 | const AddressType inter_addr_end = it->first.upper(); | ||
| 151 | const AddressType inter_addr = it->first.lower(); | ||
| 152 | func(inter_addr, inter_addr_end, it->second); | ||
| 153 | } | ||
| 154 | } | ||
| 155 | |||
| 156 | template <typename Func> | ||
| 157 | void ForEachInRange(AddressType base_address, size_t size, Func&& func) const { | ||
| 158 | if (m_split_ranges_set.empty()) { | ||
| 159 | return; | ||
| 160 | } | ||
| 161 | const AddressType start_address = base_address; | ||
| 162 | const AddressType end_address = start_address + size; | ||
| 163 | const SplitRangeSetImpl::IntervalType search_interval{start_address, end_address}; | ||
| 164 | auto it = m_split_ranges_set.lower_bound(search_interval); | ||
| 165 | if (it == m_split_ranges_set.end()) { | ||
| 166 | return; | ||
| 167 | } | ||
| 168 | auto end_it = m_split_ranges_set.upper_bound(search_interval); | ||
| 169 | for (; it != end_it; it++) { | ||
| 170 | auto& inter = it->first; | ||
| 171 | AddressType inter_addr_end = inter.upper(); | ||
| 172 | AddressType inter_addr = inter.lower(); | ||
| 173 | if (inter_addr_end > end_address) { | ||
| 174 | inter_addr_end = end_address; | ||
| 175 | } | ||
| 176 | if (inter_addr < start_address) { | ||
| 177 | inter_addr = start_address; | ||
| 178 | } | ||
| 179 | func(inter_addr, inter_addr_end, it->second); | ||
| 180 | } | ||
| 181 | } | ||
| 182 | |||
| 104 | IntervalSet m_split_ranges_set; | 183 | IntervalSet m_split_ranges_set; |
| 105 | }; | 184 | }; |
| 106 | 185 | ||
| @@ -146,41 +225,13 @@ bool RangeSet<AddressType>::Empty() const { | |||
| 146 | template <typename AddressType> | 225 | template <typename AddressType> |
| 147 | template <typename Func> | 226 | template <typename Func> |
| 148 | void RangeSet<AddressType>::ForEach(Func&& func) const { | 227 | void RangeSet<AddressType>::ForEach(Func&& func) const { |
| 149 | if (m_impl->m_ranges_set.empty()) { | 228 | m_impl->ForEach(std::move(func)); |
| 150 | return; | ||
| 151 | } | ||
| 152 | auto it = m_impl->m_ranges_set.begin(); | ||
| 153 | auto end_it = m_impl->m_ranges_set.end(); | ||
| 154 | for (; it != end_it; it++) { | ||
| 155 | const AddressType inter_addr_end = it->upper(); | ||
| 156 | const AddressType inter_addr = it->lower(); | ||
| 157 | func(inter_addr, inter_addr_end); | ||
| 158 | } | ||
| 159 | } | 229 | } |
| 160 | 230 | ||
| 161 | template <typename AddressType> | 231 | template <typename AddressType> |
| 162 | template <typename Func> | 232 | template <typename Func> |
| 163 | void RangeSet<AddressType>::ForEachInRange(AddressType base_addr, size_t size, Func&& func) const { | 233 | void RangeSet<AddressType>::ForEachInRange(AddressType base_address, size_t size, Func&& func) const { |
| 164 | auto& range_set = m_impl->m_ranges_set; | 234 | m_impl->ForEachInRange(base_address, size, std::move(func)); |
| 165 | const AddressType start_address = base_addr; | ||
| 166 | const AddressType end_address = start_address + size; | ||
| 167 | const RangeSetImpl::IntervalType search_interval{start_address, end_address}; | ||
| 168 | auto it = range_set.lower_bound(search_interval); | ||
| 169 | if (it == range_set.end()) { | ||
| 170 | return; | ||
| 171 | } | ||
| 172 | auto end_it = range_set.upper_bound(search_interval); | ||
| 173 | for (; it != end_it; it++) { | ||
| 174 | AddressType inter_addr_end = it->upper(); | ||
| 175 | AddressType inter_addr = it->lower(); | ||
| 176 | if (inter_addr_end > end_address) { | ||
| 177 | inter_addr_end = end_address; | ||
| 178 | } | ||
| 179 | if (inter_addr < start_address) { | ||
| 180 | inter_addr = start_address; | ||
| 181 | } | ||
| 182 | func(inter_addr, inter_addr_end); | ||
| 183 | } | ||
| 184 | } | 235 | } |
| 185 | 236 | ||
| 186 | template <typename AddressType> | 237 | template <typename AddressType> |
| @@ -209,18 +260,18 @@ void SplitRangeSet<AddressType>::Add(AddressType base_address, size_t size) { | |||
| 209 | 260 | ||
| 210 | template <typename AddressType> | 261 | template <typename AddressType> |
| 211 | void SplitRangeSet<AddressType>::Subtract(AddressType base_address, size_t size) { | 262 | void SplitRangeSet<AddressType>::Subtract(AddressType base_address, size_t size) { |
| 212 | m_impl->Subtract<false>(base_address, size, 1, [](AddressType, AddressType) {}); | 263 | m_impl->template Subtract<false>(base_address, size, 1, [](AddressType, AddressType) {}); |
| 213 | } | 264 | } |
| 214 | 265 | ||
| 215 | template <typename AddressType> | 266 | template <typename AddressType> |
| 216 | template <typename Func> | 267 | template <typename Func> |
| 217 | void SplitRangeSet<AddressType>::Subtract(AddressType base_address, size_t size, Func&& on_delete) { | 268 | void SplitRangeSet<AddressType>::Subtract(AddressType base_address, size_t size, Func&& on_delete) { |
| 218 | m_impl->Subtract<true>(base_address, size, 1, on_delete); | 269 | m_impl->template Subtract<true, Func>(base_address, size, 1, std::move(on_delete)); |
| 219 | } | 270 | } |
| 220 | 271 | ||
| 221 | template <typename AddressType> | 272 | template <typename AddressType> |
| 222 | void SplitRangeSet<AddressType>::DeleteAll(AddressType base_address, size_t size) { | 273 | void SplitRangeSet<AddressType>::DeleteAll(AddressType base_address, size_t size) { |
| 223 | m_impl->Subtract<false>(base_address, size, std::numeric_limits<s32>::max(), | 274 | m_impl->template Subtract<false>(base_address, size, std::numeric_limits<s32>::max(), |
| 224 | [](AddressType, AddressType) {}); | 275 | [](AddressType, AddressType) {}); |
| 225 | } | 276 | } |
| 226 | 277 | ||
| @@ -237,43 +288,14 @@ bool SplitRangeSet<AddressType>::Empty() const { | |||
| 237 | template <typename AddressType> | 288 | template <typename AddressType> |
| 238 | template <typename Func> | 289 | template <typename Func> |
| 239 | void SplitRangeSet<AddressType>::ForEach(Func&& func) const { | 290 | void SplitRangeSet<AddressType>::ForEach(Func&& func) const { |
| 240 | if (m_impl->m_split_ranges_set.empty()) { | 291 | m_impl->ForEach(func); |
| 241 | return; | ||
| 242 | } | ||
| 243 | auto it = m_impl->m_split_ranges_set.begin(); | ||
| 244 | auto end_it = m_impl->m_split_ranges_set.end(); | ||
| 245 | for (; it != end_it; it++) { | ||
| 246 | const AddressType inter_addr_end = it->first.upper(); | ||
| 247 | const AddressType inter_addr = it->first.lower(); | ||
| 248 | func(inter_addr, inter_addr_end, it->second); | ||
| 249 | } | ||
| 250 | } | 292 | } |
| 251 | 293 | ||
| 252 | template <typename AddressType> | 294 | template <typename AddressType> |
| 253 | template <typename Func> | 295 | template <typename Func> |
| 254 | void SplitRangeSet<AddressType>::ForEachInRange(AddressType base_address, size_t size, | 296 | void SplitRangeSet<AddressType>::ForEachInRange(AddressType base_address, size_t size, |
| 255 | Func&& func) const { | 297 | Func&& func) const { |
| 256 | auto& range_set = m_impl->m_split_ranges_set; | 298 | m_impl->ForEachInRange(base_address, size, std::move(func)); |
| 257 | const AddressType start_address = base_address; | ||
| 258 | const AddressType end_address = start_address + size; | ||
| 259 | const SplitRangeSetImpl::IntervalType search_interval{start_address, end_address}; | ||
| 260 | auto it = range_set.lower_bound(search_interval); | ||
| 261 | if (it == range_set.end()) { | ||
| 262 | return; | ||
| 263 | } | ||
| 264 | auto end_it = range_set.upper_bound(search_interval); | ||
| 265 | for (; it != end_it; it++) { | ||
| 266 | auto& inter = it->first; | ||
| 267 | AddressType inter_addr_end = inter.upper(); | ||
| 268 | AddressType inter_addr = inter.lower(); | ||
| 269 | if (inter_addr_end > end_address) { | ||
| 270 | inter_addr_end = end_address; | ||
| 271 | } | ||
| 272 | if (inter_addr < start_address) { | ||
| 273 | inter_addr = start_address; | ||
| 274 | } | ||
| 275 | func(inter_addr, inter_addr_end, it->second); | ||
| 276 | } | ||
| 277 | } | 299 | } |
| 278 | 300 | ||
| 279 | } // namespace Common \ No newline at end of file | 301 | } // namespace Common \ No newline at end of file |