diff options
-rw-r--r-- | src/video_core/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/video_core/buffer_cache/buffer_cache.h | 7 | ||||
-rw-r--r-- | src/video_core/buffer_cache/map_interval.cpp | 33 | ||||
-rw-r--r-- | src/video_core/buffer_cache/map_interval.h | 41 |
4 files changed, 79 insertions, 3 deletions
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index d23c53843..f00c71dae 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt @@ -1,6 +1,7 @@ add_library(video_core STATIC buffer_cache/buffer_block.h buffer_cache/buffer_cache.h + buffer_cache/map_interval.cpp buffer_cache/map_interval.h dirty_flags.cpp dirty_flags.h 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: MarkRegionAsWritten(new_map.start, new_map.end - 1); new_map.is_written = true; } - // Temporary hack, leaks memory and it's not cache local - MapInterval* const storage = &mapped_addresses_storage.emplace_back(new_map); + MapInterval* const storage = mapped_addresses_allocator.Allocate(); + *storage = new_map; mapped_addresses.insert(*storage); return storage; } @@ -313,6 +313,7 @@ protected: const auto it = mapped_addresses.find(*map); ASSERT(it != mapped_addresses.end()); mapped_addresses.erase(it); + mapped_addresses_allocator.Release(map); } private: @@ -577,7 +578,7 @@ private: u64 buffer_offset = 0; u64 buffer_offset_base = 0; - std::list<MapInterval> mapped_addresses_storage; // Temporary hack + MapIntervalAllocator mapped_addresses_allocator; boost::intrusive::set<MapInterval, boost::intrusive::compare<MapIntervalCompare>> mapped_addresses; 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 @@ +// Copyright 2020 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include <algorithm> +#include <array> +#include <cstddef> +#include <memory> + +#include "video_core/buffer_cache/map_interval.h" + +namespace VideoCommon { + +MapIntervalAllocator::MapIntervalAllocator() { + FillFreeList(first_chunk); +} + +MapIntervalAllocator::~MapIntervalAllocator() = default; + +void MapIntervalAllocator::AllocateNewChunk() { + *new_chunk = std::make_unique<Chunk>(); + FillFreeList(**new_chunk); + new_chunk = &(*new_chunk)->next; +} + +void MapIntervalAllocator::FillFreeList(Chunk& chunk) { + const std::size_t old_size = free_list.size(); + free_list.resize(old_size + chunk.data.size()); + std::transform(chunk.data.rbegin(), chunk.data.rend(), free_list.begin() + old_size, + [](MapInterval& interval) { return &interval; }); +} + +} // 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 @@ #pragma once +#include <array> +#include <cstddef> +#include <memory> +#include <vector> + #include <boost/intrusive/set_hook.hpp> #include "common/common_types.h" @@ -12,6 +17,8 @@ namespace VideoCommon { struct MapInterval : public boost::intrusive::set_base_hook<boost::intrusive::optimize_size<true>> { + MapInterval() = default; + /*implicit*/ MapInterval(VAddr start_) noexcept : start{start_} {} explicit MapInterval(VAddr start_, VAddr end_, GPUVAddr gpu_addr_) noexcept @@ -48,4 +55,38 @@ struct MapIntervalCompare { } }; +class MapIntervalAllocator { +public: + MapIntervalAllocator(); + ~MapIntervalAllocator(); + + MapInterval* Allocate() { + if (free_list.empty()) { + AllocateNewChunk(); + } + MapInterval* const interval = free_list.back(); + free_list.pop_back(); + return interval; + } + + void Release(MapInterval* interval) { + free_list.push_back(interval); + } + +private: + struct Chunk { + std::unique_ptr<Chunk> next; + std::array<MapInterval, 0x8000> data; + }; + + void AllocateNewChunk(); + + void FillFreeList(Chunk& chunk); + + std::vector<MapInterval*> free_list; + std::unique_ptr<Chunk>* new_chunk = &first_chunk.next; + + Chunk first_chunk; +}; + } // namespace VideoCommon |