aboutsummaryrefslogtreecommitdiff
path: root/NvBlast/sdk/lowlevel/source/NvBlastFamily.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'NvBlast/sdk/lowlevel/source/NvBlastFamily.cpp')
-rw-r--r--NvBlast/sdk/lowlevel/source/NvBlastFamily.cpp295
1 files changed, 295 insertions, 0 deletions
diff --git a/NvBlast/sdk/lowlevel/source/NvBlastFamily.cpp b/NvBlast/sdk/lowlevel/source/NvBlastFamily.cpp
new file mode 100644
index 0000000..1f517b1
--- /dev/null
+++ b/NvBlast/sdk/lowlevel/source/NvBlastFamily.cpp
@@ -0,0 +1,295 @@
+/*
+* Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, 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.
+*/
+
+
+#include "NvBlastFamily.h"
+#include "NvBlastFamilyGraph.h"
+#include "NvBlastIndexFns.h"
+
+#include <new>
+
+namespace Nv
+{
+namespace Blast
+{
+
+//////// Global functions ////////
+
+struct FamilyDataOffsets
+{
+ size_t m_actors;
+ size_t m_visibleChunkIndexLinks;
+ size_t m_chunkActorIndices;
+ size_t m_graphNodeIndexLinks;
+ size_t m_lowerSupportChunkHealths;
+ size_t m_graphBondHealths;
+ size_t m_familyGraph;
+};
+
+
+static size_t createFamilyDataOffsets(FamilyDataOffsets& offsets, const Asset* asset)
+{
+ const Nv::Blast::SupportGraph& graph = asset->m_graph;
+
+ NvBlastCreateOffsetStart(sizeof(FamilyHeader));
+ NvBlastCreateOffsetAlign16(offsets.m_actors, asset->getLowerSupportChunkCount() * sizeof(Actor));
+ NvBlastCreateOffsetAlign16(offsets.m_visibleChunkIndexLinks, asset->m_chunkCount * sizeof(IndexDLink<uint32_t>));
+ NvBlastCreateOffsetAlign16(offsets.m_chunkActorIndices, asset->getUpperSupportChunkCount() * sizeof(uint32_t));
+ NvBlastCreateOffsetAlign16(offsets.m_graphNodeIndexLinks, graph.m_nodeCount * sizeof(uint32_t));
+ NvBlastCreateOffsetAlign16(offsets.m_lowerSupportChunkHealths, asset->getLowerSupportChunkCount() * sizeof(float));
+ NvBlastCreateOffsetAlign16(offsets.m_graphBondHealths, asset->getBondCount() * sizeof(float));
+ NvBlastCreateOffsetAlign16(offsets.m_familyGraph, static_cast<size_t>(FamilyGraph::requiredMemorySize(graph.m_nodeCount, asset->getBondCount())));
+ return NvBlastCreateOffsetEndAlign16();
+}
+
+
+size_t getFamilyMemorySize(const Asset* asset)
+{
+#if NVBLAST_CHECK_PARAMS
+ if (asset == nullptr)
+ {
+ NVBLAST_ALWAYS_ASSERT();
+ return 0;
+ }
+#endif
+
+ FamilyDataOffsets offsets;
+ return createFamilyDataOffsets(offsets, asset);
+}
+
+
+NvBlastFamily* createFamily(void* mem, const NvBlastAsset* asset, NvBlastLog logFn)
+{
+ NVBLAST_CHECK(mem != nullptr, logFn, "createFamily: NULL mem pointer input.", return nullptr);
+ NVBLAST_CHECK(asset != nullptr, logFn, "createFamily: NULL asset pointer input.", return nullptr);
+
+ NVBLAST_CHECK((reinterpret_cast<uintptr_t>(mem) & 0xF) == 0, logFn, "createFamily: mem pointer not 16-byte aligned.", return nullptr);
+
+ const Asset& solverAsset = *static_cast<const Asset*>(asset);
+
+ if (solverAsset.m_chunkCount == 0)
+ {
+ NVBLAST_LOG_ERROR(logFn, "createFamily: Asset has no chunks. Family not created.\n");
+ return nullptr;
+ }
+
+ const Nv::Blast::SupportGraph& graph = solverAsset.m_graph;
+
+ const uint32_t bondCount = solverAsset.getBondCount();
+
+ // We need to keep this many actor representations around for our island indexing scheme.
+ const uint32_t lowerSupportChunkCount = solverAsset.getLowerSupportChunkCount();
+
+ // We need this many chunk actor indices.
+ const uint32_t upperSupportChunkCount = solverAsset.getUpperSupportChunkCount();
+
+ // Family offsets
+ FamilyDataOffsets offsets;
+ const size_t dataSize = createFamilyDataOffsets(offsets, &solverAsset);
+
+ // Restricting our data size to < 4GB so that we may use uint32_t offsets
+ if (dataSize > (size_t)UINT32_MAX)
+ {
+ NVBLAST_LOG_ERROR(logFn, "Nv::Blast::Actor::instanceAllocate: Instance data block size will exceed 4GB. Instance not created.\n");
+ return nullptr;
+ }
+
+ // Allocate family
+ NvBlastFamily* family = (NvBlastFamily*)mem;
+
+ // Fill in family header
+ FamilyHeader* header = (FamilyHeader*)family;
+ header->dataType = NvBlastDataBlock::FamilyDataBlock;
+ header->formatVersion = NvBlastFamilyDataFormat::Current;
+ header->size = (uint32_t)dataSize;
+ header->m_assetID = solverAsset.m_ID;
+ header->m_actorCount = 0;
+ header->m_actorsOffset = (uint32_t)offsets.m_actors;
+ header->m_visibleChunkIndexLinksOffset = (uint32_t)offsets.m_visibleChunkIndexLinks;
+ header->m_chunkActorIndicesOffset = (uint32_t)offsets.m_chunkActorIndices;
+ header->m_graphNodeIndexLinksOffset = (uint32_t)offsets.m_graphNodeIndexLinks;
+ header->m_lowerSupportChunkHealthsOffset = (uint32_t)offsets.m_lowerSupportChunkHealths;
+ header->m_graphBondHealthsOffset = (uint32_t)offsets.m_graphBondHealths;
+ header->m_familyGraphOffset = (uint32_t)offsets.m_familyGraph;
+
+ // Runtime data
+ header->m_asset = &solverAsset; // NOTE: this should be resolved from m_assetID
+
+ // Initialize family header data:
+
+ // Actors - initialize to defaults, with zero offset value (indicating inactive state)
+ Actor* actors = header->getActors(); // This will get the subsupport actors too
+ for (uint32_t i = 0; i < lowerSupportChunkCount; ++i)
+ {
+ new (actors + i) Actor();
+ }
+
+ // Visible chunk index links - initialize to solitary links (0xFFFFFFFF fields)
+ memset(header->getVisibleChunkIndexLinks(), 0xFF, solverAsset.m_chunkCount*sizeof(IndexDLink<uint32_t>));
+
+ // Chunk actor IDs - initialize to invalid (0xFFFFFFFF)
+ memset(header->getChunkActorIndices(), 0xFF, upperSupportChunkCount*sizeof(uint32_t));
+
+ // Graph node index links - initialize to solitary links
+ memset(header->getGraphNodeIndexLinks(), 0xFF, graph.m_nodeCount*sizeof(uint32_t));
+
+ // Healths are initialized to 0
+ memset(header->getLowerSupportChunkHealths(), 0, lowerSupportChunkCount*sizeof(float));
+ memset(header->getBondHealths(), 0, bondCount*sizeof(float));
+
+ // FamilyGraph ctor
+ new (header->getFamilyGraph()) FamilyGraph(&graph);
+
+ return family;
+}
+
+} // namespace Blast
+} // namespace Nv
+
+
+// API implementation
+
+extern "C"
+{
+
+NvBlastFamily* NvBlastAssetCreateFamily(void* mem, const NvBlastAsset* asset, NvBlastLog logFn)
+{
+ return Nv::Blast::createFamily(mem, asset, logFn);
+}
+
+
+uint32_t NvBlastFamilyGetFormatVersion(const NvBlastFamily* family, NvBlastLog logFn)
+{
+ NVBLAST_CHECK(family != nullptr, logFn, "NvBlastFamilyGetFormatVersion: NULL family pointer input.", return UINT32_MAX);
+ return reinterpret_cast<const Nv::Blast::FamilyHeader*>(family)->formatVersion;
+}
+
+
+void NvBlastFamilySetAsset(NvBlastFamily* family, const NvBlastAsset* asset, NvBlastLog logFn)
+{
+ NVBLAST_CHECK(family != nullptr, logFn, "NvBlastFamilySetAsset: NULL family pointer input.", return);
+ NVBLAST_CHECK(asset != nullptr, logFn, "NvBlastFamilySetAsset: NULL asset pointer input.", return);
+
+ Nv::Blast::FamilyHeader* header = reinterpret_cast<Nv::Blast::FamilyHeader*>(family);
+ const Nv::Blast::Asset* solverAsset = reinterpret_cast<const Nv::Blast::Asset*>(asset);
+
+ if (memcmp(&header->m_assetID, &solverAsset->m_ID, sizeof(NvBlastID)))
+ {
+ NVBLAST_LOG_ERROR(logFn, "NvBlastFamilySetAsset: wrong asset. Passed asset ID doesn't match family asset ID.");
+ return;
+ }
+
+ header->m_asset = solverAsset;
+}
+
+
+uint32_t NvBlastFamilyGetSize(const NvBlastFamily* family, NvBlastLog logFn)
+{
+ NVBLAST_CHECK(family != nullptr, logFn, "NvBlastFamilyGetSize: NULL family pointer input.", return 0);
+ return reinterpret_cast<const Nv::Blast::FamilyHeader*>(family)->size;
+}
+
+
+NvBlastID NvBlastFamilyGetAssetID(const NvBlastFamily* family, NvBlastLog logFn)
+{
+ NVBLAST_CHECK(family != nullptr, logFn, "NvBlastFamilyGetAssetID: NULL family pointer input.", return NvBlastID());
+ return reinterpret_cast<const Nv::Blast::FamilyHeader*>(family)->m_assetID;
+}
+
+
+uint32_t NvBlastFamilyGetActorCount(const NvBlastFamily* family, NvBlastLog logFn)
+{
+ NVBLAST_CHECK(family != nullptr, logFn, "NvBlastFamilyGetActorCount: NULL family pointer input.", return 0);
+
+ const Nv::Blast::FamilyHeader* header = reinterpret_cast<const Nv::Blast::FamilyHeader*>(family);
+
+ if (header->formatVersion != NvBlastFamilyDataFormat::Current)
+ {
+ NVBLAST_LOG_ERROR(logFn, "NvBlastFamilyGetActorCount: wrong family format. Family must be converted to current version.");
+ return 0;
+ }
+
+ return header->m_actorCount;
+}
+
+
+uint32_t NvBlastFamilyGetActors(NvBlastActor** actors, uint32_t actorsSize, const NvBlastFamily* family, NvBlastLog logFn)
+{
+ NVBLAST_CHECK(actors != nullptr, logFn, "NvBlastFamilyGetActors: NULL actors pointer input.", return 0);
+ NVBLAST_CHECK(family != nullptr, logFn, "NvBlastFamilyGetActors: NULL family pointer input.", return 0);
+
+ const Nv::Blast::FamilyHeader* header = reinterpret_cast<const Nv::Blast::FamilyHeader*>(family);
+
+ if (header->formatVersion != NvBlastFamilyDataFormat::Current)
+ {
+ NVBLAST_LOG_ERROR(logFn, "NvBlastFamilyGetActors: wrong family format. Family must be converted to current version.");
+ return 0;
+ }
+
+ // Iterate through active actors and write to supplied array
+ const uint32_t familyActorCount = header->getActorBufferSize();
+ Nv::Blast::Actor* familyActor = header->getActors();
+ uint32_t actorCount = 0;
+ for (uint32_t i = 0; actorCount < actorsSize && i < familyActorCount; ++i, ++familyActor)
+ {
+ if (familyActor->isActive())
+ {
+ actors[actorCount++] = familyActor;
+ }
+ }
+
+ return actorCount;
+}
+
+
+NvBlastActor* NvBlastFamilyGetChunkActor(const NvBlastFamily* family, uint32_t chunkIndex, NvBlastLog logFn)
+{
+ NVBLAST_CHECK(family != nullptr, logFn, "NvBlastFamilyGetChunkActor: NULL family pointer input.", return nullptr);
+
+ const Nv::Blast::FamilyHeader* header = reinterpret_cast<const Nv::Blast::FamilyHeader*>(family);
+
+ NVBLAST_CHECK(header->m_asset != nullptr, logFn, "NvBlastFamilyGetChunkActor: NvBlastFamily has null asset set.", return nullptr);
+
+ const Nv::Blast::Asset& solverAsset = *static_cast<const Nv::Blast::Asset*>(header->m_asset);
+ NVBLAST_CHECK(chunkIndex < solverAsset.m_chunkCount, logFn, "NvBlastFamilyGetChunkActor: bad value of chunkIndex for the given family's asset.", return nullptr);
+
+ // get actorIndex from chunkIndex
+ uint32_t actorIndex;
+ if (chunkIndex < solverAsset.getUpperSupportChunkCount())
+ {
+ actorIndex = header->getChunkActorIndices()[chunkIndex];
+ }
+ else
+ {
+ actorIndex = chunkIndex - (solverAsset.getUpperSupportChunkCount() - solverAsset.m_graph.m_nodeCount);
+ }
+
+ // get actor from actorIndex
+ if (!Nv::Blast::isInvalidIndex(actorIndex))
+ {
+ NVBLAST_ASSERT(actorIndex < header->getActorBufferSize());
+ Nv::Blast::Actor* actor = &header->getActors()[actorIndex];
+ if (actor->isActive())
+ {
+ return actor;
+ }
+ }
+ return nullptr;
+}
+
+
+uint32_t NvBlastFamilyGetMaxActorCount(const NvBlastFamily* family, NvBlastLog logFn)
+{
+ NVBLAST_CHECK(family != nullptr, logFn, "NvBlastFamilyGetMaxActorCount: NULL family pointer input.", return 0);
+ const Nv::Blast::FamilyHeader* header = reinterpret_cast<const Nv::Blast::FamilyHeader*>(family);
+ return header->getActorBufferSize();
+}
+
+} // extern "C"