Browse Source

[core] coalesce tracking entries for GPU

Signed-off-by: lizzie <lizzie@eden-emu.dev>
lizzie 2 days ago
parent
commit
7dd0801a62
  1. 26
      src/core/device_memory_manager.h
  2. 79
      src/core/device_memory_manager.inc

26
src/core/device_memory_manager.h

@ -76,16 +76,16 @@ public:
template <typename Func>
void ApplyOpOnPAddr(PAddr address, Common::ScratchBuffer<u32>& buffer, Func&& operation) {
DAddr subbits = static_cast<DAddr>(address & page_mask);
DAddr subbits = DAddr(address & page_mask);
const u32 base = compressed_device_addr[(address >> page_bits)];
if ((base >> MULTI_FLAG_BITS) == 0) [[likely]] {
const DAddr d_address = (static_cast<DAddr>(base) << page_bits) + subbits;
const DAddr d_address = (DAddr(base) << page_bits) + subbits;
operation(d_address);
return;
}
InnerGatherDeviceAddresses(buffer, address);
for (u32 value : buffer) {
operation((static_cast<DAddr>(value) << page_bits) + subbits);
operation((DAddr(value) << page_bits) + subbits);
}
}
@ -96,12 +96,12 @@ public:
}
PAddr GetPhysicalRawAddressFromDAddr(DAddr address) const {
PAddr subbits = static_cast<PAddr>(address & page_mask);
auto paddr = compressed_physical_ptr[(address >> page_bits)];
PAddr subbits = PAddr(address & page_mask);
auto paddr = tracked_entries[(address >> page_bits)].compressed_physical_ptr;
if (paddr == 0) {
return 0;
}
return (static_cast<PAddr>(paddr - 1) << page_bits) + subbits;
return (PAddr(paddr - 1) << page_bits) + subbits;
}
template <typename T>
@ -172,9 +172,14 @@ private:
const uintptr_t physical_base;
DeviceInterface* device_inter;
Common::VirtualBuffer<u32> compressed_physical_ptr;
struct TrackedEntry {
VAddr cpu_backing_address;
u32 continuity_tracker;
u32 compressed_physical_ptr;
};
Common::VirtualBuffer<u32> compressed_device_addr;
Common::VirtualBuffer<u32> continuity_tracker;
Common::VirtualBuffer<TrackedEntry> tracked_entries;
// Process memory interfaces
@ -189,17 +194,16 @@ private:
static constexpr size_t asid_start_bit = guest_max_as_bits;
std::pair<Asid, VAddr> ExtractCPUBacking(size_t page_index) {
auto content = cpu_backing_address[page_index];
auto content = tracked_entries[page_index].cpu_backing_address;
const VAddr address = content & guest_mask;
const Asid asid{static_cast<size_t>(content >> asid_start_bit)};
return std::make_pair(asid, address);
}
void InsertCPUBacking(size_t page_index, VAddr address, Asid asid) {
cpu_backing_address[page_index] = address | (asid.id << asid_start_bit);
tracked_entries[page_index].cpu_backing_address = address | (asid.id << asid_start_bit);
}
Common::VirtualBuffer<VAddr> cpu_backing_address;
std::array<TranslationEntry, 4> t_slot{};
u32 cache_cursor = 0;
using CounterType = u8;

79
src/core/device_memory_manager.inc

@ -166,29 +166,21 @@ struct DeviceMemoryManagerAllocator {
template <typename Traits>
DeviceMemoryManager<Traits>::DeviceMemoryManager(const DeviceMemory& device_memory_)
: physical_base{reinterpret_cast<const uintptr_t>(device_memory_.buffer.BackingBasePointer())},
device_inter{nullptr}, compressed_physical_ptr(device_as_size >> Memory::YUZU_PAGEBITS),
compressed_device_addr(1ULL << ((Settings::values.memory_layout_mode.GetValue() ==
Settings::MemoryLayout::Memory_4Gb
? physical_min_bits
: physical_max_bits) -
Memory::YUZU_PAGEBITS)),
continuity_tracker(device_as_size >> Memory::YUZU_PAGEBITS),
cpu_backing_address(device_as_size >> Memory::YUZU_PAGEBITS) {
: physical_base{uintptr_t(device_memory_.buffer.BackingBasePointer())}
, device_inter{nullptr}
, compressed_device_addr(1ULL << ((Settings::values.memory_layout_mode.GetValue() == Settings::MemoryLayout::Memory_4Gb ? physical_min_bits : physical_max_bits) - Memory::YUZU_PAGEBITS))
, tracked_entries(device_as_size >> Memory::YUZU_PAGEBITS)
{
impl = std::make_unique<DeviceMemoryManagerAllocator<Traits>>();
cached_pages = std::make_unique<CachedPages>();
const size_t total_virtual = device_as_size >> Memory::YUZU_PAGEBITS;
for (size_t i = 0; i < total_virtual; i++) {
compressed_physical_ptr[i] = 0;
continuity_tracker[i] = 1;
cpu_backing_address[i] = 0;
tracked_entries[i].compressed_physical_ptr = 0;
tracked_entries[i].continuity_tracker = 1;
tracked_entries[i].cpu_backing_address = 0;
}
const size_t total_phys = 1ULL << ((Settings::values.memory_layout_mode.GetValue() ==
Settings::MemoryLayout::Memory_4Gb
? physical_min_bits
: physical_max_bits) -
Memory::YUZU_PAGEBITS);
const size_t total_phys = 1ULL << ((Settings::values.memory_layout_mode.GetValue() == Settings::MemoryLayout::Memory_4Gb ? physical_min_bits : physical_max_bits) - Memory::YUZU_PAGEBITS);
for (size_t i = 0; i < total_phys; i++) {
compressed_device_addr[i] = 0;
}
@ -228,11 +220,11 @@ void DeviceMemoryManager<Traits>::Map(DAddr address, VAddr virtual_address, size
const VAddr new_vaddress = virtual_address + i * Memory::YUZU_PAGESIZE;
auto* ptr = process_memory->GetPointerSilent(Common::ProcessAddress(new_vaddress));
if (ptr == nullptr) [[unlikely]] {
compressed_physical_ptr[start_page_d + i] = 0;
tracked_entries[start_page_d + i].compressed_physical_ptr = 0;
continue;
}
auto phys_addr = static_cast<u32>(GetRawPhysicalAddr(ptr) >> Memory::YUZU_PAGEBITS) + 1U;
compressed_physical_ptr[start_page_d + i] = phys_addr;
tracked_entries[start_page_d + i].compressed_physical_ptr = phys_addr;
InsertCPUBacking(start_page_d + i, new_vaddress, asid);
const u32 base_dev = compressed_device_addr[phys_addr - 1U];
const u32 new_dev = static_cast<u32>(start_page_d + i);
@ -260,9 +252,9 @@ void DeviceMemoryManager<Traits>::Unmap(DAddr address, size_t size) {
device_inter->InvalidateRegion(address, size);
std::scoped_lock lk(mapping_guard);
for (size_t i = 0; i < num_pages; i++) {
auto phys_addr = compressed_physical_ptr[start_page_d + i];
compressed_physical_ptr[start_page_d + i] = 0;
cpu_backing_address[start_page_d + i] = 0;
auto phys_addr = tracked_entries[start_page_d + i].compressed_physical_ptr;
tracked_entries[start_page_d + i].compressed_physical_ptr = 0;
tracked_entries[start_page_d + i].cpu_backing_address = 0;
if (phys_addr != 0) [[likely]] {
const u32 base_dev = compressed_device_addr[phys_addr - 1U];
if ((base_dev >> MULTI_FLAG_BITS) == 0) [[likely]] {
@ -300,14 +292,14 @@ void DeviceMemoryManager<Traits>::TrackContinuityImpl(DAddr address, VAddr virtu
page_count = 1;
}
last_ptr = new_ptr;
continuity_tracker[start_page_d + index] = static_cast<u32>(page_count);
tracked_entries[start_page_d + index].continuity_tracker = static_cast<u32>(page_count);
}
}
template <typename Traits>
u8* DeviceMemoryManager<Traits>::GetSpan(const DAddr src_addr, const std::size_t size) {
size_t page_index = src_addr >> page_bits;
size_t subbits = src_addr & page_mask;
if ((static_cast<size_t>(continuity_tracker[page_index]) << page_bits) >= size + subbits) {
if ((static_cast<size_t>(tracked_entries[page_index].continuity_tracker) << page_bits) >= size + subbits) {
return GetPointer<u8>(src_addr);
}
return nullptr;
@ -317,7 +309,7 @@ template <typename Traits>
const u8* DeviceMemoryManager<Traits>::GetSpan(const DAddr src_addr, const std::size_t size) const {
size_t page_index = src_addr >> page_bits;
size_t subbits = src_addr & page_mask;
if ((static_cast<size_t>(continuity_tracker[page_index]) << page_bits) >= size + subbits) {
if ((static_cast<size_t>(tracked_entries[page_index].continuity_tracker) << page_bits) >= size + subbits) {
return GetPointer<u8>(src_addr);
}
return nullptr;
@ -342,12 +334,10 @@ template <typename T>
T* DeviceMemoryManager<Traits>::GetPointer(DAddr address) {
const size_t index = address >> Memory::YUZU_PAGEBITS;
const size_t offset = address & Memory::YUZU_PAGEMASK;
auto phys_addr = compressed_physical_ptr[index];
if (phys_addr == 0) [[unlikely]] {
auto phys_addr = tracked_entries[index].compressed_physical_ptr;
if (phys_addr == 0) [[unlikely]]
return nullptr;
}
return GetPointerFromRaw<T>((static_cast<PAddr>(phys_addr - 1) << Memory::YUZU_PAGEBITS) +
offset);
return GetPointerFromRaw<T>((PAddr(phys_addr - 1) << Memory::YUZU_PAGEBITS) + offset);
}
template <typename Traits>
@ -355,12 +345,10 @@ template <typename T>
const T* DeviceMemoryManager<Traits>::GetPointer(DAddr address) const {
const size_t index = address >> Memory::YUZU_PAGEBITS;
const size_t offset = address & Memory::YUZU_PAGEMASK;
auto phys_addr = compressed_physical_ptr[index];
if (phys_addr == 0) [[unlikely]] {
auto phys_addr = tracked_entries[index].compressed_physical_ptr;
if (phys_addr == 0)
return nullptr;
}
return GetPointerFromRaw<T>((static_cast<PAddr>(phys_addr - 1) << Memory::YUZU_PAGEBITS) +
offset);
return GetPointerFromRaw<T>((PAddr(phys_addr - 1) << Memory::YUZU_PAGEBITS) + offset);
}
template <typename Traits>
@ -386,18 +374,14 @@ T DeviceMemoryManager<Traits>::Read(DAddr address) const {
}
template <typename Traits>
void DeviceMemoryManager<Traits>::WalkBlock(DAddr addr, std::size_t size, auto on_unmapped,
auto on_memory, auto increment) {
void DeviceMemoryManager<Traits>::WalkBlock(DAddr addr, std::size_t size, auto on_unmapped, auto on_memory, auto increment) {
std::size_t remaining_size = size;
std::size_t page_index = addr >> Memory::YUZU_PAGEBITS;
std::size_t page_offset = addr & Memory::YUZU_PAGEMASK;
while (remaining_size) {
const size_t next_pages = static_cast<std::size_t>(continuity_tracker[page_index]);
const std::size_t copy_amount =
(std::min)((next_pages << Memory::YUZU_PAGEBITS) - page_offset, remaining_size);
const auto current_vaddr =
static_cast<u64>((page_index << Memory::YUZU_PAGEBITS) + page_offset);
const size_t next_pages = std::size_t(tracked_entries[page_index].continuity_tracker);
const std::size_t copy_amount = (std::min)((next_pages << Memory::YUZU_PAGEBITS) - page_offset, remaining_size);
const auto current_vaddr = u64((page_index << Memory::YUZU_PAGEBITS) + page_offset);
SCOPE_EXIT{
page_index += next_pages;
page_offset = 0;
@ -405,13 +389,12 @@ void DeviceMemoryManager<Traits>::WalkBlock(DAddr addr, std::size_t size, auto o
remaining_size -= copy_amount;
};
auto phys_addr = compressed_physical_ptr[page_index];
auto phys_addr = tracked_entries[page_index].compressed_physical_ptr;
if (phys_addr == 0) {
on_unmapped(copy_amount, current_vaddr);
continue;
}
auto* mem_ptr = GetPointerFromRaw<u8>(
(static_cast<PAddr>(phys_addr - 1) << Memory::YUZU_PAGEBITS) + page_offset);
auto* mem_ptr = GetPointerFromRaw<u8>((PAddr(phys_addr - 1) << Memory::YUZU_PAGEBITS) + page_offset);
on_memory(copy_amount, mem_ptr);
}
}
@ -430,7 +413,7 @@ void DeviceMemoryManager<Traits>::ReadBlock(DAddr address, void* dest_pointer, s
}
const std::size_t page_index = address >> Memory::YUZU_PAGEBITS;
const auto phys_addr = compressed_physical_ptr[page_index];
const auto phys_addr = tracked_entries[page_index].compressed_physical_ptr;
if (phys_addr != 0) {
auto* const mem_ptr = GetPointerFromRaw<u8>((PAddr(phys_addr - 1) << Memory::YUZU_PAGEBITS));
t_slot[cache_cursor % t_slot.size()] = TranslationEntry{.guest_page = guest_page, .host_ptr = mem_ptr};
@ -488,7 +471,7 @@ void DeviceMemoryManager<Traits>::ReadBlockUnsafe(DAddr address, void* dest_poin
}
const std::size_t page_index = address >> Memory::YUZU_PAGEBITS;
const auto phys_addr = compressed_physical_ptr[page_index];
const auto phys_addr = tracked_entries[page_index].compressed_physical_ptr;
if (phys_addr != 0) {
auto* const mem_ptr = GetPointerFromRaw<u8>((PAddr(phys_addr - 1) << Memory::YUZU_PAGEBITS));
t_slot[cache_cursor % t_slot.size()] = TranslationEntry{.guest_page = guest_page, .host_ptr = mem_ptr};

Loading…
Cancel
Save