Преглед изворни кода

video_core: rasterizer_accelerated: Use a flat array instead of interval_map for cached pages.

- Uses a fixed 64MB for the cache instead of an ever growing map.
- Slightly faster by using atomics instead of a single mutex for access.
- Thanks for Rodrigo for the idea.
bunnei пре 5 година
родитељ
комит
94da1e8a7e
2 измењених фајлова са 32 додато и 44 уклоњено
  1. 13 38
      src/video_core/rasterizer_accelerated.cpp
  2. 19 6
      src/video_core/rasterizer_accelerated.h

+ 13 - 38
src/video_core/rasterizer_accelerated.cpp

@@ -2,64 +2,39 @@
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 
-#include <mutex>
-
-#include <boost/icl/interval_map.hpp>
-#include <boost/range/iterator_range.hpp>
-
 #include "common/assert.h"
 #include "common/common_types.h"
+#include "common/div_ceil.h"
 #include "core/memory.h"
 #include "video_core/rasterizer_accelerated.h"
 
 namespace VideoCore {
 
-namespace {
-
-template <typename Map, typename Interval>
-constexpr auto RangeFromInterval(Map& map, const Interval& interval) {
-    return boost::make_iterator_range(map.equal_range(interval));
-}
-
-} // Anonymous namespace
-
 RasterizerAccelerated::RasterizerAccelerated(Core::Memory::Memory& cpu_memory_)
     : cpu_memory{cpu_memory_} {}
 
 RasterizerAccelerated::~RasterizerAccelerated() = default;
 
 void RasterizerAccelerated::UpdatePagesCachedCount(VAddr addr, u64 size, int delta) {
-    std::lock_guard lock{pages_mutex};
-    const u64 page_start{addr >> Core::Memory::PAGE_BITS};
-    const u64 page_end{(addr + size + Core::Memory::PAGE_SIZE - 1) >> Core::Memory::PAGE_BITS};
-
-    // Interval maps will erase segments if count reaches 0, so if delta is negative we have to
-    // subtract after iterating
-    const auto pages_interval = CachedPageMap::interval_type::right_open(page_start, page_end);
-    if (delta > 0) {
-        cached_pages.add({pages_interval, delta});
-    }
+    const auto page_end = Common::DivCeil(addr + size, Core::Memory::PAGE_SIZE);
+    for (auto page = addr >> Core::Memory::PAGE_BITS; page != page_end; ++page) {
+        auto& count = cached_pages.at(page >> 3).Count(page);
 
-    for (const auto& pair : RangeFromInterval(cached_pages, pages_interval)) {
-        const auto interval = pair.first & pages_interval;
-        const int count = pair.second;
+        ASSERT_MSG(count < UINT8_MAX, "Count may exceed UINT8_MAX!");
 
-        const VAddr interval_start_addr = boost::icl::first(interval) << Core::Memory::PAGE_BITS;
-        const VAddr interval_end_addr = boost::icl::last_next(interval) << Core::Memory::PAGE_BITS;
-        const u64 interval_size = interval_end_addr - interval_start_addr;
+        count += delta;
 
-        if (delta > 0 && count == delta) {
-            cpu_memory.RasterizerMarkRegionCached(interval_start_addr, interval_size, true);
-        } else if (delta < 0 && count == -delta) {
-            cpu_memory.RasterizerMarkRegionCached(interval_start_addr, interval_size, false);
+        // Assume delta is either -1 or 1
+        if (count == 0) {
+            cpu_memory.RasterizerMarkRegionCached(page << Core::Memory::PAGE_BITS,
+                                                  Core::Memory::PAGE_SIZE, false);
+        } else if (count == 1 && delta > 0) {
+            cpu_memory.RasterizerMarkRegionCached(page << Core::Memory::PAGE_BITS,
+                                                  Core::Memory::PAGE_SIZE, true);
         } else {
             ASSERT(count >= 0);
         }
     }
-
-    if (delta < 0) {
-        cached_pages.add({pages_interval, delta});
-    }
 }
 
 } // namespace VideoCore

+ 19 - 6
src/video_core/rasterizer_accelerated.h

@@ -4,9 +4,8 @@
 
 #pragma once
 
-#include <mutex>
-
-#include <boost/icl/interval_map.hpp>
+#include <array>
+#include <atomic>
 
 #include "common/common_types.h"
 #include "video_core/rasterizer_interface.h"
@@ -26,10 +25,24 @@ public:
     void UpdatePagesCachedCount(VAddr addr, u64 size, int delta) override;
 
 private:
-    using CachedPageMap = boost::icl::interval_map<u64, int>;
-    CachedPageMap cached_pages;
-    std::mutex pages_mutex;
+    class CacheEntry final {
+    public:
+        CacheEntry() = default;
+
+        std::atomic_uint8_t& Count(std::size_t page) {
+            return values[page & 7];
+        }
+
+        const std::atomic_uint8_t& Count(std::size_t page) const {
+            return values[page & 7];
+        }
+
+    private:
+        std::array<std::atomic_uint8_t, 8> values{};
+    };
+    static_assert(sizeof(CacheEntry) == 8, "CacheEntry should be 8 bytes!");
 
+    std::array<CacheEntry, 0x800000> cached_pages;
     Core::Memory::Memory& cpu_memory;
 };