diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/common/common_types.h | 1 | ||||
| -rw-r--r-- | src/core/device_memory.h | 16 | ||||
| -rw-r--r-- | src/core/device_memory_manager.h | 97 | ||||
| -rw-r--r-- | src/core/device_memory_manager.inc | 304 | ||||
| -rw-r--r-- | src/video_core/host1x/gpu_device_memory_manager.cpp | 21 | ||||
| -rw-r--r-- | src/video_core/host1x/gpu_device_memory_manager.h | 20 |
6 files changed, 459 insertions, 0 deletions
diff --git a/src/common/common_types.h b/src/common/common_types.h index 0fc225aff..ae04c4d60 100644 --- a/src/common/common_types.h +++ b/src/common/common_types.h | |||
| @@ -45,6 +45,7 @@ using f32 = float; ///< 32-bit floating point | |||
| 45 | using f64 = double; ///< 64-bit floating point | 45 | using f64 = double; ///< 64-bit floating point |
| 46 | 46 | ||
| 47 | using VAddr = u64; ///< Represents a pointer in the userspace virtual address space. | 47 | using VAddr = u64; ///< Represents a pointer in the userspace virtual address space. |
| 48 | using DAddr = u64; ///< Represents a pointer in the device specific virtual address space. | ||
| 48 | using PAddr = u64; ///< Represents a pointer in the ARM11 physical address space. | 49 | using PAddr = u64; ///< Represents a pointer in the ARM11 physical address space. |
| 49 | using GPUVAddr = u64; ///< Represents a pointer in the GPU virtual address space. | 50 | using GPUVAddr = u64; ///< Represents a pointer in the GPU virtual address space. |
| 50 | 51 | ||
diff --git a/src/core/device_memory.h b/src/core/device_memory.h index 13388b73e..11bf0e326 100644 --- a/src/core/device_memory.h +++ b/src/core/device_memory.h | |||
| @@ -32,6 +32,12 @@ public: | |||
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | template <typename T> | 34 | template <typename T> |
| 35 | PAddr GetRawPhysicalAddr(const T* ptr) const { | ||
| 36 | return static_cast<PAddr>(reinterpret_cast<uintptr_t>(ptr) - | ||
| 37 | reinterpret_cast<uintptr_t>(buffer.BackingBasePointer())); | ||
| 38 | } | ||
| 39 | |||
| 40 | template <typename T> | ||
| 35 | T* GetPointer(Common::PhysicalAddress addr) { | 41 | T* GetPointer(Common::PhysicalAddress addr) { |
| 36 | return reinterpret_cast<T*>(buffer.BackingBasePointer() + | 42 | return reinterpret_cast<T*>(buffer.BackingBasePointer() + |
| 37 | (GetInteger(addr) - DramMemoryMap::Base)); | 43 | (GetInteger(addr) - DramMemoryMap::Base)); |
| @@ -43,6 +49,16 @@ public: | |||
| 43 | (GetInteger(addr) - DramMemoryMap::Base)); | 49 | (GetInteger(addr) - DramMemoryMap::Base)); |
| 44 | } | 50 | } |
| 45 | 51 | ||
| 52 | template <typename T> | ||
| 53 | T* GetPointerFromRaw(PAddr addr) { | ||
| 54 | return reinterpret_cast<T*>(buffer.BackingBasePointer() + addr); | ||
| 55 | } | ||
| 56 | |||
| 57 | template <typename T> | ||
| 58 | const T* GetPointerFromRaw(PAddr addr) const { | ||
| 59 | return reinterpret_cast<T*>(buffer.BackingBasePointer() + addr); | ||
| 60 | } | ||
| 61 | |||
| 46 | Common::HostMemory buffer; | 62 | Common::HostMemory buffer; |
| 47 | }; | 63 | }; |
| 48 | 64 | ||
diff --git a/src/core/device_memory_manager.h b/src/core/device_memory_manager.h new file mode 100644 index 000000000..0861b792d --- /dev/null +++ b/src/core/device_memory_manager.h | |||
| @@ -0,0 +1,97 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <deque> | ||
| 7 | #include <memory> | ||
| 8 | |||
| 9 | #include "common/common_types.h" | ||
| 10 | #include "common/virtual_buffer.h" | ||
| 11 | |||
| 12 | namespace Core { | ||
| 13 | |||
| 14 | class DeviceMemory; | ||
| 15 | |||
| 16 | namespace Memory { | ||
| 17 | class Memory; | ||
| 18 | } | ||
| 19 | |||
| 20 | template <typename DTraits> | ||
| 21 | struct DeviceMemoryManagerAllocator; | ||
| 22 | |||
| 23 | template <typename Traits> | ||
| 24 | class DeviceMemoryManager { | ||
| 25 | using DeviceInterface = typename Traits::DeviceInterface; | ||
| 26 | |||
| 27 | public: | ||
| 28 | DeviceMemoryManager(const DeviceMemory& device_memory); | ||
| 29 | ~DeviceMemoryManager(); | ||
| 30 | |||
| 31 | void BindInterface(DeviceInterface* interface); | ||
| 32 | |||
| 33 | DAddr Allocate(size_t size); | ||
| 34 | void AllocateFixed(DAddr start, size_t size); | ||
| 35 | DAddr AllocatePinned(size_t size); | ||
| 36 | void Free(DAddr start, size_t size); | ||
| 37 | |||
| 38 | void Map(DAddr address, VAddr virtual_address, size_t size, size_t p_id); | ||
| 39 | void Unmap(DAddr address, size_t size); | ||
| 40 | |||
| 41 | // Write / Read | ||
| 42 | template <typename T> | ||
| 43 | T* GetPointer(DAddr address); | ||
| 44 | |||
| 45 | template <typename T> | ||
| 46 | const T* GetPointer(DAddr address) const; | ||
| 47 | |||
| 48 | template <typename T> | ||
| 49 | void Write(DAddr address, T value); | ||
| 50 | |||
| 51 | template <typename T> | ||
| 52 | T Read(DAddr address) const; | ||
| 53 | |||
| 54 | void ReadBlock(DAddr address, void* dest_pointer, size_t size); | ||
| 55 | void WriteBlock(DAddr address, void* src_pointer, size_t size); | ||
| 56 | |||
| 57 | size_t RegisterProcess(Memory::Memory* memory); | ||
| 58 | void UnregisterProcess(size_t id); | ||
| 59 | |||
| 60 | private: | ||
| 61 | static constexpr bool supports_pinning = Traits::supports_pinning; | ||
| 62 | static constexpr size_t device_virtual_bits = Traits::device_virtual_bits; | ||
| 63 | static constexpr size_t device_as_size = 1ULL << device_virtual_bits; | ||
| 64 | static constexpr size_t physical_max_bits = 33; | ||
| 65 | static constexpr size_t page_bits = 12; | ||
| 66 | static constexpr u32 physical_address_base = 1U << page_bits; | ||
| 67 | |||
| 68 | template <typename T> | ||
| 69 | T* GetPointerFromRaw(PAddr addr) { | ||
| 70 | return reinterpret_cast<T*>(physical_base + addr); | ||
| 71 | } | ||
| 72 | |||
| 73 | template <typename T> | ||
| 74 | const T* GetPointerFromRaw(PAddr addr) const { | ||
| 75 | return reinterpret_cast<T*>(physical_base + addr); | ||
| 76 | } | ||
| 77 | |||
| 78 | template <typename T> | ||
| 79 | PAddr GetRawPhysicalAddr(const T* ptr) const { | ||
| 80 | return static_cast<PAddr>(reinterpret_cast<uintptr_t>(ptr) - physical_base); | ||
| 81 | } | ||
| 82 | |||
| 83 | void WalkBlock(const DAddr addr, const std::size_t size, auto on_unmapped, auto on_memory, | ||
| 84 | auto increment); | ||
| 85 | |||
| 86 | std::unique_ptr<DeviceMemoryManagerAllocator<Traits>> impl; | ||
| 87 | |||
| 88 | const uintptr_t physical_base; | ||
| 89 | DeviceInterface* interface; | ||
| 90 | Common::VirtualBuffer<u32> compressed_physical_ptr; | ||
| 91 | Common::VirtualBuffer<u32> compressed_device_addr; | ||
| 92 | |||
| 93 | std::deque<size_t> id_pool; | ||
| 94 | std::deque<Memory::Memory*> registered_processes; | ||
| 95 | }; | ||
| 96 | |||
| 97 | } // namespace Core \ No newline at end of file | ||
diff --git a/src/core/device_memory_manager.inc b/src/core/device_memory_manager.inc new file mode 100644 index 000000000..1f52b92d5 --- /dev/null +++ b/src/core/device_memory_manager.inc | |||
| @@ -0,0 +1,304 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include <atomic> | ||
| 5 | #include <memory> | ||
| 6 | #include <type_traits> | ||
| 7 | |||
| 8 | #include "common/address_space.h" | ||
| 9 | #include "common/address_space.inc" | ||
| 10 | #include "common/alignment.h" | ||
| 11 | #include "common/scope_exit.h" | ||
| 12 | #include "core/device_memory.h" | ||
| 13 | #include "core/device_memory_manager.h" | ||
| 14 | #include "core/memory.h" | ||
| 15 | |||
| 16 | namespace Core { | ||
| 17 | |||
| 18 | struct EmptyAllocator { | ||
| 19 | EmptyAllocator([[maybe_unused]] DAddr address) {} | ||
| 20 | }; | ||
| 21 | |||
| 22 | template <typename DTraits> | ||
| 23 | struct DeviceMemoryManagerAllocator { | ||
| 24 | static constexpr bool supports_pinning = DTraits::supports_pinning; | ||
| 25 | static constexpr size_t device_virtual_bits = DTraits::device_virtual_bits; | ||
| 26 | static constexpr size_t pin_bits = 32; | ||
| 27 | static constexpr DAddr first_address = 1ULL << Memory::YUZU_PAGEBITS; | ||
| 28 | static constexpr DAddr max_pin_area = supports_pinning ? 1ULL << pin_bits : first_address; | ||
| 29 | static constexpr DAddr max_device_area = 1ULL << device_virtual_bits; | ||
| 30 | |||
| 31 | DeviceMemoryManagerAllocator() | ||
| 32 | : pin_allocator(first_address), | ||
| 33 | main_allocator(supports_pinning ? 1ULL << pin_bits : first_address) {} | ||
| 34 | |||
| 35 | std::conditional_t<supports_pinning, Common::FlatAllocator<DAddr, 0, pin_bits>, EmptyAllocator> | ||
| 36 | pin_allocator; | ||
| 37 | Common::FlatAllocator<DAddr, 0, device_virtual_bits> main_allocator; | ||
| 38 | |||
| 39 | /// Returns true when vaddr -> vaddr+size is fully contained in the buffer | ||
| 40 | template <bool pin_area> | ||
| 41 | [[nodiscard]] bool IsInBounds(VAddr addr, u64 size) const noexcept { | ||
| 42 | if constexpr (pin_area) { | ||
| 43 | return addr >= 0 && addr + size <= max_pin_area; | ||
| 44 | } else { | ||
| 45 | return addr >= max_pin_area && addr + size <= max_device_area; | ||
| 46 | } | ||
| 47 | } | ||
| 48 | |||
| 49 | DAddr Allocate(size_t size) { | ||
| 50 | return main_allocator.Allocate(size); | ||
| 51 | } | ||
| 52 | |||
| 53 | DAddr AllocatePinned(size_t size) { | ||
| 54 | return pin_allocator.Allocate(size); | ||
| 55 | } | ||
| 56 | |||
| 57 | void DoInRange(DAddr address, size_t size, auto pin_func, auto main_func) { | ||
| 58 | if (IsInBounds<true>(address, size)) { | ||
| 59 | pin_func(address, size); | ||
| 60 | return; | ||
| 61 | } | ||
| 62 | if (IsInBounds<false>(address, size)) { | ||
| 63 | main_func(address, size); | ||
| 64 | return; | ||
| 65 | } | ||
| 66 | DAddr end_size = address + size - max_pin_area; | ||
| 67 | DAddr end_size2 = max_pin_area - address; | ||
| 68 | pin_func(address, end_size2); | ||
| 69 | main_func(max_pin_area, end_size); | ||
| 70 | } | ||
| 71 | |||
| 72 | void AllocateFixed(DAddr b_address, size_t b_size) { | ||
| 73 | if constexpr (supports_pinning) { | ||
| 74 | DoInRange( | ||
| 75 | b_address, b_size, | ||
| 76 | [this](DAddr address, size_t size) { pin_allocator.AllocateFixed(address, size); }, | ||
| 77 | [this](DAddr address, size_t size) { | ||
| 78 | main_allocator.AllocateFixed(address, size); | ||
| 79 | }); | ||
| 80 | } else { | ||
| 81 | main_allocator.AllocateFixed(b_address, b_size); | ||
| 82 | } | ||
| 83 | } | ||
| 84 | |||
| 85 | void Free(DAddr b_address, size_t b_size) { | ||
| 86 | if constexpr (supports_pinning) { | ||
| 87 | DoInRange( | ||
| 88 | b_address, b_size, | ||
| 89 | [this](DAddr address, size_t size) { pin_allocator.Free(address, size); }, | ||
| 90 | [this](DAddr address, size_t size) { main_allocator.Free(address, size); }); | ||
| 91 | } else { | ||
| 92 | main_allocator.Free(b_address, b_size); | ||
| 93 | } | ||
| 94 | } | ||
| 95 | }; | ||
| 96 | |||
| 97 | template <typename Traits> | ||
| 98 | DeviceMemoryManager<Traits>::DeviceMemoryManager(const DeviceMemory& device_memory_) | ||
| 99 | : physical_base{reinterpret_cast<const uintptr_t>(device_memory_.buffer.BackingBasePointer())}, | ||
| 100 | interface{nullptr}, compressed_physical_ptr(device_as_size >> Memory::YUZU_PAGEBITS), | ||
| 101 | compressed_device_addr(1ULL << (physical_max_bits - Memory::YUZU_PAGEBITS)) { | ||
| 102 | impl = std::make_unique<DeviceMemoryManagerAllocator<Traits>>(); | ||
| 103 | } | ||
| 104 | |||
| 105 | template <typename Traits> | ||
| 106 | DeviceMemoryManager<Traits>::~DeviceMemoryManager() = default; | ||
| 107 | |||
| 108 | template <typename Traits> | ||
| 109 | void DeviceMemoryManager<Traits>::BindInterface(DeviceInterface* interface_) { | ||
| 110 | interface = interface_; | ||
| 111 | } | ||
| 112 | |||
| 113 | template <typename Traits> | ||
| 114 | DAddr DeviceMemoryManager<Traits>::Allocate(size_t size) { | ||
| 115 | return impl->Allocate(size); | ||
| 116 | } | ||
| 117 | |||
| 118 | template <typename Traits> | ||
| 119 | void DeviceMemoryManager<Traits>::AllocateFixed(DAddr start, size_t size) { | ||
| 120 | return impl->AllocateFixed(start, size); | ||
| 121 | } | ||
| 122 | |||
| 123 | template <typename Traits> | ||
| 124 | DAddr DeviceMemoryManager<Traits>::AllocatePinned(size_t size) { | ||
| 125 | return impl->AllocatePinned(size); | ||
| 126 | } | ||
| 127 | |||
| 128 | template <typename Traits> | ||
| 129 | void DeviceMemoryManager<Traits>::Free(DAddr start, size_t size) { | ||
| 130 | impl->Free(start, size); | ||
| 131 | } | ||
| 132 | |||
| 133 | template <typename Traits> | ||
| 134 | void DeviceMemoryManager<Traits>::Map(DAddr address, VAddr virtual_address, size_t size, | ||
| 135 | size_t p_id) { | ||
| 136 | Core::Memory::Memory* process_memory = registered_processes[p_id]; | ||
| 137 | size_t start_page_d = address >> Memory::YUZU_PAGEBITS; | ||
| 138 | size_t num_pages = Common::AlignUp(size, Memory::YUZU_PAGESIZE) >> Memory::YUZU_PAGEBITS; | ||
| 139 | std::atomic_thread_fence(std::memory_order_acquire); | ||
| 140 | for (size_t i = 0; i < num_pages; i++) { | ||
| 141 | auto* ptr = process_memory->GetPointer( | ||
| 142 | Common::ProcessAddress(virtual_address + i * Memory::YUZU_PAGESIZE)); | ||
| 143 | if (ptr == nullptr) [[unlikely]] { | ||
| 144 | compressed_physical_ptr[start_page_d + i] = 0; | ||
| 145 | continue; | ||
| 146 | } | ||
| 147 | auto phys_addr = static_cast<u32>(GetRawPhysicalAddr(ptr) >> Memory::YUZU_PAGEBITS) + 1U; | ||
| 148 | compressed_physical_ptr[start_page_d + i] = phys_addr; | ||
| 149 | compressed_device_addr[phys_addr - 1U] = static_cast<u32>(start_page_d + i); | ||
| 150 | } | ||
| 151 | std::atomic_thread_fence(std::memory_order_release); | ||
| 152 | } | ||
| 153 | |||
| 154 | template <typename Traits> | ||
| 155 | void DeviceMemoryManager<Traits>::Unmap(DAddr address, size_t size) { | ||
| 156 | size_t start_page_d = address >> Memory::YUZU_PAGEBITS; | ||
| 157 | size_t num_pages = Common::AlignUp(size, Memory::YUZU_PAGESIZE) >> Memory::YUZU_PAGEBITS; | ||
| 158 | std::atomic_thread_fence(std::memory_order_acquire); | ||
| 159 | for (size_t i = 0; i < num_pages; i++) { | ||
| 160 | auto phys_addr = compressed_physical_ptr[start_page_d + i]; | ||
| 161 | compressed_physical_ptr[start_page_d + i] = 0; | ||
| 162 | if (phys_addr != 0) { | ||
| 163 | compressed_device_addr[phys_addr - 1] = 0; | ||
| 164 | } | ||
| 165 | } | ||
| 166 | std::atomic_thread_fence(std::memory_order_release); | ||
| 167 | } | ||
| 168 | |||
| 169 | template <typename Traits> | ||
| 170 | template <typename T> | ||
| 171 | T* DeviceMemoryManager<Traits>::GetPointer(DAddr address) { | ||
| 172 | const size_t index = address >> Memory::YUZU_PAGEBITS; | ||
| 173 | const size_t offset = address & Memory::YUZU_PAGEMASK; | ||
| 174 | auto phys_addr = compressed_physical_ptr[index]; | ||
| 175 | if (phys_addr == 0) [[unlikely]] { | ||
| 176 | return nullptr; | ||
| 177 | } | ||
| 178 | return GetPointerFromRaw<T>( | ||
| 179 | static_cast<PAddr>(((phys_addr - 1) << Memory::YUZU_PAGEBITS) + offset)); | ||
| 180 | } | ||
| 181 | |||
| 182 | template <typename Traits> | ||
| 183 | template <typename T> | ||
| 184 | const T* DeviceMemoryManager<Traits>::GetPointer(DAddr address) const { | ||
| 185 | const size_t index = address >> Memory::YUZU_PAGEBITS; | ||
| 186 | const size_t offset = address & Memory::YUZU_PAGEMASK; | ||
| 187 | auto phys_addr = compressed_physical_ptr[index]; | ||
| 188 | if (phys_addr == 0) [[unlikely]] { | ||
| 189 | return nullptr; | ||
| 190 | } | ||
| 191 | return GetPointerFromRaw<T>( | ||
| 192 | static_cast<PAddr>(((phys_addr - 1) << Memory::YUZU_PAGEBITS) + offset)); | ||
| 193 | } | ||
| 194 | |||
| 195 | template <typename Traits> | ||
| 196 | template <typename T> | ||
| 197 | void DeviceMemoryManager<Traits>::Write(DAddr address, T value) { | ||
| 198 | T* ptr = GetPointer<T>(address); | ||
| 199 | if (!ptr) [[unlikely]] { | ||
| 200 | return; | ||
| 201 | } | ||
| 202 | std::memcpy(ptr, &value, sizeof(T)); | ||
| 203 | } | ||
| 204 | |||
| 205 | template <typename Traits> | ||
| 206 | template <typename T> | ||
| 207 | T DeviceMemoryManager<Traits>::Read(DAddr address) const { | ||
| 208 | const T* ptr = GetPointer<T>(address); | ||
| 209 | T result{}; | ||
| 210 | if (!ptr) [[unlikely]] { | ||
| 211 | return result; | ||
| 212 | } | ||
| 213 | std::memcpy(&result, ptr, sizeof(T)); | ||
| 214 | return result; | ||
| 215 | } | ||
| 216 | |||
| 217 | template <typename Traits> | ||
| 218 | void DeviceMemoryManager<Traits>::WalkBlock(DAddr addr, std::size_t size, auto on_unmapped, | ||
| 219 | auto on_memory, auto increment) { | ||
| 220 | std::size_t remaining_size = size; | ||
| 221 | std::size_t page_index = addr >> Memory::YUZU_PAGEBITS; | ||
| 222 | std::size_t page_offset = addr & Memory::YUZU_PAGEMASK; | ||
| 223 | |||
| 224 | while (remaining_size) { | ||
| 225 | const std::size_t copy_amount = | ||
| 226 | std::min(static_cast<std::size_t>(Memory::YUZU_PAGESIZE) - page_offset, remaining_size); | ||
| 227 | const auto current_vaddr = | ||
| 228 | static_cast<u64>((page_index << Memory::YUZU_PAGEBITS) + page_offset); | ||
| 229 | SCOPE_EXIT({ | ||
| 230 | page_index++; | ||
| 231 | page_offset = 0; | ||
| 232 | increment(copy_amount); | ||
| 233 | remaining_size -= copy_amount; | ||
| 234 | }); | ||
| 235 | |||
| 236 | auto phys_addr = compressed_physical_ptr[page_index]; | ||
| 237 | if (phys_addr == 0) { | ||
| 238 | on_unmapped(copy_amount, current_vaddr); | ||
| 239 | continue; | ||
| 240 | } | ||
| 241 | auto* mem_ptr = GetPointerFromRaw<u8>( | ||
| 242 | static_cast<PAddr>(((phys_addr - 1) << Memory::YUZU_PAGEBITS) + page_offset)); | ||
| 243 | on_memory(copy_amount, mem_ptr); | ||
| 244 | } | ||
| 245 | } | ||
| 246 | |||
| 247 | template <typename Traits> | ||
| 248 | void DeviceMemoryManager<Traits>::ReadBlock(DAddr address, void* dest_pointer, size_t size) { | ||
| 249 | WalkBlock( | ||
| 250 | address, size, | ||
| 251 | [&](size_t copy_amount, DAddr current_vaddr) { | ||
| 252 | LOG_ERROR( | ||
| 253 | HW_Memory, | ||
| 254 | "Unmapped Device ReadBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})", | ||
| 255 | current_vaddr, address, size); | ||
| 256 | std::memset(dest_pointer, 0, copy_amount); | ||
| 257 | }, | ||
| 258 | [&](size_t copy_amount, const u8* const src_ptr) { | ||
| 259 | std::memcpy(dest_pointer, src_ptr, copy_amount); | ||
| 260 | }, | ||
| 261 | [&](const std::size_t copy_amount) { | ||
| 262 | dest_pointer = static_cast<u8*>(dest_pointer) + copy_amount; | ||
| 263 | }); | ||
| 264 | } | ||
| 265 | |||
| 266 | template <typename Traits> | ||
| 267 | void DeviceMemoryManager<Traits>::WriteBlock(DAddr address, void* src_pointer, size_t size) { | ||
| 268 | WalkBlock( | ||
| 269 | address, size, | ||
| 270 | [&](size_t copy_amount, DAddr current_vaddr) { | ||
| 271 | LOG_ERROR( | ||
| 272 | HW_Memory, | ||
| 273 | "Unmapped Device WriteBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})", | ||
| 274 | current_vaddr, address, size); | ||
| 275 | }, | ||
| 276 | [&](size_t copy_amount, u8* const dst_ptr) { | ||
| 277 | std::memcpy(dst_ptr, src_pointer, copy_amount); | ||
| 278 | }, | ||
| 279 | [&](const std::size_t copy_amount) { | ||
| 280 | src_pointer = static_cast<u8*>(src_pointer) + copy_amount; | ||
| 281 | }); | ||
| 282 | } | ||
| 283 | |||
| 284 | template <typename Traits> | ||
| 285 | size_t DeviceMemoryManager<Traits>::RegisterProcess(Memory::Memory* memory_interface) { | ||
| 286 | size_t new_id; | ||
| 287 | if (!id_pool.empty()) { | ||
| 288 | new_id = id_pool.front(); | ||
| 289 | id_pool.pop_front(); | ||
| 290 | registered_processes[new_id] = memory_interface; | ||
| 291 | } else { | ||
| 292 | registered_processes.emplace_back(memory_interface); | ||
| 293 | new_id = registered_processes.size() - 1U; | ||
| 294 | } | ||
| 295 | return new_id; | ||
| 296 | } | ||
| 297 | |||
| 298 | template <typename Traits> | ||
| 299 | void DeviceMemoryManager<Traits>::UnregisterProcess(size_t id) { | ||
| 300 | registered_processes[id] = nullptr; | ||
| 301 | id_pool.push_front(id); | ||
| 302 | } | ||
| 303 | |||
| 304 | } // namespace Core \ No newline at end of file | ||
diff --git a/src/video_core/host1x/gpu_device_memory_manager.cpp b/src/video_core/host1x/gpu_device_memory_manager.cpp new file mode 100644 index 000000000..2ca445081 --- /dev/null +++ b/src/video_core/host1x/gpu_device_memory_manager.cpp | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/device_memory_manager.inc" | ||
| 5 | #include "video_core/host1x/gpu_device_memory_manager.h" | ||
| 6 | #include "video_core/rasterizer_interface.h" | ||
| 7 | |||
| 8 | template struct Core::DeviceMemoryManagerAllocator<Tegra::MaxwellDeviceTraits>; | ||
| 9 | template class Core::DeviceMemoryManager<Tegra::MaxwellDeviceTraits>; | ||
| 10 | |||
| 11 | template const u8* Tegra::MaxwellDeviceMemoryManager::GetPointer<u8>(DAddr addr) const; | ||
| 12 | template u8* Tegra::MaxwellDeviceMemoryManager::GetPointer<u8>(DAddr addr); | ||
| 13 | |||
| 14 | template u8 Tegra::MaxwellDeviceMemoryManager::Read<u8>(DAddr addr) const; | ||
| 15 | template u16 Tegra::MaxwellDeviceMemoryManager::Read<u16>(DAddr addr) const; | ||
| 16 | template u32 Tegra::MaxwellDeviceMemoryManager::Read<u32>(DAddr addr) const; | ||
| 17 | template u64 Tegra::MaxwellDeviceMemoryManager::Read<u64>(DAddr addr) const; | ||
| 18 | template void Tegra::MaxwellDeviceMemoryManager::Write<u8>(DAddr addr, u8 data); | ||
| 19 | template void Tegra::MaxwellDeviceMemoryManager::Write<u16>(DAddr addr, u16 data); | ||
| 20 | template void Tegra::MaxwellDeviceMemoryManager::Write<u32>(DAddr addr, u32 data); | ||
| 21 | template void Tegra::MaxwellDeviceMemoryManager::Write<u64>(DAddr addr, u64 data); \ No newline at end of file | ||
diff --git a/src/video_core/host1x/gpu_device_memory_manager.h b/src/video_core/host1x/gpu_device_memory_manager.h new file mode 100644 index 000000000..30ad52017 --- /dev/null +++ b/src/video_core/host1x/gpu_device_memory_manager.h | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/device_memory_manager.h" | ||
| 5 | |||
| 6 | namespace VideoCore { | ||
| 7 | class RasterizerInterface; | ||
| 8 | } | ||
| 9 | |||
| 10 | namespace Tegra { | ||
| 11 | |||
| 12 | struct MaxwellDeviceTraits { | ||
| 13 | static constexpr bool supports_pinning = true; | ||
| 14 | static constexpr size_t device_virtual_bits = 34; | ||
| 15 | using DeviceInterface = typename VideoCore::RasterizerInterface; | ||
| 16 | }; | ||
| 17 | |||
| 18 | using MaxwellDeviceMemoryManager = Core::DeviceMemoryManager<MaxwellDeviceTraits>; | ||
| 19 | |||
| 20 | } // namespace Tegra \ No newline at end of file | ||