feat(physics): wire physx sdk into build
This commit is contained in:
705
engine/third_party/physx/source/pvd/src/PxProfileEvents.h
vendored
Normal file
705
engine/third_party/physx/source/pvd/src/PxProfileEvents.h
vendored
Normal file
@@ -0,0 +1,705 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
|
||||
#ifndef PX_PROFILE_EVENTS_H
|
||||
#define PX_PROFILE_EVENTS_H
|
||||
|
||||
#include "foundation/PxMath.h"
|
||||
#include "foundation/PxAssert.h"
|
||||
|
||||
#include "PxProfileEventId.h"
|
||||
|
||||
|
||||
#define PX_PROFILE_UNION_1(a) physx::profile::TUnion<a, physx::profile::Empty>
|
||||
#define PX_PROFILE_UNION_2(a,b) physx::profile::TUnion<a, PX_PROFILE_UNION_1(b)>
|
||||
#define PX_PROFILE_UNION_3(a,b,c) physx::profile::TUnion<a, PX_PROFILE_UNION_2(b,c)>
|
||||
#define PX_PROFILE_UNION_4(a,b,c,d) physx::profile::TUnion<a, PX_PROFILE_UNION_3(b,c,d)>
|
||||
#define PX_PROFILE_UNION_5(a,b,c,d,e) physx::profile::TUnion<a, PX_PROFILE_UNION_4(b,c,d,e)>
|
||||
#define PX_PROFILE_UNION_6(a,b,c,d,e,f) physx::profile::TUnion<a, PX_PROFILE_UNION_5(b,c,d,e,f)>
|
||||
#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)>
|
||||
#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)>
|
||||
#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)>
|
||||
|
||||
namespace physx { namespace profile {
|
||||
|
||||
struct Empty {};
|
||||
|
||||
template <typename T> struct Type2Type {};
|
||||
|
||||
template <typename U, typename V>
|
||||
union TUnion
|
||||
{
|
||||
typedef U Head;
|
||||
typedef V Tail;
|
||||
|
||||
Head head;
|
||||
Tail tail;
|
||||
|
||||
template <typename TDataType>
|
||||
void init(const TDataType& inData)
|
||||
{
|
||||
toType(Type2Type<TDataType>()).init(inData);
|
||||
}
|
||||
|
||||
template <typename TDataType>
|
||||
PX_FORCE_INLINE TDataType& toType(const Type2Type<TDataType>& outData) { return tail.toType(outData); }
|
||||
|
||||
PX_FORCE_INLINE Head& toType(const Type2Type<Head>&) { return head; }
|
||||
|
||||
template <typename TDataType>
|
||||
PX_FORCE_INLINE const TDataType& toType(const Type2Type<TDataType>& outData) const { return tail.toType(outData); }
|
||||
|
||||
PX_FORCE_INLINE const Head& toType(const Type2Type<Head>&) const { return head; }
|
||||
};
|
||||
|
||||
struct EventTypes
|
||||
{
|
||||
enum Enum
|
||||
{
|
||||
Unknown = 0,
|
||||
StartEvent,
|
||||
StopEvent,
|
||||
RelativeStartEvent, //reuses context,id from the earlier event.
|
||||
RelativeStopEvent, //reuses context,id from the earlier event.
|
||||
EventValue,
|
||||
CUDAProfileBuffer //obsolete, placeholder to skip data from PhysX SDKs < 3.4
|
||||
};
|
||||
};
|
||||
|
||||
struct EventStreamCompressionFlags
|
||||
{
|
||||
enum Enum
|
||||
{
|
||||
U8 = 0,
|
||||
U16 = 1,
|
||||
U32 = 2,
|
||||
U64 = 3,
|
||||
CompressionMask = 3
|
||||
};
|
||||
};
|
||||
|
||||
#if PX_APPLE_FAMILY
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wimplicit-fallthrough"
|
||||
#endif
|
||||
|
||||
//Find the smallest value that will represent the incoming value without loss.
|
||||
//We can enlarge the current compression value, but we can't make is smaller.
|
||||
//In this way, we can use this function to find the smallest compression setting
|
||||
//that will work for a set of values.
|
||||
inline EventStreamCompressionFlags::Enum findCompressionValue( uint64_t inValue, EventStreamCompressionFlags::Enum inCurrentCompressionValue = EventStreamCompressionFlags::U8 )
|
||||
{
|
||||
PX_ASSERT_WITH_MESSAGE( (inCurrentCompressionValue >= EventStreamCompressionFlags::U8) &&
|
||||
(inCurrentCompressionValue <= EventStreamCompressionFlags::U64),
|
||||
"Invalid inCurrentCompressionValue in profile::findCompressionValue");
|
||||
|
||||
//Fallthrough is intentional
|
||||
switch( inCurrentCompressionValue )
|
||||
{
|
||||
case EventStreamCompressionFlags::U8:
|
||||
if ( inValue <= UINT8_MAX )
|
||||
return EventStreamCompressionFlags::U8;
|
||||
case EventStreamCompressionFlags::U16:
|
||||
if ( inValue <= UINT16_MAX )
|
||||
return EventStreamCompressionFlags::U16;
|
||||
case EventStreamCompressionFlags::U32:
|
||||
if ( inValue <= UINT32_MAX )
|
||||
return EventStreamCompressionFlags::U32;
|
||||
case EventStreamCompressionFlags::U64:
|
||||
break;
|
||||
}
|
||||
return EventStreamCompressionFlags::U64;
|
||||
}
|
||||
|
||||
//Find the smallest value that will represent the incoming value without loss.
|
||||
//We can enlarge the current compression value, but we can't make is smaller.
|
||||
//In this way, we can use this function to find the smallest compression setting
|
||||
//that will work for a set of values.
|
||||
inline EventStreamCompressionFlags::Enum findCompressionValue( uint32_t inValue, EventStreamCompressionFlags::Enum inCurrentCompressionValue = EventStreamCompressionFlags::U8 )
|
||||
{
|
||||
PX_ASSERT_WITH_MESSAGE( (inCurrentCompressionValue >= EventStreamCompressionFlags::U8) &&
|
||||
(inCurrentCompressionValue <= EventStreamCompressionFlags::U64),
|
||||
"Invalid inCurrentCompressionValue in profile::findCompressionValue");
|
||||
|
||||
//Fallthrough is intentional
|
||||
switch( inCurrentCompressionValue )
|
||||
{
|
||||
case EventStreamCompressionFlags::U8:
|
||||
if ( inValue <= UINT8_MAX )
|
||||
return EventStreamCompressionFlags::U8;
|
||||
case EventStreamCompressionFlags::U16:
|
||||
if ( inValue <= UINT16_MAX )
|
||||
return EventStreamCompressionFlags::U16;
|
||||
case EventStreamCompressionFlags::U32:
|
||||
case EventStreamCompressionFlags::U64:
|
||||
break;
|
||||
}
|
||||
return EventStreamCompressionFlags::U32;
|
||||
}
|
||||
|
||||
#if PX_APPLE_FAMILY
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
//Event header is 32 bytes and precedes all events.
|
||||
struct EventHeader
|
||||
{
|
||||
uint8_t mEventType; //Used to parse the correct event out of the stream
|
||||
uint8_t mStreamOptions; //Timestamp compression, etc.
|
||||
uint16_t mEventId; //16 bit per-event-system event id
|
||||
EventHeader( uint8_t type = 0, uint16_t id = 0 )
|
||||
: mEventType( type )
|
||||
, mStreamOptions( uint8_t(-1) )
|
||||
, mEventId( id )
|
||||
{
|
||||
}
|
||||
|
||||
EventHeader( EventTypes::Enum type, uint16_t id )
|
||||
: mEventType( static_cast<uint8_t>( type ) )
|
||||
, mStreamOptions( uint8_t(-1) )
|
||||
, mEventId( id )
|
||||
{
|
||||
}
|
||||
|
||||
EventStreamCompressionFlags::Enum getTimestampCompressionFlags() const
|
||||
{
|
||||
return static_cast<EventStreamCompressionFlags::Enum> ( mStreamOptions & EventStreamCompressionFlags::CompressionMask );
|
||||
}
|
||||
|
||||
uint64_t compressTimestamp( uint64_t inLastTimestamp, uint64_t inCurrentTimestamp )
|
||||
{
|
||||
mStreamOptions = EventStreamCompressionFlags::U64;
|
||||
uint64_t retval = inCurrentTimestamp;
|
||||
if ( inLastTimestamp )
|
||||
{
|
||||
retval = inCurrentTimestamp - inLastTimestamp;
|
||||
EventStreamCompressionFlags::Enum compressionValue = findCompressionValue( retval );
|
||||
mStreamOptions = static_cast<uint8_t>( compressionValue );
|
||||
if ( compressionValue == EventStreamCompressionFlags::U64 )
|
||||
retval = inCurrentTimestamp; //just send the timestamp as is.
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
uint64_t uncompressTimestamp( uint64_t inLastTimestamp, uint64_t inCurrentTimestamp ) const
|
||||
{
|
||||
if ( getTimestampCompressionFlags() != EventStreamCompressionFlags::U64 )
|
||||
return inLastTimestamp + inCurrentTimestamp;
|
||||
return inCurrentTimestamp;
|
||||
}
|
||||
|
||||
void setContextIdCompressionFlags( uint64_t inContextId )
|
||||
{
|
||||
uint8_t options = static_cast<uint8_t>( findCompressionValue( inContextId ) );
|
||||
mStreamOptions = uint8_t(mStreamOptions | options << 2);
|
||||
}
|
||||
|
||||
EventStreamCompressionFlags::Enum getContextIdCompressionFlags() const
|
||||
{
|
||||
return static_cast< EventStreamCompressionFlags::Enum >( ( mStreamOptions >> 2 ) & EventStreamCompressionFlags::CompressionMask );
|
||||
}
|
||||
|
||||
bool operator==( const EventHeader& inOther ) const
|
||||
{
|
||||
return mEventType == inOther.mEventType
|
||||
&& mStreamOptions == inOther.mStreamOptions
|
||||
&& mEventId == inOther.mEventId;
|
||||
}
|
||||
|
||||
template<typename TStreamType>
|
||||
inline uint32_t streamify( TStreamType& inStream )
|
||||
{
|
||||
uint32_t writtenSize = inStream.streamify( "EventType", mEventType );
|
||||
writtenSize += inStream.streamify("StreamOptions", mStreamOptions); //Timestamp compression, etc.
|
||||
writtenSize += inStream.streamify("EventId", mEventId); //16 bit per-event-system event id
|
||||
return writtenSize;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
//Declaration of type level getEventType function that maps enumeration event types to datatypes
|
||||
template<typename TDataType>
|
||||
inline EventTypes::Enum getEventType() { PX_ASSERT( false ); return EventTypes::Unknown; }
|
||||
|
||||
//Relative profile event means this event is sharing the context and thread id
|
||||
//with the event before it.
|
||||
struct RelativeProfileEvent
|
||||
{
|
||||
uint64_t mTensOfNanoSeconds; //timestamp is in tensOfNanonseconds
|
||||
void init( uint64_t inTs ) { mTensOfNanoSeconds = inTs; }
|
||||
void init( const RelativeProfileEvent& inData ) { mTensOfNanoSeconds = inData.mTensOfNanoSeconds; }
|
||||
bool operator==( const RelativeProfileEvent& other ) const
|
||||
{
|
||||
return mTensOfNanoSeconds == other.mTensOfNanoSeconds;
|
||||
}
|
||||
template<typename TStreamType>
|
||||
uint32_t streamify( TStreamType& inStream, const EventHeader& inHeader )
|
||||
{
|
||||
return inStream.streamify( "TensOfNanoSeconds", mTensOfNanoSeconds, inHeader.getTimestampCompressionFlags() );
|
||||
}
|
||||
uint64_t getTimestamp() const { return mTensOfNanoSeconds; }
|
||||
void setTimestamp( uint64_t inTs ) { mTensOfNanoSeconds = inTs; }
|
||||
void setupHeader( EventHeader& inHeader, uint64_t inLastTimestamp )
|
||||
{
|
||||
mTensOfNanoSeconds = inHeader.compressTimestamp( inLastTimestamp, mTensOfNanoSeconds );
|
||||
}
|
||||
|
||||
uint32_t getEventSize(const EventHeader& inHeader)
|
||||
{
|
||||
uint32_t size = 0;
|
||||
switch (inHeader.getTimestampCompressionFlags())
|
||||
{
|
||||
case EventStreamCompressionFlags::U8:
|
||||
size = 1;
|
||||
break;
|
||||
case EventStreamCompressionFlags::U16:
|
||||
size = 2;
|
||||
break;
|
||||
case EventStreamCompressionFlags::U32:
|
||||
size = 4;
|
||||
break;
|
||||
case EventStreamCompressionFlags::U64:
|
||||
size = 8;
|
||||
break;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
};
|
||||
|
||||
//Start version of the relative event.
|
||||
struct RelativeStartEvent : public RelativeProfileEvent
|
||||
{
|
||||
void init( uint64_t inTs = 0 ) { RelativeProfileEvent::init( inTs ); }
|
||||
void init( const RelativeStartEvent& inData ) { RelativeProfileEvent::init( inData ); }
|
||||
template<typename THandlerType>
|
||||
void handle( THandlerType* inHdlr, uint16_t eventId, uint32_t thread, uint64_t context, uint8_t inCpuId, uint8_t threadPriority ) const
|
||||
{
|
||||
inHdlr->onStartEvent( PxProfileEventId( eventId ), thread, context, inCpuId, threadPriority, mTensOfNanoSeconds );
|
||||
}
|
||||
};
|
||||
|
||||
template<> inline EventTypes::Enum getEventType<RelativeStartEvent>() { return EventTypes::RelativeStartEvent; }
|
||||
|
||||
//Stop version of relative event.
|
||||
struct RelativeStopEvent : public RelativeProfileEvent
|
||||
{
|
||||
void init( uint64_t inTs = 0 ) { RelativeProfileEvent::init( inTs ); }
|
||||
void init( const RelativeStopEvent& inData ) { RelativeProfileEvent::init( inData ); }
|
||||
template<typename THandlerType>
|
||||
void handle( THandlerType* inHdlr, uint16_t eventId, uint32_t thread, uint64_t context, uint8_t inCpuId, uint8_t threadPriority ) const
|
||||
{
|
||||
inHdlr->onStopEvent( PxProfileEventId( eventId ), thread, context, inCpuId, threadPriority, mTensOfNanoSeconds );
|
||||
}
|
||||
};
|
||||
|
||||
template<> inline EventTypes::Enum getEventType<RelativeStopEvent>() { return EventTypes::RelativeStopEvent; }
|
||||
|
||||
struct EventContextInformation
|
||||
{
|
||||
uint64_t mContextId;
|
||||
uint32_t mThreadId; //Thread this event was taken from
|
||||
uint8_t mThreadPriority;
|
||||
uint8_t mCpuId;
|
||||
|
||||
void init( uint32_t inThreadId = UINT32_MAX
|
||||
, uint64_t inContextId = (uint64_t(-1))
|
||||
, uint8_t inPriority = UINT8_MAX
|
||||
, uint8_t inCpuId = UINT8_MAX )
|
||||
{
|
||||
mContextId = inContextId;
|
||||
mThreadId = inThreadId;
|
||||
mThreadPriority = inPriority;
|
||||
mCpuId = inCpuId;
|
||||
}
|
||||
|
||||
void init( const EventContextInformation& inData )
|
||||
{
|
||||
mContextId = inData.mContextId;
|
||||
mThreadId = inData.mThreadId;
|
||||
mThreadPriority = inData.mThreadPriority;
|
||||
mCpuId = inData.mCpuId;
|
||||
}
|
||||
|
||||
template<typename TStreamType>
|
||||
uint32_t streamify( TStreamType& inStream, EventStreamCompressionFlags::Enum inContextIdFlags )
|
||||
{
|
||||
uint32_t writtenSize = inStream.streamify( "ThreadId", mThreadId );
|
||||
writtenSize += inStream.streamify("ContextId", mContextId, inContextIdFlags);
|
||||
writtenSize += inStream.streamify("ThreadPriority", mThreadPriority);
|
||||
writtenSize += inStream.streamify("CpuId", mCpuId);
|
||||
return writtenSize;
|
||||
}
|
||||
|
||||
bool operator==( const EventContextInformation& other ) const
|
||||
{
|
||||
return mThreadId == other.mThreadId
|
||||
&& mContextId == other.mContextId
|
||||
&& mThreadPriority == other.mThreadPriority
|
||||
&& mCpuId == other.mCpuId;
|
||||
}
|
||||
|
||||
void setToDefault()
|
||||
{
|
||||
*this = EventContextInformation();
|
||||
}
|
||||
};
|
||||
|
||||
//Profile event contains all the data required to tell the profile what is going
|
||||
//on.
|
||||
struct ProfileEvent
|
||||
{
|
||||
EventContextInformation mContextInformation;
|
||||
RelativeProfileEvent mTimeData; //timestamp in seconds.
|
||||
void init( uint32_t inThreadId, uint64_t inContextId, uint8_t inCpuId, uint8_t inPriority, uint64_t inTs )
|
||||
{
|
||||
mContextInformation.init( inThreadId, inContextId, inPriority, inCpuId );
|
||||
mTimeData.init( inTs );
|
||||
}
|
||||
|
||||
void init( const ProfileEvent& inData )
|
||||
{
|
||||
mContextInformation.init( inData.mContextInformation );
|
||||
mTimeData.init( inData.mTimeData );
|
||||
}
|
||||
|
||||
bool operator==( const ProfileEvent& other ) const
|
||||
{
|
||||
return mContextInformation == other.mContextInformation
|
||||
&& mTimeData == other.mTimeData;
|
||||
}
|
||||
|
||||
template<typename TStreamType>
|
||||
uint32_t streamify( TStreamType& inStream, const EventHeader& inHeader )
|
||||
{
|
||||
uint32_t writtenSize = mContextInformation.streamify(inStream, inHeader.getContextIdCompressionFlags());
|
||||
writtenSize += mTimeData.streamify(inStream, inHeader);
|
||||
return writtenSize;
|
||||
}
|
||||
|
||||
uint32_t getEventSize(const EventHeader& inHeader)
|
||||
{
|
||||
uint32_t eventSize = 0;
|
||||
// time is stored depending on the conpress flag mTimeData.streamify(inStream, inHeader);
|
||||
switch (inHeader.getTimestampCompressionFlags())
|
||||
{
|
||||
case EventStreamCompressionFlags::U8:
|
||||
eventSize++;
|
||||
break;
|
||||
case EventStreamCompressionFlags::U16:
|
||||
eventSize += 2;
|
||||
break;
|
||||
case EventStreamCompressionFlags::U32:
|
||||
eventSize += 4;
|
||||
break;
|
||||
case EventStreamCompressionFlags::U64:
|
||||
eventSize += 8;
|
||||
break;
|
||||
}
|
||||
|
||||
// context information
|
||||
// mContextInformation.streamify( inStream, inHeader.getContextIdCompressionFlags() );
|
||||
eventSize += 6; // uint32_t mThreadId; uint8_t mThreadPriority; uint8_t mCpuId;
|
||||
switch (inHeader.getContextIdCompressionFlags())
|
||||
{
|
||||
case EventStreamCompressionFlags::U8:
|
||||
eventSize++;
|
||||
break;
|
||||
case EventStreamCompressionFlags::U16:
|
||||
eventSize += 2;
|
||||
break;
|
||||
case EventStreamCompressionFlags::U32:
|
||||
eventSize += 4;
|
||||
break;
|
||||
case EventStreamCompressionFlags::U64:
|
||||
eventSize += 8;
|
||||
break;
|
||||
}
|
||||
|
||||
return eventSize;
|
||||
}
|
||||
|
||||
uint64_t getTimestamp() const { return mTimeData.getTimestamp(); }
|
||||
void setTimestamp( uint64_t inTs ) { mTimeData.setTimestamp( inTs ); }
|
||||
|
||||
void setupHeader( EventHeader& inHeader, uint64_t inLastTimestamp )
|
||||
{
|
||||
mTimeData.setupHeader( inHeader, inLastTimestamp );
|
||||
inHeader.setContextIdCompressionFlags( mContextInformation.mContextId );
|
||||
}
|
||||
};
|
||||
|
||||
//profile start event starts the profile session.
|
||||
struct StartEvent : public ProfileEvent
|
||||
{
|
||||
void init( uint32_t inThreadId = 0, uint64_t inContextId = 0, uint8_t inCpuId = 0, uint8_t inPriority = 0, uint64_t inTensOfNanoSeconds = 0 )
|
||||
{
|
||||
ProfileEvent::init( inThreadId, inContextId, inCpuId, inPriority, inTensOfNanoSeconds );
|
||||
}
|
||||
void init( const StartEvent& inData )
|
||||
{
|
||||
ProfileEvent::init( inData );
|
||||
}
|
||||
|
||||
RelativeStartEvent getRelativeEvent() const { RelativeStartEvent theEvent; theEvent.init( mTimeData.mTensOfNanoSeconds ); return theEvent; }
|
||||
EventTypes::Enum getRelativeEventType() const { return getEventType<RelativeStartEvent>(); }
|
||||
};
|
||||
|
||||
template<> inline EventTypes::Enum getEventType<StartEvent>() { return EventTypes::StartEvent; }
|
||||
|
||||
//Profile stop event stops the profile session.
|
||||
struct StopEvent : public ProfileEvent
|
||||
{
|
||||
void init( uint32_t inThreadId = 0, uint64_t inContextId = 0, uint8_t inCpuId = 0, uint8_t inPriority = 0, uint64_t inTensOfNanoSeconds = 0 )
|
||||
{
|
||||
ProfileEvent::init( inThreadId, inContextId, inCpuId, inPriority, inTensOfNanoSeconds );
|
||||
}
|
||||
void init( const StopEvent& inData )
|
||||
{
|
||||
ProfileEvent::init( inData );
|
||||
}
|
||||
RelativeStopEvent getRelativeEvent() const { RelativeStopEvent theEvent; theEvent.init( mTimeData.mTensOfNanoSeconds ); return theEvent; }
|
||||
EventTypes::Enum getRelativeEventType() const { return getEventType<RelativeStopEvent>(); }
|
||||
};
|
||||
|
||||
template<> inline EventTypes::Enum getEventType<StopEvent>() { return EventTypes::StopEvent; }
|
||||
|
||||
struct EventValue
|
||||
{
|
||||
uint64_t mValue;
|
||||
uint64_t mContextId;
|
||||
uint32_t mThreadId;
|
||||
void init( int64_t inValue = 0, uint64_t inContextId = 0, uint32_t inThreadId = 0 )
|
||||
{
|
||||
mValue = static_cast<uint64_t>( inValue );
|
||||
mContextId = inContextId;
|
||||
mThreadId = inThreadId;
|
||||
}
|
||||
|
||||
void init( const EventValue& inData )
|
||||
{
|
||||
mValue = inData.mValue;
|
||||
mContextId = inData.mContextId;
|
||||
mThreadId = inData.mThreadId;
|
||||
}
|
||||
|
||||
int64_t getValue() const { return static_cast<int16_t>( mValue ); }
|
||||
|
||||
void setupHeader( EventHeader& inHeader )
|
||||
{
|
||||
mValue = inHeader.compressTimestamp( 0, mValue );
|
||||
inHeader.setContextIdCompressionFlags( mContextId );
|
||||
}
|
||||
|
||||
template<typename TStreamType>
|
||||
uint32_t streamify( TStreamType& inStream, const EventHeader& inHeader )
|
||||
{
|
||||
uint32_t writtenSize = inStream.streamify("Value", mValue, inHeader.getTimestampCompressionFlags());
|
||||
writtenSize += inStream.streamify("ContextId", mContextId, inHeader.getContextIdCompressionFlags());
|
||||
writtenSize += inStream.streamify("ThreadId", mThreadId);
|
||||
return writtenSize;
|
||||
}
|
||||
|
||||
uint32_t getEventSize(const EventHeader& inHeader)
|
||||
{
|
||||
uint32_t eventSize = 0;
|
||||
// value
|
||||
switch (inHeader.getTimestampCompressionFlags())
|
||||
{
|
||||
case EventStreamCompressionFlags::U8:
|
||||
eventSize++;
|
||||
break;
|
||||
case EventStreamCompressionFlags::U16:
|
||||
eventSize += 2;
|
||||
break;
|
||||
case EventStreamCompressionFlags::U32:
|
||||
eventSize += 4;
|
||||
break;
|
||||
case EventStreamCompressionFlags::U64:
|
||||
eventSize += 8;
|
||||
break;
|
||||
}
|
||||
|
||||
// context information
|
||||
switch (inHeader.getContextIdCompressionFlags())
|
||||
{
|
||||
case EventStreamCompressionFlags::U8:
|
||||
eventSize++;
|
||||
break;
|
||||
case EventStreamCompressionFlags::U16:
|
||||
eventSize += 2;
|
||||
break;
|
||||
case EventStreamCompressionFlags::U32:
|
||||
eventSize += 4;
|
||||
break;
|
||||
case EventStreamCompressionFlags::U64:
|
||||
eventSize += 8;
|
||||
break;
|
||||
}
|
||||
|
||||
eventSize += 4; // uint32_t mThreadId;
|
||||
|
||||
return eventSize;
|
||||
}
|
||||
|
||||
bool operator==( const EventValue& other ) const
|
||||
{
|
||||
return mValue == other.mValue
|
||||
&& mContextId == other.mContextId
|
||||
&& mThreadId == other.mThreadId;
|
||||
}
|
||||
|
||||
template<typename THandlerType>
|
||||
void handle( THandlerType* inHdlr, uint16_t eventId ) const
|
||||
{
|
||||
inHdlr->onEventValue( PxProfileEventId( eventId ), mThreadId, mContextId, getValue() );
|
||||
}
|
||||
|
||||
};
|
||||
template<> inline EventTypes::Enum getEventType<EventValue>() { return EventTypes::EventValue; }
|
||||
|
||||
//obsolete, placeholder to skip data from PhysX SDKs < 3.4
|
||||
struct CUDAProfileBuffer
|
||||
{
|
||||
uint64_t mTimestamp;
|
||||
float mTimespan;
|
||||
const uint8_t* mCudaData;
|
||||
uint32_t mBufLen;
|
||||
uint32_t mVersion;
|
||||
|
||||
template<typename TStreamType>
|
||||
uint32_t streamify( TStreamType& inStream, const EventHeader& )
|
||||
{
|
||||
uint32_t writtenSize = inStream.streamify("Timestamp", mTimestamp);
|
||||
writtenSize += inStream.streamify("Timespan", mTimespan);
|
||||
writtenSize += inStream.streamify("CudaData", mCudaData, mBufLen);
|
||||
writtenSize += inStream.streamify("BufLen", mBufLen);
|
||||
writtenSize += inStream.streamify("Version", mVersion);
|
||||
return writtenSize;
|
||||
}
|
||||
|
||||
bool operator==( const CUDAProfileBuffer& other ) const
|
||||
{
|
||||
return mTimestamp == other.mTimestamp
|
||||
&& mTimespan == other.mTimespan
|
||||
&& mBufLen == other.mBufLen
|
||||
&& memcmp( mCudaData, other.mCudaData, mBufLen ) == 0
|
||||
&& mVersion == other.mVersion;
|
||||
}
|
||||
};
|
||||
|
||||
template<> inline EventTypes::Enum getEventType<CUDAProfileBuffer>() { return EventTypes::CUDAProfileBuffer; }
|
||||
|
||||
//Provides a generic equal operation for event data objects.
|
||||
template <typename TEventData>
|
||||
struct EventDataEqualOperator
|
||||
{
|
||||
TEventData mData;
|
||||
EventDataEqualOperator( const TEventData& inD ) : mData( inD ) {}
|
||||
template<typename TDataType> bool operator()( const TDataType& inRhs ) const { return mData.toType( Type2Type<TDataType>() ) == inRhs; }
|
||||
bool operator()() const { return false; }
|
||||
};
|
||||
|
||||
/**
|
||||
* Generic event container that combines and even header with the generic event data type.
|
||||
* Provides unsafe and typesafe access to the event data.
|
||||
*/
|
||||
class Event
|
||||
{
|
||||
public:
|
||||
typedef PX_PROFILE_UNION_7(StartEvent, StopEvent, RelativeStartEvent, RelativeStopEvent, EventValue, CUDAProfileBuffer, uint8_t) EventData;
|
||||
|
||||
private:
|
||||
EventHeader mHeader;
|
||||
EventData mData;
|
||||
public:
|
||||
Event() {}
|
||||
|
||||
template <typename TDataType>
|
||||
Event( EventHeader inHeader, const TDataType& inData )
|
||||
: mHeader( inHeader )
|
||||
{
|
||||
mData.init<TDataType>(inData);
|
||||
}
|
||||
|
||||
template<typename TDataType>
|
||||
Event( uint16_t eventId, const TDataType& inData )
|
||||
: mHeader( getEventType<TDataType>(), eventId )
|
||||
{
|
||||
mData.init<TDataType>(inData);
|
||||
}
|
||||
const EventHeader& getHeader() const { return mHeader; }
|
||||
const EventData& getData() const { return mData; }
|
||||
|
||||
template<typename TDataType>
|
||||
const TDataType& getValue() const { PX_ASSERT( mHeader.mEventType == getEventType<TDataType>() ); return mData.toType<TDataType>(); }
|
||||
|
||||
template<typename TDataType>
|
||||
TDataType& getValue() { PX_ASSERT( mHeader.mEventType == getEventType<TDataType>() ); return mData.toType<TDataType>(); }
|
||||
|
||||
template<typename TRetVal, typename TOperator>
|
||||
inline TRetVal visit( TOperator inOp ) const;
|
||||
|
||||
bool operator==( const Event& inOther ) const
|
||||
{
|
||||
if ( !(mHeader == inOther.mHeader ) ) return false;
|
||||
if ( mHeader.mEventType )
|
||||
return inOther.visit<bool>( EventDataEqualOperator<EventData>( mData ) );
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
//Combining the above union type with an event type means that an object can get the exact
|
||||
//data out of the union. Using this function means that all callsites will be forced to
|
||||
//deal with the newer datatypes and that the switch statement only exists in once place.
|
||||
//Implements conversion from enum -> datatype
|
||||
template<typename TRetVal, typename TOperator>
|
||||
TRetVal visit( EventTypes::Enum inEventType, const Event::EventData& inData, TOperator inOperator )
|
||||
{
|
||||
switch( inEventType )
|
||||
{
|
||||
case EventTypes::StartEvent: return inOperator( inData.toType( Type2Type<StartEvent>() ) );
|
||||
case EventTypes::StopEvent: return inOperator( inData.toType( Type2Type<StopEvent>() ) );
|
||||
case EventTypes::RelativeStartEvent: return inOperator( inData.toType( Type2Type<RelativeStartEvent>() ) );
|
||||
case EventTypes::RelativeStopEvent: return inOperator( inData.toType( Type2Type<RelativeStopEvent>() ) );
|
||||
case EventTypes::EventValue: return inOperator( inData.toType( Type2Type<EventValue>() ) );
|
||||
//obsolete, placeholder to skip data from PhysX SDKs < 3.4
|
||||
case EventTypes::CUDAProfileBuffer: return inOperator( inData.toType( Type2Type<CUDAProfileBuffer>() ) );
|
||||
case EventTypes::Unknown: break;
|
||||
}
|
||||
uint8_t type = static_cast<uint8_t>( inEventType );
|
||||
return inOperator( type );
|
||||
}
|
||||
|
||||
template<typename TRetVal, typename TOperator>
|
||||
inline TRetVal Event::visit( TOperator inOp ) const
|
||||
{
|
||||
return physx::profile::visit<TRetVal>( static_cast<EventTypes::Enum>(mHeader.mEventType), mData, inOp );
|
||||
}
|
||||
} }
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user