213 lines
6.4 KiB
C
213 lines
6.4 KiB
C
|
// This code contains NVIDIA Confidential Information and is disclosed to you
|
||
|
// under a form of NVIDIA software license agreement provided separately to you.
|
||
|
//
|
||
|
// Notice
|
||
|
// NVIDIA Corporation and its licensors retain all intellectual property and
|
||
|
// proprietary rights in and to this software and related documentation and
|
||
|
// any modifications thereto. Any use, reproduction, disclosure, or
|
||
|
// distribution of this software and related documentation without an express
|
||
|
// license agreement from NVIDIA Corporation is strictly prohibited.
|
||
|
//
|
||
|
// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
|
||
|
// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
|
||
|
// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
|
||
|
// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
|
||
|
//
|
||
|
// Information and code furnished is believed to be accurate and reliable.
|
||
|
// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
|
||
|
// information or for any infringement of patents or other rights of third parties that may
|
||
|
// result from its use. No license is granted by implication or otherwise under any patent
|
||
|
// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
|
||
|
// This code supersedes and replaces all information previously supplied.
|
||
|
// NVIDIA Corporation products are not authorized for use as critical
|
||
|
// components in life support devices or systems without express written approval of
|
||
|
// NVIDIA Corporation.
|
||
|
//
|
||
|
// Copyright (c) 2008-2013 NVIDIA Corporation. All rights reserved.
|
||
|
|
||
|
#ifndef PX_SPU_TASK_H
|
||
|
#define PX_SPU_TASK_H
|
||
|
|
||
|
#include "pxtask/PxTask.h"
|
||
|
#include "pxtask/PxSpuDispatcher.h"
|
||
|
|
||
|
#ifndef PX_DOXYGEN
|
||
|
namespace physx
|
||
|
{
|
||
|
#endif
|
||
|
|
||
|
namespace pxtask
|
||
|
{
|
||
|
|
||
|
/**
|
||
|
\brief A task to be executed on one or more SPUs
|
||
|
|
||
|
Each SpuTask can run in a data parallel fashion on up to 6 SPUs. To coordinate the
|
||
|
workers, each SPU will be passed it's own set of arguments.
|
||
|
|
||
|
When all SPU workers have completed their work, the task is considered complete and the
|
||
|
SpuDispatcher will call release on the task, this in turn will call removeReference()
|
||
|
on the task's continuation.
|
||
|
|
||
|
In this way LightCpuTasks may be launched automatically at SpuTask completion and vice versa.
|
||
|
|
||
|
Users should not need to implement or create SpuTasks directly. The SDK creates the tasks
|
||
|
internally and will submit them to the TaskManager's SpuDispatcher for execution. The
|
||
|
SpuDispatcher that will be used is configured on a per-scene basis through the PxSceneDesc.
|
||
|
|
||
|
@see SpuDispatcher
|
||
|
@see PxSceneDesc
|
||
|
*/
|
||
|
class SpuTask : public LightCpuTask
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
static const PxU32 kMaxSpus = 6; //!< The maximum number of SPUs
|
||
|
static const PxU32 kArgsPerSpu = 2; //!< Arguments per SPU
|
||
|
|
||
|
/**
|
||
|
\brief Construct a new SpuTask object
|
||
|
\param[in] elfStart The starting address of the embedded SPU binary
|
||
|
\param[in] elfSize The size in bytes of the embedded SPU binary
|
||
|
\param[in] numSpus The number of SPU workers this task will run across
|
||
|
\param[in] args A pointer to an array of arguments, must be at least kArgsPerSpu*numSpus big
|
||
|
*/
|
||
|
SpuTask(const void* elfStart, PxU32 elfSize, PxU32 numSpus=1, const PxU32* args=NULL)
|
||
|
: mElfStart(elfStart)
|
||
|
, mElfSize(elfSize)
|
||
|
, mNumSpusToRun(numSpus)
|
||
|
, mNumSpusFinished(0)
|
||
|
{
|
||
|
if (args)
|
||
|
{
|
||
|
memcpy(mArgs, args, mNumSpusToRun*kArgsPerSpu*sizeof(PxU32));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
virtual ~SpuTask() {}
|
||
|
|
||
|
/**
|
||
|
\brief Return the number of SPUs used to run this task
|
||
|
*/
|
||
|
PX_INLINE PxU32 getSpuCount() const
|
||
|
{
|
||
|
return mNumSpusToRun;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
\brief Set the number of SPUs to be used when running this task
|
||
|
*/
|
||
|
PX_INLINE void setSpuCount(PxU32 numSpusToRun)
|
||
|
{
|
||
|
PX_ASSERT(numSpusToRun);
|
||
|
mNumSpusToRun = numSpusToRun;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
\brief Retrieve the per-SPU argument
|
||
|
\param[in] spuIndex The SPU that we want to retrieve the argument for
|
||
|
\return A pointer to the parameters for the given SPU index
|
||
|
*/
|
||
|
PX_INLINE const PxU32* getArgs(PxU32 spuIndex) const
|
||
|
{
|
||
|
PX_ASSERT(spuIndex < kMaxSpus);
|
||
|
return mArgs[spuIndex];
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
\brief Set the arguments for a given SPU worker
|
||
|
\param[in] spuIndex The index of the SPU worker whose arguments are to be set
|
||
|
\param[in] arg1 The first argument to be passed to this worker
|
||
|
\param[in] arg2 The second argument to be passed to this worker
|
||
|
*/
|
||
|
PX_INLINE void setArgs(PxU32 spuIndex, PxU32 arg1, PxU32 arg2)
|
||
|
{
|
||
|
PX_ASSERT(spuIndex < kMaxSpus);
|
||
|
PxU32* arguments = mArgs[spuIndex];
|
||
|
arguments[0]=arg1;
|
||
|
arguments[1]=arg2;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
\brief Return the address to the start of the embedded elf binary for this task
|
||
|
*/
|
||
|
PX_INLINE const void* getElfStart() const
|
||
|
{
|
||
|
return mElfStart;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
\brief Return the size of the embedded elf binary for this task
|
||
|
*/
|
||
|
PX_INLINE PxU32 getElfSize() const
|
||
|
{
|
||
|
return mElfSize;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
\brief Called by the SpuDispatcher when a SPU worker has completed, when all
|
||
|
workers have completed the task is considered finished and the continuation will
|
||
|
have it's ref count decremented.
|
||
|
*/
|
||
|
PX_INLINE void notifySpuFinish()
|
||
|
{
|
||
|
++mNumSpusFinished;
|
||
|
|
||
|
// if all SPU tasks have finished clean-up and release
|
||
|
if (mNumSpusFinished == mNumSpusToRun)
|
||
|
{
|
||
|
mNumSpusFinished = 0;
|
||
|
release();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
\brief Modifies LightCpuTask's behavior by submitting to the SpuDispatcher
|
||
|
*/
|
||
|
virtual void removeReference()
|
||
|
{
|
||
|
PX_ASSERT(mTm);
|
||
|
mTm->decrReference(*this);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
\brief Allow the task to perform PPU side intialization before the task is
|
||
|
scheduled to the SPUs.
|
||
|
|
||
|
This should be called by the SpuDispatcher from whichever thread calls
|
||
|
submitTask(); the task should be scheduled to the SPUs immediately
|
||
|
following this function returning.
|
||
|
*/
|
||
|
virtual void run() {}
|
||
|
|
||
|
/** \brief Called by the SpuDispatcher after scheduling a task to the SPUs.
|
||
|
|
||
|
This virtual method allows the task to perform PPU side work while the SPU
|
||
|
task is running, for example using the PPU as a producer and the SPUs as
|
||
|
a consumer.
|
||
|
*/
|
||
|
virtual void runAfterDispatch() {}
|
||
|
|
||
|
protected:
|
||
|
|
||
|
const void* mElfStart; //!< A pointer to the start of the ELF image
|
||
|
PxU32 mElfSize; //!< The size of the ELF image
|
||
|
PxU32 mNumSpusToRun; //!< The number of SPUs to run
|
||
|
PxU32 mNumSpusFinished; //!< The number of SPUs finished
|
||
|
PxU32 mArgs[kMaxSpus][kArgsPerSpu]; //!< The arguments for the SPUs
|
||
|
|
||
|
}
|
||
|
// wrap this in a macro so Doxygen doesn't get confused and output it
|
||
|
#ifndef PX_DOXYGEN
|
||
|
PX_ALIGN_SUFFIX(16)
|
||
|
#endif
|
||
|
;
|
||
|
|
||
|
} // end pxtask namespace
|
||
|
|
||
|
#ifndef PX_DOXYGEN
|
||
|
} // end physx namespace
|
||
|
#endif
|
||
|
|
||
|
#endif
|