Compare commits
27 commits
7bfa16bf0d
...
b9c3b410a9
Author | SHA1 | Date | |
---|---|---|---|
b9c3b410a9 | |||
b706758cc4 | |||
c5f3be5d56 | |||
bb843e3865 | |||
9a3bfc69ac | |||
00ae926575 | |||
59f1a61768 | |||
aa750d49d7 | |||
8e3b74a19e | |||
37deef0ace | |||
c4e7a5d335 | |||
dc1087c6eb | |||
eb601142e1 | |||
46941150de | |||
32c54ec2bc | |||
c6425cd780 | |||
86705f8901 | |||
0c81b0d6e1 | |||
268fec820e | |||
141b35b00b | |||
18411a0db0 | |||
741db73fe3 | |||
49315bf53e | |||
3ce6ec76f7 | |||
9cc1df496f | |||
b5fdccf08b | |||
87d42cf542 |
9 changed files with 54 additions and 271 deletions
|
@ -107,8 +107,7 @@ add_library(core STATIC
|
|||
file_sys/fssystem/fssystem_nca_header.cpp
|
||||
file_sys/fssystem/fssystem_nca_header.h
|
||||
file_sys/fssystem/fssystem_nca_reader.cpp
|
||||
file_sys/fssystem/fssystem_pooled_buffer.cpp
|
||||
file_sys/fssystem/fssystem_pooled_buffer.h
|
||||
file_sys/fssystem/fssystem_passthrough_storage.h
|
||||
file_sys/fssystem/fssystem_sparse_storage.cpp
|
||||
file_sys/fssystem/fssystem_sparse_storage.h
|
||||
file_sys/fssystem/fssystem_switch_storage.h
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/alignment.h"
|
||||
#include "common/swap.h"
|
||||
#include "core/file_sys/fssystem/fssystem_aes_ctr_storage.h"
|
||||
#include "core/file_sys/fssystem/fssystem_pooled_buffer.h"
|
||||
#include "core/file_sys/fssystem/fssystem_utility.h"
|
||||
|
||||
namespace FileSys {
|
||||
|
@ -76,13 +78,6 @@ size_t AesCtrStorage::Write(const u8* buffer, size_t size, size_t offset) {
|
|||
ASSERT(Common::IsAligned(offset, BlockSize));
|
||||
ASSERT(Common::IsAligned(size, BlockSize));
|
||||
|
||||
// Get a pooled buffer.
|
||||
PooledBuffer pooled_buffer;
|
||||
const bool use_work_buffer = true;
|
||||
if (use_work_buffer) {
|
||||
pooled_buffer.Allocate(size, BlockSize);
|
||||
}
|
||||
|
||||
// Setup the counter.
|
||||
std::array<u8, IvSize> ctr;
|
||||
std::memcpy(ctr.data(), m_iv.data(), IvSize);
|
||||
|
@ -91,25 +86,20 @@ size_t AesCtrStorage::Write(const u8* buffer, size_t size, size_t offset) {
|
|||
// Loop until all data is written.
|
||||
size_t remaining = size;
|
||||
s64 cur_offset = 0;
|
||||
|
||||
// Get a pooled buffer.
|
||||
std::vector<char> pooled_buffer(BlockSize);
|
||||
while (remaining > 0) {
|
||||
// Determine data we're writing and where.
|
||||
const size_t write_size =
|
||||
use_work_buffer ? (std::min)(pooled_buffer.GetSize(), remaining) : remaining;
|
||||
|
||||
void* write_buf;
|
||||
if (use_work_buffer) {
|
||||
write_buf = pooled_buffer.GetBuffer();
|
||||
} else {
|
||||
write_buf = const_cast<u8*>(buffer);
|
||||
}
|
||||
const size_t write_size = std::min(pooled_buffer.size(), remaining);
|
||||
u8* write_buf = reinterpret_cast<u8*>(pooled_buffer.data());
|
||||
|
||||
// Encrypt the data.
|
||||
m_cipher->SetIV(ctr);
|
||||
m_cipher->Transcode(buffer, write_size, reinterpret_cast<u8*>(write_buf),
|
||||
Core::Crypto::Op::Encrypt);
|
||||
m_cipher->Transcode(buffer, write_size, write_buf, Core::Crypto::Op::Encrypt);
|
||||
|
||||
// Write the encrypted data.
|
||||
m_base_storage->Write(reinterpret_cast<u8*>(write_buf), write_size, offset + cur_offset);
|
||||
m_base_storage->Write(write_buf, write_size, offset + cur_offset);
|
||||
|
||||
// Advance.
|
||||
cur_offset += write_size;
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/alignment.h"
|
||||
#include "common/swap.h"
|
||||
#include "core/file_sys/errors.h"
|
||||
#include "core/file_sys/fssystem/fssystem_aes_xts_storage.h"
|
||||
#include "core/file_sys/fssystem/fssystem_pooled_buffer.h"
|
||||
#include "core/file_sys/fssystem/fssystem_utility.h"
|
||||
|
||||
namespace FileSys {
|
||||
|
@ -69,17 +70,14 @@ size_t AesXtsStorage::Read(u8* buffer, size_t size, size_t offset) const {
|
|||
|
||||
// Decrypt into a pooled buffer.
|
||||
{
|
||||
PooledBuffer tmp_buf(m_block_size, m_block_size);
|
||||
ASSERT(tmp_buf.GetSize() >= m_block_size);
|
||||
|
||||
std::memset(tmp_buf.GetBuffer(), 0, skip_size);
|
||||
std::memcpy(tmp_buf.GetBuffer() + skip_size, buffer, data_size);
|
||||
std::vector<char> tmp_buf(m_block_size, 0);
|
||||
std::memcpy(tmp_buf.data() + skip_size, buffer, data_size);
|
||||
|
||||
m_cipher->SetIV(ctr);
|
||||
m_cipher->Transcode(tmp_buf.GetBuffer(), m_block_size, tmp_buf.GetBuffer(),
|
||||
m_cipher->Transcode(tmp_buf.data(), m_block_size, tmp_buf.data(),
|
||||
Core::Crypto::Op::Decrypt);
|
||||
|
||||
std::memcpy(buffer, tmp_buf.GetBuffer() + skip_size, data_size);
|
||||
std::memcpy(buffer, tmp_buf.data() + skip_size, data_size);
|
||||
}
|
||||
|
||||
AddCounter(ctr.data(), IvSize, 1);
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/alignment.h"
|
||||
#include "core/file_sys/errors.h"
|
||||
#include "core/file_sys/fssystem/fs_i_storage.h"
|
||||
#include "core/file_sys/fssystem/fssystem_alignment_matching_storage_impl.h"
|
||||
#include "core/file_sys/fssystem/fssystem_pooled_buffer.h"
|
||||
|
||||
namespace FileSys {
|
||||
|
||||
|
@ -89,10 +90,11 @@ private:
|
|||
VirtualFile m_base_storage;
|
||||
s64 m_base_storage_size;
|
||||
size_t m_data_align;
|
||||
mutable std::vector<char> work_buffer;
|
||||
|
||||
public:
|
||||
explicit AlignmentMatchingStoragePooledBuffer(VirtualFile bs, size_t da)
|
||||
: m_base_storage(std::move(bs)), m_data_align(da) {
|
||||
: m_base_storage(std::move(bs)), m_data_align(da), work_buffer(da) {
|
||||
ASSERT(Common::IsPowerOfTwo(da));
|
||||
}
|
||||
|
||||
|
@ -104,16 +106,10 @@ public:
|
|||
|
||||
// Validate arguments.
|
||||
ASSERT(buffer != nullptr);
|
||||
|
||||
s64 bs_size = this->GetSize();
|
||||
ASSERT(R_SUCCEEDED(IStorage::CheckAccessRange(offset, size, bs_size)));
|
||||
|
||||
// Allocate a pooled buffer.
|
||||
PooledBuffer pooled_buffer;
|
||||
pooled_buffer.AllocateParticularlyLarge(m_data_align, m_data_align);
|
||||
|
||||
return AlignmentMatchingStorageImpl::Read(m_base_storage, pooled_buffer.GetBuffer(),
|
||||
pooled_buffer.GetSize(), m_data_align,
|
||||
return AlignmentMatchingStorageImpl::Read(m_base_storage, work_buffer.data(),
|
||||
work_buffer.size(), m_data_align,
|
||||
BufferAlign, offset, buffer, size);
|
||||
}
|
||||
|
||||
|
@ -125,16 +121,10 @@ public:
|
|||
|
||||
// Validate arguments.
|
||||
ASSERT(buffer != nullptr);
|
||||
|
||||
s64 bs_size = this->GetSize();
|
||||
ASSERT(R_SUCCEEDED(IStorage::CheckAccessRange(offset, size, bs_size)));
|
||||
|
||||
// Allocate a pooled buffer.
|
||||
PooledBuffer pooled_buffer;
|
||||
pooled_buffer.AllocateParticularlyLarge(m_data_align, m_data_align);
|
||||
|
||||
return AlignmentMatchingStorageImpl::Write(m_base_storage, pooled_buffer.GetBuffer(),
|
||||
pooled_buffer.GetSize(), m_data_align,
|
||||
return AlignmentMatchingStorageImpl::Write(m_base_storage, work_buffer.data(),
|
||||
work_buffer.size(), m_data_align,
|
||||
BufferAlign, offset, buffer, size);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
#include "core/file_sys/errors.h"
|
||||
#include "core/file_sys/fssystem/fssystem_bucket_tree.h"
|
||||
#include "core/file_sys/fssystem/fssystem_bucket_tree_utils.h"
|
||||
#include "core/file_sys/fssystem/fssystem_pooled_buffer.h"
|
||||
|
||||
namespace FileSys {
|
||||
|
||||
|
@ -465,16 +464,8 @@ Result BucketTree::Visitor::Find(s64 virtual_address) {
|
|||
}
|
||||
|
||||
Result BucketTree::Visitor::FindEntrySet(s32* out_index, s64 virtual_address, s32 node_index) {
|
||||
const auto node_size = m_tree->m_node_size;
|
||||
|
||||
PooledBuffer pool(node_size, 1);
|
||||
if (node_size <= pool.GetSize()) {
|
||||
R_RETURN(
|
||||
this->FindEntrySetWithBuffer(out_index, virtual_address, node_index, pool.GetBuffer()));
|
||||
} else {
|
||||
pool.Deallocate();
|
||||
R_RETURN(this->FindEntrySetWithoutBuffer(out_index, virtual_address, node_index));
|
||||
}
|
||||
std::vector<char> pool(m_tree->m_node_size);
|
||||
R_RETURN(FindEntrySetWithBuffer(out_index, virtual_address, node_index, pool.data()));
|
||||
}
|
||||
|
||||
Result BucketTree::Visitor::FindEntrySetWithBuffer(s32* out_index, s64 virtual_address,
|
||||
|
@ -525,15 +516,8 @@ Result BucketTree::Visitor::FindEntrySetWithoutBuffer(s32* out_index, s64 virtua
|
|||
}
|
||||
|
||||
Result BucketTree::Visitor::FindEntry(s64 virtual_address, s32 entry_set_index) {
|
||||
const auto entry_set_size = m_tree->m_node_size;
|
||||
|
||||
PooledBuffer pool(entry_set_size, 1);
|
||||
if (entry_set_size <= pool.GetSize()) {
|
||||
R_RETURN(this->FindEntryWithBuffer(virtual_address, entry_set_index, pool.GetBuffer()));
|
||||
} else {
|
||||
pool.Deallocate();
|
||||
R_RETURN(this->FindEntryWithoutBuffer(virtual_address, entry_set_index));
|
||||
}
|
||||
std::vector<char> pool(m_tree->m_node_size);
|
||||
R_RETURN(FindEntryWithBuffer(virtual_address, entry_set_index, pool.data()));
|
||||
}
|
||||
|
||||
Result BucketTree::Visitor::FindEntryWithBuffer(s64 virtual_address, s32 entry_set_index,
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
|
@ -6,7 +9,6 @@
|
|||
#include "core/file_sys/errors.h"
|
||||
#include "core/file_sys/fssystem/fssystem_bucket_tree.h"
|
||||
#include "core/file_sys/fssystem/fssystem_bucket_tree_utils.h"
|
||||
#include "core/file_sys/fssystem/fssystem_pooled_buffer.h"
|
||||
|
||||
namespace FileSys {
|
||||
|
||||
|
@ -35,23 +37,19 @@ Result BucketTree::ScanContinuousReading(ContinuousReadingInfo* out_info,
|
|||
R_UNLESS(entry.GetVirtualOffset() <= cur_offset, ResultOutOfRange);
|
||||
|
||||
// Create a pooled buffer for our scan.
|
||||
PooledBuffer pool(m_node_size, 1);
|
||||
char* buffer = nullptr;
|
||||
|
||||
std::vector<char> pool(m_node_size);
|
||||
s64 entry_storage_size = m_entry_storage->GetSize();
|
||||
|
||||
// Read the node.
|
||||
if (m_node_size <= pool.GetSize()) {
|
||||
buffer = pool.GetBuffer();
|
||||
const auto ofs = param.entry_set.index * static_cast<s64>(m_node_size);
|
||||
R_UNLESS(m_node_size + ofs <= static_cast<size_t>(entry_storage_size),
|
||||
ResultInvalidBucketTreeNodeEntryCount);
|
||||
u8* buffer = reinterpret_cast<u8*>(pool.data());
|
||||
const auto ofs = param.entry_set.index * s64(m_node_size);
|
||||
R_UNLESS(m_node_size + ofs <= size_t(entry_storage_size),
|
||||
ResultInvalidBucketTreeNodeEntryCount);
|
||||
|
||||
m_entry_storage->Read(reinterpret_cast<u8*>(buffer), m_node_size, ofs);
|
||||
}
|
||||
m_entry_storage->Read(buffer, m_node_size, ofs);
|
||||
|
||||
// Calculate extents.
|
||||
const auto end_offset = cur_offset + static_cast<s64>(param.size);
|
||||
const auto end_offset = cur_offset + s64(param.size);
|
||||
s64 phys_offset = entry.GetPhysicalOffset();
|
||||
|
||||
// Start merge tracking.
|
||||
|
@ -76,14 +74,8 @@ Result BucketTree::ScanContinuousReading(ContinuousReadingInfo* out_info,
|
|||
s64 next_entry_offset;
|
||||
|
||||
if (entry_index + 1 < entry_count) {
|
||||
if (buffer != nullptr) {
|
||||
const auto ofs = impl::GetBucketTreeEntryOffset(0, m_entry_size, entry_index + 1);
|
||||
std::memcpy(std::addressof(next_entry), buffer + ofs, m_entry_size);
|
||||
} else {
|
||||
const auto ofs = impl::GetBucketTreeEntryOffset(param.entry_set.index, m_node_size,
|
||||
m_entry_size, entry_index + 1);
|
||||
m_entry_storage->ReadObject(std::addressof(next_entry), ofs);
|
||||
}
|
||||
const auto offset = impl::GetBucketTreeEntryOffset(0, m_entry_size, entry_index + 1);
|
||||
std::memcpy(std::addressof(next_entry), buffer + offset, m_entry_size);
|
||||
|
||||
next_entry_offset = next_entry.GetVirtualOffset();
|
||||
R_UNLESS(param.offsets.IsInclude(next_entry_offset), ResultInvalidIndirectEntryOffset);
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
|
@ -9,8 +12,6 @@
|
|||
#include "core/file_sys/fssystem/fs_i_storage.h"
|
||||
#include "core/file_sys/fssystem/fssystem_bucket_tree.h"
|
||||
#include "core/file_sys/fssystem/fssystem_compression_common.h"
|
||||
#include "core/file_sys/fssystem/fssystem_pooled_buffer.h"
|
||||
#include "core/file_sys/vfs/vfs.h"
|
||||
|
||||
namespace FileSys {
|
||||
|
||||
|
@ -317,23 +318,11 @@ private:
|
|||
R_SUCCEED_IF(entry_count == 0);
|
||||
|
||||
// Get the remaining size in a convenient form.
|
||||
const size_t total_required_size =
|
||||
static_cast<size_t>(required_access_physical_size);
|
||||
const size_t total_required_size = size_t(required_access_physical_size);
|
||||
|
||||
// Perform the read based on whether we need to allocate a buffer.
|
||||
if (will_allocate_pooled_buffer) {
|
||||
// Allocate a pooled buffer.
|
||||
PooledBuffer pooled_buffer;
|
||||
if (pooled_buffer.GetAllocatableSizeMax() >= total_required_size) {
|
||||
pooled_buffer.Allocate(total_required_size, m_block_size_max);
|
||||
} else {
|
||||
pooled_buffer.AllocateParticularlyLarge(
|
||||
std::min<size_t>(
|
||||
total_required_size,
|
||||
PooledBuffer::GetAllocatableParticularlyLargeSizeMax()),
|
||||
m_block_size_max);
|
||||
}
|
||||
|
||||
std::vector<char> pooled_buffer(std::max(m_block_size_max, total_required_size));
|
||||
// Read each of the entries.
|
||||
for (s32 entry_idx = 0; entry_idx < entry_count; ++entry_idx) {
|
||||
// Determine the current read size.
|
||||
|
@ -342,13 +331,13 @@ private:
|
|||
if (const size_t target_entry_size =
|
||||
static_cast<size_t>(entries[entry_idx].physical_size) +
|
||||
static_cast<size_t>(entries[entry_idx].gap_from_prev);
|
||||
target_entry_size <= pooled_buffer.GetSize()) {
|
||||
target_entry_size <= pooled_buffer.size()) {
|
||||
// We'll be using the pooled buffer.
|
||||
will_use_pooled_buffer = true;
|
||||
|
||||
// Determine how much we can read.
|
||||
const size_t max_size = std::min<size_t>(
|
||||
required_access_physical_size, pooled_buffer.GetSize());
|
||||
required_access_physical_size, pooled_buffer.size());
|
||||
|
||||
size_t read_size = 0;
|
||||
for (auto n = entry_idx; n < entry_count; ++n) {
|
||||
|
@ -376,7 +365,7 @@ private:
|
|||
// Perform the read based on whether or not we'll use the pooled buffer.
|
||||
if (will_use_pooled_buffer) {
|
||||
// Read the compressed data into the pooled buffer.
|
||||
auto* const buffer = pooled_buffer.GetBuffer();
|
||||
auto* const buffer = pooled_buffer.data();
|
||||
m_data_storage->Read(reinterpret_cast<u8*>(buffer), cur_read_size,
|
||||
required_access_physical_offset);
|
||||
|
||||
|
@ -863,11 +852,9 @@ private:
|
|||
static_cast<size_t>(unaligned_range->virtual_size));
|
||||
|
||||
// Get a pooled buffer for our read.
|
||||
PooledBuffer pooled_buffer;
|
||||
pooled_buffer.Allocate(size_buffer_required, size_buffer_required);
|
||||
|
||||
std::vector<char> pooled_buffer(size_buffer_required);
|
||||
// Perform read.
|
||||
Result rc = read_impl(pooled_buffer.GetBuffer(), size_buffer_required);
|
||||
Result rc = read_impl(pooled_buffer.data(), size_buffer_required);
|
||||
if (R_FAILED(rc)) {
|
||||
R_THROW(rc);
|
||||
}
|
||||
|
@ -876,8 +863,7 @@ private:
|
|||
const size_t skip_size = cur_offset - unaligned_range->virtual_offset;
|
||||
const size_t copy_size = std::min<size_t>(
|
||||
cur_size, unaligned_range->GetEndVirtualOffset() - cur_offset);
|
||||
|
||||
std::memcpy(cur_dst, pooled_buffer.GetBuffer() + skip_size, copy_size);
|
||||
std::memcpy(cur_dst, pooled_buffer.data() + skip_size, copy_size);
|
||||
|
||||
// Advance.
|
||||
cur_dst += copy_size;
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/alignment.h"
|
||||
#include "core/file_sys/fssystem/fssystem_pooled_buffer.h"
|
||||
|
||||
namespace FileSys {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr size_t HeapBlockSize = BufferPoolAlignment;
|
||||
static_assert(HeapBlockSize == 4_KiB);
|
||||
|
||||
// A heap block is 4KiB. An order is a power of two.
|
||||
// This gives blocks of the order 32KiB, 512KiB, 4MiB.
|
||||
constexpr s32 HeapOrderMax = 7;
|
||||
constexpr s32 HeapOrderMaxForLarge = HeapOrderMax + 3;
|
||||
|
||||
constexpr size_t HeapAllocatableSizeMax = HeapBlockSize * (static_cast<size_t>(1) << HeapOrderMax);
|
||||
constexpr size_t HeapAllocatableSizeMaxForLarge =
|
||||
HeapBlockSize * (static_cast<size_t>(1) << HeapOrderMaxForLarge);
|
||||
|
||||
} // namespace
|
||||
|
||||
size_t PooledBuffer::GetAllocatableSizeMaxCore(bool large) {
|
||||
return large ? HeapAllocatableSizeMaxForLarge : HeapAllocatableSizeMax;
|
||||
}
|
||||
|
||||
void PooledBuffer::AllocateCore(size_t ideal_size, size_t required_size, bool large) {
|
||||
// Ensure preconditions.
|
||||
ASSERT(m_buffer == nullptr);
|
||||
|
||||
// Check that we can allocate this size.
|
||||
ASSERT(required_size <= GetAllocatableSizeMaxCore(large));
|
||||
|
||||
const size_t target_size =
|
||||
(std::min)((std::max)(ideal_size, required_size), GetAllocatableSizeMaxCore(large));
|
||||
|
||||
// Dummy implementation for allocate.
|
||||
if (target_size > 0) {
|
||||
m_buffer =
|
||||
reinterpret_cast<char*>(::operator new(target_size, std::align_val_t{HeapBlockSize}));
|
||||
m_size = target_size;
|
||||
|
||||
// Ensure postconditions.
|
||||
ASSERT(m_buffer != nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void PooledBuffer::Shrink(size_t ideal_size) {
|
||||
ASSERT(ideal_size <= GetAllocatableSizeMaxCore(true));
|
||||
|
||||
// Shrinking to zero means that we have no buffer.
|
||||
if (ideal_size == 0) {
|
||||
::operator delete(m_buffer, std::align_val_t{HeapBlockSize});
|
||||
m_buffer = nullptr;
|
||||
m_size = ideal_size;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace FileSys
|
|
@ -1,95 +0,0 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/common_funcs.h"
|
||||
#include "common/common_types.h"
|
||||
#include "common/literals.h"
|
||||
#include "core/hle/result.h"
|
||||
|
||||
namespace FileSys {
|
||||
|
||||
using namespace Common::Literals;
|
||||
|
||||
constexpr inline size_t BufferPoolAlignment = 4_KiB;
|
||||
constexpr inline size_t BufferPoolWorkSize = 320;
|
||||
|
||||
class PooledBuffer {
|
||||
YUZU_NON_COPYABLE(PooledBuffer);
|
||||
|
||||
public:
|
||||
// Constructor/Destructor.
|
||||
constexpr PooledBuffer() : m_buffer(), m_size() {}
|
||||
|
||||
PooledBuffer(size_t ideal_size, size_t required_size) : m_buffer(), m_size() {
|
||||
this->Allocate(ideal_size, required_size);
|
||||
}
|
||||
|
||||
~PooledBuffer() {
|
||||
this->Deallocate();
|
||||
}
|
||||
|
||||
// Move and assignment.
|
||||
explicit PooledBuffer(PooledBuffer&& rhs) : m_buffer(rhs.m_buffer), m_size(rhs.m_size) {
|
||||
rhs.m_buffer = nullptr;
|
||||
rhs.m_size = 0;
|
||||
}
|
||||
|
||||
PooledBuffer& operator=(PooledBuffer&& rhs) {
|
||||
PooledBuffer(std::move(rhs)).Swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Allocation API.
|
||||
void Allocate(size_t ideal_size, size_t required_size) {
|
||||
return this->AllocateCore(ideal_size, required_size, false);
|
||||
}
|
||||
|
||||
void AllocateParticularlyLarge(size_t ideal_size, size_t required_size) {
|
||||
return this->AllocateCore(ideal_size, required_size, true);
|
||||
}
|
||||
|
||||
void Shrink(size_t ideal_size);
|
||||
|
||||
void Deallocate() {
|
||||
// Shrink the buffer to empty.
|
||||
this->Shrink(0);
|
||||
ASSERT(m_buffer == nullptr);
|
||||
}
|
||||
|
||||
char* GetBuffer() const {
|
||||
ASSERT(m_buffer != nullptr);
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
size_t GetSize() const {
|
||||
ASSERT(m_buffer != nullptr);
|
||||
return m_size;
|
||||
}
|
||||
|
||||
public:
|
||||
static size_t GetAllocatableSizeMax() {
|
||||
return GetAllocatableSizeMaxCore(false);
|
||||
}
|
||||
static size_t GetAllocatableParticularlyLargeSizeMax() {
|
||||
return GetAllocatableSizeMaxCore(true);
|
||||
}
|
||||
|
||||
private:
|
||||
static size_t GetAllocatableSizeMaxCore(bool large);
|
||||
|
||||
private:
|
||||
void Swap(PooledBuffer& rhs) {
|
||||
std::swap(m_buffer, rhs.m_buffer);
|
||||
std::swap(m_size, rhs.m_size);
|
||||
}
|
||||
|
||||
void AllocateCore(size_t ideal_size, size_t required_size, bool large);
|
||||
|
||||
private:
|
||||
char* m_buffer;
|
||||
size_t m_size;
|
||||
};
|
||||
|
||||
} // namespace FileSys
|
Loading…
Add table
Add a link
Reference in a new issue