summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/video_core/rasterizer_accelerated.cpp62
-rw-r--r--src/video_core/rasterizer_accelerated.h25
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
15namespace VideoCore { 11namespace VideoCore {
16 12
17namespace {
18
19template <typename Map, typename Interval>
20constexpr auto RangeFromInterval(Map& map, const Interval& interval) {
21 return boost::make_iterator_range(map.equal_range(interval));
22}
23
24} // Anonymous namespace
25
26RasterizerAccelerated::RasterizerAccelerated(Core::Memory::Memory& cpu_memory_) 13RasterizerAccelerated::RasterizerAccelerated(Core::Memory::Memory& cpu_memory_)
27 : cpu_memory{cpu_memory_} {} 14 : cpu_memory{cpu_memory_} {}
28 15
29RasterizerAccelerated::~RasterizerAccelerated() = default; 16RasterizerAccelerated::~RasterizerAccelerated() = default;
30 17
31void RasterizerAccelerated::UpdatePagesCachedCount(VAddr addr, u64 size, int delta) { 18void 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
28private: 27private:
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