Fix render memory alignment issues to prevent crashes on Android
This commit is contained in:
@@ -24,6 +24,11 @@ void ArenaAllocator::Free()
|
|||||||
|
|
||||||
void* ArenaAllocator::Allocate(uint64 size, uint64 alignment)
|
void* ArenaAllocator::Allocate(uint64 size, uint64 alignment)
|
||||||
{
|
{
|
||||||
|
if (size == 0)
|
||||||
|
return nullptr;
|
||||||
|
if (alignment < PLATFORM_MEMORY_ALIGNMENT)
|
||||||
|
alignment = PLATFORM_MEMORY_ALIGNMENT;
|
||||||
|
|
||||||
// Find the first page that has some space left
|
// Find the first page that has some space left
|
||||||
Page* page = _first;
|
Page* page = _first;
|
||||||
while (page && page->Offset + size + alignment > page->Size)
|
while (page && page->Offset + size + alignment > page->Size)
|
||||||
@@ -79,6 +84,10 @@ void ConcurrentArenaAllocator::Free()
|
|||||||
|
|
||||||
void* ConcurrentArenaAllocator::Allocate(uint64 size, uint64 alignment)
|
void* ConcurrentArenaAllocator::Allocate(uint64 size, uint64 alignment)
|
||||||
{
|
{
|
||||||
|
if (size == 0)
|
||||||
|
return nullptr;
|
||||||
|
if (alignment < PLATFORM_MEMORY_ALIGNMENT)
|
||||||
|
alignment = PLATFORM_MEMORY_ALIGNMENT;
|
||||||
RETRY:
|
RETRY:
|
||||||
|
|
||||||
// Check if the current page has some space left
|
// Check if the current page has some space left
|
||||||
@@ -120,6 +129,6 @@ RETRY:
|
|||||||
|
|
||||||
_locker.Unlock();
|
_locker.Unlock();
|
||||||
|
|
||||||
// Use a single cde for allocation
|
// Use a single code for allocation
|
||||||
goto RETRY;
|
goto RETRY;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,7 +79,6 @@ private:
|
|||||||
int64 Size;
|
int64 Size;
|
||||||
};
|
};
|
||||||
|
|
||||||
int32 _pageSize;
|
|
||||||
volatile int64 _first = 0;
|
volatile int64 _first = 0;
|
||||||
volatile int64 _totalBytes = 0;
|
volatile int64 _totalBytes = 0;
|
||||||
void*(*_allocate1)(uint64 size, uint64 alignment) = nullptr;
|
void*(*_allocate1)(uint64 size, uint64 alignment) = nullptr;
|
||||||
@@ -87,19 +86,20 @@ private:
|
|||||||
void*(*_allocate2)(uint64 size) = nullptr;
|
void*(*_allocate2)(uint64 size) = nullptr;
|
||||||
void(*_free2)(void* ptr, uint64 size) = nullptr;
|
void(*_free2)(void* ptr, uint64 size) = nullptr;
|
||||||
CriticalSection _locker;
|
CriticalSection _locker;
|
||||||
|
int32 _pageSize;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ConcurrentArenaAllocator(int32 pageSizeBytes, void* (*customAllocate)(uint64 size, uint64 alignment), void(*customFree)(void* ptr))
|
ConcurrentArenaAllocator(int32 pageSizeBytes, void* (*customAllocate)(uint64 size, uint64 alignment), void(*customFree)(void* ptr))
|
||||||
: _pageSize(pageSizeBytes)
|
: _allocate1(customAllocate)
|
||||||
, _allocate1(customAllocate)
|
|
||||||
, _free1(customFree)
|
, _free1(customFree)
|
||||||
|
, _pageSize(pageSizeBytes)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
ConcurrentArenaAllocator(int32 pageSizeBytes, void* (*customAllocate)(uint64 size), void(*customFree)(void* ptr, uint64 size))
|
ConcurrentArenaAllocator(int32 pageSizeBytes, void* (*customAllocate)(uint64 size), void(*customFree)(void* ptr, uint64 size))
|
||||||
: _pageSize(pageSizeBytes)
|
: _allocate2(customAllocate)
|
||||||
, _allocate2(customAllocate)
|
|
||||||
, _free2(customFree)
|
, _free2(customFree)
|
||||||
|
, _pageSize(pageSizeBytes)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,7 +120,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Allocates a chunk of unitialized memory.
|
// Allocates a chunk of unitialized memory.
|
||||||
void* Allocate(uint64 size, uint64 alignment = 1);
|
void* Allocate(uint64 size, uint64 alignment = PLATFORM_MEMORY_ALIGNMENT);
|
||||||
|
|
||||||
// Frees all memory allocations within allocator.
|
// Frees all memory allocations within allocator.
|
||||||
void Free();
|
void Free();
|
||||||
|
|||||||
@@ -11,14 +11,13 @@
|
|||||||
class CrtAllocator
|
class CrtAllocator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Allocates memory on a specified alignment boundary.
|
/// Allocates memory on a specified alignment boundary.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="size">The size of the allocation (in bytes).</param>
|
/// <param name="size">The size of the allocation (in bytes).</param>
|
||||||
/// <param name="alignment">The memory alignment (in bytes). Must be an integer power of 2.</param>
|
/// <param name="alignment">The memory alignment (in bytes). Must be an integer power of 2.</param>
|
||||||
/// <returns>The pointer to the allocated chunk of the memory. The pointer is a multiple of alignment.</returns>
|
/// <returns>The pointer to the allocated chunk of the memory. The pointer is a multiple of alignment.</returns>
|
||||||
FORCE_INLINE static void* Allocate(uint64 size, uint64 alignment = 16)
|
FORCE_INLINE static void* Allocate(uint64 size, uint64 alignment = PLATFORM_MEMORY_ALIGNMENT)
|
||||||
{
|
{
|
||||||
return Platform::Allocate(size, alignment);
|
return Platform::Allocate(size, alignment);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -201,6 +201,9 @@ API_ENUM() enum class ArchitectureType
|
|||||||
#ifndef PLATFORM_THREADS_LIMIT
|
#ifndef PLATFORM_THREADS_LIMIT
|
||||||
#define PLATFORM_THREADS_LIMIT 64
|
#define PLATFORM_THREADS_LIMIT 64
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef PLATFORM_MEMORY_ALIGNMENT
|
||||||
|
#define PLATFORM_MEMORY_ALIGNMENT 16
|
||||||
|
#endif
|
||||||
#define PLATFORM_32BITS (!PLATFORM_64BITS)
|
#define PLATFORM_32BITS (!PLATFORM_64BITS)
|
||||||
|
|
||||||
// Platform family defines
|
// Platform family defines
|
||||||
|
|||||||
@@ -463,20 +463,20 @@ bool DrawCallsList::IsEmpty() const
|
|||||||
|
|
||||||
RenderListAlloc::~RenderListAlloc()
|
RenderListAlloc::~RenderListAlloc()
|
||||||
{
|
{
|
||||||
if (!List && Data) // Render List memory doesn't need free (arena allocator)
|
if (NeedFree && Data) // Render List memory doesn't need free (arena allocator)
|
||||||
RendererAllocation::Free(Data, Size);
|
RendererAllocation::Free(Data, Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* RenderListAlloc::Init(RenderList* list, uintptr size, uintptr alignment)
|
void* RenderListAlloc::Init(RenderList* list, uint32 size, uint32 alignment)
|
||||||
{
|
{
|
||||||
ASSERT_LOW_LAYER(!Data);
|
ASSERT_LOW_LAYER(!Data);
|
||||||
Size = size;
|
Size = size;
|
||||||
bool useList = alignment <= 16 && size < 1024;
|
if (size == 0)
|
||||||
List = useList ? list : nullptr;
|
return nullptr;
|
||||||
if (useList)
|
if (size < 1024 || (alignment != 16 && alignment != 8 && alignment != 4 && alignment != 1))
|
||||||
Data = list->Memory.Allocate(size, alignment);
|
return (Data = list->Memory.Allocate(size, alignment));
|
||||||
else
|
NeedFree = true;
|
||||||
Data = RendererAllocation::Allocate(size);
|
Data = RendererAllocation::Allocate(size);
|
||||||
return Data;
|
return Data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -281,16 +281,16 @@ struct DrawCallsList
|
|||||||
// Small utility for allocating memory from RenderList arena pool with automatic fallback to shared RendererAllocation for larger memory blocks.
|
// Small utility for allocating memory from RenderList arena pool with automatic fallback to shared RendererAllocation for larger memory blocks.
|
||||||
struct RenderListAlloc
|
struct RenderListAlloc
|
||||||
{
|
{
|
||||||
RenderList* List;
|
|
||||||
void* Data = nullptr;
|
void* Data = nullptr;
|
||||||
uintptr Size;
|
uint32 Size = 0;
|
||||||
|
bool NeedFree = false;
|
||||||
|
|
||||||
~RenderListAlloc();
|
~RenderListAlloc();
|
||||||
|
|
||||||
void* Init(RenderList* list, uintptr size, uintptr alignment = 1);
|
void* Init(RenderList* list, uint32 size, uint32 alignment = 1);
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
FORCE_INLINE T* Init(RenderList* list, int32 count, uintptr alignment = 1)
|
FORCE_INLINE T* Init(RenderList* list, int32 count, uint32 alignment = 1)
|
||||||
{
|
{
|
||||||
return (T*)Init(list, count * sizeof(T), alignment);
|
return (T*)Init(list, count * sizeof(T), alignment);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user