/* void GHavok::Step(double dt){ _dCurrentTime += dt; if(_dCurrentTime >= _dPhysicsTimeThresh){ // This must be called single threaded here, prior to calling startStepWorld() below. physicsWorld->resetThreadTokens(); // This will signal all threads which are in the wait state, to start processing stepDeltaTime() concurrently. multithreadingUtil->startStepWorld( _currentTime ); // We can now do other things in this thread if we wish, while the physics runs in separate threads. // The call below will block until all physics processing the timestep is finished in all threads. multithreadingUtil->waitForStepWorldFinished(); stepVisualDebugger( _hkVis, _multithreadingUtil, _context ); //Get physics ball position hkVector4 pos = _hkSphere->getPosition(); //Apply ball position to ogrenode _ogreScene->setPosition(pos(0),pos(1)+0.05f,pos(2)); _dCurrentTime = 0.0f; } }*/ void GHavok::DestroyHavok() { WriteToLog("Destroying havok environment..."); _physicsWorld->markForWrite(); _physicsWorld->removeReference(); delete _multithreadingUtil; _hkVis->removeReference(); // Contexts are not reference counted at the base class level by the VDB as // they are just interfaces really. So only delete the context after you have // finished using the VDB. _context->removeReference(); // Deallocate stack area _threadMemory->setStackArea(0, 0); hkDeallocate(_stackBuffer); WriteToLog("Complete\n"); //Deallocate runtime blocks hkMemory::getInstance().freeRuntimeBlocks(); _bCreated = false; _nThreads = 0; _bThreaded = false; }
hkDemoFileSystem::~hkDemoFileSystem() { m_parent->removeReference(); for( int i = 0; i < m_locations.getSize(); ++i ) { hkDeallocate( m_locations[i] ); } }
ObjectsOnLandscapeDemo::~ObjectsOnLandscapeDemo() { // Delete the world before removing reference to the packfile data if(m_world) { m_world->markForWrite(); m_world->removeReference(); m_world = HK_NULL; } if (m_packfileData) m_packfileData->removeReference(); hkDeallocate( m_stackBuffer ); hkThreadMemory::getInstance().setStackArea( m_oldStack.m_current, m_oldStack.getFreeBytes() ); }
RayTraceDemo::~RayTraceDemo() { // Re-enable warnings: hkError::getInstance().setEnabled(0x7dd65995, true); hkReferencedObject::lockAll(); hkAlignedDeallocate<unsigned char>(m_canvasData); m_world->markForWrite(); m_world->removeReference(); m_world = HK_NULL; m_shape->removeReference(); m_context->lock(); m_texture->free(); m_texture->release(); m_context->unlock(); hkReferencedObject::unlockAll(); hkDeallocate( m_stackBuffer ); hkThreadMemory::getInstance().setStackArea( m_oldStack.m_current, m_oldStack.getFreeBytes() ); }
void Havok::Close() { /* if(0) { udword Size = mRigidBodies.size(); for(udword i=0;i<Size;i++) { hkpRigidBody* rb = mRigidBodies[i]; DELETESINGLE(rb); } }*/ { mPhysicsWorld->lock(); const udword Size = mPhantoms.GetNbEntries(); for(udword i=0;i<Size;i++) { hkpAabbPhantom* phantom = (hkpAabbPhantom*)mPhantoms[i]; phantom->removeReference(); } mPhysicsWorld->unlock(); } // <PHYSICS-ONLY>: cleanup physics { mPhysicsWorld->markForWrite(); mPhysicsWorld->removeReference(); mPhysicsWorld = null; } { if(mVdb) { mVdb->removeReference(); mVdb = null; } // Contexts are not reference counted at the base class level by the VDB as // they are just interfaces really. So only delete the context after you have // finished using the VDB. if(mContext) { mContext->removeReference(); mContext = null; } } { DELETESINGLE(mJobQueue); // // Clean up the thread pool // if(mThreadPool) { mThreadPool->removeReference(); mThreadPool = null; } } // Deallocate stack area // mThreadMemory->setStackArea(0, 0); hkDeallocate(mStackBuffer); mStackBuffer = null; // mThreadMemory->removeReference(); // mThreadMemory = null; mMemoryRouter = null; // Quit base system hkBaseSystem::quit(); // DELETESINGLE(gMemoryManager); // gMemoryManager = null; hkMemoryInitUtil::quit(); }
int HK_CALL main(int argc, const char** argv) { // // Do platform specific initialization // #if !defined(HK_PLATFORM_WIN32) extern void initPlatform(); initPlatform(); #endif // // Initialize the base system including our memory system // hkPoolMemory* memoryManager = new hkPoolMemory(); hkThreadMemory* threadMemory = new hkThreadMemory(memoryManager); hkBaseSystem::init( memoryManager, threadMemory, errorReport ); memoryManager->removeReference(); // We now initialize the stack area to 100k (fast temporary memory to be used by the engine). char* stackBuffer; { int stackSize = 0x100000; stackBuffer = hkAllocate<char>( stackSize, HK_MEMORY_CLASS_BASE); hkThreadMemory::getInstance().setStackArea( stackBuffer, stackSize); } { // // Initialize the multi-threading classes, hkJobQueue, and hkJobThreadPool // // They can be used for all Havok multithreading tasks. In this exmaple we only show how to use // them for physics, but you can reference other multithreading demos in the demo framework // to see how to multithread other products. The model of usage is the same as for physics. // The hkThreadpool has a specified number of threads that can run Havok jobs. These can work // alongside the main thread to perform any Havok multi-threadable computations. // The model for running Havok tasks in Spus and in auxilary threads is identical. It is encapsulated in the // class hkJobThreadPool. On PLAYSTATION(R)3 we initialize the SPU version of this class, which is simply a SPURS taskset. // On other multi-threaded platforms we initialize the CPU version of this class, hkCpuJobThreadPool, which creates a pool of threads // that run in exactly the same way. On the PLAYSTATION(R)3 we could also create a hkCpuJobThreadPool. However, it is only // necessary (and advisable) to use one Havok PPU thread for maximum efficiency. In this case we simply use this main thread // for this purpose, and so do not create a hkCpuJobThreadPool. hkJobThreadPool* threadPool; // We can cap the number of threads used - here we use the maximum for whatever multithreaded platform we are running on. This variable is // set in the following code sections. int totalNumThreadsUsed; #if defined HK_PLATFORM_PS3_PPU hkSpuJobThreadPoolCinfo threadPoolCinfo; extern CellSpurs* initSpurs(); HK_CELL_SPURS* spurs = initSpurs(); hkSpuUtil* spuUtil = new hkSpuUtil( spurs ); spuUtil->attachHelperThreadToSpurs(); threadPoolCinfo.m_spuUtil = spuUtil; threadPoolCinfo.m_numSpus = 6; // Use all 6 SPUs for this example totalNumThreadsUsed = 1; // only use one CPU thread for PS3. // This line enables timers collection, by allocating 200 Kb per thread. If you leave this at its default (0), // timer collection will not be enabled. threadPoolCinfo.m_perSpuMontiorBufferSize = 200000; threadPool = new hkSpuJobThreadPool( threadPoolCinfo ); spuUtil->removeReference(); #else // Get the number of physical threads available on the system hkHardwareInfo hwInfo; hkGetHardwareInfo(hwInfo); totalNumThreadsUsed = hwInfo.m_numThreads; // We use one less than this for our thread pool, because we must also use this thread for our simulation hkCpuJobThreadPoolCinfo threadPoolCinfo; threadPoolCinfo.m_numThreads = totalNumThreadsUsed - 1; // This line enables timers collection, by allocating 200 Kb per thread. If you leave this at its default (0), // timer collection will not be enabled. threadPoolCinfo.m_timerBufferPerThreadAllocation = 200000; threadPool = new hkCpuJobThreadPool( threadPoolCinfo ); #endif // We also need to create a Job queue. This job queue will be used by all Havok modules to run multithreaded work. // Here we only use it for physics. hkJobQueueCinfo info; info.m_jobQueueHwSetup.m_numCpuThreads = totalNumThreadsUsed; hkJobQueue* jobQueue = new hkJobQueue(info); // // Enable monitors for this thread. // // Monitors have been enabled for thread pool threads already (see above comment). hkMonitorStream::getInstance().resize(200000); // // <PHYSICS-ONLY>: Create the physics world. // At this point you would initialize any other Havok modules you are using. // hkpWorld* physicsWorld; { // The world cinfo contains global simulation parameters, including gravity, solver settings etc. hkpWorldCinfo worldInfo; // Set the simulation type of the world to multi-threaded. worldInfo.m_simulationType = hkpWorldCinfo::SIMULATION_TYPE_MULTITHREADED; // Flag objects that fall "out of the world" to be automatically removed - just necessary for this physics scene worldInfo.m_broadPhaseBorderBehaviour = hkpWorldCinfo::BROADPHASE_BORDER_REMOVE_ENTITY; physicsWorld = new hkpWorld(worldInfo); // Disable deactivation, so that you can view timers in the VDB. This should not be done in your game. physicsWorld->m_wantDeactivation = false; // When the simulation type is SIMULATION_TYPE_MULTITHREADED, in the debug build, the sdk performs checks // to make sure only one thread is modifying the world at once to prevent multithreaded bugs. Each thread // must call markForRead / markForWrite before it modifies the world to enable these checks. physicsWorld->markForWrite(); // Register all collision agents, even though only box - box will be used in this particular example. // It's important to register collision agents before adding any entities to the world. hkpAgentRegisterUtil::registerAllAgents( physicsWorld->getCollisionDispatcher() ); // We need to register all modules we will be running multi-threaded with the job queue physicsWorld->registerWithJobQueue( jobQueue ); // Create all the physics rigid bodies setupPhysics( physicsWorld ); } // // Initialize the VDB // hkArray<hkProcessContext*> contexts; // <PHYSICS-ONLY>: Register physics specific visual debugger processes // By default the VDB will show debug points and lines, however some products such as physics and cloth have additional viewers // that can show geometries etc and can be enabled and disabled by the VDB app. hkpPhysicsContext* context; { // The visual debugger so we can connect remotely to the simulation // The context must exist beyond the use of the VDB instance, and you can make // whatever contexts you like for your own viewer types. context = new hkpPhysicsContext(); hkpPhysicsContext::registerAllPhysicsProcesses(); // all the physics viewers context->addWorld(physicsWorld); // add the physics world so the viewers can see it contexts.pushBack(context); // Now we have finished modifying the world, release our write marker. physicsWorld->unmarkForWrite(); } hkVisualDebugger* vdb = new hkVisualDebugger(contexts); vdb->serve(); // // Simulate the world for 1 minute. // // Take fixed time steps of 1/60th of a second. // This works well if your game runs solidly at 60Hz. If your game runs at 30Hz // you can take either 2 60Hz steps or 1 30Hz step. Note that at lower frequencies (i.e. 30 Hz) // more bullet through paper issues appear, and constraints will not be as stiff. // If you run at variable frame rate, or are likely to drop frames, you can consider // running your physics for a variable number of steps based on the system clock (i.e. last frame time). // Please refer to the user guide section on time stepping for a full treatment of this issue. // A stopwatch for waiting until the real time has passed hkStopwatch stopWatch; stopWatch.start(); hkReal lastTime = stopWatch.getElapsedSeconds(); hkReal timestep = 1.f / 60.f; int numSteps = int(60.f / timestep); for ( int i = 0; i < numSteps; ++i ) { // <PHYSICS-ONLY>: // Step the physics world. This single call steps using this thread and all threads // in the threadPool. For other products you add jobs, call process all jobs and wait for completion. // See the multithreading chapter in the user guide for details { physicsWorld->stepMultithreaded( jobQueue, threadPool, timestep ); } // Step the visual debugger. We first synchronize the timer data context->syncTimers( threadPool ); vdb->step(); // Clear accumulated timer data in this thread and all slave threads hkMonitorStream::getInstance().reset(); threadPool->clearTimerData(); // <PHYSICS-ONLY>: Display the sphereRigidBody position to the console every second if (i % 60 == 0) { hkVector4 pos = g_ball->getPosition(); printf("[%f,%f,%f]\n", pos(0), pos(1), pos(2)); } // Pause until the actual time has passed while (stopWatch.getElapsedSeconds() < lastTime + timestep); lastTime += timestep; // Step the graphics display (none in this demo). } // // Clean up physics and graphics // // <PHYSICS-ONLY>: cleanup physics { physicsWorld->markForWrite(); physicsWorld->removeReference(); } vdb->removeReference(); // Contexts are not reference counted at the base class level by the VDB as // they are just interfaces really. So only delete the context after you have // finished using the VDB. context->removeReference(); delete jobQueue; // // Clean up the thread pool // threadPool->removeReference(); #if defined HK_PLATFORM_PS3_PPU extern void quitSpurs( CellSpurs* spurs ); quitSpurs( spurs ); #endif } // Deallocate stack area threadMemory->setStackArea(0, 0); hkDeallocate(stackBuffer); threadMemory->removeReference(); // Quit base system hkBaseSystem::quit(); return 0; }