diff options
| author | Bryan Galdrikian <[email protected]> | 2017-02-24 09:32:20 -0800 |
|---|---|---|
| committer | Bryan Galdrikian <[email protected]> | 2017-02-24 09:32:20 -0800 |
| commit | e1bf674c16e3c8472b29574159c789cd3f0c64e0 (patch) | |
| tree | 9f0cfce09c71a2c27ff19589fcad6cd83504477c /NvBlast/test/src | |
| parent | first commit (diff) | |
| download | blast-e1bf674c16e3c8472b29574159c789cd3f0c64e0.tar.xz blast-e1bf674c16e3c8472b29574159c789cd3f0c64e0.zip | |
Updating to [email protected] and [email protected] with a new directory structure.
NvBlast folder is gone, files have been moved to top level directory. README is changed to reflect this.
Diffstat (limited to 'NvBlast/test/src')
| -rw-r--r-- | NvBlast/test/src/AlignedAllocator.h | 69 | ||||
| -rw-r--r-- | NvBlast/test/src/BlastBaseTest.h | 159 | ||||
| -rw-r--r-- | NvBlast/test/src/TkBaseTest.h | 467 | ||||
| -rw-r--r-- | NvBlast/test/src/perf/BlastBasePerfTest.h | 374 | ||||
| -rw-r--r-- | NvBlast/test/src/perf/SolverPerfTests.cpp | 211 | ||||
| -rw-r--r-- | NvBlast/test/src/unit/APITests.cpp | 1354 | ||||
| -rw-r--r-- | NvBlast/test/src/unit/ActorTests.cpp | 1059 | ||||
| -rw-r--r-- | NvBlast/test/src/unit/AssetTests.cpp | 529 | ||||
| -rw-r--r-- | NvBlast/test/src/unit/CoreTests.cpp | 293 | ||||
| -rw-r--r-- | NvBlast/test/src/unit/FamilyGraphTests.cpp | 377 | ||||
| -rw-r--r-- | NvBlast/test/src/unit/MultithreadingTests.cpp | 395 | ||||
| -rw-r--r-- | NvBlast/test/src/unit/SyncTests.cpp | 309 | ||||
| -rw-r--r-- | NvBlast/test/src/unit/TkCompositeTests.cpp | 739 | ||||
| -rw-r--r-- | NvBlast/test/src/unit/TkTests.cpp | 1528 | ||||
| -rw-r--r-- | NvBlast/test/src/utils/TaskDispatcher.h | 191 | ||||
| -rw-r--r-- | NvBlast/test/src/utils/TestAssets.cpp | 288 | ||||
| -rw-r--r-- | NvBlast/test/src/utils/TestAssets.h | 40 | ||||
| -rw-r--r-- | NvBlast/test/src/utils/TestProfiler.h | 27 |
18 files changed, 0 insertions, 8409 deletions
diff --git a/NvBlast/test/src/AlignedAllocator.h b/NvBlast/test/src/AlignedAllocator.h deleted file mode 100644 index f8bf3a5..0000000 --- a/NvBlast/test/src/AlignedAllocator.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -* 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. -*/ - -#ifndef ALIGNEDALLOCATOR_H -#define ALIGNEDALLOCATOR_H - -#include "NvPreprocessor.h" - - -/** -Aligned allocation. First template argument has the signature of stdlib malloc. - -Example using malloc and 16-byte alignment: - -// b will lie on a 16-byte boundary and point to 50 bytes of usable memory -void* b = alignedAlloc<malloc,16>(50); -*/ -template<void*(*allocFn)(size_t), int A> -void* alignedAlloc(size_t size) -{ - NV_COMPILE_TIME_ASSERT(A > 0 && A <= 256); - unsigned char* mem = (unsigned char*)allocFn(size + A); - const unsigned char offset = (unsigned char)((uintptr_t)A - (uintptr_t)mem % A - 1); - mem += offset; - *mem++ = offset; - return mem; -}; - - -/** -Version of alignedAlloc specialized 16-byte aligned allocation. -*/ -template<void*(*allocFn)(size_t)> -void* alignedAlloc(size_t size) -{ - return alignedAlloc<allocFn, 16>(size); -} - - -/** -Aligned deallocation. First template argument has the signature of stdlib free. - -Memory freed using this function MUST have been allocated using alignedAlloc. - -Example using free: - -// Using the memory pointer b from the example above (for alignedAlloc) -alignedFree<free>(b); -*/ -template<void(*freeFn)(void*)> -void alignedFree(void* block) -{ - if (block != nullptr) - { - unsigned char* mem = (unsigned char*)block; - const unsigned char offset = *--mem; - freeFn(mem - offset); - } -}; - - -#endif // ALIGNEDALLOCATOR_H diff --git a/NvBlast/test/src/BlastBaseTest.h b/NvBlast/test/src/BlastBaseTest.h deleted file mode 100644 index 2881645..0000000 --- a/NvBlast/test/src/BlastBaseTest.h +++ /dev/null @@ -1,159 +0,0 @@ -/* -* 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. -*/ - -#ifndef BLASTBASETEST_H -#define BLASTBASETEST_H - - -#include "NvBlastTkFramework.h" - -#include "gtest/gtest.h" - -#include "NvBlast.h" - -#include "AlignedAllocator.h" - -#include "TestAssets.h" - -#include "PxErrorCallback.h" -#include "PxAllocatorCallback.h" - - -#include <ostream> - - -template<int FailLevel, int Verbosity> -class BlastBaseTest : public testing::Test, public physx::PxAllocatorCallback, public physx::PxErrorCallback -{ -public: - static void* tkAlloc(size_t size) - { - Nv::Blast::TkFramework* fw = NvBlastTkFrameworkGet(); - if (fw != nullptr) - { - return fw->getAllocatorCallback().allocate(size, nullptr, __FILE__, __LINE__); - } - else - { - return std::malloc(size); - } - } - - static void tkFree(void* mem) - { - Nv::Blast::TkFramework* fw = NvBlastTkFrameworkGet(); - if (fw != nullptr) - { - fw->getAllocatorCallback().deallocate(mem); - } - else - { - std::free(mem); - } - } - - // A zeroing alloc with the same signature as malloc - static void* alloc(size_t size) - { - return memset(alignedAlloc<tkAlloc>(size), 0, size); - } - - static void free(void* mem) - { - alignedFree<tkFree>(mem); - } - - // Message log for blast functions - static void messageLog(int type, const char* msg, const char* file, int line) - { - if (FailLevel >= type) - { - switch (type) - { - case NvBlastMessage::Error: EXPECT_TRUE(false) << "NvBlast Error message in " << file << "(" << line << "): " << msg << "\n"; break; - case NvBlastMessage::Warning: EXPECT_TRUE(false) << "NvBlast Warning message in " << file << "(" << line << "): " << msg << "\n"; break; - case NvBlastMessage::Info: EXPECT_TRUE(false) << "NvBlast Info message in " << file << "(" << line << "): " << msg << "\n"; break; - case NvBlastMessage::Debug: EXPECT_TRUE(false) << "NvBlast Debug message in " << file << "(" << line << "): " << msg << "\n"; break; - } - } - else - if (Verbosity > 0) - { - switch (type) - { - case NvBlastMessage::Error: std::cout << "NvBlast Error message in " << file << "(" << line << "): " << msg << "\n"; break; - case NvBlastMessage::Warning: std::cout << "NvBlast Warning message in " << file << "(" << line << "): " << msg << "\n"; break; - case NvBlastMessage::Info: std::cout << "NvBlast Info message in " << file << "(" << line << "): " << msg << "\n"; break; - case NvBlastMessage::Debug: std::cout << "NvBlast Debug message in " << file << "(" << line << "): " << msg << "\n"; break; - } - } - } - - // PxAllocatorCallback interface - virtual void* allocate(size_t size, const char* typeName, const char* filename, int line) override - { - NV_UNUSED(typeName); - NV_UNUSED(filename); - NV_UNUSED(line); - return alignedAlloc<std::malloc>(size); - } - - // PxAllocatorCallback interface - virtual void deallocate(void* ptr) override - { - alignedFree<std::free>(ptr); - } - - // PxErrorCallback interface - virtual void reportError(physx::PxErrorCode::Enum code, const char* message, const char* file, int line) override - { - uint32_t failMask = 0; - switch (FailLevel) - { - case NvBlastMessage::Debug: - case NvBlastMessage::Info: failMask |= physx::PxErrorCode::eDEBUG_INFO; - case NvBlastMessage::Warning: failMask |= physx::PxErrorCode::eDEBUG_WARNING; - case NvBlastMessage::Error: failMask |= physx::PxErrorCode::eABORT | physx::PxErrorCode::eABORT | physx::PxErrorCode::eINTERNAL_ERROR | physx::PxErrorCode::eOUT_OF_MEMORY | physx::PxErrorCode::eINVALID_OPERATION | physx::PxErrorCode::eINVALID_PARAMETER; - } - - if (!(failMask & code) && Verbosity <= 0) - { - return; - } - - std::string output = "NvBlast Test "; - switch (code) - { - case physx::PxErrorCode::eNO_ERROR: break; - case physx::PxErrorCode::eDEBUG_INFO: output += "Debug Info"; break; - case physx::PxErrorCode::eDEBUG_WARNING: output += "Debug Warning"; break; - case physx::PxErrorCode::eINVALID_PARAMETER: output += "Invalid Parameter"; break; - case physx::PxErrorCode::eINVALID_OPERATION: output += "Invalid Operation"; break; - case physx::PxErrorCode::eOUT_OF_MEMORY: output += "Out of Memory"; break; - case physx::PxErrorCode::eINTERNAL_ERROR: output += "Internal Error"; break; - case physx::PxErrorCode::eABORT: output += "Abort"; break; - case physx::PxErrorCode::ePERF_WARNING: output += "Perf Warning"; break; - default: FAIL(); - } - output += std::string(" message in ") + file + "(" + std::to_string(line) + "): " + message + "\n"; - - if (failMask & code) - { - EXPECT_TRUE(false) << output; - } - else - { - std::cout << output; - } - } -}; - - -#endif // #ifndef BLASTBASETEST_H diff --git a/NvBlast/test/src/TkBaseTest.h b/NvBlast/test/src/TkBaseTest.h deleted file mode 100644 index 9ea632b..0000000 --- a/NvBlast/test/src/TkBaseTest.h +++ /dev/null @@ -1,467 +0,0 @@ -/* -* 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. -*/ - -#ifndef TKBASETEST_H -#define TKBASETEST_H - - -#include "NvBlastTk.h" -#include "NvBlastTkActor.h" - -#include "BlastBaseTest.h" - -#include "NvBlastExtDamageShaders.h" - -#include "NvBlastIndexFns.h" -#include "NvBlastProfiler.h" -#include "TestProfiler.h" - -#include "PxAllocatorCallback.h" -#include "PxErrorCallback.h" -#include "PxCpuDispatcher.h" -#include "PxTask.h" -#include "PxFoundation.h" -#include "PxFoundationVersion.h" - -#include <thread> -#include <algorithm> -#include <queue> -#include <mutex> -#include <condition_variable> -#include <atomic> - - -#define USE_PHYSX_DISPATCHER 0 - -#if USE_PHYSX_DISPATCHER -#include "PxDefaultCpuDispatcher.h" -#endif - - -using namespace Nv::Blast; -using namespace physx; - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Helpers -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -NV_INLINE void ExpectArrayMatch(TkObject** arr0, size_t size0, TkObject** arr1, size_t size1) -{ - EXPECT_TRUE(size0 == size1); - std::set<TkObject*> set0(arr0, arr0 + size0); - std::set<TkObject*> set1(arr1, arr1 + size1); - EXPECT_TRUE(set0 == set1); -} - -class TestCpuDispatcher : public physx::PxCpuDispatcher -{ - struct SharedContext - { - std::queue<PxBaseTask*> workQueue; - std::condition_variable cv; - std::mutex mutex; - std::atomic<bool> quit; - }; - - void submitTask(PxBaseTask& task) override - { - if (m_threads.size() > 0) - { - std::unique_lock<std::mutex> lk(m_context.mutex); - m_context.workQueue.push(&task); - lk.unlock(); - m_context.cv.notify_one(); - } - else - { - TEST_ZONE_BEGIN(task.getName()); - task.run(); - TEST_ZONE_END(task.getName()); - task.release(); - } - } - - uint32_t getWorkerCount() const override { return (uint32_t)m_threads.size(); } - - static void execute(SharedContext& context) - { - while (!context.quit) - { - std::unique_lock<std::mutex> lk(context.mutex); - if (!context.workQueue.empty()) - { - PxBaseTask& task = *context.workQueue.front(); - context.workQueue.pop(); - lk.unlock(); - TEST_ZONE_BEGIN(task.getName()); - task.run(); - TEST_ZONE_END(task.getName()); - task.release(); - } - else - { - // shared variables must be modified under the mutex in order - // to correctly publish the modification to the waiting thread - context.cv.wait(lk, [&]{ return !context.workQueue.empty() || context.quit; }); - } - } - } - - SharedContext m_context; - std::vector<std::thread> m_threads; - -public: - TestCpuDispatcher(uint32_t numWorkers) - { - m_context.quit = false; - for (uint32_t i = 0; i < numWorkers; ++i) - { - m_threads.push_back(std::thread(execute, std::ref(m_context))); - } - } - - void release() - { - std::unique_lock<std::mutex> lk(m_context.mutex); - m_context.quit = true; - lk.unlock(); - m_context.cv.notify_all(); - for (std::thread& t : m_threads) - { - t.join(); - } - delete this; - } -}; - - -struct CSParams -{ - CSParams(uint32_t axis_, float coord_) : axis(axis_), coord(coord_) {} - uint32_t axis; - float coord; -}; - -static void CubeSlicer(NvBlastFractureBuffers* outbuf, const NvBlastGraphShaderActor* actor, const NvBlastProgramParams* params) -{ - uint32_t bondFractureCount = 0; - uint32_t bondFractureCountMax = outbuf->bondFractureCount; - - for (size_t i = 0; i < params->damageDescCount; ++i) - { - const CSParams& p = (reinterpret_cast<const CSParams*> (params->damageDescBuffer))[i]; - - uint32_t currentNodeIndex = actor->firstGraphNodeIndex; - while (!Nv::Blast::isInvalidIndex(currentNodeIndex)) - { - for (uint32_t adj = actor->adjacencyPartition[currentNodeIndex]; adj < actor->adjacencyPartition[currentNodeIndex + 1]; ++adj) - { - if (currentNodeIndex < actor->adjacentNodeIndices[adj]) - { - if (actor->assetBonds[actor->adjacentBondIndices[adj]].centroid[p.axis] == p.coord && bondFractureCount < bondFractureCountMax) - { - NvBlastBondFractureData& data = outbuf->bondFractures[bondFractureCount++]; - data.userdata = 0; - data.nodeIndex0 = currentNodeIndex; - data.nodeIndex1 = actor->adjacentNodeIndices[adj]; - data.health = 1.0f; - } - } - } - currentNodeIndex = actor->graphNodeIndexLinks[currentNodeIndex]; - } - } - - outbuf->bondFractureCount = bondFractureCount; - outbuf->chunkFractureCount = 0; - - //printf("slicer outcount %d\n", bondFractureCount); -} - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// TkBaseTest Class -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - -template<int FailLevel, int Verbosity> -class TkBaseTest : public BlastBaseTest<FailLevel, Verbosity> -{ -public: - TkBaseTest() : m_cpuDispatcher(), m_taskman(nullptr), m_foundation(nullptr) - { - } - - virtual void SetUp() override - { - m_foundation = PxCreateFoundation(PX_FOUNDATION_VERSION, *this, *this); - - NvBlastProfilerEnablePlatform(true); - -#if USE_PHYSX_DISPATCHER - PxU32 affinity[] = { 1, 2, 4, 8 }; - m_cpuDispatcher = PxDefaultCpuDispatcherCreate(4, affinity); - m_cpuDispatcher->setRunProfiled(false); -#else - m_cpuDispatcher = new TestCpuDispatcher(4); -#endif - - m_taskman = PxTaskManager::createTaskManager(*this, m_cpuDispatcher, nullptr); - } - - virtual void TearDown() override - { - m_cpuDispatcher->release(); - if (m_taskman) m_taskman->release(); - if (m_foundation) m_foundation->release(); - } - - void createFramework() - { - TkFrameworkDesc desc; - desc.allocatorCallback = this; - desc.errorCallback = this; - TkFramework* framework = NvBlastTkFrameworkCreate(desc); - EXPECT_TRUE(framework != nullptr); - EXPECT_EQ(framework, NvBlastTkFrameworkGet()); - } - - void releaseFramework() - { - TkFramework* framework = NvBlastTkFrameworkGet(); - framework->release(); - EXPECT_TRUE(NvBlastTkFrameworkGet() == nullptr); - } - - void createTestAssets(bool addInternalJoints = false) - { - const uint8_t cube1BondDescFlags_internalJoints[12] = - { - TkAssetDesc::NoFlags, - TkAssetDesc::NoFlags, - TkAssetDesc::NoFlags, - TkAssetDesc::NoFlags, - - TkAssetDesc::NoFlags, - TkAssetDesc::NoFlags, - TkAssetDesc::NoFlags, - TkAssetDesc::NoFlags, - - TkAssetDesc::BondJointed, - TkAssetDesc::BondJointed, - TkAssetDesc::BondJointed, - TkAssetDesc::BondJointed - }; - - const uint32_t assetDescCount = sizeof(g_assetDescs) / sizeof(g_assetDescs[0]); - TkFramework* framework = NvBlastTkFrameworkGet(); - for (uint32_t i = 0; i < assetDescCount; ++i) - { - TkAssetDesc desc; - reinterpret_cast<NvBlastAssetDesc&>(desc) = g_assetDescs[i]; - desc.bondFlags = addInternalJoints ? cube1BondDescFlags_internalJoints : nullptr; - testAssets.push_back(framework->createAsset(desc)); - EXPECT_TRUE(testAssets[i] != nullptr); - } - } - - TkAsset* createCubeAsset(size_t maxDepth, size_t width, int32_t supportDepth = -1, bool addInternalJoints = false) - { - TkFramework* framework = NvBlastTkFrameworkGet(); - GeneratorAsset cube; - TkAssetDesc assetDesc; - generateCube(cube, assetDesc, maxDepth, width, supportDepth); - std::vector<uint8_t> bondFlags(assetDesc.bondCount); - std::fill(bondFlags.begin(), bondFlags.end(), addInternalJoints ? 1 : 0); - assetDesc.bondFlags = bondFlags.data(); - TkAsset* cubeAsset = framework->createAsset(assetDesc); - testAssets.push_back(cubeAsset); - return cubeAsset; - } - - void releaseTestAssets() - { - for (uint32_t i = 0; i < testAssets.size(); ++i) - { - testAssets[i]->release(); - } - testAssets.clear(); - } - - NvBlastExtRadialDamageDesc getRadialDamageDesc(float x, float y, float z, float minRadius = 10.0f, float maxRadius = 10.0f, float compressive = 10.0f) - { - NvBlastExtRadialDamageDesc desc; - desc.position[0] = x; - desc.position[1] = y; - desc.position[2] = z; - - desc.minRadius = minRadius; - desc.maxRadius = maxRadius; - desc.compressive = compressive; - return desc; - } - - NvBlastExtShearDamageDesc getShearDamageDesc(float x, float y, float z, float shearX = 1.0f, float shearY = 0.0f, float shearZ = 0.0f) - { - NvBlastExtShearDamageDesc desc; - desc.position[0] = x; - desc.position[1] = y; - desc.position[2] = z; - - desc.shear[0] = shearX; - desc.shear[1] = shearY; - desc.shear[2] = shearZ; - return desc; - } - - static const NvBlastDamageProgram& getCubeSlicerProgram() - { - static NvBlastDamageProgram program = { CubeSlicer, nullptr }; - return program; - } - - static const NvBlastDamageProgram& getFalloffProgram() - { - static NvBlastDamageProgram program = { NvBlastExtFalloffGraphShader, NvBlastExtFalloffSubgraphShader }; - return program; - } - - static const NvBlastDamageProgram& getShearProgram() - { - static NvBlastDamageProgram program = { NvBlastExtShearGraphShader, NvBlastExtShearSubgraphShader }; - return program; - } - - static const NvBlastExtMaterial* getDefaultMaterial() - { - static NvBlastExtMaterial material = { - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 0.0f - }; - return &material; - }; - - TkFamily* familySerialization(TkFamily* family); - - - std::vector<TkAsset*> testAssets; - -#if USE_PHYSX_DISPATCHER - PxDefaultCpuDispatcher* m_cpuDispatcher; -#else - TestCpuDispatcher* m_cpuDispatcher; -#endif - - PxTaskManager* m_taskman; - PxFoundation* m_foundation; -}; - - -#define TkPxErrorMask (PxErrorCode::eINVALID_PARAMETER | PxErrorCode::eINVALID_OPERATION | PxErrorCode::eOUT_OF_MEMORY | PxErrorCode::eINTERNAL_ERROR | PxErrorCode::eABORT) -#define TkPxWarningMask (PxErrorCode::eDEBUG_WARNING | PxErrorCode::ePERF_WARNING) - -typedef TkBaseTest<NvBlastMessage::Error, 1> TkTestAllowWarnings; -typedef TkBaseTest<NvBlastMessage::Warning, 1> TkTestStrict; - - -class TestFamilyTracker : public TkEventListener -{ -public: - TestFamilyTracker() {} - - typedef std::pair<TkFamily*, uint32_t> Actor; - - virtual void receive(const TkEvent* events, uint32_t eventCount) override - { - TEST_ZONE_BEGIN("TestFamilyTracker"); - for (size_t i = 0; i < eventCount; ++i) - { - const TkEvent& e = events[i]; - switch (e.type) - { - case (TkEvent::Split): - { - const TkSplitEvent* splitEvent = e.getPayload<TkSplitEvent>(); - EXPECT_EQ((size_t)1, actors.erase(Actor(splitEvent->parentData.family, splitEvent->parentData.index))); - for (size_t i = 0; i < splitEvent->numChildren; ++i) - { - TkActor* a = splitEvent->children[i]; - EXPECT_TRUE(actors.insert(Actor(&a->getFamily(), a->getIndex())).second); - } - break; - } - case (TkEvent::FractureCommand): - { - const TkFractureCommands* fracEvent = e.getPayload<TkFractureCommands>(); - EXPECT_TRUE(!isInvalidIndex(fracEvent->tkActorData.index)); -#if 0 - printf("chunks broken: %d\n", fracEvent->buffers.chunkFractureCount); - printf("bonds broken: %d\n", fracEvent->buffers.bondFractureCount); - for (uint32_t t = 0; t < fracEvent->buffers.bondFractureCount; t++) - { - //printf("%x ", fracEvent->buffers.bondFractures[t].userdata); - } - //printf("\n"); -#endif - break; - } - case (TkEvent::FractureEvent): - { - const TkFractureEvents* fracEvent = e.getPayload<TkFractureEvents>(); - EXPECT_TRUE(!isInvalidIndex(fracEvent->tkActorData.index)); - break; - } - case (TkEvent::JointUpdate): - { - const TkJointUpdateEvent* jointEvent = e.getPayload<TkJointUpdateEvent>(); - TkJoint* joint = jointEvent->joint; - EXPECT_TRUE(joint != nullptr); - - switch (jointEvent->subtype) - { - case TkJointUpdateEvent::External: - EXPECT_TRUE(joints.end() == joints.find(joint)); // We should not have this joint yet - joints.insert(joint); - break; - case TkJointUpdateEvent::Changed: - break; - case TkJointUpdateEvent::Unreferenced: - EXPECT_EQ(1, joints.erase(joint)); - joint->release(); - break; - } - break; - } - default: - break; - } - } - TEST_ZONE_END("TestFamilyTracker"); - } - - void insertActor(const TkActor* actor) - { - actors.insert(TestFamilyTracker::Actor(&actor->getFamily(), actor->getIndex())); - } - - void eraseActor(const TkActor* actor) - { - actors.erase(TestFamilyTracker::Actor(&actor->getFamily(), actor->getIndex())); - } - - std::set<Actor> actors; - std::set<TkJoint*> joints; -}; - - -#endif // #ifndef TKBASETEST_H diff --git a/NvBlast/test/src/perf/BlastBasePerfTest.h b/NvBlast/test/src/perf/BlastBasePerfTest.h deleted file mode 100644 index 2a4701d..0000000 --- a/NvBlast/test/src/perf/BlastBasePerfTest.h +++ /dev/null @@ -1,374 +0,0 @@ -/* -* 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. -*/ - -#ifndef BLASTBASEPERFTEST_H -#define BLASTBASEPERFTEST_H - - -#include "BlastBaseTest.h" -#include <fstream> - -#include <algorithm> -#include <map> - - -template<typename T> -class DataCollection -{ -public: - struct Stats - { - double m_mean; - double m_sdev; - double m_min; - double m_max; - - Stats() - { - reset(); - } - - void reset() - { - m_mean = 0.0; - m_sdev = 0.0; - m_min = std::numeric_limits<double>().max(); - m_max = -std::numeric_limits<double>().max(); - } - }; - - struct DataSet - { - std::vector<T> m_data; - Stats m_stats; - - void calculateStats() - { - m_stats.reset(); - if (m_data.size() > 0) - { - if (m_data.size() > 1) // Remove top half of values to eliminate outliers - { - std::sort(m_data.begin(), m_data.end()); - m_data.resize(m_data.size() / 2); - } - for (size_t i = 0; i < m_data.size(); ++i) - { - m_stats.m_mean += m_data[i]; - m_stats.m_min = std::min(m_stats.m_min, (double)m_data[i]); - m_stats.m_max = std::max(m_stats.m_max, (double)m_data[i]); - } - m_stats.m_mean /= m_data.size(); - if (m_data.size() > 1) - { - for (size_t i = 0; i < m_data.size(); ++i) - { - m_stats.m_sdev += pow(m_data[i] - m_stats.m_mean, 2); - } - m_stats.m_sdev = sqrt(m_stats.m_sdev / (m_data.size() - 1)); - } - } - } - }; - - DataSet& getDataSet(const std::string& name) - { - auto entry = m_lookup.find(name); - if (entry != m_lookup.end()) - { - return m_dataSets[entry->second]; - } - m_lookup[name] = m_dataSets.size(); - m_dataSets.push_back(DataSet()); - return m_dataSets.back(); - } - - bool dataSetExists(const std::string& name) const - { - return m_lookup.find(name) != m_lookup.end(); - } - - void calculateStats() - { - for (size_t i = 0; i < m_dataSets.size(); ++i) - { - m_dataSets[i].calculateStats(); - } - } - - void test(DataCollection<int64_t>& calibration, double relativeThreshold = 0.10, double tickThreshold = 100.0) - { - for (auto entry = m_lookup.begin(); entry != m_lookup.end(); ++entry) - { - const std::string& name = entry->first; - DataCollection<int64_t>::DataSet& data = m_dataSets[entry->second]; - data.calculateStats(); - - if (!calibration.dataSetExists(name)) - { - FAIL() << "PerfTest is not calibrated!" << std::endl << "Missing DataSet: " << name << std::endl; - } - const DataCollection<int64_t>::DataSet& cal = calibration.getDataSet(name); - const double calMin = cal.m_stats.m_min; - - if (data.m_stats.m_min > (1.0 + relativeThreshold) * calMin && data.m_stats.m_min - calMin > tickThreshold) - { - std::cout << name << ":" << std::endl; - std::cout << "PERF - : Timing (" << data.m_stats.m_min << ") exceeds recorded min (" << calMin << ") by more than allowed relative threshold (" << relativeThreshold*100 << "%) and absolute threshold (" << tickThreshold << " ticks)." << std::endl; - EXPECT_FALSE(data.m_stats.m_min > (1.0 + relativeThreshold) * calMin && data.m_stats.m_min - calMin > tickThreshold) - << name << ":" << std::endl - << "PERF - : Timing (" << data.m_stats.m_min << ") exceeds recorded min (" << calMin << ") by more than allowed relative threshold (" << relativeThreshold * 100 << "%) and absolute threshold (" << tickThreshold << " ticks)." << std::endl; - } - else - if (data.m_stats.m_min < (1.0 - relativeThreshold) * calMin && data.m_stats.m_min - calMin < -tickThreshold) - { - std::cout << name << ":" << std::endl; - std::cout << "PERF + : Timing (" << data.m_stats.m_min << ") is less than the recorded min (" << calMin << ") by more than the relative threshold (" << relativeThreshold * 100 << "%) and absolute threshold (" << tickThreshold << " ticks)." << std::endl; - } - } - } - - size_t size() const - { - return m_dataSets.size(); - } - - void clear() - { - m_lookup.clear(); - m_dataSets.clear(); - } - - template<class S> - friend std::istream& operator >> (std::istream& stream, DataCollection<S>& c); - - template<class S> - friend std::ostream& operator << (std::ostream& stream, const DataCollection<S>& c); - -private: - std::map<std::string, size_t> m_lookup; - std::vector< DataSet > m_dataSets; -}; - -template<typename T> -std::istream& operator >> (std::istream& stream, DataCollection<T>& c) -{ - std::string name; - while (!stream.eof()) - { - std::getline(stream >> std::ws, name); - typename DataCollection<T>::DataSet& dataSet = c.getDataSet(name); - stream >> dataSet.m_stats.m_mean >> dataSet.m_stats.m_sdev >> dataSet.m_stats.m_min >> dataSet.m_stats.m_max >> std::ws; - } - return stream; -} - -template<typename T> -std::ostream& operator << (std::ostream& stream, const DataCollection<T>& c) -{ - for (auto entry = c.m_lookup.begin(); entry != c.m_lookup.end(); ++entry) - { - const std::string& name = entry->first; - stream << name.c_str() << std::endl; - const typename DataCollection<T>::DataSet& data = c.m_dataSets[entry->second]; - stream << data.m_stats.m_mean << " " << data.m_stats.m_sdev << " " << data.m_stats.m_min << " " << data.m_stats.m_max << std::endl; - } - return stream; -} - - -static const char* getPlatformSuffix() -{ -#if NV_WIN32 - return "win32"; -#elif NV_WIN64 - return "win64"; -#elif NV_XBOXONE - return "xb1"; -#elif NV_PS4 - return "ps4"; -#elif NV_LINUX - #if NV_X64 - return "linux64"; - #else - return "linux32"; - #endif -#else - return "gen"; -#endif -} - -static const char* getPlatformRoot() -{ -#if NV_PS4 - return "/app0/"; -#elif NV_XBOXONE - return "G:/"; -#else - return "../../"; -#endif -} - -static std::string defaultRelativeDataPath() -{ - const char* dataDir = "test/data/"; - - std::string rootDir = getPlatformRoot(); - return rootDir + dataDir + getPlatformSuffix() + "/"; -} - -class PerfTestEngine -{ -public: - PerfTestEngine(const char* collectionName) : m_calibrate(false) - { - m_filename = defaultRelativeDataPath() + std::string(collectionName) + "_" + getPlatformSuffix() + ".cal"; - - auto argvs = testing::internal::GetArgvs(); - size_t argCount = argvs.size(); - - for (size_t argNum = 0; argNum < argCount; ++argNum) - { - if (argvs[argNum] == "-calibrate") - { - m_calibrate = true; - } - else - if (argvs[argNum] == "-calPath") - { - if (++argNum < argCount) - { - m_filename = argvs[argNum]; - } - } - } - - if (!m_calibrate) - { - std::ifstream in; - in.open(m_filename); - if (in.is_open()) - { - std::string name; - std::getline(in, name); // Eat header - std::getline(in, name); // Eat header (2 lines) - in >> m_dataCalibration; - in.close(); - } - m_calibrate = m_dataCalibration.size() == 0; - } - - if (m_calibrate) - { - std::ofstream out; - out.open(m_filename); - if (out.is_open()) - { - out << "Format: timing name (whole line)" << std::endl << "timing mean s.d. min max" << std::endl; // Header (2 lines) - out.close(); - } - } - - if (m_calibrate) - { - std::cout << "******** Calibration Mode ********\n"; - } - else - { - std::cout << "******** Test Mode ********\n"; - std::cout << "Read calibration data from " << m_filename << std::endl; - } - } - - void endTest() - { - if (m_calibrate) - { - m_dataTempCollection.calculateStats(); - std::ofstream out; - out.open(m_filename, std::ofstream::app); - if (out.is_open()) - { - out << m_dataTempCollection; - out.close(); - std::cout << "Calibration stats written to " << m_filename << std::endl; - } - else - { - std::cout << "Failed to open calibration file " << m_filename << ". Stats not written." << std::endl; - FAIL() << "Failed to open calibration file " << m_filename << ". Stats not written." << std::endl; - } - } - else - { - m_dataTempCollection.test(m_dataCalibration); - } - m_dataTempCollection.clear(); - } - - void reportData(const std::string& name, int64_t data) - { - m_dataTempCollection.getDataSet(name).m_data.push_back(data); - } - -private: - std::string m_filename; - bool m_calibrate; - DataCollection<int64_t> m_dataTempCollection; - DataCollection<int64_t> m_dataCalibration; -}; - - -template<int FailLevel, int Verbosity> -class BlastBasePerfTest : public BlastBaseTest<FailLevel, Verbosity> -{ -public: - /** - This function allows to create/destroy and get PerfTestEngine in local static variable (works header only). - It allows to have PeftTestEngine alive through life span of gtest TestCase. - */ - static PerfTestEngine* getEngineDeadOrAlive(bool alive = true) - { - static PerfTestEngine* engine = nullptr; - if (alive && !engine) - { - engine = new PerfTestEngine(::testing::UnitTest::GetInstance()->current_test_case()->name()); - } - else if (!alive && engine) - { - delete engine; - engine = nullptr; - } - return engine; - } - - static void SetUpTestCase() - { - getEngineDeadOrAlive(); - } - - static void TearDownTestCase() - { - getEngineDeadOrAlive(false); - } - - void TearDown() override - { - getEngineDeadOrAlive()->endTest(); - } - - void reportData(const std::string& name, int64_t data) - { - getEngineDeadOrAlive()->reportData(name, data); - } -}; - - -#endif // #ifndef BLASTBASEPERFTEST_H diff --git a/NvBlast/test/src/perf/SolverPerfTests.cpp b/NvBlast/test/src/perf/SolverPerfTests.cpp deleted file mode 100644 index 8a53c97..0000000 --- a/NvBlast/test/src/perf/SolverPerfTests.cpp +++ /dev/null @@ -1,211 +0,0 @@ -#include "BlastBasePerfTest.h" -#include "TestAssets.h" -#include "NvBlastExtDamageShaders.h" -#include <memory> - - -static void blast -( - std::set<NvBlastActor*>& actorsToDamage, - GeneratorAsset* testAsset, - GeneratorAsset::Vec3 localPos, - float minRadius, float maxRadius, - float compressiveDamage, - NvBlastTimers& timers -) -{ - std::vector<NvBlastChunkFractureData> chunkEvents; /* num lower-support chunks + bonds */ - std::vector<NvBlastBondFractureData> bondEvents; /* num lower-support chunks + bonds */ - chunkEvents.resize(testAsset->solverChunks.size()); - bondEvents.resize(testAsset->solverBonds.size()); - - NvBlastExtRadialDamageDesc damage[] = { - { - compressiveDamage, - { localPos.x, localPos.y, localPos.z }, - minRadius, - maxRadius - } - }; - - NvBlastProgramParams programParams = - { - &damage, - 1, - nullptr - }; - - NvBlastDamageProgram program = { - NvBlastExtFalloffGraphShader, - nullptr - }; - - std::vector<char> splitScratch; - std::vector<NvBlastActor*> newActors(testAsset->solverChunks.size()); - - size_t totalNewActorsCount = 0; - for (std::set<NvBlastActor*>::iterator k = actorsToDamage.begin(); k != actorsToDamage.end();) - { - NvBlastActor* actor = *k; - - NvBlastFractureBuffers events = { (uint32_t)bondEvents.size(), (uint32_t)chunkEvents.size(), bondEvents.data(), chunkEvents.data() }; - - NvBlastActorGenerateFracture(&events, actor, program, &programParams, nullptr, &timers); - NvBlastActorApplyFracture(&events, actor, &events, nullptr, &timers); - - bool removeActor = false; - - if (events.bondFractureCount + events.chunkFractureCount > 0) - { - splitScratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, nullptr)); - NvBlastActorSplitEvent result; - result.deletedActor = nullptr; - result.newActors = &newActors[totalNewActorsCount]; - const size_t bufferSize = newActors.size() - totalNewActorsCount; - const size_t newActorsCount = NvBlastActorSplit(&result, actor, (uint32_t)bufferSize, splitScratch.data(), nullptr, &timers); - totalNewActorsCount += newActorsCount; - removeActor = newActorsCount > 0; - } - - if (removeActor) - { - k = actorsToDamage.erase(k); - } - else - { - ++k; - } - } - - for (size_t i = 0; i < totalNewActorsCount; ++i) - { - actorsToDamage.insert(newActors[i]); - } -} - -typedef BlastBasePerfTest<NvBlastMessage::Warning, 1> BlastBasePerfTestStrict; - -class PerfTest : public BlastBasePerfTestStrict -{ -public: - void damageLeafSupportActors(const char* testName, uint32_t assetCount, uint32_t familyCount, uint32_t damageCount) - { - const float relativeDamageRadius = 0.2f; - const float compressiveDamage = 1.0f; - const uint32_t minChunkCount = 100; - const uint32_t maxChunkCount = 10000; - - srand(0); - - for (uint32_t assetNum = 0; assetNum < assetCount; ++assetNum) - { - CubeAssetGenerator::Settings settings; - settings.extents = GeneratorAsset::Vec3(1, 1, 1); - CubeAssetGenerator::DepthInfo depthInfo; - depthInfo.slicesPerAxis = GeneratorAsset::Vec3(1, 1, 1); - depthInfo.flag = NvBlastChunkDesc::Flags::NoFlags; - settings.depths.push_back(depthInfo); - uint32_t chunkCount = 1; - while (chunkCount < minChunkCount) - { - uint32_t chunkMul; - do - { - depthInfo.slicesPerAxis = GeneratorAsset::Vec3((float)(1 + rand() % 4), (float)(1 + rand() % 4), (float)(1 + rand() % 4)); - chunkMul = (uint32_t)(depthInfo.slicesPerAxis.x * depthInfo.slicesPerAxis.y * depthInfo.slicesPerAxis.z); - } while (chunkMul == 1); - if (chunkCount*chunkMul > maxChunkCount) - { - break; - } - chunkCount *= chunkMul; - settings.depths.push_back(depthInfo); - settings.extents = settings.extents * depthInfo.slicesPerAxis; - } - settings.depths.back().flag = NvBlastChunkDesc::SupportFlag; // Leaves are support - - // Make largest direction unit size - settings.extents = settings.extents * (1.0f / std::max(settings.extents.x, std::max(settings.extents.y, settings.extents.z))); - - // Create asset - GeneratorAsset testAsset; - CubeAssetGenerator::generate(testAsset, settings); - - NvBlastAssetDesc desc; - desc.chunkDescs = &testAsset.solverChunks[0]; - desc.chunkCount = (uint32_t)testAsset.solverChunks.size(); - desc.bondDescs = &testAsset.solverBonds[0]; - desc.bondCount = (uint32_t)testAsset.solverBonds.size(); - - { - std::vector<char> scratch; - scratch.resize((size_t)NvBlastGetRequiredScratchForCreateAsset(&desc, messageLog)); - void* mem = alloc(NvBlastGetAssetMemorySize(&desc, messageLog)); - NvBlastAsset* asset = NvBlastCreateAsset(mem, &desc, &scratch[0], messageLog); - EXPECT_TRUE(asset != nullptr); - - // Generate familes - for (uint32_t familyNum = 0; familyNum < familyCount; ++familyNum) - { - // create actor - NvBlastActorDesc actorDesc; - actorDesc.initialBondHealths = nullptr; - actorDesc.uniformInitialBondHealth = 1.0f; - actorDesc.initialSupportChunkHealths = nullptr; - actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f; - void* mem = alloc(NvBlastAssetGetFamilyMemorySize(asset, messageLog)); - NvBlastFamily* family = NvBlastAssetCreateFamily(mem, asset, messageLog); - scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, messageLog)); - EXPECT_TRUE(family != nullptr); - NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, &scratch[0], messageLog); - EXPECT_TRUE(actor != nullptr); - - // Generate damage - std::set<NvBlastActor*> actors; - actors.insert(actor); - for (uint32_t damageNum = 0; damageNum < damageCount; ++damageNum) - { - GeneratorAsset::Vec3 localPos = settings.extents*GeneratorAsset::Vec3((float)rand() / RAND_MAX - 0.5f, (float)rand() / RAND_MAX - 0.5f, (float)rand() / RAND_MAX - 0.5f); - - NvBlastTimers timers; - NvBlastTimersReset(&timers); - blast(actors, &testAsset, localPos, relativeDamageRadius, relativeDamageRadius*1.2f, compressiveDamage, timers); - const std::string timingName = std::string(testName) + " asset " + std::to_string(assetNum) + " family " + std::to_string(familyNum) + " damage " + std::to_string(damageNum); - BlastBasePerfTestStrict::reportData(timingName + " material", timers.material); - BlastBasePerfTestStrict::reportData(timingName + " fracture", timers.fracture); - BlastBasePerfTestStrict::reportData(timingName + " island", timers.island); - BlastBasePerfTestStrict::reportData(timingName + " partition", timers.partition); - BlastBasePerfTestStrict::reportData(timingName + " visibility", timers.visibility); - } - - // Release remaining actors - std::for_each(actors.begin(), actors.end(), [](NvBlastActor* a){ NvBlastActorDeactivate(a, messageLog); }); - actors.clear(); - - free(family); - } - - // Release asset data - free(asset); - } - } - } -}; - - -// Tests -TEST_F(PerfTest, DamageLeafSupportActorsTestVisibility) -{ - const int trialCount = 1000; - std::cout << "Trial (of " << trialCount << "): "; - for (int trial = 1; trial <= trialCount; ++trial) - { - if (trial % 100 == 0) - { - std::cout << trial << ".. "; - std::cout.flush(); - } - damageLeafSupportActors(test_info_->name(), 4, 4, 5); - } - std::cout << "done." << std::endl; -} diff --git a/NvBlast/test/src/unit/APITests.cpp b/NvBlast/test/src/unit/APITests.cpp deleted file mode 100644 index c2a4a04..0000000 --- a/NvBlast/test/src/unit/APITests.cpp +++ /dev/null @@ -1,1354 +0,0 @@ -#include "BlastBaseTest.h" -#include "NvBlastIndexFns.h" -#include "NvBlastExtDamageShaders.h" - -#include <algorithm> - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Utils / Tests Common -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -using namespace Nv::Blast; - -class APITest : public BlastBaseTest < NvBlastMessage::Error, 1 > -{ -}; - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Tests -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -TEST_F(APITest, Basic) -{ - // create asset - const NvBlastAssetDesc& assetDesc = g_assetDescs[0]; - - std::vector<char> scratch((size_t)NvBlastGetRequiredScratchForCreateAsset(&assetDesc, messageLog)); - void* amem = alloc(NvBlastGetAssetMemorySize(&assetDesc, messageLog)); - NvBlastAsset* asset = NvBlastCreateAsset(amem, &assetDesc, scratch.data(), messageLog); - EXPECT_TRUE(asset != nullptr); - - // create actor - NvBlastActorDesc actorDesc; - actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr; - actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f; - void* fmem = alloc(NvBlastAssetGetFamilyMemorySize(asset, messageLog)); - NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, messageLog); - scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, messageLog)); - NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, scratch.data(), messageLog); - EXPECT_TRUE(actor != nullptr); - - NvBlastExtRadialDamageDesc damage[] = { - { - 10.0f, // compressive - { 0.0f, 0.0f, 0.0f }, // position - 4.0f, // min radius - maximum damage - 6.0f // max radius - zero damage - } // linear falloff - }; - - NvBlastBondFractureData outFracture[12]; /*num lower-support chunks + bonds?*/ - - NvBlastFractureBuffers events; - events.bondFractureCount = 12; - events.bondFractures = outFracture; - events.chunkFractureCount = 0; - events.chunkFractures = nullptr; - - NvBlastProgramParams programParams; - programParams.damageDescCount = 1; - programParams.damageDescBuffer = &damage; - - NvBlastDamageProgram program = { - NvBlastExtFalloffGraphShader, - nullptr - }; - - NvBlastActorGenerateFracture(&events, actor, program, &programParams, messageLog, nullptr); - NvBlastActorApplyFracture(&events, actor, &events, messageLog, nullptr); - EXPECT_EQ(12, events.bondFractureCount); - - NvBlastActor* newActors[8]; /* num lower-support chunks? plus space for deletedActor */ - NvBlastActorSplitEvent result; - result.deletedActor = nullptr; - result.newActors = newActors; - scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, messageLog)); - size_t newActorsCount = NvBlastActorSplit(&result, actor, 8, scratch.data(), messageLog, nullptr); - EXPECT_EQ(8, newActorsCount); - EXPECT_EQ(true, result.deletedActor == actor); - - for (uint32_t i = 0; i < newActorsCount; ++i) - { - const bool actorReleaseResult = NvBlastActorDeactivate(result.newActors[i], messageLog); - EXPECT_TRUE(actorReleaseResult); - } - free(family); - free(asset); -} - -TEST_F(APITest, DamageBondsCompressive) -{ - const size_t bondsCount = 6; - - const NvBlastChunkDesc c_chunks[8] = - { - // centroid volume parent idx flags ID - { {0.0f, 0.0f, 0.0f}, 0.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 0 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 1 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 2 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 3 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 4 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 5 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 6 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 7 } - }; - - const NvBlastBondDesc c_bonds[bondsCount] = - { - { { 1, 2 }, { { -1.0f, 0.0f, 0.0f }, 1.0f, { 1.0f, 2.0f, 0.0f }, 0 } }, - { { 2, 3 }, { { -1.0f, 0.0f, 0.0f }, 1.0f, { -1.0f, 2.0f, 0.0f }, 0 } }, - { { 3, 4 }, { { 0.0f, -1.0f, 0.0f }, 1.0f, { -2.0f, 1.0f, 0.0f }, 0 } }, - { { 4, 5 }, { { 0.0f, -1.0f, 0.0f }, 1.0f, { -2.0f, -1.0f, 0.0f }, 0 } }, - { { 5, 6 }, { { 1.0f, 0.0f, 0.0f }, 1.0f, { -1.0f, -2.0f, 0.0f }, 0 } }, - { { 6, 7 }, { { 1.0f, 0.0f, 0.0f }, 1.0f, { 1.0f, -2.0f, 0.0f }, 0 } } - }; - - // create asset - const NvBlastAssetDesc assetDesc = { 8, c_chunks, bondsCount, c_bonds }; - - std::vector<char> scratch((size_t)NvBlastGetRequiredScratchForCreateAsset(&assetDesc, messageLog)); - void* amem = alloc(NvBlastGetAssetMemorySize(&assetDesc, messageLog)); - NvBlastAsset* asset = NvBlastCreateAsset(amem, &assetDesc, scratch.data(), messageLog); - EXPECT_TRUE(asset != nullptr); - - // create actor - NvBlastActorDesc actorDesc; - actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr; - actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f; - void* fmem = alloc(NvBlastAssetGetFamilyMemorySize(asset, messageLog)); - NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, messageLog); - scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, messageLog)); - NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, scratch.data(), messageLog); - EXPECT_TRUE(actor != nullptr); - - // get graph nodes check - std::vector<uint32_t> graphNodeIndices; - graphNodeIndices.resize(NvBlastActorGetGraphNodeCount(actor, nullptr)); - uint32_t graphNodesCount = NvBlastActorGetGraphNodeIndices(graphNodeIndices.data(), (uint32_t)graphNodeIndices.size(), actor, nullptr); - EXPECT_EQ(graphNodesCount, 7); - - NvBlastExtRadialDamageDesc damage = { - 1.0f, // compressive - { 4.0f, 2.0f, 0.0f }, // position - 4.0f, // min radius - maximum damage - 6.0f // max radius - zero damage - }; // linear falloff - - NvBlastBondFractureData outCommands[bondsCount] = { - { UINT32_MAX, UINT32_MAX, UINT32_MAX, 0 }, - { UINT32_MAX, UINT32_MAX, UINT32_MAX, 0 }, - { UINT32_MAX, UINT32_MAX, UINT32_MAX, 0 }, - { UINT32_MAX, UINT32_MAX, UINT32_MAX, 0 }, - { UINT32_MAX, UINT32_MAX, UINT32_MAX, 0 }, - { UINT32_MAX, UINT32_MAX, UINT32_MAX, 0 }, - }; - - NvBlastFractureBuffers commands = { - 6, 0, outCommands, nullptr - }; - - NvBlastProgramParams programParams; - programParams.damageDescCount = 1; - programParams.damageDescBuffer = &damage; - - NvBlastDamageProgram program = { - NvBlastExtFalloffGraphShader, - nullptr - }; - - NvBlastActorGenerateFracture(&commands, actor, program, &programParams, messageLog, nullptr); - - ASSERT_EQ(3, commands.bondFractureCount); - ASSERT_EQ(0, commands.chunkFractureCount); - - // node indices in _graph_ chunks - NvBlastBondFractureData expectedCommand[] = { - { 0, 0, 1, 1.0f }, - { 0, 1, 2, 0.5f }, - { 0, 5, 6, 0.5f } - }; - - for (int i = 0; i < 3; i++) - { - EXPECT_EQ(expectedCommand[i].nodeIndex0, outCommands[i].nodeIndex0); - EXPECT_EQ(expectedCommand[i].nodeIndex1, outCommands[i].nodeIndex1); - EXPECT_EQ(expectedCommand[i].health, outCommands[i].health); - } - - const bool actorReleaseResult = NvBlastActorDeactivate(actor, messageLog); - EXPECT_TRUE(actorReleaseResult); - free(family); - free(asset); -} - -TEST_F(APITest, DirectFractureKillsChunk) -{ - // 1--2 - // | | - // 3--4 <-- kill 4 - - const NvBlastChunkDesc c_chunks[9] = - { - // centroid volume parent idx flags ID - { {0.0f, 0.0f, 0.0f}, 0.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 0 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 1 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 2 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 3 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 4 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 4, NvBlastChunkDesc::NoFlags, 5 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 4, NvBlastChunkDesc::NoFlags, 6 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 4, NvBlastChunkDesc::NoFlags, 7 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 4, NvBlastChunkDesc::NoFlags, 8 }, - }; - - const NvBlastBondDesc c_bonds[4] = - { - { { 1, 2 }, { { 1.0f, 0.0f, 0.0f }, 1.0f, { 0.0f, +1.0f, 0.0f }, 0 } }, - { { 3, 4 }, { { 1.0f, 0.0f, 0.0f }, 1.0f, { 0.0f, -1.0f, 0.0f }, 0 } }, - { { 1, 3 }, { { 0.0f, -1.0f, 0.0f }, 1.0f, { -1.0f, 0.0f, 0.0f }, 0 } }, - { { 2, 4 }, { { 0.0f, -1.0f, 0.0f }, 1.0f, { +1.0f, 0.0f, 0.0f }, 0 } }, - }; - - NvBlastAssetDesc assetDesc; - assetDesc.chunkCount = 9; - assetDesc.chunkDescs = c_chunks; - assetDesc.bondCount = 4; - assetDesc.bondDescs = c_bonds; - - // create asset - std::vector<char> scratch((size_t)NvBlastGetRequiredScratchForCreateAsset(&assetDesc, messageLog)); - void* amem = alloc(NvBlastGetAssetMemorySize(&assetDesc, messageLog)); - NvBlastAsset* asset = NvBlastCreateAsset(amem, &assetDesc, scratch.data(), messageLog); - EXPECT_TRUE(asset != nullptr); - - // create actor - NvBlastActorDesc actorDesc; - actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr; - actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f; - void* fmem = alloc(NvBlastAssetGetFamilyMemorySize(asset, messageLog)); - NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, messageLog); - scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, messageLog)); - NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, scratch.data(), messageLog); - EXPECT_TRUE(actor != nullptr); - - NvBlastChunkFractureData fractureCmd; - fractureCmd.chunkIndex = 4; - fractureCmd.health = 1.0f; - - NvBlastFractureBuffers commands = { 0, 1, nullptr, &fractureCmd }; - - NvBlastChunkFractureData fractureEvt; - NvBlastFractureBuffers events = { 0, 1, nullptr, &fractureEvt }; - - NvBlastActorApplyFracture(&events, actor, &commands, messageLog, nullptr); - EXPECT_EQ(1, events.chunkFractureCount); - - scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, messageLog)); - std::vector<NvBlastActor*> newActors(NvBlastActorGetMaxActorCountForSplit(actor, messageLog)); - NvBlastActorSplitEvent result; - result.deletedActor = nullptr; - result.newActors = newActors.data(); - size_t newActorsCount = NvBlastActorSplit(&result, actor, static_cast<uint32_t>(newActors.size()), scratch.data(), messageLog, nullptr); - newActors.resize(newActorsCount); - - EXPECT_EQ(5, newActorsCount); - EXPECT_EQ(actor, result.deletedActor); - // check newActors contain original actor - EXPECT_TRUE(std::any_of(newActors.begin(), newActors.end(), [&](const NvBlastActor* a) { return actor == a; })); - - for (uint32_t i = 0; i < newActorsCount; ++i) - { - const bool actorReleaseResult = NvBlastActorDeactivate(result.newActors[i], messageLog); - EXPECT_TRUE(actorReleaseResult); - } - free(family); - free(asset); -} - -TEST_F(APITest, DirectFractureKillsIslandRootChunk) -{ - // 1--2 <-- kill 1 - // | | - // 3--4 - - const NvBlastChunkDesc c_chunks[9] = - { - // centroid volume parent idx flags ID - { {0.0f, 0.0f, 0.0f}, 0.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 0 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 1 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 2 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 3 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 4 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 1, NvBlastChunkDesc::NoFlags, 5 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 1, NvBlastChunkDesc::NoFlags, 6 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 1, NvBlastChunkDesc::NoFlags, 7 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 1, NvBlastChunkDesc::NoFlags, 8 }, - }; - - const NvBlastBondDesc c_bonds[4] = - { - { { 1, 2 }, { { 1.0f, 0.0f, 0.0f }, 1.0f, { 0.0f, +1.0f, 0.0f }, 0 } }, - { { 3, 4 }, { { 1.0f, 0.0f, 0.0f }, 1.0f, { 0.0f, -1.0f, 0.0f }, 0 } }, - { { 1, 3 }, { { 0.0f, -1.0f, 0.0f }, 1.0f, { -1.0f, 0.0f, 0.0f }, 0 } }, - { { 2, 4 }, { { 0.0f, -1.0f, 0.0f }, 1.0f, { +1.0f, 0.0f, 0.0f }, 0 } }, - }; - - NvBlastAssetDesc assetDesc; - assetDesc.chunkCount = 9; - assetDesc.chunkDescs = c_chunks; - assetDesc.bondCount = 4; - assetDesc.bondDescs = c_bonds; - - // create asset - std::vector<char> scratch((size_t)NvBlastGetRequiredScratchForCreateAsset(&assetDesc, messageLog)); - void* amem = alloc(NvBlastGetAssetMemorySize(&assetDesc, messageLog)); - NvBlastAsset* asset = NvBlastCreateAsset(amem, &assetDesc, scratch.data(), messageLog); - EXPECT_TRUE(asset != nullptr); - - // create actor - NvBlastActorDesc actorDesc; - actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr; - actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f; - void* fmem = alloc(NvBlastAssetGetFamilyMemorySize(asset, messageLog)); - NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, messageLog); - scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, messageLog)); - NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, scratch.data(), messageLog); - EXPECT_TRUE(actor != nullptr); - - NvBlastChunkFractureData fractureCmd; - fractureCmd.chunkIndex = 1; - fractureCmd.health = 1.0f; - - NvBlastFractureBuffers commands = { 0, 1, nullptr, &fractureCmd }; - - NvBlastChunkFractureData fractureEvt; - NvBlastFractureBuffers events = { 0, 1, nullptr, &fractureEvt }; - - NvBlastActorApplyFracture(&events, actor, &commands, messageLog, nullptr); - EXPECT_EQ(1, events.chunkFractureCount); - - scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, messageLog)); - std::vector<NvBlastActor*> newActors(NvBlastActorGetMaxActorCountForSplit(actor, messageLog)); - NvBlastActorSplitEvent result; - result.deletedActor = nullptr; - result.newActors = newActors.data(); - size_t newActorsCount = NvBlastActorSplit(&result, actor, static_cast<uint32_t>(newActors.size()), scratch.data(), messageLog, nullptr); - newActors.resize(newActorsCount); - - EXPECT_EQ(5, newActorsCount); - EXPECT_EQ(actor, result.deletedActor); - // check if newActors don't contain original actor - EXPECT_TRUE(!std::any_of(newActors.begin(), newActors.end(), [&](const NvBlastActor* a) { return actor == a; })); - - for (uint32_t i = 0; i < newActorsCount; ++i) - { - const bool actorReleaseResult = NvBlastActorDeactivate(result.newActors[i], messageLog); - EXPECT_TRUE(actorReleaseResult); - } - free(family); - free(asset); -} - -TEST_F(APITest, SubsupportFracture) -{ - const NvBlastAssetDesc& assetDesc = g_assetDescs[1]; // cube with subsupport - - // create asset with chunk map - std::vector<char> scratch((size_t)NvBlastGetRequiredScratchForCreateAsset(&assetDesc, messageLog)); - void* amem = alloc(NvBlastGetAssetMemorySize(&assetDesc, messageLog)); - NvBlastAsset* asset = NvBlastCreateAsset(amem, &assetDesc, scratch.data(), messageLog); - EXPECT_TRUE(asset != nullptr); - - // create actor - NvBlastActorDesc actorDesc; - actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr; - actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f; - void* fmem = alloc(NvBlastAssetGetFamilyMemorySize(asset, messageLog)); - NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, messageLog); - scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, messageLog)); - NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, scratch.data(), messageLog); - EXPECT_TRUE(actor != nullptr); - - // first set of fracture commands - NvBlastChunkFractureData f1 = { 0, 1, 2.0f }; - NvBlastChunkFractureData f3 = { 0, 3, 0.5f }; - NvBlastChunkFractureData f5 = { 0, 5, 1.0f }; - NvBlastChunkFractureData f7 = { 0, 7, 1.0f }; - - std::vector<NvBlastChunkFractureData> chunkFractureData; - chunkFractureData.reserve(assetDesc.chunkCount); - chunkFractureData.push_back(f1); - chunkFractureData.push_back(f3); - chunkFractureData.push_back(f5); - chunkFractureData.push_back(f7); - ASSERT_EQ(assetDesc.chunkCount, chunkFractureData.capacity()); - ASSERT_EQ(4, chunkFractureData.size()); - - NvBlastFractureBuffers target = { 0, static_cast<uint32_t>(chunkFractureData.capacity()), nullptr, chunkFractureData.data() }; - { - NvBlastFractureBuffers events = target; - NvBlastFractureBuffers commands = { 0, static_cast<uint32_t>(chunkFractureData.size()), nullptr, chunkFractureData.data() }; - NvBlastActorApplyFracture(&events, actor, &commands, messageLog, nullptr); - ASSERT_EQ(4 + 8, events.chunkFractureCount); // all requested chunks take damage, and the children of one of them - } - - // re-apply same set of commands - chunkFractureData.clear(); - chunkFractureData.reserve(assetDesc.chunkCount); - chunkFractureData.push_back(f1); - chunkFractureData.push_back(f3); - chunkFractureData.push_back(f5); - chunkFractureData.push_back(f7); - ASSERT_EQ(assetDesc.chunkCount, chunkFractureData.capacity()); - ASSERT_EQ(4, chunkFractureData.size()); - - { - NvBlastFractureBuffers events = target; - NvBlastFractureBuffers commands = { 0, static_cast<uint32_t>(chunkFractureData.size()), nullptr, chunkFractureData.data() }; - NvBlastActorApplyFracture(&events, actor, &commands, messageLog, nullptr); - ASSERT_EQ(1, events.chunkFractureCount); // f3 has broken the chunk - } - - // fracture all support chunks - // the chunks from the previous fractures must not be reported again (since they are all broken already) - NvBlastChunkFractureData f2 = { 0, 2, 2.0f }; // will damage chunk and children - NvBlastChunkFractureData f4 = { 0, 4, 0.5f }; // will damage chunk without creating children on split - NvBlastChunkFractureData f6 = { 0, 6, 2.0f }; // will damage chunk and children - NvBlastChunkFractureData f8 = { 0, 8, 1.0f }; // will damage chunk - - chunkFractureData.clear(); - chunkFractureData.reserve(assetDesc.chunkCount); - chunkFractureData.push_back(f1); - chunkFractureData.push_back(f2); - chunkFractureData.push_back(f3); - chunkFractureData.push_back(f4); - chunkFractureData.push_back(f5); - chunkFractureData.push_back(f6); - chunkFractureData.push_back(f7); - chunkFractureData.push_back(f8); - ASSERT_EQ(assetDesc.chunkCount, chunkFractureData.capacity()); - ASSERT_EQ(8, chunkFractureData.size()); - - NvBlastFractureBuffers events = target; - { - NvBlastFractureBuffers commands = { 0, static_cast<uint32_t>(chunkFractureData.size()), nullptr, chunkFractureData.data() }; - NvBlastActorApplyFracture(&events, actor, &commands, messageLog, nullptr); - ASSERT_EQ(4 + 8 + 8, events.chunkFractureCount); // the new fracture commands all apply, plus two of them damage their children too - } - - for (size_t i = 0; i < events.chunkFractureCount; i++) - { - const uint32_t chunkIndex = events.chunkFractures[i].chunkIndex; - - ASSERT_TRUE(chunkIndex != 1); - ASSERT_TRUE(chunkIndex != 3); - ASSERT_TRUE(chunkIndex != 5); - ASSERT_TRUE(chunkIndex != 7); - - // literal values come from g_cube2ChunkDescs - bool isInSupportRange = chunkIndex <= 8 && chunkIndex >= 1; - bool isChildOfTwo = chunkIndex <= 24 && chunkIndex >= 17; - bool isChildOfSix = chunkIndex <= 56 && chunkIndex >= 49; - - ASSERT_TRUE(isInSupportRange || isChildOfTwo || isChildOfSix); - } - - scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, messageLog)); - std::vector<NvBlastActor*> newActors(NvBlastActorGetMaxActorCountForSplit(actor, messageLog)); - NvBlastActorSplitEvent result; - result.deletedActor = nullptr; - result.newActors = newActors.data(); - size_t newActorsCount = NvBlastActorSplit(&result, actor, static_cast<uint32_t>(newActors.size()), scratch.data(), messageLog, nullptr); - newActors.resize(newActorsCount); - - EXPECT_EQ(64 - 8 + 1, newActorsCount); - for (uint32_t i = 0; i < newActorsCount; ++i) - { - const bool actorReleaseResult = NvBlastActorDeactivate(result.newActors[i], messageLog); - EXPECT_TRUE(actorReleaseResult); - } - free(family); - free(asset); -} - -static bool hasWarned = false; -static void myLog(int type, const char* msg, const char* file, int line) -{ - BlastBaseTest<-1, 0>::messageLog(type, msg, file, line); - hasWarned = true; -} -#define EXPECT_WARNING EXPECT_TRUE(hasWarned); hasWarned=false; -#define EXPECT_NO_WARNING EXPECT_FALSE(hasWarned); hasWarned=false; - -TEST_F(APITest, FractureNoEvents) -{ - static const uint32_t GUARD = 0xb1a57; - - const uint32_t chunksCount = 17; - const NvBlastChunkDesc c_chunks[chunksCount] = - { - // centroid volume parent idx flags ID - { {0.0f, 0.0f, 0.0f}, 0.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 0 }, - - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 1 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 2 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 3 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 4 }, - - { {0.0f, 0.0f, 0.0f}, 0.0f, 1, NvBlastChunkDesc::NoFlags, 5 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 1, NvBlastChunkDesc::NoFlags, 6 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 2, NvBlastChunkDesc::NoFlags, 7 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 2, NvBlastChunkDesc::NoFlags, 8 }, - - { {0.0f, 0.0f, 0.0f}, 0.0f, 5, NvBlastChunkDesc::NoFlags, 9 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 5, NvBlastChunkDesc::NoFlags, 10 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 6, NvBlastChunkDesc::NoFlags, 11 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 6, NvBlastChunkDesc::NoFlags, 12 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 7, NvBlastChunkDesc::NoFlags, 13 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 7, NvBlastChunkDesc::NoFlags, 14 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 8, NvBlastChunkDesc::NoFlags, 15 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 8, NvBlastChunkDesc::NoFlags, 16 }, - }; - - const NvBlastBondDesc c_bonds[3] = - { - // chunks, normal, area, centroid, userdata - { { 1, 2 }, { { 1.0f, 0.0f, 0.0f }, 1.0f, { 1.0f, 0.0f, 0.0f }, 0 } }, - { { 2, 3 }, { { 1.0f, 0.0f, 0.0f }, 1.0f, { 2.0f, 0.0f, 0.0f }, 0 } }, - { { 3, 4 }, { { 1.0f, 0.0f, 0.0f }, 1.0f, { 3.0f, 0.0f, 0.0f }, 0 } }, - }; - - NvBlastAssetDesc assetDesc = { chunksCount, c_chunks, 3, c_bonds }; - - // create asset with chunk map - std::vector<char> scratch((size_t)NvBlastGetRequiredScratchForCreateAsset(&assetDesc, myLog)); - void* amem = alloc(NvBlastGetAssetMemorySize(&assetDesc, myLog)); - NvBlastAsset* asset = NvBlastCreateAsset(amem, &assetDesc, scratch.data(), myLog); - EXPECT_TRUE(asset != nullptr); - - // create actor - NvBlastActorDesc actorDesc; - actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr; - actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f; - void* fmem = alloc(NvBlastAssetGetFamilyMemorySize(asset, myLog)); - NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, myLog); - scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, myLog)); - NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, scratch.data(), myLog); - EXPECT_TRUE(actor != nullptr); - - std::vector<NvBlastChunkFractureData> cfData; - cfData.resize(0 + 1); - cfData[cfData.size() - 1].userdata = GUARD; - std::vector<NvBlastBondFractureData> bfData; - - NvBlastChunkFractureData command[] = - { - { 0, 1, 10.0f }, - { 0, 2, 10.0f }, - }; - - NvBlastFractureBuffers commands = { 0, 2, nullptr, command }; - NvBlastActorApplyFracture(nullptr, actor, &commands, myLog, nullptr); - - EXPECT_NO_WARNING; // events can be null - EXPECT_EQ(GUARD, cfData[cfData.size() - 1].userdata); - - scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, myLog)); - std::vector<NvBlastActor*> newActors(NvBlastActorGetMaxActorCountForSplit(actor, myLog)); - NvBlastActorSplitEvent result; - result.deletedActor = nullptr; - result.newActors = newActors.data(); - size_t newActorsCount = NvBlastActorSplit(&result, actor, static_cast<uint32_t>(newActors.size()), scratch.data(), myLog, nullptr); - newActors.resize(newActorsCount); - - EXPECT_EQ(9, newActorsCount); - for (uint32_t i = 0; i < newActorsCount; ++i) - { - const bool actorReleaseResult = NvBlastActorDeactivate(result.newActors[i], myLog); - EXPECT_TRUE(actorReleaseResult); - } - - free(family); - free(asset); - - EXPECT_NO_WARNING; -} - -TEST_F(APITest, FractureBufferLimits) -{ - static const uint32_t GUARD = 0xb1a57; - - const uint32_t chunksCount = 17; - const NvBlastChunkDesc c_chunks[chunksCount] = - { - // centroid volume parent idx flags ID - { {0.0f, 0.0f, 0.0f}, 0.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 0 }, - - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 1 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 2 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 3 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 4 }, - - { {0.0f, 0.0f, 0.0f}, 0.0f, 1, NvBlastChunkDesc::NoFlags, 5 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 1, NvBlastChunkDesc::NoFlags, 6 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 2, NvBlastChunkDesc::NoFlags, 7 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 2, NvBlastChunkDesc::NoFlags, 8 }, - - { {0.0f, 0.0f, 0.0f}, 0.0f, 5, NvBlastChunkDesc::NoFlags, 9 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 5, NvBlastChunkDesc::NoFlags, 10 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 6, NvBlastChunkDesc::NoFlags, 11 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 6, NvBlastChunkDesc::NoFlags, 12 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 7, NvBlastChunkDesc::NoFlags, 13 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 7, NvBlastChunkDesc::NoFlags, 14 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 8, NvBlastChunkDesc::NoFlags, 15 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 8, NvBlastChunkDesc::NoFlags, 16 }, - }; - - const NvBlastBondDesc c_bonds[3] = - { - // chunks, normal, area, centroid, userdata - { { 1, 2 }, { { 1.0f, 0.0f, 0.0f }, 1.0f, { 1.0f, 0.0f, 0.0f }, 0 } }, - { { 2, 3 }, { { 1.0f, 0.0f, 0.0f }, 1.0f, { 2.0f, 0.0f, 0.0f }, 0 } }, - { { 3, 4 }, { { 1.0f, 0.0f, 0.0f }, 1.0f, { 3.0f, 0.0f, 0.0f }, 0 } }, - }; - - NvBlastAssetDesc assetDesc = { chunksCount, c_chunks, 3, c_bonds }; - { - // create asset with chunk map - std::vector<char> scratch((size_t)NvBlastGetRequiredScratchForCreateAsset(&assetDesc, myLog)); - void* amem = alloc(NvBlastGetAssetMemorySize(&assetDesc, myLog)); - NvBlastAsset* asset = NvBlastCreateAsset(amem, &assetDesc, scratch.data(), myLog); - EXPECT_TRUE(asset != nullptr); - - for (uint32_t i = 0; i < 14; i++) - { - // create actor - NvBlastActorDesc actorDesc; - actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr; - actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f; - void* fmem = alloc(NvBlastAssetGetFamilyMemorySize(asset, myLog)); - NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, myLog); - scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, myLog)); - NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, scratch.data(), myLog); - EXPECT_TRUE(actor != nullptr); - - std::vector<NvBlastChunkFractureData> cfData; - cfData.resize(i + 1); - cfData[cfData.size() - 1].userdata = GUARD; - std::vector<NvBlastBondFractureData> bfData; - - NvBlastChunkFractureData command[] = - { - { 0, 1, 10.0f }, - { 0, 2, 10.0f }, - }; - - NvBlastFractureBuffers commands = { 0, 2, nullptr, command }; - NvBlastFractureBuffers events = { static_cast<uint32_t>(bfData.size()), static_cast<uint32_t>(cfData.size()) - 1, bfData.data(), cfData.data() }; - - NvBlastActorApplyFracture(&events, actor, &commands, myLog, nullptr); - - EXPECT_WARNING; - EXPECT_EQ(GUARD, cfData[cfData.size() - 1].userdata); - EXPECT_EQ(i, events.chunkFractureCount); - for (uint32_t i = 0; i < events.chunkFractureCount; i++) - { - EXPECT_EQ(events.chunkFractures[i].chunkIndex, events.chunkFractures[i].userdata); - } - - EXPECT_TRUE(NvBlastActorDeactivate(actor, myLog)); - free(family); - } - - { - // create actor - NvBlastActorDesc actorDesc; - actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr; - actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f; - void* fmem = alloc(NvBlastAssetGetFamilyMemorySize(asset, myLog)); - NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, myLog); - scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, myLog)); - NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, scratch.data(), myLog); - EXPECT_TRUE(actor != nullptr); - - std::vector<NvBlastChunkFractureData> cfData; - cfData.resize(14 + 1); - cfData[cfData.size() - 1].userdata = GUARD; - std::vector<NvBlastBondFractureData> bfData; - - NvBlastChunkFractureData command[] = - { - { 0, 1, 10.0f }, - { 0, 2, 10.0f }, - }; - - NvBlastFractureBuffers commands = { 0, 2, nullptr, command }; - NvBlastFractureBuffers events = { static_cast<uint32_t>(bfData.size()), static_cast<uint32_t>(cfData.size()) - 1, bfData.data(), cfData.data() }; - - NvBlastActorApplyFracture(&events, actor, &commands, myLog, nullptr); - - EXPECT_NO_WARNING; - EXPECT_EQ(14, events.chunkFractureCount); - for (uint32_t i = 0; i < events.chunkFractureCount; i++) - { - EXPECT_EQ(events.chunkFractures[i].chunkIndex, events.chunkFractures[i].userdata); - } - ASSERT_EQ(GUARD, cfData[cfData.size() - 1].userdata); - - scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, myLog)); - std::vector<NvBlastActor*> newActors(NvBlastActorGetMaxActorCountForSplit(actor, myLog)); - NvBlastActorSplitEvent result; - result.deletedActor = nullptr; - result.newActors = newActors.data(); - size_t newActorsCount = NvBlastActorSplit(&result, actor, static_cast<uint32_t>(newActors.size()), scratch.data(), myLog, nullptr); - newActors.resize(newActorsCount); - - EXPECT_EQ(9, newActorsCount); - for (uint32_t i = 0; i < newActorsCount; ++i) - { - const bool actorReleaseResult = NvBlastActorDeactivate(result.newActors[i], myLog); - EXPECT_TRUE(actorReleaseResult); - } - - free(family); - } - - free(asset); - } - EXPECT_NO_WARNING; -} - -TEST_F(APITest, FractureBufferLimitsInSitu) -{ - static const uint32_t GUARD = 0xb1a57; - - const uint32_t chunksCount = 17; - const NvBlastChunkDesc c_chunks[chunksCount] = - { - // cenroid volume parent idx flags ID - { {0.0f, 0.0f, 0.0f}, 0.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 0 }, - - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 1 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 2 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 3 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 4 }, - - { {0.0f, 0.0f, 0.0f}, 0.0f, 1, NvBlastChunkDesc::NoFlags, 5 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 1, NvBlastChunkDesc::NoFlags, 6 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 2, NvBlastChunkDesc::NoFlags, 7 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 2, NvBlastChunkDesc::NoFlags, 8 }, - - { {0.0f, 0.0f, 0.0f}, 0.0f, 5, NvBlastChunkDesc::NoFlags, 9 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 5, NvBlastChunkDesc::NoFlags, 10 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 6, NvBlastChunkDesc::NoFlags, 11 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 6, NvBlastChunkDesc::NoFlags, 12 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 7, NvBlastChunkDesc::NoFlags, 13 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 7, NvBlastChunkDesc::NoFlags, 14 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 8, NvBlastChunkDesc::NoFlags, 15 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 8, NvBlastChunkDesc::NoFlags, 16 }, - }; - - const NvBlastBondDesc c_bonds[3] = - { - // chunks, normal, area, centroid, userdata - { { 1, 2 }, { { 1.0f, 0.0f, 0.0f }, 1.0f, { 1.0f, 0.0f, 0.0f }, 0 } }, - { { 2, 3 }, { { 1.0f, 0.0f, 0.0f }, 1.0f, { 2.0f, 0.0f, 0.0f }, 0 } }, - { { 3, 4 }, { { 1.0f, 0.0f, 0.0f }, 1.0f, { 3.0f, 0.0f, 0.0f }, 0 } }, - }; - - NvBlastAssetDesc assetDesc = { chunksCount, c_chunks, 3, c_bonds }; - { - // create asset with chunk map - std::vector<char> scratch((size_t)NvBlastGetRequiredScratchForCreateAsset(&assetDesc, myLog)); - void* amem = alloc(NvBlastGetAssetMemorySize(&assetDesc, myLog)); - NvBlastAsset* asset = NvBlastCreateAsset(amem, &assetDesc, scratch.data(), myLog); - EXPECT_TRUE(asset != nullptr); - - for (uint32_t i = 0; i < 14 - 2; i++) - { - // create actor - NvBlastActorDesc actorDesc; - actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr; - actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f; - void* fmem = alloc(NvBlastAssetGetFamilyMemorySize(asset, myLog)); - NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, myLog); - scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, myLog)); - NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, scratch.data(), myLog); - EXPECT_TRUE(actor != nullptr); - - std::vector<NvBlastChunkFractureData> cfData; - cfData.resize(2 + i + 1); - - std::vector<NvBlastBondFractureData> bfData; - - cfData[0].userdata = 0; - cfData[0].chunkIndex = 1; - cfData[0].health = 10.0f; - - cfData[1].userdata = 0; - cfData[1].chunkIndex = 2; - cfData[1].health = 10.0f; - - cfData[2 + i].userdata = GUARD; - - NvBlastFractureBuffers commands = { 0, 2, nullptr, cfData.data() }; - NvBlastFractureBuffers events = { static_cast<uint32_t>(bfData.size()), static_cast<uint32_t>(cfData.size()) - 1, bfData.data(), cfData.data() }; - - NvBlastActorApplyFracture(&events, actor, &commands, myLog, nullptr); - - EXPECT_WARNING; - EXPECT_EQ(GUARD, cfData[cfData.size() - 1].userdata); - EXPECT_EQ(2 + i, events.chunkFractureCount); - for (uint32_t i = 0; i < events.chunkFractureCount; i++) - { - EXPECT_EQ(events.chunkFractures[i].chunkIndex, events.chunkFractures[i].userdata); - } - - EXPECT_TRUE(NvBlastActorDeactivate(actor, myLog)); - - free(family); - } - - { - // create actor - NvBlastActorDesc actorDesc; - actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr; - actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f; - void* fmem = alloc(NvBlastAssetGetFamilyMemorySize(asset, myLog)); - NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, myLog); - scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, myLog)); - NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, scratch.data(), myLog); - EXPECT_TRUE(actor != nullptr); - - std::vector<NvBlastChunkFractureData> cfData; - cfData.resize(14 + 1); - cfData[cfData.size() - 1].userdata = GUARD; - std::vector<NvBlastBondFractureData> bfData; - - cfData[0].userdata = 0; - cfData[0].chunkIndex = 1; - cfData[0].health = 10.0f; - - cfData[1].userdata = 0; - cfData[1].chunkIndex = 2; - cfData[1].health = 10.0f; - - cfData[14].userdata = GUARD; - - NvBlastFractureBuffers commands = { 0, 2, nullptr, cfData.data() }; - NvBlastFractureBuffers events = { static_cast<uint32_t>(bfData.size()), static_cast<uint32_t>(cfData.size()) - 1, bfData.data(), cfData.data() }; - - NvBlastActorApplyFracture(&events, actor, &commands, myLog, nullptr); - - EXPECT_NO_WARNING; - EXPECT_EQ(14, events.chunkFractureCount); - for (uint32_t i = 0; i < events.chunkFractureCount; i++) - { - EXPECT_EQ(events.chunkFractures[i].chunkIndex, events.chunkFractures[i].userdata); - } - ASSERT_EQ(GUARD, cfData[cfData.size() - 1].userdata); - - scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, myLog)); - std::vector<NvBlastActor*> newActors(NvBlastActorGetMaxActorCountForSplit(actor, myLog)); - NvBlastActorSplitEvent result; - result.deletedActor = nullptr; - result.newActors = newActors.data(); - size_t newActorsCount = NvBlastActorSplit(&result, actor, static_cast<uint32_t>(newActors.size()), scratch.data(), myLog, nullptr); - newActors.resize(newActorsCount); - - EXPECT_EQ(9, newActorsCount); - for (uint32_t i = 0; i < newActorsCount; ++i) - { - const bool actorReleaseResult = NvBlastActorDeactivate(result.newActors[i], myLog); - EXPECT_TRUE(actorReleaseResult); - } - free(family); - } - - free(asset); - } - EXPECT_NO_WARNING; -} - -#if 0 -TEST(APITest, UserChunkMap) -{ - for (int i = 0; i < 2; ++i) - { - // Choose descriptor list - const NvBlastAssetDesc* descs = nullptr; - size_t size = 0; - switch (i) - { - case 0: - descs = g_assetDescs; - size = sizeof(g_assetDescs) / sizeof(g_assetDescs[0]); - break; - case 1: - descs = g_assetDescsMissingCoverage; - size = sizeof(g_assetDescsMissingCoverage) / sizeof(g_assetDescsMissingCoverage[0]); - break; - default: - continue; - } - - // Iterate over list - for (size_t j = 0; j < size; ++j) - { - // Create asset - const NvBlastAssetDesc* desc = descs + j; - std::vector<char> scratch((size_t)NvBlastGetRequiredScratchForCreateAsset(desc)); - std::vector<uint32_t> chunkMap(desc->chunkCount); - NvBlastAsset* asset = NvBlastCreateAsset(&chunkMap[0], desc, alignedAlloc<malloc>, scratch.data(), nullptr); - EXPECT_TRUE(asset); - - // Test map - Nv::Blast::Asset& a = static_cast<Nv::Blast::Asset&>(asset); - uint32_t supportChunkCount = 0; - uint32_t subsupportChunkCount = 0; - for (uint32_t i = 0; i < desc->chunkCount; ++i) - { - const uint32_t map = chunkMap[i]; - if (Nv::Blast::isInvalidIndex(map)) - { - continue; - } - else if (map < a.m_firstSubsupportChunkIndex) - { - EXPECT_LT(map, asset.m_graph.m_nodeCount); - ++supportChunkCount; - } - else - { - EXPECT_LT(map, asset.m_chunkCount); - EXPECT_GE(map, asset.m_graph.m_nodeCount); - ++subsupportChunkCount; - } - } - EXPECT_EQ(supportChunkCount, asset.m_graph.m_nodeCount); - EXPECT_EQ(subsupportChunkCount, a.getLowerSupportChunkCount() - asset.m_graph.m_nodeCount); - - // Release asset - NvBlastAssetRelease(asset, free, nullptr); - } - } -} -#endif - -TEST_F(APITest, NoBondsSausage) -{ - // create asset - const NvBlastChunkDesc c_chunks[4] = - { - // centroid volume parent idx flags ID - { { 0.0f, 0.0f, 0.0f }, 0.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 0 }, - { { 0.0f, 0.0f, 0.0f }, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 1 }, - { { 0.0f, 0.0f, 0.0f }, 0.0f, 1, NvBlastChunkDesc::NoFlags, 2 }, - { { 0.0f, 0.0f, 0.0f }, 0.0f, 2, NvBlastChunkDesc::NoFlags, 3 } - }; - - NvBlastAssetDesc assetDesc; - assetDesc.chunkCount = 4; - assetDesc.chunkDescs = c_chunks; - assetDesc.bondCount = 0; - assetDesc.bondDescs = nullptr; - - std::vector<char> scratch((size_t)NvBlastGetRequiredScratchForCreateAsset(&assetDesc, messageLog)); - void* amem = alloc(NvBlastGetAssetMemorySize(&assetDesc, messageLog)); - NvBlastAsset* asset = NvBlastCreateAsset(amem, &assetDesc, scratch.data(), messageLog); - const NvBlastChunk* chunks = NvBlastAssetGetChunks(asset, messageLog); - EXPECT_TRUE(asset != nullptr); - - // create actor - NvBlastActorDesc actorDesc; - actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr; - actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f; - void* fmem = alloc(NvBlastAssetGetFamilyMemorySize(asset, messageLog)); - NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, messageLog); - scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, messageLog)); - NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, scratch.data(), messageLog); - EXPECT_TRUE(actor != nullptr); - - // check visible chunk - { - EXPECT_EQ(NvBlastActorGetVisibleChunkCount(actor, messageLog), 1); - uint32_t chunkIndex; - NvBlastActorGetVisibleChunkIndices(&chunkIndex, 1, actor, messageLog); - EXPECT_EQ(chunks[chunkIndex].userData, 0); - } - - // damage - NvBlastExtRadialDamageDesc damage[] = { - { - 10.0f, // compressive - { 0.0f, 0.0f, 0.0f }, // position - 4.0f, // min radius - maximum damage - 6.0f // max radius - zero damage - } // linear falloff - }; - - NvBlastBondFractureData outBondFracture[2]; - NvBlastChunkFractureData outChunkFracture[2]; - - NvBlastFractureBuffers events; - events.bondFractureCount = 2; - events.bondFractures = outBondFracture; - events.chunkFractureCount = 2; - events.chunkFractures = outChunkFracture; - - NvBlastProgramParams programParams; - programParams.damageDescCount = 1; - programParams.damageDescBuffer = &damage; - - NvBlastDamageProgram program = { - NvBlastExtFalloffGraphShader, - NvBlastExtFalloffSubgraphShader - }; - - NvBlastActorGenerateFracture(&events, actor, program, &programParams, messageLog, nullptr); - NvBlastActorApplyFracture(&events, actor, &events, messageLog, nullptr); - EXPECT_EQ(0, events.bondFractureCount); - EXPECT_EQ(1, events.chunkFractureCount); - - // split - NvBlastActor* newActors[8]; /* num lower-support chunks? plus space for deletedActor */ - NvBlastActorSplitEvent result; - result.deletedActor = nullptr; - result.newActors = newActors; - scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, messageLog)); - size_t newActorsCount = NvBlastActorSplit(&result, actor, 8, scratch.data(), messageLog, nullptr); - EXPECT_EQ(1, newActorsCount); - EXPECT_EQ(true, result.deletedActor == actor); - - // check visible chunk - { - EXPECT_EQ(NvBlastActorGetVisibleChunkCount(result.newActors[0], messageLog), 1); - uint32_t chunkIndex; - NvBlastActorGetVisibleChunkIndices(&chunkIndex, 1, result.newActors[0], messageLog); - EXPECT_EQ(chunks[chunkIndex].userData, 3); - } - - // release all - for (uint32_t i = 0; i < newActorsCount; ++i) - { - const bool actorReleaseResult = NvBlastActorDeactivate(result.newActors[i], messageLog); - EXPECT_TRUE(actorReleaseResult); - } - - free(family); - free(asset); -} - -TEST_F(APITest, SplitOnlyWhenNecessary) -{ - static const uint32_t GUARD = 0xb1a57; - - const uint32_t chunksCount = 17; - const NvBlastChunkDesc c_chunks[chunksCount] = - { - // centroid volume parent idx flags ID - { { 0.0f, 0.0f, 0.0f }, 0.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 0 }, - - { { 0.0f, 0.0f, 0.0f }, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 1 }, - { { 0.0f, 0.0f, 0.0f }, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 2 }, - { { 0.0f, 0.0f, 0.0f }, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 3 }, - { { 0.0f, 0.0f, 0.0f }, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 4 }, - - { { 0.0f, 0.0f, 0.0f }, 0.0f, 1, NvBlastChunkDesc::NoFlags, 5 }, - { { 0.0f, 0.0f, 0.0f }, 0.0f, 1, NvBlastChunkDesc::NoFlags, 6 }, - { { 0.0f, 0.0f, 0.0f }, 0.0f, 2, NvBlastChunkDesc::NoFlags, 7 }, - { { 0.0f, 0.0f, 0.0f }, 0.0f, 2, NvBlastChunkDesc::NoFlags, 8 }, - - { { 0.0f, 0.0f, 0.0f }, 0.0f, 5, NvBlastChunkDesc::NoFlags, 9 }, - { { 0.0f, 0.0f, 0.0f }, 0.0f, 5, NvBlastChunkDesc::NoFlags, 10 }, - { { 0.0f, 0.0f, 0.0f }, 0.0f, 6, NvBlastChunkDesc::NoFlags, 11 }, - { { 0.0f, 0.0f, 0.0f }, 0.0f, 6, NvBlastChunkDesc::NoFlags, 12 }, - { { 0.0f, 0.0f, 0.0f }, 0.0f, 7, NvBlastChunkDesc::NoFlags, 13 }, - { { 0.0f, 0.0f, 0.0f }, 0.0f, 7, NvBlastChunkDesc::NoFlags, 14 }, - { { 0.0f, 0.0f, 0.0f }, 0.0f, 8, NvBlastChunkDesc::NoFlags, 15 }, - { { 0.0f, 0.0f, 0.0f }, 0.0f, 8, NvBlastChunkDesc::NoFlags, 16 }, - }; - - const NvBlastBondDesc c_bonds[4] = - { - // chunks, normal, area, centroid, userdata - { { 1, 2 }, { { 1.0f, 0.0f, 0.0f }, 1.0f, { 1.0f, 0.0f, 0.0f }, 0 } }, - { { 2, 3 }, { { 1.0f, 0.0f, 0.0f }, 1.0f, { 1.0f, 0.0f, 0.0f }, 0 } }, - { { 3, 4 }, { { 1.0f, 0.0f, 0.0f }, 1.0f, { 1.0f, 0.0f, 0.0f }, 0 } }, - { { 1, 3 }, { { 1.0f, 0.0f, 0.0f }, 1.0f, { 1.0f, 0.0f, 0.0f }, 0 } } - }; - - NvBlastAssetDesc assetDesc = { chunksCount, c_chunks, 4, c_bonds }; - - // create asset with chunk map - std::vector<char> scratch((size_t)NvBlastGetRequiredScratchForCreateAsset(&assetDesc, myLog)); - void* amem = alloc(NvBlastGetAssetMemorySize(&assetDesc, myLog)); - NvBlastAsset* asset = NvBlastCreateAsset(amem, &assetDesc, scratch.data(), myLog); - EXPECT_TRUE(asset != nullptr); - - // create actor - NvBlastActorDesc actorDesc; - actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr; - actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f; - void* fmem = alloc(NvBlastAssetGetFamilyMemorySize(asset, myLog)); - NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, myLog); - scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, myLog)); - NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, scratch.data(), myLog); - EXPECT_TRUE(actor != nullptr); - - - // damage health only (expect no split) - { - NvBlastBondFractureData command[] = - { - { 0, 0, 1, 0.99f }, - { 0, 1, 2, 0.50f }, - { 0, 2, 3, 0.01f } - }; - - NvBlastFractureBuffers commands = { 3, 0, command, nullptr }; - NvBlastActorApplyFracture(nullptr, actor, &commands, myLog, nullptr); - - scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, myLog)); - std::vector<NvBlastActor*> newActors(NvBlastActorGetMaxActorCountForSplit(actor, myLog)); - NvBlastActorSplitEvent result; - result.deletedActor = nullptr; - result.newActors = newActors.data(); - size_t newActorsCount = NvBlastActorSplit(&result, actor, static_cast<uint32_t>(newActors.size()), scratch.data(), myLog, nullptr); - - EXPECT_EQ(0, newActorsCount); - EXPECT_EQ(nullptr, result.deletedActor); - - EXPECT_EQ(1, NvBlastActorGetVisibleChunkCount(actor, myLog)); - uint32_t chunkIndex; - NvBlastActorGetVisibleChunkIndices(&chunkIndex, 1, actor, myLog); - EXPECT_EQ(0, chunkIndex); - } - - // break 1 bond (expect no split) - { - NvBlastBondFractureData command[] = - { - { 0, 0, 2, 10.0f }, - }; - - NvBlastFractureBuffers commands = { 1, 0, command, nullptr }; - NvBlastActorApplyFracture(nullptr, actor, &commands, myLog, nullptr); - - scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, myLog)); - std::vector<NvBlastActor*> newActors(NvBlastActorGetMaxActorCountForSplit(actor, myLog)); - NvBlastActorSplitEvent result; - result.deletedActor = nullptr; - result.newActors = newActors.data(); - size_t newActorsCount = NvBlastActorSplit(&result, actor, static_cast<uint32_t>(newActors.size()), scratch.data(), myLog, nullptr); - - EXPECT_EQ(0, newActorsCount); - EXPECT_EQ(nullptr, result.deletedActor); - - EXPECT_EQ(1, NvBlastActorGetVisibleChunkCount(actor, myLog)); - uint32_t chunkIndex; - NvBlastActorGetVisibleChunkIndices(&chunkIndex, 1, actor, myLog); - EXPECT_EQ(0, chunkIndex); - } - - // split in 4 - std::vector<NvBlastActor*> actors; - { - NvBlastBondFractureData command[] = - { - { 0, 0, 1, 10.0f }, - { 0, 1, 2, 10.0f }, - { 0, 2, 3, 10.0f } - }; - - NvBlastFractureBuffers commands = { 3, 0, command, nullptr }; - NvBlastActorApplyFracture(nullptr, actor, &commands, myLog, nullptr); - - scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, myLog)); - std::vector<NvBlastActor*> newActors(NvBlastActorGetMaxActorCountForSplit(actor, myLog)); - NvBlastActorSplitEvent result; - result.deletedActor = nullptr; - result.newActors = newActors.data(); - size_t newActorsCount = NvBlastActorSplit(&result, actor, static_cast<uint32_t>(newActors.size()), scratch.data(), myLog, nullptr); - - EXPECT_EQ(4, newActorsCount); - EXPECT_EQ(actor, result.deletedActor); - - actors.insert(actors.begin(), result.newActors, result.newActors + newActorsCount); - } - - // damage chunk's health only (expect no split) - { - for (NvBlastActor* actor : actors) - { - uint32_t chunkToDamage; - NvBlastActorGetVisibleChunkIndices(&chunkToDamage, 1, actor, myLog); - - NvBlastChunkFractureData command[] = - { - { 0, chunkToDamage, 0.9f }, - }; - - NvBlastFractureBuffers commands = { 0, 1, nullptr, command }; - NvBlastActorApplyFracture(nullptr, actor, &commands, myLog, nullptr); - - scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, myLog)); - std::vector<NvBlastActor*> newActors(NvBlastActorGetMaxActorCountForSplit(actor, myLog)); - NvBlastActorSplitEvent result; - result.deletedActor = nullptr; - result.newActors = newActors.data(); - size_t newActorsCount = NvBlastActorSplit(&result, actor, static_cast<uint32_t>(newActors.size()), scratch.data(), myLog, nullptr); - - EXPECT_EQ(0, newActorsCount); - EXPECT_EQ(nullptr, result.deletedActor); - - EXPECT_EQ(1, NvBlastActorGetVisibleChunkCount(actor, myLog)); - uint32_t chunkIndex; - NvBlastActorGetVisibleChunkIndices(&chunkIndex, 1, actor, myLog); - EXPECT_EQ(chunkToDamage, chunkIndex); - } - } - - for (NvBlastActor* actor : actors) - { - NvBlastActorDeactivate(actor, myLog); - } - - free(family); - free(asset); - - EXPECT_NO_WARNING; -} - -#if NV_WINDOWS_FAMILY -#include <windows.h> -TEST_F(APITest,CExportsNoNameMangling) -{ - - // - // tests the lib-link-free approach using unmangled names (extern "C") - // - -#if NV_WIN32 -#if NV_DEBUG - const char* dllName = "NvBlastDebug_x86.dll"; -#elif NV_CHECKED - const char* dllName = "NvBlastChecked_x86.dll"; -#elif NV_PROFILE - const char* dllName = "NvBlastProfile_x86.dll"; -#else - const char* dllName = "NvBlast_x86.dll"; -#endif -#elif NV_WIN64 -#if NV_DEBUG - const char* dllName = "NvBlastDebug_x64.dll"; -#elif NV_CHECKED - const char* dllName = "NvBlastChecked_x64.dll"; -#elif NV_PROFILE - const char* dllName = "NvBlastProfile_x64.dll"; -#else - const char* dllName = "NvBlast_x64.dll"; -#endif -#endif - - HMODULE dllHandle = LoadLibrary(TEXT(dllName)); - DWORD error = GetLastError(); - ASSERT_TRUE(dllHandle != nullptr); - - - // Asset functions - typedef size_t(*NvBlastGetRequiredScratchForCreateAsset)(const NvBlastAssetDesc* desc); - typedef size_t(*NvBlastGetAssetMemorySize)(const NvBlastAssetDesc* desc); - typedef NvBlastAsset*(*NvBlastCreateAsset)(void* mem, const NvBlastAssetDesc* desc, void* scratch, NvBlastLog logFn); - - NvBlastGetRequiredScratchForCreateAsset assetCreateRequiredScratch = (NvBlastGetRequiredScratchForCreateAsset)GetProcAddress(dllHandle, TEXT("NvBlastGetRequiredScratchForCreateAsset")); - ASSERT_TRUE(assetCreateRequiredScratch != nullptr); - - NvBlastGetAssetMemorySize assetGetMemorySize = (NvBlastGetAssetMemorySize)GetProcAddress(dllHandle, TEXT("NvBlastGetAssetMemorySize")); - ASSERT_TRUE(assetGetMemorySize != nullptr); - - NvBlastCreateAsset assetCreate = (NvBlastCreateAsset)GetProcAddress(dllHandle, TEXT("NvBlastCreateAsset")); - ASSERT_TRUE(assetCreate != nullptr); - - // Family functions - typedef NvBlastFamily* (*NvBlastAssetCreateFamily)(void* mem, const NvBlastAsset* asset, NvBlastLog logFn); - typedef size_t(*NVBLASTASSETGETFAMILYMEMORYSIZE)(const NvBlastAsset* asset); - - NVBLASTASSETGETFAMILYMEMORYSIZE familyGetMemorySize = (NVBLASTASSETGETFAMILYMEMORYSIZE)GetProcAddress(dllHandle, TEXT("NvBlastAssetGetFamilyMemorySize")); - ASSERT_TRUE(familyGetMemorySize != nullptr); - - NvBlastAssetCreateFamily familyCreate = (NvBlastAssetCreateFamily)GetProcAddress(dllHandle, TEXT("NvBlastAssetCreateFamily")); - ASSERT_TRUE(familyCreate != nullptr); - - - // Actor functions - typedef size_t(*NvBlastFamilyGetRequiredScratchForCreateFirstActor)(const NvBlastFamily* family); - typedef NvBlastActor* (*NvBlastFamilyCreateFirstActor)(NvBlastFamily* family, const NvBlastActorDesc* desc, void* scratch, NvBlastLog logFn); - typedef bool(*NVBLASTACTORDEACTIVATE)(NvBlastActor* actor); - - NvBlastFamilyGetRequiredScratchForCreateFirstActor actorcreaterequiredscratch = (NvBlastFamilyGetRequiredScratchForCreateFirstActor)GetProcAddress(dllHandle, TEXT("NvBlastFamilyGetRequiredScratchForCreateFirstActor")); - ASSERT_TRUE(actorcreaterequiredscratch != nullptr); - - NvBlastFamilyCreateFirstActor actorCreate = (NvBlastFamilyCreateFirstActor)GetProcAddress(dllHandle, TEXT("NvBlastFamilyCreateFirstActor")); - ASSERT_TRUE(actorCreate != nullptr); - - NVBLASTACTORDEACTIVATE actorRelease = (NVBLASTACTORDEACTIVATE)GetProcAddress(dllHandle, TEXT("NvBlastActorDeactivate")); - ASSERT_TRUE(actorRelease != nullptr); - - - const NvBlastChunkDesc c_chunks[] = - { - // centroid volume parent idx flags ID - { {0.0f, 0.0f, 0.0f}, 0.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 0 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 0 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 0 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 0 }, - }; - - NvBlastAssetDesc assetDesc; - assetDesc.bondCount = 0; - assetDesc.bondDescs = nullptr; - assetDesc.chunkCount = 4; - assetDesc.chunkDescs = c_chunks; - - NvBlastAsset* asset; - { - size_t requiredsize = assetCreateRequiredScratch(&assetDesc); - std::vector<char>scratch(requiredsize); - void* mem = alloc(assetGetMemorySize(&assetDesc)); - asset = assetCreate(mem, &assetDesc, scratch.data(), myLog); - ASSERT_TRUE(asset != nullptr); - } - - void* fmem = alloc(familyGetMemorySize(asset)); - NvBlastFamily* family = familyCreate(fmem, asset, myLog); - - { - NvBlastActorDesc actorD; - actorD.initialBondHealths = actorD.initialSupportChunkHealths = nullptr; - actorD.uniformInitialBondHealth = actorD.uniformInitialLowerSupportChunkHealth = 1.0f; - - size_t requiredsize = actorcreaterequiredscratch(family); - std::vector<char>scratch(requiredsize); - NvBlastActor* actor = actorCreate(family, &actorD, scratch.data(), myLog); - ASSERT_TRUE(actor != nullptr); - - ASSERT_TRUE(actorRelease(actor)); - } - - free(family); - free(asset); - - EXPECT_NO_WARNING; -} -#endif diff --git a/NvBlast/test/src/unit/ActorTests.cpp b/NvBlast/test/src/unit/ActorTests.cpp deleted file mode 100644 index 12dc19c..0000000 --- a/NvBlast/test/src/unit/ActorTests.cpp +++ /dev/null @@ -1,1059 +0,0 @@ -#include "BlastBaseTest.h" -#include "AssetGenerator.h" - -#include <map> -#include <algorithm> - -#include "NvBlastActor.h" -#include "NvBlastExtDamageShaders.h" - - -static bool chooseRandomGraphNodes(uint32_t* g, uint32_t count, const Nv::Blast::Actor& actor) -{ - const uint32_t graphNodeCount = actor.getGraphNodeCount(); - - if (graphNodeCount < count) - { - return false; - } - - std::vector<uint32_t> graphNodeIndices(graphNodeCount); - uint32_t* index = graphNodeIndices.data(); - for (Nv::Blast::Actor::GraphNodeIt i = actor; (bool)i ; ++i) - { - *index++ = (uint32_t)i; - } - struct UserDataSorter - { - UserDataSorter(const Nv::Blast::Actor& actor) : m_asset(*actor.getAsset()) {} - - bool operator () (uint32_t i0, uint32_t i1) const - { - const uint32_t c0 = m_asset.m_graph.getChunkIndices()[i0]; - const uint32_t c1 = m_asset.m_graph.getChunkIndices()[i1]; - return m_asset.getChunks()[c0].userData < m_asset.getChunks()[c1].userData; - } - - const Nv::Blast::Asset& m_asset; - } userDataSorter(actor); - std::sort(graphNodeIndices.data(), graphNodeIndices.data() + graphNodeCount, userDataSorter); - -#if 0 - std::vector<uint32_t> descUserData(graphNodeCount); - for (uint32_t i = 0; i < graphNodeCount; ++i) - { - descUserData[i] = actor.getAsset()->m_chunks[actor.getAsset()->m_graph.m_chunkIndices[graphNodeIndices[i]]].userData; - } -#endif - - uint32_t t = 0; - uint32_t m = 0; - for (uint32_t i = 0; i < graphNodeCount && m < count; ++i, ++t) - { - NVBLAST_ASSERT(t < graphNodeCount); - if (t >= graphNodeCount) - { - break; - } - const float U = (float)rand()/RAND_MAX; // U is uniform random number in [0,1) - if ((graphNodeCount - t)*U < count - m) - { - g[m++] = graphNodeIndices[i]; - } - } - - return m == count; -} - - -static void blast(std::set<NvBlastActor*>& actorsToDamage, GeneratorAsset* testAsset, GeneratorAsset::Vec3 localPos, float minRadius, float maxRadius, float compressiveDamage) -{ - std::vector<NvBlastChunkFractureData> chunkEvents; /* num lower-support chunks + bonds */ - std::vector<NvBlastBondFractureData> bondEvents; /* num lower-support chunks + bonds */ - chunkEvents.resize(testAsset->solverChunks.size()); - bondEvents.resize(testAsset->solverBonds.size()); - - - std::vector<char> splitScratch; - std::vector<NvBlastActor*> newActorsBuffer(testAsset->solverChunks.size()); - - NvBlastExtRadialDamageDesc damage[] = { - { - compressiveDamage, - { localPos.x, localPos.y, localPos.z }, - minRadius, - maxRadius - } - }; - - NvBlastProgramParams programParams = - { - &damage, - 1, - nullptr - }; - - NvBlastDamageProgram program = { - NvBlastExtFalloffGraphShader, - nullptr - }; - - size_t totalNewActorsCount = 0; - for (std::set<NvBlastActor*>::iterator k = actorsToDamage.begin(); k != actorsToDamage.end();) - { - NvBlastActor* actor = *k; - NvBlastFractureBuffers events = { static_cast<uint32_t>(bondEvents.size()), static_cast<uint32_t>(chunkEvents.size()), bondEvents.data(), chunkEvents.data() }; - - NvBlastActorGenerateFracture(&events, actor, program, &programParams, nullptr, nullptr); - NvBlastActorApplyFracture(&events, actor, &events, nullptr, nullptr); - bool removeActor = false; - - if (events.bondFractureCount + events.chunkFractureCount > 0) - { - NvBlastActorSplitEvent splitEvent; - splitEvent.newActors = &newActorsBuffer.data()[totalNewActorsCount]; - uint32_t newActorSize = (uint32_t)(newActorsBuffer.size() - totalNewActorsCount); - - splitScratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, nullptr)); - const size_t newActorsCount = NvBlastActorSplit(&splitEvent, actor, newActorSize, splitScratch.data(), nullptr, nullptr); - totalNewActorsCount += newActorsCount; - removeActor = splitEvent.deletedActor != NULL; - } - - if (removeActor) - { - k = actorsToDamage.erase(k); - } - else - { - ++k; - } - } - - for (size_t i = 0; i < totalNewActorsCount; ++i) - { - actorsToDamage.insert(newActorsBuffer[i]); - } -} - - -template<int FailLevel, int Verbosity> -class ActorTest : public BlastBaseTest<FailLevel, Verbosity> -{ -public: - ActorTest() - { - - } - - static void messageLog(int type, const char* msg, const char* file, int line) - { - BlastBaseTest<FailLevel, Verbosity>::messageLog(type, msg, file, line); - } - - static void* alloc(size_t size) - { - return BlastBaseTest<FailLevel, Verbosity>::alloc(size); - } - - static void free(void* mem) - { - BlastBaseTest<FailLevel, Verbosity>::free(mem); - } - - NvBlastAsset* buildAsset(const NvBlastAssetDesc& desc) - { - // fix desc if wrong order or missing coverage first - NvBlastAssetDesc fixedDesc = desc; - std::vector<NvBlastChunkDesc> chunkDescs(desc.chunkDescs, desc.chunkDescs + desc.chunkCount); - std::vector<NvBlastBondDesc> bondDescs(desc.bondDescs, desc.bondDescs + desc.bondCount); - std::vector<uint32_t> chunkReorderMap(desc.chunkCount); - std::vector<char> scratch(desc.chunkCount * sizeof(NvBlastChunkDesc)); - NvBlastEnsureAssetExactSupportCoverage(chunkDescs.data(), fixedDesc.chunkCount, scratch.data(), messageLog); - NvBlastReorderAssetDescChunks(chunkDescs.data(), fixedDesc.chunkCount, bondDescs.data(), fixedDesc.bondCount, chunkReorderMap.data(), scratch.data(), messageLog); - fixedDesc.chunkDescs = chunkDescs.data(); - fixedDesc.bondDescs = bondDescs.empty() ? nullptr : bondDescs.data(); - - // create asset - m_scratch.resize((size_t)NvBlastGetRequiredScratchForCreateAsset(&fixedDesc, messageLog)); - void* mem = alloc(NvBlastGetAssetMemorySize(&fixedDesc, messageLog)); - NvBlastAsset* asset = NvBlastCreateAsset(mem, &fixedDesc, &m_scratch[0], messageLog); - EXPECT_TRUE(asset != nullptr); - return asset; - } - - void buildAssets() - { - m_assets.resize(getAssetDescCount()); - for (uint32_t i = 0; i < m_assets.size(); ++i) - { - m_assets[i] = buildAsset(g_assetDescs[i]); - } - } - - NvBlastActor* instanceActor(const NvBlastAsset& asset) - { - NvBlastActorDesc actorDesc; - actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr; - actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f; - void* fmem = alloc(NvBlastAssetGetFamilyMemorySize(&asset, nullptr)); - NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, &asset, nullptr); - std::vector<char> scratch((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, messageLog)); - NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, &scratch[0], messageLog); - EXPECT_TRUE(actor != nullptr); - return actor; - } - - void instanceActors() - { - m_actors.resize(m_assets.size()); - for (uint32_t i = 0; i < m_actors.size(); ++i) - { - m_actors[i] = instanceActor(*m_assets[i]); - } - } - - void releaseActors() - { - for (uint32_t i = 0; i < m_actors.size(); ++i) - { - NvBlastFamily* family = NvBlastActorGetFamily(m_actors[i], messageLog); - - const bool actorReleaseResult = NvBlastActorDeactivate(m_actors[i], messageLog); - EXPECT_TRUE(actorReleaseResult); - - free(family); - } - } - - void destroyAssets() - { - for (uint32_t i = 0; i < m_assets.size(); ++i) - { - free(m_assets[i]); - } - } - - void instanceAndPartitionRecursively - ( - const NvBlastAsset& asset, - bool partitionToSubsupport, - void (*preSplitTest)(const Nv::Blast::Actor&, NvBlastLog), - void (*postSplitTest)(const std::vector<Nv::Blast::Actor*>&, uint32_t, uint32_t, bool) - ) - { - const Nv::Blast::Asset& solverAsset = *static_cast<const Nv::Blast::Asset*>(&asset); - - std::vector<Nv::Blast::Actor*> actors; - std::vector<Nv::Blast::Actor*> buffer(NvBlastAssetGetChunkCount(&asset, messageLog)); - - // Instance the first actor from the asset - actors.push_back(static_cast<Nv::Blast::Actor*>(instanceActor(asset))); - - NvBlastFamily* family = NvBlastActorGetFamily(actors[0], messageLog); - - const uint32_t supportChunkCount = actors[0]->getAsset()->m_graph.m_nodeCount; - const uint32_t leafChunkCount = actors[0]->getAsset()->m_leafChunkCount; - - // Now randomly partition the actors in the array, and keep going until we're down to single support chunks - bool canFracture = true; - - while (canFracture) - { - canFracture = false; - - for (uint32_t actorToPartition = 0; actorToPartition < actors.size(); ++actorToPartition) - { - Nv::Blast::Actor* a = (Nv::Blast::Actor*)actors[actorToPartition]; - if (a == nullptr) - { - continue; - } - - m_scratch.reserve((size_t)NvBlastActorGetRequiredScratchForSplit(a, messageLog)); - - if (preSplitTest) - { - preSplitTest(*a, nullptr); - } - - const bool singleLowerSupportChunk = a->getGraphNodeCount() <= 1; - uint32_t newActorCount = 0; - - for (int damageNum = 0; newActorCount < 2 && damageNum < 100; ++damageNum) // Avoid infinite loops - { - if (!singleLowerSupportChunk) - { - uint32_t g[2]; - chooseRandomGraphNodes(g, 2, *a); - const uint32_t bondIndex = solverAsset.m_graph.findBond(g[0], g[1]); - if (bondIndex != Nv::Blast::invalidIndex<uint32_t>()) - { - a->damageBond(g[0], g[1], bondIndex, 100.0f); - a->findIslands(&m_scratch[0]); - } - } - else - if (!partitionToSubsupport) - { - continue; - } - - // Split actor - newActorCount = a->partition((Nv::Blast::Actor**)&buffer[0], (uint32_t)buffer.size(), messageLog); - - if (newActorCount >= 2) - { - actors[actorToPartition] = nullptr; - } - } - - if (newActorCount > 1) - { - canFracture = true; - } - - for (uint32_t i = 0; i < newActorCount; ++i) - { - actors.push_back(buffer[i]); - buffer[i]->updateVisibleChunksFromGraphNodes(); - } - } - } - - if (postSplitTest) - { - postSplitTest(actors, leafChunkCount, supportChunkCount, partitionToSubsupport); - } - - for (auto actor : actors) - { - if (actor) - actor->release(); - } - - free(family); - } - - static void recursivePartitionPostSplitTestCounts(const std::vector<Nv::Blast::Actor*>& actors, uint32_t leafChunkCount, uint32_t supportChunkCount, bool partitionToSubsupport) - { - // Test to see that all actors are split down to single support chunks - uint32_t remainingActorCount = 0; - for (uint32_t i = 0; i < actors.size(); ++i) - { - Nv::Blast::Actor* a = (Nv::Blast::Actor*)actors[i]; - if (a == nullptr) - { - continue; - } - - ++remainingActorCount; - - NVBLAST_ASSERT(1 == a->getVisibleChunkCount()); - EXPECT_EQ(1, a->getVisibleChunkCount()); - if (!partitionToSubsupport) - { - EXPECT_EQ(1, a->getGraphNodeCount()); - } - - const bool actorReleaseResult = NvBlastActorDeactivate(actors[i], nullptr); - EXPECT_TRUE(actorReleaseResult); - } - - if (partitionToSubsupport) - { - EXPECT_EQ(leafChunkCount, remainingActorCount); - } - else - { - EXPECT_EQ(supportChunkCount, remainingActorCount); - } - } - - static void testActorVisibleChunks(const Nv::Blast::Actor& actor, NvBlastLog) - { - const Nv::Blast::Asset& asset = *actor.getAsset(); - const NvBlastChunk* chunks = asset.getChunks(); - - if (actor.isSubSupportChunk()) - { - EXPECT_EQ(1, actor.getVisibleChunkCount()); - - const uint32_t firstVisibleChunkIndex = (uint32_t)Nv::Blast::Actor::VisibleChunkIt(actor); - - EXPECT_EQ(actor.getIndex() - asset.m_graph.m_nodeCount, firstVisibleChunkIndex - asset.m_firstSubsupportChunkIndex); - - // Make sure the visible chunk is subsupport - // Array of support flags - std::vector<bool> isSupport(asset.m_chunkCount, false); - for (uint32_t i = 0; i < asset.m_graph.m_nodeCount; ++i) - { - isSupport[asset.m_graph.getChunkIndices()[i]] = true; - } - - // Climb hierarchy to find support chunk - uint32_t chunkIndex = firstVisibleChunkIndex; - while (chunkIndex != Nv::Blast::invalidIndex<uint32_t>()) - { - if (isSupport[chunkIndex]) - { - break; - } - chunkIndex = chunks[chunkIndex].parentChunkIndex; - } - - EXPECT_FALSE(Nv::Blast::isInvalidIndex(chunkIndex)); - } - else - { - // Array of visibility flags - std::vector<bool> isVisible(asset.m_chunkCount, false); - for (Nv::Blast::Actor::VisibleChunkIt i = actor; (bool)i; ++i) - { - isVisible[(uint32_t)i] = true; - } - - // Mark visible nodes representing graph chunks - std::vector<bool> visibleChunkFound(asset.m_chunkCount, false); - - // Make sure every graph chunk is represented by a visible chunk - for (Nv::Blast::Actor::GraphNodeIt i = actor; (bool)i; ++i) - { - const uint32_t graphNodeIndex = (uint32_t)i; - uint32_t chunkIndex = asset.m_graph.getChunkIndices()[graphNodeIndex]; - // Climb hierarchy to find visible chunk - while (chunkIndex != Nv::Blast::invalidIndex<uint32_t>()) - { - // Check that chunk owners are accurate - EXPECT_EQ(actor.getIndex(), actor.getFamilyHeader()->getChunkActorIndices()[chunkIndex]); - if (isVisible[chunkIndex]) - { - visibleChunkFound[chunkIndex] = true; - break; - } - chunkIndex = chunks[chunkIndex].parentChunkIndex; - } - EXPECT_FALSE(Nv::Blast::isInvalidIndex(chunkIndex)); - } - - // Check that all visible chunks are accounted for - for (uint32_t i = 0; i < asset.m_chunkCount; ++i) - { - EXPECT_EQ(visibleChunkFound[i], isVisible[i]); - } - - // Make sure that, if all siblings are intact, they are invisible - for (uint32_t i = 0; i < asset.m_chunkCount; ++i) - { - bool allIntact = true; - bool noneVisible = true; - if (chunks[i].firstChildIndex < asset.getUpperSupportChunkCount()) // Do not check subsupport - { - for (uint32_t j = chunks[i].firstChildIndex; j < chunks[i].childIndexStop; ++j) - { - allIntact = allIntact && actor.getFamilyHeader()->getChunkActorIndices()[j] == actor.getIndex(); - noneVisible = noneVisible && !isVisible[j]; - } - EXPECT_TRUE(!allIntact || noneVisible); - } - } - } - } - - static void recursivePartitionPostSplitTestVisibleChunks(const std::vector<Nv::Blast::Actor*>& actors, uint32_t leafChunkCount, uint32_t supportChunkCount, bool partitionToSubsupport) - { - for (uint32_t i = 0; i < actors.size(); ++i) - { - Nv::Blast::Actor* a = (Nv::Blast::Actor*)actors[i]; - if (a == nullptr) - { - continue; - } - - testActorVisibleChunks(*a, nullptr); - } - } - - void partitionActorsToSupportChunks - ( - uint32_t assetDescCount, - const NvBlastAssetDesc* assetDescs, - void(*preSplitTest)(const Nv::Blast::Actor&, NvBlastLog), - void(*postSplitTest)(const std::vector<Nv::Blast::Actor*>&, uint32_t, uint32_t, bool), - bool partitionToSubsupport - ) - { - srand(0); - - for (uint32_t i = 0; i < assetDescCount; ++i) - { - // Create an asset - NvBlastAsset* asset = buildAsset(assetDescs[i]); - - // Perform repeated partitioning - instanceAndPartitionRecursively(*asset, partitionToSubsupport, preSplitTest, postSplitTest); - - // Free the asset - free(asset); - } - } - - static void compareFamilies(const NvBlastFamily* family1, const NvBlastFamily* family2, size_t size, NvBlastLog logFn) - { - const char* block1 = reinterpret_cast<const char*>(family1); - const char* block2 = reinterpret_cast<const char*>(family2); -#if 0 - EXPECT_EQ(0, memcmp(block1, block2, size)); -#else - bool diffFound = false; - size_t startDiff = 0; - for (size_t i = 0; i < size; ++i) - { - if (block1[i] != block2[i]) - { - diffFound = true; - startDiff = i; - break; - } - } - if (!diffFound) - { - return; - } - size_t endDiff = startDiff; - for (size_t i = size; i--;) - { - if (block1[i] != block2[i]) - { - endDiff = i; - break; - } - } - std::ostringstream msg; - msg << "Block deserialization does not match current block in position range [" << startDiff << ", " << endDiff << "]."; - logFn(NvBlastMessage::Error, msg.str().c_str(), __FILE__, __LINE__); -#endif - } - - static void testActorBlockSerialize(std::vector<NvBlastActor*>& actors, NvBlastLog logFn) - { - if (actors.size()) - { - const NvBlastFamily* family = NvBlastActorGetFamily(actors[0], logFn); - const uint32_t size = NvBlastFamilyGetSize(family, logFn); - s_storage.insert(s_storage.end(), (char*)family, (char*)family + size); - } - } - - static void testActorBlockDeserialize(std::vector<NvBlastActor*>& actors, NvBlastLog logFn) - { - if (actors.size()) - { - EXPECT_LT(s_curr, s_storage.size()); - const NvBlastFamily* family = reinterpret_cast<NvBlastFamily*>(&s_storage[s_curr]); - const uint32_t size = NvBlastFamilyGetSize(family, logFn); - EXPECT_LE(s_curr + size, s_storage.size()); - s_curr += size; - const NvBlastFamily* actorFamily = NvBlastActorGetFamily(actors[0], logFn); - // Family may contain different assets pointers, copy into new family block and set the same asset before comparing - Nv::Blast::Actor& a = *static_cast<Nv::Blast::Actor*>(actors[0]); - const Nv::Blast::Asset* solverAsset = a.getAsset(); - std::vector<char> storageFamilyCopy((char*)family, (char*)family + size); - NvBlastFamily* storageFamily = reinterpret_cast<NvBlastFamily*>(storageFamilyCopy.data()); - NvBlastFamilySetAsset(storageFamily, solverAsset, logFn); - { - const uint32_t actorCountExpected = NvBlastFamilyGetActorCount(storageFamily, logFn); - std::vector<NvBlastActor*> blockActors(actorCountExpected); - const uint32_t actorCountReturned = NvBlastFamilyGetActors(&blockActors[0], actorCountExpected, storageFamily, logFn); - EXPECT_EQ(actorCountExpected, actorCountReturned); - } - compareFamilies(storageFamily, actorFamily, size, logFn); - } - } - - // Serialize all actors and then deserialize back into a new family in a random order, and compare with the original family - static void testActorSerializationNewFamily(std::vector<NvBlastActor*>& actors, NvBlastLog logFn) - { - if (actors.size() == 0) - { - return; - } - - Nv::Blast::Actor& a = *static_cast<Nv::Blast::Actor*>(actors[0]); - const Nv::Blast::Asset* solverAsset = a.getAsset(); - - const uint32_t serSizeBound = NvBlastAssetGetActorSerializationSizeUpperBound(solverAsset, logFn); - - std::vector< std::vector<char> > streams(actors.size()); - for (size_t i = 0; i < actors.size(); ++i) - { - const uint32_t serSize = NvBlastActorGetSerializationSize(actors[i], logFn); - EXPECT_GE(serSizeBound, serSize); - std::vector<char>& stream = streams[i]; - stream.resize(serSize); - const uint32_t bytesWritten = NvBlastActorSerialize(&stream[0], serSize, actors[i], logFn); - EXPECT_EQ(serSize, bytesWritten); - } - - void* fmem = alloc(NvBlastAssetGetFamilyMemorySize(solverAsset, logFn)); - NvBlastFamily* newFamily = NvBlastAssetCreateFamily(fmem, solverAsset, logFn); - - std::vector<size_t> order(actors.size()); - for (size_t i = 0; i < order.size(); ++i) - { - order[i] = i; - } - std::random_shuffle(order.begin(), order.end()); - - for (size_t i = 0; i < actors.size(); ++i) - { - NvBlastActor* newActor = NvBlastFamilyDeserializeActor(newFamily, &streams[order[i]][0], logFn); - EXPECT_TRUE(newActor != nullptr); - } - - const NvBlastFamily* oldFamily = NvBlastActorGetFamily(&a, logFn); - compareFamilies(oldFamily, newFamily, NvBlastFamilyGetSize(oldFamily, logFn), logFn); - - free(newFamily); - } - - // Copy the family and then serialize some subset of actors, deleting them afterwards. - // Then, deserialize back into the block and compare the original and new families. - static void testActorSerializationPartialBlock(std::vector<NvBlastActor*>& actors, NvBlastLog logFn) - { - if (actors.size() <= 1) - { - return; - } - - Nv::Blast::Actor& a = *static_cast<Nv::Blast::Actor*>(actors[0]); - const Nv::Blast::Asset* solverAsset = a.getAsset(); - - const NvBlastFamily* oldFamily = NvBlastActorGetFamily(&a, logFn); - const uint32_t size = NvBlastFamilyGetSize(oldFamily, logFn); - std::vector<char> buffer((char*)oldFamily, (char*)oldFamily + size); - NvBlastFamily* familyCopy = reinterpret_cast<NvBlastFamily*>(&buffer[0]); - - const uint32_t serCount = 1 + (rand() % actors.size() - 1); - - const uint32_t actorCount = NvBlastFamilyGetActorCount(familyCopy, logFn); - std::vector<NvBlastActor*> actorsRemaining(actorCount); - const uint32_t actorsInFamily = NvBlastFamilyGetActors(&actorsRemaining[0], actorCount, familyCopy, logFn); - EXPECT_EQ(actorCount, actorsInFamily); - - const uint32_t serSizeBound = NvBlastAssetGetActorSerializationSizeUpperBound(solverAsset, logFn); - - std::vector< std::vector<char> > streams(serCount); - for (uint32_t i = 0; i < serCount; ++i) - { - std::vector<char>& stream = streams[i]; - const uint32_t indexToStream = rand() % actorsRemaining.size(); - NvBlastActor* actorToStream = actorsRemaining[indexToStream]; - std::swap(actorsRemaining[indexToStream], actorsRemaining[actorsRemaining.size() - 1]); - actorsRemaining.pop_back(); - const uint32_t serSize = NvBlastActorGetSerializationSize(actorToStream, logFn); - EXPECT_GE(serSizeBound, serSize); - stream.resize(serSize); - const uint32_t bytesWritten = NvBlastActorSerialize(&stream[0], serSize, actorToStream, logFn); - EXPECT_EQ(serSize, bytesWritten); - NvBlastActorDeactivate(actorToStream, logFn); - } - - for (uint32_t i = 0; i < serCount; ++i) - { - NvBlastActor* newActor = NvBlastFamilyDeserializeActor(familyCopy, &streams[i][0], logFn); - EXPECT_TRUE(newActor != nullptr); - } - - compareFamilies(oldFamily, familyCopy, size, logFn); - } - - void damageLeafSupportActors - ( - uint32_t assetCount, - uint32_t familyCount, - uint32_t damageCount, - bool simple, - void (*actorTest)(const Nv::Blast::Actor&, NvBlastLog), - void (*postDamageTest)(std::vector<NvBlastActor*>&, NvBlastLog), - CubeAssetGenerator::BondFlags bondFlags = CubeAssetGenerator::BondFlags::ALL_BONDS - ) - { - const float relativeDamageRadius = simple ? 0.75f : 0.2f; - const float compressiveDamage = 1.0f; - const uint32_t minChunkCount = simple ? 9 : 100; - const uint32_t maxChunkCount = simple ? 9 : 10000; - const bool printActorCount = false; - - srand(0); - - std::cout << "Asset # (out of " << assetCount << "): "; - for (uint32_t assetNum = 0; assetNum < assetCount; ++assetNum) - { - std::cout << assetNum + 1 << ".. "; - CubeAssetGenerator::Settings settings; - settings.extents = GeneratorAsset::Vec3(1, 1, 1); - settings.bondFlags = bondFlags; - CubeAssetGenerator::DepthInfo depthInfo; - depthInfo.slicesPerAxis = GeneratorAsset::Vec3(1, 1, 1); - depthInfo.flag = NvBlastChunkDesc::Flags::NoFlags; - settings.depths.push_back(depthInfo); - uint32_t chunkCount = 1; - while (chunkCount < minChunkCount) - { - uint32_t chunkMul; - do - { - depthInfo.slicesPerAxis = simple ? GeneratorAsset::Vec3(2, 2, 2) : GeneratorAsset::Vec3((float)(1 + rand() % 4), (float)(1 + rand() % 4), (float)(1 + rand() % 4)); - chunkMul = (uint32_t)(depthInfo.slicesPerAxis.x * depthInfo.slicesPerAxis.y * depthInfo.slicesPerAxis.z); - } while (chunkMul == 1); - if (chunkCount*chunkMul > maxChunkCount) - { - break; - } - chunkCount *= chunkMul; - settings.depths.push_back(depthInfo); - settings.extents = settings.extents * depthInfo.slicesPerAxis; - } - settings.depths.back().flag = NvBlastChunkDesc::SupportFlag; // Leaves are support - - // Make largest direction unit size - settings.extents = settings.extents * (1.0f / std::max(settings.extents.x, std::max(settings.extents.y, settings.extents.z))); - - // Create asset - GeneratorAsset testAsset; - CubeAssetGenerator::generate(testAsset, settings); - - NvBlastAssetDesc desc; - desc.chunkDescs = testAsset.solverChunks.data(); - desc.chunkCount = (uint32_t)testAsset.solverChunks.size(); - desc.bondDescs = testAsset.solverBonds.data(); - desc.bondCount = (uint32_t)testAsset.solverBonds.size(); - - NvBlastAsset* asset = buildAsset(desc); - NvBlastID assetID = NvBlastAssetGetID(asset, messageLog); - - // copy asset (for setAsset testing) - const char* data = (const char*)asset; - const uint32_t dataSize = NvBlastAssetGetSize(asset, messageLog); - char* duplicateData = (char*)alloc(dataSize); - memcpy(duplicateData, data, dataSize); - NvBlastAsset* assetDuplicate = (NvBlastAsset*)duplicateData; - - // Generate families - for (uint32_t familyNum = 0; familyNum < familyCount; ++familyNum) - { - // family - void* fmem = alloc(NvBlastAssetGetFamilyMemorySize(asset, messageLog)); - NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, messageLog); // Using zeroingAlloc in case actorTest compares memory blocks - NvBlastID id = NvBlastFamilyGetAssetID(family, messageLog); - EXPECT_TRUE(!memcmp(&assetID, &id, sizeof(NvBlastID))); - if (rand() % 2 == 0) - { - // replace asset with duplicate in half of cases to test setAsset - NvBlastFamilySetAsset(family, assetDuplicate, messageLog); - NvBlastID id2 = NvBlastFamilyGetAssetID(family, messageLog); - EXPECT_TRUE(!memcmp(&assetID, &id2, sizeof(NvBlastID))); - } - - // actor - NvBlastActorDesc actorDesc; - actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr; - actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f; - m_scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, messageLog)); - NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, m_scratch.data(), messageLog); - EXPECT_TRUE(actor != nullptr); - - // Generate damage - std::set<NvBlastActor*> actors; - actors.insert(actor); - if (printActorCount) std::cout << "Actors: 1.. "; - for (uint32_t damageNum = 0; damageNum < damageCount; ++damageNum) - { - GeneratorAsset::Vec3 localPos = settings.extents*GeneratorAsset::Vec3((float)rand() / RAND_MAX - 0.5f, (float)rand() / RAND_MAX - 0.5f, (float)rand() / RAND_MAX - 0.5f); - blast(actors, &testAsset, localPos, relativeDamageRadius, relativeDamageRadius*1.2f, compressiveDamage); - if (printActorCount) std::cout << actors.size() << ".. "; - if (actors.size() > 0) - { - const NvBlastFamily* family = NvBlastActorGetFamily(*actors.begin(), messageLog); - const uint32_t actorCount = NvBlastFamilyGetActorCount(family, messageLog); - EXPECT_EQ((uint32_t)actors.size(), actorCount); - if ((uint32_t)actors.size() == actorCount) - { - std::vector<NvBlastActor*> buffer1(actorCount); - const uint32_t actorsWritten = NvBlastFamilyGetActors(&buffer1[0], actorCount, family, messageLog); - EXPECT_EQ(actorsWritten, actorCount); - std::vector<NvBlastActor*> buffer2(actors.begin(), actors.end()); - EXPECT_EQ(0, memcmp(&buffer1[0], &buffer2[0], actorCount*sizeof(NvBlastActor*))); - } - } - // Test individual actors - if (actorTest != nullptr) - { - for (std::set<NvBlastActor*>::iterator k = actors.begin(); k != actors.end(); ++k) - { - actorTest(*static_cast<Nv::Blast::Actor*>(*k), messageLog); - } - } - } - if (printActorCount) std::cout << "\n"; - - // Test fractured actor set - if (postDamageTest) - { - std::vector<NvBlastActor*> actorArray(actors.begin(), actors.end()); - postDamageTest(actorArray, messageLog); - } - - // Release remaining actors - for (std::set<NvBlastActor*>::iterator k = actors.begin(); k != actors.end(); ++k) - { - NvBlastActorDeactivate(*k, messageLog); - } - actors.clear(); - - free(family); - } - - // Release asset data - free(asset); - free(assetDuplicate); - } - std::cout << "done.\n"; - } - - std::vector<NvBlastAsset*> m_assets; - std::vector<NvBlastActor*> m_actors; - std::vector<char> m_scratch; - static std::vector<char> s_storage; - - static size_t s_curr; -}; - -// Static values -template<int FailLevel, int Verbosity> -std::vector<char> ActorTest<FailLevel, Verbosity>::s_storage; - -template<int FailLevel, int Verbosity> -size_t ActorTest<FailLevel, Verbosity>::s_curr; - -// Specializations -typedef ActorTest<NvBlastMessage::Error, 1> ActorTestAllowWarnings; -typedef ActorTest<NvBlastMessage::Warning, 1> ActorTestStrict; - -// Tests -TEST_F(ActorTestStrict, InstanceActors) -{ - // Build assets and instance actors - buildAssets(); - instanceActors(); - - // Release actors and destroy assets - releaseActors(); - destroyAssets(); -} - -TEST_F(ActorTestAllowWarnings, ActorHealthInitialization) -{ - // Test all assets - std::vector<NvBlastAssetDesc> assetDescs; - assetDescs.insert(assetDescs.end(), g_assetDescs, g_assetDescs + getAssetDescCount()); - assetDescs.insert(assetDescs.end(), g_assetDescsMissingCoverage, g_assetDescsMissingCoverage + getAssetDescMissingCoverageCount()); - - struct TestMode - { - enum Enum - { - Uniform, - Nonuniform, - - Count - }; - }; - - for (auto assetDesc : assetDescs) - { - NvBlastAsset* asset = buildAsset(assetDesc); - EXPECT_TRUE(asset != nullptr); - - Nv::Blast::Asset& assetInt = static_cast<Nv::Blast::Asset&>(*asset); - - NvBlastSupportGraph graph = NvBlastAssetGetSupportGraph(asset, nullptr); - - std::vector<float> supportChunkHealths(graph.nodeCount); - for (size_t i = 0; i < supportChunkHealths.size(); ++i) - { - supportChunkHealths[i] = 1.0f + (float)i; - } - - std::vector<float> bondHealths(assetInt.getBondCount()); - for (size_t i = 0; i < bondHealths.size(); ++i) - { - bondHealths[i] = 1.5f + (float)i; - } - - for (int chunkTestMode = 0; chunkTestMode < TestMode::Count; ++chunkTestMode) - { - for (int bondTestMode = 0; bondTestMode < TestMode::Count; ++bondTestMode) - { - NvBlastActorDesc actorDesc; - - switch (chunkTestMode) - { - default: - case TestMode::Uniform: - actorDesc.initialSupportChunkHealths = nullptr; - actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f; - break; - case TestMode::Nonuniform: - actorDesc.initialSupportChunkHealths = supportChunkHealths.data(); - break; - } - - switch (bondTestMode) - { - default: - case TestMode::Uniform: - actorDesc.initialBondHealths = nullptr; - actorDesc.uniformInitialBondHealth = 2.0f; - break; - case TestMode::Nonuniform: - actorDesc.initialBondHealths = bondHealths.data(); - break; - } - - void* fmem = alloc(NvBlastAssetGetFamilyMemorySize(asset, messageLog)); - NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, nullptr); - std::vector<char> scratch((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, messageLog)); - NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, &scratch[0], messageLog); - EXPECT_TRUE(actor != nullptr); - - Nv::Blast::Actor& actorInt = static_cast<Nv::Blast::Actor&>(*actor); - Nv::Blast::FamilyHeader* header = actorInt.getFamilyHeader(); - - - for (uint32_t i = 0; i < graph.nodeCount; ++i) - { - const uint32_t supportChunkIndex = graph.chunkIndices[i]; - for (Nv::Blast::Asset::DepthFirstIt it(assetInt, supportChunkIndex); (bool)it; ++it) - { - const uint32_t chunkIndex = (uint32_t)it; - const uint32_t lowerSupportIndex = assetInt.getContiguousLowerSupportIndex(chunkIndex); - NVBLAST_ASSERT(lowerSupportIndex < assetInt.getLowerSupportChunkCount()); - const float health = header->getLowerSupportChunkHealths()[lowerSupportIndex]; - switch (chunkTestMode) - { - default: - case TestMode::Uniform: - EXPECT_EQ(1.0f, health); - break; - case TestMode::Nonuniform: - EXPECT_EQ(supportChunkHealths[i], health); - break; - } - } - } - - for (uint32_t i = 0; i < assetInt.getBondCount(); ++i) - { - switch (bondTestMode) - { - default: - case TestMode::Uniform: - EXPECT_EQ(2.0f, header->getBondHealths()[i]); - break; - case TestMode::Nonuniform: - EXPECT_EQ(bondHealths[i], header->getBondHealths()[i]); - break; - } - } - - NvBlastActorDeactivate(actor, messageLog); - free(family); - } - } - - free(asset); - } -} - -TEST_F(ActorTestStrict, PartitionActorsToSupportChunksTestCounts) -{ - partitionActorsToSupportChunks(getAssetDescCount(), g_assetDescs, nullptr, recursivePartitionPostSplitTestCounts, false); -} - -TEST_F(ActorTestAllowWarnings, PartitionActorsFromBadDescriptorsToSupportChunksTestCounts) -{ - partitionActorsToSupportChunks(getAssetDescMissingCoverageCount(), g_assetDescsMissingCoverage, nullptr, recursivePartitionPostSplitTestCounts, false); -} - -TEST_F(ActorTestStrict, PartitionActorsToLeafChunksTestCounts) -{ - partitionActorsToSupportChunks(getAssetDescCount(), g_assetDescs, nullptr, recursivePartitionPostSplitTestCounts, true); -} - -TEST_F(ActorTestAllowWarnings, PartitionActorsFromBadDescriptorsToLeafChunksTestCounts) -{ - partitionActorsToSupportChunks(getAssetDescMissingCoverageCount(), g_assetDescsMissingCoverage, nullptr, recursivePartitionPostSplitTestCounts, true); -} - -TEST_F(ActorTestStrict, PartitionActorsToSupportChunksTestVisibility) -{ - partitionActorsToSupportChunks(getAssetDescCount(), g_assetDescs, testActorVisibleChunks, recursivePartitionPostSplitTestVisibleChunks, false); -} - -TEST_F(ActorTestAllowWarnings, PartitionActorsFromBadDescriptorsToSupportChunksTestVisibility) -{ - partitionActorsToSupportChunks(getAssetDescMissingCoverageCount(), g_assetDescsMissingCoverage, testActorVisibleChunks, recursivePartitionPostSplitTestVisibleChunks, false); -} - -TEST_F(ActorTestStrict, PartitionActorsToLeafChunksTestVisibility) -{ - partitionActorsToSupportChunks(getAssetDescCount(), g_assetDescs, testActorVisibleChunks, recursivePartitionPostSplitTestVisibleChunks, true); -} - -TEST_F(ActorTestAllowWarnings, PartitionActorsFromBadDescriptorsToLeafChunksTestVisibility) -{ - partitionActorsToSupportChunks(getAssetDescMissingCoverageCount(), g_assetDescsMissingCoverage, testActorVisibleChunks, recursivePartitionPostSplitTestVisibleChunks, true); -} - -TEST_F(ActorTestStrict, DamageLeafSupportActorsTestVisibility) -{ - damageLeafSupportActors(4, 4, 5, false, testActorVisibleChunks, nullptr); -} - -TEST_F(ActorTestStrict, DamageLeafSupportActorTestBlockSerialization) -{ - s_storage.resize(0); - damageLeafSupportActors(4, 4, 5, false, nullptr, testActorBlockSerialize); - s_curr = 0; - damageLeafSupportActors(4, 4, 5, false, nullptr, testActorBlockDeserialize); - s_storage.resize(0); -} - -TEST_F(ActorTestStrict, DamageSimpleLeafSupportActorTestActorSerializationNewFamily) -{ - damageLeafSupportActors(1, 1, 4, true, nullptr, testActorSerializationNewFamily); -} - -TEST_F(ActorTestStrict, DamageSimpleLeafSupportActorTestActorSerializationPartialBlock) -{ - damageLeafSupportActors(1, 1, 4, true, nullptr, testActorSerializationPartialBlock); -} - -TEST_F(ActorTestStrict, DamageLeafSupportActorTestActorSerializationNewFamily) -{ - damageLeafSupportActors(4, 4, 4, false, nullptr, testActorSerializationNewFamily); -} - -TEST_F(ActorTestStrict, DamageLeafSupportActorTestActorSerializationPartialBlock) -{ - damageLeafSupportActors(4, 4, 4, false, nullptr, testActorSerializationPartialBlock); -} - -TEST_F(ActorTestStrict, DamageMultipleIslandLeafSupportActorsTestVisibility) -{ - damageLeafSupportActors(4, 4, 5, false, testActorVisibleChunks, nullptr, CubeAssetGenerator::BondFlags::Y_BONDS | CubeAssetGenerator::BondFlags::Z_BONDS); // Only connect y-z plane islands - damageLeafSupportActors(4, 4, 5, false, testActorVisibleChunks, nullptr, CubeAssetGenerator::BondFlags::Z_BONDS); // Only connect z-direction islands - damageLeafSupportActors(4, 4, 5, false, testActorVisibleChunks, nullptr, CubeAssetGenerator::BondFlags::NO_BONDS); // All support chunks disconnected (single-chunk islands) -} diff --git a/NvBlast/test/src/unit/AssetTests.cpp b/NvBlast/test/src/unit/AssetTests.cpp deleted file mode 100644 index 24e5f77..0000000 --- a/NvBlast/test/src/unit/AssetTests.cpp +++ /dev/null @@ -1,529 +0,0 @@ -#include "NvBlastAsset.h" - -#include "BlastBaseTest.h" - -#include "NvBlastTkFramework.h" - -#include <algorithm> - - -#if defined(_MSC_VER) && _MSC_VER < 1900 || defined(_XBOX_ONE) || defined(PS4) || PX_LINUX -#define ENABLE_SERIALIZATION_TESTS 0 -#else -#define ENABLE_SERIALIZATION_TESTS 1 -#endif - -#pragma warning( push ) -#pragma warning( disable : 4267 ) -// NOTE: Instead of excluding serialization and the tests when on VC12, should break the tests out into a separate C++ file. - -#if ENABLE_SERIALIZATION_TESTS -#include "NvBlastExtSerializationInterface.h" - -#include "generated/NvBlastExtSerialization.capn.h" -#endif - -#pragma warning( pop ) - -#include <fstream> -#include <iosfwd> - -#ifdef WIN32 -#include <windows.h> -#endif - -template<int FailLevel, int Verbosity> -class AssetTest : public BlastBaseTest<FailLevel, Verbosity> -{ -public: - - AssetTest() - { - Nv::Blast::TkFrameworkDesc desc; - desc.allocatorCallback = this; - desc.errorCallback = this; - NvBlastTkFrameworkCreate(desc); - } - - ~AssetTest() - { - NvBlastTkFrameworkGet()->release(); - } - - static void messageLog(int type, const char* msg, const char* file, int line) - { - BlastBaseTest<FailLevel, Verbosity>::messageLog(type, msg, file, line); - } - - static void* alloc(size_t size) - { - return BlastBaseTest<FailLevel, Verbosity>::alloc(size); - } - - static void free(void* mem) - { - BlastBaseTest<FailLevel, Verbosity>::free(mem); - } - - void testSubtreeLeafChunkCounts(const Nv::Blast::Asset& a) - { - const NvBlastChunk* chunks = a.getChunks(); - const uint32_t* subtreeLeafChunkCounts = a.getSubtreeLeafChunkCounts(); - uint32_t totalLeafChunkCount = 0; - for (uint32_t chunkIndex = 0; chunkIndex < a.m_chunkCount; ++chunkIndex) - { - const NvBlastChunk& chunk = chunks[chunkIndex]; - if (Nv::Blast::isInvalidIndex(chunk.parentChunkIndex)) - { - totalLeafChunkCount += subtreeLeafChunkCounts[chunkIndex]; - } - const bool isLeafChunk = chunk.firstChildIndex >= chunk.childIndexStop; - uint32_t subtreeLeafChunkCount = isLeafChunk ? 1 : 0; - for (uint32_t childIndex = chunk.firstChildIndex; childIndex < chunk.childIndexStop; ++childIndex) - { - subtreeLeafChunkCount += subtreeLeafChunkCounts[childIndex]; - } - EXPECT_EQ(subtreeLeafChunkCount, subtreeLeafChunkCounts[chunkIndex]); - } - EXPECT_EQ(totalLeafChunkCount, a.m_leafChunkCount); - } - - void testChunkToNodeMap(const Nv::Blast::Asset& a) - { - for (uint32_t chunkIndex = 0; chunkIndex < a.m_chunkCount; ++chunkIndex) - { - const uint32_t nodeIndex = a.getChunkToGraphNodeMap()[chunkIndex]; - if (!Nv::Blast::isInvalidIndex(nodeIndex)) - { - EXPECT_LT(nodeIndex, a.m_graph.m_nodeCount); - EXPECT_EQ(chunkIndex, a.m_graph.getChunkIndices()[nodeIndex]); - } - else - { - const uint32_t* chunkIndexStop = a.m_graph.getChunkIndices() + a.m_graph.m_nodeCount; - const uint32_t* it = std::find<const uint32_t*, uint32_t>(a.m_graph.getChunkIndices(), chunkIndexStop, chunkIndex); - EXPECT_EQ(chunkIndexStop, it); - } - } - } - - NvBlastAsset* buildAsset(const ExpectedAssetValues& expected, const NvBlastAssetDesc* desc) - { - std::vector<char> scratch; - scratch.resize((size_t)NvBlastGetRequiredScratchForCreateAsset(desc, messageLog)); - void* mem = alloc(NvBlastGetAssetMemorySize(desc, messageLog)); - NvBlastAsset* asset = NvBlastCreateAsset(mem, desc, &scratch[0], messageLog); - EXPECT_TRUE(asset != nullptr); - if (asset == nullptr) - { - free(mem); - return nullptr; - } - Nv::Blast::Asset& a = *(Nv::Blast::Asset*)asset; - EXPECT_EQ(expected.totalChunkCount, a.m_chunkCount); - EXPECT_EQ(expected.graphNodeCount, a.m_graph.m_nodeCount); - EXPECT_EQ(expected.bondCount, a.m_graph.getAdjacencyPartition()[a.m_graph.m_nodeCount] / 2); - EXPECT_EQ(expected.leafChunkCount, a.m_leafChunkCount); - EXPECT_EQ(expected.subsupportChunkCount, a.m_chunkCount - a.m_firstSubsupportChunkIndex); - testSubtreeLeafChunkCounts(a); - testChunkToNodeMap(a); - return asset; - } - - void checkAssetsExpected(Nv::Blast::Asset& asset, const ExpectedAssetValues& expected) - { - EXPECT_EQ(expected.totalChunkCount, asset.m_chunkCount); - EXPECT_EQ(expected.graphNodeCount, asset.m_graph.m_nodeCount); - EXPECT_EQ(expected.bondCount, asset.m_graph.getAdjacencyPartition()[asset.m_graph.m_nodeCount] / 2); - EXPECT_EQ(expected.leafChunkCount, asset.m_leafChunkCount); - EXPECT_EQ(expected.subsupportChunkCount, asset.m_chunkCount - asset.m_firstSubsupportChunkIndex); - testSubtreeLeafChunkCounts(asset); - testChunkToNodeMap(asset); - } - - void buildAssetShufflingDescriptors(const NvBlastAssetDesc* desc, const ExpectedAssetValues& expected, uint32_t shuffleCount, bool useTk) - { - NvBlastAssetDesc shuffledDesc = *desc; - std::vector<NvBlastChunkDesc> chunkDescs(desc->chunkDescs, desc->chunkDescs + desc->chunkCount); - shuffledDesc.chunkDescs = &chunkDescs[0]; - std::vector<NvBlastBondDesc> bondDescs(desc->bondDescs, desc->bondDescs + desc->bondCount); - shuffledDesc.bondDescs = &bondDescs[0]; - if (!useTk) - { - std::vector<char> scratch(desc->chunkCount); - NvBlastEnsureAssetExactSupportCoverage(chunkDescs.data(), desc->chunkCount, scratch.data(), messageLog); - } - else - { - NvBlastTkFrameworkGet()->ensureAssetExactSupportCoverage(chunkDescs.data(), desc->chunkCount); - } - for (uint32_t i = 0; i < shuffleCount; ++i) - { - shuffleAndFixChunkDescs(&chunkDescs[0], desc->chunkCount, &bondDescs[0], desc->bondCount, useTk); - NvBlastAsset* asset = buildAsset(expected, &shuffledDesc); - EXPECT_TRUE(asset != nullptr); - if (asset) - { - free(asset); - } - } - } - - void shuffleAndFixChunkDescs(NvBlastChunkDesc* chunkDescs, uint32_t chunkDescCount, NvBlastBondDesc* bondDescs, uint32_t bondDescCount, bool useTk) - { - // Create reorder array and fill with identity map - std::vector<uint32_t> shuffledOrder(chunkDescCount); - for (uint32_t i = 0; i < chunkDescCount; ++i) - { - shuffledOrder[i] = i; - } - - // An array into which to copy the reordered descs - std::vector<NvBlastChunkDesc> shuffledChunkDescs(chunkDescCount); - - std::vector<char> scratch; - const uint32_t trials = 30; - uint32_t attempt = 0; - while(1) - { - // Shuffle the reorder array - std::random_shuffle(shuffledOrder.begin(), shuffledOrder.end()); - - // Save initial bonds - std::vector<NvBlastBondDesc> savedBondDescs(bondDescs, bondDescs + bondDescCount); - - // Shuffle chunks and bonds - NvBlastApplyAssetDescChunkReorderMap(shuffledChunkDescs.data(), chunkDescs, chunkDescCount, bondDescs, bondDescCount, shuffledOrder.data(), nullptr); - - // Check the results - for (uint32_t i = 0; i < chunkDescCount; ++i) - { - EXPECT_EQ(chunkDescs[i].userData, shuffledChunkDescs[shuffledOrder[i]].userData); - EXPECT_TRUE(chunkDescs[i].parentChunkIndex > chunkDescCount || shuffledChunkDescs[shuffledOrder[i]].parentChunkIndex == shuffledOrder[chunkDescs[i].parentChunkIndex]); - } - for (uint32_t i = 0; i < bondDescCount; ++i) - { - for (uint32_t k = 0; k < 2; ++k) - { - EXPECT_EQ(shuffledOrder[savedBondDescs[i].chunkIndices[k]], bondDescs[i].chunkIndices[k]); - } - } - - // Try creating asset, usually it should fail (otherwise make another attempt) - NvBlastAssetDesc desc = { chunkDescCount, shuffledChunkDescs.data(), bondDescCount, bondDescs }; - scratch.resize((size_t)NvBlastGetRequiredScratchForCreateAsset(&desc, nullptr)); - void* mem = alloc(NvBlastGetAssetMemorySize(&desc, nullptr)); - NvBlastAsset* asset = NvBlastCreateAsset(mem, &desc, scratch.data(), nullptr); - if (asset == nullptr) - { - free(mem); - break; - } - else - { - free(asset); - memcpy(bondDescs, savedBondDescs.data(), sizeof(NvBlastBondDesc) * bondDescCount); - attempt++; - if (attempt >= trials) - { - GTEST_NONFATAL_FAILURE_("Shuffled chunk descs should fail asset creation (most of the time)."); - break; - } - } - } - - // Now we want to fix that order - if (!useTk) - { - std::vector<uint32_t> chunkReorderMap(chunkDescCount); - std::vector<char> scratch2(2 * chunkDescCount * sizeof(uint32_t)); - const bool isIdentity = NvBlastBuildAssetDescChunkReorderMap(chunkReorderMap.data(), shuffledChunkDescs.data(), chunkDescCount, scratch2.data(), messageLog); - EXPECT_FALSE(isIdentity); - NvBlastApplyAssetDescChunkReorderMap(chunkDescs, shuffledChunkDescs.data(), chunkDescCount, bondDescs, bondDescCount, chunkReorderMap.data(), messageLog); - } - else - { - memcpy(chunkDescs, shuffledChunkDescs.data(), chunkDescCount * sizeof(NvBlastChunkDesc)); - const bool isIdentity = NvBlastTkFrameworkGet()->reorderAssetDescChunks(chunkDescs, chunkDescCount, bondDescs, bondDescCount); - EXPECT_FALSE(isIdentity); - } - } -}; - -typedef AssetTest<NvBlastMessage::Error, 0> AssetTestAllowWarningsSilently; -typedef AssetTest<NvBlastMessage::Error, 1> AssetTestAllowWarnings; -typedef AssetTest<NvBlastMessage::Warning, 1> AssetTestStrict; - - -TEST_F(AssetTestStrict, BuildAssets) -{ - const uint32_t assetDescCount = sizeof(g_assetDescs) / sizeof(g_assetDescs[0]); - - std::vector<NvBlastAsset*> assets(assetDescCount); - - // Build - for (uint32_t i = 0; i < assetDescCount; ++i) - { - assets[i] = buildAsset(g_assetExpectedValues[i], &g_assetDescs[i]); - } - - // Destroy - for (uint32_t i = 0; i < assetDescCount; ++i) - { - if (assets[i]) - { - free(assets[i]); - } - } -} - -#if ENABLE_SERIALIZATION_TESTS -// Restricting this test to windows since we don't have a handy cross platform temp file. -#if defined(WIN32) || defined(WIN64) -TEST_F(AssetTestStrict, SerializeAssetIntoFile) -{ - const uint32_t assetDescCount = sizeof(g_assetDescs) / sizeof(g_assetDescs[0]); - - std::vector<Nv::Blast::Asset *> assets(assetDescCount); - - // Build - for (uint32_t i = 0; i < assetDescCount; ++i) - { - assets[i] = reinterpret_cast<Nv::Blast::Asset*>(buildAsset(g_assetExpectedValues[i], &g_assetDescs[i])); - } - - char tempPath[1024]; - GetTempPathA(1024, tempPath); - - char tempFilename[1024]; - - GetTempFileNameA(tempPath, nullptr, 0, tempFilename); - - std::ofstream myFile(tempFilename, std::ios::out | std::ios::binary); - - EXPECT_TRUE(serializeAssetIntoStream(assets[0], myFile)); - - myFile.flush(); - - // Load it back - - std::ifstream myFileReader(tempFilename, std::ios::binary); - - Nv::Blast::Asset* rtAsset = reinterpret_cast<Nv::Blast::Asset *>(deserializeAssetFromStream(myFileReader)); - EXPECT_TRUE(rtAsset != nullptr); - - checkAssetsExpected(*rtAsset, g_assetExpectedValues[0]); - - for (uint32_t i = 0; i < assetDescCount; ++i) - { - free(assets[i]); - } - free(rtAsset); -} -#endif - -TEST_F(AssetTestStrict, SerializeAssetsNewBuffer) -{ - const uint32_t assetDescCount = sizeof(g_assetDescs) / sizeof(g_assetDescs[0]); - - std::vector<Nv::Blast::Asset *> assets(assetDescCount); - - // Build - for (uint32_t i = 0; i < assetDescCount; ++i) - { - assets[i] = reinterpret_cast<Nv::Blast::Asset*>(buildAsset(g_assetExpectedValues[i], &g_assetDescs[i])); - } - - // Serialize them - for (Nv::Blast::Asset* asset : assets) - { - uint32_t size = 0; - unsigned char* buffer = nullptr; - - -// auto result = Nv::Blast::BlastSerialization<Nv::Blast::Asset, Nv::Blast::Serialization::Asset::Reader, Nv::Blast::Serialization::Asset::Builder>::serializeIntoNewBuffer(asset, &buffer, size); - EXPECT_TRUE(serializeAssetIntoNewBuffer(asset, &buffer, size)); - - free(static_cast<void*>(buffer)); - } - - // Destroy - for (uint32_t i = 0; i < assetDescCount; ++i) - { - if (assets[i]) - { - free(assets[i]); - } - } - -} - -TEST_F(AssetTestStrict, SerializeAssetsExistingBuffer) -{ - const uint32_t assetDescCount = sizeof(g_assetDescs) / sizeof(g_assetDescs[0]); - - std::vector<Nv::Blast::Asset *> assets(assetDescCount); - - // Build - for (uint32_t i = 0; i < assetDescCount; ++i) - { - assets[i] = reinterpret_cast<Nv::Blast::Asset*>(buildAsset(g_assetExpectedValues[i], &g_assetDescs[i])); - } - - // How big does our buffer need to be? Guess. - - uint32_t maxSize = 1024 * 1024; - void* buffer = alloc(maxSize); - - // Serialize them - for (Nv::Blast::Asset* asset : assets) - { - uint32_t usedSize = 0; - - EXPECT_TRUE(serializeAssetIntoExistingBuffer(asset, (unsigned char *)buffer, maxSize, usedSize)); - } - - free(static_cast<void*>(buffer)); - - // Destroy - for (uint32_t i = 0; i < assetDescCount; ++i) - { - if (assets[i]) - { - free(assets[i]); - } - } - -} - -TEST_F(AssetTestStrict, SerializeAssetsRoundTrip) -{ - const uint32_t assetDescCount = sizeof(g_assetDescs) / sizeof(g_assetDescs[0]); - - std::vector<Nv::Blast::Asset *> assets(assetDescCount); - - // Build - for (uint32_t i = 0; i < assetDescCount; ++i) - { - assets[i] = reinterpret_cast<Nv::Blast::Asset*>(buildAsset(g_assetExpectedValues[i], &g_assetDescs[i])); - } - - // Serialize them - for (uint32_t i = 0; i < assetDescCount; ++i) - { - Nv::Blast::Asset* asset = assets[i]; - uint32_t size = 0; - unsigned char* buffer = nullptr; - - EXPECT_TRUE(serializeAssetIntoNewBuffer(asset, &buffer, size)); - - // No release needed for this asset since it's never put into that system - Nv::Blast::Asset* rtAsset = reinterpret_cast<Nv::Blast::Asset*>(deserializeAsset(buffer, size)); - - //TODO: Compare assets - checkAssetsExpected(*rtAsset, g_assetExpectedValues[i]); - - free(static_cast<void*>(buffer)); - free(static_cast<void*>(rtAsset)); - } - - // Destroy - for (uint32_t i = 0; i < assetDescCount; ++i) - { - if (assets[i]) - { - free(assets[i]); - } - } -} -#endif - - -#if 0 -TEST_F(AssetTestStrict, AssociateAsset) -{ - const uint32_t assetDescCount = sizeof(g_assetDescs) / sizeof(g_assetDescs[0]); - - for (uint32_t i = 0; i < assetDescCount; ++i) - { - // Build - NvBlastAsset asset; - if (!buildAsset(&asset, g_assetExpectedValues[i], &g_assetDescs[i])) - { - continue; - } - - // Copy - const char* data = (const char*)NvBlastAssetGetData(&asset, messageLog); - const size_t dataSize = NvBlastAssetDataGetSize(data, messageLog); - NvBlastAsset duplicate; - char* duplicateData = (char*)alloc(dataSize); - memcpy(duplicateData, data, dataSize); - const bool assetAssociateResult = NvBlastAssetAssociateData(&duplicate, duplicateData, messageLog); - EXPECT_TRUE(assetAssociateResult); - - // Destroy - NvBlastAssetFreeData(&asset, free, messageLog); - NvBlastAssetFreeData(&duplicate, free, messageLog); - } -} -#endif - -TEST_F(AssetTestAllowWarnings, BuildAssetsMissingCoverage) -{ - const uint32_t assetDescCount = sizeof(g_assetDescsMissingCoverage) / sizeof(g_assetDescsMissingCoverage[0]); - - std::vector<NvBlastAsset*> assets(assetDescCount); - - // Build - for (uint32_t i = 0; i < assetDescCount; ++i) - { - const NvBlastAssetDesc* desc = &g_assetDescsMissingCoverage[i]; - NvBlastAssetDesc fixedDesc = *desc; - std::vector<NvBlastChunkDesc> chunkDescs(desc->chunkDescs, desc->chunkDescs + desc->chunkCount); - std::vector<NvBlastBondDesc> bondDescs(desc->bondDescs, desc->bondDescs + desc->bondCount); - std::vector<uint32_t> chunkReorderMap(desc->chunkCount); - std::vector<char> scratch(desc->chunkCount * sizeof(NvBlastChunkDesc)); - const bool changedCoverage = !NvBlastEnsureAssetExactSupportCoverage(chunkDescs.data(), fixedDesc.chunkCount, scratch.data(), messageLog); - EXPECT_TRUE(changedCoverage); - NvBlastReorderAssetDescChunks(chunkDescs.data(), fixedDesc.chunkCount, bondDescs.data(), fixedDesc.bondCount, chunkReorderMap.data(), scratch.data(), messageLog); - fixedDesc.chunkDescs = chunkDescs.data(); - fixedDesc.bondDescs = bondDescs.data(); - assets[i] = buildAsset(g_assetsFromMissingCoverageExpectedValues[i], &fixedDesc); - } - - // Destroy - for (uint32_t i = 0; i < assetDescCount; ++i) - { - if (assets[i]) - { - free(assets[i]); - } - } -} - -TEST_F(AssetTestAllowWarningsSilently, BuildAssetsShufflingChunkDescriptors) -{ - for (uint32_t i = 0; i < sizeof(g_assetDescs) / sizeof(g_assetDescs[0]); ++i) - { - buildAssetShufflingDescriptors(&g_assetDescs[i], g_assetExpectedValues[i], 10, false); - } - - for (uint32_t i = 0; i < sizeof(g_assetDescsMissingCoverage) / sizeof(g_assetDescsMissingCoverage[0]); ++i) - { - buildAssetShufflingDescriptors(&g_assetDescsMissingCoverage[i], g_assetsFromMissingCoverageExpectedValues[i], 10, false); - } -} - -TEST_F(AssetTestAllowWarningsSilently, BuildAssetsShufflingChunkDescriptorsUsingTk) -{ - for (uint32_t i = 0; i < sizeof(g_assetDescs) / sizeof(g_assetDescs[0]); ++i) - { - buildAssetShufflingDescriptors(&g_assetDescs[i], g_assetExpectedValues[i], 10, true); - } - - for (uint32_t i = 0; i < sizeof(g_assetDescsMissingCoverage) / sizeof(g_assetDescsMissingCoverage[0]); ++i) - { - buildAssetShufflingDescriptors(&g_assetDescsMissingCoverage[i], g_assetsFromMissingCoverageExpectedValues[i], 10, true); - } -} diff --git a/NvBlast/test/src/unit/CoreTests.cpp b/NvBlast/test/src/unit/CoreTests.cpp deleted file mode 100644 index 4aff4ae..0000000 --- a/NvBlast/test/src/unit/CoreTests.cpp +++ /dev/null @@ -1,293 +0,0 @@ -#include <algorithm> -#include "gtest/gtest.h" - -//#include "NvBlast.h" -#include "NvBlastActor.h" -#include "NvBlastIndexFns.h" - -#include "AlignedAllocator.h" - -#include "TestAssets.h" -#include "NvBlastActor.h" - -static void messageLog(int type, const char* msg, const char* file, int line) -{ - { - switch (type) - { - case NvBlastMessage::Error: std::cout << "NvBlast Error message in " << file << "(" << line << "): " << msg << "\n"; break; - case NvBlastMessage::Warning: std::cout << "NvBlast Warning message in " << file << "(" << line << "): " << msg << "\n"; break; - case NvBlastMessage::Info: std::cout << "NvBlast Info message in " << file << "(" << line << "): " << msg << "\n"; break; - case NvBlastMessage::Debug: std::cout << "NvBlast Debug message in " << file << "(" << line << "): " << msg << "\n"; break; - } - } -} - -TEST(CoreTests, IndexStartLookup) -{ - uint32_t lookup[32]; - uint32_t indices[] = {1,1,2,2,4,4,4}; - - Nv::Blast::createIndexStartLookup<uint32_t>(lookup, 0, 30, indices, 7, 4); - - EXPECT_EQ(lookup[0], 0); - EXPECT_EQ(lookup[1], 0); - EXPECT_EQ(lookup[2], 2); - EXPECT_EQ(lookup[3], 4); - EXPECT_EQ(lookup[4], 4); - EXPECT_EQ(lookup[5], 7); - EXPECT_EQ(lookup[31], 7); -} - -#include "NvBlastGeometry.h" - -TEST(CoreTests, FindChunkByPosition) -{ - std::vector<char> scratch; - const NvBlastAssetDesc& desc = g_assetDescs[0]; // 1-cube - scratch.resize((size_t)NvBlastGetRequiredScratchForCreateAsset(&desc, nullptr)); - void* amem = alignedAlloc<malloc>(NvBlastGetAssetMemorySize(&desc, nullptr)); - NvBlastAsset* asset = NvBlastCreateAsset(amem, &desc, &scratch[0], nullptr); - ASSERT_TRUE(asset != nullptr); - - uint32_t expectedNode[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; - const float positions[] = { - -2.0f, -2.0f, -2.0f, - +2.0f, -2.0f, -2.0f, - -2.0f, +2.0f, -2.0f, - +2.0f, +2.0f, -2.0f, - -2.0f, -2.0f, +2.0f, - +2.0f, -2.0f, +2.0f, - -2.0f, +2.0f, +2.0f, - +2.0f, +2.0f, +2.0f, - }; - const float* pos = &positions[0]; - - NvBlastActorDesc actorDesc; - actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr; - actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f; - void* fmem = alignedAlloc<malloc>(NvBlastAssetGetFamilyMemorySize(asset, nullptr)); - NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, nullptr); - scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, nullptr)); - NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, &scratch[0], nullptr); - ASSERT_TRUE(actor != nullptr); - - std::vector<uint32_t> graphNodeIndices; - graphNodeIndices.resize(NvBlastActorGetGraphNodeCount(actor, nullptr)); - const float* bondHealths = NvBlastActorGetBondHealths(actor, messageLog); - uint32_t graphNodesCount = NvBlastActorGetGraphNodeIndices(graphNodeIndices.data(), (uint32_t)graphNodeIndices.size(), actor, nullptr); - - const NvBlastBond* bonds = NvBlastAssetGetBonds(asset, nullptr); - NvBlastSupportGraph graph = NvBlastAssetGetSupportGraph(asset, nullptr); - for (int i = 0; i < 8; ++i, pos += 3) - { - EXPECT_EQ(expectedNode[i], Nv::Blast::findNodeByPosition(pos, graphNodesCount, graphNodeIndices.data(), graph, bonds, bondHealths)); - EXPECT_EQ(expectedNode[i] + 1, NvBlastActorClosestChunk(pos, actor, nullptr)); // Works because (chunk index) = (node index) + 1 in these cases - } - - EXPECT_TRUE(NvBlastActorDeactivate(actor, nullptr)); - alignedFree<free>(family); - alignedFree<free>(asset); -} - -TEST(CoreTests, FindChunkByPositionUShape) -{ - /* - considering this graph - - 4->5->6 - ^ - | - 1->2->3 - - and trying to find chunks by some position - */ - const NvBlastChunkDesc uchunks[7] = - { - // centroid volume parent idx flags ID - { {0.0f, 0.0f, 0.0f}, 0.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 0 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 1 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 2 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 3 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 4 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 5 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 6 } - }; - - const NvBlastBondDesc ubonds[5] = - { - // chunks normal area centroid userData - { { 2, 1 }, { { 1.0f, 0.0f, 0.0f }, 1.0f, { 2.0f, 1.0f, 0.0f }, 0 } }, // index swap should not matter - { { 2, 3 }, { { 1.0f, 0.0f, 0.0f }, 1.0f, { 4.0f, 1.0f, 0.0f }, 0 } }, - { { 1, 4 }, { { 0.0f, 1.0f, 0.0f }, 1.0f, { 1.0f, 2.0f, 0.0f }, 0 } }, - { { 4, 5 }, { { 1.0f, 0.0f, 0.0f }, 1.0f, { 2.0f, 3.0f, 0.0f }, 0 } }, - { { 5, 6 }, { { 1.0f, 0.0f, 0.0f }, 1.0f, { 4.0f, 3.0f, 0.0f }, 0 } }, - }; - - const NvBlastAssetDesc desc = { 7, uchunks, 5, ubonds }; - std::vector<char> scratch; - scratch.resize((size_t)NvBlastGetRequiredScratchForCreateAsset(&desc, messageLog)); - void* amem = alignedAlloc<malloc>(NvBlastGetAssetMemorySize(&desc, messageLog)); - NvBlastAsset* asset = NvBlastCreateAsset(amem, &desc, &scratch[0], messageLog); - ASSERT_TRUE(asset != nullptr); - - NvBlastActorDesc actorDesc; - actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr; - actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f; - void* fmem = alignedAlloc<malloc>(NvBlastAssetGetFamilyMemorySize(asset, messageLog)); - NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, nullptr); - scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, messageLog)); - NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, &scratch[0], nullptr); - ASSERT_TRUE(actor != nullptr); - - std::vector<uint32_t> graphNodeIndices; - graphNodeIndices.resize(NvBlastActorGetGraphNodeCount(actor, nullptr)); - uint32_t graphNodesCount = NvBlastActorGetGraphNodeIndices(graphNodeIndices.data(), (uint32_t)graphNodeIndices.size(), actor, nullptr); - - const NvBlastBond* bonds = NvBlastAssetGetBonds(asset, nullptr); - NvBlastSupportGraph graph = NvBlastAssetGetSupportGraph(asset, nullptr); - - srand(100); - for (uint32_t i = 0; i < 100000; i++) - { - float rx = 20 * (float)(rand() - 1) / RAND_MAX - 10; - float ry = 20 * (float)(rand() - 1) / RAND_MAX - 10; - float rz = 0.0f; - float rpos[] = { rx, ry, rz }; - - // open boundaries - uint32_t col = std::max(0, std::min(2, int(rx / 2))); - uint32_t row = std::max(0, std::min(1, int(ry / 2))); - uint32_t expectedNode = col + row * 3; - - //printf("iteration %i: %.1f %.1f %.1f expected: %d\n", i, rpos[0], rpos[1], rpos[2], expectedNode); - { - uint32_t returnedNode = Nv::Blast::findNodeByPosition(rpos, graphNodesCount, graphNodeIndices.data(), graph, bonds, NvBlastActorGetBondHealths(actor, messageLog)); - if (expectedNode != returnedNode) - Nv::Blast::findNodeByPosition(rpos, graphNodesCount, graphNodeIndices.data(), graph, bonds, NvBlastActorGetBondHealths(actor, messageLog)); - EXPECT_EQ(expectedNode, returnedNode); - } - { - // +1 to account for graph vs. asset indices - uint32_t expectedChunk = expectedNode + 1; - uint32_t returnedChunk = NvBlastActorClosestChunk(rpos, actor, nullptr); - if (expectedChunk != returnedChunk) - NvBlastActorClosestChunk(rpos, actor, nullptr); - EXPECT_EQ(expectedChunk, returnedChunk); - } - - } - - EXPECT_TRUE(NvBlastActorDeactivate(actor, messageLog)); - - alignedFree<free>(family); - alignedFree<free>(asset); -} - -TEST(CoreTests, FindChunkByPositionLandlocked) -{ - const NvBlastChunkDesc chunks[10] = - { - // centroid volume parent idx flags ID - { {0.0f, 0.0f, 0.0f}, 0.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 0 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 1 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 2 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 3 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 4 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 5 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 6 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 7 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 8 }, - { {0.0f, 0.0f, 0.0f}, 0.0f, 0, NvBlastChunkDesc::SupportFlag, 9 }, - }; - - const NvBlastBondDesc bonds[12] = - { - // chunks normal area centroid userData - { { 1, 2 }, { { 1.0f, 0.0f, 0.0f }, 1.0f, { 2.0f, 1.0f, 0.0f }, 0 } }, - { { 2, 3 }, { { 1.0f, 0.0f, 0.0f }, 1.0f, { 4.0f, 1.0f, 0.0f }, 0 } }, - { { 4, 5 }, { { 1.0f, 0.0f, 0.0f }, 1.0f, { 2.0f, 3.0f, 0.0f }, 0 } }, - { { 5, 6 }, { { 1.0f, 0.0f, 0.0f }, 1.0f, { 4.0f, 3.0f, 0.0f }, 0 } }, - { { 7, 8 }, { { 1.0f, 0.0f, 0.0f }, 1.0f, { 2.0f, 5.0f, 0.0f }, 0 } }, - { { 8, 9 }, { { 1.0f, 0.0f, 0.0f }, 1.0f, { 4.0f, 5.0f, 0.0f }, 0 } }, - { { 1, 4 }, { { 0.0f, 1.0f, 0.0f }, 1.0f, { 1.0f, 2.0f, 0.0f }, 0 } }, - { { 2, 5 }, { { 0.0f, 1.0f, 0.0f }, 1.0f, { 3.0f, 2.0f, 0.0f }, 0 } }, - { { 3, 6 }, { { 0.0f, 1.0f, 0.0f }, 1.0f, { 5.0f, 2.0f, 0.0f }, 0 } }, - { { 4, 7 }, { { 0.0f, 1.0f, 0.0f }, 1.0f, { 1.0f, 4.0f, 0.0f }, 0 } }, - { { 5, 8 }, { { 0.0f, 1.0f, 0.0f }, 1.0f, { 3.0f, 4.0f, 0.0f }, 0 } }, - { { 6, 9 }, { { 0.0f, 1.0f, 0.0f }, 1.0f, { 5.0f, 4.0f, 0.0f }, 0 } }, - }; - - const NvBlastAssetDesc desc = { 10, chunks, 12, bonds }; - std::vector<char> scratch; - scratch.resize((size_t)NvBlastGetRequiredScratchForCreateAsset(&desc, messageLog)); - void* amem = alignedAlloc<malloc>(NvBlastGetAssetMemorySize(&desc, messageLog)); - NvBlastAsset* asset = NvBlastCreateAsset(amem, &desc, &scratch[0], messageLog); - ASSERT_TRUE(asset != nullptr); - - NvBlastActorDesc actorDesc; - actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr; - actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f; - void* fmem = alignedAlloc<malloc>(NvBlastAssetGetFamilyMemorySize(asset, nullptr)); - NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, nullptr); - scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, nullptr)); - NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, &scratch[0], nullptr); - ASSERT_TRUE(actor != nullptr); - - const NvBlastBond* assetBonds = NvBlastAssetGetBonds(asset, nullptr); - NvBlastSupportGraph graph = NvBlastAssetGetSupportGraph(asset, nullptr); - - float point[4] = { 3.0f, 3.0f, 0.0f }; - EXPECT_EQ(5, NvBlastActorClosestChunk(point, actor, nullptr)); - { - std::vector<uint32_t> graphNodeIndices; - graphNodeIndices.resize(NvBlastActorGetGraphNodeCount(actor, nullptr)); - uint32_t graphNodesCount = NvBlastActorGetGraphNodeIndices(graphNodeIndices.data(), (uint32_t)graphNodeIndices.size(), actor, nullptr); - - EXPECT_EQ(4, Nv::Blast::findNodeByPosition(point, graphNodesCount, graphNodeIndices.data(), graph, assetBonds, NvBlastActorGetBondHealths(actor, messageLog))); - } - - NvBlastChunkFractureData chunkBuffer[1]; - NvBlastFractureBuffers events = { 0, 1, nullptr, chunkBuffer }; - - NvBlastChunkFractureData chunkFracture = { 0, 5, 1.0f }; - NvBlastFractureBuffers commands = { 0, 1, nullptr, &chunkFracture }; - - NvBlastActorApplyFracture(&events, actor, &commands, messageLog, nullptr); - EXPECT_EQ(1, events.chunkFractureCount); - - NvBlastActor* newActors[5]; - NvBlastActorSplitEvent splitEvent = { nullptr, newActors }; - scratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, messageLog)); - size_t newActorsCount = NvBlastActorSplit(&splitEvent, actor, 5, scratch.data(), messageLog, nullptr); - - ASSERT_EQ(actor, newActors[1]); - - EXPECT_NE(5, NvBlastActorClosestChunk(point, actor, nullptr)); - - float point2[4] = { 80.0f, 80.0f, 80.0f }; - EXPECT_EQ(5, NvBlastActorClosestChunk(point2, newActors[0], nullptr)); - - { - const float* bondHealths = NvBlastActorGetBondHealths(actor, messageLog); - std::vector<uint32_t> graphNodeIndices; - graphNodeIndices.resize(NvBlastActorGetGraphNodeCount(actor, nullptr)); - uint32_t graphNodesCount = NvBlastActorGetGraphNodeIndices(graphNodeIndices.data(), (uint32_t)graphNodeIndices.size(), actor, nullptr); - - EXPECT_NE(4, Nv::Blast::findNodeByPosition(point, graphNodesCount, graphNodeIndices.data(), graph, assetBonds, bondHealths)); - - graphNodeIndices.resize(NvBlastActorGetGraphNodeCount(newActors[0], nullptr)); - graphNodesCount = NvBlastActorGetGraphNodeIndices(graphNodeIndices.data(), (uint32_t)graphNodeIndices.size(), newActors[0], nullptr); - - EXPECT_EQ(4, Nv::Blast::findNodeByPosition(point, graphNodesCount, graphNodeIndices.data(), graph, assetBonds, bondHealths)); - } - - - for (uint32_t i = 0; i < newActorsCount; ++i) - { - EXPECT_TRUE(NvBlastActorDeactivate(newActors[i], nullptr)); - } - - alignedFree<free>(family); - alignedFree<free>(asset); -} diff --git a/NvBlast/test/src/unit/FamilyGraphTests.cpp b/NvBlast/test/src/unit/FamilyGraphTests.cpp deleted file mode 100644 index fdb9738..0000000 --- a/NvBlast/test/src/unit/FamilyGraphTests.cpp +++ /dev/null @@ -1,377 +0,0 @@ -#include "BlastBaseTest.h" - -#include "NvBlastSupportGraph.h" -#include "NvBlastFamilyGraph.h" -#include "NvBlastAssert.h" -#include "NvBlastIndexFns.h" - -#include <stdlib.h> -#include <ostream> -#include <stdint.h> -#include <map> -#include <algorithm> - - -// ==================================================================================================================== -// HELPERS -// ==================================================================================================================== - -::testing::AssertionResult VectorMatch(const std::vector<uint32_t>& actual, const uint32_t* expected, uint32_t size) -{ - for (size_t i(0); i < size; ++i) - { - if (expected[i] != actual[i]) - { - testing::Message msg; - msg << "array[" << i - << "] (" << actual[i] << ") != expected[" << i - << "] (" << expected[i] << ")"; - return (::testing::AssertionFailure(msg));; - } - } - - return ::testing::AssertionSuccess(); -} - -#define VECTOR_MATCH(actual, ...) \ -{ \ - const uint32_t arr[] = { __VA_ARGS__ }; \ - const uint32_t size = (sizeof(arr) / sizeof(arr[0])); \ - EXPECT_EQ(size, actual.size()); \ - EXPECT_TRUE(VectorMatch(actual, arr, size)); \ -} - - -// ==================================================================================================================== -// TEST CLASS -// ==================================================================================================================== - -using namespace Nv::Blast; - -template<int FailLevel, int Verbosity> -class FamilyGraphTest : public BlastBaseTest < FailLevel, Verbosity > -{ -public: - FamilyGraphTest() - { - } - -protected: - FamilyGraph* buildFamilyGraph(uint32_t chunkCount, const uint32_t* adjacentChunkPartition, const uint32_t* adjacentChunkIndices) - { - NVBLAST_ASSERT(m_memoryBlock.size() == 0); // can't build twice per test - - // Fill SupportGraph with data: - NvBlastCreateOffsetStart(sizeof(SupportGraph)); - const size_t NvBlastCreateOffsetAlign16(chunkIndicesOffset, chunkCount*sizeof(uint32_t)); - const size_t NvBlastCreateOffsetAlign16(adjacencyPartitionOffset, (chunkCount + 1)*sizeof(uint32_t)); - const size_t NvBlastCreateOffsetAlign16(adjacentNodeIndicesOffset, adjacentChunkPartition[chunkCount] * sizeof(uint32_t)); - const size_t NvBlastCreateOffsetAlign16(adjacentBondIndicesOffset, adjacentChunkPartition[chunkCount] * sizeof(uint32_t)); - const size_t graphDataSize = NvBlastCreateOffsetEndAlign16(); - m_graphMemory.resize(graphDataSize); - m_graph = reinterpret_cast<SupportGraph*>(m_graphMemory.data()); - - m_graph->m_nodeCount = chunkCount; - m_graph->m_chunkIndicesOffset = static_cast<uint32_t>(chunkIndicesOffset); - m_graph->m_adjacencyPartitionOffset = static_cast<uint32_t>(adjacencyPartitionOffset); - m_graph->m_adjacentNodeIndicesOffset = static_cast<uint32_t>(adjacentNodeIndicesOffset); - m_graph->m_adjacentBondIndicesOffset = static_cast<uint32_t>(adjacentBondIndicesOffset); - - memcpy(m_graph->getAdjacencyPartition(), adjacentChunkPartition, (chunkCount + 1) * sizeof(uint32_t)); - memcpy(m_graph->getAdjacentNodeIndices(), adjacentChunkIndices, adjacentChunkPartition[chunkCount] * sizeof(uint32_t)); - - // fill bondIndices by incrementing bondIndex and putting same bondIndex in mirror bond index for (n0, n1) == (n1, n0) - memset(m_graph->getAdjacentBondIndices(), (uint32_t)-1, adjacentChunkPartition[chunkCount] * sizeof(uint32_t)); - uint32_t bondIndex = 0; - for (uint32_t chunk0 = 0; chunk0 < m_graph->m_nodeCount; chunk0++) - { - for (uint32_t i = m_graph->getAdjacencyPartition()[chunk0]; i < m_graph->getAdjacencyPartition()[chunk0 + 1]; i++) - { - if (m_graph->getAdjacentBondIndices()[i] == (uint32_t)-1) - { - m_graph->getAdjacentBondIndices()[i] = bondIndex; - - uint32_t chunk1 = m_graph->getAdjacentNodeIndices()[i]; - for (uint32_t j = m_graph->getAdjacencyPartition()[chunk1]; j < m_graph->getAdjacencyPartition()[chunk1 + 1]; j++) - { - if (m_graph->getAdjacentNodeIndices()[j] == chunk0) - { - m_graph->getAdjacentBondIndices()[j] = bondIndex; - } - } - bondIndex++; - } - } - } - - // reserve memory for family graph and asset pointer - uint32_t familyGraphMemorySize = (uint32_t)FamilyGraph::requiredMemorySize(m_graph->m_nodeCount, bondIndex); - m_memoryBlock.resize(familyGraphMemorySize); - // placement new family graph - FamilyGraph* familyGraph = new(&m_memoryBlock[0]) FamilyGraph(m_graph); - - return familyGraph; - } - - struct IslandInfo - { - std::vector<NodeIndex> nodes; - }; - - /** - Function to gather islands info for tests and debug purposes - Returned islands sorted by nodes counts. Island nodes also sorted by NodeIndex. - */ - void getIslandsInfo(const FamilyGraph& graph, std::vector<IslandInfo>& info) - { - IslandId* islandIds = graph.getIslandIds(); - - std::map<IslandId, IslandInfo> islandMap; - - for (NodeIndex n = 0; n < m_graph->m_nodeCount; n++) - { - EXPECT_TRUE(islandIds[n] != invalidIndex<uint32_t>()); - IslandId islandId = islandIds[n]; - if (islandMap.find(islandId) == islandMap.end()) - { - IslandInfo info; - info.nodes.push_back(n); - islandMap[islandId] = info; - } - else - { - islandMap[islandId].nodes.push_back(n); - } - } - - for (auto it = islandMap.begin(); it != islandMap.end(); ++it) - { - std::sort(it->second.nodes.begin(), it->second.nodes.end()); - info.push_back(it->second); - } - - // sort islands by size ascending - std::sort(info.begin(), info.end(), [](const IslandInfo& i0, const IslandInfo& i1) -> bool - { - size_t s0 = i0.nodes.size(); - size_t s1 = i1.nodes.size(); - if (s0 == s1 && s0 > 0) - { - s0 = i0.nodes[0]; - s1 = i1.nodes[0]; - } - return s0 < s1; - }); - } - - static const uint32_t DEFAULT_ACTOR_INDEX = 0; - - SupportGraph* m_graph; - std::vector<char> m_graphMemory; - std::vector<char> m_memoryBlock; -}; - -typedef FamilyGraphTest<NvBlastMessage::Error, 1> FamilyGraphTestAllowWarnings; -typedef FamilyGraphTest<NvBlastMessage::Warning, 1> FamilyGraphTestStrict; - - -// ==================================================================================================================== -// GRAPH DATA -// ==================================================================================================================== - -// Graph 0: -// -// 0 -- 1 -- 2 -- 3 -// | | | | -// | | | | -// 4 -- 5 6 -- 7 -// -const uint32_t chunkCount0 = 8; -const uint32_t adjacentChunkPartition0[] = { 0, 2, 5, 8, 10, 12, 14, 16, 18 }; -const uint32_t adjacentChunkIndices0[] = { /*0*/ 1, 4, /*1*/ 0, 2, 5, /*2*/ 1, 3, 6, /*3*/ 2, 7, /*4*/ 0, 5, /*5*/ 1, 4, /*6*/ 2, 7, /*7*/ 3, 6 }; - - -// Graph 1: -// -// 0 -- 1 -- 2 -- 3 -// | | | | -// 4 -- 5 -- 6 -- 7 -// | | | | -// 8 -- 9 -- 10-- 11 -// -const uint32_t chunkCount1 = 12; -const uint32_t adjacentChunkPartition1[] = { 0, 2, 5, 8, 10, 13, 17, 21, 24, 26, 29, 32, 34 }; -const uint32_t adjacentChunkIndices1[] = { /*0*/ 1, 4, /*1*/ 0, 2, 5, /*2*/ 1, 3, 6, /*3*/ 2, 7, /*4*/ 0, 5, 8, /*5*/ 1, 4, 6, 9, /*6*/ 2, 5, 7, 10, - /*7*/ 3, 6, 11, /*8*/ 4, 9, /*9*/ 5, 8, 10, /*10*/ 6, 9, 11, /*11*/ 7, 10 }; - - -// ==================================================================================================================== -// TESTS -// ==================================================================================================================== - -TEST_F(FamilyGraphTestStrict, Graph0FindIslands0) -{ - FamilyGraph* graph = buildFamilyGraph(chunkCount0, adjacentChunkPartition0, adjacentChunkIndices0); - graph->initialize(DEFAULT_ACTOR_INDEX, m_graph); - - std::vector<char> scratch; - scratch.resize((size_t)FamilyGraph::findIslandsRequiredScratch(chunkCount0)); - - EXPECT_EQ(9, graph->getEdgesCount(m_graph)); - graph->notifyEdgeRemoved(DEFAULT_ACTOR_INDEX, 0, 4, m_graph); - EXPECT_EQ(8, graph->getEdgesCount(m_graph)); - EXPECT_EQ(1, graph->findIslands(DEFAULT_ACTOR_INDEX, &scratch[0], m_graph)); - - graph->notifyEdgeRemoved(DEFAULT_ACTOR_INDEX, 1, 2, m_graph); - EXPECT_EQ(1, graph->findIslands(DEFAULT_ACTOR_INDEX, &scratch[0], m_graph)); - - std::vector<IslandInfo> info; - getIslandsInfo(*graph, info); - EXPECT_EQ(2, info.size()); - VECTOR_MATCH(info[0].nodes, 0, 1, 4, 5); - VECTOR_MATCH(info[1].nodes, 2, 3, 6, 7); -} - -TEST_F(FamilyGraphTestStrict, Graph0FindIslands1) -{ - FamilyGraph* graph = buildFamilyGraph(chunkCount0, adjacentChunkPartition0, adjacentChunkIndices0); - graph->initialize(DEFAULT_ACTOR_INDEX, m_graph); - - std::vector<char> scratch; - scratch.resize((size_t)FamilyGraph::findIslandsRequiredScratch(chunkCount0)); - - graph->notifyEdgeRemoved(DEFAULT_ACTOR_INDEX, 0, 4, m_graph); - graph->notifyEdgeRemoved(DEFAULT_ACTOR_INDEX, 4, 5, m_graph); - graph->notifyEdgeRemoved(DEFAULT_ACTOR_INDEX, 1, 2, m_graph); - EXPECT_EQ(6, graph->getEdgesCount(m_graph)); - EXPECT_EQ(3, graph->findIslands(DEFAULT_ACTOR_INDEX, &scratch[0], m_graph)); - - std::vector<IslandInfo> info; - getIslandsInfo(*graph, info); - EXPECT_EQ(3, info.size()); - VECTOR_MATCH(info[0].nodes, 4); - VECTOR_MATCH(info[1].nodes, 0, 1, 5); - VECTOR_MATCH(info[2].nodes, 2, 3, 6, 7); -} - -TEST_F(FamilyGraphTestStrict, Graph0FindIslandsDifferentActors) -{ - const uint32_t ACTOR_0_INDEX = 5; - const uint32_t ACTOR_1_INDEX = 2; - - FamilyGraph* graph = buildFamilyGraph(chunkCount0, adjacentChunkPartition0, adjacentChunkIndices0); - graph->initialize(ACTOR_0_INDEX, m_graph); - - std::vector<char> scratch; - scratch.resize((size_t)FamilyGraph::findIslandsRequiredScratch(chunkCount0)); - - EXPECT_EQ(0, graph->findIslands(ACTOR_1_INDEX, &scratch[0], m_graph)); - EXPECT_EQ(1, graph->findIslands(ACTOR_0_INDEX, &scratch[0], m_graph)); - - graph->notifyEdgeRemoved(ACTOR_0_INDEX, 2, 1, m_graph); - EXPECT_EQ(8, graph->getEdgesCount(m_graph)); - - EXPECT_EQ(1, graph->findIslands(ACTOR_0_INDEX, &scratch[0], m_graph)); - - graph->notifyEdgeRemoved(ACTOR_1_INDEX, 2, 6, m_graph); - graph->notifyEdgeRemoved(ACTOR_1_INDEX, 7, 3, m_graph); - EXPECT_EQ(1, graph->findIslands(ACTOR_1_INDEX, &scratch[0], m_graph)); - - graph->notifyEdgeRemoved(ACTOR_0_INDEX, 0, 1, m_graph); - graph->notifyEdgeRemoved(ACTOR_0_INDEX, 4, 5, m_graph); - EXPECT_EQ(1, graph->findIslands(ACTOR_0_INDEX, &scratch[0], m_graph)); - - - std::vector<IslandInfo> info; - getIslandsInfo(*graph, info); - EXPECT_EQ(4, info.size()); - VECTOR_MATCH(info[0].nodes, 0, 4); - VECTOR_MATCH(info[1].nodes, 1, 5); - VECTOR_MATCH(info[2].nodes, 2, 3); - VECTOR_MATCH(info[3].nodes, 6, 7); -} - -TEST_F(FamilyGraphTestStrict, Graph1FindIslands0) -{ - FamilyGraph* graph = buildFamilyGraph(chunkCount1, adjacentChunkPartition1, adjacentChunkIndices1); - graph->initialize(DEFAULT_ACTOR_INDEX, m_graph); - - std::vector<char> scratch; - scratch.resize((size_t)FamilyGraph::findIslandsRequiredScratch(chunkCount1)); - - graph->notifyEdgeRemoved(DEFAULT_ACTOR_INDEX, 0, 4, m_graph); - graph->notifyEdgeRemoved(DEFAULT_ACTOR_INDEX, 1, 5, m_graph); - graph->notifyEdgeRemoved(DEFAULT_ACTOR_INDEX, 2, 6, m_graph); - graph->notifyEdgeRemoved(DEFAULT_ACTOR_INDEX, 3, 7, m_graph); - graph->notifyEdgeRemoved(DEFAULT_ACTOR_INDEX, 5, 6, m_graph); - graph->notifyEdgeRemoved(DEFAULT_ACTOR_INDEX, 9, 10, m_graph); - EXPECT_EQ(11, graph->getEdgesCount(m_graph)); - EXPECT_EQ(3, graph->findIslands(DEFAULT_ACTOR_INDEX, &scratch[0], m_graph)); - - std::vector<IslandInfo> info; - getIslandsInfo(*graph, info); - EXPECT_EQ(3, info.size()); - - VECTOR_MATCH(info[0].nodes, 0, 1, 2, 3); - VECTOR_MATCH(info[1].nodes, 4, 5, 8, 9); - VECTOR_MATCH(info[2].nodes, 6, 7, 10, 11); -} - -TEST_F(FamilyGraphTestStrict, Graph1FindIslands1) -{ - FamilyGraph* graph = buildFamilyGraph(chunkCount1, adjacentChunkPartition1, adjacentChunkIndices1); - graph->initialize(DEFAULT_ACTOR_INDEX, m_graph); - - std::vector<char> scratch; - scratch.resize((size_t)FamilyGraph::findIslandsRequiredScratch(chunkCount1)); - - graph->notifyEdgeRemoved(DEFAULT_ACTOR_INDEX, 0, 4, m_graph); - EXPECT_EQ(1, graph->findIslands(DEFAULT_ACTOR_INDEX, &scratch[0], m_graph)); - graph->notifyEdgeRemoved(DEFAULT_ACTOR_INDEX, 1, 5, m_graph); - EXPECT_EQ(0, graph->findIslands(DEFAULT_ACTOR_INDEX, &scratch[0], m_graph)); - graph->notifyEdgeRemoved(DEFAULT_ACTOR_INDEX, 2, 6, m_graph); - EXPECT_EQ(0, graph->findIslands(DEFAULT_ACTOR_INDEX, &scratch[0], m_graph)); - graph->notifyEdgeRemoved(DEFAULT_ACTOR_INDEX, 3, 7, m_graph); - EXPECT_EQ(1, graph->findIslands(DEFAULT_ACTOR_INDEX, &scratch[0], m_graph)); - graph->notifyEdgeRemoved(DEFAULT_ACTOR_INDEX, 5, 6, m_graph); - EXPECT_EQ(0, graph->findIslands(DEFAULT_ACTOR_INDEX, &scratch[0], m_graph)); - graph->notifyEdgeRemoved(DEFAULT_ACTOR_INDEX, 9, 10, m_graph); - EXPECT_EQ(1, graph->findIslands(DEFAULT_ACTOR_INDEX, &scratch[0], m_graph)); - - std::vector<IslandInfo> info; - getIslandsInfo(*graph, info); - EXPECT_EQ(3, info.size()); - VECTOR_MATCH(info[0].nodes, 0, 1, 2, 3); - VECTOR_MATCH(info[1].nodes, 4, 5, 8, 9); - VECTOR_MATCH(info[2].nodes, 6, 7, 10, 11); -} - -TEST_F(FamilyGraphTestStrict, Graph1FindIslandsRemoveAllEdges) -{ - FamilyGraph* graph = buildFamilyGraph(chunkCount1, adjacentChunkPartition1, adjacentChunkIndices1); - graph->initialize(DEFAULT_ACTOR_INDEX, m_graph); - - std::vector<char> scratch; - scratch.resize((size_t)FamilyGraph::findIslandsRequiredScratch(chunkCount1)); - - uint32_t edges = graph->getEdgesCount(m_graph); - for (uint32_t node0 = 0; node0 < chunkCount1; node0++) - { - for (uint32_t i = adjacentChunkPartition1[node0]; i < adjacentChunkPartition1[node0 + 1]; i++) - { - if (graph->notifyEdgeRemoved(DEFAULT_ACTOR_INDEX, node0, adjacentChunkIndices1[i], m_graph)) - { - edges--; - EXPECT_EQ(edges, graph->getEdgesCount(m_graph)); - } - } - } - EXPECT_EQ(0, graph->getEdgesCount(m_graph)); - - EXPECT_EQ(12, graph->findIslands(DEFAULT_ACTOR_INDEX, &scratch[0], m_graph)); - - for (uint32_t node0 = 0; node0 < chunkCount1; node0++) - { - EXPECT_EQ(node0, graph->getIslandIds()[node0]); - } -} diff --git a/NvBlast/test/src/unit/MultithreadingTests.cpp b/NvBlast/test/src/unit/MultithreadingTests.cpp deleted file mode 100644 index f1ae176..0000000 --- a/NvBlast/test/src/unit/MultithreadingTests.cpp +++ /dev/null @@ -1,395 +0,0 @@ -#include "BlastBaseTest.h" -#include "AssetGenerator.h" - -#include <iostream> -#include <memory> -#include "TaskDispatcher.h" - -#include "NvBlastActor.h" -#include "NvBlastExtDamageShaders.h" - -#if NV_XBOXONE -#undef min -#undef max -#endif - -typedef std::function<void(const Nv::Blast::Actor&, NvBlastLog)> ActorTestFunction; -typedef std::function<void(std::vector<NvBlastActor*>&, NvBlastLog)> PostDamageTestFunction; - - -static void blast(std::set<NvBlastActor*>& actorsToDamage, GeneratorAsset* testAsset, GeneratorAsset::Vec3 localPos, float minRadius, float maxRadius, float compressiveDamage) -{ - std::vector<NvBlastChunkFractureData> chunkEvents; /* num lower-support chunks + bonds */ - std::vector<NvBlastBondFractureData> bondEvents; /* num lower-support chunks + bonds */ - chunkEvents.resize(testAsset->solverChunks.size()); - bondEvents.resize(testAsset->solverBonds.size()); - - NvBlastFractureBuffers events = { static_cast<uint32_t>(bondEvents.size()), static_cast<uint32_t>(chunkEvents.size()), bondEvents.data(), chunkEvents.data() }; - - std::vector<float> scratch(chunkEvents.size() + bondEvents.size(), 0.0f); - - std::vector<char> splitScratch; - std::vector<NvBlastActor*> newActorsBuffer(testAsset->solverChunks.size()); - - NvBlastExtRadialDamageDesc damage[] = { - { - compressiveDamage, - { localPos.x, localPos.y, localPos.z }, - minRadius, - maxRadius - } - }; - - NvBlastProgramParams programParams = - { - &damage, - 1, - nullptr - }; - - NvBlastDamageProgram program = { - NvBlastExtFalloffGraphShader, - nullptr - }; - - size_t totalNewActorsCount = 0; - for (std::set<NvBlastActor*>::iterator k = actorsToDamage.begin(); k != actorsToDamage.end();) - { - NvBlastActor* actor = *k; - - NvBlastActorGenerateFracture(&events, actor, program, &programParams, nullptr, nullptr); - NvBlastActorApplyFracture(&events, actor, &events, nullptr, nullptr); - - bool removeActor = false; - - if (events.bondFractureCount + events.chunkFractureCount > 0) - { - NvBlastActorSplitEvent splitEvent; - splitEvent.newActors = &newActorsBuffer.data()[totalNewActorsCount]; - uint32_t newActorSize = (uint32_t)(newActorsBuffer.size() - totalNewActorsCount); - - splitScratch.resize((size_t)NvBlastActorGetRequiredScratchForSplit(actor, nullptr)); - const size_t newActorsCount = NvBlastActorSplit(&splitEvent, actor, newActorSize, splitScratch.data(), nullptr, nullptr); - totalNewActorsCount += newActorsCount; - removeActor = splitEvent.deletedActor != NULL; - } - - if (removeActor) - { - k = actorsToDamage.erase(k); - } - else - { - ++k; - } - } - - for (size_t i = 0; i < totalNewActorsCount; ++i) - { - actorsToDamage.insert(newActorsBuffer[i]); - } -} - - -template<int FailLevel, int Verbosity> -class MultithreadingTest : public BlastBaseTest<FailLevel, Verbosity> -{ -public: - MultithreadingTest() - { - - } - - static void messageLog(int type, const char* msg, const char* file, int line) - { - BlastBaseTest<FailLevel, Verbosity>::messageLog(type, msg, file, line); - } - - static void* alloc(size_t size) - { - return BlastBaseTest<FailLevel, Verbosity>::alloc(size); - } - - static void free(void* mem) - { - BlastBaseTest<FailLevel, Verbosity>::free(mem); - } - - static void testActorVisibleChunks(const Nv::Blast::Actor& actor, NvBlastLog) - { - const Nv::Blast::Asset& asset = *actor.getAsset(); - const NvBlastChunk* chunks = asset.getChunks(); - - if (actor.isSubSupportChunk()) - { - EXPECT_EQ(1, actor.getVisibleChunkCount()); - - const uint32_t firstVisibleChunkIndex = (uint32_t)Nv::Blast::Actor::VisibleChunkIt(actor); - - EXPECT_EQ(actor.getIndex() - asset.m_graph.m_nodeCount, firstVisibleChunkIndex - asset.m_firstSubsupportChunkIndex); - - // Make sure the visible chunk is subsupport - // Array of support flags - std::vector<bool> isSupport(asset.m_chunkCount, false); - for (uint32_t i = 0; i < asset.m_graph.m_nodeCount; ++i) - { - isSupport[asset.m_graph.getChunkIndices()[i]] = true; - } - - // Climb hierarchy to find support chunk - uint32_t chunkIndex = firstVisibleChunkIndex; - while (chunkIndex != Nv::Blast::invalidIndex<uint32_t>()) - { - if (isSupport[chunkIndex]) - { - break; - } - chunkIndex = chunks[chunkIndex].parentChunkIndex; - } - - EXPECT_FALSE(Nv::Blast::isInvalidIndex(chunkIndex)); - } - else - { - // Array of visibility flags - std::vector<bool> isVisible(asset.m_chunkCount, false); - for (Nv::Blast::Actor::VisibleChunkIt i = actor; (bool)i; ++i) - { - isVisible[(uint32_t)i] = true; - } - - // Mark visible nodes representing graph chunks - std::vector<bool> visibleChunkFound(asset.m_chunkCount, false); - - // Make sure every graph chunk is represented by a visible chunk - for (Nv::Blast::Actor::GraphNodeIt i = actor; (bool)i; ++i) - { - const uint32_t graphNodeIndex = (uint32_t)i; - uint32_t chunkIndex = asset.m_graph.getChunkIndices()[graphNodeIndex]; - // Climb hierarchy to find visible chunk - while (chunkIndex != Nv::Blast::invalidIndex<uint32_t>()) - { - // Check that chunk owners are accurate - EXPECT_EQ(actor.getIndex(), actor.getFamilyHeader()->getChunkActorIndices()[chunkIndex]); - if (isVisible[chunkIndex]) - { - visibleChunkFound[chunkIndex] = true; - break; - } - chunkIndex = chunks[chunkIndex].parentChunkIndex; - } - EXPECT_FALSE(Nv::Blast::isInvalidIndex(chunkIndex)); - } - - // Check that all visible chunks are accounted for - for (uint32_t i = 0; i < asset.m_chunkCount; ++i) - { - EXPECT_EQ(visibleChunkFound[i], isVisible[i]); - } - - // Make sure that, if all siblings are intact, they are invisible - for (uint32_t i = 0; i < asset.m_chunkCount; ++i) - { - bool allIntact = true; - bool noneVisible = true; - if (chunks[i].firstChildIndex < asset.getUpperSupportChunkCount()) // Do not check subsupport - { - for (uint32_t j = chunks[i].firstChildIndex; j < chunks[i].childIndexStop; ++j) - { - allIntact = allIntact && actor.getFamilyHeader()->getChunkActorIndices()[j] == actor.getIndex(); - noneVisible = noneVisible && !isVisible[j]; - } - EXPECT_TRUE(!allIntact || noneVisible); - } - } - } - } - - class DamageActorTask : public TaskDispatcher::Task - { - public: - DamageActorTask(NvBlastActor* actor, GeneratorAsset* asset, GeneratorAsset::Vec3 localPos, float minRadius, float maxRadius, float compressiveDamage, ActorTestFunction testFunction) - : m_asset(asset) - , m_localPos(localPos) - , m_minRadius(minRadius) - , m_maxRadius(maxRadius) - , m_compressiveDamage(compressiveDamage) - , m_testFunction(testFunction) - { - m_actors.insert(actor); - } - - virtual void process() - { - blast(m_actors, m_asset, m_localPos, m_minRadius, m_maxRadius, m_compressiveDamage); - - // Test individual actors - if (m_testFunction != nullptr) - { - for (std::set<NvBlastActor*>::iterator k = m_actors.begin(); k != m_actors.end(); ++k) - { - m_testFunction(*static_cast<Nv::Blast::Actor*>(*k), messageLog); - } - } - } - - const std::set<NvBlastActor*>& getResult() const { return m_actors; } - - private: - std::set<NvBlastActor*> m_actors; - GeneratorAsset* m_asset; - GeneratorAsset::Vec3 m_localPos; - float m_minRadius; - float m_maxRadius; - float m_compressiveDamage; - ActorTestFunction m_testFunction; - - std::vector<NvBlastActor*> m_resultActors; - }; - - void damageLeafSupportActorsParallelized - ( - uint32_t assetCount, - uint32_t minChunkCount, - uint32_t damageCount, - uint32_t threadCount, - ActorTestFunction actorTestFunction, - PostDamageTestFunction postDamageTestFunction - ) - { - const float relativeDamageRadius = 0.05f; - const float compressiveDamage = 1.0f; - - srand(0); - - std::cout << "Asset # (out of " << assetCount << "): "; - for (uint32_t assetNum = 0; assetNum < assetCount; ++assetNum) - { - std::cout << assetNum + 1 << ".. "; - CubeAssetGenerator::Settings settings; - settings.extents = GeneratorAsset::Vec3(1, 1, 1); - CubeAssetGenerator::DepthInfo depthInfo; - depthInfo.slicesPerAxis = GeneratorAsset::Vec3(1, 1, 1); - depthInfo.flag = NvBlastChunkDesc::Flags::NoFlags; - settings.depths.push_back(depthInfo); - uint32_t chunkCount = 1; - while (chunkCount < minChunkCount) - { - uint32_t chunkMul; - do - { - depthInfo.slicesPerAxis = GeneratorAsset::Vec3((float)(1 + rand() % 4), (float)(1 + rand() % 4), (float)(1 + rand() % 4)); - chunkMul = (uint32_t)(depthInfo.slicesPerAxis.x * depthInfo.slicesPerAxis.y * depthInfo.slicesPerAxis.z); - } while (chunkMul == 1); - chunkCount *= chunkMul; - settings.depths.push_back(depthInfo); - settings.extents = settings.extents * depthInfo.slicesPerAxis; - } - settings.depths.back().flag = NvBlastChunkDesc::SupportFlag; // Leaves are support - - // Make largest direction unit size - settings.extents = settings.extents * (1.0f / std::max(settings.extents.x, std::max(settings.extents.y, settings.extents.z))); - - // Create asset - GeneratorAsset testAsset; - CubeAssetGenerator::generate(testAsset, settings); - - NvBlastAssetDesc desc; - desc.chunkDescs = &testAsset.solverChunks[0]; - desc.chunkCount = (uint32_t)testAsset.solverChunks.size(); - desc.bondDescs = &testAsset.solverBonds[0]; - desc.bondCount = (uint32_t)testAsset.solverBonds.size(); - - std::vector<char> scratch; - scratch.resize((size_t)NvBlastGetRequiredScratchForCreateAsset(&desc, messageLog)); - void* mem = alloc(NvBlastGetAssetMemorySize(&desc, messageLog)); - NvBlastAsset* asset = NvBlastCreateAsset(mem, &desc, &scratch[0], messageLog); - EXPECT_TRUE(asset != nullptr); - - NvBlastActorDesc actorDesc; - actorDesc.initialBondHealths = actorDesc.initialSupportChunkHealths = nullptr; - actorDesc.uniformInitialBondHealth = actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f; - void* fmem = alloc(NvBlastAssetGetFamilyMemorySize(asset, messageLog)); - NvBlastFamily* family = NvBlastAssetCreateFamily(fmem, asset, nullptr); // Using zeroingAlloc in case actorTest compares memory blocks - scratch.resize((size_t)NvBlastFamilyGetRequiredScratchForCreateFirstActor(family, messageLog)); - NvBlastActor* actor = NvBlastFamilyCreateFirstActor(family, &actorDesc, &scratch[0], messageLog); - EXPECT_TRUE(actor != nullptr); - - // Run parallelized damage through TaskDispatcher - std::set<NvBlastActor*> resultActors; - { - uint32_t damageNum = 0; - - // create DamageActorTask and it to dispatcher helper function - auto addDamageTaskFunction = [&](TaskDispatcher& dispatcher, NvBlastActor* actor) - { - GeneratorAsset::Vec3 localPos = settings.extents*GeneratorAsset::Vec3((float)rand() / RAND_MAX - 0.5f, (float)rand() / RAND_MAX - 0.5f, (float)rand() / RAND_MAX - 0.5f); - auto newTask = std::unique_ptr<DamageActorTask>(new DamageActorTask(actor, &testAsset, localPos, relativeDamageRadius, relativeDamageRadius*1.2f, compressiveDamage, actorTestFunction)); - dispatcher.addTask(std::move(newTask)); - }; - - // on task finished function for dispatcher (main thread) - TaskDispatcher::OnTaskFinishedFunction onTaskFinishedFunction = [&](TaskDispatcher& dispatcher, std::unique_ptr<TaskDispatcher::Task> task) { - const DamageActorTask* damageTask = static_cast<const DamageActorTask*>(task.get()); - const std::set<NvBlastActor*>& actors = damageTask->getResult(); - for (NvBlastActor* actor : actors) - { - if (damageNum >= damageCount) - { - resultActors.insert(actor); - } - else - { - damageNum++; - addDamageTaskFunction(dispatcher, actor); - } - } - }; - - // create dispatcher, add first task and run - TaskDispatcher dispatcher(threadCount, onTaskFinishedFunction); - addDamageTaskFunction(dispatcher, actor); - dispatcher.process(); - } - - // Test fractured actor set - if (postDamageTestFunction) - { - std::vector<NvBlastActor*> actorArray(resultActors.begin(), resultActors.end()); - postDamageTestFunction(actorArray, messageLog); - } - - // Release remaining actors - for (std::set<NvBlastActor*>::iterator k = resultActors.begin(); k != resultActors.end(); ++k) - { - NvBlastActorDeactivate(*k, messageLog); - } - resultActors.clear(); - - const uint32_t actorCount = NvBlastFamilyGetActorCount(family, messageLog); - EXPECT_TRUE(actorCount == 0); - - free(family); - - // Release asset data - free(asset); - } - std::cout << "done.\n"; - } -}; - - -// Specializations -typedef MultithreadingTest<NvBlastMessage::Error, 1> MultithreadingTestAllowWarnings; -typedef MultithreadingTest<NvBlastMessage::Error, 1> MultithreadingTestStrict; - - -TEST_F(MultithreadingTestStrict, MultithreadingTestDamageLeafSupportActorsTestVisibility) -{ - damageLeafSupportActorsParallelized(1, 1000, 50, 4, testActorVisibleChunks, nullptr); -} - -TEST_F(MultithreadingTestStrict, MultithreadingTestDamageLeafSupportActors) -{ - damageLeafSupportActorsParallelized(1, 3000, 1000, 4, nullptr, nullptr); -} diff --git a/NvBlast/test/src/unit/SyncTests.cpp b/NvBlast/test/src/unit/SyncTests.cpp deleted file mode 100644 index 425210d..0000000 --- a/NvBlast/test/src/unit/SyncTests.cpp +++ /dev/null @@ -1,309 +0,0 @@ -#include "TkBaseTest.h" - -#include "NvBlastExtSync.h" -#include "NvBlastTkEvent.h" - -#include <map> - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// ExtSync Tests -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -class Base -{ -public: - Base(TkTestStrict* test) : m_test(test) - { - - } - - void run(std::stringstream& finalState) - { - //////// initial setup //////// - - m_test->createTestAssets(); - - TkFramework* fwk = NvBlastTkFrameworkGet(); - - TkGroupDesc gdesc; - gdesc.pxTaskManager = m_test->m_taskman; - m_group = fwk->createGroup(gdesc); - EXPECT_TRUE(m_group != nullptr); - - TkActorDesc adesc(m_test->testAssets[0]); - - NvBlastID id; - - TkActor* actor0 = fwk->createActor(adesc); - EXPECT_TRUE(actor0 != nullptr); - families[0] = &actor0->getFamily(); - memcpy(id.data, "Mumble Jumble Bumble", sizeof(NvBlastID)); // Stuffing an arbitrary 16 bytes (The prefix of the given string) - families[0]->setID(id); - m_group->addActor(*actor0); - - TkActor* actor1 = fwk->createActor(adesc); - EXPECT_TRUE(actor1 != nullptr); - families[1] = &actor1->getFamily(); - memcpy(id.data, "buzzkillerdiller", sizeof(NvBlastID)); // Stuffing an arbitrary 16 bytes (The prefix of the given string) - families[1]->setID(id); - m_group->addActor(*actor1); - - - //////// server/client specific impl //////// - - impl(); - - - //////// write out framework final state //////// - - finalState.clear(); - for (auto family : families) - { - std::vector<TkActor*> actors(family->getActorCount()); - family->getActors(actors.data(), static_cast<uint32_t>(actors.size())); - for (auto actor : actors) - { - finalState << actor->getVisibleChunkCount(); - finalState << actor->getGraphNodeCount(); - std::vector<uint32_t> chunkIndices(actor->getGraphNodeCount()); - actor->getVisibleChunkIndices(chunkIndices.data(), (uint32_t)chunkIndices.size()); - - for (uint32_t chunkIndex : chunkIndices) - finalState << chunkIndex; - const float* bondHealths = actor->getBondHealths(); - for (uint32_t i = 0; i < actor->getAsset()->getBondCount(); ++i) - finalState << bondHealths[i]; - } - } - - - //////// release //////// - - m_group->release(); - - for (auto family : families) - { - family->release(); - } - - m_test->releaseTestAssets(); - } - -protected: - virtual void impl() = 0; - - TkTestStrict* m_test; - TkGroup* m_group; - TkFamily* families[2]; -}; - - -class Server : public Base -{ -public: - Server(TkTestStrict* test, std::vector<ExtSyncEvent*>& syncBuffer) : Base(test), m_syncBuffer(syncBuffer) {} - -protected: - virtual void impl() override - { - // create sync ext - ExtSync* sync = ExtSync::create(); - - // add sync as listener to family #1 - families[1]->addListener(*sync); - - // damage family #0 (make it split) - { - TkActor* actor; - families[0]->getActors(&actor, 1); - CSParams p(1, 0.0f); - actor->damage(m_test->getCubeSlicerProgram(), &p, sizeof(p), m_test->getDefaultMaterial()); - } - - // process - m_group->process(); - m_group->sync(); - EXPECT_EQ(families[0]->getActorCount(), 2); - - // sync family #0 - sync->syncFamily(*families[0]); - - // add sync as listener to family #0 - families[0]->addListener(*sync); - - // damage family #0 (make it split fully) - { - TkActor* actor; - families[0]->getActors(&actor, 1, 1); - NvBlastExtRadialDamageDesc radialDamage = m_test->getRadialDamageDesc(0, 0, 0); - actor->damage(m_test->getFalloffProgram(), &radialDamage, sizeof(radialDamage), m_test->getDefaultMaterial()); - } - - - // damage family 1 (just damage bonds health) - { - TkActor* actor; - families[1]->getActors(&actor, 1); - NvBlastExtRadialDamageDesc radialDamage = m_test->getRadialDamageDesc(0, 0, 0, 10.0f, 10.0f, 0.1f); - actor->damage(m_test->getFalloffProgram(), &radialDamage, sizeof(radialDamage), m_test->getDefaultMaterial()); - } - - // process - m_group->process(); - m_group->sync(); - EXPECT_EQ(families[0]->getActorCount(), 5); - EXPECT_EQ(families[1]->getActorCount(), 1); - - // take sync buffer from sync - { - const ExtSyncEvent*const* buffer; - uint32_t size; - sync->acquireSyncBuffer(buffer, size); - - m_syncBuffer.resize(size); - for (size_t i = 0; i < size; ++i) - { - m_syncBuffer[i] = buffer[i]->clone(); - } - - sync->releaseSyncBuffer(); - } - - // - families[0]->removeListener(*sync); - families[1]->removeListener(*sync); - - // - sync->release(); - } - -private: - std::vector<ExtSyncEvent*>& m_syncBuffer; -}; - - -class Client : public Base, public TkEventListener -{ -public: - Client(TkTestStrict* test, std::vector<ExtSyncEvent*>& syncBuffer) : Base(test), m_syncBuffer(syncBuffer) {} - -protected: - - virtual void impl() override - { - ExtSync* sync = ExtSync::create(); - - // fill map - for (auto& family : families) - { - std::vector<TkActor*> actors(family->getActorCount()); - family->getActors(actors.data(), static_cast<uint32_t>(actors.size())); - auto& actorsSet = m_actorsPerFamily[family]; - for (auto actor : actors) - EXPECT_TRUE(actorsSet.insert(actor->getIndex()).second); - } - - // subscribe - for (auto& family : families) - { - family->addListener(*this); - } - - // apply sync buffer - sync->applySyncBuffer(*NvBlastTkFrameworkGet(), (const Nv::Blast::ExtSyncEvent**)m_syncBuffer.data(), static_cast<uint32_t>(m_syncBuffer.size()), m_group); - - // check map - for (auto& family : families) - { - std::vector<TkActor*> actors(family->getActorCount()); - family->getActors(actors.data(), static_cast<uint32_t>(actors.size())); - std::set<uint32_t> actorsSet; - for (auto actor : actors) - EXPECT_TRUE(actorsSet.insert(actor->getIndex()).second); - EXPECT_TRUE(m_actorsPerFamily[family] == actorsSet); - } - - // unsubscribe - for (auto& family : families) - { - family->removeListener(*this); - } - - m_group->process(); - m_group->sync(); - - sync->release(); - } - - // listen for Split event and update actors map - virtual void receive(const TkEvent* events, uint32_t eventCount) override - { - for (size_t i = 0; i < eventCount; ++i) - { - const TkEvent& e = events[i]; - switch (e.type) - { - case (TkEvent::Split) : - { - const TkSplitEvent* splitEvent = e.getPayload<TkSplitEvent>(); - auto& actorsSet = m_actorsPerFamily[splitEvent->parentData.family]; - if (!isInvalidIndex(splitEvent->parentData.index)) - { - EXPECT_EQ((size_t)1, actorsSet.erase(splitEvent->parentData.index)); - } - for (size_t i = 0; i < splitEvent->numChildren; ++i) - { - TkActor* a = splitEvent->children[i]; - EXPECT_TRUE(actorsSet.insert(a->getIndex()).second); - } - break; - } - case (TkEvent::FractureCommand) : - { - break; - } - case (TkEvent::JointUpdate) : - { - FAIL(); - break; - } - default: - break; - } - } - } - -private: - std::map<TkFamily*, std::set<uint32_t>> m_actorsPerFamily; - std::vector<ExtSyncEvent*>& m_syncBuffer; -}; - -TEST_F(TkTestStrict, SyncTest1) -{ - this->createFramework(); - - std::vector<ExtSyncEvent*> syncBuffer; - - std::stringstream serverFinalState; - { - Server s(this, syncBuffer); - s.run(serverFinalState); - } - EXPECT_TRUE(syncBuffer.size() > 0); - - std::stringstream clientFinalState; - { - Client c(this, syncBuffer); - c.run(clientFinalState); - } - - for (auto e : syncBuffer) - { - e->release(); - } - syncBuffer.clear(); - - EXPECT_EQ(serverFinalState.str(), clientFinalState.str()); - - this->releaseFramework(); -} diff --git a/NvBlast/test/src/unit/TkCompositeTests.cpp b/NvBlast/test/src/unit/TkCompositeTests.cpp deleted file mode 100644 index 60fbe49..0000000 --- a/NvBlast/test/src/unit/TkCompositeTests.cpp +++ /dev/null @@ -1,739 +0,0 @@ -#include "TkBaseTest.h" - -#include <map> -#include <random> -#include <algorithm> - -#include "PsMemoryBuffer.h" - -#include "NvBlastTkSerializable.h" - -#include "NvBlastTime.h" - - -/* -Composite and joint tests: - -0) Test serialization of composites and assemblies - -1) Create assembly, actors and joints should be created automatically - -2) Create an actor with internal joints. Splitting the actor should cause joint create events to be dispatched - -3) Joint update events should be fired when attached actors change - -4) Joint delete events should be fired when at least one attached actor is deleted - -5) Creating a composite from assets with internal joints should have expected behaviors (1-4) above -*/ - - -struct Composite -{ - std::vector<TkActorDesc> m_actorDescs; - std::vector<physx::PxTransform> m_relTMs; - std::vector<TkJointDesc> m_jointDescs; -}; - - -template<int FailLevel, int Verbosity> -class TkCompositeTest : public TkBaseTest<FailLevel, Verbosity> -{ -public: - virtual void* allocate(size_t size, const char* typeName, const char* filename, int line) override - { - void* ptr = TkBaseTest<FailLevel, Verbosity>::allocate(size, typeName, filename, line); - return ptr; - } - - virtual void deallocate(void* ptr) override - { - return TkBaseTest<FailLevel, Verbosity>::deallocate(ptr); - } - - - // Composite/joint tests - void createAssembly(std::vector<TkActor*>& actors, std::vector<TkJoint*>& joints, bool createNRFJoints) - { - TkFramework* fw = NvBlastTkFrameworkGet(); - - actors.resize(4, nullptr); - actors[0] = fw->createActor(TkActorDesc(testAssets[0])); - actors[1] = fw->createActor(TkActorDesc(testAssets[0])); - actors[2] = fw->createActor(TkActorDesc(testAssets[1])); - actors[3] = fw->createActor(TkActorDesc(testAssets[1])); - - std::vector<TkFamily*> families(4); - families[0] = &actors[0]->getFamily(); - families[1] = &actors[1]->getFamily(); - families[2] = &actors[2]->getFamily(); - families[3] = &actors[3]->getFamily(); - - EXPECT_FALSE(actors[0] == nullptr); - EXPECT_FALSE(actors[1] == nullptr); - EXPECT_FALSE(actors[2] == nullptr); - EXPECT_FALSE(actors[3] == nullptr); - - const TkJointDesc jointDescsNoNRF[8] = - { - // Actor indices, chunk indices, attach position in the composite frame - { { families[0], families[1] }, { 6, 5 }, { PxVec3(0.0f, -1.5f, 0.5f), PxVec3(0.0f, -1.5f, 0.5f) } }, - { { families[0], families[1] }, { 4, 3 }, { PxVec3(0.0f, -0.5f, -0.5f), PxVec3(0.0f, -0.5f, -0.5f) } }, - - { { families[0], families[2] }, { 8, 6 }, { PxVec3(-0.5f, 0.0f, 0.5f), PxVec3(-0.5f, 0.0f, 0.5f) } }, - { { families[0], families[2] }, { 3, 1 }, { PxVec3(-1.5f, 0.0f, -0.5f), PxVec3(-1.5f, 0.0f, -0.5f) } }, - - { { families[1], families[3] }, { 7, 5 }, { PxVec3(0.5f, 0.0f, 0.5f), PxVec3(0.5f, 0.0f, 0.5f) } }, - { { families[1], families[3] }, { 4, 2 }, { PxVec3(1.0f, 0.0f, -0.5f), PxVec3(1.0f, 0.0f, -0.5f) } }, - - { { families[2], families[3] }, { 8, 7 }, { PxVec3(0.0f, 1.5f, 0.5f), PxVec3(0.0f, 1.5f, 0.5f) } }, - { { families[2], families[3] }, { 2, 1 }, { PxVec3(0.0f, 0.5f, -0.5f), PxVec3(0.0f, 0.5f, -0.5f) } } - }; - - const TkJointDesc jointDescsWithNRF[12] = - { - // Actor indices, chunk indices, attach position in the composite frame - { { families[0], families[1] }, { 6, 5 }, { PxVec3(0.0f, -1.5f, 0.5f), PxVec3(0.0f, -1.5f, 0.5f) } }, - { { families[0], families[1] }, { 4, 3 }, { PxVec3(0.0f, -0.5f, -0.5f), PxVec3(0.0f, -0.5f, -0.5f) } }, - - { { families[0], nullptr }, { 8, 0xFFFFFFFF }, { PxVec3(-0.5f, 0.0f, 0.5f), PxVec3(-0.5f, 0.0f, 0.5f) } }, - { { families[0], nullptr }, { 3, 0xFFFFFFFF }, { PxVec3(-1.5f, 0.0f, -0.5f), PxVec3(-1.5f, 0.0f, -0.5f) } }, - - { { nullptr, families[2] }, { 0xFFFFFFFF, 6 }, { PxVec3(-0.5f, 0.0f, 0.5f), PxVec3(-0.5f, 0.0f, 0.5f) } }, - { { nullptr, families[2] }, { 0xFFFFFFFF, 1 }, { PxVec3(-1.5f, 0.0f, -0.5f), PxVec3(-1.5f, 0.0f, -0.5f) } }, - - { { families[1], nullptr }, { 7, 0xFFFFFFFF }, { PxVec3(0.5f, 0.0f, 0.5f), PxVec3(0.5f, 0.0f, 0.5f) } }, - { { families[1], nullptr }, { 4, 0xFFFFFFFF }, { PxVec3(1.0f, 0.0f, -0.5f), PxVec3(1.0f, 0.0f, -0.5f) } }, - - { { nullptr, families[3] }, { 0xFFFFFFFF, 5 }, { PxVec3(0.5f, 0.0f, 0.5f), PxVec3(0.5f, 0.0f, 0.5f) } }, - { { nullptr, families[3] }, { 0xFFFFFFFF, 2 }, { PxVec3(1.0f, 0.0f, -0.5f), PxVec3(1.0f, 0.0f, -0.5f) } }, - - { { families[2], families[3] }, { 8, 7 }, { PxVec3(0.0f, 1.5f, 0.5f), PxVec3(0.0f, 1.5f, 0.5f) } }, - { { families[2], families[3] }, { 2, 1 }, { PxVec3(0.0f, 0.5f, -0.5f), PxVec3(0.0f, 0.5f, -0.5f), } } - }; - - const TkJointDesc* jointDescs = createNRFJoints ? jointDescsWithNRF : jointDescsNoNRF; - const int jointCount = createNRFJoints ? 12 : 8; - - joints.resize(jointCount, nullptr); - for (int i = 0; i < jointCount; ++i) - { - joints[i] = fw->createJoint(jointDescs[i]); - EXPECT_FALSE(joints[i] == nullptr); - } - } - - void familySerialization(std::vector<TkFamily*>& families, TestFamilyTracker& tracker) - { - TkFramework* fw = NvBlastTkFrameworkGet(); - - PsMemoryBuffer* membuf = PX_NEW(PsMemoryBuffer); - EXPECT_TRUE(membuf != nullptr); - if (membuf == nullptr) - { - return; - } - - std::vector<TkFamily*> oldFamilies = families; - - for (size_t familyNum = 0; familyNum < families.size(); ++familyNum) - { - families[familyNum]->serialize(*membuf); - } - - for (size_t familyNum = 0; familyNum < families.size(); ++familyNum) - { - TkFamily* f = families[familyNum]; - - std::vector<TkActor*> actors(f->getActorCount()); - f->getActors(actors.data(), static_cast<uint32_t>(actors.size())); - for (auto a : actors) - { - tracker.eraseActor(a); - } - - f->release(); - families[familyNum] = nullptr; - } - - for (size_t familyNum = 0; familyNum < families.size(); ++familyNum) - { - TkFamily* f = reinterpret_cast<TkFamily*>(fw->deserialize(*membuf)); - f->addListener(tracker); - families[familyNum] = f; - } - - for (size_t familyNum = 0; familyNum < families.size(); ++familyNum) - { - TkFamily* f = families[familyNum]; - - std::vector<TkActor*> actors(f->getActorCount()); - f->getActors(actors.data(), static_cast<uint32_t>(actors.size())); - for (auto a : actors) - { - tracker.insertActor(a); - - std::vector<TkJoint*> joints(a->getJointCount()); - a->getJoints(joints.data(), (uint32_t)joints.size()); - - for (auto j : joints) - { - const TkJointData jd = j->getData(); - if (jd.actors[0] != jd.actors[1]) - { - tracker.joints.insert(j); - } - } - } - } - - membuf->release(); - } - - void recollectActors(std::vector<TkFamily*>& families, std::vector<TkActor*>& actors) - { - uint32_t totalActorCount = 0; - for (auto family : families) - { - EXPECT_LE(family->getActorCount() + totalActorCount, actors.size()); - totalActorCount += family->getActors(actors.data() + totalActorCount, static_cast<uint32_t>(actors.size()) - totalActorCount); - } - } - - void assemblyCreateAndRelease(bool createNRFJoints, bool serializationTest) - { - createFramework(); - createTestAssets(); - - TkFramework* fw = NvBlastTkFrameworkGet(); - - const TkType* familyType = fw->getType(TkTypeIndex::Family); - EXPECT_TRUE(familyType != nullptr); - - TestFamilyTracker tracker; - - std::vector<TkFamily*> families1; - std::vector<TkFamily*> families2; - - // Create one assembly - std::vector<TkActor*> actors1; - std::vector<TkJoint*> joints1; - createAssembly(actors1, joints1, createNRFJoints); - tracker.joints.insert(joints1.begin(), joints1.end()); - - // Create another assembly - std::vector<TkActor*> actors2; - std::vector<TkJoint*> joints2; - createAssembly(actors2, joints2, createNRFJoints); - tracker.joints.insert(joints2.begin(), joints2.end()); - - // Store families and fill group - for (size_t actorNum = 0; actorNum < actors1.size(); ++actorNum) - { - TkFamily& family = actors1[actorNum]->getFamily(); - families1.push_back(&family); - family.addListener(tracker); - } - for (size_t actorNum = 0; actorNum < actors2.size(); ++actorNum) - { - TkFamily& family = actors2[actorNum]->getFamily(); - families2.push_back(&family); - family.addListener(tracker); - } - - if (serializationTest) - { - familySerialization(families1, tracker); - recollectActors(families1, actors1); - familySerialization(families2, tracker); - recollectActors(families2, actors2); - } - - EXPECT_EQ(joints1.size() + joints2.size(), tracker.joints.size()); - - // Release 1st assembly's actors - for (size_t actorNum = 0; actorNum < actors1.size(); ++actorNum) - { - actors1[actorNum]->release(); - } - - if (serializationTest) - { - familySerialization(families2, tracker); - recollectActors(families2, actors2); - } - - EXPECT_EQ(joints2.size(), tracker.joints.size()); - - // Release 2nd assembly's actors - for (size_t actorNum = 0; actorNum < actors1.size(); ++actorNum) - { - actors2[actorNum]->release(); - } - - EXPECT_EQ(0, tracker.joints.size()); - - releaseTestAssets(); - releaseFramework(); - } - - void assemblyInternalJoints(bool testAssemblySerialization) - { - createFramework(); - createTestAssets(true); // Create assets with internal joints - - TkFramework* fw = NvBlastTkFrameworkGet(); - - TestFamilyTracker tracker; - - TkGroupDesc gdesc; - gdesc.pxTaskManager = m_taskman; - TkGroup* group = fw->createGroup(gdesc); - EXPECT_TRUE(group != nullptr); - - TkActorDesc adesc(testAssets[0]); - - TkActor* actor1 = fw->createActor(adesc); - EXPECT_TRUE(actor1 != nullptr); - tracker.insertActor(actor1); - - actor1->getFamily().addListener(tracker); - - TkFamily* family = &actor1->getFamily(); - - group->addActor(*actor1); - - CSParams p(2, 0.0f); - actor1->damage(getCubeSlicerProgram(), &p, sizeof(p), getDefaultMaterial()); - - EXPECT_EQ((size_t)0, tracker.joints.size()); - - group->process(); - group->sync(); - - if (testAssemblySerialization) - { - std::vector<TkFamily*> families; - families.push_back(family); - familySerialization(families, tracker); - family = families[0]; - std::vector<TkActor*> actors(family->getActorCount()); - family->getActors(actors.data(), static_cast<uint32_t>(actors.size())); - for (TkActor* actor : actors) - { - group->addActor(*actor); - } - } - - EXPECT_EQ((size_t)2, family->getActorCount()); - EXPECT_EQ((size_t)4, tracker.joints.size()); // 2) Create an actor with internal joints. Splitting the actor should cause joint create events to be dispatched - - std::vector<TkActor*> actors(family->getActorCount()); - family->getActors(actors.data(), static_cast<uint32_t>(actors.size())); - - for (TkJoint* joint : tracker.joints) - { - TkJointData jd = joint->getData(); - EXPECT_FALSE(actors.end() == std::find(actors.begin(), actors.end(), jd.actors[0])); - EXPECT_FALSE(actors.end() == std::find(actors.begin(), actors.end(), jd.actors[1])); - } - - NvBlastExtRadialDamageDesc radialDamage = getRadialDamageDesc(0, 0, 0); - for (TkActor* actor : actors) - { - actor->damage(getFalloffProgram(), &radialDamage, sizeof(radialDamage), getDefaultMaterial()); - } - - group->process(); - group->sync(); - - if (testAssemblySerialization) - { - std::vector<TkFamily*> families; - families.push_back(family); - familySerialization(families, tracker); - family = families[0]; - } - - EXPECT_EQ((size_t)8, family->getActorCount()); - EXPECT_EQ((size_t)4, tracker.joints.size()); - - // 3) Joint update events should be fired when attached actors change - - actors.resize(family->getActorCount()); - family->getActors(actors.data(), static_cast<uint32_t>(actors.size())); - - for (TkJoint* joint : tracker.joints) - { - TkJointData jd = joint->getData(); - EXPECT_FALSE(actors.end() == std::find(actors.begin(), actors.end(), jd.actors[0])); - EXPECT_FALSE(actors.end() == std::find(actors.begin(), actors.end(), jd.actors[1])); - } - - for (TkActor* actor : actors) - { - actor->release(); - } - - EXPECT_EQ((size_t)0, tracker.joints.size()); // 4) Joint delete events should be fired when at least one attached actor is deleted - - group->release(); - - releaseTestAssets(); - releaseFramework(); - } - - void assemblyCompositeWithInternalJoints(bool createNRFJoints, bool serializationTest) - { - createFramework(); - createTestAssets(true); // Create assets with internal joints - - TkFramework* fw = NvBlastTkFrameworkGet(); - - const TkType* familyType = fw->getType(TkTypeIndex::Family); - EXPECT_TRUE(familyType != nullptr); - - if (familyType == nullptr) - { - return; - } - - TestFamilyTracker tracker; - - std::vector<TkFamily*> families; - - // Create assembly - std::vector<TkActor*> actors; - std::vector<TkJoint*> joints; - createAssembly(actors, joints, createNRFJoints); - tracker.joints.insert(joints.begin(), joints.end()); - - TkGroupDesc gdesc; - gdesc.pxTaskManager = m_taskman; - TkGroup* group = fw->createGroup(gdesc); - EXPECT_TRUE(group != nullptr); - - for (size_t i = 0; i < actors.size(); ++i) - { - TkFamily& family = actors[i]->getFamily(); - families.push_back(&family); - family.addListener(tracker); - tracker.insertActor(actors[i]); - group->addActor(*actors[i]); - } - - if (serializationTest) - { - familySerialization(families, tracker); - recollectActors(families, actors); - for (auto actor : actors) - { - group->addActor(*actor); - } - } - - EXPECT_EQ((size_t)4, actors.size()); - - const size_t compJointCount = createNRFJoints ? (size_t)12 : (size_t)8; - - EXPECT_EQ(compJointCount, tracker.joints.size()); - - size_t totalActorCount = 0; - for (uint32_t i = 0; i < 4; ++i) - { - CSParams p(2, 0.0f); - actors[i]->damage(getCubeSlicerProgram(), &p, sizeof(p), getDefaultMaterial()); - - group->process(); - group->sync(); - - if (serializationTest) - { - familySerialization(families, tracker); - for (size_t j = 0; j < families.size(); ++j) - { - TkFamily* family = families[j]; - std::vector<TkActor*> a(family->getActorCount()); - family->getActors(a.data(), static_cast<uint32_t>(a.size())); - for (auto actor : a) - { - group->addActor(*actor); - } - EXPECT_TRUE(j <= i || a.size() == 1); - if (j > i && a.size() == 1) - { - actors[j] = a[0]; - } - } - } - - EXPECT_EQ((size_t)2, families[i]->getActorCount()); - EXPECT_EQ((size_t)(compJointCount + 4 * (i + 1)), tracker.joints.size()); // Four joints created per actor - - totalActorCount += families[i]->getActorCount(); - } - - actors.resize(totalActorCount); - totalActorCount = 0; - for (int i = 0; i < 4; ++i) - { - families[i]->getActors(actors.data() + totalActorCount, families[i]->getActorCount()); - totalActorCount += families[i]->getActorCount(); - } - - for (TkJoint* joint : tracker.joints) - { - TkJointData jd = joint->getData(); - EXPECT_TRUE(jd.actors[0] == nullptr || actors.end() != std::find(actors.begin(), actors.end(), jd.actors[0])); - EXPECT_TRUE(jd.actors[1] == nullptr || actors.end() != std::find(actors.begin(), actors.end(), jd.actors[1])); - } - - NvBlastExtRadialDamageDesc radialDamage = getRadialDamageDesc(0, 0, 0); - for (TkActor* actor : actors) - { - actor->damage(getFalloffProgram(), &radialDamage, sizeof(radialDamage), getDefaultMaterial()); - } - - group->process(); - group->sync(); - - totalActorCount = 0; - for (int i = 0; i < 4; ++i) - { - totalActorCount += families[i]->getActorCount(); - } - - if (serializationTest) - { - familySerialization(families, tracker); - } - - EXPECT_EQ((size_t)32, totalActorCount); - EXPECT_EQ(compJointCount + (size_t)16, tracker.joints.size()); - - actors.resize(totalActorCount); - totalActorCount = 0; - for (int i = 0; i < 4; ++i) - { - families[i]->getActors(actors.data() + totalActorCount, families[i]->getActorCount()); - totalActorCount += families[i]->getActorCount(); - } - - // 3) Joint update events should be fired when attached actors change - - for (TkActor* actor : actors) - { - actor->release(); - } - - EXPECT_EQ((size_t)0, tracker.joints.size()); // 4) Joint delete events should be fired when at least one attached actor is deleted - - group->release(); - - releaseTestAssets(); - releaseFramework(); - } - - void assemblyExternalJoints_MultiFamilyDamage(bool explicitJointRelease = true) - { - createFramework(); - - const NvBlastChunkDesc chunkDescs[3] = - { -// centroid volume parent idx flags ID - { { 0.0f, 0.0f, 0.0f }, 4.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 0 }, - { { 0.0f,-1.0f, 0.0f }, 2.0f, 0, NvBlastChunkDesc::SupportFlag, 1 }, - { { 0.0f, 1.0f, 0.0f }, 2.0f, 0, NvBlastChunkDesc::SupportFlag, 2 } - }; - - const NvBlastBondDesc bondDesc = -// chunks normal area centroid userData - { { 1, 2 },{ { 0.0f, 1.0f, 0.0f }, 1.0f,{ 0.0f, 0.0f, 0.0f }, 0 } }; - - TkFramework* framework = NvBlastTkFrameworkGet(); - - TestFamilyTracker tracker; - - TkAssetDesc desc; - desc.chunkCount = 3; - desc.chunkDescs = chunkDescs; - desc.bondCount = 1; - desc.bondDescs = &bondDesc; - desc.bondFlags = nullptr; - TkAsset* asset = framework->createAsset(desc); - EXPECT_TRUE(asset != nullptr); - - TkGroupDesc gdesc; - gdesc.pxTaskManager = m_taskman; - TkGroup* group = framework->createGroup(gdesc); - EXPECT_TRUE(group != nullptr); - - TkActorDesc adesc(asset); - TkActor* actor1 = framework->createActor(adesc); - EXPECT_TRUE(actor1 != nullptr); - TkActor* actor2 = framework->createActor(adesc); - EXPECT_TRUE(actor2 != nullptr); - - group->addActor(*actor1); - group->addActor(*actor2); - - TkFamily* family1 = &actor1->getFamily(); - TkFamily* family2 = &actor2->getFamily(); - - family1->addListener(tracker); - family2->addListener(tracker); - tracker.insertActor(actor1); - tracker.insertActor(actor2); - - TkJointDesc jdesc; - jdesc.families[0] = family1; - jdesc.families[1] = family2; - jdesc.chunkIndices[0] = 2; - jdesc.chunkIndices[1] = 1; - jdesc.attachPositions[0] = PxVec3(0.0f, 1.0f, 0.0f); - jdesc.attachPositions[1] = PxVec3(0.0f, -1.0f, 0.0f); - TkJoint* joint = framework->createJoint(jdesc); - EXPECT_TRUE(joint != nullptr); - tracker.joints.insert(joint); - - NvBlastExtRadialDamageDesc radialDamage1 = getRadialDamageDesc(0, 1, 0, 2, 2); - actor1->damage(getFalloffProgram(), &radialDamage1, sizeof(radialDamage1), getDefaultMaterial()); - NvBlastExtRadialDamageDesc radialDamage2 = getRadialDamageDesc(0, -1, 0, 2, 2); - actor2->damage(getFalloffProgram(), &radialDamage2, sizeof(radialDamage2), getDefaultMaterial()); - - group->process(); - group->sync(); - - TkActor* actors1[2]; - TkActor* actors2[2]; - EXPECT_EQ(2, family1->getActors(actors1, 2)); - EXPECT_EQ(2, family2->getActors(actors2, 2)); - - const TkJointData jdata = joint->getData(); - EXPECT_TRUE(jdata.actors[0] != nullptr); - EXPECT_TRUE(jdata.actors[1] != nullptr); - EXPECT_TRUE(&jdata.actors[0]->getFamily() == family1); - EXPECT_TRUE(&jdata.actors[1]->getFamily() == family2); - - // Clean up - if (explicitJointRelease) - { - joint->release(); - family2->release(); - family1->release(); - asset->release(); - releaseFramework(); - } - else - { - EXPECT_EQ(1, tracker.joints.size()); - releaseFramework(); - // Commenting these out - but shouldn't we be sending delete events when we release the framework? -// EXPECT_EQ(0, tracker.joints.size()); -// EXPECT_EQ(0, tracker.actors.size()); - } - } - -protected: - // http://clang.llvm.org/compatibility.html#dep_lookup_bases - // http://stackoverflow.com/questions/6592512/templates-parent-class-member-variables-not-visible-in-inherited-class - - using TkBaseTest<FailLevel, Verbosity>::testAssets; - using TkBaseTest<FailLevel, Verbosity>::m_taskman; - using TkBaseTest<FailLevel, Verbosity>::createFramework; - using TkBaseTest<FailLevel, Verbosity>::releaseFramework; - using TkBaseTest<FailLevel, Verbosity>::createTestAssets; - using TkBaseTest<FailLevel, Verbosity>::releaseTestAssets; - using TkBaseTest<FailLevel, Verbosity>::getCubeSlicerProgram; - using TkBaseTest<FailLevel, Verbosity>::getDefaultMaterial; - using TkBaseTest<FailLevel, Verbosity>::getRadialDamageDesc; - using TkBaseTest<FailLevel, Verbosity>::getFalloffProgram; -}; - - -typedef TkCompositeTest<NvBlastMessage::Error, 1> TkCompositeTestAllowWarnings; -typedef TkCompositeTest<NvBlastMessage::Error, 1> TkCompositeTestStrict; - - -/* -1) Create assembly, actors and joints should be created automatically -*/ - -TEST_F(TkCompositeTestStrict, AssemblyCreateAndRelease_NoNRFJoints_NoSerialization) -{ - assemblyCreateAndRelease(false, false); -} - -TEST_F(TkCompositeTestStrict, AssemblyCreateAndRelease_NoNRFJoints_AssemblySerialization) -{ - assemblyCreateAndRelease(false, true); -} - -TEST_F(TkCompositeTestStrict, AssemblyCreateAndRelease_WithNRFJoints_NoSerialization) -{ - assemblyCreateAndRelease(true, false); -} - -TEST_F(TkCompositeTestStrict, AssemblyCreateAndRelease_WithNRFJoints_AssemblySerialization) -{ - assemblyCreateAndRelease(true, true); -} - - -/** -2) Create an actor with internal joints. Splitting the actor should cause joint create events to be dispatched - -3) Joint update events should be fired when attached actors change - -4) Joint delete events should be fired when at least one attached actor is deleted -*/ - -TEST_F(TkCompositeTestStrict, AssemblyInternalJoints_NoSerialization) -{ - assemblyInternalJoints(false); -} - -TEST_F(TkCompositeTestStrict, AssemblyInternalJoints_AssemblySerialization) -{ - assemblyInternalJoints(true); -} - - -/** -5) Creating a composite from assets with internal joints should have expected behaviors (1-4) above -*/ - -TEST_F(TkCompositeTestStrict, AssemblyCompositeWithInternalJoints_NoNRFJoints_NoSerialization) -{ - assemblyCompositeWithInternalJoints(false, false); -} - -TEST_F(TkCompositeTestStrict, AssemblyCompositeWithInternalJoints_NoNRFJoints_AssemblySerialization) -{ - assemblyCompositeWithInternalJoints(false, true); -} - -TEST_F(TkCompositeTestStrict, AssemblyCompositeWithInternalJoints_WithNRFJoints_NoSerialization) -{ - assemblyCompositeWithInternalJoints(true, false); -} - -TEST_F(TkCompositeTestStrict, AssemblyCompositeWithInternalJoints_WithNRFJoints_AssemblySerialization) -{ - assemblyCompositeWithInternalJoints(true, true); -} - - -/* -More tests -*/ - -TEST_F(TkCompositeTestStrict, AssemblyExternalJoints_MultiFamilyDamage) -{ - assemblyExternalJoints_MultiFamilyDamage(true); -} - -TEST_F(TkCompositeTestStrict, AssemblyExternalJoints_MultiFamilyDamage_AutoJointRelease) -{ - assemblyExternalJoints_MultiFamilyDamage(false); -} diff --git a/NvBlast/test/src/unit/TkTests.cpp b/NvBlast/test/src/unit/TkTests.cpp deleted file mode 100644 index 045b0c9..0000000 --- a/NvBlast/test/src/unit/TkTests.cpp +++ /dev/null @@ -1,1528 +0,0 @@ -#include "TkBaseTest.h" - -#include <map> -#include <random> -#include <algorithm> - -#include "PsMemoryBuffer.h" - -#include "NvBlastTkSerializable.h" - -#include "NvBlastTime.h" - - -struct ExpectedVisibleChunks -{ - ExpectedVisibleChunks() :numActors(0), numChunks(0) {} - ExpectedVisibleChunks(size_t a, size_t c) :numActors(a), numChunks(c) {} - size_t numActors; size_t numChunks; -}; - -void testResults(std::vector<TkFamily*>& families, std::map<TkFamily*, ExpectedVisibleChunks>& expectedVisibleChunks) -{ - size_t numActors = 0; - for (TkFamily* fam : families) - { - auto ex = expectedVisibleChunks[fam]; - EXPECT_EQ(ex.numActors, fam->getActorCount()); - numActors += ex.numActors; - std::vector<TkActor*> actors(fam->getActorCount()); - fam->getActors(actors.data(), static_cast<uint32_t>(actors.size())); - for (TkActor* actor : actors) - { - EXPECT_EQ(ex.numChunks, actor->getVisibleChunkCount()); - } - } - - size_t numActorsExpected = 0; - for (auto expected : expectedVisibleChunks) - { - numActorsExpected += expected.second.numActors; - } - - EXPECT_EQ(numActorsExpected, numActors); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Tests -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - -TEST_F(TkTestStrict, CreateFramework) -{ - createFramework(); - releaseFramework(); -} - -TEST_F(TkTestStrict, CreateAsset) -{ - createFramework(); - - createTestAssets(); - releaseTestAssets(); - - releaseFramework(); -} - -#if USE_PHYSX_DISPATCHER -TEST_F(TkTestStrict, DISABLED_MemLeak) -{ - PxFoundation* pxFoundation = PxCreateFoundation(PX_FOUNDATION_VERSION, *this, *this); - PxU32 affinity[] = { 1, 2, 4, 8 }; - PxDefaultCpuDispatcher* cpuDispatcher = PxDefaultCpuDispatcherCreate(4, affinity); - cpuDispatcher->setRunProfiled(false); - PxTaskManager* taskman = PxTaskManager::createTaskManager(*this, cpuDispatcher, nullptr); - - cpuDispatcher->release(); - taskman->release(); - pxFoundation->release(); -} -#endif - -TEST_F(TkTestAllowWarnings, ActorDamageNoGroup) -{ - createFramework(); - createTestAssets(); - - TkFramework* fwk = NvBlastTkFrameworkGet(); - - TkActorDesc actorDesc; - actorDesc.asset = testAssets[0]; - TkActor* actor = fwk->createActor(actorDesc); - - const size_t bondFractureCount = 4; - NvBlastFractureBuffers commands; - NvBlastBondFractureData bdata[bondFractureCount]; - for (uint32_t i = 0; i < bondFractureCount; i++) - { - bdata[i].nodeIndex0 = 2 * i + 0; - bdata[i].nodeIndex1 = 2 * i + 1; - bdata[i].health = 1.0f; - } - commands.bondFractureCount = bondFractureCount; - commands.bondFractures = bdata; - commands.chunkFractureCount = 0; - commands.chunkFractures = nullptr; - actor->applyFracture(&commands, &commands); - - TkFamily& family = actor->getFamily(); - - EXPECT_TRUE(commands.bondFractureCount == 4); - EXPECT_TRUE(actor->isPending()); - - TkGroupDesc gdesc; - gdesc.pxTaskManager = m_taskman; - TkGroup* group = fwk->createGroup(gdesc); - EXPECT_TRUE(group != nullptr); - - group->addActor(*actor); - - group->process(); - group->sync(true); - - EXPECT_FALSE(actor->isPending()); - EXPECT_EQ(2, family.getActorCount()); - - releaseFramework(); -} - -TEST_F(TkTestAllowWarnings, ActorDamageGroup) -{ - TEST_ZONE_BEGIN("ActorDamageGroup"); - - createFramework(); - createTestAssets(); - - TkFramework* fwk = NvBlastTkFrameworkGet(); - - TestFamilyTracker ftrack1, ftrack2; - - TkGroupDesc gdesc; - gdesc.pxTaskManager = m_taskman; - TkGroup* group = fwk->createGroup(gdesc); - EXPECT_TRUE(group != nullptr); - - NvBlastExtRadialDamageDesc radialDamage = getRadialDamageDesc(0, 0, 0); - NvBlastExtShearDamageDesc shearDamage = getShearDamageDesc(0, 0, 0); - - std::vector<TkFamily*> families; - TkFamily* trackedFamily; - std::map<TkFamily*, ExpectedVisibleChunks> expectedVisibleChunks; - - { - TkActorDesc adesc(testAssets[0]); - - TkActor* actor1 = fwk->createActor(adesc); - EXPECT_TRUE(actor1 != nullptr); - - TkActor* actor2 = fwk->createActor(adesc); - EXPECT_TRUE(actor2 != nullptr); - - - expectedVisibleChunks[&actor1->getFamily()] = ExpectedVisibleChunks(8, 1); // full damage - expectedVisibleChunks[&actor2->getFamily()] = ExpectedVisibleChunks(1, 1); // not split - - GeneratorAsset cube; - generateCube(cube, 5, 2); - TkAssetDesc assetDesc; - assetDesc.bondCount = (uint32_t)cube.solverBonds.size(); - assetDesc.bondDescs = cube.solverBonds.data(); - assetDesc.chunkCount = (uint32_t)cube.chunks.size(); - assetDesc.chunkDescs = cube.solverChunks.data(); - assetDesc.bondFlags = nullptr; - - TkAsset* cubeAsset = fwk->createAsset(assetDesc); - testAssets.push_back(cubeAsset); - - TkActorDesc cubeAD(cubeAsset); - - TkActor* cubeActor1 = fwk->createActor(cubeAD); - EXPECT_TRUE(cubeActor1 != nullptr); - - trackedFamily = &cubeActor1->getFamily(); - cubeActor1->getFamily().addListener(ftrack1); - - TkActor* cubeActor2 = fwk->createActor(cubeAD); - EXPECT_TRUE(cubeActor2 != nullptr); - - CSParams p(0, 0.0f); - - expectedVisibleChunks[&cubeActor1->getFamily()] = ExpectedVisibleChunks(2, 4); // split in 2, 4 chunks each - expectedVisibleChunks[&cubeActor2->getFamily()] = ExpectedVisibleChunks(1, 1); // not split - - ftrack1.insertActor(cubeActor1); - ftrack2.insertActor(actor1); - - actor1->getFamily().addListener(ftrack2); - - TEST_ZONE_BEGIN("add to groups"); - group->addActor(*cubeActor1); - group->addActor(*cubeActor2); - group->addActor(*actor1); - group->addActor(*actor2); - TEST_ZONE_END("add to groups"); - - families.push_back(&cubeActor1->getFamily()); - families.push_back(&cubeActor2->getFamily()); - families.push_back(&actor1->getFamily()); - families.push_back(&actor2->getFamily()); - - cubeActor1->damage(getCubeSlicerProgram(), &p, sizeof(p), getDefaultMaterial()); - actor1->damage(getFalloffProgram(), &radialDamage, sizeof(radialDamage), getDefaultMaterial()); - } - - EXPECT_FALSE(group->sync(true)); - EXPECT_FALSE(group->sync(false)); - - group->process(); - group->sync(); - - testResults(families, expectedVisibleChunks); - - - { - std::vector<TkActor*> actors(trackedFamily->getActorCount()); - trackedFamily->getActors(actors.data(), static_cast<uint32_t>(actors.size())); - for (TkActor* actor : actors) - { - CSParams p(1, 0.0f); - actor->damage(getCubeSlicerProgram(), &p, sizeof(p), getDefaultMaterial()); - } - } - expectedVisibleChunks[trackedFamily] = ExpectedVisibleChunks(4, 2); - - group->process(); - group->sync(); - - testResults(families, expectedVisibleChunks); - - - { - std::vector<TkActor*> actors(trackedFamily->getActorCount()); - trackedFamily->getActors(actors.data(), static_cast<uint32_t>(actors.size())); - for (TkActor* actor : actors) - { - CSParams p(2, 0.0f); - actor->damage(getCubeSlicerProgram(), &p, sizeof(p), getDefaultMaterial()); - } - } - - expectedVisibleChunks[trackedFamily] = ExpectedVisibleChunks(8, 1); - - group->process(); - group->sync(); - - testResults(families, expectedVisibleChunks); - - - { - std::vector<TkActor*> actors(trackedFamily->getActorCount()); - trackedFamily->getActors(actors.data(), static_cast<uint32_t>(actors.size())); - TEST_ZONE_BEGIN("damage"); - for (TkActor* actor : actors) - { - actor->damage(getFalloffProgram(), &radialDamage, sizeof(radialDamage), getDefaultMaterial()); - } - TEST_ZONE_END("damage"); - } - expectedVisibleChunks[trackedFamily] = ExpectedVisibleChunks(4096, 1); - - group->process(); - while (!group->sync(true)); - - testResults(families, expectedVisibleChunks); - - - - { - std::vector<TkActor*> actors(trackedFamily->getActorCount()); - trackedFamily->getActors(actors.data(), static_cast<uint32_t>(actors.size())); - TEST_ZONE_BEGIN("damage"); - for (TkActor* actor : actors) - { - actor->damage(getShearProgram(), &shearDamage, sizeof(shearDamage), getDefaultMaterial()); - } - TEST_ZONE_END("damage"); - } - - group->process(); - while (!group->sync(true)) - ; - - - - { - std::vector<TkActor*> actors(trackedFamily->getActorCount()); - trackedFamily->getActors(actors.data(), static_cast<uint32_t>(actors.size())); - TEST_ZONE_BEGIN("damage"); - for (TkActor* actor : actors) - { - actor->damage(getShearProgram(), &shearDamage, sizeof(shearDamage), getDefaultMaterial()); - } - TEST_ZONE_END("damage"); - } - - group->process(); - while (!group->sync(true)); - - group->release(); - - TEST_ZONE_BEGIN("family release"); - trackedFamily->release(); - TEST_ZONE_END("family release"); - - releaseTestAssets(); - releaseFramework(); - - TEST_ZONE_END("ActorDamageGroup"); -} - - -TEST_F(TkTestAllowWarnings, ActorDamageMultiGroup) -{ - createFramework(); - createTestAssets(); - - TkFramework* fwk = NvBlastTkFrameworkGet(); - - TestFamilyTracker ftrack1, ftrack2; - - TkGroupDesc gdesc; - gdesc.pxTaskManager = m_taskman; - TkGroup* group0 = fwk->createGroup(gdesc); - EXPECT_TRUE(group0 != nullptr); - TkGroup* group1 = fwk->createGroup(gdesc); - EXPECT_TRUE(group1 != nullptr); - - std::vector<TkFamily*> families(2); - std::map<TkFamily*, ExpectedVisibleChunks> expectedVisibleChunks; - - // prepare 2 equal actors/families and damage - { - GeneratorAsset cube; - generateCube(cube, 6, 2, 5); - TkAssetDesc assetDesc; - assetDesc.bondCount = (uint32_t)cube.solverBonds.size(); - assetDesc.bondDescs = cube.solverBonds.data(); - assetDesc.chunkCount = (uint32_t)cube.chunks.size(); - assetDesc.chunkDescs = cube.solverChunks.data(); - assetDesc.bondFlags = nullptr; - - TkAsset* cubeAsset = fwk->createAsset(assetDesc); - testAssets.push_back(cubeAsset); - - TkActorDesc cubeAD(cubeAsset); - - TkActor* cubeActor0 = fwk->createActor(cubeAD); - EXPECT_TRUE(cubeActor0 != nullptr); - cubeActor0->getFamily().addListener(ftrack1); - - TkActor* cubeActor1 = fwk->createActor(cubeAD); - EXPECT_TRUE(cubeActor1 != nullptr); - cubeActor1->getFamily().addListener(ftrack2); - - ftrack1.insertActor(cubeActor0); - ftrack2.insertActor(cubeActor1); - - group0->addActor(*cubeActor0); - group1->addActor(*cubeActor1); - - families[0] = (&cubeActor0->getFamily()); - families[1] = (&cubeActor1->getFamily()); - - { - CSParams p0(0, 0.0f); - CSParams p1(1, 0.0f); - cubeActor0->damage(getCubeSlicerProgram(), &p0, sizeof(p0), getDefaultMaterial()); - cubeActor0->damage(getCubeSlicerProgram(), &p1, sizeof(p1), getDefaultMaterial()); - - cubeActor1->damage(getCubeSlicerProgram(), &p0, sizeof(p0), getDefaultMaterial()); - } - - expectedVisibleChunks[families[0]] = ExpectedVisibleChunks(4, 2); // split in 4, 2 chunks each - expectedVisibleChunks[families[1]] = ExpectedVisibleChunks(2, 4); // split in 2, 4 chunks each - } - - // async process 2 groups - { - EXPECT_TRUE(group0->process()); - EXPECT_TRUE(group1->process()); - uint32_t completed = 0; - while (completed < 2) - { - if (group0->sync(false)) - completed++; - if (group1->sync(false)) - completed++; - } - } - - // checks - testResults(families, expectedVisibleChunks); - EXPECT_EQ(families[0]->getActorCount(), 4); - EXPECT_EQ(group0->getActorCount(), 4); - EXPECT_EQ(families[1]->getActorCount(), 2); - EXPECT_EQ(group1->getActorCount(), 2); - - // we have group0 with 4 actors 2 chunks: - // group0: [2]' [2]' [2]' [2]' (family0') - // group1: [4]'' [4]'' (family1'') - // rearrange: - // group0: [2]' [2]' [4]'' - // group1: [4]'' [2]' [2]' - { - TkActor* group0Actors[2]; - group0->getActors(group0Actors, 2, 1); // start index: 1, because..why not? - TkActor* group1Actors[2]; - group1->getActors(group1Actors, 2, 0); - group0Actors[0]->removeFromGroup(); - group1->addActor(*group0Actors[0]); - group0Actors[1]->removeFromGroup(); - group1->addActor(*group0Actors[1]); - group1Actors[0]->removeFromGroup(); - group0->addActor(*group1Actors[0]); - } - - // checks - EXPECT_EQ(families[0]->getActorCount(), 4); - EXPECT_EQ(group0->getActorCount(), 3); - EXPECT_EQ(families[1]->getActorCount(), 2); - EXPECT_EQ(group1->getActorCount(), 3); - - // damage all - { - TkActor* allActors[6]; - families[0]->getActors(allActors, 4, 0); - families[1]->getActors(allActors + 4, 2, 0); - - typedef std::pair<TkGroup*, TkFamily*> pair; - std::set<pair> combinations; - for (auto actor : allActors) - { - combinations.emplace(pair(actor->getGroup(), &actor->getFamily())); - if (actor->getVisibleChunkCount() == 4) - { - CSParams p1(1, 0.0f); - actor->damage(getCubeSlicerProgram(), &p1, sizeof(p1), getDefaultMaterial()); - } - CSParams p2(2, 0.0f); - actor->damage(getCubeSlicerProgram(), &p2, sizeof(p2), getDefaultMaterial()); - } - EXPECT_EQ(combinations.size(), 4); - - expectedVisibleChunks[families[0]] = ExpectedVisibleChunks(8, 1); // split in 8, 1 chunks each - expectedVisibleChunks[families[1]] = ExpectedVisibleChunks(8, 1); // split in 8, 1 chunks each - } - - // async process 2 groups - { - EXPECT_TRUE(group1->process()); - EXPECT_TRUE(group0->process()); - uint32_t completed = 0; - while (completed < 2) - { - if (group0->sync(false)) - completed++; - if (group1->sync(false)) - completed++; - } - } - - // checks - testResults(families, expectedVisibleChunks); - EXPECT_EQ(families[0]->getActorCount(), 8); - EXPECT_EQ(ftrack1.actors.size(), 8); - EXPECT_EQ(group0->getActorCount(), 8); - EXPECT_EQ(families[1]->getActorCount(), 8); - EXPECT_EQ(ftrack2.actors.size(), 8); - EXPECT_EQ(group1->getActorCount(), 8); - - // damage till the end, aggressively - std::default_random_engine re; - { - NvBlastExtRadialDamageDesc radialDamage = getRadialDamageDesc(0, 0, 0); - NvBlastExtShearDamageDesc shearDamage = getShearDamageDesc(0, 0, 0); - - std::vector<TkActor*> actors; - while (1) - { - TEST_ZONE_BEGIN("damage loop"); - uint32_t n0 = families[0]->getActorCount(); - uint32_t n1 = families[1]->getActorCount(); - actors.resize(n0 + n1); - families[0]->getActors(actors.data(), n0, 0); - families[1]->getActors(actors.data() + n0, n1, 0); - - bool workTBD = false; - for (TkActor* actor : actors) - { - if (!NvBlastActorCanFracture(actor->getActorLL(), nullptr)) - { - continue; - } - - workTBD = true; - - if (actor->getGraphNodeCount() > 1) - { - actor->damage(getFalloffProgram(), &radialDamage, sizeof(radialDamage), getDefaultMaterial()); - } - else - { - actor->damage(getShearProgram(), &shearDamage, sizeof(shearDamage), getDefaultMaterial()); - } - - if (re() % 1000 < 500) - { - // switch group - TkGroup* newGroup = actor->getGroup() == group0 ? group1 : group0; - actor->removeFromGroup(); - newGroup->addActor(*actor); - } - } - - if (!workTBD) - break; - - // async process 2 groups - { - EXPECT_TRUE(group1->process()); - EXPECT_TRUE(group0->process()); - uint32_t completed = 0; - while (completed < 2) - { - if (group0->sync(false)) - completed++; - if (group1->sync(false)) - completed++; - } - } - TEST_ZONE_END("damage loop"); - } - } - - // checks - EXPECT_EQ(families[0]->getActorCount(), ftrack1.actors.size()); - EXPECT_EQ(families[1]->getActorCount(), ftrack2.actors.size()); - EXPECT_EQ(65536, families[0]->getActorCount() + families[1]->getActorCount()); - EXPECT_EQ(65536, group0->getActorCount() + group1->getActorCount()); - - group0->release(); - group1->release(); - - for (auto f : families) - f->release(); - - releaseTestAssets(); - releaseFramework(); -} - -TEST_F(TkTestAllowWarnings, ActorDamageBufferedDamage) -{ - createFramework(); - TkFramework* fwk = NvBlastTkFrameworkGet(); - - // group - TkGroupDesc gdesc; - gdesc.pxTaskManager = m_taskman; - TkGroup* group = fwk->createGroup(gdesc); - EXPECT_TRUE(group != nullptr); - - // random engine - std::default_random_engine re; - - // cube asset - GeneratorAsset cube; - generateCube(cube, 4, 2, 3); - TkAssetDesc assetDesc; - assetDesc.bondCount = (uint32_t)cube.solverBonds.size(); - assetDesc.bondDescs = cube.solverBonds.data(); - assetDesc.chunkCount = (uint32_t)cube.chunks.size(); - assetDesc.chunkDescs = cube.solverChunks.data(); - assetDesc.bondFlags = nullptr; - TkAsset* cubeAsset = fwk->createAsset(assetDesc); - testAssets.push_back(cubeAsset); - - // actor desc - TkActorDesc cubeAD(cubeAsset); - - // test will be repated 'trials' times. Because of random shuffle inside. - const uint32_t trials = 100; - for (uint32_t i = 0; i < trials; i++) - { - // create actor - TkActor* actor = fwk->createActor(cubeAD); - EXPECT_TRUE(actor != nullptr); - TkFamily* family = (&actor->getFamily()); - group->addActor(*actor); - - // damage 3 times with CubeSlicer 2 * 2 * 2 = 8 actors - // damage 4 corners with falloff radial 4 * 2 = 8 actors - // total 16 actors - uint32_t expectedActorCount = 16; - - // fallof params - const float P = 0.5f; - const float R = 0.35f; - - // 2 of damage types would be through user's NvBlastDamageProgram, this pointer must live till group->sync() - NvBlastExtRadialDamageDesc userR0 = getRadialDamageDesc(P, P, 0, R, R); - NvBlastProgramParams userProgramParams0 = - { - &userR0, // damageDescBuffer - 1, // damageDescCount - nullptr, // material - }; - - NvBlastExtRadialDamageDesc userR1 = getRadialDamageDesc(-P, P, 0, R, R); - NvBlastProgramParams userProgramParams1 = - { - &userR1, // damageDescBuffer - 1, // damageDescCount - nullptr, // material - }; - - // fill damage functions, shuffle and apply - { - CSParams p0(0, 0.0f); - CSParams p1(1, 0.0f); - CSParams p2(2, 0.0f); - NvBlastExtRadialDamageDesc r0 = getRadialDamageDesc(P, -P, 0, R, R); - NvBlastExtRadialDamageDesc r1 = getRadialDamageDesc(-P, -P, 0, R, R); - - const uint32_t damageCount = 7; - std::vector<std::function<void(void)>> damageFns(damageCount); - damageFns[0] = [&]() { actor->damage(getCubeSlicerProgram(), &p0, sizeof(p0), getDefaultMaterial()); }; - damageFns[1] = [&]() { actor->damage(getCubeSlicerProgram(), &p1, sizeof(p1), getDefaultMaterial()); }; - damageFns[2] = [&]() { actor->damage(getCubeSlicerProgram(), &p2, sizeof(p2), getDefaultMaterial()); }; - damageFns[3] = [&]() { actor->damage(getFalloffProgram(), &r0, sizeof(r0), getDefaultMaterial()); }; - damageFns[4] = [&]() { actor->damage(getFalloffProgram(), &r1, sizeof(r1), getDefaultMaterial()); }; - damageFns[5] = [&]() { actor->damage(getFalloffProgram(), &userProgramParams0); }; - damageFns[6] = [&]() { actor->damage(getFalloffProgram(), &userProgramParams1); }; - - // shuffle order! - std::shuffle(std::begin(damageFns), std::end(damageFns), re); - - for (uint32_t i = 0; i < damageCount; i++) - { - damageFns[i](); - } - } - - // sync - EXPECT_TRUE(group->process()); - group->sync(true); - - const auto ac = family->getActorCount(); - - // check - EXPECT_EQ(family->getActorCount(), expectedActorCount); - EXPECT_EQ(group->getActorCount(), expectedActorCount); - - // release - std::vector<TkActor*> actors(family->getActorCount()); - family->getActors(actors.data(), static_cast<uint32_t>(actors.size())); - for (auto a : actors) - a->removeFromGroup(); - family->release(); - } - - group->release(); - releaseFramework(); -} - -TEST_F(TkTestStrict, CreateActor) -{ - createFramework(); - TkFramework* framework = NvBlastTkFrameworkGet(); - - const uint32_t assetDescCount = sizeof(g_assetDescs) / sizeof(g_assetDescs[0]); - - std::vector<TkAsset*> assets(assetDescCount); - - // assets - for (uint32_t i = 0; i < assetDescCount; ++i) - { - TkAssetDesc desc; - reinterpret_cast<NvBlastAssetDesc&>(desc) = g_assetDescs[i]; - desc.bondFlags = nullptr; - assets[i] = framework->createAsset(desc); - EXPECT_TRUE(assets[i] != nullptr); - } - - // actors - std::vector<TkActor*> actors;; - std::vector<TkFamily*> actorFamilies;; - for (const TkAsset* asset : assets) - { - for (int i = 0; i < 2; i++) - { - TkActorDesc desc(asset); - TkActor* actor = framework->createActor(desc); - EXPECT_TRUE(actor != nullptr); - EXPECT_TRUE(actor->getActorLL() != nullptr); - //EXPECT_TRUE(&actor->getFamily() != nullptr); - EXPECT_TRUE(actor->getFamily().getActorCount() == 1); - actors.push_back(actor); - EXPECT_TRUE(std::find(actorFamilies.begin(), actorFamilies.end(), &actor->getFamily()) == actorFamilies.end()); - actorFamilies.push_back(&actor->getFamily()); - - } - } - - // framework checks - { - std::vector<TkObject*> objects; - - // assets - { - const TkType* assetType = framework->getType(TkTypeIndex::Asset); - objects.resize(framework->getObjectCount(*assetType)); - EXPECT_TRUE(framework->getObjects(reinterpret_cast<TkIdentifiable**>(objects.data()), static_cast<uint32_t>(objects.size()), *assetType) == static_cast<uint32_t>(objects.size())); - ExpectArrayMatch(objects.data(), objects.size(), (TkObject**)assets.data(), assets.size()); - } - - // actors -# if(0) // framework does not track actors explicitly anymore - { - const TkType* actorType = framework->getType(TkTypeIndex::Actor); - objects.resize(framework->getObjectCount(*actorType)); - EXPECT_TRUE(framework->getObjects(reinterpret_cast<TkIdentifiable**>(objects.data()), objects.size(), *actorType) == objects.size()); - ExpectArrayMatch(objects.data(), objects.size(), (TkObject**)actors.data(), actors.size()); - } -# endif - // families - { - const TkType* familyType = framework->getType(TkTypeIndex::Family); - objects.resize(framework->getObjectCount(*familyType)); - EXPECT_TRUE(framework->getObjects(reinterpret_cast<TkIdentifiable**>(objects.data()), static_cast<uint32_t>(objects.size()), *familyType) == static_cast<uint32_t>(objects.size())); - ExpectArrayMatch(objects.data(), objects.size(), (TkObject**)actorFamilies.data(), actorFamilies.size()); - } - } - - // release - for (TkActor* actor : actors) - { - actor->release(); - } - for (TkAsset* asset : assets) - { - asset->release(); - } - - releaseFramework(); -} - -template<int FailMask, int Verbosity> -TkFamily* TkBaseTest<FailMask, Verbosity>::familySerialization(TkFamily* family) -{ - TkFramework* fw = NvBlastTkFrameworkGet(); - - const TkType* familyType = fw->getType(TkTypeIndex::Family); - EXPECT_TRUE(familyType != nullptr); - - PsMemoryBuffer* membuf = PX_NEW(PsMemoryBuffer); - EXPECT_TRUE(membuf != nullptr); - if (membuf != nullptr) - { - const bool result = family->serialize(*membuf); - EXPECT_EQ(true, result); - if (!result) - { - return family; - } - const size_t familyActorCount = family->getActorCount(); - const TkAsset* familyAsset = family->getAsset(); - family->release(); - family = reinterpret_cast<TkFamily*>(fw->deserialize(*membuf)); - EXPECT_TRUE(family != nullptr); - if (family != nullptr) - { - EXPECT_EQ(familyActorCount, family->getActorCount()); - EXPECT_EQ(familyAsset, family->getAsset()); - } - membuf->release(); - } - - return family; -} - -TEST_F(TkTestAllowWarnings, FamilySerialization) -{ - createFramework(); - TkFramework* fwk = NvBlastTkFrameworkGet(); - - // group - TkGroupDesc gdesc; - gdesc.pxTaskManager = m_taskman; - TkGroup* group = fwk->createGroup(gdesc); - EXPECT_TRUE(group != nullptr); - - // random engine - std::default_random_engine re; - - // cube asset - TkAsset* cubeAsset = createCubeAsset(4, 2, 3, false); - - // actor desc - TkActorDesc cubeAD(cubeAsset); - - // create actor - TkActor* actor = fwk->createActor(cubeAD); - EXPECT_TRUE(actor != nullptr); - TkFamily* family = (&actor->getFamily()); - - // set an ID - NvBlastID id; - memcpy(id.data, "Observer-expectancy effect", sizeof(NvBlastID)); // Stuffing an arbitrary 16 bytes (The prefix of the given string) - cubeAsset->setID(id); - - // serialize/deserialize - family = familySerialization(family); - - // fill damage functions, apply one by one and serialize family in between - { - // damage 3 times with CubeSlicer 2 * 2 * 2 = 8 actors - // damage 4 corners with falloff radial 4 * 2 = 8 actors - // total 16 actors - uint32_t expectedActorCount = 16; - - // cube slicer params - CSParams p0(0, 0.0f); - CSParams p1(1, 0.0f); - CSParams p2(2, 0.0f); - - // fallof params - const float P = 0.5f; - const float R = 0.35f; - NvBlastExtRadialDamageDesc r0 = getRadialDamageDesc(P, P, 0, R, R); - NvBlastExtRadialDamageDesc r1 = getRadialDamageDesc(-P, P, 0, R, R); - NvBlastExtRadialDamageDesc r2 = getRadialDamageDesc(P, -P, 0, R, R); - NvBlastExtRadialDamageDesc r3 = getRadialDamageDesc(-P, -P, 0, R, R); - - const uint32_t damageCount = 7; - std::vector<std::function<void(TkActor* a)>> damageFns(damageCount); - damageFns[0] = [&](TkActor* a) { a->damage(getCubeSlicerProgram(), &p0, sizeof(p0), getDefaultMaterial()); }; - damageFns[1] = [&](TkActor* a) { a->damage(getCubeSlicerProgram(), &p1, sizeof(p1), getDefaultMaterial()); }; - damageFns[2] = [&](TkActor* a) { a->damage(getCubeSlicerProgram(), &p2, sizeof(p2), getDefaultMaterial()); }; - damageFns[3] = [&](TkActor* a) { a->damage(getFalloffProgram(), &r0, sizeof(r0), getDefaultMaterial()); }; - damageFns[4] = [&](TkActor* a) { a->damage(getFalloffProgram(), &r1, sizeof(r1), getDefaultMaterial()); }; - damageFns[5] = [&](TkActor* a) { a->damage(getFalloffProgram(), &r2, sizeof(r2), getDefaultMaterial()); }; - damageFns[6] = [&](TkActor* a) { a->damage(getFalloffProgram(), &r3, sizeof(r3), getDefaultMaterial()); }; - - std::vector<TkActor*> actors(64); - - for (uint32_t i = 0; i < damageCount; i++) - { - actors.resize(family->getActorCount()); - family->getActors(actors.data(), static_cast<uint32_t>(actors.size())); - - // damage - for (auto actor : actors) - { - group->addActor(*actor); - damageFns[i](actor); - } - - // sync - EXPECT_TRUE(group->process()); - group->sync(true); - - family = familySerialization(family); - } - - // check - EXPECT_EQ(family->getActorCount(), expectedActorCount); - } - - // release - family->release(); - - group->release(); - releaseFramework(); -} - -TEST_F(TkTestStrict, GroupStats) -{ - createFramework(); - TkFramework* fwk = NvBlastTkFrameworkGet(); - - // group - TkGroupDesc gdesc; - gdesc.pxTaskManager = m_taskman; - TkGroup* group = fwk->createGroup(gdesc); - EXPECT_TRUE(group != nullptr); - - TkAsset* cubeAsset = createCubeAsset(4, 2); - TkActorDesc cubeDesc(cubeAsset); - - TkActor* cubeActor1 = fwk->createActor(cubeDesc); - TkActor* cubeActor2 = fwk->createActor(cubeDesc); - TkActor* cubeActor3 = fwk->createActor(cubeDesc); - TkActor* cubeActor4 = fwk->createActor(cubeDesc); - - group->addActor(*cubeActor1); - group->addActor(*cubeActor2); - group->addActor(*cubeActor3); - group->addActor(*cubeActor4); - - NvBlastExtRadialDamageDesc r0 = getRadialDamageDesc(0.0f, 0.0f, 0.0f); - cubeActor1->damage(getFalloffProgram(), &r0, sizeof(r0)); - cubeActor2->damage(getFalloffProgram(), &r0, sizeof(r0)); - cubeActor3->damage(getFalloffProgram(), &r0, sizeof(r0)); - cubeActor4->damage(getFalloffProgram(), &r0, sizeof(r0)); - - Nv::Blast::Time time; - group->process(); - group->sync(true); - int64_t groupTime = time.getElapsedTicks(); - - TkGroupStats gstats; - group->getStats(gstats); - - int64_t total = gstats.timers.fracture + gstats.timers.island + gstats.timers.material + gstats.timers.partition + gstats.timers.visibility; - -#if NV_PROFILE - EXPECT_GT(total, 0); // some values are reported - EXPECT_LT(groupTime, total); // total LL time is higher than group time - EXPECT_GT((double)gstats.workerTime / groupTime, 2.0); // expect some minimal speedup (including overhead) - EXPECT_EQ(4, gstats.processedActorsCount); // actors processed -#endif - - releaseFramework(); -} - -TEST_F(TkTestStrict, FractureReportSupport) -{ - createFramework(); - - TkFramework* fwk = NvBlastTkFrameworkGet(); - - NvBlastChunkDesc chunkDescs[] = - { - { { 0,0,0 }, 2, UINT32_MAX, NvBlastChunkDesc::SupportFlag, 'prnt' }, - { { -1,0,0 }, 1, 0, NvBlastChunkDesc::NoFlags, 'left' }, - { { +1,0,0 }, 1, 0, NvBlastChunkDesc::NoFlags, 'rght' }, - }; - - TkAssetDesc assetDesc; - assetDesc.chunkCount = sizeof(chunkDescs) / sizeof(NvBlastChunkDesc); - assetDesc.chunkDescs = chunkDescs; - assetDesc.bondCount = 0; - assetDesc.bondDescs = nullptr; - assetDesc.bondFlags = nullptr; - const TkAsset* asset = fwk->createAsset(assetDesc); - - TkActorDesc actorDesc; - actorDesc.asset = asset; - TkActor* actor = fwk->createActor(actorDesc); - actor->userData = (void*)'root'; - - class Listener : public TkEventListener - { - void receive(const TkEvent* events, uint32_t eventCount) override - { - for (uint32_t i = 0; i < eventCount; i++) - { - const TkEvent& event = events[i]; - switch (event.type) - { - case TkJointUpdateEvent::EVENT_TYPE: - FAIL() << "not expecting joints here"; - break; - - case TkFractureCommands::EVENT_TYPE: - { - const TkActorData& actor = event.getPayload<TkFractureCommands>()->tkActorData; - - // Group::sync still needed the family for SharedMemory management. - EXPECT_TRUE(nullptr != actor.family); - - EXPECT_EQ((void*)'root', actor.userData); - EXPECT_EQ(0, actor.index); - } - break; - - case TkFractureEvents::EVENT_TYPE: - { - const TkActorData& actor = event.getPayload<TkFractureEvents>()->tkActorData; - EXPECT_EQ((void*)'root', actor.userData); - EXPECT_EQ(0, actor.index); - } - break; - - case TkSplitEvent::EVENT_TYPE: - { - const TkSplitEvent* split = event.getPayload<TkSplitEvent>(); - - EXPECT_TRUE(nullptr != split->parentData.family); - EXPECT_EQ((void*)'root', split->parentData.userData); - EXPECT_EQ(0, split->parentData.index); - - EXPECT_EQ(2, split->numChildren); - EXPECT_EQ(1, split->children[0]->getVisibleChunkCount()); - - uint32_t visibleChunkIndex; - // child order is not mandatory - { - TkActor* a = split->children[0]; - a->getVisibleChunkIndices(&visibleChunkIndex, 1); - uint32_t li = a->getIndex(); - EXPECT_EQ(1, li); - EXPECT_EQ(split->parentData.family, &a->getFamily()); - EXPECT_EQ('left', a->getAsset()->getChunks()[visibleChunkIndex].userData); - } - - { - TkActor*a = split->children[1]; - a->getVisibleChunkIndices(&visibleChunkIndex, 1); - uint32_t ri = a->getIndex(); - EXPECT_EQ(2, ri); - EXPECT_EQ(split->parentData.family, &a->getFamily()); - EXPECT_EQ('rght', a->getAsset()->getChunks()[visibleChunkIndex].userData); - } - } - break; - - default: - FAIL() << "should not get here"; - } - } - } - } listener; - actor->getFamily().addListener(listener); - - // expected state for the original actor, see Listener - EXPECT_EQ((void*)'root', actor->userData); - EXPECT_EQ(0, actor->getIndex()); - - TkGroupDesc groupDesc = { m_taskman }; - TkGroup* group = fwk->createGroup(groupDesc); - - group->addActor(*actor); - - // this will trigger hierarchical chunk fracture - NvBlastExtRadialDamageDesc radialDamage = getRadialDamageDesc(0, 0, 0); - actor->damage(getFalloffProgram(), &radialDamage, sizeof(NvBlastExtRadialDamageDesc), getDefaultMaterial()); - - group->process(); - group->sync(); - - releaseFramework(); -} - -TEST_F(TkTestStrict, FractureReportGraph) -{ - createFramework(); - - TkFramework* fwk = NvBlastTkFrameworkGet(); - - NvBlastBond bondToBreak = { { 1,0,0 }, 1,{ 0, 0, 0 }, 0 }; - NvBlastBond bondToKeep = { { 1,0,0 }, 1,{ 10, 10, 10 }, 0 }; - NvBlastBondDesc bondDescs[] = - { - { { 1,2 }, bondToKeep }, - { { 2,3 }, bondToBreak }, - }; - - NvBlastChunkDesc chunkDescs[] = - { - { { 0,0,0 }, 2, UINT32_MAX, NvBlastChunkDesc::NoFlags, 'root' }, - { { -1,0,0 }, 1, 0, NvBlastChunkDesc::SupportFlag, 'A' }, - { { +1,0,0 }, 1, 0, NvBlastChunkDesc::SupportFlag, 'B' }, - { { +1,0,0 }, 1, 0, NvBlastChunkDesc::SupportFlag, 'C' }, - }; - - TkAssetDesc assetDesc; - assetDesc.chunkCount = sizeof(chunkDescs) / sizeof(NvBlastChunkDesc); - assetDesc.chunkDescs = chunkDescs; - assetDesc.bondCount = 2; - assetDesc.bondDescs = bondDescs; - assetDesc.bondFlags = nullptr; - const TkAsset* asset = fwk->createAsset(assetDesc); - - TkActorDesc actorDesc; - actorDesc.asset = asset; - TkActor* rootActor = fwk->createActor(actorDesc); - rootActor->userData = (void*)'root'; - - class Listener : public TkEventListener - { - void receive(const TkEvent* events, uint32_t eventCount) override - { - for (uint32_t i = 0; i < eventCount; i++) - { - const TkEvent& event = events[i]; - switch (event.type) - { - case TkJointUpdateEvent::EVENT_TYPE: - FAIL() << "not expecting joints here"; - break; - - case TkFractureCommands::EVENT_TYPE: - { - const TkActorData& actor = event.getPayload<TkFractureCommands>()->tkActorData; - - // Group::sync still needed the family for SharedMemory management. - EXPECT_TRUE(nullptr != actor.family); - - // original actor state is not preserved, the last test will fail - EXPECT_EQ((void*)'root', actor.userData); - EXPECT_EQ(0, actor.index); - - // this information was invalid anyway - //EXPECT_EQ(1, actor->getVisibleChunkCount()) << "state not preserved"; - } - break; - - case TkFractureEvents::EVENT_TYPE: - { - const TkActorData& actor = event.getPayload<TkFractureEvents>()->tkActorData; - - // Group::sync still needed the family for SharedMemory management. - EXPECT_TRUE(nullptr != actor.family); - - // original actor state is not preserved, the last test will fail - EXPECT_EQ((void*)'root', actor.userData); - EXPECT_EQ(0, actor.index); - - // this information was invalid anyway - //EXPECT_EQ(1, actor->getVisibleChunkCount()) << "state not preserved"; - } - break; - - case TkSplitEvent::EVENT_TYPE: - { - const TkSplitEvent* split = event.getPayload<TkSplitEvent>(); - EXPECT_EQ((void*)'root', split->parentData.userData); - EXPECT_EQ(0, split->parentData.index); - EXPECT_EQ(2, split->numChildren); - - uint32_t visibleChunkIndex[2]; - // child order is not mandatory - { - TkActor* a = split->children[1]; - EXPECT_EQ(2, a->getVisibleChunkCount()); // chunks A and B - a->getVisibleChunkIndices(visibleChunkIndex, 2); - uint32_t actorIndex = a->getIndex(); - EXPECT_EQ(0, actorIndex); // same index as the original actor - - // visible chunk order is not mandatory - EXPECT_EQ('B', a->getAsset()->getChunks()[visibleChunkIndex[0]].userData); - EXPECT_EQ('A', a->getAsset()->getChunks()[visibleChunkIndex[1]].userData); - } - - { - TkActor* a = split->children[0]; - EXPECT_EQ(1, a->getVisibleChunkCount()); - a->getVisibleChunkIndices(visibleChunkIndex, 1); - uint32_t actorIndex = a->getIndex(); - EXPECT_EQ(2, actorIndex); - EXPECT_EQ('C', a->getAsset()->getChunks()[visibleChunkIndex[0]].userData); - } - } - break; - - default: - FAIL() << "should not get here"; - } - } - } - } listener; - rootActor->getFamily().addListener(listener); - - // expected state for the original actor, see Listener - EXPECT_EQ((void*)'root', rootActor->userData); - EXPECT_EQ(0, rootActor->getIndex()); - EXPECT_EQ(1, rootActor->getVisibleChunkCount()); - - TkGroupDesc groupDesc = { m_taskman }; - TkGroup* group = fwk->createGroup(groupDesc); - - group->addActor(*rootActor); - - // this will trigger one bond to break - NvBlastExtRadialDamageDesc radialDamage = getRadialDamageDesc(0, 0, 0, 0.5f, 0.5f); - rootActor->damage(getFalloffProgram(), &radialDamage, sizeof(NvBlastExtRadialDamageDesc), getDefaultMaterial()); - - group->process(); - group->sync(); - - releaseFramework(); -} - -TEST_F(TkTestStrict, SplitWarning) // GWD-167 -{ - createFramework(); - - TkFramework* fwk = NvBlastTkFrameworkGet(); - - NvBlastChunkDesc chunkDescs[] = - { - { { 0,0,0 }, 2, UINT32_MAX, NvBlastChunkDesc::SupportFlag, 'root' }, - { { -1,0,0 }, 1, 0, NvBlastChunkDesc::NoFlags, 'A' }, - { { +1,0,0 }, 1, 0, NvBlastChunkDesc::NoFlags, 'B' }, - { { -1,0,0 }, 1, 0, NvBlastChunkDesc::NoFlags, 'C' }, - { { +1,0,0 }, 1, 0, NvBlastChunkDesc::NoFlags, 'D' }, - { { -1,0,0 }, 1, 1, NvBlastChunkDesc::NoFlags, 'AAAA' }, - { { +1,0,0 }, 1, 2, NvBlastChunkDesc::NoFlags, 'BBBB' }, - { { -1,0,0 }, 1, 3, NvBlastChunkDesc::NoFlags, 'CCCC' }, - { { +1,0,0 }, 1, 4, NvBlastChunkDesc::NoFlags, 'DDDD' }, - }; - - TkAssetDesc assetDesc; - assetDesc.chunkCount = sizeof(chunkDescs) / sizeof(NvBlastChunkDesc); - assetDesc.chunkDescs = chunkDescs; - assetDesc.bondCount = 0; - assetDesc.bondDescs = nullptr; - assetDesc.bondFlags = nullptr; - const TkAsset* asset = fwk->createAsset(assetDesc); - - TkActorDesc actorDesc; - actorDesc.asset = asset; - TkActor* actor = fwk->createActor(actorDesc); - - TkGroupDesc groupDesc = { m_taskman }; - TkGroup* group = fwk->createGroup(groupDesc); - - group->addActor(*actor); - - NvBlastExtRadialDamageDesc radialDamage = getRadialDamageDesc(0, 0, 0); - actor->damage(getFalloffProgram(), &radialDamage, sizeof(NvBlastExtRadialDamageDesc), getDefaultMaterial()); - - group->process(); - group->sync(); - - releaseFramework(); -} - - -TEST_F(TkTestAllowWarnings, ChangeThreadCountToZero) -{ - // tests that group still allocates memory for one worker - // by replacing to a 0 threads cpu dispatcher (warns) - // mainly relies on internal asserts - - class EventCounter : public TkEventListener - { - public: - EventCounter() :fracCommands(0), fracEvents(0) {} - - void receive(const TkEvent* events, uint32_t eventCount) - { - for (uint32_t i = 0; i < eventCount; i++) - { - const TkEvent& event = events[i]; - switch (event.type) - { - case TkFractureCommands::EVENT_TYPE: - fracCommands++; - break; - case TkFractureEvents::EVENT_TYPE: - fracEvents++; - break; - default: - FAIL(); - // no split due to single chunk - // no joints - } - } - } - - uint32_t fracCommands, fracEvents; - } listener; - - createFramework(); - TkFramework* fwk = NvBlastTkFrameworkGet(); - NvBlastChunkDesc chunkDescs[] = { - { { 0,0,0 }, 2, UINT32_MAX, NvBlastChunkDesc::SupportFlag, 'root' } - }; - - TkAssetDesc assetDesc; - assetDesc.chunkCount = sizeof(chunkDescs) / sizeof(NvBlastChunkDesc); - assetDesc.chunkDescs = chunkDescs; - assetDesc.bondCount = 0; - assetDesc.bondDescs = nullptr; - assetDesc.bondFlags = nullptr; - const TkAsset* asset = fwk->createAsset(assetDesc); - - TkActorDesc actorDesc; - actorDesc.asset = asset; - TkActor* actor1 = fwk->createActor(actorDesc); - TkActor* actor2 = fwk->createActor(actorDesc); - TkActor* actor3 = fwk->createActor(actorDesc); - TkActor* actor4 = fwk->createActor(actorDesc); - - actor1->getFamily().addListener(listener); - actor2->getFamily().addListener(listener); - actor3->getFamily().addListener(listener); - actor4->getFamily().addListener(listener); - -#if USE_PHYSX_DISPATCHER - PxU32 affinity[] = { 1, 2, 4, 8 }; - PxDefaultCpuDispatcher* disp0 = PxDefaultCpuDispatcherCreate(0, affinity); - disp0->setRunProfiled(false); - PxDefaultCpuDispatcher* disp4 = PxDefaultCpuDispatcherCreate(4, affinity); - disp4->setRunProfiled(false); -#else - TestCpuDispatcher* disp0 = new TestCpuDispatcher(0); - TestCpuDispatcher* disp4 = new TestCpuDispatcher(4); -#endif - - PxTaskManager* taskman = PxTaskManager::createTaskManager(*this, disp4); - - TkGroupDesc groupDesc = { taskman }; - TkGroup* group = fwk->createGroup(groupDesc); - - group->addActor(*actor1); - group->addActor(*actor2); - taskman->setCpuDispatcher(*disp0); - group->addActor(*actor3); - group->addActor(*actor4); - - NvBlastExtRadialDamageDesc radialDamage = getRadialDamageDesc(0, 0, 0); - actor1->damage(getFalloffProgram(), &radialDamage, sizeof(NvBlastExtRadialDamageDesc), getDefaultMaterial()); - actor2->damage(getFalloffProgram(), &radialDamage, sizeof(NvBlastExtRadialDamageDesc), getDefaultMaterial()); - actor3->damage(getFalloffProgram(), &radialDamage, sizeof(NvBlastExtRadialDamageDesc), getDefaultMaterial()); - actor4->damage(getFalloffProgram(), &radialDamage, sizeof(NvBlastExtRadialDamageDesc), getDefaultMaterial()); - - group->process(); - group->sync(); - - EXPECT_EQ(4, listener.fracCommands); - EXPECT_EQ(4, listener.fracEvents); - - releaseFramework(); - - disp0->release(); - disp4->release(); - taskman->release(); -} - -TEST_F(TkTestAllowWarnings, ChangeThreadCountUp) -{ - // tests that group allocates more memory for additional workers - // by replacing to a higher thread count cpu dispatcher (warns) - // mainly relies on internal asserts - - class EventCounter : public TkEventListener - { - public: - EventCounter() :fracCommands(0), fracEvents(0) {} - - void receive(const TkEvent* events, uint32_t eventCount) - { - for (uint32_t i = 0; i < eventCount; i++) - { - const TkEvent& event = events[i]; - switch (event.type) - { - case TkFractureCommands::EVENT_TYPE: - fracCommands++; - break; - case TkFractureEvents::EVENT_TYPE: - fracEvents++; - break; - default: - FAIL(); - // no split due to single chunk - // no joints - } - } - } - - uint32_t fracCommands, fracEvents; - } listener; - - createFramework(); - TkFramework* fwk = NvBlastTkFrameworkGet(); - NvBlastChunkDesc chunkDescs[] = { - { { 0,0,0 }, 2, UINT32_MAX, NvBlastChunkDesc::SupportFlag, 'root' } - }; - - TkAssetDesc assetDesc; - assetDesc.chunkCount = sizeof(chunkDescs) / sizeof(NvBlastChunkDesc); - assetDesc.chunkDescs = chunkDescs; - assetDesc.bondCount = 0; - assetDesc.bondDescs = nullptr; - assetDesc.bondFlags = nullptr; - const TkAsset* asset = fwk->createAsset(assetDesc); - - TkActorDesc actorDesc; - actorDesc.asset = asset; - TkActor* actor1 = fwk->createActor(actorDesc); - TkActor* actor2 = fwk->createActor(actorDesc); - TkActor* actor3 = fwk->createActor(actorDesc); - TkActor* actor4 = fwk->createActor(actorDesc); - - actor1->getFamily().addListener(listener); - actor2->getFamily().addListener(listener); - actor3->getFamily().addListener(listener); - actor4->getFamily().addListener(listener); - -#if USE_PHYSX_DISPATCHER - PxU32 affinity[] = { 1, 2, 4, 8 }; - PxDefaultCpuDispatcher* disp2 = PxDefaultCpuDispatcherCreate(2, affinity); - disp2->setRunProfiled(false); - PxDefaultCpuDispatcher* disp4 = PxDefaultCpuDispatcherCreate(4, affinity); - disp4->setRunProfiled(false); -#else - TestCpuDispatcher* disp2 = new TestCpuDispatcher(2); - TestCpuDispatcher* disp4 = new TestCpuDispatcher(4); -#endif - - PxTaskManager* taskman = PxTaskManager::createTaskManager(*this, disp2); - - TkGroupDesc groupDesc = { taskman }; - TkGroup* group = fwk->createGroup(groupDesc); - - group->addActor(*actor1); - group->addActor(*actor2); - group->addActor(*actor3); - group->addActor(*actor4); - - NvBlastExtRadialDamageDesc radialDamage = getRadialDamageDesc(0, 0, 0); - actor1->damage(getFalloffProgram(), &radialDamage, sizeof(NvBlastExtRadialDamageDesc), getDefaultMaterial()); - actor2->damage(getFalloffProgram(), &radialDamage, sizeof(NvBlastExtRadialDamageDesc), getDefaultMaterial()); - actor3->damage(getFalloffProgram(), &radialDamage, sizeof(NvBlastExtRadialDamageDesc), getDefaultMaterial()); - actor4->damage(getFalloffProgram(), &radialDamage, sizeof(NvBlastExtRadialDamageDesc), getDefaultMaterial()); - - taskman->setCpuDispatcher(*disp4); - - group->process(); - group->sync(); - - EXPECT_EQ(4, listener.fracCommands); - EXPECT_EQ(4, listener.fracEvents); - - releaseFramework(); - - disp2->release(); - disp4->release(); - taskman->release(); -} - -TEST_F(TkTestAllowWarnings, GroupNoWorkers) -{ - // tests that group still works without a taskmanager - // a warnings is expected - // mainly relies on internal asserts - - class EventCounter : public TkEventListener - { - public: - EventCounter() :fracCommands(0), fracEvents(0) {} - - void receive(const TkEvent* events, uint32_t eventCount) - { - for (uint32_t i = 0; i < eventCount; i++) - { - const TkEvent& event = events[i]; - switch (event.type) - { - case TkFractureCommands::EVENT_TYPE: - fracCommands++; - break; - case TkFractureEvents::EVENT_TYPE: - fracEvents++; - break; - default: - FAIL(); - // no split due to single chunk - // no joints - } - } - } - - uint32_t fracCommands, fracEvents; - } listener; - - createFramework(); - TkFramework* fwk = NvBlastTkFrameworkGet(); - NvBlastChunkDesc chunkDescs[] = { - { { 0,0,0 }, 2, UINT32_MAX, NvBlastChunkDesc::SupportFlag, 'root' } - }; - - TkAssetDesc assetDesc; - assetDesc.chunkCount = sizeof(chunkDescs) / sizeof(NvBlastChunkDesc); - assetDesc.chunkDescs = chunkDescs; - assetDesc.bondCount = 0; - assetDesc.bondDescs = nullptr; - assetDesc.bondFlags = nullptr; - const TkAsset* asset = fwk->createAsset(assetDesc); - - TkActorDesc actorDesc; - actorDesc.asset = asset; - TkActor* actor1 = fwk->createActor(actorDesc); - TkActor* actor2 = fwk->createActor(actorDesc); - TkActor* actor3 = fwk->createActor(actorDesc); - TkActor* actor4 = fwk->createActor(actorDesc); - - actor1->getFamily().addListener(listener); - actor2->getFamily().addListener(listener); - actor3->getFamily().addListener(listener); - actor4->getFamily().addListener(listener); - - TkGroupDesc groupDesc = { nullptr }; - TkGroup* group = fwk->createGroup(groupDesc); - - group->addActor(*actor1); - group->addActor(*actor2); - group->addActor(*actor3); - group->addActor(*actor4); - - NvBlastExtRadialDamageDesc radialDamage = getRadialDamageDesc(0, 0, 0); - actor1->damage(getFalloffProgram(), &radialDamage, sizeof(NvBlastExtRadialDamageDesc), getDefaultMaterial()); - actor2->damage(getFalloffProgram(), &radialDamage, sizeof(NvBlastExtRadialDamageDesc), getDefaultMaterial()); - actor3->damage(getFalloffProgram(), &radialDamage, sizeof(NvBlastExtRadialDamageDesc), getDefaultMaterial()); - actor4->damage(getFalloffProgram(), &radialDamage, sizeof(NvBlastExtRadialDamageDesc), getDefaultMaterial()); - - group->process(); - group->sync(); - - EXPECT_EQ(4, listener.fracCommands); - EXPECT_EQ(4, listener.fracEvents); - - releaseFramework(); -} - diff --git a/NvBlast/test/src/utils/TaskDispatcher.h b/NvBlast/test/src/utils/TaskDispatcher.h deleted file mode 100644 index bd8bfc8..0000000 --- a/NvBlast/test/src/utils/TaskDispatcher.h +++ /dev/null @@ -1,191 +0,0 @@ -#pragma once - -#include <thread> -#include <mutex> -#include <queue> -#include <list> -#include <future> -#include <condition_variable> -#include <memory> -#include <atomic> - -class TaskDispatcher -{ -public: - class Task - { - public: - virtual void process() = 0; - virtual ~Task() {}; - }; - - typedef std::function<void(TaskDispatcher& dispatcher, std::unique_ptr<Task>)> OnTaskFinishedFunction; - - TaskDispatcher(uint32_t threadCount, OnTaskFinishedFunction onTaskFinished) : - m_workingThreadsCount(0), m_onTaskFinished(onTaskFinished) - { - m_threads.resize(threadCount); - for (uint32_t i = 0; i < threadCount; i++) - { - m_threads[i] = std::unique_ptr<Thread>(new Thread(i, m_completionSemaphore)); - m_threads[i]->start(); - m_freeThreads.push(m_threads[i].get()); - } - } - - void addTask(std::unique_ptr<Task> task) - { - m_tasks.push(std::move(task)); - } - - void process() - { - // main loop - while (m_tasks.size() > 0 || m_workingThreadsCount > 0) - { - // assign tasks - while (!(m_tasks.empty() || m_freeThreads.empty())) - { - auto task = std::move(m_tasks.front()); - m_tasks.pop(); - - Thread* freeThread = m_freeThreads.front(); - m_freeThreads.pop(); - - freeThread->processTask(std::move(task)); - m_workingThreadsCount++; - } - - m_completionSemaphore.wait(); - - // check for completion - for (std::unique_ptr<Thread>& thread : m_threads) - { - if (thread->isTaskFinished()) - { - std::unique_ptr<Task> task; - thread->collectTask(task); - m_onTaskFinished(*this, std::move(task)); - - m_freeThreads.push(thread.get()); - m_workingThreadsCount--; - break; - } - } - } - } - -private: - class Semaphore - { - public: - Semaphore(int count_ = 0) - : m_count(count_) {} - - inline void notify() - { - std::unique_lock<std::mutex> lock(m_mutex); - m_count++; - m_cv.notify_one(); - } - - inline void wait() - { - std::unique_lock<std::mutex> lock(m_mutex); - - while (m_count == 0){ - m_cv.wait(lock); - } - m_count--; - } - - - private: - std::mutex m_mutex; - std::condition_variable m_cv; - int m_count; - }; - - class Thread - { - public: - Thread(uint32_t id_, Semaphore& completionSemaphore) : m_id(id_), m_completionSemaphore(completionSemaphore), m_running(false), m_taskFinished(false) {} - virtual ~Thread() { stop(); } - - void start() - { - if (!m_running) - { - m_running = true; - m_thread = std::thread(&Thread::body, this); - } - } - - void stop() - { - if (m_running) - { - m_running = false; - m_newTaskSemaphore.notify(); - m_thread.join(); - } - } - - void processTask(std::unique_ptr<Task> task) - { - m_task = std::move(task); - m_taskFinished = false; - m_newTaskSemaphore.notify(); - } - - void collectTask(std::unique_ptr<Task>& task) - { - task = std::move(m_task); - m_task = nullptr; - m_taskFinished = false; - } - - bool hasTask() const { return m_task != nullptr; } - - bool isTaskFinished() const { return m_taskFinished; } - - private: - void body() - { - while (1) - { - m_newTaskSemaphore.wait(); - - if (!m_running) - return; - - m_task->process(); - m_taskFinished = true; - - m_completionSemaphore.notify(); - } - } - - uint32_t m_id; - Semaphore& m_completionSemaphore; - std::thread m_thread; - bool m_running; - - std::unique_ptr<Task> m_task; - std::atomic<bool> m_taskFinished; - - Semaphore m_newTaskSemaphore; - }; - -private: - uint32_t m_workingThreadsCount; - - std::queue<std::unique_ptr<Task>> m_tasks; - OnTaskFinishedFunction m_onTaskFinished; - - std::vector<std::unique_ptr<Thread>> m_threads; - std::queue<Thread*> m_freeThreads; - - Semaphore m_completionSemaphore; -}; - diff --git a/NvBlast/test/src/utils/TestAssets.cpp b/NvBlast/test/src/utils/TestAssets.cpp deleted file mode 100644 index f2a1396..0000000 --- a/NvBlast/test/src/utils/TestAssets.cpp +++ /dev/null @@ -1,288 +0,0 @@ -#include "TestAssets.h" -#include "AssetGenerator.h" - -const NvBlastChunkDesc g_cube1ChunkDescs[9] = -{ -// centroid volume parent idx flags ID - { { 0.0f, 0.0f, 0.0f }, 8.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 0 }, - { {-0.5f,-0.5f,-0.5f }, 1.0f, 0, NvBlastChunkDesc::SupportFlag, 1 }, - { { 0.5f,-0.5f,-0.5f }, 1.0f, 0, NvBlastChunkDesc::SupportFlag, 2 }, - { {-0.5f, 0.5f,-0.5f }, 1.0f, 0, NvBlastChunkDesc::SupportFlag, 3 }, - { { 0.5f, 0.5f,-0.5f }, 1.0f, 0, NvBlastChunkDesc::SupportFlag, 4 }, - { {-0.5f,-0.5f, 0.5f }, 1.0f, 0, NvBlastChunkDesc::SupportFlag, 5 }, - { { 0.5f,-0.5f, 0.5f }, 1.0f, 0, NvBlastChunkDesc::SupportFlag, 6 }, - { {-0.5f, 0.5f, 0.5f }, 1.0f, 0, NvBlastChunkDesc::SupportFlag, 7 }, - { { 0.5f, 0.5f, 0.5f }, 1.0f, 0, NvBlastChunkDesc::SupportFlag, 8 }, -}; - -const NvBlastBondDesc g_cube1BondDescs[12] = -{ -// chunks normal area centroid userData - { { 1, 2 }, { { 1.0f, 0.0f, 0.0f }, 1.0f, { 0.0f,-0.5f,-0.5f }, 0 } }, - { { 3, 4 }, { { 1.0f, 0.0f, 0.0f }, 1.0f, { 0.0f, 0.5f,-0.5f }, 0 } }, - { { 5, 6 }, { { 1.0f, 0.0f, 0.0f }, 1.0f, { 0.0f,-0.5f, 0.5f }, 0 } }, - { { 7, 8 }, { { 1.0f, 0.0f, 0.0f }, 1.0f, { 0.0f, 0.5f, 0.5f }, 0 } }, - - { { 1, 3 }, { { 0.0f, 1.0f, 0.0f }, 1.0f, {-0.5f, 0.0f,-0.5f }, 0 } }, - { { 2, 4 }, { { 0.0f, 1.0f, 0.0f }, 1.0f, { 0.5f, 0.0f,-0.5f }, 0 } }, - { { 5, 7 }, { { 0.0f, 1.0f, 0.0f }, 1.0f, {-0.5f, 0.0f, 0.5f }, 0 } }, - { { 6, 8 }, { { 0.0f, 1.0f, 0.0f }, 1.0f, { 0.5f, 0.0f, 0.5f }, 0 } }, - - { { 1, 5 }, { { 0.0f, 0.0f, 1.0f }, 1.0f, {-0.5f,-0.5f, 0.0f }, 0 } }, - { { 2, 6 }, { { 0.0f, 0.0f, 1.0f }, 1.0f, { 0.5f,-0.5f, 0.0f }, 0 } }, - { { 3, 7 }, { { 0.0f, 0.0f, 1.0f }, 1.0f, {-0.5f, 0.5f, 0.0f }, 0 } }, - { { 4, 8 }, { { 0.0f, 0.0f, 1.0f }, 1.0f, { 0.5f, 0.5f, 0.0f }, 0 } }, -}; - -const NvBlastChunkDesc g_cube2ChunkDescs[73] = -{ -// centroid volume parent idx flags ID - { { 0.0f, 0.0f, 0.0f }, 8.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 0 }, - { {-0.5f, -0.5f, -0.5f }, 1.0f, 0, NvBlastChunkDesc::SupportFlag, 1 }, - { { 0.5f, -0.5f, -0.5f }, 1.0f, 0, NvBlastChunkDesc::SupportFlag, 2 }, - { {-0.5f, 0.5f, -0.5f }, 1.0f, 0, NvBlastChunkDesc::SupportFlag, 3 }, - { { 0.5f, 0.5f, -0.5f }, 1.0f, 0, NvBlastChunkDesc::SupportFlag, 4 }, - { {-0.5f, -0.5f, 0.5f }, 1.0f, 0, NvBlastChunkDesc::SupportFlag, 5 }, - { { 0.5f, -0.5f, 0.5f }, 1.0f, 0, NvBlastChunkDesc::SupportFlag, 6 }, - { {-0.5f, 0.5f, 0.5f }, 1.0f, 0, NvBlastChunkDesc::SupportFlag, 7 }, - { { 0.5f, 0.5f, 0.5f }, 1.0f, 0, NvBlastChunkDesc::SupportFlag, 8 }, - { {-0.25f-0.5f,-0.25f-0.5f,-0.25f-0.5f }, 0.125f, 1, NvBlastChunkDesc::NoFlags, 9 }, - { { 0.25f-0.5f,-0.25f-0.5f,-0.25f-0.5f }, 0.125f, 1, NvBlastChunkDesc::NoFlags, 10 }, - { {-0.25f-0.5f, 0.25f-0.5f,-0.25f-0.5f }, 0.125f, 1, NvBlastChunkDesc::NoFlags, 11 }, - { { 0.25f-0.5f, 0.25f-0.5f,-0.25f-0.5f }, 0.125f, 1, NvBlastChunkDesc::NoFlags, 12 }, - { {-0.25f-0.5f,-0.25f-0.5f, 0.25f-0.5f }, 0.125f, 1, NvBlastChunkDesc::NoFlags, 13 }, - { { 0.25f-0.5f,-0.25f-0.5f, 0.25f-0.5f }, 0.125f, 1, NvBlastChunkDesc::NoFlags, 14 }, - { {-0.25f-0.5f, 0.25f-0.5f, 0.25f-0.5f }, 0.125f, 1, NvBlastChunkDesc::NoFlags, 15 }, - { { 0.25f-0.5f, 0.25f-0.5f, 0.25f-0.5f }, 0.125f, 1, NvBlastChunkDesc::NoFlags, 16 }, - { {-0.25f+0.5f,-0.25f-0.5f,-0.25f-0.5f }, 0.125f, 2, NvBlastChunkDesc::NoFlags, 17 }, - { { 0.25f+0.5f,-0.25f-0.5f,-0.25f-0.5f }, 0.125f, 2, NvBlastChunkDesc::NoFlags, 18 }, - { {-0.25f+0.5f, 0.25f-0.5f,-0.25f-0.5f }, 0.125f, 2, NvBlastChunkDesc::NoFlags, 19 }, - { { 0.25f+0.5f, 0.25f-0.5f,-0.25f-0.5f }, 0.125f, 2, NvBlastChunkDesc::NoFlags, 20 }, - { {-0.25f+0.5f,-0.25f-0.5f, 0.25f-0.5f }, 0.125f, 2, NvBlastChunkDesc::NoFlags, 21 }, - { { 0.25f+0.5f,-0.25f-0.5f, 0.25f-0.5f }, 0.125f, 2, NvBlastChunkDesc::NoFlags, 22 }, - { {-0.25f+0.5f, 0.25f-0.5f, 0.25f-0.5f }, 0.125f, 2, NvBlastChunkDesc::NoFlags, 23 }, - { { 0.25f+0.5f, 0.25f-0.5f, 0.25f-0.5f }, 0.125f, 2, NvBlastChunkDesc::NoFlags, 24 }, - { {-0.25f-0.5f,-0.25f+0.5f,-0.25f-0.5f }, 0.125f, 3, NvBlastChunkDesc::NoFlags, 25 }, - { { 0.25f-0.5f,-0.25f+0.5f,-0.25f-0.5f }, 0.125f, 3, NvBlastChunkDesc::NoFlags, 26 }, - { {-0.25f-0.5f, 0.25f+0.5f,-0.25f-0.5f }, 0.125f, 3, NvBlastChunkDesc::NoFlags, 27 }, - { { 0.25f-0.5f, 0.25f+0.5f,-0.25f-0.5f }, 0.125f, 3, NvBlastChunkDesc::NoFlags, 28 }, - { {-0.25f-0.5f,-0.25f+0.5f, 0.25f-0.5f }, 0.125f, 3, NvBlastChunkDesc::NoFlags, 29 }, - { { 0.25f-0.5f,-0.25f+0.5f, 0.25f-0.5f }, 0.125f, 3, NvBlastChunkDesc::NoFlags, 30 }, - { {-0.25f-0.5f, 0.25f+0.5f, 0.25f-0.5f }, 0.125f, 3, NvBlastChunkDesc::NoFlags, 31 }, - { { 0.25f-0.5f, 0.25f+0.5f, 0.25f-0.5f }, 0.125f, 3, NvBlastChunkDesc::NoFlags, 32 }, - { {-0.25f+0.5f,-0.25f+0.5f,-0.25f-0.5f }, 0.125f, 4, NvBlastChunkDesc::NoFlags, 33 }, - { { 0.25f+0.5f,-0.25f+0.5f,-0.25f-0.5f }, 0.125f, 4, NvBlastChunkDesc::NoFlags, 34 }, - { {-0.25f+0.5f, 0.25f+0.5f,-0.25f-0.5f }, 0.125f, 4, NvBlastChunkDesc::NoFlags, 35 }, - { { 0.25f+0.5f, 0.25f+0.5f,-0.25f-0.5f }, 0.125f, 4, NvBlastChunkDesc::NoFlags, 36 }, - { {-0.25f+0.5f,-0.25f+0.5f, 0.25f-0.5f }, 0.125f, 4, NvBlastChunkDesc::NoFlags, 37 }, - { { 0.25f+0.5f,-0.25f+0.5f, 0.25f-0.5f }, 0.125f, 4, NvBlastChunkDesc::NoFlags, 38 }, - { {-0.25f+0.5f, 0.25f+0.5f, 0.25f-0.5f }, 0.125f, 4, NvBlastChunkDesc::NoFlags, 39 }, - { { 0.25f+0.5f, 0.25f+0.5f, 0.25f-0.5f }, 0.125f, 4, NvBlastChunkDesc::NoFlags, 40 }, - { {-0.25f-0.5f,-0.25f-0.5f,-0.25f+0.5f }, 0.125f, 5, NvBlastChunkDesc::NoFlags, 41 }, - { { 0.25f-0.5f,-0.25f-0.5f,-0.25f+0.5f }, 0.125f, 5, NvBlastChunkDesc::NoFlags, 42 }, - { {-0.25f-0.5f, 0.25f-0.5f,-0.25f+0.5f }, 0.125f, 5, NvBlastChunkDesc::NoFlags, 43 }, - { { 0.25f-0.5f, 0.25f-0.5f,-0.25f+0.5f }, 0.125f, 5, NvBlastChunkDesc::NoFlags, 44 }, - { {-0.25f-0.5f,-0.25f-0.5f, 0.25f+0.5f }, 0.125f, 5, NvBlastChunkDesc::NoFlags, 45 }, - { { 0.25f-0.5f,-0.25f-0.5f, 0.25f+0.5f }, 0.125f, 5, NvBlastChunkDesc::NoFlags, 46 }, - { {-0.25f-0.5f, 0.25f-0.5f, 0.25f+0.5f }, 0.125f, 5, NvBlastChunkDesc::NoFlags, 47 }, - { { 0.25f-0.5f, 0.25f-0.5f, 0.25f+0.5f }, 0.125f, 5, NvBlastChunkDesc::NoFlags, 48 }, - { {-0.25f+0.5f,-0.25f-0.5f,-0.25f+0.5f }, 0.125f, 6, NvBlastChunkDesc::NoFlags, 49 }, - { { 0.25f+0.5f,-0.25f-0.5f,-0.25f+0.5f }, 0.125f, 6, NvBlastChunkDesc::NoFlags, 50 }, - { {-0.25f+0.5f, 0.25f-0.5f,-0.25f+0.5f }, 0.125f, 6, NvBlastChunkDesc::NoFlags, 51 }, - { { 0.25f+0.5f, 0.25f-0.5f,-0.25f+0.5f }, 0.125f, 6, NvBlastChunkDesc::NoFlags, 52 }, - { {-0.25f+0.5f,-0.25f-0.5f, 0.25f+0.5f }, 0.125f, 6, NvBlastChunkDesc::NoFlags, 53 }, - { { 0.25f+0.5f,-0.25f-0.5f, 0.25f+0.5f }, 0.125f, 6, NvBlastChunkDesc::NoFlags, 54 }, - { {-0.25f+0.5f, 0.25f-0.5f, 0.25f+0.5f }, 0.125f, 6, NvBlastChunkDesc::NoFlags, 55 }, - { { 0.25f+0.5f, 0.25f-0.5f, 0.25f+0.5f }, 0.125f, 6, NvBlastChunkDesc::NoFlags, 56 }, - { {-0.25f-0.5f,-0.25f+0.5f,-0.25f+0.5f }, 0.125f, 7, NvBlastChunkDesc::NoFlags, 57 }, - { { 0.25f-0.5f,-0.25f+0.5f,-0.25f+0.5f }, 0.125f, 7, NvBlastChunkDesc::NoFlags, 58 }, - { {-0.25f-0.5f, 0.25f+0.5f,-0.25f+0.5f }, 0.125f, 7, NvBlastChunkDesc::NoFlags, 59 }, - { { 0.25f-0.5f, 0.25f+0.5f,-0.25f+0.5f }, 0.125f, 7, NvBlastChunkDesc::NoFlags, 60 }, - { {-0.25f-0.5f,-0.25f+0.5f, 0.25f+0.5f }, 0.125f, 7, NvBlastChunkDesc::NoFlags, 61 }, - { { 0.25f-0.5f,-0.25f+0.5f, 0.25f+0.5f }, 0.125f, 7, NvBlastChunkDesc::NoFlags, 62 }, - { {-0.25f-0.5f, 0.25f+0.5f, 0.25f+0.5f }, 0.125f, 7, NvBlastChunkDesc::NoFlags, 63 }, - { { 0.25f-0.5f, 0.25f+0.5f, 0.25f+0.5f }, 0.125f, 7, NvBlastChunkDesc::NoFlags, 64 }, - { {-0.25f+0.5f,-0.25f+0.5f,-0.25f+0.5f }, 0.125f, 8, NvBlastChunkDesc::NoFlags, 65 }, - { { 0.25f+0.5f,-0.25f+0.5f,-0.25f+0.5f }, 0.125f, 8, NvBlastChunkDesc::NoFlags, 66 }, - { {-0.25f+0.5f, 0.25f+0.5f,-0.25f+0.5f }, 0.125f, 8, NvBlastChunkDesc::NoFlags, 67 }, - { { 0.25f+0.5f, 0.25f+0.5f,-0.25f+0.5f }, 0.125f, 8, NvBlastChunkDesc::NoFlags, 68 }, - { {-0.25f+0.5f,-0.25f+0.5f, 0.25f+0.5f }, 0.125f, 8, NvBlastChunkDesc::NoFlags, 69 }, - { { 0.25f+0.5f,-0.25f+0.5f, 0.25f+0.5f }, 0.125f, 8, NvBlastChunkDesc::NoFlags, 70 }, - { {-0.25f+0.5f, 0.25f+0.5f, 0.25f+0.5f }, 0.125f, 8, NvBlastChunkDesc::NoFlags, 71 }, - { { 0.25f+0.5f, 0.25f+0.5f, 0.25f+0.5f }, 0.125f, 8, NvBlastChunkDesc::NoFlags, 72 }, -}; - -const NvBlastChunkDesc g_cube3ChunkDescs[11] = -{ -// centroid volume parent idx flags ID - { { 0.0f, 0.0f, 0.0f }, 4.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 0 }, - { { 0.0f, 0.0f, 0.0f }, 3.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 1 }, - { { 0.0f, 0.0f, 0.0f }, 1.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 2 }, - { {-0.5f,-0.5f,-0.5f }, 1.0f, 0, NvBlastChunkDesc::SupportFlag, 3 }, - { { 0.5f,-0.5f,-0.5f }, 1.0f, 0, NvBlastChunkDesc::SupportFlag, 4 }, - { {-0.5f, 0.5f,-0.5f }, 1.0f, 0, NvBlastChunkDesc::SupportFlag, 5 }, - { { 0.5f, 0.5f,-0.5f }, 1.0f, 1, NvBlastChunkDesc::SupportFlag, 6 }, - { {-0.5f,-0.5f, 0.5f }, 1.0f, 1, NvBlastChunkDesc::SupportFlag, 7 }, - { { 0.5f,-0.5f, 0.5f }, 1.0f, 1, NvBlastChunkDesc::SupportFlag, 8 }, - { {-0.5f, 0.5f, 0.5f }, 1.0f, 2, NvBlastChunkDesc::SupportFlag, 9 }, - { { 0.5f, 0.5f, 0.5f }, 1.0f, 2, NvBlastChunkDesc::SupportFlag, 10 }, -}; - -const NvBlastBondDesc g_cube3BondDescs[12] = -{ - // chunks normal area centroid userData - { { 3, 4 },{ { 1.0f, 0.0f, 0.0f }, 1.0f,{ 0.0f,-0.5f,-0.5f }, 0 } }, - { { 5, 6 },{ { 1.0f, 0.0f, 0.0f }, 1.0f,{ 0.0f, 0.5f,-0.5f }, 0 } }, - { { 7, 8 },{ { 1.0f, 0.0f, 0.0f }, 1.0f,{ 0.0f,-0.5f, 0.5f }, 0 } }, - { { 9, 10},{ { 1.0f, 0.0f, 0.0f }, 1.0f,{ 0.0f, 0.5f, 0.5f }, 0 } }, - - { { 3, 5 },{ { 0.0f, 1.0f, 0.0f }, 1.0f,{-0.5f, 0.0f,-0.5f }, 0 } }, - { { 4, 6 },{ { 0.0f, 1.0f, 0.0f }, 1.0f,{ 0.5f, 0.0f,-0.5f }, 0 } }, - { { 7, 9 },{ { 0.0f, 1.0f, 0.0f }, 1.0f,{-0.5f, 0.0f, 0.5f }, 0 } }, - { { 8, 10},{ { 0.0f, 1.0f, 0.0f }, 1.0f,{ 0.5f, 0.0f, 0.5f }, 0 } }, - - { { 3, 7 },{ { 0.0f, 0.0f, 1.0f }, 1.0f,{-0.5f,-0.5f, 0.0f }, 0 } }, - { { 4, 8 },{ { 0.0f, 0.0f, 1.0f }, 1.0f,{ 0.5f,-0.5f, 0.0f }, 0 } }, - { { 5, 9 },{ { 0.0f, 0.0f, 1.0f }, 1.0f,{-0.5f, 0.5f, 0.0f }, 0 } }, - { { 6, 10},{ { 0.0f, 0.0f, 1.0f }, 1.0f,{ 0.5f, 0.5f, 0.0f }, 0 } }, -}; - -const NvBlastAssetDesc g_assetDescs[3] = -{ - // 2x2x2 axis-aligned cube centered at the origin, split into 8 depth-1 1x1x1 child chunks - { sizeof(g_cube1ChunkDescs) / sizeof(g_cube1ChunkDescs[0]), g_cube1ChunkDescs, sizeof(g_cube1BondDescs) / sizeof(g_cube1BondDescs[0]), g_cube1BondDescs }, - - // 2x2x2 axis-aligned cube centered at the origin, split into 8 depth-1 1x1x1 child chunks which are then split into 8 depth-2 (1/2)x(1/2)x(1/2) child chunks each - // Support is at depth-1, so the g_cube1BondDescs are used - { sizeof(g_cube2ChunkDescs) / sizeof(g_cube2ChunkDescs[0]), g_cube2ChunkDescs, sizeof(g_cube1BondDescs) / sizeof(g_cube1BondDescs[0]), g_cube1BondDescs }, - - // 2x2x2 axis-aligned cube centered at the origin, split into 8 depth-1 1x1x1 child chunks with multiple roots - { sizeof(g_cube3ChunkDescs) / sizeof(g_cube3ChunkDescs[0]), g_cube3ChunkDescs, sizeof(g_cube3BondDescs) / sizeof(g_cube3BondDescs[0]), g_cube3BondDescs }, -}; - - - -struct ExpectedValues -{ - uint32_t totalChunkCount; - uint32_t graphNodeCount; - uint32_t leafChunkCount; - uint32_t bondCount; - uint32_t subsupportChunkCount; -}; - -const ExpectedAssetValues g_assetExpectedValues[3] = -{ -// total graph leaves bonds sub - { 9, 8, 8, 12, 0 }, - { 73, 8, 64, 12, 64 }, - { 11, 8, 8, 12, 0 } -}; - - -///////////// Badly-formed asset descs below ////////////// - -const NvBlastChunkDesc g_cube1ChunkDescsMissingCoverage[9] = -{ -// centroid volume parent idx flags ID - { { 0.0f, 0.0f, 0.0f }, 8.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 0 }, - { {-0.5f,-0.5f,-0.5f }, 1.0f, 0, NvBlastChunkDesc::SupportFlag, 1 }, - { { 0.5f,-0.5f,-0.5f }, 1.0f, 0, NvBlastChunkDesc::SupportFlag, 2 }, - { {-0.5f, 0.5f,-0.5f }, 1.0f, 0, NvBlastChunkDesc::SupportFlag, 3 }, - { { 0.5f, 0.5f,-0.5f }, 1.0f, 0, NvBlastChunkDesc::SupportFlag, 4 }, - { {-0.5f,-0.5f, 0.5f }, 1.0f, 0, NvBlastChunkDesc::SupportFlag, 5 }, - { { 0.5f,-0.5f, 0.5f }, 1.0f, 0, NvBlastChunkDesc::SupportFlag, 6 }, - { {-0.5f, 0.5f, 0.5f }, 1.0f, 0, NvBlastChunkDesc::SupportFlag, 7 }, - { { 0.5f, 0.5f, 0.5f }, 1.0f, 0, NvBlastChunkDesc::NoFlags, 8 }, -}; - - -const NvBlastChunkDesc g_cube2ChunkDescsMissingCoverage1[17] = -{ -// centroid volume parent idx flags ID - { { 0.0f, 0.0f, 0.0f }, 8.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 0 }, - { {-0.5f,-0.5f,-0.5f }, 1.0f, 0, NvBlastChunkDesc::NoFlags, 1 }, - { { 0.5f,-0.5f,-0.5f }, 1.0f, 0, NvBlastChunkDesc::SupportFlag, 2 }, - { {-0.5f, 0.5f,-0.5f }, 1.0f, 0, NvBlastChunkDesc::SupportFlag, 3 }, - { { 0.5f, 0.5f,-0.5f }, 1.0f, 0, NvBlastChunkDesc::SupportFlag, 4 }, - { {-0.5f,-0.5f, 0.5f }, 1.0f, 0, NvBlastChunkDesc::SupportFlag, 5 }, - { { 0.5f,-0.5f, 0.5f }, 1.0f, 0, NvBlastChunkDesc::SupportFlag, 6 }, - { {-0.5f, 0.5f, 0.5f }, 1.0f, 0, NvBlastChunkDesc::SupportFlag, 7 }, - { { 0.5f, 0.5f, 0.5f }, 1.0f, 0, NvBlastChunkDesc::NoFlags, 8 }, - { {-0.25f-0.5f,-0.25f-0.5f,-0.25f-0.5f }, 0.125f, 1, NvBlastChunkDesc::NoFlags, 9 }, - { { 0.25f-0.5f,-0.25f-0.5f,-0.25f-0.5f }, 0.125f, 1, NvBlastChunkDesc::NoFlags, 10 }, - { {-0.25f-0.5f, 0.25f-0.5f,-0.25f-0.5f }, 0.125f, 1, NvBlastChunkDesc::NoFlags, 11 }, - { { 0.25f-0.5f, 0.25f-0.5f,-0.25f-0.5f }, 0.125f, 1, NvBlastChunkDesc::NoFlags, 12 }, - { {-0.25f-0.5f,-0.25f-0.5f, 0.25f-0.5f }, 0.125f, 1, NvBlastChunkDesc::NoFlags, 13 }, - { { 0.25f-0.5f,-0.25f-0.5f, 0.25f-0.5f }, 0.125f, 1, NvBlastChunkDesc::NoFlags, 14 }, - { {-0.25f-0.5f, 0.25f-0.5f, 0.25f-0.5f }, 0.125f, 1, NvBlastChunkDesc::NoFlags, 15 }, - { { 0.25f-0.5f, 0.25f-0.5f, 0.25f-0.5f }, 0.125f, 1, NvBlastChunkDesc::NoFlags, 16 }, -}; - - -const NvBlastChunkDesc g_cube2ChunkDescsMissingCoverage2[17] = -{ -// centroid volume parent idx flags ID - { { 0.0f, 0.0f, 0.0f }, 8.0f, UINT32_MAX, NvBlastChunkDesc::NoFlags, 0 }, - { {-0.5f,-0.5f,-0.5f }, 1.0f, 0, NvBlastChunkDesc::NoFlags, 1 }, - { { 0.5f,-0.5f,-0.5f }, 1.0f, 0, NvBlastChunkDesc::SupportFlag, 2 }, - { {-0.5f, 0.5f,-0.5f }, 1.0f, 0, NvBlastChunkDesc::SupportFlag, 3 }, - { { 0.5f, 0.5f,-0.5f }, 1.0f, 0, NvBlastChunkDesc::SupportFlag, 4 }, - { {-0.5f,-0.5f, 0.5f }, 1.0f, 0, NvBlastChunkDesc::SupportFlag, 5 }, - { { 0.5f,-0.5f, 0.5f }, 1.0f, 0, NvBlastChunkDesc::SupportFlag, 6 }, - { {-0.5f, 0.5f, 0.5f }, 1.0f, 0, NvBlastChunkDesc::SupportFlag, 7 }, - { { 0.5f, 0.5f, 0.5f }, 1.0f, 0, NvBlastChunkDesc::NoFlags, 8 }, - { {-0.25f-0.5f,-0.25f-0.5f,-0.25f-0.5f }, 0.125f, 1, NvBlastChunkDesc::NoFlags, 9 }, - { { 0.25f-0.5f,-0.25f-0.5f,-0.25f-0.5f }, 0.125f, 1, NvBlastChunkDesc::NoFlags, 10 }, - { {-0.25f-0.5f, 0.25f-0.5f,-0.25f-0.5f }, 0.125f, 1, NvBlastChunkDesc::NoFlags, 11 }, - { { 0.25f-0.5f, 0.25f-0.5f,-0.25f-0.5f }, 0.125f, 1, NvBlastChunkDesc::NoFlags, 12 }, - { {-0.25f-0.5f,-0.25f-0.5f, 0.25f-0.5f }, 0.125f, 1, NvBlastChunkDesc::NoFlags, 13 }, - { { 0.25f-0.5f,-0.25f-0.5f, 0.25f-0.5f }, 0.125f, 1, NvBlastChunkDesc::NoFlags, 14 }, - { {-0.25f-0.5f, 0.25f-0.5f, 0.25f-0.5f }, 0.125f, 1, NvBlastChunkDesc::NoFlags, 15 }, - { { 0.25f-0.5f, 0.25f-0.5f, 0.25f-0.5f }, 0.125f, 1, NvBlastChunkDesc::SupportFlag, 16 }, -}; - - -const NvBlastAssetDesc g_assetDescsMissingCoverage[3] = -{ - { sizeof(g_cube1ChunkDescsMissingCoverage) / sizeof(g_cube1ChunkDescsMissingCoverage[0]), g_cube1ChunkDescsMissingCoverage, sizeof(g_cube1BondDescs) / sizeof(g_cube1BondDescs[0]), g_cube1BondDescs }, - { sizeof(g_cube2ChunkDescsMissingCoverage1) / sizeof(g_cube2ChunkDescsMissingCoverage1[0]), g_cube2ChunkDescsMissingCoverage1, sizeof(g_cube1BondDescs) / sizeof(g_cube1BondDescs[0]), g_cube1BondDescs }, - { sizeof(g_cube2ChunkDescsMissingCoverage2) / sizeof(g_cube2ChunkDescsMissingCoverage2[0]), g_cube2ChunkDescsMissingCoverage2, sizeof(g_cube1BondDescs) / sizeof(g_cube1BondDescs[0]), g_cube1BondDescs }, -}; - -extern const ExpectedAssetValues g_assetsFromMissingCoverageExpectedValues[3] = -{ -// total graph leaves bonds sub - { 9, 8, 8, 12, 0 }, - { 17, 8, 15, 12, 8 }, - { 17, 15, 15, 9, 0 }, -}; - - -void generateCube(GeneratorAsset& cubeAsset, size_t maxDepth, size_t width, int32_t supportDepth) -{ - CubeAssetGenerator::Settings settings; - settings.extents = GeneratorAsset::Vec3(1, 1, 1); - CubeAssetGenerator::DepthInfo depthInfo; - depthInfo.slicesPerAxis = GeneratorAsset::Vec3(1, 1, 1); - depthInfo.flag = NvBlastChunkDesc::Flags::NoFlags; - settings.depths.push_back(depthInfo); - - for (uint32_t depth = 1; depth < maxDepth; ++depth) - { - depthInfo.slicesPerAxis = GeneratorAsset::Vec3((float)width, (float)width, (float)width); - settings.depths.push_back(depthInfo); - } - settings.depths[(supportDepth > 0 ? supportDepth : maxDepth) - 1].flag = NvBlastChunkDesc::SupportFlag; // Leaves are support - - CubeAssetGenerator::generate(cubeAsset, settings); -} - -void generateCube(GeneratorAsset& cubeAsset, NvBlastAssetDesc& assetDesc, size_t maxDepth, size_t width, int32_t supportDepth) -{ - generateCube(cubeAsset, maxDepth, width, supportDepth); - assetDesc.bondCount = (uint32_t)cubeAsset.solverBonds.size(); - assetDesc.bondDescs = cubeAsset.solverBonds.data(); - assetDesc.chunkCount = (uint32_t)cubeAsset.chunks.size(); - assetDesc.chunkDescs = cubeAsset.solverChunks.data(); -}
\ No newline at end of file diff --git a/NvBlast/test/src/utils/TestAssets.h b/NvBlast/test/src/utils/TestAssets.h deleted file mode 100644 index e4a9c77..0000000 --- a/NvBlast/test/src/utils/TestAssets.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef TESTASSETS_H -#define TESTASSETS_H - -#include "NvBlast.h" -#include "AssetGenerator.h" - -struct ExpectedAssetValues -{ - uint32_t totalChunkCount; - uint32_t graphNodeCount; - uint32_t leafChunkCount; - uint32_t bondCount; - uint32_t subsupportChunkCount; -}; - - -// Indexable asset descriptors and expected values -extern const NvBlastAssetDesc g_assetDescs[3]; -extern const ExpectedAssetValues g_assetExpectedValues[3]; - -// Indexable asset descriptors for assets missing coverage and expected values -extern const NvBlastAssetDesc g_assetDescsMissingCoverage[3]; -extern const ExpectedAssetValues g_assetsFromMissingCoverageExpectedValues[3]; - - -inline uint32_t getAssetDescCount() -{ - return sizeof(g_assetDescs) / sizeof(g_assetDescs[0]); -} - -inline uint32_t getAssetDescMissingCoverageCount() -{ - return sizeof(g_assetDescsMissingCoverage) / sizeof(g_assetDescsMissingCoverage[0]); -} - - -void generateCube(GeneratorAsset& cubeAsset, size_t maxDepth, size_t width, int32_t supportDepth = -1); -void generateCube(GeneratorAsset& cubeAsset, NvBlastAssetDesc& assetDesc, size_t maxDepth, size_t width, int32_t supportDepth = -1); - -#endif // #ifdef TESTASSETS_H diff --git a/NvBlast/test/src/utils/TestProfiler.h b/NvBlast/test/src/utils/TestProfiler.h deleted file mode 100644 index 318e6e6..0000000 --- a/NvBlast/test/src/utils/TestProfiler.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef TESTPROFILER_H -#define TESTPROFILER_H - -#include "NvBlastPreprocessor.h" - -#if NV_NVTX -#include "nvToolsExt.h" -NV_INLINE void platformZoneStart(const char* name) { nvtxRangePush(name); } -NV_INLINE void platformZoneEnd(const char*) { nvtxRangePop(); } - -#elif NV_XBOXONE -#define NOMINMAX -#include "xboxone/NvBlastProfilerXB1.h" - -#elif NV_PS4 -#include "ps4/NvBlastProfilerPS4.h" - -#else -NV_INLINE void platformZoneStart(const char*) { } -NV_INLINE void platformZoneEnd(const char*) { } - -#endif - -#define TEST_ZONE_BEGIN(name) platformZoneStart(name) -#define TEST_ZONE_END(name) platformZoneEnd(name) - -#endif // TESTPROFILER_H |