rsx: Properly implement data alignment in simple_array<T>

This commit is contained in:
kd-11
2025-11-21 02:07:06 +03:00
committed by Elad
parent 7f6842705c
commit 6e11978638
+40 -5
View File
@@ -3,11 +3,46 @@
#include <util/types.hpp> #include <util/types.hpp>
#include <functional> #include <functional>
#include <algorithm> #include <algorithm>
#include <cstdlib>
#include "reverse_ptr.hpp" #include "reverse_ptr.hpp"
namespace rsx namespace rsx
{ {
namespace aligned_allocator
{
template <size_t Align>
void* malloc(size_t size)
{
#ifdef _MSC_VER
return _aligned_malloc(size, Align);
#else
return std::aligned_alloc(Align, size);
#endif
}
template <size_t Align>
void* realloc(void* prev_ptr, [[maybe_unused]] size_t prev_size, size_t new_size)
{
#ifdef _MSC_VER
return _aligned_realloc(prev_ptr, new_size, Align);
#else
void* ret = std::aligned_alloc(Align, new_size);
std::memcpy(ret, prev_ptr, std::min(prev_size, new_size));
return ret;
#endif
}
static inline void free(void* ptr)
{
#ifdef _MSC_VER
_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) {
@@ -15,7 +50,7 @@ namespace rsx
{ c.size() } -> std::integral; { c.size() } -> std::integral;
}; };
template <typename Ty> template <typename Ty, size_t Align=alignof(Ty)>
requires std::is_trivially_destructible_v<Ty> && std::is_trivially_copyable_v<Ty> requires std::is_trivially_destructible_v<Ty> && std::is_trivially_copyable_v<Ty>
struct simple_array struct simple_array
{ {
@@ -28,7 +63,7 @@ namespace rsx
private: private:
static constexpr u32 _local_capacity = std::max<u32>(64u / sizeof(Ty), 1u); static constexpr u32 _local_capacity = std::max<u32>(64u / sizeof(Ty), 1u);
char _local_storage[_local_capacity * sizeof(Ty)]; alignas(Align) char _local_storage[_local_capacity * sizeof(Ty)];
u32 _capacity = _local_capacity; u32 _capacity = _local_capacity;
Ty* _data = _local_capacity ? reinterpret_cast<Ty*>(_local_storage) : nullptr; Ty* _data = _local_capacity ? reinterpret_cast<Ty*>(_local_storage) : nullptr;
@@ -128,7 +163,7 @@ namespace rsx
{ {
if (!is_local_storage()) if (!is_local_storage())
{ {
free(_data); aligned_allocator::free(_data);
} }
_data = nullptr; _data = nullptr;
@@ -196,13 +231,13 @@ namespace rsx
if (is_local_storage()) if (is_local_storage())
{ {
// Switch to heap storage // Switch to heap storage
ensure(_data = static_cast<Ty*>(std::malloc(sizeof(Ty) * size))); ensure(_data = static_cast<Ty*>(aligned_allocator::malloc<Align>(sizeof(Ty) * size)));
std::memcpy(static_cast<void*>(_data), _local_storage, size_bytes()); std::memcpy(static_cast<void*>(_data), _local_storage, size_bytes());
} }
else else
{ {
// Extend heap storage // Extend heap storage
ensure(_data = static_cast<Ty*>(std::realloc(_data, sizeof(Ty) * size))); // "realloc() failed!" ensure(_data = static_cast<Ty*>(aligned_allocator::realloc<Align>(_data, size_bytes(), sizeof(Ty) * size))); // "realloc() failed!"
} }
_capacity = size; _capacity = size;