1 | /* |
2 | * Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved. |
3 | * |
4 | * NVIDIA CORPORATION and its licensors retain all intellectual property |
5 | * and proprietary rights in and to this software, related documentation |
6 | * and any modifications thereto. Any use, reproduction, disclosure or |
7 | * distribution of this software and related documentation without an express |
8 | * license agreement from NVIDIA CORPORATION is strictly prohibited. |
9 | */ |
10 | |
11 | #ifndef PX_PROFILE_EVENTS_H |
12 | #define PX_PROFILE_EVENTS_H |
13 | |
14 | #include "physxprofilesdk/PxProfileBase.h" |
15 | #include "physxprofilesdk/PxProfileEventId.h" |
16 | |
17 | #define UNION_1(a) physx::profile::TUnion<a, physx::profile::Empty> |
18 | #define UNION_2(a,b) physx::profile::TUnion<a, UNION_1(b)> |
19 | #define UNION_3(a,b,c) physx::profile::TUnion<a, UNION_2(b,c)> |
20 | #define UNION_4(a,b,c,d) physx::profile::TUnion<a, UNION_3(b,c,d)> |
21 | #define UNION_5(a,b,c,d,e) physx::profile::TUnion<a, UNION_4(b,c,d,e)> |
22 | #define UNION_6(a,b,c,d,e,f) physx::profile::TUnion<a, UNION_5(b,c,d,e,f)> |
23 | #define UNION_7(a,b,c,d,e,f,g) physx::profile::TUnion<a, UNION_6(b,c,d,e,f,g)> |
24 | #define UNION_8(a,b,c,d,e,f,g,h) physx::profile::TUnion<a, UNION_7(b,c,d,e,f,g,h)> |
25 | #define UNION_9(a,b,c,d,e,f,g,h,i) physx::profile::TUnion<a, UNION_8(b,c,d,e,f,g,h,i)> |
26 | |
27 | namespace physx { namespace profile { |
28 | |
29 | struct Empty {}; |
30 | |
31 | template <typename T> struct Type2Type {}; |
32 | |
33 | template <typename U, typename V> |
34 | union TUnion |
35 | { |
36 | typedef U Head; |
37 | typedef V Tail; |
38 | |
39 | Head head; |
40 | Tail tail; |
41 | |
42 | template <typename TDataType> |
43 | void init(const TDataType& inData) |
44 | { |
45 | toType(Type2Type<TDataType>()).init(inData); |
46 | } |
47 | |
48 | template <typename TDataType> |
49 | PX_FORCE_INLINE TDataType& toType(const Type2Type<TDataType>& outData) { return tail.toType(outData); } |
50 | |
51 | PX_FORCE_INLINE Head& toType(const Type2Type<Head>&) { return head; } |
52 | |
53 | template <typename TDataType> |
54 | PX_FORCE_INLINE const TDataType& toType(const Type2Type<TDataType>& outData) const { return tail.toType(outData); } |
55 | |
56 | PX_FORCE_INLINE const Head& toType(const Type2Type<Head>&) const { return head; } |
57 | }; |
58 | |
59 | struct EventTypes |
60 | { |
61 | enum Enum |
62 | { |
63 | Unknown = 0, |
64 | StartEvent, |
65 | StopEvent, |
66 | RelativeStartEvent, //reuses context,id from the earlier event. |
67 | RelativeStopEvent, //reuses context,id from the earlier event. |
68 | EventValue, |
69 | CUDAProfileBuffer |
70 | }; |
71 | }; |
72 | |
73 | struct EventStreamCompressionFlags |
74 | { |
75 | enum Enum |
76 | { |
77 | U8 = 0, |
78 | U16 = 1, |
79 | U32 = 2, |
80 | U64 = 3, |
81 | CompressionMask = 3 |
82 | }; |
83 | }; |
84 | |
85 | |
86 | //Find the smallest value that will represent the incoming value without loss. |
87 | //We can enlarge the current compression value, but we can't make is smaller. |
88 | //In this way, we can use this function to find the smallest compression setting |
89 | //that will work for a set of values. |
90 | inline EventStreamCompressionFlags::Enum findCompressionValue( PxU64 inValue, EventStreamCompressionFlags::Enum inCurrentCompressionValue = EventStreamCompressionFlags::U8 ) |
91 | { |
92 | //Fallthrough is intentional |
93 | switch( inCurrentCompressionValue ) |
94 | { |
95 | case EventStreamCompressionFlags::U8: |
96 | if ( inValue <= PX_MAX_U8 ) |
97 | return EventStreamCompressionFlags::U8; |
98 | case EventStreamCompressionFlags::U16: |
99 | if ( inValue <= PX_MAX_U16 ) |
100 | return EventStreamCompressionFlags::U16; |
101 | case EventStreamCompressionFlags::U32: |
102 | if ( inValue <= PX_MAX_U32 ) |
103 | return EventStreamCompressionFlags::U32; |
104 | case EventStreamCompressionFlags::U64: |
105 | default: |
106 | return EventStreamCompressionFlags::U64; |
107 | } |
108 | } |
109 | |
110 | //Find the smallest value that will represent the incoming value without loss. |
111 | //We can enlarge the current compression value, but we can't make is smaller. |
112 | //In this way, we can use this function to find the smallest compression setting |
113 | //that will work for a set of values. |
114 | inline EventStreamCompressionFlags::Enum findCompressionValue( PxU32 inValue, EventStreamCompressionFlags::Enum inCurrentCompressionValue = EventStreamCompressionFlags::U8 ) |
115 | { |
116 | //Fallthrough is intentional |
117 | switch( inCurrentCompressionValue ) |
118 | { |
119 | case EventStreamCompressionFlags::U8: |
120 | if ( inValue <= PX_MAX_U8 ) |
121 | return EventStreamCompressionFlags::U8; |
122 | case EventStreamCompressionFlags::U16: |
123 | if ( inValue <= PX_MAX_U16 ) |
124 | return EventStreamCompressionFlags::U16; |
125 | case EventStreamCompressionFlags::U32: |
126 | case EventStreamCompressionFlags::U64: |
127 | default: |
128 | return EventStreamCompressionFlags::U32; |
129 | } |
130 | } |
131 | |
132 | //Event header is 32 bytes and precedes all events. |
133 | struct |
134 | { |
135 | PxU8 ; //Used to parse the correct event out of the stream |
136 | PxU8 ; //Timestamp compression, etc. |
137 | PxU16 ; //16 bit per-event-system event id |
138 | ( PxU8 type = 0, PxU16 id = 0 ) |
139 | : mEventType( type ) |
140 | , mStreamOptions( (PxU8)-1 ) |
141 | , mEventId( id ) |
142 | { |
143 | } |
144 | |
145 | ( EventTypes::Enum type, PxU16 id ) |
146 | : mEventType( static_cast<PxU8>( type ) ) |
147 | , mStreamOptions( (PxU8)-1 ) |
148 | , mEventId( id ) |
149 | { |
150 | } |
151 | |
152 | EventStreamCompressionFlags::Enum () const |
153 | { |
154 | return static_cast<EventStreamCompressionFlags::Enum> ( mStreamOptions & EventStreamCompressionFlags::CompressionMask ); |
155 | } |
156 | |
157 | PxU64 ( PxU64 inLastTimestamp, PxU64 inCurrentTimestamp ) |
158 | { |
159 | mStreamOptions = EventStreamCompressionFlags::U64; |
160 | PxU64 retval = inCurrentTimestamp; |
161 | if ( inLastTimestamp ) |
162 | { |
163 | retval = inCurrentTimestamp - inLastTimestamp; |
164 | EventStreamCompressionFlags::Enum compressionValue = findCompressionValue( retval ); |
165 | mStreamOptions = static_cast<PxU8>( compressionValue ); |
166 | if ( compressionValue == EventStreamCompressionFlags::U64 ) |
167 | retval = inCurrentTimestamp; //just send the timestamp as is. |
168 | } |
169 | return retval; |
170 | } |
171 | |
172 | PxU64 ( PxU64 inLastTimestamp, PxU64 inCurrentTimestamp ) const |
173 | { |
174 | if ( getTimestampCompressionFlags() != EventStreamCompressionFlags::U64 ) |
175 | return inLastTimestamp + inCurrentTimestamp; |
176 | return inCurrentTimestamp; |
177 | } |
178 | |
179 | void ( PxU64 inContextId ) |
180 | { |
181 | PxU8 options = static_cast<PxU8>( findCompressionValue( inContextId ) ); |
182 | mStreamOptions = PxU8(mStreamOptions | options << 2); |
183 | } |
184 | |
185 | EventStreamCompressionFlags::Enum () const |
186 | { |
187 | return static_cast< EventStreamCompressionFlags::Enum >( ( mStreamOptions >> 2 ) & EventStreamCompressionFlags::CompressionMask ); |
188 | } |
189 | |
190 | bool ( const EventHeader& inOther ) const |
191 | { |
192 | return mEventType == inOther.mEventType |
193 | && mStreamOptions == inOther.mStreamOptions |
194 | && mEventId == inOther.mEventId; |
195 | } |
196 | |
197 | template<typename TStreamType> |
198 | inline void ( TStreamType& inStream ) |
199 | { |
200 | inStream.streamify( "EventType" , mEventType ); |
201 | inStream.streamify( "StreamOptions" , mStreamOptions ); //Timestamp compression, etc. |
202 | inStream.streamify( "EventId" , mEventId ); //16 bit per-event-system event id |
203 | } |
204 | }; |
205 | |
206 | //Declaration of type level getEventType function that maps enumeration event types to datatypes |
207 | template<typename TDataType> |
208 | inline EventTypes::Enum getEventType() { PX_ASSERT( false ); return EventTypes::Unknown; } |
209 | |
210 | //Relative profile event means this event is sharing the context and thread id |
211 | //with the event before it. |
212 | struct RelativeProfileEvent |
213 | { |
214 | PxU64 mTensOfNanoSeconds; //timestamp is in tensOfNanonseconds |
215 | void init( PxU64 inTs ) { mTensOfNanoSeconds = inTs; } |
216 | void init( const RelativeProfileEvent& inData ) { mTensOfNanoSeconds = inData.mTensOfNanoSeconds; } |
217 | bool operator==( const RelativeProfileEvent& other ) const |
218 | { |
219 | return mTensOfNanoSeconds == other.mTensOfNanoSeconds; |
220 | } |
221 | template<typename TStreamType> |
222 | void ( TStreamType& inStream, const EventHeader& ) |
223 | { |
224 | inStream.streamify( "TensOfNanoSeconds" , mTensOfNanoSeconds, inHeader.getTimestampCompressionFlags() ); |
225 | } |
226 | PxU64 getTimestamp() const { return mTensOfNanoSeconds; } |
227 | void setTimestamp( PxU64 inTs ) { mTensOfNanoSeconds = inTs; } |
228 | void ( EventHeader& , PxU64 inLastTimestamp ) |
229 | { |
230 | mTensOfNanoSeconds = inHeader.compressTimestamp( inLastTimestamp, mTensOfNanoSeconds ); |
231 | } |
232 | }; |
233 | |
234 | //Start version of the relative event. |
235 | struct RelativeStartEvent : public RelativeProfileEvent |
236 | { |
237 | void init( PxU64 inTs = 0 ) { RelativeProfileEvent::init( inTs ); } |
238 | void init( const RelativeStartEvent& inData ) { RelativeProfileEvent::init( inData ); } |
239 | template<typename THandlerType> |
240 | void handle( THandlerType* inHdlr, PxU16 eventId, PxU32 thread, PxU64 context, PxU8 inCpuId, PxU8 threadPriority ) const |
241 | { |
242 | inHdlr->onStartEvent( PxProfileEventId( eventId ), thread, context, inCpuId, threadPriority, mTensOfNanoSeconds ); |
243 | } |
244 | }; |
245 | |
246 | template<> inline EventTypes::Enum getEventType<RelativeStartEvent>() { return EventTypes::RelativeStartEvent; } |
247 | |
248 | //Stop version of relative event. |
249 | struct RelativeStopEvent : public RelativeProfileEvent |
250 | { |
251 | void init( PxU64 inTs = 0 ) { RelativeProfileEvent::init( inTs ); } |
252 | void init( const RelativeStopEvent& inData ) { RelativeProfileEvent::init( inData ); } |
253 | template<typename THandlerType> |
254 | void handle( THandlerType* inHdlr, PxU16 eventId, PxU32 thread, PxU64 context, PxU8 inCpuId, PxU8 threadPriority ) const |
255 | { |
256 | inHdlr->onStopEvent( PxProfileEventId( eventId ), thread, context, inCpuId, threadPriority, mTensOfNanoSeconds ); |
257 | } |
258 | }; |
259 | |
260 | template<> inline EventTypes::Enum getEventType<RelativeStopEvent>() { return EventTypes::RelativeStopEvent; } |
261 | |
262 | struct EventContextInformation |
263 | { |
264 | PxU64 mContextId; |
265 | PxU32 mThreadId; //Thread this event was taken from |
266 | PxU8 mThreadPriority; |
267 | PxU8 mCpuId; |
268 | |
269 | void init( PxU32 inThreadId = PX_MAX_U32 |
270 | , PxU64 inContextId = ((PxU64) -1) |
271 | , PxU8 inPriority = PX_MAX_U8 |
272 | , PxU8 inCpuId = PX_MAX_U8 ) |
273 | { |
274 | mContextId = inContextId; |
275 | mThreadId = inThreadId; |
276 | mThreadPriority = inPriority; |
277 | mCpuId = inCpuId; |
278 | } |
279 | |
280 | void init( const EventContextInformation& inData ) |
281 | { |
282 | mContextId = inData.mContextId; |
283 | mThreadId = inData.mThreadId; |
284 | mThreadPriority = inData.mThreadPriority; |
285 | mCpuId = inData.mCpuId; |
286 | } |
287 | |
288 | template<typename TStreamType> |
289 | void streamify( TStreamType& inStream, EventStreamCompressionFlags::Enum inContextIdFlags ) |
290 | { |
291 | inStream.streamify( "ThreadId" , mThreadId ); |
292 | inStream.streamify( "ContextId" , mContextId, inContextIdFlags ); |
293 | inStream.streamify( "ThreadPriority" , mThreadPriority ); |
294 | inStream.streamify( "CpuId" , mCpuId ); |
295 | } |
296 | |
297 | bool operator==( const EventContextInformation& other ) const |
298 | { |
299 | return mThreadId == other.mThreadId |
300 | && mContextId == other.mContextId |
301 | && mThreadPriority == other.mThreadPriority |
302 | && mCpuId == other.mCpuId; |
303 | } |
304 | |
305 | void setToDefault() |
306 | { |
307 | *this = EventContextInformation(); |
308 | } |
309 | }; |
310 | |
311 | //Profile event contains all the data required to tell the profile what is going |
312 | //on. |
313 | struct ProfileEvent |
314 | { |
315 | EventContextInformation mContextInformation; |
316 | RelativeProfileEvent mTimeData; //timestamp in seconds. |
317 | void init( PxU32 inThreadId, PxU64 inContextId, PxU8 inCpuId, PxU8 inPriority, PxU64 inTs ) |
318 | { |
319 | mContextInformation.init( inThreadId, inContextId, inPriority, inCpuId ); |
320 | mTimeData.init( inTs ); |
321 | } |
322 | |
323 | void init( const ProfileEvent& inData ) |
324 | { |
325 | mContextInformation.init( inData.mContextInformation ); |
326 | mTimeData.init( inData.mTimeData ); |
327 | } |
328 | |
329 | bool operator==( const ProfileEvent& other ) const |
330 | { |
331 | return mContextInformation == other.mContextInformation |
332 | && mTimeData == other.mTimeData; |
333 | } |
334 | |
335 | template<typename TStreamType> |
336 | void ( TStreamType& inStream, const EventHeader& ) |
337 | { |
338 | mContextInformation.streamify( inStream, inHeader.getContextIdCompressionFlags() ); |
339 | mTimeData.streamify( inStream, inHeader ); |
340 | } |
341 | |
342 | PxU64 getTimestamp() const { return mTimeData.getTimestamp(); } |
343 | void setTimestamp( PxU64 inTs ) { mTimeData.setTimestamp( inTs ); } |
344 | |
345 | void ( EventHeader& , PxU64 inLastTimestamp ) |
346 | { |
347 | mTimeData.setupHeader( inHeader, inLastTimestamp ); |
348 | inHeader.setContextIdCompressionFlags( mContextInformation.mContextId ); |
349 | } |
350 | }; |
351 | |
352 | //profile start event starts the profile session. |
353 | struct StartEvent : public ProfileEvent |
354 | { |
355 | void init( PxU32 inThreadId = 0, PxU64 inContextId = 0, PxU8 inCpuId = 0, PxU8 inPriority = 0, PxU64 inTensOfNanoSeconds = 0 ) |
356 | { |
357 | ProfileEvent::init( inThreadId, inContextId, inCpuId, inPriority, inTensOfNanoSeconds ); |
358 | } |
359 | void init( const StartEvent& inData ) |
360 | { |
361 | ProfileEvent::init( inData ); |
362 | } |
363 | |
364 | RelativeStartEvent getRelativeEvent() const { RelativeStartEvent theEvent; theEvent.init( mTimeData.mTensOfNanoSeconds ); return theEvent; } |
365 | EventTypes::Enum getRelativeEventType() const { return getEventType<RelativeStartEvent>(); } |
366 | }; |
367 | |
368 | template<> inline EventTypes::Enum getEventType<StartEvent>() { return EventTypes::StartEvent; } |
369 | |
370 | //Profile stop event stops the profile session. |
371 | struct StopEvent : public ProfileEvent |
372 | { |
373 | void init( PxU32 inThreadId = 0, PxU64 inContextId = 0, PxU8 inCpuId = 0, PxU8 inPriority = 0, PxU64 inTensOfNanoSeconds = 0 ) |
374 | { |
375 | ProfileEvent::init( inThreadId, inContextId, inCpuId, inPriority, inTensOfNanoSeconds ); |
376 | } |
377 | void init( const StopEvent& inData ) |
378 | { |
379 | ProfileEvent::init( inData ); |
380 | } |
381 | RelativeStopEvent getRelativeEvent() const { RelativeStopEvent theEvent; theEvent.init( mTimeData.mTensOfNanoSeconds ); return theEvent; } |
382 | EventTypes::Enum getRelativeEventType() const { return getEventType<RelativeStopEvent>(); } |
383 | }; |
384 | |
385 | template<> inline EventTypes::Enum getEventType<StopEvent>() { return EventTypes::StopEvent; } |
386 | |
387 | struct EventValue |
388 | { |
389 | PxU64 mValue; |
390 | PxU64 mContextId; |
391 | PxU32 mThreadId; |
392 | void init( PxI64 inValue = 0, PxU64 inContextId = 0, PxU32 inThreadId = 0 ) |
393 | { |
394 | mValue = static_cast<PxU64>( inValue ); |
395 | mContextId = inContextId; |
396 | mThreadId = inThreadId; |
397 | } |
398 | |
399 | void init( const EventValue& inData ) |
400 | { |
401 | mValue = inData.mValue; |
402 | mContextId = inData.mContextId; |
403 | mThreadId = inData.mThreadId; |
404 | } |
405 | |
406 | PxI64 getValue() const { return static_cast<PxI16>( mValue ); } |
407 | |
408 | void ( EventHeader& ) |
409 | { |
410 | mValue = inHeader.compressTimestamp( 0, mValue ); |
411 | inHeader.setContextIdCompressionFlags( mContextId ); |
412 | } |
413 | |
414 | template<typename TStreamType> |
415 | void ( TStreamType& inStream, const EventHeader& ) |
416 | { |
417 | inStream.streamify( "Value" , mValue, inHeader.getTimestampCompressionFlags() ); |
418 | inStream.streamify( "ContextId" , mContextId, inHeader.getContextIdCompressionFlags() ); |
419 | inStream.streamify( "ThreadId" , mThreadId ); |
420 | } |
421 | |
422 | bool operator==( const EventValue& other ) const |
423 | { |
424 | return mValue == other.mValue |
425 | && mContextId == other.mContextId |
426 | && mThreadId == other.mThreadId; |
427 | } |
428 | |
429 | template<typename THandlerType> |
430 | void handle( THandlerType* inHdlr, PxU16 eventId ) const |
431 | { |
432 | inHdlr->onEventValue( PxProfileEventId( eventId ), mThreadId, mContextId, getValue() ); |
433 | } |
434 | |
435 | }; |
436 | template<> inline EventTypes::Enum getEventType<EventValue>() { return EventTypes::EventValue; } |
437 | |
438 | struct CUDAProfileBuffer |
439 | { |
440 | PxU64 mTimestamp; |
441 | PxF32 mTimespan; |
442 | const PxU8* mCudaData; |
443 | PxU32 mBufLen; |
444 | PxU32 mVersion; |
445 | |
446 | void init( PxU64 timestamp = 0, PxF32 span = 0, const PxU8* cdata= 0, PxU32 buflen= 0, PxU32 version= 0 ) |
447 | { |
448 | mTimestamp = timestamp; |
449 | mTimespan = span; |
450 | mCudaData = cdata; |
451 | mBufLen = buflen; |
452 | mVersion = version; |
453 | } |
454 | |
455 | void init( const CUDAProfileBuffer& inData ) |
456 | { |
457 | mTimestamp = inData.mTimestamp; |
458 | mTimespan = inData.mTimespan; |
459 | mCudaData = inData.mCudaData; |
460 | mBufLen = inData.mBufLen; |
461 | mVersion = inData.mVersion; |
462 | } |
463 | |
464 | template<typename TStreamType> |
465 | void ( TStreamType& inStream, const EventHeader& ) |
466 | { |
467 | inStream.streamify( "Timestamp" , mTimestamp ); |
468 | inStream.streamify( "Timespan" , mTimespan ); |
469 | inStream.streamify( "CudaData" , mCudaData, mBufLen ); |
470 | inStream.streamify( "BufLen" , mBufLen ); |
471 | inStream.streamify( "Version" , mVersion ); |
472 | } |
473 | |
474 | bool operator==( const CUDAProfileBuffer& other ) const |
475 | { |
476 | return mTimestamp == other.mTimestamp |
477 | && mTimespan == other.mTimespan |
478 | && mBufLen == other.mBufLen |
479 | && memcmp( mCudaData, other.mCudaData, mBufLen ) == 0 |
480 | && mVersion == other.mVersion; |
481 | } |
482 | |
483 | template<typename THandlerType> |
484 | void handle( THandlerType* inHdlr ) const |
485 | { |
486 | inHdlr->onCUDAProfileBuffer( mTimestamp, mTimespan, mCudaData, mBufLen, mVersion ); |
487 | } |
488 | }; |
489 | |
490 | template<> inline EventTypes::Enum getEventType<CUDAProfileBuffer>() { return EventTypes::CUDAProfileBuffer; } |
491 | |
492 | //Provides a generic equal operation for event data objects. |
493 | template <typename TEventData> |
494 | struct EventDataEqualOperator |
495 | { |
496 | TEventData mData; |
497 | EventDataEqualOperator( const TEventData& inD ) : mData( inD ) {} |
498 | template<typename TDataType> bool operator()( const TDataType& inRhs ) const { return mData.toType( Type2Type<TDataType>() ) == inRhs; } |
499 | bool operator()() const { return false; } |
500 | }; |
501 | |
502 | /** |
503 | * Generic event container that combines and even header with the generic event data type. |
504 | * Provides unsafe and typesafe access to the event data. |
505 | */ |
506 | class Event |
507 | { |
508 | public: |
509 | typedef UNION_7(StartEvent, StopEvent, RelativeStartEvent, RelativeStopEvent, EventValue, CUDAProfileBuffer, PxU8) EventData; |
510 | |
511 | private: |
512 | EventHeader ; |
513 | EventData mData; |
514 | public: |
515 | Event() {} |
516 | |
517 | template <typename TDataType> |
518 | ( EventHeader , const TDataType& inData ) |
519 | : mHeader( inHeader ) |
520 | { |
521 | mData.init<TDataType>(inData); |
522 | } |
523 | |
524 | template<typename TDataType> |
525 | Event( PxU16 eventId, const TDataType& inData ) |
526 | : mHeader( getEventType<TDataType>(), eventId ) |
527 | { |
528 | mData.init<TDataType>(inData); |
529 | } |
530 | const EventHeader& () const { return mHeader; } |
531 | const EventData& getData() const { return mData; } |
532 | |
533 | template<typename TDataType> |
534 | const TDataType& getValue() const { PX_ASSERT( mHeader.mEventType == getEventType<TDataType>() ); return mData.toType<TDataType>(); } |
535 | |
536 | template<typename TDataType> |
537 | TDataType& getValue() { PX_ASSERT( mHeader.mEventType == getEventType<TDataType>() ); return mData.toType<TDataType>(); } |
538 | |
539 | template<typename TRetVal, typename TOperator> |
540 | inline TRetVal visit( TOperator inOp ) const; |
541 | |
542 | bool operator==( const Event& inOther ) const |
543 | { |
544 | if ( !(mHeader == inOther.mHeader ) ) return false; |
545 | if ( mHeader.mEventType ) |
546 | return inOther.visit<bool>( EventDataEqualOperator<EventData>( mData ) ); |
547 | return true; |
548 | } |
549 | }; |
550 | |
551 | //Combining the above union type with an event type means that an object can get the exact |
552 | //data out of the union. Using this function means that all callsites will be forced to |
553 | //deal with the newer datatypes and that the switch statement only exists in once place. |
554 | //Implements conversion from enum -> datatype |
555 | template<typename TRetVal, typename TOperator> |
556 | TRetVal visit( EventTypes::Enum inEventType, const Event::EventData& inData, TOperator inOperator ) |
557 | { |
558 | switch( inEventType ) |
559 | { |
560 | case EventTypes::StartEvent: return inOperator( inData.toType( Type2Type<StartEvent>() ) ); |
561 | case EventTypes::StopEvent: return inOperator( inData.toType( Type2Type<StopEvent>() ) ); |
562 | case EventTypes::RelativeStartEvent: return inOperator( inData.toType( Type2Type<RelativeStartEvent>() ) ); |
563 | case EventTypes::RelativeStopEvent: return inOperator( inData.toType( Type2Type<RelativeStopEvent>() ) ); |
564 | case EventTypes::EventValue: return inOperator( inData.toType( Type2Type<EventValue>() ) ); |
565 | case EventTypes::CUDAProfileBuffer: return inOperator( inData.toType( Type2Type<CUDAProfileBuffer>() ) ); |
566 | case EventTypes::Unknown: |
567 | default: return inOperator( static_cast<PxU8>( inEventType ) ); |
568 | } |
569 | } |
570 | |
571 | template<typename TRetVal, typename TOperator> |
572 | inline TRetVal Event::visit( TOperator inOp ) const |
573 | { |
574 | return physx::profile::visit<TRetVal>( static_cast<EventTypes::Enum>(mHeader.mEventType), mData, inOp ); |
575 | } |
576 | } } |
577 | |
578 | #endif // PX_PROFILE_EVENTS_H |
579 | |