diff options
Diffstat (limited to 'src/video_core')
| -rw-r--r-- | src/video_core/buffer_cache/buffer_cache.h | 63 | ||||
| -rw-r--r-- | src/video_core/buffer_cache/map_interval.h | 62 | 
2 files changed, 76 insertions, 49 deletions
| diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index e36f85705..7c1737fe2 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -25,6 +25,8 @@ class RasterizerInterface;  namespace VideoCommon { +using MapInterval = std::shared_ptr<MapIntervalBase>; +  template <typename TBuffer, typename TBufferType, typename StreamBuffer>  class BufferCache {  public: @@ -90,7 +92,9 @@ public:          std::vector<MapInterval> objects = GetMapsInRange(addr, size);          for (auto& object : objects) { -            Unregister(object); +            if (object->IsRegistered()) { +                Unregister(object); +            }          }      } @@ -120,51 +124,54 @@ protected:                             std::size_t dst_offset, std::size_t size) = 0;      /// Register an object into the cache -    void Register(const MapInterval& new_interval, const GPUVAddr gpu_addr) { -        const CacheAddr cache_ptr = new_interval.start; -        const std::size_t size = new_interval.end - new_interval.start; +    void Register(const MapInterval& new_map) { +        const CacheAddr cache_ptr = new_map->GetStart();          const std::optional<VAddr> cpu_addr = -            system.GPU().MemoryManager().GpuToCpuAddress(gpu_addr); +            system.GPU().MemoryManager().GpuToCpuAddress(new_map->GetGpuAddress());          if (!cache_ptr || !cpu_addr) {              LOG_CRITICAL(HW_GPU, "Failed to register buffer with unmapped gpu_address 0x{:016x}", -                         gpu_addr); +                         new_map->GetGpuAddress());              return;          } -        const IntervalType interval{new_interval.start, new_interval.end}; -        mapped_addresses.insert(interval); -        map_storage[new_interval] = MapInfo{gpu_addr, *cpu_addr}; - +        const std::size_t size = new_map->GetEnd() - new_map->GetStart(); +        new_map->SetCpuAddress(*cpu_addr); +        new_map->MarkAsRegistered(true); +        const IntervalType interval{new_map->GetStart(), new_map->GetEnd()}; +        mapped_addresses.insert({interval, new_map});          rasterizer.UpdatePagesCachedCount(*cpu_addr, size, 1);      }      /// Unregisters an object from the cache -    void Unregister(const MapInterval& interval) { -        const MapInfo info = map_storage[interval]; -        const std::size_t size = interval.end - interval.start; -        rasterizer.UpdatePagesCachedCount(info.cpu_addr, size, -1); -        const IntervalType delete_interval{interval.start, interval.end}; +    void Unregister(MapInterval& map) { +        const std::size_t size = map->GetEnd() - map->GetStart(); +        rasterizer.UpdatePagesCachedCount(map->GetCpuAddress(), size, -1); +        map->MarkAsRegistered(false); +        const IntervalType delete_interval{map->GetStart(), map->GetEnd()};          mapped_addresses.erase(delete_interval); -        map_storage.erase(interval);      }  private: +    MapInterval CreateMap(const CacheAddr start, const CacheAddr end, const GPUVAddr gpu_addr) { +        return std::make_shared<MapIntervalBase>(start, end, gpu_addr); +    } +      void MapAddress(const TBuffer& block, const GPUVAddr gpu_addr, const CacheAddr cache_addr,                      const std::size_t size) {          std::vector<MapInterval> overlaps = GetMapsInRange(cache_addr, size);          if (overlaps.empty()) {              const CacheAddr cache_addr_end = cache_addr + size; -            MapInterval new_interval{cache_addr, cache_addr_end}; +            MapInterval new_map = CreateMap(cache_addr, cache_addr_end, gpu_addr);              u8* host_ptr = FromCacheAddr(cache_addr);              UploadBlockData(block, block->GetOffset(cache_addr), size, host_ptr); -            Register(new_interval, gpu_addr); +            Register(new_map);              return;          }          const CacheAddr cache_addr_end = cache_addr + size;          if (overlaps.size() == 1) {              const MapInterval& current_map = overlaps[0]; -            if (current_map.IsInside(cache_addr, cache_addr_end)) { +            if (current_map->IsInside(cache_addr, cache_addr_end)) {                  return;              }          } @@ -172,25 +179,25 @@ private:          CacheAddr new_end = cache_addr_end;          // Calculate new buffer parameters          for (auto& overlap : overlaps) { -            new_start = std::min(overlap.start, new_start); -            new_end = std::max(overlap.end, new_end); +            new_start = std::min(overlap->GetStart(), new_start); +            new_end = std::max(overlap->GetEnd(), new_end);          }          GPUVAddr new_gpu_addr = gpu_addr + new_start - cache_addr;          for (auto& overlap : overlaps) {              Unregister(overlap);          }          UpdateBlock(block, new_start, new_end, overlaps); -        MapInterval new_interval{new_start, new_end}; -        Register(new_interval, new_gpu_addr); +        MapInterval new_map = CreateMap(new_start, new_end, new_gpu_addr); +        Register(new_map);      }      void UpdateBlock(const TBuffer& block, CacheAddr start, CacheAddr end,                       std::vector<MapInterval>& overlaps) {          const IntervalType base_interval{start, end}; -        IntervalCache interval_set{}; +        IntervalSet interval_set{};          interval_set.add(base_interval);          for (auto& overlap : overlaps) { -            const IntervalType subtract{overlap.start, overlap.end}; +            const IntervalType subtract{overlap->GetStart(), overlap->GetEnd()};              interval_set.subtract(subtract);          }          for (auto& interval : interval_set) { @@ -210,7 +217,7 @@ private:          std::vector<MapInterval> objects{};          const IntervalType interval{addr, addr + size};          for (auto& pair : boost::make_iterator_range(mapped_addresses.equal_range(interval))) { -            objects.emplace_back(pair.lower(), pair.upper()); +            objects.push_back(pair.second);          }          return objects; @@ -322,10 +329,10 @@ private:      u64 buffer_offset = 0;      u64 buffer_offset_base = 0; -    using IntervalCache = boost::icl::interval_set<CacheAddr>; +    using IntervalSet = boost::icl::interval_set<CacheAddr>; +    using IntervalCache = boost::icl::interval_map<CacheAddr, MapInterval>;      using IntervalType = typename IntervalCache::interval_type;      IntervalCache mapped_addresses{}; -    std::unordered_map<MapInterval, MapInfo> map_storage;      static constexpr u64 block_page_bits{24};      static constexpr u64 block_page_size{1 << block_page_bits}; diff --git a/src/video_core/buffer_cache/map_interval.h b/src/video_core/buffer_cache/map_interval.h index c1cd52ca4..a01eddf49 100644 --- a/src/video_core/buffer_cache/map_interval.h +++ b/src/video_core/buffer_cache/map_interval.h @@ -4,45 +4,65 @@  #pragma once -#include <boost/functional/hash.hpp>  #include "common/common_types.h"  #include "video_core/gpu.h"  namespace VideoCommon { -struct MapInterval { -    MapInterval(const CacheAddr start, const CacheAddr end) : start{start}, end{end} {} -    CacheAddr start; -    CacheAddr end; +class MapIntervalBase { +public: +    MapIntervalBase(const CacheAddr start, const CacheAddr end, const GPUVAddr gpu_addr) +        : start{start}, end{end}, gpu_addr{gpu_addr} {} + +    void SetCpuAddress(VAddr new_cpu_addr) { +        cpu_addr = new_cpu_addr; +    } + +    VAddr GetCpuAddress() const { +        return cpu_addr; +    } + +    GPUVAddr GetGpuAddress() const { +        return gpu_addr; +    } +      bool IsInside(const CacheAddr other_start, const CacheAddr other_end) const {          return (start <= other_start && other_end <= end);      } -    bool operator==(const MapInterval& rhs) const { +    bool operator==(const MapIntervalBase& rhs) const {          return std::tie(start, end) == std::tie(rhs.start, rhs.end);      } -    bool operator!=(const MapInterval& rhs) const { +    bool operator!=(const MapIntervalBase& rhs) const {          return !operator==(rhs);      } -}; -struct MapInfo { -    GPUVAddr gpu_addr; -    VAddr cpu_addr; -}; +    void MarkAsRegistered(const bool registered) { +        is_registered = registered; +    } -} // namespace VideoCommon +    bool IsRegistered() const { +        return is_registered; +    } -namespace std { +    CacheAddr GetStart() const { +        return start; +    } -template <> -struct hash<VideoCommon::MapInterval> { -    std::size_t operator()(const VideoCommon::MapInterval& k) const noexcept { -        std::size_t a = std::hash<CacheAddr>()(k.start); -        boost::hash_combine(a, std::hash<CacheAddr>()(k.end)); -        return a; +    CacheAddr GetEnd() const { +        return end;      } + +private: +    CacheAddr start; +    CacheAddr end; +    GPUVAddr gpu_addr; +    VAddr cpu_addr{}; +    bool is_write{}; +    bool is_modified{}; +    bool is_registered{}; +    u64 ticks{};  }; -} // namespace std +} // namespace VideoCommon | 
