This commit is contained in:
2025-11-28 23:13:44 +05:30
commit a3a8e79709
7360 changed files with 1156074 additions and 0 deletions

View File

@ -0,0 +1,83 @@
//
// 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-2021 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_PSPVD_H
#define PXPVDSDK_PSPVD_H
/** \addtogroup pvd
@{
*/
#include "pvd/PxPvd.h"
#include "PsBroadcast.h"
#if !PX_DOXYGEN
namespace physx
{
#endif
class PxPvdTransport;
#if !PX_DOXYGEN
namespace pvdsdk
{
#endif
class PvdDataStream;
class PvdClient;
class PvdOMMetaDataProvider;
// PsPvd is used for advanced user, it support custom pvd client API
class PsPvd : public physx::PxPvd, public shdfnd::AllocationListener
{
public:
virtual void addClient(PvdClient* client) = 0;
virtual void removeClient(PvdClient* client) = 0;
virtual bool registerObject(const void* inItem) = 0;
virtual bool unRegisterObject(const void* inItem) = 0;
//AllocationListener
void onAllocation(size_t size, const char* typeName, const char* filename, int line, void* allocatedMemory) = 0;
void onDeallocation(void* addr) = 0;
virtual PvdOMMetaDataProvider& getMetaDataProvider() = 0;
virtual uint64_t getNextStreamId() = 0;
// Call to flush events to PVD
virtual void flush() = 0;
};
#if !PX_DOXYGEN
} // namespace pvdsdk
} // namespace physx
#endif
/** @} */
#endif // PXPVDSDK_PSPVD_H

View File

@ -0,0 +1,231 @@
//
// 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-2021 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_PXPROFILEALLOCATORWRAPPER_H
#define PXPVDSDK_PXPROFILEALLOCATORWRAPPER_H
#include "foundation/PxPreprocessor.h"
#include "foundation/PxAllocatorCallback.h"
#include "foundation/PxErrorCallback.h"
#include "foundation/PxAssert.h"
#include "PsArray.h"
#include "PsHashMap.h"
namespace physx { namespace profile {
/**
\brief Helper struct to encapsulate the user allocator callback
Useful for array and hash templates
*/
struct PxProfileAllocatorWrapper
{
PxAllocatorCallback* mUserAllocator;
PxProfileAllocatorWrapper( PxAllocatorCallback& inUserAllocator )
: mUserAllocator( &inUserAllocator )
{
}
PxProfileAllocatorWrapper( PxAllocatorCallback* inUserAllocator )
: mUserAllocator( inUserAllocator )
{
}
PxAllocatorCallback& getAllocator() const
{
PX_ASSERT( NULL != mUserAllocator );
return *mUserAllocator;
}
};
/**
\brief Helper class to encapsulate the reflection allocator
*/
template <typename T>
class PxProfileWrapperReflectionAllocator
{
static const char* getName()
{
#if PX_LINUX || PX_ANDROID || PX_PS4 || PX_IOS || PX_OSX || PX_EMSCRIPTEN || PX_SWITCH
return __PRETTY_FUNCTION__;
#else
return typeid(T).name();
#endif
}
PxProfileAllocatorWrapper* mWrapper;
public:
PxProfileWrapperReflectionAllocator(PxProfileAllocatorWrapper& inWrapper) : mWrapper( &inWrapper ) {}
PxProfileWrapperReflectionAllocator( const PxProfileWrapperReflectionAllocator& inOther )
: mWrapper( inOther.mWrapper )
{
}
PxProfileWrapperReflectionAllocator& operator=( const PxProfileWrapperReflectionAllocator& inOther )
{
mWrapper = inOther.mWrapper;
return *this;
}
PxAllocatorCallback& getAllocator() { return mWrapper->getAllocator(); }
void* allocate(size_t size, const char* filename, int line)
{
#if PX_CHECKED // checked and debug builds
if(!size)
return 0;
return getAllocator().allocate(size, getName(), filename, line);
#else
return getAllocator().allocate(size, "<no allocation names in this config>", filename, line);
#endif
}
void deallocate(void* ptr)
{
if(ptr)
getAllocator().deallocate(ptr);
}
};
/**
\brief Helper class to encapsulate the named allocator
*/
struct PxProfileWrapperNamedAllocator
{
PxProfileAllocatorWrapper* mWrapper;
const char* mAllocationName;
PxProfileWrapperNamedAllocator(PxProfileAllocatorWrapper& inWrapper, const char* inAllocationName)
: mWrapper( &inWrapper )
, mAllocationName( inAllocationName )
{}
PxProfileWrapperNamedAllocator( const PxProfileWrapperNamedAllocator& inOther )
: mWrapper( inOther.mWrapper )
, mAllocationName( inOther.mAllocationName )
{
}
PxProfileWrapperNamedAllocator& operator=( const PxProfileWrapperNamedAllocator& inOther )
{
mWrapper = inOther.mWrapper;
mAllocationName = inOther.mAllocationName;
return *this;
}
PxAllocatorCallback& getAllocator() { return mWrapper->getAllocator(); }
void* allocate(size_t size, const char* filename, int line)
{
if(!size)
return 0;
return getAllocator().allocate(size, mAllocationName, filename, line);
}
void deallocate(void* ptr)
{
if(ptr)
getAllocator().deallocate(ptr);
}
};
/**
\brief Helper struct to encapsulate the array
*/
template<class T>
struct PxProfileArray : public shdfnd::Array<T, PxProfileWrapperReflectionAllocator<T> >
{
typedef PxProfileWrapperReflectionAllocator<T> TAllocatorType;
PxProfileArray( PxProfileAllocatorWrapper& inWrapper )
: shdfnd::Array<T, TAllocatorType >( TAllocatorType( inWrapper ) )
{
}
PxProfileArray( const PxProfileArray< T >& inOther )
: shdfnd::Array<T, TAllocatorType >( inOther, inOther )
{
}
};
/**
\brief Helper struct to encapsulate the array
*/
template<typename TKeyType, typename TValueType, typename THashType=shdfnd::Hash<TKeyType> >
struct PxProfileHashMap : public shdfnd::HashMap<TKeyType, TValueType, THashType, PxProfileWrapperReflectionAllocator< TValueType > >
{
typedef shdfnd::HashMap<TKeyType, TValueType, THashType, PxProfileWrapperReflectionAllocator< TValueType > > THashMapType;
typedef PxProfileWrapperReflectionAllocator<TValueType> TAllocatorType;
PxProfileHashMap( PxProfileAllocatorWrapper& inWrapper )
: THashMapType( TAllocatorType( inWrapper ) )
{
}
};
/**
\brief Helper function to encapsulate the profile allocation
*/
template<typename TDataType>
inline TDataType* PxProfileAllocate( PxAllocatorCallback* inAllocator, const char* file, int inLine )
{
PxProfileAllocatorWrapper wrapper( inAllocator );
typedef PxProfileWrapperReflectionAllocator< TDataType > TAllocator;
TAllocator theAllocator( wrapper );
return reinterpret_cast<TDataType*>( theAllocator.allocate( sizeof( TDataType ), file, inLine ) );
}
/**
\brief Helper function to encapsulate the profile allocation
*/
template<typename TDataType>
inline TDataType* PxProfileAllocate( PxAllocatorCallback& inAllocator, const char* file, int inLine )
{
return PxProfileAllocate<TDataType>( &inAllocator, file, inLine );
}
/**
\brief Helper function to encapsulate the profile deallocation
*/
template<typename TDataType>
inline void PxProfileDeleteAndDeallocate( PxProfileAllocatorWrapper& inAllocator, TDataType* inDType )
{
PX_ASSERT(inDType);
PxAllocatorCallback& allocator( inAllocator.getAllocator() );
inDType->~TDataType();
allocator.deallocate( inDType );
}
/**
\brief Helper function to encapsulate the profile deallocation
*/
template<typename TDataType>
inline void PxProfileDeleteAndDeallocate( PxAllocatorCallback& inAllocator, TDataType* inDType )
{
PxProfileAllocatorWrapper wrapper( &inAllocator );
PxProfileDeleteAndDeallocate( wrapper, inDType );
}
} }
#define PX_PROFILE_NEW( allocator, dtype ) new (physx::profile::PxProfileAllocate<dtype>( allocator, __FILE__, __LINE__ )) dtype
#define PX_PROFILE_DELETE( allocator, obj ) physx::profile::PxProfileDeleteAndDeallocate( allocator, obj );
#endif // PXPVDSDK_PXPROFILEALLOCATORWRAPPER_H

View File

@ -0,0 +1,76 @@
//
// 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-2021 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_PXPVDCLIENT_H
#define PXPVDSDK_PXPVDCLIENT_H
/** \addtogroup pvd
@{
*/
#include "foundation/PxFlags.h"
#include "foundation/PxVec3.h"
#if !PX_DOXYGEN
namespace physx
{
namespace pvdsdk
{
#endif
class PvdDataStream;
class PvdUserRenderer;
/**
\brief PvdClient is the per-client connection to PVD.
It provides callback when PVD is connected/disconnted.
It provides access to the internal object so that advanced users can create extension client.
*/
class PvdClient
{
public:
virtual PvdDataStream* getDataStream() = 0;
virtual bool isConnected() const = 0;
virtual void onPvdConnected() = 0;
virtual void onPvdDisconnected() = 0;
virtual void flush() = 0;
protected:
virtual ~PvdClient()
{
}
};
#if !PX_DOXYGEN
} // namespace pvdsdk
} // namespace physx
#endif
/** @} */
#endif // PXPVDSDK_PXPVDCLIENT_H

View File

@ -0,0 +1,272 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
#ifndef PXPVDSDK_PXPVDDATASTREAM_H
#define PXPVDSDK_PXPVDDATASTREAM_H
/** \addtogroup pvd
@{
*/
#include "pvd/PxPvd.h"
#include "PxPvdErrorCodes.h"
#include "PxPvdObjectModelBaseTypes.h"
#if !PX_DOXYGEN
namespace physx
{
namespace pvdsdk
{
#endif
class PvdPropertyDefinitionHelper;
class PvdMetaDataStream
{
protected:
virtual ~PvdMetaDataStream()
{
}
public:
virtual PvdError createClass(const NamespacedName& nm) = 0;
template <typename TDataType>
PvdError createClass()
{
return createClass(getPvdNamespacedNameForType<TDataType>());
}
virtual PvdError deriveClass(const NamespacedName& parent, const NamespacedName& child) = 0;
template <typename TParentType, typename TChildType>
PvdError deriveClass()
{
return deriveClass(getPvdNamespacedNameForType<TParentType>(), getPvdNamespacedNameForType<TChildType>());
}
virtual bool isClassExist(const NamespacedName& nm) = 0;
template <typename TDataType>
bool isClassExist()
{
return isClassExist(getPvdNamespacedNameForType<TDataType>());
}
virtual PvdError createProperty(const NamespacedName& clsName, const char* name, const char* semantic,
const NamespacedName& dtypeName, PropertyType::Enum propertyType,
DataRef<NamedValue> values = DataRef<NamedValue>()) = 0;
template <typename TClsType, typename TDataType>
PvdError createProperty(String name, String semantic = "", PropertyType::Enum propertyType = PropertyType::Scalar,
DataRef<NamedValue> values = DataRef<NamedValue>())
{
return createProperty(getPvdNamespacedNameForType<TClsType>(), name, semantic,
getPvdNamespacedNameForType<TDataType>(), propertyType, values);
}
virtual PvdError createPropertyMessage(const NamespacedName& cls, const NamespacedName& msgName,
DataRef<PropertyMessageArg> entries, uint32_t messageSizeInBytes) = 0;
template <typename TClsType, typename TMsgType>
PvdError createPropertyMessage(DataRef<PropertyMessageArg> entries)
{
return createPropertyMessage(getPvdNamespacedNameForType<TClsType>(), getPvdNamespacedNameForType<TMsgType>(),
entries, sizeof(TMsgType));
}
};
class PvdInstanceDataStream
{
protected:
virtual ~PvdInstanceDataStream()
{
}
public:
virtual PvdError createInstance(const NamespacedName& cls, const void* instance) = 0;
template <typename TDataType>
PvdError createInstance(const TDataType* inst)
{
return createInstance(getPvdNamespacedNameForType<TDataType>(), inst);
}
virtual bool isInstanceValid(const void* instance) = 0;
// If the property will fit or is already completely in memory
virtual PvdError setPropertyValue(const void* instance, String name, DataRef<const uint8_t> data,
const NamespacedName& incomingTypeName) = 0;
template <typename TDataType>
PvdError setPropertyValue(const void* instance, String name, const TDataType& value)
{
const uint8_t* dataStart = reinterpret_cast<const uint8_t*>(&value);
return setPropertyValue(instance, name, DataRef<const uint8_t>(dataStart, dataStart + sizeof(TDataType)),
getPvdNamespacedNameForType<TDataType>());
}
template <typename TDataType>
PvdError setPropertyValue(const void* instance, String name, const TDataType* value, uint32_t numItems)
{
const uint8_t* dataStart = reinterpret_cast<const uint8_t*>(value);
return setPropertyValue(instance, name,
DataRef<const uint8_t>(dataStart, dataStart + sizeof(TDataType) * numItems),
getPvdNamespacedNameForType<TDataType>());
}
// Else if the property is very large (contact reports) you can send it in chunks.
virtual PvdError beginSetPropertyValue(const void* instance, String name, const NamespacedName& incomingTypeName) = 0;
template <typename TDataType>
PvdError beginSetPropertyValue(const void* instance, String name)
{
return beginSetPropertyValue(instance, name, getPvdNamespacedNameForType<TDataType>());
}
virtual PvdError appendPropertyValueData(DataRef<const uint8_t> data) = 0;
template <typename TDataType>
PvdError appendPropertyValueData(const TDataType* value, uint32_t numItems)
{
const uint8_t* dataStart = reinterpret_cast<const uint8_t*>(value);
return appendPropertyValueData(DataRef<const uint8_t>(dataStart, dataStart + numItems * sizeof(TDataType)));
}
virtual PvdError endSetPropertyValue() = 0;
// Set a set of properties to various values on an object.
virtual PvdError setPropertyMessage(const void* instance, const NamespacedName& msgName,
DataRef<const uint8_t> data) = 0;
template <typename TDataType>
PvdError setPropertyMessage(const void* instance, const TDataType& value)
{
const uint8_t* dataStart = reinterpret_cast<const uint8_t*>(&value);
return setPropertyMessage(instance, getPvdNamespacedNameForType<TDataType>(),
DataRef<const uint8_t>(dataStart, sizeof(TDataType)));
}
// If you need to send of lot of identical messages, this avoids a hashtable lookup per message.
virtual PvdError beginPropertyMessageGroup(const NamespacedName& msgName) = 0;
template <typename TDataType>
PvdError beginPropertyMessageGroup()
{
return beginPropertyMessageGroup(getPvdNamespacedNameForType<TDataType>());
}
virtual PvdError sendPropertyMessageFromGroup(const void* instance, DataRef<const uint8_t> data) = 0;
template <typename TDataType>
PvdError sendPropertyMessageFromGroup(const void* instance, const TDataType& value)
{
const uint8_t* dataStart = reinterpret_cast<const uint8_t*>(&value);
return sendPropertyMessageFromGroup(instance, DataRef<const uint8_t>(dataStart, sizeof(TDataType)));
}
virtual PvdError endPropertyMessageGroup() = 0;
// These functions ensure the target array doesn't contain duplicates
virtual PvdError pushBackObjectRef(const void* instId, String propName, const void* objRef) = 0;
virtual PvdError removeObjectRef(const void* instId, String propName, const void* objRef) = 0;
// Instance elimination.
virtual PvdError destroyInstance(const void* key) = 0;
// Profiling hooks
virtual PvdError beginSection(const void* instance, String name) = 0;
virtual PvdError endSection(const void* instance, String name) = 0;
// Origin Shift
virtual PvdError originShift(const void* scene, PxVec3 shift) = 0;
public:
/*For some cases, pvd command cannot be run immediately. For example, when create joints, while the actors may still
*pending for insert, the joints update commands can be run deffered.
*/
class PvdCommand
{
public:
// Assigned is needed for copying
PvdCommand(const PvdCommand&)
{
}
PvdCommand& operator=(const PvdCommand&)
{
return *this;
}
public:
PvdCommand()
{
}
virtual ~PvdCommand()
{
}
// Not pure virtual so can have default PvdCommand obj
virtual bool canRun(PvdInstanceDataStream&)
{
return false;
}
virtual void run(PvdInstanceDataStream&)
{
}
};
// PVD SDK provide this helper function to allocate cmd's memory and release them at after flush the command queue
virtual void* allocateMemForCmd(uint32_t length) = 0;
// PVD will call the destructor of PvdCommand object at the end fo flushPvdCommand
virtual void pushPvdCommand(PvdCommand& cmd) = 0;
virtual void flushPvdCommand() = 0;
};
class PvdDataStream : public PvdInstanceDataStream, public PvdMetaDataStream
{
protected:
virtual ~PvdDataStream()
{
}
public:
virtual void release() = 0;
virtual bool isConnected() = 0;
virtual void addProfileZone(void* zone, const char* name) = 0;
virtual void addProfileZoneEvent(void* zone, const char* name, uint16_t eventId, bool compileTimeEnabled) = 0;
virtual PvdPropertyDefinitionHelper& getPropertyDefinitionHelper() = 0;
virtual void setIsTopLevelUIElement(const void* instance, bool topLevel) = 0;
virtual void sendErrorMessage(uint32_t code, const char* message, const char* file, uint32_t line) = 0;
virtual void updateCamera(const char* name, const PxVec3& origin, const PxVec3& up, const PxVec3& target) = 0;
/**
\brief Create a new PvdDataStream.
\param pvd A pointer to a valid PxPvd instance. This must be non-null.
*/
static PvdDataStream* create(PxPvd* pvd);
};
#if !PX_DOXYGEN
} // pvdsdk
} // physx
#endif
/** @} */
#endif // PXPVDSDK_PXPVDDATASTREAM_H

View File

@ -0,0 +1,120 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
#ifndef PXPVDSDK_PXPVDDATASTREAMHELPERS_H
#define PXPVDSDK_PXPVDDATASTREAMHELPERS_H
/** \addtogroup pvd
@{
*/
#include "PxPvdObjectModelBaseTypes.h"
#if !PX_DOXYGEN
namespace physx
{
namespace pvdsdk
{
#endif
class PvdPropertyDefinitionHelper
{
protected:
virtual ~PvdPropertyDefinitionHelper()
{
}
public:
/**
Push a name c such that it appends such as a.b.c.
*/
virtual void pushName(const char* inName, const char* inAppendStr = ".") = 0;
/**
Push a name c such that it appends like a.b[c]
*/
virtual void pushBracketedName(const char* inName, const char* leftBracket = "[", const char* rightBracket = "]") = 0;
/**
* Pop the current name
*/
virtual void popName() = 0;
virtual void clearNameStack() = 0;
/**
* Get the current name at the top of the name stack.
* Would return "a.b.c" or "a.b[c]" in the above examples.
*/
virtual const char* getTopName() = 0;
virtual void addNamedValue(const char* name, uint32_t value) = 0;
virtual void clearNamedValues() = 0;
virtual DataRef<NamedValue> getNamedValues() = 0;
/**
* Define a property using the top of the name stack and the passed-in semantic
*/
virtual void createProperty(const NamespacedName& clsName, const char* inSemantic, const NamespacedName& dtypeName,
PropertyType::Enum propType = PropertyType::Scalar) = 0;
template <typename TClsType, typename TDataType>
void createProperty(const char* inSemantic = "", PropertyType::Enum propType = PropertyType::Scalar)
{
createProperty(getPvdNamespacedNameForType<TClsType>(), inSemantic, getPvdNamespacedNameForType<TDataType>(),
propType);
}
// The datatype used for instances needs to be pointer unless you actually have pvdsdk::InstanceId members on your
// value structs.
virtual void addPropertyMessageArg(const NamespacedName& inDatatype, uint32_t inOffset, uint32_t inSize) = 0;
template <typename TDataType>
void addPropertyMessageArg(uint32_t offset)
{
addPropertyMessageArg(getPvdNamespacedNameForType<TDataType>(), offset, static_cast<uint32_t>(sizeof(TDataType)));
}
virtual void addPropertyMessage(const NamespacedName& clsName, const NamespacedName& msgName,
uint32_t inStructSizeInBytes) = 0;
template <typename TClsType, typename TMsgType>
void addPropertyMessage()
{
addPropertyMessage(getPvdNamespacedNameForType<TClsType>(), getPvdNamespacedNameForType<TMsgType>(),
static_cast<uint32_t>(sizeof(TMsgType)));
}
virtual void clearPropertyMessageArgs() = 0;
void clearBufferedData()
{
clearNameStack();
clearPropertyMessageArgs();
clearNamedValues();
}
};
#if !PX_DOXYGEN
} // pvdsdk
} // physx
#endif
/** @} */
#endif // PXPVDSDK_PXPVDDATASTREAMHELPERS_H

View File

@ -0,0 +1,62 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
#ifndef PXPVDSDK_PXPVDERRORCODES_H
#define PXPVDSDK_PXPVDERRORCODES_H
/** \addtogroup pvd
@{
*/
#include "foundation/Px.h"
#if !PX_DOXYGEN
namespace physx
{
namespace pvdsdk
{
#endif
struct PvdErrorType
{
enum Enum
{
Success = 0,
NetworkError,
ArgumentError,
Disconnect,
InternalProblem
};
};
typedef PvdErrorType::Enum PvdError;
#if !PX_DOXYGEN
}
}
#endif
/** @} */
#endif // PXPVDSDK_PXPVDERRORCODES_H

View File

@ -0,0 +1,428 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
#ifndef PXPVDSDK_PXPVDOBJECTMODELBASETYPES_H
#define PXPVDSDK_PXPVDOBJECTMODELBASETYPES_H
/** \addtogroup pvd
@{
*/
#include "foundation/PxAssert.h"
#if !PX_DOXYGEN
namespace physx
{
namespace pvdsdk
{
#endif
using namespace physx;
inline const char* nonNull(const char* str)
{
return str ? str : "";
}
// strcmp will crash if passed a null string, however,
// so we need to make sure that doesn't happen. We do that
// by equating NULL and the empty string, "".
inline bool safeStrEq(const char* lhs, const char* rhs)
{
return ::strcmp(nonNull(lhs), nonNull(rhs)) == 0;
}
// Does this string have useful information in it.
inline bool isMeaningful(const char* str)
{
return *(nonNull(str)) > 0;
}
inline uint32_t safeStrLen(const char* str)
{
str = nonNull(str);
return static_cast<uint32_t>(strlen(str));
}
struct ObjectRef
{
int32_t mInstanceId;
ObjectRef(int32_t iid = -1) : mInstanceId(iid)
{
}
operator int32_t() const
{
return mInstanceId;
}
bool hasValue() const
{
return mInstanceId > 0;
}
};
struct U32Array4
{
uint32_t mD0;
uint32_t mD1;
uint32_t mD2;
uint32_t mD3;
U32Array4(uint32_t d0, uint32_t d1, uint32_t d2, uint32_t d3) : mD0(d0), mD1(d1), mD2(d2), mD3(d3)
{
}
U32Array4() : mD0(0), mD1(0), mD2(0), mD3(0)
{
}
};
typedef bool PvdBool;
typedef const char* String;
typedef void* VoidPtr;
typedef double PvdF64;
typedef float PvdF32;
typedef int64_t PvdI64;
typedef uint64_t PvdU64;
typedef int32_t PvdI32;
typedef uint32_t PvdU32;
typedef int16_t PvdI16;
typedef uint16_t PvdU16;
typedef int8_t PvdI8;
typedef uint8_t PvdU8;
struct PvdColor
{
uint8_t r;
uint8_t g;
uint8_t b;
uint8_t a;
PvdColor(uint8_t _r, uint8_t _g, uint8_t _b, uint8_t _a = 255) : r(_r), g(_g), b(_b), a(_a)
{
}
PvdColor() : r(0), g(0), b(0), a(255)
{
}
PvdColor(uint32_t abgr)
{
uint8_t* valPtr = reinterpret_cast<uint8_t*>(&abgr);
r = valPtr[0];
g = valPtr[1];
b = valPtr[2];
a = valPtr[3];
}
};
struct StringHandle
{
uint32_t mHandle;
StringHandle(uint32_t val = 0) : mHandle(val)
{
}
operator uint32_t() const
{
return mHandle;
}
};
#define DECLARE_TYPES \
DECLARE_BASE_PVD_TYPE(PvdI8) \
DECLARE_BASE_PVD_TYPE(PvdU8) \
DECLARE_BASE_PVD_TYPE(PvdI16) \
DECLARE_BASE_PVD_TYPE(PvdU16) \
DECLARE_BASE_PVD_TYPE(PvdI32) \
DECLARE_BASE_PVD_TYPE(PvdU32) \
DECLARE_BASE_PVD_TYPE(PvdI64) \
DECLARE_BASE_PVD_TYPE(PvdU64) \
DECLARE_BASE_PVD_TYPE(PvdF32) \
DECLARE_BASE_PVD_TYPE(PvdF64) \
DECLARE_BASE_PVD_TYPE(PvdBool) \
DECLARE_BASE_PVD_TYPE(PvdColor) \
DECLARE_BASE_PVD_TYPE(String) \
DECLARE_BASE_PVD_TYPE(StringHandle) \
DECLARE_BASE_PVD_TYPE(ObjectRef) \
DECLARE_BASE_PVD_TYPE(VoidPtr) \
DECLARE_BASE_PVD_TYPE(PxVec2) \
DECLARE_BASE_PVD_TYPE(PxVec3) \
DECLARE_BASE_PVD_TYPE(PxVec4) \
DECLARE_BASE_PVD_TYPE(PxBounds3) \
DECLARE_BASE_PVD_TYPE(PxQuat) \
DECLARE_BASE_PVD_TYPE(PxTransform) \
DECLARE_BASE_PVD_TYPE(PxMat33) \
DECLARE_BASE_PVD_TYPE(PxMat44) \
DECLARE_BASE_PVD_TYPE(U32Array4)
struct PvdBaseType
{
enum Enum
{
None = 0,
InternalStart = 1,
InternalStop = 64,
#define DECLARE_BASE_PVD_TYPE(type) type,
DECLARE_TYPES
Last
#undef DECLARE_BASE_PVD_TYPE
};
};
struct NamespacedName
{
String mNamespace;
String mName;
NamespacedName(String ns, String nm) : mNamespace(ns), mName(nm)
{
}
NamespacedName(String nm = "") : mNamespace(""), mName(nm)
{
}
bool operator==(const NamespacedName& other) const
{
return safeStrEq(mNamespace, other.mNamespace) && safeStrEq(mName, other.mName);
}
};
struct NamedValue
{
String mName;
uint32_t mValue;
NamedValue(String nm = "", uint32_t val = 0) : mName(nm), mValue(val)
{
}
};
template <typename T>
struct BaseDataTypeToTypeMap
{
bool compile_error;
};
template <PvdBaseType::Enum>
struct BaseTypeToDataTypeMap
{
bool compile_error;
};
// Users can extend this mapping with new datatypes.
template <typename T>
struct PvdDataTypeToNamespacedNameMap
{
bool Name;
};
// This mapping tells you the what class id to use for the base datatypes
//
#define DECLARE_BASE_PVD_TYPE(type) \
template <> \
struct BaseDataTypeToTypeMap<type> \
{ \
enum Enum \
{ \
BaseTypeEnum = PvdBaseType::type \
}; \
}; \
template <> \
struct BaseDataTypeToTypeMap<const type&> \
{ \
enum Enum \
{ \
BaseTypeEnum = PvdBaseType::type \
}; \
}; \
template <> \
struct BaseTypeToDataTypeMap<PvdBaseType::type> \
{ \
typedef type TDataType; \
}; \
template <> \
struct PvdDataTypeToNamespacedNameMap<type> \
{ \
NamespacedName Name; \
PvdDataTypeToNamespacedNameMap<type>() : Name("physx3", #type) \
{ \
} \
}; \
template <> \
struct PvdDataTypeToNamespacedNameMap<const type&> \
{ \
NamespacedName Name; \
PvdDataTypeToNamespacedNameMap<const type&>() : Name("physx3", #type) \
{ \
} \
};
DECLARE_TYPES
#undef DECLARE_BASE_PVD_TYPE
template <typename TDataType>
inline int32_t getPvdTypeForType()
{
return static_cast<PvdBaseType::Enum>(BaseDataTypeToTypeMap<TDataType>::BaseTypeEnum);
}
template <typename TDataType>
inline NamespacedName getPvdNamespacedNameForType()
{
return PvdDataTypeToNamespacedNameMap<TDataType>().Name;
}
#define DEFINE_PVD_TYPE_NAME_MAP(type, ns, name) \
template <> \
struct PvdDataTypeToNamespacedNameMap<type> \
{ \
NamespacedName Name; \
PvdDataTypeToNamespacedNameMap<type>() : Name(ns, name) \
{ \
} \
};
#define DEFINE_PVD_TYPE_ALIAS(newType, oldType) \
template <> \
struct PvdDataTypeToNamespacedNameMap<newType> \
{ \
NamespacedName Name; \
PvdDataTypeToNamespacedNameMap<newType>() : Name(PvdDataTypeToNamespacedNameMap<oldType>().Name) \
{ \
} \
};
DEFINE_PVD_TYPE_ALIAS(const void*, void*)
struct ArrayData
{
uint8_t* mBegin;
uint8_t* mEnd;
uint8_t* mCapacity; //>= stop
ArrayData(uint8_t* beg = NULL, uint8_t* end = NULL, uint8_t* cap = NULL) : mBegin(beg), mEnd(end), mCapacity(cap)
{
}
uint8_t* begin()
{
return mBegin;
}
uint8_t* end()
{
return mEnd;
}
uint32_t byteCapacity()
{
return static_cast<uint32_t>(mCapacity - mBegin);
}
uint32_t byteSize() const
{
return static_cast<uint32_t>(mEnd - mBegin);
} // in bytes
uint32_t numberOfItems(uint32_t objectByteSize)
{
if(objectByteSize)
return byteSize() / objectByteSize;
return 0;
}
void forgetData()
{
mBegin = mEnd = mCapacity = 0;
}
};
template <typename T>
class DataRef
{
const T* mBegin;
const T* mEnd;
public:
DataRef(const T* b, uint32_t count) : mBegin(b), mEnd(b + count)
{
}
DataRef(const T* b = NULL, const T* e = NULL) : mBegin(b), mEnd(e)
{
}
DataRef(const DataRef& o) : mBegin(o.mBegin), mEnd(o.mEnd)
{
}
DataRef& operator=(const DataRef& o)
{
mBegin = o.mBegin;
mEnd = o.mEnd;
return *this;
}
uint32_t size() const
{
return static_cast<uint32_t>(mEnd - mBegin);
}
const T* begin() const
{
return mBegin;
}
const T* end() const
{
return mEnd;
}
const T& operator[](uint32_t idx) const
{
PX_ASSERT(idx < size());
return mBegin[idx];
}
const T& back() const
{
PX_ASSERT(mEnd > mBegin);
return *(mEnd - 1);
}
};
struct PropertyType
{
enum Enum
{
Unknown = 0,
Scalar,
Array
};
};
// argument to the create property message function
struct PropertyMessageArg
{
String mPropertyName;
NamespacedName mDatatypeName;
// where in the message this property starts.
uint32_t mMessageOffset;
// size of this entry object
uint32_t mByteSize;
PropertyMessageArg(String propName, NamespacedName dtype, uint32_t msgOffset, uint32_t byteSize)
: mPropertyName(propName), mDatatypeName(dtype), mMessageOffset(msgOffset), mByteSize(byteSize)
{
}
PropertyMessageArg() : mPropertyName(""), mMessageOffset(0), mByteSize(0)
{
}
};
class PvdUserRenderer;
DEFINE_PVD_TYPE_NAME_MAP(PvdUserRenderer, "_debugger_", "PvdUserRenderer")
#if !PX_DOXYGEN
}
}
#endif
/** @} */
#endif // PXPVDSDK_PXPVDOBJECTMODELBASETYPES_H

View File

@ -0,0 +1,140 @@
//
// 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-2021 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_PXPVDRENDERBUFFER_H
#define PXPVDSDK_PXPVDRENDERBUFFER_H
/** \addtogroup pvd
@{
*/
#include "foundation/PxVec3.h"
#if !PX_DOXYGEN
namespace physx
{
namespace pvdsdk
{
#endif
/**
\brief Default color values used for debug rendering.
*/
struct PvdDebugColor
{
enum Enum
{
eARGB_BLACK = 0xff000000,
eARGB_RED = 0xffff0000,
eARGB_GREEN = 0xff00ff00,
eARGB_BLUE = 0xff0000ff,
eARGB_YELLOW = 0xffffff00,
eARGB_MAGENTA = 0xffff00ff,
eARGB_CYAN = 0xff00ffff,
eARGB_WHITE = 0xffffffff,
eARGB_GREY = 0xff808080,
eARGB_DARKRED = 0x88880000,
eARGB_DARKGREEN = 0x88008800,
eARGB_DARKBLUE = 0x88000088
};
};
/**
\brief Used to store a single point and colour for debug rendering.
*/
struct PvdDebugPoint
{
PvdDebugPoint(const PxVec3& p, const uint32_t& c) : pos(p), color(c)
{
}
PxVec3 pos;
uint32_t color;
};
/**
\brief Used to store a single line and colour for debug rendering.
*/
struct PvdDebugLine
{
PvdDebugLine(const PxVec3& p0, const PxVec3& p1, const uint32_t& c) : pos0(p0), color0(c), pos1(p1), color1(c)
{
}
PxVec3 pos0;
uint32_t color0;
PxVec3 pos1;
uint32_t color1;
};
/**
\brief Used to store a single triangle and colour for debug rendering.
*/
struct PvdDebugTriangle
{
PvdDebugTriangle(const PxVec3& p0, const PxVec3& p1, const PxVec3& p2, const uint32_t& c)
: pos0(p0), color0(c), pos1(p1), color1(c), pos2(p2), color2(c)
{
}
PxVec3 pos0;
uint32_t color0;
PxVec3 pos1;
uint32_t color1;
PxVec3 pos2;
uint32_t color2;
};
/**
\brief Used to store a text for debug rendering. Doesn't own 'string' array.
*/
struct PvdDebugText
{
PvdDebugText() : string(0)
{
}
PvdDebugText(const PxVec3& p, const float& s, const uint32_t& c, const char* str)
: position(p), size(s), color(c), string(str)
{
}
PxVec3 position;
float size;
uint32_t color;
const char* string;
};
#if !PX_DOXYGEN
}
} // namespace physx
#endif
/** @} */
#endif // PXPVDSDK_PXPVDRENDERBUFFER_H

View File

@ -0,0 +1,107 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
#ifndef PXPVDSDK_PXPVDUSERRENDERER_H
#define PXPVDSDK_PXPVDUSERRENDERER_H
/** \addtogroup pvd
@{
*/
#include "foundation/PxVec3.h"
#include "foundation/PxTransform.h"
#include "pvd/PxPvd.h"
#include "PxPvdDataStream.h"
#include "PxPvdRenderBuffer.h"
#include "PsUserAllocated.h"
#if !PX_DOXYGEN
namespace physx
{
#endif
class PxPvd;
#if !PX_DOXYGEN
namespace pvdsdk
{
#endif
class RendererEventClient;
class PvdUserRenderer : public shdfnd::UserAllocated
{
protected:
virtual ~PvdUserRenderer()
{
}
public:
virtual void release() = 0;
virtual void setClient(RendererEventClient* client) = 0;
// Instance to associate the further rendering with.
virtual void setInstanceId(const void* instanceId) = 0;
// Draw these points associated with this instance
virtual void drawPoints(const PvdDebugPoint* points, uint32_t count) = 0;
// Draw these lines associated with this instance
virtual void drawLines(const PvdDebugLine* lines, uint32_t count) = 0;
// Draw these triangles associated with this instance
virtual void drawTriangles(const PvdDebugTriangle* triangles, uint32_t count) = 0;
// Draw this text associated with this instance
virtual void drawText(const PvdDebugText& text) = 0;
// Draw SDK debug render
virtual void drawRenderbuffer(const PvdDebugPoint* pointData, uint32_t pointCount, const PvdDebugLine* lineData,
uint32_t lineCount, const PvdDebugTriangle* triangleData, uint32_t triangleCount) = 0;
// Constraint visualization routines
virtual void visualizeJointFrames(const PxTransform& parent, const PxTransform& child) = 0;
virtual void visualizeLinearLimit(const PxTransform& t0, const PxTransform& t1, float value, bool active) = 0;
virtual void visualizeAngularLimit(const PxTransform& t0, float lower, float upper, bool active) = 0;
virtual void visualizeLimitCone(const PxTransform& t, float tanQSwingY, float tanQSwingZ, bool active) = 0;
virtual void visualizeDoubleCone(const PxTransform& t, float angle, bool active) = 0;
// Clear the immedate buffer.
virtual void flushRenderEvents() = 0;
static PvdUserRenderer* create(uint32_t bufferSize = 0x2000);
};
class RendererEventClient
{
public:
virtual ~RendererEventClient(){}
virtual void handleBufferFlush(const uint8_t* inData, uint32_t inLength) = 0;
};
#if !PX_DOXYGEN
}
}
#endif
/** @} */
#endif // PXPVDSDK_PXPVDUSERRENDERER_H

View File

@ -0,0 +1,58 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
#ifndef PXPVDSDK_PXPROFILECONTEXTPROVIDER_H
#define PXPVDSDK_PXPROFILECONTEXTPROVIDER_H
#include "foundation/Px.h"
namespace physx { namespace profile {
struct PxProfileEventExecutionContext
{
uint32_t mThreadId;
uint8_t mCpuId;
uint8_t mThreadPriority;
PxProfileEventExecutionContext( uint32_t inThreadId = 0, uint8_t inThreadPriority = 2 /*eThreadPriorityNormal*/, uint8_t inCpuId = 0 )
: mThreadId( inThreadId )
, mCpuId( inCpuId )
, mThreadPriority( inThreadPriority )
{
}
bool operator==( const PxProfileEventExecutionContext& inOther ) const
{
return mThreadId == inOther.mThreadId
&& mCpuId == inOther.mCpuId
&& mThreadPriority == inOther.mThreadPriority;
}
};
} }
#endif // PXPVDSDK_PXPROFILECONTEXTPROVIDER_H

View File

@ -0,0 +1,52 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
#ifndef PXPVDSDK_PXPROFILECONTEXTPROVIDERIMPL_H
#define PXPVDSDK_PXPROFILECONTEXTPROVIDERIMPL_H
#include "PxProfileContextProvider.h"
#include "PsThread.h"
namespace physx { namespace profile {
struct PxDefaultContextProvider
{
PxProfileEventExecutionContext getExecutionContext()
{
shdfnd::Thread::Id theId( shdfnd::Thread::getId() );
return PxProfileEventExecutionContext( static_cast<uint32_t>( theId ), static_cast<uint8_t>( shdfnd::ThreadPriority::eNORMAL ), 0 );
}
uint32_t getThreadId()
{
return static_cast<uint32_t>( shdfnd::Thread::getId() );
}
};
} }
#endif // PXPVDSDK_PXPROFILECONTEXTPROVIDERIMPL_H

View File

@ -0,0 +1,167 @@
//
// 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-2021 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_PXPROFILEDATABUFFER_H
#define PXPVDSDK_PXPROFILEDATABUFFER_H
#include "PxProfileAllocatorWrapper.h"
#include "PxProfileMemoryBuffer.h"
#include "PxProfileEventBufferClient.h"
namespace physx { namespace profile {
template<typename TMutex
, typename TScopedLock>
class DataBuffer //base class for buffers that cache data and then dump the data to clients.
{
public:
typedef TMutex TMutexType;
typedef TScopedLock TScopedLockType;
typedef PxProfileWrapperNamedAllocator TU8AllocatorType;
typedef MemoryBuffer<TU8AllocatorType > TMemoryBufferType;
typedef PxProfileArray<PxProfileEventBufferClient*> TBufferClientArray;
protected:
PxProfileAllocatorWrapper mWrapper;
TMemoryBufferType mDataArray;
TBufferClientArray mBufferClients;
uint32_t mBufferFullAmount;
EventContextInformation mEventContextInformation;
TMutexType* mBufferMutex;
volatile bool mHasClients;
EventSerializer<TMemoryBufferType > mSerializer;
public:
DataBuffer( PxAllocatorCallback* inFoundation
, uint32_t inBufferFullAmount
, TMutexType* inBufferMutex
, const char* inAllocationName )
: mWrapper( inFoundation )
, mDataArray( TU8AllocatorType( mWrapper, inAllocationName ) )
, mBufferClients( mWrapper )
, mBufferFullAmount( inBufferFullAmount )
, mBufferMutex( inBufferMutex )
, mHasClients( false )
, mSerializer( &mDataArray )
{
//The data array is never resized really. We ensure
//it is bigger than it will ever need to be.
mDataArray.reserve( inBufferFullAmount + 68 );
}
virtual ~DataBuffer()
{
while(mBufferClients.size() )
{
removeClient( *mBufferClients[0] );
}
}
PxProfileAllocatorWrapper& getWrapper() { return mWrapper; }
TMutexType* getBufferMutex() { return mBufferMutex; }
void setBufferMutex(TMutexType* mutex) { mBufferMutex = mutex; }
void addClient( PxProfileEventBufferClient& inClient )
{
TScopedLockType lock( mBufferMutex );
mBufferClients.pushBack( &inClient );
mHasClients = true;
}
void removeClient( PxProfileEventBufferClient& inClient )
{
TScopedLockType lock( mBufferMutex );
for ( uint32_t idx =0; idx < mBufferClients.size(); ++idx )
{
if (mBufferClients[idx] == &inClient )
{
inClient.handleClientRemoved();
mBufferClients.replaceWithLast( idx );
break;
}
}
mHasClients = mBufferClients.size() != 0;
}
bool hasClients() const
{
return mHasClients;
}
virtual void flushEvents()
{
TScopedLockType lock(mBufferMutex);
const uint8_t* theData = mDataArray.begin();
uint32_t theDataSize = mDataArray.size();
sendDataToClients(theData, theDataSize);
mDataArray.clear();
clearCachedData();
}
//Used for chaining together event buffers.
virtual void handleBufferFlush( const uint8_t* inData, uint32_t inDataSize )
{
TScopedLockType lock( mBufferMutex );
if ( inData && inDataSize )
{
clearCachedData();
if ( mDataArray.size() + inDataSize >= mBufferFullAmount )
flushEvents();
if ( inDataSize >= mBufferFullAmount )
sendDataToClients( inData, inDataSize );
else
mDataArray.write( inData, inDataSize );
}
}
protected:
virtual void clearCachedData()
{
}
private:
void sendDataToClients( const uint8_t* inData, uint32_t inDataSize )
{
uint32_t clientCount = mBufferClients.size();
for( uint32_t idx =0; idx < clientCount; ++idx )
mBufferClients[idx]->handleBufferFlush( inData, inDataSize );
}
};
}}
#endif // PXPVDSDK_PXPROFILEDATABUFFER_H

View File

@ -0,0 +1,218 @@
//
// 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-2021 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_PXPROFILEDATAPARSING_H
#define PXPVDSDK_PXPROFILEDATAPARSING_H
#include "foundation/Px.h"
namespace physx { namespace profile {
//Converts datatypes without using type punning.
struct BlockParserDataConverter
{
union
{
uint8_t mU8[8];
uint16_t mU16[4];
uint32_t mU32[2];
uint64_t mU64[1];
int8_t mI8[8];
int16_t mI16[4];
int32_t mI32[2];
int64_t mI64[1];
float mF32[2];
double mF64[1];
};
template<typename TDataType> inline TDataType convert() { PX_ASSERT( false ); return TDataType(); }
template<typename TDataType>
inline void convert( const TDataType& ) {}
};
template<> inline uint8_t BlockParserDataConverter::convert<uint8_t>() { return mU8[0]; }
template<> inline uint16_t BlockParserDataConverter::convert<uint16_t>() { return mU16[0]; }
template<> inline uint32_t BlockParserDataConverter::convert<uint32_t>() { return mU32[0]; }
template<> inline uint64_t BlockParserDataConverter::convert<uint64_t>() { return mU64[0]; }
template<> inline int8_t BlockParserDataConverter::convert<int8_t>() { return mI8[0]; }
template<> inline int16_t BlockParserDataConverter::convert<int16_t>() { return mI16[0]; }
template<> inline int32_t BlockParserDataConverter::convert<int32_t>() { return mI32[0]; }
template<> inline int64_t BlockParserDataConverter::convert<int64_t>() { return mI64[0]; }
template<> inline float BlockParserDataConverter::convert<float>() { return mF32[0]; }
template<> inline double BlockParserDataConverter::convert<double>() { return mF64[0]; }
template<> inline void BlockParserDataConverter::convert<uint8_t>( const uint8_t& inData ) { mU8[0] = inData; }
template<> inline void BlockParserDataConverter::convert<uint16_t>( const uint16_t& inData ) { mU16[0] = inData; }
template<> inline void BlockParserDataConverter::convert<uint32_t>( const uint32_t& inData ) { mU32[0] = inData; }
template<> inline void BlockParserDataConverter::convert<uint64_t>( const uint64_t& inData ) { mU64[0] = inData; }
template<> inline void BlockParserDataConverter::convert<int8_t>( const int8_t& inData ) { mI8[0] = inData; }
template<> inline void BlockParserDataConverter::convert<int16_t>( const int16_t& inData ) { mI16[0] = inData; }
template<> inline void BlockParserDataConverter::convert<int32_t>( const int32_t& inData ) { mI32[0] = inData; }
template<> inline void BlockParserDataConverter::convert<int64_t>( const int64_t& inData ) { mI64[0] = inData; }
template<> inline void BlockParserDataConverter::convert<float>( const float& inData ) { mF32[0] = inData; }
template<> inline void BlockParserDataConverter::convert<double>( const double& inData ) { mF64[0] = inData; }
//Handles various details around parsing blocks of uint8_t data.
struct BlockParseFunctions
{
template<uint8_t ByteCount>
static inline void swapBytes( uint8_t* inData )
{
for ( uint32_t idx = 0; idx < ByteCount/2; ++idx )
{
uint32_t endIdx = ByteCount-idx-1;
uint8_t theTemp = inData[idx];
inData[idx] = inData[endIdx];
inData[endIdx] = theTemp;
}
}
static inline bool checkLength( const uint8_t* inStart, const uint8_t* inStop, uint32_t inLength )
{
return static_cast<uint32_t>(inStop - inStart) >= inLength;
}
//warning work-around
template<typename T>
static inline T val(T v) {return v;}
template<bool DoSwapBytes, typename TDataType>
static inline bool parse( const uint8_t*& inStart, const uint8_t* inStop, TDataType& outData )
{
if ( checkLength( inStart, inStop, sizeof( TDataType ) ) )
{
BlockParserDataConverter theConverter;
for ( uint32_t idx =0; idx < sizeof( TDataType ); ++idx )
theConverter.mU8[idx] = inStart[idx];
if ( val(DoSwapBytes))
swapBytes<sizeof(TDataType)>( theConverter.mU8 );
outData = theConverter.convert<TDataType>();
inStart += sizeof( TDataType );
return true;
}
return false;
}
template<bool DoSwapBytes, typename TDataType>
static inline bool parseBlock( const uint8_t*& inStart, const uint8_t* inStop, TDataType* outData, uint32_t inNumItems )
{
uint32_t desired = sizeof(TDataType)*inNumItems;
if ( checkLength( inStart, inStop, desired ) )
{
if ( val(DoSwapBytes) )
{
for ( uint32_t item = 0; item < inNumItems; ++item )
{
BlockParserDataConverter theConverter;
for ( uint32_t idx =0; idx < sizeof( TDataType ); ++idx )
theConverter.mU8[idx] = inStart[idx];
swapBytes<sizeof(TDataType)>( theConverter.mU8 );
outData[item] = theConverter.convert<TDataType>();
inStart += sizeof(TDataType);
}
}
else
{
uint8_t* target = reinterpret_cast<uint8_t*>(outData);
memmove( target, inStart, desired );
inStart += desired;
}
return true;
}
return false;
}
//In-place byte swapping block
template<bool DoSwapBytes, typename TDataType>
static inline bool parseBlock( uint8_t*& inStart, const uint8_t* inStop, uint32_t inNumItems )
{
uint32_t desired = sizeof(TDataType)*inNumItems;
if ( checkLength( inStart, inStop, desired ) )
{
if ( val(DoSwapBytes) )
{
for ( uint32_t item = 0; item < inNumItems; ++item, inStart += sizeof( TDataType ) )
swapBytes<sizeof(TDataType)>( inStart ); //In-place swap.
}
else
inStart += sizeof( TDataType ) * inNumItems;
return true;
}
return false;
}
};
//Wraps the begin/end keeping track of them.
template<bool DoSwapBytes>
struct BlockParser
{
const uint8_t* mBegin;
const uint8_t* mEnd;
BlockParser( const uint8_t* inBegin=NULL, const uint8_t* inEnd=NULL )
: mBegin( inBegin )
, mEnd( inEnd )
{
}
inline bool hasMoreData() const { return mBegin != mEnd; }
inline bool checkLength( uint32_t inLength ) { return BlockParseFunctions::checkLength( mBegin, mEnd, inLength ); }
template<typename TDataType>
inline bool read( TDataType& outDatatype ) { return BlockParseFunctions::parse<DoSwapBytes>( mBegin, mEnd, outDatatype ); }
template<typename TDataType>
inline bool readBlock( TDataType* outDataPtr, uint32_t inNumItems ) { return BlockParseFunctions::parseBlock<DoSwapBytes>( mBegin, mEnd, outDataPtr, inNumItems ); }
template<typename TDataType>
inline bool readBlock( uint32_t inNumItems )
{
uint8_t* theTempPtr = const_cast<uint8_t*>(mBegin);
bool retval = BlockParseFunctions::parseBlock<DoSwapBytes, TDataType>( theTempPtr, mEnd, inNumItems );
mBegin = theTempPtr;
return retval;
}
uint32_t amountLeft() const { return static_cast<uint32_t>( mEnd - mBegin ); }
};
//Reads the data without checking for error conditions
template<typename TDataType, typename TBlockParserType>
inline TDataType blockParserRead( TBlockParserType& inType )
{
TDataType retval;
inType.read( retval );
return retval;
}
}}
#endif // PXPVDSDK_PXPROFILEDATAPARSING_H

View File

@ -0,0 +1,267 @@
//
// 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-2021 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_PXPROFILEEVENTBUFFER_H
#define PXPVDSDK_PXPROFILEEVENTBUFFER_H
#include "PxProfileEvents.h"
#include "PxProfileEventSerialization.h"
#include "PxProfileDataBuffer.h"
#include "PxProfileContextProvider.h"
#include "PsTime.h"
namespace physx { namespace profile {
/**
* An event buffer maintains an in-memory buffer of events. When this buffer is full
* it sends to buffer to all handlers registered and resets the buffer.
*
* It is parameterized in four ways. The first is a context provider that provides
* both thread id and context id.
*
* The second is the mutex (which may be null) and a scoped locking mechanism. Thus the buffer
* may be used in a multithreaded context but clients of the buffer don't pay for this if they
* don't intend to use it this way.
*
* Finally the buffer may use an event filtering mechanism. This mechanism needs one function,
* namely isEventEnabled( uint8_t subsystem, uint8_t eventId ).
*
* All of these systems can be parameterized at compile time leading to an event buffer
* that should be as fast as possible given the constraints.
*
* Buffers may be chained together as this buffer has a handleBufferFlush method that
* will grab the mutex and add the data to this event buffer.
*
* Overall, lets look at the PhysX SDK an how all the pieces fit together.
* The SDK should have a mutex-protected event buffer where actual devs or users of PhysX
* can register handlers. This buffer has slow but correct implementations of the
* context provider interface.
*
* The SDK object should also have a concrete event filter which was used in the
* construction of the event buffer and which it exposes through opaque interfaces.
*
* The SDK should protect its event buffer and its event filter from multithreaded
* access and thus this provides the safest and slowest way to log events and to
* enable/disable events.
*
* Each scene should also have a concrete event filter. This filter is updated from
* the SDK event filter (in a mutex protected way) every frame. Thus scenes can change
* their event filtering on a frame-by-frame basis. It means that tasks running
* under the scene don't need a mutex when accessing the filter.
*
* Furthermore the scene should have an event buffer that always sets the context id
* on each event to the scene. This allows PVD and other systems to correlate events
* to scenes. Scenes should provide access only to a relative event sending system
* that looks up thread id upon each event but uses the scene id.
*
* The SDK's event buffer should be setup as an EventBufferClient for each scene's
* event buffer. Thus the SDK should expose an EventBufferClient interface that
* any client can use.
*
* For extremely *extremely* performance sensitive areas we should create a specialized
* per-scene, per-thread event buffer that is set on the task for these occasions. This buffer
* uses a trivial event context setup with the scene's context id and the thread id. It should
* share the scene's concrete event filter and it should have absolutely no locking. It should
* empty into the scene's event buffer which in some cases should empty into the SDK's event buffer
* which when full will push events all the way out of the system. The task should *always* flush
* the event buffer (if it has one) when it is finished; nothing else will work reliably.
*
* If the per-scene,per-thread event buffer is correctly parameterized and fully defined adding
* a new event should be an inline operation requiring no mutex grabs in the common case. I don't
* believe you can get faster event production than this; the events are as small as possible (all
* relative events) and they are all produced inline resulting in one 4 byte header and one
* 8 byte timestamp per event. Reducing the memory pressure in this way reduces the communication
* overhead, the mutex grabs, basically everything that makes profiling expensive at the cost
* of a per-scene,per-thread event buffer (which could easily be reduced to a per-thread event
* buffer.
*/
template<typename TContextProvider,
typename TMutex,
typename TScopedLock,
typename TEventFilter>
class EventBuffer : public DataBuffer<TMutex, TScopedLock>
{
public:
typedef DataBuffer<TMutex, TScopedLock> TBaseType;
typedef TContextProvider TContextProviderType;
typedef TEventFilter TEventFilterType;
typedef typename TBaseType::TMutexType TMutexType;
typedef typename TBaseType::TScopedLockType TScopedLockType;
typedef typename TBaseType::TU8AllocatorType TU8AllocatorType;
typedef typename TBaseType::TMemoryBufferType TMemoryBufferType;
typedef typename TBaseType::TBufferClientArray TBufferClientArray;
private:
EventContextInformation mEventContextInformation;
uint64_t mLastTimestamp;
TContextProvider mContextProvider;
TEventFilterType mEventFilter;
public:
EventBuffer(PxAllocatorCallback* inFoundation
, uint32_t inBufferFullAmount
, const TContextProvider& inProvider
, TMutexType* inBufferMutex
, const TEventFilterType& inEventFilter )
: TBaseType( inFoundation, inBufferFullAmount, inBufferMutex, "struct physx::profile::ProfileEvent" )
, mLastTimestamp( 0 )
, mContextProvider( inProvider )
, mEventFilter( inEventFilter )
{
memset(&mEventContextInformation,0,sizeof(EventContextInformation));
}
TContextProvider& getContextProvider() { return mContextProvider; }
PX_FORCE_INLINE void startEvent(uint16_t inId, uint32_t threadId, uint64_t contextId, uint8_t cpuId, uint8_t threadPriority, uint64_t inTimestamp)
{
TScopedLockType lock(TBaseType::mBufferMutex);
if ( mEventFilter.isEventEnabled( inId ) )
{
StartEvent theEvent;
theEvent.init( threadId, contextId, cpuId, threadPriority, inTimestamp );
doAddProfileEvent( inId, theEvent );
}
}
PX_FORCE_INLINE void startEvent(uint16_t inId, uint64_t contextId)
{
PxProfileEventExecutionContext ctx( mContextProvider.getExecutionContext() );
startEvent( inId, ctx.mThreadId, contextId, ctx.mCpuId, static_cast<uint8_t>(ctx.mThreadPriority), shdfnd::Time::getCurrentCounterValue() );
}
PX_FORCE_INLINE void startEvent(uint16_t inId, uint64_t contextId, uint32_t threadId)
{
startEvent( inId, threadId, contextId, 0, 0, shdfnd::Time::getCurrentCounterValue() );
}
PX_FORCE_INLINE void stopEvent(uint16_t inId, uint32_t threadId, uint64_t contextId, uint8_t cpuId, uint8_t threadPriority, uint64_t inTimestamp)
{
TScopedLockType lock(TBaseType::mBufferMutex);
if ( mEventFilter.isEventEnabled( inId ) )
{
StopEvent theEvent;
theEvent.init( threadId, contextId, cpuId, threadPriority, inTimestamp );
doAddProfileEvent( inId, theEvent );
}
}
PX_FORCE_INLINE void stopEvent(uint16_t inId, uint64_t contextId)
{
PxProfileEventExecutionContext ctx( mContextProvider.getExecutionContext() );
stopEvent( inId, ctx.mThreadId, contextId, ctx.mCpuId, static_cast<uint8_t>(ctx.mThreadPriority), shdfnd::Time::getCurrentCounterValue() );
}
PX_FORCE_INLINE void stopEvent(uint16_t inId, uint64_t contextId, uint32_t threadId)
{
stopEvent( inId, threadId, contextId, 0, 0, shdfnd::Time::getCurrentCounterValue() );
}
inline void eventValue( uint16_t inId, uint64_t contextId, int64_t inValue )
{
eventValue( inId, mContextProvider.getThreadId(), contextId, inValue );
}
inline void eventValue( uint16_t inId, uint32_t threadId, uint64_t contextId, int64_t inValue )
{
TScopedLockType lock( TBaseType::mBufferMutex );
EventValue theEvent;
theEvent.init( inValue, contextId, threadId );
EventHeader theHeader( static_cast<uint8_t>( getEventType<EventValue>() ), inId );
//set the header relative timestamp;
EventValue& theType( theEvent );
theType.setupHeader( theHeader );
sendEvent( theHeader, theType );
}
void flushProfileEvents()
{
TBaseType::flushEvents();
}
void release()
{
PX_PROFILE_DELETE( TBaseType::mWrapper.mUserFoundation, this );
}
protected:
//Clears the cache meaning event compression
//starts over again.
//only called when the buffer mutex is held
void clearCachedData()
{
mEventContextInformation.setToDefault();
mLastTimestamp = 0;
}
template<typename TProfileEventType>
PX_FORCE_INLINE void doAddProfileEvent(uint16_t eventId, const TProfileEventType& inType)
{
TScopedLockType lock(TBaseType::mBufferMutex);
if (mEventContextInformation == inType.mContextInformation)
doAddEvent(static_cast<uint8_t>(inType.getRelativeEventType()), eventId, inType.getRelativeEvent());
else
{
mEventContextInformation = inType.mContextInformation;
doAddEvent( static_cast<uint8_t>( getEventType<TProfileEventType>() ), eventId, inType );
}
}
template<typename TDataType>
PX_FORCE_INLINE void doAddEvent(uint8_t inEventType, uint16_t eventId, const TDataType& inType)
{
EventHeader theHeader( inEventType, eventId );
//set the header relative timestamp;
TDataType& theType( const_cast<TDataType&>( inType ) );
uint64_t currentTs = inType.getTimestamp();
theType.setupHeader(theHeader, mLastTimestamp);
mLastTimestamp = currentTs;
sendEvent( theHeader, theType );
}
template<typename TDataType>
PX_FORCE_INLINE void sendEvent( EventHeader& inHeader, TDataType& inType )
{
uint32_t sizeToWrite = sizeof(inHeader) + inType.getEventSize(inHeader);
PX_UNUSED(sizeToWrite);
uint32_t writtenSize = inHeader.streamify( TBaseType::mSerializer );
writtenSize += inType.streamify(TBaseType::mSerializer, inHeader);
PX_ASSERT(writtenSize == sizeToWrite);
if ( TBaseType::mDataArray.size() >= TBaseType::mBufferFullAmount )
flushProfileEvents();
}
};
}}
#endif // PXPVDSDK_PXPROFILEEVENTBUFFER_H

View File

@ -0,0 +1,318 @@
//
// 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-2021 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_PXPROFILEEVENTBUFFERATOMIC_H
#define PXPVDSDK_PXPROFILEEVENTBUFFERATOMIC_H
#include "PxProfileEvents.h"
#include "PxProfileEventSerialization.h"
#include "PxProfileDataBuffer.h"
#include "PsArray.h"
#include "PsAlloca.h"
#include "PsTime.h"
#include "PsCpu.h"
#include "PsAtomic.h"
#include "PsAllocator.h"
namespace physx {
namespace profile {
static const uint32_t LOCAL_BUFFER_SIZE = 512;
/**
* An event buffer maintains an in-memory buffer of events. When this buffer is full
* it sends to buffer to all handlers registered and resets the buffer.
*
* It is parameterized in four ways. The first is a context provider that provides
* both thread id and context id.
*
* The second is the mutex (which may be null) and a scoped locking mechanism. Thus the buffer
* may be used in a multithreaded context but clients of the buffer don't pay for this if they
* don't intend to use it this way.
*
* Finally the buffer may use an event filtering mechanism. This mechanism needs one function,
* namely isEventEnabled( uint8_t subsystem, uint8_t eventId ).
*
* All of these systems can be parameterized at compile time leading to an event buffer
* that should be as fast as possible given the constraints.
*
* Buffers may be chained together as this buffer has a handleBufferFlush method that
* will grab the mutex and add the data to this event buffer.
*
* Overall, lets look at the PhysX SDK an how all the pieces fit together.
* The SDK should have a mutex-protected event buffer where actual devs or users of PhysX
* can register handlers. This buffer has slow but correct implementations of the
* context provider interface.
*
* The SDK object should also have a concrete event filter which was used in the
* construction of the event buffer and which it exposes through opaque interfaces.
*
* The SDK should protect its event buffer and its event filter from multithreaded
* access and thus this provides the safest and slowest way to log events and to
* enable/disable events.
*
* Each scene should also have a concrete event filter. This filter is updated from
* the SDK event filter (in a mutex protected way) every frame. Thus scenes can change
* their event filtering on a frame-by-frame basis. It means that tasks running
* under the scene don't need a mutex when accessing the filter.
*
* Furthermore the scene should have an event buffer that always sets the context id
* on each event to the scene. This allows PVD and other systems to correlate events
* to scenes. Scenes should provide access only to a relative event sending system
* that looks up thread id upon each event but uses the scene id.
*
* The SDK's event buffer should be setup as an EventBufferClient for each scene's
* event buffer. Thus the SDK should expose an EventBufferClient interface that
* any client can use.
*
* For extremely *extremely* performance sensitive areas we should create a specialized
* per-scene, per-thread event buffer that is set on the task for these occasions. This buffer
* uses a trivial event context setup with the scene's context id and the thread id. It should
* share the scene's concrete event filter and it should have absolutely no locking. It should
* empty into the scene's event buffer which in some cases should empty into the SDK's event buffer
* which when full will push events all the way out of the system. The task should *always* flush
* the event buffer (if it has one) when it is finished; nothing else will work reliably.
*
* If the per-scene,per-thread event buffer is correctly parameterized and fully defined adding
* a new event should be an inline operation requiring no mutex grabs in the common case. I don't
* believe you can get faster event production than this; the events are as small as possible (all
* relative events) and they are all produced inline resulting in one 4 byte header and one
* 8 byte timestamp per event. Reducing the memory pressure in this way reduces the communication
* overhead, the mutex grabs, basically everything that makes profiling expensive at the cost
* of a per-scene,per-thread event buffer (which could easily be reduced to a per-thread event
* buffer.
*/
template<typename TContextProvider,
typename TMutex,
typename TScopedLock,
typename TEventFilter>
class EventBufferAtomic : public DataBuffer < TMutex, TScopedLock >
{
public:
typedef DataBuffer<TMutex, TScopedLock> TBaseType;
typedef TContextProvider TContextProviderType;
typedef TEventFilter TEventFilterType;
typedef typename TBaseType::TMutexType TMutexType;
typedef typename TBaseType::TScopedLockType TScopedLockType;
typedef typename TBaseType::TU8AllocatorType TU8AllocatorType;
typedef typename TBaseType::TMemoryBufferType TMemoryBufferType;
typedef typename TBaseType::TBufferClientArray TBufferClientArray;
private:
TContextProvider mContextProvider;
TEventFilterType mEventFilter;
volatile int32_t mReserved;
volatile int32_t mWritten;
public:
EventBufferAtomic(PxAllocatorCallback* inFoundation
, uint32_t inBufferFullAmount
, const TContextProvider& inProvider
, TMutexType* inBufferMutex
, const TEventFilterType& inEventFilter)
: TBaseType(inFoundation, inBufferFullAmount, inBufferMutex, "struct physx::profile::ProfileEvent")
, mContextProvider(inProvider)
, mEventFilter(inEventFilter)
, mReserved(0)
, mWritten(0)
{
}
TContextProvider& getContextProvider() { return mContextProvider; }
PX_FORCE_INLINE void startEvent(uint16_t inId, uint32_t threadId, uint64_t contextId, uint8_t cpuId, uint8_t threadPriority, uint64_t inTimestamp)
{
if (mEventFilter.isEventEnabled(inId))
{
StartEvent theEvent;
theEvent.init(threadId, contextId, cpuId, threadPriority, inTimestamp);
doAddProfileEvent(inId, theEvent);
}
}
PX_FORCE_INLINE void startEvent(uint16_t inId, uint64_t contextId)
{
PxProfileEventExecutionContext ctx(mContextProvider.getExecutionContext());
startEvent(inId, ctx.mThreadId, contextId, ctx.mCpuId, static_cast<uint8_t>(ctx.mThreadPriority), shdfnd::Time::getCurrentCounterValue());
}
PX_FORCE_INLINE void startEvent(uint16_t inId, uint64_t contextId, uint32_t threadId)
{
startEvent(inId, threadId, contextId, 0, 0, shdfnd::Time::getCurrentCounterValue());
}
PX_FORCE_INLINE void stopEvent(uint16_t inId, uint32_t threadId, uint64_t contextId, uint8_t cpuId, uint8_t threadPriority, uint64_t inTimestamp)
{
if (mEventFilter.isEventEnabled(inId))
{
StopEvent theEvent;
theEvent.init(threadId, contextId, cpuId, threadPriority, inTimestamp);
doAddProfileEvent(inId, theEvent);
}
}
PX_FORCE_INLINE void stopEvent(uint16_t inId, uint64_t contextId)
{
PxProfileEventExecutionContext ctx(mContextProvider.getExecutionContext());
stopEvent(inId, ctx.mThreadId, contextId, ctx.mCpuId, static_cast<uint8_t>(ctx.mThreadPriority), shdfnd::Time::getCurrentCounterValue());
}
PX_FORCE_INLINE void stopEvent(uint16_t inId, uint64_t contextId, uint32_t threadId)
{
stopEvent(inId, threadId, contextId, 0, 0, shdfnd::Time::getCurrentCounterValue());
}
inline void eventValue(uint16_t inId, uint64_t contextId, int64_t inValue)
{
eventValue(inId, mContextProvider.getThreadId(), contextId, inValue);
}
inline void eventValue(uint16_t inId, uint32_t threadId, uint64_t contextId, int64_t inValue)
{
EventValue theEvent;
theEvent.init(inValue, contextId, threadId);
EventHeader theHeader(static_cast<uint8_t>(getEventType<EventValue>()), inId);
//set the header relative timestamp;
EventValue& theType(theEvent);
theType.setupHeader(theHeader);
int32_t sizeToWrite = int32_t(sizeof(theHeader) + theType.getEventSize(theHeader));
int32_t reserved = shdfnd::atomicAdd(&mReserved, sizeToWrite);
sendEvent(theHeader, theType, reserved, sizeToWrite);
}
void flushProfileEvents(int32_t reserved = -1)
{
TScopedLockType lock(TBaseType::mBufferMutex);
// set the buffer full to lock additional writes
int32_t reservedOld = shdfnd::atomicExchange(&mReserved, int32_t(TBaseType::mBufferFullAmount + 1));
if (reserved == -1)
reserved = reservedOld;
// spin till we have written all the data
while (reserved > mWritten)
{
}
// check if we have written all data
PX_ASSERT(reserved == mWritten);
// set the correct size of the serialization data buffer
TBaseType::mSerializer.mArray->setEnd(TBaseType::mSerializer.mArray->begin() + mWritten);
// flush events
TBaseType::flushEvents();
// write master timestamp and set reserved/written to start writing to buffer again
mWritten = 0;
mReserved = 0;
}
void release()
{
PX_PROFILE_DELETE(TBaseType::mWrapper.mUserFoundation, this);
}
protected:
//Clears the cache meaning event compression
//starts over again.
//only called when the buffer mutex is held
void clearCachedData()
{
}
template<typename TProfileEventType>
PX_FORCE_INLINE void doAddProfileEvent(uint16_t eventId, const TProfileEventType& inType)
{
doAddEvent(static_cast<uint8_t>(getEventType<TProfileEventType>()), eventId, inType);
}
template<typename TDataType>
PX_FORCE_INLINE void doAddEvent(uint8_t inEventType, uint16_t eventId, const TDataType& inType)
{
EventHeader theHeader(inEventType, eventId);
TDataType& theType(const_cast<TDataType&>(inType));
theType.setupHeader(theHeader, 0);
const int32_t sizeToWrite = int32_t(sizeof(theHeader) + theType.getEventSize(theHeader));
int32_t reserved = shdfnd::atomicAdd(&mReserved, sizeToWrite);
sendEvent(theHeader, theType, reserved, sizeToWrite);
}
template<typename TDataType>
PX_FORCE_INLINE void sendEvent(EventHeader& inHeader, TDataType& inType, int32_t reserved, int32_t sizeToWrite)
{
// if we don't fit to the buffer, we wait till it is flushed
if (reserved - sizeToWrite >= int32_t(TBaseType::mBufferFullAmount))
{
while (reserved - sizeToWrite >= int32_t(TBaseType::mBufferFullAmount))
{
// I32 overflow
if (mReserved < int32_t(TBaseType::mBufferFullAmount))
{
reserved = shdfnd::atomicAdd(&mReserved, sizeToWrite);
}
}
}
int32_t writeIndex = reserved - sizeToWrite;
uint32_t writtenSize = 0;
PX_ASSERT(writeIndex >= 0);
PX_ALLOCA(tempBuffer, uint8_t, sizeToWrite);
TempMemoryBuffer memoryBuffer(tempBuffer, sizeToWrite);
EventSerializer<TempMemoryBuffer> eventSerializer(&memoryBuffer);
writtenSize = inHeader.streamify(eventSerializer);
writtenSize += inType.streamify(eventSerializer, inHeader);
TBaseType::mSerializer.mArray->reserve(writeIndex + writtenSize);
TBaseType::mSerializer.mArray->write(&tempBuffer[0], writtenSize, writeIndex);
PX_ASSERT(writtenSize == uint32_t(sizeToWrite));
shdfnd::atomicAdd(&mWritten, sizeToWrite);
if (reserved >= int32_t(TBaseType::mBufferFullAmount))
{
TScopedLockType lock(TBaseType::mBufferMutex);
// we flush the buffer if its full and we did not flushed him in the meantime
if(mReserved >= reserved)
flushProfileEvents(reserved);
}
}
};
}
}
#endif // PXPVDSDK_PXPROFILEEVENTBUFFERATOMIC_H

View File

@ -0,0 +1,80 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
#ifndef PXPVDSDK_PXPROFILEEVENTBUFFERCLIENT_H
#define PXPVDSDK_PXPROFILEEVENTBUFFERCLIENT_H
#include "PxProfileEventNames.h"
namespace physx { namespace profile {
/**
\brief Client handles the data when an event buffer flushes. This data
can be parsed (PxProfileEventHandler.h) as a binary set of events.
*/
class PxProfileEventBufferClient
{
protected:
virtual ~PxProfileEventBufferClient(){}
public:
/**
\brief Callback when the event buffer is full. This data is serialized profile events
and can be read back using: PxProfileEventHandler::parseEventBuffer.
\param inData Provided buffer data.
\param inLength Data length.
@see PxProfileEventHandler::parseEventBuffer.
*/
virtual void handleBufferFlush( const uint8_t* inData, uint32_t inLength ) = 0;
/**
\brief Happens if something removes all the clients from the manager.
*/
virtual void handleClientRemoved() = 0;
};
/**
\brief Client handles new profile event add.
*/
class PxProfileZoneClient : public PxProfileEventBufferClient
{
protected:
virtual ~PxProfileZoneClient(){}
public:
/**
\brief Callback when new profile event is added.
\param inName Added profile event name.
*/
virtual void handleEventAdded( const PxProfileEventName& inName ) = 0;
};
} }
#endif // PXPVDSDK_PXPROFILEEVENTBUFFERCLIENT_H

View File

@ -0,0 +1,94 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
#ifndef PXPVDSDK_PXPROFILEEVENTBUFFERCLIENTMANAGER_H
#define PXPVDSDK_PXPROFILEEVENTBUFFERCLIENTMANAGER_H
#include "PxProfileEventBufferClient.h"
namespace physx { namespace profile {
/**
\brief Manager keep collections of PxProfileEventBufferClient clients.
@see PxProfileEventBufferClient
*/
class PxProfileEventBufferClientManager
{
protected:
virtual ~PxProfileEventBufferClientManager(){}
public:
/**
\brief Adds new client.
\param inClient Client to add.
*/
virtual void addClient( PxProfileEventBufferClient& inClient ) = 0;
/**
\brief Removes a client.
\param inClient Client to remove.
*/
virtual void removeClient( PxProfileEventBufferClient& inClient ) = 0;
/**
\brief Check if manager has clients.
\return True if manager has added clients.
*/
virtual bool hasClients() const = 0;
};
/**
\brief Manager keep collections of PxProfileZoneClient clients.
@see PxProfileZoneClient
*/
class PxProfileZoneClientManager
{
protected:
virtual ~PxProfileZoneClientManager(){}
public:
/**
\brief Adds new client.
\param inClient Client to add.
*/
virtual void addClient( PxProfileZoneClient& inClient ) = 0;
/**
\brief Removes a client.
\param inClient Client to remove.
*/
virtual void removeClient( PxProfileZoneClient& inClient ) = 0;
/**
\brief Check if manager has clients.
\return True if manager has added clients.
*/
virtual bool hasClients() const = 0;
};
} }
#endif // PXPVDSDK_PXPROFILEEVENTBUFFERCLIENTMANAGER_H

View File

@ -0,0 +1,64 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
#ifndef PXPVDSDK_PXPROFILEEVENTID_H
#define PXPVDSDK_PXPROFILEEVENTID_H
#include "foundation/Px.h"
namespace physx { namespace profile {
/**
\brief A event id structure. Optionally includes information about
if the event was enabled at compile time.
*/
struct PxProfileEventId
{
uint16_t eventId;
mutable bool compileTimeEnabled;
/**
\brief Profile event id constructor.
\param inId Profile event id.
\param inCompileTimeEnabled Compile time enabled.
*/
PxProfileEventId( uint16_t inId = 0, bool inCompileTimeEnabled = true )
: eventId( inId )
, compileTimeEnabled( inCompileTimeEnabled )
{
}
operator uint16_t () const { return eventId; }
bool operator==( const PxProfileEventId& inOther ) const
{
return eventId == inOther.eventId;
}
};
} }
#endif // PXPVDSDK_PXPROFILEEVENTID_H

View File

@ -0,0 +1,63 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
#include "PxProfileEventBuffer.h"
#include "PxProfileZoneImpl.h"
#include "PxProfileZoneManagerImpl.h"
#include "PxProfileMemoryEventBuffer.h"
#include "PsUserAllocated.h"
namespace physx { namespace profile {
struct PxProfileNameProviderForward
{
PxProfileNames mNames;
PxProfileNameProviderForward( PxProfileNames inNames )
: mNames( inNames )
{
}
PxProfileNames getProfileNames() const { return mNames; }
};
PxProfileZone& PxProfileZone::createProfileZone( PxAllocatorCallback* inAllocator, const char* inSDKName, PxProfileNames inNames, uint32_t inEventBufferByteSize )
{
typedef ZoneImpl<PxProfileNameProviderForward> TSDKType;
return *PX_PROFILE_NEW( inAllocator, TSDKType ) ( inAllocator, inSDKName, inEventBufferByteSize, PxProfileNameProviderForward( inNames ) );
}
PxProfileZoneManager& PxProfileZoneManager::createProfileZoneManager(PxAllocatorCallback* inAllocator )
{
return *PX_PROFILE_NEW( inAllocator, ZoneManagerImpl ) ( inAllocator );
}
PxProfileMemoryEventBuffer& PxProfileMemoryEventBuffer::createMemoryEventBuffer( PxAllocatorCallback& inAllocator, uint32_t inBufferSize )
{
return *PX_PROFILE_NEW( &inAllocator, PxProfileMemoryEventBufferImpl )( inAllocator, inBufferSize );
}
} }

View File

@ -0,0 +1,63 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
#ifndef PXPVDSDK_PXPROFILEEVENTMUTEX_H
#define PXPVDSDK_PXPROFILEEVENTMUTEX_H
#include "foundation/Px.h"
namespace physx { namespace profile {
/**
* Mutex interface that hides implementation around lock and unlock.
* The event system locks the mutex for every interaction.
*/
class PxProfileEventMutex
{
protected:
virtual ~PxProfileEventMutex(){}
public:
virtual void lock() = 0;
virtual void unlock() = 0;
};
/**
* Take any mutex type that implements lock and unlock and make an EventMutex out of it.
*/
template<typename TMutexType>
struct PxProfileEventMutexImpl : public PxProfileEventMutex
{
TMutexType* mMutex;
PxProfileEventMutexImpl( TMutexType* inMtx ) : mMutex( inMtx ) {}
virtual void lock() { mMutex->lock(); }
virtual void unlock() { mMutex->unlock(); }
};
} }
#endif // PXPVDSDK_PXPROFILEEVENTMUTEX_H

View File

@ -0,0 +1,89 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
#ifndef PXPVDSDK_PXPROFILEEVENTNAMES_H
#define PXPVDSDK_PXPROFILEEVENTNAMES_H
#include "PxProfileEventId.h"
namespace physx { namespace profile {
/**
\brief Mapping from event id to name.
*/
struct PxProfileEventName
{
const char* name;
PxProfileEventId eventId;
/**
\brief Default constructor.
\param inName Profile event name.
\param inId Profile event id.
*/
PxProfileEventName( const char* inName, PxProfileEventId inId ) : name( inName ), eventId( inId ) {}
};
/**
\brief Aggregator of event id -> name mappings
*/
struct PxProfileNames
{
/**
\brief Default constructor that doesn't point to any names.
\param inEventCount Number of provided events.
\param inSubsystems Event names array.
*/
PxProfileNames( uint32_t inEventCount = 0, const PxProfileEventName* inSubsystems = NULL )
: eventCount( inEventCount )
, events( inSubsystems )
{
}
uint32_t eventCount;
const PxProfileEventName* events;
};
/**
\brief Provides a mapping from event ID -> name.
*/
class PxProfileNameProvider
{
public:
/**
\brief Returns profile event names.
\return Profile event names.
*/
virtual PxProfileNames getProfileNames() const = 0;
protected:
virtual ~PxProfileNameProvider(){}
PxProfileNameProvider& operator=(const PxProfileNameProvider&) { return *this; }
};
} }
#endif // PXPVDSDK_PXPROFILEEVENTNAMES_H

View File

@ -0,0 +1,111 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
#ifndef PXPVDSDK_PXPROFILEEVENTSENDER_H
#define PXPVDSDK_PXPROFILEEVENTSENDER_H
#include "foundation/Px.h"
namespace physx { namespace profile {
/**
\brief Tagging interface to indicate an object that is capable of flushing a profile
event stream at a certain point.
*/
class PxProfileEventFlusher
{
protected:
virtual ~PxProfileEventFlusher(){}
public:
/**
\brief Flush profile events. Sends the profile event buffer to hooked clients.
*/
virtual void flushProfileEvents() = 0;
};
/**
\brief Sends the full events where the caller must provide the context and thread id.
*/
class PxProfileEventSender
{
protected:
virtual ~PxProfileEventSender(){}
public:
/**
\brief Use this as a thread id for events that start on one thread and end on another
*/
static const uint32_t CrossThreadId = 99999789;
/**
\brief Send a start profile event, optionally with a context. Events are sorted by thread
and context in the client side.
\param inId Profile event id.
\param contextId Context id.
*/
virtual void startEvent( uint16_t inId, uint64_t contextId) = 0;
/**
\brief Send a stop profile event, optionally with a context. Events are sorted by thread
and context in the client side.
\param inId Profile event id.
\param contextId Context id.
*/
virtual void stopEvent( uint16_t inId, uint64_t contextId) = 0;
/**
\brief Send a start profile event, optionally with a context. Events are sorted by thread
and context in the client side.
\param inId Profile event id.
\param contextId Context id.
\param threadId Thread id.
*/
virtual void startEvent( uint16_t inId, uint64_t contextId, uint32_t threadId) = 0;
/**
\brief Send a stop profile event, optionally with a context. Events are sorted by thread
and context in the client side.
\param inId Profile event id.
\param contextId Context id.
\param threadId Thread id.
*/
virtual void stopEvent( uint16_t inId, uint64_t contextId, uint32_t threadId ) = 0;
virtual void atEvent(uint16_t inId, uint64_t contextId, uint32_t threadId, uint64_t start, uint64_t stop) = 0;
/**
\brief Set an specific events value. This is different than the profiling value
for the event; it is a value recorded and kept around without a timestamp associated
with it. This value is displayed when the event itself is processed.
\param inId Profile event id.
\param contextId Context id.
\param inValue Value to set for the event.
*/
virtual void eventValue( uint16_t inId, uint64_t contextId, int64_t inValue ) = 0;
};
} }
#endif // PXPVDSDK_PXPROFILEEVENTSENDER_H

View File

@ -0,0 +1,257 @@
//
// 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-2021 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_PXPROFILEEVENTSERIALIZATION_H
#define PXPVDSDK_PXPROFILEEVENTSERIALIZATION_H
#include "PxProfileDataParsing.h"
#include "PxProfileEvents.h"
namespace physx { namespace profile {
/**
* Array type must be a pxu8 container. Templated so that this object can write
* to different collections.
*/
template<typename TArrayType>
struct EventSerializer
{
TArrayType* mArray;
EventSerializer( TArrayType* inA ) : mArray( inA ) {}
template<typename TDataType>
uint32_t streamify( const char*, const TDataType& inType )
{
return mArray->write( inType );
}
uint32_t streamify( const char*, const char*& inType )
{
PX_ASSERT( inType != NULL );
uint32_t len( static_cast<uint32_t>( strlen( inType ) ) );
++len; //include the null terminator
uint32_t writtenSize = 0;
writtenSize = mArray->write(len);
writtenSize += mArray->write(inType, len);
return writtenSize;
}
uint32_t streamify( const char*, const uint8_t* inData, uint32_t len )
{
uint32_t writtenSize = mArray->write(len);
if ( len )
writtenSize += mArray->write(inData, len);
return writtenSize;
}
uint32_t streamify( const char* nm, const uint64_t& inType, EventStreamCompressionFlags::Enum inFlags )
{
uint32_t writtenSize = 0;
switch( inFlags )
{
case EventStreamCompressionFlags::U8:
writtenSize = streamify(nm, static_cast<uint8_t>(inType));
break;
case EventStreamCompressionFlags::U16:
writtenSize = streamify(nm, static_cast<uint16_t>(inType));
break;
case EventStreamCompressionFlags::U32:
writtenSize = streamify(nm, static_cast<uint32_t>(inType));
break;
case EventStreamCompressionFlags::U64:
writtenSize = streamify(nm, inType);
break;
}
return writtenSize;
}
uint32_t streamify( const char* nm, const uint32_t& inType, EventStreamCompressionFlags::Enum inFlags )
{
uint32_t writtenSize = 0;
switch( inFlags )
{
case EventStreamCompressionFlags::U8:
writtenSize = streamify(nm, static_cast<uint8_t>(inType));
break;
case EventStreamCompressionFlags::U16:
writtenSize = streamify(nm, static_cast<uint16_t>(inType));
break;
case EventStreamCompressionFlags::U32:
case EventStreamCompressionFlags::U64:
writtenSize = streamify(nm, inType);
break;
}
return writtenSize;
}
};
/**
* The event deserializes takes a buffer implements the streamify functions
* by setting the passed in data to the data in the buffer.
*/
template<bool TSwapBytes>
struct EventDeserializer
{
const uint8_t* mData;
uint32_t mLength;
bool mFail;
EventDeserializer( const uint8_t* inData, uint32_t inLength )
: mData( inData )
, mLength( inLength )
, mFail( false )
{
if ( mData == NULL )
mLength = 0;
}
bool val() { return TSwapBytes; }
uint32_t streamify( const char* , uint8_t& inType )
{
uint8_t* theData = reinterpret_cast<uint8_t*>( &inType ); //type punned pointer...
if ( mFail || sizeof( inType ) > mLength )
{
PX_ASSERT( false );
mFail = true;
}
else
{
for( uint32_t idx = 0; idx < sizeof( uint8_t ); ++idx, ++mData, --mLength )
theData[idx] = *mData;
}
return 0;
}
//default streamify reads things natively as bytes.
template<typename TDataType>
uint32_t streamify( const char* , TDataType& inType )
{
uint8_t* theData = reinterpret_cast<uint8_t*>( &inType ); //type punned pointer...
if ( mFail || sizeof( inType ) > mLength )
{
PX_ASSERT( false );
mFail = true;
}
else
{
for( uint32_t idx = 0; idx < sizeof( TDataType ); ++idx, ++mData, --mLength )
theData[idx] = *mData;
bool temp = val();
if ( temp )
BlockParseFunctions::swapBytes<sizeof(TDataType)>( theData );
}
return 0;
}
uint32_t streamify( const char*, const char*& inType )
{
uint32_t theLen;
streamify( "", theLen );
theLen = PxMin( theLen, mLength );
inType = reinterpret_cast<const char*>( mData );
mData += theLen;
mLength -= theLen;
return 0;
}
uint32_t streamify( const char*, const uint8_t*& inData, uint32_t& len )
{
uint32_t theLen;
streamify( "", theLen );
theLen = PxMin( theLen, mLength );
len = theLen;
inData = reinterpret_cast<const uint8_t*>( mData );
mData += theLen;
mLength -= theLen;
return 0;
}
uint32_t streamify( const char* nm, uint64_t& inType, EventStreamCompressionFlags::Enum inFlags )
{
switch( inFlags )
{
case EventStreamCompressionFlags::U8:
{
uint8_t val=0;
streamify( nm, val );
inType = val;
}
break;
case EventStreamCompressionFlags::U16:
{
uint16_t val;
streamify( nm, val );
inType = val;
}
break;
case EventStreamCompressionFlags::U32:
{
uint32_t val;
streamify( nm, val );
inType = val;
}
break;
case EventStreamCompressionFlags::U64:
streamify( nm, inType );
break;
}
return 0;
}
uint32_t streamify( const char* nm, uint32_t& inType, EventStreamCompressionFlags::Enum inFlags )
{
switch( inFlags )
{
case EventStreamCompressionFlags::U8:
{
uint8_t val=0;
streamify( nm, val );
inType = val;
}
break;
case EventStreamCompressionFlags::U16:
{
uint16_t val=0;
streamify( nm, val );
inType = val;
}
break;
case EventStreamCompressionFlags::U32:
case EventStreamCompressionFlags::U64:
streamify( nm, inType );
break;
}
return 0;
}
};
}}
#endif // PXPVDSDK_PXPROFILEEVENTSERIALIZATION_H

View 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-2021 NVIDIA Corporation. All rights reserved.
#ifndef PXPVDSDK_PXPROFILEEVENTS_H
#define PXPVDSDK_PXPROFILEEVENTS_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_PS4) || (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_PS4) || (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 // PXPVDSDK_PXPROFILEEVENTS_H

View File

@ -0,0 +1,92 @@
//
// 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-2021 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_PXPROFILEMEMORY_H
#define PXPVDSDK_PXPROFILEMEMORY_H
#include "PxProfileEventBufferClientManager.h"
#include "PxProfileEventSender.h"
#include "PsBroadcast.h"
namespace physx { namespace profile {
/**
\brief Record events so a late-connecting client knows about
all outstanding allocations
*/
class PxProfileMemoryEventRecorder : public shdfnd::AllocationListener
{
protected:
virtual ~PxProfileMemoryEventRecorder(){}
public:
/**
\brief Set the allocation listener
\param inListener Allocation listener.
*/
virtual void setListener(AllocationListener* inListener) = 0;
/**
\brief Release the instance.
*/
virtual void release() = 0;
};
/**
\brief Stores memory events into the memory buffer.
*/
class PxProfileMemoryEventBuffer
: public shdfnd::AllocationListener //add a new event to the buffer
, public PxProfileEventBufferClientManager //add clients to handle the serialized memory events
, public PxProfileEventFlusher //flush the buffer
{
protected:
virtual ~PxProfileMemoryEventBuffer(){}
public:
/**
\brief Release the instance.
*/
virtual void release() = 0;
/**
\brief Create a non-mutex-protected event buffer.
\param inAllocator Allocation callback.
\param inBufferSize Internal buffer size.
*/
static PxProfileMemoryEventBuffer& createMemoryEventBuffer(PxAllocatorCallback& inAllocator, uint32_t inBufferSize = 0x1000);
};
} } // namespace physx
#endif // PXPVDSDK_PXPROFILEMEMORY_H

View File

@ -0,0 +1,192 @@
//
// 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-2021 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_PXPROFILEMEMORYBUFFER_H
#define PXPVDSDK_PXPROFILEMEMORYBUFFER_H
#include "PsAllocator.h"
#include "foundation/PxMemory.h"
namespace physx { namespace profile {
template<typename TAllocator = typename shdfnd::AllocatorTraits<uint8_t>::Type >
class MemoryBuffer : public TAllocator
{
uint8_t* mBegin;
uint8_t* mEnd;
uint8_t* mCapacityEnd;
public:
MemoryBuffer( const TAllocator& inAlloc = TAllocator() ) : TAllocator( inAlloc ), mBegin( 0 ), mEnd( 0 ), mCapacityEnd( 0 ) {}
~MemoryBuffer()
{
if ( mBegin ) TAllocator::deallocate( mBegin );
}
uint32_t size() const { return static_cast<uint32_t>( mEnd - mBegin ); }
uint32_t capacity() const { return static_cast<uint32_t>( mCapacityEnd - mBegin ); }
uint8_t* begin() { return mBegin; }
uint8_t* end() { return mEnd; }
void setEnd(uint8_t* nEnd) { mEnd = nEnd; }
const uint8_t* begin() const { return mBegin; }
const uint8_t* end() const { return mEnd; }
void clear() { mEnd = mBegin; }
uint32_t write( uint8_t inValue )
{
growBuf( 1 );
*mEnd = inValue;
++mEnd;
return 1;
}
template<typename TDataType>
uint32_t write( const TDataType& inValue )
{
uint32_t writtenSize = sizeof(TDataType);
growBuf(writtenSize);
const uint8_t* __restrict readPtr = reinterpret_cast< const uint8_t* >( &inValue );
uint8_t* __restrict writePtr = mEnd;
for ( uint32_t idx = 0; idx < sizeof(TDataType); ++idx ) writePtr[idx] = readPtr[idx];
mEnd += writtenSize;
return writtenSize;
}
template<typename TDataType>
uint32_t write( const TDataType* inValue, uint32_t inLength )
{
if ( inValue && inLength )
{
uint32_t writeSize = inLength * sizeof( TDataType );
growBuf( writeSize );
PxMemCopy( mBegin + size(), inValue, writeSize );
mEnd += writeSize;
return writeSize;
}
return 0;
}
// used by atomic write. Store the data and write the end afterwards
// we dont check the buffer size, it should not resize on the fly
template<typename TDataType>
uint32_t write(const TDataType* inValue, uint32_t inLength, int32_t index)
{
if (inValue && inLength)
{
uint32_t writeSize = inLength * sizeof(TDataType);
PX_ASSERT(mBegin + index + writeSize < mCapacityEnd);
PxMemCopy(mBegin + index, inValue, writeSize);
return writeSize;
}
return 0;
}
void growBuf( uint32_t inAmount )
{
uint32_t newSize = size() + inAmount;
reserve( newSize );
}
void resize( uint32_t inAmount )
{
reserve( inAmount );
mEnd = mBegin + inAmount;
}
void reserve( uint32_t newSize )
{
uint32_t currentSize = size();
if ( newSize >= capacity() )
{
const uint32_t allocSize = mBegin ? newSize * 2 : newSize;
uint8_t* newData = static_cast<uint8_t*>(TAllocator::allocate(allocSize, __FILE__, __LINE__));
memset(newData, 0xf,allocSize);
if ( mBegin )
{
PxMemCopy( newData, mBegin, currentSize );
TAllocator::deallocate( mBegin );
}
mBegin = newData;
mEnd = mBegin + currentSize;
mCapacityEnd = mBegin + allocSize;
}
}
};
class TempMemoryBuffer
{
uint8_t* mBegin;
uint8_t* mEnd;
uint8_t* mCapacityEnd;
public:
TempMemoryBuffer(uint8_t* data, int32_t size) : mBegin(data), mEnd(data), mCapacityEnd(data + size) {}
~TempMemoryBuffer()
{
}
uint32_t size() const { return static_cast<uint32_t>(mEnd - mBegin); }
uint32_t capacity() const { return static_cast<uint32_t>(mCapacityEnd - mBegin); }
const uint8_t* begin() { return mBegin; }
uint8_t* end() { return mEnd; }
const uint8_t* begin() const { return mBegin; }
const uint8_t* end() const { return mEnd; }
uint32_t write(uint8_t inValue)
{
*mEnd = inValue;
++mEnd;
return 1;
}
template<typename TDataType>
uint32_t write(const TDataType& inValue)
{
uint32_t writtenSize = sizeof(TDataType);
const uint8_t* __restrict readPtr = reinterpret_cast<const uint8_t*>(&inValue);
uint8_t* __restrict writePtr = mEnd;
for (uint32_t idx = 0; idx < sizeof(TDataType); ++idx) writePtr[idx] = readPtr[idx];
mEnd += writtenSize;
return writtenSize;
}
template<typename TDataType>
uint32_t write(const TDataType* inValue, uint32_t inLength)
{
if (inValue && inLength)
{
uint32_t writeSize = inLength * sizeof(TDataType);
PxMemCopy(mBegin + size(), inValue, writeSize);
mEnd += writeSize;
return writeSize;
}
return 0;
}
};
}}
#endif // PXPVDSDK_PXPROFILEMEMORYBUFFER_H

View File

@ -0,0 +1,157 @@
//
// 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-2021 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_PXPROFILEMEMORYEVENTBUFFER_H
#define PXPVDSDK_PXPROFILEMEMORYEVENTBUFFER_H
#include "PxProfileDataBuffer.h"
#include "PxProfileMemoryEvents.h"
#include "PxProfileMemory.h"
#include "PxProfileScopedMutexLock.h"
#include "PxProfileAllocatorWrapper.h"
#include "PxProfileEventMutex.h"
#include "PsHash.h"
#include "PsHashMap.h"
#include "PsUserAllocated.h"
namespace physx { namespace profile {
template<typename TMutex,
typename TScopedLock>
class MemoryEventBuffer : public DataBuffer<TMutex, TScopedLock>
{
public:
typedef DataBuffer<TMutex, TScopedLock> TBaseType;
typedef typename TBaseType::TMutexType TMutexType;
typedef typename TBaseType::TScopedLockType TScopedLockType;
typedef typename TBaseType::TU8AllocatorType TU8AllocatorType;
typedef typename TBaseType::TMemoryBufferType TMemoryBufferType;
typedef typename TBaseType::TBufferClientArray TBufferClientArray;
typedef shdfnd::HashMap<const char*, uint32_t, shdfnd::Hash<const char*>, TU8AllocatorType> TCharPtrToHandleMap;
protected:
TCharPtrToHandleMap mStringTable;
public:
MemoryEventBuffer( PxAllocatorCallback& cback
, uint32_t inBufferFullAmount
, TMutexType* inBufferMutex )
: TBaseType( &cback, inBufferFullAmount, inBufferMutex, "struct physx::profile::MemoryEvent" )
, mStringTable( TU8AllocatorType( TBaseType::getWrapper(), "MemoryEventStringBuffer" ) )
{
}
uint32_t getHandle( const char* inData )
{
if ( inData == NULL ) inData = "";
const typename TCharPtrToHandleMap::Entry* result( mStringTable.find( inData ) );
if ( result )
return result->second;
uint32_t hdl = mStringTable.size() + 1;
mStringTable.insert( inData, hdl );
StringTableEvent theEvent;
theEvent.init( inData, hdl );
sendEvent( theEvent );
return hdl;
}
void onAllocation( size_t inSize, const char* inType, const char* inFile, uint32_t inLine, uint64_t addr )
{
if ( addr == 0 )
return;
uint32_t typeHdl( getHandle( inType ) );
uint32_t fileHdl( getHandle( inFile ) );
AllocationEvent theEvent;
theEvent.init( inSize, typeHdl, fileHdl, inLine, addr );
sendEvent( theEvent );
}
void onDeallocation( uint64_t addr )
{
if ( addr == 0 )
return;
DeallocationEvent theEvent;
theEvent.init( addr );
sendEvent( theEvent );
}
void flushProfileEvents()
{
TBaseType::flushEvents();
}
protected:
template<typename TDataType>
void sendEvent( TDataType inType )
{
MemoryEventHeader theHeader( getMemoryEventType<TDataType>() );
inType.setup( theHeader );
theHeader.streamify( TBaseType::mSerializer );
inType.streamify( TBaseType::mSerializer, theHeader );
if ( TBaseType::mDataArray.size() >= TBaseType::mBufferFullAmount )
flushProfileEvents();
}
};
class PxProfileMemoryEventBufferImpl : public shdfnd::UserAllocated
, public PxProfileMemoryEventBuffer
{
typedef MemoryEventBuffer<PxProfileEventMutex, NullLock> TMemoryBufferType;
TMemoryBufferType mBuffer;
public:
PxProfileMemoryEventBufferImpl( PxAllocatorCallback& alloc, uint32_t inBufferFullAmount )
: mBuffer( alloc, inBufferFullAmount, NULL )
{
}
virtual void onAllocation( size_t size, const char* typeName, const char* filename, int line, void* allocatedMemory )
{
mBuffer.onAllocation( size, typeName, filename, uint32_t(line), static_cast<uint64_t>(reinterpret_cast<size_t>(allocatedMemory)) );
}
virtual void onDeallocation( void* allocatedMemory )
{
mBuffer.onDeallocation(static_cast<uint64_t>(reinterpret_cast<size_t>(allocatedMemory)) );
}
virtual void addClient( PxProfileEventBufferClient& inClient ) { mBuffer.addClient( inClient ); }
virtual void removeClient( PxProfileEventBufferClient& inClient ) { mBuffer.removeClient( inClient ); }
virtual bool hasClients() const { return mBuffer.hasClients(); }
virtual void flushProfileEvents() { mBuffer.flushProfileEvents(); }
virtual void release(){ PX_PROFILE_DELETE( mBuffer.getWrapper().getAllocator(), this ); }
};
}}
#endif // PXPVDSDK_PXPROFILEMEMORYEVENTBUFFER_H

View File

@ -0,0 +1,411 @@
//
// 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-2021 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

View File

@ -0,0 +1,107 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
#ifndef PXPVDSDK_PXPROFILESCOPEDEVENT_H
#define PXPVDSDK_PXPROFILESCOPEDEVENT_H
#include "PxProfileEventId.h"
#include "PxProfileCompileTimeEventFilter.h"
namespace physx { namespace profile {
/**
\brief Template version of startEvent, called directly on provided profile buffer.
\param inBuffer Profile event buffer.
\param inId Profile event id.
\param inContext Profile event context.
*/
template<bool TEnabled, typename TBufferType>
inline void startEvent( TBufferType* inBuffer, const PxProfileEventId& inId, uint64_t inContext )
{
if ( TEnabled && inBuffer ) inBuffer->startEvent( inId, inContext );
}
/**
\brief Template version of stopEvent, called directly on provided profile buffer.
\param inBuffer Profile event buffer.
\param inId Profile event id.
\param inContext Profile event context.
*/
template<bool TEnabled, typename TBufferType>
inline void stopEvent( TBufferType* inBuffer, const PxProfileEventId& inId, uint64_t inContext )
{
if ( TEnabled && inBuffer ) inBuffer->stopEvent( inId, inContext );
}
/**
\brief Template version of startEvent, called directly on provided profile buffer.
\param inEnabled If profile event is enabled.
\param inBuffer Profile event buffer.
\param inId Profile event id.
\param inContext Profile event context.
*/
template<typename TBufferType>
inline void startEvent( bool inEnabled, TBufferType* inBuffer, const PxProfileEventId& inId, uint64_t inContext )
{
if ( inEnabled && inBuffer ) inBuffer->startEvent( inId, inContext );
}
/**
\brief Template version of stopEvent, called directly on provided profile buffer.
\param inEnabled If profile event is enabled.
\param inBuffer Profile event buffer.
\param inId Profile event id.
\param inContext Profile event context.
*/
template<typename TBufferType>
inline void stopEvent( bool inEnabled, TBufferType* inBuffer, const PxProfileEventId& inId, uint64_t inContext )
{
if ( inEnabled && inBuffer ) inBuffer->stopEvent( inId, inContext );
}
/**
\brief Template version of eventValue, called directly on provided profile buffer.
\param inEnabled If profile event is enabled.
\param inBuffer Profile event buffer.
\param inId Profile event id.
\param inContext Profile event context.
\param inValue Event value.
*/
template<typename TBufferType>
inline void eventValue( bool inEnabled, TBufferType* inBuffer, const PxProfileEventId& inId, uint64_t inContext, int64_t inValue )
{
if ( inEnabled && inBuffer ) inBuffer->eventValue( inId, inContext, inValue );
}
}}
#endif // PXPVDSDK_PXPROFILESCOPEDEVENT_H

View File

@ -0,0 +1,64 @@
//
// 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-2021 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_PXPROFILESCOPEDMUTEXLOCK_H
#define PXPVDSDK_PXPROFILESCOPEDMUTEXLOCK_H
#include "foundation/Px.h"
namespace physx { namespace profile {
/**
* Generic class to wrap any mutex type that has lock and unlock methods
*/
template<typename TMutexType>
struct ScopedLockImpl
{
TMutexType* mMutex;
ScopedLockImpl( TMutexType* inM ) : mMutex( inM )
{
if ( mMutex ) mMutex->lock();
}
~ScopedLockImpl()
{
if ( mMutex ) mMutex->unlock();
}
};
/**
* Null locking system that does nothing.
*/
struct NullLock
{
template<typename TDataType> NullLock( TDataType*) {}
};
}}
#endif // PXPVDSDK_PXPROFILESCOPEDMUTEXLOCK_H

View File

@ -0,0 +1,315 @@
//
// 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-2021 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_PXPROFILEZONEIMPL_H
#define PXPVDSDK_PXPROFILEZONEIMPL_H
#include "PxPvdProfileZone.h"
#include "PxProfileZoneManager.h"
#include "PxProfileContextProviderImpl.h"
#include "PxProfileScopedMutexLock.h"
#include "PxProfileEventBufferAtomic.h"
#include "PsMutex.h"
namespace physx { namespace profile {
/**
\brief Simple event filter that enables all events.
*/
struct PxProfileNullEventFilter
{
void setEventEnabled( const PxProfileEventId&, bool) { PX_ASSERT(false); }
bool isEventEnabled( const PxProfileEventId&) const { return true; }
};
typedef shdfnd::MutexT<PxProfileWrapperReflectionAllocator<uint8_t> > TZoneMutexType;
typedef ScopedLockImpl<TZoneMutexType> TZoneLockType;
typedef EventBuffer< PxDefaultContextProvider, TZoneMutexType, TZoneLockType, PxProfileNullEventFilter > TZoneEventBufferType;
//typedef EventBufferAtomic< PxDefaultContextProvider, TZoneMutexType, TZoneLockType, PxProfileNullEventFilter > TZoneEventBufferType;
template<typename TNameProvider>
class ZoneImpl : TZoneEventBufferType //private inheritance intended
, public PxProfileZone
, public PxProfileEventBufferClient
{
typedef shdfnd::MutexT<PxProfileWrapperReflectionAllocator<uint8_t> > TMutexType;
typedef PxProfileHashMap<const char*, uint32_t> TNameToEvtIndexMap;
//ensure we don't reuse event ids.
typedef PxProfileHashMap<uint16_t, const char*> TEvtIdToNameMap;
typedef TMutexType::ScopedLock TLockType;
const char* mName;
mutable TMutexType mMutex;
PxProfileArray<PxProfileEventName> mEventNames;
// to avoid locking, read-only and read-write map exist
TNameToEvtIndexMap mNameToEvtIndexMapR;
TNameToEvtIndexMap mNameToEvtIndexMapRW;
//ensure we don't reuse event ids.
TEvtIdToNameMap mEvtIdToNameMap;
PxProfileZoneManager* mProfileZoneManager;
PxProfileArray<PxProfileZoneClient*> mZoneClients;
volatile bool mEventsActive;
PX_NOCOPY(ZoneImpl<TNameProvider>)
public:
ZoneImpl( PxAllocatorCallback* inAllocator, const char* inName, uint32_t bufferSize = 0x10000 /*64k*/, const TNameProvider& inProvider = TNameProvider() )
: TZoneEventBufferType( inAllocator, bufferSize, PxDefaultContextProvider(), NULL, PxProfileNullEventFilter() )
, mName( inName )
, mMutex( PxProfileWrapperReflectionAllocator<uint8_t>( mWrapper ) )
, mEventNames( mWrapper )
, mNameToEvtIndexMapR( mWrapper )
, mNameToEvtIndexMapRW( mWrapper )
, mEvtIdToNameMap( mWrapper )
, mProfileZoneManager( NULL )
, mZoneClients( mWrapper )
, mEventsActive( false )
{
TZoneEventBufferType::setBufferMutex( &mMutex );
//Initialize the event name structure with existing names from the name provider.
PxProfileNames theNames( inProvider.getProfileNames() );
for ( uint32_t idx = 0; idx < theNames.eventCount; ++idx )
{
const PxProfileEventName& theName (theNames.events[idx]);
doAddName( theName.name, theName.eventId.eventId, theName.eventId.compileTimeEnabled );
}
TZoneEventBufferType::addClient( *this );
}
virtual ~ZoneImpl() {
if ( mProfileZoneManager != NULL )
mProfileZoneManager->removeProfileZone( *this );
mProfileZoneManager = NULL;
TZoneEventBufferType::removeClient( *this );
}
void doAddName( const char* inName, uint16_t inEventId, bool inCompileTimeEnabled )
{
TLockType theLocker( mMutex );
mEvtIdToNameMap.insert( inEventId, inName );
uint32_t idx = static_cast<uint32_t>( mEventNames.size() );
mNameToEvtIndexMapRW.insert( inName, idx );
mEventNames.pushBack( PxProfileEventName( inName, PxProfileEventId( inEventId, inCompileTimeEnabled ) ) );
}
virtual void flushEventIdNameMap()
{
// copy the RW map into R map
if (mNameToEvtIndexMapRW.size())
{
for (TNameToEvtIndexMap::Iterator iter = mNameToEvtIndexMapRW.getIterator(); !iter.done(); ++iter)
{
mNameToEvtIndexMapR.insert(iter->first, iter->second);
}
mNameToEvtIndexMapRW.clear();
}
}
virtual uint16_t getEventIdForName( const char* inName )
{
return getEventIdsForNames( &inName, 1 );
}
virtual uint16_t getEventIdsForNames( const char** inNames, uint32_t inLen )
{
if ( inLen == 0 )
return 0;
// search the read-only map first
const TNameToEvtIndexMap::Entry* theEntry( mNameToEvtIndexMapR.find( inNames[0] ) );
if ( theEntry )
return mEventNames[theEntry->second].eventId;
TLockType theLocker(mMutex);
const TNameToEvtIndexMap::Entry* theReEntry(mNameToEvtIndexMapRW.find(inNames[0]));
if (theReEntry)
return mEventNames[theReEntry->second].eventId;
//Else git R dun.
uint16_t nameSize = static_cast<uint16_t>( mEventNames.size() );
//We don't allow 0 as an event id.
uint16_t eventId = nameSize;
//Find a contiguous set of unique event ids
bool foundAnEventId = false;
do
{
foundAnEventId = false;
++eventId;
for ( uint16_t idx = 0; idx < inLen && foundAnEventId == false; ++idx )
foundAnEventId = mEvtIdToNameMap.find( uint16_t(eventId + idx) ) != NULL;
}
while( foundAnEventId );
uint32_t clientCount = mZoneClients.size();
for ( uint16_t nameIdx = 0; nameIdx < inLen; ++nameIdx )
{
uint16_t newId = uint16_t(eventId + nameIdx);
doAddName( inNames[nameIdx], newId, true );
for( uint32_t clientIdx =0; clientIdx < clientCount; ++clientIdx )
mZoneClients[clientIdx]->handleEventAdded( PxProfileEventName( inNames[nameIdx], PxProfileEventId( newId ) ) );
}
return eventId;
}
virtual void setProfileZoneManager(PxProfileZoneManager* inMgr)
{
mProfileZoneManager = inMgr;
}
virtual PxProfileZoneManager* getProfileZoneManager()
{
return mProfileZoneManager;
}
const char* getName() { return mName; }
PxProfileEventBufferClient* getEventBufferClient() { return this; }
//SDK implementation
void addClient( PxProfileZoneClient& inClient )
{
TLockType lock( mMutex );
mZoneClients.pushBack( &inClient );
mEventsActive = true;
}
void removeClient( PxProfileZoneClient& inClient )
{
TLockType lock( mMutex );
for ( uint32_t idx =0; idx < mZoneClients.size(); ++idx )
{
if (mZoneClients[idx] == &inClient )
{
inClient.handleClientRemoved();
mZoneClients.replaceWithLast( idx );
break;
}
}
mEventsActive = mZoneClients.size() != 0;
}
virtual bool hasClients() const
{
return mEventsActive;
}
virtual PxProfileNames getProfileNames() const
{
TLockType theLocker( mMutex );
const PxProfileEventName* theNames = mEventNames.begin();
uint32_t theEventCount = uint32_t(mEventNames.size());
return PxProfileNames( theEventCount, theNames );
}
virtual void release()
{
PX_PROFILE_DELETE( mWrapper.getAllocator(), this );
}
//Implementation chaining the buffer flush to our clients
virtual void handleBufferFlush( const uint8_t* inData, uint32_t inLength )
{
TLockType theLocker( mMutex );
uint32_t clientCount = mZoneClients.size();
for( uint32_t idx =0; idx < clientCount; ++idx )
mZoneClients[idx]->handleBufferFlush( inData, inLength );
}
//Happens if something removes all the clients from the manager.
virtual void handleClientRemoved() {}
//Send a profile event, optionally with a context. Events are sorted by thread
//and context in the client side.
virtual void startEvent( uint16_t inId, uint64_t contextId)
{
if( mEventsActive )
{
TZoneEventBufferType::startEvent( inId, contextId );
}
}
virtual void stopEvent( uint16_t inId, uint64_t contextId)
{
if( mEventsActive )
{
TZoneEventBufferType::stopEvent( inId, contextId );
}
}
virtual void startEvent( uint16_t inId, uint64_t contextId, uint32_t threadId)
{
if( mEventsActive )
{
TZoneEventBufferType::startEvent( inId, contextId, threadId );
}
}
virtual void stopEvent( uint16_t inId, uint64_t contextId, uint32_t threadId )
{
if( mEventsActive )
{
TZoneEventBufferType::stopEvent( inId, contextId, threadId );
}
}
virtual void atEvent(uint16_t inId, uint64_t contextId, uint32_t threadId, uint64_t start, uint64_t stop)
{
if (mEventsActive)
{
TZoneEventBufferType::startEvent(inId, threadId, contextId, 0, 0, start);
TZoneEventBufferType::stopEvent(inId, threadId, contextId, 0, 0, stop);
}
}
/**
* Set an specific events value. This is different than the profiling value
* for the event; it is a value recorded and kept around without a timestamp associated
* with it. This value is displayed when the event itself is processed.
*/
virtual void eventValue( uint16_t inId, uint64_t contextId, int64_t inValue )
{
if( mEventsActive )
{
TZoneEventBufferType::eventValue( inId, contextId, inValue );
}
}
virtual void flushProfileEvents()
{
TZoneEventBufferType::flushProfileEvents();
}
};
}}
#endif // PXPVDSDK_PXPROFILEZONEIMPL_H

View File

@ -0,0 +1,155 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
#ifndef PXPVDSDK_PXPROFILEZONEMANAGER_H
#define PXPVDSDK_PXPROFILEZONEMANAGER_H
#include "PxProfileEventSender.h"
#include "PxProfileEventNames.h"
namespace physx {
class PxAllocatorCallback;
namespace profile {
class PxProfileZone;
class PxProfileNameProvider;
/**
\brief Profile zone handler for zone add/remove notification.
*/
class PxProfileZoneHandler
{
protected:
virtual ~PxProfileZoneHandler(){}
public:
/**
\brief On zone added notification
\note Not a threadsafe call; handlers are expected to be able to handle
this from any thread.
\param inSDK Added zone.
*/
virtual void onZoneAdded( PxProfileZone& inSDK ) = 0;
/**
\brief On zone removed notification
\note Not a threadsafe call; handlers are expected to be able to handle
this from any thread.
\param inSDK removed zone.
*/
virtual void onZoneRemoved( PxProfileZone& inSDK ) = 0;
};
/**
\brief The profiling system was setup in the expectation that there would be several
systems that each had its own island of profile information. PhysX, client code,
and APEX would be the first examples of these. Each one of these islands is represented
by a profile zone.
The Manager is a singleton-like object where all these different systems can be registered
so that clients of the profiling system can have one point to capture *all* profiling events.
Flushing the manager implies that you want to loop through all the profile zones and flush
each one.
@see PxProfileEventFlusher
*/
class PxProfileZoneManager
: public PxProfileEventFlusher //Tell all SDK's to flush their queue of profile events.
{
protected:
virtual ~PxProfileZoneManager(){}
public:
/**
\brief Add new profile zone for the manager.
\note Threadsafe call, can be done from any thread. Handlers that are already connected
will get a new callback on the current thread.
\param inSDK Profile zone to add.
*/
virtual void addProfileZone( PxProfileZone& inSDK ) = 0;
/**
\brief Removes profile zone from the manager.
\note Threadsafe call, can be done from any thread. Handlers that are already connected
will get a new callback on the current thread.
\param inSDK Profile zone to remove.
*/
virtual void removeProfileZone( PxProfileZone& inSDK ) = 0;
/**
\brief Add profile zone handler callback for the profile zone notifications.
\note Threadsafe call. The new handler will immediately be notified about all
known SDKs.
\param inHandler Profile zone handler to add.
*/
virtual void addProfileZoneHandler( PxProfileZoneHandler& inHandler ) = 0;
/**
\brief Removes profile zone handler callback for the profile zone notifications.
\note Threadsafe call. The new handler will immediately be notified about all
known SDKs.
\param inHandler Profile zone handler to remove.
*/
virtual void removeProfileZoneHandler( PxProfileZoneHandler& inHandler ) = 0;
/**
\brief Create a new profile zone. This means you don't need access to a PxFoundation to
create your profile zone object, and your object is automatically registered with
the profile zone manager.
You still need to release your object when you are finished with it.
\param inSDKName Name of the SDK object.
\param inNames Option set of event id to name mappings.
\param inEventBufferByteSize rough maximum size of the event buffer. May exceed this size
by sizeof one event. When full an immediate call to all listeners is made.
*/
virtual PxProfileZone& createProfileZone( const char* inSDKName, PxProfileNames inNames = PxProfileNames(), uint32_t inEventBufferByteSize = 0x4000 /*16k*/ ) = 0;
/**
\brief Releases the profile manager instance.
*/
virtual void release() = 0;
/**
\brief Create the profile zone manager.
\param inAllocatorCallback Allocator callback.
*/
static PxProfileZoneManager& createProfileZoneManager(PxAllocatorCallback* inAllocatorCallback );
};
} }
#endif // PXPVDSDK_PXPROFILEZONEMANAGER_H

View File

@ -0,0 +1,173 @@
//
// 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-2021 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_PXPROFILEZONEMANAGERIMPL_H
#define PXPVDSDK_PXPROFILEZONEMANAGERIMPL_H
#include "PxProfileZoneManager.h"
#include "PxProfileScopedMutexLock.h"
#include "PxPvdProfileZone.h"
#include "PxProfileAllocatorWrapper.h"
#include "PsArray.h"
#include "PsMutex.h"
namespace physx { namespace profile {
struct NullEventNameProvider : public PxProfileNameProvider
{
virtual PxProfileNames getProfileNames() const { return PxProfileNames( 0, 0 ); }
};
class ZoneManagerImpl : public PxProfileZoneManager
{
typedef ScopedLockImpl<shdfnd::Mutex> TScopedLockType;
PxProfileAllocatorWrapper mWrapper;
PxProfileArray<PxProfileZone*> mZones;
PxProfileArray<PxProfileZoneHandler*> mHandlers;
shdfnd::Mutex mMutex;
ZoneManagerImpl( const ZoneManagerImpl& inOther );
ZoneManagerImpl& operator=( const ZoneManagerImpl& inOther );
public:
ZoneManagerImpl(PxAllocatorCallback* inFoundation)
: mWrapper( inFoundation )
, mZones( mWrapper )
, mHandlers( mWrapper )
{}
virtual ~ZoneManagerImpl()
{
//This assert would mean that a profile zone is outliving us.
//This will cause a crash when the profile zone is released.
PX_ASSERT( mZones.size() == 0 );
while( mZones.size() )
removeProfileZone( *mZones.back() );
}
virtual void addProfileZone( PxProfileZone& inSDK )
{
TScopedLockType lock( &mMutex );
if ( inSDK.getProfileZoneManager() != NULL )
{
if ( inSDK.getProfileZoneManager() == this )
return;
else //there must be two managers in the system somehow.
{
PX_ASSERT( false );
inSDK.getProfileZoneManager()->removeProfileZone( inSDK );
}
}
mZones.pushBack( &inSDK );
inSDK.setProfileZoneManager( this );
for ( uint32_t idx =0; idx < mHandlers.size(); ++idx )
mHandlers[idx]->onZoneAdded( inSDK );
}
virtual void removeProfileZone( PxProfileZone& inSDK )
{
TScopedLockType lock( &mMutex );
if ( inSDK.getProfileZoneManager() == NULL )
return;
else if ( inSDK.getProfileZoneManager() != this )
{
PX_ASSERT( false );
inSDK.getProfileZoneManager()->removeProfileZone( inSDK );
return;
}
inSDK.setProfileZoneManager( NULL );
for ( uint32_t idx = 0; idx < mZones.size(); ++idx )
{
if ( mZones[idx] == &inSDK )
{
for ( uint32_t handler =0; handler < mHandlers.size(); ++handler )
mHandlers[handler]->onZoneRemoved( inSDK );
mZones.replaceWithLast( idx );
}
}
}
virtual void flushProfileEvents()
{
uint32_t sdkCount = mZones.size();
for ( uint32_t idx = 0; idx < sdkCount; ++idx )
mZones[idx]->flushProfileEvents();
}
virtual void addProfileZoneHandler( PxProfileZoneHandler& inHandler )
{
TScopedLockType lock( &mMutex );
mHandlers.pushBack( &inHandler );
for ( uint32_t idx = 0; idx < mZones.size(); ++idx )
inHandler.onZoneAdded( *mZones[idx] );
}
virtual void removeProfileZoneHandler( PxProfileZoneHandler& inHandler )
{
TScopedLockType lock( &mMutex );
for( uint32_t idx = 0; idx < mZones.size(); ++idx )
inHandler.onZoneRemoved( *mZones[idx] );
for( uint32_t idx = 0; idx < mHandlers.size(); ++idx )
{
if ( mHandlers[idx] == &inHandler )
mHandlers.replaceWithLast( idx );
}
}
virtual PxProfileZone& createProfileZone( const char* inSDKName, PxProfileNameProvider* inProvider, uint32_t inEventBufferByteSize )
{
NullEventNameProvider nullProvider;
if ( inProvider == NULL )
inProvider = &nullProvider;
return createProfileZone( inSDKName, inProvider->getProfileNames(), inEventBufferByteSize );
}
virtual PxProfileZone& createProfileZone( const char* inSDKName, PxProfileNames inNames, uint32_t inEventBufferByteSize )
{
PxProfileZone& retval( PxProfileZone::createProfileZone( &mWrapper.getAllocator(), inSDKName, inNames, inEventBufferByteSize ) );
addProfileZone( retval );
return retval;
}
virtual void release()
{
PX_PROFILE_DELETE( mWrapper.getAllocator(), this );
}
};
} }
#endif // PXPVDSDK_PXPROFILEZONEMANAGERIMPL_H

View File

@ -0,0 +1,46 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "PxPvdImpl.h"
namespace physx
{
namespace pvdsdk
{
ForwardingAllocator gForwardingAllocator;
PxAllocatorCallback* gPvdAllocatorCallback = &gForwardingAllocator;
} // namespace pvdsdk
PxPvd* PxCreatePvd(PxFoundation& foundation)
{
pvdsdk::gPvdAllocatorCallback = &foundation.getAllocatorCallback();
pvdsdk::PvdImpl::initialize();
return pvdsdk::PvdImpl::getInstance();
}
} // namespace physx

View File

@ -0,0 +1,132 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
#ifndef PXPVDSDK_PXPVDBITS_H
#define PXPVDSDK_PXPVDBITS_H
#include "PxPvdObjectModelBaseTypes.h"
namespace physx
{
namespace pvdsdk
{
// Marshallers cannot assume src is aligned, but they can assume dest is aligned.
typedef void (*TSingleMarshaller)(const uint8_t* src, uint8_t* dest);
typedef void (*TBlockMarshaller)(const uint8_t* src, uint8_t* dest, uint32_t numItems);
template <uint8_t ByteCount>
static inline void doSwapBytes(uint8_t* __restrict inData)
{
for(uint32_t idx = 0; idx < ByteCount / 2; ++idx)
{
uint32_t endIdx = ByteCount - idx - 1;
uint8_t theTemp = inData[idx];
inData[idx] = inData[endIdx];
inData[endIdx] = theTemp;
}
}
template <uint8_t ByteCount>
static inline void doSwapBytes(uint8_t* __restrict inData, uint32_t itemCount)
{
uint8_t* end = inData + itemCount * ByteCount;
for(; inData < end; inData += ByteCount)
doSwapBytes<ByteCount>(inData);
}
static inline void swapBytes(uint8_t* __restrict dataPtr, uint32_t numBytes, uint32_t itemWidth)
{
uint32_t numItems = numBytes / itemWidth;
switch(itemWidth)
{
case 1:
break;
case 2:
doSwapBytes<2>(dataPtr, numItems);
break;
case 4:
doSwapBytes<4>(dataPtr, numItems);
break;
case 8:
doSwapBytes<8>(dataPtr, numItems);
break;
case 16:
doSwapBytes<16>(dataPtr, numItems);
break;
default:
PX_ASSERT(false);
break;
}
}
static inline void swapBytes(uint8_t&)
{
}
static inline void swapBytes(int8_t&)
{
}
static inline void swapBytes(uint16_t& inData)
{
doSwapBytes<2>(reinterpret_cast<uint8_t*>(&inData));
}
static inline void swapBytes(int16_t& inData)
{
doSwapBytes<2>(reinterpret_cast<uint8_t*>(&inData));
}
static inline void swapBytes(uint32_t& inData)
{
doSwapBytes<4>(reinterpret_cast<uint8_t*>(&inData));
}
static inline void swapBytes(int32_t& inData)
{
doSwapBytes<4>(reinterpret_cast<uint8_t*>(&inData));
}
static inline void swapBytes(float& inData)
{
doSwapBytes<4>(reinterpret_cast<uint8_t*>(&inData));
}
static inline void swapBytes(uint64_t& inData)
{
doSwapBytes<8>(reinterpret_cast<uint8_t*>(&inData));
}
static inline void swapBytes(int64_t& inData)
{
doSwapBytes<8>(reinterpret_cast<uint8_t*>(&inData));
}
static inline void swapBytes(double& inData)
{
doSwapBytes<8>(reinterpret_cast<uint8_t*>(&inData));
}
static inline bool checkLength(const uint8_t* inStart, const uint8_t* inStop, uint32_t inLength)
{
return static_cast<uint32_t>(inStop - inStart) >= inLength;
}
}
}
#endif // PXPVDSDK_PXPVDBITS_H

View File

@ -0,0 +1,126 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
#ifndef PXPVDSDK_PXPVDBYTESTREAMS_H
#define PXPVDSDK_PXPVDBYTESTREAMS_H
#include "PxPvdObjectModelBaseTypes.h"
namespace physx
{
namespace pvdsdk
{
static inline uint32_t strLen(const char* inStr)
{
uint32_t len = 0;
if(inStr)
{
while(*inStr)
{
++len;
++inStr;
}
}
return len;
}
class PvdInputStream
{
protected:
virtual ~PvdInputStream()
{
}
public:
// Return false if you can't write the number of bytes requested
// But make an absolute best effort to read the data...
virtual bool read(uint8_t* buffer, uint32_t& len) = 0;
template <typename TDataType>
bool read(TDataType* buffer, uint32_t numItems)
{
uint32_t expected = numItems;
uint32_t amountToRead = numItems * sizeof(TDataType);
read(reinterpret_cast<uint8_t*>(buffer), amountToRead);
numItems = amountToRead / sizeof(TDataType);
PX_ASSERT(numItems == expected);
return expected == numItems;
}
template <typename TDataType>
PvdInputStream& operator>>(TDataType& data)
{
uint32_t dataSize = static_cast<uint32_t>(sizeof(TDataType));
bool success = read(reinterpret_cast<uint8_t*>(&data), dataSize);
// PX_ASSERT( success );
// PX_ASSERT( dataSize == sizeof( data ) );
(void)success;
return *this;
}
};
class PvdOutputStream
{
protected:
virtual ~PvdOutputStream()
{
}
public:
// Return false if you can't write the number of bytes requested
// But make an absolute best effort to write the data...
virtual bool write(const uint8_t* buffer, uint32_t len) = 0;
virtual bool directCopy(PvdInputStream& inStream, uint32_t len) = 0;
template <typename TDataType>
bool write(const TDataType* buffer, uint32_t numItems)
{
return write(reinterpret_cast<const uint8_t*>(buffer), numItems * sizeof(TDataType));
}
template <typename TDataType>
PvdOutputStream& operator<<(const TDataType& data)
{
bool success = write(reinterpret_cast<const uint8_t*>(&data), sizeof(data));
PX_ASSERT(success);
(void)success;
return *this;
}
PvdOutputStream& operator<<(const char* inString)
{
if(inString && *inString)
{
uint32_t len(strLen(inString));
write(inString, len);
}
return *this;
}
};
}
}
#endif // PXPVDSDK_PXPVDBYTESTREAMS_H

View File

@ -0,0 +1,55 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
#ifndef PXPVDSDK_PXPVDCOMMSTREAMEVENTSINK_H
#define PXPVDSDK_PXPVDCOMMSTREAMEVENTSINK_H
#include "PxPvdObjectModelBaseTypes.h"
#include "PxPvdCommStreamEvents.h"
#include "PxPvdCommStreamTypes.h"
namespace physx
{
namespace pvdsdk
{
class PvdCommStreamEventSink
{
public:
template <typename TStreamType>
static void writeStreamEvent(const EventSerializeable& evt, PvdCommStreamEventTypes::Enum evtType, TStreamType& stream)
{
EventStreamifier<TStreamType> streamifier_concrete(stream);
PvdEventSerializer& streamifier(streamifier_concrete);
streamifier.streamify(evtType);
const_cast<EventSerializeable&>(evt).serialize(streamifier);
}
};
} // pvd
} // physx
#endif // PXPVDSDK_PXPVDCOMMSTREAMEVENTSINK_H

View File

@ -0,0 +1,987 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
#ifndef PXPVDSDK_PXPVDCOMMSTREAMEVENTS_H
#define PXPVDSDK_PXPVDCOMMSTREAMEVENTS_H
#include "foundation/PxVec3.h"
#include "foundation/PxFlags.h"
#include "PxPvdObjectModelBaseTypes.h"
#include "PsTime.h"
namespace physx
{
namespace pvdsdk
{
struct CommStreamFlagTypes
{
enum Enum
{
Is64BitPtr = 1
};
};
typedef PxFlags<CommStreamFlagTypes::Enum, uint32_t> CommStreamFlags;
template <typename TDataType>
struct PvdCommVariableSizedEventCheck
{
bool variable_size_check;
};
// Pick out the events that are possibly very large.
// This helps us keep our buffers close to the size the user requested.
#define DECLARE_TYPE_VARIABLE_SIZED(type) \
template <> \
struct PvdCommVariableSizedEventCheck<type> \
{ \
uint32_t variable_size_check; \
};
struct NameHandleValue;
struct StreamPropMessageArg;
struct StringHandleEvent;
struct CreateClass;
struct DeriveClass;
struct CreateProperty;
struct CreatePropertyMessage;
struct CreateInstance;
struct SetPropertyValue;
struct BeginSetPropertyValue;
struct AppendPropertyValueData;
struct EndSetPropertyValue;
struct SetPropertyMessage;
struct BeginPropertyMessageGroup;
struct SendPropertyMessageFromGroup;
struct EndPropertyMessageGroup;
struct CreateDestroyInstanceProperty;
struct PushBackObjectRef;
struct RemoveObjectRef;
struct BeginSection;
struct EndSection;
struct SetPickable;
struct SetColor;
struct SetIsTopLevel;
struct SetCamera;
struct AddProfileZone;
struct AddProfileZoneEvent;
struct StreamEndEvent;
struct ErrorMessage;
struct OriginShift;
struct DestroyInstance;
#define DECLARE_COMM_STREAM_EVENTS \
\
DECLARE_PVD_COMM_STREAM_EVENT(StringHandleEvent) \
DECLARE_PVD_COMM_STREAM_EVENT(CreateClass) \
DECLARE_PVD_COMM_STREAM_EVENT(DeriveClass) \
DECLARE_PVD_COMM_STREAM_EVENT(CreateProperty) \
DECLARE_PVD_COMM_STREAM_EVENT(CreatePropertyMessage) \
DECLARE_PVD_COMM_STREAM_EVENT(CreateInstance) \
DECLARE_PVD_COMM_STREAM_EVENT(SetPropertyValue) \
DECLARE_PVD_COMM_STREAM_EVENT(BeginSetPropertyValue) \
DECLARE_PVD_COMM_STREAM_EVENT(AppendPropertyValueData) \
DECLARE_PVD_COMM_STREAM_EVENT(EndSetPropertyValue) \
DECLARE_PVD_COMM_STREAM_EVENT(SetPropertyMessage) \
DECLARE_PVD_COMM_STREAM_EVENT(BeginPropertyMessageGroup) \
DECLARE_PVD_COMM_STREAM_EVENT(SendPropertyMessageFromGroup) \
DECLARE_PVD_COMM_STREAM_EVENT(EndPropertyMessageGroup) \
DECLARE_PVD_COMM_STREAM_EVENT(DestroyInstance) \
DECLARE_PVD_COMM_STREAM_EVENT(PushBackObjectRef) \
DECLARE_PVD_COMM_STREAM_EVENT(RemoveObjectRef) \
DECLARE_PVD_COMM_STREAM_EVENT(BeginSection) \
DECLARE_PVD_COMM_STREAM_EVENT(EndSection) \
DECLARE_PVD_COMM_STREAM_EVENT(SetPickable) \
DECLARE_PVD_COMM_STREAM_EVENT(SetColor) \
DECLARE_PVD_COMM_STREAM_EVENT(SetIsTopLevel) \
DECLARE_PVD_COMM_STREAM_EVENT(SetCamera) \
DECLARE_PVD_COMM_STREAM_EVENT(AddProfileZone) \
DECLARE_PVD_COMM_STREAM_EVENT(AddProfileZoneEvent) \
DECLARE_PVD_COMM_STREAM_EVENT(StreamEndEvent) \
DECLARE_PVD_COMM_STREAM_EVENT(ErrorMessage) \
DECLARE_PVD_COMM_STREAM_EVENT_NO_COMMA(OriginShift)
struct PvdCommStreamEventTypes
{
enum Enum
{
Unknown = 0,
#define DECLARE_PVD_COMM_STREAM_EVENT(x) x,
#define DECLARE_PVD_COMM_STREAM_EVENT_NO_COMMA(x) x
DECLARE_COMM_STREAM_EVENTS
#undef DECLARE_PVD_COMM_STREAM_EVENT_NO_COMMA
#undef DECLARE_PVD_COMM_STREAM_EVENT
, Last
};
};
template <typename TDataType>
struct DatatypeToCommEventType
{
bool compile_error;
};
template <PvdCommStreamEventTypes::Enum TEnumType>
struct CommEventTypeToDatatype
{
bool compile_error;
};
#define DECLARE_PVD_COMM_STREAM_EVENT(x) \
template <> \
struct DatatypeToCommEventType<x> \
{ \
enum Enum \
{ \
EEventTypeMap = PvdCommStreamEventTypes::x \
}; \
}; \
template <> \
struct CommEventTypeToDatatype<PvdCommStreamEventTypes::x> \
{ \
typedef x TEventType; \
};
#define DECLARE_PVD_COMM_STREAM_EVENT_NO_COMMA(x) \
\
template<> struct DatatypeToCommEventType<x> \
{ \
enum Enum \
{ \
EEventTypeMap = PvdCommStreamEventTypes::x \
}; \
}; \
\
template<> struct CommEventTypeToDatatype<PvdCommStreamEventTypes::x> \
{ \
typedef x TEventType; \
};
DECLARE_COMM_STREAM_EVENTS
#undef DECLARE_PVD_COMM_STREAM_EVENT_NO_COMMA
#undef DECLARE_PVD_COMM_STREAM_EVENT
template <typename TDataType>
PvdCommStreamEventTypes::Enum getCommStreamEventType()
{
return static_cast<PvdCommStreamEventTypes::Enum>(DatatypeToCommEventType<TDataType>::EEventTypeMap);
}
struct StreamNamespacedName
{
StringHandle mNamespace; // StringHandle handles
StringHandle mName;
StreamNamespacedName(StringHandle ns = 0, StringHandle nm = 0) : mNamespace(ns), mName(nm)
{
}
};
class EventSerializeable;
class PvdEventSerializer
{
protected:
virtual ~PvdEventSerializer()
{
}
public:
virtual void streamify(uint8_t& val) = 0;
virtual void streamify(uint16_t& val) = 0;
virtual void streamify(uint32_t& val) = 0;
virtual void streamify(float& val) = 0;
virtual void streamify(uint64_t& val) = 0;
virtual void streamify(String& val) = 0;
virtual void streamify(DataRef<const uint8_t>& data) = 0;
virtual void streamify(DataRef<NameHandleValue>& data) = 0;
virtual void streamify(DataRef<StreamPropMessageArg>& data) = 0;
virtual void streamify(DataRef<StringHandle>& data) = 0;
void streamify(StringHandle& hdl)
{
streamify(hdl.mHandle);
}
void streamify(CommStreamFlags& flags)
{
uint32_t val(flags);
streamify(val);
flags = CommStreamFlags(val);
}
void streamify(PvdCommStreamEventTypes::Enum& val)
{
uint8_t detyped = static_cast<uint8_t>(val);
streamify(detyped);
val = static_cast<PvdCommStreamEventTypes::Enum>(detyped);
}
void streamify(PropertyType::Enum& val)
{
uint8_t detyped = static_cast<uint8_t>(val);
streamify(detyped);
val = static_cast<PropertyType::Enum>(detyped);
}
void streamify(bool& val)
{
uint8_t detyped = uint8_t(val ? 1 : 0);
streamify(detyped);
val = detyped ? true : false;
}
void streamify(StreamNamespacedName& name)
{
streamify(name.mNamespace);
streamify(name.mName);
}
void streamify(PvdColor& color)
{
streamify(color.r);
streamify(color.g);
streamify(color.b);
streamify(color.a);
}
void streamify(PxVec3& vec)
{
streamify(vec.x);
streamify(vec.y);
streamify(vec.z);
}
static uint32_t measure(const EventSerializeable& evt);
};
class EventSerializeable
{
protected:
virtual ~EventSerializeable()
{
}
public:
virtual void serialize(PvdEventSerializer& serializer) = 0;
};
/** Numbers generated from random.org
129919156 17973702 401496246 144984007 336950759
907025328 837150850 679717896 601529147 269478202
*/
struct StreamInitialization : public EventSerializeable
{
static uint32_t getStreamId()
{
return 837150850;
}
static uint32_t getStreamVersion()
{
return 1;
}
uint32_t mStreamId;
uint32_t mStreamVersion;
uint64_t mTimestampNumerator;
uint64_t mTimestampDenominator;
CommStreamFlags mStreamFlags;
StreamInitialization()
: mStreamId(getStreamId())
, mStreamVersion(getStreamVersion())
, mTimestampNumerator(physx::shdfnd::Time::getCounterFrequency().mNumerator * 10)
, mTimestampDenominator(physx::shdfnd::Time::getCounterFrequency().mDenominator)
, mStreamFlags(sizeof(void*) == 4 ? 0 : 1)
{
}
void serialize(PvdEventSerializer& s)
{
s.streamify(mStreamId);
s.streamify(mStreamVersion);
s.streamify(mTimestampNumerator);
s.streamify(mTimestampDenominator);
s.streamify(mStreamFlags);
}
};
struct EventGroup : public EventSerializeable
{
uint32_t mDataSize; // in bytes, data directly follows this header
uint32_t mNumEvents;
uint64_t mStreamId;
uint64_t mTimestamp;
EventGroup(uint32_t dataSize = 0, uint32_t numEvents = 0, uint64_t streamId = 0, uint64_t ts = 0)
: mDataSize(dataSize), mNumEvents(numEvents), mStreamId(streamId), mTimestamp(ts)
{
}
void serialize(PvdEventSerializer& s)
{
s.streamify(mDataSize);
s.streamify(mNumEvents);
s.streamify(mStreamId);
s.streamify(mTimestamp);
}
};
struct StringHandleEvent : public EventSerializeable
{
String mString;
uint32_t mHandle;
StringHandleEvent(String str, uint32_t hdl) : mString(str), mHandle(hdl)
{
}
StringHandleEvent()
{
}
void serialize(PvdEventSerializer& s)
{
s.streamify(mString);
s.streamify(mHandle);
}
};
DECLARE_TYPE_VARIABLE_SIZED(StringHandleEvent)
typedef uint64_t Timestamp;
struct CreateClass : public EventSerializeable
{
StreamNamespacedName mName;
CreateClass(StreamNamespacedName nm) : mName(nm)
{
}
CreateClass()
{
}
void serialize(PvdEventSerializer& s)
{
s.streamify(mName);
}
};
struct DeriveClass : public EventSerializeable
{
StreamNamespacedName mParent;
StreamNamespacedName mChild;
DeriveClass(StreamNamespacedName p, StreamNamespacedName c) : mParent(p), mChild(c)
{
}
DeriveClass()
{
}
void serialize(PvdEventSerializer& s)
{
s.streamify(mParent);
s.streamify(mChild);
}
};
struct NameHandleValue : public EventSerializeable
{
StringHandle mName;
uint32_t mValue;
NameHandleValue(StringHandle name, uint32_t val) : mName(name), mValue(val)
{
}
NameHandleValue()
{
}
void serialize(PvdEventSerializer& s)
{
s.streamify(mName);
s.streamify(mValue);
}
};
/*virtual PvdError createProperty( StreamNamespacedName clsName, StringHandle name, StringHandle semantic
, StreamNamespacedName dtypeName, PropertyType::Enum propertyType
, DataRef<NamedValue> values = DataRef<NamedValue>() ) = 0; */
struct CreateProperty : public EventSerializeable
{
StreamNamespacedName mClass;
StringHandle mName;
StringHandle mSemantic;
StreamNamespacedName mDatatypeName;
PropertyType::Enum mPropertyType;
DataRef<NameHandleValue> mValues;
CreateProperty(StreamNamespacedName cls, StringHandle name, StringHandle semantic, StreamNamespacedName dtypeName,
PropertyType::Enum ptype, DataRef<NameHandleValue> values)
: mClass(cls), mName(name), mSemantic(semantic), mDatatypeName(dtypeName), mPropertyType(ptype), mValues(values)
{
}
CreateProperty()
{
}
void serialize(PvdEventSerializer& s)
{
s.streamify(mClass);
s.streamify(mName);
s.streamify(mSemantic);
s.streamify(mDatatypeName);
s.streamify(mPropertyType);
s.streamify(mValues);
}
};
struct StreamPropMessageArg : public EventSerializeable
{
StringHandle mPropertyName;
StreamNamespacedName mDatatypeName;
uint32_t mMessageOffset;
uint32_t mByteSize;
StreamPropMessageArg(StringHandle pname, StreamNamespacedName dtypeName, uint32_t offset, uint32_t byteSize)
: mPropertyName(pname), mDatatypeName(dtypeName), mMessageOffset(offset), mByteSize(byteSize)
{
}
StreamPropMessageArg()
{
}
void serialize(PvdEventSerializer& s)
{
s.streamify(mPropertyName);
s.streamify(mDatatypeName);
s.streamify(mMessageOffset);
s.streamify(mByteSize);
}
};
/*
virtual PvdError createPropertyMessage( StreamNamespacedName cls, StreamNamespacedName msgName
, DataRef<PropertyMessageArg> entries, uint32_t messageSizeInBytes ) =
0;*/
struct CreatePropertyMessage : public EventSerializeable
{
StreamNamespacedName mClass;
StreamNamespacedName mMessageName;
DataRef<StreamPropMessageArg> mMessageEntries;
uint32_t mMessageByteSize;
CreatePropertyMessage(StreamNamespacedName cls, StreamNamespacedName msgName, DataRef<StreamPropMessageArg> propArg,
uint32_t messageByteSize)
: mClass(cls), mMessageName(msgName), mMessageEntries(propArg), mMessageByteSize(messageByteSize)
{
}
CreatePropertyMessage()
{
}
void serialize(PvdEventSerializer& s)
{
s.streamify(mClass);
s.streamify(mMessageName);
s.streamify(mMessageEntries);
s.streamify(mMessageByteSize);
}
};
/**Changing immediate data on instances*/
// virtual PvdError createInstance( StreamNamespacedName cls, uint64_t instance ) = 0;
struct CreateInstance : public EventSerializeable
{
StreamNamespacedName mClass;
uint64_t mInstanceId;
CreateInstance(StreamNamespacedName cls, uint64_t streamId) : mClass(cls), mInstanceId(streamId)
{
}
CreateInstance()
{
}
void serialize(PvdEventSerializer& s)
{
s.streamify(mClass);
s.streamify(mInstanceId);
}
};
// virtual PvdError setPropertyValue( uint64_t instance, StringHandle name, DataRef<const uint8_t> data,
// StreamNamespacedName incomingTypeName ) = 0;
struct SetPropertyValue : public EventSerializeable
{
uint64_t mInstanceId;
StringHandle mPropertyName;
DataRef<const uint8_t> mData;
StreamNamespacedName mIncomingTypeName;
uint32_t mNumItems;
SetPropertyValue(uint64_t instance, StringHandle name, DataRef<const uint8_t> data,
StreamNamespacedName incomingTypeName, uint32_t numItems)
: mInstanceId(instance), mPropertyName(name), mData(data), mIncomingTypeName(incomingTypeName), mNumItems(numItems)
{
}
SetPropertyValue()
{
}
void serializeBeginning(PvdEventSerializer& s)
{
s.streamify(mInstanceId);
s.streamify(mPropertyName);
s.streamify(mIncomingTypeName);
s.streamify(mNumItems);
}
void serialize(PvdEventSerializer& s)
{
serializeBeginning(s);
s.streamify(mData);
}
};
DECLARE_TYPE_VARIABLE_SIZED(SetPropertyValue)
struct BeginSetPropertyValue : public EventSerializeable
{
uint64_t mInstanceId;
StringHandle mPropertyName;
StreamNamespacedName mIncomingTypeName;
BeginSetPropertyValue(uint64_t instance, StringHandle name, StreamNamespacedName incomingTypeName)
: mInstanceId(instance), mPropertyName(name), mIncomingTypeName(incomingTypeName)
{
}
BeginSetPropertyValue()
{
}
void serialize(PvdEventSerializer& s)
{
s.streamify(mInstanceId);
s.streamify(mPropertyName);
s.streamify(mIncomingTypeName);
}
};
// virtual PvdError appendPropertyValueData( DataRef<const uint8_t> data ) = 0;
struct AppendPropertyValueData : public EventSerializeable
{
DataRef<const uint8_t> mData;
uint32_t mNumItems;
AppendPropertyValueData(DataRef<const uint8_t> data, uint32_t numItems) : mData(data), mNumItems(numItems)
{
}
AppendPropertyValueData()
{
}
void serialize(PvdEventSerializer& s)
{
s.streamify(mData);
s.streamify(mNumItems);
}
};
DECLARE_TYPE_VARIABLE_SIZED(AppendPropertyValueData)
// virtual PvdError endSetPropertyValue() = 0;
struct EndSetPropertyValue : public EventSerializeable
{
EndSetPropertyValue()
{
}
void serialize(PvdEventSerializer&)
{
}
};
// virtual PvdError setPropertyMessage( uint64_t instance, StreamNamespacedName msgName, DataRef<const uint8_t> data ) =
// 0;
struct SetPropertyMessage : public EventSerializeable
{
uint64_t mInstanceId;
StreamNamespacedName mMessageName;
DataRef<const uint8_t> mData;
SetPropertyMessage(uint64_t instance, StreamNamespacedName msgName, DataRef<const uint8_t> data)
: mInstanceId(instance), mMessageName(msgName), mData(data)
{
}
SetPropertyMessage()
{
}
void serialize(PvdEventSerializer& s)
{
s.streamify(mInstanceId);
s.streamify(mMessageName);
s.streamify(mData);
}
};
DECLARE_TYPE_VARIABLE_SIZED(SetPropertyMessage)
// virtual PvdError beginPropertyMessageGroup( StreamNamespacedName msgName ) = 0;
struct BeginPropertyMessageGroup : public EventSerializeable
{
StreamNamespacedName mMsgName;
BeginPropertyMessageGroup(StreamNamespacedName msgName) : mMsgName(msgName)
{
}
BeginPropertyMessageGroup()
{
}
void serialize(PvdEventSerializer& s)
{
s.streamify(mMsgName);
}
};
// virtual PvdError sendPropertyMessageFromGroup( uint64_t instance, DataRef<const uint8_t*> data ) = 0;
struct SendPropertyMessageFromGroup : public EventSerializeable
{
uint64_t mInstance;
DataRef<const uint8_t> mData;
SendPropertyMessageFromGroup(uint64_t instance, DataRef<const uint8_t> data) : mInstance(instance), mData(data)
{
}
SendPropertyMessageFromGroup()
{
}
void serialize(PvdEventSerializer& s)
{
s.streamify(mInstance);
s.streamify(mData);
}
};
DECLARE_TYPE_VARIABLE_SIZED(SendPropertyMessageFromGroup)
// virtual PvdError endPropertyMessageGroup() = 0;
struct EndPropertyMessageGroup : public EventSerializeable
{
EndPropertyMessageGroup()
{
}
void serialize(PvdEventSerializer&)
{
}
};
struct PushBackObjectRef : public EventSerializeable
{
uint64_t mInstanceId;
StringHandle mProperty;
uint64_t mObjectRef;
PushBackObjectRef(uint64_t instId, StringHandle prop, uint64_t objRef)
: mInstanceId(instId), mProperty(prop), mObjectRef(objRef)
{
}
PushBackObjectRef()
{
}
void serialize(PvdEventSerializer& s)
{
s.streamify(mInstanceId);
s.streamify(mProperty);
s.streamify(mObjectRef);
}
};
struct RemoveObjectRef : public EventSerializeable
{
uint64_t mInstanceId;
StringHandle mProperty;
uint64_t mObjectRef;
RemoveObjectRef(uint64_t instId, StringHandle prop, uint64_t objRef)
: mInstanceId(instId), mProperty(prop), mObjectRef(objRef)
{
}
RemoveObjectRef()
{
}
void serialize(PvdEventSerializer& s)
{
s.streamify(mInstanceId);
s.streamify(mProperty);
s.streamify(mObjectRef);
}
};
// virtual PvdError destroyInstance( uint64_t key ) = 0;
struct DestroyInstance : public EventSerializeable
{
uint64_t mInstanceId;
DestroyInstance(uint64_t instance) : mInstanceId(instance)
{
}
DestroyInstance()
{
}
void serialize(PvdEventSerializer& s)
{
s.streamify(mInstanceId);
}
};
// virtual PvdError beginSection( uint64_t sectionId, StringHandle name ) = 0;
struct BeginSection : public EventSerializeable
{
uint64_t mSectionId;
StringHandle mName;
Timestamp mTimestamp;
BeginSection(uint64_t sectionId, StringHandle name, uint64_t timestamp)
: mSectionId(sectionId), mName(name), mTimestamp(timestamp)
{
}
BeginSection()
{
}
void serialize(PvdEventSerializer& s)
{
s.streamify(mSectionId);
s.streamify(mName);
s.streamify(mTimestamp);
}
};
// virtual PvdError endSection( uint64_t sectionId, StringHandle name ) = 0;
struct EndSection : public EventSerializeable
{
uint64_t mSectionId;
StringHandle mName;
Timestamp mTimestamp;
EndSection(uint64_t sectionId, StringHandle name, uint64_t timestamp)
: mSectionId(sectionId), mName(name), mTimestamp(timestamp)
{
}
EndSection()
{
}
void serialize(PvdEventSerializer& s)
{
s.streamify(mSectionId);
s.streamify(mName);
s.streamify(mTimestamp);
}
};
// virtual void setPickable( void* instance, bool pickable ) = 0;
struct SetPickable : public EventSerializeable
{
uint64_t mInstanceId;
bool mPickable;
SetPickable(uint64_t instId, bool pick) : mInstanceId(instId), mPickable(pick)
{
}
SetPickable()
{
}
void serialize(PvdEventSerializer& s)
{
s.streamify(mInstanceId);
s.streamify(mPickable);
}
};
// virtual void setColor( void* instance, const PvdColor& color ) = 0;
struct SetColor : public EventSerializeable
{
uint64_t mInstanceId;
PvdColor mColor;
SetColor(uint64_t instId, PvdColor color) : mInstanceId(instId), mColor(color)
{
}
SetColor()
{
}
void serialize(PvdEventSerializer& s)
{
s.streamify(mInstanceId);
s.streamify(mColor);
}
};
// virtual void setColor( void* instance, const PvdColor& color ) = 0;
struct SetIsTopLevel : public EventSerializeable
{
uint64_t mInstanceId;
bool mIsTopLevel;
SetIsTopLevel(uint64_t instId, bool topLevel) : mInstanceId(instId), mIsTopLevel(topLevel)
{
}
SetIsTopLevel() : mIsTopLevel(false)
{
}
void serialize(PvdEventSerializer& s)
{
s.streamify(mInstanceId);
s.streamify(mIsTopLevel);
}
};
struct SetCamera : public EventSerializeable
{
String mName;
PxVec3 mPosition;
PxVec3 mUp;
PxVec3 mTarget;
SetCamera(String name, const PxVec3& pos, const PxVec3& up, const PxVec3& target)
: mName(name), mPosition(pos), mUp(up), mTarget(target)
{
}
SetCamera() : mName(NULL)
{
}
void serialize(PvdEventSerializer& s)
{
s.streamify(mName);
s.streamify(mPosition);
s.streamify(mUp);
s.streamify(mTarget);
}
};
struct ErrorMessage : public EventSerializeable
{
uint32_t mCode;
String mMessage;
String mFile;
uint32_t mLine;
ErrorMessage(uint32_t code, String message, String file, uint32_t line)
: mCode(code), mMessage(message), mFile(file), mLine(line)
{
}
ErrorMessage() : mMessage(NULL), mFile(NULL)
{
}
void serialize(PvdEventSerializer& s)
{
s.streamify(mCode);
s.streamify(mMessage);
s.streamify(mFile);
s.streamify(mLine);
}
};
struct AddProfileZone : public EventSerializeable
{
uint64_t mInstanceId;
String mName;
AddProfileZone(uint64_t iid, String nm) : mInstanceId(iid), mName(nm)
{
}
AddProfileZone() : mName(NULL)
{
}
void serialize(PvdEventSerializer& s)
{
s.streamify(mInstanceId);
s.streamify(mName);
}
};
struct AddProfileZoneEvent : public EventSerializeable
{
uint64_t mInstanceId;
String mName;
uint16_t mEventId;
bool mCompileTimeEnabled;
AddProfileZoneEvent(uint64_t iid, String nm, uint16_t eid, bool cte)
: mInstanceId(iid), mName(nm), mEventId(eid), mCompileTimeEnabled(cte)
{
}
AddProfileZoneEvent()
{
}
void serialize(PvdEventSerializer& s)
{
s.streamify(mInstanceId);
s.streamify(mName);
s.streamify(mEventId);
s.streamify(mCompileTimeEnabled);
}
};
struct StreamEndEvent : public EventSerializeable
{
String mName;
StreamEndEvent() : mName("StreamEnd")
{
}
void serialize(PvdEventSerializer& s)
{
s.streamify(mName);
}
};
struct OriginShift : public EventSerializeable
{
uint64_t mInstanceId;
PxVec3 mShift;
OriginShift(uint64_t iid, const PxVec3& shift) : mInstanceId(iid), mShift(shift)
{
}
OriginShift()
{
}
void serialize(PvdEventSerializer& s)
{
s.streamify(mInstanceId);
s.streamify(mShift);
}
};
} // pvdsdk
} // physx
#endif // PXPVDSDK_PXPVDCOMMSTREAMEVENTS_H

View File

@ -0,0 +1,229 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
#ifndef PXPVDSDK_PXPVDCOMMSTREAMTYPES_H
#define PXPVDSDK_PXPVDCOMMSTREAMTYPES_H
#include "foundation/PxErrorCallback.h"
#include "pvd/PxPvdTransport.h"
#include "PxPvdRenderBuffer.h"
#include "PxPvdObjectModelBaseTypes.h"
#include "PxPvdCommStreamEvents.h"
#include "PxPvdDataStream.h"
#include "PsMutex.h"
namespace physx
{
namespace profile
{
class PxProfileZone;
class PxProfileMemoryEventBuffer;
}
namespace pvdsdk
{
struct PvdErrorMessage;
class PvdObjectModelMetaData;
DEFINE_PVD_TYPE_NAME_MAP(profile::PxProfileZone, "_debugger_", "PxProfileZone")
DEFINE_PVD_TYPE_NAME_MAP(profile::PxProfileMemoryEventBuffer, "_debugger_", "PxProfileMemoryEventBuffer")
DEFINE_PVD_TYPE_NAME_MAP(PvdErrorMessage, "_debugger_", "PvdErrorMessage")
// All event streams are on the 'events' property of objects of these types
static inline NamespacedName getMemoryEventTotalsClassName()
{
return NamespacedName("_debugger", "MemoryEventTotals");
}
class PvdOMMetaDataProvider
{
protected:
virtual ~PvdOMMetaDataProvider()
{
}
public:
virtual void addRef() = 0;
virtual void release() = 0;
virtual PvdObjectModelMetaData& lock() = 0;
virtual void unlock() = 0;
virtual bool createInstance(const NamespacedName& clsName, const void* instance) = 0;
virtual bool isInstanceValid(const void* instance) = 0;
virtual void destroyInstance(const void* instance) = 0;
virtual int32_t getInstanceClassType(const void* instance) = 0;
};
class PvdCommStreamEmbeddedTypes
{
public:
static const char* getProfileEventStreamSemantic()
{
return "profile event stream";
}
static const char* getMemoryEventStreamSemantic()
{
return "memory event stream";
}
static const char* getRendererEventStreamSemantic()
{
return "render event stream";
}
};
class PvdCommStreamEventBufferClient;
template <typename TStreamType>
struct EventStreamifier : public PvdEventSerializer
{
TStreamType& mBuffer;
EventStreamifier(TStreamType& buf) : mBuffer(buf)
{
}
template <typename TDataType>
void write(const TDataType& type)
{
mBuffer.write(reinterpret_cast<const uint8_t*>(&type), sizeof(TDataType));
}
template <typename TDataType>
void write(const TDataType* type, uint32_t count)
{
mBuffer.write(reinterpret_cast<const uint8_t*>(type), count * sizeof(TDataType));
}
void writeRef(DataRef<const uint8_t> data)
{
uint32_t amount = static_cast<uint32_t>(data.size());
write(amount);
write(data.begin(), amount);
}
void writeRef(DataRef<StringHandle> data)
{
uint32_t amount = static_cast<uint32_t>(data.size());
write(amount);
write(data.begin(), amount);
}
template <typename TDataType>
void writeRef(DataRef<TDataType> data)
{
uint32_t amount = static_cast<uint32_t>(data.size());
write(amount);
for(uint32_t idx = 0; idx < amount; ++idx)
{
TDataType& dtype(const_cast<TDataType&>(data[idx]));
dtype.serialize(*this);
}
}
virtual void streamify(uint16_t& val)
{
write(val);
}
virtual void streamify(uint8_t& val)
{
write(val);
}
virtual void streamify(uint32_t& val)
{
write(val);
}
virtual void streamify(float& val)
{
write(val);
}
virtual void streamify(uint64_t& val)
{
write(val);
}
virtual void streamify(PvdDebugText& val)
{
write(val.color);
write(val.position);
write(val.size);
streamify(val.string);
}
virtual void streamify(String& val)
{
uint32_t len = 0;
String temp = nonNull(val);
if(*temp)
len = static_cast<uint32_t>(strlen(temp) + 1);
write(len);
write(val, len);
}
virtual void streamify(DataRef<const uint8_t>& val)
{
writeRef(val);
}
virtual void streamify(DataRef<NameHandleValue>& val)
{
writeRef(val);
}
virtual void streamify(DataRef<StreamPropMessageArg>& val)
{
writeRef(val);
}
virtual void streamify(DataRef<StringHandle>& val)
{
writeRef(val);
}
private:
EventStreamifier& operator=(const EventStreamifier&);
};
struct MeasureStream
{
uint32_t mSize;
MeasureStream() : mSize(0)
{
}
template <typename TDataType>
void write(const TDataType& val)
{
mSize += sizeof(val);
}
template <typename TDataType>
void write(const TDataType*, uint32_t count)
{
mSize += sizeof(TDataType) * count;
}
};
struct DataStreamState
{
enum Enum
{
Open,
SetPropertyValue,
PropertyMessageGroup
};
};
} // pvdsdk
} // physx
#endif // PXPVDSDK_PXPVDCOMMSTREAMTYPES_H

View File

@ -0,0 +1,865 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
#include "foundation/PxAssert.h"
#include "PxPvdCommStreamEventSink.h"
#include "PxPvdDataStreamHelpers.h"
#include "PxPvdObjectModelInternalTypes.h"
#include "PxPvdImpl.h"
#include "PsFoundation.h"
using namespace physx;
using namespace physx::pvdsdk;
using namespace physx::shdfnd;
namespace
{
struct ScopedMetaData
{
PvdOMMetaDataProvider& mProvider;
PvdObjectModelMetaData& mMeta;
ScopedMetaData(PvdOMMetaDataProvider& provider) : mProvider(provider), mMeta(provider.lock())
{
}
~ScopedMetaData()
{
mProvider.unlock();
}
PvdObjectModelMetaData* operator->()
{
return &mMeta;
}
private:
ScopedMetaData& operator=(const ScopedMetaData&);
};
struct PropertyDefinitionHelper : public PvdPropertyDefinitionHelper
{
PvdDataStream* mStream;
PvdOMMetaDataProvider& mProvider;
Array<char> mNameBuffer;
Array<uint32_t> mNameStack;
Array<NamedValue> mNamedValues;
Array<PropertyMessageArg> mPropertyMessageArgs;
PropertyDefinitionHelper(PvdOMMetaDataProvider& provider)
: mStream(NULL)
, mProvider(provider)
, mNameBuffer("PropertyDefinitionHelper::mNameBuffer")
, mNameStack("PropertyDefinitionHelper::mNameStack")
, mNamedValues("PropertyDefinitionHelper::mNamedValues")
, mPropertyMessageArgs("PropertyDefinitionHelper::mPropertyMessageArgs")
{
}
void setStream(PvdDataStream* stream)
{
mStream = stream;
}
inline void appendStrToBuffer(const char* str)
{
if(str == NULL)
return;
size_t strLen = strlen(str);
size_t endBufOffset = mNameBuffer.size();
size_t resizeLen = endBufOffset;
// account for null
if(mNameBuffer.empty())
resizeLen += 1;
else
endBufOffset -= 1;
mNameBuffer.resize(static_cast<uint32_t>(resizeLen + strLen));
char* endPtr = mNameBuffer.begin() + endBufOffset;
PxMemCopy(endPtr, str, static_cast<uint32_t>(strLen));
}
virtual void pushName(const char* nm, const char* appender = ".")
{
size_t nameBufLen = mNameBuffer.size();
mNameStack.pushBack(static_cast<uint32_t>(nameBufLen));
if(mNameBuffer.empty() == false)
appendStrToBuffer(appender);
appendStrToBuffer(nm);
mNameBuffer.back() = 0;
}
virtual void pushBracketedName(const char* inName, const char* leftBracket = "[", const char* rightBracket = "]")
{
size_t nameBufLen = mNameBuffer.size();
mNameStack.pushBack(static_cast<uint32_t>(nameBufLen));
appendStrToBuffer(leftBracket);
appendStrToBuffer(inName);
appendStrToBuffer(rightBracket);
mNameBuffer.back() = 0;
}
virtual void popName()
{
if(mNameStack.empty())
return;
mNameBuffer.resize(static_cast<uint32_t>(mNameStack.back()));
mNameStack.popBack();
if(mNameBuffer.empty() == false)
mNameBuffer.back() = 0;
}
virtual const char* getTopName()
{
if(mNameBuffer.size())
return mNameBuffer.begin();
return "";
}
virtual void clearNameStack()
{
mNameBuffer.clear();
mNameStack.clear();
}
virtual void addNamedValue(const char* name, uint32_t value)
{
mNamedValues.pushBack(NamedValue(name, value));
}
virtual void clearNamedValues()
{
mNamedValues.clear();
}
virtual DataRef<NamedValue> getNamedValues()
{
return DataRef<NamedValue>(mNamedValues.begin(), mNamedValues.size());
}
virtual void createProperty(const NamespacedName& clsName, const char* inSemantic, const NamespacedName& dtypeName,
PropertyType::Enum propType)
{
mStream->createProperty(clsName, getTopName(), inSemantic, dtypeName, propType, getNamedValues());
clearNamedValues();
}
const char* registerStr(const char* str)
{
ScopedMetaData scopedProvider(mProvider);
return scopedProvider->getStringTable().registerStr(str);
}
virtual void addPropertyMessageArg(const NamespacedName& inDatatype, uint32_t inOffset, uint32_t inSize)
{
mPropertyMessageArgs.pushBack(PropertyMessageArg(registerStr(getTopName()), inDatatype, inOffset, inSize));
}
virtual void addPropertyMessage(const NamespacedName& clsName, const NamespacedName& msgName,
uint32_t inStructSizeInBytes)
{
if(mPropertyMessageArgs.empty())
{
PX_ASSERT(false);
return;
}
mStream->createPropertyMessage(
clsName, msgName, DataRef<PropertyMessageArg>(mPropertyMessageArgs.begin(), mPropertyMessageArgs.size()),
inStructSizeInBytes);
}
virtual void clearPropertyMessageArgs()
{
mPropertyMessageArgs.clear();
}
private:
PropertyDefinitionHelper& operator=(const PropertyDefinitionHelper&);
};
class PvdMemPool
{
// Link List
Array<uint8_t*> mMemBuffer;
uint32_t mLength;
uint32_t mBufIndex;
// 4k for one page
static const int BUFFER_LENGTH = 4096;
PX_NOCOPY(PvdMemPool)
public:
PvdMemPool(const char* bufDataName) : mMemBuffer(bufDataName), mLength(0), mBufIndex(0)
{
grow();
}
~PvdMemPool()
{
for(uint32_t i = 0; i < mMemBuffer.size(); i++)
{
PX_FREE(mMemBuffer[i]);
}
}
void grow()
{
if(mBufIndex + 1 < mMemBuffer.size())
{
mBufIndex++;
}
else
{
uint8_t* Buf = reinterpret_cast<uint8_t*>(PX_ALLOC(BUFFER_LENGTH, "PvdMemPool::mMemBuffer.buf"));
mMemBuffer.pushBack(Buf);
mBufIndex = mMemBuffer.size() - 1;
}
mLength = 0;
}
void* allocate(uint32_t length)
{
if(length > uint32_t(BUFFER_LENGTH))
return NULL;
if(length + mLength > uint32_t(BUFFER_LENGTH))
grow();
void* mem = reinterpret_cast<void*>(&mMemBuffer[mBufIndex][mLength]);
mLength += length;
return mem;
}
void clear()
{
mLength = 0;
mBufIndex = 0;
}
};
struct PvdOutStream : public PvdDataStream, public UserAllocated
{
HashMap<String, uint32_t> mStringHashMap;
PvdOMMetaDataProvider& mMetaDataProvider;
Array<uint8_t> mTempBuffer;
PropertyDefinitionHelper mPropertyDefinitionHelper;
DataStreamState::Enum mStreamState;
ClassDescription mSPVClass;
PropertyMessageDescription mMessageDesc;
// Set property value and SetPropertyMessage calls require
// us to write the data out to a separate buffer
// when strings are involved.
ForwardingMemoryBuffer mSPVBuffer;
uint32_t mEventCount;
uint32_t mPropertyMessageSize;
bool mConnected;
uint64_t mStreamId;
Array<PvdCommand*> mPvdCommandArray;
PvdMemPool mPvdCommandPool;
PxPvdTransport& mTransport;
PvdOutStream(PxPvdTransport& transport, PvdOMMetaDataProvider& provider, uint64_t streamId)
: mStringHashMap("PvdOutStream::mStringHashMap")
, mMetaDataProvider(provider)
, mTempBuffer("PvdOutStream::mTempBuffer")
, mPropertyDefinitionHelper(mMetaDataProvider)
, mStreamState(DataStreamState::Open)
, mSPVBuffer("PvdCommStreamBufferedEventSink::mSPVBuffer")
, mEventCount(0)
, mPropertyMessageSize(0)
, mConnected(true)
, mStreamId(streamId)
, mPvdCommandArray("PvdCommStreamBufferedEventSink::mPvdCommandArray")
, mPvdCommandPool("PvdCommStreamBufferedEventSink::mPvdCommandPool")
, mTransport(transport)
{
mPropertyDefinitionHelper.setStream(this);
}
virtual ~PvdOutStream()
{
}
virtual void release()
{
PVD_DELETE(this);
}
StringHandle toStream(String nm)
{
if(nm == NULL || *nm == 0)
return 0;
const HashMap<String, uint32_t>::Entry* entry(mStringHashMap.find(nm));
if(entry)
return entry->second;
ScopedMetaData meta(mMetaDataProvider);
StringHandle hdl = meta->getStringTable().strToHandle(nm);
nm = meta->getStringTable().handleToStr(hdl);
handlePvdEvent(StringHandleEvent(nm, hdl));
mStringHashMap.insert(nm, hdl);
return hdl;
}
StreamNamespacedName toStream(const NamespacedName& nm)
{
return StreamNamespacedName(toStream(nm.mNamespace), toStream(nm.mName));
}
bool isClassExist(const NamespacedName& nm)
{
ScopedMetaData meta(mMetaDataProvider);
return meta->findClass(nm).hasValue();
}
bool createMetaClass(const NamespacedName& nm)
{
ScopedMetaData meta(mMetaDataProvider);
meta->getOrCreateClass(nm);
return true;
}
bool deriveMetaClass(const NamespacedName& parent, const NamespacedName& child)
{
ScopedMetaData meta(mMetaDataProvider);
return meta->deriveClass(parent, child);
}
// You will notice that some functions are #pragma'd out throughout this file.
// This is because they are only called from asserts which means they aren't
// called in release. This causes warnings when building using snc which break
// the build.
#if PX_DEBUG
bool propertyExists(const NamespacedName& nm, String pname)
{
ScopedMetaData meta(mMetaDataProvider);
return meta->findProperty(nm, pname).hasValue();
}
#endif
PvdError boolToError(bool val)
{
if(val)
return PvdErrorType::Success;
return PvdErrorType::NetworkError;
}
// PvdMetaDataStream
virtual PvdError createClass(const NamespacedName& nm)
{
PX_ASSERT(mStreamState == DataStreamState::Open);
#if PX_DEBUG
PX_ASSERT(isClassExist(nm) == false);
#endif
createMetaClass(nm);
return boolToError(handlePvdEvent(CreateClass(toStream(nm))));
}
virtual PvdError deriveClass(const NamespacedName& parent, const NamespacedName& child)
{
PX_ASSERT(mStreamState == DataStreamState::Open);
#if PX_DEBUG
PX_ASSERT(isClassExist(parent));
PX_ASSERT(isClassExist(child));
#endif
deriveMetaClass(parent, child);
return boolToError(handlePvdEvent(DeriveClass(toStream(parent), toStream(child))));
}
template <typename TDataType>
TDataType* allocTemp(uint32_t numItems)
{
uint32_t desiredBytes = numItems * sizeof(TDataType);
if(desiredBytes > mTempBuffer.size())
mTempBuffer.resize(desiredBytes);
TDataType* retval = reinterpret_cast<TDataType*>(mTempBuffer.begin());
if(numItems)
{
PVD_FOREACH(idx, numItems) new (retval + idx) TDataType();
}
return retval;
}
#if PX_DEBUG
// Property datatypes need to be uniform.
// At this point, the data stream cannot handle properties that
// A struct with a float member and a char member would work.
// A struct with a float member and a long member would work (more efficiently).
bool isValidPropertyDatatype(const NamespacedName& dtypeName)
{
ScopedMetaData meta(mMetaDataProvider);
ClassDescription clsDesc(meta->findClass(dtypeName));
return clsDesc.mRequiresDestruction == false;
}
#endif
NamespacedName createMetaProperty(const NamespacedName& clsName, String name, String semantic,
const NamespacedName& dtypeName, PropertyType::Enum propertyType)
{
ScopedMetaData meta(mMetaDataProvider);
int32_t dtypeType = meta->findClass(dtypeName)->mClassId;
NamespacedName typeName = dtypeName;
if(dtypeType == getPvdTypeForType<String>())
{
dtypeType = getPvdTypeForType<StringHandle>();
typeName = getPvdNamespacedNameForType<StringHandle>();
}
Option<PropertyDescription> propOpt =
meta->createProperty(meta->findClass(clsName)->mClassId, name, semantic, dtypeType, propertyType);
PX_ASSERT(propOpt.hasValue());
PX_UNUSED(propOpt);
return typeName;
}
virtual PvdError createProperty(const NamespacedName& clsName, String name, String semantic,
const NamespacedName& incomingDtypeName, PropertyType::Enum propertyType,
DataRef<NamedValue> values)
{
PX_ASSERT(mStreamState == DataStreamState::Open);
#if PX_DEBUG
PX_ASSERT(isClassExist(clsName));
PX_ASSERT(propertyExists(clsName, name) == false);
#endif
NamespacedName dtypeName(incomingDtypeName);
if(safeStrEq(dtypeName.mName, "VoidPtr"))
dtypeName.mName = "ObjectRef";
#if PX_DEBUG
PX_ASSERT(isClassExist(dtypeName));
PX_ASSERT(isValidPropertyDatatype(dtypeName));
#endif
NamespacedName typeName = createMetaProperty(clsName, name, semantic, dtypeName, propertyType);
// Can't have arrays of strings or arrays of string handles due to the difficulty
// of quickly dealing with them on the network receiving side.
if(propertyType == PropertyType::Array && safeStrEq(typeName.mName, "StringHandle"))
{
PX_ASSERT(false);
return PvdErrorType::ArgumentError;
}
uint32_t numItems = values.size();
NameHandleValue* streamValues = allocTemp<NameHandleValue>(numItems);
PVD_FOREACH(idx, numItems)
streamValues[idx] = NameHandleValue(toStream(values[idx].mName), values[idx].mValue);
CreateProperty evt(toStream(clsName), toStream(name), toStream(semantic), toStream(typeName), propertyType,
DataRef<NameHandleValue>(streamValues, numItems));
return boolToError(handlePvdEvent(evt));
}
bool createMetaPropertyMessage(const NamespacedName& cls, const NamespacedName& msgName,
DataRef<PropertyMessageArg> entries, uint32_t messageSizeInBytes)
{
ScopedMetaData meta(mMetaDataProvider);
return meta->createPropertyMessage(cls, msgName, entries, messageSizeInBytes).hasValue();
}
#if PX_DEBUG
bool messageExists(const NamespacedName& msgName)
{
ScopedMetaData meta(mMetaDataProvider);
return meta->findPropertyMessage(msgName).hasValue();
}
#endif
virtual PvdError createPropertyMessage(const NamespacedName& cls, const NamespacedName& msgName,
DataRef<PropertyMessageArg> entries, uint32_t messageSizeInBytes)
{
PX_ASSERT(mStreamState == DataStreamState::Open);
#if PX_DEBUG
PX_ASSERT(isClassExist(cls));
PX_ASSERT(messageExists(msgName) == false);
#endif
createMetaPropertyMessage(cls, msgName, entries, messageSizeInBytes);
uint32_t numItems = entries.size();
StreamPropMessageArg* streamValues = allocTemp<StreamPropMessageArg>(numItems);
PVD_FOREACH(idx, numItems)
streamValues[idx] =
StreamPropMessageArg(toStream(entries[idx].mPropertyName), toStream(entries[idx].mDatatypeName),
entries[idx].mMessageOffset, entries[idx].mByteSize);
CreatePropertyMessage evt(toStream(cls), toStream(msgName),
DataRef<StreamPropMessageArg>(streamValues, numItems), messageSizeInBytes);
return boolToError(handlePvdEvent(evt));
}
uint64_t toStream(const void* instance)
{
return PVD_POINTER_TO_U64(instance);
}
virtual PvdError createInstance(const NamespacedName& cls, const void* instance)
{
PX_ASSERT(isInstanceValid(instance) == false);
PX_ASSERT(mStreamState == DataStreamState::Open);
bool success = mMetaDataProvider.createInstance(cls, instance);
PX_ASSERT(success);
(void)success;
return boolToError(handlePvdEvent(CreateInstance(toStream(cls), toStream(instance))));
}
virtual bool isInstanceValid(const void* instance)
{
return mMetaDataProvider.isInstanceValid(instance);
}
#if PX_DEBUG
// If the property will fit or is already completely in memory
bool checkPropertyType(const void* instance, String name, const NamespacedName& incomingType)
{
int32_t instType = mMetaDataProvider.getInstanceClassType(instance);
ScopedMetaData meta(mMetaDataProvider);
Option<PropertyDescription> prop = meta->findProperty(instType, name);
if(prop.hasValue() == false)
return false;
int32_t propType = prop->mDatatype;
int32_t incomingTypeId = meta->findClass(incomingType)->mClassId;
if(incomingTypeId != getPvdTypeForType<VoidPtr>())
{
MarshalQueryResult result = meta->checkMarshalling(incomingTypeId, propType);
bool possible = result.needsMarshalling == false || result.canMarshal;
return possible;
}
else
{
if(propType != getPvdTypeForType<ObjectRef>())
return false;
}
return true;
}
#endif
DataRef<const uint8_t> bufferPropertyValue(ClassDescriptionSizeInfo info, DataRef<const uint8_t> data)
{
uint32_t realSize = info.mByteSize;
uint32_t numItems = data.size() / realSize;
if(info.mPtrOffsets.size() != 0)
{
mSPVBuffer.clear();
PVD_FOREACH(item, numItems)
{
const uint8_t* itemPtr = data.begin() + item * realSize;
mSPVBuffer.write(itemPtr, realSize);
PVD_FOREACH(stringIdx, info.mPtrOffsets.size())
{
PtrOffset offset(info.mPtrOffsets[stringIdx]);
if(offset.mOffsetType == PtrOffsetType::VoidPtrOffset)
continue;
const char* strPtr;
physx::intrinsics::memCopy(&strPtr, itemPtr + offset.mOffset, sizeof(char*));
strPtr = nonNull(strPtr);
uint32_t len = safeStrLen(strPtr) + 1;
mSPVBuffer.write(strPtr, len);
}
}
data = DataRef<const uint8_t>(mSPVBuffer.begin(), mSPVBuffer.size());
}
return data;
}
virtual PvdError setPropertyValue(const void* instance, String name, DataRef<const uint8_t> data,
const NamespacedName& incomingTypeName)
{
PX_ASSERT(isInstanceValid(instance));
#if PX_DEBUG
PX_ASSERT(isClassExist(incomingTypeName));
#endif
PX_ASSERT(mStreamState == DataStreamState::Open);
ClassDescription clsDesc;
{
ScopedMetaData meta(mMetaDataProvider);
clsDesc = meta->findClass(incomingTypeName);
}
uint32_t realSize = clsDesc.getNativeSize();
uint32_t numItems = data.size() / realSize;
data = bufferPropertyValue(clsDesc.getNativeSizeInfo(), data);
SetPropertyValue evt(toStream(instance), toStream(name), data, toStream(incomingTypeName), numItems);
return boolToError(handlePvdEvent(evt));
}
// Else if the property is very large (contact reports) you can send it in chunks.
virtual PvdError beginSetPropertyValue(const void* instance, String name, const NamespacedName& incomingTypeName)
{
PX_ASSERT(isInstanceValid(instance));
#if PX_DEBUG
PX_ASSERT(isClassExist(incomingTypeName));
PX_ASSERT(checkPropertyType(instance, name, incomingTypeName));
#endif
PX_ASSERT(mStreamState == DataStreamState::Open);
mStreamState = DataStreamState::SetPropertyValue;
{
ScopedMetaData meta(mMetaDataProvider);
mSPVClass = meta->findClass(incomingTypeName);
}
BeginSetPropertyValue evt(toStream(instance), toStream(name), toStream(incomingTypeName));
return boolToError(handlePvdEvent(evt));
}
virtual PvdError appendPropertyValueData(DataRef<const uint8_t> data)
{
uint32_t realSize = mSPVClass.getNativeSize();
uint32_t numItems = data.size() / realSize;
data = bufferPropertyValue(mSPVClass.getNativeSizeInfo(), data);
PX_ASSERT(mStreamState == DataStreamState::SetPropertyValue);
return boolToError(handlePvdEvent(AppendPropertyValueData(data, numItems)));
}
virtual PvdError endSetPropertyValue()
{
PX_ASSERT(mStreamState == DataStreamState::SetPropertyValue);
mStreamState = DataStreamState::Open;
return boolToError(handlePvdEvent(EndSetPropertyValue()));
}
#if PX_DEBUG
bool checkPropertyMessage(const void* instance, const NamespacedName& msgName)
{
int32_t clsId = mMetaDataProvider.getInstanceClassType(instance);
ScopedMetaData meta(mMetaDataProvider);
PropertyMessageDescription desc(meta->findPropertyMessage(msgName));
bool retval = meta->isDerivedFrom(clsId, desc.mClassId);
return retval;
}
#endif
DataRef<const uint8_t> bufferPropertyMessage(const PropertyMessageDescription& desc, DataRef<const uint8_t> data)
{
if(desc.mStringOffsets.size())
{
mSPVBuffer.clear();
mSPVBuffer.write(data.begin(), data.size());
PVD_FOREACH(idx, desc.mStringOffsets.size())
{
const char* strPtr;
physx::intrinsics::memCopy(&strPtr, data.begin() + desc.mStringOffsets[idx], sizeof(char*));
strPtr = nonNull(strPtr);
uint32_t len = safeStrLen(strPtr) + 1;
mSPVBuffer.write(strPtr, len);
}
data = DataRef<const uint8_t>(mSPVBuffer.begin(), mSPVBuffer.end());
}
return data;
}
virtual PvdError setPropertyMessage(const void* instance, const NamespacedName& msgName, DataRef<const uint8_t> data)
{
ScopedMetaData meta(mMetaDataProvider);
PX_ASSERT(isInstanceValid(instance));
#if PX_DEBUG
PX_ASSERT(messageExists(msgName));
PX_ASSERT(checkPropertyMessage(instance, msgName));
#endif
PropertyMessageDescription desc(meta->findPropertyMessage(msgName));
if(data.size() < desc.mMessageByteSize)
{
PX_ASSERT(false);
return PvdErrorType::ArgumentError;
}
data = bufferPropertyMessage(desc, data);
PX_ASSERT(mStreamState == DataStreamState::Open);
return boolToError(handlePvdEvent(SetPropertyMessage(toStream(instance), toStream(msgName), data)));
}
#if PX_DEBUG
bool checkBeginPropertyMessageGroup(const NamespacedName& msgName)
{
ScopedMetaData meta(mMetaDataProvider);
PropertyMessageDescription desc(meta->findPropertyMessage(msgName));
return desc.mStringOffsets.size() == 0;
}
#endif
// If you need to send of lot of identical messages, this avoids a hashtable lookup per message.
virtual PvdError beginPropertyMessageGroup(const NamespacedName& msgName)
{
#if PX_DEBUG
PX_ASSERT(messageExists(msgName));
PX_ASSERT(checkBeginPropertyMessageGroup(msgName));
#endif
PX_ASSERT(mStreamState == DataStreamState::Open);
mStreamState = DataStreamState::PropertyMessageGroup;
ScopedMetaData meta(mMetaDataProvider);
mMessageDesc = meta->findPropertyMessage(msgName);
return boolToError(handlePvdEvent(BeginPropertyMessageGroup(toStream(msgName))));
}
virtual PvdError sendPropertyMessageFromGroup(const void* instance, DataRef<const uint8_t> data)
{
PX_ASSERT(mStreamState == DataStreamState::PropertyMessageGroup);
PX_ASSERT(isInstanceValid(instance));
#if PX_DEBUG
PX_ASSERT(checkPropertyMessage(instance, mMessageDesc.mMessageName));
#endif
if(mMessageDesc.mMessageByteSize != data.size())
{
PX_ASSERT(false);
return PvdErrorType::ArgumentError;
}
if(data.size() < mMessageDesc.mMessageByteSize)
return PvdErrorType::ArgumentError;
data = bufferPropertyMessage(mMessageDesc, data);
return boolToError(handlePvdEvent(SendPropertyMessageFromGroup(toStream(instance), data)));
}
virtual PvdError endPropertyMessageGroup()
{
PX_ASSERT(mStreamState == DataStreamState::PropertyMessageGroup);
mStreamState = DataStreamState::Open;
return boolToError(handlePvdEvent(EndPropertyMessageGroup()));
}
virtual PvdError pushBackObjectRef(const void* instance, String propName, const void* data)
{
PX_ASSERT(isInstanceValid(instance));
PX_ASSERT(isInstanceValid(data));
PX_ASSERT(mStreamState == DataStreamState::Open);
return boolToError(handlePvdEvent(PushBackObjectRef(toStream(instance), toStream(propName), toStream(data))));
}
virtual PvdError removeObjectRef(const void* instance, String propName, const void* data)
{
PX_ASSERT(isInstanceValid(instance));
PX_ASSERT(isInstanceValid(data));
PX_ASSERT(mStreamState == DataStreamState::Open);
return boolToError(handlePvdEvent(RemoveObjectRef(toStream(instance), toStream(propName), toStream(data))));
}
// Instance elimination.
virtual PvdError destroyInstance(const void* instance)
{
PX_ASSERT(isInstanceValid(instance));
PX_ASSERT(mStreamState == DataStreamState::Open);
mMetaDataProvider.destroyInstance(instance);
return boolToError(handlePvdEvent(DestroyInstance(toStream(instance))));
}
// Profiling hooks
virtual PvdError beginSection(const void* instance, String name)
{
PX_ASSERT(mStreamState == DataStreamState::Open);
return boolToError(handlePvdEvent(
BeginSection(toStream(instance), toStream(name), Time::getCurrentCounterValue())));
}
virtual PvdError endSection(const void* instance, String name)
{
PX_ASSERT(mStreamState == DataStreamState::Open);
return boolToError(handlePvdEvent(
EndSection(toStream(instance), toStream(name), Time::getCurrentCounterValue())));
}
virtual PvdError originShift(const void* scene, PxVec3 shift)
{
PX_ASSERT(mStreamState == DataStreamState::Open);
return boolToError(handlePvdEvent(OriginShift(toStream(scene), shift)));
}
virtual void addProfileZone(void* zone, const char* name)
{
handlePvdEvent(AddProfileZone(toStream(zone), name));
}
virtual void addProfileZoneEvent(void* zone, const char* name, uint16_t eventId, bool compileTimeEnabled)
{
handlePvdEvent(AddProfileZoneEvent(toStream(zone), name, eventId, compileTimeEnabled));
}
// add a variable sized event
void addEvent(const EventSerializeable& evt, PvdCommStreamEventTypes::Enum evtType)
{
MeasureStream measure;
PvdCommStreamEventSink::writeStreamEvent(evt, evtType, measure);
EventGroup evtGroup(measure.mSize, 1, mStreamId, Time::getCurrentCounterValue());
EventStreamifier<PxPvdTransport> streamifier(mTransport.lock());
evtGroup.serialize(streamifier);
PvdCommStreamEventSink::writeStreamEvent(evt, evtType, mTransport);
mTransport.unlock();
}
void setIsTopLevelUIElement(const void* instance, bool topLevel)
{
addEvent(SetIsTopLevel(static_cast<uint64_t>(reinterpret_cast<size_t>(instance)), topLevel),
getCommStreamEventType<SetIsTopLevel>());
}
void sendErrorMessage(uint32_t code, const char* message, const char* file, uint32_t line)
{
addEvent(ErrorMessage(code, message, file, line), getCommStreamEventType<ErrorMessage>());
}
void updateCamera(const char* name, const PxVec3& origin, const PxVec3& up, const PxVec3& target)
{
addEvent(SetCamera(name, origin, up, target), getCommStreamEventType<SetCamera>());
}
template <typename TEventType>
bool handlePvdEvent(const TEventType& evt)
{
addEvent(evt, getCommStreamEventType<TEventType>());
return mConnected;
}
virtual PvdPropertyDefinitionHelper& getPropertyDefinitionHelper()
{
mPropertyDefinitionHelper.clearBufferedData();
return mPropertyDefinitionHelper;
}
virtual bool isConnected()
{
return mConnected;
}
virtual void* allocateMemForCmd(uint32_t length)
{
return mPvdCommandPool.allocate(length);
}
virtual void pushPvdCommand(PvdCommand& cmd)
{
mPvdCommandArray.pushBack(&cmd);
}
virtual void flushPvdCommand()
{
uint32_t cmdQueueSize = mPvdCommandArray.size();
for(uint32_t i = 0; i < cmdQueueSize; i++)
{
if(mPvdCommandArray[i])
{
// if(mPvdCommandArray[i]->canRun(*this))
mPvdCommandArray[i]->run(*this);
mPvdCommandArray[i]->~PvdCommand();
}
}
mPvdCommandArray.clear();
mPvdCommandPool.clear();
}
PX_NOCOPY(PvdOutStream)
};
}
PvdDataStream* PvdDataStream::create(PxPvd* pvd)
{
if(pvd == NULL)
{
getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "PvdDataStream::create - pvd must be non-NULL!");
return NULL;
}
PvdImpl* pvdImpl = static_cast<PvdImpl*>(pvd);
return PVD_NEW(PvdOutStream)(*pvdImpl->getTransport(), pvdImpl->getMetaDataProvider(), pvdImpl->getNextStreamId());
}

View File

@ -0,0 +1,218 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "PxPvdDefaultFileTransport.h"
namespace physx
{
namespace pvdsdk
{
PvdDefaultFileTransport::PvdDefaultFileTransport(const char* name) : mConnected(false), mWrittenData(0), mLocked(false)
{
mFileBuffer = PX_NEW(PsFileBuffer)(name, PxFileBuf::OPEN_WRITE_ONLY);
}
PvdDefaultFileTransport::~PvdDefaultFileTransport()
{
}
bool PvdDefaultFileTransport::connect()
{
PX_ASSERT(mFileBuffer);
mConnected = mFileBuffer->isOpen();
return mConnected;
}
void PvdDefaultFileTransport::disconnect()
{
mConnected = false;
}
bool PvdDefaultFileTransport::isConnected()
{
return mConnected;
}
bool PvdDefaultFileTransport::write(const uint8_t* inBytes, uint32_t inLength)
{
PX_ASSERT(mLocked);
PX_ASSERT(mFileBuffer);
if (mConnected)
{
uint32_t len = mFileBuffer->write(inBytes, inLength);
mWrittenData += len;
return len == inLength;
}
else
return false;
}
PxPvdTransport& PvdDefaultFileTransport::lock()
{
mMutex.lock();
PX_ASSERT(!mLocked);
mLocked = true;
return *this;
}
void PvdDefaultFileTransport::unlock()
{
PX_ASSERT(mLocked);
mLocked = false;
mMutex.unlock();
}
void PvdDefaultFileTransport::flush()
{
}
uint64_t PvdDefaultFileTransport::getWrittenDataSize()
{
return mWrittenData;
}
void PvdDefaultFileTransport::release()
{
if (mFileBuffer)
{
mFileBuffer->close();
delete mFileBuffer;
}
mFileBuffer = NULL;
PX_DELETE(this);
}
class NullFileTransport : public physx::PxPvdTransport, public physx::shdfnd::UserAllocated
{
PX_NOCOPY(NullFileTransport)
public:
NullFileTransport();
virtual ~NullFileTransport();
virtual bool connect();
virtual void disconnect();
virtual bool isConnected();
virtual bool write(const uint8_t* inBytes, uint32_t inLength);
virtual PxPvdTransport& lock();
virtual void unlock();
virtual void flush();
virtual uint64_t getWrittenDataSize();
virtual void release();
private:
bool mConnected;
uint64_t mWrittenData;
physx::shdfnd::Mutex mMutex;
bool mLocked; // for debug, remove it when finished
};
NullFileTransport::NullFileTransport() : mConnected(false), mWrittenData(0), mLocked(false)
{
}
NullFileTransport::~NullFileTransport()
{
}
bool NullFileTransport::connect()
{
mConnected = true;
return true;
}
void NullFileTransport::disconnect()
{
mConnected = false;
}
bool NullFileTransport::isConnected()
{
return mConnected;
}
bool NullFileTransport::write(const uint8_t* /*inBytes*/, uint32_t inLength)
{
PX_ASSERT(mLocked);
if(mConnected)
{
uint32_t len = inLength;
mWrittenData += len;
return len == inLength;
}
else
return false;
}
PxPvdTransport& NullFileTransport::lock()
{
mMutex.lock();
PX_ASSERT(!mLocked);
mLocked = true;
return *this;
}
void NullFileTransport::unlock()
{
PX_ASSERT(mLocked);
mLocked = false;
mMutex.unlock();
}
void NullFileTransport::flush()
{
}
uint64_t NullFileTransport::getWrittenDataSize()
{
return mWrittenData;
}
void NullFileTransport::release()
{
PX_DELETE(this);
}
} // namespace pvdsdk
PxPvdTransport* PxDefaultPvdFileTransportCreate(const char* name)
{
if(name)
return PX_NEW(pvdsdk::PvdDefaultFileTransport)(name);
else
return PX_NEW(pvdsdk::NullFileTransport)();
}
} // namespace physx

View File

@ -0,0 +1,77 @@
//
// 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-2021 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_PXPVDDEFAULTFILETRANSPORT_H
#define PXPVDSDK_PXPVDDEFAULTFILETRANSPORT_H
#include "pvd/PxPvdTransport.h"
#include "PsUserAllocated.h"
#include "PsFileBuffer.h"
#include "PsMutex.h"
namespace physx
{
namespace pvdsdk
{
class PvdDefaultFileTransport : public physx::PxPvdTransport, public physx::shdfnd::UserAllocated
{
PX_NOCOPY(PvdDefaultFileTransport)
public:
PvdDefaultFileTransport(const char* name);
virtual ~PvdDefaultFileTransport();
virtual bool connect();
virtual void disconnect();
virtual bool isConnected();
virtual bool write(const uint8_t* inBytes, uint32_t inLength);
virtual PxPvdTransport& lock();
virtual void unlock();
virtual void flush();
virtual uint64_t getWrittenDataSize();
virtual void release();
private:
physx::PsFileBuffer* mFileBuffer;
bool mConnected;
uint64_t mWrittenData;
physx::shdfnd::Mutex mMutex;
bool mLocked; // for debug, remove it when finished
};
} // pvdsdk
} // physx
#endif // PXPVDSDK_PXPVDDEFAULTFILETRANSPORT_H

View File

@ -0,0 +1,134 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "PxPvdDefaultSocketTransport.h"
namespace physx
{
namespace pvdsdk
{
PvdDefaultSocketTransport::PvdDefaultSocketTransport(const char* host, int port, unsigned int timeoutInMilliseconds)
: mHost(host), mPort(uint16_t(port)), mTimeout(timeoutInMilliseconds), mConnected(false), mWrittenData(0)
{
}
PvdDefaultSocketTransport::~PvdDefaultSocketTransport()
{
}
bool PvdDefaultSocketTransport::connect()
{
if(mConnected)
return true;
if(mSocket.connect(mHost, mPort, mTimeout))
{
mSocket.setBlocking(true);
mConnected = true;
}
return mConnected;
}
void PvdDefaultSocketTransport::disconnect()
{
mSocket.flush();
mSocket.disconnect();
mConnected = false;
}
bool PvdDefaultSocketTransport::isConnected()
{
return mSocket.isConnected();
}
bool PvdDefaultSocketTransport::write(const uint8_t* inBytes, uint32_t inLength)
{
if(mConnected)
{
if(inLength == 0)
return true;
uint32_t amountWritten = 0;
uint32_t totalWritten = 0;
do
{
// Sockets don't have to write as much as requested, so we need
// to wrap this call in a do/while loop.
// If they don't write any bytes then we consider them disconnected.
amountWritten = mSocket.write(inBytes, inLength);
inLength -= amountWritten;
inBytes += amountWritten;
totalWritten += amountWritten;
} while(inLength && amountWritten);
if(amountWritten == 0)
return false;
mWrittenData += totalWritten;
return true;
}
else
return false;
}
PxPvdTransport& PvdDefaultSocketTransport::lock()
{
mMutex.lock();
return *this;
}
void PvdDefaultSocketTransport::unlock()
{
mMutex.unlock();
}
void PvdDefaultSocketTransport::flush()
{
mSocket.flush();
}
uint64_t PvdDefaultSocketTransport::getWrittenDataSize()
{
return mWrittenData;
}
void PvdDefaultSocketTransport::release()
{
PX_DELETE(this);
}
} // namespace pvdsdk
PxPvdTransport* PxDefaultPvdSocketTransportCreate(const char* host, int port, unsigned int timeoutInMilliseconds)
{
return PX_NEW(pvdsdk::PvdDefaultSocketTransport)(host, port, timeoutInMilliseconds);
}
} // namespace physx

View File

@ -0,0 +1,79 @@
//
// 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-2021 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_PXPVDDEFAULTSOCKETTRANSPORT_H
#define PXPVDSDK_PXPVDDEFAULTSOCKETTRANSPORT_H
#include "pvd/PxPvdTransport.h"
#include "PsUserAllocated.h"
#include "PsSocket.h"
#include "PsMutex.h"
namespace physx
{
namespace pvdsdk
{
class PvdDefaultSocketTransport : public PxPvdTransport, public shdfnd::UserAllocated
{
PX_NOCOPY(PvdDefaultSocketTransport)
public:
PvdDefaultSocketTransport(const char* host, int port, unsigned int timeoutInMilliseconds);
virtual ~PvdDefaultSocketTransport();
virtual bool connect();
virtual void disconnect();
virtual bool isConnected();
virtual bool write(const uint8_t* inBytes, uint32_t inLength);
virtual void flush();
virtual PxPvdTransport& lock();
virtual void unlock();
virtual uint64_t getWrittenDataSize();
virtual void release();
private:
shdfnd::Socket mSocket;
const char* mHost;
uint16_t mPort;
unsigned int mTimeout;
bool mConnected;
uint64_t mWrittenData;
shdfnd::Mutex mMutex;
bool mlocked;
};
} // pvdsdk
} // physx
#endif // PXPVDSDK_PXPVDDEFAULTSOCKETTRANSPORT_H

View File

@ -0,0 +1,318 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
#ifndef PXPVDSDK_PXPVDFOUNDATION_H
#define PXPVDSDK_PXPVDFOUNDATION_H
#include "foundation/PxVec3.h"
#include "foundation/PxTransform.h"
#include "foundation/PxBounds3.h"
#include "PsArray.h"
#include "PsHashMap.h"
#include "PsHashSet.h"
#include "PsPool.h"
#include "PsString.h"
#include "PxPvdObjectModelBaseTypes.h"
namespace physx
{
namespace pvdsdk
{
extern PxAllocatorCallback* gPvdAllocatorCallback;
class ForwardingAllocator : public PxAllocatorCallback
{
void* allocate(size_t size, const char* typeName, const char* filename, int line)
{
return shdfnd::getAllocator().allocate(size, typeName, filename, line);
}
void deallocate(void* ptr)
{
shdfnd::getAllocator().deallocate(ptr);
}
};
class RawMemoryBuffer
{
uint8_t* mBegin;
uint8_t* mEnd;
uint8_t* mCapacityEnd;
const char* mBufDataName;
public:
RawMemoryBuffer(const char* name) : mBegin(0), mEnd(0), mCapacityEnd(0),mBufDataName(name)
{
PX_UNUSED(mBufDataName);
}
~RawMemoryBuffer()
{
if(mBegin)
PX_FREE(mBegin);
}
uint32_t size() const
{
return static_cast<uint32_t>(mEnd - mBegin);
}
uint32_t capacity() const
{
return static_cast<uint32_t>(mCapacityEnd - mBegin);
}
uint8_t* begin()
{
return mBegin;
}
uint8_t* end()
{
return mEnd;
}
const uint8_t* begin() const
{
return mBegin;
}
const uint8_t* end() const
{
return mEnd;
}
void clear()
{
mEnd = mBegin;
}
const char* cStr()
{
if(mEnd && (*mEnd != 0))
write(0);
return reinterpret_cast<const char*>(mBegin);
}
uint32_t write(uint8_t inValue)
{
*growBuf(1) = inValue;
return 1;
}
template <typename TDataType>
uint32_t write(const TDataType& inValue)
{
const uint8_t* __restrict readPtr = reinterpret_cast<const uint8_t*>(&inValue);
uint8_t* __restrict writePtr = growBuf(sizeof(TDataType));
for(uint32_t idx = 0; idx < sizeof(TDataType); ++idx)
writePtr[idx] = readPtr[idx];
return sizeof(TDataType);
}
template <typename TDataType>
uint32_t write(const TDataType* inValue, uint32_t inLength)
{
uint32_t writeSize = inLength * sizeof(TDataType);
if(inValue && inLength)
{
physx::intrinsics::memCopy(growBuf(writeSize), inValue, writeSize);
}
if(inLength && !inValue)
{
PX_ASSERT(false);
// You can't not write something, because that will cause
// the receiving end to crash.
for(uint32_t idx = 0; idx < writeSize; ++idx)
write(0);
}
return writeSize;
}
uint8_t* growBuf(uint32_t inAmount)
{
uint32_t offset = size();
uint32_t newSize = offset + inAmount;
reserve(newSize);
mEnd += inAmount;
return mBegin + offset;
}
void writeZeros(uint32_t inAmount)
{
uint32_t offset = size();
growBuf(inAmount);
physx::intrinsics::memZero(begin() + offset, inAmount);
}
void reserve(uint32_t newSize)
{
uint32_t currentSize = size();
if(newSize && newSize >= capacity())
{
uint32_t newDataSize = newSize > 4096 ? newSize + (newSize >> 2) : newSize*2;
uint8_t* newData = static_cast<uint8_t*>(PX_ALLOC(newDataSize, mBufDataName));
if(mBegin)
{
physx::intrinsics::memCopy(newData, mBegin, currentSize);
PX_FREE(mBegin);
}
mBegin = newData;
mEnd = mBegin + currentSize;
mCapacityEnd = mBegin + newDataSize;
}
}
};
struct ForwardingMemoryBuffer : public RawMemoryBuffer
{
ForwardingMemoryBuffer(const char* bufDataName) : RawMemoryBuffer(bufDataName)
{
}
ForwardingMemoryBuffer& operator<<(const char* inString)
{
if(inString && *inString)
{
uint32_t len = static_cast<uint32_t>(strlen(inString));
write(inString, len);
}
return *this;
}
template <typename TDataType>
inline ForwardingMemoryBuffer& toStream(const char* inFormat, const TDataType inData)
{
char buffer[128] = { 0 };
shdfnd::snprintf(buffer, 128, inFormat, inData);
*this << buffer;
return *this;
}
inline ForwardingMemoryBuffer& operator<<(bool inData)
{
*this << (inData ? "true" : "false");
return *this;
}
inline ForwardingMemoryBuffer& operator<<(int32_t inData)
{
return toStream("%d", inData);
}
inline ForwardingMemoryBuffer& operator<<(uint16_t inData)
{
return toStream("%u", uint32_t(inData));
}
inline ForwardingMemoryBuffer& operator<<(uint8_t inData)
{
return toStream("%u", uint32_t(inData));
}
inline ForwardingMemoryBuffer& operator<<(char inData)
{
return toStream("%c", inData);
}
inline ForwardingMemoryBuffer& operator<<(uint32_t inData)
{
return toStream("%u", inData);
}
inline ForwardingMemoryBuffer& operator<<(uint64_t inData)
{
return toStream("%I64u", inData);
}
inline ForwardingMemoryBuffer& operator<<(int64_t inData)
{
return toStream("%I64d", inData);
}
inline ForwardingMemoryBuffer& operator<<(const void* inData)
{
return *this << static_cast<uint64_t>(reinterpret_cast<size_t>(inData));
}
inline ForwardingMemoryBuffer& operator<<(float inData)
{
return toStream("%g", double(inData));
}
inline ForwardingMemoryBuffer& operator<<(double inData)
{
return toStream("%g", inData);
}
inline ForwardingMemoryBuffer& operator<<(const PxVec3& inData)
{
*this << inData[0];
*this << " ";
*this << inData[1];
*this << " ";
*this << inData[2];
return *this;
}
inline ForwardingMemoryBuffer& operator<<(const PxQuat& inData)
{
*this << inData.x;
*this << " ";
*this << inData.y;
*this << " ";
*this << inData.z;
*this << " ";
*this << inData.w;
return *this;
}
inline ForwardingMemoryBuffer& operator<<(const PxTransform& inData)
{
*this << inData.q;
*this << " ";
*this << inData.p;
return *this;
}
inline ForwardingMemoryBuffer& operator<<(const PxBounds3& inData)
{
*this << inData.minimum;
*this << " ";
*this << inData.maximum;
return *this;
}
};
template <typename TDataType>
inline void* PvdAllocate(const char* typeName, const char* file, int line)
{
PX_ASSERT(gPvdAllocatorCallback);
return gPvdAllocatorCallback->allocate(sizeof(TDataType), typeName, file, line);
}
template <typename TDataType>
inline void PvdDeleteAndDeallocate(TDataType* inDType)
{
PX_ASSERT(gPvdAllocatorCallback);
if(inDType)
{
inDType->~TDataType();
gPvdAllocatorCallback->deallocate(inDType);
}
}
}
}
#define PVD_NEW(dtype) new (PvdAllocate<dtype>(#dtype, __FILE__, __LINE__)) dtype
#define PVD_DELETE(obj) PvdDeleteAndDeallocate(obj);
//#define PVD_NEW(dtype) PX_NEW(dtype)
//#define PVD_DELETE(obj) PX_DELETE(obj)
#define PVD_FOREACH(varname, stop) for(uint32_t varname = 0; varname < stop; ++varname)
#define PVD_POINTER_TO_U64(ptr) static_cast<uint64_t>(reinterpret_cast<size_t>(ptr))
#endif // PXPVDSDK_PXPVDFOUNDATION_H

View File

@ -0,0 +1,399 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "PxPvdImpl.h"
#include "PxPvdMemClient.h"
#include "PxPvdProfileZoneClient.h"
#include "PxPvdProfileZone.h"
#include "PsFoundation.h"
#if PX_NVTX
#include "nvToolsExt.h"
#endif
namespace
{
const char* gSdkName = "PhysXSDK";
}
namespace physx
{
namespace pvdsdk
{
class CmEventNameProvider : public physx::profile::PxProfileNameProvider
{
public:
physx::profile::PxProfileNames getProfileNames() const
{
physx::profile::PxProfileNames ret;
ret.eventCount = 0;
return ret;
}
};
CmEventNameProvider gProfileNameProvider;
void initializeModelTypes(PvdDataStream& stream)
{
stream.createClass<profile::PxProfileZone>();
stream.createProperty<profile::PxProfileZone, uint8_t>(
"events", PvdCommStreamEmbeddedTypes::getProfileEventStreamSemantic(), PropertyType::Array);
stream.createClass<profile::PxProfileMemoryEventBuffer>();
stream.createProperty<profile::PxProfileMemoryEventBuffer, uint8_t>(
"events", PvdCommStreamEmbeddedTypes::getMemoryEventStreamSemantic(), PropertyType::Array);
stream.createClass<PvdUserRenderer>();
stream.createProperty<PvdUserRenderer, uint8_t>(
"events", PvdCommStreamEmbeddedTypes::getRendererEventStreamSemantic(), PropertyType::Array);
}
PvdImpl* PvdImpl::sInstance = NULL;
uint32_t PvdImpl::sRefCount = 0;
PvdImpl::PvdImpl()
: mPvdTransport(NULL)
, mSharedMetaProvider(NULL)
, mMemClient(NULL)
, mIsConnected(false)
, mIsNVTXSupportEnabled(true)
, mNVTXContext(0)
, mNextStreamId(1)
, mProfileClient(NULL)
, mProfileZone(NULL)
{
mProfileZoneManager = &physx::profile::PxProfileZoneManager::createProfileZoneManager(&physx::shdfnd::getAllocator());
mProfileClient = PVD_NEW(PvdProfileZoneClient)(*this);
}
PvdImpl::~PvdImpl()
{
if((mFlags & PxPvdInstrumentationFlag::ePROFILE) )
{
PxSetProfilerCallback(NULL);
}
disconnect();
if ( mProfileZoneManager )
{
mProfileZoneManager->release();
mProfileZoneManager = NULL;
}
PVD_DELETE(mProfileClient);
mProfileClient = NULL;
}
bool PvdImpl::connect(PxPvdTransport& transport, PxPvdInstrumentationFlags flags)
{
if(mIsConnected)
{
physx::shdfnd::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "PxPvd::connect - recall connect! Should call disconnect before re-connect.");
return false;
}
mFlags = flags;
mPvdTransport = &transport;
mIsConnected = mPvdTransport->connect();
if(mIsConnected)
{
mSharedMetaProvider = PVD_NEW(MetaDataProvider);
sendTransportInitialization();
PvdDataStream* stream = PvdDataStream::create(this);
initializeModelTypes(*stream);
stream->release();
if(mFlags & PxPvdInstrumentationFlag::eMEMORY)
{
mMemClient = PVD_NEW(PvdMemClient)(*this);
mPvdClients.pushBack(mMemClient);
}
if((mFlags & PxPvdInstrumentationFlag::ePROFILE) && mProfileZoneManager)
{
mPvdClients.pushBack(mProfileClient);
mProfileZone = &physx::profile::PxProfileZone::createProfileZone(&physx::shdfnd::getAllocator(),gSdkName,gProfileNameProvider.getProfileNames());
}
for(uint32_t i = 0; i < mPvdClients.size(); i++)
mPvdClients[i]->onPvdConnected();
if (mProfileZone)
{
mProfileZoneManager->addProfileZoneHandler(*mProfileClient);
mProfileZoneManager->addProfileZone( *mProfileZone );
}
if ((mFlags & PxPvdInstrumentationFlag::ePROFILE))
{
PxSetProfilerCallback(this);
}
}
return mIsConnected;
}
void PvdImpl::disconnect()
{
if(mProfileZone)
{
mProfileZoneManager->removeProfileZoneHandler(*mProfileClient);
mProfileZoneManager->removeProfileZone( *mProfileZone );
mProfileZone->release();
mProfileZone=NULL;
removeClient(mProfileClient);
}
if(mIsConnected)
{
for(uint32_t i = 0; i < mPvdClients.size(); i++)
mPvdClients[i]->onPvdDisconnected();
if(mMemClient)
{
removeClient(mMemClient);
PvdMemClient* tmp = mMemClient; //avoid tracking deallocation itsself
mMemClient = NULL;
PVD_DELETE(tmp);
}
mSharedMetaProvider->release();
mPvdTransport->disconnect();
mObjectRegistrar.clear();
mIsConnected = false;
}
}
void PvdImpl::flush()
{
for(uint32_t i = 0; i < mPvdClients.size(); i++)
mPvdClients[i]->flush();
if ( mProfileZone )
{
mProfileZone->flushEventIdNameMap();
mProfileZone->flushProfileEvents();
}
}
bool PvdImpl::isConnected(bool useCachedStatus)
{
if(mPvdTransport)
return useCachedStatus ? mIsConnected : mPvdTransport->isConnected();
else
return false;
}
PxPvdTransport* PvdImpl::getTransport()
{
return mPvdTransport;
}
PxPvdInstrumentationFlags PvdImpl::getInstrumentationFlags()
{
return mFlags;
}
void PvdImpl::sendTransportInitialization()
{
StreamInitialization init;
EventStreamifier<PxPvdTransport> stream(mPvdTransport->lock());
init.serialize(stream);
mPvdTransport->unlock();
}
void PvdImpl::addClient(PvdClient* client)
{
PX_ASSERT(client);
for(uint32_t i = 0; i < mPvdClients.size(); i++)
{
if(client == mPvdClients[i])
return;
}
mPvdClients.pushBack(client);
if(mIsConnected)
{
client->onPvdConnected();
}
}
void PvdImpl::removeClient(PvdClient* client)
{
for(uint32_t i = 0; i < mPvdClients.size(); i++)
{
if(client == mPvdClients[i])
{
client->onPvdDisconnected();
mPvdClients.remove(i);
}
}
}
void PvdImpl::onAllocation(size_t inSize, const char* inType, const char* inFile, int inLine, void* inAddr)
{
if(mMemClient)
mMemClient->onAllocation(inSize, inType, inFile, inLine, inAddr);
}
void PvdImpl::onDeallocation(void* inAddr)
{
if(mMemClient)
mMemClient->onDeallocation(inAddr);
}
PvdOMMetaDataProvider& PvdImpl::getMetaDataProvider()
{
return *mSharedMetaProvider;
}
bool PvdImpl::registerObject(const void* inItem)
{
return mObjectRegistrar.addItem(inItem);
}
bool PvdImpl::unRegisterObject(const void* inItem)
{
return mObjectRegistrar.decItem(inItem);
}
uint64_t PvdImpl::getNextStreamId()
{
uint64_t retval = ++mNextStreamId;
return retval;
}
bool PvdImpl::initialize()
{
if(0 == sRefCount)
{
sInstance = PVD_NEW(PvdImpl)();
}
++sRefCount;
return !!sInstance;
}
void PvdImpl::release()
{
if(sRefCount > 0)
{
if(--sRefCount)
return;
PVD_DELETE(sInstance);
sInstance = NULL;
}
}
PvdImpl* PvdImpl::getInstance()
{
return sInstance;
}
/**************************************************************************************************************************
Instrumented profiling events
***************************************************************************************************************************/
static const uint32_t CrossThreadId = 99999789;
void* PvdImpl::zoneStart(const char* eventName, bool detached, uint64_t contextId)
{
if(mProfileZone)
{
const uint16_t id = mProfileZone->getEventIdForName(eventName);
if(detached)
mProfileZone->startEvent(id, contextId, CrossThreadId);
else
mProfileZone->startEvent(id, contextId);
}
#if PX_NVTX
if(mIsNVTXSupportEnabled)
{
if(detached)
{
// TODO : Need to use the nvtxRangeStart API for cross thread events
nvtxEventAttributes_t eventAttrib;
memset(&eventAttrib, 0, sizeof(eventAttrib));
eventAttrib.version = NVTX_VERSION;
eventAttrib.size = NVTX_EVENT_ATTRIB_STRUCT_SIZE;
eventAttrib.colorType = NVTX_COLOR_ARGB;
eventAttrib.color = 0xFF00FF00;
eventAttrib.messageType = NVTX_MESSAGE_TYPE_ASCII;
eventAttrib.message.ascii = eventName;
nvtxMarkEx(&eventAttrib);
}
else
{
nvtxRangePush(eventName);
}
}
#endif
return NULL;
}
void PvdImpl::zoneEnd(void* /*profilerData*/, const char* eventName, bool detached, uint64_t contextId)
{
if(mProfileZone)
{
const uint16_t id = mProfileZone->getEventIdForName(eventName);
if(detached)
mProfileZone->stopEvent(id, contextId, CrossThreadId);
else
mProfileZone->stopEvent(id, contextId);
}
#if PX_NVTX
if(mIsNVTXSupportEnabled)
{
if(detached)
{
nvtxEventAttributes_t eventAttrib;
memset(&eventAttrib, 0, sizeof(eventAttrib));
eventAttrib.version = NVTX_VERSION;
eventAttrib.size = NVTX_EVENT_ATTRIB_STRUCT_SIZE;
eventAttrib.colorType = NVTX_COLOR_ARGB;
eventAttrib.color = 0xFFFF0000;
eventAttrib.messageType = NVTX_MESSAGE_TYPE_ASCII;
eventAttrib.message.ascii = eventName;
nvtxMarkEx(&eventAttrib);
}
else
{
nvtxRangePop();
}
}
#endif
}
} // pvd
} // physx

View File

@ -0,0 +1,221 @@
//
// 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-2021 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_PXPVDIMPL_H
#define PXPVDSDK_PXPVDIMPL_H
#include "foundation/PxProfiler.h"
#include "PsAllocator.h"
#include "PsPvd.h"
#include "PsArray.h"
#include "PsMutex.h"
#include "PxPvdCommStreamTypes.h"
#include "PxPvdFoundation.h"
#include "PxPvdObjectModelMetaData.h"
#include "PxPvdObjectRegistrar.h"
namespace physx
{
namespace profile
{
class PxProfileZoneManager;
}
namespace pvdsdk
{
class PvdMemClient;
class PvdProfileZoneClient;
struct MetaDataProvider : public PvdOMMetaDataProvider, public shdfnd::UserAllocated
{
typedef shdfnd::Mutex::ScopedLock TScopedLockType;
typedef shdfnd::HashMap<const void*, int32_t> TInstTypeMap;
PvdObjectModelMetaData& mMetaData;
shdfnd::Mutex mMutex;
uint32_t mRefCount;
TInstTypeMap mTypeMap;
MetaDataProvider()
: mMetaData(PvdObjectModelMetaData::create()), mRefCount(0), mTypeMap("MetaDataProvider::mTypeMap")
{
mMetaData.addRef();
}
virtual ~MetaDataProvider()
{
mMetaData.release();
}
virtual void addRef()
{
TScopedLockType locker(mMutex);
++mRefCount;
}
virtual void release()
{
{
TScopedLockType locker(mMutex);
if(mRefCount)
--mRefCount;
}
if(!mRefCount)
PVD_DELETE(this);
}
virtual PvdObjectModelMetaData& lock()
{
mMutex.lock();
return mMetaData;
}
virtual void unlock()
{
mMutex.unlock();
}
virtual bool createInstance(const NamespacedName& clsName, const void* instance)
{
TScopedLockType locker(mMutex);
Option<ClassDescription> cls(mMetaData.findClass(clsName));
if(cls.hasValue() == false)
return false;
int32_t instType = cls->mClassId;
mTypeMap.insert(instance, instType);
return true;
}
virtual bool isInstanceValid(const void* instance)
{
TScopedLockType locker(mMutex);
ClassDescription classDesc;
bool retval = mTypeMap.find(instance) != NULL;
#if PX_DEBUG
if(retval)
classDesc = mMetaData.getClass(mTypeMap.find(instance)->second);
#endif
return retval;
}
virtual void destroyInstance(const void* instance)
{
{
TScopedLockType locker(mMutex);
mTypeMap.erase(instance);
}
}
virtual int32_t getInstanceClassType(const void* instance)
{
TScopedLockType locker(mMutex);
const TInstTypeMap::Entry* entry = mTypeMap.find(instance);
if(entry)
return entry->second;
return -1;
}
private:
MetaDataProvider& operator=(const MetaDataProvider&);
MetaDataProvider(const MetaDataProvider&);
};
//////////////////////////////////////////////////////////////////////////
/*!
PvdImpl is the realization of PxPvd.
It implements the interface methods and provides richer functionality for advanced users or internal clients (such as
PhysX or APEX), including handler notification for clients.
*/
//////////////////////////////////////////////////////////////////////////
class PvdImpl : public PsPvd, public shdfnd::UserAllocated
{
PX_NOCOPY(PvdImpl)
typedef shdfnd::Mutex::ScopedLock TScopedLockType;
typedef void (PvdImpl::*TAllocationHandler)(size_t size, const char* typeName, const char* filename, int line,
void* allocatedMemory);
typedef void (PvdImpl::*TDeallocationHandler)(void* allocatedMemory);
public:
PvdImpl();
virtual ~PvdImpl();
void release();
bool connect(PxPvdTransport& transport, PxPvdInstrumentationFlags flags);
void disconnect();
bool isConnected(bool useCachedStatus = true);
void flush();
PxPvdTransport* getTransport();
PxPvdInstrumentationFlags getInstrumentationFlags();
void addClient(PvdClient* client);
void removeClient(PvdClient* client);
PvdOMMetaDataProvider& getMetaDataProvider();
bool registerObject(const void* inItem);
bool unRegisterObject(const void* inItem);
//AllocationListener
void onAllocation(size_t size, const char* typeName, const char* filename, int line, void* allocatedMemory);
void onDeallocation(void* addr);
uint64_t getNextStreamId();
static bool initialize();
static PvdImpl* getInstance();
// Profiling
virtual void* zoneStart(const char* eventName, bool detached, uint64_t contextId);
virtual void zoneEnd(void* profilerData, const char *eventName, bool detached, uint64_t contextId);
private:
void sendTransportInitialization();
PxPvdTransport* mPvdTransport;
physx::shdfnd::Array<PvdClient*> mPvdClients;
MetaDataProvider* mSharedMetaProvider; // shared between clients
ObjectRegistrar mObjectRegistrar;
PvdMemClient* mMemClient;
PxPvdInstrumentationFlags mFlags;
bool mIsConnected;
bool mIsNVTXSupportEnabled;
uint32_t mNVTXContext;
uint64_t mNextStreamId;
physx::profile::PxProfileZoneManager*mProfileZoneManager;
PvdProfileZoneClient* mProfileClient;
physx::profile::PxProfileZone* mProfileZone;
static PvdImpl* sInstance;
static uint32_t sRefCount;
};
} // namespace pvdsdk
}
#endif // PXPVDSDK_PXPVDIMPL_H

View File

@ -0,0 +1,99 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
#ifndef PXPVDSDK_PXPVDINTERNALBYTESTREAMS_H
#define PXPVDSDK_PXPVDINTERNALBYTESTREAMS_H
#include "PxPvdByteStreams.h"
#include "PxPvdFoundation.h"
namespace physx
{
namespace pvdsdk
{
struct MemPvdInputStream : public PvdInputStream
{
const uint8_t* mBegin;
const uint8_t* mEnd;
bool mGood;
MemPvdInputStream(const uint8_t* beg = NULL, const uint8_t* end = NULL)
{
mBegin = beg;
mEnd = end;
mGood = true;
}
uint32_t size() const
{
return mGood ? static_cast<uint32_t>(mEnd - mBegin) : 0;
}
bool isGood() const
{
return mGood;
}
void setup(uint8_t* start, uint8_t* stop)
{
mBegin = start;
mEnd = stop;
}
void nocopyRead(uint8_t*& buffer, uint32_t& len)
{
if(len == 0 || mGood == false)
{
len = 0;
buffer = NULL;
return;
}
uint32_t original = len;
len = PxMin(len, size());
if(mGood && len != original)
mGood = false;
buffer = const_cast<uint8_t*>(mBegin);
mBegin += len;
}
virtual bool read(uint8_t* buffer, uint32_t& len)
{
if(len == 0)
return true;
uint32_t original = len;
len = PxMin(len, size());
physx::intrinsics::memCopy(buffer, mBegin, len);
mBegin += len;
if(len < original)
physx::intrinsics::memZero(buffer + len, original - len);
mGood = mGood && len == original;
return mGood;
}
};
}
}
#endif // PXPVDSDK_PXPVDINTERNALBYTESTREAMS_H

View File

@ -0,0 +1,220 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
#ifndef PXPVDSDK_PXPVDMARSHALLING_H
#define PXPVDSDK_PXPVDMARSHALLING_H
#include "foundation/PxIntrinsics.h"
#include "PxPvdObjectModelBaseTypes.h"
#include "PxPvdBits.h"
namespace physx
{
namespace pvdsdk
{
// Define marshalling
template <typename TSmallerType, typename TLargerType>
struct PvdMarshalling
{
bool canMarshal;
PvdMarshalling() : canMarshal(false)
{
}
};
template <typename smtype, typename lgtype>
static inline void marshalSingleT(const uint8_t* srcData, uint8_t* destData)
{
smtype incoming;
physx::intrinsics::memCopy(&incoming, srcData, sizeof(smtype));
lgtype outgoing = static_cast<lgtype>(incoming);
physx::intrinsics::memCopy(destData, &outgoing, sizeof(lgtype));
}
template <typename smtype, typename lgtype>
static inline void marshalBlockT(const uint8_t* srcData, uint8_t* destData, uint32_t numBytes)
{
for(const uint8_t* item = srcData, *end = srcData + numBytes; item < end;
item += sizeof(smtype), destData += sizeof(lgtype))
marshalSingleT<smtype, lgtype>(item, destData);
}
#define PVD_TYPE_MARSHALLER(smtype, lgtype) \
template <> \
struct PvdMarshalling<smtype, lgtype> \
{ \
uint32_t canMarshal; \
static void marshalSingle(const uint8_t* srcData, uint8_t* destData) \
{ \
marshalSingleT<smtype, lgtype>(srcData, destData); \
} \
static void marshalBlock(const uint8_t* srcData, uint8_t* destData, uint32_t numBytes) \
{ \
marshalBlockT<smtype, lgtype>(srcData, destData, numBytes); \
} \
};
// define marshalling tables.
PVD_TYPE_MARSHALLER(int8_t, int16_t)
PVD_TYPE_MARSHALLER(int8_t, uint16_t)
PVD_TYPE_MARSHALLER(int8_t, int32_t)
PVD_TYPE_MARSHALLER(int8_t, uint32_t)
PVD_TYPE_MARSHALLER(int8_t, int64_t)
PVD_TYPE_MARSHALLER(int8_t, uint64_t)
PVD_TYPE_MARSHALLER(int8_t, PvdF32)
PVD_TYPE_MARSHALLER(int8_t, PvdF64)
PVD_TYPE_MARSHALLER(uint8_t, int16_t)
PVD_TYPE_MARSHALLER(uint8_t, uint16_t)
PVD_TYPE_MARSHALLER(uint8_t, int32_t)
PVD_TYPE_MARSHALLER(uint8_t, uint32_t)
PVD_TYPE_MARSHALLER(uint8_t, int64_t)
PVD_TYPE_MARSHALLER(uint8_t, uint64_t)
PVD_TYPE_MARSHALLER(uint8_t, PvdF32)
PVD_TYPE_MARSHALLER(uint8_t, PvdF64)
PVD_TYPE_MARSHALLER(int16_t, int32_t)
PVD_TYPE_MARSHALLER(int16_t, uint32_t)
PVD_TYPE_MARSHALLER(int16_t, int64_t)
PVD_TYPE_MARSHALLER(int16_t, uint64_t)
PVD_TYPE_MARSHALLER(int16_t, PvdF32)
PVD_TYPE_MARSHALLER(int16_t, PvdF64)
PVD_TYPE_MARSHALLER(uint16_t, int32_t)
PVD_TYPE_MARSHALLER(uint16_t, uint32_t)
PVD_TYPE_MARSHALLER(uint16_t, int64_t)
PVD_TYPE_MARSHALLER(uint16_t, uint64_t)
PVD_TYPE_MARSHALLER(uint16_t, PvdF32)
PVD_TYPE_MARSHALLER(uint16_t, PvdF64)
PVD_TYPE_MARSHALLER(int32_t, int64_t)
PVD_TYPE_MARSHALLER(int32_t, uint64_t)
PVD_TYPE_MARSHALLER(int32_t, PvdF64)
PVD_TYPE_MARSHALLER(int32_t, PvdF32)
PVD_TYPE_MARSHALLER(uint32_t, int64_t)
PVD_TYPE_MARSHALLER(uint32_t, uint64_t)
PVD_TYPE_MARSHALLER(uint32_t, PvdF64)
PVD_TYPE_MARSHALLER(uint32_t, PvdF32)
PVD_TYPE_MARSHALLER(PvdF32, PvdF64)
PVD_TYPE_MARSHALLER(PvdF32, uint32_t)
PVD_TYPE_MARSHALLER(PvdF32, int32_t)
PVD_TYPE_MARSHALLER(uint64_t, PvdF64)
PVD_TYPE_MARSHALLER(int64_t, PvdF64)
PVD_TYPE_MARSHALLER(PvdF64, uint64_t)
PVD_TYPE_MARSHALLER(PvdF64, int64_t)
template <typename TMarshaller>
static inline bool getMarshalOperators(TSingleMarshaller&, TBlockMarshaller&, TMarshaller&, bool)
{
return false;
}
template <typename TMarshaller>
static inline bool getMarshalOperators(TSingleMarshaller& single, TBlockMarshaller& block, TMarshaller&, uint32_t)
{
single = TMarshaller::marshalSingle;
block = TMarshaller::marshalBlock;
return true;
}
template <typename smtype, typename lgtype>
static inline bool getMarshalOperators(TSingleMarshaller& single, TBlockMarshaller& block)
{
single = NULL;
block = NULL;
PvdMarshalling<smtype, lgtype> marshaller = PvdMarshalling<smtype, lgtype>();
return getMarshalOperators(single, block, marshaller, marshaller.canMarshal);
}
template <typename smtype>
static inline bool getMarshalOperators(TSingleMarshaller& single, TBlockMarshaller& block, int32_t lgtypeId)
{
switch(lgtypeId)
{
case PvdBaseType::PvdI8: // int8_t:
return getMarshalOperators<smtype, int8_t>(single, block);
case PvdBaseType::PvdU8: // uint8_t:
return getMarshalOperators<smtype, uint8_t>(single, block);
case PvdBaseType::PvdI16: // int16_t:
return getMarshalOperators<smtype, int16_t>(single, block);
case PvdBaseType::PvdU16: // uint16_t:
return getMarshalOperators<smtype, uint16_t>(single, block);
case PvdBaseType::PvdI32: // int32_t:
return getMarshalOperators<smtype, int32_t>(single, block);
case PvdBaseType::PvdU32: // uint32_t:
return getMarshalOperators<smtype, uint32_t>(single, block);
case PvdBaseType::PvdI64: // int64_t:
return getMarshalOperators<smtype, int64_t>(single, block);
case PvdBaseType::PvdU64: // uint64_t:
return getMarshalOperators<smtype, uint64_t>(single, block);
case PvdBaseType::PvdF32:
return getMarshalOperators<smtype, PvdF32>(single, block);
case PvdBaseType::PvdF64:
return getMarshalOperators<smtype, PvdF64>(single, block);
}
return false;
}
static inline bool getMarshalOperators(TSingleMarshaller& single, TBlockMarshaller& block, int32_t smtypeId,
int32_t lgtypeId)
{
switch(smtypeId)
{
case PvdBaseType::PvdI8: // int8_t:
return getMarshalOperators<int8_t>(single, block, lgtypeId);
case PvdBaseType::PvdU8: // uint8_t:
return getMarshalOperators<uint8_t>(single, block, lgtypeId);
case PvdBaseType::PvdI16: // int16_t:
return getMarshalOperators<int16_t>(single, block, lgtypeId);
case PvdBaseType::PvdU16: // uint16_t:
return getMarshalOperators<uint16_t>(single, block, lgtypeId);
case PvdBaseType::PvdI32: // int32_t:
return getMarshalOperators<int32_t>(single, block, lgtypeId);
case PvdBaseType::PvdU32: // uint32_t:
return getMarshalOperators<uint32_t>(single, block, lgtypeId);
case PvdBaseType::PvdI64: // int64_t:
return getMarshalOperators<int64_t>(single, block, lgtypeId);
case PvdBaseType::PvdU64: // uint64_t:
return getMarshalOperators<uint64_t>(single, block, lgtypeId);
case PvdBaseType::PvdF32:
return getMarshalOperators<PvdF32>(single, block, lgtypeId);
case PvdBaseType::PvdF64:
return getMarshalOperators<PvdF64>(single, block, lgtypeId);
}
return false;
}
}
}
#endif // PXPVDSDK_PXPVDMARSHALLING_H

View File

@ -0,0 +1,120 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "PxPvdImpl.h"
#include "PxPvdMemClient.h"
namespace physx
{
namespace pvdsdk
{
PvdMemClient::PvdMemClient(PvdImpl& pvd)
: mSDKPvd(pvd)
, mPvdDataStream(NULL)
, mIsConnected(false)
, mMemEventBuffer(profile::PxProfileMemoryEventBuffer::createMemoryEventBuffer(*gPvdAllocatorCallback))
{
}
PvdMemClient::~PvdMemClient()
{
mSDKPvd.removeClient(this);
if(mMemEventBuffer.hasClients())
mPvdDataStream->destroyInstance(&mMemEventBuffer);
mMemEventBuffer.release();
}
PvdDataStream* PvdMemClient::getDataStream()
{
return mPvdDataStream;
}
bool PvdMemClient::isConnected() const
{
return mIsConnected;
}
void PvdMemClient::onPvdConnected()
{
if(mIsConnected)
return;
mIsConnected = true;
mPvdDataStream = PvdDataStream::create(&mSDKPvd);
mPvdDataStream->createInstance(&mMemEventBuffer);
mMemEventBuffer.addClient(*this);
}
void PvdMemClient::onPvdDisconnected()
{
if(!mIsConnected)
return;
mIsConnected = false;
flush();
mMemEventBuffer.removeClient(*this);
mPvdDataStream->release();
mPvdDataStream = NULL;
}
void PvdMemClient::onAllocation(size_t inSize, const char* inType, const char* inFile, int inLine, void* inAddr)
{
mMutex.lock();
mMemEventBuffer.onAllocation(inSize, inType, inFile, inLine, inAddr);
mMutex.unlock();
}
void PvdMemClient::onDeallocation(void* inAddr)
{
mMutex.lock();
mMemEventBuffer.onDeallocation(inAddr);
mMutex.unlock();
}
void PvdMemClient::flush()
{
mMutex.lock();
mMemEventBuffer.flushProfileEvents();
mMutex.unlock();
}
void PvdMemClient::handleBufferFlush(const uint8_t* inData, uint32_t inLength)
{
if(mPvdDataStream)
mPvdDataStream->setPropertyValue(&mMemEventBuffer, "events", inData, inLength);
}
void PvdMemClient::handleClientRemoved()
{
}
} // pvd
} // physx

View File

@ -0,0 +1,83 @@
//
// 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-2021 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_PXPVDMEMCLIENT_H
#define PXPVDSDK_PXPVDMEMCLIENT_H
#include "PxPvdClient.h"
#include "PsHashMap.h"
#include "PsMutex.h"
#include "PsBroadcast.h"
#include "PxProfileEventBufferClient.h"
#include "PxProfileMemory.h"
namespace physx
{
class PvdDataStream;
namespace pvdsdk
{
class PvdImpl;
class PvdMemClient : public PvdClient,
public profile::PxProfileEventBufferClient,
public shdfnd::UserAllocated
{
PX_NOCOPY(PvdMemClient)
public:
PvdMemClient(PvdImpl& pvd);
virtual ~PvdMemClient();
bool isConnected() const;
void onPvdConnected();
void onPvdDisconnected();
void flush();
PvdDataStream* getDataStream();
void sendMemEvents();
// memory event
void onAllocation(size_t size, const char* typeName, const char* filename, int line, void* allocatedMemory);
void onDeallocation(void* addr);
private:
PvdImpl& mSDKPvd;
PvdDataStream* mPvdDataStream;
bool mIsConnected;
// mem profile
shdfnd::Mutex mMutex; // mem onallocation can called from different threads
profile::PxProfileMemoryEventBuffer& mMemEventBuffer;
void handleBufferFlush(const uint8_t* inData, uint32_t inLength);
void handleClientRemoved();
};
} // namespace pvdsdk
} // namespace physx
#endif // PXPVDSDK_PXPVDMEMCLIENT_H

View File

@ -0,0 +1,32 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
#define THERE_IS_NO_INCLUDE_GUARD_HERE_FOR_A_REASON
DECLARE_INTERNAL_PVD_TYPE(ArrayData)
#undef THERE_IS_NO_INCLUDE_GUARD_HERE_FOR_A_REASON

View File

@ -0,0 +1,154 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
#ifndef PXPVDSDK_PXPVDOBJECTMODELINTERNALTYPES_H
#define PXPVDSDK_PXPVDOBJECTMODELINTERNALTYPES_H
#include "foundation/PxMemory.h"
#include "PxPvdObjectModelBaseTypes.h"
#include "PsArray.h"
#include "PxPvdFoundation.h"
namespace physx
{
namespace pvdsdk
{
struct PvdInternalType
{
enum Enum
{
None = 0,
#define DECLARE_INTERNAL_PVD_TYPE(type) type,
#include "PxPvdObjectModelInternalTypeDefs.h"
Last
#undef DECLARE_INTERNAL_PVD_TYPE
};
};
PX_COMPILE_TIME_ASSERT(uint32_t(PvdInternalType::Last) <= uint32_t(PvdBaseType::InternalStop));
template <typename T>
struct DataTypeToPvdTypeMap
{
bool compile_error;
};
template <PvdInternalType::Enum>
struct PvdTypeToDataTypeMap
{
bool compile_error;
};
#define DECLARE_INTERNAL_PVD_TYPE(type) \
template <> \
struct DataTypeToPvdTypeMap<type> \
{ \
enum Enum \
{ \
BaseTypeEnum = PvdInternalType::type \
}; \
}; \
template <> \
struct PvdTypeToDataTypeMap<PvdInternalType::type> \
{ \
typedef type TDataType; \
}; \
template <> \
struct PvdDataTypeToNamespacedNameMap<type> \
{ \
NamespacedName Name; \
PvdDataTypeToNamespacedNameMap<type>() : Name("physx3_debugger_internal", #type) \
{ \
} \
};
#include "PxPvdObjectModelInternalTypeDefs.h"
#undef DECLARE_INTERNAL_PVD_TYPE
template <typename TDataType, typename TAlloc>
DataRef<TDataType> toDataRef(const shdfnd::Array<TDataType, TAlloc>& data)
{
return DataRef<TDataType>(data.begin(), data.end());
}
static inline bool safeStrEq(const DataRef<String>& lhs, const DataRef<String>& rhs)
{
uint32_t count = lhs.size();
if(count != rhs.size())
return false;
for(uint32_t idx = 0; idx < count; ++idx)
if(!safeStrEq(lhs[idx], rhs[idx]))
return false;
return true;
}
static inline char* copyStr(const char* str)
{
str = nonNull(str);
uint32_t len = static_cast<uint32_t>(strlen(str));
char* newData = reinterpret_cast<char*>(PX_ALLOC(len + 1, "string"));
PxMemCopy(newData, str, len);
newData[len] = 0;
return newData;
}
// 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 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 = ~(createOffsetMask());
// Clear out current value.
inCurrent = inCurrent & theMask;
// Create the new value.
TDataType theAddition = reinterpret_cast<TDataType>(inData << TOffset);
// or it into the existing value.
inCurrent = inCurrent | theAddition;
}
TInputType getValue(TDataType inCurrent)
{
return static_cast<TInputType>((inCurrent >> TOffset) & createMask());
}
};
}
}
#endif // PXPVDSDK_PXPVDOBJECTMODELINTERNALTYPES_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,481 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
#ifndef PXPVDSDK_PXPVDOBJECTMODELMETADATA_H
#define PXPVDSDK_PXPVDOBJECTMODELMETADATA_H
#include "foundation/PxAssert.h"
#include "PxPvdObjectModelBaseTypes.h"
#include "PxPvdBits.h"
namespace physx
{
namespace pvdsdk
{
class PvdInputStream;
class PvdOutputStream;
struct PropertyDescription
{
NamespacedName mOwnerClassName;
int32_t mOwnerClassId;
String mName;
String mSemantic;
// The datatype this property corresponds to.
int32_t mDatatype;
// The name of the datatype
NamespacedName mDatatypeName;
// Scalar or array.
PropertyType::Enum mPropertyType;
// No other property under any class has this id, it is DB-unique.
int32_t mPropertyId;
// Offset in bytes into the object's data section where this property starts.
uint32_t m32BitOffset;
// Offset in bytes into the object's data section where this property starts.
uint32_t m64BitOffset;
PropertyDescription(const NamespacedName& clsName, int32_t classId, String name, String semantic, int32_t datatype,
const NamespacedName& datatypeName, PropertyType::Enum propType, int32_t propId,
uint32_t offset32, uint32_t offset64)
: mOwnerClassName(clsName)
, mOwnerClassId(classId)
, mName(name)
, mSemantic(semantic)
, mDatatype(datatype)
, mDatatypeName(datatypeName)
, mPropertyType(propType)
, mPropertyId(propId)
, m32BitOffset(offset32)
, m64BitOffset(offset64)
{
}
PropertyDescription()
: mOwnerClassId(-1)
, mName("")
, mSemantic("")
, mDatatype(-1)
, mPropertyType(PropertyType::Unknown)
, mPropertyId(-1)
, m32BitOffset(0)
, m64BitOffset(0)
{
}
virtual ~PropertyDescription()
{
}
};
struct PtrOffsetType
{
enum Enum
{
UnknownOffset,
VoidPtrOffset,
StringOffset
};
};
struct PtrOffset
{
PtrOffsetType::Enum mOffsetType;
uint32_t mOffset;
PtrOffset(PtrOffsetType::Enum type, uint32_t offset) : mOffsetType(type), mOffset(offset)
{
}
PtrOffset() : mOffsetType(PtrOffsetType::UnknownOffset), mOffset(0)
{
}
};
inline uint32_t align(uint32_t offset, uint32_t alignment)
{
uint32_t startOffset = offset;
uint32_t alignmentMask = ~(alignment - 1);
offset = (offset + alignment - 1) & alignmentMask;
PX_ASSERT(offset >= startOffset && (offset % alignment) == 0);
(void)startOffset;
return offset;
}
struct ClassDescriptionSizeInfo
{
// The size of the data section of this object, padded to alignment.
uint32_t mByteSize;
// The last data member goes to here.
uint32_t mDataByteSize;
// Alignment in bytes of the data section of this object.
uint32_t mAlignment;
// the offsets of string handles in the binary value of this class
DataRef<PtrOffset> mPtrOffsets;
ClassDescriptionSizeInfo() : mByteSize(0), mDataByteSize(0), mAlignment(0)
{
}
};
struct ClassDescription
{
NamespacedName mName;
// No other class has this id, it is DB-unique
int32_t mClassId;
// Only single derivation supported.
int32_t mBaseClass;
// If this class has properties that are of uniform type, then we note that.
// This means that when deserialization an array of these objects we can just use
// single function to endian convert the entire mess at once.
int32_t mPackedUniformWidth;
// If this class is composed uniformly of members of a given type
// Or all of its properties are composed uniformly of members of
// a give ntype, then this class's packed type is that type.
// PxTransform's packed type would be float.
int32_t mPackedClassType;
// 0: 32Bit 1: 64Bit
ClassDescriptionSizeInfo mSizeInfo[2];
// No further property additions allowed.
bool mLocked;
// True when this datatype has an array on it that needs to be
// separately deleted.
bool mRequiresDestruction;
ClassDescription(NamespacedName name, int32_t id)
: mName(name)
, mClassId(id)
, mBaseClass(-1)
, mPackedUniformWidth(-1)
, mPackedClassType(-1)
, mLocked(false)
, mRequiresDestruction(false)
{
}
ClassDescription()
: mClassId(-1), mBaseClass(-1), mPackedUniformWidth(-1), mPackedClassType(-1), mLocked(false), mRequiresDestruction(false)
{
}
virtual ~ClassDescription()
{
}
ClassDescriptionSizeInfo& get32BitSizeInfo()
{
return mSizeInfo[0];
}
ClassDescriptionSizeInfo& get64BitSizeInfo()
{
return mSizeInfo[1];
}
uint32_t& get32BitSize()
{
return get32BitSizeInfo().mByteSize;
}
uint32_t& get64BitSize()
{
return get64BitSizeInfo().mByteSize;
}
uint32_t get32BitSize() const
{
return mSizeInfo[0].mByteSize;
}
const ClassDescriptionSizeInfo& getNativeSizeInfo() const
{
return mSizeInfo[(sizeof(void*) >> 2) - 1];
}
uint32_t getNativeSize() const
{
return getNativeSizeInfo().mByteSize;
}
};
struct MarshalQueryResult
{
int32_t srcType;
int32_t dstType;
// If canMarshal != needsMarshalling we have a problem.
bool canMarshal;
bool needsMarshalling;
// Non null if marshalling is possible.
TBlockMarshaller marshaller;
MarshalQueryResult(int32_t _srcType = -1, int32_t _dstType = -1, bool _canMarshal = false, bool _needs = false,
TBlockMarshaller _m = NULL)
: srcType(_srcType), dstType(_dstType), canMarshal(_canMarshal), needsMarshalling(_needs), marshaller(_m)
{
}
};
struct PropertyMessageEntry
{
PropertyDescription mProperty;
NamespacedName mDatatypeName;
// datatype of the data in the message.
int32_t mDatatypeId;
// where in the message this property starts.
uint32_t mMessageOffset;
// size of this entry object
uint32_t mByteSize;
// If the chain of properties doesn't have any array properties this indicates the
uint32_t mDestByteSize;
PropertyMessageEntry(PropertyDescription propName, NamespacedName dtypeName, int32_t dtype, uint32_t messageOff,
uint32_t byteSize, uint32_t destByteSize)
: mProperty(propName)
, mDatatypeName(dtypeName)
, mDatatypeId(dtype)
, mMessageOffset(messageOff)
, mByteSize(byteSize)
, mDestByteSize(destByteSize)
{
}
PropertyMessageEntry() : mDatatypeId(-1), mMessageOffset(0), mByteSize(0), mDestByteSize(0)
{
}
};
// Create a struct that defines a subset of the properties on an object.
struct PropertyMessageDescription
{
NamespacedName mClassName;
// No other class has this id, it is DB-unique
int32_t mClassId;
NamespacedName mMessageName;
int32_t mMessageId;
DataRef<PropertyMessageEntry> mProperties;
uint32_t mMessageByteSize;
// Offsets into the property message where const char* items are.
DataRef<uint32_t> mStringOffsets;
PropertyMessageDescription(const NamespacedName& nm, int32_t clsId, const NamespacedName& msgName, int32_t msgId,
uint32_t msgSize)
: mClassName(nm), mClassId(clsId), mMessageName(msgName), mMessageId(msgId), mMessageByteSize(msgSize)
{
}
PropertyMessageDescription() : mClassId(-1), mMessageId(-1), mMessageByteSize(0)
{
}
virtual ~PropertyMessageDescription()
{
}
};
class StringTable
{
protected:
virtual ~StringTable()
{
}
public:
virtual uint32_t getNbStrs() = 0;
virtual uint32_t getStrs(const char** outStrs, uint32_t bufLen, uint32_t startIdx = 0) = 0;
virtual const char* registerStr(const char* str, bool& outAdded) = 0;
const char* registerStr(const char* str)
{
bool ignored;
return registerStr(str, ignored);
}
virtual StringHandle strToHandle(const char* str) = 0;
virtual const char* handleToStr(uint32_t hdl) = 0;
virtual void release() = 0;
static StringTable& create();
};
struct None
{
};
template <typename T>
class Option
{
T mValue;
bool mHasValue;
public:
Option(const T& val) : mValue(val), mHasValue(true)
{
}
Option(None nothing = None()) : mHasValue(false)
{
(void)nothing;
}
Option(const Option& other) : mValue(other.mValue), mHasValue(other.mHasValue)
{
}
Option& operator=(const Option& other)
{
mValue = other.mValue;
mHasValue = other.mHasValue;
return *this;
}
bool hasValue() const
{
return mHasValue;
}
const T& getValue() const
{
PX_ASSERT(hasValue());
return mValue;
}
T& getValue()
{
PX_ASSERT(hasValue());
return mValue;
}
operator const T&() const
{
return getValue();
}
operator T&()
{
return getValue();
}
T* operator->()
{
return &getValue();
}
const T* operator->() const
{
return &getValue();
}
};
/**
* Create new classes and add properties to some existing ones.
* The default classes are created already, the simple types
* along with the basic math types.
* (uint8_t, int8_t, etc )
* (PxVec3, PxQuat, PxTransform, PxMat33, PxMat34, PxMat44)
*/
class PvdObjectModelMetaData
{
protected:
virtual ~PvdObjectModelMetaData()
{
}
public:
virtual ClassDescription getOrCreateClass(const NamespacedName& nm) = 0;
// get or create parent, lock parent. deriveFrom getOrCreatechild.
virtual bool deriveClass(const NamespacedName& parent, const NamespacedName& child) = 0;
virtual Option<ClassDescription> findClass(const NamespacedName& nm) const = 0;
template <typename TDataType>
Option<ClassDescription> findClass()
{
return findClass(getPvdNamespacedNameForType<TDataType>());
}
virtual Option<ClassDescription> getClass(int32_t classId) const = 0;
virtual ClassDescription* getClassPtr(int32_t classId) const = 0;
virtual Option<ClassDescription> getParentClass(int32_t classId) const = 0;
bool isDerivedFrom(int32_t classId, int32_t parentClass) const
{
if(classId == parentClass)
return true;
ClassDescription* p = getClassPtr(getClassPtr(classId)->mBaseClass);
while(p != NULL)
{
if(p->mClassId == parentClass)
return true;
p = getClassPtr(p->mBaseClass);
}
return false;
}
virtual void lockClass(int32_t classId) = 0;
virtual uint32_t getNbClasses() const = 0;
virtual uint32_t getClasses(ClassDescription* outClasses, uint32_t requestCount, uint32_t startIndex = 0) const = 0;
// Create a nested property.
// This way you can have obj.p.x without explicity defining the class p.
virtual Option<PropertyDescription> createProperty(int32_t classId, String name, String semantic, int32_t datatype,
PropertyType::Enum propertyType = PropertyType::Scalar) = 0;
Option<PropertyDescription> createProperty(NamespacedName clsId, String name, String semantic, NamespacedName dtype,
PropertyType::Enum propertyType = PropertyType::Scalar)
{
return createProperty(findClass(clsId)->mClassId, name, semantic, findClass(dtype)->mClassId, propertyType);
}
Option<PropertyDescription> createProperty(NamespacedName clsId, String name, NamespacedName dtype,
PropertyType::Enum propertyType = PropertyType::Scalar)
{
return createProperty(findClass(clsId)->mClassId, name, "", findClass(dtype)->mClassId, propertyType);
}
Option<PropertyDescription> createProperty(int32_t clsId, String name, int32_t dtype,
PropertyType::Enum propertyType = PropertyType::Scalar)
{
return createProperty(clsId, name, "", dtype, propertyType);
}
template <typename TDataType>
Option<PropertyDescription> createProperty(int32_t clsId, String name, String semantic = "",
PropertyType::Enum propertyType = PropertyType::Scalar)
{
return createProperty(clsId, name, semantic, getPvdNamespacedNameForType<TDataType>(), propertyType);
}
virtual Option<PropertyDescription> findProperty(const NamespacedName& cls, String prop) const = 0;
virtual Option<PropertyDescription> findProperty(int32_t clsId, String prop) const = 0;
virtual Option<PropertyDescription> getProperty(int32_t propId) const = 0;
virtual void setNamedPropertyValues(DataRef<NamedValue> values, int32_t propId) = 0;
// for enumerations and flags.
virtual DataRef<NamedValue> getNamedPropertyValues(int32_t propId) const = 0;
virtual uint32_t getNbProperties(int32_t classId) const = 0;
virtual uint32_t getProperties(int32_t classId, PropertyDescription* outBuffer, uint32_t bufCount,
uint32_t startIdx = 0) const = 0;
// Does one cls id differ marshalling to another and if so return the functions to do it.
virtual MarshalQueryResult checkMarshalling(int32_t srcClsId, int32_t dstClsId) const = 0;
// messages and classes are stored in separate maps, so a property message can have the same name as a class.
virtual Option<PropertyMessageDescription> createPropertyMessage(const NamespacedName& cls,
const NamespacedName& msgName,
DataRef<PropertyMessageArg> entries,
uint32_t messageSize) = 0;
virtual Option<PropertyMessageDescription> findPropertyMessage(const NamespacedName& msgName) const = 0;
virtual Option<PropertyMessageDescription> getPropertyMessage(int32_t msgId) const = 0;
virtual uint32_t getNbPropertyMessages() const = 0;
virtual uint32_t getPropertyMessages(PropertyMessageDescription* msgBuf, uint32_t bufLen,
uint32_t startIdx = 0) const = 0;
virtual StringTable& getStringTable() const = 0;
virtual void write(PvdOutputStream& stream) const = 0;
void save(PvdOutputStream& stream) const
{
write(stream);
}
virtual void addRef() = 0;
virtual void release() = 0;
static uint32_t getCurrentPvdObjectModelVersion();
static PvdObjectModelMetaData& create();
static PvdObjectModelMetaData& create(PvdInputStream& stream);
};
}
}
#endif // PXPVDSDK_PXPVDOBJECTMODELMETADATA_H

View File

@ -0,0 +1,80 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "PxPvdObjectRegistrar.h"
namespace physx
{
namespace pvdsdk
{
bool ObjectRegistrar::addItem(const void* inItem)
{
physx::shdfnd::Mutex::ScopedLock lock(mRefCountMapLock);
if(mRefCountMap.find(inItem))
{
uint32_t& counter = mRefCountMap[inItem];
counter++;
return false;
}
else
{
mRefCountMap.insert(inItem, 1);
return true;
}
}
bool ObjectRegistrar::decItem(const void* inItem)
{
physx::shdfnd::Mutex::ScopedLock lock(mRefCountMapLock);
const physx::shdfnd::HashMap<const void*, uint32_t>::Entry* entry = mRefCountMap.find(inItem);
if(entry)
{
uint32_t& retval(const_cast<uint32_t&>(entry->second));
if(retval)
--retval;
uint32_t theValue = retval;
if(theValue == 0)
{
mRefCountMap.erase(inItem);
return true;
}
}
return false;
}
void ObjectRegistrar::clear()
{
physx::shdfnd::Mutex::ScopedLock lock(mRefCountMapLock);
mRefCountMap.clear();
}
} // pvdsdk
} // physx

View File

@ -0,0 +1,71 @@
//
// 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-2021 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_PXPVDOBJECTREGISTRAR_H
#define PXPVDSDK_PXPVDOBJECTREGISTRAR_H
/** \addtogroup pvd
@{
*/
#include "PsHashMap.h"
#include "PsMutex.h"
#if !PX_DOXYGEN
namespace physx
{
namespace pvdsdk
{
#endif
class ObjectRegistrar
{
PX_NOCOPY(ObjectRegistrar)
public:
ObjectRegistrar()
{
}
virtual ~ObjectRegistrar()
{
}
bool addItem(const void* inItem);
bool decItem(const void* inItem);
void clear();
private:
physx::shdfnd::HashMap<const void*, uint32_t> mRefCountMap;
physx::shdfnd::Mutex mRefCountMapLock;
};
#if !PX_DOXYGEN
} // pvdsdk
} // physx
#endif
/** @} */
#endif // PXPVDSDK_PXPVDOBJECTREGISTRAR_H

View File

@ -0,0 +1,142 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
#ifndef PXPVDSDK_PXPVDPROFILEZONE_H
#define PXPVDSDK_PXPVDPROFILEZONE_H
#include "foundation/PxPreprocessor.h"
#include "PxProfileEventBufferClientManager.h"
#include "PxProfileEventNames.h"
#include "PxProfileEventSender.h"
namespace physx {
class PxAllocatorCallback;
namespace profile {
class PxProfileZoneManager;
/**
\brief The profiling system was setup in the expectation that there would be several
systems that each had its own island of profile information. PhysX, client code,
and APEX would be the first examples of these. Each one of these islands is represented
by a profile zone.
A profile zone combines a name, a place where all the events coming from its interface
can flushed, and a mapping from event number to full event name.
It also provides a top level filtering service where profile events
can be filtered by event id.
The profile zone implements a system where if there is no one
listening to events it doesn't provide a mechanism to send them. In this way
the event system is short circuited when there aren't any clients.
All functions on this interface should be considered threadsafe.
@see PxProfileZoneClientManager, PxProfileNameProvider, PxProfileEventSender, PxProfileEventFlusher
*/
class PxProfileZone : public PxProfileZoneClientManager
, public PxProfileNameProvider
, public PxProfileEventSender
, public PxProfileEventFlusher
{
protected:
virtual ~PxProfileZone(){}
public:
/**
\brief Get profile zone name.
\return Zone name.
*/
virtual const char* getName() = 0;
/**
\brief Release the profile zone.
*/
virtual void release() = 0;
/**
\brief Set profile zone manager for the zone.
\param inMgr Profile zone manager.
*/
virtual void setProfileZoneManager(PxProfileZoneManager* inMgr) = 0;
/**
\brief Get profile zone manager for the zone.
\return Profile zone manager.
*/
virtual PxProfileZoneManager* getProfileZoneManager() = 0;
/**
\brief Get or create a new event id for a given name.
If you pass in a previously defined event name (including one returned)
from the name provider) you will just get the same event id back.
\param inName Profile event name.
*/
virtual uint16_t getEventIdForName( const char* inName ) = 0;
/**
\brief Specifies that it is a safe point to flush read-write name map into
read-only map. Make sure getEventIdForName is not called from a different thread.
*/
virtual void flushEventIdNameMap() = 0;
/**
\brief Reserve a contiguous set of profile event ids for a set of names.
This function does not do any meaningful error checking other than to ensure
that if it does generate new ids they are contiguous. If the first name is already
registered, that is the ID that will be returned regardless of what other
names are registered. Thus either use this function alone (without the above
function) or don't use it.
If you register "one","two","three" and the function returns an id of 4, then
"one" is mapped to 4, "two" is mapped to 5, and "three" is mapped to 6.
\param inNames set of names to register.
\param inLen Length of the name list.
\return The first id associated with the first name. The rest of the names
will be associated with monotonically incrementing uint16_t values from the first
id.
*/
virtual uint16_t getEventIdsForNames( const char** inNames, uint32_t inLen ) = 0;
/**
\brief Create a new profile zone.
\param inAllocator memory allocation is controlled through the foundation if one is passed in.
\param inSDKName Name of the profile zone; useful for clients to understand where events came from.
\param inNames Mapping from event id -> event name.
\param inEventBufferByteSize Size of the canonical event buffer. This does not need to be a large number
as profile events are fairly small individually.
\return a profile zone implementation.
*/
static PxProfileZone& createProfileZone(PxAllocatorCallback* inAllocator, const char* inSDKName, PxProfileNames inNames = PxProfileNames(), uint32_t inEventBufferByteSize = 0x10000 /*64k*/);
};
} }
#endif // PXPVDSDK_PXPVDPROFILEZONE_H

View File

@ -0,0 +1,161 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "PxPvdImpl.h"
#include "PxPvdProfileZoneClient.h"
#include "PxPvdProfileZone.h"
namespace physx
{
namespace pvdsdk
{
struct ProfileZoneClient : public profile::PxProfileZoneClient, public shdfnd::UserAllocated
{
profile::PxProfileZone& mZone;
PvdDataStream& mStream;
ProfileZoneClient(profile::PxProfileZone& zone, PvdDataStream& stream) : mZone(zone), mStream(stream)
{
}
~ProfileZoneClient()
{
mZone.removeClient(*this);
}
virtual void createInstance()
{
mStream.addProfileZone(&mZone, mZone.getName());
mStream.createInstance(&mZone);
mZone.addClient(*this);
profile::PxProfileNames names(mZone.getProfileNames());
PVD_FOREACH(idx, names.eventCount)
{
handleEventAdded(names.events[idx]);
}
}
virtual void handleEventAdded(const profile::PxProfileEventName& inName)
{
mStream.addProfileZoneEvent(&mZone, inName.name, inName.eventId.eventId, inName.eventId.compileTimeEnabled);
}
virtual void handleBufferFlush(const uint8_t* inData, uint32_t inLength)
{
mStream.setPropertyValue(&mZone, "events", inData, inLength);
}
virtual void handleClientRemoved()
{
mStream.destroyInstance(&mZone);
}
private:
ProfileZoneClient& operator=(const ProfileZoneClient&);
};
}
}
using namespace physx;
using namespace pvdsdk;
PvdProfileZoneClient::PvdProfileZoneClient(PvdImpl& pvd) : mSDKPvd(pvd), mPvdDataStream(NULL), mIsConnected(false)
{
}
PvdProfileZoneClient::~PvdProfileZoneClient()
{
mSDKPvd.removeClient(this);
// all zones should removed
PX_ASSERT(mProfileZoneClients.size() == 0);
}
PvdDataStream* PvdProfileZoneClient::getDataStream()
{
return mPvdDataStream;
}
bool PvdProfileZoneClient::isConnected() const
{
return mIsConnected;
}
void PvdProfileZoneClient::onPvdConnected()
{
if(mIsConnected)
return;
mIsConnected = true;
mPvdDataStream = PvdDataStream::create(&mSDKPvd);
}
void PvdProfileZoneClient::onPvdDisconnected()
{
if(!mIsConnected)
return;
mIsConnected = false;
flush();
mPvdDataStream->release();
mPvdDataStream = NULL;
}
void PvdProfileZoneClient::flush()
{
PVD_FOREACH(idx, mProfileZoneClients.size())
mProfileZoneClients[idx]->mZone.flushProfileEvents();
}
void PvdProfileZoneClient::onZoneAdded(profile::PxProfileZone& zone)
{
PX_ASSERT(mIsConnected);
ProfileZoneClient* client = PVD_NEW(ProfileZoneClient)(zone, *mPvdDataStream);
mMutex.lock();
client->createInstance();
mProfileZoneClients.pushBack(client);
mMutex.unlock();
}
void PvdProfileZoneClient::onZoneRemoved(profile::PxProfileZone& zone)
{
for(uint32_t i = 0; i < mProfileZoneClients.size(); i++)
{
if(&zone == &mProfileZoneClients[i]->mZone)
{
mMutex.lock();
ProfileZoneClient* client = mProfileZoneClients[i];
mProfileZoneClients.replaceWithLast(i);
PVD_DELETE(client);
mMutex.unlock();
return;
}
}
}

View File

@ -0,0 +1,75 @@
//
// 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-2021 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_PXPVDPROFILEZONECLIENT_H
#define PXPVDSDK_PXPVDPROFILEZONECLIENT_H
#include "PxPvdClient.h"
#include "PsHashMap.h"
#include "PsMutex.h"
#include "PxProfileZoneManager.h"
namespace physx
{
namespace pvdsdk
{
class PvdImpl;
class PvdDataStream;
struct ProfileZoneClient;
class PvdProfileZoneClient : public PvdClient, public profile::PxProfileZoneHandler, public shdfnd::UserAllocated
{
PX_NOCOPY(PvdProfileZoneClient)
public:
PvdProfileZoneClient(PvdImpl& pvd);
virtual ~PvdProfileZoneClient();
bool isConnected() const;
void onPvdConnected();
void onPvdDisconnected();
void flush();
PvdDataStream* getDataStream();
// PxProfileZoneHandler
void onZoneAdded(profile::PxProfileZone& inSDK);
void onZoneRemoved(profile::PxProfileZone& inSDK);
private:
shdfnd::Mutex mMutex; // zoneAdded can called from different threads
PvdImpl& mSDKPvd;
PvdDataStream* mPvdDataStream;
physx::shdfnd::Array<ProfileZoneClient*> mProfileZoneClients;
bool mIsConnected;
};
} // namespace pvdsdk
} // namespace physx
#endif // PXPVDSDK_PXPVDPROFILEZONECLIENT_H

View File

@ -0,0 +1,385 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
#ifndef PXPVDSDK_PXPVDUSERRENDERIMPL_H
#define PXPVDSDK_PXPVDUSERRENDERIMPL_H
#include "PxPvdUserRenderer.h"
namespace physx
{
namespace pvdsdk
{
struct PvdUserRenderTypes
{
enum Enum
{
Unknown = 0,
#define DECLARE_PVD_IMMEDIATE_RENDER_TYPE(type) type,
#define DECLARE_PVD_IMMEDIATE_RENDER_TYPE_NO_COMMA(type) type
#include "PxPvdUserRenderTypes.h"
#undef DECLARE_PVD_IMMEDIATE_RENDER_TYPE_NO_COMMA
#undef DECLARE_PVD_IMMEDIATE_RENDER_TYPE
};
};
class RenderSerializer
{
protected:
virtual ~RenderSerializer()
{
}
public:
virtual void streamify(uint64_t& val) = 0;
virtual void streamify(float& val) = 0;
virtual void streamify(uint32_t& val) = 0;
virtual void streamify(uint8_t& val) = 0;
virtual void streamify(DataRef<uint8_t>& val) = 0;
virtual void streamify(DataRef<PvdDebugPoint>& val) = 0;
virtual void streamify(DataRef<PvdDebugLine>& val) = 0;
virtual void streamify(DataRef<PvdDebugTriangle>& val) = 0;
virtual void streamify(PvdDebugText& val) = 0;
virtual bool isGood() = 0;
virtual uint32_t hasData() = 0;
void streamify(PvdUserRenderTypes::Enum& val)
{
uint8_t data = static_cast<uint8_t>(val);
streamify(data);
val = static_cast<PvdUserRenderTypes::Enum>(data);
}
void streamify(PxVec3& val)
{
streamify(val[0]);
streamify(val[1]);
streamify(val[2]);
}
void streamify(PvdColor& val)
{
streamify(val.r);
streamify(val.g);
streamify(val.b);
streamify(val.a);
}
void streamify(PxTransform& val)
{
streamify(val.q.x);
streamify(val.q.y);
streamify(val.q.z);
streamify(val.q.w);
streamify(val.p.x);
streamify(val.p.y);
streamify(val.p.z);
}
void streamify(bool& val)
{
uint8_t tempVal = uint8_t(val ? 1 : 0);
streamify(tempVal);
val = tempVal ? true : false;
}
};
template <typename TBulkRenderType>
struct BulkRenderEvent
{
DataRef<TBulkRenderType> mData;
BulkRenderEvent(const TBulkRenderType* data, uint32_t count) : mData(data, count)
{
}
BulkRenderEvent()
{
}
void serialize(RenderSerializer& serializer)
{
serializer.streamify(mData);
}
};
struct SetInstanceIdRenderEvent
{
uint64_t mInstanceId;
SetInstanceIdRenderEvent(uint64_t iid) : mInstanceId(iid)
{
}
SetInstanceIdRenderEvent()
{
}
void serialize(RenderSerializer& serializer)
{
serializer.streamify(mInstanceId);
}
};
struct PointsRenderEvent : BulkRenderEvent<PvdDebugPoint>
{
PointsRenderEvent(const PvdDebugPoint* data, uint32_t count) : BulkRenderEvent<PvdDebugPoint>(data, count)
{
}
PointsRenderEvent()
{
}
};
struct LinesRenderEvent : BulkRenderEvent<PvdDebugLine>
{
LinesRenderEvent(const PvdDebugLine* data, uint32_t count) : BulkRenderEvent<PvdDebugLine>(data, count)
{
}
LinesRenderEvent()
{
}
};
struct TrianglesRenderEvent : BulkRenderEvent<PvdDebugTriangle>
{
TrianglesRenderEvent(const PvdDebugTriangle* data, uint32_t count) : BulkRenderEvent<PvdDebugTriangle>(data, count)
{
}
TrianglesRenderEvent()
{
}
};
struct DebugRenderEvent
{
DataRef<PvdDebugPoint> mPointData;
DataRef<PvdDebugLine> mLineData;
DataRef<PvdDebugTriangle> mTriangleData;
DebugRenderEvent(const PvdDebugPoint* pointData, uint32_t pointCount, const PvdDebugLine* lineData,
uint32_t lineCount, const PvdDebugTriangle* triangleData, uint32_t triangleCount)
: mPointData(pointData, pointCount), mLineData(lineData, lineCount), mTriangleData(triangleData, triangleCount)
{
}
DebugRenderEvent()
{
}
void serialize(RenderSerializer& serializer)
{
serializer.streamify(mPointData);
serializer.streamify(mLineData);
serializer.streamify(mTriangleData);
}
};
struct TextRenderEvent
{
PvdDebugText mText;
TextRenderEvent(const PvdDebugText& text)
{
mText.color = text.color;
mText.position = text.position;
mText.size = text.size;
mText.string = text.string;
}
TextRenderEvent()
{
}
void serialize(RenderSerializer& serializer)
{
serializer.streamify(mText);
}
};
struct JointFramesRenderEvent
{
PxTransform parent;
PxTransform child;
JointFramesRenderEvent(const PxTransform& p, const PxTransform& c) : parent(p), child(c)
{
}
JointFramesRenderEvent()
{
}
void serialize(RenderSerializer& serializer)
{
serializer.streamify(parent);
serializer.streamify(child);
}
};
struct LinearLimitRenderEvent
{
PxTransform t0;
PxTransform t1;
float value;
bool active;
LinearLimitRenderEvent(const PxTransform& _t0, const PxTransform& _t1, float _value, bool _active)
: t0(_t0), t1(_t1), value(_value), active(_active)
{
}
LinearLimitRenderEvent()
{
}
void serialize(RenderSerializer& serializer)
{
serializer.streamify(t0);
serializer.streamify(t1);
serializer.streamify(value);
serializer.streamify(active);
}
};
struct AngularLimitRenderEvent
{
PxTransform t0;
float lower;
float upper;
bool active;
AngularLimitRenderEvent(const PxTransform& _t0, float _lower, float _upper, bool _active)
: t0(_t0), lower(_lower), upper(_upper), active(_active)
{
}
AngularLimitRenderEvent()
{
}
void serialize(RenderSerializer& serializer)
{
serializer.streamify(t0);
serializer.streamify(lower);
serializer.streamify(upper);
serializer.streamify(active);
}
};
struct LimitConeRenderEvent
{
PxTransform t;
float ySwing;
float zSwing;
bool active;
LimitConeRenderEvent(const PxTransform& _t, float _ySwing, float _zSwing, bool _active)
: t(_t), ySwing(_ySwing), zSwing(_zSwing), active(_active)
{
}
LimitConeRenderEvent()
{
}
void serialize(RenderSerializer& serializer)
{
serializer.streamify(t);
serializer.streamify(ySwing);
serializer.streamify(zSwing);
serializer.streamify(active);
}
};
struct DoubleConeRenderEvent
{
PxTransform t;
float angle;
bool active;
DoubleConeRenderEvent(const PxTransform& _t, float _angle, bool _active) : t(_t), angle(_angle), active(_active)
{
}
DoubleConeRenderEvent()
{
}
void serialize(RenderSerializer& serializer)
{
serializer.streamify(t);
serializer.streamify(angle);
serializer.streamify(active);
}
};
template <typename TDataType>
struct RenderSerializerMap
{
void serialize(RenderSerializer& s, TDataType& d)
{
d.serialize(s);
}
};
template <>
struct RenderSerializerMap<uint8_t>
{
void serialize(RenderSerializer& s, uint8_t& d)
{
s.streamify(d);
}
};
template <>
struct RenderSerializerMap<PvdDebugPoint>
{
void serialize(RenderSerializer& s, PvdDebugPoint& d)
{
s.streamify(d.pos);
s.streamify(d.color);
}
};
template <>
struct RenderSerializerMap<PvdDebugLine>
{
void serialize(RenderSerializer& s, PvdDebugLine& d)
{
s.streamify(d.pos0);
s.streamify(d.color0);
s.streamify(d.pos1);
s.streamify(d.color1);
}
};
template <>
struct RenderSerializerMap<PvdDebugTriangle>
{
void serialize(RenderSerializer& s, PvdDebugTriangle& d)
{
s.streamify(d.pos0);
s.streamify(d.color0);
s.streamify(d.pos1);
s.streamify(d.color1);
s.streamify(d.pos2);
s.streamify(d.color2);
}
};
template <typename TDataType>
struct PvdTypeToRenderType
{
bool compile_error;
};
#define DECLARE_PVD_IMMEDIATE_RENDER_TYPE(type) \
template <> \
struct PvdTypeToRenderType<type##RenderEvent> \
{ \
enum Enum \
{ \
EnumVal = PvdUserRenderTypes::type \
}; \
};
#include "PxPvdUserRenderTypes.h"
#undef DECLARE_PVD_IMMEDIATE_RENDER_TYPE
template <typename TDataType>
PvdUserRenderTypes::Enum getPvdRenderTypeFromType()
{
return static_cast<PvdUserRenderTypes::Enum>(PvdTypeToRenderType<TDataType>::EnumVal);
}
}
}
#endif // PXPVDSDK_PXPVDUSERRENDERIMPL_H

View File

@ -0,0 +1,46 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
#define THERE_IS_NO_INCLUDE_GUARD_HERE_FOR_A_REASON
#ifndef DECLARE_PVD_IMMEDIATE_RENDER_TYPE_NO_COMMA
#define DECLARE_PVD_IMMEDIATE_RENDER_TYPE_NO_COMMA DECLARE_PVD_IMMEDIATE_RENDER_TYPE
#endif
DECLARE_PVD_IMMEDIATE_RENDER_TYPE(SetInstanceId)
DECLARE_PVD_IMMEDIATE_RENDER_TYPE(Points)
DECLARE_PVD_IMMEDIATE_RENDER_TYPE(Lines)
DECLARE_PVD_IMMEDIATE_RENDER_TYPE(Triangles)
DECLARE_PVD_IMMEDIATE_RENDER_TYPE(JointFrames)
DECLARE_PVD_IMMEDIATE_RENDER_TYPE(LinearLimit)
DECLARE_PVD_IMMEDIATE_RENDER_TYPE(AngularLimit)
DECLARE_PVD_IMMEDIATE_RENDER_TYPE(LimitCone)
DECLARE_PVD_IMMEDIATE_RENDER_TYPE(DoubleCone)
DECLARE_PVD_IMMEDIATE_RENDER_TYPE(Text)
DECLARE_PVD_IMMEDIATE_RENDER_TYPE_NO_COMMA(Debug)
#undef DECLARE_PVD_IMMEDIATE_RENDER_TYPE_NO_COMMA
#undef THERE_IS_NO_INCLUDE_GUARD_HERE_FOR_A_REASON

View File

@ -0,0 +1,405 @@
//
// 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-2021 NVIDIA Corporation. All rights reserved.
#include "PxPvdUserRenderImpl.h"
#include "PxPvdInternalByteStreams.h"
#include "PxPvdBits.h"
#include <stdarg.h>
using namespace physx;
using namespace physx::pvdsdk;
namespace
{
template <typename TStreamType>
struct RenderWriter : public RenderSerializer
{
TStreamType& mStream;
RenderWriter(TStreamType& stream) : mStream(stream)
{
}
template <typename TDataType>
void write(const TDataType* val, uint32_t count)
{
uint32_t numBytes = count * sizeof(TDataType);
mStream.write(reinterpret_cast<const uint8_t*>(val), numBytes);
}
template <typename TDataType>
void write(const TDataType& val)
{
write(&val, 1);
}
template <typename TDataType>
void writeRef(DataRef<TDataType>& val)
{
uint32_t amount = val.size();
write(amount);
if(amount)
write(val.begin(), amount);
}
virtual void streamify(uint64_t& val)
{
write(val);
}
virtual void streamify(uint32_t& val)
{
write(val);
}
virtual void streamify(float& val)
{
write(val);
}
virtual void streamify(uint8_t& val)
{
write(val);
}
virtual void streamify(DataRef<uint8_t>& val)
{
writeRef(val);
}
virtual void streamify(PvdDebugText& val)
{
write(val.color);
write(val.position);
write(val.size);
uint32_t amount = static_cast<uint32_t>(strlen(val.string)) + 1;
write(amount);
if(amount)
write(val.string, amount);
}
virtual void streamify(DataRef<PvdDebugPoint>& val)
{
writeRef(val);
}
virtual void streamify(DataRef<PvdDebugLine>& val)
{
writeRef(val);
}
virtual void streamify(DataRef<PvdDebugTriangle>& val)
{
writeRef(val);
}
virtual uint32_t hasData()
{
return false;
}
virtual bool isGood()
{
return true;
}
private:
RenderWriter& operator=(const RenderWriter&);
};
struct UserRenderer : public PvdUserRenderer
{
ForwardingMemoryBuffer mBuffer;
uint32_t mBufferCapacity;
RendererEventClient* mClient;
UserRenderer(uint32_t bufferFullAmount)
: mBuffer("UserRenderBuffer"), mBufferCapacity(bufferFullAmount), mClient(NULL)
{
}
virtual ~UserRenderer()
{
}
virtual void release()
{
PVD_DELETE(this);
}
template <typename TEventType>
void handleEvent(TEventType evt)
{
RenderWriter<ForwardingMemoryBuffer> _writer(mBuffer);
RenderSerializer& writer(_writer);
PvdUserRenderTypes::Enum evtType(getPvdRenderTypeFromType<TEventType>());
writer.streamify(evtType);
evt.serialize(writer);
if(mBuffer.size() >= mBufferCapacity)
flushRenderEvents();
}
virtual void setInstanceId(const void* iid)
{
handleEvent(SetInstanceIdRenderEvent(PVD_POINTER_TO_U64(iid)));
}
// Draw these points associated with this instance
virtual void drawPoints(const PvdDebugPoint* points, uint32_t count)
{
handleEvent(PointsRenderEvent(points, count));
}
// Draw these lines associated with this instance
virtual void drawLines(const PvdDebugLine* lines, uint32_t count)
{
handleEvent(LinesRenderEvent(lines, count));
}
// Draw these triangles associated with this instance
virtual void drawTriangles(const PvdDebugTriangle* triangles, uint32_t count)
{
handleEvent(TrianglesRenderEvent(triangles, count));
}
virtual void drawText(const PvdDebugText& text)
{
handleEvent(TextRenderEvent(text));
}
virtual void drawRenderbuffer(const PvdDebugPoint* pointData, uint32_t pointCount, const PvdDebugLine* lineData,
uint32_t lineCount, const PvdDebugTriangle* triangleData, uint32_t triangleCount)
{
handleEvent(DebugRenderEvent(pointData, pointCount, lineData, lineCount, triangleData, triangleCount));
}
// Constraint visualization routines
virtual void visualizeJointFrames(const PxTransform& parent, const PxTransform& child)
{
handleEvent(JointFramesRenderEvent(parent, child));
}
virtual void visualizeLinearLimit(const PxTransform& t0, const PxTransform& t1, float value, bool active)
{
handleEvent(LinearLimitRenderEvent(t0, t1, value, active));
}
virtual void visualizeAngularLimit(const PxTransform& t0, float lower, float upper, bool active)
{
handleEvent(AngularLimitRenderEvent(t0, lower, upper, active));
}
virtual void visualizeLimitCone(const PxTransform& t, float tanQSwingY, float tanQSwingZ, bool active)
{
handleEvent(LimitConeRenderEvent(t, tanQSwingY, tanQSwingZ, active));
}
virtual void visualizeDoubleCone(const PxTransform& t, float angle, bool active)
{
handleEvent(DoubleConeRenderEvent(t, angle, active));
}
// Clear the immedate buffer.
virtual void flushRenderEvents()
{
if(mClient)
mClient->handleBufferFlush(mBuffer.begin(), mBuffer.size());
mBuffer.clear();
}
virtual void setClient(RendererEventClient* client)
{
mClient = client;
}
private:
UserRenderer& operator=(const UserRenderer&);
};
template <bool swapBytes>
struct RenderReader : public RenderSerializer
{
MemPvdInputStream mStream;
ForwardingMemoryBuffer& mBuffer;
RenderReader(ForwardingMemoryBuffer& buf) : mBuffer(buf)
{
}
void setData(DataRef<const uint8_t> data)
{
mStream.setup(const_cast<uint8_t*>(data.begin()), const_cast<uint8_t*>(data.end()));
}
virtual void streamify(uint32_t& val)
{
mStream >> val;
}
virtual void streamify(uint64_t& val)
{
mStream >> val;
}
virtual void streamify(float& val)
{
mStream >> val;
}
virtual void streamify(uint8_t& val)
{
mStream >> val;
}
template <typename TDataType>
void readRef(DataRef<TDataType>& val)
{
uint32_t count;
mStream >> count;
uint32_t numBytes = sizeof(TDataType) * count;
TDataType* dataPtr = reinterpret_cast<TDataType*>(mBuffer.growBuf(numBytes));
mStream.read(reinterpret_cast<uint8_t*>(dataPtr), numBytes);
val = DataRef<TDataType>(dataPtr, count);
}
virtual void streamify(DataRef<PvdDebugPoint>& val)
{
readRef(val);
}
virtual void streamify(DataRef<PvdDebugLine>& val)
{
readRef(val);
}
virtual void streamify(DataRef<PvdDebugTriangle>& val)
{
readRef(val);
}
virtual void streamify(PvdDebugText& val)
{
mStream >> val.color;
mStream >> val.position;
mStream >> val.size;
uint32_t len = 0;
mStream >> len;
uint8_t* dataPtr = mBuffer.growBuf(len);
mStream.read(dataPtr, len);
val.string = reinterpret_cast<const char*>(dataPtr);
}
virtual void streamify(DataRef<uint8_t>& val)
{
readRef(val);
}
virtual bool isGood()
{
return mStream.isGood();
}
virtual uint32_t hasData()
{
return uint32_t(mStream.size() > 0);
}
private:
RenderReader& operator=(const RenderReader&);
};
template <>
struct RenderReader<true> : public RenderSerializer
{
MemPvdInputStream mStream;
ForwardingMemoryBuffer& mBuffer;
RenderReader(ForwardingMemoryBuffer& buf) : mBuffer(buf)
{
}
void setData(DataRef<const uint8_t> data)
{
mStream.setup(const_cast<uint8_t*>(data.begin()), const_cast<uint8_t*>(data.end()));
}
template <typename TDataType>
void read(TDataType& val)
{
mStream >> val;
swapBytes(val);
}
virtual void streamify(uint64_t& val)
{
read(val);
}
virtual void streamify(uint32_t& val)
{
read(val);
}
virtual void streamify(float& val)
{
read(val);
}
virtual void streamify(uint8_t& val)
{
read(val);
}
template <typename TDataType>
void readRef(DataRef<TDataType>& val)
{
uint32_t count;
mStream >> count;
swapBytes(count);
uint32_t numBytes = sizeof(TDataType) * count;
TDataType* dataPtr = reinterpret_cast<TDataType*>(mBuffer.growBuf(numBytes));
PVD_FOREACH(idx, count)
RenderSerializerMap<TDataType>().serialize(*this, dataPtr[idx]);
val = DataRef<TDataType>(dataPtr, count);
}
virtual void streamify(DataRef<PvdDebugPoint>& val)
{
readRef(val);
}
virtual void streamify(DataRef<PvdDebugLine>& val)
{
readRef(val);
}
virtual void streamify(DataRef<PvdDebugTriangle>& val)
{
readRef(val);
}
virtual void streamify(PvdDebugText& val)
{
mStream >> val.color;
mStream >> val.position;
mStream >> val.size;
uint32_t len = 0;
mStream >> len;
uint8_t* dataPtr = mBuffer.growBuf(len);
mStream.read(dataPtr, len);
val.string = reinterpret_cast<const char*>(dataPtr);
}
virtual void streamify(DataRef<uint8_t>& val)
{
readRef(val);
}
virtual bool isGood()
{
return mStream.isGood();
}
virtual uint32_t hasData()
{
return uint32_t(mStream.size() > 0);
}
private:
RenderReader& operator=(const RenderReader&);
};
}
PvdUserRenderer* PvdUserRenderer::create(uint32_t bufferSize)
{
return PVD_NEW(UserRenderer)(bufferSize);
}