353 lines
9.2 KiB
C
353 lines
9.2 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_TASK_H
|
||
|
#define PX_TASK_H
|
||
|
|
||
|
#include "foundation/Px.h"
|
||
|
#include "pxtask/PxTaskManager.h"
|
||
|
#include "foundation/PxAssert.h"
|
||
|
|
||
|
#ifndef PX_DOXYGEN
|
||
|
namespace physx
|
||
|
{
|
||
|
#endif
|
||
|
|
||
|
namespace pxtask
|
||
|
{
|
||
|
|
||
|
/**
|
||
|
* \brief Base class of all task types
|
||
|
*
|
||
|
* BaseTask defines a runnable reference counted task with built-in profiling.
|
||
|
*/
|
||
|
class BaseTask
|
||
|
{
|
||
|
public:
|
||
|
BaseTask() : mEventID(0xFFFF), mProfileStat(0), mTm(0) {}
|
||
|
virtual ~BaseTask() {}
|
||
|
|
||
|
/**
|
||
|
* \brief The user-implemented run method where the task's work should be performed
|
||
|
*
|
||
|
* run() methods must be thread safe, stack friendly (no alloca, etc), and
|
||
|
* must never block.
|
||
|
*/
|
||
|
virtual void run() = 0;
|
||
|
|
||
|
/**
|
||
|
* \brief Return a user-provided task name for profiling purposes.
|
||
|
*
|
||
|
* It does not have to be unique, but unique names are helpful.
|
||
|
*
|
||
|
* \return The name of this task
|
||
|
*/
|
||
|
virtual const char *getName() const = 0;
|
||
|
|
||
|
//! \brief Implemented by derived implementation classes
|
||
|
virtual void addReference() = 0;
|
||
|
//! \brief Implemented by derived implementation classes
|
||
|
virtual void removeReference() = 0;
|
||
|
//! \brief Implemented by derived implementation classes
|
||
|
virtual PxI32 getReference() const = 0;
|
||
|
|
||
|
//! \brief Implemented by derived implementation classes
|
||
|
virtual void release() = 0;
|
||
|
|
||
|
/**
|
||
|
* \brief Execute user run method with wrapping profiling events.
|
||
|
*
|
||
|
* Optional entry point for use by CpuDispatchers.
|
||
|
*/
|
||
|
PX_INLINE void runProfiled()
|
||
|
{
|
||
|
mTm->emitStartEvent(*this);
|
||
|
run();
|
||
|
mTm->emitStopEvent(*this);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* \brief Specify stop event statistic
|
||
|
*
|
||
|
* If called before or while the task is executing, the given value
|
||
|
* will appear in the task's event bar in the profile viewer
|
||
|
*
|
||
|
* \param[in] stat The stat to signal when the task is finished
|
||
|
*/
|
||
|
PX_INLINE void setProfileStat( PxU16 stat )
|
||
|
{
|
||
|
mProfileStat = stat;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* \brief Return TaskManager to which this task was submitted
|
||
|
*
|
||
|
* Note, can return NULL if task was not submitted, or has been
|
||
|
* completed.
|
||
|
*/
|
||
|
PX_INLINE TaskManager* getTaskManager() const
|
||
|
{
|
||
|
return mTm;
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
PxU16 mEventID; //!< Registered profile event ID
|
||
|
PxU16 mProfileStat; //!< Profiling statistic
|
||
|
TaskManager * mTm; //!< Owning TaskManager instance
|
||
|
|
||
|
friend class TaskMgr;
|
||
|
};
|
||
|
|
||
|
|
||
|
/**
|
||
|
* \brief A BaseTask implementation with deferred execution and full dependencies
|
||
|
*
|
||
|
* A Task must be submitted to a TaskManager to to be executed, Tasks may
|
||
|
* optionally be named when they are submitted.
|
||
|
*/
|
||
|
class Task : public BaseTask
|
||
|
{
|
||
|
public:
|
||
|
Task() : mTaskID(0) {}
|
||
|
virtual ~Task() {}
|
||
|
|
||
|
//! \brief Release method implementation
|
||
|
virtual void release()
|
||
|
{
|
||
|
PX_ASSERT(mTm);
|
||
|
|
||
|
// clear mTm before calling taskCompleted() for safety
|
||
|
TaskManager *save = mTm;
|
||
|
mTm = NULL;
|
||
|
save->taskCompleted( *this );
|
||
|
}
|
||
|
|
||
|
//! \brief Inform the TaskManager this task must finish before the given
|
||
|
// task is allowed to start.
|
||
|
PX_INLINE void finishBefore( TaskID taskID )
|
||
|
{
|
||
|
PX_ASSERT(mTm);
|
||
|
mTm->finishBefore( *this, taskID);
|
||
|
}
|
||
|
|
||
|
//! \brief Inform the TaskManager this task cannot start until the given
|
||
|
// task has completed.
|
||
|
PX_INLINE void startAfter( TaskID taskID )
|
||
|
{
|
||
|
PX_ASSERT(mTm);
|
||
|
mTm->startAfter( *this, taskID );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* \brief Manually increment this task's reference count. The task will
|
||
|
* not be allowed to run until removeReference() is called.
|
||
|
*/
|
||
|
PX_INLINE void addReference()
|
||
|
{
|
||
|
PX_ASSERT(mTm);
|
||
|
mTm->addReference( mTaskID );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* \brief Manually decrement this task's reference count. If the reference
|
||
|
* count reaches zero, the task will be dispatched.
|
||
|
*/
|
||
|
PX_INLINE void removeReference()
|
||
|
{
|
||
|
PX_ASSERT(mTm);
|
||
|
mTm->decrReference( mTaskID );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* \brief Return the ref-count for this task
|
||
|
*/
|
||
|
PX_INLINE PxI32 getReference() const
|
||
|
{
|
||
|
return mTm->getReference( mTaskID );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* \brief Return the unique ID for this task
|
||
|
*/
|
||
|
PX_INLINE TaskID getTaskID() const
|
||
|
{
|
||
|
return mTaskID;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* \brief Called by TaskManager at submission time for initialization
|
||
|
*
|
||
|
* Perform simulation step initialization here.
|
||
|
*/
|
||
|
virtual void submitted()
|
||
|
{
|
||
|
mStreamIndex = 0;
|
||
|
mPreSyncRequired = false;
|
||
|
mProfileStat = 0;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* \brief Specify that the GpuTask sync flag be set
|
||
|
*/
|
||
|
PX_INLINE void requestSyncPoint()
|
||
|
{
|
||
|
mPreSyncRequired = true;
|
||
|
}
|
||
|
|
||
|
|
||
|
protected:
|
||
|
TaskID mTaskID; //!< ID assigned at submission
|
||
|
PxU32 mStreamIndex; //!< GpuTask CUDA stream index
|
||
|
bool mPreSyncRequired; //!< GpuTask sync flag
|
||
|
|
||
|
friend class TaskMgr;
|
||
|
friend class GpuWorkerThread;
|
||
|
};
|
||
|
|
||
|
|
||
|
/**
|
||
|
* \brief A BaseTask implementation with immediate execution and simple dependencies
|
||
|
*
|
||
|
* A LightCpuTask bypasses the TaskManager launch dependencies and will be
|
||
|
* submitted directly to your scene's CpuDispatcher. When the run() function
|
||
|
* completes, it will decrement the reference count of the specified
|
||
|
* continuation task.
|
||
|
*
|
||
|
* You must use a full-blown pxtask::Task if you want your task to be resolved
|
||
|
* by another pxtask::Task, or you need more than a single dependency to be
|
||
|
* resolved when your task completes, or your task will not run on the
|
||
|
* CpuDispatcher.
|
||
|
*/
|
||
|
class LightCpuTask : public BaseTask
|
||
|
{
|
||
|
public:
|
||
|
LightCpuTask()
|
||
|
: mCont( NULL )
|
||
|
, mRefCount( 0 )
|
||
|
{
|
||
|
}
|
||
|
virtual ~LightCpuTask()
|
||
|
{
|
||
|
mTm = NULL;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* \brief Initialize this task and specify the task that will have it's ref count decremented on completion.
|
||
|
*
|
||
|
* Submission is deferred until the task's mRefCount is decremented to zero.
|
||
|
* Note that we only use the TaskManager to query the appropriate dispatcher.
|
||
|
*
|
||
|
* \param[in] tm The TaskManager this task is managed by
|
||
|
* \param[in] c The task to be executed when this task has finished running
|
||
|
*/
|
||
|
PX_INLINE void setContinuation(TaskManager& tm, BaseTask* c)
|
||
|
{
|
||
|
PX_ASSERT( mRefCount == 0 );
|
||
|
mRefCount = 1;
|
||
|
mCont = c;
|
||
|
mTm = &tm;
|
||
|
if( mCont )
|
||
|
{
|
||
|
mCont->addReference();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* \brief Initialize this task and specify the task that will have it's ref count decremented on completion.
|
||
|
*
|
||
|
* This overload of setContinuation() queries the TaskManager from the continuation
|
||
|
* task, which cannot be NULL.
|
||
|
* \param[in] c The task to be executed after this task has finished running
|
||
|
*/
|
||
|
PX_INLINE void setContinuation( BaseTask *c )
|
||
|
{
|
||
|
PX_ASSERT( c );
|
||
|
PX_ASSERT( mRefCount == 0 );
|
||
|
mRefCount = 1;
|
||
|
mCont = c;
|
||
|
if( mCont )
|
||
|
{
|
||
|
mCont->addReference();
|
||
|
mTm = mCont->getTaskManager();
|
||
|
PX_ASSERT( mTm );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* \brief Manually decrement this task's reference count. If the reference
|
||
|
* count reaches zero, the task will be dispatched.
|
||
|
*/
|
||
|
PX_INLINE void removeReference()
|
||
|
{
|
||
|
mTm->decrReference(*this);
|
||
|
}
|
||
|
|
||
|
/** \brief Return the ref-count for this task */
|
||
|
PX_INLINE PxI32 getReference() const
|
||
|
{
|
||
|
return mRefCount;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* \brief Manually increment this task's reference count. The task will
|
||
|
* not be allowed to run until removeReference() is called.
|
||
|
*/
|
||
|
PX_INLINE void addReference()
|
||
|
{
|
||
|
mTm->addReference(*this);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* \brief called by CpuDispatcher after run method has completed
|
||
|
*
|
||
|
* Decrements the continuation task's reference count, if specified.
|
||
|
*/
|
||
|
PX_INLINE void release()
|
||
|
{
|
||
|
if( mCont )
|
||
|
{
|
||
|
mCont->removeReference();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
|
||
|
BaseTask * mCont; //!< Continuation task, can be NULL
|
||
|
volatile PxI32 mRefCount; //!< Task is dispatched when reaches 0
|
||
|
|
||
|
friend class TaskMgr;
|
||
|
};
|
||
|
|
||
|
|
||
|
} // end pxtask namespace
|
||
|
|
||
|
#ifndef PX_DOXYGEN
|
||
|
} // end physx namespace
|
||
|
#endif
|
||
|
|
||
|
#endif
|