common/host_memory: Implement a fallback if fastmem fails.
This falls back to the old approach of using a virtual buffer. Windows is untested, but this build should fix support for Windows < 10 v1803. However without fastmem support at all.
This commit is contained in:
parent
f332d4a9b5
commit
7f85abb281
|
@ -449,21 +449,52 @@ private:
|
||||||
int fd{-1}; // memfd file descriptor, -1 is the error value of memfd_create
|
int fd{-1}; // memfd file descriptor, -1 is the error value of memfd_create
|
||||||
};
|
};
|
||||||
|
|
||||||
#else // ^^^ Linux ^^^
|
#else // ^^^ Linux ^^^ vvv Generic vvv
|
||||||
|
|
||||||
#error Please implement the host memory for your platform
|
class HostMemory::Impl {
|
||||||
|
public:
|
||||||
|
explicit Impl(size_t /*backing_size */, size_t /* virtual_size */) {
|
||||||
|
// This is just a place holder.
|
||||||
|
// Please implement fastmem in a propper way on your platform.
|
||||||
|
throw std::bad_alloc{};
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
void Map(size_t virtual_offset, size_t host_offset, size_t length) {}
|
||||||
|
|
||||||
|
void Unmap(size_t virtual_offset, size_t length) {}
|
||||||
|
|
||||||
|
void Protect(size_t virtual_offset, size_t length, bool read, bool write) {}
|
||||||
|
|
||||||
|
u8* backing_base{nullptr};
|
||||||
|
u8* virtual_base{nullptr};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ^^^ Generic ^^^
|
||||||
|
|
||||||
HostMemory::HostMemory(size_t backing_size_, size_t virtual_size_)
|
HostMemory::HostMemory(size_t backing_size_, size_t virtual_size_)
|
||||||
: backing_size(backing_size_),
|
: backing_size(backing_size_), virtual_size(virtual_size_) {
|
||||||
virtual_size(virtual_size_), impl{std::make_unique<HostMemory::Impl>(
|
try {
|
||||||
AlignUp(backing_size, PageAlignment),
|
// Try to allocate a fastmem arena.
|
||||||
AlignUp(virtual_size, PageAlignment) + 3 * HugePageSize)},
|
// The implementation will fail with std::bad_alloc on errors.
|
||||||
backing_base{impl->backing_base}, virtual_base{impl->virtual_base} {
|
impl = std::make_unique<HostMemory::Impl>(AlignUp(backing_size, PageAlignment),
|
||||||
|
AlignUp(virtual_size, PageAlignment) +
|
||||||
|
3 * HugePageSize);
|
||||||
|
backing_base = impl->backing_base;
|
||||||
|
virtual_base = impl->virtual_base;
|
||||||
|
|
||||||
|
if (virtual_base) {
|
||||||
virtual_base += 2 * HugePageSize - 1;
|
virtual_base += 2 * HugePageSize - 1;
|
||||||
virtual_base -= reinterpret_cast<size_t>(virtual_base) & (HugePageSize - 1);
|
virtual_base -= reinterpret_cast<size_t>(virtual_base) & (HugePageSize - 1);
|
||||||
virtual_base_offset = virtual_base - impl->virtual_base;
|
virtual_base_offset = virtual_base - impl->virtual_base;
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (const std::bad_alloc&) {
|
||||||
|
LOG_CRITICAL(HW_Memory,
|
||||||
|
"Fastmem unavailable, falling back to VirtualBuffer for memory allocation");
|
||||||
|
fallback_buffer = std::make_unique<Common::VirtualBuffer<u8>>(backing_size);
|
||||||
|
backing_base = fallback_buffer->data();
|
||||||
|
virtual_base = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HostMemory::~HostMemory() = default;
|
HostMemory::~HostMemory() = default;
|
||||||
|
@ -478,7 +509,7 @@ void HostMemory::Map(size_t virtual_offset, size_t host_offset, size_t length) {
|
||||||
ASSERT(length % PageAlignment == 0);
|
ASSERT(length % PageAlignment == 0);
|
||||||
ASSERT(virtual_offset + length <= virtual_size);
|
ASSERT(virtual_offset + length <= virtual_size);
|
||||||
ASSERT(host_offset + length <= backing_size);
|
ASSERT(host_offset + length <= backing_size);
|
||||||
if (length == 0) {
|
if (length == 0 || !virtual_base || !impl) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
impl->Map(virtual_offset + virtual_base_offset, host_offset, length);
|
impl->Map(virtual_offset + virtual_base_offset, host_offset, length);
|
||||||
|
@ -488,7 +519,7 @@ void HostMemory::Unmap(size_t virtual_offset, size_t length) {
|
||||||
ASSERT(virtual_offset % PageAlignment == 0);
|
ASSERT(virtual_offset % PageAlignment == 0);
|
||||||
ASSERT(length % PageAlignment == 0);
|
ASSERT(length % PageAlignment == 0);
|
||||||
ASSERT(virtual_offset + length <= virtual_size);
|
ASSERT(virtual_offset + length <= virtual_size);
|
||||||
if (length == 0) {
|
if (length == 0 || !virtual_base || !impl) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
impl->Unmap(virtual_offset + virtual_base_offset, length);
|
impl->Unmap(virtual_offset + virtual_base_offset, length);
|
||||||
|
@ -498,7 +529,7 @@ void HostMemory::Protect(size_t virtual_offset, size_t length, bool read, bool w
|
||||||
ASSERT(virtual_offset % PageAlignment == 0);
|
ASSERT(virtual_offset % PageAlignment == 0);
|
||||||
ASSERT(length % PageAlignment == 0);
|
ASSERT(length % PageAlignment == 0);
|
||||||
ASSERT(virtual_offset + length <= virtual_size);
|
ASSERT(virtual_offset + length <= virtual_size);
|
||||||
if (length == 0) {
|
if (length == 0 || !virtual_base || !impl) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
impl->Protect(virtual_offset + virtual_base_offset, length, read, write);
|
impl->Protect(virtual_offset + virtual_base_offset, length, read, write);
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
#include "common/virtual_buffer.h"
|
||||||
|
|
||||||
namespace Common {
|
namespace Common {
|
||||||
|
|
||||||
|
@ -61,6 +62,9 @@ private:
|
||||||
u8* backing_base{};
|
u8* backing_base{};
|
||||||
u8* virtual_base{};
|
u8* virtual_base{};
|
||||||
size_t virtual_base_offset{};
|
size_t virtual_base_offset{};
|
||||||
|
|
||||||
|
// Fallback if fastmem is not supported on this platform
|
||||||
|
std::unique_ptr<Common::VirtualBuffer<u8>> fallback_buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Common
|
} // namespace Common
|
||||||
|
|
Reference in New Issue