rsx: Improve handling of aligned memory
This commit is contained in:
@@ -0,0 +1,88 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
namespace rsx
|
||||||
|
{
|
||||||
|
namespace aligned_allocator
|
||||||
|
{
|
||||||
|
template <size_t Align>
|
||||||
|
requires (Align != 0) && ((Align& (Align - 1)) == 0)
|
||||||
|
size_t align_up(size_t size)
|
||||||
|
{
|
||||||
|
return (size + (Align - 1)) & ~(Align - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <size_t Align>
|
||||||
|
requires (Align != 0) && ((Align& (Align - 1)) == 0)
|
||||||
|
void* malloc(size_t size)
|
||||||
|
{
|
||||||
|
#if defined(_WIN32)
|
||||||
|
return _aligned_malloc(size, Align);
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
constexpr size_t NativeAlign = std::max(Align, sizeof(void*));
|
||||||
|
return std::aligned_alloc(NativeAlign, align_up<NativeAlign>(size));
|
||||||
|
#else
|
||||||
|
return std::aligned_alloc(Align, align_up<Align>(size));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
template <size_t Align>
|
||||||
|
requires (Align != 0) && ((Align& (Align - 1)) == 0)
|
||||||
|
void* realloc(void* prev_ptr, [[maybe_unused]] size_t prev_size, size_t new_size)
|
||||||
|
{
|
||||||
|
if (align_up<Align>(prev_size) >= new_size)
|
||||||
|
{
|
||||||
|
return prev_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure(reinterpret_cast<usz>(prev_ptr) % Align == 0, "Pointer not aligned to Align");
|
||||||
|
#if defined(_WIN32)
|
||||||
|
return _aligned_realloc(prev_ptr, new_size, Align);
|
||||||
|
#else
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
constexpr size_t NativeAlign = std::max(Align, sizeof(void*));
|
||||||
|
void* ret = std::aligned_alloc(NativeAlign, align_up<NativeAlign>(new_size));
|
||||||
|
#else
|
||||||
|
void* ret = std::aligned_alloc(Align, align_up<Align>(new_size));
|
||||||
|
#endif
|
||||||
|
std::memcpy(ret, prev_ptr, std::min(prev_size, new_size));
|
||||||
|
std::free(prev_ptr);
|
||||||
|
return ret;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void free(void* ptr)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
_aligned_free(ptr);
|
||||||
|
#else
|
||||||
|
std::free(ptr);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, int Alignment = sizeof(T)>
|
||||||
|
class aligned_pointer_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
aligned_pointer_t(size_t size)
|
||||||
|
{
|
||||||
|
m_ptr = aligned_allocator::malloc<Alignment>(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~aligned_pointer_t()
|
||||||
|
{
|
||||||
|
aligned_allocator::free(m_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
T* data() const { return m_ptr; }
|
||||||
|
|
||||||
|
T& operator * () const { return *m_ptr; }
|
||||||
|
|
||||||
|
T* operator -> () const { return m_ptr; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
T* m_ptr;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -81,10 +81,17 @@ namespace rsx
|
|||||||
std::span<T> as_span() const
|
std::span<T> as_span() const
|
||||||
{
|
{
|
||||||
auto bytes = data();
|
auto bytes = data();
|
||||||
ensure((reinterpret_cast<uintptr_t>(bytes) & (sizeof(T) - 1)) == 0, "IO buffer span cast requires naturally aligned pointers.");
|
ensure(is_naturally_aligned<T>(), "IO buffer span cast requires naturally aligned pointers.");
|
||||||
return { utils::bless<T>(bytes), m_size / sizeof(T) };
|
return { utils::bless<T>(bytes), m_size / sizeof(T) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
bool is_naturally_aligned() const
|
||||||
|
{
|
||||||
|
return ((reinterpret_cast<uintptr_t>(data()) & (alignof(T) - 1)) == 0) &&
|
||||||
|
(m_size % sizeof(T)) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool empty() const
|
bool empty() const
|
||||||
{
|
{
|
||||||
return m_size == 0;
|
return m_size == 0;
|
||||||
|
|||||||
@@ -3,70 +3,12 @@
|
|||||||
#include <util/types.hpp>
|
#include <util/types.hpp>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstdlib>
|
|
||||||
|
|
||||||
|
#include "aligned_malloc.hpp"
|
||||||
#include "reverse_ptr.hpp"
|
#include "reverse_ptr.hpp"
|
||||||
|
|
||||||
namespace rsx
|
namespace rsx
|
||||||
{
|
{
|
||||||
namespace aligned_allocator
|
|
||||||
{
|
|
||||||
template <size_t Align>
|
|
||||||
requires (Align != 0) && ((Align & (Align - 1)) == 0)
|
|
||||||
size_t align_up(size_t size)
|
|
||||||
{
|
|
||||||
return (size + (Align - 1)) & ~(Align - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <size_t Align>
|
|
||||||
requires (Align != 0) && ((Align & (Align - 1)) == 0)
|
|
||||||
void* malloc(size_t size)
|
|
||||||
{
|
|
||||||
#if defined(_WIN32)
|
|
||||||
return _aligned_malloc(size, Align);
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
constexpr size_t NativeAlign = std::max(Align, sizeof(void*));
|
|
||||||
return std::aligned_alloc(NativeAlign, align_up<NativeAlign>(size));
|
|
||||||
#else
|
|
||||||
return std::aligned_alloc(Align, align_up<Align>(size));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
template <size_t Align>
|
|
||||||
requires (Align != 0) && ((Align & (Align - 1)) == 0)
|
|
||||||
void* realloc(void* prev_ptr, [[maybe_unused]] size_t prev_size, size_t new_size)
|
|
||||||
{
|
|
||||||
if (align_up<Align>(prev_size) >= new_size)
|
|
||||||
{
|
|
||||||
return prev_ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
ensure(reinterpret_cast<usz>(prev_ptr) % Align == 0, "Pointer not aligned to Align");
|
|
||||||
#if defined(_WIN32)
|
|
||||||
return _aligned_realloc(prev_ptr, new_size, Align);
|
|
||||||
#else
|
|
||||||
#if defined(__APPLE__)
|
|
||||||
constexpr size_t NativeAlign = std::max(Align, sizeof(void*));
|
|
||||||
void* ret = std::aligned_alloc(NativeAlign, align_up<NativeAlign>(new_size));
|
|
||||||
#else
|
|
||||||
void* ret = std::aligned_alloc(Align, align_up<Align>(new_size));
|
|
||||||
#endif
|
|
||||||
std::memcpy(ret, prev_ptr, std::min(prev_size, new_size));
|
|
||||||
std::free(prev_ptr);
|
|
||||||
return ret;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void free(void* ptr)
|
|
||||||
{
|
|
||||||
#ifdef _WIN32
|
|
||||||
_aligned_free(ptr);
|
|
||||||
#else
|
|
||||||
std::free(ptr);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename C, typename T>
|
template <typename C, typename T>
|
||||||
concept span_like =
|
concept span_like =
|
||||||
requires(C& c) {
|
requires(C& c) {
|
||||||
|
|||||||
@@ -661,6 +661,7 @@
|
|||||||
<ClInclude Include="Emu\NP\ip_address.h" />
|
<ClInclude Include="Emu\NP\ip_address.h" />
|
||||||
<ClInclude Include="Emu\perf_monitor.hpp" />
|
<ClInclude Include="Emu\perf_monitor.hpp" />
|
||||||
<ClInclude Include="Emu\RSX\color_utils.h" />
|
<ClInclude Include="Emu\RSX\color_utils.h" />
|
||||||
|
<ClInclude Include="Emu\RSX\Common\aligned_malloc.hpp" />
|
||||||
<ClInclude Include="Emu\RSX\Common\bitfield.hpp" />
|
<ClInclude Include="Emu\RSX\Common\bitfield.hpp" />
|
||||||
<ClInclude Include="Emu\RSX\Common\buffer_stream.hpp" />
|
<ClInclude Include="Emu\RSX\Common\buffer_stream.hpp" />
|
||||||
<ClInclude Include="Emu\RSX\Common\reverse_ptr.hpp" />
|
<ClInclude Include="Emu\RSX\Common\reverse_ptr.hpp" />
|
||||||
|
|||||||
@@ -2872,6 +2872,9 @@
|
|||||||
<ClInclude Include="Emu\RSX\Overlays\overlay_arrow.h">
|
<ClInclude Include="Emu\RSX\Overlays\overlay_arrow.h">
|
||||||
<Filter>Emu\GPU\RSX\Overlays</Filter>
|
<Filter>Emu\GPU\RSX\Overlays</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="Emu\RSX\Common\aligned_malloc.hpp">
|
||||||
|
<Filter>Emu\GPU\RSX\Common</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="Emu\RSX\Program\GLSLSnippets\GPUDeswizzle.glsl">
|
<None Include="Emu\RSX\Program\GLSLSnippets\GPUDeswizzle.glsl">
|
||||||
|
|||||||
Reference in New Issue
Block a user