aboutsummaryrefslogtreecommitdiff
path: root/PxShared/src/pvd
diff options
context:
space:
mode:
authorgit perforce import user <a@b>2016-10-25 12:29:14 -0600
committerSheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees>2016-10-25 18:56:37 -0500
commit3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch)
treefa6485c169e50d7415a651bf838f5bcd0fd3bfbd /PxShared/src/pvd
downloadphysx-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')
-rw-r--r--PxShared/src/pvd/include/PsPvd.h85
-rw-r--r--PxShared/src/pvd/include/PxProfileAllocatorWrapper.h231
-rw-r--r--PxShared/src/pvd/include/PxPvdClient.h77
-rw-r--r--PxShared/src/pvd/include/PxPvdDataStream.h272
-rw-r--r--PxShared/src/pvd/include/PxPvdDataStreamHelpers.h120
-rw-r--r--PxShared/src/pvd/include/PxPvdErrorCodes.h62
-rw-r--r--PxShared/src/pvd/include/PxPvdObjectModelBaseTypes.h428
-rw-r--r--PxShared/src/pvd/include/PxPvdRenderBuffer.h140
-rw-r--r--PxShared/src/pvd/include/PxPvdUserRenderer.h107
-rw-r--r--PxShared/src/pvd/src/PxProfileBase.h35
-rw-r--r--PxShared/src/pvd/src/PxProfileCompileTimeEventFilter.h75
-rw-r--r--PxShared/src/pvd/src/PxProfileContextProvider.h98
-rw-r--r--PxShared/src/pvd/src/PxProfileContextProviderImpl.h52
-rw-r--r--PxShared/src/pvd/src/PxProfileDataBuffer.h167
-rw-r--r--PxShared/src/pvd/src/PxProfileDataParsing.h218
-rw-r--r--PxShared/src/pvd/src/PxProfileEventBuffer.h270
-rw-r--r--PxShared/src/pvd/src/PxProfileEventBufferAtomic.h320
-rw-r--r--PxShared/src/pvd/src/PxProfileEventBufferClient.h81
-rw-r--r--PxShared/src/pvd/src/PxProfileEventBufferClientManager.h94
-rw-r--r--PxShared/src/pvd/src/PxProfileEventFilter.h93
-rw-r--r--PxShared/src/pvd/src/PxProfileEventHandler.h99
-rw-r--r--PxShared/src/pvd/src/PxProfileEventId.h80
-rw-r--r--PxShared/src/pvd/src/PxProfileEventImpl.cpp230
-rw-r--r--PxShared/src/pvd/src/PxProfileEventMutex.h63
-rw-r--r--PxShared/src/pvd/src/PxProfileEventNames.h90
-rw-r--r--PxShared/src/pvd/src/PxProfileEventParser.h193
-rw-r--r--PxShared/src/pvd/src/PxProfileEventSender.h129
-rw-r--r--PxShared/src/pvd/src/PxProfileEventSerialization.h258
-rw-r--r--PxShared/src/pvd/src/PxProfileEventSystem.h56
-rw-r--r--PxShared/src/pvd/src/PxProfileEvents.h706
-rw-r--r--PxShared/src/pvd/src/PxProfileMemory.h99
-rw-r--r--PxShared/src/pvd/src/PxProfileMemoryBuffer.h192
-rw-r--r--PxShared/src/pvd/src/PxProfileMemoryEventBuffer.h156
-rw-r--r--PxShared/src/pvd/src/PxProfileMemoryEventParser.h185
-rw-r--r--PxShared/src/pvd/src/PxProfileMemoryEventRecorder.h147
-rw-r--r--PxShared/src/pvd/src/PxProfileMemoryEventReflexiveWriter.h71
-rw-r--r--PxShared/src/pvd/src/PxProfileMemoryEventSummarizer.h304
-rw-r--r--PxShared/src/pvd/src/PxProfileMemoryEventTypes.h90
-rw-r--r--PxShared/src/pvd/src/PxProfileMemoryEvents.h411
-rw-r--r--PxShared/src/pvd/src/PxProfileScopedEvent.h150
-rw-r--r--PxShared/src/pvd/src/PxProfileScopedMutexLock.h64
-rw-r--r--PxShared/src/pvd/src/PxProfileZone.h142
-rw-r--r--PxShared/src/pvd/src/PxProfileZoneImpl.h318
-rw-r--r--PxShared/src/pvd/src/PxProfileZoneManager.h155
-rw-r--r--PxShared/src/pvd/src/PxProfileZoneManagerImpl.h174
-rw-r--r--PxShared/src/pvd/src/PxPvd.cpp56
-rw-r--r--PxShared/src/pvd/src/PxPvdBits.h173
-rw-r--r--PxShared/src/pvd/src/PxPvdByteStreams.h155
-rw-r--r--PxShared/src/pvd/src/PxPvdCommStreamEventSink.h55
-rw-r--r--PxShared/src/pvd/src/PxPvdCommStreamEvents.h986
-rw-r--r--PxShared/src/pvd/src/PxPvdCommStreamSDKEventTypes.h32
-rw-r--r--PxShared/src/pvd/src/PxPvdCommStreamTypes.h262
-rw-r--r--PxShared/src/pvd/src/PxPvdDataStream.cpp869
-rw-r--r--PxShared/src/pvd/src/PxPvdDefaultFileTransport.cpp123
-rw-r--r--PxShared/src/pvd/src/PxPvdDefaultFileTransport.h77
-rw-r--r--PxShared/src/pvd/src/PxPvdDefaultSocketTransport.cpp136
-rw-r--r--PxShared/src/pvd/src/PxPvdDefaultSocketTransport.h79
-rw-r--r--PxShared/src/pvd/src/PxPvdFoundation.h504
-rw-r--r--PxShared/src/pvd/src/PxPvdImpl.cpp405
-rw-r--r--PxShared/src/pvd/src/PxPvdImpl.h221
-rw-r--r--PxShared/src/pvd/src/PxPvdInternalByteStreams.h147
-rw-r--r--PxShared/src/pvd/src/PxPvdMarshalling.h220
-rw-r--r--PxShared/src/pvd/src/PxPvdMemClient.cpp134
-rw-r--r--PxShared/src/pvd/src/PxPvdMemClient.h85
-rw-r--r--PxShared/src/pvd/src/PxPvdObjectModel.h437
-rw-r--r--PxShared/src/pvd/src/PxPvdObjectModelInternalTypeDefs.h32
-rw-r--r--PxShared/src/pvd/src/PxPvdObjectModelInternalTypes.h169
-rw-r--r--PxShared/src/pvd/src/PxPvdObjectModelMetaData.cpp1515
-rw-r--r--PxShared/src/pvd/src/PxPvdObjectModelMetaData.h495
-rw-r--r--PxShared/src/pvd/src/PxPvdObjectRegistrar.cpp80
-rw-r--r--PxShared/src/pvd/src/PxPvdObjectRegistrar.h71
-rw-r--r--PxShared/src/pvd/src/PxPvdProfileZoneClient.cpp173
-rw-r--r--PxShared/src/pvd/src/PxPvdProfileZoneClient.h77
-rw-r--r--PxShared/src/pvd/src/PxPvdUserRenderImpl.h411
-rw-r--r--PxShared/src/pvd/src/PxPvdUserRenderTypes.h46
-rw-r--r--PxShared/src/pvd/src/PxPvdUserRenderer.cpp460
-rw-r--r--PxShared/src/pvd/src/windows/PxWindowsPvdDelayLoadHook.cpp82
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;