mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-22 05:15:51 +12:00
Move away from PCSX2 fastmem
This commit is contained in:
parent
fbddb02ac3
commit
ede3a93cda
10 changed files with 1058 additions and 1023 deletions
75
third_party/host_memory/include/host_memory/dynamic_library.h
vendored
Normal file
75
third_party/host_memory/include/host_memory/dynamic_library.h
vendored
Normal file
|
@ -0,0 +1,75 @@
|
|||
// SPDX-FileCopyrightText: 2019 Dolphin Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Common {
|
||||
|
||||
/**
|
||||
* Provides a platform-independent interface for loading a dynamic library and retrieving symbols.
|
||||
* The interface maintains an internal reference count to allow one handle to be shared between
|
||||
* multiple users.
|
||||
*/
|
||||
class DynamicLibrary final {
|
||||
public:
|
||||
/// Default constructor, does not load a library.
|
||||
explicit DynamicLibrary();
|
||||
|
||||
/// Automatically loads the specified library. Call IsOpen() to check validity before use.
|
||||
explicit DynamicLibrary(const char* filename);
|
||||
|
||||
/// Initializes the dynamic library with an already opened handle.
|
||||
explicit DynamicLibrary(void* handle_);
|
||||
|
||||
/// Moves the library.
|
||||
DynamicLibrary(DynamicLibrary&&) noexcept;
|
||||
DynamicLibrary& operator=(DynamicLibrary&&) noexcept;
|
||||
|
||||
/// Delete copies, we can't copy a dynamic library.
|
||||
DynamicLibrary(const DynamicLibrary&) = delete;
|
||||
DynamicLibrary& operator=(const DynamicLibrary&) = delete;
|
||||
|
||||
/// Closes the library.
|
||||
~DynamicLibrary();
|
||||
|
||||
/// Returns the specified library name with the platform-specific suffix added.
|
||||
[[nodiscard]] static std::string GetUnprefixedFilename(const char* filename);
|
||||
|
||||
/// Returns the specified library name in platform-specific format.
|
||||
/// Major/minor versions will not be included if set to -1.
|
||||
/// If libname already contains the "lib" prefix, it will not be added again.
|
||||
/// Windows: LIBNAME-MAJOR-MINOR.dll
|
||||
/// Linux: libLIBNAME.so.MAJOR.MINOR
|
||||
/// Mac: libLIBNAME.MAJOR.MINOR.dylib
|
||||
[[nodiscard]] static std::string GetVersionedFilename(const char* libname, int major = -1, int minor = -1);
|
||||
|
||||
/// Returns true if a module is loaded, otherwise false.
|
||||
[[nodiscard]] bool IsOpen() const { return handle != nullptr; }
|
||||
|
||||
/// Loads (or replaces) the handle with the specified library file name.
|
||||
/// Returns true if the library was loaded and can be used.
|
||||
[[nodiscard]] bool Open(const char* filename);
|
||||
|
||||
/// Unloads the library, any function pointers from this library are no longer valid.
|
||||
void Close();
|
||||
|
||||
/// Returns the address of the specified symbol (function or variable) as an untyped pointer.
|
||||
/// If the specified symbol does not exist in this library, nullptr is returned.
|
||||
[[nodiscard]] void* GetSymbolAddress(const char* name) const;
|
||||
|
||||
/// Obtains the address of the specified symbol, automatically casting to the correct type.
|
||||
/// Returns true if the symbol was found and assigned, otherwise false.
|
||||
template <typename T>
|
||||
[[nodiscard]] bool GetSymbol(const char* name, T* ptr) const {
|
||||
*ptr = reinterpret_cast<T>(GetSymbolAddress(name));
|
||||
return *ptr != nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
/// Platform-dependent data type representing a dynamic library handle.
|
||||
void* handle = nullptr;
|
||||
};
|
||||
|
||||
} // namespace Common
|
75
third_party/host_memory/include/host_memory/host_memory.h
vendored
Normal file
75
third_party/host_memory/include/host_memory/host_memory.h
vendored
Normal file
|
@ -0,0 +1,75 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "common/common_funcs.h"
|
||||
#include "host_memory/virtual_buffer.h"
|
||||
#include "helpers.hpp"
|
||||
|
||||
namespace Common {
|
||||
|
||||
enum class MemoryPermission : u32 {
|
||||
Read = 1 << 0,
|
||||
Write = 1 << 1,
|
||||
ReadWrite = Read | Write,
|
||||
Execute = 1 << 2,
|
||||
};
|
||||
DECLARE_ENUM_FLAG_OPERATORS(MemoryPermission)
|
||||
|
||||
/**
|
||||
* A low level linear memory buffer, which supports multiple mappings
|
||||
* Its purpose is to rebuild a given sparse memory layout, including mirrors.
|
||||
*/
|
||||
class HostMemory {
|
||||
public:
|
||||
explicit HostMemory(size_t backing_size_, size_t virtual_size_);
|
||||
~HostMemory();
|
||||
|
||||
/**
|
||||
* Copy constructors. They shall return a copy of the buffer without the mappings.
|
||||
* TODO: Implement them with COW if needed.
|
||||
*/
|
||||
HostMemory(const HostMemory& other) = delete;
|
||||
HostMemory& operator=(const HostMemory& other) = delete;
|
||||
|
||||
/**
|
||||
* Move constructors. They will move the buffer and the mappings to the new object.
|
||||
*/
|
||||
HostMemory(HostMemory&& other) noexcept;
|
||||
HostMemory& operator=(HostMemory&& other) noexcept;
|
||||
|
||||
void Map(size_t virtual_offset, size_t host_offset, size_t length, MemoryPermission perms, bool separate_heap);
|
||||
void Unmap(size_t virtual_offset, size_t length, bool separate_heap);
|
||||
void Protect(size_t virtual_offset, size_t length, MemoryPermission perms);
|
||||
|
||||
void EnableDirectMappedAddress();
|
||||
|
||||
void ClearBackingRegion(size_t physical_offset, size_t length, u32 fill_value);
|
||||
|
||||
[[nodiscard]] u8* BackingBasePointer() noexcept { return backing_base; }
|
||||
[[nodiscard]] const u8* BackingBasePointer() const noexcept { return backing_base; }
|
||||
|
||||
[[nodiscard]] u8* VirtualBasePointer() noexcept { return virtual_base; }
|
||||
[[nodiscard]] const u8* VirtualBasePointer() const noexcept { return virtual_base; }
|
||||
|
||||
bool IsInVirtualRange(void* address) const noexcept { return address >= virtual_base && address < virtual_base + virtual_size; }
|
||||
|
||||
private:
|
||||
size_t backing_size{};
|
||||
size_t virtual_size{};
|
||||
|
||||
// Low level handler for the platform dependent memory routines
|
||||
class Impl;
|
||||
std::unique_ptr<Impl> impl;
|
||||
u8* backing_base{};
|
||||
u8* virtual_base{};
|
||||
size_t virtual_base_offset{};
|
||||
|
||||
// Fallback if fastmem is not supported on this platform
|
||||
std::unique_ptr<Common::VirtualBuffer<u8>> fallback_buffer;
|
||||
};
|
||||
|
||||
} // namespace Common
|
68
third_party/host_memory/include/host_memory/virtual_buffer.h
vendored
Normal file
68
third_party/host_memory/include/host_memory/virtual_buffer.h
vendored
Normal file
|
@ -0,0 +1,68 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "helpers.hpp"
|
||||
#include <utility>
|
||||
|
||||
namespace Common {
|
||||
|
||||
void* AllocateMemoryPages(std::size_t size) noexcept;
|
||||
void FreeMemoryPages(void* base, std::size_t size) noexcept;
|
||||
|
||||
template <typename T>
|
||||
class VirtualBuffer final {
|
||||
public:
|
||||
// TODO: Uncomment this and change Common::PageTable::PageInfo to be trivially constructible
|
||||
// using std::atomic_ref once libc++ has support for it
|
||||
// static_assert(
|
||||
// std::is_trivially_constructible_v<T>,
|
||||
// "T must be trivially constructible, as non-trivial constructors will not be executed "
|
||||
// "with the current allocator");
|
||||
|
||||
constexpr VirtualBuffer() = default;
|
||||
explicit VirtualBuffer(std::size_t count) : alloc_size{count * sizeof(T)} {
|
||||
base_ptr = reinterpret_cast<T*>(AllocateMemoryPages(alloc_size));
|
||||
}
|
||||
|
||||
~VirtualBuffer() noexcept { FreeMemoryPages(base_ptr, alloc_size); }
|
||||
|
||||
VirtualBuffer(const VirtualBuffer&) = delete;
|
||||
VirtualBuffer& operator=(const VirtualBuffer&) = delete;
|
||||
|
||||
VirtualBuffer(VirtualBuffer&& other) noexcept
|
||||
: alloc_size{std::exchange(other.alloc_size, 0)}, base_ptr{std::exchange(other.base_ptr), nullptr} {}
|
||||
|
||||
VirtualBuffer& operator=(VirtualBuffer&& other) noexcept {
|
||||
alloc_size = std::exchange(other.alloc_size, 0);
|
||||
base_ptr = std::exchange(other.base_ptr, nullptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void resize(std::size_t count) {
|
||||
const auto new_size = count * sizeof(T);
|
||||
if (new_size == alloc_size) {
|
||||
return;
|
||||
}
|
||||
|
||||
FreeMemoryPages(base_ptr, alloc_size);
|
||||
|
||||
alloc_size = new_size;
|
||||
base_ptr = reinterpret_cast<T*>(AllocateMemoryPages(alloc_size));
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr const T& operator[](std::size_t index) const { return base_ptr[index]; }
|
||||
[[nodiscard]] constexpr T& operator[](std::size_t index) { return base_ptr[index]; }
|
||||
|
||||
[[nodiscard]] constexpr T* data() { return base_ptr; }
|
||||
[[nodiscard]] constexpr const T* data() const { return base_ptr; }
|
||||
|
||||
[[nodiscard]] constexpr std::size_t size() const { return alloc_size / sizeof(T); }
|
||||
|
||||
private:
|
||||
std::size_t alloc_size{};
|
||||
T* base_ptr{};
|
||||
};
|
||||
|
||||
} // namespace Common
|
Loading…
Add table
Add a link
Reference in a new issue