moveContext * initMove() { moveContext *context = NULL; Spurs *spurs; gemAttribute gem_attr; int ret; int i; spurs = initSpurs ("gem_spurs"); if (spurs == NULL) goto error; printf ("preparing GemAttribute structure with spurs\n"); gem_attr.version = 2; gem_attr.max = 1; gem_attr.spurs = spurs; gem_attr.memory = NULL; gem_attr.spu_priorities[0] = 1; for (i = 1; i < 8; ++i) gem_attr.spu_priorities[i] = 0; printf ("calling GemInit with GemAttribute structure version=%d max_connect=%d spurs=%X\n", gem_attr.version, gem_attr.max, gem_attr.spurs); ret = gemInit (&gem_attr); printf ("return from GemInit %X \n", ret); if (ret) goto error; ret = gemPrepareCamera (128, 0.5); printf ("GemPrepareCamera return %d exposure set to 128 and quality to 0.5\n", ret); if (ret) goto error; ret = gemReset (0); printf ("GemReset return %X \n", ret); if (ret) goto error; context = (moveContext *)malloc (sizeof (moveContext)); context->spurs = spurs; ret = initCamera (context); if (ret == 0) return context; error: if (spurs) endSpurs (spurs); if (context) free (context); return NULL; }
int initGem () { int ret; int i; initSpurs (); ret = gemGetMemorySize (1); printf ("return from GemGetMemorySize %X size in bytes needed for move device to init libgem\n", ret); gem_memory = malloc (ret); printf ("preparing GemAttribute structure with sprus and memory stuff is very important align correctly spurs structure \n"); u8 gem_spu_priorities[8] = { 1, 1, 1, 1, 1, 0, 0, 0 }; // execute // libgem jobs // on 5 spu gemAttribute gem_attr; initAttributeGem (&gem_attr, 1, gem_memory, spurs, gem_spu_priorities); printf ("calling GemInit with GemAttribute structure version=%d max_connect=%d spurs=%X memory_ptr=%X \n", gem_attr.version, gem_attr.max, gem_attr.spurs, gem_attr.memory); ret = gemInit (&gem_attr); printf ("return from GemInit %X \n", ret); ret= initGemVideoConvert(); printf ("return from initGemVideoConvert %X \n", ret); ret = gemPrepareCamera (128, 0.5); printf ("GemPrepareCamera return %d exposure set to 128 and quality to 0.5\n", ret); ret = gemReset (0); printf ("GemReset return %X \n", ret); return ret; }
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; }