aboutsummaryrefslogtreecommitdiff
path: root/sdk/toolkit/source
diff options
context:
space:
mode:
authorBryan Galdrikian <[email protected]>2018-05-31 11:36:08 -0700
committerBryan Galdrikian <[email protected]>2018-05-31 11:36:08 -0700
commit7115f60b91b5717d90f643fd692010905c7004db (patch)
treeeffd68c6978751c517d54c2f2bb5bb6e7dc93e18 /sdk/toolkit/source
parentUpdating BlastTool zip (diff)
downloadblast-1.1.3_rc1.tar.xz
blast-1.1.3_rc1.zip
Blast 1.1.3. See docs/release_notes.txt.v1.1.3_rc1
Diffstat (limited to 'sdk/toolkit/source')
-rwxr-xr-x[-rw-r--r--]sdk/toolkit/source/NvBlastTkActorImpl.cpp746
-rwxr-xr-x[-rw-r--r--]sdk/toolkit/source/NvBlastTkActorImpl.h684
-rwxr-xr-x[-rw-r--r--]sdk/toolkit/source/NvBlastTkAssetImpl.cpp552
-rwxr-xr-x[-rw-r--r--]sdk/toolkit/source/NvBlastTkAssetImpl.h326
-rwxr-xr-x[-rw-r--r--]sdk/toolkit/source/NvBlastTkCommon.h214
-rwxr-xr-x[-rw-r--r--]sdk/toolkit/source/NvBlastTkEventQueue.h496
-rwxr-xr-x[-rw-r--r--]sdk/toolkit/source/NvBlastTkFamilyImpl.cpp1116
-rwxr-xr-x[-rw-r--r--]sdk/toolkit/source/NvBlastTkFamilyImpl.h458
-rwxr-xr-x[-rw-r--r--]sdk/toolkit/source/NvBlastTkFrameworkImpl.cpp926
-rwxr-xr-x[-rw-r--r--]sdk/toolkit/source/NvBlastTkFrameworkImpl.h324
-rwxr-xr-x[-rw-r--r--]sdk/toolkit/source/NvBlastTkGUID.h296
-rwxr-xr-x[-rw-r--r--]sdk/toolkit/source/NvBlastTkGroupImpl.cpp1224
-rwxr-xr-x[-rw-r--r--]sdk/toolkit/source/NvBlastTkGroupImpl.h388
-rwxr-xr-x[-rw-r--r--]sdk/toolkit/source/NvBlastTkJointImpl.cpp390
-rwxr-xr-x[-rw-r--r--]sdk/toolkit/source/NvBlastTkJointImpl.h328
-rwxr-xr-x[-rw-r--r--]sdk/toolkit/source/NvBlastTkTaskImpl.cpp542
-rwxr-xr-x[-rw-r--r--]sdk/toolkit/source/NvBlastTkTaskImpl.h746
-rwxr-xr-x[-rw-r--r--]sdk/toolkit/source/NvBlastTkTypeImpl.h322
18 files changed, 5039 insertions, 5039 deletions
diff --git a/sdk/toolkit/source/NvBlastTkActorImpl.cpp b/sdk/toolkit/source/NvBlastTkActorImpl.cpp
index 32114ef..0074237 100644..100755
--- a/sdk/toolkit/source/NvBlastTkActorImpl.cpp
+++ b/sdk/toolkit/source/NvBlastTkActorImpl.cpp
@@ -1,373 +1,373 @@
-// 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) 2016-2018 NVIDIA Corporation. All rights reserved.
-
-
-#include "NvBlastPreprocessor.h"
-
-#include "NvBlastTkFrameworkImpl.h"
-#include "NvBlastTkActorImpl.h"
-#include "NvBlastTkGroupImpl.h"
-#include "NvBlastTkAssetImpl.h"
-#include "NvBlastTkFamilyImpl.h"
-#include "NvBlastTkJointImpl.h"
-
-#include "NvBlast.h"
-#include "NvBlastAssert.h"
-#include "NvBlastMemory.h"
-
-
-namespace Nv
-{
-namespace Blast
-{
-
-TkActorImpl* TkActorImpl::create(const TkActorDesc& desc)
-{
- const TkAssetImpl* asset = static_cast<const TkAssetImpl*>(desc.asset);
-
- TkFamilyImpl* family = TkFamilyImpl::create(asset);
-
- NvBlastFamily* familyLL = family->getFamilyLLInternal();
- Array<char>::type scratch((uint32_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(familyLL, logLL));
- NvBlastActor* actorLL = NvBlastFamilyCreateFirstActor(familyLL, &desc, scratch.begin(), logLL);
- if (actorLL == nullptr)
- {
- NVBLAST_LOG_ERROR("TkActorImpl::create: low-level actor could not be created.");
- return nullptr;
- }
-
- TkActorImpl* actor = family->addActor(actorLL);
-
- if (actor != nullptr)
- {
- // Add internal joints
- const uint32_t internalJointCount = asset->getJointDescCountInternal();
- const TkAssetJointDesc* jointDescs = asset->getJointDescsInternal();
- const NvBlastSupportGraph graph = asset->getGraph();
- TkJointImpl* joints = family->getInternalJoints();
- for (uint32_t jointNum = 0; jointNum < internalJointCount; ++jointNum)
- {
- const TkAssetJointDesc& assetJointDesc = jointDescs[jointNum];
- NVBLAST_ASSERT(assetJointDesc.nodeIndices[0] < graph.nodeCount && assetJointDesc.nodeIndices[1] < graph.nodeCount);
- TkJointDesc jointDesc;
- jointDesc.families[0] = jointDesc.families[1] = family;
- jointDesc.chunkIndices[0] = graph.chunkIndices[assetJointDesc.nodeIndices[0]];
- jointDesc.chunkIndices[1] = graph.chunkIndices[assetJointDesc.nodeIndices[1]];
- jointDesc.attachPositions[0] = assetJointDesc.attachPositions[0];
- jointDesc.attachPositions[1] = assetJointDesc.attachPositions[1];
- TkJointImpl* joint = new (joints + jointNum) TkJointImpl(jointDesc, family);
- actor->addJoint(joint->m_links[0]);
- }
-
- // Mark as damaged to trigger first split call. It could be the case that asset is already split into few actors initially.
- actor->markAsDamaged();
- }
-
- return actor;
-}
-
-
-//////// Member functions ////////
-
-TkActorImpl::TkActorImpl()
- : m_actorLL(nullptr)
- , m_family(nullptr)
- , m_group(nullptr)
- , m_groupJobIndex(invalidIndex<uint32_t>())
- , m_flags(0)
- , m_jointCount(0)
-{
-#if NV_PROFILE
- NvBlastTimersReset(&m_timers);
-#endif
-}
-
-
-TkActorImpl::~TkActorImpl()
-{
-}
-
-
-void TkActorImpl::release()
-{
- // Disassoaciate all joints
-
- // Copy joint array for safety against implementation of joint->setActor
- TkJointImpl** joints = reinterpret_cast<TkJointImpl**>(NvBlastAlloca(sizeof(TkJointImpl*)*getJointCountInternal()));
- TkJointImpl** stop = joints + getJointCountInternal();
- TkJointImpl** jointHandle = joints;
- for (JointIt j(*this); (bool)j; ++j)
- {
- *jointHandle++ = *j;
- }
- jointHandle = joints;
- while (jointHandle < stop)
- {
- NVBLAST_ASSERT(*jointHandle != nullptr);
- NVBLAST_ASSERT((*jointHandle)->getDataInternal().actors[0] == this || (*jointHandle)->getDataInternal().actors[1] == this);
- (*jointHandle++)->setActors(nullptr, nullptr);
- }
- NVBLAST_ASSERT(getJointCountInternal() == 0);
-
- if (m_group != nullptr)
- {
- m_group->removeActor(*this);
- }
-
- if (m_actorLL != nullptr)
- {
- NvBlastActorDeactivate(m_actorLL, logLL);
- }
-
- if (m_family != nullptr)
- {
- m_family->removeActor(this);
-
- // Make sure we dispatch any remaining events when this family is emptied, since it will no longer be done by any group
- if (m_family->getActorCountInternal() == 0)
- {
- m_family->getQueue().dispatch();
- }
- }
-}
-
-
-const NvBlastActor* TkActorImpl::getActorLL() const
-{
- return m_actorLL;
-}
-
-
-TkFamily& TkActorImpl::getFamily() const
-{
- return getFamilyImpl();
-}
-
-
-uint32_t TkActorImpl::getIndex() const
-{
- return getIndexInternal();
-}
-
-
-TkGroup* TkActorImpl::getGroup() const
-{
- return getGroupImpl();
-}
-
-
-TkGroup* TkActorImpl::removeFromGroup()
-{
- if (m_group == nullptr)
- {
- NVBLAST_LOG_WARNING("TkActorImpl::removeFromGroup: actor not in a group.");
- return nullptr;
- }
-
- if (m_group->isProcessing())
- {
- NVBLAST_LOG_ERROR("TkActorImpl::removeFromGroup: cannot alter Group while processing.");
- return nullptr;
- }
-
- TkGroup* group = m_group;
-
- return m_group->removeActor(*this) ? group : nullptr;
-}
-
-
-NvBlastFamily* TkActorImpl::getFamilyLL() const
-{
- return m_family->getFamilyLLInternal();
-}
-
-
-const TkAsset* TkActorImpl::getAsset() const
-{
- return m_family->getAssetImpl();
-}
-
-
-uint32_t TkActorImpl::getVisibleChunkCount() const
-{
- return NvBlastActorGetVisibleChunkCount(m_actorLL, logLL);
-}
-
-
-uint32_t TkActorImpl::getVisibleChunkIndices(uint32_t* visibleChunkIndices, uint32_t visibleChunkIndicesSize) const
-{
- return NvBlastActorGetVisibleChunkIndices(visibleChunkIndices, visibleChunkIndicesSize, m_actorLL, logLL);
-}
-
-
-uint32_t TkActorImpl::getGraphNodeCount() const
-{
- return NvBlastActorGetGraphNodeCount(m_actorLL, logLL);
-}
-
-
-uint32_t TkActorImpl::getGraphNodeIndices(uint32_t* graphNodeIndices, uint32_t graphNodeIndicesSize) const
-{
- return NvBlastActorGetGraphNodeIndices(graphNodeIndices, graphNodeIndicesSize, m_actorLL, logLL);
-}
-
-
-const float* TkActorImpl::getBondHealths() const
-{
- return NvBlastActorGetBondHealths(m_actorLL, logLL);
-}
-
-
-uint32_t TkActorImpl::getSplitMaxActorCount() const
-{
- return NvBlastActorGetMaxActorCountForSplit(m_actorLL, logLL);
-}
-
-
-bool TkActorImpl::isDamaged() const
-{
- NVBLAST_ASSERT(!m_flags.isSet(TkActorFlag::DAMAGED) || (m_flags.isSet(TkActorFlag::DAMAGED) && m_flags.isSet(TkActorFlag::PENDING)));
- return m_flags.isSet(TkActorFlag::DAMAGED);
-}
-
-
-void TkActorImpl::markAsDamaged()
-{
- m_flags |= TkActorFlag::DAMAGED;
- makePending();
-}
-
-
-void TkActorImpl::makePending()
-{
- if (m_group != nullptr && !isPending())
- {
- m_group->enqueue(this);
- }
-
- m_flags |= TkActorFlag::PENDING;
-}
-
-
-TkActorImpl::operator Nv::Blast::TkActorData() const
-{
- TkActorData data = { m_family, userData, getIndex() };
- return data;
-}
-
-
-void TkActorImpl::damage(const NvBlastDamageProgram& program, const void* programParams)
-{
- BLAST_PROFILE_SCOPE_L("TkActor::damage");
-
- if (m_group == nullptr)
- {
- NVBLAST_LOG_WARNING("TkActor::damage: actor is not in a group, cannot fracture.");
- return;
- }
-
- if (m_group->isProcessing())
- {
- NVBLAST_LOG_WARNING("TkActor::damage: group is being processed, cannot fracture this actor.");
- return;
- }
-
- if (NvBlastActorCanFracture(m_actorLL, logLL))
- {
- m_damageBuffer.pushBack(DamageData{ program, programParams});
- makePending();
- }
-}
-
-
-void TkActorImpl::generateFracture(NvBlastFractureBuffers* commands, const NvBlastDamageProgram& program, const void* programParams) const
-{
- BLAST_PROFILE_SCOPE_L("TkActor::generateFracture");
-
- if (m_group && m_group->isProcessing())
- {
- NVBLAST_LOG_WARNING("TkActor::generateFracture: group is being processed, cannot fracture this actor.");
- return;
- }
-
- // const context, must make m_timers mutable otherwise
- NvBlastActorGenerateFracture(commands, m_actorLL, program, programParams, logLL, const_cast<NvBlastTimers*>(&m_timers));
-}
-
-
-void TkActorImpl::applyFracture(NvBlastFractureBuffers* eventBuffers, const NvBlastFractureBuffers* commands)
-{
- BLAST_PROFILE_SCOPE_L("TkActor::applyFracture");
-
- if (m_group && m_group->isProcessing())
- {
- NVBLAST_LOG_WARNING("TkActor::applyFracture: group is being processed, cannot fracture this actor.");
- return;
- }
-
- NvBlastActorApplyFracture(eventBuffers, m_actorLL, commands, logLL, &m_timers);
-
- if (commands->chunkFractureCount > 0 || commands->bondFractureCount > 0)
- {
- markAsDamaged();
-
- TkFractureCommands* fevt = getFamilyImpl().getQueue().allocData<TkFractureCommands>();
- fevt->tkActorData = *this;
- fevt->buffers = *commands;
- getFamilyImpl().getQueue().addEvent(fevt);
- getFamilyImpl().getQueue().dispatch();
- }
-}
-
-
-uint32_t TkActorImpl::getJointCount() const
-{
- return getJointCountInternal();
-}
-
-
-uint32_t TkActorImpl::getJoints(TkJoint** joints, uint32_t jointsSize) const
-{
- uint32_t jointsWritten = 0;
-
- for (JointIt j(*this); (bool)j && jointsWritten < jointsSize; ++j)
- {
- joints[jointsWritten++] = *j;
- }
-
- return jointsWritten;
-}
-
-
-bool TkActorImpl::isBoundToWorld() const
-{
- return NvBlastActorIsBoundToWorld(m_actorLL, logLL);
-}
-
-
-} // namespace Blast
-} // namespace Nv
+// 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) 2016-2018 NVIDIA Corporation. All rights reserved.
+
+
+#include "NvBlastPreprocessor.h"
+
+#include "NvBlastTkFrameworkImpl.h"
+#include "NvBlastTkActorImpl.h"
+#include "NvBlastTkGroupImpl.h"
+#include "NvBlastTkAssetImpl.h"
+#include "NvBlastTkFamilyImpl.h"
+#include "NvBlastTkJointImpl.h"
+
+#include "NvBlast.h"
+#include "NvBlastAssert.h"
+#include "NvBlastMemory.h"
+
+
+namespace Nv
+{
+namespace Blast
+{
+
+TkActorImpl* TkActorImpl::create(const TkActorDesc& desc)
+{
+ const TkAssetImpl* asset = static_cast<const TkAssetImpl*>(desc.asset);
+
+ TkFamilyImpl* family = TkFamilyImpl::create(asset);
+
+ NvBlastFamily* familyLL = family->getFamilyLLInternal();
+ Array<char>::type scratch((uint32_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(familyLL, logLL));
+ NvBlastActor* actorLL = NvBlastFamilyCreateFirstActor(familyLL, &desc, scratch.begin(), logLL);
+ if (actorLL == nullptr)
+ {
+ NVBLAST_LOG_ERROR("TkActorImpl::create: low-level actor could not be created.");
+ return nullptr;
+ }
+
+ TkActorImpl* actor = family->addActor(actorLL);
+
+ if (actor != nullptr)
+ {
+ // Add internal joints
+ const uint32_t internalJointCount = asset->getJointDescCountInternal();
+ const TkAssetJointDesc* jointDescs = asset->getJointDescsInternal();
+ const NvBlastSupportGraph graph = asset->getGraph();
+ TkJointImpl* joints = family->getInternalJoints();
+ for (uint32_t jointNum = 0; jointNum < internalJointCount; ++jointNum)
+ {
+ const TkAssetJointDesc& assetJointDesc = jointDescs[jointNum];
+ NVBLAST_ASSERT(assetJointDesc.nodeIndices[0] < graph.nodeCount && assetJointDesc.nodeIndices[1] < graph.nodeCount);
+ TkJointDesc jointDesc;
+ jointDesc.families[0] = jointDesc.families[1] = family;
+ jointDesc.chunkIndices[0] = graph.chunkIndices[assetJointDesc.nodeIndices[0]];
+ jointDesc.chunkIndices[1] = graph.chunkIndices[assetJointDesc.nodeIndices[1]];
+ jointDesc.attachPositions[0] = assetJointDesc.attachPositions[0];
+ jointDesc.attachPositions[1] = assetJointDesc.attachPositions[1];
+ TkJointImpl* joint = new (joints + jointNum) TkJointImpl(jointDesc, family);
+ actor->addJoint(joint->m_links[0]);
+ }
+
+ // Mark as damaged to trigger first split call. It could be the case that asset is already split into few actors initially.
+ actor->markAsDamaged();
+ }
+
+ return actor;
+}
+
+
+//////// Member functions ////////
+
+TkActorImpl::TkActorImpl()
+ : m_actorLL(nullptr)
+ , m_family(nullptr)
+ , m_group(nullptr)
+ , m_groupJobIndex(invalidIndex<uint32_t>())
+ , m_flags(0)
+ , m_jointCount(0)
+{
+#if NV_PROFILE
+ NvBlastTimersReset(&m_timers);
+#endif
+}
+
+
+TkActorImpl::~TkActorImpl()
+{
+}
+
+
+void TkActorImpl::release()
+{
+ // Disassoaciate all joints
+
+ // Copy joint array for safety against implementation of joint->setActor
+ TkJointImpl** joints = reinterpret_cast<TkJointImpl**>(NvBlastAlloca(sizeof(TkJointImpl*)*getJointCountInternal()));
+ TkJointImpl** stop = joints + getJointCountInternal();
+ TkJointImpl** jointHandle = joints;
+ for (JointIt j(*this); (bool)j; ++j)
+ {
+ *jointHandle++ = *j;
+ }
+ jointHandle = joints;
+ while (jointHandle < stop)
+ {
+ NVBLAST_ASSERT(*jointHandle != nullptr);
+ NVBLAST_ASSERT((*jointHandle)->getDataInternal().actors[0] == this || (*jointHandle)->getDataInternal().actors[1] == this);
+ (*jointHandle++)->setActors(nullptr, nullptr);
+ }
+ NVBLAST_ASSERT(getJointCountInternal() == 0);
+
+ if (m_group != nullptr)
+ {
+ m_group->removeActor(*this);
+ }
+
+ if (m_actorLL != nullptr)
+ {
+ NvBlastActorDeactivate(m_actorLL, logLL);
+ }
+
+ if (m_family != nullptr)
+ {
+ m_family->removeActor(this);
+
+ // Make sure we dispatch any remaining events when this family is emptied, since it will no longer be done by any group
+ if (m_family->getActorCountInternal() == 0)
+ {
+ m_family->getQueue().dispatch();
+ }
+ }
+}
+
+
+const NvBlastActor* TkActorImpl::getActorLL() const
+{
+ return m_actorLL;
+}
+
+
+TkFamily& TkActorImpl::getFamily() const
+{
+ return getFamilyImpl();
+}
+
+
+uint32_t TkActorImpl::getIndex() const
+{
+ return getIndexInternal();
+}
+
+
+TkGroup* TkActorImpl::getGroup() const
+{
+ return getGroupImpl();
+}
+
+
+TkGroup* TkActorImpl::removeFromGroup()
+{
+ if (m_group == nullptr)
+ {
+ NVBLAST_LOG_WARNING("TkActorImpl::removeFromGroup: actor not in a group.");
+ return nullptr;
+ }
+
+ if (m_group->isProcessing())
+ {
+ NVBLAST_LOG_ERROR("TkActorImpl::removeFromGroup: cannot alter Group while processing.");
+ return nullptr;
+ }
+
+ TkGroup* group = m_group;
+
+ return m_group->removeActor(*this) ? group : nullptr;
+}
+
+
+NvBlastFamily* TkActorImpl::getFamilyLL() const
+{
+ return m_family->getFamilyLLInternal();
+}
+
+
+const TkAsset* TkActorImpl::getAsset() const
+{
+ return m_family->getAssetImpl();
+}
+
+
+uint32_t TkActorImpl::getVisibleChunkCount() const
+{
+ return NvBlastActorGetVisibleChunkCount(m_actorLL, logLL);
+}
+
+
+uint32_t TkActorImpl::getVisibleChunkIndices(uint32_t* visibleChunkIndices, uint32_t visibleChunkIndicesSize) const
+{
+ return NvBlastActorGetVisibleChunkIndices(visibleChunkIndices, visibleChunkIndicesSize, m_actorLL, logLL);
+}
+
+
+uint32_t TkActorImpl::getGraphNodeCount() const
+{
+ return NvBlastActorGetGraphNodeCount(m_actorLL, logLL);
+}
+
+
+uint32_t TkActorImpl::getGraphNodeIndices(uint32_t* graphNodeIndices, uint32_t graphNodeIndicesSize) const
+{
+ return NvBlastActorGetGraphNodeIndices(graphNodeIndices, graphNodeIndicesSize, m_actorLL, logLL);
+}
+
+
+const float* TkActorImpl::getBondHealths() const
+{
+ return NvBlastActorGetBondHealths(m_actorLL, logLL);
+}
+
+
+uint32_t TkActorImpl::getSplitMaxActorCount() const
+{
+ return NvBlastActorGetMaxActorCountForSplit(m_actorLL, logLL);
+}
+
+
+bool TkActorImpl::isDamaged() const
+{
+ NVBLAST_ASSERT(!m_flags.isSet(TkActorFlag::DAMAGED) || (m_flags.isSet(TkActorFlag::DAMAGED) && m_flags.isSet(TkActorFlag::PENDING)));
+ return m_flags.isSet(TkActorFlag::DAMAGED);
+}
+
+
+void TkActorImpl::markAsDamaged()
+{
+ m_flags |= TkActorFlag::DAMAGED;
+ makePending();
+}
+
+
+void TkActorImpl::makePending()
+{
+ if (m_group != nullptr && !isPending())
+ {
+ m_group->enqueue(this);
+ }
+
+ m_flags |= TkActorFlag::PENDING;
+}
+
+
+TkActorImpl::operator Nv::Blast::TkActorData() const
+{
+ TkActorData data = { m_family, userData, getIndex() };
+ return data;
+}
+
+
+void TkActorImpl::damage(const NvBlastDamageProgram& program, const void* programParams)
+{
+ BLAST_PROFILE_SCOPE_L("TkActor::damage");
+
+ if (m_group == nullptr)
+ {
+ NVBLAST_LOG_WARNING("TkActor::damage: actor is not in a group, cannot fracture.");
+ return;
+ }
+
+ if (m_group->isProcessing())
+ {
+ NVBLAST_LOG_WARNING("TkActor::damage: group is being processed, cannot fracture this actor.");
+ return;
+ }
+
+ if (NvBlastActorCanFracture(m_actorLL, logLL))
+ {
+ m_damageBuffer.pushBack(DamageData{ program, programParams});
+ makePending();
+ }
+}
+
+
+void TkActorImpl::generateFracture(NvBlastFractureBuffers* commands, const NvBlastDamageProgram& program, const void* programParams) const
+{
+ BLAST_PROFILE_SCOPE_L("TkActor::generateFracture");
+
+ if (m_group && m_group->isProcessing())
+ {
+ NVBLAST_LOG_WARNING("TkActor::generateFracture: group is being processed, cannot fracture this actor.");
+ return;
+ }
+
+ // const context, must make m_timers mutable otherwise
+ NvBlastActorGenerateFracture(commands, m_actorLL, program, programParams, logLL, const_cast<NvBlastTimers*>(&m_timers));
+}
+
+
+void TkActorImpl::applyFracture(NvBlastFractureBuffers* eventBuffers, const NvBlastFractureBuffers* commands)
+{
+ BLAST_PROFILE_SCOPE_L("TkActor::applyFracture");
+
+ if (m_group && m_group->isProcessing())
+ {
+ NVBLAST_LOG_WARNING("TkActor::applyFracture: group is being processed, cannot fracture this actor.");
+ return;
+ }
+
+ NvBlastActorApplyFracture(eventBuffers, m_actorLL, commands, logLL, &m_timers);
+
+ if (commands->chunkFractureCount > 0 || commands->bondFractureCount > 0)
+ {
+ markAsDamaged();
+
+ TkFractureCommands* fevt = getFamilyImpl().getQueue().allocData<TkFractureCommands>();
+ fevt->tkActorData = *this;
+ fevt->buffers = *commands;
+ getFamilyImpl().getQueue().addEvent(fevt);
+ getFamilyImpl().getQueue().dispatch();
+ }
+}
+
+
+uint32_t TkActorImpl::getJointCount() const
+{
+ return getJointCountInternal();
+}
+
+
+uint32_t TkActorImpl::getJoints(TkJoint** joints, uint32_t jointsSize) const
+{
+ uint32_t jointsWritten = 0;
+
+ for (JointIt j(*this); (bool)j && jointsWritten < jointsSize; ++j)
+ {
+ joints[jointsWritten++] = *j;
+ }
+
+ return jointsWritten;
+}
+
+
+bool TkActorImpl::isBoundToWorld() const
+{
+ return NvBlastActorIsBoundToWorld(m_actorLL, logLL);
+}
+
+
+} // namespace Blast
+} // namespace Nv
diff --git a/sdk/toolkit/source/NvBlastTkActorImpl.h b/sdk/toolkit/source/NvBlastTkActorImpl.h
index 8feeb9c..482f0de 100644..100755
--- a/sdk/toolkit/source/NvBlastTkActorImpl.h
+++ b/sdk/toolkit/source/NvBlastTkActorImpl.h
@@ -1,342 +1,342 @@
-// 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) 2016-2018 NVIDIA Corporation. All rights reserved.
-
-
-#ifndef NVBLASTTKACTORIMPL_H
-#define NVBLASTTKACTORIMPL_H
-
-
-#include "NvBlastTkCommon.h"
-
-#include "NvBlastAssert.h"
-#include "NvBlastDLink.h"
-#include "NvBlastIteratorBase.h"
-
-#include "NvBlastTkJointImpl.h"
-
-#include "NvBlast.h"
-
-#include "NvBlastTkActor.h"
-
-#include "PxFlags.h"
-
-namespace Nv
-{
-namespace Blast
-{
-
-// Forward declarations:
-class TkGroupImpl;
-class TkFamilyImpl;
-class TkAssetImpl;
-class TkJointImpl;
-
-
-/**
-Struct-enum for actor status flags, used in TkGroup processing.
-*/
-struct TkActorFlag
-{
- enum Enum
- {
- DAMAGED = (1 << 0), //!< The actor had fractures applied successfully and will take the split step.
- PENDING = (1 << 1), //!< The actor will be processed when its group executes, used to update job queues when moving group.
- };
-};
-
-
-/**
-Implementation of TkActor.
-*/
-class TkActorImpl : public TkActor
-{
-public:
- TkActorImpl();
- ~TkActorImpl();
-
- // Begin TkActor
- virtual const NvBlastActor* getActorLL() const override;
-
- virtual TkFamily& getFamily() const override;
-
- virtual uint32_t getIndex() const override;
-
- virtual TkGroup* getGroup() const override;
-
- virtual TkGroup* removeFromGroup() override;
-
- virtual const TkAsset* getAsset() const override;
-
- virtual uint32_t getVisibleChunkCount() const override;
-
- virtual uint32_t getVisibleChunkIndices(uint32_t* visibleChunkIndices, uint32_t visibleChunkIndicesSize) const override;
-
- virtual uint32_t getGraphNodeCount() const override;
-
- virtual uint32_t getGraphNodeIndices(uint32_t* graphNodeIndices, uint32_t graphNodeIndicesSize) const override;
-
- virtual const float* getBondHealths() const override;
-
- virtual uint32_t getSplitMaxActorCount() const override;
-
- virtual void damage(const NvBlastDamageProgram& program, const void* programParams) override;
-
- virtual bool isPending() const override;
-
- virtual void generateFracture(NvBlastFractureBuffers* commands, const NvBlastDamageProgram& program, const void* programParams) const override;
-
- virtual void applyFracture(NvBlastFractureBuffers* eventBuffers, const NvBlastFractureBuffers* commands) override;
-
- virtual uint32_t getJointCount() const override;
-
- virtual uint32_t getJoints(TkJoint** joints, uint32_t jointsSize) const override;
-
- virtual bool isBoundToWorld() const override;
- // End TkActor
-
- // Begin TkObject
- virtual void release() override;
- // End TkObject
-
-
- // Public methods
-
- /**
- Factory create method.
-
- \param[in] desc Actor descriptor set by the user.
-
- \return a pointer to a new TkActorImpl object if successful, NULL otherwise.
- */
- static TkActorImpl* create(const TkActorDesc& desc);
-
- /**
- TkActorImpl objects are created in an array within a TkFamilyImpl. Actors may become
- 'inactive' without their memory being freed. If inactive, the actor should be treated as if
- it has been released.
-
- \return the active status of this TkActorImpl.
- */
- bool isActive() const;
-
- /**
- Utility to return the low-level family to which the low-level actor belongs.
-
- \return a pointer to the NvBlastFamily to which the low-level actor belongs.
- */
- NvBlastFamily* getFamilyLL() const;
-
- /**
- Utility to access the TkFamily to which this actor belongs.
-
- \return a reference to the TkFamilyImpl to which this TkActorImpl belongs.
- */
- TkFamilyImpl& getFamilyImpl() const;
-
- /**
- \return the index of this actor with its TkFamilyImpl.
- */
- uint32_t getIndexInternal() const;
-
- /**
- Access to the group to which this actor belongs, if any.
-
- \return a pointer to the TkGroupImpl to which this TkActorImpl belongs, if any. If this actor is not in a group, this function returns NULL.
- */
- TkGroupImpl* getGroupImpl() const;
-
- /**
- Access to the low-level actor associated with this TkActorImpl.
-
- \return a pointer to the NvBlastActor associated with this TkActorImpl. If this actor is inactive (see isActive), this function returns NULL.
- */
- NvBlastActor* getActorLLInternal() const;
-
- /**
- \return the number of TkJointImpl objects that reference this actor.
- */
- uint32_t getJointCountInternal() const;
-
- /**
- Joint iterator. Usage:
-
- Given a TkActorImpl a,
-
- for (TkActorImpl::JointIt i(a); (bool)i; ++i)
- {
- TkJointImpl* joint = (TkJointImpl*)i;
- // ...
- }
- */
- class JointIt : public DList::It
- {
- public:
- /** Constructed from an actor. */
- JointIt(const TkActorImpl& actor, Direction dir = Forward);
-
- /** Current joint. */
- TkJointImpl* operator * () const;
- };
-
- /**
- Implicit converter to TkActorData for events.
- */
- operator Nv::Blast::TkActorData() const;
-
-private:
- /**
- Functions to raise or check 'damaged' state: this actor will take the split step.
- 'damaged' actors automatically become 'pending' also.
- */
- void markAsDamaged();
- bool isDamaged() const;
-
- /**
- Raise actor to 'pending' state: this actor will be processed when its group executes next.
- Enqueues the actor in its group's job list if a group is set. Otherwise the group will enqueue the actor when it is added.
- */
- void makePending();
-
- /**
- Functions to add or remove an internal reference to a joint. (Joints and actors mutually reference each other.)
- */
- void addJoint(TkJointLink& jointLink);
- void removeJoint(TkJointLink& jointLink);
-
- struct DamageData
- {
- NvBlastDamageProgram program;
- const void* programParams;
- };
-
- // Data
-
- NvBlastActor* m_actorLL; //!< The low-level actor associated with this actor
- TkFamilyImpl* m_family; //!< The TkFamilyImpl to which this actor belongs
- TkGroupImpl* m_group; //!< The TkGroupImpl (if any) to which this actor belongs
- uint32_t m_groupJobIndex; //!< The index of this actor's job within its group's job list
- physx::PxFlags<TkActorFlag::Enum, char> m_flags; //!< Status flags for this actor
- Array<DamageData>::type m_damageBuffer; //!< Buffered damage input
- uint32_t m_jointCount; //!< The number of joints referenced in m_jointList
- DList m_jointList; //!< A doubly-linked list of joint references
-
-//#if NV_PROFILE
- NvBlastTimers m_timers; //!< If profiling, each actor stores timing data
-//#endif
-
- friend class TkWorker; // m_damageBuffer and m_flags
- friend class TkGroupImpl;
- friend class TkFamilyImpl;
- friend class TkJointImpl;
- friend class TkFrameworkImpl;
-};
-
-
-//////// TkActorImpl inline methods ////////
-
-NV_INLINE TkFamilyImpl& TkActorImpl::getFamilyImpl() const
-{
- NVBLAST_ASSERT(m_family != nullptr);
-
- return *m_family;
-}
-
-
-NV_INLINE uint32_t TkActorImpl::getIndexInternal() const
-{
- NVBLAST_ASSERT(isActive());
- return NvBlastActorGetIndex(m_actorLL, logLL);
-}
-
-
-NV_INLINE NvBlastActor* TkActorImpl::getActorLLInternal() const
-{
- return m_actorLL;
-}
-
-
-NV_INLINE uint32_t TkActorImpl::getJointCountInternal() const
-{
- return m_jointCount;
-}
-
-
-NV_INLINE TkGroupImpl* TkActorImpl::getGroupImpl() const
-{
- return m_group;
-}
-
-
-NV_INLINE bool TkActorImpl::isActive() const
-{
- return m_actorLL != nullptr;
-}
-
-
-NV_INLINE bool TkActorImpl::isPending() const
-{
- return m_flags.isSet(TkActorFlag::PENDING);
-}
-
-
-NV_INLINE void TkActorImpl::addJoint(TkJointLink& jointLink)
-{
- NVBLAST_ASSERT(m_jointList.isSolitary(jointLink));
-
- m_jointList.insertHead(jointLink);
- ++m_jointCount;
-}
-
-
-NV_INLINE void TkActorImpl::removeJoint(TkJointLink& jointLink)
-{
- NVBLAST_ASSERT(!m_jointList.isSolitary(jointLink));
- NVBLAST_ASSERT(m_jointCount > 0);
- if (m_jointCount > 0)
- {
- --m_jointCount;
- m_jointList.remove(jointLink);
- }
-}
-
-
-//////// TkActorImpl::JointIt methods ////////
-
-NV_INLINE TkActorImpl::JointIt::JointIt(const TkActorImpl& actor, Direction dir) : DList::It(actor.m_jointList, dir) {}
-
-
-NV_INLINE TkJointImpl* TkActorImpl::JointIt::operator * () const
-{
- const DLink* link = (const DLink*)(*this);
- return reinterpret_cast<const TkJointLink*>(link)->m_joint;
-}
-
-} // namespace Blast
-} // namespace Nv
-
-
-#endif // ifndef NVBLASTTKACTORIMPL_H
+// 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) 2016-2018 NVIDIA Corporation. All rights reserved.
+
+
+#ifndef NVBLASTTKACTORIMPL_H
+#define NVBLASTTKACTORIMPL_H
+
+
+#include "NvBlastTkCommon.h"
+
+#include "NvBlastAssert.h"
+#include "NvBlastDLink.h"
+#include "NvBlastIteratorBase.h"
+
+#include "NvBlastTkJointImpl.h"
+
+#include "NvBlast.h"
+
+#include "NvBlastTkActor.h"
+
+#include "PxFlags.h"
+
+namespace Nv
+{
+namespace Blast
+{
+
+// Forward declarations:
+class TkGroupImpl;
+class TkFamilyImpl;
+class TkAssetImpl;
+class TkJointImpl;
+
+
+/**
+Struct-enum for actor status flags, used in TkGroup processing.
+*/
+struct TkActorFlag
+{
+ enum Enum
+ {
+ DAMAGED = (1 << 0), //!< The actor had fractures applied successfully and will take the split step.
+ PENDING = (1 << 1), //!< The actor will be processed when its group executes, used to update job queues when moving group.
+ };
+};
+
+
+/**
+Implementation of TkActor.
+*/
+class TkActorImpl : public TkActor
+{
+public:
+ TkActorImpl();
+ ~TkActorImpl();
+
+ // Begin TkActor
+ virtual const NvBlastActor* getActorLL() const override;
+
+ virtual TkFamily& getFamily() const override;
+
+ virtual uint32_t getIndex() const override;
+
+ virtual TkGroup* getGroup() const override;
+
+ virtual TkGroup* removeFromGroup() override;
+
+ virtual const TkAsset* getAsset() const override;
+
+ virtual uint32_t getVisibleChunkCount() const override;
+
+ virtual uint32_t getVisibleChunkIndices(uint32_t* visibleChunkIndices, uint32_t visibleChunkIndicesSize) const override;
+
+ virtual uint32_t getGraphNodeCount() const override;
+
+ virtual uint32_t getGraphNodeIndices(uint32_t* graphNodeIndices, uint32_t graphNodeIndicesSize) const override;
+
+ virtual const float* getBondHealths() const override;
+
+ virtual uint32_t getSplitMaxActorCount() const override;
+
+ virtual void damage(const NvBlastDamageProgram& program, const void* programParams) override;
+
+ virtual bool isPending() const override;
+
+ virtual void generateFracture(NvBlastFractureBuffers* commands, const NvBlastDamageProgram& program, const void* programParams) const override;
+
+ virtual void applyFracture(NvBlastFractureBuffers* eventBuffers, const NvBlastFractureBuffers* commands) override;
+
+ virtual uint32_t getJointCount() const override;
+
+ virtual uint32_t getJoints(TkJoint** joints, uint32_t jointsSize) const override;
+
+ virtual bool isBoundToWorld() const override;
+ // End TkActor
+
+ // Begin TkObject
+ virtual void release() override;
+ // End TkObject
+
+
+ // Public methods
+
+ /**
+ Factory create method.
+
+ \param[in] desc Actor descriptor set by the user.
+
+ \return a pointer to a new TkActorImpl object if successful, NULL otherwise.
+ */
+ static TkActorImpl* create(const TkActorDesc& desc);
+
+ /**
+ TkActorImpl objects are created in an array within a TkFamilyImpl. Actors may become
+ 'inactive' without their memory being freed. If inactive, the actor should be treated as if
+ it has been released.
+
+ \return the active status of this TkActorImpl.
+ */
+ bool isActive() const;
+
+ /**
+ Utility to return the low-level family to which the low-level actor belongs.
+
+ \return a pointer to the NvBlastFamily to which the low-level actor belongs.
+ */
+ NvBlastFamily* getFamilyLL() const;
+
+ /**
+ Utility to access the TkFamily to which this actor belongs.
+
+ \return a reference to the TkFamilyImpl to which this TkActorImpl belongs.
+ */
+ TkFamilyImpl& getFamilyImpl() const;
+
+ /**
+ \return the index of this actor with its TkFamilyImpl.
+ */
+ uint32_t getIndexInternal() const;
+
+ /**
+ Access to the group to which this actor belongs, if any.
+
+ \return a pointer to the TkGroupImpl to which this TkActorImpl belongs, if any. If this actor is not in a group, this function returns NULL.
+ */
+ TkGroupImpl* getGroupImpl() const;
+
+ /**
+ Access to the low-level actor associated with this TkActorImpl.
+
+ \return a pointer to the NvBlastActor associated with this TkActorImpl. If this actor is inactive (see isActive), this function returns NULL.
+ */
+ NvBlastActor* getActorLLInternal() const;
+
+ /**
+ \return the number of TkJointImpl objects that reference this actor.
+ */
+ uint32_t getJointCountInternal() const;
+
+ /**
+ Joint iterator. Usage:
+
+ Given a TkActorImpl a,
+
+ for (TkActorImpl::JointIt i(a); (bool)i; ++i)
+ {
+ TkJointImpl* joint = (TkJointImpl*)i;
+ // ...
+ }
+ */
+ class JointIt : public DList::It
+ {
+ public:
+ /** Constructed from an actor. */
+ JointIt(const TkActorImpl& actor, Direction dir = Forward);
+
+ /** Current joint. */
+ TkJointImpl* operator * () const;
+ };
+
+ /**
+ Implicit converter to TkActorData for events.
+ */
+ operator Nv::Blast::TkActorData() const;
+
+private:
+ /**
+ Functions to raise or check 'damaged' state: this actor will take the split step.
+ 'damaged' actors automatically become 'pending' also.
+ */
+ void markAsDamaged();
+ bool isDamaged() const;
+
+ /**
+ Raise actor to 'pending' state: this actor will be processed when its group executes next.
+ Enqueues the actor in its group's job list if a group is set. Otherwise the group will enqueue the actor when it is added.
+ */
+ void makePending();
+
+ /**
+ Functions to add or remove an internal reference to a joint. (Joints and actors mutually reference each other.)
+ */
+ void addJoint(TkJointLink& jointLink);
+ void removeJoint(TkJointLink& jointLink);
+
+ struct DamageData
+ {
+ NvBlastDamageProgram program;
+ const void* programParams;
+ };
+
+ // Data
+
+ NvBlastActor* m_actorLL; //!< The low-level actor associated with this actor
+ TkFamilyImpl* m_family; //!< The TkFamilyImpl to which this actor belongs
+ TkGroupImpl* m_group; //!< The TkGroupImpl (if any) to which this actor belongs
+ uint32_t m_groupJobIndex; //!< The index of this actor's job within its group's job list
+ physx::PxFlags<TkActorFlag::Enum, char> m_flags; //!< Status flags for this actor
+ Array<DamageData>::type m_damageBuffer; //!< Buffered damage input
+ uint32_t m_jointCount; //!< The number of joints referenced in m_jointList
+ DList m_jointList; //!< A doubly-linked list of joint references
+
+//#if NV_PROFILE
+ NvBlastTimers m_timers; //!< If profiling, each actor stores timing data
+//#endif
+
+ friend class TkWorker; // m_damageBuffer and m_flags
+ friend class TkGroupImpl;
+ friend class TkFamilyImpl;
+ friend class TkJointImpl;
+ friend class TkFrameworkImpl;
+};
+
+
+//////// TkActorImpl inline methods ////////
+
+NV_INLINE TkFamilyImpl& TkActorImpl::getFamilyImpl() const
+{
+ NVBLAST_ASSERT(m_family != nullptr);
+
+ return *m_family;
+}
+
+
+NV_INLINE uint32_t TkActorImpl::getIndexInternal() const
+{
+ NVBLAST_ASSERT(isActive());
+ return NvBlastActorGetIndex(m_actorLL, logLL);
+}
+
+
+NV_INLINE NvBlastActor* TkActorImpl::getActorLLInternal() const
+{
+ return m_actorLL;
+}
+
+
+NV_INLINE uint32_t TkActorImpl::getJointCountInternal() const
+{
+ return m_jointCount;
+}
+
+
+NV_INLINE TkGroupImpl* TkActorImpl::getGroupImpl() const
+{
+ return m_group;
+}
+
+
+NV_INLINE bool TkActorImpl::isActive() const
+{
+ return m_actorLL != nullptr;
+}
+
+
+NV_INLINE bool TkActorImpl::isPending() const
+{
+ return m_flags.isSet(TkActorFlag::PENDING);
+}
+
+
+NV_INLINE void TkActorImpl::addJoint(TkJointLink& jointLink)
+{
+ NVBLAST_ASSERT(m_jointList.isSolitary(jointLink));
+
+ m_jointList.insertHead(jointLink);
+ ++m_jointCount;
+}
+
+
+NV_INLINE void TkActorImpl::removeJoint(TkJointLink& jointLink)
+{
+ NVBLAST_ASSERT(!m_jointList.isSolitary(jointLink));
+ NVBLAST_ASSERT(m_jointCount > 0);
+ if (m_jointCount > 0)
+ {
+ --m_jointCount;
+ m_jointList.remove(jointLink);
+ }
+}
+
+
+//////// TkActorImpl::JointIt methods ////////
+
+NV_INLINE TkActorImpl::JointIt::JointIt(const TkActorImpl& actor, Direction dir) : DList::It(actor.m_jointList, dir) {}
+
+
+NV_INLINE TkJointImpl* TkActorImpl::JointIt::operator * () const
+{
+ const DLink* link = (const DLink*)(*this);
+ return reinterpret_cast<const TkJointLink*>(link)->m_joint;
+}
+
+} // namespace Blast
+} // namespace Nv
+
+
+#endif // ifndef NVBLASTTKACTORIMPL_H
diff --git a/sdk/toolkit/source/NvBlastTkAssetImpl.cpp b/sdk/toolkit/source/NvBlastTkAssetImpl.cpp
index 2f3b9cc..55c35d3 100644..100755
--- a/sdk/toolkit/source/NvBlastTkAssetImpl.cpp
+++ b/sdk/toolkit/source/NvBlastTkAssetImpl.cpp
@@ -1,276 +1,276 @@
-// 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) 2016-2018 NVIDIA Corporation. All rights reserved.
-
-
-#include "NvBlastTkFrameworkImpl.h"
-#include "NvBlastTkAssetImpl.h"
-#include "NvBlastTkFamilyImpl.h"
-
-#include "NvBlast.h"
-#include "NvBlastMemory.h"
-
-
-namespace Nv
-{
-namespace Blast
-{
-
-//////// Static data ////////
-
-NVBLASTTK_DEFINE_TYPE_IDENTIFIABLE(Asset);
-
-
-//////// Member functions ////////
-
-TkAssetImpl::TkAssetImpl()
- : m_assetLL(nullptr), m_ownsAsset(false)
-{
-}
-
-
-TkAssetImpl::TkAssetImpl(const NvBlastID& id)
- : TkAssetType(id), m_assetLL(nullptr), m_ownsAsset(false)
-{
-}
-
-
-TkAssetImpl::~TkAssetImpl()
-{
- if (m_assetLL != nullptr && m_ownsAsset)
- {
- NVBLAST_FREE(m_assetLL);
- }
-}
-
-
-const NvBlastAsset* TkAssetImpl::getAssetLL() const
-{
- return getAssetLLInternal();
-}
-
-
-uint32_t TkAssetImpl::getChunkCount() const
-{
- return NvBlastAssetGetChunkCount(m_assetLL, logLL);
-}
-
-
-uint32_t TkAssetImpl::getLeafChunkCount() const
-{
- return NvBlastAssetGetLeafChunkCount(m_assetLL, logLL);
-}
-
-
-uint32_t TkAssetImpl::getBondCount() const
-{
- return NvBlastAssetGetBondCount(m_assetLL, logLL);
-}
-
-
-const NvBlastChunk* TkAssetImpl::getChunks() const
-{
- return NvBlastAssetGetChunks(m_assetLL, logLL);
-}
-
-
-const NvBlastBond* TkAssetImpl::getBonds() const
-{
- return NvBlastAssetGetBonds(m_assetLL, logLL);
-}
-
-
-const NvBlastSupportGraph TkAssetImpl::getGraph() const
-{
- return NvBlastAssetGetSupportGraph(m_assetLL, logLL);
-}
-
-
-uint32_t TkAssetImpl::getDataSize() const
-{
- return NvBlastAssetGetSize(m_assetLL, logLL);
-}
-
-
-uint32_t TkAssetImpl::getJointDescCount() const
-{
- return getJointDescCountInternal();
-}
-
-
-const TkAssetJointDesc* TkAssetImpl::getJointDescs() const
-{
- return getJointDescsInternal();
-}
-
-
-void TkAssetImpl::release()
-{
- const TkType& tkType = TkFamilyImpl::s_type;
- const uint32_t num = TkFrameworkImpl::get()->getObjectCount(tkType);
-
- if (num)
- {
- Array<TkIdentifiable*>::type dependents(num);
- TkFrameworkImpl::get()->getObjects(dependents.begin(), dependents.size(), tkType);
-
- for (TkObject* o : dependents)
- {
- TkFamilyImpl* f = static_cast<TkFamilyImpl*>(o);
- if (f->getAssetImpl() == this)
- {
- f->release();
- }
- }
- }
-
- NVBLAST_DELETE(this, TkAssetImpl);
-}
-
-
-//////// Static functions ////////
-
-TkAssetImpl* TkAssetImpl::create(const TkAssetDesc& desc)
-{
- TkAssetImpl* asset = NVBLAST_NEW(TkAssetImpl);
-
- Array<char>::type scratch((uint32_t)NvBlastGetRequiredScratchForCreateAsset(&desc, logLL));
- void* mem = NVBLAST_ALLOC_NAMED(NvBlastGetAssetMemorySize(&desc, logLL), "TkAssetImpl::create");
- asset->m_assetLL = NvBlastCreateAsset(mem, &desc, scratch.begin(), logLL);
- if (asset->m_assetLL == nullptr)
- {
- NVBLAST_LOG_ERROR("TkAssetImpl::create: low-level asset could not be created.");
- asset->release();
- return nullptr;
- }
-
- if (desc.bondFlags != nullptr)
- {
- for (uint32_t bondN = 0; bondN < desc.bondCount; ++bondN)
- {
- if (0 != (desc.bondFlags[bondN] & TkAssetDesc::BondJointed))
- {
- const NvBlastBondDesc& bondDesc = desc.bondDescs[bondN];
- const uint32_t c0 = bondDesc.chunkIndices[0];
- const uint32_t c1 = bondDesc.chunkIndices[1];
- if (c0 >= desc.chunkCount || c1 >= desc.chunkCount)
- {
- NVBLAST_LOG_WARNING("TkAssetImpl::create: joint flag set for badly described bond. No joint descriptor created.");
- continue;
- }
-
- if (!asset->addJointDesc(c0, c1))
- {
- NVBLAST_LOG_WARNING("TkAssetImpl::create: no bond corresponds to the user-described bond indices. No joint descriptor created.");
- }
- }
- }
- }
-
- asset->m_ownsAsset = true;
-// asset->setID(NvBlastAssetGetID(asset->m_assetLL, logLL)); // Keeping LL and Tk IDs distinct
-
- return asset;
-}
-
-
-TkAssetImpl* TkAssetImpl::create(const NvBlastAsset* assetLL, Nv::Blast::TkAssetJointDesc* jointDescs, uint32_t jointDescCount, bool ownsAsset)
-{
- TkAssetImpl* asset = NVBLAST_NEW(TkAssetImpl);
-
- //NOTE: Why are we passing in a const NvBlastAsset* and then discarding the const?
- asset->m_assetLL = const_cast<NvBlastAsset*>(assetLL);
- if (asset->m_assetLL == nullptr)
- {
- NVBLAST_LOG_ERROR("TkAssetImpl::create: low-level asset could not be created.");
- asset->release();
- return nullptr;
- }
-
- asset->m_ownsAsset = ownsAsset;
- asset->setID(NvBlastAssetGetID(asset->m_assetLL, logLL));
-
- asset->m_jointDescs.resize(jointDescCount);
- for (uint32_t i = 0; i < asset->m_jointDescs.size(); ++i)
- {
- asset->m_jointDescs[i] = jointDescs[i];
- }
-
- return asset;
-}
-
-bool TkAssetImpl::addJointDesc(uint32_t chunkIndex0, uint32_t chunkIndex1)
-{
- if (m_assetLL == nullptr)
- {
- return false;
- }
-
- const uint32_t upperSupportChunkCount = NvBlastAssetGetFirstSubsupportChunkIndex(m_assetLL, logLL);
- if (chunkIndex0 >= upperSupportChunkCount || chunkIndex1 >= upperSupportChunkCount)
- {
- return false;
- }
-
- const uint32_t* chunkToGraphNodeMap = NvBlastAssetGetChunkToGraphNodeMap(m_assetLL, logLL);
- const uint32_t node0 = chunkToGraphNodeMap[chunkIndex0];
- const uint32_t node1 = chunkToGraphNodeMap[chunkIndex1];
- const NvBlastSupportGraph graph = NvBlastAssetGetSupportGraph(m_assetLL, logLL);
- if (node0 >= graph.nodeCount && node1 >= graph.nodeCount)
- {
- return false;
- }
-
- // Find bond index
- // Iterate through all neighbors of node0 chunk
- uint32_t bondIndex = 0xFFFFFFFF;
- for (uint32_t i = graph.adjacencyPartition[node0]; i < graph.adjacencyPartition[node0 + 1]; i++)
- {
- if (graph.adjacentNodeIndices[i] == node1)
- {
- bondIndex = graph.adjacentBondIndices[i];
- break;
- }
- }
-
- if (bondIndex >= NvBlastAssetGetBondCount(m_assetLL, logLL))
- {
- return false;
- }
-
- const NvBlastBond& bond = NvBlastAssetGetBonds(m_assetLL, logLL)[bondIndex];
-
- TkAssetJointDesc jointDesc;
- jointDesc.attachPositions[0] = jointDesc.attachPositions[1] = physx::PxVec3(bond.centroid[0], bond.centroid[1], bond.centroid[2]);
- jointDesc.nodeIndices[0] = node0;
- jointDesc.nodeIndices[1] = node1;
- m_jointDescs.pushBack(jointDesc);
-
- return true;
-}
-
-} // namespace Blast
-} // namespace Nv
+// 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) 2016-2018 NVIDIA Corporation. All rights reserved.
+
+
+#include "NvBlastTkFrameworkImpl.h"
+#include "NvBlastTkAssetImpl.h"
+#include "NvBlastTkFamilyImpl.h"
+
+#include "NvBlast.h"
+#include "NvBlastMemory.h"
+
+
+namespace Nv
+{
+namespace Blast
+{
+
+//////// Static data ////////
+
+NVBLASTTK_DEFINE_TYPE_IDENTIFIABLE(Asset);
+
+
+//////// Member functions ////////
+
+TkAssetImpl::TkAssetImpl()
+ : m_assetLL(nullptr), m_ownsAsset(false)
+{
+}
+
+
+TkAssetImpl::TkAssetImpl(const NvBlastID& id)
+ : TkAssetType(id), m_assetLL(nullptr), m_ownsAsset(false)
+{
+}
+
+
+TkAssetImpl::~TkAssetImpl()
+{
+ if (m_assetLL != nullptr && m_ownsAsset)
+ {
+ NVBLAST_FREE(m_assetLL);
+ }
+}
+
+
+const NvBlastAsset* TkAssetImpl::getAssetLL() const
+{
+ return getAssetLLInternal();
+}
+
+
+uint32_t TkAssetImpl::getChunkCount() const
+{
+ return NvBlastAssetGetChunkCount(m_assetLL, logLL);
+}
+
+
+uint32_t TkAssetImpl::getLeafChunkCount() const
+{
+ return NvBlastAssetGetLeafChunkCount(m_assetLL, logLL);
+}
+
+
+uint32_t TkAssetImpl::getBondCount() const
+{
+ return NvBlastAssetGetBondCount(m_assetLL, logLL);
+}
+
+
+const NvBlastChunk* TkAssetImpl::getChunks() const
+{
+ return NvBlastAssetGetChunks(m_assetLL, logLL);
+}
+
+
+const NvBlastBond* TkAssetImpl::getBonds() const
+{
+ return NvBlastAssetGetBonds(m_assetLL, logLL);
+}
+
+
+const NvBlastSupportGraph TkAssetImpl::getGraph() const
+{
+ return NvBlastAssetGetSupportGraph(m_assetLL, logLL);
+}
+
+
+uint32_t TkAssetImpl::getDataSize() const
+{
+ return NvBlastAssetGetSize(m_assetLL, logLL);
+}
+
+
+uint32_t TkAssetImpl::getJointDescCount() const
+{
+ return getJointDescCountInternal();
+}
+
+
+const TkAssetJointDesc* TkAssetImpl::getJointDescs() const
+{
+ return getJointDescsInternal();
+}
+
+
+void TkAssetImpl::release()
+{
+ const TkType& tkType = TkFamilyImpl::s_type;
+ const uint32_t num = TkFrameworkImpl::get()->getObjectCount(tkType);
+
+ if (num)
+ {
+ Array<TkIdentifiable*>::type dependents(num);
+ TkFrameworkImpl::get()->getObjects(dependents.begin(), dependents.size(), tkType);
+
+ for (TkObject* o : dependents)
+ {
+ TkFamilyImpl* f = static_cast<TkFamilyImpl*>(o);
+ if (f->getAssetImpl() == this)
+ {
+ f->release();
+ }
+ }
+ }
+
+ NVBLAST_DELETE(this, TkAssetImpl);
+}
+
+
+//////// Static functions ////////
+
+TkAssetImpl* TkAssetImpl::create(const TkAssetDesc& desc)
+{
+ TkAssetImpl* asset = NVBLAST_NEW(TkAssetImpl);
+
+ Array<char>::type scratch((uint32_t)NvBlastGetRequiredScratchForCreateAsset(&desc, logLL));
+ void* mem = NVBLAST_ALLOC_NAMED(NvBlastGetAssetMemorySize(&desc, logLL), "TkAssetImpl::create");
+ asset->m_assetLL = NvBlastCreateAsset(mem, &desc, scratch.begin(), logLL);
+ if (asset->m_assetLL == nullptr)
+ {
+ NVBLAST_LOG_ERROR("TkAssetImpl::create: low-level asset could not be created.");
+ asset->release();
+ return nullptr;
+ }
+
+ if (desc.bondFlags != nullptr)
+ {
+ for (uint32_t bondN = 0; bondN < desc.bondCount; ++bondN)
+ {
+ if (0 != (desc.bondFlags[bondN] & TkAssetDesc::BondJointed))
+ {
+ const NvBlastBondDesc& bondDesc = desc.bondDescs[bondN];
+ const uint32_t c0 = bondDesc.chunkIndices[0];
+ const uint32_t c1 = bondDesc.chunkIndices[1];
+ if (c0 >= desc.chunkCount || c1 >= desc.chunkCount)
+ {
+ NVBLAST_LOG_WARNING("TkAssetImpl::create: joint flag set for badly described bond. No joint descriptor created.");
+ continue;
+ }
+
+ if (!asset->addJointDesc(c0, c1))
+ {
+ NVBLAST_LOG_WARNING("TkAssetImpl::create: no bond corresponds to the user-described bond indices. No joint descriptor created.");
+ }
+ }
+ }
+ }
+
+ asset->m_ownsAsset = true;
+// asset->setID(NvBlastAssetGetID(asset->m_assetLL, logLL)); // Keeping LL and Tk IDs distinct
+
+ return asset;
+}
+
+
+TkAssetImpl* TkAssetImpl::create(const NvBlastAsset* assetLL, Nv::Blast::TkAssetJointDesc* jointDescs, uint32_t jointDescCount, bool ownsAsset)
+{
+ TkAssetImpl* asset = NVBLAST_NEW(TkAssetImpl);
+
+ //NOTE: Why are we passing in a const NvBlastAsset* and then discarding the const?
+ asset->m_assetLL = const_cast<NvBlastAsset*>(assetLL);
+ if (asset->m_assetLL == nullptr)
+ {
+ NVBLAST_LOG_ERROR("TkAssetImpl::create: low-level asset could not be created.");
+ asset->release();
+ return nullptr;
+ }
+
+ asset->m_ownsAsset = ownsAsset;
+ asset->setID(NvBlastAssetGetID(asset->m_assetLL, logLL));
+
+ asset->m_jointDescs.resize(jointDescCount);
+ for (uint32_t i = 0; i < asset->m_jointDescs.size(); ++i)
+ {
+ asset->m_jointDescs[i] = jointDescs[i];
+ }
+
+ return asset;
+}
+
+bool TkAssetImpl::addJointDesc(uint32_t chunkIndex0, uint32_t chunkIndex1)
+{
+ if (m_assetLL == nullptr)
+ {
+ return false;
+ }
+
+ const uint32_t upperSupportChunkCount = NvBlastAssetGetFirstSubsupportChunkIndex(m_assetLL, logLL);
+ if (chunkIndex0 >= upperSupportChunkCount || chunkIndex1 >= upperSupportChunkCount)
+ {
+ return false;
+ }
+
+ const uint32_t* chunkToGraphNodeMap = NvBlastAssetGetChunkToGraphNodeMap(m_assetLL, logLL);
+ const uint32_t node0 = chunkToGraphNodeMap[chunkIndex0];
+ const uint32_t node1 = chunkToGraphNodeMap[chunkIndex1];
+ const NvBlastSupportGraph graph = NvBlastAssetGetSupportGraph(m_assetLL, logLL);
+ if (node0 >= graph.nodeCount && node1 >= graph.nodeCount)
+ {
+ return false;
+ }
+
+ // Find bond index
+ // Iterate through all neighbors of node0 chunk
+ uint32_t bondIndex = 0xFFFFFFFF;
+ for (uint32_t i = graph.adjacencyPartition[node0]; i < graph.adjacencyPartition[node0 + 1]; i++)
+ {
+ if (graph.adjacentNodeIndices[i] == node1)
+ {
+ bondIndex = graph.adjacentBondIndices[i];
+ break;
+ }
+ }
+
+ if (bondIndex >= NvBlastAssetGetBondCount(m_assetLL, logLL))
+ {
+ return false;
+ }
+
+ const NvBlastBond& bond = NvBlastAssetGetBonds(m_assetLL, logLL)[bondIndex];
+
+ TkAssetJointDesc jointDesc;
+ jointDesc.attachPositions[0] = jointDesc.attachPositions[1] = physx::PxVec3(bond.centroid[0], bond.centroid[1], bond.centroid[2]);
+ jointDesc.nodeIndices[0] = node0;
+ jointDesc.nodeIndices[1] = node1;
+ m_jointDescs.pushBack(jointDesc);
+
+ return true;
+}
+
+} // namespace Blast
+} // namespace Nv
diff --git a/sdk/toolkit/source/NvBlastTkAssetImpl.h b/sdk/toolkit/source/NvBlastTkAssetImpl.h
index 8c7b597..3ae9cfc 100644..100755
--- a/sdk/toolkit/source/NvBlastTkAssetImpl.h
+++ b/sdk/toolkit/source/NvBlastTkAssetImpl.h
@@ -1,163 +1,163 @@
-// 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) 2016-2018 NVIDIA Corporation. All rights reserved.
-
-
-#ifndef NVBLASTTKASSETIMPL_H
-#define NVBLASTTKASSETIMPL_H
-
-
-#include "NvBlastTkCommon.h"
-#include "NvBlastTkJoint.h"
-#include "NvBlastTkAsset.h"
-#include "NvBlastTkTypeImpl.h"
-#include "NvBlastArray.h"
-
-
-// Forward declarations
-struct NvBlastAsset;
-
-
-namespace Nv
-{
-namespace Blast
-{
-
-/**
-Implementation of TkAsset
-*/
-NVBLASTTK_IMPL_DECLARE(Asset)
-{
-public:
- TkAssetImpl();
- TkAssetImpl(const NvBlastID& id);
- ~TkAssetImpl();
-
- NVBLASTTK_IMPL_DEFINE_IDENTIFIABLE('A', 'S', 'S', 'T');
-
- // Public methods
-
- /**
- Factory create method. This method creates a low-level asset and stores a reference to it.
-
- \param[in] desc Asset descriptor set by the user.
-
- \return a pointer to a new TkAssetImpl object if successful, NULL otherwise.
- */
- static TkAssetImpl* create(const TkAssetDesc& desc);
-
- /**
- Static method to create an asset from an existing low-level asset.
-
- \param[in] assetLL A valid low-level asset passed in by the user.
- \param[in] jointDescs Optional joint descriptors to add to the new asset.
- \param[in] jointDescCount The number of joint descriptors in the jointDescs array. If non-zero, jointDescs cannot be NULL.
- \param[in] ownsAsset Whether or not to let this TkAssetImpl object release the low-level NvBlastAsset memory upon its own release.
-
- \return a pointer to a new TkAssetImpl object if successful, NULL otherwise.
- */
- static TkAssetImpl* create(const NvBlastAsset* assetLL, Nv::Blast::TkAssetJointDesc* jointDescs = nullptr, uint32_t jointDescCount = 0, bool ownsAsset = false);
-
- /**
- \return a pointer to the underlying low-level NvBlastAsset associated with this asset.
- */
- const NvBlastAsset* getAssetLLInternal() const;
-
- /**
- \return the number of internal joint descriptors stored with this asset.
- */
- uint32_t getJointDescCountInternal() const;
-
- /**
- \return the array of internal joint descriptors stored with this asset, with size given by getJointDescCountInternal().
- */
- const TkAssetJointDesc* getJointDescsInternal() const;
-
- // Begin TkAsset
- virtual const NvBlastAsset* getAssetLL() const override;
-
- virtual uint32_t getChunkCount() const override;
-
- virtual uint32_t getLeafChunkCount() const override;
-
- virtual uint32_t getBondCount() const override;
-
- virtual const NvBlastChunk* getChunks() const override;
-
- virtual const NvBlastBond* getBonds() const override;
-
- virtual const NvBlastSupportGraph getGraph() const override;
-
- virtual uint32_t getDataSize() const override;
-
- virtual uint32_t getJointDescCount() const override;
-
- virtual const TkAssetJointDesc* getJointDescs() const override;
- // End TkAsset
-
-private:
- /**
- Utility to add a joint descriptor between the indexed chunks. The two chunks
- must be support chunks, and there must exist a bond between them. The joint's
- attachment positions will be the bond centroid.
-
- \param[in] chunkIndex0 The first chunk index.
- \param[in] chunkIndex1 The second chunk index.
-
- \return true iff successful.
- */
- bool addJointDesc(uint32_t chunkIndex0, uint32_t chunkIndex1);
-
- NvBlastAsset* m_assetLL; //!< The underlying low-level asset.
- Array<TkAssetJointDesc>::type m_jointDescs; //!< The array of internal joint descriptors.
- bool m_ownsAsset; //!< Whether or not this asset should release its low-level asset upon its own release.
-};
-
-
-//////// TkAssetImpl inline methods ////////
-
-NV_INLINE const NvBlastAsset* TkAssetImpl::getAssetLLInternal() const
-{
- return m_assetLL;
-}
-
-
-NV_INLINE uint32_t TkAssetImpl::getJointDescCountInternal() const
-{
- return m_jointDescs.size();
-}
-
-
-NV_INLINE const TkAssetJointDesc* TkAssetImpl::getJointDescsInternal() const
-{
- return m_jointDescs.begin();
-}
-
-} // namespace Blast
-} // namespace Nv
-
-
-#endif // ifndef NVBLASTTKASSETIMPL_H
+// 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) 2016-2018 NVIDIA Corporation. All rights reserved.
+
+
+#ifndef NVBLASTTKASSETIMPL_H
+#define NVBLASTTKASSETIMPL_H
+
+
+#include "NvBlastTkCommon.h"
+#include "NvBlastTkJoint.h"
+#include "NvBlastTkAsset.h"
+#include "NvBlastTkTypeImpl.h"
+#include "NvBlastArray.h"
+
+
+// Forward declarations
+struct NvBlastAsset;
+
+
+namespace Nv
+{
+namespace Blast
+{
+
+/**
+Implementation of TkAsset
+*/
+NVBLASTTK_IMPL_DECLARE(Asset)
+{
+public:
+ TkAssetImpl();
+ TkAssetImpl(const NvBlastID& id);
+ ~TkAssetImpl();
+
+ NVBLASTTK_IMPL_DEFINE_IDENTIFIABLE('A', 'S', 'S', 'T');
+
+ // Public methods
+
+ /**
+ Factory create method. This method creates a low-level asset and stores a reference to it.
+
+ \param[in] desc Asset descriptor set by the user.
+
+ \return a pointer to a new TkAssetImpl object if successful, NULL otherwise.
+ */
+ static TkAssetImpl* create(const TkAssetDesc& desc);
+
+ /**
+ Static method to create an asset from an existing low-level asset.
+
+ \param[in] assetLL A valid low-level asset passed in by the user.
+ \param[in] jointDescs Optional joint descriptors to add to the new asset.
+ \param[in] jointDescCount The number of joint descriptors in the jointDescs array. If non-zero, jointDescs cannot be NULL.
+ \param[in] ownsAsset Whether or not to let this TkAssetImpl object release the low-level NvBlastAsset memory upon its own release.
+
+ \return a pointer to a new TkAssetImpl object if successful, NULL otherwise.
+ */
+ static TkAssetImpl* create(const NvBlastAsset* assetLL, Nv::Blast::TkAssetJointDesc* jointDescs = nullptr, uint32_t jointDescCount = 0, bool ownsAsset = false);
+
+ /**
+ \return a pointer to the underlying low-level NvBlastAsset associated with this asset.
+ */
+ const NvBlastAsset* getAssetLLInternal() const;
+
+ /**
+ \return the number of internal joint descriptors stored with this asset.
+ */
+ uint32_t getJointDescCountInternal() const;
+
+ /**
+ \return the array of internal joint descriptors stored with this asset, with size given by getJointDescCountInternal().
+ */
+ const TkAssetJointDesc* getJointDescsInternal() const;
+
+ // Begin TkAsset
+ virtual const NvBlastAsset* getAssetLL() const override;
+
+ virtual uint32_t getChunkCount() const override;
+
+ virtual uint32_t getLeafChunkCount() const override;
+
+ virtual uint32_t getBondCount() const override;
+
+ virtual const NvBlastChunk* getChunks() const override;
+
+ virtual const NvBlastBond* getBonds() const override;
+
+ virtual const NvBlastSupportGraph getGraph() const override;
+
+ virtual uint32_t getDataSize() const override;
+
+ virtual uint32_t getJointDescCount() const override;
+
+ virtual const TkAssetJointDesc* getJointDescs() const override;
+ // End TkAsset
+
+private:
+ /**
+ Utility to add a joint descriptor between the indexed chunks. The two chunks
+ must be support chunks, and there must exist a bond between them. The joint's
+ attachment positions will be the bond centroid.
+
+ \param[in] chunkIndex0 The first chunk index.
+ \param[in] chunkIndex1 The second chunk index.
+
+ \return true iff successful.
+ */
+ bool addJointDesc(uint32_t chunkIndex0, uint32_t chunkIndex1);
+
+ NvBlastAsset* m_assetLL; //!< The underlying low-level asset.
+ Array<TkAssetJointDesc>::type m_jointDescs; //!< The array of internal joint descriptors.
+ bool m_ownsAsset; //!< Whether or not this asset should release its low-level asset upon its own release.
+};
+
+
+//////// TkAssetImpl inline methods ////////
+
+NV_INLINE const NvBlastAsset* TkAssetImpl::getAssetLLInternal() const
+{
+ return m_assetLL;
+}
+
+
+NV_INLINE uint32_t TkAssetImpl::getJointDescCountInternal() const
+{
+ return m_jointDescs.size();
+}
+
+
+NV_INLINE const TkAssetJointDesc* TkAssetImpl::getJointDescsInternal() const
+{
+ return m_jointDescs.begin();
+}
+
+} // namespace Blast
+} // namespace Nv
+
+
+#endif // ifndef NVBLASTTKASSETIMPL_H
diff --git a/sdk/toolkit/source/NvBlastTkCommon.h b/sdk/toolkit/source/NvBlastTkCommon.h
index f38b1a5..372a911 100644..100755
--- a/sdk/toolkit/source/NvBlastTkCommon.h
+++ b/sdk/toolkit/source/NvBlastTkCommon.h
@@ -1,107 +1,107 @@
-// 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) 2016-2018 NVIDIA Corporation. All rights reserved.
-
-
-#ifndef NVBLASTTKCOMMON_H
-#define NVBLASTTKCOMMON_H
-
-
-#include "NvBlastGlobals.h"
-#include "NvBlastTkGUID.h"
-
-
-// Macro to define standard object classes. An intermediate class is defined which holds common implementations.
-#define NVBLASTTK_IMPL_DECLARE(_name) \
-class Tk##_name##Type : public Tk##_name \
-{ \
-public: \
- /* Blank constructor generates a new NvBlastID and informs framework */ \
- Tk##_name##Type() \
- { \
- memset(&m_ID, 0, sizeof(NvBlastID)); \
- setID(TkGenerateGUID(this)); \
- TkFrameworkImpl::get()->onCreate(*this); \
- } \
- \
- /* This constructor takes an existing NvBlastID and informs framework */ \
- Tk##_name##Type(const NvBlastID& id) \
- { \
- memset(&m_ID, 0, sizeof(NvBlastID)); \
- setID(id); \
- TkFrameworkImpl::get()->onCreate(*this); \
- } \
- \
- /* Destructor informs framework */ \
- ~Tk##_name##Type() { TkFrameworkImpl::get()->onDestroy(*this); } \
- \
- /* Begin TkIdentifiable */ \
- virtual void setID(const NvBlastID& id) override \
- { \
- /* Inform framework of ID change */ \
- TkFrameworkImpl::get()->onIDChange(*this, m_ID, id); \
- m_ID = id; \
- } \
- virtual const NvBlastID& getID() const override { return getIDInternal(); } \
- virtual const TkType& getType() const override { return s_type; } \
- /* End TkIdentifiable */ \
- \
- /* Begin public API */ \
- \
- /* Inline method for internal access to NvBlastID */ \
- const NvBlastID& getIDInternal() const { return m_ID; } \
- \
- /* End public API */ \
- \
- /* Static type information */ \
- static TkTypeImpl s_type; \
- \
-private: \
- NvBlastID m_ID; /* NvBlastID for a TkIdentifiable object */ \
-}; \
- \
-/* Derive object implementation from common implementation class above */ \
-class Tk##_name##Impl final : public Tk##_name##Type
-
-
-// Macro to declare standard object interfaces, enums, etc.
-#define NVBLASTTK_IMPL_DEFINE_IDENTIFIABLE(_id0, _id1, _id2, _id3) \
- /* Begin TkObject */ \
- virtual void release() override; \
- /* End TkObject */ \
- \
- /* Enums */ \
- \
- /* Generate a ClassID enum used to identify this TkIdentifiable. */ \
- enum { ClassID = NVBLAST_FOURCC(_id0, _id1, _id2, _id3) }
-
-
-// Macro to define class type data
-#define NVBLASTTK_DEFINE_TYPE_IDENTIFIABLE(_name) \
- TkTypeImpl Tk##_name##Type::s_type("Tk" #_name, Tk##_name##Impl::ClassID, 0)
-
-
-#endif // ifndef NVBLASTTKCOMMON_H
+// 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) 2016-2018 NVIDIA Corporation. All rights reserved.
+
+
+#ifndef NVBLASTTKCOMMON_H
+#define NVBLASTTKCOMMON_H
+
+
+#include "NvBlastGlobals.h"
+#include "NvBlastTkGUID.h"
+
+
+// Macro to define standard object classes. An intermediate class is defined which holds common implementations.
+#define NVBLASTTK_IMPL_DECLARE(_name) \
+class Tk##_name##Type : public Tk##_name \
+{ \
+public: \
+ /* Blank constructor generates a new NvBlastID and informs framework */ \
+ Tk##_name##Type() \
+ { \
+ memset(&m_ID, 0, sizeof(NvBlastID)); \
+ setID(TkGenerateGUID(this)); \
+ TkFrameworkImpl::get()->onCreate(*this); \
+ } \
+ \
+ /* This constructor takes an existing NvBlastID and informs framework */ \
+ Tk##_name##Type(const NvBlastID& id) \
+ { \
+ memset(&m_ID, 0, sizeof(NvBlastID)); \
+ setID(id); \
+ TkFrameworkImpl::get()->onCreate(*this); \
+ } \
+ \
+ /* Destructor informs framework */ \
+ ~Tk##_name##Type() { TkFrameworkImpl::get()->onDestroy(*this); } \
+ \
+ /* Begin TkIdentifiable */ \
+ virtual void setID(const NvBlastID& id) override \
+ { \
+ /* Inform framework of ID change */ \
+ TkFrameworkImpl::get()->onIDChange(*this, m_ID, id); \
+ m_ID = id; \
+ } \
+ virtual const NvBlastID& getID() const override { return getIDInternal(); } \
+ virtual const TkType& getType() const override { return s_type; } \
+ /* End TkIdentifiable */ \
+ \
+ /* Begin public API */ \
+ \
+ /* Inline method for internal access to NvBlastID */ \
+ const NvBlastID& getIDInternal() const { return m_ID; } \
+ \
+ /* End public API */ \
+ \
+ /* Static type information */ \
+ static TkTypeImpl s_type; \
+ \
+private: \
+ NvBlastID m_ID; /* NvBlastID for a TkIdentifiable object */ \
+}; \
+ \
+/* Derive object implementation from common implementation class above */ \
+class Tk##_name##Impl final : public Tk##_name##Type
+
+
+// Macro to declare standard object interfaces, enums, etc.
+#define NVBLASTTK_IMPL_DEFINE_IDENTIFIABLE(_id0, _id1, _id2, _id3) \
+ /* Begin TkObject */ \
+ virtual void release() override; \
+ /* End TkObject */ \
+ \
+ /* Enums */ \
+ \
+ /* Generate a ClassID enum used to identify this TkIdentifiable. */ \
+ enum { ClassID = NVBLAST_FOURCC(_id0, _id1, _id2, _id3) }
+
+
+// Macro to define class type data
+#define NVBLASTTK_DEFINE_TYPE_IDENTIFIABLE(_name) \
+ TkTypeImpl Tk##_name##Type::s_type("Tk" #_name, Tk##_name##Impl::ClassID, 0)
+
+
+#endif // ifndef NVBLASTTKCOMMON_H
diff --git a/sdk/toolkit/source/NvBlastTkEventQueue.h b/sdk/toolkit/source/NvBlastTkEventQueue.h
index 2e56a89..86d793f 100644..100755
--- a/sdk/toolkit/source/NvBlastTkEventQueue.h
+++ b/sdk/toolkit/source/NvBlastTkEventQueue.h
@@ -1,248 +1,248 @@
-// 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) 2016-2018 NVIDIA Corporation. All rights reserved.
-
-
-#ifndef NVBLASTTKEVENTQUEUE_H
-#define NVBLASTTKEVENTQUEUE_H
-
-#include <algorithm>
-#include <vector>
-
-#include <mutex>
-#include <atomic>
-
-#include "NvBlastTkFrameworkImpl.h"
-#include "NvBlastAssert.h"
-
-
-namespace Nv {
-namespace Blast {
-
-/**
-A dispatcher queue providing preallocation and thread-safe insertions therein.
-
-Typical usage:
-- preallocate space for events and payload:
- - reserveEvents, reserveData
-- enable asserts to detect undersized storage (allocations are not thread safe):
- - protect(true)
-- get pointers to payload data and events to fill in, thread safe for preallocated memory:
- - allocData, addEvent
-- back on main thread, ensure consistency:
- - protect(false)
-
-- continue adding events and payload on main thread if necessary like above (allocations are safe here)
-eventually dispatch, or reset if dispatched by proxy
-*/
-class TkEventQueue
-{
-public:
- TkEventQueue() : m_currentEvent(0), m_poolCapacity(0), m_pool(nullptr), m_allowAllocs(true) {}
-
- /**
- Peek events queue for dispatch.
- Do not use in protected state.
- */
- operator const Array<TkEvent>::type&()
- {
- NVBLAST_ASSERT(m_allowAllocs);
- NVBLAST_ASSERT(m_currentEvent == m_events.size());
- return m_events;
- }
-
- /**
- Debug help to catch (unwanted) allocations during task work.
- Note that this will not actually avoid allocations, but assert in debug builds.
-
- Set true before using in distributed environment.
- Set false to return to single-thread mode.
- */
- void protect(bool enable)
- {
- // During parallel use, m_events.size() and m_currentEvent are allowed to diverge.
- // This is fine because resizeUninitialized does not alter the stored data.
- NVBLAST_ASSERT(m_currentEvent <= m_events.capacity());
- m_events.resizeUninitialized(m_currentEvent);
- m_allowAllocs = !enable;
- }
-
- /**
- Restores initial state.
- Data memory is currently not being reused. To be improved.
- */
- void reset()
- {
- m_events.clear();
- m_currentEvent = 0;
- for (void* mem : m_memory)
- {
- NVBLAST_FREE(mem);
- }
- m_memory.clear();
- m_currentData = 0;
- m_allowAllocs = true;
- m_poolCapacity = 0;
- m_pool = nullptr;
- }
-
- /**
- Queue an event with a payload.
- */
- template<class T>
- void addEvent(T* payload)
- {
- uint32_t index = m_currentEvent.fetch_add(1);
-
- // Should not allocate in protected state.
- NVBLAST_ASSERT(m_allowAllocs || m_currentEvent <= m_events.capacity());
-
- m_events.resizeUninitialized(m_currentEvent);
-
- // During parallel use, m_events.size() and m_currentEvent are allowed to diverge.
- // Consistency is restored in protect().
- NVBLAST_ASSERT(!m_allowAllocs || m_currentEvent == m_events.size());
-
- TkEvent& evt = m_events[index];
- evt.type = TkEvent::Type(T::EVENT_TYPE);
- evt.payload = payload;
- }
-
- /**
- Request storage for payload.
- */
- template<typename T>
- T* allocData()
- {
- uint32_t index = m_currentData.fetch_add(sizeof(T));
- if (m_currentData <= m_poolCapacity)
- {
- return reinterpret_cast<T*>(&m_pool[index]);
- }
- else
- {
- // Could do larger block allocation here.
- reserveData(sizeof(T));
- // Account for the requested size.
- m_currentData = sizeof(T);
- return reinterpret_cast<T*>(&m_pool[0]);
- }
- }
-
- /**
- Preallocate a memory block of size Bytes for payload data.
- Note that this will inevitably allocate a new memory block.
- Subsequent calls to allocData will use this memory piecewise.
- */
- void reserveData(size_t size)
- {
- NVBLAST_ASSERT(m_allowAllocs);
- m_pool = reinterpret_cast<uint8_t*>(allocDataBySize(size));
- m_poolCapacity = size;
- m_currentData = 0;
- }
-
- /**
- Preallocate space for events.
- */
- void reserveEvents(uint32_t n)
- {
- NVBLAST_ASSERT(m_allowAllocs);
- m_events.reserve(m_events.size() + n);
- }
-
- /**
- Add a listener to dispatch to.
- */
- void addListener(TkEventListener& l)
- {
- m_listeners.pushBack(&l);
- }
-
- /**
- Remove a listener from dispatch list.
- */
- void removeListener(TkEventListener& l)
- {
- m_listeners.findAndReplaceWithLast(&l);
- }
-
- /**
- Dispatch the stored events to the registered listeners.
- After dispatch, all data is invalidated.
- */
- void dispatch()
- {
- dispatch(*this);
- reset();
- }
-
- /**
- Proxy function to dispatch events to this queue's listeners.
- */
- void dispatch(const Array<TkEvent>::type& events) const
- {
- if (events.size())
- {
- for (TkEventListener* l : m_listeners)
- {
- BLAST_PROFILE_SCOPE_M("TkEventQueue::dispatch");
- l->receive(events.begin(), events.size());
- }
- }
- }
-
-private:
- /**
- Allocates and stores a block of size Bytes of payload data.
- */
- void* allocDataBySize(size_t size)
- {
- void* memory = nullptr;
- if (size > 0)
- {
- memory = NVBLAST_ALLOC_NAMED(size, "TkEventQueue Data");
- m_memory.pushBack(memory);
- }
- return memory;
- }
-
-
- Array<TkEvent>::type m_events; //!< holds events
- Array<void*>::type m_memory; //!< holds allocated data memory blocks
- std::atomic<uint32_t> m_currentEvent; //!< reference index for event insertion
- std::atomic<uint32_t> m_currentData; //!< reference index for data insertion
- size_t m_poolCapacity; //!< size of the currently active memory block (m_pool)
- uint8_t* m_pool; //!< the current memory block allocData() uses
- bool m_allowAllocs; //!< assert guard
- InlineArray<TkEventListener*,4>::type m_listeners; //!< objects to dispatch to
-};
-
-} // namespace Blast
-} // namespace Nv
-
-
-#endif // ifndef NVBLASTTKEVENTQUEUE_H
+// 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) 2016-2018 NVIDIA Corporation. All rights reserved.
+
+
+#ifndef NVBLASTTKEVENTQUEUE_H
+#define NVBLASTTKEVENTQUEUE_H
+
+#include <algorithm>
+#include <vector>
+
+#include <mutex>
+#include <atomic>
+
+#include "NvBlastTkFrameworkImpl.h"
+#include "NvBlastAssert.h"
+
+
+namespace Nv {
+namespace Blast {
+
+/**
+A dispatcher queue providing preallocation and thread-safe insertions therein.
+
+Typical usage:
+- preallocate space for events and payload:
+ - reserveEvents, reserveData
+- enable asserts to detect undersized storage (allocations are not thread safe):
+ - protect(true)
+- get pointers to payload data and events to fill in, thread safe for preallocated memory:
+ - allocData, addEvent
+- back on main thread, ensure consistency:
+ - protect(false)
+
+- continue adding events and payload on main thread if necessary like above (allocations are safe here)
+eventually dispatch, or reset if dispatched by proxy
+*/
+class TkEventQueue
+{
+public:
+ TkEventQueue() : m_currentEvent(0), m_poolCapacity(0), m_pool(nullptr), m_allowAllocs(true) {}
+
+ /**
+ Peek events queue for dispatch.
+ Do not use in protected state.
+ */
+ operator const Array<TkEvent>::type&()
+ {
+ NVBLAST_ASSERT(m_allowAllocs);
+ NVBLAST_ASSERT(m_currentEvent == m_events.size());
+ return m_events;
+ }
+
+ /**
+ Debug help to catch (unwanted) allocations during task work.
+ Note that this will not actually avoid allocations, but assert in debug builds.
+
+ Set true before using in distributed environment.
+ Set false to return to single-thread mode.
+ */
+ void protect(bool enable)
+ {
+ // During parallel use, m_events.size() and m_currentEvent are allowed to diverge.
+ // This is fine because resizeUninitialized does not alter the stored data.
+ NVBLAST_ASSERT(m_currentEvent <= m_events.capacity());
+ m_events.resizeUninitialized(m_currentEvent);
+ m_allowAllocs = !enable;
+ }
+
+ /**
+ Restores initial state.
+ Data memory is currently not being reused. To be improved.
+ */
+ void reset()
+ {
+ m_events.clear();
+ m_currentEvent = 0;
+ for (void* mem : m_memory)
+ {
+ NVBLAST_FREE(mem);
+ }
+ m_memory.clear();
+ m_currentData = 0;
+ m_allowAllocs = true;
+ m_poolCapacity = 0;
+ m_pool = nullptr;
+ }
+
+ /**
+ Queue an event with a payload.
+ */
+ template<class T>
+ void addEvent(T* payload)
+ {
+ uint32_t index = m_currentEvent.fetch_add(1);
+
+ // Should not allocate in protected state.
+ NVBLAST_ASSERT(m_allowAllocs || m_currentEvent <= m_events.capacity());
+
+ m_events.resizeUninitialized(m_currentEvent);
+
+ // During parallel use, m_events.size() and m_currentEvent are allowed to diverge.
+ // Consistency is restored in protect().
+ NVBLAST_ASSERT(!m_allowAllocs || m_currentEvent == m_events.size());
+
+ TkEvent& evt = m_events[index];
+ evt.type = TkEvent::Type(T::EVENT_TYPE);
+ evt.payload = payload;
+ }
+
+ /**
+ Request storage for payload.
+ */
+ template<typename T>
+ T* allocData()
+ {
+ uint32_t index = m_currentData.fetch_add(sizeof(T));
+ if (m_currentData <= m_poolCapacity)
+ {
+ return reinterpret_cast<T*>(&m_pool[index]);
+ }
+ else
+ {
+ // Could do larger block allocation here.
+ reserveData(sizeof(T));
+ // Account for the requested size.
+ m_currentData = sizeof(T);
+ return reinterpret_cast<T*>(&m_pool[0]);
+ }
+ }
+
+ /**
+ Preallocate a memory block of size Bytes for payload data.
+ Note that this will inevitably allocate a new memory block.
+ Subsequent calls to allocData will use this memory piecewise.
+ */
+ void reserveData(size_t size)
+ {
+ NVBLAST_ASSERT(m_allowAllocs);
+ m_pool = reinterpret_cast<uint8_t*>(allocDataBySize(size));
+ m_poolCapacity = size;
+ m_currentData = 0;
+ }
+
+ /**
+ Preallocate space for events.
+ */
+ void reserveEvents(uint32_t n)
+ {
+ NVBLAST_ASSERT(m_allowAllocs);
+ m_events.reserve(m_events.size() + n);
+ }
+
+ /**
+ Add a listener to dispatch to.
+ */
+ void addListener(TkEventListener& l)
+ {
+ m_listeners.pushBack(&l);
+ }
+
+ /**
+ Remove a listener from dispatch list.
+ */
+ void removeListener(TkEventListener& l)
+ {
+ m_listeners.findAndReplaceWithLast(&l);
+ }
+
+ /**
+ Dispatch the stored events to the registered listeners.
+ After dispatch, all data is invalidated.
+ */
+ void dispatch()
+ {
+ dispatch(*this);
+ reset();
+ }
+
+ /**
+ Proxy function to dispatch events to this queue's listeners.
+ */
+ void dispatch(const Array<TkEvent>::type& events) const
+ {
+ if (events.size())
+ {
+ for (TkEventListener* l : m_listeners)
+ {
+ BLAST_PROFILE_SCOPE_M("TkEventQueue::dispatch");
+ l->receive(events.begin(), events.size());
+ }
+ }
+ }
+
+private:
+ /**
+ Allocates and stores a block of size Bytes of payload data.
+ */
+ void* allocDataBySize(size_t size)
+ {
+ void* memory = nullptr;
+ if (size > 0)
+ {
+ memory = NVBLAST_ALLOC_NAMED(size, "TkEventQueue Data");
+ m_memory.pushBack(memory);
+ }
+ return memory;
+ }
+
+
+ Array<TkEvent>::type m_events; //!< holds events
+ Array<void*>::type m_memory; //!< holds allocated data memory blocks
+ std::atomic<uint32_t> m_currentEvent; //!< reference index for event insertion
+ std::atomic<uint32_t> m_currentData; //!< reference index for data insertion
+ size_t m_poolCapacity; //!< size of the currently active memory block (m_pool)
+ uint8_t* m_pool; //!< the current memory block allocData() uses
+ bool m_allowAllocs; //!< assert guard
+ InlineArray<TkEventListener*,4>::type m_listeners; //!< objects to dispatch to
+};
+
+} // namespace Blast
+} // namespace Nv
+
+
+#endif // ifndef NVBLASTTKEVENTQUEUE_H
diff --git a/sdk/toolkit/source/NvBlastTkFamilyImpl.cpp b/sdk/toolkit/source/NvBlastTkFamilyImpl.cpp
index 50b3266..26133f0 100644..100755
--- a/sdk/toolkit/source/NvBlastTkFamilyImpl.cpp
+++ b/sdk/toolkit/source/NvBlastTkFamilyImpl.cpp
@@ -1,558 +1,558 @@
-// 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) 2016-2018 NVIDIA Corporation. All rights reserved.
-
-
-#include "NvBlastTkFrameworkImpl.h"
-#include "NvBlastTkFamilyImpl.h"
-#include "NvBlastTkGroupImpl.h"
-#include "NvBlastTkAssetImpl.h"
-#include "NvBlastTkActorImpl.h"
-#include "NvBlastTkJointImpl.h"
-
-#include "NvBlastIndexFns.h"
-#include "NvBlastMemory.h"
-
-
-namespace Nv
-{
-namespace Blast
-{
-
-//////// Static data ////////
-
-NVBLASTTK_DEFINE_TYPE_IDENTIFIABLE(Family);
-
-
-//////// Member functions ////////
-
-TkFamilyImpl::TkFamilyImpl() : m_familyLL(nullptr), m_internalJointCount(0), m_asset(nullptr)
-{
-}
-
-
-TkFamilyImpl::TkFamilyImpl(const NvBlastID& id) : TkFamilyType(id), m_familyLL(nullptr), m_internalJointCount(0), m_asset(nullptr)
-{
-}
-
-
-TkFamilyImpl::~TkFamilyImpl()
-{
- if (m_familyLL != nullptr)
- {
- uint32_t familyActorCount = NvBlastFamilyGetActorCount(m_familyLL, logLL);
- if (familyActorCount != 0)
- {
- NVBLAST_LOG_WARNING("TkFamilyImpl::~TkFamilyImpl(): family actor count is not 0.");
- }
- NVBLAST_FREE(m_familyLL);
- }
-}
-
-
-void TkFamilyImpl::release()
-{
- for (TkActorImpl& actor : m_actors)
- {
- if (actor.isActive())
- {
- actor.release();
- }
- }
-
- m_actors.clear();
-
- NVBLAST_DELETE(this, TkFamilyImpl);
-}
-
-
-const NvBlastFamily* TkFamilyImpl::getFamilyLL() const
-{
- return m_familyLL;
-}
-
-
-TkActorImpl* TkFamilyImpl::addActor(NvBlastActor* actorLL)
-{
- TkActorImpl* actor = getActorByActorLL(actorLL);
- NVBLAST_ASSERT(actor);
- actor->m_actorLL = actorLL;
- actor->m_family = this;
- return actor;
-}
-
-
-void TkFamilyImpl::removeActor(TkActorImpl* actor)
-{
- NVBLAST_ASSERT(actor != nullptr && actor->m_family == this);
- //actor->m_family = nullptr;
- actor->m_actorLL = nullptr;
-}
-
-
-uint32_t TkFamilyImpl::getActorCount() const
-{
- return getActorCountInternal();
-}
-
-
-uint32_t TkFamilyImpl::getActors(TkActor** buffer, uint32_t bufferSize, uint32_t indexStart /*= 0*/) const
-{
- uint32_t actorCount = getActorCount();
- if (actorCount <= indexStart)
- {
- NVBLAST_LOG_WARNING("TkFamilyImpl::getActors: indexStart beyond end of actor list.");
- return 0;
- }
-
- actorCount -= indexStart;
- if (actorCount > bufferSize)
- {
- actorCount = static_cast<uint32_t>(bufferSize);
- }
-
- uint32_t index = 0;
- for (const TkActorImpl& actor : m_actors)
- {
- if (actor.isActive())
- {
- if (index >= indexStart)
- {
- if ((index - indexStart) >= actorCount)
- {
- break;
- }
- else
- {
- *buffer++ = const_cast<TkActorImpl*>(&actor);
- }
- }
- index++;
- }
- }
-
- return actorCount;
-}
-
-
-NV_INLINE bool areLLActorsEqual(const NvBlastActor* actor0, const NvBlastActor* actor1, Array<uint32_t>::type& scratch)
-{
- if (NvBlastActorGetGraphNodeCount(actor0, logLL) != NvBlastActorGetGraphNodeCount(actor1, logLL))
- {
- return false;
- }
-
- const uint32_t chunkCount = NvBlastActorGetVisibleChunkCount(actor0, logLL);
- if (chunkCount != NvBlastActorGetVisibleChunkCount(actor1, logLL))
- {
- return false;
- }
-
- scratch.resize(chunkCount * 2);
- NvBlastActorGetVisibleChunkIndices(scratch.begin(), chunkCount, actor0, logLL);
- NvBlastActorGetVisibleChunkIndices(scratch.begin() + chunkCount, chunkCount, actor1, logLL);
- return memcmp(scratch.begin(), scratch.begin() + chunkCount, chunkCount * sizeof(uint32_t)) == 0;
-}
-
-
-void TkFamilyImpl::reinitialize(const NvBlastFamily* newFamily, TkGroup* group)
-{
- NVBLAST_ASSERT(newFamily);
-#if NV_ENABLE_ASSERTS
- NvBlastID id0 = NvBlastFamilyGetAssetID(m_familyLL, logLL);
- NvBlastID id1 = NvBlastFamilyGetAssetID(newFamily, logLL);
- NVBLAST_ASSERT(TkGUIDsEqual(&id0, &id1));
-#endif
- NVBLAST_ASSERT(NvBlastFamilyGetSize(m_familyLL, logLL) == NvBlastFamilyGetSize(newFamily, logLL));
-
- // alloc and init new family
- const uint32_t blockSize = NvBlastFamilyGetSize(newFamily, logLL);
- NvBlastFamily* newFamilyCopy = (NvBlastFamily*)NVBLAST_ALLOC_NAMED(blockSize, "TkFamilyImpl::reinitialize");
- memcpy(newFamilyCopy, newFamily, blockSize);
- NvBlastFamilySetAsset(newFamilyCopy, m_asset->getAssetLL(), logLL);
-
- // get actors from new family
- Array<NvBlastActor*>::type newLLActors(NvBlastFamilyGetActorCount(newFamilyCopy, logLL));
- uint32_t actorCount = NvBlastFamilyGetActors(newLLActors.begin(), newLLActors.size(), newFamilyCopy, logLL);
-
- // reset actor families to nullptr (we use it as a flag later)
- for (TkActorImpl& actor : m_actors)
- {
- if (actor.isActive())
- {
- actor.m_family = nullptr;
- }
- }
-
- // prepare split event with new actors
- auto newActorsSplitEvent = getQueue().allocData<TkSplitEvent>();
- Array<TkActor*>::type children(actorCount);
- children.resizeUninitialized(0);
- newActorsSplitEvent->children = children.begin();
-
- // scratch
- Array<uint32_t>::type scratch(m_asset->getChunkCount());
-
- for (uint32_t i = 0; i < actorCount; ++i)
- {
- NvBlastActor* newLLActor = newLLActors[i];
- uint32_t actorIndex = NvBlastActorGetIndex(newLLActor, logLL);
- TkActorImpl& tkActor = *getActorByIndex(actorIndex);
-
- tkActor.m_family = this;
-
- if (!tkActor.isActive() || !areLLActorsEqual(newLLActor, tkActor.m_actorLL, scratch))
- {
- if (tkActor.isActive())
- {
- auto removeSplitEvent = getQueue().allocData<TkSplitEvent>();
- removeSplitEvent->parentData.family = this;
- removeSplitEvent->numChildren = 0;
- removeSplitEvent->parentData.userData = tkActor.userData;
- removeSplitEvent->parentData.index = tkActor.getIndex();
- getQueue().addEvent(removeSplitEvent);
- }
-
- tkActor.m_actorLL = newLLActor;
-
- // switch groups
- TkGroupImpl* prevGroup = tkActor.m_group;
- if (prevGroup != group)
- {
- if (prevGroup)
- {
- prevGroup->removeActor(tkActor);
- }
- if (group)
- {
- group->addActor(tkActor);
- }
- }
-
- children.pushBack(&tkActor);
- }
- else
- {
- tkActor.m_actorLL = newLLActor;
- }
- }
-
- // if m_family is still nullptr for an active actor -> remove it. It doesn't exist in new family.
- for (TkActorImpl& tkActor : m_actors)
- {
- if (tkActor.isActive() && tkActor.m_family == nullptr)
- {
- tkActor.m_family = this;
- if (tkActor.m_group)
- {
- tkActor.m_group->removeActor(tkActor);
- }
-
- auto removeSplitEvent = getQueue().allocData<TkSplitEvent>();
- removeSplitEvent->parentData.family = this;
- removeSplitEvent->numChildren = 0;
- removeSplitEvent->parentData.userData = tkActor.userData;
- removeSplitEvent->parentData.index = tkActor.getIndex();
- getQueue().addEvent(removeSplitEvent);
-
- tkActor.m_actorLL = nullptr;
- }
- }
-
- // add split event with all new actors
- newActorsSplitEvent->parentData.family = this;
- newActorsSplitEvent->parentData.userData = 0;
- newActorsSplitEvent->parentData.index = invalidIndex<uint32_t>();
- newActorsSplitEvent->numChildren = children.size();
- if (newActorsSplitEvent->numChildren > 0)
- {
- getQueue().addEvent(newActorsSplitEvent);
- }
-
- // replace family
- NVBLAST_FREE(m_familyLL);
- m_familyLL = newFamilyCopy;
-
- // update joints
- for (TkActorImpl& tkActor : m_actors)
- {
- if (!tkActor.m_jointList.isEmpty())
- {
- updateJoints(&tkActor);
- }
- }
-
- getQueue().dispatch();
-}
-
-
-TkActorImpl* TkFamilyImpl::getActorByChunk(uint32_t chunk)
-{
- if (chunk >= NvBlastAssetGetChunkCount(m_asset->getAssetLLInternal(), logLL))
- {
- NVBLAST_LOG_WARNING("TkFamilyImpl::getActorByChunk: invalid chunk index. Returning NULL.");
- return nullptr;
- }
-
- NvBlastActor* actorLL = NvBlastFamilyGetChunkActor(m_familyLL, chunk, logLL);
- return actorLL ? getActorByActorLL(actorLL) : nullptr;
-}
-
-
-void TkFamilyImpl::applyFractureInternal(const NvBlastFractureBuffers* commands)
-{
- NvBlastSupportGraph graph = getAsset()->getGraph();
-
- // apply bond fracture commands on relevant actors
- {
- TkActorImpl* currActor = nullptr;
- NvBlastBondFractureData* bondFractures = commands->bondFractures;
- uint32_t bondFracturesCount = 0;
-
- auto applyFracture = [&]()
- {
- if (bondFracturesCount > 0)
- {
- if (currActor != nullptr && currActor->isActive())
- {
- NvBlastFractureBuffers newCommands;
- newCommands.bondFractures = bondFractures;
- newCommands.bondFractureCount = bondFracturesCount;
- newCommands.chunkFractures = nullptr;
- newCommands.chunkFractureCount = 0;
- currActor->applyFracture(nullptr, &newCommands);
- }
-
- bondFractures += bondFracturesCount;
- bondFracturesCount = 0;
- }
- };
-
- for (uint32_t i = 0; i < commands->bondFractureCount; ++i, ++bondFracturesCount)
- {
- const NvBlastBondFractureData& command = commands->bondFractures[i];
- uint32_t chunk0 = graph.chunkIndices[command.nodeIndex0];
- uint32_t chunk1 = graph.chunkIndices[command.nodeIndex1];
- TkActorImpl* actor0 = getActorByChunk(chunk0);
- TkActorImpl* actor1 = getActorByChunk(chunk1);
- if (actor0 != actor1)
- {
- // skipping this event, bond already broken
- actor0 = nullptr;
- }
- if (actor0 != currActor)
- {
- applyFracture();
- currActor = actor0;
- }
- }
-
- if (bondFracturesCount > 0)
- {
- applyFracture();
- }
- }
-
- // apply chunk fracture commands on relevant actors
- {
- TkActorImpl* currActor = nullptr;
- NvBlastChunkFractureData* chunkFractures = commands->chunkFractures;
- uint32_t chunkFracturesCount = 0;
-
- auto applyFracture = [&]()
- {
- if (chunkFracturesCount > 0)
- {
- if (currActor != nullptr && currActor->isActive())
- {
- NvBlastFractureBuffers newCommands;
- newCommands.bondFractures = nullptr;
- newCommands.bondFractureCount = 0;
- newCommands.chunkFractures = chunkFractures;
- newCommands.chunkFractureCount = chunkFracturesCount;
- currActor->applyFracture(nullptr, &newCommands);
- }
-
- chunkFractures += chunkFracturesCount;
- chunkFracturesCount = 0;
- }
- };
-
- for (uint32_t i = 0; i < commands->chunkFractureCount; ++i, ++chunkFracturesCount)
- {
- const NvBlastChunkFractureData& command = commands->chunkFractures[i];
- TkActorImpl* actor = getActorByChunk(command.chunkIndex);
- if (actor != currActor)
- {
- applyFracture();
- currActor = actor;
- }
- }
- if (chunkFracturesCount > 0)
- {
- applyFracture();
- }
- }
-}
-
-
-void TkFamilyImpl::updateJoints(TkActorImpl* actor, TkEventQueue* alternateQueue)
-{
- // Copy joint array for safety against implementation of joint->setActor
- TkJointImpl** joints = reinterpret_cast<TkJointImpl**>(NvBlastAlloca(sizeof(TkJointImpl*)*actor->getJointCountInternal()));
- TkJointImpl** stop = joints + actor->getJointCountInternal();
- TkJointImpl** jointHandle = joints;
- for (TkActorImpl::JointIt j(*actor); (bool)j; ++j)
- {
- *jointHandle++ = *j;
- }
- jointHandle = joints;
- while (jointHandle < stop)
- {
- TkJointImpl* joint = *jointHandle++;
-
- const TkJointData& data = joint->getDataInternal();
-
- TkActorImpl* actor0 = data.actors[0] != nullptr ?
- static_cast<TkActorImpl&>(*data.actors[0]).getFamilyImpl().getActorByChunk(data.chunkIndices[0]) : nullptr;
-
- TkActorImpl* actor1 = data.actors[1] != nullptr ?
- static_cast<TkActorImpl&>(*data.actors[1]).getFamilyImpl().getActorByChunk(data.chunkIndices[1]) : nullptr;
-
- joint->setActors(actor0, actor1, alternateQueue);
- }
-}
-
-
-const TkAsset* TkFamilyImpl::getAsset() const
-{
- return m_asset;
-}
-
-
-//////// Static functions ////////
-
-TkFamilyImpl* TkFamilyImpl::create(const TkAssetImpl* asset)
-{
- TkFamilyImpl* family = NVBLAST_NEW(TkFamilyImpl);
- family->m_asset = asset;
- void* mem = NVBLAST_ALLOC_NAMED(NvBlastAssetGetFamilyMemorySize(asset->getAssetLL(), logLL), "TkFamilyImpl::create");
- family->m_familyLL = NvBlastAssetCreateFamily(mem, asset->getAssetLL(), logLL);
- //family->addListener(*TkFrameworkImpl::get());
-
- if (family->m_familyLL == nullptr)
- {
- NVBLAST_LOG_ERROR("TkFamilyImpl::create: low-level family could not be created.");
- family->release();
- return nullptr;
- }
-
- uint32_t maxActorCount = NvBlastFamilyGetMaxActorCount(family->m_familyLL, logLL);
- family->m_actors.resize(maxActorCount);
-
- family->m_internalJointBuffer.resize(asset->getJointDescCountInternal() * sizeof(TkJointImpl), 0);
- family->m_internalJointCount = asset->getJointDescCountInternal();
-
- return family;
-}
-
-
-TkJointImpl** TkFamilyImpl::createExternalJointHandle(const NvBlastID& otherFamilyID, uint32_t chunkIndex0, uint32_t chunkIndex1)
-{
- JointSet* jointSet;
- const FamilyIDMap::Entry* jointSetIndexEntry = m_familyIDMap.find(otherFamilyID);
- uint32_t otherFamilyIndex;
- if (jointSetIndexEntry != nullptr)
- {
- otherFamilyIndex = jointSetIndexEntry->second;
- jointSet = m_jointSets[otherFamilyIndex];
- }
- else
- {
- jointSet = NVBLAST_NEW(JointSet);
- NVBLAST_CHECK_ERROR(jointSet != nullptr, "TkFamilyImpl::addExternalJoint: failed to create joint set for other family ID.", return nullptr);
- jointSet->m_familyID = otherFamilyID;
- otherFamilyIndex = m_jointSets.size();
- m_familyIDMap[otherFamilyID] = otherFamilyIndex;
- m_jointSets.pushBack(jointSet);
- }
-
- const ExternalJointKey key(chunkIndex0, chunkIndex1);
- const bool jointExists = jointSet->m_joints.find(key) != nullptr;
- NVBLAST_CHECK_WARNING(!jointExists, "TkFamilyImpl::addExternalJoint: joint already added.", return nullptr);
-
- return &jointSet->m_joints[key];
-}
-
-
-bool TkFamilyImpl::deleteExternalJointHandle(TkJointImpl*& joint, const NvBlastID& otherFamilyID, uint32_t chunkIndex0, uint32_t chunkIndex1)
-{
- const FamilyIDMap::Entry* jointSetIndexEntry = m_familyIDMap.find(otherFamilyID);
- if (jointSetIndexEntry != nullptr)
- {
- const uint32_t jointSetIndex = jointSetIndexEntry->second;
- HashMap<ExternalJointKey, TkJointImpl*>::type::Entry e;
- if (m_jointSets[jointSetIndex]->m_joints.erase(ExternalJointKey(chunkIndex0, chunkIndex1), e))
- {
- // Delete the joint set if it is empty
- if (m_jointSets[jointSetIndex]->m_joints.size() == 0)
- {
- NVBLAST_DELETE(m_jointSets[jointSetIndex], JointSet);
- m_jointSets.replaceWithLast(jointSetIndex);
- m_familyIDMap.erase(otherFamilyID);
- if (jointSetIndex < m_jointSets.size())
- {
- m_familyIDMap[m_jointSets[jointSetIndex]->m_familyID] = jointSetIndex;
- }
- }
-
- // Return value that was stored
- joint = e.second;
- return true;
- }
- }
-
- return false;
-}
-
-
-TkJointImpl* TkFamilyImpl::findExternalJoint(const TkFamilyImpl* otherFamily, ExternalJointKey key) const
-{
- const FamilyIDMap::Entry* jointSetIndexEntry = m_familyIDMap.find(getFamilyID(otherFamily));
- if (jointSetIndexEntry != nullptr)
- {
- const HashMap<ExternalJointKey, TkJointImpl*>::type::Entry* e = m_jointSets[jointSetIndexEntry->second]->m_joints.find(key);
- if (e != nullptr)
- {
- return e->second;
- }
- }
-
- return nullptr;
-}
-
-} // namespace Blast
-} // namespace Nv
+// 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) 2016-2018 NVIDIA Corporation. All rights reserved.
+
+
+#include "NvBlastTkFrameworkImpl.h"
+#include "NvBlastTkFamilyImpl.h"
+#include "NvBlastTkGroupImpl.h"
+#include "NvBlastTkAssetImpl.h"
+#include "NvBlastTkActorImpl.h"
+#include "NvBlastTkJointImpl.h"
+
+#include "NvBlastIndexFns.h"
+#include "NvBlastMemory.h"
+
+
+namespace Nv
+{
+namespace Blast
+{
+
+//////// Static data ////////
+
+NVBLASTTK_DEFINE_TYPE_IDENTIFIABLE(Family);
+
+
+//////// Member functions ////////
+
+TkFamilyImpl::TkFamilyImpl() : m_familyLL(nullptr), m_internalJointCount(0), m_asset(nullptr)
+{
+}
+
+
+TkFamilyImpl::TkFamilyImpl(const NvBlastID& id) : TkFamilyType(id), m_familyLL(nullptr), m_internalJointCount(0), m_asset(nullptr)
+{
+}
+
+
+TkFamilyImpl::~TkFamilyImpl()
+{
+ if (m_familyLL != nullptr)
+ {
+ uint32_t familyActorCount = NvBlastFamilyGetActorCount(m_familyLL, logLL);
+ if (familyActorCount != 0)
+ {
+ NVBLAST_LOG_WARNING("TkFamilyImpl::~TkFamilyImpl(): family actor count is not 0.");
+ }
+ NVBLAST_FREE(m_familyLL);
+ }
+}
+
+
+void TkFamilyImpl::release()
+{
+ for (TkActorImpl& actor : m_actors)
+ {
+ if (actor.isActive())
+ {
+ actor.release();
+ }
+ }
+
+ m_actors.clear();
+
+ NVBLAST_DELETE(this, TkFamilyImpl);
+}
+
+
+const NvBlastFamily* TkFamilyImpl::getFamilyLL() const
+{
+ return m_familyLL;
+}
+
+
+TkActorImpl* TkFamilyImpl::addActor(NvBlastActor* actorLL)
+{
+ TkActorImpl* actor = getActorByActorLL(actorLL);
+ NVBLAST_ASSERT(actor);
+ actor->m_actorLL = actorLL;
+ actor->m_family = this;
+ return actor;
+}
+
+
+void TkFamilyImpl::removeActor(TkActorImpl* actor)
+{
+ NVBLAST_ASSERT(actor != nullptr && actor->m_family == this);
+ //actor->m_family = nullptr;
+ actor->m_actorLL = nullptr;
+}
+
+
+uint32_t TkFamilyImpl::getActorCount() const
+{
+ return getActorCountInternal();
+}
+
+
+uint32_t TkFamilyImpl::getActors(TkActor** buffer, uint32_t bufferSize, uint32_t indexStart /*= 0*/) const
+{
+ uint32_t actorCount = getActorCount();
+ if (actorCount <= indexStart)
+ {
+ NVBLAST_LOG_WARNING("TkFamilyImpl::getActors: indexStart beyond end of actor list.");
+ return 0;
+ }
+
+ actorCount -= indexStart;
+ if (actorCount > bufferSize)
+ {
+ actorCount = static_cast<uint32_t>(bufferSize);
+ }
+
+ uint32_t index = 0;
+ for (const TkActorImpl& actor : m_actors)
+ {
+ if (actor.isActive())
+ {
+ if (index >= indexStart)
+ {
+ if ((index - indexStart) >= actorCount)
+ {
+ break;
+ }
+ else
+ {
+ *buffer++ = const_cast<TkActorImpl*>(&actor);
+ }
+ }
+ index++;
+ }
+ }
+
+ return actorCount;
+}
+
+
+NV_INLINE bool areLLActorsEqual(const NvBlastActor* actor0, const NvBlastActor* actor1, Array<uint32_t>::type& scratch)
+{
+ if (NvBlastActorGetGraphNodeCount(actor0, logLL) != NvBlastActorGetGraphNodeCount(actor1, logLL))
+ {
+ return false;
+ }
+
+ const uint32_t chunkCount = NvBlastActorGetVisibleChunkCount(actor0, logLL);
+ if (chunkCount != NvBlastActorGetVisibleChunkCount(actor1, logLL))
+ {
+ return false;
+ }
+
+ scratch.resize(chunkCount * 2);
+ NvBlastActorGetVisibleChunkIndices(scratch.begin(), chunkCount, actor0, logLL);
+ NvBlastActorGetVisibleChunkIndices(scratch.begin() + chunkCount, chunkCount, actor1, logLL);
+ return memcmp(scratch.begin(), scratch.begin() + chunkCount, chunkCount * sizeof(uint32_t)) == 0;
+}
+
+
+void TkFamilyImpl::reinitialize(const NvBlastFamily* newFamily, TkGroup* group)
+{
+ NVBLAST_ASSERT(newFamily);
+#if NV_ENABLE_ASSERTS
+ NvBlastID id0 = NvBlastFamilyGetAssetID(m_familyLL, logLL);
+ NvBlastID id1 = NvBlastFamilyGetAssetID(newFamily, logLL);
+ NVBLAST_ASSERT(TkGUIDsEqual(&id0, &id1));
+#endif
+ NVBLAST_ASSERT(NvBlastFamilyGetSize(m_familyLL, logLL) == NvBlastFamilyGetSize(newFamily, logLL));
+
+ // alloc and init new family
+ const uint32_t blockSize = NvBlastFamilyGetSize(newFamily, logLL);
+ NvBlastFamily* newFamilyCopy = (NvBlastFamily*)NVBLAST_ALLOC_NAMED(blockSize, "TkFamilyImpl::reinitialize");
+ memcpy(newFamilyCopy, newFamily, blockSize);
+ NvBlastFamilySetAsset(newFamilyCopy, m_asset->getAssetLL(), logLL);
+
+ // get actors from new family
+ Array<NvBlastActor*>::type newLLActors(NvBlastFamilyGetActorCount(newFamilyCopy, logLL));
+ uint32_t actorCount = NvBlastFamilyGetActors(newLLActors.begin(), newLLActors.size(), newFamilyCopy, logLL);
+
+ // reset actor families to nullptr (we use it as a flag later)
+ for (TkActorImpl& actor : m_actors)
+ {
+ if (actor.isActive())
+ {
+ actor.m_family = nullptr;
+ }
+ }
+
+ // prepare split event with new actors
+ auto newActorsSplitEvent = getQueue().allocData<TkSplitEvent>();
+ Array<TkActor*>::type children(actorCount);
+ children.resizeUninitialized(0);
+ newActorsSplitEvent->children = children.begin();
+
+ // scratch
+ Array<uint32_t>::type scratch(m_asset->getChunkCount());
+
+ for (uint32_t i = 0; i < actorCount; ++i)
+ {
+ NvBlastActor* newLLActor = newLLActors[i];
+ uint32_t actorIndex = NvBlastActorGetIndex(newLLActor, logLL);
+ TkActorImpl& tkActor = *getActorByIndex(actorIndex);
+
+ tkActor.m_family = this;
+
+ if (!tkActor.isActive() || !areLLActorsEqual(newLLActor, tkActor.m_actorLL, scratch))
+ {
+ if (tkActor.isActive())
+ {
+ auto removeSplitEvent = getQueue().allocData<TkSplitEvent>();
+ removeSplitEvent->parentData.family = this;
+ removeSplitEvent->numChildren = 0;
+ removeSplitEvent->parentData.userData = tkActor.userData;
+ removeSplitEvent->parentData.index = tkActor.getIndex();
+ getQueue().addEvent(removeSplitEvent);
+ }
+
+ tkActor.m_actorLL = newLLActor;
+
+ // switch groups
+ TkGroupImpl* prevGroup = tkActor.m_group;
+ if (prevGroup != group)
+ {
+ if (prevGroup)
+ {
+ prevGroup->removeActor(tkActor);
+ }
+ if (group)
+ {
+ group->addActor(tkActor);
+ }
+ }
+
+ children.pushBack(&tkActor);
+ }
+ else
+ {
+ tkActor.m_actorLL = newLLActor;
+ }
+ }
+
+ // if m_family is still nullptr for an active actor -> remove it. It doesn't exist in new family.
+ for (TkActorImpl& tkActor : m_actors)
+ {
+ if (tkActor.isActive() && tkActor.m_family == nullptr)
+ {
+ tkActor.m_family = this;
+ if (tkActor.m_group)
+ {
+ tkActor.m_group->removeActor(tkActor);
+ }
+
+ auto removeSplitEvent = getQueue().allocData<TkSplitEvent>();
+ removeSplitEvent->parentData.family = this;
+ removeSplitEvent->numChildren = 0;
+ removeSplitEvent->parentData.userData = tkActor.userData;
+ removeSplitEvent->parentData.index = tkActor.getIndex();
+ getQueue().addEvent(removeSplitEvent);
+
+ tkActor.m_actorLL = nullptr;
+ }
+ }
+
+ // add split event with all new actors
+ newActorsSplitEvent->parentData.family = this;
+ newActorsSplitEvent->parentData.userData = 0;
+ newActorsSplitEvent->parentData.index = invalidIndex<uint32_t>();
+ newActorsSplitEvent->numChildren = children.size();
+ if (newActorsSplitEvent->numChildren > 0)
+ {
+ getQueue().addEvent(newActorsSplitEvent);
+ }
+
+ // replace family
+ NVBLAST_FREE(m_familyLL);
+ m_familyLL = newFamilyCopy;
+
+ // update joints
+ for (TkActorImpl& tkActor : m_actors)
+ {
+ if (!tkActor.m_jointList.isEmpty())
+ {
+ updateJoints(&tkActor);
+ }
+ }
+
+ getQueue().dispatch();
+}
+
+
+TkActorImpl* TkFamilyImpl::getActorByChunk(uint32_t chunk)
+{
+ if (chunk >= NvBlastAssetGetChunkCount(m_asset->getAssetLLInternal(), logLL))
+ {
+ NVBLAST_LOG_WARNING("TkFamilyImpl::getActorByChunk: invalid chunk index. Returning NULL.");
+ return nullptr;
+ }
+
+ NvBlastActor* actorLL = NvBlastFamilyGetChunkActor(m_familyLL, chunk, logLL);
+ return actorLL ? getActorByActorLL(actorLL) : nullptr;
+}
+
+
+void TkFamilyImpl::applyFractureInternal(const NvBlastFractureBuffers* commands)
+{
+ NvBlastSupportGraph graph = getAsset()->getGraph();
+
+ // apply bond fracture commands on relevant actors
+ {
+ TkActorImpl* currActor = nullptr;
+ NvBlastBondFractureData* bondFractures = commands->bondFractures;
+ uint32_t bondFracturesCount = 0;
+
+ auto applyFracture = [&]()
+ {
+ if (bondFracturesCount > 0)
+ {
+ if (currActor != nullptr && currActor->isActive())
+ {
+ NvBlastFractureBuffers newCommands;
+ newCommands.bondFractures = bondFractures;
+ newCommands.bondFractureCount = bondFracturesCount;
+ newCommands.chunkFractures = nullptr;
+ newCommands.chunkFractureCount = 0;
+ currActor->applyFracture(nullptr, &newCommands);
+ }
+
+ bondFractures += bondFracturesCount;
+ bondFracturesCount = 0;
+ }
+ };
+
+ for (uint32_t i = 0; i < commands->bondFractureCount; ++i, ++bondFracturesCount)
+ {
+ const NvBlastBondFractureData& command = commands->bondFractures[i];
+ uint32_t chunk0 = graph.chunkIndices[command.nodeIndex0];
+ uint32_t chunk1 = graph.chunkIndices[command.nodeIndex1];
+ TkActorImpl* actor0 = getActorByChunk(chunk0);
+ TkActorImpl* actor1 = getActorByChunk(chunk1);
+ if (actor0 != actor1)
+ {
+ // skipping this event, bond already broken
+ actor0 = nullptr;
+ }
+ if (actor0 != currActor)
+ {
+ applyFracture();
+ currActor = actor0;
+ }
+ }
+
+ if (bondFracturesCount > 0)
+ {
+ applyFracture();
+ }
+ }
+
+ // apply chunk fracture commands on relevant actors
+ {
+ TkActorImpl* currActor = nullptr;
+ NvBlastChunkFractureData* chunkFractures = commands->chunkFractures;
+ uint32_t chunkFracturesCount = 0;
+
+ auto applyFracture = [&]()
+ {
+ if (chunkFracturesCount > 0)
+ {
+ if (currActor != nullptr && currActor->isActive())
+ {
+ NvBlastFractureBuffers newCommands;
+ newCommands.bondFractures = nullptr;
+ newCommands.bondFractureCount = 0;
+ newCommands.chunkFractures = chunkFractures;
+ newCommands.chunkFractureCount = chunkFracturesCount;
+ currActor->applyFracture(nullptr, &newCommands);
+ }
+
+ chunkFractures += chunkFracturesCount;
+ chunkFracturesCount = 0;
+ }
+ };
+
+ for (uint32_t i = 0; i < commands->chunkFractureCount; ++i, ++chunkFracturesCount)
+ {
+ const NvBlastChunkFractureData& command = commands->chunkFractures[i];
+ TkActorImpl* actor = getActorByChunk(command.chunkIndex);
+ if (actor != currActor)
+ {
+ applyFracture();
+ currActor = actor;
+ }
+ }
+ if (chunkFracturesCount > 0)
+ {
+ applyFracture();
+ }
+ }
+}
+
+
+void TkFamilyImpl::updateJoints(TkActorImpl* actor, TkEventQueue* alternateQueue)
+{
+ // Copy joint array for safety against implementation of joint->setActor
+ TkJointImpl** joints = reinterpret_cast<TkJointImpl**>(NvBlastAlloca(sizeof(TkJointImpl*)*actor->getJointCountInternal()));
+ TkJointImpl** stop = joints + actor->getJointCountInternal();
+ TkJointImpl** jointHandle = joints;
+ for (TkActorImpl::JointIt j(*actor); (bool)j; ++j)
+ {
+ *jointHandle++ = *j;
+ }
+ jointHandle = joints;
+ while (jointHandle < stop)
+ {
+ TkJointImpl* joint = *jointHandle++;
+
+ const TkJointData& data = joint->getDataInternal();
+
+ TkActorImpl* actor0 = data.actors[0] != nullptr ?
+ static_cast<TkActorImpl&>(*data.actors[0]).getFamilyImpl().getActorByChunk(data.chunkIndices[0]) : nullptr;
+
+ TkActorImpl* actor1 = data.actors[1] != nullptr ?
+ static_cast<TkActorImpl&>(*data.actors[1]).getFamilyImpl().getActorByChunk(data.chunkIndices[1]) : nullptr;
+
+ joint->setActors(actor0, actor1, alternateQueue);
+ }
+}
+
+
+const TkAsset* TkFamilyImpl::getAsset() const
+{
+ return m_asset;
+}
+
+
+//////// Static functions ////////
+
+TkFamilyImpl* TkFamilyImpl::create(const TkAssetImpl* asset)
+{
+ TkFamilyImpl* family = NVBLAST_NEW(TkFamilyImpl);
+ family->m_asset = asset;
+ void* mem = NVBLAST_ALLOC_NAMED(NvBlastAssetGetFamilyMemorySize(asset->getAssetLL(), logLL), "TkFamilyImpl::create");
+ family->m_familyLL = NvBlastAssetCreateFamily(mem, asset->getAssetLL(), logLL);
+ //family->addListener(*TkFrameworkImpl::get());
+
+ if (family->m_familyLL == nullptr)
+ {
+ NVBLAST_LOG_ERROR("TkFamilyImpl::create: low-level family could not be created.");
+ family->release();
+ return nullptr;
+ }
+
+ uint32_t maxActorCount = NvBlastFamilyGetMaxActorCount(family->m_familyLL, logLL);
+ family->m_actors.resize(maxActorCount);
+
+ family->m_internalJointBuffer.resize(asset->getJointDescCountInternal() * sizeof(TkJointImpl), 0);
+ family->m_internalJointCount = asset->getJointDescCountInternal();
+
+ return family;
+}
+
+
+TkJointImpl** TkFamilyImpl::createExternalJointHandle(const NvBlastID& otherFamilyID, uint32_t chunkIndex0, uint32_t chunkIndex1)
+{
+ JointSet* jointSet;
+ const FamilyIDMap::Entry* jointSetIndexEntry = m_familyIDMap.find(otherFamilyID);
+ uint32_t otherFamilyIndex;
+ if (jointSetIndexEntry != nullptr)
+ {
+ otherFamilyIndex = jointSetIndexEntry->second;
+ jointSet = m_jointSets[otherFamilyIndex];
+ }
+ else
+ {
+ jointSet = NVBLAST_NEW(JointSet);
+ NVBLAST_CHECK_ERROR(jointSet != nullptr, "TkFamilyImpl::addExternalJoint: failed to create joint set for other family ID.", return nullptr);
+ jointSet->m_familyID = otherFamilyID;
+ otherFamilyIndex = m_jointSets.size();
+ m_familyIDMap[otherFamilyID] = otherFamilyIndex;
+ m_jointSets.pushBack(jointSet);
+ }
+
+ const ExternalJointKey key(chunkIndex0, chunkIndex1);
+ const bool jointExists = jointSet->m_joints.find(key) != nullptr;
+ NVBLAST_CHECK_WARNING(!jointExists, "TkFamilyImpl::addExternalJoint: joint already added.", return nullptr);
+
+ return &jointSet->m_joints[key];
+}
+
+
+bool TkFamilyImpl::deleteExternalJointHandle(TkJointImpl*& joint, const NvBlastID& otherFamilyID, uint32_t chunkIndex0, uint32_t chunkIndex1)
+{
+ const FamilyIDMap::Entry* jointSetIndexEntry = m_familyIDMap.find(otherFamilyID);
+ if (jointSetIndexEntry != nullptr)
+ {
+ const uint32_t jointSetIndex = jointSetIndexEntry->second;
+ HashMap<ExternalJointKey, TkJointImpl*>::type::Entry e;
+ if (m_jointSets[jointSetIndex]->m_joints.erase(ExternalJointKey(chunkIndex0, chunkIndex1), e))
+ {
+ // Delete the joint set if it is empty
+ if (m_jointSets[jointSetIndex]->m_joints.size() == 0)
+ {
+ NVBLAST_DELETE(m_jointSets[jointSetIndex], JointSet);
+ m_jointSets.replaceWithLast(jointSetIndex);
+ m_familyIDMap.erase(otherFamilyID);
+ if (jointSetIndex < m_jointSets.size())
+ {
+ m_familyIDMap[m_jointSets[jointSetIndex]->m_familyID] = jointSetIndex;
+ }
+ }
+
+ // Return value that was stored
+ joint = e.second;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+TkJointImpl* TkFamilyImpl::findExternalJoint(const TkFamilyImpl* otherFamily, ExternalJointKey key) const
+{
+ const FamilyIDMap::Entry* jointSetIndexEntry = m_familyIDMap.find(getFamilyID(otherFamily));
+ if (jointSetIndexEntry != nullptr)
+ {
+ const HashMap<ExternalJointKey, TkJointImpl*>::type::Entry* e = m_jointSets[jointSetIndexEntry->second]->m_joints.find(key);
+ if (e != nullptr)
+ {
+ return e->second;
+ }
+ }
+
+ return nullptr;
+}
+
+} // namespace Blast
+} // namespace Nv
diff --git a/sdk/toolkit/source/NvBlastTkFamilyImpl.h b/sdk/toolkit/source/NvBlastTkFamilyImpl.h
index 7eec486..7a33d10 100644..100755
--- a/sdk/toolkit/source/NvBlastTkFamilyImpl.h
+++ b/sdk/toolkit/source/NvBlastTkFamilyImpl.h
@@ -1,229 +1,229 @@
-// 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) 2016-2018 NVIDIA Corporation. All rights reserved.
-
-
-#ifndef NVBLASTTKFAMILYIMPL_H
-#define NVBLASTTKFAMILYIMPL_H
-
-#include "NvBlastTkCommon.h"
-
-#include "NvBlastTkFamily.h"
-#include "NvBlastTkTypeImpl.h"
-#include "NvBlastTkActorImpl.h"
-
-#include "NvBlastTkEventQueue.h"
-#include "NvBlastHashSet.h"
-#include "NvBlastHashMap.h"
-
-#include "NvBlast.h"
-#include "NvBlastAssert.h"
-#include "NvBlastDLink.h"
-
-
-// Forward declarations
-struct NvBlastFamily;
-
-namespace Nv
-{
-namespace Blast
-{
-
-// Forward declarations
-class TkGroupImpl;
-class TkAssetImpl;
-
-
-NVBLASTTK_IMPL_DECLARE(Family)
-{
-public:
- TkFamilyImpl();
- TkFamilyImpl(const NvBlastID& id);
- ~TkFamilyImpl();
-
- NVBLASTTK_IMPL_DEFINE_IDENTIFIABLE('A', 'C', 'T', 'F');
-
- // Begin TkFamily
- virtual const NvBlastFamily* getFamilyLL() const override;
-
- virtual uint32_t getActorCount() const override;
-
- virtual uint32_t getActors(TkActor** buffer, uint32_t bufferSize, uint32_t indexStart = 0) const override;
-
- virtual void addListener(TkEventListener& l) override { m_queue.addListener(l); }
-
- virtual void removeListener(TkEventListener& l) override { m_queue.removeListener(l); }
-
- virtual void applyFracture(const NvBlastFractureBuffers* commands) override { applyFractureInternal(commands); }
-
- virtual const TkAsset* getAsset() const override;
-
- virtual void reinitialize(const NvBlastFamily* newFamily, TkGroup* group) override;
- // End TkFamily
-
- // Public methods
- static TkFamilyImpl* create(const TkAssetImpl* asset);
-
- const TkAssetImpl* getAssetImpl() const;
-
- NvBlastFamily* getFamilyLLInternal() const;
-
- uint32_t getActorCountInternal() const;
-
- TkActorImpl* addActor(NvBlastActor* actorLL);
-
- void applyFractureInternal(const NvBlastFractureBuffers* commands);
-
- void removeActor(TkActorImpl* actorLL);
-
- TkEventQueue& getQueue() { return m_queue; }
-
- TkActorImpl* getActorByActorLL(const NvBlastActor* actorLL);
-
- void updateJoints(TkActorImpl* actor, TkEventQueue* alternateQueue = nullptr);
-
- Array<TkActorImpl>::type& getActorsInternal();
-
- uint32_t getInternalJointCount() const;
-
- TkJointImpl* getInternalJoints() const;
-
- TkJointImpl** createExternalJointHandle(const NvBlastID& otherFamilyID, uint32_t chunkIndex0, uint32_t chunkIndex1);
-
- bool deleteExternalJointHandle(TkJointImpl*& joint, const NvBlastID& otherFamilyID, uint32_t chunkIndex0, uint32_t chunkIndex1);
-
- void releaseJoint(TkJointImpl& joint);
-
- TkActorImpl* getActorByChunk(uint32_t chunkIndex);
-
- typedef physx::shdfnd::Pair<uint32_t, uint32_t> ExternalJointKey; //!< The chunk indices within the TkFamily objects joined by the joint. These chunks will be support chunks.
-
- TkJointImpl* findExternalJoint(const TkFamilyImpl* otherFamily, ExternalJointKey key) const;
-
-private:
- TkActorImpl* getActorByIndex(uint32_t index);
-
- struct JointSet
- {
- NvBlastID m_familyID;
- HashMap<ExternalJointKey, TkJointImpl*>::type m_joints;
- };
-
- typedef HashMap<NvBlastID, uint32_t>::type FamilyIDMap;
-
- NvBlastFamily* m_familyLL;
- Array<TkActorImpl>::type m_actors;
- uint32_t m_internalJointCount;
- Array<uint8_t>::type m_internalJointBuffer;
- Array<JointSet*>::type m_jointSets;
- FamilyIDMap m_familyIDMap;
- const TkAssetImpl* m_asset;
-
- TkEventQueue m_queue;
-};
-
-
-//////// TkFamilyImpl inline methods ////////
-
-NV_INLINE const TkAssetImpl* TkFamilyImpl::getAssetImpl() const
-{
- return m_asset;
-}
-
-
-NV_INLINE NvBlastFamily* TkFamilyImpl::getFamilyLLInternal() const
-{
- return m_familyLL;
-}
-
-
-NV_INLINE uint32_t TkFamilyImpl::getActorCountInternal() const
-{
- NVBLAST_ASSERT(m_familyLL != nullptr);
-
- return NvBlastFamilyGetActorCount(m_familyLL, logLL);
-}
-
-
-NV_INLINE TkActorImpl* TkFamilyImpl::getActorByIndex(uint32_t index)
-{
- NVBLAST_ASSERT(index < m_actors.size());
- return &m_actors[index];
-}
-
-
-NV_INLINE TkActorImpl* TkFamilyImpl::getActorByActorLL(const NvBlastActor* actorLL)
-{
- uint32_t index = NvBlastActorGetIndex(actorLL, logLL);
- return getActorByIndex(index);
-}
-
-
-NV_INLINE Array<TkActorImpl>::type& TkFamilyImpl::getActorsInternal()
-{
- return m_actors;
-}
-
-
-NV_INLINE uint32_t TkFamilyImpl::getInternalJointCount() const
-{
- return m_internalJointCount;
-}
-
-
-NV_INLINE TkJointImpl* TkFamilyImpl::getInternalJoints() const
-{
- return const_cast<TkJointImpl*>(reinterpret_cast<const TkJointImpl*>(m_internalJointBuffer.begin()));
-}
-
-
-NV_INLINE void TkFamilyImpl::releaseJoint(TkJointImpl& joint)
-{
- NVBLAST_ASSERT(joint.m_owner == this);
- NVBLAST_ASSERT(&joint >= getInternalJoints() && &joint < getInternalJoints() + getInternalJointCount() * sizeof(TkJointImpl));
-
- joint.~TkJointImpl();
- joint.m_owner = nullptr;
-}
-
-
-//////// Inline global functions ////////
-
-NV_INLINE const NvBlastID& getFamilyID(const TkActor* actor)
-{
- return actor != nullptr ? static_cast<const TkActorImpl*>(actor)->getFamilyImpl().getIDInternal() : *reinterpret_cast<const NvBlastID*>("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
-}
-
-NV_INLINE const NvBlastID& getFamilyID(const TkFamilyImpl* family)
-{
- return family != nullptr ? family->getIDInternal() : *reinterpret_cast<const NvBlastID*>("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
-}
-
-} // namespace Blast
-} // namespace Nv
-
-
-#endif // ifndef NVBLASTTKFAMILYIMPL_H
+// 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) 2016-2018 NVIDIA Corporation. All rights reserved.
+
+
+#ifndef NVBLASTTKFAMILYIMPL_H
+#define NVBLASTTKFAMILYIMPL_H
+
+#include "NvBlastTkCommon.h"
+
+#include "NvBlastTkFamily.h"
+#include "NvBlastTkTypeImpl.h"
+#include "NvBlastTkActorImpl.h"
+
+#include "NvBlastTkEventQueue.h"
+#include "NvBlastHashSet.h"
+#include "NvBlastHashMap.h"
+
+#include "NvBlast.h"
+#include "NvBlastAssert.h"
+#include "NvBlastDLink.h"
+
+
+// Forward declarations
+struct NvBlastFamily;
+
+namespace Nv
+{
+namespace Blast
+{
+
+// Forward declarations
+class TkGroupImpl;
+class TkAssetImpl;
+
+
+NVBLASTTK_IMPL_DECLARE(Family)
+{
+public:
+ TkFamilyImpl();
+ TkFamilyImpl(const NvBlastID& id);
+ ~TkFamilyImpl();
+
+ NVBLASTTK_IMPL_DEFINE_IDENTIFIABLE('A', 'C', 'T', 'F');
+
+ // Begin TkFamily
+ virtual const NvBlastFamily* getFamilyLL() const override;
+
+ virtual uint32_t getActorCount() const override;
+
+ virtual uint32_t getActors(TkActor** buffer, uint32_t bufferSize, uint32_t indexStart = 0) const override;
+
+ virtual void addListener(TkEventListener& l) override { m_queue.addListener(l); }
+
+ virtual void removeListener(TkEventListener& l) override { m_queue.removeListener(l); }
+
+ virtual void applyFracture(const NvBlastFractureBuffers* commands) override { applyFractureInternal(commands); }
+
+ virtual const TkAsset* getAsset() const override;
+
+ virtual void reinitialize(const NvBlastFamily* newFamily, TkGroup* group) override;
+ // End TkFamily
+
+ // Public methods
+ static TkFamilyImpl* create(const TkAssetImpl* asset);
+
+ const TkAssetImpl* getAssetImpl() const;
+
+ NvBlastFamily* getFamilyLLInternal() const;
+
+ uint32_t getActorCountInternal() const;
+
+ TkActorImpl* addActor(NvBlastActor* actorLL);
+
+ void applyFractureInternal(const NvBlastFractureBuffers* commands);
+
+ void removeActor(TkActorImpl* actorLL);
+
+ TkEventQueue& getQueue() { return m_queue; }
+
+ TkActorImpl* getActorByActorLL(const NvBlastActor* actorLL);
+
+ void updateJoints(TkActorImpl* actor, TkEventQueue* alternateQueue = nullptr);
+
+ Array<TkActorImpl>::type& getActorsInternal();
+
+ uint32_t getInternalJointCount() const;
+
+ TkJointImpl* getInternalJoints() const;
+
+ TkJointImpl** createExternalJointHandle(const NvBlastID& otherFamilyID, uint32_t chunkIndex0, uint32_t chunkIndex1);
+
+ bool deleteExternalJointHandle(TkJointImpl*& joint, const NvBlastID& otherFamilyID, uint32_t chunkIndex0, uint32_t chunkIndex1);
+
+ void releaseJoint(TkJointImpl& joint);
+
+ TkActorImpl* getActorByChunk(uint32_t chunkIndex);
+
+ typedef physx::shdfnd::Pair<uint32_t, uint32_t> ExternalJointKey; //!< The chunk indices within the TkFamily objects joined by the joint. These chunks will be support chunks.
+
+ TkJointImpl* findExternalJoint(const TkFamilyImpl* otherFamily, ExternalJointKey key) const;
+
+private:
+ TkActorImpl* getActorByIndex(uint32_t index);
+
+ struct JointSet
+ {
+ NvBlastID m_familyID;
+ HashMap<ExternalJointKey, TkJointImpl*>::type m_joints;
+ };
+
+ typedef HashMap<NvBlastID, uint32_t>::type FamilyIDMap;
+
+ NvBlastFamily* m_familyLL;
+ Array<TkActorImpl>::type m_actors;
+ uint32_t m_internalJointCount;
+ Array<uint8_t>::type m_internalJointBuffer;
+ Array<JointSet*>::type m_jointSets;
+ FamilyIDMap m_familyIDMap;
+ const TkAssetImpl* m_asset;
+
+ TkEventQueue m_queue;
+};
+
+
+//////// TkFamilyImpl inline methods ////////
+
+NV_INLINE const TkAssetImpl* TkFamilyImpl::getAssetImpl() const
+{
+ return m_asset;
+}
+
+
+NV_INLINE NvBlastFamily* TkFamilyImpl::getFamilyLLInternal() const
+{
+ return m_familyLL;
+}
+
+
+NV_INLINE uint32_t TkFamilyImpl::getActorCountInternal() const
+{
+ NVBLAST_ASSERT(m_familyLL != nullptr);
+
+ return NvBlastFamilyGetActorCount(m_familyLL, logLL);
+}
+
+
+NV_INLINE TkActorImpl* TkFamilyImpl::getActorByIndex(uint32_t index)
+{
+ NVBLAST_ASSERT(index < m_actors.size());
+ return &m_actors[index];
+}
+
+
+NV_INLINE TkActorImpl* TkFamilyImpl::getActorByActorLL(const NvBlastActor* actorLL)
+{
+ uint32_t index = NvBlastActorGetIndex(actorLL, logLL);
+ return getActorByIndex(index);
+}
+
+
+NV_INLINE Array<TkActorImpl>::type& TkFamilyImpl::getActorsInternal()
+{
+ return m_actors;
+}
+
+
+NV_INLINE uint32_t TkFamilyImpl::getInternalJointCount() const
+{
+ return m_internalJointCount;
+}
+
+
+NV_INLINE TkJointImpl* TkFamilyImpl::getInternalJoints() const
+{
+ return const_cast<TkJointImpl*>(reinterpret_cast<const TkJointImpl*>(m_internalJointBuffer.begin()));
+}
+
+
+NV_INLINE void TkFamilyImpl::releaseJoint(TkJointImpl& joint)
+{
+ NVBLAST_ASSERT(joint.m_owner == this);
+ NVBLAST_ASSERT(&joint >= getInternalJoints() && &joint < getInternalJoints() + getInternalJointCount() * sizeof(TkJointImpl));
+
+ joint.~TkJointImpl();
+ joint.m_owner = nullptr;
+}
+
+
+//////// Inline global functions ////////
+
+NV_INLINE const NvBlastID& getFamilyID(const TkActor* actor)
+{
+ return actor != nullptr ? static_cast<const TkActorImpl*>(actor)->getFamilyImpl().getIDInternal() : *reinterpret_cast<const NvBlastID*>("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
+}
+
+NV_INLINE const NvBlastID& getFamilyID(const TkFamilyImpl* family)
+{
+ return family != nullptr ? family->getIDInternal() : *reinterpret_cast<const NvBlastID*>("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
+}
+
+} // namespace Blast
+} // namespace Nv
+
+
+#endif // ifndef NVBLASTTKFAMILYIMPL_H
diff --git a/sdk/toolkit/source/NvBlastTkFrameworkImpl.cpp b/sdk/toolkit/source/NvBlastTkFrameworkImpl.cpp
index 1d88701..65e1d45 100644..100755
--- a/sdk/toolkit/source/NvBlastTkFrameworkImpl.cpp
+++ b/sdk/toolkit/source/NvBlastTkFrameworkImpl.cpp
@@ -1,463 +1,463 @@
-// 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) 2016-2018 NVIDIA Corporation. All rights reserved.
-
-
-#include "NvBlastAssert.h"
-
-#include "NvBlastTkFrameworkImpl.h"
-#include "NvBlastTkAssetImpl.h"
-#include "NvBlastTkFamilyImpl.h"
-#include "NvBlastTkGroupImpl.h"
-#include "NvBlastTkActorImpl.h"
-#include "NvBlastTkJointImpl.h"
-#include "NvBlastTkTypeImpl.h"
-
-#include "NvBlastGlobals.h"
-
-#include <algorithm>
-
-
-using namespace physx;
-using namespace physx::shdfnd;
-
-
-NV_INLINE bool operator < (const NvBlastID& id1, const NvBlastID& id2)
-{
- return memcmp(&id1, &id2, sizeof(NvBlastID)) < 0;
-}
-
-
-namespace Nv
-{
-namespace Blast
-{
-
-//////// Local definitions ////////
-
-// Map type ID to static type data
-#define NVBLASTTK_REGISTER_TYPE(_name) \
- if (!Tk##_name##Impl::s_type.indexIsValid()) \
- { \
- Tk##_name##Impl::s_type.setIndex(TkTypeIndex::_name); \
- } \
- m_types[TkTypeIndex::_name] = &Tk##_name##Impl::s_type; \
- m_typeIDToIndex[Tk##_name##Impl::s_type.getID()] = TkTypeIndex::_name
-
-
-#define NVBLASTTK_RELEASE_TYPE(_name) \
- { \
- TkTypeImpl& type = Tk##_name##Impl::s_type; \
- auto& toRelease = m_objects[type.getIndex()]; \
- for (TkObject* obj : toRelease) \
- { \
- obj->release(); \
- } \
- }
-
-
-//////// TkFrameworkImpl static variables ////////
-
-TkFrameworkImpl* TkFrameworkImpl::s_framework = nullptr;
-
-
-//////// TkFrameworkImpl static function ////////
-
-TkFrameworkImpl* TkFrameworkImpl::get()
-{
- return s_framework;
-}
-
-
-bool TkFrameworkImpl::set(TkFrameworkImpl* framework)
-{
- if (s_framework != nullptr)
- {
- if (framework != nullptr)
- {
- NVBLAST_LOG_ERROR("TkFrameworkImpl::set: framework already set. Pass NULL to this function to destroy framework.");
- return false;
- }
-
- NVBLAST_DELETE(s_framework, TkFrameworkImpl);
- }
-
- s_framework = framework;
-
- return true;
-}
-
-
-//////// TkFrameworkImpl methods ////////
-
-TkFrameworkImpl::TkFrameworkImpl()
- : TkFramework()
-{
- // Register types
- m_types.resize(TkTypeIndex::TypeCount);
- m_objects.resize(TkTypeIndex::TypeCount);
- NVBLASTTK_REGISTER_TYPE(Asset);
- NVBLASTTK_REGISTER_TYPE(Family);
- NVBLASTTK_REGISTER_TYPE(Group);
-}
-
-
-TkFrameworkImpl::~TkFrameworkImpl()
-{
-}
-
-
-void TkFrameworkImpl::release()
-{
- // Special release of joints, which are not TkIdentifiable:
- Array<TkJointImpl*>::type joints; // Since the EraseIterator is not exposed
- joints.reserve(m_joints.size());
- for (auto j = m_joints.getIterator(); !j.done(); ++j)
- {
- joints.pushBack(*j);
- }
- for (uint32_t i = 0; i < joints.size(); ++i)
- {
- joints[i]->release();
- }
- NVBLAST_ASSERT(m_joints.size() == 0);
- joints.reset(); // Since we will be deleting the allocator
-
- NVBLASTTK_RELEASE_TYPE(Group);
- NVBLASTTK_RELEASE_TYPE(Asset);
- set(nullptr);
-}
-
-
-const TkType* TkFrameworkImpl::getType(TkTypeIndex::Enum typeIndex) const
-{
- if (typeIndex < 0 || typeIndex >= TkTypeIndex::TypeCount)
- {
- NVBLAST_LOG_WARNING("TkFrameworkImpl::getType: invalid typeIndex.");
- return nullptr;
- }
-
- return m_types[typeIndex];
-}
-
-
-TkIdentifiable* TkFrameworkImpl::findObjectByID(const NvBlastID& id) const
-{
- TkIdentifiable* object = findObjectByIDInternal(id);
-
- if (object == nullptr)
- {
- NVBLAST_LOG_WARNING("TkFrameworkImpl::findObjectByID: object not found.");
- }
-
- return object;
-}
-
-
-uint32_t TkFrameworkImpl::getObjectCount(const TkType& type) const
-{
- const uint32_t index = static_cast<const TkTypeImpl&>(type).getIndex();
-
- if (index >= m_objects.size())
- {
- NVBLAST_LOG_ERROR("TkFrameworkImpl::getObjectCount: BlastTk object type unrecognized.");
- return 0;
-
- }
-
- return m_objects[index].size();
-}
-
-
-uint32_t TkFrameworkImpl::getObjects(TkIdentifiable** buffer, uint32_t bufferSize, const TkType& type, uint32_t indexStart /* = 0 */) const
-{
- const uint32_t index = static_cast<const TkTypeImpl&>(type).getIndex();
-
- if (index >= m_objects.size())
- {
- NVBLAST_LOG_ERROR("TkFrameworkImpl::getObjectCount: BlastTk object type unrecognized.");
- return 0;
- }
-
- const auto& objectArray = m_objects[index];
-
- uint32_t objectCount = objectArray.size();
- if (objectCount <= indexStart)
- {
- NVBLAST_LOG_WARNING("TkFrameworkImpl::getObjects: indexStart beyond end of object list.");
- return 0;
- }
-
- objectCount -= indexStart;
- if (objectCount > bufferSize)
- {
- objectCount = bufferSize;
- }
-
- memcpy(buffer, objectArray.begin() + indexStart, objectCount * sizeof(TkObject*));
-
- return objectCount;
-}
-
-
-bool TkFrameworkImpl::reorderAssetDescChunks(NvBlastChunkDesc* chunkDescs, uint32_t chunkCount, NvBlastBondDesc* bondDescs, uint32_t bondCount, uint32_t* chunkReorderMap /*= nullptr*/, bool keepBondNormalChunkOrder /*= false*/) const
-{
- uint32_t* map = chunkReorderMap != nullptr ? chunkReorderMap : static_cast<uint32_t*>(NVBLAST_ALLOC_NAMED(chunkCount * sizeof(uint32_t), "reorderAssetDescChunks:chunkReorderMap"));
- void* scratch = NVBLAST_ALLOC_NAMED(chunkCount * sizeof(NvBlastChunkDesc), "reorderAssetDescChunks:scratch");
- const bool result = NvBlastReorderAssetDescChunks(chunkDescs, chunkCount, bondDescs, bondCount, map, keepBondNormalChunkOrder, scratch, logLL);
- NVBLAST_FREE(scratch);
- if (chunkReorderMap == nullptr)
- {
- NVBLAST_FREE(map);
- }
- return result;
-}
-
-
-bool TkFrameworkImpl::ensureAssetExactSupportCoverage(NvBlastChunkDesc* chunkDescs, uint32_t chunkCount) const
-{
- void* scratch = NVBLAST_ALLOC_NAMED(chunkCount, "ensureAssetExactSupportCoverage:scratch");
- const bool result = NvBlastEnsureAssetExactSupportCoverage(chunkDescs, chunkCount, scratch, logLL);
- NVBLAST_FREE(scratch);
- return result;
-}
-
-
-TkAsset* TkFrameworkImpl::createAsset(const TkAssetDesc& desc)
-{
- TkAssetImpl* asset = TkAssetImpl::create(desc);
- if (asset == nullptr)
- {
- NVBLAST_LOG_ERROR("TkFrameworkImpl::createAsset: failed to create asset.");
- }
-
- return asset;
-}
-
-
-TkAsset* TkFrameworkImpl::createAsset(const NvBlastAsset* assetLL, Nv::Blast::TkAssetJointDesc* jointDescs, uint32_t jointDescCount, bool ownsAsset)
-{
- TkAssetImpl* asset = TkAssetImpl::create(assetLL, jointDescs, jointDescCount, ownsAsset);
- if (asset == nullptr)
- {
- NVBLAST_LOG_ERROR("TkFrameworkImpl::createAsset: failed to create asset.");
- }
-
- return asset;
-}
-
-
-TkGroup* TkFrameworkImpl::createGroup(const TkGroupDesc& desc)
-{
- TkGroupImpl* group = TkGroupImpl::create(desc);
- if (group == nullptr)
- {
- NVBLAST_LOG_ERROR("TkFrameworkImpl::createGroup: failed to create group.");
- }
-
- return group;
-}
-
-
-TkActor* TkFrameworkImpl::createActor(const TkActorDesc& desc)
-{
- TkActor* actor = TkActorImpl::create(desc);
- if (actor == nullptr)
- {
- NVBLAST_LOG_ERROR("TkFrameworkImpl::createActor: failed to create actor.");
- }
-
- return actor;
-}
-
-
-TkJoint* TkFrameworkImpl::createJoint(const TkJointDesc& desc)
-{
- TkJointImpl** handle0 = nullptr;
- TkJointImpl** handle1 = nullptr;
-
- TkFamilyImpl* family0 = static_cast<TkFamilyImpl*>(desc.families[0]);
- TkFamilyImpl* family1 = static_cast<TkFamilyImpl*>(desc.families[1]);
-
- NVBLAST_CHECK_ERROR(family0 != nullptr || family1 != nullptr, "TkFrameworkImpl::createJoint: at least one family in the TkJointDesc must be valid.", return nullptr);
-
- NVBLAST_CHECK_ERROR(family0 == nullptr || desc.chunkIndices[0] < family0->getAssetImpl()->getChunkCount(), "TkFrameworkImpl::createJoint: desc.chunkIndices[0] is invalid.", return nullptr);
- NVBLAST_CHECK_ERROR(family1 == nullptr || desc.chunkIndices[1] < family1->getAssetImpl()->getChunkCount(), "TkFrameworkImpl::createJoint: desc.chunkIndices[1] is invalid.", return nullptr);
-
- const bool actorsAreTheSame = family0 == family1 && family0->getActorByChunk(desc.chunkIndices[0]) == family1->getActorByChunk(desc.chunkIndices[1]);
- NVBLAST_CHECK_ERROR(!actorsAreTheSame, "TkFrameworkImpl::createJoint: the chunks listed in the TkJointDesc must be in different actors.", return nullptr);
-
- if (family0 != nullptr)
- {
- const bool isSupportChunk = !isInvalidIndex(NvBlastAssetGetChunkToGraphNodeMap(family0->getAssetImpl()->getAssetLLInternal(), logLL)[desc.chunkIndices[0]]);
- NVBLAST_CHECK_ERROR(isSupportChunk, "TkFrameworkImpl::createJoint: desc.chunkIndices[0] is not a support chunk in the asset for desc.families[0]. Joint not created.", return nullptr);
- handle0 = family0->createExternalJointHandle(getFamilyID(family1), desc.chunkIndices[0], desc.chunkIndices[1]);
- NVBLAST_CHECK_ERROR(handle0 != nullptr, "TkFrameworkImpl::createJoint: could not create joint handle in family[0]. Joint not created.", return nullptr);
- }
-
- if (family1 != nullptr)
- {
- const bool isSupportChunk = !isInvalidIndex(NvBlastAssetGetChunkToGraphNodeMap(family1->getAssetImpl()->getAssetLLInternal(), logLL)[desc.chunkIndices[1]]);
- NVBLAST_CHECK_ERROR(isSupportChunk, "TkFrameworkImpl::createJoint: desc.chunkIndices[1] is not a support chunk in the asset for desc.families[1]. Joint not created.", return nullptr);
- if (family1 != family0)
- {
- handle1 = family1->createExternalJointHandle(getFamilyID(family0), desc.chunkIndices[1], desc.chunkIndices[0]);
- NVBLAST_CHECK_ERROR(handle1 != nullptr, "TkFrameworkImpl::createJoint: could not create joint handle in family[1]. Joint not created.", return nullptr);
- }
- }
-
- TkJointImpl* joint = NVBLAST_NEW(TkJointImpl)(desc, nullptr);
- NVBLAST_CHECK_ERROR(joint != nullptr, "TkFrameworkImpl::createJoint: failed to create joint.", return nullptr);
-
- const TkJointData& jointData = joint->getDataInternal();
-
- if (handle0 != nullptr)
- {
- *handle0 = joint;
- static_cast<TkActorImpl*>(jointData.actors[0])->addJoint(joint->m_links[0]);
- }
-
- if (handle1 != nullptr)
- {
- *handle1 = joint;
- if (jointData.actors[0] != jointData.actors[1])
- {
- static_cast<TkActorImpl*>(jointData.actors[1])->addJoint(joint->m_links[1]);
- }
- }
-
- return joint;
-}
-
-
-void TkFrameworkImpl::onCreate(TkIdentifiable& object)
-{
- const TkTypeImpl& type = static_cast<const TkTypeImpl&>(object.getType());
-
- const uint32_t index = type.getIndex();
-
- if (index >= m_objects.size())
- {
- if (!isInvalidIndex(index))
- {
- NVBLAST_LOG_ERROR("TkFrameworkImpl::addObject: object type unrecognized.");
- }
- return;
- }
-
- auto& objectArray = m_objects[index];
- NVBLAST_ASSERT(objectArray.find(&object) == objectArray.end());
- objectArray.pushBack(&object);
-}
-
-
-void TkFrameworkImpl::onDestroy(TkIdentifiable& object)
-{
- // remove from id map if present
- const auto id = object.getID();
- if (!TkGUIDIsZero(&id))
- {
- m_IDToObject.erase(id);
- }
-
- // remove from object list
- const TkTypeImpl& type = static_cast<const TkTypeImpl&>(object.getType());
-
- const uint32_t index = type.getIndex();
-
- if (index >= m_objects.size())
- {
- if (!isInvalidIndex(index))
- {
- NVBLAST_LOG_ERROR("TkFrameworkImpl::removeObject: object type unrecognized.");
- }
- return;
- }
-
- auto& objectArray = m_objects[index];
- objectArray.findAndReplaceWithLast(&object);
-}
-
-
-void TkFrameworkImpl::onCreate(TkJointImpl& joint)
-{
- NVBLAST_CHECK_ERROR(m_joints.insert(&joint), "TkFrameworkImpl::onCreate: Joint already tracked.", return);
-}
-
-
-void TkFrameworkImpl::onDestroy(TkJointImpl& joint)
-{
- NVBLAST_CHECK_ERROR(m_joints.erase(&joint), "TkFrameworkImpl::onDestroy: Joint not tracked.", return);
-}
-
-
-void TkFrameworkImpl::onIDChange(TkIdentifiable& object, const NvBlastID& IDPrev, const NvBlastID& IDCurr)
-{
- if (!TkGUIDIsZero(&IDPrev))
- {
- if (!m_IDToObject.erase(IDPrev))
- {
- NVBLAST_LOG_ERROR("TkFrameworkImpl::reportIDChanged: object with previous ID doesn't exist.");
- }
- }
-
- if (!TkGUIDIsZero(&IDCurr))
- {
- auto& value = m_IDToObject[IDCurr];
- if (value != nullptr)
- {
- NVBLAST_LOG_ERROR("TkFrameworkImpl::reportIDChanged: object with new ID already exists.");
- return;
- }
- value = &object;
- }
-}
-
-} // namespace Blast
-} // namespace Nv
-
-
-//////// Global API implementation ////////
-
-Nv::Blast::TkFramework* NvBlastTkFrameworkCreate()
-{
- if (Nv::Blast::TkFrameworkImpl::get() != nullptr)
- {
- NVBLAST_LOG_ERROR("TkFramework::create: framework already created. Use TkFramework::get() to access.");
- return nullptr;
- }
-
- Nv::Blast::TkFrameworkImpl* framework = NVBLAST_NEW(Nv::Blast::TkFrameworkImpl) ();
- Nv::Blast::TkFrameworkImpl::set(framework);
-
- return Nv::Blast::TkFrameworkImpl::get();
-}
-
-
-Nv::Blast::TkFramework* NvBlastTkFrameworkGet()
-{
- return Nv::Blast::TkFrameworkImpl::get();
-}
+// 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) 2016-2018 NVIDIA Corporation. All rights reserved.
+
+
+#include "NvBlastAssert.h"
+
+#include "NvBlastTkFrameworkImpl.h"
+#include "NvBlastTkAssetImpl.h"
+#include "NvBlastTkFamilyImpl.h"
+#include "NvBlastTkGroupImpl.h"
+#include "NvBlastTkActorImpl.h"
+#include "NvBlastTkJointImpl.h"
+#include "NvBlastTkTypeImpl.h"
+
+#include "NvBlastGlobals.h"
+
+#include <algorithm>
+
+
+using namespace physx;
+using namespace physx::shdfnd;
+
+
+NV_INLINE bool operator < (const NvBlastID& id1, const NvBlastID& id2)
+{
+ return memcmp(&id1, &id2, sizeof(NvBlastID)) < 0;
+}
+
+
+namespace Nv
+{
+namespace Blast
+{
+
+//////// Local definitions ////////
+
+// Map type ID to static type data
+#define NVBLASTTK_REGISTER_TYPE(_name) \
+ if (!Tk##_name##Impl::s_type.indexIsValid()) \
+ { \
+ Tk##_name##Impl::s_type.setIndex(TkTypeIndex::_name); \
+ } \
+ m_types[TkTypeIndex::_name] = &Tk##_name##Impl::s_type; \
+ m_typeIDToIndex[Tk##_name##Impl::s_type.getID()] = TkTypeIndex::_name
+
+
+#define NVBLASTTK_RELEASE_TYPE(_name) \
+ { \
+ TkTypeImpl& type = Tk##_name##Impl::s_type; \
+ auto& toRelease = m_objects[type.getIndex()]; \
+ for (TkObject* obj : toRelease) \
+ { \
+ obj->release(); \
+ } \
+ }
+
+
+//////// TkFrameworkImpl static variables ////////
+
+TkFrameworkImpl* TkFrameworkImpl::s_framework = nullptr;
+
+
+//////// TkFrameworkImpl static function ////////
+
+TkFrameworkImpl* TkFrameworkImpl::get()
+{
+ return s_framework;
+}
+
+
+bool TkFrameworkImpl::set(TkFrameworkImpl* framework)
+{
+ if (s_framework != nullptr)
+ {
+ if (framework != nullptr)
+ {
+ NVBLAST_LOG_ERROR("TkFrameworkImpl::set: framework already set. Pass NULL to this function to destroy framework.");
+ return false;
+ }
+
+ NVBLAST_DELETE(s_framework, TkFrameworkImpl);
+ }
+
+ s_framework = framework;
+
+ return true;
+}
+
+
+//////// TkFrameworkImpl methods ////////
+
+TkFrameworkImpl::TkFrameworkImpl()
+ : TkFramework()
+{
+ // Register types
+ m_types.resize(TkTypeIndex::TypeCount);
+ m_objects.resize(TkTypeIndex::TypeCount);
+ NVBLASTTK_REGISTER_TYPE(Asset);
+ NVBLASTTK_REGISTER_TYPE(Family);
+ NVBLASTTK_REGISTER_TYPE(Group);
+}
+
+
+TkFrameworkImpl::~TkFrameworkImpl()
+{
+}
+
+
+void TkFrameworkImpl::release()
+{
+ // Special release of joints, which are not TkIdentifiable:
+ Array<TkJointImpl*>::type joints; // Since the EraseIterator is not exposed
+ joints.reserve(m_joints.size());
+ for (auto j = m_joints.getIterator(); !j.done(); ++j)
+ {
+ joints.pushBack(*j);
+ }
+ for (uint32_t i = 0; i < joints.size(); ++i)
+ {
+ joints[i]->release();
+ }
+ NVBLAST_ASSERT(m_joints.size() == 0);
+ joints.reset(); // Since we will be deleting the allocator
+
+ NVBLASTTK_RELEASE_TYPE(Group);
+ NVBLASTTK_RELEASE_TYPE(Asset);
+ set(nullptr);
+}
+
+
+const TkType* TkFrameworkImpl::getType(TkTypeIndex::Enum typeIndex) const
+{
+ if (typeIndex < 0 || typeIndex >= TkTypeIndex::TypeCount)
+ {
+ NVBLAST_LOG_WARNING("TkFrameworkImpl::getType: invalid typeIndex.");
+ return nullptr;
+ }
+
+ return m_types[typeIndex];
+}
+
+
+TkIdentifiable* TkFrameworkImpl::findObjectByID(const NvBlastID& id) const
+{
+ TkIdentifiable* object = findObjectByIDInternal(id);
+
+ if (object == nullptr)
+ {
+ NVBLAST_LOG_WARNING("TkFrameworkImpl::findObjectByID: object not found.");
+ }
+
+ return object;
+}
+
+
+uint32_t TkFrameworkImpl::getObjectCount(const TkType& type) const
+{
+ const uint32_t index = static_cast<const TkTypeImpl&>(type).getIndex();
+
+ if (index >= m_objects.size())
+ {
+ NVBLAST_LOG_ERROR("TkFrameworkImpl::getObjectCount: BlastTk object type unrecognized.");
+ return 0;
+
+ }
+
+ return m_objects[index].size();
+}
+
+
+uint32_t TkFrameworkImpl::getObjects(TkIdentifiable** buffer, uint32_t bufferSize, const TkType& type, uint32_t indexStart /* = 0 */) const
+{
+ const uint32_t index = static_cast<const TkTypeImpl&>(type).getIndex();
+
+ if (index >= m_objects.size())
+ {
+ NVBLAST_LOG_ERROR("TkFrameworkImpl::getObjectCount: BlastTk object type unrecognized.");
+ return 0;
+ }
+
+ const auto& objectArray = m_objects[index];
+
+ uint32_t objectCount = objectArray.size();
+ if (objectCount <= indexStart)
+ {
+ NVBLAST_LOG_WARNING("TkFrameworkImpl::getObjects: indexStart beyond end of object list.");
+ return 0;
+ }
+
+ objectCount -= indexStart;
+ if (objectCount > bufferSize)
+ {
+ objectCount = bufferSize;
+ }
+
+ memcpy(buffer, objectArray.begin() + indexStart, objectCount * sizeof(TkObject*));
+
+ return objectCount;
+}
+
+
+bool TkFrameworkImpl::reorderAssetDescChunks(NvBlastChunkDesc* chunkDescs, uint32_t chunkCount, NvBlastBondDesc* bondDescs, uint32_t bondCount, uint32_t* chunkReorderMap /*= nullptr*/, bool keepBondNormalChunkOrder /*= false*/) const
+{
+ uint32_t* map = chunkReorderMap != nullptr ? chunkReorderMap : static_cast<uint32_t*>(NVBLAST_ALLOC_NAMED(chunkCount * sizeof(uint32_t), "reorderAssetDescChunks:chunkReorderMap"));
+ void* scratch = NVBLAST_ALLOC_NAMED(chunkCount * sizeof(NvBlastChunkDesc), "reorderAssetDescChunks:scratch");
+ const bool result = NvBlastReorderAssetDescChunks(chunkDescs, chunkCount, bondDescs, bondCount, map, keepBondNormalChunkOrder, scratch, logLL);
+ NVBLAST_FREE(scratch);
+ if (chunkReorderMap == nullptr)
+ {
+ NVBLAST_FREE(map);
+ }
+ return result;
+}
+
+
+bool TkFrameworkImpl::ensureAssetExactSupportCoverage(NvBlastChunkDesc* chunkDescs, uint32_t chunkCount) const
+{
+ void* scratch = NVBLAST_ALLOC_NAMED(chunkCount, "ensureAssetExactSupportCoverage:scratch");
+ const bool result = NvBlastEnsureAssetExactSupportCoverage(chunkDescs, chunkCount, scratch, logLL);
+ NVBLAST_FREE(scratch);
+ return result;
+}
+
+
+TkAsset* TkFrameworkImpl::createAsset(const TkAssetDesc& desc)
+{
+ TkAssetImpl* asset = TkAssetImpl::create(desc);
+ if (asset == nullptr)
+ {
+ NVBLAST_LOG_ERROR("TkFrameworkImpl::createAsset: failed to create asset.");
+ }
+
+ return asset;
+}
+
+
+TkAsset* TkFrameworkImpl::createAsset(const NvBlastAsset* assetLL, Nv::Blast::TkAssetJointDesc* jointDescs, uint32_t jointDescCount, bool ownsAsset)
+{
+ TkAssetImpl* asset = TkAssetImpl::create(assetLL, jointDescs, jointDescCount, ownsAsset);
+ if (asset == nullptr)
+ {
+ NVBLAST_LOG_ERROR("TkFrameworkImpl::createAsset: failed to create asset.");
+ }
+
+ return asset;
+}
+
+
+TkGroup* TkFrameworkImpl::createGroup(const TkGroupDesc& desc)
+{
+ TkGroupImpl* group = TkGroupImpl::create(desc);
+ if (group == nullptr)
+ {
+ NVBLAST_LOG_ERROR("TkFrameworkImpl::createGroup: failed to create group.");
+ }
+
+ return group;
+}
+
+
+TkActor* TkFrameworkImpl::createActor(const TkActorDesc& desc)
+{
+ TkActor* actor = TkActorImpl::create(desc);
+ if (actor == nullptr)
+ {
+ NVBLAST_LOG_ERROR("TkFrameworkImpl::createActor: failed to create actor.");
+ }
+
+ return actor;
+}
+
+
+TkJoint* TkFrameworkImpl::createJoint(const TkJointDesc& desc)
+{
+ TkJointImpl** handle0 = nullptr;
+ TkJointImpl** handle1 = nullptr;
+
+ TkFamilyImpl* family0 = static_cast<TkFamilyImpl*>(desc.families[0]);
+ TkFamilyImpl* family1 = static_cast<TkFamilyImpl*>(desc.families[1]);
+
+ NVBLAST_CHECK_ERROR(family0 != nullptr || family1 != nullptr, "TkFrameworkImpl::createJoint: at least one family in the TkJointDesc must be valid.", return nullptr);
+
+ NVBLAST_CHECK_ERROR(family0 == nullptr || desc.chunkIndices[0] < family0->getAssetImpl()->getChunkCount(), "TkFrameworkImpl::createJoint: desc.chunkIndices[0] is invalid.", return nullptr);
+ NVBLAST_CHECK_ERROR(family1 == nullptr || desc.chunkIndices[1] < family1->getAssetImpl()->getChunkCount(), "TkFrameworkImpl::createJoint: desc.chunkIndices[1] is invalid.", return nullptr);
+
+ const bool actorsAreTheSame = family0 == family1 && family0->getActorByChunk(desc.chunkIndices[0]) == family1->getActorByChunk(desc.chunkIndices[1]);
+ NVBLAST_CHECK_ERROR(!actorsAreTheSame, "TkFrameworkImpl::createJoint: the chunks listed in the TkJointDesc must be in different actors.", return nullptr);
+
+ if (family0 != nullptr)
+ {
+ const bool isSupportChunk = !isInvalidIndex(NvBlastAssetGetChunkToGraphNodeMap(family0->getAssetImpl()->getAssetLLInternal(), logLL)[desc.chunkIndices[0]]);
+ NVBLAST_CHECK_ERROR(isSupportChunk, "TkFrameworkImpl::createJoint: desc.chunkIndices[0] is not a support chunk in the asset for desc.families[0]. Joint not created.", return nullptr);
+ handle0 = family0->createExternalJointHandle(getFamilyID(family1), desc.chunkIndices[0], desc.chunkIndices[1]);
+ NVBLAST_CHECK_ERROR(handle0 != nullptr, "TkFrameworkImpl::createJoint: could not create joint handle in family[0]. Joint not created.", return nullptr);
+ }
+
+ if (family1 != nullptr)
+ {
+ const bool isSupportChunk = !isInvalidIndex(NvBlastAssetGetChunkToGraphNodeMap(family1->getAssetImpl()->getAssetLLInternal(), logLL)[desc.chunkIndices[1]]);
+ NVBLAST_CHECK_ERROR(isSupportChunk, "TkFrameworkImpl::createJoint: desc.chunkIndices[1] is not a support chunk in the asset for desc.families[1]. Joint not created.", return nullptr);
+ if (family1 != family0)
+ {
+ handle1 = family1->createExternalJointHandle(getFamilyID(family0), desc.chunkIndices[1], desc.chunkIndices[0]);
+ NVBLAST_CHECK_ERROR(handle1 != nullptr, "TkFrameworkImpl::createJoint: could not create joint handle in family[1]. Joint not created.", return nullptr);
+ }
+ }
+
+ TkJointImpl* joint = NVBLAST_NEW(TkJointImpl)(desc, nullptr);
+ NVBLAST_CHECK_ERROR(joint != nullptr, "TkFrameworkImpl::createJoint: failed to create joint.", return nullptr);
+
+ const TkJointData& jointData = joint->getDataInternal();
+
+ if (handle0 != nullptr)
+ {
+ *handle0 = joint;
+ static_cast<TkActorImpl*>(jointData.actors[0])->addJoint(joint->m_links[0]);
+ }
+
+ if (handle1 != nullptr)
+ {
+ *handle1 = joint;
+ if (jointData.actors[0] != jointData.actors[1])
+ {
+ static_cast<TkActorImpl*>(jointData.actors[1])->addJoint(joint->m_links[1]);
+ }
+ }
+
+ return joint;
+}
+
+
+void TkFrameworkImpl::onCreate(TkIdentifiable& object)
+{
+ const TkTypeImpl& type = static_cast<const TkTypeImpl&>(object.getType());
+
+ const uint32_t index = type.getIndex();
+
+ if (index >= m_objects.size())
+ {
+ if (!isInvalidIndex(index))
+ {
+ NVBLAST_LOG_ERROR("TkFrameworkImpl::addObject: object type unrecognized.");
+ }
+ return;
+ }
+
+ auto& objectArray = m_objects[index];
+ NVBLAST_ASSERT(objectArray.find(&object) == objectArray.end());
+ objectArray.pushBack(&object);
+}
+
+
+void TkFrameworkImpl::onDestroy(TkIdentifiable& object)
+{
+ // remove from id map if present
+ const auto id = object.getID();
+ if (!TkGUIDIsZero(&id))
+ {
+ m_IDToObject.erase(id);
+ }
+
+ // remove from object list
+ const TkTypeImpl& type = static_cast<const TkTypeImpl&>(object.getType());
+
+ const uint32_t index = type.getIndex();
+
+ if (index >= m_objects.size())
+ {
+ if (!isInvalidIndex(index))
+ {
+ NVBLAST_LOG_ERROR("TkFrameworkImpl::removeObject: object type unrecognized.");
+ }
+ return;
+ }
+
+ auto& objectArray = m_objects[index];
+ objectArray.findAndReplaceWithLast(&object);
+}
+
+
+void TkFrameworkImpl::onCreate(TkJointImpl& joint)
+{
+ NVBLAST_CHECK_ERROR(m_joints.insert(&joint), "TkFrameworkImpl::onCreate: Joint already tracked.", return);
+}
+
+
+void TkFrameworkImpl::onDestroy(TkJointImpl& joint)
+{
+ NVBLAST_CHECK_ERROR(m_joints.erase(&joint), "TkFrameworkImpl::onDestroy: Joint not tracked.", return);
+}
+
+
+void TkFrameworkImpl::onIDChange(TkIdentifiable& object, const NvBlastID& IDPrev, const NvBlastID& IDCurr)
+{
+ if (!TkGUIDIsZero(&IDPrev))
+ {
+ if (!m_IDToObject.erase(IDPrev))
+ {
+ NVBLAST_LOG_ERROR("TkFrameworkImpl::reportIDChanged: object with previous ID doesn't exist.");
+ }
+ }
+
+ if (!TkGUIDIsZero(&IDCurr))
+ {
+ auto& value = m_IDToObject[IDCurr];
+ if (value != nullptr)
+ {
+ NVBLAST_LOG_ERROR("TkFrameworkImpl::reportIDChanged: object with new ID already exists.");
+ return;
+ }
+ value = &object;
+ }
+}
+
+} // namespace Blast
+} // namespace Nv
+
+
+//////// Global API implementation ////////
+
+Nv::Blast::TkFramework* NvBlastTkFrameworkCreate()
+{
+ if (Nv::Blast::TkFrameworkImpl::get() != nullptr)
+ {
+ NVBLAST_LOG_ERROR("TkFramework::create: framework already created. Use TkFramework::get() to access.");
+ return nullptr;
+ }
+
+ Nv::Blast::TkFrameworkImpl* framework = NVBLAST_NEW(Nv::Blast::TkFrameworkImpl) ();
+ Nv::Blast::TkFrameworkImpl::set(framework);
+
+ return Nv::Blast::TkFrameworkImpl::get();
+}
+
+
+Nv::Blast::TkFramework* NvBlastTkFrameworkGet()
+{
+ return Nv::Blast::TkFrameworkImpl::get();
+}
diff --git a/sdk/toolkit/source/NvBlastTkFrameworkImpl.h b/sdk/toolkit/source/NvBlastTkFrameworkImpl.h
index 29914c2..497ab10 100644..100755
--- a/sdk/toolkit/source/NvBlastTkFrameworkImpl.h
+++ b/sdk/toolkit/source/NvBlastTkFrameworkImpl.h
@@ -1,162 +1,162 @@
-// 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) 2016-2018 NVIDIA Corporation. All rights reserved.
-
-
-#ifndef NVBLASTTKFRAMEWORKIMPL_H
-#define NVBLASTTKFRAMEWORKIMPL_H
-
-#include "NvBlastTkFramework.h"
-#include "NvBlastProfilerInternal.h"
-
-#include "NvBlastTkCommon.h"
-
-#include "NvBlastArray.h"
-#include "NvBlastHashMap.h"
-#include "NvBlastHashSet.h"
-
-
-namespace Nv
-{
-namespace Blast
-{
-
-// Forward declarations
-class TkTypeImpl;
-class TkJointImpl;
-
-/**
-Implementation of TkFramework
-*/
-class TkFrameworkImpl : public TkFramework
-{
-public:
- TkFrameworkImpl();
- ~TkFrameworkImpl();
-
- // Begin TkFramework
- virtual void release() override;
-
- virtual const TkType* getType(TkTypeIndex::Enum typeIndex) const override;
-
- virtual TkIdentifiable* findObjectByID(const NvBlastID& id) const override;
-
- virtual uint32_t getObjectCount(const TkType& type) const override;
-
- virtual uint32_t getObjects(TkIdentifiable** buffer, uint32_t bufferSize, const TkType& type, uint32_t indexStart = 0) const override;
-
- virtual bool reorderAssetDescChunks(NvBlastChunkDesc* chunkDescs, uint32_t chunkCount, NvBlastBondDesc* bondDescs, uint32_t bondCount, uint32_t* chunkReorderMap = nullptr, bool keepBondNormalChunkOrder = false) const override;
-
- virtual bool ensureAssetExactSupportCoverage(NvBlastChunkDesc* chunkDescs, uint32_t chunkCount) const override;
-
- virtual TkAsset* createAsset(const TkAssetDesc& desc) override;
-
- virtual TkAsset* createAsset(const NvBlastAsset* assetLL, Nv::Blast::TkAssetJointDesc* jointDescs = nullptr, uint32_t jointDescCount = 0, bool ownsAsset = false) override;
-
- virtual TkGroup* createGroup(const TkGroupDesc& desc) override;
-
- virtual TkActor* createActor(const TkActorDesc& desc) override;
-
- virtual TkJoint* createJoint(const TkJointDesc& desc) override;
- // End TkFramework
-
- // Public methods
- /**
- To be called by any TkIdentifiable object when it is created, so the framework can track it.
- */
- void onCreate(TkIdentifiable& object);
-
- /**
- To be called by any TkIdentifiable object when it is deleted, so the framework can stop tracking it.
- */
- void onDestroy(TkIdentifiable& object);
-
- /**
- Special onCreate method for joints, since they are not TkIdentifiable.
- */
- void onCreate(TkJointImpl& joint);
-
- /**
- Special onDestroy method for joints, since they are not TkIdentifiable.
- */
- void onDestroy(TkJointImpl& joint);
-
- /**
- Must be called whenever a TkIdentifiable object's ID is changed, so that the framework can associate the new ID with it.
- */
- void onIDChange(TkIdentifiable& object, const NvBlastID& IDPrev, const NvBlastID& IDCurr);
-
- /**
- Internal (non-virtual) method to find a TkIdentifiable object based upon its NvBlastID.
- */
- TkIdentifiable* findObjectByIDInternal(const NvBlastID& id) const;
-
- // Access to singleton
-
- /** Retrieve the global singleton. */
- static TkFrameworkImpl* get();
-
- /** Set the global singleton, if it's not already set, or set it to NULL. Returns true iff successful. */
- static bool set(TkFrameworkImpl* framework);
-
-private:
- // Enums
- enum { ClassID = NVBLAST_FOURCC('T', 'K', 'F', 'W') }; //!< TkFramework identifier token, used in serialization
-
- // Static data
- static TkFrameworkImpl* s_framework; //!< Global (singleton) object pointer
-
- // Types
- InlineArray<const TkTypeImpl*, TkTypeIndex::TypeCount>::type m_types; //!< TkIdentifiable static type data
- HashMap<uint32_t, uint32_t>::type m_typeIDToIndex; //!< Map to type data keyed by ClassID
-
- // Objects and object names
- HashMap<NvBlastID, TkIdentifiable*>::type m_IDToObject; //!< Map to all TkIdentifiable objects, keyed by NvBlastID
- InlineArray<Array<TkIdentifiable*>::type, TkTypeIndex::TypeCount>::type m_objects; //!< Catalog of all TkIdentifiable objects, grouped by type. (Revisit implementation.)
-
- // Track external joints (to do: make this a pool)
- HashSet<TkJointImpl*>::type m_joints; //!< All internal joints
-};
-
-
-//////// TkFrameworkImpl inline methods ////////
-
-NV_INLINE TkIdentifiable* TkFrameworkImpl::findObjectByIDInternal(const NvBlastID& id) const
-{
- const auto entry = m_IDToObject.find(id);
- if (entry == nullptr)
- {
- return nullptr;
- }
-
- return entry->second;
-}
-
-} // namespace Blast
-} // namespace Nv
-
-
-#endif // ifndef NVBLASTTKFRAMEWORKIMPL_H
+// 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) 2016-2018 NVIDIA Corporation. All rights reserved.
+
+
+#ifndef NVBLASTTKFRAMEWORKIMPL_H
+#define NVBLASTTKFRAMEWORKIMPL_H
+
+#include "NvBlastTkFramework.h"
+#include "NvBlastProfilerInternal.h"
+
+#include "NvBlastTkCommon.h"
+
+#include "NvBlastArray.h"
+#include "NvBlastHashMap.h"
+#include "NvBlastHashSet.h"
+
+
+namespace Nv
+{
+namespace Blast
+{
+
+// Forward declarations
+class TkTypeImpl;
+class TkJointImpl;
+
+/**
+Implementation of TkFramework
+*/
+class TkFrameworkImpl : public TkFramework
+{
+public:
+ TkFrameworkImpl();
+ ~TkFrameworkImpl();
+
+ // Begin TkFramework
+ virtual void release() override;
+
+ virtual const TkType* getType(TkTypeIndex::Enum typeIndex) const override;
+
+ virtual TkIdentifiable* findObjectByID(const NvBlastID& id) const override;
+
+ virtual uint32_t getObjectCount(const TkType& type) const override;
+
+ virtual uint32_t getObjects(TkIdentifiable** buffer, uint32_t bufferSize, const TkType& type, uint32_t indexStart = 0) const override;
+
+ virtual bool reorderAssetDescChunks(NvBlastChunkDesc* chunkDescs, uint32_t chunkCount, NvBlastBondDesc* bondDescs, uint32_t bondCount, uint32_t* chunkReorderMap = nullptr, bool keepBondNormalChunkOrder = false) const override;
+
+ virtual bool ensureAssetExactSupportCoverage(NvBlastChunkDesc* chunkDescs, uint32_t chunkCount) const override;
+
+ virtual TkAsset* createAsset(const TkAssetDesc& desc) override;
+
+ virtual TkAsset* createAsset(const NvBlastAsset* assetLL, Nv::Blast::TkAssetJointDesc* jointDescs = nullptr, uint32_t jointDescCount = 0, bool ownsAsset = false) override;
+
+ virtual TkGroup* createGroup(const TkGroupDesc& desc) override;
+
+ virtual TkActor* createActor(const TkActorDesc& desc) override;
+
+ virtual TkJoint* createJoint(const TkJointDesc& desc) override;
+ // End TkFramework
+
+ // Public methods
+ /**
+ To be called by any TkIdentifiable object when it is created, so the framework can track it.
+ */
+ void onCreate(TkIdentifiable& object);
+
+ /**
+ To be called by any TkIdentifiable object when it is deleted, so the framework can stop tracking it.
+ */
+ void onDestroy(TkIdentifiable& object);
+
+ /**
+ Special onCreate method for joints, since they are not TkIdentifiable.
+ */
+ void onCreate(TkJointImpl& joint);
+
+ /**
+ Special onDestroy method for joints, since they are not TkIdentifiable.
+ */
+ void onDestroy(TkJointImpl& joint);
+
+ /**
+ Must be called whenever a TkIdentifiable object's ID is changed, so that the framework can associate the new ID with it.
+ */
+ void onIDChange(TkIdentifiable& object, const NvBlastID& IDPrev, const NvBlastID& IDCurr);
+
+ /**
+ Internal (non-virtual) method to find a TkIdentifiable object based upon its NvBlastID.
+ */
+ TkIdentifiable* findObjectByIDInternal(const NvBlastID& id) const;
+
+ // Access to singleton
+
+ /** Retrieve the global singleton. */
+ static TkFrameworkImpl* get();
+
+ /** Set the global singleton, if it's not already set, or set it to NULL. Returns true iff successful. */
+ static bool set(TkFrameworkImpl* framework);
+
+private:
+ // Enums
+ enum { ClassID = NVBLAST_FOURCC('T', 'K', 'F', 'W') }; //!< TkFramework identifier token, used in serialization
+
+ // Static data
+ static TkFrameworkImpl* s_framework; //!< Global (singleton) object pointer
+
+ // Types
+ InlineArray<const TkTypeImpl*, TkTypeIndex::TypeCount>::type m_types; //!< TkIdentifiable static type data
+ HashMap<uint32_t, uint32_t>::type m_typeIDToIndex; //!< Map to type data keyed by ClassID
+
+ // Objects and object names
+ HashMap<NvBlastID, TkIdentifiable*>::type m_IDToObject; //!< Map to all TkIdentifiable objects, keyed by NvBlastID
+ InlineArray<Array<TkIdentifiable*>::type, TkTypeIndex::TypeCount>::type m_objects; //!< Catalog of all TkIdentifiable objects, grouped by type. (Revisit implementation.)
+
+ // Track external joints (to do: make this a pool)
+ HashSet<TkJointImpl*>::type m_joints; //!< All internal joints
+};
+
+
+//////// TkFrameworkImpl inline methods ////////
+
+NV_INLINE TkIdentifiable* TkFrameworkImpl::findObjectByIDInternal(const NvBlastID& id) const
+{
+ const auto entry = m_IDToObject.find(id);
+ if (entry == nullptr)
+ {
+ return nullptr;
+ }
+
+ return entry->second;
+}
+
+} // namespace Blast
+} // namespace Nv
+
+
+#endif // ifndef NVBLASTTKFRAMEWORKIMPL_H
diff --git a/sdk/toolkit/source/NvBlastTkGUID.h b/sdk/toolkit/source/NvBlastTkGUID.h
index 927e915..907a803 100644..100755
--- a/sdk/toolkit/source/NvBlastTkGUID.h
+++ b/sdk/toolkit/source/NvBlastTkGUID.h
@@ -1,148 +1,148 @@
-// 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) 2016-2018 NVIDIA Corporation. All rights reserved.
-
-
-#ifndef NVBLASTTKGUID_H
-#define NVBLASTTKGUID_H
-
-#include "NvPreprocessor.h"
-
-#if NV_WINDOWS_FAMILY
-#include <rpc.h>
-#else
-//#include <uuid/uuid.h>
-#include "NvBlastTime.h"
-#endif
-
-#include "PsHash.h"
-
-namespace Nv
-{
-namespace Blast
-{
-
-#if NV_WINDOWS_FAMILY
-
-NV_INLINE NvBlastID TkGenerateGUID(void* ptr)
-{
- NV_UNUSED(ptr);
-
- NV_COMPILE_TIME_ASSERT(sizeof(UUID) == sizeof(NvBlastID));
-
- NvBlastID guid;
- UuidCreate(reinterpret_cast<UUID*>(&guid));
-
- return guid;
-}
-
-#else
-
-NV_INLINE NvBlastID TkGenerateGUID(void* ptr)
-{
-// NV_COMPILE_TIME_ASSERT(sizeof(uuid_t) == sizeof(NvBlastID));
- Time time;
-
- NvBlastID guid;
- // uuid_generate_random(reinterpret_cast<uuid_t&>(guid));
-
- *reinterpret_cast<uint64_t*>(guid.data) = reinterpret_cast<uintptr_t>(ptr);
- *reinterpret_cast<int64_t*>(guid.data + 8) = time.getLastTickCount();
-
- return guid;
-}
-
-#endif
-
-
-/**
-Compares two NvBlastIDs.
-
-\param[in] id1 A pointer to the first id to compare.
-\param[in] id2 A pointer to the second id to compare.
-
-\return true iff ids are equal.
-*/
-NV_INLINE bool TkGUIDsEqual(const NvBlastID* id1, const NvBlastID* id2)
-{
- return !memcmp(id1, id2, sizeof(NvBlastID));
-}
-
-
-/**
-Clears an NvBlastID (sets all of its fields to zero).
-
-\param[out] id A pointer to the ID to clear.
-*/
-NV_INLINE void TkGUIDReset(NvBlastID* id)
-{
- memset(id, 0, sizeof(NvBlastID));
-}
-
-
-/**
-Tests an NvBlastID to determine if it's zeroed. After calling TkGUIDReset
-on an ID, passing it to this function will return a value of true.
-
-\param[in] id A pointer to the ID to test.
-*/
-NV_INLINE bool TkGUIDIsZero(const NvBlastID* id)
-{
- return *reinterpret_cast<const uint64_t*>(&id->data[0]) == 0 && *reinterpret_cast<const uint64_t*>(&id->data[8]) == 0;
-}
-
-} // namespace Blast
-} // namespace Nv
-
-
-namespace physx
-{
-namespace shdfnd
-{
-
-// hash specialization for NvBlastID
-template <>
-struct Hash<NvBlastID>
-{
- uint32_t operator()(const NvBlastID& k) const
- {
- // "DJB" string hash
- uint32_t h = 5381;
- for (uint32_t i = 0; i < sizeof(k.data) / sizeof(k.data[0]); ++i)
- h = ((h << 5) + h) ^ uint32_t(k.data[i]);
- return h;
- }
- bool equal(const NvBlastID& k0, const NvBlastID& k1) const
- {
- return Nv::Blast::TkGUIDsEqual(&k0, &k1);
- }
-};
-
-} // namespace shdfnd
-} // namespace physx
-
-
-#endif // #ifndef NVBLASTTKGUID_H
+// 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) 2016-2018 NVIDIA Corporation. All rights reserved.
+
+
+#ifndef NVBLASTTKGUID_H
+#define NVBLASTTKGUID_H
+
+#include "NvPreprocessor.h"
+
+#if NV_WINDOWS_FAMILY
+#include <rpc.h>
+#else
+//#include <uuid/uuid.h>
+#include "NvBlastTime.h"
+#endif
+
+#include "PsHash.h"
+
+namespace Nv
+{
+namespace Blast
+{
+
+#if NV_WINDOWS_FAMILY
+
+NV_INLINE NvBlastID TkGenerateGUID(void* ptr)
+{
+ NV_UNUSED(ptr);
+
+ NV_COMPILE_TIME_ASSERT(sizeof(UUID) == sizeof(NvBlastID));
+
+ NvBlastID guid;
+ UuidCreate(reinterpret_cast<UUID*>(&guid));
+
+ return guid;
+}
+
+#else
+
+NV_INLINE NvBlastID TkGenerateGUID(void* ptr)
+{
+// NV_COMPILE_TIME_ASSERT(sizeof(uuid_t) == sizeof(NvBlastID));
+ Time time;
+
+ NvBlastID guid;
+ // uuid_generate_random(reinterpret_cast<uuid_t&>(guid));
+
+ *reinterpret_cast<uint64_t*>(guid.data) = reinterpret_cast<uintptr_t>(ptr);
+ *reinterpret_cast<int64_t*>(guid.data + 8) = time.getLastTickCount();
+
+ return guid;
+}
+
+#endif
+
+
+/**
+Compares two NvBlastIDs.
+
+\param[in] id1 A pointer to the first id to compare.
+\param[in] id2 A pointer to the second id to compare.
+
+\return true iff ids are equal.
+*/
+NV_INLINE bool TkGUIDsEqual(const NvBlastID* id1, const NvBlastID* id2)
+{
+ return !memcmp(id1, id2, sizeof(NvBlastID));
+}
+
+
+/**
+Clears an NvBlastID (sets all of its fields to zero).
+
+\param[out] id A pointer to the ID to clear.
+*/
+NV_INLINE void TkGUIDReset(NvBlastID* id)
+{
+ memset(id, 0, sizeof(NvBlastID));
+}
+
+
+/**
+Tests an NvBlastID to determine if it's zeroed. After calling TkGUIDReset
+on an ID, passing it to this function will return a value of true.
+
+\param[in] id A pointer to the ID to test.
+*/
+NV_INLINE bool TkGUIDIsZero(const NvBlastID* id)
+{
+ return *reinterpret_cast<const uint64_t*>(&id->data[0]) == 0 && *reinterpret_cast<const uint64_t*>(&id->data[8]) == 0;
+}
+
+} // namespace Blast
+} // namespace Nv
+
+
+namespace physx
+{
+namespace shdfnd
+{
+
+// hash specialization for NvBlastID
+template <>
+struct Hash<NvBlastID>
+{
+ uint32_t operator()(const NvBlastID& k) const
+ {
+ // "DJB" string hash
+ uint32_t h = 5381;
+ for (uint32_t i = 0; i < sizeof(k.data) / sizeof(k.data[0]); ++i)
+ h = ((h << 5) + h) ^ uint32_t(k.data[i]);
+ return h;
+ }
+ bool equal(const NvBlastID& k0, const NvBlastID& k1) const
+ {
+ return Nv::Blast::TkGUIDsEqual(&k0, &k1);
+ }
+};
+
+} // namespace shdfnd
+} // namespace physx
+
+
+#endif // #ifndef NVBLASTTKGUID_H
diff --git a/sdk/toolkit/source/NvBlastTkGroupImpl.cpp b/sdk/toolkit/source/NvBlastTkGroupImpl.cpp
index 1769f33..bcb8463 100644..100755
--- a/sdk/toolkit/source/NvBlastTkGroupImpl.cpp
+++ b/sdk/toolkit/source/NvBlastTkGroupImpl.cpp
@@ -1,612 +1,612 @@
-// 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) 2016-2018 NVIDIA Corporation. All rights reserved.
-
-
-#include "NvPreprocessor.h"
-
-#include "NvBlastAssert.h"
-#include "NvBlast.h"
-
-#include "NvBlastTkFrameworkImpl.h"
-#include "NvBlastTkGroupImpl.h"
-#include "NvBlastTkActorImpl.h"
-#include "NvBlastTkFamilyImpl.h"
-#include "NvBlastTkAssetImpl.h"
-#include "NvBlastTkTaskImpl.h"
-
-#undef max
-#undef min
-#include <algorithm>
-
-using namespace physx;
-
-
-namespace Nv
-{
-namespace Blast
-{
-
-//////// Static data ////////
-
-NVBLASTTK_DEFINE_TYPE_IDENTIFIABLE(Group);
-
-
-//////// Member functions ////////
-
-TkGroupImpl::TkGroupImpl() : m_actorCount(0), m_isProcessing(false)
-{
-#if NV_PROFILE
- memset(&m_stats, 0, sizeof(TkGroupStats));
-#endif
-}
-
-
-TkGroupImpl::~TkGroupImpl()
-{
- NVBLAST_ASSERT(getActorCount() == 0);
- NVBLAST_ASSERT(m_sharedMemory.size() == 0);
-}
-
-
-void TkGroupImpl::release()
-{
- if (isProcessing())
- {
- // abort all processing?
- NVBLAST_LOG_ERROR("TkGroup::release: cannot release Group while processing.");
- NVBLAST_ALWAYS_ASSERT_MESSAGE("TkGroup::release: cannot release Group while processing.");
- return;
- }
-
- for (auto it = m_sharedMemory.getIterator(); !it.done(); ++it)
- {
- TkFamilyImpl* family = it->first;
- for (TkActorImpl& actor : family->getActorsInternal())
- {
- if (actor.m_group == this)
- {
- removeActorInternal(actor);
- }
- }
- SharedMemory* mem = it->second;
- mem->release();
- NVBLAST_DELETE(mem, SharedMemory);
- }
- m_sharedMemory.clear();
-
- m_bondTempDataBlock.release();
- m_chunkTempDataBlock.release();
- m_bondEventDataBlock.release();
- m_chunkEventDataBlock.release();
- m_splitScratchBlock.release();
-
- NVBLAST_DELETE(this, TkGroupImpl);
-}
-
-
-void TkGroupImpl::addActorsInternal(TkActorImpl** actors, uint32_t numActors)
-{
- for (uint32_t i = 0; i < numActors; i++)
- {
- addActorInternal(*actors[i]);
- }
-}
-
-
-void TkGroupImpl::addActorInternal(TkActorImpl& tkActor)
-{
- NVBLAST_ASSERT(tkActor.getGroup() == nullptr);
- tkActor.m_group = this;
- m_actorCount++;
-}
-
-
-bool TkGroupImpl::addActor(TkActor& actor)
-{
- TkActorImpl& tkActor = static_cast<TkActorImpl&>(actor);
- if (tkActor.getGroup() != nullptr)
- {
- NVBLAST_LOG_ERROR("TkGroup::addActor: actor already belongs to a Group. Remove from current group first.");
- return false;
- }
-
- if (isProcessing())
- {
- NVBLAST_LOG_ERROR("TkGroup::addActor: cannot alter Group while processing.");
- return false;
- }
-
- // mark the actor that it now belongs to this group
- addActorInternal(tkActor);
-
- // actors that were fractured already or have damage requested
- // must be enqueued to be processed
- if (tkActor.isPending())
- {
- enqueue(&tkActor);
- }
-
- TkFamilyImpl& family = tkActor.getFamilyImpl();
- SharedMemory* mem = m_sharedMemory[&family];
- if (mem == nullptr)
- {
- // the actor belongs to a family not involved in this group yet
- // shared memory must be allocated and temporary buffers adjusted accordingly
-
- BLAST_PROFILE_ZONE_BEGIN("family memory");
- mem = NVBLAST_NEW(SharedMemory);
- mem->allocate(family);
- m_sharedMemory[&family] = mem;
- BLAST_PROFILE_ZONE_END("family memory");
-
- BLAST_PROFILE_ZONE_BEGIN("group memory");
-
- const uint32_t workerCount = m_workers.size();
-
- NvBlastLog theLog = logLL;
-
- // this group's tasks will use one temporary buffer each, which is of max size of, for all families involved
- const size_t requiredScratch = NvBlastActorGetRequiredScratchForSplit(tkActor.getActorLL(), theLog);
- if (static_cast<size_t>(m_splitScratchBlock.numElementsPerBlock()) < requiredScratch)
- {
- m_splitScratchBlock.release();
- m_splitScratchBlock.allocate(static_cast<uint32_t>(requiredScratch), workerCount);
- }
-
- // generate and apply fracture may create an entry for each bond
- const uint32_t bondCount = NvBlastAssetGetBondCount(tkActor.getAsset()->getAssetLL(), theLog);
- if (m_bondTempDataBlock.numElementsPerBlock() < bondCount)
- {
- m_bondTempDataBlock.release();
- m_bondTempDataBlock.allocate(bondCount, workerCount);
- m_bondEventDataBlock.release();
- m_bondEventDataBlock.allocate(bondCount, workerCount);
- }
-
- // apply fracture may create an entry for each lower-support chunk
- const uint32_t graphNodeCount = NvBlastAssetGetSupportGraph(tkActor.getAsset()->getAssetLL(), theLog).nodeCount;
- const uint32_t subsupportChunkCount
- = NvBlastAssetGetChunkCount(tkActor.getAsset()->getAssetLL(), theLog)
- - NvBlastAssetGetFirstSubsupportChunkIndex(tkActor.getAsset()->getAssetLL(), theLog);
- const uint32_t chunkCount = graphNodeCount + subsupportChunkCount;
- if (m_chunkTempDataBlock.numElementsPerBlock() < chunkCount)
- {
- m_chunkTempDataBlock.release();
- m_chunkTempDataBlock.allocate(chunkCount, workerCount);
- m_chunkEventDataBlock.release();
- m_chunkEventDataBlock.allocate(chunkCount, workerCount);
- }
- BLAST_PROFILE_ZONE_END("group memory");
- }
- mem->addReference();
-
- return true;
-}
-
-
-uint32_t TkGroupImpl::getActors(TkActor** buffer, uint32_t bufferSize, uint32_t indexStart /* = 0 */) const
-{
- BLAST_PROFILE_SCOPE_L("TkGroup::getActors");
-
- uint32_t actorCount = m_actorCount;
- if (actorCount <= indexStart)
- {
- NVBLAST_LOG_WARNING("TkGroup::getActors: indexStart beyond end of actor list.");
- return 0;
- }
-
- actorCount -= indexStart;
- if (actorCount > bufferSize)
- {
- actorCount = bufferSize;
- }
-
- uint32_t index = 0;
- bool done = false;
- for (auto it = const_cast<TkGroupImpl*>(this)->m_sharedMemory.getIterator(); !it.done();++it)
- {
- TkFamilyImpl* fam = it->first;
- for (TkActorImpl& actor : fam->getActorsInternal())
- {
- if (actor.m_group == this)
- {
- NVBLAST_ASSERT(actor.isActive());
-
- if (index >= indexStart)
- {
- *buffer++ = &actor;
- }
-
- index++;
- done = (index - indexStart) >= actorCount;
- }
- if (done) break;
- }
- if (done) break;
- }
-
- return actorCount;
-}
-
-
-void TkGroupImpl::removeActorInternal(TkActorImpl& tkActor)
-{
- NVBLAST_ASSERT(tkActor.m_group == this);
- tkActor.m_group = nullptr;
- m_actorCount--;
-}
-
-
-void TkGroupImpl::releaseSharedMemory(TkFamilyImpl* fam, SharedMemory* mem)
-{
- NVBLAST_ASSERT(mem != nullptr && m_sharedMemory[fam] == mem);
- mem->release();
- m_sharedMemory.erase(fam);
- NVBLAST_DELETE(mem, SharedMemory);
-}
-
-
-bool TkGroupImpl::removeActor(TkActor& actor)
-{
- TkActorImpl& tkActor = static_cast<TkActorImpl&>(actor);
-
- if (tkActor.getGroup() != this)
- {
- NVBLAST_LOG_ERROR("TkGroup::removeActor: actor does not belong to this Group.");
- return false;
- }
-
- if (isProcessing())
- {
- NVBLAST_LOG_ERROR("TkGroup::removeActor: cannot alter Group while processing.");
- return false;
- }
-
- removeActorInternal(tkActor);
-
- // pending actors must be removed from the job queue as well
- if(tkActor.isPending())
- {
- uint32_t index = tkActor.m_groupJobIndex;
- tkActor.m_groupJobIndex = invalidIndex<uint32_t>();
- m_jobs.replaceWithLast(index);
- if (index < m_jobs.size())
- {
- NVBLAST_ASSERT(m_jobs[index].m_tkActor->m_groupJobIndex == m_jobs.size());
- NVBLAST_ASSERT(m_jobs[index].m_tkActor->isPending());
- m_jobs[index].m_tkActor->m_groupJobIndex = index;
- }
- }
-
- // if the actor is the last of its family in this group
- // the group-family memory can be released
- TkFamilyImpl* family = &tkActor.getFamilyImpl();
- SharedMemory* mem = getSharedMemory(family);
- if (mem->removeReference())
- {
- releaseSharedMemory(family, mem);
- }
-
- return true;
-}
-
-
-TkGroupImpl* TkGroupImpl::create(const TkGroupDesc& desc)
-{
- TkGroupImpl* group = NVBLAST_NEW(TkGroupImpl);
-
- group->setWorkerCount(desc.workerCount);
-
- return group;
-}
-
-
-void TkGroupImpl::setWorkerCount(uint32_t workerCount)
-{
- if (isProcessing())
- {
- NVBLAST_LOG_WARNING("TkGroup::setWorkerCount: Group is still processing, call TkGroup::endProcess first.");
- return;
- }
-
- if (workerCount == 0)
- {
- NVBLAST_LOG_WARNING("TkGroup: attempting to create a Group with 0 workers. Forced to 1.");
- workerCount = 1;
- }
-
- if (workerCount != m_workers.size())
- {
- m_workers.resize(workerCount);
-
- uint32_t workerId = 0;
- for (auto& worker : m_workers)
- {
- worker.m_id = workerId++;
- worker.m_group = this;
- }
-
- const uint32_t bondCount = m_bondTempDataBlock.numElementsPerBlock();
- if (bondCount > 0)
- {
- m_bondTempDataBlock.release();
- m_bondTempDataBlock.allocate(bondCount, workerCount);
- m_bondEventDataBlock.release();
- m_bondEventDataBlock.allocate(bondCount, workerCount);
- }
- const uint32_t chunkCount = m_chunkTempDataBlock.numElementsPerBlock();
- if (chunkCount > 0)
- {
- m_chunkTempDataBlock.release();
- m_chunkTempDataBlock.allocate(chunkCount, workerCount);
- m_chunkEventDataBlock.release();
- m_chunkEventDataBlock.allocate(chunkCount, workerCount);
- }
- const uint32_t scratchSize = m_splitScratchBlock.numElementsPerBlock();
- if (scratchSize > 0)
- {
- m_splitScratchBlock.release();
- m_splitScratchBlock.allocate(scratchSize, workerCount);
- }
- }
-}
-
-
-NV_INLINE uint32_t TkGroupImpl::getWorkerCount() const
-{
- return m_workers.size();
-}
-
-
-uint32_t TkGroupImpl::startProcess()
-{
- BLAST_PROFILE_SCOPE_L("TkGroup::startProcess");
-
- if (!setProcessing(true))
- {
- NVBLAST_LOG_WARNING("TkGroup::process: Group is still processing, call TkGroup::endProcess first.");
- return 0;
- }
-
- if (m_jobs.size() > 0)
- {
- BLAST_PROFILE_ZONE_BEGIN("task setup");
-
- BLAST_PROFILE_ZONE_BEGIN("setup job queue");
- for (const auto& job : m_jobs)
- {
- const TkActorImpl* a = job.m_tkActor;
- SharedMemory* mem = getSharedMemory(&a->getFamilyImpl());
-
- const uint32_t damageCount = a->m_damageBuffer.size();
-
- // applyFracture'd actor do not necessarily have damage queued
- NVBLAST_ASSERT(damageCount > 0 || a->m_flags.isSet(TkActorFlag::DAMAGED));
-
- // no reason to be here without these
- NVBLAST_ASSERT(a->m_flags.isSet(TkActorFlag::PENDING));
- NVBLAST_ASSERT(a->m_group == this);
-
- // collect the amount of event payload memory to preallocate for TkWorkers
- mem->m_eventsMemory += damageCount * (sizeof(TkFractureCommands) + sizeof(TkFractureEvents)) + sizeof(TkSplitEvent);
-
- // collect the amount of event entries to preallocate for TkWorkers
- // (two TkFracture* events per damage plus one TkSplitEvent)
- mem->m_eventsCount += 2 * damageCount + 1;
- }
- BLAST_PROFILE_ZONE_END("setup job queue");
-
- BLAST_PROFILE_ZONE_BEGIN("memory protect");
- for (auto it = m_sharedMemory.getIterator(); !it.done(); ++it)
- {
- // preallocate the event memory for TkWorkers
- SharedMemory* mem = it->second;
- mem->m_events.reserveData(mem->m_eventsMemory);
- mem->m_events.reserveEvents(mem->m_eventsCount);
-
- // these counters are not used anymore
- // reset them immediately for next time
- mem->m_eventsCount = 0;
- mem->m_eventsMemory = 0;
-
- // switch to parallel mode
- mem->m_events.protect(true);
- }
- BLAST_PROFILE_ZONE_END("memory protect");
-
- BLAST_PROFILE_ZONE_END("task setup");
-
-
- for (auto&worker : m_workers)
- {
- worker.initialize();
- }
-
- return m_jobs.size();
- }
- else
- {
- bool success = setProcessing(false);
- NVBLAST_ASSERT(success);
- NV_UNUSED(success);
- return 0;
- }
-}
-
-
-bool TkGroupImpl::endProcess()
-{
- if (isProcessing())
- {
- BLAST_PROFILE_SCOPE_L("TkGroupImpl::endProcess");
-
- if (m_jobs.size() > 0)
- {
-#if NV_PROFILE
- BLAST_PROFILE_ZONE_BEGIN("accumulate timers");
- NvBlastTimers accumulated;
- NvBlastTimersReset(&accumulated);
- uint32_t jobCount = 0;
- int64_t workerTime = 0;
- for (TkWorker& worker : m_workers)
- {
- accumulated += worker.m_stats.timers;
- jobCount += worker.m_stats.processedActorsCount;
- workerTime += worker.m_stats.workerTime;
- }
- m_stats.timers = accumulated;
- m_stats.processedActorsCount = jobCount;
- m_stats.workerTime = workerTime;
- BLAST_PROFILE_ZONE_END("accumulate timers");
-#endif
-
- BLAST_PROFILE_ZONE_BEGIN("job update");
- for (auto& j : m_jobs)
- {
- if (j.m_newActorsCount)
- {
- TkFamilyImpl* fam = &j.m_tkActor->getFamilyImpl();
- SharedMemory* mem = getSharedMemory(fam);
-
- // as LL is implemented, where newActorsCount the parent is always deleted
- removeActorInternal(*j.m_tkActor);
- mem->removeReference();
- addActorsInternal(j.m_newActors, j.m_newActorsCount);
- mem->addReference(j.m_newActorsCount);
-
- // Update joints
- mem->m_events.protect(false); // allow allocations again
- BLAST_PROFILE_ZONE_BEGIN("updateJoints");
- fam->updateJoints(j.m_tkActor, &mem->m_events);
- BLAST_PROFILE_ZONE_END("updateJoints");
- }
-
- // virtually dequeue the actor
- // the queue itself is cleared right after this loop
- j.m_tkActor->m_flags.clear(TkActorFlag::PENDING);
- j.m_tkActor->m_groupJobIndex = invalidIndex<uint32_t>();
- BLAST_PROFILE_ZONE_BEGIN("damageBuffer.clear");
- j.m_tkActor->m_damageBuffer.clear();
- BLAST_PROFILE_ZONE_END("damageBuffer.clear");
- }
- m_jobs.clear();
- BLAST_PROFILE_ZONE_END("job update");
-
- BLAST_PROFILE_ZONE_BEGIN("event dispatch");
- for (auto it = m_sharedMemory.getIterator(); !it.done(); ++it)
- {
- BLAST_PROFILE_SCOPE_L("event dispatch");
- TkFamilyImpl* family = it->first;
- SharedMemory* mem = it->second;
-
- NVBLAST_ASSERT(family != nullptr);
- NVBLAST_ASSERT(mem != nullptr && mem->isUsed());
-
- // where no actor of a family has split,
- // its group/family event queue has not been
- // unprotected in the jobs loop above
- mem->m_events.protect(false);
-
- family->getQueue().dispatch(mem->m_events);
-
- mem->m_events.reset();
- mem->reset();
- }
- BLAST_PROFILE_ZONE_END("event dispatch");
-
- BLAST_PROFILE_ZONE_BEGIN("event memory release");
- for (auto& worker : m_workers)
- {
- worker.m_bondBuffer.clear();
- worker.m_chunkBuffer.clear();
- }
- BLAST_PROFILE_ZONE_END("event memory release");
- }
-
- bool success = setProcessing(false);
- NVBLAST_ASSERT(success);
- return success;
- }
-
- return false;
-}
-
-
-bool TkGroupImpl::setProcessing(bool value)
-{
- bool expected = !value;
- return m_isProcessing.compare_exchange_strong(expected, value);
-}
-
-
-void TkGroupImpl::enqueue(TkActorImpl* tkActor)
-{
- NVBLAST_ASSERT(tkActor->getGroupImpl() != nullptr);
- NVBLAST_ASSERT(tkActor->getGroupImpl() == this);
- NVBLAST_ASSERT(isInvalidIndex(tkActor->m_groupJobIndex));
- NVBLAST_ASSERT(isProcessing() == false);
-#if NV_DEBUG
- for (TkWorkerJob& j : m_jobs)
- {
- NVBLAST_ASSERT(j.m_tkActor != tkActor);
- }
-#endif
-
- tkActor->m_groupJobIndex = m_jobs.size();
- TkWorkerJob& j = m_jobs.insert();
- j.m_tkActor = tkActor;
-}
-
-
-TkGroupWorker* TkGroupImpl::acquireWorker()
-{
- BLAST_PROFILE_SCOPE_L("TkGroupImpl::acquireWorker");
- std::unique_lock<std::mutex> lk(m_workerMtx);
- for (auto& worker:m_workers)
- {
- if (!worker.m_isBusy)
- {
- worker.m_isBusy = true;
- return &worker;
- }
- }
- return nullptr;
-}
-
-
-void TkGroupImpl::returnWorker(TkGroupWorker* worker)
-{
- BLAST_PROFILE_SCOPE_L("TkGroupImpl::returnWorker");
- std::unique_lock<std::mutex> lk(m_workerMtx);
- auto w = static_cast<TkWorker*>(worker);
- NVBLAST_CHECK_WARNING(w->m_group == this, "TkGroup::returnWorker worker does not belong to this group.", return);
- w->m_isBusy = false;
-}
-
-
-} // namespace Blast
-} // namespace Nv
+// 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) 2016-2018 NVIDIA Corporation. All rights reserved.
+
+
+#include "NvPreprocessor.h"
+
+#include "NvBlastAssert.h"
+#include "NvBlast.h"
+
+#include "NvBlastTkFrameworkImpl.h"
+#include "NvBlastTkGroupImpl.h"
+#include "NvBlastTkActorImpl.h"
+#include "NvBlastTkFamilyImpl.h"
+#include "NvBlastTkAssetImpl.h"
+#include "NvBlastTkTaskImpl.h"
+
+#undef max
+#undef min
+#include <algorithm>
+
+using namespace physx;
+
+
+namespace Nv
+{
+namespace Blast
+{
+
+//////// Static data ////////
+
+NVBLASTTK_DEFINE_TYPE_IDENTIFIABLE(Group);
+
+
+//////// Member functions ////////
+
+TkGroupImpl::TkGroupImpl() : m_actorCount(0), m_isProcessing(false)
+{
+#if NV_PROFILE
+ memset(&m_stats, 0, sizeof(TkGroupStats));
+#endif
+}
+
+
+TkGroupImpl::~TkGroupImpl()
+{
+ NVBLAST_ASSERT(getActorCount() == 0);
+ NVBLAST_ASSERT(m_sharedMemory.size() == 0);
+}
+
+
+void TkGroupImpl::release()
+{
+ if (isProcessing())
+ {
+ // abort all processing?
+ NVBLAST_LOG_ERROR("TkGroup::release: cannot release Group while processing.");
+ NVBLAST_ALWAYS_ASSERT_MESSAGE("TkGroup::release: cannot release Group while processing.");
+ return;
+ }
+
+ for (auto it = m_sharedMemory.getIterator(); !it.done(); ++it)
+ {
+ TkFamilyImpl* family = it->first;
+ for (TkActorImpl& actor : family->getActorsInternal())
+ {
+ if (actor.m_group == this)
+ {
+ removeActorInternal(actor);
+ }
+ }
+ SharedMemory* mem = it->second;
+ mem->release();
+ NVBLAST_DELETE(mem, SharedMemory);
+ }
+ m_sharedMemory.clear();
+
+ m_bondTempDataBlock.release();
+ m_chunkTempDataBlock.release();
+ m_bondEventDataBlock.release();
+ m_chunkEventDataBlock.release();
+ m_splitScratchBlock.release();
+
+ NVBLAST_DELETE(this, TkGroupImpl);
+}
+
+
+void TkGroupImpl::addActorsInternal(TkActorImpl** actors, uint32_t numActors)
+{
+ for (uint32_t i = 0; i < numActors; i++)
+ {
+ addActorInternal(*actors[i]);
+ }
+}
+
+
+void TkGroupImpl::addActorInternal(TkActorImpl& tkActor)
+{
+ NVBLAST_ASSERT(tkActor.getGroup() == nullptr);
+ tkActor.m_group = this;
+ m_actorCount++;
+}
+
+
+bool TkGroupImpl::addActor(TkActor& actor)
+{
+ TkActorImpl& tkActor = static_cast<TkActorImpl&>(actor);
+ if (tkActor.getGroup() != nullptr)
+ {
+ NVBLAST_LOG_ERROR("TkGroup::addActor: actor already belongs to a Group. Remove from current group first.");
+ return false;
+ }
+
+ if (isProcessing())
+ {
+ NVBLAST_LOG_ERROR("TkGroup::addActor: cannot alter Group while processing.");
+ return false;
+ }
+
+ // mark the actor that it now belongs to this group
+ addActorInternal(tkActor);
+
+ // actors that were fractured already or have damage requested
+ // must be enqueued to be processed
+ if (tkActor.isPending())
+ {
+ enqueue(&tkActor);
+ }
+
+ TkFamilyImpl& family = tkActor.getFamilyImpl();
+ SharedMemory* mem = m_sharedMemory[&family];
+ if (mem == nullptr)
+ {
+ // the actor belongs to a family not involved in this group yet
+ // shared memory must be allocated and temporary buffers adjusted accordingly
+
+ BLAST_PROFILE_ZONE_BEGIN("family memory");
+ mem = NVBLAST_NEW(SharedMemory);
+ mem->allocate(family);
+ m_sharedMemory[&family] = mem;
+ BLAST_PROFILE_ZONE_END("family memory");
+
+ BLAST_PROFILE_ZONE_BEGIN("group memory");
+
+ const uint32_t workerCount = m_workers.size();
+
+ NvBlastLog theLog = logLL;
+
+ // this group's tasks will use one temporary buffer each, which is of max size of, for all families involved
+ const size_t requiredScratch = NvBlastActorGetRequiredScratchForSplit(tkActor.getActorLL(), theLog);
+ if (static_cast<size_t>(m_splitScratchBlock.numElementsPerBlock()) < requiredScratch)
+ {
+ m_splitScratchBlock.release();
+ m_splitScratchBlock.allocate(static_cast<uint32_t>(requiredScratch), workerCount);
+ }
+
+ // generate and apply fracture may create an entry for each bond
+ const uint32_t bondCount = NvBlastAssetGetBondCount(tkActor.getAsset()->getAssetLL(), theLog);
+ if (m_bondTempDataBlock.numElementsPerBlock() < bondCount)
+ {
+ m_bondTempDataBlock.release();
+ m_bondTempDataBlock.allocate(bondCount, workerCount);
+ m_bondEventDataBlock.release();
+ m_bondEventDataBlock.allocate(bondCount, workerCount);
+ }
+
+ // apply fracture may create an entry for each lower-support chunk
+ const uint32_t graphNodeCount = NvBlastAssetGetSupportGraph(tkActor.getAsset()->getAssetLL(), theLog).nodeCount;
+ const uint32_t subsupportChunkCount
+ = NvBlastAssetGetChunkCount(tkActor.getAsset()->getAssetLL(), theLog)
+ - NvBlastAssetGetFirstSubsupportChunkIndex(tkActor.getAsset()->getAssetLL(), theLog);
+ const uint32_t chunkCount = graphNodeCount + subsupportChunkCount;
+ if (m_chunkTempDataBlock.numElementsPerBlock() < chunkCount)
+ {
+ m_chunkTempDataBlock.release();
+ m_chunkTempDataBlock.allocate(chunkCount, workerCount);
+ m_chunkEventDataBlock.release();
+ m_chunkEventDataBlock.allocate(chunkCount, workerCount);
+ }
+ BLAST_PROFILE_ZONE_END("group memory");
+ }
+ mem->addReference();
+
+ return true;
+}
+
+
+uint32_t TkGroupImpl::getActors(TkActor** buffer, uint32_t bufferSize, uint32_t indexStart /* = 0 */) const
+{
+ BLAST_PROFILE_SCOPE_L("TkGroup::getActors");
+
+ uint32_t actorCount = m_actorCount;
+ if (actorCount <= indexStart)
+ {
+ NVBLAST_LOG_WARNING("TkGroup::getActors: indexStart beyond end of actor list.");
+ return 0;
+ }
+
+ actorCount -= indexStart;
+ if (actorCount > bufferSize)
+ {
+ actorCount = bufferSize;
+ }
+
+ uint32_t index = 0;
+ bool done = false;
+ for (auto it = const_cast<TkGroupImpl*>(this)->m_sharedMemory.getIterator(); !it.done();++it)
+ {
+ TkFamilyImpl* fam = it->first;
+ for (TkActorImpl& actor : fam->getActorsInternal())
+ {
+ if (actor.m_group == this)
+ {
+ NVBLAST_ASSERT(actor.isActive());
+
+ if (index >= indexStart)
+ {
+ *buffer++ = &actor;
+ }
+
+ index++;
+ done = (index - indexStart) >= actorCount;
+ }
+ if (done) break;
+ }
+ if (done) break;
+ }
+
+ return actorCount;
+}
+
+
+void TkGroupImpl::removeActorInternal(TkActorImpl& tkActor)
+{
+ NVBLAST_ASSERT(tkActor.m_group == this);
+ tkActor.m_group = nullptr;
+ m_actorCount--;
+}
+
+
+void TkGroupImpl::releaseSharedMemory(TkFamilyImpl* fam, SharedMemory* mem)
+{
+ NVBLAST_ASSERT(mem != nullptr && m_sharedMemory[fam] == mem);
+ mem->release();
+ m_sharedMemory.erase(fam);
+ NVBLAST_DELETE(mem, SharedMemory);
+}
+
+
+bool TkGroupImpl::removeActor(TkActor& actor)
+{
+ TkActorImpl& tkActor = static_cast<TkActorImpl&>(actor);
+
+ if (tkActor.getGroup() != this)
+ {
+ NVBLAST_LOG_ERROR("TkGroup::removeActor: actor does not belong to this Group.");
+ return false;
+ }
+
+ if (isProcessing())
+ {
+ NVBLAST_LOG_ERROR("TkGroup::removeActor: cannot alter Group while processing.");
+ return false;
+ }
+
+ removeActorInternal(tkActor);
+
+ // pending actors must be removed from the job queue as well
+ if(tkActor.isPending())
+ {
+ uint32_t index = tkActor.m_groupJobIndex;
+ tkActor.m_groupJobIndex = invalidIndex<uint32_t>();
+ m_jobs.replaceWithLast(index);
+ if (index < m_jobs.size())
+ {
+ NVBLAST_ASSERT(m_jobs[index].m_tkActor->m_groupJobIndex == m_jobs.size());
+ NVBLAST_ASSERT(m_jobs[index].m_tkActor->isPending());
+ m_jobs[index].m_tkActor->m_groupJobIndex = index;
+ }
+ }
+
+ // if the actor is the last of its family in this group
+ // the group-family memory can be released
+ TkFamilyImpl* family = &tkActor.getFamilyImpl();
+ SharedMemory* mem = getSharedMemory(family);
+ if (mem->removeReference())
+ {
+ releaseSharedMemory(family, mem);
+ }
+
+ return true;
+}
+
+
+TkGroupImpl* TkGroupImpl::create(const TkGroupDesc& desc)
+{
+ TkGroupImpl* group = NVBLAST_NEW(TkGroupImpl);
+
+ group->setWorkerCount(desc.workerCount);
+
+ return group;
+}
+
+
+void TkGroupImpl::setWorkerCount(uint32_t workerCount)
+{
+ if (isProcessing())
+ {
+ NVBLAST_LOG_WARNING("TkGroup::setWorkerCount: Group is still processing, call TkGroup::endProcess first.");
+ return;
+ }
+
+ if (workerCount == 0)
+ {
+ NVBLAST_LOG_WARNING("TkGroup: attempting to create a Group with 0 workers. Forced to 1.");
+ workerCount = 1;
+ }
+
+ if (workerCount != m_workers.size())
+ {
+ m_workers.resize(workerCount);
+
+ uint32_t workerId = 0;
+ for (auto& worker : m_workers)
+ {
+ worker.m_id = workerId++;
+ worker.m_group = this;
+ }
+
+ const uint32_t bondCount = m_bondTempDataBlock.numElementsPerBlock();
+ if (bondCount > 0)
+ {
+ m_bondTempDataBlock.release();
+ m_bondTempDataBlock.allocate(bondCount, workerCount);
+ m_bondEventDataBlock.release();
+ m_bondEventDataBlock.allocate(bondCount, workerCount);
+ }
+ const uint32_t chunkCount = m_chunkTempDataBlock.numElementsPerBlock();
+ if (chunkCount > 0)
+ {
+ m_chunkTempDataBlock.release();
+ m_chunkTempDataBlock.allocate(chunkCount, workerCount);
+ m_chunkEventDataBlock.release();
+ m_chunkEventDataBlock.allocate(chunkCount, workerCount);
+ }
+ const uint32_t scratchSize = m_splitScratchBlock.numElementsPerBlock();
+ if (scratchSize > 0)
+ {
+ m_splitScratchBlock.release();
+ m_splitScratchBlock.allocate(scratchSize, workerCount);
+ }
+ }
+}
+
+
+NV_INLINE uint32_t TkGroupImpl::getWorkerCount() const
+{
+ return m_workers.size();
+}
+
+
+uint32_t TkGroupImpl::startProcess()
+{
+ BLAST_PROFILE_SCOPE_L("TkGroup::startProcess");
+
+ if (!setProcessing(true))
+ {
+ NVBLAST_LOG_WARNING("TkGroup::process: Group is still processing, call TkGroup::endProcess first.");
+ return 0;
+ }
+
+ if (m_jobs.size() > 0)
+ {
+ BLAST_PROFILE_ZONE_BEGIN("task setup");
+
+ BLAST_PROFILE_ZONE_BEGIN("setup job queue");
+ for (const auto& job : m_jobs)
+ {
+ const TkActorImpl* a = job.m_tkActor;
+ SharedMemory* mem = getSharedMemory(&a->getFamilyImpl());
+
+ const uint32_t damageCount = a->m_damageBuffer.size();
+
+ // applyFracture'd actor do not necessarily have damage queued
+ NVBLAST_ASSERT(damageCount > 0 || a->m_flags.isSet(TkActorFlag::DAMAGED));
+
+ // no reason to be here without these
+ NVBLAST_ASSERT(a->m_flags.isSet(TkActorFlag::PENDING));
+ NVBLAST_ASSERT(a->m_group == this);
+
+ // collect the amount of event payload memory to preallocate for TkWorkers
+ mem->m_eventsMemory += damageCount * (sizeof(TkFractureCommands) + sizeof(TkFractureEvents)) + sizeof(TkSplitEvent);
+
+ // collect the amount of event entries to preallocate for TkWorkers
+ // (two TkFracture* events per damage plus one TkSplitEvent)
+ mem->m_eventsCount += 2 * damageCount + 1;
+ }
+ BLAST_PROFILE_ZONE_END("setup job queue");
+
+ BLAST_PROFILE_ZONE_BEGIN("memory protect");
+ for (auto it = m_sharedMemory.getIterator(); !it.done(); ++it)
+ {
+ // preallocate the event memory for TkWorkers
+ SharedMemory* mem = it->second;
+ mem->m_events.reserveData(mem->m_eventsMemory);
+ mem->m_events.reserveEvents(mem->m_eventsCount);
+
+ // these counters are not used anymore
+ // reset them immediately for next time
+ mem->m_eventsCount = 0;
+ mem->m_eventsMemory = 0;
+
+ // switch to parallel mode
+ mem->m_events.protect(true);
+ }
+ BLAST_PROFILE_ZONE_END("memory protect");
+
+ BLAST_PROFILE_ZONE_END("task setup");
+
+
+ for (auto&worker : m_workers)
+ {
+ worker.initialize();
+ }
+
+ return m_jobs.size();
+ }
+ else
+ {
+ bool success = setProcessing(false);
+ NVBLAST_ASSERT(success);
+ NV_UNUSED(success);
+ return 0;
+ }
+}
+
+
+bool TkGroupImpl::endProcess()
+{
+ if (isProcessing())
+ {
+ BLAST_PROFILE_SCOPE_L("TkGroupImpl::endProcess");
+
+ if (m_jobs.size() > 0)
+ {
+#if NV_PROFILE
+ BLAST_PROFILE_ZONE_BEGIN("accumulate timers");
+ NvBlastTimers accumulated;
+ NvBlastTimersReset(&accumulated);
+ uint32_t jobCount = 0;
+ int64_t workerTime = 0;
+ for (TkWorker& worker : m_workers)
+ {
+ accumulated += worker.m_stats.timers;
+ jobCount += worker.m_stats.processedActorsCount;
+ workerTime += worker.m_stats.workerTime;
+ }
+ m_stats.timers = accumulated;
+ m_stats.processedActorsCount = jobCount;
+ m_stats.workerTime = workerTime;
+ BLAST_PROFILE_ZONE_END("accumulate timers");
+#endif
+
+ BLAST_PROFILE_ZONE_BEGIN("job update");
+ for (auto& j : m_jobs)
+ {
+ if (j.m_newActorsCount)
+ {
+ TkFamilyImpl* fam = &j.m_tkActor->getFamilyImpl();
+ SharedMemory* mem = getSharedMemory(fam);
+
+ // as LL is implemented, where newActorsCount the parent is always deleted
+ removeActorInternal(*j.m_tkActor);
+ mem->removeReference();
+ addActorsInternal(j.m_newActors, j.m_newActorsCount);
+ mem->addReference(j.m_newActorsCount);
+
+ // Update joints
+ mem->m_events.protect(false); // allow allocations again
+ BLAST_PROFILE_ZONE_BEGIN("updateJoints");
+ fam->updateJoints(j.m_tkActor, &mem->m_events);
+ BLAST_PROFILE_ZONE_END("updateJoints");
+ }
+
+ // virtually dequeue the actor
+ // the queue itself is cleared right after this loop
+ j.m_tkActor->m_flags.clear(TkActorFlag::PENDING);
+ j.m_tkActor->m_groupJobIndex = invalidIndex<uint32_t>();
+ BLAST_PROFILE_ZONE_BEGIN("damageBuffer.clear");
+ j.m_tkActor->m_damageBuffer.clear();
+ BLAST_PROFILE_ZONE_END("damageBuffer.clear");
+ }
+ m_jobs.clear();
+ BLAST_PROFILE_ZONE_END("job update");
+
+ BLAST_PROFILE_ZONE_BEGIN("event dispatch");
+ for (auto it = m_sharedMemory.getIterator(); !it.done(); ++it)
+ {
+ BLAST_PROFILE_SCOPE_L("event dispatch");
+ TkFamilyImpl* family = it->first;
+ SharedMemory* mem = it->second;
+
+ NVBLAST_ASSERT(family != nullptr);
+ NVBLAST_ASSERT(mem != nullptr && mem->isUsed());
+
+ // where no actor of a family has split,
+ // its group/family event queue has not been
+ // unprotected in the jobs loop above
+ mem->m_events.protect(false);
+
+ family->getQueue().dispatch(mem->m_events);
+
+ mem->m_events.reset();
+ mem->reset();
+ }
+ BLAST_PROFILE_ZONE_END("event dispatch");
+
+ BLAST_PROFILE_ZONE_BEGIN("event memory release");
+ for (auto& worker : m_workers)
+ {
+ worker.m_bondBuffer.clear();
+ worker.m_chunkBuffer.clear();
+ }
+ BLAST_PROFILE_ZONE_END("event memory release");
+ }
+
+ bool success = setProcessing(false);
+ NVBLAST_ASSERT(success);
+ return success;
+ }
+
+ return false;
+}
+
+
+bool TkGroupImpl::setProcessing(bool value)
+{
+ bool expected = !value;
+ return m_isProcessing.compare_exchange_strong(expected, value);
+}
+
+
+void TkGroupImpl::enqueue(TkActorImpl* tkActor)
+{
+ NVBLAST_ASSERT(tkActor->getGroupImpl() != nullptr);
+ NVBLAST_ASSERT(tkActor->getGroupImpl() == this);
+ NVBLAST_ASSERT(isInvalidIndex(tkActor->m_groupJobIndex));
+ NVBLAST_ASSERT(isProcessing() == false);
+#if NV_DEBUG
+ for (TkWorkerJob& j : m_jobs)
+ {
+ NVBLAST_ASSERT(j.m_tkActor != tkActor);
+ }
+#endif
+
+ tkActor->m_groupJobIndex = m_jobs.size();
+ TkWorkerJob& j = m_jobs.insert();
+ j.m_tkActor = tkActor;
+}
+
+
+TkGroupWorker* TkGroupImpl::acquireWorker()
+{
+ BLAST_PROFILE_SCOPE_L("TkGroupImpl::acquireWorker");
+ std::unique_lock<std::mutex> lk(m_workerMtx);
+ for (auto& worker:m_workers)
+ {
+ if (!worker.m_isBusy)
+ {
+ worker.m_isBusy = true;
+ return &worker;
+ }
+ }
+ return nullptr;
+}
+
+
+void TkGroupImpl::returnWorker(TkGroupWorker* worker)
+{
+ BLAST_PROFILE_SCOPE_L("TkGroupImpl::returnWorker");
+ std::unique_lock<std::mutex> lk(m_workerMtx);
+ auto w = static_cast<TkWorker*>(worker);
+ NVBLAST_CHECK_WARNING(w->m_group == this, "TkGroup::returnWorker worker does not belong to this group.", return);
+ w->m_isBusy = false;
+}
+
+
+} // namespace Blast
+} // namespace Nv
diff --git a/sdk/toolkit/source/NvBlastTkGroupImpl.h b/sdk/toolkit/source/NvBlastTkGroupImpl.h
index be617c0..6807832 100644..100755
--- a/sdk/toolkit/source/NvBlastTkGroupImpl.h
+++ b/sdk/toolkit/source/NvBlastTkGroupImpl.h
@@ -1,194 +1,194 @@
-// 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) 2016-2018 NVIDIA Corporation. All rights reserved.
-
-
-#ifndef NVBLASTTKGROUPIMPL_H
-#define NVBLASTTKGROUPIMPL_H
-
-
-#include "NvBlastTkTaskImpl.h"
-#include "NvBlastTkGroup.h"
-#include "NvBlastTkTypeImpl.h"
-
-
-namespace Nv
-{
-namespace Blast
-{
-
-class TkActorImpl;
-class TkFamilyImpl;
-
-NVBLASTTK_IMPL_DECLARE(Group)
-{
- ~TkGroupImpl();
-
-public:
- TkGroupImpl();
-
- NVBLASTTK_IMPL_DEFINE_IDENTIFIABLE('G', 'R', 'P', '\0');
-
- static TkGroupImpl* create(const TkGroupDesc& desc);
-
- // Begin TkGroup
- virtual bool addActor(TkActor& actor) override;
-
- virtual uint32_t getActorCount() const override;
-
- virtual uint32_t getActors(TkActor** buffer, uint32_t bufferSize, uint32_t indexStart = 0) const override;
-
- virtual uint32_t startProcess() override;
- virtual bool endProcess() override;
-
- virtual void getStats(TkGroupStats& stats) const override;
-
- virtual void setWorkerCount(uint32_t workerCount) override;
- virtual uint32_t getWorkerCount() const override;
-
- virtual TkGroupWorker* acquireWorker() override;
- virtual void returnWorker(TkGroupWorker*) override;
- // End TkGroup
-
- // TkGroupImpl API
-
- /**
- Remove the actor from this group if the actor actually belongs to it and the group is not processing.
-
- \param[in] actor The TkActor to remove.
-
- \return true if removing succeeded, false otherwise
- */
- bool removeActor(TkActor& actor);
-
- /**
- Add the actor to this group's job queue.
- It is the caller's responsibility to add an actor only once. This condition is checked in debug builds.
- */
- void enqueue(TkActorImpl* tkActor);
-
- /**
- Atomically check if this group is processing actors. @see setProcessing()
-
- \return true between startProcess() and endProcess() calls, false otherwise
- */
- bool isProcessing() const;
-
-private:
- /**
- Atomically set the processing state. This function checks for the current state
- before changing it. @see isProcessing()
-
- \param[in] value the value of the new state
-
- \return true if the new state could be set, false otherwise
- */
- bool setProcessing(bool value);
-
- /**
- Get the group-family shared memory for the specified family. To be used when the memory is expected to already exist.
- */
- SharedMemory* getSharedMemory(TkFamilyImpl* family);
- void releaseSharedMemory(TkFamilyImpl* fam, SharedMemory* mem);
-
- // functions to add/remove actors _without_ group-family memory management
- void addActorInternal(TkActorImpl& tkActor);
- void addActorsInternal(TkActorImpl** actors, uint32_t numActors);
- void removeActorInternal(TkActorImpl& tkActor);
-
-
- uint32_t m_actorCount; //!< number of actors in this group
-
- HashMap<TkFamilyImpl*, SharedMemory*>::type m_sharedMemory; //!< memory sharable by actors in the same family in this group
-
- // it is assumed no more than the asset's number of bond and chunks fracture commands are produced
- SharedBlock<NvBlastChunkFractureData> m_chunkTempDataBlock; //!< chunk data for damage/fracture
- SharedBlock<NvBlastBondFractureData> m_bondTempDataBlock; //!< bond data for damage/fracture
- SharedBlock<NvBlastChunkFractureData> m_chunkEventDataBlock; //!< initial memory block for event data
- SharedBlock<NvBlastBondFractureData> m_bondEventDataBlock; //!< initial memory block for event data
- SharedBlock<char> m_splitScratchBlock; //!< split scratch memory
-
- std::atomic<bool> m_isProcessing; //!< true while workers are processing
-
- Array<TkWorker>::type m_workers; //!< this group's workers
-
- Array<TkWorkerJob>::type m_jobs; //!< this group's process jobs
-
-//#if NV_PROFILE
- TkGroupStats m_stats; //!< accumulated group's worker stats
-//#endif
-
- std::mutex m_workerMtx;
-
- friend class TkWorker;
-};
-
-
-NV_INLINE bool TkGroupImpl::isProcessing() const
-{
- return m_isProcessing.load();
-}
-
-
-NV_INLINE void TkGroupImpl::getStats(TkGroupStats& stats) const
-{
-#if NV_PROFILE
- memcpy(&stats, &m_stats, sizeof(TkGroupStats));
-#else
- NV_UNUSED(stats);
-#endif
-}
-
-
-NV_INLINE uint32_t TkGroupImpl::getActorCount() const
-{
- return m_actorCount;
-}
-
-
-NV_INLINE SharedMemory* TkGroupImpl::getSharedMemory(TkFamilyImpl* family)
-{
- SharedMemory* mem = m_sharedMemory[family];
- NVBLAST_ASSERT(mem != nullptr);
- return mem;
-}
-
-
-NV_FORCE_INLINE void operator +=(NvBlastTimers& lhs, const NvBlastTimers& rhs)
-{
- lhs.material += rhs.material;
- lhs.fracture += rhs.fracture;
- lhs.island += rhs.fracture;
- lhs.partition += rhs.partition;
- lhs.visibility += rhs.visibility;
-}
-
-
-} // namespace Blast
-} // namespace Nv
-
-
-#endif // ifndef NVBLASTTKGROUPIMPL_H
+// 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) 2016-2018 NVIDIA Corporation. All rights reserved.
+
+
+#ifndef NVBLASTTKGROUPIMPL_H
+#define NVBLASTTKGROUPIMPL_H
+
+
+#include "NvBlastTkTaskImpl.h"
+#include "NvBlastTkGroup.h"
+#include "NvBlastTkTypeImpl.h"
+
+
+namespace Nv
+{
+namespace Blast
+{
+
+class TkActorImpl;
+class TkFamilyImpl;
+
+NVBLASTTK_IMPL_DECLARE(Group)
+{
+ ~TkGroupImpl();
+
+public:
+ TkGroupImpl();
+
+ NVBLASTTK_IMPL_DEFINE_IDENTIFIABLE('G', 'R', 'P', '\0');
+
+ static TkGroupImpl* create(const TkGroupDesc& desc);
+
+ // Begin TkGroup
+ virtual bool addActor(TkActor& actor) override;
+
+ virtual uint32_t getActorCount() const override;
+
+ virtual uint32_t getActors(TkActor** buffer, uint32_t bufferSize, uint32_t indexStart = 0) const override;
+
+ virtual uint32_t startProcess() override;
+ virtual bool endProcess() override;
+
+ virtual void getStats(TkGroupStats& stats) const override;
+
+ virtual void setWorkerCount(uint32_t workerCount) override;
+ virtual uint32_t getWorkerCount() const override;
+
+ virtual TkGroupWorker* acquireWorker() override;
+ virtual void returnWorker(TkGroupWorker*) override;
+ // End TkGroup
+
+ // TkGroupImpl API
+
+ /**
+ Remove the actor from this group if the actor actually belongs to it and the group is not processing.
+
+ \param[in] actor The TkActor to remove.
+
+ \return true if removing succeeded, false otherwise
+ */
+ bool removeActor(TkActor& actor);
+
+ /**
+ Add the actor to this group's job queue.
+ It is the caller's responsibility to add an actor only once. This condition is checked in debug builds.
+ */
+ void enqueue(TkActorImpl* tkActor);
+
+ /**
+ Atomically check if this group is processing actors. @see setProcessing()
+
+ \return true between startProcess() and endProcess() calls, false otherwise
+ */
+ bool isProcessing() const;
+
+private:
+ /**
+ Atomically set the processing state. This function checks for the current state
+ before changing it. @see isProcessing()
+
+ \param[in] value the value of the new state
+
+ \return true if the new state could be set, false otherwise
+ */
+ bool setProcessing(bool value);
+
+ /**
+ Get the group-family shared memory for the specified family. To be used when the memory is expected to already exist.
+ */
+ SharedMemory* getSharedMemory(TkFamilyImpl* family);
+ void releaseSharedMemory(TkFamilyImpl* fam, SharedMemory* mem);
+
+ // functions to add/remove actors _without_ group-family memory management
+ void addActorInternal(TkActorImpl& tkActor);
+ void addActorsInternal(TkActorImpl** actors, uint32_t numActors);
+ void removeActorInternal(TkActorImpl& tkActor);
+
+
+ uint32_t m_actorCount; //!< number of actors in this group
+
+ HashMap<TkFamilyImpl*, SharedMemory*>::type m_sharedMemory; //!< memory sharable by actors in the same family in this group
+
+ // it is assumed no more than the asset's number of bond and chunks fracture commands are produced
+ SharedBlock<NvBlastChunkFractureData> m_chunkTempDataBlock; //!< chunk data for damage/fracture
+ SharedBlock<NvBlastBondFractureData> m_bondTempDataBlock; //!< bond data for damage/fracture
+ SharedBlock<NvBlastChunkFractureData> m_chunkEventDataBlock; //!< initial memory block for event data
+ SharedBlock<NvBlastBondFractureData> m_bondEventDataBlock; //!< initial memory block for event data
+ SharedBlock<char> m_splitScratchBlock; //!< split scratch memory
+
+ std::atomic<bool> m_isProcessing; //!< true while workers are processing
+
+ Array<TkWorker>::type m_workers; //!< this group's workers
+
+ Array<TkWorkerJob>::type m_jobs; //!< this group's process jobs
+
+//#if NV_PROFILE
+ TkGroupStats m_stats; //!< accumulated group's worker stats
+//#endif
+
+ std::mutex m_workerMtx;
+
+ friend class TkWorker;
+};
+
+
+NV_INLINE bool TkGroupImpl::isProcessing() const
+{
+ return m_isProcessing.load();
+}
+
+
+NV_INLINE void TkGroupImpl::getStats(TkGroupStats& stats) const
+{
+#if NV_PROFILE
+ memcpy(&stats, &m_stats, sizeof(TkGroupStats));
+#else
+ NV_UNUSED(stats);
+#endif
+}
+
+
+NV_INLINE uint32_t TkGroupImpl::getActorCount() const
+{
+ return m_actorCount;
+}
+
+
+NV_INLINE SharedMemory* TkGroupImpl::getSharedMemory(TkFamilyImpl* family)
+{
+ SharedMemory* mem = m_sharedMemory[family];
+ NVBLAST_ASSERT(mem != nullptr);
+ return mem;
+}
+
+
+NV_FORCE_INLINE void operator +=(NvBlastTimers& lhs, const NvBlastTimers& rhs)
+{
+ lhs.material += rhs.material;
+ lhs.fracture += rhs.fracture;
+ lhs.island += rhs.fracture;
+ lhs.partition += rhs.partition;
+ lhs.visibility += rhs.visibility;
+}
+
+
+} // namespace Blast
+} // namespace Nv
+
+
+#endif // ifndef NVBLASTTKGROUPIMPL_H
diff --git a/sdk/toolkit/source/NvBlastTkJointImpl.cpp b/sdk/toolkit/source/NvBlastTkJointImpl.cpp
index 18ee8d0..48c8370 100644..100755
--- a/sdk/toolkit/source/NvBlastTkJointImpl.cpp
+++ b/sdk/toolkit/source/NvBlastTkJointImpl.cpp
@@ -1,195 +1,195 @@
-// 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) 2016-2018 NVIDIA Corporation. All rights reserved.
-
-
-#include "NvBlastTkFrameworkImpl.h"
-#include "NvBlastTkJointImpl.h"
-#include "NvBlastTkActorImpl.h"
-#include "NvBlastTkAssetImpl.h"
-#include "NvBlastTkFamilyImpl.h"
-
-
-namespace Nv
-{
-namespace Blast
-{
-
-//////// Member functions ////////
-
-TkJointImpl::TkJointImpl(const TkJointDesc& desc, TkFamilyImpl* owner) : m_owner(owner)
-{
- userData = nullptr;
-
- // Do not fire off a creation event. Creation events will only be fired when a family-internal joint is created.
- NVBLAST_ASSERT(desc.families[0] != nullptr || desc.families[1] != nullptr);
- NVBLAST_ASSERT(desc.families[0] == nullptr || desc.chunkIndices[0] < static_cast<TkFamilyImpl*>(desc.families[0])->getAssetImpl()->getChunkCount());
- NVBLAST_ASSERT(desc.attachPositions[0].isFinite());
- NVBLAST_ASSERT(desc.families[1] == nullptr || desc.chunkIndices[1] < static_cast<TkFamilyImpl*>(desc.families[1])->getAssetImpl()->getChunkCount());
- NVBLAST_ASSERT(desc.attachPositions[1].isFinite());
-
- for (int i = 0; i < 2; ++i)
- {
- m_data.actors[i] = desc.families[i] != nullptr ? static_cast<TkFamilyImpl*>(desc.families[i])->getActorByChunk(desc.chunkIndices[i]) : nullptr;
- m_data.chunkIndices[i] = desc.chunkIndices[i];
- m_data.attachPositions[i] = desc.attachPositions[i];
- m_links[i].m_joint = this;
- }
-
- if (owner == nullptr)
- {
- TkFrameworkImpl::get()->onCreate(*this);
- }
-}
-
-
-void TkJointImpl::release()
-{
- removeReferencesInActors();
-
- if (m_owner != nullptr)
- {
- // Internal joint
- m_owner->releaseJoint(*this);
- }
- else
- {
- // External joint
- removeReferencesInFamilies();
- TkFrameworkImpl::get()->onDestroy(*this);
- NVBLAST_DELETE(this, TkJointImpl);
- }
-}
-
-
-void TkJointImpl::setActors(TkActorImpl* actor0, TkActorImpl* actor1, TkEventQueue* alternateQueue)
-{
- NVBLAST_ASSERT(m_data.actors[0] != nullptr || m_data.actors[1] != nullptr);
-
- const bool unreferenced = (actor0 == nullptr && m_data.actors[0] != nullptr) || (actor1 == nullptr && m_data.actors[1] != nullptr);
-
- removeReferencesInActors();
-
- if (!unreferenced)
- {
- if (actor0 != nullptr)
- {
- actor0->addJoint(m_links[0]);
- }
-
- if (actor1 != nullptr && actor1 != actor0) // If the actors are the same, we only need one joint reference
- {
- actor1->addJoint(m_links[1]);
- }
- }
-
- // We do _not_ return if m_data.m_actors[0] == actor0 && m_data.m_actors[1] == actor1 since
- // this leads to a bug. This function will only be called when an actor is split. It is
- // possible that the two TkActors in a joint are the same as before, but in this case one
- // of the actors will be the split actor. Since will be represented by a different
- // physical actor, this case still needs to be reported in an event. Returning when neither
- // TkActor has changed will prevent that, and lead to unwanted joint disconnection.
-
- const uint32_t familyToUse = m_data.actors[0] != actor0 ? 0 : 1;
-
- TkEventQueue* q = alternateQueue == nullptr ?
- &static_cast<TkActorImpl*>(m_data.actors[familyToUse])->getFamilyImpl().getQueue()
- : alternateQueue;
-
- const bool jointWasInternal = m_data.actors[0] == m_data.actors[1];
-
- if (unreferenced)
- {
- removeReferencesInFamilies();
- actor0 = actor1 = nullptr; // Make both new actors NULL
- }
-
- if (!jointWasInternal || actor0 != actor1)
- {
- // The original actors were different, or they are now, signal a joint update
- TkJointUpdateEvent* e = q->allocData<TkJointUpdateEvent>();
- e->joint = this;
- e->subtype = unreferenced ? TkJointUpdateEvent::Unreferenced : (jointWasInternal ? TkJointUpdateEvent::External : TkJointUpdateEvent::Changed);
- m_data.actors[0] = actor0;
- m_data.actors[1] = actor1;
- q->addEvent(e);
- }
- else
- if (jointWasInternal)
- {
- // The joint was originally created within the same actor and now it remains within the same actor.
- m_data.actors[0] = m_data.actors[1] = actor0;
- }
-}
-
-
-const TkJointData TkJointImpl::getData() const
-{
- return getDataInternal();
-}
-
-
-void TkJointImpl::removeReferencesInActors()
-{
- TkActorImpl* actor0 = static_cast<TkActorImpl*>(m_data.actors[0]);
- TkActorImpl* actor1 = static_cast<TkActorImpl*>(m_data.actors[1]);
-
- if (actor0 != nullptr)
- {
- actor0->removeJoint(m_links[0]);
- }
-
- if (actor1 != nullptr && actor1 != actor0) // If the actors are the same, we only had one joint reference
- {
- actor1->removeJoint(m_links[1]);
- }
-}
-
-
-void TkJointImpl::removeReferencesInFamilies()
-{
- if (m_owner != nullptr)
- {
- return; // Only concerned with external joints
- }
-
- NVBLAST_ASSERT(m_data.actors[0] != m_data.actors[1] || m_data.actors[0] == nullptr); // This is enforced by the initial assumption in TkFrameworkImpl::createJoint.
-
- for (int i = 0; i < 2; ++i)
- {
- if (m_data.actors[i] != nullptr)
- {
- TkFamilyImpl& family = static_cast<TkActorImpl*>(m_data.actors[i])->getFamilyImpl();
- TkJointImpl* joint = nullptr;
- const bool found = family.deleteExternalJointHandle(joint, getFamilyID(m_data.actors[i ^ 1]), m_data.chunkIndices[i], m_data.chunkIndices[i ^ 1]);
- NVBLAST_ASSERT((!found && m_data.actors[i ^ 1] == nullptr) || joint == this); // Might not be found if the actors in a family are in the process of being deleted
- NV_UNUSED(found);
- }
- }
-}
-
-} // namespace Blast
-} // namespace Nv
+// 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) 2016-2018 NVIDIA Corporation. All rights reserved.
+
+
+#include "NvBlastTkFrameworkImpl.h"
+#include "NvBlastTkJointImpl.h"
+#include "NvBlastTkActorImpl.h"
+#include "NvBlastTkAssetImpl.h"
+#include "NvBlastTkFamilyImpl.h"
+
+
+namespace Nv
+{
+namespace Blast
+{
+
+//////// Member functions ////////
+
+TkJointImpl::TkJointImpl(const TkJointDesc& desc, TkFamilyImpl* owner) : m_owner(owner)
+{
+ userData = nullptr;
+
+ // Do not fire off a creation event. Creation events will only be fired when a family-internal joint is created.
+ NVBLAST_ASSERT(desc.families[0] != nullptr || desc.families[1] != nullptr);
+ NVBLAST_ASSERT(desc.families[0] == nullptr || desc.chunkIndices[0] < static_cast<TkFamilyImpl*>(desc.families[0])->getAssetImpl()->getChunkCount());
+ NVBLAST_ASSERT(desc.attachPositions[0].isFinite());
+ NVBLAST_ASSERT(desc.families[1] == nullptr || desc.chunkIndices[1] < static_cast<TkFamilyImpl*>(desc.families[1])->getAssetImpl()->getChunkCount());
+ NVBLAST_ASSERT(desc.attachPositions[1].isFinite());
+
+ for (int i = 0; i < 2; ++i)
+ {
+ m_data.actors[i] = desc.families[i] != nullptr ? static_cast<TkFamilyImpl*>(desc.families[i])->getActorByChunk(desc.chunkIndices[i]) : nullptr;
+ m_data.chunkIndices[i] = desc.chunkIndices[i];
+ m_data.attachPositions[i] = desc.attachPositions[i];
+ m_links[i].m_joint = this;
+ }
+
+ if (owner == nullptr)
+ {
+ TkFrameworkImpl::get()->onCreate(*this);
+ }
+}
+
+
+void TkJointImpl::release()
+{
+ removeReferencesInActors();
+
+ if (m_owner != nullptr)
+ {
+ // Internal joint
+ m_owner->releaseJoint(*this);
+ }
+ else
+ {
+ // External joint
+ removeReferencesInFamilies();
+ TkFrameworkImpl::get()->onDestroy(*this);
+ NVBLAST_DELETE(this, TkJointImpl);
+ }
+}
+
+
+void TkJointImpl::setActors(TkActorImpl* actor0, TkActorImpl* actor1, TkEventQueue* alternateQueue)
+{
+ NVBLAST_ASSERT(m_data.actors[0] != nullptr || m_data.actors[1] != nullptr);
+
+ const bool unreferenced = (actor0 == nullptr && m_data.actors[0] != nullptr) || (actor1 == nullptr && m_data.actors[1] != nullptr);
+
+ removeReferencesInActors();
+
+ if (!unreferenced)
+ {
+ if (actor0 != nullptr)
+ {
+ actor0->addJoint(m_links[0]);
+ }
+
+ if (actor1 != nullptr && actor1 != actor0) // If the actors are the same, we only need one joint reference
+ {
+ actor1->addJoint(m_links[1]);
+ }
+ }
+
+ // We do _not_ return if m_data.m_actors[0] == actor0 && m_data.m_actors[1] == actor1 since
+ // this leads to a bug. This function will only be called when an actor is split. It is
+ // possible that the two TkActors in a joint are the same as before, but in this case one
+ // of the actors will be the split actor. Since will be represented by a different
+ // physical actor, this case still needs to be reported in an event. Returning when neither
+ // TkActor has changed will prevent that, and lead to unwanted joint disconnection.
+
+ const uint32_t familyToUse = m_data.actors[0] != actor0 ? 0 : 1;
+
+ TkEventQueue* q = alternateQueue == nullptr ?
+ &static_cast<TkActorImpl*>(m_data.actors[familyToUse])->getFamilyImpl().getQueue()
+ : alternateQueue;
+
+ const bool jointWasInternal = m_data.actors[0] == m_data.actors[1];
+
+ if (unreferenced)
+ {
+ removeReferencesInFamilies();
+ actor0 = actor1 = nullptr; // Make both new actors NULL
+ }
+
+ if (!jointWasInternal || actor0 != actor1)
+ {
+ // The original actors were different, or they are now, signal a joint update
+ TkJointUpdateEvent* e = q->allocData<TkJointUpdateEvent>();
+ e->joint = this;
+ e->subtype = unreferenced ? TkJointUpdateEvent::Unreferenced : (jointWasInternal ? TkJointUpdateEvent::External : TkJointUpdateEvent::Changed);
+ m_data.actors[0] = actor0;
+ m_data.actors[1] = actor1;
+ q->addEvent(e);
+ }
+ else
+ if (jointWasInternal)
+ {
+ // The joint was originally created within the same actor and now it remains within the same actor.
+ m_data.actors[0] = m_data.actors[1] = actor0;
+ }
+}
+
+
+const TkJointData TkJointImpl::getData() const
+{
+ return getDataInternal();
+}
+
+
+void TkJointImpl::removeReferencesInActors()
+{
+ TkActorImpl* actor0 = static_cast<TkActorImpl*>(m_data.actors[0]);
+ TkActorImpl* actor1 = static_cast<TkActorImpl*>(m_data.actors[1]);
+
+ if (actor0 != nullptr)
+ {
+ actor0->removeJoint(m_links[0]);
+ }
+
+ if (actor1 != nullptr && actor1 != actor0) // If the actors are the same, we only had one joint reference
+ {
+ actor1->removeJoint(m_links[1]);
+ }
+}
+
+
+void TkJointImpl::removeReferencesInFamilies()
+{
+ if (m_owner != nullptr)
+ {
+ return; // Only concerned with external joints
+ }
+
+ NVBLAST_ASSERT(m_data.actors[0] != m_data.actors[1] || m_data.actors[0] == nullptr); // This is enforced by the initial assumption in TkFrameworkImpl::createJoint.
+
+ for (int i = 0; i < 2; ++i)
+ {
+ if (m_data.actors[i] != nullptr)
+ {
+ TkFamilyImpl& family = static_cast<TkActorImpl*>(m_data.actors[i])->getFamilyImpl();
+ TkJointImpl* joint = nullptr;
+ const bool found = family.deleteExternalJointHandle(joint, getFamilyID(m_data.actors[i ^ 1]), m_data.chunkIndices[i], m_data.chunkIndices[i ^ 1]);
+ NVBLAST_ASSERT((!found && m_data.actors[i ^ 1] == nullptr) || joint == this); // Might not be found if the actors in a family are in the process of being deleted
+ NV_UNUSED(found);
+ }
+ }
+}
+
+} // namespace Blast
+} // namespace Nv
diff --git a/sdk/toolkit/source/NvBlastTkJointImpl.h b/sdk/toolkit/source/NvBlastTkJointImpl.h
index 773481b..8be96cd 100644..100755
--- a/sdk/toolkit/source/NvBlastTkJointImpl.h
+++ b/sdk/toolkit/source/NvBlastTkJointImpl.h
@@ -1,164 +1,164 @@
-// 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) 2016-2018 NVIDIA Corporation. All rights reserved.
-
-
-#ifndef NVBLASTTKJOINTIMPL_H
-#define NVBLASTTKJOINTIMPL_H
-
-
-#include "NvBlastTkJoint.h"
-#include "NvBlastTkCommon.h"
-#include "NvBlastIndexFns.h"
-
-#include "NvBlastAssert.h"
-#include "NvBlastDLink.h"
-
-#include <atomic>
-
-
-namespace Nv
-{
-namespace Blast
-{
-
-// Forward declarations
-class TkActorImpl;
-class TkJointImpl;
-class TkFamilyImpl;
-class TkEventQueue;
-
-
-/**
-Double-sided link (DLink) which holds a reference back to a joint which contains it.
-*/
-struct TkJointLink : public DLink
-{
- TkJointImpl* m_joint; //!< The joint containing this link.
-};
-
-
-/**
-Implementation of TkJoint.
-*/
-class TkJointImpl : public TkJoint
-{
-public:
- /** Blank constructor only creates valid TkJointLinks (point back to this object) */
- TkJointImpl();
-
- /**
- This constructor sets all internal data. If the joint is defined in an asset, the family
- instanced from that asset will own this joint, and the 'owner' parameter is that family.
- Otherwise, in the case where a joint is created from TkFramwork::createJoint, the joint
- is not owned by a family and 'owner' will be NULL.
- */
- TkJointImpl(const TkJointDesc& desc, TkFamilyImpl* owner);
-
- // Begin TkObject
- virtual void release() override;
- // End TkObject
-
- // Begin TkJoint
- virtual const TkJointData getData() const override;
- // End TkJoint
-
- // Public API
-
- /**
- Internal method to access a const reference to the joint data.
-
- \return a const reference to the joint data.
- */
- const TkJointData& getDataInternal() const;
-
- /**
- Internal method to access a non-const reference to the joint data.
-
- \return a non-const reference to the joint data.
- */
- TkJointData& getDataWritable();
-
- /**
- Set the actors that this joint attaches to. When the actors are different from the joint's current actors,
- an event will be generated on one of the actors' families event queues to signal the change. Alternatively,
- if alternateQueue is not NULL then it will be used to hold the event.
-
- If a non-NULL attached actor becomes NULL, then this joint will detach its references to both actors (if
- they exist) and send an event of subtype Unreferenced. This signals the user that the joint may be deleted.
-
- \param[in] actor0 The new TkActor to replace the first attached actor.
- \param[in] actor1 The new TkActor to replace the second attached actor.
- \param[in] alternateQueue If not NULL, this queue will be used to hold events generated by this function.
- */
- void setActors(TkActorImpl* actor0, TkActorImpl* actor1, TkEventQueue* alternateQueue = nullptr);
-
- /**
- Ensures that any attached actors no longer refer to this joint.
- */
- void removeReferencesInActors();
-
- /**
- Ensures that any attached actors' families no longer refer to this joint. External joints (created using
- TkFramework::createJoint) are referenced by the attached actors' families.
- */
- void removeReferencesInFamilies();
-
-private:
- TkJointData m_data; //!< The data given to the user: attached actors, chunk indices, and actor-local attachment positions.
- TkJointLink m_links[2]; //!< One link for each actor in m_data.m_actors. If m_data.m_actors[0] == m_data.m_actors[1], then only m_links[0] is used.
- TkFamilyImpl* m_owner; //!< The owning family if this is an internal joint created during TkFramework::createActor() from a TkAssetDesc with joint flags.
-
- friend class TkFrameworkImpl;
- friend class TkFamilyImpl;
- friend class TkActorImpl;
-};
-
-
-//////// TkJointImpl inline methods ////////
-
-NV_INLINE TkJointImpl::TkJointImpl()
-{
- m_links[0].m_joint = m_links[1].m_joint = this;
-}
-
-
-NV_INLINE const TkJointData& TkJointImpl::getDataInternal() const
-{
- return m_data;
-}
-
-
-NV_INLINE TkJointData& TkJointImpl::getDataWritable()
-{
- return m_data;
-}
-
-} // namespace Blast
-} // namespace Nv
-
-
-#endif // ifndef NVBLASTTKJOINTIMPL_H
+// 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) 2016-2018 NVIDIA Corporation. All rights reserved.
+
+
+#ifndef NVBLASTTKJOINTIMPL_H
+#define NVBLASTTKJOINTIMPL_H
+
+
+#include "NvBlastTkJoint.h"
+#include "NvBlastTkCommon.h"
+#include "NvBlastIndexFns.h"
+
+#include "NvBlastAssert.h"
+#include "NvBlastDLink.h"
+
+#include <atomic>
+
+
+namespace Nv
+{
+namespace Blast
+{
+
+// Forward declarations
+class TkActorImpl;
+class TkJointImpl;
+class TkFamilyImpl;
+class TkEventQueue;
+
+
+/**
+Double-sided link (DLink) which holds a reference back to a joint which contains it.
+*/
+struct TkJointLink : public DLink
+{
+ TkJointImpl* m_joint; //!< The joint containing this link.
+};
+
+
+/**
+Implementation of TkJoint.
+*/
+class TkJointImpl : public TkJoint
+{
+public:
+ /** Blank constructor only creates valid TkJointLinks (point back to this object) */
+ TkJointImpl();
+
+ /**
+ This constructor sets all internal data. If the joint is defined in an asset, the family
+ instanced from that asset will own this joint, and the 'owner' parameter is that family.
+ Otherwise, in the case where a joint is created from TkFramwork::createJoint, the joint
+ is not owned by a family and 'owner' will be NULL.
+ */
+ TkJointImpl(const TkJointDesc& desc, TkFamilyImpl* owner);
+
+ // Begin TkObject
+ virtual void release() override;
+ // End TkObject
+
+ // Begin TkJoint
+ virtual const TkJointData getData() const override;
+ // End TkJoint
+
+ // Public API
+
+ /**
+ Internal method to access a const reference to the joint data.
+
+ \return a const reference to the joint data.
+ */
+ const TkJointData& getDataInternal() const;
+
+ /**
+ Internal method to access a non-const reference to the joint data.
+
+ \return a non-const reference to the joint data.
+ */
+ TkJointData& getDataWritable();
+
+ /**
+ Set the actors that this joint attaches to. When the actors are different from the joint's current actors,
+ an event will be generated on one of the actors' families event queues to signal the change. Alternatively,
+ if alternateQueue is not NULL then it will be used to hold the event.
+
+ If a non-NULL attached actor becomes NULL, then this joint will detach its references to both actors (if
+ they exist) and send an event of subtype Unreferenced. This signals the user that the joint may be deleted.
+
+ \param[in] actor0 The new TkActor to replace the first attached actor.
+ \param[in] actor1 The new TkActor to replace the second attached actor.
+ \param[in] alternateQueue If not NULL, this queue will be used to hold events generated by this function.
+ */
+ void setActors(TkActorImpl* actor0, TkActorImpl* actor1, TkEventQueue* alternateQueue = nullptr);
+
+ /**
+ Ensures that any attached actors no longer refer to this joint.
+ */
+ void removeReferencesInActors();
+
+ /**
+ Ensures that any attached actors' families no longer refer to this joint. External joints (created using
+ TkFramework::createJoint) are referenced by the attached actors' families.
+ */
+ void removeReferencesInFamilies();
+
+private:
+ TkJointData m_data; //!< The data given to the user: attached actors, chunk indices, and actor-local attachment positions.
+ TkJointLink m_links[2]; //!< One link for each actor in m_data.m_actors. If m_data.m_actors[0] == m_data.m_actors[1], then only m_links[0] is used.
+ TkFamilyImpl* m_owner; //!< The owning family if this is an internal joint created during TkFramework::createActor() from a TkAssetDesc with joint flags.
+
+ friend class TkFrameworkImpl;
+ friend class TkFamilyImpl;
+ friend class TkActorImpl;
+};
+
+
+//////// TkJointImpl inline methods ////////
+
+NV_INLINE TkJointImpl::TkJointImpl()
+{
+ m_links[0].m_joint = m_links[1].m_joint = this;
+}
+
+
+NV_INLINE const TkJointData& TkJointImpl::getDataInternal() const
+{
+ return m_data;
+}
+
+
+NV_INLINE TkJointData& TkJointImpl::getDataWritable()
+{
+ return m_data;
+}
+
+} // namespace Blast
+} // namespace Nv
+
+
+#endif // ifndef NVBLASTTKJOINTIMPL_H
diff --git a/sdk/toolkit/source/NvBlastTkTaskImpl.cpp b/sdk/toolkit/source/NvBlastTkTaskImpl.cpp
index 07bde19..63e6c2a 100644..100755
--- a/sdk/toolkit/source/NvBlastTkTaskImpl.cpp
+++ b/sdk/toolkit/source/NvBlastTkTaskImpl.cpp
@@ -1,271 +1,271 @@
-// 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) 2016-2018 NVIDIA Corporation. All rights reserved.
-
-
-#include "NvBlastTime.h"
-
-#include "NvBlastTkTaskImpl.h"
-#include "NvBlastTkFamilyImpl.h"
-#include "NvBlastTkAssetImpl.h"
-#include "NvBlastTkGroupImpl.h"
-
-
-using namespace Nv::Blast;
-
-
-void SharedMemory::allocate(TkFamilyImpl& tkFamily)
-{
- NVBLAST_ASSERT(m_refCount == 0);
- const NvBlastAsset* assetLL = tkFamily.getAsset()->getAssetLL();
-
- // at most leafChunkCount actors can be created within a family
- // tasks will grab their portion out of these memory blocks
- uint32_t leafChunkCount = NvBlastAssetGetLeafChunkCount(assetLL, logLL);
- m_newActorBuffers.allocate(2 * leafChunkCount); // GWD-167 workaround (2*)
- m_newTkActorBuffers.allocate(leafChunkCount);
-}
-
-
-/**
-Creates a TkEvent::FractureCommand according to the input buffer for tkActor
-into events queue using the LocalBuffers to store the actual event data.
-*/
-NV_FORCE_INLINE void reportFractureCommands(
- const NvBlastFractureBuffers& buffer,
- LocalBuffer<NvBlastBondFractureData>& bondBuffer, LocalBuffer<NvBlastChunkFractureData>& chunkBuffer,
- TkEventQueue& events, const TkActorImpl* tkActor)
-{
-
- NvBlastBondFractureData* bdata = nullptr;
- if (buffer.bondFractureCount > 0)
- {
- bdata = bondBuffer.allocate(buffer.bondFractureCount);
- memcpy(bdata, buffer.bondFractures, sizeof(NvBlastBondFractureData)*buffer.bondFractureCount);
- }
-
- NvBlastChunkFractureData* cdata = nullptr;
- if (buffer.chunkFractureCount > 0)
- {
- cdata = chunkBuffer.allocate(buffer.chunkFractureCount);
- memcpy(cdata, buffer.chunkFractures, sizeof(NvBlastChunkFractureData)*buffer.chunkFractureCount);
- }
-
- TkFractureCommands* fevt = events.allocData<TkFractureCommands>();
- fevt->tkActorData = *tkActor;
- fevt->buffers = { buffer.bondFractureCount, buffer.chunkFractureCount, bdata, cdata };
- events.addEvent(fevt);
-}
-
-
-/**
-Creates a TkEvent::FractureEvent according to the input buffer for tkActor
-into events queue using the LocalBuffers to store the actual event data.
-*/
-NV_FORCE_INLINE void reportFractureEvents(
- const NvBlastFractureBuffers& buffer,
- LocalBuffer<NvBlastBondFractureData>& bondBuffer, LocalBuffer<NvBlastChunkFractureData>& chunkBuffer,
- TkEventQueue& events, const TkActorImpl* tkActor)
-{
- uint32_t result[4] = { 0,0,0,0 };
-
- NvBlastBondFractureData* bdata = nullptr;
- if (buffer.bondFractureCount > 0)
- {
- bdata = bondBuffer.allocate(buffer.bondFractureCount);
- for (uint32_t b = 0; b < buffer.bondFractureCount; ++b)
- {
- bdata[b] = buffer.bondFractures[b];
- result[buffer.bondFractures[b].health > 0 ? 0 : 1]++;
- }
- }
-
- NvBlastChunkFractureData* cdata = nullptr;
- if (buffer.chunkFractureCount > 0)
- {
- cdata = chunkBuffer.allocate(buffer.chunkFractureCount);
- for (uint32_t c = 0; c < buffer.chunkFractureCount; ++c)
- {
- cdata[c] = buffer.chunkFractures[c];
- result[buffer.chunkFractures[c].health > 0 ? 2 : 3]++;
- }
- }
-
- TkFractureEvents* fevt = events.allocData<TkFractureEvents>();
- fevt->tkActorData = *tkActor;
- fevt->buffers = { buffer.bondFractureCount, buffer.chunkFractureCount, bdata, cdata };
- fevt->bondsDamaged = result[0];
- fevt->bondsBroken = result[1];
- fevt->chunksDamaged = result[2];
- fevt->chunksBroken = result[3];
- events.addEvent(fevt);
-}
-
-
-void TkWorker::initialize()
-{
- // temporary memory used to generate and apply fractures
- // it must fit for the largest family involved in the group that owns this worker
- NvBlastBondFractureData* bondFractureData = m_group->m_bondTempDataBlock.getBlock(m_id);
- uint32_t bondFractureCount = m_group->m_bondTempDataBlock.numElementsPerBlock();
- NvBlastChunkFractureData* chunkFractureData = m_group->m_chunkTempDataBlock.getBlock(m_id);
- uint32_t chunkFractureCount = m_group->m_chunkTempDataBlock.numElementsPerBlock();
- m_tempBuffer = { bondFractureCount, chunkFractureCount, bondFractureData, chunkFractureData };
-
- // temporary memory used to split the actor
- // large enough for the largest family involved
- m_splitScratch = m_group->m_splitScratchBlock.getBlock(m_id);
-
- // to avoid unnecessary allocations, preallocated memory exists to fit all chunks and bonds taking damage once
- // where multiple damage occurs, more memory will be allocated on demand (this may thwart other threads doing the same)
- m_bondBuffer.initialize(m_group->m_bondEventDataBlock.getBlock(m_id), m_group->m_bondEventDataBlock.numElementsPerBlock());
- m_chunkBuffer.initialize(m_group->m_chunkEventDataBlock.getBlock(m_id), m_group->m_chunkEventDataBlock.numElementsPerBlock());
-
-#if NV_PROFILE
- NvBlastTimersReset(&m_stats.timers);
- m_stats.processedActorsCount = 0;
-#endif
-}
-
-void TkWorker::process(TkWorkerJob& j)
-{
- NvBlastTimers* timers = nullptr;
-
- BLAST_PROFILE_SCOPE_M("TkActor");
-
- TkActorImpl* tkActor = j.m_tkActor;
- const uint32_t tkActorIndex = tkActor->getIndex();
- NvBlastActor* actorLL = tkActor->getActorLLInternal();
- TkFamilyImpl& family = tkActor->getFamilyImpl();
- SharedMemory* mem = m_group->getSharedMemory(&family);
- TkEventQueue& events = mem->m_events;
-
- NVBLAST_ASSERT(tkActor->getGroupImpl() == m_group);
- NVBLAST_ASSERT(tkActor->m_flags.isSet(TkActorFlag::PENDING));
-
-#if NV_PROFILE
- timers = &m_stats.timers;
- *timers += tkActor->m_timers;
- NvBlastTimersReset(&tkActor->m_timers);
- m_stats.processedActorsCount++;
-#endif
-
- // generate and apply fracture for all damage requested on this actor
- // and queue events accordingly
- for (const auto& damage : tkActor->m_damageBuffer)
- {
- NvBlastFractureBuffers commandBuffer = m_tempBuffer;
-
- BLAST_PROFILE_ZONE_BEGIN("Material");
- NvBlastActorGenerateFracture(&commandBuffer, actorLL, damage.program, damage.programParams, logLL, timers);
- BLAST_PROFILE_ZONE_END("Material");
-
- if (commandBuffer.chunkFractureCount > 0 || commandBuffer.bondFractureCount > 0)
- {
- BLAST_PROFILE_SCOPE_M("Fill Command Events");
- reportFractureCommands(commandBuffer, m_bondBuffer, m_chunkBuffer, events, tkActor);
- }
-
- NvBlastFractureBuffers eventBuffer = m_tempBuffer;
-
- BLAST_PROFILE_ZONE_BEGIN("Fracture");
- NvBlastActorApplyFracture(&eventBuffer, actorLL, &commandBuffer, logLL, timers);
- BLAST_PROFILE_ZONE_END("Fracture");
-
- if (eventBuffer.chunkFractureCount > 0 || eventBuffer.bondFractureCount > 0)
- {
- BLAST_PROFILE_SCOPE_M("Fill Fracture Events");
- tkActor->m_flags |= (TkActorFlag::DAMAGED);
- reportFractureEvents(eventBuffer, m_bondBuffer, m_chunkBuffer, events, tkActor);
- }
- }
-
-
- // split the actor, which could have been damaged directly though the TkActor's fracture functions
- // i.e. it did not have damage queued for the above loop
-
- NvBlastActorSplitEvent splitEvent = { nullptr, nullptr };
- if (tkActor->isDamaged())
- {
- BLAST_PROFILE_ZONE_BEGIN("Split Memory");
- uint32_t maxActorCount = NvBlastActorGetMaxActorCountForSplit(actorLL, logLL);
- splitEvent.newActors = mem->reserveNewActors(maxActorCount);
- BLAST_PROFILE_ZONE_END("Split Memory");
- BLAST_PROFILE_ZONE_BEGIN("Split");
- j.m_newActorsCount = NvBlastActorSplit(&splitEvent, actorLL, maxActorCount, m_splitScratch, logLL, timers);
- BLAST_PROFILE_ZONE_END("Split");
-
- tkActor->m_flags.clear(TkActorFlag::DAMAGED);
- }
- else
- {
- j.m_newActorsCount = 0;
- }
-
-
- // update the TkActor according to the LL split results and queue events accordingly
- if (j.m_newActorsCount > 0)
- {
- NVBLAST_ASSERT(splitEvent.deletedActor == tkActor->getActorLL());
-
- BLAST_PROFILE_ZONE_BEGIN("memory new actors");
-
- auto tkSplitEvent = events.allocData<TkSplitEvent>();
-
- tkSplitEvent->children = mem->reserveNewTkActors(j.m_newActorsCount);
- tkSplitEvent->numChildren = j.m_newActorsCount;
-
- tkSplitEvent->parentData.family = &family;
- tkSplitEvent->parentData.userData = tkActor->userData;
- tkSplitEvent->parentData.index = tkActorIndex;
- family.removeActor(tkActor);
-
- BLAST_PROFILE_ZONE_END("memory new actors");
-
-
- BLAST_PROFILE_ZONE_BEGIN("create new actors");
- for (uint32_t i = 0; i < j.m_newActorsCount; ++i)
- {
- TkActorImpl* newActor = family.addActor(splitEvent.newActors[i]);
- tkSplitEvent->children[i] = newActor;
- }
- j.m_newActors = reinterpret_cast<TkActorImpl**>(tkSplitEvent->children);
- BLAST_PROFILE_ZONE_END("create new actors");
-
- BLAST_PROFILE_ZONE_BEGIN("split event");
- events.addEvent(tkSplitEvent);
- BLAST_PROFILE_ZONE_END("split event");
- }
-
- j.m_tkActor->m_flags.clear(TkActorFlag::PENDING);
-}
-
-
-void TkWorker::process(uint32_t jobID)
-{
- TkWorkerJob& j = m_group->m_jobs[jobID];
- process(j);
-}
+// 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) 2016-2018 NVIDIA Corporation. All rights reserved.
+
+
+#include "NvBlastTime.h"
+
+#include "NvBlastTkTaskImpl.h"
+#include "NvBlastTkFamilyImpl.h"
+#include "NvBlastTkAssetImpl.h"
+#include "NvBlastTkGroupImpl.h"
+
+
+using namespace Nv::Blast;
+
+
+void SharedMemory::allocate(TkFamilyImpl& tkFamily)
+{
+ NVBLAST_ASSERT(m_refCount == 0);
+ const NvBlastAsset* assetLL = tkFamily.getAsset()->getAssetLL();
+
+ // at most leafChunkCount actors can be created within a family
+ // tasks will grab their portion out of these memory blocks
+ uint32_t leafChunkCount = NvBlastAssetGetLeafChunkCount(assetLL, logLL);
+ m_newActorBuffers.allocate(2 * leafChunkCount); // GWD-167 workaround (2*)
+ m_newTkActorBuffers.allocate(leafChunkCount);
+}
+
+
+/**
+Creates a TkEvent::FractureCommand according to the input buffer for tkActor
+into events queue using the LocalBuffers to store the actual event data.
+*/
+NV_FORCE_INLINE void reportFractureCommands(
+ const NvBlastFractureBuffers& buffer,
+ LocalBuffer<NvBlastBondFractureData>& bondBuffer, LocalBuffer<NvBlastChunkFractureData>& chunkBuffer,
+ TkEventQueue& events, const TkActorImpl* tkActor)
+{
+
+ NvBlastBondFractureData* bdata = nullptr;
+ if (buffer.bondFractureCount > 0)
+ {
+ bdata = bondBuffer.allocate(buffer.bondFractureCount);
+ memcpy(bdata, buffer.bondFractures, sizeof(NvBlastBondFractureData)*buffer.bondFractureCount);
+ }
+
+ NvBlastChunkFractureData* cdata = nullptr;
+ if (buffer.chunkFractureCount > 0)
+ {
+ cdata = chunkBuffer.allocate(buffer.chunkFractureCount);
+ memcpy(cdata, buffer.chunkFractures, sizeof(NvBlastChunkFractureData)*buffer.chunkFractureCount);
+ }
+
+ TkFractureCommands* fevt = events.allocData<TkFractureCommands>();
+ fevt->tkActorData = *tkActor;
+ fevt->buffers = { buffer.bondFractureCount, buffer.chunkFractureCount, bdata, cdata };
+ events.addEvent(fevt);
+}
+
+
+/**
+Creates a TkEvent::FractureEvent according to the input buffer for tkActor
+into events queue using the LocalBuffers to store the actual event data.
+*/
+NV_FORCE_INLINE void reportFractureEvents(
+ const NvBlastFractureBuffers& buffer,
+ LocalBuffer<NvBlastBondFractureData>& bondBuffer, LocalBuffer<NvBlastChunkFractureData>& chunkBuffer,
+ TkEventQueue& events, const TkActorImpl* tkActor)
+{
+ uint32_t result[4] = { 0,0,0,0 };
+
+ NvBlastBondFractureData* bdata = nullptr;
+ if (buffer.bondFractureCount > 0)
+ {
+ bdata = bondBuffer.allocate(buffer.bondFractureCount);
+ for (uint32_t b = 0; b < buffer.bondFractureCount; ++b)
+ {
+ bdata[b] = buffer.bondFractures[b];
+ result[buffer.bondFractures[b].health > 0 ? 0 : 1]++;
+ }
+ }
+
+ NvBlastChunkFractureData* cdata = nullptr;
+ if (buffer.chunkFractureCount > 0)
+ {
+ cdata = chunkBuffer.allocate(buffer.chunkFractureCount);
+ for (uint32_t c = 0; c < buffer.chunkFractureCount; ++c)
+ {
+ cdata[c] = buffer.chunkFractures[c];
+ result[buffer.chunkFractures[c].health > 0 ? 2 : 3]++;
+ }
+ }
+
+ TkFractureEvents* fevt = events.allocData<TkFractureEvents>();
+ fevt->tkActorData = *tkActor;
+ fevt->buffers = { buffer.bondFractureCount, buffer.chunkFractureCount, bdata, cdata };
+ fevt->bondsDamaged = result[0];
+ fevt->bondsBroken = result[1];
+ fevt->chunksDamaged = result[2];
+ fevt->chunksBroken = result[3];
+ events.addEvent(fevt);
+}
+
+
+void TkWorker::initialize()
+{
+ // temporary memory used to generate and apply fractures
+ // it must fit for the largest family involved in the group that owns this worker
+ NvBlastBondFractureData* bondFractureData = m_group->m_bondTempDataBlock.getBlock(m_id);
+ uint32_t bondFractureCount = m_group->m_bondTempDataBlock.numElementsPerBlock();
+ NvBlastChunkFractureData* chunkFractureData = m_group->m_chunkTempDataBlock.getBlock(m_id);
+ uint32_t chunkFractureCount = m_group->m_chunkTempDataBlock.numElementsPerBlock();
+ m_tempBuffer = { bondFractureCount, chunkFractureCount, bondFractureData, chunkFractureData };
+
+ // temporary memory used to split the actor
+ // large enough for the largest family involved
+ m_splitScratch = m_group->m_splitScratchBlock.getBlock(m_id);
+
+ // to avoid unnecessary allocations, preallocated memory exists to fit all chunks and bonds taking damage once
+ // where multiple damage occurs, more memory will be allocated on demand (this may thwart other threads doing the same)
+ m_bondBuffer.initialize(m_group->m_bondEventDataBlock.getBlock(m_id), m_group->m_bondEventDataBlock.numElementsPerBlock());
+ m_chunkBuffer.initialize(m_group->m_chunkEventDataBlock.getBlock(m_id), m_group->m_chunkEventDataBlock.numElementsPerBlock());
+
+#if NV_PROFILE
+ NvBlastTimersReset(&m_stats.timers);
+ m_stats.processedActorsCount = 0;
+#endif
+}
+
+void TkWorker::process(TkWorkerJob& j)
+{
+ NvBlastTimers* timers = nullptr;
+
+ BLAST_PROFILE_SCOPE_M("TkActor");
+
+ TkActorImpl* tkActor = j.m_tkActor;
+ const uint32_t tkActorIndex = tkActor->getIndex();
+ NvBlastActor* actorLL = tkActor->getActorLLInternal();
+ TkFamilyImpl& family = tkActor->getFamilyImpl();
+ SharedMemory* mem = m_group->getSharedMemory(&family);
+ TkEventQueue& events = mem->m_events;
+
+ NVBLAST_ASSERT(tkActor->getGroupImpl() == m_group);
+ NVBLAST_ASSERT(tkActor->m_flags.isSet(TkActorFlag::PENDING));
+
+#if NV_PROFILE
+ timers = &m_stats.timers;
+ *timers += tkActor->m_timers;
+ NvBlastTimersReset(&tkActor->m_timers);
+ m_stats.processedActorsCount++;
+#endif
+
+ // generate and apply fracture for all damage requested on this actor
+ // and queue events accordingly
+ for (const auto& damage : tkActor->m_damageBuffer)
+ {
+ NvBlastFractureBuffers commandBuffer = m_tempBuffer;
+
+ BLAST_PROFILE_ZONE_BEGIN("Material");
+ NvBlastActorGenerateFracture(&commandBuffer, actorLL, damage.program, damage.programParams, logLL, timers);
+ BLAST_PROFILE_ZONE_END("Material");
+
+ if (commandBuffer.chunkFractureCount > 0 || commandBuffer.bondFractureCount > 0)
+ {
+ BLAST_PROFILE_SCOPE_M("Fill Command Events");
+ reportFractureCommands(commandBuffer, m_bondBuffer, m_chunkBuffer, events, tkActor);
+ }
+
+ NvBlastFractureBuffers eventBuffer = m_tempBuffer;
+
+ BLAST_PROFILE_ZONE_BEGIN("Fracture");
+ NvBlastActorApplyFracture(&eventBuffer, actorLL, &commandBuffer, logLL, timers);
+ BLAST_PROFILE_ZONE_END("Fracture");
+
+ if (eventBuffer.chunkFractureCount > 0 || eventBuffer.bondFractureCount > 0)
+ {
+ BLAST_PROFILE_SCOPE_M("Fill Fracture Events");
+ tkActor->m_flags |= (TkActorFlag::DAMAGED);
+ reportFractureEvents(eventBuffer, m_bondBuffer, m_chunkBuffer, events, tkActor);
+ }
+ }
+
+
+ // split the actor, which could have been damaged directly though the TkActor's fracture functions
+ // i.e. it did not have damage queued for the above loop
+
+ NvBlastActorSplitEvent splitEvent = { nullptr, nullptr };
+ if (tkActor->isDamaged())
+ {
+ BLAST_PROFILE_ZONE_BEGIN("Split Memory");
+ uint32_t maxActorCount = NvBlastActorGetMaxActorCountForSplit(actorLL, logLL);
+ splitEvent.newActors = mem->reserveNewActors(maxActorCount);
+ BLAST_PROFILE_ZONE_END("Split Memory");
+ BLAST_PROFILE_ZONE_BEGIN("Split");
+ j.m_newActorsCount = NvBlastActorSplit(&splitEvent, actorLL, maxActorCount, m_splitScratch, logLL, timers);
+ BLAST_PROFILE_ZONE_END("Split");
+
+ tkActor->m_flags.clear(TkActorFlag::DAMAGED);
+ }
+ else
+ {
+ j.m_newActorsCount = 0;
+ }
+
+
+ // update the TkActor according to the LL split results and queue events accordingly
+ if (j.m_newActorsCount > 0)
+ {
+ NVBLAST_ASSERT(splitEvent.deletedActor == tkActor->getActorLL());
+
+ BLAST_PROFILE_ZONE_BEGIN("memory new actors");
+
+ auto tkSplitEvent = events.allocData<TkSplitEvent>();
+
+ tkSplitEvent->children = mem->reserveNewTkActors(j.m_newActorsCount);
+ tkSplitEvent->numChildren = j.m_newActorsCount;
+
+ tkSplitEvent->parentData.family = &family;
+ tkSplitEvent->parentData.userData = tkActor->userData;
+ tkSplitEvent->parentData.index = tkActorIndex;
+ family.removeActor(tkActor);
+
+ BLAST_PROFILE_ZONE_END("memory new actors");
+
+
+ BLAST_PROFILE_ZONE_BEGIN("create new actors");
+ for (uint32_t i = 0; i < j.m_newActorsCount; ++i)
+ {
+ TkActorImpl* newActor = family.addActor(splitEvent.newActors[i]);
+ tkSplitEvent->children[i] = newActor;
+ }
+ j.m_newActors = reinterpret_cast<TkActorImpl**>(tkSplitEvent->children);
+ BLAST_PROFILE_ZONE_END("create new actors");
+
+ BLAST_PROFILE_ZONE_BEGIN("split event");
+ events.addEvent(tkSplitEvent);
+ BLAST_PROFILE_ZONE_END("split event");
+ }
+
+ j.m_tkActor->m_flags.clear(TkActorFlag::PENDING);
+}
+
+
+void TkWorker::process(uint32_t jobID)
+{
+ TkWorkerJob& j = m_group->m_jobs[jobID];
+ process(j);
+}
diff --git a/sdk/toolkit/source/NvBlastTkTaskImpl.h b/sdk/toolkit/source/NvBlastTkTaskImpl.h
index 1ab3ee0..a0aa11f 100644..100755
--- a/sdk/toolkit/source/NvBlastTkTaskImpl.h
+++ b/sdk/toolkit/source/NvBlastTkTaskImpl.h
@@ -1,373 +1,373 @@
-// 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) 2016-2018 NVIDIA Corporation. All rights reserved.
-
-
-#ifndef NVBLASTTKTASKIMPL_H
-#define NVBLASTTKTASKIMPL_H
-
-#include "NvBlast.h"
-
-#include "NvBlastTkFrameworkImpl.h"
-#include "NvBlastTkEventQueue.h"
-#include "NvBlastArray.h"
-
-#include <atomic>
-#include <mutex>
-#include <condition_variable>
-
-#include "NvBlastAssert.h"
-
-#include "NvBlastTkGroup.h" // TkGroupStats
-
-
-namespace Nv
-{
-namespace Blast
-{
-
-class TkGroupImpl;
-class TkActorImpl;
-class TkFamilyImpl;
-
-
-/**
-Transient structure describing a job and its results.
-*/
-struct TkWorkerJob
-{
- TkActorImpl* m_tkActor; //!< the actor to process
- TkActorImpl** m_newActors; //!< list of child actors created by splitting
- uint32_t m_newActorsCount; //!< the number of child actors created
-};
-
-
-
-
-
-/**
-A list of equally sized memory blocks sharable between tasks.
-*/
-template<typename T>
-class SharedBlock
-{
-public:
-
- SharedBlock() : m_numElementsPerBlock(0), m_numBlocks(0), m_buffer(nullptr) {}
-
- /**
- Allocates one large memory block of elementsPerBlock*numBlocks elements.
- */
- void allocate(uint32_t elementsPerBlock, uint32_t numBlocks)
- {
- NVBLAST_ASSERT(elementsPerBlock > 0 && numBlocks > 0);
-
- m_buffer = reinterpret_cast<T*>(NVBLAST_ALLOC_NAMED(elementsPerBlock*numBlocks*sizeof(T), "SharedBlock"));
- m_numElementsPerBlock = elementsPerBlock;
- m_numBlocks = numBlocks;
- }
-
- /**
- Returns the pointer to the first element of a block of numElementsPerBlock() elements.
- */
- T* getBlock(uint32_t id)
- {
- NVBLAST_ASSERT(id < m_numBlocks || 0 == m_numElementsPerBlock);
- return &m_buffer[id*m_numElementsPerBlock];
- }
-
- /**
- The number of elements available per block.
- */
- uint32_t numElementsPerBlock() const
- {
- return m_numElementsPerBlock;
- }
-
- /**
- Frees the whole memory block.
- */
- void release()
- {
- m_numBlocks = 0;
- m_numElementsPerBlock = 0;
- NVBLAST_FREE(m_buffer);
- m_buffer = nullptr;
- }
-
-private:
- uint32_t m_numElementsPerBlock; //!< elements available in one block
- uint32_t m_numBlocks; //!< number of virtual blocks available
- T* m_buffer; //!< contiguous memory for all blocks
-};
-
-
-/**
-A preallocated, shared array from which can be allocated from in tasks.
-Intended to be used when the maximum amount of data (e.g. for a family)
-is known in advance. No further allocations take place on exhaustion.
-Exhaustion asserts in debug builds and overflows otherwise.
-*/
-template<typename T>
-class SharedBuffer
-{
-public:
- SharedBuffer() : m_capacity(0), m_used(0), m_buffer(nullptr) {}
-
- /**
- Atomically gets a pointer to the first element of an array of n elements.
- */
- T* reserve(size_t n)
- {
- NVBLAST_ASSERT(m_used + n <= m_capacity);
- size_t start = m_used.fetch_add(n);
- return &m_buffer[start];
- }
-
- /**
- Preallocates memory for capacity elements.
- */
- void allocate(size_t capacity)
- {
- NVBLAST_ASSERT(m_buffer == nullptr);
- m_buffer = reinterpret_cast<T*>(NVBLAST_ALLOC_NAMED(capacity*sizeof(T), "SplitMemory"));
- m_capacity = capacity;
- }
-
- /**
- Preserves the memory allocated but resets to reserve from the beginning of the array.
- */
- void reset()
- {
- m_used = 0;
- }
-
- /**
- Frees the preallocated array.
- */
- void release()
- {
- NVBLAST_ASSERT(m_buffer != nullptr);
- NVBLAST_FREE(m_buffer);
- m_buffer = nullptr;
- m_capacity = m_used = 0;
- }
-
-private:
- size_t m_capacity; //!< available elements in the buffer
- std::atomic<size_t> m_used; //!< used elements in the buffer
- T* m_buffer; //!< the memory containing T's
-};
-
-
-/**
-Allocates from a preallocated, externally owned memory block initialized with.
-When blocks run out of space, new ones are allocated and owned by this class.
-*/
-template<typename T>
-class LocalBuffer
-{
-public:
- /**
- Returns the pointer to the first element of an array of n elements.
- Allocates a new block of memory when exhausted, its size being the larger of n and capacity set with initialize().
- */
- T* allocate(size_t n)
- {
- if (m_used + n > m_capacity)
- {
- allocateNewBlock(n > m_capacity ? n : m_capacity);
- }
-
- size_t index = m_used;
- m_used += n;
- return &m_currentBlock[index];
- }
-
- /**
- Release the additionally allocated memory blocks.
- The externally owned memory block remains untouched.
- */
- void clear()
- {
- for (void* block : m_memoryBlocks)
- {
- NVBLAST_FREE(block);
- }
- m_memoryBlocks.clear();
- }
-
- /**
- Set the externally owned memory block to start allocating from,
- with a size of capacity elements.
- */
- void initialize(T* block, size_t capacity)
- {
- m_currentBlock = block;
- m_capacity = capacity;
- m_used = 0;
- }
-
-private:
- /**
- Allocates space for capacity elements.
- */
- void allocateNewBlock(size_t capacity)
- {
- BLAST_PROFILE_SCOPE_L("Local Buffer allocation");
- m_capacity = capacity;
- m_currentBlock = static_cast<T*>(NVBLAST_ALLOC_NAMED(capacity*sizeof(T), "Blast LocalBuffer"));
- m_memoryBlocks.pushBack(m_currentBlock);
- m_used = 0;
- }
-
- InlineArray<void*, 4>::type m_memoryBlocks; //!< storage for memory blocks
- T* m_currentBlock; //!< memory block used to allocate from
- size_t m_used; //!< elements used in current block
- size_t m_capacity; //!< elements available in current block
-};
-
-
-/**
-Holds the memory used by TkWorker for each family in each group.
-*/
-class SharedMemory
-{
-public:
- SharedMemory() : m_eventsMemory(0), m_eventsCount(0), m_refCount(0) {}
-
- /**
- Reserves n entries from preallocated memory.
- */
- NvBlastActor** reserveNewActors(size_t n)
- {
- return m_newActorBuffers.reserve(n);
- }
-
- /**
- Reserves n entries from preallocated memory.
- */
- TkActor** reserveNewTkActors(size_t n)
- {
- return m_newTkActorBuffers.reserve(n);
- }
-
- /**
- Allocates buffers to hold
- */
- void allocate(TkFamilyImpl&);
-
- /**
- Resets the internal buffers to reserve from their beginning.
- Preserves the allocated memory.
- */
- void reset()
- {
- m_newActorBuffers.reset();
- m_newTkActorBuffers.reset();
- }
-
- /**
- Increments the reference count.
- */
- void addReference() { m_refCount++; }
-
- /**
- Increments the reference count by n.
- */
- void addReference(size_t n) { m_refCount += n; }
-
- /**
- Decrements the reference count.
- Returns true if the count reached zero.
- */
- bool removeReference()
- {
- m_refCount--;
- return !isUsed();
- }
-
- /**
- Checks if the reference count is not zero.
- */
- bool isUsed()
- {
- return m_refCount > 0;
- }
-
- /**
- Release the internal buffers' memory.
- */
- void release()
- {
- m_newActorBuffers.release();
- m_newTkActorBuffers.release();
- }
-
- TkEventQueue m_events; //!< event queue shared across a group's actors of the same family
- uint32_t m_eventsMemory; //!< expected memory size for event data
- uint32_t m_eventsCount; //!< expected number of events
-
-private:
- size_t m_refCount; //!< helper for usage and releasing memory
-
- SharedBuffer<NvBlastActor*> m_newActorBuffers; //!< memory for splitting
- SharedBuffer<TkActor*> m_newTkActorBuffers; //!< memory for split events
-};
-
-
-/**
-Thread worker fracturing and splitting actors sequentially.
-The list of actual jobs is provided by the group owning this worker.
-*/
-class TkWorker final : public TkGroupWorker
-{
-public:
- TkWorker() : m_id(~(uint32_t)0), m_group(nullptr), m_isBusy(false) {}
-
- void process(uint32_t jobID);
- void initialize();
-
- void process(TkWorkerJob& job);
-
- uint32_t m_id; //!< this worker's id
- TkGroupImpl* m_group; //!< the group owning this worker
-
- LocalBuffer<NvBlastChunkFractureData> m_chunkBuffer; //!< memory manager for chunk event data
- LocalBuffer<NvBlastBondFractureData> m_bondBuffer; //!< memory manager for bonds event data
-
- void* m_splitScratch;
- NvBlastFractureBuffers m_tempBuffer;
- bool m_isBusy;
-
-#if NV_PROFILE
- TkGroupStats m_stats;
-#endif
-};
-}
-}
-
-#endif // NVBLASTTKTASKIMPL_H
+// 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) 2016-2018 NVIDIA Corporation. All rights reserved.
+
+
+#ifndef NVBLASTTKTASKIMPL_H
+#define NVBLASTTKTASKIMPL_H
+
+#include "NvBlast.h"
+
+#include "NvBlastTkFrameworkImpl.h"
+#include "NvBlastTkEventQueue.h"
+#include "NvBlastArray.h"
+
+#include <atomic>
+#include <mutex>
+#include <condition_variable>
+
+#include "NvBlastAssert.h"
+
+#include "NvBlastTkGroup.h" // TkGroupStats
+
+
+namespace Nv
+{
+namespace Blast
+{
+
+class TkGroupImpl;
+class TkActorImpl;
+class TkFamilyImpl;
+
+
+/**
+Transient structure describing a job and its results.
+*/
+struct TkWorkerJob
+{
+ TkActorImpl* m_tkActor; //!< the actor to process
+ TkActorImpl** m_newActors; //!< list of child actors created by splitting
+ uint32_t m_newActorsCount; //!< the number of child actors created
+};
+
+
+
+
+
+/**
+A list of equally sized memory blocks sharable between tasks.
+*/
+template<typename T>
+class SharedBlock
+{
+public:
+
+ SharedBlock() : m_numElementsPerBlock(0), m_numBlocks(0), m_buffer(nullptr) {}
+
+ /**
+ Allocates one large memory block of elementsPerBlock*numBlocks elements.
+ */
+ void allocate(uint32_t elementsPerBlock, uint32_t numBlocks)
+ {
+ NVBLAST_ASSERT(elementsPerBlock > 0 && numBlocks > 0);
+
+ m_buffer = reinterpret_cast<T*>(NVBLAST_ALLOC_NAMED(elementsPerBlock*numBlocks*sizeof(T), "SharedBlock"));
+ m_numElementsPerBlock = elementsPerBlock;
+ m_numBlocks = numBlocks;
+ }
+
+ /**
+ Returns the pointer to the first element of a block of numElementsPerBlock() elements.
+ */
+ T* getBlock(uint32_t id)
+ {
+ NVBLAST_ASSERT(id < m_numBlocks || 0 == m_numElementsPerBlock);
+ return &m_buffer[id*m_numElementsPerBlock];
+ }
+
+ /**
+ The number of elements available per block.
+ */
+ uint32_t numElementsPerBlock() const
+ {
+ return m_numElementsPerBlock;
+ }
+
+ /**
+ Frees the whole memory block.
+ */
+ void release()
+ {
+ m_numBlocks = 0;
+ m_numElementsPerBlock = 0;
+ NVBLAST_FREE(m_buffer);
+ m_buffer = nullptr;
+ }
+
+private:
+ uint32_t m_numElementsPerBlock; //!< elements available in one block
+ uint32_t m_numBlocks; //!< number of virtual blocks available
+ T* m_buffer; //!< contiguous memory for all blocks
+};
+
+
+/**
+A preallocated, shared array from which can be allocated from in tasks.
+Intended to be used when the maximum amount of data (e.g. for a family)
+is known in advance. No further allocations take place on exhaustion.
+Exhaustion asserts in debug builds and overflows otherwise.
+*/
+template<typename T>
+class SharedBuffer
+{
+public:
+ SharedBuffer() : m_capacity(0), m_used(0), m_buffer(nullptr) {}
+
+ /**
+ Atomically gets a pointer to the first element of an array of n elements.
+ */
+ T* reserve(size_t n)
+ {
+ NVBLAST_ASSERT(m_used + n <= m_capacity);
+ size_t start = m_used.fetch_add(n);
+ return &m_buffer[start];
+ }
+
+ /**
+ Preallocates memory for capacity elements.
+ */
+ void allocate(size_t capacity)
+ {
+ NVBLAST_ASSERT(m_buffer == nullptr);
+ m_buffer = reinterpret_cast<T*>(NVBLAST_ALLOC_NAMED(capacity*sizeof(T), "SplitMemory"));
+ m_capacity = capacity;
+ }
+
+ /**
+ Preserves the memory allocated but resets to reserve from the beginning of the array.
+ */
+ void reset()
+ {
+ m_used = 0;
+ }
+
+ /**
+ Frees the preallocated array.
+ */
+ void release()
+ {
+ NVBLAST_ASSERT(m_buffer != nullptr);
+ NVBLAST_FREE(m_buffer);
+ m_buffer = nullptr;
+ m_capacity = m_used = 0;
+ }
+
+private:
+ size_t m_capacity; //!< available elements in the buffer
+ std::atomic<size_t> m_used; //!< used elements in the buffer
+ T* m_buffer; //!< the memory containing T's
+};
+
+
+/**
+Allocates from a preallocated, externally owned memory block initialized with.
+When blocks run out of space, new ones are allocated and owned by this class.
+*/
+template<typename T>
+class LocalBuffer
+{
+public:
+ /**
+ Returns the pointer to the first element of an array of n elements.
+ Allocates a new block of memory when exhausted, its size being the larger of n and capacity set with initialize().
+ */
+ T* allocate(size_t n)
+ {
+ if (m_used + n > m_capacity)
+ {
+ allocateNewBlock(n > m_capacity ? n : m_capacity);
+ }
+
+ size_t index = m_used;
+ m_used += n;
+ return &m_currentBlock[index];
+ }
+
+ /**
+ Release the additionally allocated memory blocks.
+ The externally owned memory block remains untouched.
+ */
+ void clear()
+ {
+ for (void* block : m_memoryBlocks)
+ {
+ NVBLAST_FREE(block);
+ }
+ m_memoryBlocks.clear();
+ }
+
+ /**
+ Set the externally owned memory block to start allocating from,
+ with a size of capacity elements.
+ */
+ void initialize(T* block, size_t capacity)
+ {
+ m_currentBlock = block;
+ m_capacity = capacity;
+ m_used = 0;
+ }
+
+private:
+ /**
+ Allocates space for capacity elements.
+ */
+ void allocateNewBlock(size_t capacity)
+ {
+ BLAST_PROFILE_SCOPE_L("Local Buffer allocation");
+ m_capacity = capacity;
+ m_currentBlock = static_cast<T*>(NVBLAST_ALLOC_NAMED(capacity*sizeof(T), "Blast LocalBuffer"));
+ m_memoryBlocks.pushBack(m_currentBlock);
+ m_used = 0;
+ }
+
+ InlineArray<void*, 4>::type m_memoryBlocks; //!< storage for memory blocks
+ T* m_currentBlock; //!< memory block used to allocate from
+ size_t m_used; //!< elements used in current block
+ size_t m_capacity; //!< elements available in current block
+};
+
+
+/**
+Holds the memory used by TkWorker for each family in each group.
+*/
+class SharedMemory
+{
+public:
+ SharedMemory() : m_eventsMemory(0), m_eventsCount(0), m_refCount(0) {}
+
+ /**
+ Reserves n entries from preallocated memory.
+ */
+ NvBlastActor** reserveNewActors(size_t n)
+ {
+ return m_newActorBuffers.reserve(n);
+ }
+
+ /**
+ Reserves n entries from preallocated memory.
+ */
+ TkActor** reserveNewTkActors(size_t n)
+ {
+ return m_newTkActorBuffers.reserve(n);
+ }
+
+ /**
+ Allocates buffers to hold
+ */
+ void allocate(TkFamilyImpl&);
+
+ /**
+ Resets the internal buffers to reserve from their beginning.
+ Preserves the allocated memory.
+ */
+ void reset()
+ {
+ m_newActorBuffers.reset();
+ m_newTkActorBuffers.reset();
+ }
+
+ /**
+ Increments the reference count.
+ */
+ void addReference() { m_refCount++; }
+
+ /**
+ Increments the reference count by n.
+ */
+ void addReference(size_t n) { m_refCount += n; }
+
+ /**
+ Decrements the reference count.
+ Returns true if the count reached zero.
+ */
+ bool removeReference()
+ {
+ m_refCount--;
+ return !isUsed();
+ }
+
+ /**
+ Checks if the reference count is not zero.
+ */
+ bool isUsed()
+ {
+ return m_refCount > 0;
+ }
+
+ /**
+ Release the internal buffers' memory.
+ */
+ void release()
+ {
+ m_newActorBuffers.release();
+ m_newTkActorBuffers.release();
+ }
+
+ TkEventQueue m_events; //!< event queue shared across a group's actors of the same family
+ uint32_t m_eventsMemory; //!< expected memory size for event data
+ uint32_t m_eventsCount; //!< expected number of events
+
+private:
+ size_t m_refCount; //!< helper for usage and releasing memory
+
+ SharedBuffer<NvBlastActor*> m_newActorBuffers; //!< memory for splitting
+ SharedBuffer<TkActor*> m_newTkActorBuffers; //!< memory for split events
+};
+
+
+/**
+Thread worker fracturing and splitting actors sequentially.
+The list of actual jobs is provided by the group owning this worker.
+*/
+class TkWorker final : public TkGroupWorker
+{
+public:
+ TkWorker() : m_id(~(uint32_t)0), m_group(nullptr), m_isBusy(false) {}
+
+ void process(uint32_t jobID);
+ void initialize();
+
+ void process(TkWorkerJob& job);
+
+ uint32_t m_id; //!< this worker's id
+ TkGroupImpl* m_group; //!< the group owning this worker
+
+ LocalBuffer<NvBlastChunkFractureData> m_chunkBuffer; //!< memory manager for chunk event data
+ LocalBuffer<NvBlastBondFractureData> m_bondBuffer; //!< memory manager for bonds event data
+
+ void* m_splitScratch;
+ NvBlastFractureBuffers m_tempBuffer;
+ bool m_isBusy;
+
+#if NV_PROFILE
+ TkGroupStats m_stats;
+#endif
+};
+}
+}
+
+#endif // NVBLASTTKTASKIMPL_H
diff --git a/sdk/toolkit/source/NvBlastTkTypeImpl.h b/sdk/toolkit/source/NvBlastTkTypeImpl.h
index 81ff5ef..9a5dc6e 100644..100755
--- a/sdk/toolkit/source/NvBlastTkTypeImpl.h
+++ b/sdk/toolkit/source/NvBlastTkTypeImpl.h
@@ -1,161 +1,161 @@
-// 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) 2016-2018 NVIDIA Corporation. All rights reserved.
-
-
-#ifndef NVBLASTTKTYPEIMPL_H
-#define NVBLASTTKTYPEIMPL_H
-
-
-#include "NvPreprocessor.h"
-
-#include "NvBlastTkType.h"
-
-
-namespace Nv
-{
-namespace Blast
-{
-
-/**
-Implementation of TkType, storing class information for TkIdentifiable-derived classes.
-*/
-class TkTypeImpl : public TkType
-{
-public:
- TkTypeImpl(const char* typeName, uint32_t typeID, uint32_t version);
-
- // Begin TkType
- virtual const char* getName() const override { return getNameInternal(); }
-
- virtual uint32_t getVersion() const override { return getVersionInternal(); }
- // End TkType
-
- // Public methods
-
- /**
- Access to the class name.
-
- \return a C string pointer to the class name.
- */
- const char* getNameInternal() const;
-
- /**
- Access to the data format version for the class.
-
- \return the data format version.
- */
- uint32_t getVersionInternal() const;
-
- /**
- Access to a unique identifier for the class (set using the NVBLASTTK_IMPL_DEFINE_IDENTIFIABLE macro).
-
- \return the class's unique identifier.
- */
- uint32_t getID() const;
-
- /**
- Access to a runtime-unique small index for the class.
-
- \return the index for the class.
- */
- uint32_t getIndex() const;
-
- /**
- \return whether or not the index has been set (see setIndex) to a valid value.
- */
- bool indexIsValid() const;
-
-private:
- enum { InvalidIndex = 0xFFFFFFFF };
-
- /**
- Sets the type index.
-
- \param[in] index The index to set.
- */
- void setIndex(uint32_t index);
-
- const char* m_name; //!< The name of the class, set by the constructor.
- uint32_t m_ID; //!< The unique identifier for the class, set by the constructor.
- uint32_t m_version; //!< The data format version for the class, set by the constructor.
- uint32_t m_index; //!< The index set for this class, set using setIndex().
-
- friend class TkFrameworkImpl;
-};
-
-
-//////// TkTypeImpl inline methods ////////
-
-NV_INLINE TkTypeImpl::TkTypeImpl(const char* typeName, uint32_t typeID, uint32_t version)
- : m_name(typeName)
- , m_ID(typeID)
- , m_version(version)
- , m_index((uint32_t)InvalidIndex)
-{
-}
-
-
-NV_INLINE const char* TkTypeImpl::getNameInternal() const
-{
- return m_name;
-}
-
-
-NV_INLINE uint32_t TkTypeImpl::getVersionInternal() const
-{
- return m_version;
-}
-
-
-NV_INLINE uint32_t TkTypeImpl::getID() const
-{
- return m_ID;
-}
-
-
-NV_INLINE uint32_t TkTypeImpl::getIndex() const
-{
- return m_index;
-}
-
-
-NV_INLINE bool TkTypeImpl::indexIsValid() const
-{
- return m_index != (uint32_t)InvalidIndex;
-}
-
-
-NV_INLINE void TkTypeImpl::setIndex(uint32_t index)
-{
- m_index = index;
-}
-
-} // namespace Blast
-} // namespace Nv
-
-
-#endif // ifndef NVBLASTTKTYPEIMPL_H
+// 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) 2016-2018 NVIDIA Corporation. All rights reserved.
+
+
+#ifndef NVBLASTTKTYPEIMPL_H
+#define NVBLASTTKTYPEIMPL_H
+
+
+#include "NvPreprocessor.h"
+
+#include "NvBlastTkType.h"
+
+
+namespace Nv
+{
+namespace Blast
+{
+
+/**
+Implementation of TkType, storing class information for TkIdentifiable-derived classes.
+*/
+class TkTypeImpl : public TkType
+{
+public:
+ TkTypeImpl(const char* typeName, uint32_t typeID, uint32_t version);
+
+ // Begin TkType
+ virtual const char* getName() const override { return getNameInternal(); }
+
+ virtual uint32_t getVersion() const override { return getVersionInternal(); }
+ // End TkType
+
+ // Public methods
+
+ /**
+ Access to the class name.
+
+ \return a C string pointer to the class name.
+ */
+ const char* getNameInternal() const;
+
+ /**
+ Access to the data format version for the class.
+
+ \return the data format version.
+ */
+ uint32_t getVersionInternal() const;
+
+ /**
+ Access to a unique identifier for the class (set using the NVBLASTTK_IMPL_DEFINE_IDENTIFIABLE macro).
+
+ \return the class's unique identifier.
+ */
+ uint32_t getID() const;
+
+ /**
+ Access to a runtime-unique small index for the class.
+
+ \return the index for the class.
+ */
+ uint32_t getIndex() const;
+
+ /**
+ \return whether or not the index has been set (see setIndex) to a valid value.
+ */
+ bool indexIsValid() const;
+
+private:
+ enum { InvalidIndex = 0xFFFFFFFF };
+
+ /**
+ Sets the type index.
+
+ \param[in] index The index to set.
+ */
+ void setIndex(uint32_t index);
+
+ const char* m_name; //!< The name of the class, set by the constructor.
+ uint32_t m_ID; //!< The unique identifier for the class, set by the constructor.
+ uint32_t m_version; //!< The data format version for the class, set by the constructor.
+ uint32_t m_index; //!< The index set for this class, set using setIndex().
+
+ friend class TkFrameworkImpl;
+};
+
+
+//////// TkTypeImpl inline methods ////////
+
+NV_INLINE TkTypeImpl::TkTypeImpl(const char* typeName, uint32_t typeID, uint32_t version)
+ : m_name(typeName)
+ , m_ID(typeID)
+ , m_version(version)
+ , m_index((uint32_t)InvalidIndex)
+{
+}
+
+
+NV_INLINE const char* TkTypeImpl::getNameInternal() const
+{
+ return m_name;
+}
+
+
+NV_INLINE uint32_t TkTypeImpl::getVersionInternal() const
+{
+ return m_version;
+}
+
+
+NV_INLINE uint32_t TkTypeImpl::getID() const
+{
+ return m_ID;
+}
+
+
+NV_INLINE uint32_t TkTypeImpl::getIndex() const
+{
+ return m_index;
+}
+
+
+NV_INLINE bool TkTypeImpl::indexIsValid() const
+{
+ return m_index != (uint32_t)InvalidIndex;
+}
+
+
+NV_INLINE void TkTypeImpl::setIndex(uint32_t index)
+{
+ m_index = index;
+}
+
+} // namespace Blast
+} // namespace Nv
+
+
+#endif // ifndef NVBLASTTKTYPEIMPL_H