Browse Source

[TEST] Adjustments on AHB

tmp/BEoi4ah1YwU
CamilleLaVey 4 days ago
parent
commit
c81547b295
  1. 29
      src/common/heap_tracker.cpp
  2. 3
      src/common/heap_tracker.h
  3. 62
      src/common/host_memory.cpp
  4. 2
      src/common/host_memory.h

29
src/common/heap_tracker.cpp

@ -31,7 +31,9 @@ s64 GetMaxPermissibleResidentMapCount() {
} // namespace } // namespace
HeapTracker::HeapTracker(Common::HostMemory& buffer) HeapTracker::HeapTracker(Common::HostMemory& buffer)
: m_buffer(buffer), m_max_resident_map_count(GetMaxPermissibleResidentMapCount()) {}
: m_buffer(buffer),
m_has_hardware_buffer_backing(!buffer.BackingHardwareBuffers().empty()),
m_max_resident_map_count(GetMaxPermissibleResidentMapCount()) {}
HeapTracker::~HeapTracker() = default; HeapTracker::~HeapTracker() = default;
void HeapTracker::Map(size_t virtual_offset, size_t host_offset, size_t length, void HeapTracker::Map(size_t virtual_offset, size_t host_offset, size_t length,
@ -85,7 +87,8 @@ void HeapTracker::Unmap(size_t virtual_offset, size_t size, bool is_separate_hea
// If resident, erase from resident map. // If resident, erase from resident map.
if (item->is_resident) { if (item->is_resident) {
ASSERT(--m_resident_map_count >= 0);
m_resident_map_count -= this->HostMapCount(item->paddr, item->size);
ASSERT(m_resident_map_count >= 0);
m_resident_mappings.erase(m_resident_mappings.iterator_to(*item)); m_resident_mappings.erase(m_resident_mappings.iterator_to(*item));
} }
@ -191,7 +194,7 @@ bool HeapTracker::DeferredMapSeparateHeap(size_t virtual_offset) {
// This map is now resident. // This map is now resident.
it->is_resident = true; it->is_resident = true;
m_resident_map_count++;
m_resident_map_count += this->HostMapCount(it->paddr, it->size);
m_resident_mappings.insert(*it); m_resident_mappings.insert(*it);
} }
@ -213,17 +216,17 @@ void HeapTracker::RebuildSeparateHeapAddressSpace() {
// Despite being worse in theory, this has proven to be better in practice than more // Despite being worse in theory, this has proven to be better in practice than more
// regularly dumping a smaller amount, because it significantly reduces average case // regularly dumping a smaller amount, because it significantly reduces average case
// lock contention. // lock contention.
std::size_t const desired_count = (std::min)(m_resident_map_count, m_max_resident_map_count) / 2;
std::size_t const evict_count = m_resident_map_count - desired_count;
s64 const desired_count = (std::min)(m_resident_map_count, m_max_resident_map_count) / 2;
auto it = m_resident_mappings.begin(); auto it = m_resident_mappings.begin();
for (size_t i = 0; i < evict_count && it != m_resident_mappings.end(); i++) {
while (m_resident_map_count > desired_count && it != m_resident_mappings.end()) {
// Unmark and unmap. // Unmark and unmap.
it->is_resident = false; it->is_resident = false;
m_buffer.Unmap(it->vaddr, it->size, false); m_buffer.Unmap(it->vaddr, it->size, false);
// Advance. // Advance.
ASSERT(--m_resident_map_count >= 0);
m_resident_map_count -= this->HostMapCount(it->paddr, it->size);
ASSERT(m_resident_map_count >= 0);
it = m_resident_mappings.erase(it); it = m_resident_mappings.erase(it);
} }
} }
@ -245,6 +248,7 @@ void HeapTracker::SplitHeapMapLocked(VAddr offset) {
// Cache the original values. // Cache the original values.
auto* const left = std::addressof(*it); auto* const left = std::addressof(*it);
const size_t orig_size = left->size; const size_t orig_size = left->size;
const s64 orig_host_map_count = this->HostMapCount(left->paddr, orig_size);
// Adjust the left map. // Adjust the left map.
const size_t left_size = offset - left->vaddr; const size_t left_size = offset - left->vaddr;
@ -266,11 +270,20 @@ void HeapTracker::SplitHeapMapLocked(VAddr offset) {
// If resident, also insert into resident map. // If resident, also insert into resident map.
if (right->is_resident) { if (right->is_resident) {
m_resident_map_count++;
m_resident_map_count += this->HostMapCount(left->paddr, left->size) +
this->HostMapCount(right->paddr, right->size) -
orig_host_map_count;
m_resident_mappings.insert(*right); m_resident_mappings.insert(*right);
} }
} }
s64 HeapTracker::HostMapCount(PAddr paddr, size_t size) const {
if (!m_has_hardware_buffer_backing) {
return size != 0 ? 1 : 0;
}
return static_cast<s64>(m_buffer.BackingMapCount(paddr, size));
}
HeapTracker::AddrTree::iterator HeapTracker::GetNearestHeapMapLocked(VAddr offset) { HeapTracker::AddrTree::iterator HeapTracker::GetNearestHeapMapLocked(VAddr offset) {
const SeparateHeapMap key{ const SeparateHeapMap key{
.vaddr = offset, .vaddr = offset,

3
src/common/heap_tracker.h

@ -85,10 +85,13 @@ private:
AddrTree::iterator GetNearestHeapMapLocked(VAddr offset); AddrTree::iterator GetNearestHeapMapLocked(VAddr offset);
s64 HostMapCount(PAddr paddr, size_t size) const;
void RebuildSeparateHeapAddressSpace(); void RebuildSeparateHeapAddressSpace();
private: private:
Common::HostMemory& m_buffer; Common::HostMemory& m_buffer;
const bool m_has_hardware_buffer_backing;
const s64 m_max_resident_map_count; const s64 m_max_resident_map_count;
std::shared_mutex m_rebuild_lock{}; std::shared_mutex m_rebuild_lock{};

62
src/common/host_memory.cpp

@ -708,18 +708,11 @@ public:
if (budget == 0) { if (budget == 0) {
return false; return false;
} }
const AHardwareBuffer_Desc window_desc = MakeBlobDesc(window_size);
if (AHardwareBuffer_isSupported(&window_desc) == 0) {
return false;
}
if (!ProbeAhbBacking(get_native_handle)) { if (!ProbeAhbBacking(get_native_handle)) {
return false; return false;
} }
const size_t aligned_backing = Common::AlignDown(backing_size, window_size); const size_t aligned_backing = Common::AlignDown(backing_size, window_size);
const size_t region_size = (std::min)(budget, aligned_backing);
const size_t region_base = Common::AlignDown(
(std::min)(preferred_offset, aligned_backing - region_size), window_size);
const size_t num_windows = region_size / window_size;
const size_t max_windows = (std::min)(budget, aligned_backing) / window_size;
std::vector<AHardwareBuffer*> buffers; std::vector<AHardwareBuffer*> buffers;
std::vector<int> buffer_fds; std::vector<int> buffer_fds;
@ -730,27 +723,33 @@ public:
buffers.clear(); buffers.clear();
buffer_fds.clear(); buffer_fds.clear();
}; };
for (size_t i = 0; i < num_windows; ++i) {
for (size_t i = 0; i < max_windows; ++i) {
const AHardwareBuffer_Desc desc = MakeBlobDesc(window_size); const AHardwareBuffer_Desc desc = MakeBlobDesc(window_size);
AHardwareBuffer* buffer{}; AHardwareBuffer* buffer{};
if (AHardwareBuffer_allocate(&desc, &buffer) != 0 || buffer == nullptr) { if (AHardwareBuffer_allocate(&desc, &buffer) != 0 || buffer == nullptr) {
cleanup();
return false;
break;
} }
buffers.push_back(buffer);
const NativeHandle* const handle = get_native_handle(buffer); const NativeHandle* const handle = get_native_handle(buffer);
if (handle == nullptr || handle->numFds < 1) { if (handle == nullptr || handle->numFds < 1) {
cleanup();
return false;
AHardwareBuffer_release(buffer);
break;
} }
const int buffer_fd = handle->data[0]; const int buffer_fd = handle->data[0];
const off_t buffer_len = lseek(buffer_fd, 0, SEEK_END); const off_t buffer_len = lseek(buffer_fd, 0, SEEK_END);
if (buffer_len < static_cast<off_t>(window_size)) { if (buffer_len < static_cast<off_t>(window_size)) {
cleanup();
return false;
AHardwareBuffer_release(buffer);
break;
} }
buffers.push_back(buffer);
buffer_fds.push_back(buffer_fd); buffer_fds.push_back(buffer_fd);
} }
const size_t num_windows = buffers.size();
if (num_windows == 0) {
return false;
}
const size_t region_size = num_windows * window_size;
const size_t region_base = Common::AlignDown(
(std::min)(preferred_offset, aligned_backing - region_size), window_size);
u8* const base = static_cast<u8*>(mmap(nullptr, backing_size, PROT_NONE, u8* const base = static_cast<u8*>(mmap(nullptr, backing_size, PROT_NONE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0)); MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0));
if (base == MAP_FAILED) { if (base == MAP_FAILED) {
@ -818,6 +817,29 @@ public:
} }
} }
size_t BackingMapCount(size_t host_offset, size_t length) const noexcept {
if (length == 0) {
return 0;
}
if (ahb_bytes == 0) {
return 1;
}
size_t count = 0;
while (length > 0) {
size_t chunk = length;
if (host_offset < ahb_base) {
chunk = (std::min)(chunk, ahb_base - host_offset);
} else if (host_offset < ahb_base + ahb_bytes) {
const size_t local = (host_offset - ahb_base) % ahb_window_size;
chunk = (std::min)(chunk, ahb_window_size - local);
}
host_offset += chunk;
length -= chunk;
++count;
}
return count;
}
std::span<AHardwareBuffer* const> AhbWindows() const noexcept { std::span<AHardwareBuffer* const> AhbWindows() const noexcept {
return ahb_windows; return ahb_windows;
} }
@ -1075,6 +1097,14 @@ std::span<AHardwareBuffer* const> HostMemory::BackingHardwareBuffers() const noe
#endif #endif
} }
size_t HostMemory::BackingMapCount(size_t host_offset, size_t length) const noexcept {
#ifdef __ANDROID__
return impl ? impl->BackingMapCount(host_offset, length) : (length != 0 ? 1 : 0);
#else
return length != 0 ? 1 : 0;
#endif
}
size_t HostMemory::BackingHardwareBufferWindowSize() const noexcept { size_t HostMemory::BackingHardwareBufferWindowSize() const noexcept {
#ifdef __ANDROID__ #ifdef __ANDROID__
return impl ? impl->AhbWindowSize() : 0; return impl ? impl->AhbWindowSize() : 0;

2
src/common/host_memory.h

@ -71,6 +71,8 @@ public:
return backing_size; return backing_size;
} }
[[nodiscard]] size_t BackingMapCount(size_t host_offset, size_t length) const noexcept;
[[nodiscard]] std::span<AHardwareBuffer* const> BackingHardwareBuffers() const noexcept; [[nodiscard]] std::span<AHardwareBuffer* const> BackingHardwareBuffers() const noexcept;
[[nodiscard]] size_t BackingHardwareBufferWindowSize() const noexcept; [[nodiscard]] size_t BackingHardwareBufferWindowSize() const noexcept;

Loading…
Cancel
Save