RavEngine
Loading...
Searching...
No Matches
PxProfileEvents.h
1// Redistribution and use in source and binary forms, with or without
2// modification, are permitted provided that the following conditions
3// are met:
4// * Redistributions of source code must retain the above copyright
5// notice, this list of conditions and the following disclaimer.
6// * Redistributions in binary form must reproduce the above copyright
7// notice, this list of conditions and the following disclaimer in the
8// documentation and/or other materials provided with the distribution.
9// * Neither the name of NVIDIA CORPORATION nor the names of its
10// contributors may be used to endorse or promote products derived
11// from this software without specific prior written permission.
12//
13// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
14// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
17// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24//
25// Copyright (c) 2008-2022 NVIDIA Corporation. All rights reserved.
26
27#ifndef PX_PROFILE_EVENTS_H
28#define PX_PROFILE_EVENTS_H
29
30#include "foundation/PxMath.h"
31#include "foundation/PxAssert.h"
32
33#include "PxProfileEventId.h"
34
35
36#define PX_PROFILE_UNION_1(a) physx::profile::TUnion<a, physx::profile::Empty>
37#define PX_PROFILE_UNION_2(a,b) physx::profile::TUnion<a, PX_PROFILE_UNION_1(b)>
38#define PX_PROFILE_UNION_3(a,b,c) physx::profile::TUnion<a, PX_PROFILE_UNION_2(b,c)>
39#define PX_PROFILE_UNION_4(a,b,c,d) physx::profile::TUnion<a, PX_PROFILE_UNION_3(b,c,d)>
40#define PX_PROFILE_UNION_5(a,b,c,d,e) physx::profile::TUnion<a, PX_PROFILE_UNION_4(b,c,d,e)>
41#define PX_PROFILE_UNION_6(a,b,c,d,e,f) physx::profile::TUnion<a, PX_PROFILE_UNION_5(b,c,d,e,f)>
42#define PX_PROFILE_UNION_7(a,b,c,d,e,f,g) physx::profile::TUnion<a, PX_PROFILE_UNION_6(b,c,d,e,f,g)>
43#define PX_PROFILE_UNION_8(a,b,c,d,e,f,g,h) physx::profile::TUnion<a, PX_PROFILE_UNION_7(b,c,d,e,f,g,h)>
44#define PX_PROFILE_UNION_9(a,b,c,d,e,f,g,h,i) physx::profile::TUnion<a, PX_PROFILE_UNION_8(b,c,d,e,f,g,h,i)>
45
46namespace physx { namespace profile {
47
48 struct Empty {};
49
50 template <typename T> struct Type2Type {};
51
52 template <typename U, typename V>
53 union TUnion
54 {
55 typedef U Head;
56 typedef V Tail;
57
58 Head head;
59 Tail tail;
60
61 template <typename TDataType>
62 void init(const TDataType& inData)
63 {
64 toType(Type2Type<TDataType>()).init(inData);
65 }
66
67 template <typename TDataType>
68 PX_FORCE_INLINE TDataType& toType(const Type2Type<TDataType>& outData) { return tail.toType(outData); }
69
70 PX_FORCE_INLINE Head& toType(const Type2Type<Head>&) { return head; }
71
72 template <typename TDataType>
73 PX_FORCE_INLINE const TDataType& toType(const Type2Type<TDataType>& outData) const { return tail.toType(outData); }
74
75 PX_FORCE_INLINE const Head& toType(const Type2Type<Head>&) const { return head; }
76 };
77
79 {
80 enum Enum
81 {
82 Unknown = 0,
85 RelativeStartEvent, //reuses context,id from the earlier event.
86 RelativeStopEvent, //reuses context,id from the earlier event.
88 CUDAProfileBuffer //obsolete, placeholder to skip data from PhysX SDKs < 3.4
89 };
90 };
91
93 {
94 enum Enum
95 {
96 U8 = 0,
97 U16 = 1,
98 U32 = 2,
99 U64 = 3,
100 CompressionMask = 3
101 };
102 };
103
104#if PX_APPLE_FAMILY
105#pragma clang diagnostic push
106#pragma clang diagnostic ignored "-Wimplicit-fallthrough"
107#endif
108
109 //Find the smallest value that will represent the incoming value without loss.
110 //We can enlarge the current compression value, but we can't make is smaller.
111 //In this way, we can use this function to find the smallest compression setting
112 //that will work for a set of values.
113 inline EventStreamCompressionFlags::Enum findCompressionValue( uint64_t inValue, EventStreamCompressionFlags::Enum inCurrentCompressionValue = EventStreamCompressionFlags::U8 )
114 {
115 PX_ASSERT_WITH_MESSAGE( (inCurrentCompressionValue >= EventStreamCompressionFlags::U8) &&
116 (inCurrentCompressionValue <= EventStreamCompressionFlags::U64),
117 "Invalid inCurrentCompressionValue in profile::findCompressionValue");
118
119 //Fallthrough is intentional
120 switch( inCurrentCompressionValue )
121 {
122 case EventStreamCompressionFlags::U8:
123 if ( inValue <= UINT8_MAX )
124 return EventStreamCompressionFlags::U8;
125 case EventStreamCompressionFlags::U16:
126 if ( inValue <= UINT16_MAX )
127 return EventStreamCompressionFlags::U16;
128 case EventStreamCompressionFlags::U32:
129 if ( inValue <= UINT32_MAX )
130 return EventStreamCompressionFlags::U32;
131 case EventStreamCompressionFlags::U64:
132 break;
133 }
134 return EventStreamCompressionFlags::U64;
135 }
136
137 //Find the smallest value that will represent the incoming value without loss.
138 //We can enlarge the current compression value, but we can't make is smaller.
139 //In this way, we can use this function to find the smallest compression setting
140 //that will work for a set of values.
141 inline EventStreamCompressionFlags::Enum findCompressionValue( uint32_t inValue, EventStreamCompressionFlags::Enum inCurrentCompressionValue = EventStreamCompressionFlags::U8 )
142 {
143 PX_ASSERT_WITH_MESSAGE( (inCurrentCompressionValue >= EventStreamCompressionFlags::U8) &&
144 (inCurrentCompressionValue <= EventStreamCompressionFlags::U64),
145 "Invalid inCurrentCompressionValue in profile::findCompressionValue");
146
147 //Fallthrough is intentional
148 switch( inCurrentCompressionValue )
149 {
150 case EventStreamCompressionFlags::U8:
151 if ( inValue <= UINT8_MAX )
152 return EventStreamCompressionFlags::U8;
153 case EventStreamCompressionFlags::U16:
154 if ( inValue <= UINT16_MAX )
155 return EventStreamCompressionFlags::U16;
156 case EventStreamCompressionFlags::U32:
157 case EventStreamCompressionFlags::U64:
158 break;
159 }
160 return EventStreamCompressionFlags::U32;
161 }
162
163#if PX_APPLE_FAMILY
164#pragma clang diagnostic pop
165#endif
166
167 //Event header is 32 bytes and precedes all events.
169 {
170 uint8_t mEventType; //Used to parse the correct event out of the stream
171 uint8_t mStreamOptions; //Timestamp compression, etc.
172 uint16_t mEventId; //16 bit per-event-system event id
173 EventHeader( uint8_t type = 0, uint16_t id = 0 )
174 : mEventType( type )
175 , mStreamOptions( uint8_t(-1) )
176 , mEventId( id )
177 {
178 }
179
180 EventHeader( EventTypes::Enum type, uint16_t id )
181 : mEventType( static_cast<uint8_t>( type ) )
182 , mStreamOptions( uint8_t(-1) )
183 , mEventId( id )
184 {
185 }
186
187 EventStreamCompressionFlags::Enum getTimestampCompressionFlags() const
188 {
189 return static_cast<EventStreamCompressionFlags::Enum> ( mStreamOptions & EventStreamCompressionFlags::CompressionMask );
190 }
191
192 uint64_t compressTimestamp( uint64_t inLastTimestamp, uint64_t inCurrentTimestamp )
193 {
194 mStreamOptions = EventStreamCompressionFlags::U64;
195 uint64_t retval = inCurrentTimestamp;
196 if ( inLastTimestamp )
197 {
198 retval = inCurrentTimestamp - inLastTimestamp;
199 EventStreamCompressionFlags::Enum compressionValue = findCompressionValue( retval );
200 mStreamOptions = static_cast<uint8_t>( compressionValue );
201 if ( compressionValue == EventStreamCompressionFlags::U64 )
202 retval = inCurrentTimestamp; //just send the timestamp as is.
203 }
204 return retval;
205 }
206
207 uint64_t uncompressTimestamp( uint64_t inLastTimestamp, uint64_t inCurrentTimestamp ) const
208 {
209 if ( getTimestampCompressionFlags() != EventStreamCompressionFlags::U64 )
210 return inLastTimestamp + inCurrentTimestamp;
211 return inCurrentTimestamp;
212 }
213
214 void setContextIdCompressionFlags( uint64_t inContextId )
215 {
216 uint8_t options = static_cast<uint8_t>( findCompressionValue( inContextId ) );
217 mStreamOptions = uint8_t(mStreamOptions | options << 2);
218 }
219
220 EventStreamCompressionFlags::Enum getContextIdCompressionFlags() const
221 {
222 return static_cast< EventStreamCompressionFlags::Enum >( ( mStreamOptions >> 2 ) & EventStreamCompressionFlags::CompressionMask );
223 }
224
225 bool operator==( const EventHeader& inOther ) const
226 {
227 return mEventType == inOther.mEventType
228 && mStreamOptions == inOther.mStreamOptions
229 && mEventId == inOther.mEventId;
230 }
231
232 template<typename TStreamType>
233 inline uint32_t streamify( TStreamType& inStream )
234 {
235 uint32_t writtenSize = inStream.streamify( "EventType", mEventType );
236 writtenSize += inStream.streamify("StreamOptions", mStreamOptions); //Timestamp compression, etc.
237 writtenSize += inStream.streamify("EventId", mEventId); //16 bit per-event-system event id
238 return writtenSize;
239 }
240
241
242 };
243
244 //Declaration of type level getEventType function that maps enumeration event types to datatypes
245 template<typename TDataType>
246 inline EventTypes::Enum getEventType() { PX_ASSERT( false ); return EventTypes::Unknown; }
247
248 //Relative profile event means this event is sharing the context and thread id
249 //with the event before it.
251 {
252 uint64_t mTensOfNanoSeconds; //timestamp is in tensOfNanonseconds
253 void init( uint64_t inTs ) { mTensOfNanoSeconds = inTs; }
254 void init( const RelativeProfileEvent& inData ) { mTensOfNanoSeconds = inData.mTensOfNanoSeconds; }
255 bool operator==( const RelativeProfileEvent& other ) const
256 {
257 return mTensOfNanoSeconds == other.mTensOfNanoSeconds;
258 }
259 template<typename TStreamType>
260 uint32_t streamify( TStreamType& inStream, const EventHeader& inHeader )
261 {
262 return inStream.streamify( "TensOfNanoSeconds", mTensOfNanoSeconds, inHeader.getTimestampCompressionFlags() );
263 }
264 uint64_t getTimestamp() const { return mTensOfNanoSeconds; }
265 void setTimestamp( uint64_t inTs ) { mTensOfNanoSeconds = inTs; }
266 void setupHeader( EventHeader& inHeader, uint64_t inLastTimestamp )
267 {
268 mTensOfNanoSeconds = inHeader.compressTimestamp( inLastTimestamp, mTensOfNanoSeconds );
269 }
270
271 uint32_t getEventSize(const EventHeader& inHeader)
272 {
273 uint32_t size = 0;
274 switch (inHeader.getTimestampCompressionFlags())
275 {
276 case EventStreamCompressionFlags::U8:
277 size = 1;
278 break;
279 case EventStreamCompressionFlags::U16:
280 size = 2;
281 break;
282 case EventStreamCompressionFlags::U32:
283 size = 4;
284 break;
285 case EventStreamCompressionFlags::U64:
286 size = 8;
287 break;
288 }
289 return size;
290 }
291 };
292
293 //Start version of the relative event.
295 {
296 void init( uint64_t inTs = 0 ) { RelativeProfileEvent::init( inTs ); }
297 void init( const RelativeStartEvent& inData ) { RelativeProfileEvent::init( inData ); }
298 template<typename THandlerType>
299 void handle( THandlerType* inHdlr, uint16_t eventId, uint32_t thread, uint64_t context, uint8_t inCpuId, uint8_t threadPriority ) const
300 {
301 inHdlr->onStartEvent( PxProfileEventId( eventId ), thread, context, inCpuId, threadPriority, mTensOfNanoSeconds );
302 }
303 };
304
305 template<> inline EventTypes::Enum getEventType<RelativeStartEvent>() { return EventTypes::RelativeStartEvent; }
306
307 //Stop version of relative event.
309 {
310 void init( uint64_t inTs = 0 ) { RelativeProfileEvent::init( inTs ); }
311 void init( const RelativeStopEvent& inData ) { RelativeProfileEvent::init( inData ); }
312 template<typename THandlerType>
313 void handle( THandlerType* inHdlr, uint16_t eventId, uint32_t thread, uint64_t context, uint8_t inCpuId, uint8_t threadPriority ) const
314 {
315 inHdlr->onStopEvent( PxProfileEventId( eventId ), thread, context, inCpuId, threadPriority, mTensOfNanoSeconds );
316 }
317 };
318
319 template<> inline EventTypes::Enum getEventType<RelativeStopEvent>() { return EventTypes::RelativeStopEvent; }
320
322 {
323 uint64_t mContextId;
324 uint32_t mThreadId; //Thread this event was taken from
325 uint8_t mThreadPriority;
326 uint8_t mCpuId;
327
328 void init( uint32_t inThreadId = UINT32_MAX
329 , uint64_t inContextId = (uint64_t(-1))
330 , uint8_t inPriority = UINT8_MAX
331 , uint8_t inCpuId = UINT8_MAX )
332 {
333 mContextId = inContextId;
334 mThreadId = inThreadId;
335 mThreadPriority = inPriority;
336 mCpuId = inCpuId;
337 }
338
339 void init( const EventContextInformation& inData )
340 {
341 mContextId = inData.mContextId;
342 mThreadId = inData.mThreadId;
343 mThreadPriority = inData.mThreadPriority;
344 mCpuId = inData.mCpuId;
345 }
346
347 template<typename TStreamType>
348 uint32_t streamify( TStreamType& inStream, EventStreamCompressionFlags::Enum inContextIdFlags )
349 {
350 uint32_t writtenSize = inStream.streamify( "ThreadId", mThreadId );
351 writtenSize += inStream.streamify("ContextId", mContextId, inContextIdFlags);
352 writtenSize += inStream.streamify("ThreadPriority", mThreadPriority);
353 writtenSize += inStream.streamify("CpuId", mCpuId);
354 return writtenSize;
355 }
356
357 bool operator==( const EventContextInformation& other ) const
358 {
359 return mThreadId == other.mThreadId
360 && mContextId == other.mContextId
361 && mThreadPriority == other.mThreadPriority
362 && mCpuId == other.mCpuId;
363 }
364
365 void setToDefault()
366 {
367 *this = EventContextInformation();
368 }
369 };
370
371 //Profile event contains all the data required to tell the profile what is going
372 //on.
374 {
375 EventContextInformation mContextInformation;
376 RelativeProfileEvent mTimeData; //timestamp in seconds.
377 void init( uint32_t inThreadId, uint64_t inContextId, uint8_t inCpuId, uint8_t inPriority, uint64_t inTs )
378 {
379 mContextInformation.init( inThreadId, inContextId, inPriority, inCpuId );
380 mTimeData.init( inTs );
381 }
382
383 void init( const ProfileEvent& inData )
384 {
385 mContextInformation.init( inData.mContextInformation );
386 mTimeData.init( inData.mTimeData );
387 }
388
389 bool operator==( const ProfileEvent& other ) const
390 {
391 return mContextInformation == other.mContextInformation
392 && mTimeData == other.mTimeData;
393 }
394
395 template<typename TStreamType>
396 uint32_t streamify( TStreamType& inStream, const EventHeader& inHeader )
397 {
398 uint32_t writtenSize = mContextInformation.streamify(inStream, inHeader.getContextIdCompressionFlags());
399 writtenSize += mTimeData.streamify(inStream, inHeader);
400 return writtenSize;
401 }
402
403 uint32_t getEventSize(const EventHeader& inHeader)
404 {
405 uint32_t eventSize = 0;
406 // time is stored depending on the conpress flag mTimeData.streamify(inStream, inHeader);
407 switch (inHeader.getTimestampCompressionFlags())
408 {
409 case EventStreamCompressionFlags::U8:
410 eventSize++;
411 break;
412 case EventStreamCompressionFlags::U16:
413 eventSize += 2;
414 break;
415 case EventStreamCompressionFlags::U32:
416 eventSize += 4;
417 break;
418 case EventStreamCompressionFlags::U64:
419 eventSize += 8;
420 break;
421 }
422
423 // context information
424 // mContextInformation.streamify( inStream, inHeader.getContextIdCompressionFlags() );
425 eventSize += 6; // uint32_t mThreadId; uint8_t mThreadPriority; uint8_t mCpuId;
426 switch (inHeader.getContextIdCompressionFlags())
427 {
428 case EventStreamCompressionFlags::U8:
429 eventSize++;
430 break;
431 case EventStreamCompressionFlags::U16:
432 eventSize += 2;
433 break;
434 case EventStreamCompressionFlags::U32:
435 eventSize += 4;
436 break;
437 case EventStreamCompressionFlags::U64:
438 eventSize += 8;
439 break;
440 }
441
442 return eventSize;
443 }
444
445 uint64_t getTimestamp() const { return mTimeData.getTimestamp(); }
446 void setTimestamp( uint64_t inTs ) { mTimeData.setTimestamp( inTs ); }
447
448 void setupHeader( EventHeader& inHeader, uint64_t inLastTimestamp )
449 {
450 mTimeData.setupHeader( inHeader, inLastTimestamp );
451 inHeader.setContextIdCompressionFlags( mContextInformation.mContextId );
452 }
453 };
454
455 //profile start event starts the profile session.
456 struct StartEvent : public ProfileEvent
457 {
458 void init( uint32_t inThreadId = 0, uint64_t inContextId = 0, uint8_t inCpuId = 0, uint8_t inPriority = 0, uint64_t inTensOfNanoSeconds = 0 )
459 {
460 ProfileEvent::init( inThreadId, inContextId, inCpuId, inPriority, inTensOfNanoSeconds );
461 }
462 void init( const StartEvent& inData )
463 {
464 ProfileEvent::init( inData );
465 }
466
467 RelativeStartEvent getRelativeEvent() const { RelativeStartEvent theEvent; theEvent.init( mTimeData.mTensOfNanoSeconds ); return theEvent; }
468 EventTypes::Enum getRelativeEventType() const { return getEventType<RelativeStartEvent>(); }
469 };
470
471 template<> inline EventTypes::Enum getEventType<StartEvent>() { return EventTypes::StartEvent; }
472
473 //Profile stop event stops the profile session.
474 struct StopEvent : public ProfileEvent
475 {
476 void init( uint32_t inThreadId = 0, uint64_t inContextId = 0, uint8_t inCpuId = 0, uint8_t inPriority = 0, uint64_t inTensOfNanoSeconds = 0 )
477 {
478 ProfileEvent::init( inThreadId, inContextId, inCpuId, inPriority, inTensOfNanoSeconds );
479 }
480 void init( const StopEvent& inData )
481 {
482 ProfileEvent::init( inData );
483 }
484 RelativeStopEvent getRelativeEvent() const { RelativeStopEvent theEvent; theEvent.init( mTimeData.mTensOfNanoSeconds ); return theEvent; }
485 EventTypes::Enum getRelativeEventType() const { return getEventType<RelativeStopEvent>(); }
486 };
487
488 template<> inline EventTypes::Enum getEventType<StopEvent>() { return EventTypes::StopEvent; }
489
491 {
492 uint64_t mValue;
493 uint64_t mContextId;
494 uint32_t mThreadId;
495 void init( int64_t inValue = 0, uint64_t inContextId = 0, uint32_t inThreadId = 0 )
496 {
497 mValue = static_cast<uint64_t>( inValue );
498 mContextId = inContextId;
499 mThreadId = inThreadId;
500 }
501
502 void init( const EventValue& inData )
503 {
504 mValue = inData.mValue;
505 mContextId = inData.mContextId;
506 mThreadId = inData.mThreadId;
507 }
508
509 int64_t getValue() const { return static_cast<int16_t>( mValue ); }
510
511 void setupHeader( EventHeader& inHeader )
512 {
513 mValue = inHeader.compressTimestamp( 0, mValue );
514 inHeader.setContextIdCompressionFlags( mContextId );
515 }
516
517 template<typename TStreamType>
518 uint32_t streamify( TStreamType& inStream, const EventHeader& inHeader )
519 {
520 uint32_t writtenSize = inStream.streamify("Value", mValue, inHeader.getTimestampCompressionFlags());
521 writtenSize += inStream.streamify("ContextId", mContextId, inHeader.getContextIdCompressionFlags());
522 writtenSize += inStream.streamify("ThreadId", mThreadId);
523 return writtenSize;
524 }
525
526 uint32_t getEventSize(const EventHeader& inHeader)
527 {
528 uint32_t eventSize = 0;
529 // value
530 switch (inHeader.getTimestampCompressionFlags())
531 {
532 case EventStreamCompressionFlags::U8:
533 eventSize++;
534 break;
535 case EventStreamCompressionFlags::U16:
536 eventSize += 2;
537 break;
538 case EventStreamCompressionFlags::U32:
539 eventSize += 4;
540 break;
541 case EventStreamCompressionFlags::U64:
542 eventSize += 8;
543 break;
544 }
545
546 // context information
547 switch (inHeader.getContextIdCompressionFlags())
548 {
549 case EventStreamCompressionFlags::U8:
550 eventSize++;
551 break;
552 case EventStreamCompressionFlags::U16:
553 eventSize += 2;
554 break;
555 case EventStreamCompressionFlags::U32:
556 eventSize += 4;
557 break;
558 case EventStreamCompressionFlags::U64:
559 eventSize += 8;
560 break;
561 }
562
563 eventSize += 4; // uint32_t mThreadId;
564
565 return eventSize;
566 }
567
568 bool operator==( const EventValue& other ) const
569 {
570 return mValue == other.mValue
571 && mContextId == other.mContextId
572 && mThreadId == other.mThreadId;
573 }
574
575 template<typename THandlerType>
576 void handle( THandlerType* inHdlr, uint16_t eventId ) const
577 {
578 inHdlr->onEventValue( PxProfileEventId( eventId ), mThreadId, mContextId, getValue() );
579 }
580
581 };
582 template<> inline EventTypes::Enum getEventType<EventValue>() { return EventTypes::EventValue; }
583
584 //obsolete, placeholder to skip data from PhysX SDKs < 3.4
586 {
587 uint64_t mTimestamp;
588 float mTimespan;
589 const uint8_t* mCudaData;
590 uint32_t mBufLen;
591 uint32_t mVersion;
592
593 template<typename TStreamType>
594 uint32_t streamify( TStreamType& inStream, const EventHeader& )
595 {
596 uint32_t writtenSize = inStream.streamify("Timestamp", mTimestamp);
597 writtenSize += inStream.streamify("Timespan", mTimespan);
598 writtenSize += inStream.streamify("CudaData", mCudaData, mBufLen);
599 writtenSize += inStream.streamify("BufLen", mBufLen);
600 writtenSize += inStream.streamify("Version", mVersion);
601 return writtenSize;
602 }
603
604 bool operator==( const CUDAProfileBuffer& other ) const
605 {
606 return mTimestamp == other.mTimestamp
607 && mTimespan == other.mTimespan
608 && mBufLen == other.mBufLen
609 && memcmp( mCudaData, other.mCudaData, mBufLen ) == 0
610 && mVersion == other.mVersion;
611 }
612 };
613
614 template<> inline EventTypes::Enum getEventType<CUDAProfileBuffer>() { return EventTypes::CUDAProfileBuffer; }
615
616 //Provides a generic equal operation for event data objects.
617 template <typename TEventData>
619 {
620 TEventData mData;
621 EventDataEqualOperator( const TEventData& inD ) : mData( inD ) {}
622 template<typename TDataType> bool operator()( const TDataType& inRhs ) const { return mData.toType( Type2Type<TDataType>() ) == inRhs; }
623 bool operator()() const { return false; }
624 };
625
630 class Event
631 {
632 public:
633 typedef PX_PROFILE_UNION_7(StartEvent, StopEvent, RelativeStartEvent, RelativeStopEvent, EventValue, CUDAProfileBuffer, uint8_t) EventData;
634
635 private:
636 EventHeader mHeader;
637 EventData mData;
638 public:
639 Event() {}
640
641 template <typename TDataType>
642 Event( EventHeader inHeader, const TDataType& inData )
643 : mHeader( inHeader )
644 {
645 mData.init<TDataType>(inData);
646 }
647
648 template<typename TDataType>
649 Event( uint16_t eventId, const TDataType& inData )
650 : mHeader( getEventType<TDataType>(), eventId )
651 {
652 mData.init<TDataType>(inData);
653 }
654 const EventHeader& getHeader() const { return mHeader; }
655 const EventData& getData() const { return mData; }
656
657 template<typename TDataType>
658 const TDataType& getValue() const { PX_ASSERT( mHeader.mEventType == getEventType<TDataType>() ); return mData.toType<TDataType>(); }
659
660 template<typename TDataType>
661 TDataType& getValue() { PX_ASSERT( mHeader.mEventType == getEventType<TDataType>() ); return mData.toType<TDataType>(); }
662
663 template<typename TRetVal, typename TOperator>
664 inline TRetVal visit( TOperator inOp ) const;
665
666 bool operator==( const Event& inOther ) const
667 {
668 if ( !(mHeader == inOther.mHeader ) ) return false;
669 if ( mHeader.mEventType )
670 return inOther.visit<bool>( EventDataEqualOperator<EventData>( mData ) );
671 return true;
672 }
673 };
674
675 //Combining the above union type with an event type means that an object can get the exact
676 //data out of the union. Using this function means that all callsites will be forced to
677 //deal with the newer datatypes and that the switch statement only exists in once place.
678 //Implements conversion from enum -> datatype
679 template<typename TRetVal, typename TOperator>
680 TRetVal visit( EventTypes::Enum inEventType, const Event::EventData& inData, TOperator inOperator )
681 {
682 switch( inEventType )
683 {
684 case EventTypes::StartEvent: return inOperator( inData.toType( Type2Type<StartEvent>() ) );
685 case EventTypes::StopEvent: return inOperator( inData.toType( Type2Type<StopEvent>() ) );
686 case EventTypes::RelativeStartEvent: return inOperator( inData.toType( Type2Type<RelativeStartEvent>() ) );
687 case EventTypes::RelativeStopEvent: return inOperator( inData.toType( Type2Type<RelativeStopEvent>() ) );
688 case EventTypes::EventValue: return inOperator( inData.toType( Type2Type<EventValue>() ) );
689 //obsolete, placeholder to skip data from PhysX SDKs < 3.4
690 case EventTypes::CUDAProfileBuffer: return inOperator( inData.toType( Type2Type<CUDAProfileBuffer>() ) );
691 case EventTypes::Unknown: break;
692 }
693 uint8_t type = static_cast<uint8_t>( inEventType );
694 return inOperator( type );
695 }
696
697 template<typename TRetVal, typename TOperator>
698 inline TRetVal Event::visit( TOperator inOp ) const
699 {
700 return physx::profile::visit<TRetVal>( static_cast<EventTypes::Enum>(mHeader.mEventType), mData, inOp );
701 }
702} }
703
704#endif
705
Definition base.h:1940
Definition PxProfileEvents.h:631
#define PX_FORCE_INLINE
Definition PxPreprocessor.h:335
Sorts an array of objects in ascending order, assuming that the predicate implements the < operator:
Definition PxBoxController.h:39
Definition PxProfileEvents.h:586
Definition PxProfileEvents.h:48
Definition PxProfileEvents.h:322
Definition PxProfileEvents.h:619
Definition PxProfileEvents.h:169
Definition PxProfileEvents.h:93
Definition PxProfileEvents.h:79
Definition PxProfileEvents.h:491
Definition PxProfileEvents.h:374
A event id structure. Optionally includes information about if the event was enabled at compile time.
Definition PxProfileEventId.h:38
Definition PxProfileEvents.h:251
Definition PxProfileEvents.h:295
Definition PxProfileEvents.h:309
Definition PxProfileEvents.h:457
Definition PxProfileEvents.h:475
Definition PxProfileEvents.h:50
Definition PxProfileEvents.h:54