You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Code/Tools/Standalone/Source/Driller/DrillerDataContainer.cpp

290 lines
11 KiB
C++

/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "StandaloneTools_precompiled.h"
#include "DrillerDataContainer.h"
#include <AzCore/Driller/Stream.h>
#include <AzCore/Driller/DrillerRootHandler.h>
#include <AzCore/Driller/DefaultStringPool.h>
#include <AzCore/IO/SystemFile.h> // temp for DebugHackProcessFile
#include <AzCore/XML/rapidxml_print.h> // metadata is stored this way
#include "Unsupported/UnsupportedDataAggregator.hxx"
#include "Memory/MemoryDataAggregator.hxx"
#include "Trace/TraceMessageDataAggregator.hxx"
#include "Profiler/ProfilerDataAggregator.hxx"
#include "Carrier/CarrierDataAggregator.hxx"
#include "Replica/ReplicaDataAggregator.hxx"
#include "Rendering/VRAM/VRAMDataAggregator.hxx"
#include "EventTrace/EventTraceDataAggregator.h"
// IMPORTANT: include new aggregators above
namespace Driller
{
class DrillerDataHandler : public AZ::Debug::DrillerHandlerParser
{
public:
AZ_CLASS_ALLOCATOR(DrillerDataHandler,AZ::SystemAllocator,0)
DrillerDataHandler(int identity, DrillerDataContainer* container)
: AZ::Debug::DrillerHandlerParser(/*true*/false)
, m_identity(identity)
, m_currentFrame(-1)
, m_dataContainer(container)
, m_dataParser(nullptr)
{
m_drillerSessionInfo.m_platform = static_cast<int>(AZ::g_currentPlatform); /// Init with current platform so no endian swapping till we read all the initial settings.
m_inputStream.SetStringPool(&m_stringPool);
m_dataParser = aznew AZ::Debug::DrillerSAXParserHandler(this);
}
~DrillerDataHandler()
{
delete m_dataParser;
}
virtual AZ::Debug::DrillerHandlerParser* OnEnterTag(AZ::u32 tagName)
{
if( tagName == AZ_CRC("StartData", 0xecf3f53f) )
return &m_drillerSessionInfo;
if( tagName == AZ_CRC("Frame", 0xb5f83ccd) )
return this;
for(DrillerNetworkMessages::AggregatorList::iterator it = m_dataContainer->m_aggregators.begin(); it != m_dataContainer->m_aggregators.end(); ++it)
{
if( (*it)->GetDrillerId() == tagName )
return (*it)->GetDrillerDataParser();
}
AZ_TracePrintf("Driller", "We should never get here as we should have added 'Unsupported driller(s)' in OnExitTag('StartData')");
return nullptr;
}
virtual void OnExitTag(DrillerHandlerParser* handler, AZ::u32 tagName)
{
(void)handler;
if( tagName == AZ_CRC("StartData", 0xecf3f53f) )
{
// create all drillers that were in the session data
for(AZ::Debug::DrillerManager::DrillerListType::iterator itDriller = m_drillerSessionInfo.m_drillers.begin(); itDriller != m_drillerSessionInfo.m_drillers.end(); ++itDriller )
{
AZ::u32 drillerId = itDriller->id;
bool isCreated = false;
for(DrillerNetworkMessages::AggregatorList::iterator it = m_dataContainer->m_aggregators.begin(); it != m_dataContainer->m_aggregators.end(); ++it)
{
if( (*it)->GetDrillerId() == drillerId )
{
isCreated = true;
break;
}
}
if( !isCreated )
{
// Create the aggregator, if the driller is missing add UnsupportedAggregator
Aggregator* aggr = m_dataContainer->CreateAggregator(drillerId, true);
if( aggr )
m_dataContainer->m_aggregators.push_back(aggr);
// two ways to add aggregators:
// 1) "NewAggregatorList" send an entire list which replaces the current setup, which is most efficient
// 2) "AddAggregator" send a single aggregator which gets appended
EBUS_EVENT_ID(m_identity, DrillerNetworkMessages::Bus,AddAggregator, *m_dataContainer->m_aggregators.back());
}
}
}
}
virtual void OnData(const AZ::Debug::DrillerSAXParser::Data& dataNode)
{
if( dataNode.m_name == AZ_CRC("FrameNum", 0x85a1a919) )
{
// Send event that previous frame has finished
if( m_currentFrame != -1 )
{
EBUS_EVENT_ID(m_identity, DrillerNetworkMessages::Bus,EndFrame, m_currentFrame);
}
dataNode.Read(m_currentFrame);
for(DrillerNetworkMessages::AggregatorList::iterator it = m_dataContainer->m_aggregators.begin(); it != m_dataContainer->m_aggregators.end(); ++it)
{
(*it)->AddNewFrame();
}
}
}
void ProcessStream(const char* streamIdentifier, const void* data, unsigned int dataSize)
{
m_inputStream.SetData(streamIdentifier, data, dataSize);
m_dataParser->ProcessStream(m_inputStream);
}
AZ::Debug::DrillerStartdataHandler m_drillerSessionInfo;
int m_currentFrame;
DrillerDataContainer* m_dataContainer;
AZ::Debug::DrillerSAXParserHandler* m_dataParser;
AZ::Debug::DrillerInputMemoryStream m_inputStream;
AZ::Debug::DrillerDefaultStringPool m_stringPool;
int m_identity;
};
DrillerDataContainer::DrillerDataContainer(int identity, const char* tmpCaptureFilename)
: m_dataHandler(nullptr)
, m_identity(identity)
, m_tmpCaptureFilename(tmpCaptureFilename)
{
AzFramework::DrillerNetworkConsoleEventBus::Handler::BusConnect();
EBUS_EVENT(AzFramework::DrillerNetworkConsoleCommandBus, EnumerateAvailableDrillers);
}
DrillerDataContainer::~DrillerDataContainer()
{
AzFramework::DrillerNetworkConsoleEventBus::Handler::BusDisconnect();
DestroyAggregators();
delete m_dataHandler;
}
void DrillerDataContainer::OnReceivedDrillerEnumeration(const AzFramework::DrillerInfoListType& availableDrillers)
{
// TODO: Decide how the available driller list should influence the behavior of the driller
// display. For now we will display whatever is available.
m_availableDrillers = availableDrillers;
EBUS_EVENT_ID(m_identity, DrillerNetworkMessages::Bus, NewAggregatorsAvailable);
}
void DrillerDataContainer::CreateAggregators()
{
DestroyAggregators();
if (m_availableDrillers.size())
{
for (size_t i = 0; i < m_availableDrillers.size(); ++i)
{
Aggregator* aggr = CreateAggregator(m_availableDrillers[i].m_id, true);
if( aggr )
m_aggregators.push_back(aggr);
}
}
EBUS_EVENT_ID(m_identity, DrillerNetworkMessages::Bus, NewAggregatorList,m_aggregators);
}
void DrillerDataContainer::DestroyAggregators()
{
EBUS_EVENT_ID(m_identity, DrillerNetworkMessages::Bus, DiscardAggregators);
for(DrillerNetworkMessages::AggregatorList::iterator it = m_aggregators.begin(); it != m_aggregators.end(); ++it )
delete *it;
m_aggregators.clear();
}
Aggregator* DrillerDataContainer::CreateAggregator(AZ::u32 id, bool createUnsupported)
{
if( id == MemoryDataAggregator::DrillerId() )
{
return aznew MemoryDataAggregator(m_identity);
}
else if( id == TraceMessageDataAggregator::DrillerId() )
{
return aznew TraceMessageDataAggregator(m_identity);
}
else if (id == ProfilerDataAggregator::DrillerId() )
{
return aznew ProfilerDataAggregator(m_identity);
}
else if(id == CarrierDataAggregator::DrillerId())
{
return aznew CarrierDataAggregator(m_identity);
}
else if(id == ReplicaDataAggregator::DrillerId())
{
return aznew ReplicaDataAggregator(m_identity);
}
else if(id == VRAM::VRAMDataAggregator::DrillerId())
{
return aznew VRAM::VRAMDataAggregator(m_identity);
}
else if (id == EventTraceDataAggregator::DrillerId())
{
return aznew EventTraceDataAggregator(m_identity);
}
// IMPORTANT: Add new aggregators here
return createUnsupported ? aznew UnsupportedDataAggregator(id) : nullptr;
}
void DrillerDataContainer::ProcessIncomingDrillerData(const char* streamIdentifier, const void* data, size_t dataSize)
{
AZ_Assert(m_dataHandler,"You must have a valid data handler parser to parse the data!");
m_dataHandler->ProcessStream(streamIdentifier, data, static_cast<unsigned int>(dataSize));
}
void DrillerDataContainer::OnDrillerConnectionLost()
{
StopDrilling();
}
void DrillerDataContainer::StartDrilling()
{
DrillerEvent::ResetGlobalEventId();
AzFramework::DrillerListType drillersToStart;
for(DrillerNetworkMessages::AggregatorList::iterator it = m_aggregators.begin(); it != m_aggregators.end(); ++it)
{
(*it)->Reset();
if ((*it)->IsCaptureEnabled())
{
drillersToStart.push_back((*it)->GetDrillerId());
}
}
if (drillersToStart.size())
{
delete m_dataHandler;
m_dataHandler = aznew DrillerDataHandler(m_identity, this);
AzFramework::DrillerRemoteSession::StartDrilling(drillersToStart, m_tmpCaptureFilename.c_str());
}
}
void DrillerDataContainer::LoadCaptureData(const char* fileName)
{
DrillerEvent::ResetGlobalEventId();
// Reset data
DestroyAggregators();
AZStd::string baseFilename( fileName );
delete m_dataHandler;
m_dataHandler = aznew DrillerDataHandler(m_identity, this);
AzFramework::DrillerRemoteSession::LoadCaptureData(fileName);
}
void DrillerDataContainer::CloseCaptureData()
{
StopDrilling();
DestroyAggregators();
}
void DrillerDataContainer::Reflect(AZ::ReflectContext* context)
{
MemoryDataAggregator::Reflect(context);
TraceMessageDataAggregator::Reflect(context);
ProfilerDataAggregator::Reflect(context);
ReplicaDataAggregator::Reflect(context);
}
}//namespace Driller