summaryrefslogtreecommitdiff
path: root/src/video_core/buffer_cache
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2020-05-21 01:06:40 -0300
committerGravatar ReinUsesLisp2020-05-21 16:44:00 -0300
commita2dcc642c1737721bafe54605c7826fa08d18f47 (patch)
tree655b96d46815d93259b12dccc8acad293437db41 /src/video_core/buffer_cache
parentbuffer_cache: Use boost::container::small_vector for maps in range (diff)
downloadyuzu-a2dcc642c1737721bafe54605c7826fa08d18f47.tar.gz
yuzu-a2dcc642c1737721bafe54605c7826fa08d18f47.tar.xz
yuzu-a2dcc642c1737721bafe54605c7826fa08d18f47.zip
map_interval: Add interval allocator and drop hack
Drop the std::list hack to allocate memory indefinitely. Instead use a custom allocator that keeps references valid until destruction. This allocates fixed chunks of memory and puts pointers in a free list. When an allocation is no longer used put it back to the free list, this doesn't heap allocate because std::vector doesn't change the capacity. If the free list is empty, allocate a new chunk.
Diffstat (limited to 'src/video_core/buffer_cache')
-rw-r--r--src/video_core/buffer_cache/buffer_cache.h7
-rw-r--r--src/video_core/buffer_cache/map_interval.cpp33
-rw-r--r--src/video_core/buffer_cache/map_interval.h41
3 files changed, 78 insertions, 3 deletions
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h
index 0c8500c04..2262259c7 100644
--- a/src/video_core/buffer_cache/buffer_cache.h
+++ b/src/video_core/buffer_cache/buffer_cache.h
@@ -284,8 +284,8 @@ protected:
284 MarkRegionAsWritten(new_map.start, new_map.end - 1); 284 MarkRegionAsWritten(new_map.start, new_map.end - 1);
285 new_map.is_written = true; 285 new_map.is_written = true;
286 } 286 }
287 // Temporary hack, leaks memory and it's not cache local 287 MapInterval* const storage = mapped_addresses_allocator.Allocate();
288 MapInterval* const storage = &mapped_addresses_storage.emplace_back(new_map); 288 *storage = new_map;
289 mapped_addresses.insert(*storage); 289 mapped_addresses.insert(*storage);
290 return storage; 290 return storage;
291 } 291 }
@@ -313,6 +313,7 @@ protected:
313 const auto it = mapped_addresses.find(*map); 313 const auto it = mapped_addresses.find(*map);
314 ASSERT(it != mapped_addresses.end()); 314 ASSERT(it != mapped_addresses.end());
315 mapped_addresses.erase(it); 315 mapped_addresses.erase(it);
316 mapped_addresses_allocator.Release(map);
316 } 317 }
317 318
318private: 319private:
@@ -577,7 +578,7 @@ private:
577 u64 buffer_offset = 0; 578 u64 buffer_offset = 0;
578 u64 buffer_offset_base = 0; 579 u64 buffer_offset_base = 0;
579 580
580 std::list<MapInterval> mapped_addresses_storage; // Temporary hack 581 MapIntervalAllocator mapped_addresses_allocator;
581 boost::intrusive::set<MapInterval, boost::intrusive::compare<MapIntervalCompare>> 582 boost::intrusive::set<MapInterval, boost::intrusive::compare<MapIntervalCompare>>
582 mapped_addresses; 583 mapped_addresses;
583 584
diff --git a/src/video_core/buffer_cache/map_interval.cpp b/src/video_core/buffer_cache/map_interval.cpp
new file mode 100644
index 000000000..62587e18a
--- /dev/null
+++ b/src/video_core/buffer_cache/map_interval.cpp
@@ -0,0 +1,33 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <algorithm>
6#include <array>
7#include <cstddef>
8#include <memory>
9
10#include "video_core/buffer_cache/map_interval.h"
11
12namespace VideoCommon {
13
14MapIntervalAllocator::MapIntervalAllocator() {
15 FillFreeList(first_chunk);
16}
17
18MapIntervalAllocator::~MapIntervalAllocator() = default;
19
20void MapIntervalAllocator::AllocateNewChunk() {
21 *new_chunk = std::make_unique<Chunk>();
22 FillFreeList(**new_chunk);
23 new_chunk = &(*new_chunk)->next;
24}
25
26void MapIntervalAllocator::FillFreeList(Chunk& chunk) {
27 const std::size_t old_size = free_list.size();
28 free_list.resize(old_size + chunk.data.size());
29 std::transform(chunk.data.rbegin(), chunk.data.rend(), free_list.begin() + old_size,
30 [](MapInterval& interval) { return &interval; });
31}
32
33} // namespace VideoCommon
diff --git a/src/video_core/buffer_cache/map_interval.h b/src/video_core/buffer_cache/map_interval.h
index 45705cccf..fe0bcd1d8 100644
--- a/src/video_core/buffer_cache/map_interval.h
+++ b/src/video_core/buffer_cache/map_interval.h
@@ -4,6 +4,11 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <array>
8#include <cstddef>
9#include <memory>
10#include <vector>
11
7#include <boost/intrusive/set_hook.hpp> 12#include <boost/intrusive/set_hook.hpp>
8 13
9#include "common/common_types.h" 14#include "common/common_types.h"
@@ -12,6 +17,8 @@
12namespace VideoCommon { 17namespace VideoCommon {
13 18
14struct MapInterval : public boost::intrusive::set_base_hook<boost::intrusive::optimize_size<true>> { 19struct MapInterval : public boost::intrusive::set_base_hook<boost::intrusive::optimize_size<true>> {
20 MapInterval() = default;
21
15 /*implicit*/ MapInterval(VAddr start_) noexcept : start{start_} {} 22 /*implicit*/ MapInterval(VAddr start_) noexcept : start{start_} {}
16 23
17 explicit MapInterval(VAddr start_, VAddr end_, GPUVAddr gpu_addr_) noexcept 24 explicit MapInterval(VAddr start_, VAddr end_, GPUVAddr gpu_addr_) noexcept
@@ -48,4 +55,38 @@ struct MapIntervalCompare {
48 } 55 }
49}; 56};
50 57
58class MapIntervalAllocator {
59public:
60 MapIntervalAllocator();
61 ~MapIntervalAllocator();
62
63 MapInterval* Allocate() {
64 if (free_list.empty()) {
65 AllocateNewChunk();
66 }
67 MapInterval* const interval = free_list.back();
68 free_list.pop_back();
69 return interval;
70 }
71
72 void Release(MapInterval* interval) {
73 free_list.push_back(interval);
74 }
75
76private:
77 struct Chunk {
78 std::unique_ptr<Chunk> next;
79 std::array<MapInterval, 0x8000> data;
80 };
81
82 void AllocateNewChunk();
83
84 void FillFreeList(Chunk& chunk);
85
86 std::vector<MapInterval*> free_list;
87 std::unique_ptr<Chunk>* new_chunk = &first_chunk.next;
88
89 Chunk first_chunk;
90};
91
51} // namespace VideoCommon 92} // namespace VideoCommon