diff options
| author | 2023-12-30 09:37:16 +0100 | |
|---|---|---|
| committer | 2024-01-18 21:12:30 -0500 | |
| commit | d8f1ce2f7640200d92a12698c42029316ac1a611 (patch) | |
| tree | 34c983ea5d60c58f0511f993090b70aebe778582 /src | |
| parent | SMMU: Simplify and remove old code. (diff) | |
| download | yuzu-d8f1ce2f7640200d92a12698c42029316ac1a611.tar.gz yuzu-d8f1ce2f7640200d92a12698c42029316ac1a611.tar.xz yuzu-d8f1ce2f7640200d92a12698c42029316ac1a611.zip | |
SMMU: Add continuity tracking optimization.
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/device_memory_manager.h | 21 | ||||
| -rw-r--r-- | src/core/device_memory_manager.inc | 52 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/core/container.cpp | 1 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/core/nvmap.cpp | 2 |
4 files changed, 63 insertions, 13 deletions
diff --git a/src/core/device_memory_manager.h b/src/core/device_memory_manager.h index 0273b78db..0f6599cfe 100644 --- a/src/core/device_memory_manager.h +++ b/src/core/device_memory_manager.h | |||
| @@ -13,7 +13,6 @@ | |||
| 13 | #include "common/scratch_buffer.h" | 13 | #include "common/scratch_buffer.h" |
| 14 | #include "common/virtual_buffer.h" | 14 | #include "common/virtual_buffer.h" |
| 15 | 15 | ||
| 16 | |||
| 17 | namespace Core { | 16 | namespace Core { |
| 18 | 17 | ||
| 19 | class DeviceMemory; | 18 | class DeviceMemory; |
| @@ -40,9 +39,17 @@ public: | |||
| 40 | void AllocateFixed(DAddr start, size_t size); | 39 | void AllocateFixed(DAddr start, size_t size); |
| 41 | void Free(DAddr start, size_t size); | 40 | void Free(DAddr start, size_t size); |
| 42 | 41 | ||
| 43 | void Map(DAddr address, VAddr virtual_address, size_t size, size_t process_id); | 42 | void Map(DAddr address, VAddr virtual_address, size_t size, size_t process_id, |
| 43 | bool track = false); | ||
| 44 | |||
| 44 | void Unmap(DAddr address, size_t size); | 45 | void Unmap(DAddr address, size_t size); |
| 45 | 46 | ||
| 47 | void TrackContinuityImpl(DAddr address, VAddr virtual_address, size_t size, size_t process_id); | ||
| 48 | void TrackContinuity(DAddr address, VAddr virtual_address, size_t size, size_t process_id) { | ||
| 49 | std::scoped_lock lk(mapping_guard); | ||
| 50 | TrackContinuityImpl(address, virtual_address, size, process_id); | ||
| 51 | } | ||
| 52 | |||
| 46 | // Write / Read | 53 | // Write / Read |
| 47 | template <typename T> | 54 | template <typename T> |
| 48 | T* GetPointer(DAddr address); | 55 | T* GetPointer(DAddr address); |
| @@ -86,13 +93,8 @@ public: | |||
| 86 | template <typename T> | 93 | template <typename T> |
| 87 | T Read(DAddr address) const; | 94 | T Read(DAddr address) const; |
| 88 | 95 | ||
| 89 | const u8* GetSpan(const DAddr src_addr, const std::size_t size) const { | 96 | u8* GetSpan(const DAddr src_addr, const std::size_t size); |
| 90 | return nullptr; | 97 | const u8* GetSpan(const DAddr src_addr, const std::size_t size) const; |
| 91 | } | ||
| 92 | |||
| 93 | u8* GetSpan(const DAddr src_addr, const std::size_t size) { | ||
| 94 | return nullptr; | ||
| 95 | } | ||
| 96 | 98 | ||
| 97 | void ReadBlock(DAddr address, void* dest_pointer, size_t size); | 99 | void ReadBlock(DAddr address, void* dest_pointer, size_t size); |
| 98 | void ReadBlockUnsafe(DAddr address, void* dest_pointer, size_t size); | 100 | void ReadBlockUnsafe(DAddr address, void* dest_pointer, size_t size); |
| @@ -144,6 +146,7 @@ private: | |||
| 144 | DeviceInterface* interface; | 146 | DeviceInterface* interface; |
| 145 | Common::VirtualBuffer<u32> compressed_physical_ptr; | 147 | Common::VirtualBuffer<u32> compressed_physical_ptr; |
| 146 | Common::VirtualBuffer<u32> compressed_device_addr; | 148 | Common::VirtualBuffer<u32> compressed_device_addr; |
| 149 | Common::VirtualBuffer<u32> continuity_tracker; | ||
| 147 | 150 | ||
| 148 | // Process memory interfaces | 151 | // Process memory interfaces |
| 149 | 152 | ||
diff --git a/src/core/device_memory_manager.inc b/src/core/device_memory_manager.inc index e9d0efe19..175f0cd5f 100644 --- a/src/core/device_memory_manager.inc +++ b/src/core/device_memory_manager.inc | |||
| @@ -164,6 +164,7 @@ DeviceMemoryManager<Traits>::DeviceMemoryManager(const DeviceMemory& device_memo | |||
| 164 | : physical_base{reinterpret_cast<const uintptr_t>(device_memory_.buffer.BackingBasePointer())}, | 164 | : physical_base{reinterpret_cast<const uintptr_t>(device_memory_.buffer.BackingBasePointer())}, |
| 165 | interface{nullptr}, compressed_physical_ptr(device_as_size >> Memory::YUZU_PAGEBITS), | 165 | interface{nullptr}, compressed_physical_ptr(device_as_size >> Memory::YUZU_PAGEBITS), |
| 166 | compressed_device_addr(1ULL << (physical_max_bits - Memory::YUZU_PAGEBITS)), | 166 | compressed_device_addr(1ULL << (physical_max_bits - Memory::YUZU_PAGEBITS)), |
| 167 | continuity_tracker(device_as_size >> Memory::YUZU_PAGEBITS), | ||
| 167 | cpu_backing_address(device_as_size >> Memory::YUZU_PAGEBITS) { | 168 | cpu_backing_address(device_as_size >> Memory::YUZU_PAGEBITS) { |
| 168 | impl = std::make_unique<DeviceMemoryManagerAllocator<Traits>>(); | 169 | impl = std::make_unique<DeviceMemoryManagerAllocator<Traits>>(); |
| 169 | cached_pages = std::make_unique<CachedPages>(); | 170 | cached_pages = std::make_unique<CachedPages>(); |
| @@ -194,7 +195,7 @@ void DeviceMemoryManager<Traits>::Free(DAddr start, size_t size) { | |||
| 194 | 195 | ||
| 195 | template <typename Traits> | 196 | template <typename Traits> |
| 196 | void DeviceMemoryManager<Traits>::Map(DAddr address, VAddr virtual_address, size_t size, | 197 | void DeviceMemoryManager<Traits>::Map(DAddr address, VAddr virtual_address, size_t size, |
| 197 | size_t process_id) { | 198 | size_t process_id, bool track) { |
| 198 | Core::Memory::Memory* process_memory = registered_processes[process_id]; | 199 | Core::Memory::Memory* process_memory = registered_processes[process_id]; |
| 199 | size_t start_page_d = address >> Memory::YUZU_PAGEBITS; | 200 | size_t start_page_d = address >> Memory::YUZU_PAGEBITS; |
| 200 | size_t num_pages = Common::AlignUp(size, Memory::YUZU_PAGESIZE) >> Memory::YUZU_PAGEBITS; | 201 | size_t num_pages = Common::AlignUp(size, Memory::YUZU_PAGESIZE) >> Memory::YUZU_PAGEBITS; |
| @@ -222,6 +223,9 @@ void DeviceMemoryManager<Traits>::Map(DAddr address, VAddr virtual_address, size | |||
| 222 | } | 223 | } |
| 223 | impl->multi_dev_address.Register(new_dev, start_id); | 224 | impl->multi_dev_address.Register(new_dev, start_id); |
| 224 | } | 225 | } |
| 226 | if (track) { | ||
| 227 | TrackContinuityImpl(address, virtual_address, size, process_id); | ||
| 228 | } | ||
| 225 | } | 229 | } |
| 226 | 230 | ||
| 227 | template <typename Traits> | 231 | template <typename Traits> |
| @@ -251,6 +255,47 @@ void DeviceMemoryManager<Traits>::Unmap(DAddr address, size_t size) { | |||
| 251 | } | 255 | } |
| 252 | } | 256 | } |
| 253 | } | 257 | } |
| 258 | template <typename Traits> | ||
| 259 | void DeviceMemoryManager<Traits>::TrackContinuityImpl(DAddr address, VAddr virtual_address, | ||
| 260 | size_t size, size_t process_id) { | ||
| 261 | Core::Memory::Memory* process_memory = registered_processes[process_id]; | ||
| 262 | size_t start_page_d = address >> Memory::YUZU_PAGEBITS; | ||
| 263 | size_t num_pages = Common::AlignUp(size, Memory::YUZU_PAGESIZE) >> Memory::YUZU_PAGEBITS; | ||
| 264 | uintptr_t last_ptr = 0; | ||
| 265 | size_t page_count = 1; | ||
| 266 | for (size_t i = num_pages; i > 0; i--) { | ||
| 267 | size_t index = i - 1; | ||
| 268 | const VAddr new_vaddress = virtual_address + index * Memory::YUZU_PAGESIZE; | ||
| 269 | const uintptr_t new_ptr = reinterpret_cast<uintptr_t>( | ||
| 270 | process_memory->GetPointerSilent(Common::ProcessAddress(new_vaddress))); | ||
| 271 | if (new_ptr + page_size == last_ptr) { | ||
| 272 | page_count++; | ||
| 273 | } else { | ||
| 274 | page_count = 1; | ||
| 275 | } | ||
| 276 | last_ptr = new_ptr; | ||
| 277 | continuity_tracker[start_page_d + index] = static_cast<u32>(page_count); | ||
| 278 | } | ||
| 279 | } | ||
| 280 | template <typename Traits> | ||
| 281 | u8* DeviceMemoryManager<Traits>::GetSpan(const DAddr src_addr, const std::size_t size) { | ||
| 282 | size_t page_index = src_addr >> page_bits; | ||
| 283 | size_t subbits = src_addr & page_mask; | ||
| 284 | if ((continuity_tracker[page_index] << page_bits) >= size + subbits) { | ||
| 285 | return GetPointer<u8>(src_addr); | ||
| 286 | } | ||
| 287 | return nullptr; | ||
| 288 | } | ||
| 289 | |||
| 290 | template <typename Traits> | ||
| 291 | const u8* DeviceMemoryManager<Traits>::GetSpan(const DAddr src_addr, const std::size_t size) const { | ||
| 292 | size_t page_index = src_addr >> page_bits; | ||
| 293 | size_t subbits = src_addr & page_mask; | ||
| 294 | if ((continuity_tracker[page_index] << page_bits) >= size + subbits) { | ||
| 295 | return GetPointer<u8>(src_addr); | ||
| 296 | } | ||
| 297 | return nullptr; | ||
| 298 | } | ||
| 254 | 299 | ||
| 255 | template <typename Traits> | 300 | template <typename Traits> |
| 256 | void DeviceMemoryManager<Traits>::InnerGatherDeviceAddresses(Common::ScratchBuffer<u32>& buffer, | 301 | void DeviceMemoryManager<Traits>::InnerGatherDeviceAddresses(Common::ScratchBuffer<u32>& buffer, |
| @@ -322,12 +367,13 @@ void DeviceMemoryManager<Traits>::WalkBlock(DAddr addr, std::size_t size, auto o | |||
| 322 | std::size_t page_offset = addr & Memory::YUZU_PAGEMASK; | 367 | std::size_t page_offset = addr & Memory::YUZU_PAGEMASK; |
| 323 | 368 | ||
| 324 | while (remaining_size) { | 369 | while (remaining_size) { |
| 370 | const size_t next_pages = static_cast<std::size_t>(continuity_tracker[page_index]); | ||
| 325 | const std::size_t copy_amount = | 371 | const std::size_t copy_amount = |
| 326 | std::min(static_cast<std::size_t>(Memory::YUZU_PAGESIZE) - page_offset, remaining_size); | 372 | std::min((next_pages << Memory::YUZU_PAGEBITS) - page_offset, remaining_size); |
| 327 | const auto current_vaddr = | 373 | const auto current_vaddr = |
| 328 | static_cast<u64>((page_index << Memory::YUZU_PAGEBITS) + page_offset); | 374 | static_cast<u64>((page_index << Memory::YUZU_PAGEBITS) + page_offset); |
| 329 | SCOPE_EXIT({ | 375 | SCOPE_EXIT({ |
| 330 | page_index++; | 376 | page_index += next_pages; |
| 331 | page_offset = 0; | 377 | page_offset = 0; |
| 332 | increment(copy_amount); | 378 | increment(copy_amount); |
| 333 | remaining_size -= copy_amount; | 379 | remaining_size -= copy_amount; |
diff --git a/src/core/hle/service/nvdrv/core/container.cpp b/src/core/hle/service/nvdrv/core/container.cpp index ba7eb9e24..4d3a9d696 100644 --- a/src/core/hle/service/nvdrv/core/container.cpp +++ b/src/core/hle/service/nvdrv/core/container.cpp | |||
| @@ -95,6 +95,7 @@ size_t Container::OpenSession(Kernel::KProcess* process) { | |||
| 95 | if (start_region != 0) { | 95 | if (start_region != 0) { |
| 96 | session.mapper = std::make_unique<HeapMapper>(region_start, start_region, region_size, | 96 | session.mapper = std::make_unique<HeapMapper>(region_start, start_region, region_size, |
| 97 | smmu_id, impl->host1x); | 97 | smmu_id, impl->host1x); |
| 98 | smmu.TrackContinuity(start_region, region_start, region_size, smmu_id); | ||
| 98 | session.has_preallocated_area = true; | 99 | session.has_preallocated_area = true; |
| 99 | LOG_CRITICAL(Debug, "Preallocation created!"); | 100 | LOG_CRITICAL(Debug, "Preallocation created!"); |
| 100 | } | 101 | } |
diff --git a/src/core/hle/service/nvdrv/core/nvmap.cpp b/src/core/hle/service/nvdrv/core/nvmap.cpp index 023c070d9..97634b59d 100644 --- a/src/core/hle/service/nvdrv/core/nvmap.cpp +++ b/src/core/hle/service/nvdrv/core/nvmap.cpp | |||
| @@ -221,7 +221,7 @@ DAddr NvMap::PinHandle(NvMap::Handle::Id handle, size_t session_id, bool low_are | |||
| 221 | } | 221 | } |
| 222 | 222 | ||
| 223 | handle_description->d_address = address; | 223 | handle_description->d_address = address; |
| 224 | smmu.Map(address, vaddress, map_size, session->smmu_id); | 224 | smmu.Map(address, vaddress, map_size, session->smmu_id, true); |
| 225 | handle_description->in_heap = false; | 225 | handle_description->in_heap = false; |
| 226 | } | 226 | } |
| 227 | } | 227 | } |