diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/rasterizer_accelerated.cpp | 62 | ||||
| -rw-r--r-- | src/video_core/rasterizer_accelerated.h | 25 |
2 files changed, 40 insertions, 47 deletions
diff --git a/src/video_core/rasterizer_accelerated.cpp b/src/video_core/rasterizer_accelerated.cpp index 53622ca05..62d84c0f8 100644 --- a/src/video_core/rasterizer_accelerated.cpp +++ b/src/video_core/rasterizer_accelerated.cpp | |||
| @@ -2,63 +2,43 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <mutex> | ||
| 6 | |||
| 7 | #include <boost/icl/interval_map.hpp> | ||
| 8 | #include <boost/range/iterator_range.hpp> | ||
| 9 | |||
| 10 | #include "common/assert.h" | 5 | #include "common/assert.h" |
| 11 | #include "common/common_types.h" | 6 | #include "common/common_types.h" |
| 7 | #include "common/div_ceil.h" | ||
| 12 | #include "core/memory.h" | 8 | #include "core/memory.h" |
| 13 | #include "video_core/rasterizer_accelerated.h" | 9 | #include "video_core/rasterizer_accelerated.h" |
| 14 | 10 | ||
| 15 | namespace VideoCore { | 11 | namespace VideoCore { |
| 16 | 12 | ||
| 17 | namespace { | ||
| 18 | |||
| 19 | template <typename Map, typename Interval> | ||
| 20 | constexpr auto RangeFromInterval(Map& map, const Interval& interval) { | ||
| 21 | return boost::make_iterator_range(map.equal_range(interval)); | ||
| 22 | } | ||
| 23 | |||
| 24 | } // Anonymous namespace | ||
| 25 | |||
| 26 | RasterizerAccelerated::RasterizerAccelerated(Core::Memory::Memory& cpu_memory_) | 13 | RasterizerAccelerated::RasterizerAccelerated(Core::Memory::Memory& cpu_memory_) |
| 27 | : cpu_memory{cpu_memory_} {} | 14 | : cpu_memory{cpu_memory_} {} |
| 28 | 15 | ||
| 29 | RasterizerAccelerated::~RasterizerAccelerated() = default; | 16 | RasterizerAccelerated::~RasterizerAccelerated() = default; |
| 30 | 17 | ||
| 31 | void RasterizerAccelerated::UpdatePagesCachedCount(VAddr addr, u64 size, int delta) { | 18 | void RasterizerAccelerated::UpdatePagesCachedCount(VAddr addr, u64 size, int delta) { |
| 32 | std::lock_guard lock{pages_mutex}; | 19 | const auto page_end = Common::DivCeil(addr + size, Core::Memory::PAGE_SIZE); |
| 33 | const u64 page_start{addr >> Core::Memory::PAGE_BITS}; | 20 | for (auto page = addr >> Core::Memory::PAGE_BITS; page != page_end; ++page) { |
| 34 | const u64 page_end{(addr + size + Core::Memory::PAGE_SIZE - 1) >> Core::Memory::PAGE_BITS}; | 21 | auto& count = cached_pages.at(page >> 3).Count(page); |
| 35 | 22 | ||
| 36 | // Interval maps will erase segments if count reaches 0, so if delta is negative we have to | 23 | if (delta > 0) { |
| 37 | // subtract after iterating | 24 | ASSERT_MSG(count < UINT8_MAX, "Count may overflow!"); |
| 38 | const auto pages_interval = CachedPageMap::interval_type::right_open(page_start, page_end); | 25 | } else if (delta < 0) { |
| 39 | if (delta > 0) { | 26 | ASSERT_MSG(count > 0, "Count may underflow!"); |
| 40 | cached_pages.add({pages_interval, delta}); | ||
| 41 | } | ||
| 42 | |||
| 43 | for (const auto& pair : RangeFromInterval(cached_pages, pages_interval)) { | ||
| 44 | const auto interval = pair.first & pages_interval; | ||
| 45 | const int count = pair.second; | ||
| 46 | |||
| 47 | const VAddr interval_start_addr = boost::icl::first(interval) << Core::Memory::PAGE_BITS; | ||
| 48 | const VAddr interval_end_addr = boost::icl::last_next(interval) << Core::Memory::PAGE_BITS; | ||
| 49 | const u64 interval_size = interval_end_addr - interval_start_addr; | ||
| 50 | |||
| 51 | if (delta > 0 && count == delta) { | ||
| 52 | cpu_memory.RasterizerMarkRegionCached(interval_start_addr, interval_size, true); | ||
| 53 | } else if (delta < 0 && count == -delta) { | ||
| 54 | cpu_memory.RasterizerMarkRegionCached(interval_start_addr, interval_size, false); | ||
| 55 | } else { | 27 | } else { |
| 56 | ASSERT(count >= 0); | 28 | ASSERT_MSG(true, "Delta must be non-zero!"); |
| 57 | } | 29 | } |
| 58 | } | ||
| 59 | 30 | ||
| 60 | if (delta < 0) { | 31 | // Adds or subtracts 1, as count is a unsigned 8-bit value |
| 61 | cached_pages.add({pages_interval, delta}); | 32 | count += static_cast<u8>(delta); |
| 33 | |||
| 34 | // Assume delta is either -1 or 1 | ||
| 35 | if (count == 0) { | ||
| 36 | cpu_memory.RasterizerMarkRegionCached(page << Core::Memory::PAGE_BITS, | ||
| 37 | Core::Memory::PAGE_SIZE, false); | ||
| 38 | } else if (count == 1 && delta > 0) { | ||
| 39 | cpu_memory.RasterizerMarkRegionCached(page << Core::Memory::PAGE_BITS, | ||
| 40 | Core::Memory::PAGE_SIZE, true); | ||
| 41 | } | ||
| 62 | } | 42 | } |
| 63 | } | 43 | } |
| 64 | 44 | ||
diff --git a/src/video_core/rasterizer_accelerated.h b/src/video_core/rasterizer_accelerated.h index 91866d7dd..9227a4adc 100644 --- a/src/video_core/rasterizer_accelerated.h +++ b/src/video_core/rasterizer_accelerated.h | |||
| @@ -4,9 +4,8 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <mutex> | 7 | #include <array> |
| 8 | 8 | #include <atomic> | |
| 9 | #include <boost/icl/interval_map.hpp> | ||
| 10 | 9 | ||
| 11 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 12 | #include "video_core/rasterizer_interface.h" | 11 | #include "video_core/rasterizer_interface.h" |
| @@ -26,10 +25,24 @@ public: | |||
| 26 | void UpdatePagesCachedCount(VAddr addr, u64 size, int delta) override; | 25 | void UpdatePagesCachedCount(VAddr addr, u64 size, int delta) override; |
| 27 | 26 | ||
| 28 | private: | 27 | private: |
| 29 | using CachedPageMap = boost::icl::interval_map<u64, int>; | 28 | class CacheEntry final { |
| 30 | CachedPageMap cached_pages; | 29 | public: |
| 31 | std::mutex pages_mutex; | 30 | CacheEntry() = default; |
| 31 | |||
| 32 | std::atomic_uint8_t& Count(std::size_t page) { | ||
| 33 | return values[page & 7]; | ||
| 34 | } | ||
| 35 | |||
| 36 | const std::atomic_uint8_t& Count(std::size_t page) const { | ||
| 37 | return values[page & 7]; | ||
| 38 | } | ||
| 39 | |||
| 40 | private: | ||
| 41 | std::array<std::atomic_uint8_t, 8> values{}; | ||
| 42 | }; | ||
| 43 | static_assert(sizeof(CacheEntry) == 8, "CacheEntry should be 8 bytes!"); | ||
| 32 | 44 | ||
| 45 | std::array<CacheEntry, 0x800000> cached_pages; | ||
| 33 | Core::Memory::Memory& cpu_memory; | 46 | Core::Memory::Memory& cpu_memory; |
| 34 | }; | 47 | }; |
| 35 | 48 | ||