400 lines
9.7 KiB
C++
400 lines
9.7 KiB
C++
//
|
|
// Redistribution and use in source and binary forms, with or without
|
|
// modification, are permitted provided that the following conditions
|
|
// are met:
|
|
// * Redistributions of source code must retain the above copyright
|
|
// notice, this list of conditions and the following disclaimer.
|
|
// * Redistributions in binary form must reproduce the above copyright
|
|
// notice, this list of conditions and the following disclaimer in the
|
|
// documentation and/or other materials provided with the distribution.
|
|
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
|
// contributors may be used to endorse or promote products derived
|
|
// from this software without specific prior written permission.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
|
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
|
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
//
|
|
// Copyright (c) 2008-2019 NVIDIA Corporation. All rights reserved.
|
|
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
|
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
|
|
|
#include "PxPvdImpl.h"
|
|
#include "PxPvdMemClient.h"
|
|
#include "PxPvdProfileZoneClient.h"
|
|
#include "PxPvdProfileZone.h"
|
|
|
|
#include "PsFoundation.h"
|
|
|
|
#if PX_NVTX
|
|
#include "nvToolsExt.h"
|
|
#endif
|
|
|
|
namespace
|
|
{
|
|
const char* gSdkName = "PhysXSDK";
|
|
}
|
|
|
|
namespace physx
|
|
{
|
|
namespace pvdsdk
|
|
{
|
|
|
|
class CmEventNameProvider : public physx::profile::PxProfileNameProvider
|
|
{
|
|
public:
|
|
physx::profile::PxProfileNames getProfileNames() const
|
|
{
|
|
physx::profile::PxProfileNames ret;
|
|
ret.eventCount = 0;
|
|
return ret;
|
|
}
|
|
};
|
|
|
|
CmEventNameProvider gProfileNameProvider;
|
|
|
|
void initializeModelTypes(PvdDataStream& stream)
|
|
{
|
|
stream.createClass<profile::PxProfileZone>();
|
|
stream.createProperty<profile::PxProfileZone, uint8_t>(
|
|
"events", PvdCommStreamEmbeddedTypes::getProfileEventStreamSemantic(), PropertyType::Array);
|
|
|
|
stream.createClass<profile::PxProfileMemoryEventBuffer>();
|
|
stream.createProperty<profile::PxProfileMemoryEventBuffer, uint8_t>(
|
|
"events", PvdCommStreamEmbeddedTypes::getMemoryEventStreamSemantic(), PropertyType::Array);
|
|
|
|
stream.createClass<PvdUserRenderer>();
|
|
stream.createProperty<PvdUserRenderer, uint8_t>(
|
|
"events", PvdCommStreamEmbeddedTypes::getRendererEventStreamSemantic(), PropertyType::Array);
|
|
}
|
|
|
|
PvdImpl* PvdImpl::sInstance = NULL;
|
|
uint32_t PvdImpl::sRefCount = 0;
|
|
|
|
PvdImpl::PvdImpl()
|
|
: mPvdTransport(NULL)
|
|
, mSharedMetaProvider(NULL)
|
|
, mMemClient(NULL)
|
|
, mIsConnected(false)
|
|
, mIsNVTXSupportEnabled(true)
|
|
, mNVTXContext(0)
|
|
, mNextStreamId(1)
|
|
, mProfileClient(NULL)
|
|
, mProfileZone(NULL)
|
|
{
|
|
mProfileZoneManager = &physx::profile::PxProfileZoneManager::createProfileZoneManager(&physx::shdfnd::getAllocator());
|
|
mProfileClient = PVD_NEW(PvdProfileZoneClient)(*this);
|
|
}
|
|
|
|
PvdImpl::~PvdImpl()
|
|
{
|
|
if((mFlags & PxPvdInstrumentationFlag::ePROFILE) )
|
|
{
|
|
PxSetProfilerCallback(NULL);
|
|
}
|
|
|
|
disconnect();
|
|
|
|
if ( mProfileZoneManager )
|
|
{
|
|
mProfileZoneManager->release();
|
|
mProfileZoneManager = NULL;
|
|
}
|
|
|
|
PVD_DELETE(mProfileClient);
|
|
mProfileClient = NULL;
|
|
}
|
|
|
|
bool PvdImpl::connect(PxPvdTransport& transport, PxPvdInstrumentationFlags flags)
|
|
{
|
|
if(mIsConnected)
|
|
{
|
|
physx::shdfnd::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "PxPvd::connect - recall connect! Should call disconnect before re-connect.");
|
|
return false;
|
|
}
|
|
|
|
mFlags = flags;
|
|
mPvdTransport = &transport;
|
|
|
|
mIsConnected = mPvdTransport->connect();
|
|
|
|
if(mIsConnected)
|
|
{
|
|
mSharedMetaProvider = PVD_NEW(MetaDataProvider);
|
|
sendTransportInitialization();
|
|
|
|
PvdDataStream* stream = PvdDataStream::create(this);
|
|
initializeModelTypes(*stream);
|
|
stream->release();
|
|
|
|
if(mFlags & PxPvdInstrumentationFlag::eMEMORY)
|
|
{
|
|
mMemClient = PVD_NEW(PvdMemClient)(*this);
|
|
mPvdClients.pushBack(mMemClient);
|
|
}
|
|
|
|
if((mFlags & PxPvdInstrumentationFlag::ePROFILE) && mProfileZoneManager)
|
|
{
|
|
mPvdClients.pushBack(mProfileClient);
|
|
mProfileZone = &physx::profile::PxProfileZone::createProfileZone(&physx::shdfnd::getAllocator(),gSdkName,gProfileNameProvider.getProfileNames());
|
|
}
|
|
|
|
for(uint32_t i = 0; i < mPvdClients.size(); i++)
|
|
mPvdClients[i]->onPvdConnected();
|
|
|
|
if (mProfileZone)
|
|
{
|
|
mProfileZoneManager->addProfileZoneHandler(*mProfileClient);
|
|
mProfileZoneManager->addProfileZone( *mProfileZone );
|
|
}
|
|
|
|
if ((mFlags & PxPvdInstrumentationFlag::ePROFILE))
|
|
{
|
|
PxSetProfilerCallback(this);
|
|
}
|
|
}
|
|
return mIsConnected;
|
|
}
|
|
|
|
void PvdImpl::disconnect()
|
|
{
|
|
if(mProfileZone)
|
|
{
|
|
mProfileZoneManager->removeProfileZoneHandler(*mProfileClient);
|
|
mProfileZoneManager->removeProfileZone( *mProfileZone );
|
|
mProfileZone->release();
|
|
mProfileZone=NULL;
|
|
removeClient(mProfileClient);
|
|
}
|
|
|
|
if(mIsConnected)
|
|
{
|
|
for(uint32_t i = 0; i < mPvdClients.size(); i++)
|
|
mPvdClients[i]->onPvdDisconnected();
|
|
|
|
if(mMemClient)
|
|
{
|
|
removeClient(mMemClient);
|
|
PvdMemClient* tmp = mMemClient; //avoid tracking deallocation itsself
|
|
mMemClient = NULL;
|
|
PVD_DELETE(tmp);
|
|
}
|
|
|
|
mSharedMetaProvider->release();
|
|
mPvdTransport->disconnect();
|
|
mObjectRegistrar.clear();
|
|
mIsConnected = false;
|
|
}
|
|
}
|
|
|
|
void PvdImpl::flush()
|
|
{
|
|
for(uint32_t i = 0; i < mPvdClients.size(); i++)
|
|
mPvdClients[i]->flush();
|
|
if ( mProfileZone )
|
|
{
|
|
mProfileZone->flushEventIdNameMap();
|
|
mProfileZone->flushProfileEvents();
|
|
}
|
|
}
|
|
|
|
bool PvdImpl::isConnected(bool useCachedStatus)
|
|
{
|
|
if(mPvdTransport)
|
|
return useCachedStatus ? mIsConnected : mPvdTransport->isConnected();
|
|
else
|
|
return false;
|
|
}
|
|
|
|
PxPvdTransport* PvdImpl::getTransport()
|
|
{
|
|
return mPvdTransport;
|
|
}
|
|
|
|
PxPvdInstrumentationFlags PvdImpl::getInstrumentationFlags()
|
|
{
|
|
return mFlags;
|
|
}
|
|
|
|
void PvdImpl::sendTransportInitialization()
|
|
{
|
|
StreamInitialization init;
|
|
EventStreamifier<PxPvdTransport> stream(mPvdTransport->lock());
|
|
init.serialize(stream);
|
|
mPvdTransport->unlock();
|
|
}
|
|
|
|
void PvdImpl::addClient(PvdClient* client)
|
|
{
|
|
PX_ASSERT(client);
|
|
for(uint32_t i = 0; i < mPvdClients.size(); i++)
|
|
{
|
|
if(client == mPvdClients[i])
|
|
return;
|
|
}
|
|
mPvdClients.pushBack(client);
|
|
if(mIsConnected)
|
|
{
|
|
client->onPvdConnected();
|
|
}
|
|
}
|
|
|
|
void PvdImpl::removeClient(PvdClient* client)
|
|
{
|
|
for(uint32_t i = 0; i < mPvdClients.size(); i++)
|
|
{
|
|
if(client == mPvdClients[i])
|
|
{
|
|
client->onPvdDisconnected();
|
|
mPvdClients.remove(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
void PvdImpl::onAllocation(size_t inSize, const char* inType, const char* inFile, int inLine, void* inAddr)
|
|
{
|
|
if(mMemClient)
|
|
mMemClient->onAllocation(inSize, inType, inFile, inLine, inAddr);
|
|
}
|
|
|
|
void PvdImpl::onDeallocation(void* inAddr)
|
|
{
|
|
if(mMemClient)
|
|
mMemClient->onDeallocation(inAddr);
|
|
}
|
|
|
|
PvdOMMetaDataProvider& PvdImpl::getMetaDataProvider()
|
|
{
|
|
return *mSharedMetaProvider;
|
|
}
|
|
|
|
bool PvdImpl::registerObject(const void* inItem)
|
|
{
|
|
return mObjectRegistrar.addItem(inItem);
|
|
}
|
|
|
|
|
|
bool PvdImpl::unRegisterObject(const void* inItem)
|
|
{
|
|
return mObjectRegistrar.decItem(inItem);
|
|
}
|
|
|
|
uint64_t PvdImpl::getNextStreamId()
|
|
{
|
|
uint64_t retval = ++mNextStreamId;
|
|
return retval;
|
|
}
|
|
|
|
bool PvdImpl::initialize()
|
|
{
|
|
if(0 == sRefCount)
|
|
{
|
|
sInstance = PVD_NEW(PvdImpl)();
|
|
}
|
|
++sRefCount;
|
|
return !!sInstance;
|
|
}
|
|
|
|
void PvdImpl::release()
|
|
{
|
|
if(sRefCount > 0)
|
|
{
|
|
if(--sRefCount)
|
|
return;
|
|
|
|
PVD_DELETE(sInstance);
|
|
sInstance = NULL;
|
|
}
|
|
}
|
|
|
|
PvdImpl* PvdImpl::getInstance()
|
|
{
|
|
return sInstance;
|
|
}
|
|
|
|
|
|
/**************************************************************************************************************************
|
|
Instrumented profiling events
|
|
***************************************************************************************************************************/
|
|
|
|
static const uint32_t CrossThreadId = 99999789;
|
|
|
|
void* PvdImpl::zoneStart(const char* eventName, bool detached, uint64_t contextId)
|
|
{
|
|
if(mProfileZone)
|
|
{
|
|
const uint16_t id = mProfileZone->getEventIdForName(eventName);
|
|
if(detached)
|
|
mProfileZone->startEvent(id, contextId, CrossThreadId);
|
|
else
|
|
mProfileZone->startEvent(id, contextId);
|
|
}
|
|
#if PX_NVTX
|
|
if(mIsNVTXSupportEnabled)
|
|
{
|
|
if(detached)
|
|
{
|
|
// TODO : Need to use the nvtxRangeStart API for cross thread events
|
|
nvtxEventAttributes_t eventAttrib;
|
|
memset(&eventAttrib, 0, sizeof(eventAttrib));
|
|
eventAttrib.version = NVTX_VERSION;
|
|
eventAttrib.size = NVTX_EVENT_ATTRIB_STRUCT_SIZE;
|
|
eventAttrib.colorType = NVTX_COLOR_ARGB;
|
|
eventAttrib.color = 0xFF00FF00;
|
|
eventAttrib.messageType = NVTX_MESSAGE_TYPE_ASCII;
|
|
eventAttrib.message.ascii = eventName;
|
|
nvtxMarkEx(&eventAttrib);
|
|
}
|
|
else
|
|
{
|
|
nvtxRangePush(eventName);
|
|
}
|
|
}
|
|
#endif
|
|
return NULL;
|
|
}
|
|
|
|
void PvdImpl::zoneEnd(void* /*profilerData*/, const char* eventName, bool detached, uint64_t contextId)
|
|
{
|
|
if(mProfileZone)
|
|
{
|
|
const uint16_t id = mProfileZone->getEventIdForName(eventName);
|
|
if(detached)
|
|
mProfileZone->stopEvent(id, contextId, CrossThreadId);
|
|
else
|
|
mProfileZone->stopEvent(id, contextId);
|
|
}
|
|
#if PX_NVTX
|
|
if(mIsNVTXSupportEnabled)
|
|
{
|
|
if(detached)
|
|
{
|
|
nvtxEventAttributes_t eventAttrib;
|
|
memset(&eventAttrib, 0, sizeof(eventAttrib));
|
|
eventAttrib.version = NVTX_VERSION;
|
|
eventAttrib.size = NVTX_EVENT_ATTRIB_STRUCT_SIZE;
|
|
eventAttrib.colorType = NVTX_COLOR_ARGB;
|
|
eventAttrib.color = 0xFFFF0000;
|
|
eventAttrib.messageType = NVTX_MESSAGE_TYPE_ASCII;
|
|
eventAttrib.message.ascii = eventName;
|
|
nvtxMarkEx(&eventAttrib);
|
|
}
|
|
else
|
|
{
|
|
nvtxRangePop();
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
} // pvd
|
|
|
|
} // physx
|