diff --git a/CMakeLists.txt b/CMakeLists.txt index 6bb2eaac..c2629551 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -229,6 +229,7 @@ set (REACTPHYSICS3D_SOURCES "src/memory/SingleFrameAllocator.cpp" "src/memory/HeapAllocator.cpp" "src/memory/MemoryManager.cpp" + "src/memory/MemoryAllocator.cpp" "src/utils/Profiler.cpp" "src/utils/DefaultLogger.cpp" "src/utils/DebugRenderer.cpp" diff --git a/include/reactphysics3d/memory/DefaultAllocator.h b/include/reactphysics3d/memory/DefaultAllocator.h index d928741c..727b07b2 100644 --- a/include/reactphysics3d/memory/DefaultAllocator.h +++ b/include/reactphysics3d/memory/DefaultAllocator.h @@ -57,7 +57,7 @@ class DefaultAllocator : public MemoryAllocator { virtual void* allocate(size_t size) override { // If compiler is Visual Studio -#ifdef _MSC_VER +#ifdef RP3D_COMPILER_VISUAL_STUDIO // Visual Studio doesn't not support standard std:aligned_alloc() method from c++ 17 return _alligned_malloc(size, GLOBAL_ALIGNMENT); @@ -72,7 +72,7 @@ class DefaultAllocator : public MemoryAllocator { virtual void release(void* pointer, size_t /*size*/) override { // If compiler is Visual Studio -#ifdef _MSC_VER +#ifdef RP3D_COMPILER_VISUAL_STUDIO // Visual Studio doesn't not support standard std:aligned_alloc() method from c++ 17 return _aligned_free(GLOBAL_ALIGNMENT, pointer); diff --git a/include/reactphysics3d/memory/MemoryAllocator.h b/include/reactphysics3d/memory/MemoryAllocator.h index 0e732a44..e523af94 100644 --- a/include/reactphysics3d/memory/MemoryAllocator.h +++ b/include/reactphysics3d/memory/MemoryAllocator.h @@ -28,6 +28,7 @@ // Libraries #include +#include /// ReactPhysics3D namespace namespace reactphysics3d { @@ -55,6 +56,14 @@ class MemoryAllocator { /// Release previously allocated memory. virtual void release(void* pointer, size_t size)=0; + + /// Given a pointer to memory, this method returns the next aligned address + // TODO : We need to use uint8 type instead of uint8_t here + static void* alignAddress(void* pointer, std::uint8_t alignment); + + /// Given a pointer to memory, this method returns the next aligned address and also output the alignment offset + // TODO : We need to use uint8 type instead of uint8_t here + static void* alignAddress(void* pointer, std::uint8_t alignment, ptrdiff_t& alignmentOffset); }; } diff --git a/src/components/TransformComponents.cpp b/src/components/TransformComponents.cpp index 83245022..aa7d5a58 100644 --- a/src/components/TransformComponents.cpp +++ b/src/components/TransformComponents.cpp @@ -35,7 +35,7 @@ using namespace reactphysics3d; // Constructor TransformComponents::TransformComponents(MemoryAllocator& allocator) - :Components(allocator, sizeof(Entity) + sizeof(Transform)) { + :Components(allocator, sizeof(Entity) + sizeof(Transform) + 2 * GLOBAL_ALIGNMENT) { // Allocate memory for the components data allocate(INIT_NB_ALLOCATED_COMPONENTS); @@ -55,7 +55,9 @@ void TransformComponents::allocate(uint32 nbComponentsToAllocate) { // New pointers to components data Entity* newEntities = static_cast(newBuffer); + //assert(reinterpret_cast(newEntities) % GLOBAL_ALIGNMENT == 0); Transform* newTransforms = reinterpret_cast(newEntities + nbComponentsToAllocate); + //assert(reinterpret_cast(newTransforms) % GLOBAL_ALIGNMENT == 0); // If there was already components before if (mNbComponents > 0) { diff --git a/src/memory/HeapAllocator.cpp b/src/memory/HeapAllocator.cpp index a7183ca9..565cceef 100644 --- a/src/memory/HeapAllocator.cpp +++ b/src/memory/HeapAllocator.cpp @@ -194,24 +194,20 @@ void* HeapAllocator::computeAlignedAddress(void* unalignedAddress) { // Take care of alignment to make sure that we always return an address to the // enforce the global alignment of the library - const uintptr_t currentAdress = reinterpret_cast(unalignedAddress); - - // Calculate the adjustment by masking off the lower bits of the address, to determine how "misaligned" it is. - size_t mask = GLOBAL_ALIGNMENT - 1; - uintptr_t misalignment = currentAdress & mask; - ptrdiff_t alignmentOffset = GLOBAL_ALIGNMENT - misalignment; - // Compute the aligned address - uintptr_t alignedAddress = currentAdress + alignmentOffset; + ptrdiff_t alignmentOffset; + void* alignedPointer = alignAddress(unalignedAddress, GLOBAL_ALIGNMENT, alignmentOffset); + + uintptr_t alignedAddress = reinterpret_cast(alignedPointer); // Store the adjustment in the byte immediately preceding the adjusted address. // This way we can find again the original allocated memory address returned by malloc // when this memory unit is released. - assert(alignmentOffset < 256); + assert(alignmentOffset <= GLOBAL_ALIGNMENT); uint8* pAlignedMemory = reinterpret_cast(alignedAddress); pAlignedMemory[-1] = static_cast(alignmentOffset); - return reinterpret_cast(alignedAddress); + return alignedPointer; } // Release previously allocated memory. diff --git a/src/memory/MemoryAllocator.cpp b/src/memory/MemoryAllocator.cpp new file mode 100644 index 00000000..338c55ba --- /dev/null +++ b/src/memory/MemoryAllocator.cpp @@ -0,0 +1,71 @@ +/******************************************************************************** +* ReactPhysics3D physics library, http://www.reactphysics3d.com * +* Copyright (c) 2010-2022 Daniel Chappuis * +********************************************************************************* +* * +* This software is provided 'as-is', without any express or implied warranty. * +* In no event will the authors be held liable for any damages arising from the * +* use of this software. * +* * +* Permission is granted to anyone to use this software for any purpose, * +* including commercial applications, and to alter it and redistribute it * +* freely, subject to the following restrictions: * +* * +* 1. The origin of this software must not be misrepresented; you must not claim * +* that you wrote the original software. If you use this software in a * +* product, an acknowledgment in the product documentation would be * +* appreciated but is not required. * +* * +* 2. Altered source versions must be plainly marked as such, and must not be * +* misrepresented as being the original software. * +* * +* 3. This notice may not be removed or altered from any source distribution. * +* * +********************************************************************************/ + +// Libraries +#include +#include + +using namespace reactphysics3d; + +/// Given a pointer to memory, this method returns the next aligned address +/** +* @param pointer Pointer to a memory location +* @param alignment Desired alignment +* @return Pointer to the next aligned memory location +*/ +void* MemoryAllocator::alignAddress(void* pointer, std::uint8_t alignment) { + + ptrdiff_t alignmentOffset; + return alignAddress(pointer, alignment, alignmentOffset); +} + +/// Given a pointer to memory, this method returns the next aligned address and also output the alignment offset +/** +* @param pointer Pointer to a memory location +* @param alignment Desired alignment +* @param outAlignmentOffset Output alignment offset needed to align the initial pointer +* @return Pointer to the next aligned memory location +*/ +void* MemoryAllocator::alignAddress(void* pointer, std::uint8_t alignment, ptrdiff_t& outAlignmentOffset) { + + // Take care of alignment to make sure that we always return an address to the + // enforce the global alignment of the library + const uintptr_t currentAdress = reinterpret_cast(pointer); + + // Calculate the adjustment by masking off the lower bits of the address, to determine how "misaligned" it is. + const size_t mask = alignment - 1; + const uintptr_t misalignment = currentAdress & mask; + outAlignmentOffset = alignment - misalignment; + assert(outAlignmentOffset <= alignment); + + // Compute the aligned address + const uintptr_t alignedAdress = currentAdress + outAlignmentOffset; + void* alignedPointer = reinterpret_cast(alignedAdress); + + // Check that allocated memory is correctly aligned + assert(reinterpret_cast(alignedPointer) % alignment == 0); + + return alignedPointer; +} diff --git a/src/memory/SingleFrameAllocator.cpp b/src/memory/SingleFrameAllocator.cpp index eb0eb1c8..97193e4d 100644 --- a/src/memory/SingleFrameAllocator.cpp +++ b/src/memory/SingleFrameAllocator.cpp @@ -77,19 +77,8 @@ void* SingleFrameAllocator::allocate(size_t size) { // Next available memory location void* nextAvailableMemory = mMemoryBufferStart + mCurrentOffset; - // Take care of alignment to make sure that we always return an address to the - // enforce the global alignment of the library - uintptr_t currentAdress = reinterpret_cast(nextAvailableMemory); - - // Calculate the adjustment by masking off the lower bits of the address, to determine how "misaligned" it is. - const size_t mask = GLOBAL_ALIGNMENT - 1; - const uintptr_t misalignment = currentAdress & mask; - const ptrdiff_t alignmentOffset = GLOBAL_ALIGNMENT - misalignment; - assert(alignmentOffset <= GLOBAL_ALIGNMENT); - - // Compute the aligned address - const uintptr_t alignedAdress = currentAdress + alignmentOffset; - nextAvailableMemory = reinterpret_cast(alignedAdress); + // Compute the next aligned memory address + nextAvailableMemory = alignAddress(nextAvailableMemory, GLOBAL_ALIGNMENT); // Increment the offset mCurrentOffset += totalSize;