| 1 | // | 
| 2 | // Redistribution and use in source and binary forms, with or without | 
| 3 | // modification, are permitted provided that the following conditions | 
| 4 | // are met: | 
| 5 | //  * Redistributions of source code must retain the above copyright | 
| 6 | //    notice, this list of conditions and the following disclaimer. | 
| 7 | //  * Redistributions in binary form must reproduce the above copyright | 
| 8 | //    notice, this list of conditions and the following disclaimer in the | 
| 9 | //    documentation and/or other materials provided with the distribution. | 
| 10 | //  * Neither the name of NVIDIA CORPORATION nor the names of its | 
| 11 | //    contributors may be used to endorse or promote products derived | 
| 12 | //    from this software without specific prior written permission. | 
| 13 | // | 
| 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY | 
| 15 | // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 
| 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 
| 17 | // PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR | 
| 18 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 
| 19 | // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 
| 20 | // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | 
| 21 | // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | 
| 22 | // OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
| 23 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
| 24 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
| 25 | // | 
| 26 | // Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved. | 
| 27 |  | 
| 28 | #ifndef PXTASK_PXTASK_H | 
| 29 | #define PXTASK_PXTASK_H | 
| 30 |  | 
| 31 | #include "task/PxTaskDefine.h" | 
| 32 | #include "task/PxTaskManager.h" | 
| 33 | #include "task/PxCpuDispatcher.h" | 
| 34 | #include "foundation/PxAssert.h" | 
| 35 |  | 
| 36 | namespace physx | 
| 37 | { | 
| 38 |  | 
| 39 | /** | 
| 40 |  * \brief Base class of all task types | 
| 41 |  * | 
| 42 |  * PxBaseTask defines a runnable reference counted task with built-in profiling. | 
| 43 |  */ | 
| 44 | class PxBaseTask | 
| 45 | { | 
| 46 | public: | 
| 47 | 	PxBaseTask() : mContextID(0), mTm(NULL) {} | 
| 48 | 	virtual ~PxBaseTask() {} | 
| 49 |  | 
| 50 |     /** | 
| 51 |      * \brief The user-implemented run method where the task's work should be performed | 
| 52 |      * | 
| 53 |      * run() methods must be thread safe, stack friendly (no alloca, etc), and | 
| 54 |      * must never block. | 
| 55 |      */ | 
| 56 |     virtual void        run() = 0; | 
| 57 |  | 
| 58 |     /** | 
| 59 |      * \brief Return a user-provided task name for profiling purposes. | 
| 60 |      * | 
| 61 |      * It does not have to be unique, but unique names are helpful. | 
| 62 | 	 * | 
| 63 | 	 * \return The name of this task | 
| 64 |      */ | 
| 65 |     virtual const char*	getName() const = 0; | 
| 66 |  | 
| 67 |     //! \brief Implemented by derived implementation classes | 
| 68 |     virtual void		addReference() = 0; | 
| 69 |     //! \brief Implemented by derived implementation classes | 
| 70 |     virtual void		removeReference() = 0; | 
| 71 | 	//! \brief Implemented by derived implementation classes | 
| 72 | 	virtual int32_t		getReference() const = 0; | 
| 73 |  | 
| 74 |     /** \brief Implemented by derived implementation classes | 
| 75 | 	 * | 
| 76 | 	 * A task may assume in its release() method that the task system no longer holds  | 
| 77 | 	 * references to it - so it may safely run its destructor, recycle itself, etc. | 
| 78 | 	 * provided no additional user references to the task exist | 
| 79 | 	 */ | 
| 80 |     virtual void		release() = 0; | 
| 81 |  | 
| 82 |     /** | 
| 83 |      * \brief Return PxTaskManager to which this task was submitted | 
| 84 |      * | 
| 85 |      * Note, can return NULL if task was not submitted, or has been | 
| 86 |      * completed. | 
| 87 |      */ | 
| 88 | 	PX_FORCE_INLINE PxTaskManager* getTaskManager() const | 
| 89 | 	{ | 
| 90 | 		return mTm; | 
| 91 | 	} | 
| 92 |  | 
| 93 | 	PX_FORCE_INLINE	void	setContextId(PxU64 id)			{ mContextID = id;		} | 
| 94 | 	PX_FORCE_INLINE	PxU64	getContextId()			const	{ return mContextID;	} | 
| 95 |  | 
| 96 | protected: | 
| 97 | 	PxU64				mContextID;		//!< Context ID for profiler interface | 
| 98 | 	PxTaskManager*		mTm;			//!< Owning PxTaskManager instance | 
| 99 |  | 
| 100 | 	friend class PxTaskMgr; | 
| 101 | }; | 
| 102 |  | 
| 103 |  | 
| 104 | /** | 
| 105 |  * \brief A PxBaseTask implementation with deferred execution and full dependencies | 
| 106 |  * | 
| 107 |  * A PxTask must be submitted to a PxTaskManager to to be executed, Tasks may | 
| 108 |  * optionally be named when they are submitted. | 
| 109 |  */ | 
| 110 | class PxTask : public PxBaseTask | 
| 111 | { | 
| 112 | public: | 
| 113 | 	PxTask() : mTaskID(0) {} | 
| 114 | 	virtual ~PxTask() {} | 
| 115 |  | 
| 116 |     //! \brief Release method implementation | 
| 117 |     virtual void release() | 
| 118 | 	{ | 
| 119 | 		PX_ASSERT(mTm); | 
| 120 |  | 
| 121 |         // clear mTm before calling taskCompleted() for safety | 
| 122 | 		PxTaskManager* save = mTm; | 
| 123 | 		mTm = NULL; | 
| 124 | 		save->taskCompleted( task&: *this ); | 
| 125 | 	} | 
| 126 |  | 
| 127 |     //! \brief Inform the PxTaskManager this task must finish before the given | 
| 128 |     //         task is allowed to start. | 
| 129 |     PX_INLINE void finishBefore( PxTaskID taskID ) | 
| 130 | 	{ | 
| 131 | 		PX_ASSERT(mTm); | 
| 132 | 		mTm->finishBefore( task&: *this, taskID); | 
| 133 | 	} | 
| 134 |  | 
| 135 |     //! \brief Inform the PxTaskManager this task cannot start until the given | 
| 136 |     //         task has completed. | 
| 137 |     PX_INLINE void startAfter( PxTaskID taskID ) | 
| 138 | 	{ | 
| 139 | 		PX_ASSERT(mTm); | 
| 140 | 		mTm->startAfter( task&: *this, taskID ); | 
| 141 | 	} | 
| 142 |  | 
| 143 |     /** | 
| 144 |      * \brief Manually increment this task's reference count.  The task will | 
| 145 |      * not be allowed to run until removeReference() is called. | 
| 146 |      */ | 
| 147 |     PX_INLINE void addReference() | 
| 148 | 	{ | 
| 149 | 		PX_ASSERT(mTm); | 
| 150 | 		mTm->addReference( taskID: mTaskID ); | 
| 151 | 	} | 
| 152 |  | 
| 153 |     /** | 
| 154 |      * \brief Manually decrement this task's reference count.  If the reference | 
| 155 |      * count reaches zero, the task will be dispatched. | 
| 156 |      */ | 
| 157 |     PX_INLINE void removeReference() | 
| 158 | 	{ | 
| 159 | 		PX_ASSERT(mTm); | 
| 160 | 		mTm->decrReference( taskID: mTaskID ); | 
| 161 | 	} | 
| 162 |  | 
| 163 | 	/**  | 
| 164 | 	 * \brief Return the ref-count for this task  | 
| 165 | 	 */ | 
| 166 | 	PX_INLINE int32_t getReference() const | 
| 167 | 	{ | 
| 168 | 		return mTm->getReference( taskID: mTaskID ); | 
| 169 | 	} | 
| 170 | 	 | 
| 171 | 	/** | 
| 172 | 	 * \brief Return the unique ID for this task | 
| 173 | 	 */ | 
| 174 | 	PX_INLINE PxTaskID	    getTaskID() const | 
| 175 | 	{ | 
| 176 | 		return mTaskID; | 
| 177 | 	} | 
| 178 |  | 
| 179 | 	/** | 
| 180 | 	 * \brief Called by PxTaskManager at submission time for initialization | 
| 181 | 	 * | 
| 182 | 	 * Perform simulation step initialization here. | 
| 183 | 	 */ | 
| 184 | 	virtual void submitted() | 
| 185 | 	{ | 
| 186 | 	} | 
| 187 |  | 
| 188 | protected: | 
| 189 | 	PxTaskID			mTaskID;			//!< ID assigned at submission | 
| 190 |  | 
| 191 | 	friend class PxTaskMgr; | 
| 192 | }; | 
| 193 |  | 
| 194 |  | 
| 195 | /** | 
| 196 |  * \brief A PxBaseTask implementation with immediate execution and simple dependencies | 
| 197 |  * | 
| 198 |  * A PxLightCpuTask bypasses the PxTaskManager launch dependencies and will be | 
| 199 |  * submitted directly to your scene's CpuDispatcher.  When the run() function | 
| 200 |  * completes, it will decrement the reference count of the specified | 
| 201 |  * continuation task. | 
| 202 |  * | 
| 203 |  * You must use a full-blown PxTask if you want your task to be resolved | 
| 204 |  * by another PxTask, or you need more than a single dependency to be | 
| 205 |  * resolved when your task completes, or your task will not run on the | 
| 206 |  * CpuDispatcher. | 
| 207 |  */ | 
| 208 | class PxLightCpuTask : public PxBaseTask | 
| 209 | { | 
| 210 | public: | 
| 211 | 	PxLightCpuTask() | 
| 212 | 		: mCont( NULL ) | 
| 213 | 		, mRefCount( 0 ) | 
| 214 | 	{ | 
| 215 | 	} | 
| 216 | 	virtual ~PxLightCpuTask() | 
| 217 | 	{ | 
| 218 | 		mTm = NULL; | 
| 219 | 	} | 
| 220 |  | 
| 221 |     /** | 
| 222 |      * \brief Initialize this task and specify the task that will have its ref count decremented on completion. | 
| 223 |      * | 
| 224 |      * Submission is deferred until the task's mRefCount is decremented to zero.   | 
| 225 | 	 * Note that we only use the PxTaskManager to query the appropriate dispatcher. | 
| 226 | 	 * | 
| 227 | 	 * \param[in] tm The PxTaskManager this task is managed by | 
| 228 | 	 * \param[in] c The task to be executed when this task has finished running | 
| 229 | 	 */ | 
| 230 | 	PX_INLINE void setContinuation(PxTaskManager& tm, PxBaseTask* c) | 
| 231 | 	{ | 
| 232 | 		PX_ASSERT( mRefCount == 0 ); | 
| 233 | 		mRefCount = 1; | 
| 234 | 		mCont = c; | 
| 235 | 		mTm = &tm; | 
| 236 | 		if( mCont ) | 
| 237 | 		{ | 
| 238 | 			mCont->addReference(); | 
| 239 | 	    } | 
| 240 | 	} | 
| 241 |  | 
| 242 |     /** | 
| 243 |      * \brief Initialize this task and specify the task that will have its ref count decremented on completion. | 
| 244 |      * | 
| 245 |      * This overload of setContinuation() queries the PxTaskManager from the continuation | 
| 246 |      * task, which cannot be NULL. | 
| 247 | 	 * \param[in] c The task to be executed after this task has finished running | 
| 248 | 	 */ | 
| 249 | 	PX_INLINE void setContinuation( PxBaseTask* c ) | 
| 250 | 	{ | 
| 251 | 		PX_ASSERT( c ); | 
| 252 | 		PX_ASSERT( mRefCount == 0 ); | 
| 253 | 		mRefCount = 1; | 
| 254 | 		mCont = c; | 
| 255 | 		if( mCont ) | 
| 256 | 		{ | 
| 257 | 			mCont->addReference(); | 
| 258 | 			mTm = mCont->getTaskManager(); | 
| 259 | 			PX_ASSERT( mTm ); | 
| 260 | 		} | 
| 261 | 	} | 
| 262 |  | 
| 263 |     /** | 
| 264 |      * \brief Retrieves continuation task | 
| 265 | 	 */ | 
| 266 | 	PX_INLINE PxBaseTask*	getContinuation()	const | 
| 267 | 	{ | 
| 268 | 		return mCont; | 
| 269 | 	} | 
| 270 |  | 
| 271 |     /** | 
| 272 |      * \brief Manually decrement this task's reference count.  If the reference | 
| 273 |      * count reaches zero, the task will be dispatched. | 
| 274 |      */ | 
| 275 | 	PX_INLINE void removeReference() | 
| 276 | 	{ | 
| 277 | 		mTm->decrReference(*this); | 
| 278 | 	} | 
| 279 |  | 
| 280 | 	/** \brief Return the ref-count for this task */ | 
| 281 | 	PX_INLINE int32_t getReference() const | 
| 282 | 	{ | 
| 283 | 		return mRefCount; | 
| 284 | 	} | 
| 285 |  | 
| 286 |     /** | 
| 287 |      * \brief Manually increment this task's reference count.  The task will | 
| 288 |      * not be allowed to run until removeReference() is called. | 
| 289 |      */ | 
| 290 | 	PX_INLINE void addReference() | 
| 291 | 	{ | 
| 292 | 		mTm->addReference(*this); | 
| 293 | 	} | 
| 294 |  | 
| 295 |     /** | 
| 296 |      * \brief called by CpuDispatcher after run method has completed | 
| 297 |      * | 
| 298 |      * Decrements the continuation task's reference count, if specified. | 
| 299 |      */ | 
| 300 | 	PX_INLINE void release() | 
| 301 | 	{ | 
| 302 | 		if( mCont ) | 
| 303 | 		{ | 
| 304 | 			mCont->removeReference(); | 
| 305 | 	    } | 
| 306 | 	} | 
| 307 |  | 
| 308 | protected: | 
| 309 |  | 
| 310 | 	PxBaseTask*			mCont;          //!< Continuation task, can be NULL | 
| 311 | 	volatile int32_t	mRefCount;      //!< PxTask is dispatched when reaches 0 | 
| 312 |  | 
| 313 | 	friend class PxTaskMgr; | 
| 314 | }; | 
| 315 |  | 
| 316 |  | 
| 317 | }// end physx namespace | 
| 318 |  | 
| 319 |  | 
| 320 | #endif // PXTASK_PXTASK_H | 
| 321 |  |