Projekt_Grafika/dependencies/physx-4.1/source/pvd/src/PxProfileMemoryEvents.h

412 lines
13 KiB
C++

//
// 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-2019 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef PXPVDSDK_PXPROFILEMEMORYEVENTS_H
#define PXPVDSDK_PXPROFILEMEMORYEVENTS_H
#include "PxProfileEvents.h"
//Memory events define their own event stream
namespace physx { namespace profile {
struct MemoryEventTypes
{
enum Enum
{
Unknown = 0,
StringTableEvent, //introduce a new mapping of const char* -> integer
AllocationEvent,
DeallocationEvent,
FullAllocationEvent
};
};
template<unsigned numBits, typename TDataType>
inline unsigned char convertToNBits( TDataType inType )
{
uint8_t conversion = static_cast<uint8_t>( inType );
PX_ASSERT( conversion < (1 << numBits) );
return conversion;
}
template<typename TDataType>
inline unsigned char convertToTwoBits( TDataType inType )
{
return convertToNBits<2>( inType );
}
template<typename TDataType>
inline unsigned char convertToFourBits( TDataType inType )
{
return convertToNBits<4>( inType );
}
inline EventStreamCompressionFlags::Enum fromNumber( uint8_t inNum ) { return static_cast<EventStreamCompressionFlags::Enum>( inNum ); }
template<unsigned lhs, unsigned rhs>
inline void compileCheckSize()
{
PX_COMPILE_TIME_ASSERT( lhs <= rhs );
}
//Used for predictable bit fields.
template<typename TDataType
, uint8_t TNumBits
, uint8_t TOffset
, typename TInputType>
struct BitMaskSetter
{
//Create a mask that masks out the orginal value shift into place
static TDataType createOffsetMask() { return TDataType(createMask() << TOffset); }
//Create a mask of TNumBits number of tis
static TDataType createMask() { return static_cast<TDataType>((1 << TNumBits) - 1); }
void setValue( TDataType& inCurrent, TInputType inData )
{
PX_ASSERT( inData < ( 1 << TNumBits ) );
//Create a mask to remove the current value.
TDataType theMask = TDataType(~(createOffsetMask()));
//Clear out current value.
inCurrent = TDataType(inCurrent & theMask);
//Create the new value.
TDataType theAddition = static_cast<TDataType>( inData << TOffset );
//or it into the existing value.
inCurrent = TDataType(inCurrent | theAddition);
}
TInputType getValue( TDataType inCurrent )
{
return static_cast<TInputType>( ( inCurrent >> TOffset ) & createMask() );
}
};
struct MemoryEventHeader
{
uint16_t mValue;
typedef BitMaskSetter<uint16_t, 4, 0, uint8_t> TTypeBitmask;
typedef BitMaskSetter<uint16_t, 2, 4, uint8_t> TAddrCompressBitmask;
typedef BitMaskSetter<uint16_t, 2, 6, uint8_t> TTypeCompressBitmask;
typedef BitMaskSetter<uint16_t, 2, 8, uint8_t> TFnameCompressBitmask;
typedef BitMaskSetter<uint16_t, 2, 10, uint8_t> TSizeCompressBitmask;
typedef BitMaskSetter<uint16_t, 2, 12, uint8_t> TLineCompressBitmask;
//That leaves size as the only thing not compressed usually.
MemoryEventHeader( MemoryEventTypes::Enum inType = MemoryEventTypes::Unknown )
: mValue( 0 )
{
uint8_t defaultCompression( convertToTwoBits( EventStreamCompressionFlags::U64 ) );
TTypeBitmask().setValue( mValue, convertToFourBits( inType ) );
TAddrCompressBitmask().setValue( mValue, defaultCompression );
TTypeCompressBitmask().setValue( mValue, defaultCompression );
TFnameCompressBitmask().setValue( mValue, defaultCompression );
TSizeCompressBitmask().setValue( mValue, defaultCompression );
TLineCompressBitmask().setValue( mValue, defaultCompression );
}
MemoryEventTypes::Enum getType() const { return static_cast<MemoryEventTypes::Enum>( TTypeBitmask().getValue( mValue ) ); }
#define DEFINE_MEMORY_HEADER_COMPRESSION_ACCESSOR( name ) \
void set##name( EventStreamCompressionFlags::Enum inEnum ) { T##name##Bitmask().setValue( mValue, convertToTwoBits( inEnum ) ); } \
EventStreamCompressionFlags::Enum get##name() const { return fromNumber( T##name##Bitmask().getValue( mValue ) ); }
DEFINE_MEMORY_HEADER_COMPRESSION_ACCESSOR( AddrCompress )
DEFINE_MEMORY_HEADER_COMPRESSION_ACCESSOR( TypeCompress )
DEFINE_MEMORY_HEADER_COMPRESSION_ACCESSOR( FnameCompress )
DEFINE_MEMORY_HEADER_COMPRESSION_ACCESSOR( SizeCompress )
DEFINE_MEMORY_HEADER_COMPRESSION_ACCESSOR( LineCompress )
#undef DEFINE_MEMORY_HEADER_COMPRESSION_ACCESSOR
bool operator==( const MemoryEventHeader& inOther ) const
{
return mValue == inOther.mValue;
}
template<typename TStreamType>
void streamify( TStreamType& inStream )
{
inStream.streamify( "Header", mValue );
}
};
//Declaration of type level getMemoryEventType function that maps enumeration event types to datatypes
template<typename TDataType>
inline MemoryEventTypes::Enum getMemoryEventType() { PX_ASSERT( false ); return MemoryEventTypes::Unknown; }
inline bool safeStrEq( const char* lhs, const char* rhs )
{
if ( lhs == rhs )
return true;
//If they aren't equal, and one of them is null,
//then they can't be equal.
//This is assuming that the null char* is not equal to
//the empty "" char*.
if ( !lhs || !rhs )
return false;
return ::strcmp( lhs, rhs ) == 0;
}
struct StringTableEvent
{
const char* mString;
uint32_t mHandle;
void init( const char* inStr = "", uint32_t inHdl = 0 )
{
mString = inStr;
mHandle = inHdl;
}
void init( const StringTableEvent& inData )
{
mString = inData.mString;
mHandle = inData.mHandle;
}
bool operator==( const StringTableEvent& inOther ) const
{
return mHandle == inOther.mHandle
&& safeStrEq( mString, inOther.mString );
}
void setup( MemoryEventHeader& ) const {}
template<typename TStreamType>
void streamify( TStreamType& inStream, const MemoryEventHeader& )
{
inStream.streamify( "String", mString );
inStream.streamify( "Handle", mHandle );
}
};
template<> inline MemoryEventTypes::Enum getMemoryEventType<StringTableEvent>() { return MemoryEventTypes::StringTableEvent; }
struct MemoryEventData
{
uint64_t mAddress;
void init( uint64_t addr )
{
mAddress = addr;
}
void init( const MemoryEventData& inData)
{
mAddress = inData.mAddress;
}
bool operator==( const MemoryEventData& inOther ) const
{
return mAddress == inOther.mAddress;
}
void setup( MemoryEventHeader& inHeader ) const
{
inHeader.setAddrCompress( findCompressionValue( mAddress ) );
}
template<typename TStreamType>
void streamify( TStreamType& inStream, const MemoryEventHeader& inHeader )
{
inStream.streamify( "Address", mAddress, inHeader.getAddrCompress() );
}
};
struct AllocationEvent : public MemoryEventData
{
uint32_t mSize;
uint32_t mType;
uint32_t mFile;
uint32_t mLine;
void init( size_t size = 0, uint32_t type = 0, uint32_t file = 0, uint32_t line = 0, uint64_t addr = 0 )
{
MemoryEventData::init( addr );
mSize = static_cast<uint32_t>( size );
mType = type;
mFile = file;
mLine = line;
}
void init( const AllocationEvent& inData )
{
MemoryEventData::init( inData );
mSize = inData.mSize;
mType = inData.mType;
mFile = inData.mFile;
mLine = inData.mLine;
}
bool operator==( const AllocationEvent& inOther ) const
{
return MemoryEventData::operator==( inOther )
&& mSize == inOther.mSize
&& mType == inOther.mType
&& mFile == inOther.mFile
&& mLine == inOther.mLine;
}
void setup( MemoryEventHeader& inHeader ) const
{
inHeader.setTypeCompress( findCompressionValue( mType ) );
inHeader.setFnameCompress( findCompressionValue( mFile ) );
inHeader.setSizeCompress( findCompressionValue( mSize ) );
inHeader.setLineCompress( findCompressionValue( mLine ) );
MemoryEventData::setup( inHeader );
}
template<typename TStreamType>
void streamify( TStreamType& inStream, const MemoryEventHeader& inHeader )
{
inStream.streamify( "Size", mSize, inHeader.getSizeCompress() );
inStream.streamify( "Type", mType, inHeader.getTypeCompress() );
inStream.streamify( "File", mFile, inHeader.getFnameCompress() );
inStream.streamify( "Line", mLine, inHeader.getLineCompress() );
MemoryEventData::streamify( inStream, inHeader );
}
};
template<> inline MemoryEventTypes::Enum getMemoryEventType<AllocationEvent>() { return MemoryEventTypes::AllocationEvent; }
struct FullAllocationEvent : public MemoryEventData
{
size_t mSize;
const char* mType;
const char* mFile;
uint32_t mLine;
void init( size_t size, const char* type, const char* file, uint32_t line, uint64_t addr )
{
MemoryEventData::init( addr );
mSize = size;
mType = type;
mFile = file;
mLine = line;
}
void init( const FullAllocationEvent& inData )
{
MemoryEventData::init( inData );
mSize = inData.mSize;
mType = inData.mType;
mFile = inData.mFile;
mLine = inData.mLine;
}
bool operator==( const FullAllocationEvent& inOther ) const
{
return MemoryEventData::operator==( inOther )
&& mSize == inOther.mSize
&& safeStrEq( mType, inOther.mType )
&& safeStrEq( mFile, inOther.mFile )
&& mLine == inOther.mLine;
}
void setup( MemoryEventHeader& ) const {}
};
template<> inline MemoryEventTypes::Enum getMemoryEventType<FullAllocationEvent>() { return MemoryEventTypes::FullAllocationEvent; }
struct DeallocationEvent : public MemoryEventData
{
void init( uint64_t addr = 0 ) { MemoryEventData::init( addr ); }
void init( const DeallocationEvent& inData ) { MemoryEventData::init( inData ); }
};
template<> inline MemoryEventTypes::Enum getMemoryEventType<DeallocationEvent>() { return MemoryEventTypes::DeallocationEvent; }
class MemoryEvent
{
public:
typedef PX_PROFILE_UNION_5(StringTableEvent, AllocationEvent, DeallocationEvent, FullAllocationEvent, uint8_t) EventData;
private:
MemoryEventHeader mHeader;
EventData mData;
public:
MemoryEvent() {}
MemoryEvent( MemoryEventHeader inHeader, const EventData& inData = EventData() )
: mHeader( inHeader )
, mData( inData )
{
}
template<typename TDataType>
MemoryEvent( const TDataType& inType )
: mHeader( getMemoryEventType<TDataType>() )
, mData( inType )
{
//set the appropriate compression bits.
inType.setup( mHeader );
}
const MemoryEventHeader& getHeader() const { return mHeader; }
const EventData& getData() const { return mData; }
template<typename TDataType>
const TDataType& getValue() const { PX_ASSERT( mHeader.getType() == getMemoryEventType<TDataType>() ); return mData.toType<TDataType>(); }
template<typename TDataType>
TDataType& getValue() { PX_ASSERT( mHeader.getType() == getMemoryEventType<TDataType>() ); return mData.toType<TDataType>(); }
template<typename TRetVal, typename TOperator>
inline TRetVal visit( TOperator inOp ) const;
bool operator==( const MemoryEvent& inOther ) const
{
if ( !(mHeader == inOther.mHeader ) ) return false;
if ( mHeader.getType() )
return inOther.visit<bool>( EventDataEqualOperator<EventData>( mData ) );
return true;
}
};
template<typename TRetVal, typename TOperator>
inline TRetVal visit( MemoryEventTypes::Enum inEventType, const MemoryEvent::EventData& inData, TOperator inOperator )
{
switch( inEventType )
{
case MemoryEventTypes::StringTableEvent: return inOperator( inData.toType( Type2Type<StringTableEvent>() ) );
case MemoryEventTypes::AllocationEvent: return inOperator( inData.toType( Type2Type<AllocationEvent>() ) );
case MemoryEventTypes::DeallocationEvent: return inOperator( inData.toType( Type2Type<DeallocationEvent>() ) );
case MemoryEventTypes::FullAllocationEvent: return inOperator( inData.toType( Type2Type<FullAllocationEvent>() ) );
case MemoryEventTypes::Unknown: return inOperator( static_cast<uint8_t>( inEventType ) );
}
return TRetVal();
}
template<typename TRetVal, typename TOperator>
inline TRetVal MemoryEvent::visit( TOperator inOp ) const
{
return physx::profile::visit<TRetVal>( mHeader.getType(), mData, inOp );
}
}}
#endif // PXPVDSDK_PXPROFILEMEMORYEVENTS_H