aboutsummaryrefslogtreecommitdiff
path: root/PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcNpMemBlockPool.cpp
diff options
context:
space:
mode:
authorgit perforce import user <a@b>2016-10-25 12:29:14 -0600
committerSheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees>2016-10-25 18:56:37 -0500
commit3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch)
treefa6485c169e50d7415a651bf838f5bcd0fd3bfbd /PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcNpMemBlockPool.cpp
downloadphysx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.tar.xz
physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.zip
Initial commit:
PhysX 3.4.0 Update @ 21294896 APEX 1.4.0 Update @ 21275617 [CL 21300167]
Diffstat (limited to 'PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcNpMemBlockPool.cpp')
-rw-r--r--PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcNpMemBlockPool.cpp351
1 files changed, 351 insertions, 0 deletions
diff --git a/PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcNpMemBlockPool.cpp b/PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcNpMemBlockPool.cpp
new file mode 100644
index 00000000..51eb0110
--- /dev/null
+++ b/PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcNpMemBlockPool.cpp
@@ -0,0 +1,351 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+#include "foundation/PxPreprocessor.h"
+#include "foundation/PxMath.h"
+#include "PxcNpMemBlockPool.h"
+#include "PsUserAllocated.h"
+#include "PsInlineArray.h"
+#include "PsFoundation.h"
+
+using namespace physx;
+
+PxcNpMemBlockPool::PxcNpMemBlockPool(PxcScratchAllocator& allocator):
+ mConstraints(PX_DEBUG_EXP("PxcNpMemBlockPool::mConstraints")),
+ mExceptionalConstraints(PX_DEBUG_EXP("PxcNpMemBlockPool::mExceptionalConstraints")),
+ mNpCacheActiveStream(0),
+ mFrictionActiveStream(0),
+ mCCDCacheActiveStream(0),
+ mContactIndex(0),
+ mAllocatedBlocks(0),
+ mMaxBlocks(0),
+ mUsedBlocks(0),
+ mMaxUsedBlocks(0),
+ mScratchBlockAddr(0),
+ mNbScratchBlocks(0),
+ mScratchAllocator(allocator),
+ mPeakConstraintAllocations(0),
+ mConstraintAllocations(0)
+{
+}
+
+void PxcNpMemBlockPool::init(PxU32 initialBlockCount, PxU32 maxBlocks)
+{
+ mMaxBlocks = maxBlocks;
+ mInitialBlocks = initialBlockCount;
+
+ PxU32 reserve = PxMax<PxU32>(initialBlockCount, 64);
+
+ mConstraints.reserve(reserve);
+ mExceptionalConstraints.reserve(16);
+
+ mFriction[0].reserve(reserve);
+ mFriction[1].reserve(reserve);
+ mNpCache[0].reserve(reserve);
+ mNpCache[1].reserve(reserve);
+ mUnused.reserve(reserve);
+
+ setBlockCount(initialBlockCount);
+}
+
+PxU32 PxcNpMemBlockPool::getUsedBlockCount() const
+{
+ return mUsedBlocks;
+}
+
+PxU32 PxcNpMemBlockPool::getMaxUsedBlockCount() const
+{
+ return mMaxUsedBlocks;
+}
+
+PxU32 PxcNpMemBlockPool::getPeakConstraintBlockCount() const
+{
+ return mPeakConstraintAllocations;
+}
+
+
+void PxcNpMemBlockPool::setBlockCount(PxU32 blockCount)
+{
+ Ps::Mutex::ScopedLock lock(mLock);
+ PxU32 current = getUsedBlockCount();
+ for(PxU32 i=current;i<blockCount;i++)
+ {
+ mUnused.pushBack(reinterpret_cast<PxcNpMemBlock *>(PX_ALLOC(PxcNpMemBlock::SIZE, "PxcNpMemBlock")));
+ mAllocatedBlocks++;
+ }
+}
+
+void PxcNpMemBlockPool::releaseUnusedBlocks()
+{
+ Ps::Mutex::ScopedLock lock(mLock);
+ while(mUnused.size())
+ {
+ PX_FREE(mUnused.popBack());
+ mAllocatedBlocks--;
+ }
+}
+
+
+PxcNpMemBlockPool::~PxcNpMemBlockPool()
+{
+ // swapping twice guarantees all blocks are released from the stream pairs
+ swapFrictionStreams();
+ swapFrictionStreams();
+
+ swapNpCacheStreams();
+ swapNpCacheStreams();
+
+ releaseConstraintMemory();
+ releaseContacts();
+ releaseContacts();
+
+ PX_ASSERT(mUsedBlocks == 0);
+
+ flushUnused();
+}
+
+void PxcNpMemBlockPool::acquireConstraintMemory()
+{
+ PxU32 size;
+ void* addr = mScratchAllocator.allocAll(size);
+ size = size&~(PxcNpMemBlock::SIZE-1);
+
+ PX_ASSERT(mScratchBlocks.size()==0);
+ mScratchBlockAddr = reinterpret_cast<PxcNpMemBlock*>(addr);
+ mNbScratchBlocks = size/PxcNpMemBlock::SIZE;
+
+ mScratchBlocks.resize(mNbScratchBlocks);
+ for(PxU32 i=0;i<mNbScratchBlocks;i++)
+ mScratchBlocks[i] = mScratchBlockAddr+i;
+}
+
+void PxcNpMemBlockPool::releaseConstraintMemory()
+{
+ Ps::Mutex::ScopedLock lock(mLock);
+
+ mPeakConstraintAllocations = mConstraintAllocations = 0;
+
+ while(mConstraints.size())
+ {
+ PxcNpMemBlock* block = mConstraints.popBack();
+ if(mScratchAllocator.isScratchAddr(block))
+ mScratchBlocks.pushBack(block);
+ else
+ {
+ mUnused.pushBack(block);
+ PX_ASSERT(mUsedBlocks>0);
+ mUsedBlocks--;
+ }
+ }
+
+ for(PxU32 i=0;i<mExceptionalConstraints.size();i++)
+ PX_FREE(mExceptionalConstraints[i]);
+ mExceptionalConstraints.clear();
+
+ PX_ASSERT(mScratchBlocks.size()==mNbScratchBlocks); // check we released them all
+ mScratchBlocks.clear();
+
+ if(mScratchBlockAddr)
+ {
+ mScratchAllocator.free(mScratchBlockAddr);
+ mScratchBlockAddr = 0;
+ mNbScratchBlocks = 0;
+ }
+}
+
+
+PxcNpMemBlock* PxcNpMemBlockPool::acquire(PxcNpMemBlockArray& trackingArray, PxU32* allocationCount, PxU32* peakAllocationCount, bool isScratchAllocation)
+{
+ Ps::Mutex::ScopedLock lock(mLock);
+ if(allocationCount && peakAllocationCount)
+ {
+ *peakAllocationCount = PxMax(*allocationCount + 1, *peakAllocationCount);
+ (*allocationCount)++;
+ }
+
+ // this is a bit of hack - the logic would be better placed in acquireConstraintBlock, but then we'd have to grab the mutex
+ // once there to check the scratch block array and once here if we fail - or, we'd need a larger refactor to separate out
+ // locking and acquisition.
+
+ if(isScratchAllocation && mScratchBlocks.size()>0)
+ {
+ PxcNpMemBlock* block = mScratchBlocks.popBack();
+ trackingArray.pushBack(block);
+ return block;
+ }
+
+
+ if(mUnused.size())
+ {
+ PxcNpMemBlock* block = mUnused.popBack();
+ trackingArray.pushBack(block);
+ mMaxUsedBlocks = PxMax<PxU32>(mUsedBlocks+1, mMaxUsedBlocks);
+ mUsedBlocks++;
+ return block;
+ }
+
+
+ if(mAllocatedBlocks == mMaxBlocks)
+ {
+#if PX_CHECKED
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__,
+ "Reached maximum number of allocated blocks so 16k block allocation will fail!");
+#endif
+ return NULL;
+ }
+
+#if PX_CHECKED
+ if(mInitialBlocks)
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__,
+ "Number of required 16k memory blocks has exceeded the initial number of blocks. Allocator is being called. Consider increasing the number of pre-allocated 16k blocks.");
+ }
+#endif
+
+ // increment here so that if we hit the limit in separate threads we won't overallocated
+ mAllocatedBlocks++;
+
+ PxcNpMemBlock* block = reinterpret_cast<PxcNpMemBlock*>(PX_ALLOC(sizeof(PxcNpMemBlock), "PxcNpMemBlock"));
+
+ if(block)
+ {
+ trackingArray.pushBack(block);
+ mMaxUsedBlocks = PxMax<PxU32>(mUsedBlocks+1, mMaxUsedBlocks);
+ mUsedBlocks++;
+ }
+ else
+ mAllocatedBlocks--;
+
+ return block;
+}
+
+PxU8* PxcNpMemBlockPool::acquireExceptionalConstraintMemory(PxU32 size)
+{
+ PxU8* memory = reinterpret_cast<PxU8*>(PX_ALLOC(size, "PxcNpExceptionalMemory"));
+ if(memory)
+ {
+ Ps::Mutex::ScopedLock lock(mLock);
+ mExceptionalConstraints.pushBack(memory);
+ }
+ return memory;
+}
+
+void PxcNpMemBlockPool::release(PxcNpMemBlockArray& deadArray, PxU32* allocationCount)
+{
+ Ps::Mutex::ScopedLock lock(mLock);
+ PX_ASSERT(mUsedBlocks >= deadArray.size());
+ mUsedBlocks -= deadArray.size();
+ if(allocationCount)
+ {
+ *allocationCount -= deadArray.size();
+ }
+ while(deadArray.size())
+ {
+ PxcNpMemBlock* block = deadArray.popBack();
+ for(PxU32 a = 0; a < mUnused.size(); ++a)
+ {
+ PX_ASSERT(mUnused[a] != block);
+ }
+ mUnused.pushBack(block);
+ }
+}
+
+void PxcNpMemBlockPool::flushUnused()
+{
+ while(mUnused.size())
+ PX_FREE(mUnused.popBack());
+}
+
+
+PxcNpMemBlock* PxcNpMemBlockPool::acquireConstraintBlock()
+{
+ // we track the scratch blocks in the constraint block array, because the code in acquireMultipleConstraintBlocks
+ // assumes that acquired blocks are listed there.
+
+ return acquire(mConstraints);
+}
+
+PxcNpMemBlock* PxcNpMemBlockPool::acquireConstraintBlock(PxcNpMemBlockArray& memBlocks)
+{
+ return acquire(memBlocks, &mConstraintAllocations, &mPeakConstraintAllocations, true);
+}
+
+PxcNpMemBlock* PxcNpMemBlockPool::acquireContactBlock()
+{
+ return acquire(mContacts[mContactIndex], NULL, NULL, true);
+}
+
+
+void PxcNpMemBlockPool::releaseConstraintBlocks(PxcNpMemBlockArray& memBlocks)
+{
+ Ps::Mutex::ScopedLock lock(mLock);
+
+ while(memBlocks.size())
+ {
+ PxcNpMemBlock* block = memBlocks.popBack();
+ if(mScratchAllocator.isScratchAddr(block))
+ mScratchBlocks.pushBack(block);
+ else
+ {
+ mUnused.pushBack(block);
+ PX_ASSERT(mUsedBlocks>0);
+ mUsedBlocks--;
+ }
+ }
+}
+
+void PxcNpMemBlockPool::releaseContacts()
+{
+ //releaseConstraintBlocks(mContacts);
+ release(mContacts[1-mContactIndex]);
+ mContactIndex = 1-mContactIndex;
+}
+
+PxcNpMemBlock* PxcNpMemBlockPool::acquireFrictionBlock()
+{
+ return acquire(mFriction[mFrictionActiveStream]);
+}
+
+void PxcNpMemBlockPool::swapFrictionStreams()
+{
+ release(mFriction[1-mFrictionActiveStream]);
+ mFrictionActiveStream = 1-mFrictionActiveStream;
+}
+
+PxcNpMemBlock* PxcNpMemBlockPool::acquireNpCacheBlock()
+{
+ return acquire(mNpCache[mNpCacheActiveStream]);
+}
+
+void PxcNpMemBlockPool::swapNpCacheStreams()
+{
+ release(mNpCache[1-mNpCacheActiveStream]);
+ mNpCacheActiveStream = 1-mNpCacheActiveStream;
+}
+