rsx: Improve handling of aligned memory

This commit is contained in:
kd-11 2026-04-10 02:47:31 +03:00 committed by Ani
parent 8121bd443c
commit 1b1143094e
5 changed files with 101 additions and 60 deletions

View File

@ -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;
};
}

View File

@ -81,10 +81,17 @@ namespace rsx
std::span<T> as_span() const
{
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) };
}
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
{
return m_size == 0;

View File

@ -3,70 +3,12 @@
#include <util/types.hpp>
#include <functional>
#include <algorithm>
#include <cstdlib>
#include "aligned_malloc.hpp"
#include "reverse_ptr.hpp"
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>
concept span_like =
requires(C& c) {

View File

@ -661,6 +661,7 @@
<ClInclude Include="Emu\NP\ip_address.h" />
<ClInclude Include="Emu\perf_monitor.hpp" />
<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\buffer_stream.hpp" />
<ClInclude Include="Emu\RSX\Common\reverse_ptr.hpp" />

View File

@ -2872,6 +2872,9 @@
<ClInclude Include="Emu\RSX\Overlays\overlay_arrow.h">
<Filter>Emu\GPU\RSX\Overlays</Filter>
</ClInclude>
<ClInclude Include="Emu\RSX\Common\aligned_malloc.hpp">
<Filter>Emu\GPU\RSX\Common</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="Emu\RSX\Program\GLSLSnippets\GPUDeswizzle.glsl">