diff options
| author | git perforce import user <a@b> | 2016-10-25 12:29:14 -0600 |
|---|---|---|
| committer | Sheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees> | 2016-10-25 18:56:37 -0500 |
| commit | 3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch) | |
| tree | fa6485c169e50d7415a651bf838f5bcd0fd3bfbd /PxShared/src/pvd | |
| download | physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.tar.xz physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.zip | |
Initial commit:
PhysX 3.4.0 Update @ 21294896
APEX 1.4.0 Update @ 21275617
[CL 21300167]
Diffstat (limited to 'PxShared/src/pvd')
77 files changed, 16354 insertions, 0 deletions
diff --git a/PxShared/src/pvd/include/PsPvd.h b/PxShared/src/pvd/include/PsPvd.h new file mode 100644 index 00000000..33f98bbe --- /dev/null +++ b/PxShared/src/pvd/include/PsPvd.h @@ -0,0 +1,85 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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; + +}; + +PX_PVDSDK_API void PX_CALL_CONV SetPvdAllocatorCallback(PxAllocatorCallback* inAllocatorCallback); + +#if !PX_DOXYGEN +} // namespace pvdsdk +} // namespace physx +#endif + +/** @} */ +#endif // PXPVDSDK_PSPVD_H diff --git a/PxShared/src/pvd/include/PxProfileAllocatorWrapper.h b/PxShared/src/pvd/include/PxProfileAllocatorWrapper.h new file mode 100644 index 00000000..3e4237eb --- /dev/null +++ b/PxShared/src/pvd/include/PxProfileAllocatorWrapper.h @@ -0,0 +1,231 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 + 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 diff --git a/PxShared/src/pvd/include/PxPvdClient.h b/PxShared/src/pvd/include/PxPvdClient.h new file mode 100644 index 00000000..8917d495 --- /dev/null +++ b/PxShared/src/pvd/include/PxPvdClient.h @@ -0,0 +1,77 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 PvdUserRenderer* getUserRender() = 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 diff --git a/PxShared/src/pvd/include/PxPvdDataStream.h b/PxShared/src/pvd/include/PxPvdDataStream.h new file mode 100644 index 00000000..870e5973 --- /dev/null +++ b/PxShared/src/pvd/include/PxPvdDataStream.h @@ -0,0 +1,272 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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. +*/ + PX_PVDSDK_API static PvdDataStream* create(PxPvd* pvd); +}; +#if !PX_DOXYGEN +} // pvdsdk +} // physx +#endif + +/** @} */ +#endif // PXPVDSDK_PXPVDDATASTREAM_H diff --git a/PxShared/src/pvd/include/PxPvdDataStreamHelpers.h b/PxShared/src/pvd/include/PxPvdDataStreamHelpers.h new file mode 100644 index 00000000..7517a2a0 --- /dev/null +++ b/PxShared/src/pvd/include/PxPvdDataStreamHelpers.h @@ -0,0 +1,120 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 diff --git a/PxShared/src/pvd/include/PxPvdErrorCodes.h b/PxShared/src/pvd/include/PxPvdErrorCodes.h new file mode 100644 index 00000000..bf5536fb --- /dev/null +++ b/PxShared/src/pvd/include/PxPvdErrorCodes.h @@ -0,0 +1,62 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 diff --git a/PxShared/src/pvd/include/PxPvdObjectModelBaseTypes.h b/PxShared/src/pvd/include/PxPvdObjectModelBaseTypes.h new file mode 100644 index 00000000..8fa0d376 --- /dev/null +++ b/PxShared/src/pvd/include/PxPvdObjectModelBaseTypes.h @@ -0,0 +1,428 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 diff --git a/PxShared/src/pvd/include/PxPvdRenderBuffer.h b/PxShared/src/pvd/include/PxPvdRenderBuffer.h new file mode 100644 index 00000000..47b020b4 --- /dev/null +++ b/PxShared/src/pvd/include/PxPvdRenderBuffer.h @@ -0,0 +1,140 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 diff --git a/PxShared/src/pvd/include/PxPvdUserRenderer.h b/PxShared/src/pvd/include/PxPvdUserRenderer.h new file mode 100644 index 00000000..e2a3c608 --- /dev/null +++ b/PxShared/src/pvd/include/PxPvdUserRenderer.h @@ -0,0 +1,107 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 ySwing, float zSwing, bool active) = 0; + virtual void visualizeDoubleCone(const PxTransform& t, float angle, bool active) = 0; + + // Clear the immedate buffer. + virtual void flushRenderEvents() = 0; + + PX_PVDSDK_API 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 diff --git a/PxShared/src/pvd/src/PxProfileBase.h b/PxShared/src/pvd/src/PxProfileBase.h new file mode 100644 index 00000000..ff6a5436 --- /dev/null +++ b/PxShared/src/pvd/src/PxProfileBase.h @@ -0,0 +1,35 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#ifndef PXPVDSDK_PXPROFILEBASE_H +#define PXPVDSDK_PXPROFILEBASE_H + +#include "foundation/PxSimpleTypes.h" + +#define PX_PROFILE_POINTER_TO_U64( pointer ) static_cast<uint64_t>(reinterpret_cast<size_t>(pointer)) + +#endif // PXPVDSDK_PXPROFILEBASE_H diff --git a/PxShared/src/pvd/src/PxProfileCompileTimeEventFilter.h b/PxShared/src/pvd/src/PxProfileCompileTimeEventFilter.h new file mode 100644 index 00000000..c1d5820c --- /dev/null +++ b/PxShared/src/pvd/src/PxProfileCompileTimeEventFilter.h @@ -0,0 +1,75 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#ifndef PXPVDSDK_PXPROFILECOMPILETIMEEVENTFILTER_H +#define PXPVDSDK_PXPROFILECOMPILETIMEEVENTFILTER_H + +#include "PxProfileBase.h" +#include "PxProfileEventId.h" + +//Define before including header in order to enable a different +//compile time event profile threshold. +#ifndef PX_PROFILE_EVENT_PROFILE_THRESHOLD +#define PX_PROFILE_EVENT_PROFILE_THRESHOLD EventPriorities::Medium +#endif + +namespace physx { namespace profile { + + /** + \brief Profile event priorities. Used to filter out events. + */ + struct EventPriorities + { + enum Enum + { + None, // the filter setting to kill all events + Coarse, + Medium, + Detail, + Never // the priority to set for an event if it should never fire. + }; + }; + + /** + \brief Gets the priority for a given event. + Specialize this object in order to get the priorities setup correctly. + */ + template<uint16_t TEventId> + struct EventPriority { static const uint32_t val = EventPriorities::Medium; }; + + /** + \brief Filter events by given event priority and set threshold. + */ + template<uint16_t TEventId> + struct EventFilter + { + static const bool val = EventPriority<TEventId>::val <= PX_PROFILE_EVENT_PROFILE_THRESHOLD; + }; + +}} + +#endif // PXPVDSDK_PXPROFILECOMPILETIMEEVENTFILTER_H diff --git a/PxShared/src/pvd/src/PxProfileContextProvider.h b/PxShared/src/pvd/src/PxProfileContextProvider.h new file mode 100644 index 00000000..f623c75e --- /dev/null +++ b/PxShared/src/pvd/src/PxProfileContextProvider.h @@ -0,0 +1,98 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#ifndef PXPVDSDK_PXPROFILECONTEXTPROVIDER_H +#define PXPVDSDK_PXPROFILECONTEXTPROVIDER_H + +#include "PxProfileBase.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; + } + }; + + //Provides the context in which the event is happening. + class PxProfileContextProvider + { + protected: + virtual ~PxProfileContextProvider(){} + public: + virtual PxProfileEventExecutionContext getExecutionContext() = 0; + virtual uint32_t getThreadId() = 0; + }; + //Provides pre-packaged context. + struct PxProfileTrivialContextProvider + { + PxProfileEventExecutionContext mContext; + PxProfileTrivialContextProvider( PxProfileEventExecutionContext inContext = PxProfileEventExecutionContext() ) + : mContext( inContext ) + { + } + PxProfileEventExecutionContext getExecutionContext() { return mContext; } + uint32_t getThreadId() { return mContext.mThreadId; } + }; + + //Forwards the get context calls to another (perhaps shared) context. + template<typename TProviderType> + struct PxProfileContextProviderForward + { + TProviderType* mProvider; + PxProfileContextProviderForward( TProviderType* inProvider ) : mProvider( inProvider ) {} + PxProfileEventExecutionContext getExecutionContext() { return mProvider->getExecutionContext(); } + uint32_t getThreadId() { return mProvider->getThreadId(); } + }; + + template<typename TProviderType> + struct PxProfileContextProviderImpl : public PxProfileContextProvider + { + PxProfileContextProviderForward<TProviderType> mContext; + PxProfileContextProviderImpl( TProviderType* inP ) : mContext( inP ) {} + PxProfileEventExecutionContext getExecutionContext() { return mContext.getExecutionContext(); } + uint32_t getThreadId() { return mContext.getThreadId(); } + }; + +} } + +#endif // PXPVDSDK_PXPROFILECONTEXTPROVIDER_H diff --git a/PxShared/src/pvd/src/PxProfileContextProviderImpl.h b/PxShared/src/pvd/src/PxProfileContextProviderImpl.h new file mode 100644 index 00000000..956998d0 --- /dev/null +++ b/PxShared/src/pvd/src/PxProfileContextProviderImpl.h @@ -0,0 +1,52 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 diff --git a/PxShared/src/pvd/src/PxProfileDataBuffer.h b/PxShared/src/pvd/src/PxProfileDataBuffer.h new file mode 100644 index 00000000..d97cff77 --- /dev/null +++ b/PxShared/src/pvd/src/PxProfileDataBuffer.h @@ -0,0 +1,167 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 mClients; + 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 ) ) + , mClients( 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( mClients.size() ) + { + removeClient( *mClients[0] ); + } + } + + PxProfileAllocatorWrapper& getWrapper() { return mWrapper; } + TMutexType* getBufferMutex() { return mBufferMutex; } + void setBufferMutex(TMutexType* mutex) { mBufferMutex = mutex; } + + void addClient( PxProfileEventBufferClient& inClient ) + { + TScopedLockType lock( mBufferMutex ); + mClients.pushBack( &inClient ); + mHasClients = true; + } + + void removeClient( PxProfileEventBufferClient& inClient ) + { + TScopedLockType lock( mBufferMutex ); + for ( uint32_t idx =0; idx < mClients.size(); ++idx ) + { + if ( mClients[idx] == &inClient ) + { + inClient.handleClientRemoved(); + mClients.replaceWithLast( idx ); + break; + } + } + mHasClients = mClients.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 = mClients.size(); + for( uint32_t idx =0; idx < clientCount; ++idx ) + mClients[idx]->handleBufferFlush( inData, inDataSize ); + } + + }; + +}} + + +#endif // PXPVDSDK_PXPROFILEDATABUFFER_H diff --git a/PxShared/src/pvd/src/PxProfileDataParsing.h b/PxShared/src/pvd/src/PxProfileDataParsing.h new file mode 100644 index 00000000..d4c0d388 --- /dev/null +++ b/PxShared/src/pvd/src/PxProfileDataParsing.h @@ -0,0 +1,218 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 "PxProfileBase.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 diff --git a/PxShared/src/pvd/src/PxProfileEventBuffer.h b/PxShared/src/pvd/src/PxProfileEventBuffer.h new file mode 100644 index 00000000..076d0626 --- /dev/null +++ b/PxShared/src/pvd/src/PxProfileEventBuffer.h @@ -0,0 +1,270 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 "PxProfileEventSystem.h" +#include "PxProfileDataBuffer.h" +#include "PxProfileContextProvider.h" + +#include "PsArray.h" +#include "PsTime.h" +#include "PsCpu.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 diff --git a/PxShared/src/pvd/src/PxProfileEventBufferAtomic.h b/PxShared/src/pvd/src/PxProfileEventBufferAtomic.h new file mode 100644 index 00000000..4bbe7e1d --- /dev/null +++ b/PxShared/src/pvd/src/PxProfileEventBufferAtomic.h @@ -0,0 +1,320 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 "PxProfileEventSystem.h" +#include "PxProfileDataBuffer.h" +#include "PxProfileContextProvider.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 diff --git a/PxShared/src/pvd/src/PxProfileEventBufferClient.h b/PxShared/src/pvd/src/PxProfileEventBufferClient.h new file mode 100644 index 00000000..be9752f1 --- /dev/null +++ b/PxShared/src/pvd/src/PxProfileEventBufferClient.h @@ -0,0 +1,81 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#ifndef PXPVDSDK_PXPROFILEEVENTBUFFERCLIENT_H +#define PXPVDSDK_PXPROFILEEVENTBUFFERCLIENT_H + +#include "PxProfileBase.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 diff --git a/PxShared/src/pvd/src/PxProfileEventBufferClientManager.h b/PxShared/src/pvd/src/PxProfileEventBufferClientManager.h new file mode 100644 index 00000000..e696ed3f --- /dev/null +++ b/PxShared/src/pvd/src/PxProfileEventBufferClientManager.h @@ -0,0 +1,94 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 diff --git a/PxShared/src/pvd/src/PxProfileEventFilter.h b/PxShared/src/pvd/src/PxProfileEventFilter.h new file mode 100644 index 00000000..eb27c393 --- /dev/null +++ b/PxShared/src/pvd/src/PxProfileEventFilter.h @@ -0,0 +1,93 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#ifndef PXPVDSDK_PXPROFILEEVENTFILTER_H +#define PXPVDSDK_PXPROFILEEVENTFILTER_H + +#include "foundation/PxAssert.h" +#include "PxProfileBase.h" +#include "PxProfileEventId.h" + +namespace physx { namespace profile { + + /** + \brief Called upon every event to give a quick-out before adding the event + to the event buffer. + + \note: not thread safe, can be called from different threads at the same time + */ + class PxProfileEventFilter + { + protected: + virtual ~PxProfileEventFilter(){} + public: + /** + \brief Disabled events will not go into the event buffer and will not be + transmitted to clients. + \param inId Profile event id. + \param isEnabled True if event should be enabled. + */ + virtual void setEventEnabled( const PxProfileEventId& inId, bool isEnabled ) = 0; + + /** + \brief Returns the current state of the profile event. + \return True if profile event is enabled. + */ + virtual bool isEventEnabled( const PxProfileEventId& inId ) const = 0; + }; + + /** + \brief Forwards the filter requests to another event filter. + */ + template<typename TFilterType> + struct PxProfileEventFilterForward + { + /** + \brief Default constructor. + */ + PxProfileEventFilterForward( TFilterType* inFilter ) : filter( inFilter ) {} + + /** + \brief Disabled events will not go into the event buffer and will not be + transmitted to clients. + \param inId Profile event id. + \param isEnabled True if event should be enabled. + */ + void setEventEnabled( const PxProfileEventId& inId, bool isEnabled ) { filter->setEventEnabled( inId, isEnabled ); } + + /** + \brief Returns the current state of the profile event. + \return True if profile event is enabled. + */ + bool isEventEnabled( const PxProfileEventId& inId ) const { return filter->isEventEnabled( inId ); } + + TFilterType* filter; + }; + +} } + +#endif // PXPVDSDK_PXPROFILEEVENTFILTER_H diff --git a/PxShared/src/pvd/src/PxProfileEventHandler.h b/PxShared/src/pvd/src/PxProfileEventHandler.h new file mode 100644 index 00000000..3dd0f8a2 --- /dev/null +++ b/PxShared/src/pvd/src/PxProfileEventHandler.h @@ -0,0 +1,99 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#ifndef PXPVDSDK_PXPROFILEEVENTHANDLER_H +#define PXPVDSDK_PXPROFILEEVENTHANDLER_H + +#include "PxProfileBase.h" +#include "PxProfileEventId.h" + +namespace physx { namespace profile { + + /** + \brief A client of the event system can expect to find these events in the event buffer. + */ + class PxProfileEventHandler + { + protected: + virtual ~PxProfileEventHandler(){} + public: + /** + \brief Event start - onStartEvent. + + \param[in] inId Profile event id. + \param[in] threadId Thread id. + \param[in] contextId Context id. + \param[in] cpuId CPU id. + \param[in] threadPriority Thread priority. + \param[in] timestamp Timestamp in cycles. + */ + virtual void onStartEvent( const PxProfileEventId& inId, uint32_t threadId, uint64_t contextId, uint8_t cpuId, uint8_t threadPriority, uint64_t timestamp ) = 0; + + /** + \brief Event stop - onStopEvent. + + \param[in] inId Profile event id. + \param[in] threadId Thread id. + \param[in] contextId Context id. + \param[in] cpuId CPU id. + \param[in] threadPriority Thread priority. + \param[in] timestamp Timestamp in cycles. + */ + virtual void onStopEvent( const PxProfileEventId& inId, uint32_t threadId, uint64_t contextId, uint8_t cpuId, uint8_t threadPriority, uint64_t timestamp ) = 0; + + /** + \brief Event value - onEventValue. + + \param[in] inId Profile event id. + \param[in] threadId Thread id. + \param[in] contextId Context id. + \param[in] inValue Value. + */ + virtual void onEventValue( const PxProfileEventId& inId, uint32_t threadId, uint64_t contextId, int64_t inValue ) = 0; + + /** + \brief Parse the flushed profile buffer which contains the profile events. + + \param[in] inBuffer The profile buffer with profile events. + \param[in] inBufferSize Buffer size. + \param[in] inHandler The profile event callback to receive the parsed events. + \param[in] inSwapBytes Swap bytes possibility. + */ + static void parseEventBuffer( const uint8_t* inBuffer, uint32_t inBufferSize, PxProfileEventHandler& inHandler, bool inSwapBytes ); + + /** + \brief Translates event duration in timestamp (cycles) into nanoseconds. + + \param[in] duration Timestamp duration of the event. + + \return event duration in nanoseconds. + */ + static uint64_t durationToNanoseconds(uint64_t duration); + }; +} } + +#endif // PXPVDSDK_PXPROFILEEVENTHANDLER_H diff --git a/PxShared/src/pvd/src/PxProfileEventId.h b/PxShared/src/pvd/src/PxProfileEventId.h new file mode 100644 index 00000000..f61d1792 --- /dev/null +++ b/PxShared/src/pvd/src/PxProfileEventId.h @@ -0,0 +1,80 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#ifndef PXPVDSDK_PXPROFILEEVENTID_H +#define PXPVDSDK_PXPROFILEEVENTID_H + +#include "PxProfileBase.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; + } + }; + + /** + \brief Template event id structure. + */ + template<bool TEnabled> + struct PxProfileCompileTimeFilteredEventId : public PxProfileEventId + { + /** + \brief Constructor. + \param inId Profile event id. + */ + PxProfileCompileTimeFilteredEventId( uint16_t inId = 0 ) + : PxProfileEventId( inId, TEnabled ) + { + } + }; + +} } + +#endif // PXPVDSDK_PXPROFILEEVENTID_H diff --git a/PxShared/src/pvd/src/PxProfileEventImpl.cpp b/PxShared/src/pvd/src/PxProfileEventImpl.cpp new file mode 100644 index 00000000..58bd0394 --- /dev/null +++ b/PxShared/src/pvd/src/PxProfileEventImpl.cpp @@ -0,0 +1,230 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#include "foundation/PxErrorCallback.h" +#include "foundation/PxAllocatorCallback.h" + +#include "PxProfileEvents.h" +#include "PxProfileEventSerialization.h" +#include "PxProfileEventBuffer.h" +#include "PxProfileZoneImpl.h" +#include "PxProfileZoneManagerImpl.h" +#include "PxProfileEventParser.h" +#include "PxProfileEventHandler.h" +#include "PxProfileScopedMutexLock.h" +#include "PxProfileEventFilter.h" +#include "PxProfileContextProvider.h" +#include "PxProfileEventMutex.h" +#include "PxProfileMemoryEventTypes.h" +#include "PxProfileMemoryEventRecorder.h" +#include "PxProfileMemoryEventBuffer.h" +#include "PxProfileMemoryEventParser.h" +#include "PxProfileContextProviderImpl.h" + +#include "PsUserAllocated.h" +#include "PsTime.h" + +#include <stdio.h> + +namespace physx { namespace profile { + + + uint64_t PxProfileEventHandler::durationToNanoseconds(uint64_t duration) + { + return shdfnd::Time::getBootCounterFrequency().toTensOfNanos(duration) * 10; + } + + void PxProfileEventHandler::parseEventBuffer( const uint8_t* inBuffer, uint32_t inBufferSize, PxProfileEventHandler& inHandler, bool inSwapBytes ) + { + if ( inSwapBytes == false ) + parseEventData<false>( inBuffer, inBufferSize, &inHandler ); + else + parseEventData<true>( inBuffer, inBufferSize, &inHandler ); + } + + template<uint32_t TNumEvents> + struct ProfileBulkEventHandlerBuffer + { + Event mEvents[TNumEvents]; + uint32_t mEventCount; + PxProfileBulkEventHandler* mHandler; + ProfileBulkEventHandlerBuffer( PxProfileBulkEventHandler* inHdl ) + : mEventCount( 0 ) + , mHandler( inHdl ) + { + } + void onEvent( const Event& inEvent ) + { + mEvents[mEventCount] = inEvent; + ++mEventCount; + if ( mEventCount == TNumEvents ) + flush(); + } + void onEvent( const PxProfileEventId& inId, uint32_t threadId, uint64_t contextId, uint8_t cpuId, uint8_t threadPriority, uint64_t timestamp, EventTypes::Enum inType ) + { + StartEvent theEvent; + theEvent.init( threadId, contextId, cpuId, static_cast<uint8_t>( threadPriority ), timestamp ); + onEvent( Event( EventHeader( static_cast<uint8_t>( inType ), inId.eventId ), theEvent ) ); + } + void onStartEvent( const PxProfileEventId& inId, uint32_t threadId, uint64_t contextId, uint8_t cpuId, uint8_t threadPriority, uint64_t timestamp ) + { + onEvent( inId, threadId, contextId, cpuId, threadPriority, timestamp, EventTypes::StartEvent ); + } + void onStopEvent( const PxProfileEventId& inId, uint32_t threadId, uint64_t contextId, uint8_t cpuId, uint8_t threadPriority, uint64_t timestamp ) + { + onEvent( inId, threadId, contextId, cpuId, threadPriority, timestamp, EventTypes::StopEvent ); + } + void onEventValue( const PxProfileEventId& inId, uint32_t threadId, uint64_t contextId, int64_t value ) + { + EventValue theEvent; + theEvent.init( value, contextId, threadId ); + onEvent( Event( inId.eventId, theEvent ) ); + } + void flush() + { + if ( mEventCount ) + mHandler->handleEvents( mEvents, mEventCount ); + mEventCount = 0; + } + }; + + + void PxProfileBulkEventHandler::parseEventBuffer( const uint8_t* inBuffer, uint32_t inBufferSize, PxProfileBulkEventHandler& inHandler, bool inSwapBytes ) + { + ProfileBulkEventHandlerBuffer<256> hdler( &inHandler ); + if ( inSwapBytes ) + parseEventData<true>( inBuffer, inBufferSize, &hdler ); + else + parseEventData<false>( inBuffer, inBufferSize, &hdler ); + hdler.flush(); + } + + struct PxProfileNameProviderImpl + { + PxProfileNameProvider* mImpl; + PxProfileNameProviderImpl( PxProfileNameProvider* inImpl ) + : mImpl( inImpl ) + { + } + PxProfileNames getProfileNames() const { return mImpl->getProfileNames(); } + }; + + + struct PxProfileNameProviderForward + { + PxProfileNames mNames; + PxProfileNameProviderForward( PxProfileNames inNames ) + : mNames( inNames ) + { + } + PxProfileNames getProfileNames() const { return mNames; } + }; + + + PX_FOUNDATION_API 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 ); + } + + PxProfileMemoryEventRecorder& PxProfileMemoryEventRecorder::createRecorder( PxAllocatorCallback* inAllocator ) + { + return *PX_PROFILE_NEW( inAllocator, PxProfileMemoryEventRecorderImpl )( inAllocator ); + } + + PxProfileMemoryEventBuffer& PxProfileMemoryEventBuffer::createMemoryEventBuffer( PxAllocatorCallback& inAllocator, uint32_t inBufferSize ) + { + return *PX_PROFILE_NEW( &inAllocator, PxProfileMemoryEventBufferImpl )( inAllocator, inBufferSize ); + } + template<uint32_t TNumEvents> + struct ProfileBulkMemoryEventHandlerBuffer + { + PxProfileBulkMemoryEvent mEvents[TNumEvents]; + uint32_t mEventCount; + PxProfileBulkMemoryEventHandler* mHandler; + ProfileBulkMemoryEventHandlerBuffer( PxProfileBulkMemoryEventHandler* inHdl ) + : mEventCount( 0 ) + , mHandler( inHdl ) + { + } + void onEvent( const PxProfileBulkMemoryEvent& evt ) + { + mEvents[mEventCount] = evt; + ++mEventCount; + if ( mEventCount == TNumEvents ) + flush(); + } + + template<typename TDataType> + void operator()( const MemoryEventHeader&, const TDataType& ) {} + + void operator()( const MemoryEventHeader&, const AllocationEvent& evt ) + { + onEvent( PxProfileBulkMemoryEvent( evt.mSize, evt.mType, evt.mFile, evt.mLine, evt.mAddress ) ); + } + + void operator()( const MemoryEventHeader&, const DeallocationEvent& evt ) + { + onEvent( PxProfileBulkMemoryEvent( evt.mAddress ) ); + } + + void flush() + { + if ( mEventCount ) + mHandler->handleEvents( mEvents, mEventCount ); + mEventCount = 0; + } + }; + + void PxProfileBulkMemoryEventHandler::parseEventBuffer( const uint8_t* inBuffer, uint32_t inBufferSize, PxProfileBulkMemoryEventHandler& inHandler, bool inSwapBytes, PxAllocatorCallback* inAlloc ) + { + PX_ASSERT(inAlloc); + + ProfileBulkMemoryEventHandlerBuffer<0x1000>* theBuffer = PX_PROFILE_NEW(inAlloc, ProfileBulkMemoryEventHandlerBuffer<0x1000>)(&inHandler); + + if ( inSwapBytes ) + { + MemoryEventParser<true> theParser( *inAlloc ); + theParser.parseEventData( inBuffer, inBufferSize, theBuffer ); + } + else + { + MemoryEventParser<false> theParser( *inAlloc ); + theParser.parseEventData( inBuffer, inBufferSize, theBuffer ); + } + theBuffer->flush(); + + PX_PROFILE_DELETE(*inAlloc, theBuffer); + } + +} } + diff --git a/PxShared/src/pvd/src/PxProfileEventMutex.h b/PxShared/src/pvd/src/PxProfileEventMutex.h new file mode 100644 index 00000000..9c42a73b --- /dev/null +++ b/PxShared/src/pvd/src/PxProfileEventMutex.h @@ -0,0 +1,63 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + + +#ifndef PXPVDSDK_PXPROFILEEVENTMUTEX_H +#define PXPVDSDK_PXPROFILEEVENTMUTEX_H + +#include "PxProfileBase.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 diff --git a/PxShared/src/pvd/src/PxProfileEventNames.h b/PxShared/src/pvd/src/PxProfileEventNames.h new file mode 100644 index 00000000..e69c1564 --- /dev/null +++ b/PxShared/src/pvd/src/PxProfileEventNames.h @@ -0,0 +1,90 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#ifndef PXPVDSDK_PXPROFILEEVENTNAMES_H +#define PXPVDSDK_PXPROFILEEVENTNAMES_H + +#include "PxProfileBase.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 diff --git a/PxShared/src/pvd/src/PxProfileEventParser.h b/PxShared/src/pvd/src/PxProfileEventParser.h new file mode 100644 index 00000000..06e55321 --- /dev/null +++ b/PxShared/src/pvd/src/PxProfileEventParser.h @@ -0,0 +1,193 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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_PXPROFILEEVENTPARSER_H +#define PXPVDSDK_PXPROFILEEVENTPARSER_H + +#include "PxProfileEvents.h" +#include "PxProfileEventSerialization.h" + +namespace physx { namespace profile { + + struct EventParserData + { + EventContextInformation mContextInformation; + uint64_t mLastTimestamp; + + EventParserData() : mLastTimestamp(0) + { + } + }; + + //This object will be copied a lot so all of its important + //data must be pointers. + template<typename THandlerType, bool TSwapBytes> + struct EventParseOperator + { + typedef EventDeserializer<TSwapBytes> TDeserializerType; + + EventParserData* mData; + TDeserializerType* mDeserializer; + EventHeader* mHeader; + THandlerType* mHandler; + + EventParseOperator( EventParserData* inData, TDeserializerType* inDeserializer, EventHeader* inHeader, THandlerType* inHandler ) + : mData( inData ) + , mDeserializer( inDeserializer ) + , mHeader( inHeader ) + , mHandler( inHandler ) + {} + + template<typename TEventType> + bool parse( TEventType& ioEvent ) + { + ioEvent.streamify( *mDeserializer, *mHeader ); + bool success = mDeserializer->mFail == false; + PX_ASSERT( success ); + return success; + } + + bool parseHeader( EventHeader& ioEvent ) + { + ioEvent.streamify( *mDeserializer ); + bool success = mDeserializer->mFail == false; + PX_ASSERT( success ); + return success; + } + + template<typename TEventType> + bool handleProfileEvent( TEventType& evt ) + { + bool retval = parse( evt ); + if ( retval ) + { + mData->mContextInformation = evt.mContextInformation; + handle( evt.getRelativeEvent(), evt.mContextInformation ); + } + return retval; + } + + template<typename TEventType> + bool handleRelativeProfileEvent( TEventType& evt ) + { + bool retval = parse( evt ); + if ( retval ) + handle( evt, mData->mContextInformation ); + return retval; + } + + template<typename TRelativeEventType> + void handle( const TRelativeEventType& evt, const EventContextInformation& inInfo ) + { + mData->mLastTimestamp = mHeader->uncompressTimestamp( mData->mLastTimestamp, evt.getTimestamp()); + const_cast<TRelativeEventType&>(evt).setTimestamp( mData->mLastTimestamp ); + evt.handle( mHandler, mHeader->mEventId + , inInfo.mThreadId + , inInfo.mContextId + , inInfo.mCpuId + , inInfo.mThreadPriority ); + } + + bool operator()( const StartEvent& ) + { + StartEvent evt; + return handleProfileEvent( evt ); + } + bool operator()( const StopEvent& ) + { + StopEvent evt; + return handleProfileEvent( evt ); + } + bool operator()( const RelativeStartEvent& ) + { + RelativeStartEvent evt; + return handleRelativeProfileEvent( evt ); + + } + bool operator()( const RelativeStopEvent& ) + { + RelativeStopEvent evt; + return handleRelativeProfileEvent( evt ); + } + bool operator()( const EventValue& ) + { + EventValue evt; + bool retval = parse( evt ); + if ( retval ) + { + evt.mValue = mHeader->uncompressTimestamp( 0, evt.mValue ); + evt.handle( mHandler, mHeader->mEventId ); + } + return retval; + } + + //obsolete, placeholder to skip data from PhysX SDKs < 3.4 + bool operator()( const CUDAProfileBuffer& ) + { + CUDAProfileBuffer evt; + bool retval = parse( evt ); + return retval; + } + + //Unknown event type. + bool operator()(uint8_t ) + { + PX_ASSERT( false ); + return false; + } + }; + + template<bool TSwapBytes, typename THandlerType> + inline bool parseEventData( const uint8_t* inData, uint32_t inLength, THandlerType* inHandler ) + { + EventDeserializer<TSwapBytes> deserializer( inData, inLength ); + Event::EventData crapData; + EventHeader theHeader; + EventParserData theData; + EventParseOperator<THandlerType,TSwapBytes> theOp( &theData, &deserializer, &theHeader, inHandler ); + while( deserializer.mLength && deserializer.mFail == false) + { + if ( theOp.parseHeader( theHeader ) ) + visit<bool>( static_cast<EventTypes::Enum>( theHeader.mEventType ), crapData, theOp ); + } + return deserializer.mFail == false; + } + + class PxProfileBulkEventHandler + { + protected: + virtual ~PxProfileBulkEventHandler(){} + public: + virtual void handleEvents(const physx::profile::Event* inEvents, uint32_t inBufferSize) = 0; + static void parseEventBuffer(const uint8_t* inBuffer, uint32_t inBufferSize, PxProfileBulkEventHandler& inHandler, bool inSwapBytes); + }; +}} + +#endif // PXPVDSDK_PXPROFILEEVENTPARSER_H diff --git a/PxShared/src/pvd/src/PxProfileEventSender.h b/PxShared/src/pvd/src/PxProfileEventSender.h new file mode 100644 index 00000000..d954b6d6 --- /dev/null +++ b/PxShared/src/pvd/src/PxProfileEventSender.h @@ -0,0 +1,129 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#ifndef PXPVDSDK_PXPROFILEEVENTSENDER_H +#define PXPVDSDK_PXPROFILEEVENTSENDER_H + +#include "PxProfileBase.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; + }; + + /** + \brief Tagging interface to indicate an object that may or may not return + an object capable of adding profile events to a buffer. + */ + class PxProfileEventSenderProvider + { + protected: + virtual ~PxProfileEventSenderProvider(){} + public: + /** + \brief This method can *always* return NULL. + Thus need to always check that what you are getting is what + you think it is. + + \return Perhaps a profile event sender. + */ + virtual PxProfileEventSender* getProfileEventSender() = 0; + }; +} } + +#endif // PXPVDSDK_PXPROFILEEVENTSENDER_H diff --git a/PxShared/src/pvd/src/PxProfileEventSerialization.h b/PxShared/src/pvd/src/PxProfileEventSerialization.h new file mode 100644 index 00000000..a6a47b0d --- /dev/null +++ b/PxShared/src/pvd/src/PxProfileEventSerialization.h @@ -0,0 +1,258 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 "PxProfileBase.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 diff --git a/PxShared/src/pvd/src/PxProfileEventSystem.h b/PxShared/src/pvd/src/PxProfileEventSystem.h new file mode 100644 index 00000000..1a24568a --- /dev/null +++ b/PxShared/src/pvd/src/PxProfileEventSystem.h @@ -0,0 +1,56 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#ifndef PXPVDSDK_PXPROFILEEVENTSYSTEM_H +#define PXPVDSDK_PXPROFILEEVENTSYSTEM_H + +#include "PxProfileBase.h" +#include "PxProfileEventSender.h" +#include "PxProfileEventBufferClient.h" +#include "PxProfileEventBufferClientManager.h" + +namespace physx { namespace profile { + class PxProfileContextProvider; + class PxProfileEventMutex; + class PxProfileEventFilter; + + /** + * Wraps the different interfaces into one object. + */ + class PxProfileEventSystem : public PxProfileEventSender + , public PxProfileEventBufferClient + , public PxProfileEventBufferClientManager + , public PxProfileEventFlusher + { + protected: + ~PxProfileEventSystem(){} + public: + virtual void release() = 0; + }; +} } + +#endif // PXPVDSDK_PXPROFILEEVENTSYSTEM_H diff --git a/PxShared/src/pvd/src/PxProfileEvents.h b/PxShared/src/pvd/src/PxProfileEvents.h new file mode 100644 index 00000000..99a4613c --- /dev/null +++ b/PxShared/src/pvd/src/PxProfileEvents.h @@ -0,0 +1,706 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#ifndef PXPVDSDK_PXPROFILEEVENTS_H +#define PXPVDSDK_PXPROFILEEVENTS_H + +#include "foundation/PxMath.h" +#include "foundation/PxAssert.h" + +#include "PxProfileBase.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 diff --git a/PxShared/src/pvd/src/PxProfileMemory.h b/PxShared/src/pvd/src/PxProfileMemory.h new file mode 100644 index 00000000..7141fb89 --- /dev/null +++ b/PxShared/src/pvd/src/PxProfileMemory.h @@ -0,0 +1,99 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 "PxProfileBase.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 Create the profile memory event recorder. + \param inAllocator Allocation callback. + */ + static PxProfileMemoryEventRecorder& createRecorder(PxAllocatorCallback* inAllocator); + }; + + /** + \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 + + diff --git a/PxShared/src/pvd/src/PxProfileMemoryBuffer.h b/PxShared/src/pvd/src/PxProfileMemoryBuffer.h new file mode 100644 index 00000000..f20139cd --- /dev/null +++ b/PxShared/src/pvd/src/PxProfileMemoryBuffer.h @@ -0,0 +1,192 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 "PxProfileBase.h" +#include "PsAllocator.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 ); + memcpy( 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); + memcpy(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 ) + { + memcpy( 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); + memcpy(mBegin + size(), inValue, writeSize); + mEnd += writeSize; + return writeSize; + } + return 0; + } + }; + +}} + +#endif // PXPVDSDK_PXPROFILEMEMORYBUFFER_H diff --git a/PxShared/src/pvd/src/PxProfileMemoryEventBuffer.h b/PxShared/src/pvd/src/PxProfileMemoryEventBuffer.h new file mode 100644 index 00000000..a7d057ed --- /dev/null +++ b/PxShared/src/pvd/src/PxProfileMemoryEventBuffer.h @@ -0,0 +1,156 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 "PxProfileMemoryEventTypes.h" +#include "PxProfileScopedMutexLock.h" +#include "PxProfileAllocatorWrapper.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), PX_PROFILE_POINTER_TO_U64( allocatedMemory ) ); + } + virtual void onDeallocation( void* allocatedMemory ) + { + mBuffer.onDeallocation( PX_PROFILE_POINTER_TO_U64( 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 diff --git a/PxShared/src/pvd/src/PxProfileMemoryEventParser.h b/PxShared/src/pvd/src/PxProfileMemoryEventParser.h new file mode 100644 index 00000000..3d716149 --- /dev/null +++ b/PxShared/src/pvd/src/PxProfileMemoryEventParser.h @@ -0,0 +1,185 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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_PXPROFILEMEMORYEVENTPARSER_H +#define PXPVDSDK_PXPROFILEMEMORYEVENTPARSER_H + +#include "PxProfileMemoryEvents.h" +#include "PxProfileAllocatorWrapper.h" +#include "PxProfileEventSerialization.h" + +#include "PsHashMap.h" +#include "PsString.h" + +namespace physx { namespace profile { + + template<bool TSwapBytes, typename TParserType, typename THandlerType> + bool parseEventData( TParserType& inParser, const uint8_t* inData, uint32_t inLength, THandlerType* inHandler ); + + template<bool TSwapBytes> + struct MemoryEventParser + { + typedef PxProfileWrapperReflectionAllocator<uint8_t> TAllocatorType; + typedef shdfnd::HashMap<uint32_t, char*, shdfnd::Hash<uint32_t>, TAllocatorType > THdlToStringMap; + typedef EventDeserializer<TSwapBytes> TDeserializerType; + + PxProfileAllocatorWrapper mWrapper; + THdlToStringMap mHdlToStringMap; + TDeserializerType mDeserializer; + + MemoryEventParser( PxAllocatorCallback& inAllocator ) + : mWrapper( inAllocator ) + , mHdlToStringMap( TAllocatorType( mWrapper ) ) + , mDeserializer ( 0, 0 ) + { + } + + ~MemoryEventParser() + { + for ( THdlToStringMap::Iterator iter( mHdlToStringMap.getIterator() ); iter.done() == false; ++iter ) + mWrapper.getAllocator().deallocate( reinterpret_cast<void*>(iter->second) ); + } + + template<typename TOperator> + void parse(const StringTableEvent&, const MemoryEventHeader& inHeader, TOperator& inOperator) + { + StringTableEvent evt; + evt.init(); + evt.streamify( mDeserializer, inHeader ); + uint32_t len = static_cast<uint32_t>( strlen( evt.mString ) ); + char* newStr = static_cast<char*>( mWrapper.getAllocator().allocate( len + 1, "const char*", __FILE__, __LINE__ ) ); + shdfnd::strlcpy( newStr, len+1, evt.mString ); + mHdlToStringMap[evt.mHandle] = newStr; + inOperator( inHeader, evt ); + } + + const char* getString( uint32_t inHdl ) + { + const THdlToStringMap::Entry* entry = mHdlToStringMap.find( inHdl ); + if ( entry ) return entry->second; + return ""; + } + + //Slow reverse lookup used only for testing. + uint32_t getHandle( const char* inStr ) + { + for ( THdlToStringMap::Iterator iter = mHdlToStringMap.getIterator(); + !iter.done(); + ++iter ) + { + if ( safeStrEq( iter->second, inStr ) ) + return iter->first; + } + return 0; + } + + template<typename TOperator> + void parse(const AllocationEvent&, const MemoryEventHeader& inHeader, TOperator& inOperator) + { + AllocationEvent evt; + evt.streamify( mDeserializer, inHeader ); + inOperator( inHeader, evt ); + } + + template<typename TOperator> + void parse(const DeallocationEvent&, const MemoryEventHeader& inHeader, TOperator& inOperator) + { + DeallocationEvent evt; + evt.streamify( mDeserializer, inHeader ); + inOperator( inHeader, evt ); + } + + template<typename TOperator> + void parse(const FullAllocationEvent&, const MemoryEventHeader&, TOperator& ) + { + PX_ASSERT( false ); //will never happen. + } + + template<typename THandlerType> + void parseEventData( const uint8_t* inData, uint32_t inLength, THandlerType* inOperator ) + { + physx::profile::parseEventData<TSwapBytes>( *this, inData, inLength, inOperator ); + } + }; + + + template<typename THandlerType, bool TSwapBytes> + struct MemoryEventParseOperator + { + MemoryEventParser<TSwapBytes>* mParser; + THandlerType* mOperator; + MemoryEventHeader* mHeader; + MemoryEventParseOperator( MemoryEventParser<TSwapBytes>* inParser, THandlerType* inOperator, MemoryEventHeader* inHeader ) + : mParser( inParser ) + , mOperator( inOperator ) + , mHeader( inHeader ) + { + } + + bool wasSuccessful() { return mParser->mDeserializer.mFail == false; } + + bool parseHeader() + { + mHeader->streamify( mParser->mDeserializer ); + return wasSuccessful(); + } + + template<typename TDataType> + bool operator()( const TDataType& inType ) + { + mParser->parse( inType, *mHeader, *mOperator ); + return wasSuccessful(); + } + + bool operator()( uint8_t ) { PX_ASSERT( false ); return false;} + }; + + template<bool TSwapBytes, typename TParserType, typename THandlerType> + inline bool parseEventData( TParserType& inParser, const uint8_t* inData, uint32_t inLength, THandlerType* inHandler ) + { + inParser.mDeserializer = EventDeserializer<TSwapBytes>( inData, inLength ); + MemoryEvent::EventData crapData; + uint32_t eventCount = 0; + MemoryEventHeader theHeader; + MemoryEventParseOperator<THandlerType, TSwapBytes> theOp( &inParser, inHandler, &theHeader ); + while( inParser.mDeserializer.mLength && inParser.mDeserializer.mFail == false) + { + if ( theOp.parseHeader() ) + { + if( visit<bool>( theHeader.getType(), crapData, theOp ) == false ) + inParser.mDeserializer.mFail = true; + } + ++eventCount; + } + return inParser.mDeserializer.mFail == false; + } +}} + +#endif // PXPVDSDK_PXPROFILEMEMORYEVENTPARSER_H diff --git a/PxShared/src/pvd/src/PxProfileMemoryEventRecorder.h b/PxShared/src/pvd/src/PxProfileMemoryEventRecorder.h new file mode 100644 index 00000000..1ab03d74 --- /dev/null +++ b/PxShared/src/pvd/src/PxProfileMemoryEventRecorder.h @@ -0,0 +1,147 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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_PXPROFILEMEMORYEVENTRECORDER_H +#define PXPVDSDK_PXPROFILEMEMORYEVENTRECORDER_H + + +#include "PxProfileBase.h" +#include "PxProfileAllocatorWrapper.h" +#include "PxProfileMemoryEvents.h" +#include "PxProfileMemoryEventTypes.h" + +#include "PsHashMap.h" +#include "PsUserAllocated.h" +#include "PsBroadcast.h" +#include "PxProfileMemory.h" + +namespace physx { namespace profile { + + //Remember outstanding events. + //Remembers allocations, forwards them to a listener if one is attached + //and will forward all outstanding allocations to a listener when one is + //attached. + struct MemoryEventRecorder : public shdfnd::AllocationListener + { + typedef PxProfileWrapperReflectionAllocator<uint8_t> TAllocatorType; + typedef shdfnd::HashMap<uint64_t,FullAllocationEvent,shdfnd::Hash<uint64_t>,TAllocatorType> THashMapType; + + PxProfileAllocatorWrapper mWrapper; + THashMapType mOutstandingAllocations; + AllocationListener* mListener; + + MemoryEventRecorder( PxAllocatorCallback* inFoundation ) + : mWrapper( inFoundation ) + , mOutstandingAllocations( TAllocatorType( mWrapper ) ) + , mListener( NULL ) + { + } + + static uint64_t ToU64( void* inData ) { return PX_PROFILE_POINTER_TO_U64( inData ); } + static void* ToVoidPtr( uint64_t inData ) { return reinterpret_cast<void*>(size_t(inData)); } + virtual void onAllocation( size_t size, const char* typeName, const char* filename, int line, void* allocatedMemory ) + { + onAllocation( size, typeName, filename, uint32_t(line), ToU64( allocatedMemory ) ); + } + + void onAllocation( size_t size, const char* typeName, const char* filename, uint32_t line, uint64_t allocatedMemory ) + { + if ( allocatedMemory == 0 ) + return; + FullAllocationEvent theEvent; + theEvent.init( size, typeName, filename, line, allocatedMemory ); + mOutstandingAllocations.insert( allocatedMemory, theEvent ); + if ( mListener != NULL ) mListener->onAllocation( size, typeName, filename, int(line), ToVoidPtr(allocatedMemory) ); + } + + virtual void onDeallocation( void* allocatedMemory ) + { + onDeallocation( ToU64( allocatedMemory ) ); + } + + void onDeallocation( uint64_t allocatedMemory ) + { + if ( allocatedMemory == 0 ) + return; + mOutstandingAllocations.erase( allocatedMemory ); + if ( mListener != NULL ) mListener->onDeallocation( ToVoidPtr( allocatedMemory ) ); + } + + void flushProfileEvents() {} + + void setListener( AllocationListener* inListener ) + { + mListener = inListener; + if ( mListener ) + { + for ( THashMapType::Iterator iter = mOutstandingAllocations.getIterator(); + !iter.done(); + ++iter ) + { + const FullAllocationEvent& evt( iter->second ); + mListener->onAllocation( evt.mSize, evt.mType, evt.mFile, int(evt.mLine), ToVoidPtr( evt.mAddress ) ); + } + } + } + }; + + class PxProfileMemoryEventRecorderImpl : public shdfnd::UserAllocated + , public physx::profile::PxProfileMemoryEventRecorder + { + MemoryEventRecorder mRecorder; + public: + PxProfileMemoryEventRecorderImpl( PxAllocatorCallback* inFnd ) + : mRecorder( inFnd ) + { + } + + virtual void onAllocation( size_t size, const char* typeName, const char* filename, int line, void* allocatedMemory ) + { + mRecorder.onAllocation( size, typeName, filename, line, allocatedMemory ); + } + + virtual void onDeallocation( void* allocatedMemory ) + { + mRecorder.onDeallocation( allocatedMemory ); + } + + virtual void setListener( AllocationListener* inListener ) + { + mRecorder.setListener( inListener ); + } + + virtual void release() + { + PX_PROFILE_DELETE( mRecorder.mWrapper.getAllocator(), this ); + } + }; + +}} +#endif // PXPVDSDK_PXPROFILEMEMORYEVENTRECORDER_H diff --git a/PxShared/src/pvd/src/PxProfileMemoryEventReflexiveWriter.h b/PxShared/src/pvd/src/PxProfileMemoryEventReflexiveWriter.h new file mode 100644 index 00000000..a93aa8e1 --- /dev/null +++ b/PxShared/src/pvd/src/PxProfileMemoryEventReflexiveWriter.h @@ -0,0 +1,71 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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_PXPROFILEMEMORYEVENTREFLEXIVEWRITER_H +#define PXPVDSDK_PXPROFILEMEMORYEVENTREFLEXIVEWRITER_H + +#include "PxProfileMemoryBuffer.h" +#include "PxProfileFoundationWrapper.h" +#include "PxProfileMemoryEvents.h" + +namespace physx { namespace profile { + + struct MemoryEventReflexiveWriter + { + typedef PxProfileWrapperReflectionAllocator<uint8_t> TAllocatorType; + typedef MemoryBuffer<TAllocatorType> TMemoryBufferType; + typedef EventSerializer<TMemoryBufferType> TSerializerType; + + + PxProfileAllocatorWrapper mWrapper; + TMemoryBufferType mBuffer; + TSerializerType mSerializer; + + MemoryEventReflexiveWriter( PxAllocatorCallback* inFoundation ) + : mWrapper( inFoundation ) + , mBuffer( TAllocatorType( mWrapper ) ) + , mSerializer( &mBuffer ) + { + } + + template<typename TDataType> + void operator()( const MemoryEventHeader& inHeader, const TDataType& inType ) + { + //copy to get rid of const. + MemoryEventHeader theHeader( inHeader ); + TDataType theData( inType ); + + //write them out. + theHeader.streamify( mSerializer ); + theData.streamify( mSerializer, theHeader ); + } + }; +}} + +#endif // PXPVDSDK_PXPROFILEMEMORYEVENTREFLEXIVEWRITER_H
\ No newline at end of file diff --git a/PxShared/src/pvd/src/PxProfileMemoryEventSummarizer.h b/PxShared/src/pvd/src/PxProfileMemoryEventSummarizer.h new file mode 100644 index 00000000..769c8a88 --- /dev/null +++ b/PxShared/src/pvd/src/PxProfileMemoryEventSummarizer.h @@ -0,0 +1,304 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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_PXPROFILEMEMORYEVENTSUMMARIZER_H +#define PXPVDSDK_PXPROFILEMEMORYEVENTSUMMARIZER_H + +#include "PxProfileBase.h" +#include "PxProfileAllocatorWrapper.h" +#include "PxProfileMemoryEvents.h" +#include "PxProfileMemoryEventRecorder.h" +#include "PxProfileMemoryEventParser.h" + +#include "PsHashMap.h" + +namespace physx { namespace profile { + + struct MemoryEventSummarizerEntry + { + uint32_t mType; + uint32_t mFile; + uint32_t mLine; + + MemoryEventSummarizerEntry( const AllocationEvent& evt ) + : mType( evt.mType ) + , mFile( evt.mFile ) + , mLine( evt.mLine ) + { + } + + MemoryEventSummarizerEntry( uint32_t tp, uint32_t f, uint32_t line ) + : mType( tp ) + , mFile( f ) + , mLine( line ) + { + } + }; +}} + + +namespace physx { namespace shdfnd { + + template <> + struct Hash<physx::profile::MemoryEventSummarizerEntry> + { + public: + uint32_t operator()(const physx::profile::MemoryEventSummarizerEntry& entry) const + { + //Combine hash values in a semi-reasonable way. + return Hash<uint32_t>()( entry.mType ) + ^ Hash<uint32_t>()( entry.mFile ) + ^ Hash<uint32_t>()( entry.mLine ); + } + + bool operator()(const physx::profile::MemoryEventSummarizerEntry& lhs, const physx::profile::MemoryEventSummarizerEntry& rhs) const + { + return lhs.mType == rhs.mType + && lhs.mFile == rhs.mFile + && lhs.mLine == rhs.mLine; + } + + bool equal(const physx::profile::MemoryEventSummarizerEntry& lhs, const physx::profile::MemoryEventSummarizerEntry& rhs) const + { + return lhs.mType == rhs.mType + && lhs.mFile == rhs.mFile + && lhs.mLine == rhs.mLine; + } + }; +}} + +namespace physx { namespace profile { + + struct MemoryEventSummarizerAllocatedValue + { + MemoryEventSummarizerEntry mEntry; + uint32_t mSize; + MemoryEventSummarizerAllocatedValue( MemoryEventSummarizerEntry en, uint32_t sz ) + : mEntry( en ) + , mSize( sz ) + { + } + }; + + template<typename TSummarizerType> + struct SummarizerParseHandler + { + TSummarizerType* mSummarizer; + SummarizerParseHandler( TSummarizerType* inType ) + : mSummarizer( inType ) + { + } + template<typename TDataType> + void operator()( const MemoryEventHeader& inHeader, const TDataType& inType ) + { + mSummarizer->handleParsedData( inHeader, inType ); + } + }; + + template<typename TForwardType> + struct MemoryEventForward + { + TForwardType* mForward; + MemoryEventForward( TForwardType& inForward ) + : mForward( &inForward ) + { + } + template<typename TDataType> + void operator()( const MemoryEventHeader& inHeader, const TDataType& inType ) + { + TForwardType& theForward( *mForward ); + theForward( inHeader, inType ); + } + }; + + struct NullMemoryEventHandler + { + template<typename TDataType> + void operator()( const MemoryEventHeader&, const TDataType&) + { + } + }; + + template<typename TForwardType> + struct NewEntryOperatorForward + { + TForwardType* mForward; + NewEntryOperatorForward( TForwardType& inForward ) + : mForward( &inForward ) + { + } + void operator()( const MemoryEventSummarizerEntry& inEntry, const char* inTypeStr, const char* inFileStr, uint32_t inTotalsArrayIndex ) + { + TForwardType& theType( *mForward ); + theType( inEntry, inTypeStr, inFileStr, inTotalsArrayIndex ); + } + }; + + struct NullNewEntryOperator + { + void operator()( const MemoryEventSummarizerEntry&, const char*, const char*, uint32_t) + { + } + }; + + //Very specialized class meant to take a stream of memory events + //endian-convert it. + //Produce a new stream + //And keep track of the events in a meaningful way. + //It collapses the allocations into groupings keyed + //by file, line, and type. + template<bool TSwapBytes + , typename TNewEntryOperator + , typename MemoryEventHandler> + struct MemoryEventSummarizer : public PxProfileEventBufferClient + { + typedef MemoryEventSummarizer< TSwapBytes, TNewEntryOperator, MemoryEventHandler > TThisType; + typedef PxProfileWrapperReflectionAllocator<MemoryEventSummarizerEntry> TAllocatorType; + typedef shdfnd::HashMap<MemoryEventSummarizerEntry, uint32_t, shdfnd::Hash<MemoryEventSummarizerEntry>, TAllocatorType> TSummarizeEntryToU32Hash; + typedef shdfnd::HashMap<uint64_t, MemoryEventSummarizerAllocatedValue, shdfnd::Hash<uint64_t>, TAllocatorType> TU64ToSummarizerValueHash; + PxProfileAllocatorWrapper mWrapper; + TSummarizeEntryToU32Hash mEntryIndexHash; + PxProfileArray<int32_t> mTotalsArray; + MemoryEventParser<TSwapBytes> mParser; + TU64ToSummarizerValueHash mOutstandingAllocations; + TNewEntryOperator mNewEntryOperator; + MemoryEventHandler mEventHandler; + + + MemoryEventSummarizer( PxAllocatorCallback& inAllocator + , TNewEntryOperator inNewEntryOperator + , MemoryEventHandler inEventHandler) + + : mWrapper( inAllocator ) + , mEntryIndexHash( TAllocatorType( mWrapper ) ) + , mTotalsArray( mWrapper ) + , mParser( inAllocator ) + , mOutstandingAllocations( mWrapper ) + , mNewEntryOperator( inNewEntryOperator ) + , mEventHandler( inEventHandler ) + { + } + virtual ~MemoryEventSummarizer(){} + + //parse this data block. This will endian-convert the data if necessary + //and then + void handleData( const uint8_t* inData, uint32_t inLen ) + { + SummarizerParseHandler<TThisType> theHandler( this ); + parseEventData<TSwapBytes>( mParser, inData, inLen, &theHandler ); + } + + template<typename TDataType> + void handleParsedData( const MemoryEventHeader& inHeader, const TDataType& inData ) + { + //forward it to someone who might care + mEventHandler( inHeader, inData ); + //handle the parsed data. + doHandleParsedData( inData ); + } + + template<typename TDataType> + void doHandleParsedData( const TDataType& ) {} + + void doHandleParsedData( const AllocationEvent& inEvt ) + { + onAllocation( inEvt.mSize, inEvt.mType, inEvt.mFile, inEvt.mLine, inEvt.mAddress ); + } + + void doHandleParsedData( const DeallocationEvent& inEvt ) + { + onDeallocation( inEvt.mAddress ); + } + + uint32_t getOrCreateEntryIndex( const MemoryEventSummarizerEntry& inEvent ) + { + uint32_t index = 0; + const TSummarizeEntryToU32Hash::Entry* entry( mEntryIndexHash.find(inEvent ) ); + if ( !entry ) + { + index = mTotalsArray.size(); + mTotalsArray.pushBack( 0 ); + mEntryIndexHash.insert( inEvent, index ); + + //Force a string lookup and such here. + mNewEntryOperator( inEvent, mParser.getString( inEvent.mType), mParser.getString( inEvent.mFile ), index ); + } + else + index = entry->second; + return index; + } + + //Keep a running total of what is going on, letting a listener know when new events happen. + void onMemoryEvent( const MemoryEventSummarizerEntry& inEvent, int32_t inSize ) + { + MemoryEventSummarizerEntry theEntry( inEvent ); + uint32_t index = getOrCreateEntryIndex( theEntry ); + mTotalsArray[index] += inSize; + } + + void onAllocation( uint32_t inSize, uint32_t inType, uint32_t inFile, uint32_t inLine, uint64_t inAddress ) + { + MemoryEventSummarizerEntry theEntry( inType, inFile, inLine ); + onMemoryEvent( theEntry, static_cast<int32_t>( inSize ) ); + mOutstandingAllocations.insert( inAddress, MemoryEventSummarizerAllocatedValue( theEntry, inSize ) ); + } + + void onDeallocation( uint64_t inAddress ) + { + const TU64ToSummarizerValueHash::Entry* existing( mOutstandingAllocations.find( inAddress ) ); + if ( existing ) + { + const MemoryEventSummarizerAllocatedValue& data( existing->second ); + onMemoryEvent( data.mEntry, -1 * static_cast<int32_t>( data.mSize ) ); + mOutstandingAllocations.erase( inAddress ); + } + //Not much we can do with an deallocation when we didn't track the allocation. + } + + int32_t getTypeTotal( const char* inTypeName, const char* inFilename, uint32_t inLine ) + { + uint32_t theType( mParser.getHandle( inTypeName ) ); + uint32_t theFile( mParser.getHandle( inFilename ) ); + uint32_t theLine = inLine; //all test lines are 50... + uint32_t index = getOrCreateEntryIndex( MemoryEventSummarizerEntry( theType, theFile, theLine ) ); + return mTotalsArray[index]; + } + + virtual void handleBufferFlush( const uint8_t* inData, uint32_t inLength ) + { + handleData( inData, inLength ); + } + + virtual void handleClientRemoved() {} + }; + +}} + +#endif // PXPVDSDK_PXPROFILEMEMORYEVENTSUMMARIZER_H diff --git a/PxShared/src/pvd/src/PxProfileMemoryEventTypes.h b/PxShared/src/pvd/src/PxProfileMemoryEventTypes.h new file mode 100644 index 00000000..0e4b0258 --- /dev/null +++ b/PxShared/src/pvd/src/PxProfileMemoryEventTypes.h @@ -0,0 +1,90 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#ifndef PXPVDSDK_PXPROFILEMEMORYEVENTTYPES_H +#define PXPVDSDK_PXPROFILEMEMORYEVENTTYPES_H + +#include "PxProfileBase.h" +#include "PxProfileEventBufferClientManager.h" +#include "PxProfileEventSender.h" +#include "PsBroadcast.h" + +namespace physx { namespace profile { + + struct PxProfileMemoryEventType + { + enum Enum + { + Unknown = 0, + Allocation, + Deallocation + }; + }; + + struct PxProfileBulkMemoryEvent + { + uint64_t mAddress; + uint32_t mDatatype; + uint32_t mFile; + uint32_t mLine; + uint32_t mSize; + PxProfileMemoryEventType::Enum mType; + + PxProfileBulkMemoryEvent(){} + + PxProfileBulkMemoryEvent( uint32_t size, uint32_t type, uint32_t file, uint32_t line, uint64_t addr ) + : mAddress( addr ) + , mDatatype( type ) + , mFile( file ) + , mLine( line ) + , mSize( size ) + , mType( PxProfileMemoryEventType::Allocation ) + { + } + + PxProfileBulkMemoryEvent( uint64_t addr ) + : mAddress( addr ) + , mDatatype( 0 ) + , mFile( 0 ) + , mLine( 0 ) + , mSize( 0 ) + , mType( PxProfileMemoryEventType::Deallocation ) + { + } + }; + + class PxProfileBulkMemoryEventHandler + { + protected: + virtual ~PxProfileBulkMemoryEventHandler(){} + public: + virtual void handleEvents( const PxProfileBulkMemoryEvent* inEvents, uint32_t inBufferSize ) = 0; + static void parseEventBuffer( const uint8_t* inBuffer, uint32_t inBufferSize, PxProfileBulkMemoryEventHandler& inHandler, bool inSwapBytes, PxAllocatorCallback* inAlloc ); + }; +} } + +#endif // PXPVDSDK_PXPROFILEMEMORYEVENTTYPES_H diff --git a/PxShared/src/pvd/src/PxProfileMemoryEvents.h b/PxShared/src/pvd/src/PxProfileMemoryEvents.h new file mode 100644 index 00000000..bab28e5a --- /dev/null +++ b/PxShared/src/pvd/src/PxProfileMemoryEvents.h @@ -0,0 +1,411 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 diff --git a/PxShared/src/pvd/src/PxProfileScopedEvent.h b/PxShared/src/pvd/src/PxProfileScopedEvent.h new file mode 100644 index 00000000..11106895 --- /dev/null +++ b/PxShared/src/pvd/src/PxProfileScopedEvent.h @@ -0,0 +1,150 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#ifndef PXPVDSDK_PXPROFILESCOPEDEVENT_H +#define PXPVDSDK_PXPROFILESCOPEDEVENT_H + +#include "PxProfileBase.h" +#include "PxProfileEventId.h" +#include "PxProfileCompileTimeEventFilter.h" + +namespace physx { namespace profile { + +#define TO_PXPVDSDK_PXPROFILEEVENTID( subsystem, eventId ) PxProfileEventId( SubsystemIds::subsystem, EventIds::subsystem##eventId ); + + /** + \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 ); + } + + template<bool TEnabled, typename TBufferType, uint16_t eventId> + struct ScopedEventWithContext + { + uint64_t mContext; + TBufferType* mBuffer; + ScopedEventWithContext( TBufferType* inBuffer, uint64_t inContext) + : mContext ( inContext ) + , mBuffer( inBuffer ) + { + startEvent<true>( mBuffer, PxProfileEventId(eventId), mContext ); + } + ~ScopedEventWithContext() + { + stopEvent<true>( mBuffer, PxProfileEventId(eventId), mContext ); + } + }; + + template<typename TBufferType, uint16_t eventId> + struct ScopedEventWithContext<false,TBufferType,eventId> { ScopedEventWithContext( TBufferType*, uint64_t) {} }; + + template<typename TBufferType> + struct DynamicallyEnabledScopedEvent + { + TBufferType* mBuffer; + PxProfileEventId mId; + uint64_t mContext; + DynamicallyEnabledScopedEvent( TBufferType* inBuffer, const PxProfileEventId& inId, uint64_t inContext) + : mBuffer( inBuffer ) + , mId( inId ) + , mContext( inContext ) + { + if(mBuffer) + startEvent( mId.compileTimeEnabled, mBuffer, mId, mContext ); + } + ~DynamicallyEnabledScopedEvent() + { + if(mBuffer) + stopEvent( mId.compileTimeEnabled, mBuffer, mId, mContext ); + } + }; +}} + +#endif // PXPVDSDK_PXPROFILESCOPEDEVENT_H diff --git a/PxShared/src/pvd/src/PxProfileScopedMutexLock.h b/PxShared/src/pvd/src/PxProfileScopedMutexLock.h new file mode 100644 index 00000000..48659a43 --- /dev/null +++ b/PxShared/src/pvd/src/PxProfileScopedMutexLock.h @@ -0,0 +1,64 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 "PxProfileBase.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 diff --git a/PxShared/src/pvd/src/PxProfileZone.h b/PxShared/src/pvd/src/PxProfileZone.h new file mode 100644 index 00000000..47a7abd2 --- /dev/null +++ b/PxShared/src/pvd/src/PxProfileZone.h @@ -0,0 +1,142 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#ifndef PXPVDSDK_PXPROFILEZONE_H +#define PXPVDSDK_PXPROFILEZONE_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 PX_FOUNDATION_API PxProfileZone& createProfileZone(PxAllocatorCallback* inAllocator, const char* inSDKName, PxProfileNames inNames = PxProfileNames(), uint32_t inEventBufferByteSize = 0x10000 /*64k*/); + + }; +} } + +#endif // PXPVDSDK_PXPROFILEZONE_H diff --git a/PxShared/src/pvd/src/PxProfileZoneImpl.h b/PxShared/src/pvd/src/PxProfileZoneImpl.h new file mode 100644 index 00000000..c602c44e --- /dev/null +++ b/PxShared/src/pvd/src/PxProfileZoneImpl.h @@ -0,0 +1,318 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 "PxProfileZone.h" +#include "PxProfileEventFilter.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; + PxProfileAllocatorWrapper mWrapper; + 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*> mClients; + 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 ) + , mWrapper( inAllocator ) + , mMutex( PxProfileWrapperReflectionAllocator<uint8_t>( mWrapper ) ) + , mEventNames( mWrapper ) + , mNameToEvtIndexMapR( mWrapper ) + , mNameToEvtIndexMapRW(mWrapper) + , mEvtIdToNameMap( mWrapper ) + , mProfileZoneManager( NULL ) + , mClients( 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 = mClients.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 ) + mClients[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 ); + mClients.pushBack( &inClient ); + mEventsActive = true; + } + + void removeClient( PxProfileZoneClient& inClient ) + { + TLockType lock( mMutex ); + for ( uint32_t idx =0; idx < mClients.size(); ++idx ) + { + if ( mClients[idx] == &inClient ) + { + inClient.handleClientRemoved(); + mClients.replaceWithLast( idx ); + break; + } + } + mEventsActive = mClients.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 = mClients.size(); + for( uint32_t idx =0; idx < clientCount; ++idx ) + mClients[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 diff --git a/PxShared/src/pvd/src/PxProfileZoneManager.h b/PxShared/src/pvd/src/PxProfileZoneManager.h new file mode 100644 index 00000000..37ec7ac6 --- /dev/null +++ b/PxShared/src/pvd/src/PxProfileZoneManager.h @@ -0,0 +1,155 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 diff --git a/PxShared/src/pvd/src/PxProfileZoneManagerImpl.h b/PxShared/src/pvd/src/PxProfileZoneManagerImpl.h new file mode 100644 index 00000000..090658ab --- /dev/null +++ b/PxShared/src/pvd/src/PxProfileZoneManagerImpl.h @@ -0,0 +1,174 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 "PxProfileBase.h" +#include "PxProfileScopedMutexLock.h" +#include "PxProfileZone.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 diff --git a/PxShared/src/pvd/src/PxPvd.cpp b/PxShared/src/pvd/src/PxPvd.cpp new file mode 100644 index 00000000..7793ac60 --- /dev/null +++ b/PxShared/src/pvd/src/PxPvd.cpp @@ -0,0 +1,56 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 "pvd/PxPvd.h" + +#include "PxPvdImpl.h" + +namespace physx +{ +namespace pvdsdk +{ + +ForwardingAllocator gForwardingAllocator; +PxAllocatorCallback* gPvdAllocatorCallback = &gForwardingAllocator; + +void SetPvdAllocatorCallback(PxAllocatorCallback* inAllocatorCallback) +{ + gPvdAllocatorCallback = inAllocatorCallback; +} + +} // namespace pvdsdk + +PxPvd* PxCreatePvd(PxFoundation& foundation) +{ + pvdsdk::gPvdAllocatorCallback = &foundation.getAllocatorCallback(); + pvdsdk::PvdImpl::initialize(); + return pvdsdk::PvdImpl::getInstance(); +} + +} // namespace physx diff --git a/PxShared/src/pvd/src/PxPvdBits.h b/PxShared/src/pvd/src/PxPvdBits.h new file mode 100644 index 00000000..44a5192d --- /dev/null +++ b/PxShared/src/pvd/src/PxPvdBits.h @@ -0,0 +1,173 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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; + } +} + +template <uint8_t TByteCount, bool TShouldSwap> +struct PvdByteSwapper +{ + void swapBytes(uint8_t* __restrict inData) + { + doSwapBytes<TByteCount>(inData); + } + void swapBytes(uint8_t* __restrict inData, uint32_t itemCount) + { + doSwapBytes<TByteCount>(inData, itemCount); + } + void swapBytes(uint8_t* __restrict dataPtr, uint32_t numBytes, uint32_t itemWidth) + { + physx::pvdsdk::swapBytes(dataPtr, numBytes, itemWidth); + } +}; + +struct PvdNullSwapper +{ + + void swapBytes(uint8_t* __restrict) + { + } + void swapBytes(uint8_t* __restrict, uint32_t) + { + } + void swapBytes(uint8_t* __restrict, uint32_t, uint32_t) + { + } +}; +// Anything that doesn't need swapping gets the null swapper +template <uint8_t TByteCount> +struct PvdByteSwapper<TByteCount, false> : public PvdNullSwapper +{ +}; +// A 1 byte byte swapper can't really do anything. +template <> +struct PvdByteSwapper<1, true> : public PvdNullSwapper +{ +}; + +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 diff --git a/PxShared/src/pvd/src/PxPvdByteStreams.h b/PxShared/src/pvd/src/PxPvdByteStreams.h new file mode 100644 index 00000000..6a2299ca --- /dev/null +++ b/PxShared/src/pvd/src/PxPvdByteStreams.h @@ -0,0 +1,155 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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; + } +}; + +struct ByteSwappingPvdInputStream +{ + protected: + ByteSwappingPvdInputStream& operator=(ByteSwappingPvdInputStream& other); + + public: + PvdInputStream& mStream; + ByteSwappingPvdInputStream(PvdInputStream& stream) : mStream(stream) + { + } + + template <typename TDataType> + bool read(TDataType* buffer, uint32_t& numItems) + { + bool retval = mStream.read(buffer, numItems); + for(uint32_t idx = 0; idx < numItems; ++idx) + swapBytes(buffer[idx]); + return retval; + } + + template <typename TDataType> + ByteSwappingPvdInputStream& operator>>(TDataType& data) + { + mStream >> data; + swapBytes(data); + 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 diff --git a/PxShared/src/pvd/src/PxPvdCommStreamEventSink.h b/PxShared/src/pvd/src/PxPvdCommStreamEventSink.h new file mode 100644 index 00000000..a8511958 --- /dev/null +++ b/PxShared/src/pvd/src/PxPvdCommStreamEventSink.h @@ -0,0 +1,55 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 diff --git a/PxShared/src/pvd/src/PxPvdCommStreamEvents.h b/PxShared/src/pvd/src/PxPvdCommStreamEvents.h new file mode 100644 index 00000000..4aa41184 --- /dev/null +++ b/PxShared/src/pvd/src/PxPvdCommStreamEvents.h @@ -0,0 +1,986 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 + }; +}; + +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 diff --git a/PxShared/src/pvd/src/PxPvdCommStreamSDKEventTypes.h b/PxShared/src/pvd/src/PxPvdCommStreamSDKEventTypes.h new file mode 100644 index 00000000..0228a54e --- /dev/null +++ b/PxShared/src/pvd/src/PxPvdCommStreamSDKEventTypes.h @@ -0,0 +1,32 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#define THERE_IS_NO_INCLUDE_GUARD_FOR_A_REASON + +DECLARE_PVD_COMM_STREAM_SDK_EVENT(SetPauseState) + +#undef THERE_IS_NO_INCLUDE_GUARD_FOR_A_REASON diff --git a/PxShared/src/pvd/src/PxPvdCommStreamTypes.h b/PxShared/src/pvd/src/PxPvdCommStreamTypes.h new file mode 100644 index 00000000..0deed602 --- /dev/null +++ b/PxShared/src/pvd/src/PxPvdCommStreamTypes.h @@ -0,0 +1,262 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 PvdCommStreamInternalConnection; + +class PvdConnectionListener +{ + protected: + virtual ~PvdConnectionListener() + { + } + + public: + virtual void onDisconnect(PvdCommStreamInternalConnection& connection) = 0; + virtual void onInstanceDestroyed(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 + }; +}; + +class ExtendedEventSerializer : public PvdEventSerializer +{ + protected: + virtual ~ExtendedEventSerializer() + { + } + + public: + virtual void setData(DataRef<const uint8_t> eventData) = 0; + // True if this serializer performs byte swapping + virtual bool performsSwap() = 0; + + virtual bool isGood() = 0; + + virtual void release() = 0; + + static ExtendedEventSerializer& createInputSerializer(bool swapBytes); +}; + +} // pvdsdk +} // physx +#endif // PXPVDSDK_PXPVDCOMMSTREAMTYPES_H diff --git a/PxShared/src/pvd/src/PxPvdDataStream.cpp b/PxShared/src/pvd/src/PxPvdDataStream.cpp new file mode 100644 index 00000000..39730e16 --- /dev/null +++ b/PxShared/src/pvd/src/PxPvdDataStream.cpp @@ -0,0 +1,869 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#include "PxPvdDataStream.h" +#include "PxPvdFoundation.h" +#include "PxPvdCommStreamEvents.h" +#include "PxPvdCommStreamEventSink.h" +#include "PxPvdCommStreamTypes.h" +#include "PxPvdDataStreamHelpers.h" +#include "PxPvdObjectModelInternalTypes.h" +#include "PxPvdImpl.h" +#include "PsTime.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; + memcpy(endPtr, str, 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()); +} diff --git a/PxShared/src/pvd/src/PxPvdDefaultFileTransport.cpp b/PxShared/src/pvd/src/PxPvdDefaultFileTransport.cpp new file mode 100644 index 00000000..0dcd88a5 --- /dev/null +++ b/PxShared/src/pvd/src/PxPvdDefaultFileTransport.cpp @@ -0,0 +1,123 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 "pvd/PxPvdTransport.h" +#include "foundation/PxAssert.h" + +#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); +} + +} // namespace pvdsdk + +PxPvdTransport* PxDefaultPvdFileTransportCreate(const char* name) +{ + return PX_NEW(pvdsdk::PvdDefaultFileTransport)(name); +} + +} // namespace physx + diff --git a/PxShared/src/pvd/src/PxPvdDefaultFileTransport.h b/PxShared/src/pvd/src/PxPvdDefaultFileTransport.h new file mode 100644 index 00000000..dd0aab7b --- /dev/null +++ b/PxShared/src/pvd/src/PxPvdDefaultFileTransport.h @@ -0,0 +1,77 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 diff --git a/PxShared/src/pvd/src/PxPvdDefaultSocketTransport.cpp b/PxShared/src/pvd/src/PxPvdDefaultSocketTransport.cpp new file mode 100644 index 00000000..4beb71ef --- /dev/null +++ b/PxShared/src/pvd/src/PxPvdDefaultSocketTransport.cpp @@ -0,0 +1,136 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 "pvd/PxPvdTransport.h" + +#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 diff --git a/PxShared/src/pvd/src/PxPvdDefaultSocketTransport.h b/PxShared/src/pvd/src/PxPvdDefaultSocketTransport.h new file mode 100644 index 00000000..692e4199 --- /dev/null +++ b/PxShared/src/pvd/src/PxPvdDefaultSocketTransport.h @@ -0,0 +1,79 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 diff --git a/PxShared/src/pvd/src/PxPvdFoundation.h b/PxShared/src/pvd/src/PxPvdFoundation.h new file mode 100644 index 00000000..58d8e9af --- /dev/null +++ b/PxShared/src/pvd/src/PxPvdFoundation.h @@ -0,0 +1,504 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 TObjectType, typename TGetSetIndexOp, typename TSetSetIndexOp> +class InvasiveSet +{ + shdfnd::Array<TObjectType*> mSet; + + InvasiveSet(const InvasiveSet& other); + InvasiveSet& operator=(const InvasiveSet& other); + + public: + InvasiveSet(const char* allocName) : mSet(allocName) + { + } + + bool insert(TObjectType& inObject) + { + uint32_t currentIdx = TGetSetIndexOp()(inObject); + if(currentIdx == UINT32_MAX) + { + TSetSetIndexOp()(inObject, mSet.size()); + mSet.pushBack(&inObject); + return true; + } + return false; + } + + bool remove(TObjectType& inObject) + { + uint32_t currentIdx = TGetSetIndexOp()(inObject); + if(currentIdx != UINT32_MAX) + { + TObjectType* theEnd = mSet.back(); + TObjectType* theObj = &inObject; + if(theEnd != theObj) + { + TSetSetIndexOp()(*theEnd, currentIdx); + mSet[currentIdx] = theEnd; + } + mSet.popBack(); + TSetSetIndexOp()(inObject, UINT32_MAX); + return true; + } + return false; + } + + bool contains(TObjectType& inObject) + { + return TGetSetIndexOp()(inObject) != UINT32_MAX; + } + + void clear() + { + for(uint32_t idx = 0; idx < mSet.size(); ++idx) + TSetSetIndexOp()(*(mSet[idx]), UINT32_MAX); + mSet.clear(); + } + + TObjectType* operator[](uint32_t idx) + { + return mSet[idx]; + } + const TObjectType* operator[](uint32_t idx) const + { + return mSet[idx]; + } + uint32_t size() const + { + return mSet.size(); + } + TObjectType** begin() + { + return mSet.begin(); + } + TObjectType** end() + { + return mSet.end(); + } + const TObjectType** begin() const + { + return mSet.begin(); + } + const TObjectType** end() const + { + return mSet.end(); + } + const TObjectType* back() const + { + return mSet.back(); + } + TObjectType* back() + { + return mSet.back(); + } +}; + +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) + +namespace physx +{ +namespace pvdsdk +{ + +template <typename TKeyType, typename TValueType, typename THashType, typename TBufType, typename TOperator> +uint32_t getMapKeysOp(shdfnd::HashMap<TKeyType, TValueType, THashType>& map, TBufType* buffer, uint32_t bufSize, + uint32_t startIdx, TOperator op) +{ + uint32_t numItems = static_cast<uint32_t>(map.size()); + if(numItems == 0 || bufSize == 0) + return 0; + + startIdx = PxMin(numItems - 1, startIdx); + uint32_t retval = 0; + for(typename shdfnd::HashMap<TKeyType, TValueType, THashType>::Iterator iter = map.getIterator(); + iter.done() == false && bufSize; ++iter) + { + if(startIdx) + --startIdx; + else + { + buffer[retval] = op(iter->first); + --bufSize; + ++retval; + } + } + return retval; +} + +struct IdOp +{ + template <typename TDataType> + TDataType operator()(const TDataType& item) + { + return item; + } +}; + +template <typename TKeyType, typename TValueType, typename THashType> +uint32_t getMapKeys(shdfnd::HashMap<TKeyType, TValueType, THashType>& map, TKeyType* buffer, uint32_t bufSize, uint32_t startIdx) +{ + return getMapKeysOp(map, buffer, bufSize, startIdx, IdOp()); +} + +struct DerefOp +{ + template <typename TDataType> + TDataType operator()(const TDataType* item) + { + return *item; + } +}; + +template <typename TKeyType, typename TValueType, typename TBufType, typename TOp> +uint32_t getMapValues(shdfnd::HashMap<TKeyType, TValueType>& map, TBufType* buffer, uint32_t bufSize, uint32_t startIdx, TOp op) +{ + uint32_t numItems = static_cast<uint32_t>(map.size()); + if(numItems == 0 || bufSize == 0) + return 0; + + startIdx = PxMin(numItems - 1, startIdx); + uint32_t retval = 0; + for(typename shdfnd::HashMap<TKeyType, TValueType>::Iterator iter = map.getIterator(); iter.done() == false && bufSize; ++iter) + { + if(startIdx) + --startIdx; + else + { + buffer[retval] = op(iter->second); + --bufSize; + ++retval; + } + } + return retval; +} + +template <typename TValueType, typename TBufType> +uint32_t getArrayEntries(shdfnd::Array<TValueType>& data, TBufType* buffer, uint32_t bufSize, uint32_t startIdx) +{ + uint32_t numItems = static_cast<uint32_t>(data.size()); + if(numItems == 0 || bufSize == 0) + return 0; + + startIdx = PxMin(numItems - 1, startIdx); + uint32_t available = PxMin(numItems - startIdx, bufSize); + PVD_FOREACH(idx, available) + buffer[idx] = data[idx + startIdx]; + return available; +} +#define PVD_POINTER_TO_U64(ptr) static_cast<uint64_t>(reinterpret_cast<size_t>(ptr)) +} +} +#endif // PXPVDSDK_PXPVDFOUNDATION_H diff --git a/PxShared/src/pvd/src/PxPvdImpl.cpp b/PxShared/src/pvd/src/PxPvdImpl.cpp new file mode 100644 index 00000000..ff24497b --- /dev/null +++ b/PxShared/src/pvd/src/PxPvdImpl.cpp @@ -0,0 +1,405 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 "pvd/PxPvdTransport.h" + +#include "PxPvdImpl.h" +#include "PxPvdFoundation.h" +#include "PxPvdClient.h" +#include "PxPvdMemClient.h" +#include "PxPvdProfileZoneClient.h" +#include "PxPvdCommStreamTypes.h" +#include "PxProfileZoneManager.h" +#include "PxProfileZone.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 diff --git a/PxShared/src/pvd/src/PxPvdImpl.h b/PxShared/src/pvd/src/PxPvdImpl.h new file mode 100644 index 00000000..09bf72eb --- /dev/null +++ b/PxShared/src/pvd/src/PxPvdImpl.h @@ -0,0 +1,221 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 diff --git a/PxShared/src/pvd/src/PxPvdInternalByteStreams.h b/PxShared/src/pvd/src/PxPvdInternalByteStreams.h new file mode 100644 index 00000000..f8c081a8 --- /dev/null +++ b/PxShared/src/pvd/src/PxPvdInternalByteStreams.h @@ -0,0 +1,147 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#ifndef PXPVDSDK_PXPVDINTERNALBYTESTREAMS_H +#define PXPVDSDK_PXPVDINTERNALBYTESTREAMS_H + +#include "PxPvdByteStreams.h" +#include "PxPvdFoundation.h" + +namespace physx +{ +namespace pvdsdk +{ +struct MemPvdOutputStream : public PvdOutputStream +{ + ForwardingMemoryBuffer mBuffer; + MemPvdOutputStream(const char* memName) : mBuffer(memName) + { + } + + virtual bool write(const uint8_t* buffer, uint32_t len) + { + mBuffer.write(buffer, len); + return true; + } + + virtual bool directCopy(PvdInputStream& inStream, uint32_t len) + { + uint32_t offset = mBuffer.size(); + mBuffer.growBuf(len); + uint32_t readLen = len; + inStream.read(mBuffer.begin() + offset, readLen); + if(readLen != len) + physx::intrinsics::memZero(mBuffer.begin() + offset, len); + return readLen == len; + } + + const uint8_t* begin() const + { + return mBuffer.begin(); + } + uint32_t size() const + { + return mBuffer.size(); + } + void clear() + { + mBuffer.clear(); + } + DataRef<const uint8_t> toRef() const + { + return DataRef<const uint8_t>(mBuffer.begin(), mBuffer.end()); + } +}; + +struct MemPvdInputStream : public PvdInputStream +{ + const uint8_t* mBegin; + const uint8_t* mEnd; + bool mGood; + + MemPvdInputStream(const MemPvdOutputStream& stream) : mGood(true) + { + mBegin = stream.mBuffer.begin(); + mEnd = stream.mBuffer.end(); + } + + 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 diff --git a/PxShared/src/pvd/src/PxPvdMarshalling.h b/PxShared/src/pvd/src/PxPvdMarshalling.h new file mode 100644 index 00000000..2679fc77 --- /dev/null +++ b/PxShared/src/pvd/src/PxPvdMarshalling.h @@ -0,0 +1,220 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 diff --git a/PxShared/src/pvd/src/PxPvdMemClient.cpp b/PxShared/src/pvd/src/PxPvdMemClient.cpp new file mode 100644 index 00000000..47a8c00b --- /dev/null +++ b/PxShared/src/pvd/src/PxPvdMemClient.cpp @@ -0,0 +1,134 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 "pvd/PxPvdTransport.h" +#include "foundation/PxProfiler.h" + +#include "PxPvdImpl.h" +#include "PxPvdMemClient.h" +#include "PxProfileMemory.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; +} + +PvdUserRenderer* PvdMemClient::getUserRender() +{ + PX_ASSERT(0); + return NULL; +} + +void PvdMemClient::setObjectRegistrar(ObjectRegistrar*) +{ +} + +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 diff --git a/PxShared/src/pvd/src/PxPvdMemClient.h b/PxShared/src/pvd/src/PxPvdMemClient.h new file mode 100644 index 00000000..d658b47e --- /dev/null +++ b/PxShared/src/pvd/src/PxPvdMemClient.h @@ -0,0 +1,85 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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(); + PvdUserRenderer* getUserRender(); + void setObjectRegistrar(ObjectRegistrar*); + 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 diff --git a/PxShared/src/pvd/src/PxPvdObjectModel.h b/PxShared/src/pvd/src/PxPvdObjectModel.h new file mode 100644 index 00000000..d66c5076 --- /dev/null +++ b/PxShared/src/pvd/src/PxPvdObjectModel.h @@ -0,0 +1,437 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#ifndef PXPVDSDK_PXPVDOBJECTMODEL_H +#define PXPVDSDK_PXPVDOBJECTMODEL_H + +#include "PsBasicTemplates.h" +#include "PxPvdObjectModelMetaData.h" + +namespace physx +{ +namespace pvdsdk +{ + +#if PX_VC == 11 || PX_VC == 12 || PX_VC == 14 +#pragma warning(push) +#pragma warning(disable : 4435) // 'class1' : Object layout under /vd2 will change due to virtual base 'class2' +#endif + +class PvdInputStream; +class PvdOutputStream; + +struct InstanceDescription +{ + int32_t mId; + int32_t mClassId; + void* mInstPtr; + bool mAlive; + + InstanceDescription(int32_t id, int32_t classId, void* inst, bool alive) + : mId(id), mClassId(classId), mInstPtr(inst), mAlive(alive) + { + } + InstanceDescription() : mId(-1), mClassId(-1), mInstPtr(NULL), mAlive(false) + { + } + operator void*() + { + PX_ASSERT(mAlive); + if(mAlive) + return mInstPtr; + return NULL; + } + operator int32_t() + { + return mId; + } +}; + +typedef physx::shdfnd::Pair<int32_t, int32_t> InstancePropertyPair; + +class PvdObjectModelBase +{ + protected: + virtual ~PvdObjectModelBase() + { + } + + public: + virtual void addRef() = 0; + virtual void release() = 0; + virtual void* idToPtr(int32_t instId) const = 0; + virtual int32_t ptrToId(void* instPtr) const = 0; + virtual InstanceDescription idToDescriptor(int32_t instId) const = 0; + virtual InstanceDescription ptrToDescriptor(void* instPtr) const = 0; + virtual Option<ClassDescription> getClassOf(void* instId) const = 0; + virtual const PvdObjectModelMetaData& getMetaData() const = 0; +}; + +class PvdObjectModelMutator : public virtual PvdObjectModelBase +{ + protected: + virtual ~PvdObjectModelMutator() + { + } + + public: + // if the instance is alive, this destroyes any arrays and sets the instance back to its initial state. + virtual InstanceDescription createInstance(int32_t clsId, int32_t instId) = 0; + virtual InstanceDescription createInstance(int32_t clsId) = 0; + // Instances that are pinned are not removed from the system, ever. + // This means that createInstance, pinInstance, deleteInstance + // can be called in this order and you can still call getClassOf, etc. on the instances. + // The instances will never be removed from memory if they are pinned, so use at your + // careful discretion. + virtual void pinInstance(void* instId) = 0; + virtual void unPinInstance(void* instId) = 0; + // when doing capture, should update all events in a section at once, otherwis there possible parse data + // incompltely. + virtual void recordCompletedInstances() = 0; + + virtual void destroyInstance(void* instId) = 0; + virtual int32_t getNextInstanceHandleValue() const = 0; + // reserve a set of instance handle values by getting the current, adding an amount to it + // and setting the value. You can never set the value lower than it already is, it only climbs. + virtual void setNextInstanceHandleValue(int32_t hdlValue) = 0; + // If incoming type is provided, then we may be able to marshal simple types + // This works for arrays, it just completely replaces the entire array. + // Because if this, it is an error of the property identifier + virtual bool setPropertyValue(void* instId, int32_t propId, const uint8_t* data, uint32_t dataLen, + int32_t incomingType) = 0; + // Set a set of properties defined by a property message + virtual bool setPropertyMessage(void* instId, int32_t msgId, const uint8_t* data, uint32_t dataLen) = 0; + // insert an element(s) into array index. If index > numElements, element(s) is(are) appended. + virtual bool insertArrayElement(void* instId, int32_t propId, int32_t index, const uint8_t* data, uint32_t dataLen, + int32_t incomingType = -1) = 0; + virtual bool removeArrayElement(void* instId, int32_t propId, int32_t index) = 0; + // Add this array element to end end if it doesn't already exist in the array. + // The option is false if there was an error with the function call. + // The integer has no value if nothing was added, else it tells you the index + // where the item was added. Comparison is done using memcmp. + virtual Option<int32_t> pushBackArrayElementIf(void* instId, int32_t propId, const uint8_t* data, uint32_t dataLen, + int32_t incomingType = -1) = 0; + // Remove an array element if it exists in the array. + // The option is false if there was an error with the function call. + // the integer has no value if the item wasn't found, else it tells you the index where + // the item resided. Comparison is memcmp. + virtual Option<int32_t> removeArrayElementIf(void* instId, int32_t propId, const uint8_t* data, uint32_t dataLen, + int32_t incomingType = -1) = 0; + virtual bool setArrayElementValue(void* instId, int32_t propId, int32_t propIdx, const uint8_t* data, + uint32_t dataLen, int32_t incomingType) = 0; + + virtual void originShift(void* instId, PxVec3 shift) = 0; + + InstanceDescription createInstance(const NamespacedName& name) + { + return createInstance(getMetaData().findClass(name)->mClassId); + } + template <typename TDataType> + bool setPropertyValue(void* instId, const char* propName, const TDataType* dtype, uint32_t count) + { + ClassDescription cls(getClassOf(instId)); + Option<PropertyDescription> descOpt(getMetaData().findProperty(cls.mClassId, propName)); + if(!descOpt.hasValue()) + { + PX_ASSERT(false); + return false; + } + const PropertyDescription& prop(descOpt); + Option<ClassDescription> incomingCls(getMetaData().findClass(getPvdNamespacedNameForType<TDataType>())); + if(incomingCls.hasValue()) + return setPropertyValue(instId, prop.mPropertyId, reinterpret_cast<const uint8_t*>(dtype), + sizeof(*dtype) * count, incomingCls.getValue().mClassId); + return false; + } + + // Simplest possible setPropertyValue + template <typename TDataType> + bool setPropertyValue(void* instId, const char* propName, const TDataType& dtype) + { + return setPropertyValue(instId, propName, &dtype, 1); + } + + template <typename TDataType> + bool setPropertyMessage(void* instId, const TDataType& msg) + { + Option<PropertyMessageDescription> msgId = + getMetaData().findPropertyMessage(getPvdNamespacedNameForType<TDataType>()); + if(msgId.hasValue() == false) + return false; + return setPropertyMessage(instId, msgId.getValue().mMessageId, reinterpret_cast<const uint8_t*>(&msg), + sizeof(msg)); + } + template <typename TDataType> + bool insertArrayElement(void* instId, const char* propName, int32_t idx, const TDataType& dtype) + { + ClassDescription cls(getClassOf(instId)); + Option<PropertyDescription> descOpt(getMetaData().findProperty(cls.mClassId, propName)); + if(!descOpt.hasValue()) + { + PX_ASSERT(false); + return false; + } + const PropertyDescription& prop(descOpt); + Option<ClassDescription> incomingCls(getMetaData().findClass(getPvdNamespacedNameForType<TDataType>())); + if(incomingCls.hasValue()) + { + return insertArrayElement(instId, prop.mPropertyId, idx, reinterpret_cast<const uint8_t*>(&dtype), + sizeof(dtype), incomingCls.getValue().mClassId); + } + return false; + } + + bool removeArrayElement(void* instId, const char* propName, int32_t idx) + { + ClassDescription cls(getClassOf(instId)); + Option<PropertyDescription> descOpt(getMetaData().findProperty(cls.mClassId, propName)); + if(!descOpt.hasValue()) + { + PX_ASSERT(false); + return false; + } + const PropertyDescription& prop(descOpt); + return removeArrayElement(instId, prop.mPropertyId, idx); + } + template <typename TDataType> + Option<int32_t> pushBackArrayElementIf(void* instId, const char* pname, const TDataType& item) + { + ClassDescription cls(getClassOf(instId)); + Option<PropertyDescription> descOpt(getMetaData().findProperty(cls.mClassId, pname)); + if(!descOpt.hasValue()) + { + PX_ASSERT(false); + return None(); + } + const PropertyDescription& prop(descOpt); + Option<ClassDescription> incomingCls(getMetaData().findClass(getPvdNamespacedNameForType<TDataType>())); + if(incomingCls.hasValue() && (incomingCls.getValue().mClassId == prop.mDatatype)) + { + return pushBackArrayElementIf(instId, prop.mPropertyId, reinterpret_cast<const uint8_t*>(&item), + sizeof(item), incomingCls.getValue().mClassId); + } + return None(); + } + template <typename TDataType> + Option<int32_t> removeArrayElementIf(void* instId, const char* propId, const TDataType& item) + { + ClassDescription cls(getClassOf(instId)); + Option<PropertyDescription> descOpt(getMetaData().findProperty(cls.mClassId, propId)); + if(!descOpt.hasValue()) + { + PX_ASSERT(false); + return None(); + } + const PropertyDescription& prop(descOpt); + Option<ClassDescription> incomingCls(getMetaData().findClass(getPvdNamespacedNameForType<TDataType>())); + if(incomingCls.hasValue() && (incomingCls.getValue().mClassId == prop.mDatatype)) + { + return removeArrayElementIf(instId, prop.mPropertyId, reinterpret_cast<const uint8_t*>(&item), sizeof(item), + incomingCls.getValue().mClassId); + } + return None(); + } + template <typename TDataType> + bool setArrayElementValue(void* instId, const char* propName, int32_t propIdx, TDataType& item) + { + ClassDescription cls(getClassOf(instId)); + Option<PropertyDescription> descOpt(getMetaData().findProperty(cls.mClassId, propName)); + if(!descOpt.hasValue()) + { + PX_ASSERT(false); + return false; + } + const PropertyDescription& prop(descOpt); + Option<ClassDescription> incomingCls(getMetaData().findClass(getPvdNamespacedNameForType<TDataType>())); + if(incomingCls.hasValue() && (incomingCls.getValue().mClassId == prop.mDatatype)) + return setArrayElementValue(instId, prop.mPropertyId, propIdx, reinterpret_cast<const uint8_t*>(&item), + sizeof(item), incomingCls.getValue().mClassId); + PX_ASSERT(false); + return false; + } +}; + +class PvdObjectModelReader : public virtual PvdObjectModelBase +{ + protected: + virtual ~PvdObjectModelReader() + { + } + + public: + // Return the byte size of a possible nested property + virtual uint32_t getPropertyByteSize(void* instId, int32_t propId) = 0; + uint32_t getPropertyByteSize(void* instId, String propName) + { + int32_t propId = getMetaData().findProperty(getClassOf(instId)->mClassId, propName)->mPropertyId; + return getPropertyByteSize(instId, propId); + } + // Return the value of a possible nested property + virtual uint32_t getPropertyValue(void* instId, int32_t propId, uint8_t* outData, uint32_t outDataLen) = 0; + // Get the actual raw database memory. This is subject to change drastically if the object gets deleted. + virtual DataRef<uint8_t> getRawPropertyValue(void* instId, int32_t propId) = 0; + + DataRef<uint8_t> getRawPropertyValue(void* instId, const char* propName) + { + ClassDescription cls(getClassOf(instId)); + Option<PropertyDescription> descOpt(getMetaData().findProperty(cls.mClassId, propName)); + if(!descOpt.hasValue()) + { + PX_ASSERT(false); + return 0; + } + return getRawPropertyValue(instId, descOpt->mPropertyId); + } + + template <typename TDataType> + DataRef<TDataType> getTypedRawPropertyValue(void* instId, int32_t propId) + { + DataRef<uint8_t> propVal = getRawPropertyValue(instId, propId); + return DataRef<TDataType>(reinterpret_cast<const TDataType*>(propVal.begin()), + propVal.size() / sizeof(TDataType)); + } + + template <typename TDataType> + DataRef<TDataType> getTypedRawPropertyValue(void* instId, const char* propName) + { + DataRef<uint8_t> propVal = getRawPropertyValue(instId, propName); + return DataRef<TDataType>(reinterpret_cast<const TDataType*>(propVal.begin()), + propVal.size() / sizeof(TDataType)); + } + + template <typename TDataType> + uint32_t getPropertyValue(void* instId, const char* propName, TDataType* outBuffer, uint32_t outNumBufferItems) + { + ClassDescription cls(getClassOf(instId)); + Option<PropertyDescription> descOpt(getMetaData().findProperty(cls.mClassId, propName)); + if(!descOpt.hasValue()) + { + PX_ASSERT(false); + return 0; + } + const PropertyDescription& prop(descOpt); + uint32_t desired = outNumBufferItems * sizeof(TDataType); + return getPropertyValue(instId, prop.mPropertyId, reinterpret_cast<uint8_t*>(outBuffer), desired) / + sizeof(TDataType); + } + + template <typename TDataType> + Option<TDataType> getPropertyValue(void* instId, const char* propName) + { + TDataType retval; + if(getPropertyValue(instId, propName, &retval, 1) == 1) + return retval; + return None(); + } + + // Get this one item out of the array + // return array[idx] + virtual uint32_t getPropertyValue(void* instId, int32_t propId, int inArrayIndex, uint8_t* outData, + uint32_t outDataLen) = 0; + // Get this sub element of one item out of the array + // return array[idx].a + virtual uint32_t getPropertyValue(void* instId, int32_t propId, int inArrayIndex, int nestedProperty, + uint8_t* outData, uint32_t outDataLen) = 0; + + // Get a set of properties defined by a property message + virtual bool getPropertyMessage(void* instId, int32_t msgId, uint8_t* data, uint32_t dataLen) const = 0; + + template <typename TDataType> + bool getPropertyMessage(void* instId, TDataType& msg) + { + Option<PropertyMessageDescription> msgId( + getMetaData().findPropertyMessage(getPvdNamespacedNameForType<TDataType>())); + if(msgId.hasValue() == false) + return false; + return getPropertyMessage(instId, msgId.getValue().mMessageId, reinterpret_cast<uint8_t*>(&msg), sizeof(msg)); + } + + // clearing the array is performed with a set property value call with no data. + virtual uint32_t getNbArrayElements(void* instId, int32_t propId) = 0; + uint32_t getNbArrayElements(void* instId, const char* propName) + { + ClassDescription cls(getClassOf(instId)); + Option<PropertyDescription> descOpt(getMetaData().findProperty(cls.mClassId, propName)); + if(!descOpt.hasValue()) + { + PX_ASSERT(false); + return false; + } + const PropertyDescription& prop(descOpt); + return getNbArrayElements(instId, prop.mPropertyId); + } + + // Write this instance out. Offset is set as the instances last write offset. + // This offset is cleared if the object is changed. + // If offset doesn't have a value, then the instance isn't changed. + virtual void writeInstance(void* instId, PvdOutputStream& stream) = 0; + + virtual uint32_t getNbInstances() const = 0; + virtual uint32_t getInstances(InstanceDescription* outBuffer, uint32_t count, uint32_t startIndex = 0) const = 0; + + // Get the list of updated objects since the last time someone cleared the updated instance list. + virtual uint32_t getNbUpdatedInstances() const = 0; + virtual uint32_t getUpdatedInstances(InstanceDescription* outBuffer, uint32_t count, uint32_t startIndex = 0) = 0; + // Must be called for instances to be released. Only instances that aren't live nor are they updated + // are valid. + virtual void clearUpdatedInstances() = 0; +}; + +class PvdObjectModel : public PvdObjectModelMutator, public PvdObjectModelReader +{ + protected: + virtual ~PvdObjectModel() + { + } + + public: + virtual void destroyAllInstances() = 0; + virtual bool setPropertyValueToDefault(void* instId, int32_t propId) = 0; + // Read an instance data and put a copy of the data in the output stream. + static bool readInstance(PvdInputStream& inStream, PvdOutputStream& outStream); + virtual InstanceDescription readInstance(DataRef<const uint8_t> writtenData) = 0; + // Set just this property from this serialized instance. + // Expects the instance to be alive, just like setPropertyValue + virtual bool readInstanceProperty(DataRef<const uint8_t> writtenData, int32_t propId) = 0; + + virtual void recordCompletedInstances() = 0; + + // OriginShift seekback support + virtual uint32_t getNbShifted() = 0; + virtual void getShiftedPair(InstancePropertyPair* outData, uint32_t count) = 0; + virtual void clearShiftedPair() = 0; + virtual void shiftObject(void* instId, int32_t propId, PxVec3 shift) = 0; + static PvdObjectModel& create(physx::PxAllocatorCallback& callback, PvdObjectModelMetaData& metaData, + bool isCapture = false); +}; + +#if PX_VC == 11 || PX_VC == 12 || PX_VC == 14 +#pragma warning(pop) +#endif +} +} +#endif // PXPVDSDK_PXPVDOBJECTMODEL_H diff --git a/PxShared/src/pvd/src/PxPvdObjectModelInternalTypeDefs.h b/PxShared/src/pvd/src/PxPvdObjectModelInternalTypeDefs.h new file mode 100644 index 00000000..eec3944f --- /dev/null +++ b/PxShared/src/pvd/src/PxPvdObjectModelInternalTypeDefs.h @@ -0,0 +1,32 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 diff --git a/PxShared/src/pvd/src/PxPvdObjectModelInternalTypes.h b/PxShared/src/pvd/src/PxPvdObjectModelInternalTypes.h new file mode 100644 index 00000000..e3bef0ec --- /dev/null +++ b/PxShared/src/pvd/src/PxPvdObjectModelInternalTypes.h @@ -0,0 +1,169 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#ifndef PXPVDSDK_PXPVDOBJECTMODELINTERNALTYPES_H +#define PXPVDSDK_PXPVDOBJECTMODELINTERNALTYPES_H +#include "PxPvdObjectModelBaseTypes.h" +#include "PsArray.h" +#include "PxPvdFoundation.h" +#include "PxPvdObjectModel.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")); + memcpy(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()); + } +}; + +template <typename TObjType> +DataRef<TObjType> getArray(shdfnd::Array<uint8_t>& dataBuffer, PvdObjectModelReader& reader, InstanceDescription instanceDesc, + String propName) +{ + int32_t propId = reader.getMetaData().findProperty(reader.getClassOf(instanceDesc)->mClassId, propName)->mPropertyId; + uint32_t numBytes = reader.getPropertyByteSize(instanceDesc.mInstPtr, propId); + uint32_t numItems = reader.getNbArrayElements(instanceDesc.mInstPtr, propId); + if(numBytes == 0) + return NULL; + if(numBytes > dataBuffer.size()) + dataBuffer.resize(numBytes); + + TObjType* dataPtr = reinterpret_cast<TObjType*>(dataBuffer.begin()); + reader.getPropertyValue(instanceDesc, propId, dataBuffer.begin(), numBytes); + return DataRef<TObjType>(dataPtr, numItems); +} +} +} +#endif // PXPVDSDK_PXPVDOBJECTMODELINTERNALTYPES_H diff --git a/PxShared/src/pvd/src/PxPvdObjectModelMetaData.cpp b/PxShared/src/pvd/src/PxPvdObjectModelMetaData.cpp new file mode 100644 index 00000000..10c082c1 --- /dev/null +++ b/PxShared/src/pvd/src/PxPvdObjectModelMetaData.cpp @@ -0,0 +1,1515 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +#include "PxPvdObjectModel.h" +#include "PxPvdObjectModelBaseTypes.h" +#include "PxPvdObjectModelInternalTypes.h" +#include "PxPvdObjectModelMetaData.h" +#include "PxPvdFoundation.h" +#include "PsMutex.h" +#include "PxPvdByteStreams.h" +#include "PxPvdInternalByteStreams.h" +#include "PxPvdMarshalling.h" + +using namespace physx; +using namespace pvdsdk; +using namespace shdfnd; + +namespace +{ + +struct PropDescImpl : public PropertyDescription, public UserAllocated +{ + Array<NamedValue> mValueNames; + PropDescImpl(const PropertyDescription& inBase, StringTable& table) + : PropertyDescription(inBase), mValueNames("NamedValue") + { + mName = table.registerStr(mName); + } + PropDescImpl() : mValueNames("NamedValue") + { + } + + template <typename TSerializer> + void serialize(TSerializer& serializer) + { + serializer.streamify(mOwnerClassName); + serializer.streamify(mOwnerClassId); + serializer.streamify(mSemantic); + serializer.streamify(mDatatype); + serializer.streamify(mDatatypeName); + serializer.streamify(mPropertyType); + serializer.streamify(mPropertyId); + serializer.streamify(m32BitOffset); + serializer.streamify(m64BitOffset); + serializer.streamify(mValueNames); + serializer.streamify(mName); + } +}; + +struct ClassDescImpl : public ClassDescription, public UserAllocated +{ + Array<PropDescImpl*> mPropImps; + Array<PtrOffset> m32OffsetArray; + Array<PtrOffset> m64OffsetArray; + ClassDescImpl(const ClassDescription& inBase) + : ClassDescription(inBase) + , mPropImps("PropDescImpl*") + , m32OffsetArray("ClassDescImpl::m32OffsetArray") + , m64OffsetArray("ClassDescImpl::m64OffsetArray") + { + PVD_FOREACH(idx, get32BitSizeInfo().mPtrOffsets.size()) + m32OffsetArray.pushBack(get32BitSizeInfo().mPtrOffsets[idx]); + PVD_FOREACH(idx, get64BitSizeInfo().mPtrOffsets.size()) + m64OffsetArray.pushBack(get64BitSizeInfo().mPtrOffsets[idx]); + } + ClassDescImpl() + : mPropImps("PropDescImpl*") + , m32OffsetArray("ClassDescImpl::m32OffsetArray") + , m64OffsetArray("ClassDescImpl::m64OffsetArray") + { + } + PropDescImpl* findProperty(String name) + { + PVD_FOREACH(idx, mPropImps.size()) + { + if(safeStrEq(mPropImps[idx]->mName, name)) + return mPropImps[idx]; + } + return NULL; + } + void addProperty(PropDescImpl* prop) + { + mPropImps.pushBack(prop); + } + + void addPtrOffset(PtrOffsetType::Enum type, uint32_t offset32, uint32_t offset64) + { + m32OffsetArray.pushBack(PtrOffset(type, offset32)); + m64OffsetArray.pushBack(PtrOffset(type, offset64)); + get32BitSizeInfo().mPtrOffsets = DataRef<PtrOffset>(m32OffsetArray.begin(), m32OffsetArray.end()); + get64BitSizeInfo().mPtrOffsets = DataRef<PtrOffset>(m64OffsetArray.begin(), m64OffsetArray.end()); + } + + template <typename TSerializer> + void serialize(TSerializer& serializer) + { + serializer.streamify(mName); + serializer.streamify(mClassId); + serializer.streamify(mBaseClass); + serializer.streamify(mPackedUniformWidth); + serializer.streamify(mPackedClassType); + serializer.streamify(mLocked); + serializer.streamify(mRequiresDestruction); + serializer.streamify(get32BitSize()); + serializer.streamify(get32BitSizeInfo().mDataByteSize); + serializer.streamify(get32BitSizeInfo().mAlignment); + serializer.streamify(get64BitSize()); + serializer.streamify(get64BitSizeInfo().mDataByteSize); + serializer.streamify(get64BitSizeInfo().mAlignment); + serializer.streamifyLinks(mPropImps); + serializer.streamify(m32OffsetArray); + serializer.streamify(m64OffsetArray); + get32BitSizeInfo().mPtrOffsets = DataRef<PtrOffset>(m32OffsetArray.begin(), m32OffsetArray.end()); + get64BitSizeInfo().mPtrOffsets = DataRef<PtrOffset>(m64OffsetArray.begin(), m64OffsetArray.end()); + } +}; + +class StringTableImpl : public StringTable, public UserAllocated +{ + HashMap<const char*, char*> mStrings; + uint32_t mNextStrHandle; + HashMap<uint32_t, char*> mHandleToStr; + HashMap<const char*, uint32_t> mStrToHandle; + + public: + StringTableImpl() + : mStrings("StringTableImpl::mStrings") + , mNextStrHandle(1) + , mHandleToStr("StringTableImpl::mHandleToStr") + , mStrToHandle("StringTableImpl::mStrToHandle") + { + } + uint32_t nextHandleValue() + { + return mNextStrHandle++; + } + virtual ~StringTableImpl() + { + for(HashMap<const char*, char*>::Iterator iter = mStrings.getIterator(); !iter.done(); ++iter) + PX_FREE(iter->second); + mStrings.clear(); + } + virtual uint32_t getNbStrs() + { + return mStrings.size(); + } + virtual uint32_t getStrs(const char** outStrs, uint32_t bufLen, uint32_t startIdx = 0) + { + startIdx = PxMin(getNbStrs(), startIdx); + uint32_t numStrs(PxMin(getNbStrs() - startIdx, bufLen)); + HashMap<const char*, char*>::Iterator iter(mStrings.getIterator()); + for(uint32_t idx = 0; idx < startIdx; ++idx, ++iter) + ; + for(uint32_t idx = 0; idx < numStrs && !iter.done(); ++idx, ++iter) + outStrs[idx] = iter->second; + return numStrs; + } + void addStringHandle(char* str, uint32_t hdl) + { + mHandleToStr.insert(hdl, str); + mStrToHandle.insert(str, hdl); + } + + uint32_t addStringHandle(char* str) + { + uint32_t theNewHandle = nextHandleValue(); + addStringHandle(str, theNewHandle); + return theNewHandle; + } + const char* doRegisterStr(const char* str, bool& outAdded) + { + PX_ASSERT(isMeaningful(str)); + const HashMap<const char*, char*>::Entry* entry(mStrings.find(str)); + if(entry == NULL) + { + outAdded = true; + char* retval(copyStr(str)); + mStrings.insert(retval, retval); + return retval; + } + return entry->second; + } + virtual const char* registerStr(const char* str, bool& outAdded) + { + outAdded = false; + if(isMeaningful(str) == false) + return ""; + const char* retval = doRegisterStr(str, outAdded); + if(outAdded) + addStringHandle(const_cast<char*>(retval)); + return retval; + } + + NamespacedName registerName(const NamespacedName& nm) + { + return NamespacedName(registerStr(nm.mNamespace), registerStr(nm.mName)); + } + const char* registerStr(const char* str) + { + bool ignored; + return registerStr(str, ignored); + } + + virtual StringHandle strToHandle(const char* str) + { + if(isMeaningful(str) == false) + return 0; + const HashMap<const char*, uint32_t>::Entry* entry(mStrToHandle.find(str)); + if(entry) + return entry->second; + bool added = false; + const char* registeredStr = doRegisterStr(str, added); + uint32_t theNewHandle = addStringHandle(const_cast<char*>(registeredStr)); + PX_ASSERT(mStrToHandle.find(str)); + PX_ASSERT(added); + return theNewHandle; + } + + virtual const char* handleToStr(uint32_t hdl) + { + if(hdl == 0) + return ""; + const HashMap<uint32_t, char*>::Entry* entry(mHandleToStr.find(hdl)); + if(entry) + return entry->second; + // unregistered handle... + return ""; + } + + void write(PvdOutputStream& stream) + { + uint32_t numStrs = static_cast<uint32_t>(mHandleToStr.size()); + stream << numStrs; + stream << mNextStrHandle; + for(HashMap<uint32_t, char*>::Iterator iter = mHandleToStr.getIterator(); !iter.done(); ++iter) + { + stream << iter->first; + uint32_t len = static_cast<uint32_t>(strlen(iter->second) + 1); + stream << len; + stream.write(reinterpret_cast<uint8_t*>(iter->second), len); + } + } + + template <typename TReader> + void read(TReader& stream) + { + mHandleToStr.clear(); + mStrToHandle.clear(); + uint32_t numStrs; + stream >> numStrs; + stream >> mNextStrHandle; + Array<uint8_t> readBuffer("StringTable::read::readBuffer"); + uint32_t bufSize = 0; + for(uint32_t idx = 0; idx < numStrs; ++idx) + { + uint32_t handleValue; + uint32_t bufLen; + stream >> handleValue; + stream >> bufLen; + if(bufSize < bufLen) + readBuffer.resize(bufLen); + bufSize = PxMax(bufSize, bufLen); + stream.read(readBuffer.begin(), bufLen); + bool ignored; + const char* newStr = doRegisterStr(reinterpret_cast<const char*>(readBuffer.begin()), ignored); + addStringHandle(const_cast<char*>(newStr), handleValue); + } + } + + virtual void release() + { + PVD_DELETE(this); + } + + private: + StringTableImpl& operator=(const StringTableImpl&); +}; + +struct NamespacedNameHasher +{ + uint32_t operator()(const NamespacedName& nm) + { + return Hash<const char*>()(nm.mNamespace) ^ Hash<const char*>()(nm.mName); + } + bool equal(const NamespacedName& lhs, const NamespacedName& rhs) + { + return safeStrEq(lhs.mNamespace, rhs.mNamespace) && safeStrEq(lhs.mName, rhs.mName); + } +}; + +struct ClassPropertyName +{ + NamespacedName mName; + String mPropName; + ClassPropertyName(const NamespacedName& name = NamespacedName(), String propName = "") + : mName(name), mPropName(propName) + { + } +}; + +struct ClassPropertyNameHasher +{ + uint32_t operator()(const ClassPropertyName& nm) + { + return NamespacedNameHasher()(nm.mName) ^ Hash<const char*>()(nm.mPropName); + } + bool equal(const ClassPropertyName& lhs, const ClassPropertyName& rhs) + { + return NamespacedNameHasher().equal(lhs.mName, rhs.mName) && safeStrEq(lhs.mPropName, rhs.mPropName); + } +}; + +struct PropertyMessageEntryImpl : public PropertyMessageEntry +{ + PropertyMessageEntryImpl(const PropertyMessageEntry& data) : PropertyMessageEntry(data) + { + } + PropertyMessageEntryImpl() + { + } + template <typename TSerializerType> + void serialize(TSerializerType& serializer) + { + serializer.streamify(mDatatypeName); + serializer.streamify(mDatatypeId); + serializer.streamify(mMessageOffset); + serializer.streamify(mByteSize); + serializer.streamify(mDestByteSize); + serializer.streamify(mProperty); + } +}; + +struct PropertyMessageDescriptionImpl : public PropertyMessageDescription, public UserAllocated +{ + Array<PropertyMessageEntryImpl> mEntryImpls; + Array<PropertyMessageEntry> mEntries; + Array<uint32_t> mStringOffsetArray; + PropertyMessageDescriptionImpl(const PropertyMessageDescription& data) + : PropertyMessageDescription(data) + , mEntryImpls("PropertyMessageDescriptionImpl::mEntryImpls") + , mEntries("PropertyMessageDescriptionImpl::mEntries") + , mStringOffsetArray("PropertyMessageDescriptionImpl::mStringOffsets") + { + } + PropertyMessageDescriptionImpl() + : mEntryImpls("PropertyMessageDescriptionImpl::mEntryImpls") + , mEntries("PropertyMessageDescriptionImpl::mEntries") + , mStringOffsetArray("PropertyMessageDescriptionImpl::mStringOffsets") + { + } + + ~PropertyMessageDescriptionImpl() + { + } + + void addEntry(const PropertyMessageEntryImpl& entry) + { + mEntryImpls.pushBack(entry); + mEntries.pushBack(entry); + mProperties = DataRef<PropertyMessageEntry>(mEntries.begin(), mEntries.end()); + } + + template <typename TSerializerType> + void serialize(TSerializerType& serializer) + { + serializer.streamify(mClassName); + serializer.streamify(mClassId); // No other class has this id, it is DB-unique + serializer.streamify(mMessageName); + serializer.streamify(mMessageId); + serializer.streamify(mMessageByteSize); + serializer.streamify(mEntryImpls); + serializer.streamify(mStringOffsetArray); + if(mEntries.size() != mEntryImpls.size()) + { + mEntries.clear(); + uint32_t numEntries = static_cast<uint32_t>(mEntryImpls.size()); + for(uint32_t idx = 0; idx < numEntries; ++idx) + mEntries.pushBack(mEntryImpls[idx]); + } + mProperties = DataRef<PropertyMessageEntry>(mEntries.begin(), mEntries.end()); + mStringOffsets = DataRef<uint32_t>(mStringOffsetArray.begin(), mStringOffsetArray.end()); + } + + private: + PropertyMessageDescriptionImpl& operator=(const PropertyMessageDescriptionImpl&); +}; + +struct PvdObjectModelMetaDataImpl : public PvdObjectModelMetaData, public UserAllocated +{ + typedef HashMap<NamespacedName, ClassDescImpl*, NamespacedNameHasher> TNameToClassMap; + typedef HashMap<ClassPropertyName, PropDescImpl*, ClassPropertyNameHasher> TNameToPropMap; + typedef HashMap<NamespacedName, PropertyMessageDescriptionImpl*, NamespacedNameHasher> TNameToPropertyMessageMap; + + TNameToClassMap mNameToClasses; + TNameToPropMap mNameToProperties; + Array<ClassDescImpl*> mClasses; + Array<PropDescImpl*> mProperties; + StringTableImpl* mStringTable; + TNameToPropertyMessageMap mPropertyMessageMap; + Array<PropertyMessageDescriptionImpl*> mPropertyMessages; + int32_t mNextClassId; + uint32_t mRefCount; + + PvdObjectModelMetaDataImpl() + : mNameToClasses("NamespacedName->ClassDescImpl*") + , mNameToProperties("ClassPropertyName->PropDescImpl*") + , mClasses("ClassDescImpl*") + , mProperties("PropDescImpl*") + , mStringTable(PVD_NEW(StringTableImpl)()) + , mPropertyMessageMap("PropertyMessageMap") + , mPropertyMessages("PvdObjectModelMetaDataImpl::mPropertyMessages") + , mNextClassId(1) + , mRefCount(0) + { + } + + private: + PvdObjectModelMetaDataImpl& operator=(const PvdObjectModelMetaDataImpl&); + + public: + int32_t nextClassId() + { + return mNextClassId++; + } + void initialize() + { + // Create the default classes. + { + ClassDescImpl& aryData = getOrCreateClassImpl(getPvdNamespacedNameForType<ArrayData>(), + DataTypeToPvdTypeMap<ArrayData>::BaseTypeEnum); + aryData.get32BitSize() = sizeof(ArrayData); + aryData.get32BitSizeInfo().mAlignment = sizeof(void*); + aryData.get64BitSize() = sizeof(ArrayData); + aryData.get64BitSizeInfo().mAlignment = sizeof(void*); + aryData.mLocked = true; + } +#define CREATE_BASIC_PVD_CLASS(type) \ + { \ + ClassDescImpl& cls = getOrCreateClassImpl(getPvdNamespacedNameForType<type>(), getPvdTypeForType<type>()); \ + cls.get32BitSize() = sizeof(type); \ + cls.get32BitSizeInfo().mAlignment = sizeof(type); \ + cls.get64BitSize() = sizeof(type); \ + cls.get64BitSizeInfo().mAlignment = sizeof(type); \ + cls.mLocked = true; \ + cls.mPackedUniformWidth = sizeof(type); \ + cls.mPackedClassType = getPvdTypeForType<type>(); \ + } + CREATE_BASIC_PVD_CLASS(int8_t) + CREATE_BASIC_PVD_CLASS(uint8_t) + CREATE_BASIC_PVD_CLASS(bool) + CREATE_BASIC_PVD_CLASS(int16_t) + CREATE_BASIC_PVD_CLASS(uint16_t) + CREATE_BASIC_PVD_CLASS(int32_t) + CREATE_BASIC_PVD_CLASS(uint32_t) + // CREATE_BASIC_PVD_CLASS(uint32_t) + CREATE_BASIC_PVD_CLASS(int64_t) + CREATE_BASIC_PVD_CLASS(uint64_t) + CREATE_BASIC_PVD_CLASS(float) + CREATE_BASIC_PVD_CLASS(double) +#undef CREATE_BASIC_PVD_CLASS + +#define CREATE_PTR_TYPE_PVD_CLASS(type, ptrType) \ + { \ + ClassDescImpl& cls = getOrCreateClassImpl(getPvdNamespacedNameForType<type>(), getPvdTypeForType<type>()); \ + cls.get32BitSize() = 4; \ + cls.get32BitSizeInfo().mAlignment = 4; \ + cls.get64BitSize() = 8; \ + cls.get64BitSizeInfo().mAlignment = 8; \ + cls.mLocked = true; \ + cls.addPtrOffset(PtrOffsetType::ptrType, 0, 0); \ + } + + CREATE_PTR_TYPE_PVD_CLASS(String, StringOffset) + CREATE_PTR_TYPE_PVD_CLASS(VoidPtr, VoidPtrOffset) + CREATE_PTR_TYPE_PVD_CLASS(StringHandle, StringOffset) + CREATE_PTR_TYPE_PVD_CLASS(ObjectRef, VoidPtrOffset) + +#undef CREATE_64BIT_ADJUST_PVD_CLASS + + int32_t fltClassType = getPvdTypeForType<float>(); + int32_t u32ClassType = getPvdTypeForType<uint32_t>(); + int32_t v3ClassType = getPvdTypeForType<PxVec3>(); + int32_t v4ClassType = getPvdTypeForType<PxVec4>(); + int32_t qtClassType = getPvdTypeForType<PxQuat>(); + { + ClassDescImpl& cls = + getOrCreateClassImpl(getPvdNamespacedNameForType<PvdColor>(), getPvdTypeForType<PvdColor>()); + createProperty(cls.mClassId, "r", "", getPvdTypeForType<uint8_t>(), PropertyType::Scalar); + createProperty(cls.mClassId, "g", "", getPvdTypeForType<uint8_t>(), PropertyType::Scalar); + createProperty(cls.mClassId, "b", "", getPvdTypeForType<uint8_t>(), PropertyType::Scalar); + createProperty(cls.mClassId, "a", "", getPvdTypeForType<uint8_t>(), PropertyType::Scalar); + PX_ASSERT(cls.get32BitSizeInfo().mAlignment == 1); + PX_ASSERT(cls.get32BitSize() == 4); + PX_ASSERT(cls.get64BitSizeInfo().mAlignment == 1); + PX_ASSERT(cls.get64BitSize() == 4); + PX_ASSERT(cls.mPackedUniformWidth == 1); + PX_ASSERT(cls.mPackedClassType == getPvdTypeForType<uint8_t>()); + cls.mLocked = true; + } + + { + ClassDescImpl& cls = getOrCreateClassImpl(getPvdNamespacedNameForType<PxVec2>(), getPvdTypeForType<PxVec2>()); + createProperty(cls.mClassId, "x", "", fltClassType, PropertyType::Scalar); + createProperty(cls.mClassId, "y", "", fltClassType, PropertyType::Scalar); + PX_ASSERT(cls.get32BitSizeInfo().mAlignment == 4); + PX_ASSERT(cls.get32BitSize() == 8); + PX_ASSERT(cls.get64BitSizeInfo().mAlignment == 4); + PX_ASSERT(cls.get64BitSize() == 8); + PX_ASSERT(cls.mPackedUniformWidth == 4); + PX_ASSERT(cls.mPackedClassType == fltClassType); + cls.mLocked = true; + } + { + ClassDescImpl& cls = getOrCreateClassImpl(getPvdNamespacedNameForType<PxVec3>(), getPvdTypeForType<PxVec3>()); + createProperty(cls.mClassId, "x", "", fltClassType, PropertyType::Scalar); + createProperty(cls.mClassId, "y", "", fltClassType, PropertyType::Scalar); + createProperty(cls.mClassId, "z", "", fltClassType, PropertyType::Scalar); + PX_ASSERT(cls.get32BitSizeInfo().mAlignment == 4); + PX_ASSERT(cls.get32BitSize() == 12); + PX_ASSERT(cls.get64BitSizeInfo().mAlignment == 4); + PX_ASSERT(cls.get64BitSize() == 12); + PX_ASSERT(cls.mPackedUniformWidth == 4); + PX_ASSERT(cls.mPackedClassType == fltClassType); + cls.mLocked = true; + } + { + ClassDescImpl& cls = getOrCreateClassImpl(getPvdNamespacedNameForType<PxVec4>(), getPvdTypeForType<PxVec4>()); + createProperty(cls.mClassId, "x", "", fltClassType, PropertyType::Scalar); + createProperty(cls.mClassId, "y", "", fltClassType, PropertyType::Scalar); + createProperty(cls.mClassId, "z", "", fltClassType, PropertyType::Scalar); + createProperty(cls.mClassId, "w", "", fltClassType, PropertyType::Scalar); + PX_ASSERT(cls.get32BitSizeInfo().mAlignment == 4); + PX_ASSERT(cls.get32BitSize() == 16); + PX_ASSERT(cls.get64BitSizeInfo().mAlignment == 4); + PX_ASSERT(cls.get64BitSize() == 16); + PX_ASSERT(cls.mPackedUniformWidth == 4); + PX_ASSERT(cls.mPackedClassType == fltClassType); + cls.mLocked = true; + } + + { + ClassDescImpl& cls = getOrCreateClassImpl(getPvdNamespacedNameForType<PxQuat>(), getPvdTypeForType<PxQuat>()); + createProperty(cls.mClassId, "x", "", fltClassType, PropertyType::Scalar); + createProperty(cls.mClassId, "y", "", fltClassType, PropertyType::Scalar); + createProperty(cls.mClassId, "z", "", fltClassType, PropertyType::Scalar); + createProperty(cls.mClassId, "w", "", fltClassType, PropertyType::Scalar); + PX_ASSERT(cls.get32BitSizeInfo().mAlignment == 4); + PX_ASSERT(cls.get32BitSize() == 16); + PX_ASSERT(cls.get64BitSizeInfo().mAlignment == 4); + PX_ASSERT(cls.get64BitSize() == 16); + PX_ASSERT(cls.mPackedUniformWidth == 4); + PX_ASSERT(cls.mPackedClassType == fltClassType); + cls.mLocked = true; + } + + { + ClassDescImpl& cls = + getOrCreateClassImpl(getPvdNamespacedNameForType<PxBounds3>(), getPvdTypeForType<PxBounds3>()); + createProperty(cls.mClassId, "minimum", "", v3ClassType, PropertyType::Scalar); + createProperty(cls.mClassId, "maximum", "", v3ClassType, PropertyType::Scalar); + PX_ASSERT(cls.get32BitSizeInfo().mAlignment == 4); + PX_ASSERT(cls.get32BitSize() == 24); + PX_ASSERT(cls.mPackedUniformWidth == 4); + PX_ASSERT(cls.mPackedClassType == fltClassType); + cls.mLocked = true; + } + + { + ClassDescImpl& cls = + getOrCreateClassImpl(getPvdNamespacedNameForType<PxTransform>(), getPvdTypeForType<PxTransform>()); + createProperty(cls.mClassId, "q", "", qtClassType, PropertyType::Scalar); + createProperty(cls.mClassId, "p", "", v3ClassType, PropertyType::Scalar); + PX_ASSERT(cls.get32BitSizeInfo().mAlignment == 4); + PX_ASSERT(cls.get32BitSize() == 28); + PX_ASSERT(cls.mPackedUniformWidth == 4); + PX_ASSERT(cls.mPackedClassType == fltClassType); + cls.mLocked = true; + } + + { + ClassDescImpl& cls = + getOrCreateClassImpl(getPvdNamespacedNameForType<PxMat33>(), getPvdTypeForType<PxMat33>()); + createProperty(cls.mClassId, "column0", "", v3ClassType, PropertyType::Scalar); + createProperty(cls.mClassId, "column1", "", v3ClassType, PropertyType::Scalar); + createProperty(cls.mClassId, "column2", "", v3ClassType, PropertyType::Scalar); + PX_ASSERT(cls.get32BitSizeInfo().mAlignment == 4); + PX_ASSERT(cls.get32BitSize() == 36); + PX_ASSERT(cls.mPackedUniformWidth == 4); + PX_ASSERT(cls.mPackedClassType == fltClassType); + cls.mLocked = true; + } + + { + ClassDescImpl& cls = + getOrCreateClassImpl(getPvdNamespacedNameForType<PxMat44>(), getPvdTypeForType<PxMat44>()); + createProperty(cls.mClassId, "column0", "", v4ClassType, PropertyType::Scalar); + createProperty(cls.mClassId, "column1", "", v4ClassType, PropertyType::Scalar); + createProperty(cls.mClassId, "column2", "", v4ClassType, PropertyType::Scalar); + createProperty(cls.mClassId, "column3", "", v4ClassType, PropertyType::Scalar); + PX_ASSERT(cls.get32BitSizeInfo().mAlignment == 4); + PX_ASSERT(cls.get32BitSize() == 64); + PX_ASSERT(cls.mPackedUniformWidth == 4); + PX_ASSERT(cls.mPackedClassType == fltClassType); + cls.mLocked = true; + } + + { + ClassDescImpl& cls = + getOrCreateClassImpl(getPvdNamespacedNameForType<U32Array4>(), getPvdTypeForType<U32Array4>()); + createProperty(cls.mClassId, "d0", "", u32ClassType, PropertyType::Scalar); + createProperty(cls.mClassId, "d1", "", u32ClassType, PropertyType::Scalar); + createProperty(cls.mClassId, "d2", "", u32ClassType, PropertyType::Scalar); + createProperty(cls.mClassId, "d3", "", u32ClassType, PropertyType::Scalar); + cls.mLocked = true; + } + } + virtual ~PvdObjectModelMetaDataImpl() + { + mStringTable->release(); + PVD_FOREACH(idx, mClasses.size()) + { + if(mClasses[idx] != NULL) + PVD_DELETE(mClasses[idx]); + } + mClasses.clear(); + PVD_FOREACH(idx, mProperties.size()) PVD_DELETE(mProperties[idx]); + mProperties.clear(); + PVD_FOREACH(idx, mPropertyMessages.size()) PVD_DELETE(mPropertyMessages[idx]); + mPropertyMessages.clear(); + } + + ClassDescImpl& getOrCreateClassImpl(const NamespacedName& nm, int32_t idx) + { + ClassDescImpl* impl(getClassImpl(idx)); + if(impl) + return *impl; + NamespacedName safeName(mStringTable->registerStr(nm.mNamespace), mStringTable->registerStr(nm.mName)); + while(idx >= int32_t(mClasses.size())) + mClasses.pushBack(NULL); + mClasses[uint32_t(idx)] = PVD_NEW(ClassDescImpl)(ClassDescription(safeName, idx)); + mNameToClasses.insert(nm, mClasses[uint32_t(idx)]); + mNextClassId = PxMax(mNextClassId, idx + 1); + return *mClasses[uint32_t(idx)]; + } + + ClassDescImpl& getOrCreateClassImpl(const NamespacedName& nm) + { + ClassDescImpl* retval = findClassImpl(nm); + if(retval) + return *retval; + return getOrCreateClassImpl(nm, nextClassId()); + } + virtual ClassDescription getOrCreateClass(const NamespacedName& nm) + { + return getOrCreateClassImpl(nm); + } + // get or create parent, lock parent. deriveFrom getOrCreatechild. + virtual bool deriveClass(const NamespacedName& parent, const NamespacedName& child) + { + ClassDescImpl& p(getOrCreateClassImpl(parent)); + ClassDescImpl& c(getOrCreateClassImpl(child)); + + if(c.mBaseClass >= 0) + { + PX_ASSERT(c.mBaseClass == p.mClassId); + return false; + } + p.mLocked = true; + c.mBaseClass = p.mClassId; + c.get32BitSizeInfo() = p.get32BitSizeInfo(); + c.get64BitSizeInfo() = p.get64BitSizeInfo(); + c.mPackedClassType = p.mPackedClassType; + c.mPackedUniformWidth = p.mPackedUniformWidth; + c.mRequiresDestruction = p.mRequiresDestruction; + c.m32OffsetArray = p.m32OffsetArray; + c.m64OffsetArray = p.m64OffsetArray; + // Add all the parent propertes to this class in the global name map. + for(ClassDescImpl* parent0 = &p; parent0 != NULL; parent0 = getClassImpl(parent0->mBaseClass)) + { + PVD_FOREACH(idx, parent0->mPropImps.size()) + mNameToProperties.insert(ClassPropertyName(c.mName, parent0->mPropImps[idx]->mName), parent0->mPropImps[idx]); + + if(parent0->mBaseClass < 0) + break; + } + + return true; + } + ClassDescImpl* findClassImpl(const NamespacedName& nm) const + { + const TNameToClassMap::Entry* entry(mNameToClasses.find(nm)); + if(entry) + return entry->second; + return NULL; + } + virtual Option<ClassDescription> findClass(const NamespacedName& nm) const + { + ClassDescImpl* retval = findClassImpl(nm); + if(retval) + return *retval; + return Option<ClassDescription>(); + } + + ClassDescImpl* getClassImpl(int32_t classId) const + { + if(classId < 0) + return NULL; + uint32_t idx = uint32_t(classId); + if(idx < mClasses.size()) + return mClasses[idx]; + return NULL; + } + + virtual Option<ClassDescription> getClass(int32_t classId) const + { + ClassDescImpl* impl(getClassImpl(classId)); + if(impl) + return *impl; + return None(); + } + + virtual ClassDescription* getClassPtr(int32_t classId) const + { + return getClassImpl(classId); + } + + virtual Option<ClassDescription> getParentClass(int32_t classId) const + { + ClassDescImpl* impl(getClassImpl(classId)); + if(impl == NULL) + return None(); + return getClass(impl->mBaseClass); + } + + virtual void lockClass(int32_t classId) + { + ClassDescImpl* impl(getClassImpl(classId)); + PX_ASSERT(impl); + if(impl) + impl->mLocked = true; + } + virtual uint32_t getNbClasses() const + { + uint32_t total = 0; + PVD_FOREACH(idx, mClasses.size()) if(mClasses[idx])++ total; + return total; + } + + virtual uint32_t getClasses(ClassDescription* outClasses, uint32_t requestCount, uint32_t startIndex = 0) const + { + uint32_t classCount(getNbClasses()); + startIndex = PxMin(classCount, startIndex); + uint32_t retAmount = PxMin(requestCount, classCount - startIndex); + + uint32_t idx = 0; + while(startIndex) + { + if(mClasses[idx] != NULL) + --startIndex; + ++idx; + } + + uint32_t inserted = 0; + uint32_t classesSize = static_cast<uint32_t>(mClasses.size()); + while(inserted < retAmount && idx < classesSize) + { + if(mClasses[idx] != NULL) + { + outClasses[inserted] = *mClasses[idx]; + ++inserted; + } + ++idx; + } + return inserted; + } + + uint32_t updateByteSizeAndGetPropertyAlignment(ClassDescriptionSizeInfo& dest, const ClassDescriptionSizeInfo& src) + { + uint32_t alignment = src.mAlignment; + dest.mAlignment = PxMax(dest.mAlignment, alignment); + uint32_t offset = align(dest.mDataByteSize, alignment); + dest.mDataByteSize = offset + src.mByteSize; + dest.mByteSize = align(dest.mDataByteSize, dest.mAlignment); + return offset; + } + + void transferPtrOffsets(ClassDescriptionSizeInfo& destInfo, Array<PtrOffset>& destArray, + const Array<PtrOffset>& src, uint32_t offset) + { + PVD_FOREACH(idx, src.size()) + destArray.pushBack(PtrOffset(src[idx].mOffsetType, src[idx].mOffset + offset)); + destInfo.mPtrOffsets = DataRef<PtrOffset>(destArray.begin(), destArray.end()); + } + + virtual Option<PropertyDescription> createProperty(int32_t classId, String name, String semantic, int32_t datatype, + PropertyType::Enum propertyType) + { + ClassDescImpl* cls(getClassImpl(classId)); + PX_ASSERT(cls); + if(!cls) + return None(); + if(cls->mLocked) + { + PX_ASSERT(false); + return None(); + } + PropDescImpl* impl(cls->findProperty(name)); + // duplicate property definition + if(impl) + { + PX_ASSERT(false); + return None(); + } + if(datatype == getPvdTypeForType<String>()) + { + PX_ASSERT(false); + return None(); + } + // The datatype for this property has not been declared. + ClassDescImpl* propDType(getClassImpl(datatype)); + PX_ASSERT(propDType); + if(!propDType) + return None(); + NamespacedName propClsName(propDType->mName); + int32_t propPackedWidth = propDType->mPackedUniformWidth; + int32_t propPackedType = propDType->mPackedClassType; + // The implications of properties being complex types aren't major + //*until* you start trying to undue a property event that set values + // of those complex types. Then things just get too complex. + if(propDType->mRequiresDestruction) + { + PX_ASSERT(false); + return None(); + } + bool requiresDestruction = propDType->mRequiresDestruction || cls->mRequiresDestruction; + + if(propertyType == PropertyType::Array) + { + int32_t tempId = DataTypeToPvdTypeMap<ArrayData>::BaseTypeEnum; + propDType = getClassImpl(tempId); + PX_ASSERT(propDType); + if(!propDType) + return None(); + requiresDestruction = true; + } + uint32_t offset32 = updateByteSizeAndGetPropertyAlignment(cls->get32BitSizeInfo(), propDType->get32BitSizeInfo()); + uint32_t offset64 = updateByteSizeAndGetPropertyAlignment(cls->get64BitSizeInfo(), propDType->get64BitSizeInfo()); + transferPtrOffsets(cls->get32BitSizeInfo(), cls->m32OffsetArray, propDType->m32OffsetArray, offset32); + transferPtrOffsets(cls->get64BitSizeInfo(), cls->m64OffsetArray, propDType->m64OffsetArray, offset64); + propDType->mLocked = true; // Can't add members to the property type. + cls->mRequiresDestruction = requiresDestruction; + int32_t propId = int32_t(mProperties.size()); + PropertyDescription newDesc(cls->mName, cls->mClassId, name, semantic, datatype, propClsName, propertyType, + propId, offset32, offset64); + mProperties.pushBack(PVD_NEW(PropDescImpl)(newDesc, *mStringTable)); + mNameToProperties.insert(ClassPropertyName(cls->mName, mProperties.back()->mName), mProperties.back()); + cls->addProperty(mProperties.back()); + bool firstProp = cls->mPropImps.size() == 1; + + if(firstProp) + { + cls->mPackedUniformWidth = propPackedWidth; + cls->mPackedClassType = propPackedType; + } + else + { + bool packed = (propPackedWidth > 0) && (cls->get32BitSizeInfo().mDataByteSize % propPackedWidth) == 0; + if(cls->mPackedClassType >= 0) // maybe uncheck packed class type + { + if(propPackedType < 0 || cls->mPackedClassType != propPackedType + // Object refs require conversion from stream to db id + || + datatype == getPvdTypeForType<ObjectRef>() + // Strings also require conversion from stream to db id. + || + datatype == getPvdTypeForType<StringHandle>() || packed == false) + cls->mPackedClassType = -1; + } + if(cls->mPackedUniformWidth >= 0) // maybe uncheck packed class width + { + if(propPackedWidth < 0 || cls->mPackedUniformWidth != propPackedWidth + // object refs, because they require special treatment during parsing, + // cannot be packed + || + datatype == getPvdTypeForType<ObjectRef>() + // Likewise, string handles are special because the data needs to be sent *after* + // the + || + datatype == getPvdTypeForType<StringHandle>() || packed == false) + cls->mPackedUniformWidth = -1; // invalid packed width. + } + } + return *mProperties.back(); + } + + PropDescImpl* findPropImpl(const NamespacedName& clsName, String prop) const + { + const TNameToPropMap::Entry* entry = mNameToProperties.find(ClassPropertyName(clsName, prop)); + if(entry) + return entry->second; + return NULL; + } + virtual Option<PropertyDescription> findProperty(const NamespacedName& cls, String propName) const + { + PropDescImpl* prop(findPropImpl(cls, propName)); + if(prop) + return *prop; + return None(); + } + + virtual Option<PropertyDescription> findProperty(int32_t clsId, String propName) const + { + ClassDescImpl* cls(getClassImpl(clsId)); + PX_ASSERT(cls); + if(!cls) + return None(); + PropDescImpl* prop(findPropImpl(cls->mName, propName)); + if(prop) + return *prop; + return None(); + } + + PropDescImpl* getPropertyImpl(int32_t propId) const + { + PX_ASSERT(propId >= 0); + if(propId < 0) + return NULL; + uint32_t val = uint32_t(propId); + if(val >= mProperties.size()) + { + PX_ASSERT(false); + return NULL; + } + return mProperties[val]; + } + + virtual Option<PropertyDescription> getProperty(int32_t propId) const + { + PropDescImpl* impl(getPropertyImpl(propId)); + if(impl) + return *impl; + return None(); + } + + virtual void setNamedPropertyValues(DataRef<NamedValue> values, int32_t propId) + { + PropDescImpl* impl(getPropertyImpl(propId)); + if(impl) + { + impl->mValueNames.resize(values.size()); + PVD_FOREACH(idx, values.size()) impl->mValueNames[idx] = values[idx]; + } + } + + virtual DataRef<NamedValue> getNamedPropertyValues(int32_t propId) const + { + PropDescImpl* impl(getPropertyImpl(propId)); + if(impl) + { + return toDataRef(impl->mValueNames); + } + return DataRef<NamedValue>(); + } + + virtual uint32_t getNbProperties(int32_t classId) const + { + uint32_t retval = 0; + for(ClassDescImpl* impl(getClassImpl(classId)); impl; impl = getClassImpl(impl->mBaseClass)) + { + retval += impl->mPropImps.size(); + if(impl->mBaseClass < 0) + break; + } + return retval; + } + + // Properties need to be returned in base class order, so this requires a recursive function. + uint32_t getPropertiesImpl(int32_t classId, PropertyDescription*& outBuffer, uint32_t& numItems, + uint32_t& startIdx) const + { + ClassDescImpl* impl = getClassImpl(classId); + if(impl) + { + uint32_t retval = 0; + if(impl->mBaseClass >= 0) + retval = getPropertiesImpl(impl->mBaseClass, outBuffer, numItems, startIdx); + + uint32_t localStart = PxMin(impl->mPropImps.size(), startIdx); + uint32_t localNumItems = PxMin(numItems, impl->mPropImps.size() - localStart); + PVD_FOREACH(idx, localNumItems) + { + outBuffer[idx] = *impl->mPropImps[localStart + idx]; + } + + startIdx -= localStart; + numItems -= localNumItems; + outBuffer += localNumItems; + return retval + localNumItems; + } + return 0; + } + + virtual uint32_t getProperties(int32_t classId, PropertyDescription* outBuffer, uint32_t numItems, + uint32_t startIdx) const + { + return getPropertiesImpl(classId, outBuffer, numItems, startIdx); + } + + virtual MarshalQueryResult checkMarshalling(int32_t srcClsId, int32_t dstClsId) const + { + Option<ClassDescription> propTypeOpt(getClass(dstClsId)); + if(propTypeOpt.hasValue() == false) + { + PX_ASSERT(false); + return MarshalQueryResult(); + } + const ClassDescription& propType(propTypeOpt); + + Option<ClassDescription> incomingTypeOpt(getClass(srcClsId)); + if(incomingTypeOpt.hasValue() == false) + { + PX_ASSERT(false); + return MarshalQueryResult(); + } + const ClassDescription& incomingType(incomingTypeOpt); + // Can only marshal simple things at this point in time. + bool needsMarshalling = false; + bool canMarshal = false; + TSingleMarshaller single = NULL; + TBlockMarshaller block = NULL; + if(incomingType.mClassId != propType.mClassId) + { + // Check that marshalling is even possible. + if((incomingType.mPackedUniformWidth >= 0 && propType.mPackedUniformWidth >= 0) == false) + { + PX_ASSERT(false); + return MarshalQueryResult(); + } + + int32_t srcType = incomingType.mPackedClassType; + int32_t dstType = propType.mPackedClassType; + + int32_t srcWidth = incomingType.mPackedUniformWidth; + int32_t dstWidth = propType.mPackedUniformWidth; + canMarshal = getMarshalOperators(single, block, srcType, dstType); + if(srcWidth == dstWidth) + needsMarshalling = canMarshal; // If the types are the same width, we assume we can convert between some + // of them seamlessly (uint16_t, int16_t) + else + { + needsMarshalling = true; + // If we can't marshall and we have to then we can't set the property value. + // This indicates that the src and dest are different properties and we don't + // know how to convert between them. + if(!canMarshal) + { + PX_ASSERT(false); + return MarshalQueryResult(); + } + } + } + return MarshalQueryResult(srcClsId, dstClsId, canMarshal, needsMarshalling, block); + } + + PropertyMessageDescriptionImpl* findPropertyMessageImpl(const NamespacedName& messageName) const + { + const TNameToPropertyMessageMap::Entry* entry = mPropertyMessageMap.find(messageName); + if(entry) + return entry->second; + return NULL; + } + + PropertyMessageDescriptionImpl* getPropertyMessageImpl(int32_t msg) const + { + int32_t msgCount = int32_t(mPropertyMessages.size()); + if(msg >= 0 && msg < msgCount) + return mPropertyMessages[uint32_t(msg)]; + return NULL; + } + + virtual Option<PropertyMessageDescription> createPropertyMessage(const NamespacedName& clsName, + const NamespacedName& messageName, + DataRef<PropertyMessageArg> entries, + uint32_t messageSize) + { + PropertyMessageDescriptionImpl* existing(findPropertyMessageImpl(messageName)); + if(existing) + { + PX_ASSERT(false); + return None(); + } + ClassDescImpl* cls = findClassImpl(clsName); + PX_ASSERT(cls); + if(!cls) + return None(); + int32_t msgId = int32_t(mPropertyMessages.size()); + PropertyMessageDescriptionImpl* newMessage = PVD_NEW(PropertyMessageDescriptionImpl)( + PropertyMessageDescription(mStringTable->registerName(clsName), cls->mClassId, + mStringTable->registerName(messageName), msgId, messageSize)); + uint32_t calculatedSize = 0; + PVD_FOREACH(idx, entries.size()) + { + PropertyMessageArg entry(entries[idx]); + ClassDescImpl* dtypeCls = findClassImpl(entry.mDatatypeName); + if(dtypeCls == NULL) + { + PX_ASSERT(false); + goto DestroyNewMessage; + } + ClassDescriptionSizeInfo dtypeInfo(dtypeCls->get32BitSizeInfo()); + uint32_t incomingSize = dtypeInfo.mByteSize; + if(entry.mByteSize < incomingSize) + { + PX_ASSERT(false); + goto DestroyNewMessage; + } + + calculatedSize = PxMax(calculatedSize, entry.mMessageOffset + entry.mByteSize); + if(calculatedSize > messageSize) + { + PX_ASSERT(false); + goto DestroyNewMessage; + } + + Option<PropertyDescription> propName(findProperty(cls->mClassId, entry.mPropertyName)); + if(propName.hasValue() == false) + { + PX_ASSERT(false); + goto DestroyNewMessage; + } + + Option<ClassDescription> propCls(getClass(propName.getValue().mDatatype)); + if(propCls.hasValue() == false) + { + PX_ASSERT(false); + goto DestroyNewMessage; + } + + PropertyMessageEntryImpl newEntry(PropertyMessageEntry( + propName, dtypeCls->mName, dtypeCls->mClassId, entry.mMessageOffset, incomingSize, dtypeInfo.mByteSize)); + newMessage->addEntry(newEntry); + + if(newEntry.mDatatypeId == getPvdTypeForType<String>()) + newMessage->mStringOffsetArray.pushBack(entry.mMessageOffset); + + // property messages cannot be marshalled at this time. + if(newEntry.mDatatypeId != getPvdTypeForType<String>() && newEntry.mDatatypeId != getPvdTypeForType<VoidPtr>()) + { + MarshalQueryResult marshalInfo = checkMarshalling(newEntry.mDatatypeId, newEntry.mProperty.mDatatype); + if(marshalInfo.needsMarshalling) + { + PX_ASSERT(false); + goto DestroyNewMessage; + } + } + } + + if(newMessage) + { + newMessage->mStringOffsets = + DataRef<uint32_t>(newMessage->mStringOffsetArray.begin(), newMessage->mStringOffsetArray.end()); + mPropertyMessages.pushBack(newMessage); + mPropertyMessageMap.insert(messageName, newMessage); + return *newMessage; + } + + DestroyNewMessage: + if(newMessage) + PVD_DELETE(newMessage); + + return None(); + } + virtual Option<PropertyMessageDescription> findPropertyMessage(const NamespacedName& msgName) const + { + PropertyMessageDescriptionImpl* desc(findPropertyMessageImpl(msgName)); + if(desc) + return *desc; + return None(); + } + + virtual Option<PropertyMessageDescription> getPropertyMessage(int32_t msgId) const + { + PropertyMessageDescriptionImpl* desc(getPropertyMessageImpl(msgId)); + if(desc) + return *desc; + return None(); + } + + virtual uint32_t getNbPropertyMessages() const + { + return mPropertyMessages.size(); + } + + virtual uint32_t getPropertyMessages(PropertyMessageDescription* msgBuf, uint32_t bufLen, uint32_t startIdx = 0) const + { + startIdx = PxMin(startIdx, getNbPropertyMessages()); + bufLen = PxMin(bufLen, getNbPropertyMessages() - startIdx); + PVD_FOREACH(idx, bufLen) msgBuf[idx] = *mPropertyMessages[idx + startIdx]; + return bufLen; + } + + struct MetaDataWriter + { + const PvdObjectModelMetaDataImpl& mMetaData; + PvdOutputStream& mStream; + MetaDataWriter(const PvdObjectModelMetaDataImpl& meta, PvdOutputStream& stream) + : mMetaData(meta), mStream(stream) + { + } + + void streamify(NamespacedName& type) + { + mStream << mMetaData.mStringTable->strToHandle(type.mNamespace); + mStream << mMetaData.mStringTable->strToHandle(type.mName); + } + void streamify(String& type) + { + mStream << mMetaData.mStringTable->strToHandle(type); + } + void streamify(int32_t& type) + { + mStream << type; + } + void streamify(uint32_t& type) + { + mStream << type; + } + void streamify(uint8_t type) + { + mStream << type; + } + void streamify(bool type) + { + streamify( uint8_t(type)); + } + void streamify(PropertyType::Enum type) + { + uint32_t val = static_cast<uint32_t>(type); + mStream << val; + } + void streamify(NamedValue& type) + { + streamify(type.mValue); + streamify(type.mName); + } + void streamifyLinks(PropDescImpl* prop) + { + streamify(prop->mPropertyId); + } + void streamify(PropertyDescription& prop) + { + streamify(prop.mPropertyId); + } + void streamify(PropertyMessageEntryImpl& prop) + { + prop.serialize(*this); + } + void streamify(PtrOffset& off) + { + uint32_t type = off.mOffsetType; + mStream << type; + mStream << off.mOffset; + } + template <typename TDataType> + void streamify(TDataType* type) + { + int32_t existMarker = type ? 1 : 0; + mStream << existMarker; + if(type) + type->serialize(*this); + } + template <typename TArrayType> + void streamify(const Array<TArrayType>& type) + { + mStream << static_cast<uint32_t>(type.size()); + PVD_FOREACH(idx, type.size()) streamify(const_cast<TArrayType&>(type[idx])); + } + template <typename TArrayType> + void streamifyLinks(const Array<TArrayType>& type) + { + mStream << static_cast<uint32_t>(type.size()); + PVD_FOREACH(idx, type.size()) streamifyLinks(const_cast<TArrayType&>(type[idx])); + } + + private: + MetaDataWriter& operator=(const MetaDataWriter&); + }; + + template <typename TStreamType> + struct MetaDataReader + { + PvdObjectModelMetaDataImpl& mMetaData; + TStreamType& mStream; + MetaDataReader(PvdObjectModelMetaDataImpl& meta, TStreamType& stream) : mMetaData(meta), mStream(stream) + { + } + + void streamify(NamespacedName& type) + { + streamify(type.mNamespace); + streamify(type.mName); + } + + void streamify(String& type) + { + uint32_t handle; + mStream >> handle; + type = mMetaData.mStringTable->handleToStr(handle); + } + void streamify(int32_t& type) + { + mStream >> type; + } + void streamify(uint32_t& type) + { + mStream >> type; + } + void streamify(bool& type) + { + uint8_t data; + mStream >> data; + type = data ? true : false; + } + + void streamify(PropertyType::Enum& type) + { + uint32_t val; + mStream >> val; + type = static_cast<PropertyType::Enum>(val); + } + void streamify(NamedValue& type) + { + streamify(type.mValue); + streamify(type.mName); + } + void streamify(PropertyMessageEntryImpl& type) + { + type.serialize(*this); + } + void streamify(PtrOffset& off) + { + uint32_t type; + mStream >> type; + mStream >> off.mOffset; + off.mOffsetType = static_cast<PtrOffsetType::Enum>(type); + } + void streamifyLinks(PropDescImpl*& prop) + { + int32_t propId; + streamify(propId); + prop = mMetaData.getPropertyImpl(propId); + } + void streamify(PropertyDescription& prop) + { + streamify(prop.mPropertyId); + prop = mMetaData.getProperty(prop.mPropertyId); + } + template <typename TDataType> + void streamify(TDataType*& type) + { + uint32_t existMarker; + mStream >> existMarker; + if(existMarker) + { + TDataType* newType = PVD_NEW(TDataType)(); + newType->serialize(*this); + type = newType; + } + else + type = NULL; + } + template <typename TArrayType> + void streamify(Array<TArrayType>& type) + { + uint32_t typeSize; + mStream >> typeSize; + type.resize(typeSize); + PVD_FOREACH(idx, type.size()) streamify(type[idx]); + } + template <typename TArrayType> + void streamifyLinks(Array<TArrayType>& type) + { + uint32_t typeSize; + mStream >> typeSize; + type.resize(typeSize); + PVD_FOREACH(idx, type.size()) streamifyLinks(type[idx]); + } + + private: + MetaDataReader& operator=(const MetaDataReader&); + }; + + virtual void write(PvdOutputStream& stream) const + { + stream << getCurrentPvdObjectModelVersion(); + stream << mNextClassId; + mStringTable->write(stream); + MetaDataWriter writer(*this, stream); + writer.streamify(mProperties); + writer.streamify(mClasses); + writer.streamify(mPropertyMessages); + } + + template <typename TReaderType> + void read(TReaderType& stream) + { + uint32_t version; + stream >> version; + stream >> mNextClassId; + mStringTable->read(stream); + MetaDataReader<TReaderType> reader(*this, stream); + reader.streamify(mProperties); + reader.streamify(mClasses); + reader.streamify(mPropertyMessages); + + mNameToClasses.clear(); + mNameToProperties.clear(); + mPropertyMessageMap.clear(); + PVD_FOREACH(i, mClasses.size()) + { + ClassDescImpl* cls(mClasses[i]); + if(cls == NULL) + continue; + mNameToClasses.insert(cls->mName, mClasses[i]); + uint32_t propCount = getNbProperties(cls->mClassId); + PropertyDescription descs[16]; + uint32_t offset = 0; + for(uint32_t idx = 0; idx < propCount; idx = offset) + { + uint32_t numProps = getProperties(cls->mClassId, descs, 16, offset); + offset += numProps; + for(uint32_t propIdx = 0; propIdx < numProps; ++propIdx) + { + PropDescImpl* prop = getPropertyImpl(descs[propIdx].mPropertyId); + if(prop) + mNameToProperties.insert(ClassPropertyName(cls->mName, prop->mName), prop); + } + } + } + PVD_FOREACH(idx, mPropertyMessages.size()) + mPropertyMessageMap.insert(mPropertyMessages[idx]->mMessageName, mPropertyMessages[idx]); + } + + virtual PvdObjectModelMetaData& clone() const + { + MemPvdOutputStream tempStream("PvdObjectModelMetaData::clone"); + write(tempStream); + MemPvdInputStream inStream(tempStream); + return create(inStream); + } + + virtual StringTable& getStringTable() const + { + return *mStringTable; + } + virtual void addRef() + { + ++mRefCount; + } + virtual void release() + { + if(mRefCount) + --mRefCount; + if(!mRefCount) + PVD_DELETE(this); + } +}; +} + +uint32_t PvdObjectModelMetaData::getCurrentPvdObjectModelVersion() +{ + return 1; +} + +PvdObjectModelMetaData& PvdObjectModelMetaData::create() +{ + PvdObjectModelMetaDataImpl& retval(*PVD_NEW(PvdObjectModelMetaDataImpl)()); + retval.initialize(); + return retval; +} + +PvdObjectModelMetaData& PvdObjectModelMetaData::create(PvdInputStream& stream) +{ + PvdObjectModelMetaDataImpl& retval(*PVD_NEW(PvdObjectModelMetaDataImpl)()); + retval.read(stream); + return retval; +} + +StringTable& StringTable::create() +{ + return *PVD_NEW(StringTableImpl)(); +} diff --git a/PxShared/src/pvd/src/PxPvdObjectModelMetaData.h b/PxShared/src/pvd/src/PxPvdObjectModelMetaData.h new file mode 100644 index 00000000..7e417aae --- /dev/null +++ b/PxShared/src/pvd/src/PxPvdObjectModelMetaData.h @@ -0,0 +1,495 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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; + + // Check that a property path, starting at the given class id and first property is value. Return the resolved + // properties. + // outbuffer.size *must* equal the propPath.size(). + Option<PropertyDescription> resolvePropertyPath(int32_t clsId, const int32_t propId) const + { + Option<PropertyDescription> prop(getProperty(propId)); + if(prop.hasValue() == false) + return prop; + if(isDerivedFrom(clsId, prop.getValue().mOwnerClassId) == false) + return None(); + return prop; + } + // 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 PvdObjectModelMetaData& clone() const = 0; + + virtual void addRef() = 0; + virtual void release() = 0; + + static uint32_t getCurrentPvdObjectModelVersion(); + static PvdObjectModelMetaData& create(); + static PvdObjectModelMetaData& create(PvdInputStream& stream); +}; +} +} +#endif // PXPVDSDK_PXPVDOBJECTMODELMETADATA_H diff --git a/PxShared/src/pvd/src/PxPvdObjectRegistrar.cpp b/PxShared/src/pvd/src/PxPvdObjectRegistrar.cpp new file mode 100644 index 00000000..b7106c6d --- /dev/null +++ b/PxShared/src/pvd/src/PxPvdObjectRegistrar.cpp @@ -0,0 +1,80 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 diff --git a/PxShared/src/pvd/src/PxPvdObjectRegistrar.h b/PxShared/src/pvd/src/PxPvdObjectRegistrar.h new file mode 100644 index 00000000..e62f5300 --- /dev/null +++ b/PxShared/src/pvd/src/PxPvdObjectRegistrar.h @@ -0,0 +1,71 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 diff --git a/PxShared/src/pvd/src/PxPvdProfileZoneClient.cpp b/PxShared/src/pvd/src/PxPvdProfileZoneClient.cpp new file mode 100644 index 00000000..6d9c83bf --- /dev/null +++ b/PxShared/src/pvd/src/PxPvdProfileZoneClient.cpp @@ -0,0 +1,173 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 "pvd/PxPvdTransport.h" + +#include "PxPvdImpl.h" +#include "PxPvdProfileZoneClient.h" +#include "PxProfileZone.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; +} + +PvdUserRenderer* PvdProfileZoneClient::getUserRender() +{ + PX_ASSERT(0); + return NULL; +} + +void PvdProfileZoneClient::setObjectRegistrar(ObjectRegistrar*) +{ +} + +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; + } + } +} diff --git a/PxShared/src/pvd/src/PxPvdProfileZoneClient.h b/PxShared/src/pvd/src/PxPvdProfileZoneClient.h new file mode 100644 index 00000000..0c6c185d --- /dev/null +++ b/PxShared/src/pvd/src/PxPvdProfileZoneClient.h @@ -0,0 +1,77 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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(); + PvdUserRenderer* getUserRender(); + void setObjectRegistrar(ObjectRegistrar*); + + // 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 diff --git a/PxShared/src/pvd/src/PxPvdUserRenderImpl.h b/PxShared/src/pvd/src/PxPvdUserRenderImpl.h new file mode 100644 index 00000000..63abcf71 --- /dev/null +++ b/PxShared/src/pvd/src/PxPvdUserRenderImpl.h @@ -0,0 +1,411 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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); +} + +class PvdUserRenderHandler +{ + protected: + virtual ~PvdUserRenderHandler() + { + } + + public: +#define DECLARE_PVD_IMMEDIATE_RENDER_TYPE(type) virtual void handleRenderEvent(const type##RenderEvent& evt) = 0; + +#include "PxPvdUserRenderTypes.h" +#undef DECLARE_PVD_IMMEDIATE_RENDER_TYPE +}; + +class PvdUserRenderParser +{ + protected: + virtual ~PvdUserRenderParser() + { + } + + public: + virtual void release() = 0; + virtual void parseData(DataRef<const uint8_t> data, PvdUserRenderHandler& handler) = 0; + + static PvdUserRenderParser& create(bool swapBytes); +}; +} +} + +#endif // PXPVDSDK_PXPVDUSERRENDERIMPL_H diff --git a/PxShared/src/pvd/src/PxPvdUserRenderTypes.h b/PxShared/src/pvd/src/PxPvdUserRenderTypes.h new file mode 100644 index 00000000..0aef215c --- /dev/null +++ b/PxShared/src/pvd/src/PxPvdUserRenderTypes.h @@ -0,0 +1,46 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 diff --git a/PxShared/src/pvd/src/PxPvdUserRenderer.cpp b/PxShared/src/pvd/src/PxPvdUserRenderer.cpp new file mode 100644 index 00000000..02aa6d3f --- /dev/null +++ b/PxShared/src/pvd/src/PxPvdUserRenderer.cpp @@ -0,0 +1,460 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +#include "PxPvdUserRenderer.h" +#include "PxPvdUserRenderImpl.h" +#include "PxPvdFoundation.h" +#include "PxPvdInternalByteStreams.h" +#include "PxPvdBits.h" +#include "PxPvdCommStreamTypes.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 ySwing, float zSwing, bool active) + { + handleEvent(LimitConeRenderEvent(t, ySwing, zSwing, 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&); +}; + +template <bool swapBytes> +struct Parser : public PvdUserRenderParser +{ + ForwardingMemoryBuffer mBuffer; + RenderReader<swapBytes> mReader; + Parser() : mBuffer("PvdUserRenderParser::mBuffer"), mReader(mBuffer) + { + } + + void release() + { + PVD_DELETE(this); + } + void parseData(DataRef<const uint8_t> data, PvdUserRenderHandler& handler) + { + mReader.setData(data); + RenderSerializer& serializer(mReader); + while(serializer.isGood() && serializer.hasData()) + { + mReader.mBuffer.clear(); + PvdUserRenderTypes::Enum evtType = PvdUserRenderTypes::Unknown; + serializer.streamify(evtType); + switch(evtType) + { +#define DECLARE_PVD_IMMEDIATE_RENDER_TYPE(type) \ + case PvdUserRenderTypes::type: \ + { \ + type##RenderEvent evt; \ + evt.serialize(serializer); \ + handler.handleRenderEvent(evt); \ + } \ + break; +#include "PxPvdUserRenderTypes.h" +#undef DECLARE_PVD_IMMEDIATE_RENDER_TYPE + case PvdUserRenderTypes::Unknown: + PX_ASSERT(false); + return; + } + } + PX_ASSERT(serializer.isGood()); + return; + } + + PX_NOCOPY(Parser<swapBytes>) +}; +} + +PvdUserRenderParser& PvdUserRenderParser::create(bool swapBytes) +{ + if(swapBytes) + return *PVD_NEW(Parser<true>); + else + return *PVD_NEW(Parser<false>); +} + +PvdUserRenderer* PvdUserRenderer::create(uint32_t bufferSize) +{ + return PVD_NEW(UserRenderer)(bufferSize); +} + diff --git a/PxShared/src/pvd/src/windows/PxWindowsPvdDelayLoadHook.cpp b/PxShared/src/pvd/src/windows/PxWindowsPvdDelayLoadHook.cpp new file mode 100644 index 00000000..9befe471 --- /dev/null +++ b/PxShared/src/pvd/src/windows/PxWindowsPvdDelayLoadHook.cpp @@ -0,0 +1,82 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 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 "pvd/windows/PxWindowsPvdDelayLoadHook.h" +#include "windows/PsWindowsInclude.h" +#include "windows/PsWindowsLoadLibrary.h" + +// Prior to Visual Studio 2015 Update 3, these hooks were non-const. +#define DELAYIMP_INSECURE_WRITABLE_HOOKS +#include <delayimp.h> + +static const physx::PxFoundationDelayLoadHook* gDelayLoadHook = NULL; + +void physx::PxPvdSetFoundationDelayLoadHook(const physx::PxFoundationDelayLoadHook* hook) +{ + gDelayLoadHook = hook; +} + +using namespace physx; + +#pragma comment(lib, "delayimp") + +FARPROC WINAPI delayHook(unsigned dliNotify, PDelayLoadInfo pdli) +{ + switch (dliNotify) { + case dliStartProcessing : + break; + + case dliNotePreLoadLibrary : + { + return physx::shdfnd::foundationDliNotePreLoadLibrary(pdli->szDll, gDelayLoadHook); + } + break; + + case dliNotePreGetProcAddress : + break; + + case dliFailLoadLib : + break; + + case dliFailGetProc : + break; + + case dliNoteEndProcessing : + break; + + default : + + return NULL; + } + + return NULL; +} + +PfnDliHook __pfnDliNotifyHook2 = delayHook; |