Integrating latest from github/staging
Integrating up through commit 5e1bdae
This commit is contained in:
@@ -1,630 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#include "CrySystem_precompiled.h"
|
||||
|
||||
#if defined(ENABLE_LOADING_PROFILER)
|
||||
|
||||
#include "BootProfiler.h"
|
||||
#include "ThreadInfo.h"
|
||||
#include <stack>
|
||||
#include <AzFramework/IO/FileOperations.h>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
StaticInstance<CBootProfiler, AZStd::no_destruct<CBootProfiler>> gProfilerInstance;
|
||||
enum
|
||||
{
|
||||
eMAX_THREADS_TO_PROFILE = 128,
|
||||
eNUM_RECORDS_PER_POOL = 2048, // so, eNUM_RECORDS_PER_POOL * sizeof(CBootProfilerRecord) == mem consumed by pool item
|
||||
// sizeof(CProfileBlockTimes)==152,
|
||||
// poolmem = 304Kb for 1 pool per thread
|
||||
};
|
||||
}
|
||||
|
||||
int CBootProfiler::CV_sys_bp_frames = 0;
|
||||
float CBootProfiler::CV_sys_bp_time_threshold = 0;
|
||||
|
||||
class CProfileBlockTimes
|
||||
{
|
||||
protected:
|
||||
LARGE_INTEGER m_startTimeStamp;
|
||||
LARGE_INTEGER m_stopTimeStamp;
|
||||
LARGE_INTEGER m_freq;
|
||||
CProfileBlockTimes()
|
||||
{
|
||||
memset(&m_startTimeStamp, 0, sizeof(m_startTimeStamp));
|
||||
memset(&m_stopTimeStamp, 0, sizeof(m_stopTimeStamp));
|
||||
memset(&m_freq, 0, sizeof(m_freq));
|
||||
}
|
||||
};
|
||||
|
||||
class CBootProfilerRecord
|
||||
{
|
||||
public:
|
||||
const char* m_label;
|
||||
LARGE_INTEGER m_startTimeStamp;
|
||||
LARGE_INTEGER m_stopTimeStamp;
|
||||
LARGE_INTEGER m_freq;
|
||||
|
||||
CBootProfilerRecord* m_pParent;
|
||||
typedef AZStd::vector<CBootProfilerRecord*> ChildVector;
|
||||
ChildVector m_Childs;
|
||||
|
||||
CryFixedStringT<256> m_args;
|
||||
|
||||
ILINE CBootProfilerRecord(const char* label, LARGE_INTEGER timestamp, LARGE_INTEGER freq, const char* args)
|
||||
: m_label(label)
|
||||
, m_startTimeStamp(timestamp)
|
||||
, m_freq(freq)
|
||||
, m_pParent(NULL)
|
||||
{
|
||||
memset(&m_stopTimeStamp, 0, sizeof(m_stopTimeStamp));
|
||||
if (args)
|
||||
{
|
||||
m_args = args;
|
||||
}
|
||||
}
|
||||
|
||||
ILINE ~CBootProfilerRecord()
|
||||
{
|
||||
// childs are allocated via pool as well, the destructors of each child
|
||||
// is called explicitly, for the purpose of freeing memory occupied by
|
||||
// m_Child vector. Otherwise there will be a memory leak.
|
||||
ChildVector::iterator it = m_Childs.begin();
|
||||
while (it != m_Childs.end())
|
||||
{
|
||||
(*it)->~CBootProfilerRecord();
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
void Print(AZ::IO::HandleType fileHandle, char* buf, size_t buf_size, size_t depth, LARGE_INTEGER stopTime, const char* threadName, const float timeThreshold)
|
||||
{
|
||||
if (m_stopTimeStamp.QuadPart == 0)
|
||||
{
|
||||
m_stopTimeStamp = stopTime;
|
||||
}
|
||||
|
||||
const float time = (float)(m_stopTimeStamp.QuadPart - m_startTimeStamp.QuadPart) * 1000.f / (float)m_freq.QuadPart;
|
||||
|
||||
if (timeThreshold > 0.0f && time < timeThreshold)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string tabs; //tabs(depth++, '\t')
|
||||
tabs.insert(0, depth++, '\t');
|
||||
|
||||
{
|
||||
string label = m_label;
|
||||
label.replace("&", "&");
|
||||
label.replace("<", "<");
|
||||
label.replace(">", ">");
|
||||
label.replace("\"", """);
|
||||
label.replace("'", "'");
|
||||
|
||||
if (m_args.size() > 0)
|
||||
{
|
||||
m_args.replace("&", "&");
|
||||
m_args.replace("<", "<");
|
||||
m_args.replace(">", ">");
|
||||
m_args.replace("\"", """);
|
||||
m_args.replace("'", "'");
|
||||
m_args.replace("%", "%");
|
||||
}
|
||||
|
||||
sprintf_s(buf, buf_size, "%s<block name=\"%s\" totalTimeMS=\"%f\" startTime=\"%" PRIu64 "\" stopTime=\"%" PRIu64 "\" args=\"%s\"> \n",
|
||||
tabs.c_str(), label.c_str(), time, m_startTimeStamp.QuadPart, m_stopTimeStamp.QuadPart, m_args.c_str());
|
||||
AZ::IO::Print(fileHandle, buf);
|
||||
}
|
||||
|
||||
const size_t childsSize = m_Childs.size();
|
||||
for (size_t i = 0; i < childsSize; ++i)
|
||||
{
|
||||
CBootProfilerRecord* record = m_Childs[i];
|
||||
assert(record);
|
||||
record->Print(fileHandle, buf, buf_size, depth, stopTime, threadName, timeThreshold);
|
||||
}
|
||||
|
||||
sprintf_s(buf, buf_size, "%s</block>\n", tabs.c_str());
|
||||
AZ::IO::Print(fileHandle, buf);
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class CProfileInfo
|
||||
{
|
||||
friend class CBootProfilerSession;
|
||||
private:
|
||||
CBootProfilerRecord* m_pRoot;
|
||||
CBootProfilerRecord* m_pCurrent;
|
||||
public:
|
||||
CProfileInfo()
|
||||
: m_pRoot(NULL)
|
||||
, m_pCurrent(NULL) {}
|
||||
};
|
||||
|
||||
|
||||
class CBootProfilerThreadsInterface
|
||||
{
|
||||
protected:
|
||||
CBootProfilerThreadsInterface()
|
||||
{
|
||||
memset(m_threadInfo, 0, sizeof(m_threadInfo));
|
||||
m_threadCounter = 0;
|
||||
}
|
||||
|
||||
unsigned int GetThreadIndexByID(unsigned int threadID);
|
||||
const char* GetThreadNameByIndex(unsigned int threadIndex);
|
||||
|
||||
int m_threadCounter;
|
||||
private:
|
||||
unsigned int m_threadInfo[eMAX_THREADS_TO_PROFILE]; //threadIDs
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
ILINE unsigned int CBootProfilerThreadsInterface::GetThreadIndexByID(unsigned int threadID)
|
||||
{
|
||||
for (int i = 0; i < eMAX_THREADS_TO_PROFILE; ++i)
|
||||
{
|
||||
if (m_threadInfo[i] == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (m_threadInfo[i] == threadID)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int counter = CryInterlockedIncrement(&m_threadCounter) - 1; //count to index
|
||||
m_threadInfo[counter] = threadID;
|
||||
|
||||
return counter;
|
||||
}
|
||||
|
||||
ILINE const char* CBootProfilerThreadsInterface::GetThreadNameByIndex(unsigned int threadIndex)
|
||||
{
|
||||
assert(threadIndex < m_threadCounter);
|
||||
|
||||
const char* threadName = CryThreadGetName(m_threadInfo[threadIndex]);
|
||||
return threadName;
|
||||
}
|
||||
|
||||
class CRecordPool
|
||||
{
|
||||
public:
|
||||
CRecordPool()
|
||||
: m_baseAddr(NULL)
|
||||
, m_allocCounter(0)
|
||||
, m_next(NULL)
|
||||
{
|
||||
m_baseAddr = (CBootProfilerRecord*)CryModuleMemalign(eNUM_RECORDS_PER_POOL * sizeof(CBootProfilerRecord), 16);
|
||||
}
|
||||
~CRecordPool()
|
||||
{
|
||||
CryModuleMemalignFree(m_baseAddr);
|
||||
delete m_next;
|
||||
}
|
||||
|
||||
ILINE CBootProfilerRecord* allocateRecord()
|
||||
{
|
||||
if (m_allocCounter < eNUM_RECORDS_PER_POOL)
|
||||
{
|
||||
CBootProfilerRecord* newRecord = m_baseAddr + m_allocCounter;
|
||||
++m_allocCounter;
|
||||
return newRecord;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ILINE void setNextPool(CRecordPool* pool) { m_next = pool; }
|
||||
|
||||
private:
|
||||
CBootProfilerRecord* m_baseAddr;
|
||||
uint32 m_allocCounter;
|
||||
|
||||
CRecordPool* m_next;
|
||||
};
|
||||
|
||||
class CBootProfilerSession
|
||||
: public CBootProfilerThreadsInterface
|
||||
, protected CProfileBlockTimes
|
||||
{
|
||||
public:
|
||||
CBootProfilerSession();
|
||||
~CBootProfilerSession();
|
||||
|
||||
void Start();
|
||||
void Stop();
|
||||
|
||||
CBootProfilerRecord* StartBlock(const char* name, const char* args);
|
||||
void StopBlock(CBootProfilerRecord* record);
|
||||
|
||||
void CollectResults(const char* filename, const float timeThreshold);
|
||||
|
||||
private:
|
||||
string m_name;
|
||||
|
||||
CProfileInfo m_threadsProfileInfo[eMAX_THREADS_TO_PROFILE];
|
||||
CRecordPool* m_threadsRecordsPool[eMAX_THREADS_TO_PROFILE]; //head
|
||||
CRecordPool* m_threadsCurrentPools[eMAX_THREADS_TO_PROFILE]; //current
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CBootProfilerSession::CBootProfilerSession()
|
||||
{
|
||||
memset(m_threadsProfileInfo, 0, sizeof(m_threadsProfileInfo));
|
||||
|
||||
memset(m_threadsRecordsPool, 0, sizeof(m_threadsRecordsPool));
|
||||
memset(m_threadsCurrentPools, 0, sizeof(m_threadsCurrentPools));
|
||||
}
|
||||
|
||||
CBootProfilerSession::~CBootProfilerSession()
|
||||
{
|
||||
for (unsigned int i = 0; i < m_threadCounter; ++i)
|
||||
{
|
||||
CProfileInfo& profile = m_threadsProfileInfo[i];
|
||||
|
||||
// Since m_pRoot is allocated using memory pool (line 296),
|
||||
// its destructor is called explicitly to free the memory of
|
||||
// m_Childs and each of its child.
|
||||
|
||||
if (profile.m_pRoot)
|
||||
{
|
||||
profile.m_pRoot->~CBootProfilerRecord();
|
||||
}
|
||||
delete m_threadsRecordsPool[i];
|
||||
}
|
||||
}
|
||||
|
||||
void CBootProfilerSession::Start()
|
||||
{
|
||||
LARGE_INTEGER time, freq;
|
||||
QueryPerformanceFrequency(&freq);
|
||||
QueryPerformanceCounter(&time);
|
||||
m_startTimeStamp = time;
|
||||
m_freq = freq;
|
||||
}
|
||||
|
||||
void CBootProfilerSession::Stop()
|
||||
{
|
||||
LARGE_INTEGER time;
|
||||
QueryPerformanceCounter(&time);
|
||||
m_stopTimeStamp = time;
|
||||
}
|
||||
|
||||
CBootProfilerRecord* CBootProfilerSession::StartBlock(const char* name, const char* args)
|
||||
{
|
||||
const unsigned int curThread = CryGetCurrentThreadId();
|
||||
const unsigned int threadIndex = GetThreadIndexByID(curThread);
|
||||
|
||||
assert(threadIndex < eMAX_THREADS_TO_PROFILE);
|
||||
|
||||
CProfileInfo& profile = m_threadsProfileInfo[threadIndex];
|
||||
|
||||
CRecordPool* pool = m_threadsCurrentPools[threadIndex];
|
||||
|
||||
if (!profile.m_pRoot)
|
||||
{
|
||||
if (!pool)
|
||||
{
|
||||
pool = new CRecordPool;
|
||||
m_threadsRecordsPool[threadIndex] = pool;
|
||||
m_threadsCurrentPools[threadIndex] = pool;
|
||||
}
|
||||
|
||||
CBootProfilerRecord* rec = pool->allocateRecord();
|
||||
profile.m_pRoot = profile.m_pCurrent = new(rec)CBootProfilerRecord("root", m_startTimeStamp, m_freq, args);
|
||||
}
|
||||
|
||||
assert(pool);
|
||||
|
||||
LARGE_INTEGER time, freq;
|
||||
QueryPerformanceFrequency(&freq);
|
||||
QueryPerformanceCounter(&time);
|
||||
|
||||
CBootProfilerRecord* pParent = profile.m_pCurrent;
|
||||
assert(pParent);
|
||||
assert(profile.m_pRoot);
|
||||
|
||||
CBootProfilerRecord* rec = pool->allocateRecord();
|
||||
if (!rec)
|
||||
{
|
||||
//pool is full, create a new one
|
||||
pool = new CRecordPool;
|
||||
m_threadsCurrentPools[threadIndex]->setNextPool(pool);
|
||||
m_threadsCurrentPools[threadIndex] = pool;
|
||||
|
||||
rec = pool->allocateRecord();
|
||||
}
|
||||
|
||||
profile.m_pCurrent = new(rec)CBootProfilerRecord(name, time, freq, args);
|
||||
profile.m_pCurrent->m_pParent = pParent;
|
||||
pParent->m_Childs.push_back(profile.m_pCurrent);
|
||||
|
||||
return profile.m_pCurrent;
|
||||
}
|
||||
|
||||
void CBootProfilerSession::StopBlock(CBootProfilerRecord* record)
|
||||
{
|
||||
if (record)
|
||||
{
|
||||
LARGE_INTEGER time;
|
||||
QueryPerformanceCounter(&time);
|
||||
record->m_stopTimeStamp = time;
|
||||
|
||||
unsigned int curThread = CryGetCurrentThreadId();
|
||||
unsigned int threadIndex = GetThreadIndexByID(curThread);
|
||||
assert(threadIndex < eMAX_THREADS_TO_PROFILE);
|
||||
|
||||
CProfileInfo& profile = m_threadsProfileInfo[threadIndex];
|
||||
profile.m_pCurrent = record->m_pParent;
|
||||
}
|
||||
}
|
||||
|
||||
void CBootProfilerSession::CollectResults(const char* filename, const float timeThreshold)
|
||||
{
|
||||
if (!gEnv || !gEnv->pCryPak)
|
||||
{
|
||||
AZ_Warning("BootProfiler", false, "CryPak not set - skipping CollectResults");
|
||||
return;
|
||||
}
|
||||
static const char* szTestResults = "@cache@\\TestResults";
|
||||
string filePath = string(szTestResults) + "\\" + "bp_" + filename + ".xml";
|
||||
char path[AZ::IO::IArchive::MaxPath] = "";
|
||||
gEnv->pCryPak->AdjustFileName(filePath.c_str(), path, AZ_ARRAY_SIZE(path), AZ::IO::IArchive::FLAGS_PATH_REAL | AZ::IO::IArchive::FLAGS_FOR_WRITING);
|
||||
gEnv->pCryPak->MakeDir(szTestResults);
|
||||
|
||||
AZ::IO::HandleType fileHandle = AZ::IO::InvalidHandle;
|
||||
gEnv->pFileIO->Open(path, AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeBinary, fileHandle);
|
||||
if (fileHandle == AZ::IO::InvalidHandle)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
char buf[512];
|
||||
const unsigned int buf_size = sizeof(buf);
|
||||
|
||||
sprintf_s(buf, buf_size, "<root>\n");
|
||||
AZ::IO::Print(fileHandle, buf);
|
||||
|
||||
const size_t numThreads = m_threadCounter;
|
||||
for (size_t i = 0; i < numThreads; ++i)
|
||||
{
|
||||
CBootProfilerRecord* pRoot = m_threadsProfileInfo[i].m_pRoot;
|
||||
if (pRoot)
|
||||
{
|
||||
pRoot->m_stopTimeStamp = m_stopTimeStamp;
|
||||
|
||||
const char* threadName = GetThreadNameByIndex(i);
|
||||
if (!threadName)
|
||||
{
|
||||
threadName = "UNKNOWN";
|
||||
}
|
||||
|
||||
|
||||
const float time = (float)(pRoot->m_stopTimeStamp.QuadPart - pRoot->m_startTimeStamp.QuadPart) * 1000.f / (float)pRoot->m_freq.QuadPart;
|
||||
|
||||
sprintf_s(buf, buf_size, "\t<thread name=\"%s\" totalTimeMS=\"%f\" startTime=\"%" PRIu64 "\" stopTime=\"%" PRIu64 "\" > \n", threadName, time,
|
||||
pRoot->m_startTimeStamp.QuadPart, pRoot->m_stopTimeStamp.QuadPart);
|
||||
AZ::IO::Print(fileHandle, buf);
|
||||
|
||||
for (size_t recordIdx = 0; recordIdx < pRoot->m_Childs.size(); ++recordIdx)
|
||||
{
|
||||
CBootProfilerRecord* record = pRoot->m_Childs[recordIdx];
|
||||
assert(record);
|
||||
record->Print(fileHandle, buf, buf_size, 2, m_stopTimeStamp, threadName, timeThreshold);
|
||||
}
|
||||
|
||||
sprintf_s(buf, buf_size, "\t</thread>\n");
|
||||
AZ::IO::Print(fileHandle, buf);
|
||||
}
|
||||
}
|
||||
|
||||
sprintf_s(buf, buf_size, "</root>\n");
|
||||
AZ::IO::Print(fileHandle, buf);
|
||||
gEnv->pFileIO->Close(fileHandle);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CBootProfiler& CBootProfiler::GetInstance()
|
||||
{
|
||||
return gProfilerInstance;
|
||||
}
|
||||
|
||||
CBootProfiler::CBootProfiler()
|
||||
: m_pCurrentSession(NULL)
|
||||
, m_pFrameRecord(NULL)
|
||||
, m_levelLoadAdditionalFrames(0)
|
||||
{
|
||||
}
|
||||
|
||||
CBootProfiler::~CBootProfiler()
|
||||
{
|
||||
AZStd::lock_guard<AZStd::recursive_mutex> recordGuard{ m_recordMutex };
|
||||
for (TSessionMap::iterator it = m_sessions.begin(); it != m_sessions.end(); ++it)
|
||||
{
|
||||
CBootProfilerSession* session = it->second;
|
||||
delete session;
|
||||
}
|
||||
}
|
||||
|
||||
// start session
|
||||
void CBootProfiler::StartSession(const char* sessionName)
|
||||
{
|
||||
AZStd::lock_guard<AZStd::recursive_mutex> recordGuard{ m_recordMutex };
|
||||
|
||||
TSessionMap::const_iterator it = m_sessions.find(sessionName);
|
||||
if (it == m_sessions.end())
|
||||
{
|
||||
m_pCurrentSession = new CBootProfilerSession();
|
||||
m_sessions[sessionName] = m_pCurrentSession;
|
||||
m_pCurrentSession->Start();
|
||||
}
|
||||
}
|
||||
|
||||
// stop session
|
||||
void CBootProfiler::StopSession(const char* sessionName)
|
||||
{
|
||||
AZStd::lock_guard<AZStd::recursive_mutex> recordGuard{ m_recordMutex };
|
||||
if (m_pCurrentSession)
|
||||
{
|
||||
TSessionMap::iterator it = m_sessions.find(sessionName);
|
||||
if (it != m_sessions.end())
|
||||
{
|
||||
if (m_pCurrentSession == it->second)
|
||||
{
|
||||
CBootProfilerSession* session = m_pCurrentSession;
|
||||
m_pCurrentSession = NULL;
|
||||
|
||||
session->Stop();
|
||||
session->CollectResults(sessionName, CV_sys_bp_time_threshold);
|
||||
|
||||
delete session;
|
||||
}
|
||||
m_sessions.erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CBootProfilerRecord* CBootProfiler::StartBlock(const char* name, const char* args)
|
||||
{
|
||||
AZStd::lock_guard<AZStd::recursive_mutex> recordGuard{ m_recordMutex };
|
||||
if (m_pCurrentSession)
|
||||
{
|
||||
return m_pCurrentSession->StartBlock(name, args);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void CBootProfiler::StopBlock(CBootProfilerRecord* record)
|
||||
{
|
||||
AZStd::lock_guard<AZStd::recursive_mutex> recordGuard{ m_recordMutex };
|
||||
if (m_pCurrentSession)
|
||||
{
|
||||
m_pCurrentSession->StopBlock(record);
|
||||
}
|
||||
}
|
||||
|
||||
void CBootProfiler::StartFrame(const char* name)
|
||||
{
|
||||
AZStd::lock_guard<AZStd::recursive_mutex> recordGuard{ m_recordMutex };
|
||||
if (CV_sys_bp_frames)
|
||||
{
|
||||
StartSession("frames");
|
||||
m_pFrameRecord = StartBlock(name, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void CBootProfiler::StopFrame()
|
||||
{
|
||||
AZStd::lock_guard<AZStd::recursive_mutex> recordGuard{ m_recordMutex };
|
||||
if (m_pCurrentSession && CV_sys_bp_frames)
|
||||
{
|
||||
StopBlock(m_pFrameRecord);
|
||||
m_pFrameRecord = NULL;
|
||||
|
||||
--CV_sys_bp_frames;
|
||||
if (0 == CV_sys_bp_frames)
|
||||
{
|
||||
StopSession("frames");
|
||||
}
|
||||
}
|
||||
|
||||
if (m_pCurrentSession && m_levelLoadAdditionalFrames)
|
||||
{
|
||||
--m_levelLoadAdditionalFrames;
|
||||
if (0 == m_levelLoadAdditionalFrames)
|
||||
{
|
||||
StopSession("level");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CBootProfiler::Init(ISystem* pSystem)
|
||||
{
|
||||
//REGISTER_CVAR(sys_BootProfiler, 1, VF_DEV_ONLY,
|
||||
// "Collect and output session statistics into TestResults/bp_(session_name).xml \n"
|
||||
// "0 = Disabled\n"
|
||||
// "1 = Enabled\n");
|
||||
|
||||
pSystem->GetISystemEventDispatcher()->RegisterListener(this);
|
||||
StartSession("boot");
|
||||
}
|
||||
|
||||
void CBootProfiler::RegisterCVars()
|
||||
{
|
||||
REGISTER_CVAR2("sys_bp_frames", &CV_sys_bp_frames, 0, VF_DEV_ONLY, "Starts frame profiling for specified number of frames using BootProfiler");
|
||||
REGISTER_CVAR2("sys_bp_time_threshold", &CV_sys_bp_time_threshold, 0.1f, VF_DEV_ONLY, "If greater than 0 don't write blocks that took less time (default 0.1 ms)");
|
||||
}
|
||||
|
||||
void CBootProfiler::OnSystemEvent(ESystemEvent event, UINT_PTR wparam, UINT_PTR lparam)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case ESYSTEM_EVENT_GAME_POST_INIT_DONE:
|
||||
{
|
||||
StopSession("boot");
|
||||
break;
|
||||
}
|
||||
case ESYSTEM_EVENT_GAME_MODE_SWITCH_START:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
case ESYSTEM_EVENT_GAME_MODE_SWITCH_END:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
case ESYSTEM_EVENT_LEVEL_LOAD_START:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case ESYSTEM_EVENT_LEVEL_LOAD_PREPARE:
|
||||
{
|
||||
StartSession("level");
|
||||
break;
|
||||
}
|
||||
case ESYSTEM_EVENT_LEVEL_LOAD_END:
|
||||
{
|
||||
StopSession("level");
|
||||
break;
|
||||
}
|
||||
case ESYSTEM_EVENT_LEVEL_PRECACHE_END:
|
||||
{
|
||||
//level loading can be stopped here, or m_levelLoadAdditionalFrames can be used to prolong dump for this amount of frames
|
||||
//StopSession("level");
|
||||
m_levelLoadAdditionalFrames = 20;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CBootProfiler::SetFrameCount(int frameCount)
|
||||
{
|
||||
CV_sys_bp_frames = frameCount;
|
||||
}
|
||||
#endif
|
||||
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#ifndef CRYINCLUDE_CRYSYSTEM_BOOTPROFILER_H
|
||||
#define CRYINCLUDE_CRYSYSTEM_BOOTPROFILER_H
|
||||
#pragma once
|
||||
|
||||
#if defined(ENABLE_LOADING_PROFILER)
|
||||
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzCore/std/containers/unordered_map.h>
|
||||
#include <AzCore/std/parallel/mutex.h>
|
||||
|
||||
class CBootProfilerRecord;
|
||||
class CBootProfilerSession;
|
||||
|
||||
class CBootProfiler
|
||||
: public ISystemEventListener
|
||||
{
|
||||
friend class CBootProfileBLock;
|
||||
public:
|
||||
CBootProfiler();
|
||||
~CBootProfiler();
|
||||
|
||||
static CBootProfiler& GetInstance();
|
||||
|
||||
void Init(ISystem* pSystem);
|
||||
void RegisterCVars();
|
||||
|
||||
void StartSession(const char* sessionName);
|
||||
void StopSession(const char* sessionName);
|
||||
|
||||
CBootProfilerRecord* StartBlock(const char* name, const char* args);
|
||||
void StopBlock(CBootProfilerRecord* record);
|
||||
|
||||
void StartFrame(const char* name);
|
||||
void StopFrame();
|
||||
protected:
|
||||
// === ISystemEventListener
|
||||
virtual void OnSystemEvent(ESystemEvent event, UINT_PTR wparam, UINT_PTR lparam);
|
||||
void SetFrameCount(int frameCount);
|
||||
|
||||
private:
|
||||
CBootProfilerSession* m_pCurrentSession;
|
||||
typedef AZStd::unordered_map<AZStd::string, CBootProfilerSession*> TSessionMap;
|
||||
TSessionMap m_sessions;
|
||||
|
||||
static int CV_sys_bp_frames;
|
||||
static float CV_sys_bp_time_threshold;
|
||||
CBootProfilerRecord* m_pFrameRecord;
|
||||
AZStd::recursive_mutex m_recordMutex;
|
||||
int m_levelLoadAdditionalFrames;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif // CRYINCLUDE_CRYSYSTEM_BOOTPROFILER_H
|
||||
@@ -277,17 +277,6 @@ int DebugCallStack::handleException(EXCEPTION_POINTERS* exception_pointer)
|
||||
sprintf_s(excCode, "0x%08X", exception_pointer->ExceptionRecord->ExceptionCode);
|
||||
WriteLineToLog("Exception: %s, at Address: %s", excCode, excAddr);
|
||||
|
||||
if (CSystem* pSystem = (CSystem*)GetSystem())
|
||||
{
|
||||
if (const char* pLoadingProfilerCallstack = pSystem->GetLoadingProfilerCallstack())
|
||||
{
|
||||
if (pLoadingProfilerCallstack[0])
|
||||
{
|
||||
WriteLineToLog("<CrySystem> LoadingProfilerCallstack: %s", pLoadingProfilerCallstack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
IMemoryManager::SProcessMemInfo memInfo;
|
||||
if (gEnv->pSystem->GetIMemoryManager()->GetProcessMemInfo(memInfo))
|
||||
@@ -593,7 +582,7 @@ void DebugCallStack::LogExceptionInfo(EXCEPTION_POINTERS* pex)
|
||||
AZ::Debug::SymbolStorage::DecodeFrames(frames, numFrames, lines);
|
||||
for (unsigned int i2 = 0; i2 < numFrames; ++i2)
|
||||
{
|
||||
fprintf(f, "%2d) %s\n", numFrames - i2, lines[i2]);
|
||||
fprintf(f, "%2d) %s\n", numFrames - i2, lines[i2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
#include "System.h"
|
||||
#include <AzFramework/IO/FileOperations.h>
|
||||
#include <AzCore/NativeUI/NativeUIRequests.h>
|
||||
|
||||
#include <AzFramework/StringFunc/StringFunc.h>
|
||||
#include <AzCore/StringFunc/StringFunc.h>
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
//#if !defined(LINUX)
|
||||
|
||||
#include <ISystem.h>
|
||||
@@ -186,21 +186,17 @@ AZ_PUSH_DISABLE_WARNING(4996, "-Wunknown-warning-option")
|
||||
}
|
||||
}
|
||||
|
||||
if (gEnv->pConsole)
|
||||
{
|
||||
if (ICVar* pCVarGameDir = gEnv->pConsole->GetCVar("sys_game_folder"))
|
||||
{
|
||||
sprintf(s, "GameDir: %s\n", pCVarGameDir->GetString());
|
||||
azstrcat(str, length, s);
|
||||
}
|
||||
}
|
||||
AZ::IO::FixedMaxPathString projectPath = AZ::Utils::GetProjectPath();
|
||||
azstrcat(str, length, "ProjectDir: ");
|
||||
azstrcat(str, length, projectPath.c_str());
|
||||
azstrcat(str, length, "\n");
|
||||
|
||||
#if AZ_LEGACY_CRYSYSTEM_TRAIT_DEBUGCALLSTACK_APPEND_MODULENAME
|
||||
GetModuleFileNameA(NULL, s, sizeof(s));
|
||||
|
||||
// Log EXE filename only if possible (not full EXE path which could contain sensitive info)
|
||||
AZStd::string exeName;
|
||||
if (AzFramework::StringFunc::Path::GetFullFileName(s, exeName))
|
||||
if (AZ::StringFunc::Path::GetFullFileName(s, exeName))
|
||||
{
|
||||
azstrcat(str, length, "Executable: ");
|
||||
azstrcat(str, length, exeName.c_str());
|
||||
|
||||
@@ -1,647 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#include "CrySystem_precompiled.h"
|
||||
|
||||
#if defined(ENABLE_LOADING_PROFILER)
|
||||
|
||||
#include "System.h"
|
||||
#include "LoadingProfiler.h"
|
||||
|
||||
#define LOADING_TIME_CONTAINER_MAX_TEXT_SIZE 1024
|
||||
#define MAX_LOADING_TIME_PROFILER_STACK_DEPTH 16
|
||||
|
||||
//#define SAVE_SAVELEVELSTATS_IN_ROOT
|
||||
|
||||
struct SLoadingTimeContainer
|
||||
: public _i_reference_target_t
|
||||
{
|
||||
SLoadingTimeContainer() {}
|
||||
|
||||
SLoadingTimeContainer(SLoadingTimeContainer* pParent, const char* pPureFuncName, const int nRootIndex)
|
||||
{
|
||||
m_dSelfMemUsage = m_dTotalMemUsage = m_dSelfTime = m_dTotalTime = 0;
|
||||
m_nCounter = 1;
|
||||
m_pFuncName = pPureFuncName;
|
||||
m_pParent = pParent;
|
||||
m_nRootIndex = nRootIndex;
|
||||
}
|
||||
|
||||
static int Cmp_SLoadingTimeContainer_Time(const void* v1, const void* v2)
|
||||
{
|
||||
SLoadingTimeContainer* pChunk1 = (SLoadingTimeContainer*)v1;
|
||||
SLoadingTimeContainer* pChunk2 = (SLoadingTimeContainer*)v2;
|
||||
|
||||
if (pChunk1->m_dSelfTime > pChunk2->m_dSelfTime)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (pChunk1->m_dSelfTime < pChunk2->m_dSelfTime)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int Cmp_SLoadingTimeContainer_MemUsage(const void* v1, const void* v2)
|
||||
{
|
||||
SLoadingTimeContainer* pChunk1 = (SLoadingTimeContainer*)v1;
|
||||
SLoadingTimeContainer* pChunk2 = (SLoadingTimeContainer*)v2;
|
||||
|
||||
if (pChunk1->m_dSelfMemUsage > pChunk2->m_dSelfMemUsage)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (pChunk1->m_dSelfMemUsage < pChunk2->m_dSelfMemUsage)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static double GetUsedMemory(ISystem* pSysytem)
|
||||
{
|
||||
static IMemoryManager::SProcessMemInfo processMemInfo;
|
||||
pSysytem->GetIMemoryManager()->GetProcessMemInfo(processMemInfo);
|
||||
return double(processMemInfo.PagefileUsage) / double(1024 * 1024);
|
||||
}
|
||||
|
||||
|
||||
void Clear()
|
||||
{
|
||||
for (size_t i = 0, end = m_pChilds.size(); i < end; ++i)
|
||||
{
|
||||
delete m_pChilds[i];
|
||||
}
|
||||
}
|
||||
|
||||
~SLoadingTimeContainer()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
|
||||
double m_dSelfTime, m_dTotalTime;
|
||||
double m_dSelfMemUsage, m_dTotalMemUsage;
|
||||
uint32 m_nCounter;
|
||||
|
||||
const char* m_pFuncName;
|
||||
SLoadingTimeContainer* m_pParent;
|
||||
int m_nRootIndex;
|
||||
std::vector<SLoadingTimeContainer*> m_pChilds;
|
||||
|
||||
DiskOperationInfo m_selfInfo;
|
||||
DiskOperationInfo m_totalInfo;
|
||||
bool m_bUsed;
|
||||
};
|
||||
|
||||
bool operator== (const SLoadingTimeContainer& a, const SLoadingTimeContainer& b)
|
||||
{
|
||||
return b.m_pFuncName == a.m_pFuncName;
|
||||
}
|
||||
|
||||
bool operator== (const SLoadingTimeContainer& a, const char* b)
|
||||
{
|
||||
return b == a.m_pFuncName;
|
||||
}
|
||||
|
||||
|
||||
SLoadingTimeContainer* CLoadingProfilerSystem::m_pCurrentLoadingTimeContainer = 0;
|
||||
SLoadingTimeContainer* CLoadingProfilerSystem::m_pRoot[2] = {0, 0};
|
||||
int CLoadingProfilerSystem::m_iActiveRoot = 0;
|
||||
ICVar* CLoadingProfilerSystem::m_pEnableProfile = 0;
|
||||
int CLoadingProfilerSystem::nLoadingProfileMode = 1;
|
||||
int CLoadingProfilerSystem::nLoadingProfilerNotTrackedAllocations = -1;
|
||||
CryCriticalSection CLoadingProfilerSystem::csLock;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CLoadingProfilerSystem::OutputLoadingTimeStats(ILog* pLog, int nMode)
|
||||
{
|
||||
nLoadingProfileMode = nMode;
|
||||
|
||||
PodArray<SLoadingTimeContainer> arrNoStack;
|
||||
CreateNoStackList(arrNoStack);
|
||||
|
||||
|
||||
if (nLoadingProfileMode > 0)
|
||||
{ // loading mem stats per func
|
||||
pLog->Log("------ Level loading memory allocations (MB) by function ------------");
|
||||
pLog->Log(" ||Self | Total | Calls | Function (%d MB lost)||", nLoadingProfilerNotTrackedAllocations);
|
||||
pLog->Log("---------------------------------------------------------------------");
|
||||
|
||||
qsort(arrNoStack.GetElements(), arrNoStack.Count(), sizeof(arrNoStack[0]), SLoadingTimeContainer::Cmp_SLoadingTimeContainer_MemUsage);
|
||||
|
||||
for (int i = 0; i < arrNoStack.Count(); i++)
|
||||
{
|
||||
const SLoadingTimeContainer* pTimeContainer = &arrNoStack[i];
|
||||
pLog->Log("|%6.1f | %6.1f | %6d | %s|",
|
||||
pTimeContainer->m_dSelfMemUsage, pTimeContainer->m_dTotalMemUsage, (int)pTimeContainer->m_nCounter, pTimeContainer->m_pFuncName);
|
||||
}
|
||||
|
||||
pLog->Log("---------------------------------------------------------------------");
|
||||
}
|
||||
|
||||
if (nLoadingProfileMode > 0)
|
||||
{ // loading time stats per func
|
||||
pLog->Log("----------- Level loading time (sec) by function --------------------");
|
||||
pLog->Log(" ||Self | Total | Calls | Function||");
|
||||
pLog->Log("---------------------------------------------------------------------");
|
||||
|
||||
qsort(arrNoStack.GetElements(), arrNoStack.Count(), sizeof(arrNoStack[0]), SLoadingTimeContainer::Cmp_SLoadingTimeContainer_Time);
|
||||
|
||||
for (int i = 0; i < arrNoStack.Count(); i++)
|
||||
{
|
||||
const SLoadingTimeContainer* pTimeContainer = &arrNoStack[i];
|
||||
pLog->Log("|%6.1f | %6.1f | %6d | %s|",
|
||||
pTimeContainer->m_dSelfTime, pTimeContainer->m_dTotalTime, (int)pTimeContainer->m_nCounter, pTimeContainer->m_pFuncName);
|
||||
}
|
||||
|
||||
if (nLoadingProfileMode == 1)
|
||||
{
|
||||
pLog->Log("----- ( Use sys_ProfileLevelLoading 2 for more detailed stats ) -----");
|
||||
}
|
||||
else
|
||||
{
|
||||
pLog->Log("---------------------------------------------------------------------");
|
||||
}
|
||||
}
|
||||
|
||||
if (nLoadingProfileMode > 0)
|
||||
{ // file info
|
||||
pLog->Log("----------------------------- Level file information by function --------------------------------");
|
||||
pLog->Log("|| Self | Total |Bandwith| Calls | Function||");
|
||||
pLog->Log("|| Seeks |FileOpen|FileRead| Seeks |FileOpen|FileRead| Kb/s | | ||");
|
||||
|
||||
qsort(arrNoStack.GetElements(), arrNoStack.Count(), sizeof(arrNoStack[0]), SLoadingTimeContainer::Cmp_SLoadingTimeContainer_Time);
|
||||
|
||||
for (int i = 0; i < arrNoStack.Count(); i++)
|
||||
{
|
||||
const SLoadingTimeContainer* pTimeContainer = &arrNoStack[i];
|
||||
double bandwidth = pTimeContainer->m_dSelfTime > 0 ? (pTimeContainer->m_selfInfo.m_dOperationSize / pTimeContainer->m_dSelfTime / 1024.0) : 0.;
|
||||
pLog->Log("|%6d | %6d | %6d |%6d | %6d | %6d | %6.1f | %6d | %s|",
|
||||
pTimeContainer->m_selfInfo.m_nSeeksCount, pTimeContainer->m_selfInfo.m_nFileOpenCount, pTimeContainer->m_selfInfo.m_nFileReadCount,
|
||||
pTimeContainer->m_totalInfo.m_nSeeksCount, pTimeContainer->m_totalInfo.m_nFileOpenCount, pTimeContainer->m_totalInfo.m_nFileReadCount,
|
||||
bandwidth, (int)pTimeContainer->m_nCounter, pTimeContainer->m_pFuncName);
|
||||
}
|
||||
|
||||
if (nLoadingProfileMode == 1)
|
||||
{
|
||||
pLog->Log("----- ( Use sys_ProfileLevelLoading 2 for more detailed stats ) -----");
|
||||
}
|
||||
else
|
||||
{
|
||||
pLog->Log("---------------------------------------------------------------------");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct CSystemEventListner_LoadingProfiler
|
||||
: public ISystemEventListener
|
||||
{
|
||||
private:
|
||||
CLoadingTimeProfiler* m_pPrecacheProfiler;
|
||||
ESystemEvent lastEvent;
|
||||
public:
|
||||
CSystemEventListner_LoadingProfiler()
|
||||
: m_pPrecacheProfiler(NULL) {}
|
||||
|
||||
virtual void OnSystemEvent(ESystemEvent event, UINT_PTR wparam, UINT_PTR lparam)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case ESYSTEM_EVENT_GAME_MODE_SWITCH_START:
|
||||
{
|
||||
CLoadingProfilerSystem::Clean();
|
||||
if (m_pPrecacheProfiler == NULL)
|
||||
{
|
||||
m_pPrecacheProfiler = new CLoadingTimeProfiler(gEnv->pSystem, "ModeSwitch");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ESYSTEM_EVENT_GAME_MODE_SWITCH_END:
|
||||
{
|
||||
SAFE_DELETE(m_pPrecacheProfiler);
|
||||
CLoadingProfilerSystem::SaveTimeContainersToFile(gEnv->bMultiplayer == true ? "mode_switch_mp.lmbrlp" : "mode_switch_sp.lmbrlp", 0.0, true);
|
||||
}
|
||||
|
||||
case ESYSTEM_EVENT_LEVEL_LOAD_PREPARE:
|
||||
{
|
||||
CLoadingProfilerSystem::Clean();
|
||||
if (m_pPrecacheProfiler == NULL)
|
||||
{
|
||||
m_pPrecacheProfiler = new CLoadingTimeProfiler(gEnv->pSystem, "LevelLoading");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ESYSTEM_EVENT_LEVEL_LOAD_END:
|
||||
{
|
||||
delete m_pPrecacheProfiler;
|
||||
m_pPrecacheProfiler = new CLoadingTimeProfiler(gEnv->pSystem, "Precache");
|
||||
break;
|
||||
}
|
||||
case ESYSTEM_EVENT_LEVEL_PRECACHE_END:
|
||||
{
|
||||
if (lastEvent == ESYSTEM_EVENT_LEVEL_PRECACHE_FIRST_FRAME)
|
||||
{
|
||||
SAFE_DELETE(m_pPrecacheProfiler);
|
||||
string levelName = "no_level";
|
||||
ICVar* sv_map = gEnv->pConsole->GetCVar("sv_map");
|
||||
if (sv_map)
|
||||
{
|
||||
levelName = sv_map->GetString();
|
||||
}
|
||||
|
||||
string levelNameFullProfile = levelName + "_LP.lmbrlp";
|
||||
string levelNameThreshold = levelName + "_LP_OneSec.lmbrlp";
|
||||
CLoadingProfilerSystem::SaveTimeContainersToFile(levelNameFullProfile.c_str(), 0.0, false);
|
||||
CLoadingProfilerSystem::SaveTimeContainersToFile(levelNameThreshold.c_str(), 1.0, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESYSTEM_EVENT_LEVEL_POST_UNLOAD:
|
||||
{
|
||||
// Ensure that the precache profiler is dead
|
||||
SAFE_DELETE(m_pPrecacheProfiler);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (event != ESYSTEM_EVENT_RANDOM_SEED)
|
||||
{
|
||||
lastEvent = event;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static CSystemEventListner_LoadingProfiler g_system_event_listener_loadingProfiler;
|
||||
|
||||
void CLoadingProfilerSystem::Init()
|
||||
{
|
||||
gEnv->pSystem->GetISystemEventDispatcher()->RegisterListener(&g_system_event_listener_loadingProfiler);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CLoadingProfilerSystem::ShutDown()
|
||||
{
|
||||
if (gEnv && gEnv->pSystem && gEnv->pSystem->GetISystemEventDispatcher())
|
||||
{
|
||||
gEnv->pSystem->GetISystemEventDispatcher()->RemoveListener(&g_system_event_listener_loadingProfiler);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
SLoadingTimeContainer* CLoadingProfilerSystem::StartLoadingSectionProfiling(CLoadingTimeProfiler* pProfiler, const char* szFuncName)
|
||||
{
|
||||
if (!nLoadingProfileMode || !gEnv->pConsole)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DWORD threadID = GetCurrentThreadId();
|
||||
|
||||
static DWORD dwMainThreadId = GetCurrentThreadId();
|
||||
if (threadID != dwMainThreadId)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!m_pEnableProfile)
|
||||
{
|
||||
if (gEnv->pConsole)
|
||||
{
|
||||
m_pEnableProfile = gEnv->pConsole->GetCVar("sys_ProfileLevelLoading");
|
||||
if (!m_pEnableProfile)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_pEnableProfile->GetIVal() <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//if (m_pCurrentLoadingTimeContainer == m_pRoot && strstr(szFuncName,"Open"))
|
||||
//{
|
||||
// pProfiler->m_constructorInfo.m_nFileOpenCount +=1;
|
||||
//}
|
||||
|
||||
CryAutoCriticalSection lock(csLock);
|
||||
|
||||
if (true /*pProfiler && pProfiler->m_pSystem*/)
|
||||
{
|
||||
ITimer* pTimer = pProfiler->m_pSystem->GetITimer();
|
||||
pProfiler->m_fConstructorTime = pTimer->GetAsyncTime().GetSeconds();
|
||||
pProfiler->m_fConstructorMemUsage = SLoadingTimeContainer::GetUsedMemory(pProfiler->m_pSystem);
|
||||
|
||||
DiskOperationInfo info;
|
||||
pProfiler->m_constructorInfo = info;
|
||||
|
||||
if (nLoadingProfilerNotTrackedAllocations < 0)
|
||||
{
|
||||
nLoadingProfilerNotTrackedAllocations = (int)pProfiler->m_fConstructorMemUsage;
|
||||
}
|
||||
}
|
||||
|
||||
SLoadingTimeContainer* pParent = m_pCurrentLoadingTimeContainer;
|
||||
if (!pParent)
|
||||
{
|
||||
pParent = m_pCurrentLoadingTimeContainer = m_pRoot[m_iActiveRoot] = new SLoadingTimeContainer(0, "Root", m_iActiveRoot);
|
||||
}
|
||||
|
||||
for (size_t i = 0, end = m_pCurrentLoadingTimeContainer->m_pChilds.size(); i < end; ++i)
|
||||
{
|
||||
if (m_pCurrentLoadingTimeContainer->m_pChilds[i]->m_pFuncName == szFuncName)
|
||||
{
|
||||
assert(m_pCurrentLoadingTimeContainer->m_pChilds[i]->m_pParent == m_pCurrentLoadingTimeContainer);
|
||||
assert(!m_pCurrentLoadingTimeContainer->m_pChilds[i]->m_bUsed);
|
||||
m_pCurrentLoadingTimeContainer->m_pChilds[i]->m_bUsed = true;
|
||||
m_pCurrentLoadingTimeContainer->m_pChilds[i]->m_nCounter++;
|
||||
m_pCurrentLoadingTimeContainer = m_pCurrentLoadingTimeContainer->m_pChilds[i];
|
||||
return m_pCurrentLoadingTimeContainer;
|
||||
}
|
||||
}
|
||||
|
||||
m_pCurrentLoadingTimeContainer = new SLoadingTimeContainer(pParent, szFuncName, pParent->m_nRootIndex);
|
||||
m_pCurrentLoadingTimeContainer->m_bUsed = true;
|
||||
{
|
||||
// Need to iterate from the end than
|
||||
pParent->m_pChilds.push_back(m_pCurrentLoadingTimeContainer);
|
||||
}
|
||||
|
||||
return m_pCurrentLoadingTimeContainer;
|
||||
}
|
||||
|
||||
void CLoadingProfilerSystem::EndLoadingSectionProfiling(CLoadingTimeProfiler* pProfiler)
|
||||
{
|
||||
if (!nLoadingProfileMode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static DWORD dwMainThreadId = GetCurrentThreadId();
|
||||
|
||||
if (GetCurrentThreadId() != dwMainThreadId)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pProfiler->m_pTimeContainer)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CryAutoCriticalSection lock(csLock);
|
||||
|
||||
if (true /*pProfiler && pProfiler->m_pSystem*/)
|
||||
{
|
||||
ITimer* pTimer = pProfiler->m_pSystem->GetITimer();
|
||||
double fSelfTime = pTimer->GetAsyncTime().GetSeconds() - pProfiler->m_fConstructorTime;
|
||||
double fMemUsage = SLoadingTimeContainer::GetUsedMemory(pProfiler->m_pSystem);
|
||||
double fSelfMemUsage = fMemUsage - pProfiler->m_fConstructorMemUsage;
|
||||
|
||||
|
||||
if (fSelfTime < 0.0)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
pProfiler->m_pTimeContainer->m_dSelfTime += fSelfTime;
|
||||
pProfiler->m_pTimeContainer->m_dTotalTime += fSelfTime;
|
||||
pProfiler->m_pTimeContainer->m_dSelfMemUsage += fSelfMemUsage;
|
||||
pProfiler->m_pTimeContainer->m_dTotalMemUsage += fSelfMemUsage;
|
||||
|
||||
DiskOperationInfo info;
|
||||
info -= pProfiler->m_constructorInfo;
|
||||
pProfiler->m_pTimeContainer->m_totalInfo += info;
|
||||
pProfiler->m_pTimeContainer->m_selfInfo += info;
|
||||
pProfiler->m_pTimeContainer->m_bUsed = false;
|
||||
|
||||
SLoadingTimeContainer* pParent = pProfiler->m_pTimeContainer->m_pParent;
|
||||
pParent->m_selfInfo -= info;
|
||||
pParent->m_dSelfTime -= fSelfTime;
|
||||
pParent->m_dSelfMemUsage -= fSelfMemUsage;
|
||||
if (pProfiler->m_pTimeContainer->m_pParent && pProfiler->m_pTimeContainer->m_pParent->m_nRootIndex == m_iActiveRoot)
|
||||
{
|
||||
m_pCurrentLoadingTimeContainer = pProfiler->m_pTimeContainer->m_pParent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char* CLoadingProfilerSystem::GetLoadingProfilerCallstack()
|
||||
{
|
||||
CryAutoCriticalSection lock(csLock);
|
||||
|
||||
static char szStack[1024];
|
||||
|
||||
szStack[0] = 0;
|
||||
|
||||
SLoadingTimeContainer* pC = m_pCurrentLoadingTimeContainer;
|
||||
|
||||
PodArray<SLoadingTimeContainer*> arrItems;
|
||||
|
||||
while (pC)
|
||||
{
|
||||
arrItems.Add(pC);
|
||||
pC = pC->m_pParent;
|
||||
}
|
||||
|
||||
for (int i = arrItems.Count() - 1; i >= 0; i--)
|
||||
{
|
||||
cry_strcat(szStack, " > ");
|
||||
cry_strcat(szStack, arrItems[i]->m_pFuncName);
|
||||
}
|
||||
|
||||
return &szStack[0];
|
||||
}
|
||||
|
||||
void CLoadingProfilerSystem::FillProfilersList(AZStd::vector<SLoadingProfilerInfo>& profilers)
|
||||
{
|
||||
UpdateSelfStatistics(m_pRoot[m_iActiveRoot]);
|
||||
|
||||
PodArray<SLoadingTimeContainer> arrNoStack;
|
||||
CreateNoStackList(arrNoStack);
|
||||
//qsort(arrNoStack.GetElements(), arrNoStack.Count(), sizeof(arrNoStack[0]), SLoadingTimeContainer::Cmp_SLoadingTimeContainer_Time);
|
||||
|
||||
uint32 count = arrNoStack.Size();
|
||||
profilers.resize(count);
|
||||
|
||||
for (uint32 i = 0; i < count; ++i)
|
||||
{
|
||||
profilers[i].name = arrNoStack[i].m_pFuncName;
|
||||
profilers[i].selfTime = arrNoStack[i].m_dSelfTime;
|
||||
profilers[i].callsTotal = arrNoStack[i].m_nCounter;
|
||||
profilers[i].totalTime = arrNoStack[i].m_dTotalTime;
|
||||
profilers[i].memorySize = arrNoStack[i].m_dTotalMemUsage;
|
||||
profilers[i].selfInfo = arrNoStack[i].m_selfInfo;
|
||||
profilers[i].totalInfo = arrNoStack[i].m_totalInfo;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CLoadingProfilerSystem::AddTimeContainerFunction(PodArray<SLoadingTimeContainer>& arrNoStack, SLoadingTimeContainer* node)
|
||||
{
|
||||
if (!node)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SLoadingTimeContainer* it = std::find(arrNoStack.begin(), arrNoStack.end(), node->m_pFuncName);
|
||||
|
||||
if (it == arrNoStack.end())
|
||||
{
|
||||
arrNoStack.push_back(*node);
|
||||
}
|
||||
else
|
||||
{
|
||||
it->m_dSelfMemUsage += node->m_dSelfMemUsage;
|
||||
it->m_dSelfTime += node->m_dSelfTime;
|
||||
it->m_dTotalMemUsage += node->m_dTotalMemUsage;
|
||||
it->m_dTotalTime += node->m_dTotalTime;
|
||||
it->m_nCounter += node->m_nCounter;
|
||||
it->m_selfInfo += node->m_selfInfo;
|
||||
it->m_totalInfo += node->m_totalInfo;
|
||||
}
|
||||
|
||||
for (size_t i = 0, end = node->m_pChilds.size(); i < end; ++i)
|
||||
{
|
||||
AddTimeContainerFunction(arrNoStack, node->m_pChilds[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void CLoadingProfilerSystem::CreateNoStackList(PodArray<SLoadingTimeContainer>& arrNoStack)
|
||||
{
|
||||
AddTimeContainerFunction(arrNoStack, m_pRoot[m_iActiveRoot]);
|
||||
}
|
||||
|
||||
#define g_szTestResults "@cache@\\TestResults"
|
||||
|
||||
void CLoadingProfilerSystem::SaveTimeContainersToFile(const char* name, double fMinTotalTime, bool bClean)
|
||||
{
|
||||
if (m_pRoot[m_iActiveRoot])
|
||||
{
|
||||
const char* levelName = name;
|
||||
//Ignore any folders in the input name
|
||||
const char* folder = strrchr(name, '/');
|
||||
if (folder != NULL)
|
||||
{
|
||||
levelName = folder + 1;
|
||||
}
|
||||
char path[AZ::IO::IArchive::MaxPath];
|
||||
path[sizeof(path) - 1] = 0;
|
||||
|
||||
gEnv->pCryPak->AdjustFileName(string(string(g_szTestResults) + "\\" + levelName).c_str(), path, AZ_ARRAY_SIZE(path), AZ::IO::IArchive::FLAGS_PATH_REAL | AZ::IO::IArchive::FLAGS_FOR_WRITING);
|
||||
gEnv->pCryPak->MakeDir(g_szTestResults);
|
||||
|
||||
AZ::IO::HandleType handle = AZ::IO::InvalidHandle;
|
||||
|
||||
AZ::IO::Result f = AZ::IO::FileIOBase::GetInstance()->Open(path,AZ::IO::OpenMode::ModeWrite, handle);
|
||||
|
||||
if (handle != AZ::IO::InvalidHandle)
|
||||
{
|
||||
UpdateSelfStatistics(m_pRoot[m_iActiveRoot]);
|
||||
WriteTimeContainerToFile(m_pRoot[m_iActiveRoot], handle, 0, fMinTotalTime);
|
||||
AZ::IO::FileIOBase::GetInstance()->Close(handle);
|
||||
}
|
||||
|
||||
if (bClean)
|
||||
{
|
||||
Clean();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CLoadingProfilerSystem::WriteTimeContainerToFile(SLoadingTimeContainer* p, AZ::IO::HandleType &handle, unsigned int depth, double fMinTotalTime)
|
||||
{
|
||||
if (p == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (p->m_dTotalTime < fMinTotalTime)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CryFixedStringT<MAX_LOADING_TIME_PROFILER_STACK_DEPTH> sDepth;
|
||||
for (unsigned int i = 0; i < depth; i++)
|
||||
{
|
||||
sDepth += "\t";
|
||||
}
|
||||
|
||||
CryFixedStringT<128> str(p->m_pFuncName);
|
||||
str.replace(':', '_');
|
||||
|
||||
char data[4096];
|
||||
AZ::u64 bytesWritten;
|
||||
|
||||
azsnprintf(data, sizeof(data), "%s<%s selfTime='%f' selfMemory='%f' totalTime='%f' totalMemory='%f' count='%i' totalSeeks='%i' totalReads='%i' totalOpens='%i' totalDiskSize='%f' selfSeeks='%i' selfReads='%i' selfOpens='%i' selfDiskSize='%f'>\n",
|
||||
sDepth.c_str(), str.c_str(), p->m_dSelfTime, p->m_dSelfMemUsage, p->m_dTotalTime, p->m_dTotalMemUsage, p->m_nCounter,
|
||||
p->m_totalInfo.m_nSeeksCount, p->m_totalInfo.m_nFileReadCount, p->m_totalInfo.m_nFileOpenCount, p->m_totalInfo.m_dOperationSize,
|
||||
p->m_selfInfo.m_nSeeksCount, p->m_selfInfo.m_nFileReadCount, p->m_selfInfo.m_nFileOpenCount, p->m_selfInfo.m_dOperationSize);
|
||||
|
||||
AZ::IO::FileIOBase::GetInstance()->Write(handle, data, strlen(data), &bytesWritten);
|
||||
|
||||
for (size_t i = 0, end = p->m_pChilds.size(); i < end; ++i)
|
||||
{
|
||||
WriteTimeContainerToFile(p->m_pChilds[i], handle, depth + 1, fMinTotalTime);
|
||||
}
|
||||
|
||||
azsnprintf(data, sizeof(data), "%s</%s>\n", sDepth.c_str(), str.c_str());
|
||||
AZ::IO::FileIOBase::GetInstance()->Write(handle, data, strlen(data), &bytesWritten);
|
||||
|
||||
}
|
||||
|
||||
void CLoadingProfilerSystem::UpdateSelfStatistics(SLoadingTimeContainer* p)
|
||||
{
|
||||
if (p == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
p->m_dSelfMemUsage = 0;
|
||||
p->m_dSelfTime = 0;
|
||||
p->m_nCounter = 1;
|
||||
p->m_selfInfo.m_dOperationSize = 0;
|
||||
p->m_selfInfo.m_nFileOpenCount = 0;
|
||||
p->m_selfInfo.m_nFileReadCount = 0;
|
||||
p->m_selfInfo.m_nSeeksCount = 0;
|
||||
|
||||
for (size_t i = 0, end = p->m_pChilds.size(); i < end; ++i)
|
||||
{
|
||||
p->m_dTotalMemUsage += p->m_pChilds[i]->m_dTotalMemUsage;
|
||||
p->m_dTotalTime += p->m_pChilds[i]->m_dTotalTime;
|
||||
p->m_totalInfo += p->m_pChilds[i]->m_totalInfo;
|
||||
}
|
||||
}
|
||||
|
||||
void CLoadingProfilerSystem::Clean()
|
||||
{
|
||||
m_iActiveRoot = (m_iActiveRoot + 1) % 2;
|
||||
if (m_pRoot[m_iActiveRoot])
|
||||
{
|
||||
delete m_pRoot[m_iActiveRoot];
|
||||
}
|
||||
m_pCurrentLoadingTimeContainer = m_pRoot[m_iActiveRoot] = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#ifndef CRYINCLUDE_CRYSYSTEM_LOADINGPROFILER_H
|
||||
#define CRYINCLUDE_CRYSYSTEM_LOADINGPROFILER_H
|
||||
#pragma once
|
||||
|
||||
|
||||
#if defined(ENABLE_LOADING_PROFILER)
|
||||
|
||||
struct SLoadingTimeContainer;
|
||||
|
||||
|
||||
struct SLoadingProfilerInfo
|
||||
{
|
||||
string name;
|
||||
double selfTime;
|
||||
double totalTime;
|
||||
uint32 callsTotal;
|
||||
double memorySize;
|
||||
|
||||
DiskOperationInfo selfInfo;
|
||||
DiskOperationInfo totalInfo;
|
||||
};
|
||||
|
||||
|
||||
class CLoadingProfilerSystem
|
||||
{
|
||||
public:
|
||||
static void Init();
|
||||
static void ShutDown();
|
||||
static void CreateNoStackList(PodArray<SLoadingTimeContainer>&);
|
||||
static void OutputLoadingTimeStats(ILog* pLog, int nMode);
|
||||
static SLoadingTimeContainer* StartLoadingSectionProfiling(CLoadingTimeProfiler* pProfiler, const char* szFuncName);
|
||||
static void EndLoadingSectionProfiling(CLoadingTimeProfiler* pProfiler);
|
||||
static const char* GetLoadingProfilerCallstack();
|
||||
static void FillProfilersList(AZStd::vector<SLoadingProfilerInfo>& profilers);
|
||||
static void FlushTimeContainers();
|
||||
static void SaveTimeContainersToFile(const char*, double fMinTotalTime, bool bClean);
|
||||
static void WriteTimeContainerToFile(SLoadingTimeContainer* p, AZ::IO::HandleType &handle, unsigned int depth, double fMinTotalTime);
|
||||
|
||||
static void UpdateSelfStatistics(SLoadingTimeContainer* p);
|
||||
static void Clean();
|
||||
protected:
|
||||
static void AddTimeContainerFunction(PodArray<SLoadingTimeContainer>&, SLoadingTimeContainer*);
|
||||
protected:
|
||||
static int nLoadingProfileMode;
|
||||
static int nLoadingProfilerNotTrackedAllocations;
|
||||
static CryCriticalSection csLock;
|
||||
static int m_iMaxArraySize;
|
||||
static SLoadingTimeContainer* m_pCurrentLoadingTimeContainer;
|
||||
static SLoadingTimeContainer* m_pRoot[2];
|
||||
static int m_iActiveRoot;
|
||||
static ICVar* m_pEnableProfile;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif // CRYINCLUDE_CRYSYSTEM_LOADINGPROFILER_H
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <ISystem.h>
|
||||
|
||||
#include <AzCore/Socket/AzSocket.h>
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
|
||||
#undef LockDebug
|
||||
//#define LockDebug(str1,str2) {string strMessage;strMessage.Format(str1,str2);if (m_clients.size()) OutputDebugString(strMessage.c_str());}
|
||||
@@ -46,16 +47,13 @@ public:
|
||||
|
||||
const char* path = nullptr; // Don't call GetGameFolder here, it returns a full absolute path and we just really want the game name
|
||||
|
||||
if (ICVar* pVar = gEnv->pConsole->GetCVar("sys_game_folder"))
|
||||
{
|
||||
path = pVar->GetString();
|
||||
}
|
||||
if (!path)
|
||||
AZ::IO::FixedMaxPathString projectPath = AZ::Utils::GetProjectPath();
|
||||
if (projectPath.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pNotificationNetwork->Send("SystemInfo", path, ::strlen(path) + 1);
|
||||
pNotificationNetwork->Send("SystemInfo", projectPath.c_str(), projectPath.size());
|
||||
}
|
||||
} g_queryNotification;
|
||||
|
||||
|
||||
@@ -1243,7 +1243,7 @@ namespace
|
||||
{
|
||||
char path[AZ::IO::IArchive::MaxPath];
|
||||
path[sizeof(path) - 1] = 0;
|
||||
gEnv->pCryPak->AdjustFileName("@cache@\\TestResults\\StreamingLog.txt", path, AZ_ARRAY_SIZE(path), AZ::IO::IArchive::FLAGS_PATH_REAL | AZ::IO::IArchive::FLAGS_FOR_WRITING);
|
||||
gEnv->pCryPak->AdjustFileName("@usercache@\\TestResults\\StreamingLog.txt", path, AZ_ARRAY_SIZE(path), AZ::IO::IArchive::FLAGS_PATH_REAL | AZ::IO::IArchive::FLAGS_FOR_WRITING);
|
||||
sFileName = path;
|
||||
}
|
||||
AZ::IO::HandleType fileHandle = fxopen(sFileName, (bFirstTime) ? "wt" : "at");
|
||||
|
||||
@@ -157,7 +157,6 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
#include "ServerThrottle.h"
|
||||
#include "ILocalMemoryUsage.h"
|
||||
#include "ResourceManager.h"
|
||||
#include "LoadingProfiler.h"
|
||||
#include "HMDBus.h"
|
||||
#include "OverloadSceneManager/OverloadSceneManager.h"
|
||||
#include <IThreadManager.h>
|
||||
@@ -168,7 +167,6 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
#include "IZStdDecompressor.h"
|
||||
#include "zlib.h"
|
||||
#include "RemoteConsole/RemoteConsole.h"
|
||||
#include "BootProfiler.h"
|
||||
|
||||
#include <PNoise3.h>
|
||||
#include <StringUtils.h>
|
||||
@@ -320,10 +318,6 @@ CSystem::CSystem(SharedEnvironmentInstance* pSharedEnvironment)
|
||||
m_bIsAsserting = false;
|
||||
m_pSystemEventDispatcher = new CSystemEventDispatcher(); // Must be first.
|
||||
|
||||
#if defined(ENABLE_LOADING_PROFILER)
|
||||
CBootProfiler::GetInstance().Init(this);
|
||||
#endif
|
||||
|
||||
if (m_pSystemEventDispatcher)
|
||||
{
|
||||
m_pSystemEventDispatcher->RegisterListener(this);
|
||||
@@ -422,7 +416,6 @@ CSystem::CSystem(SharedEnvironmentInstance* pSharedEnvironment)
|
||||
// m_sys_filecache = NULL;
|
||||
m_gpu_particle_physics = NULL;
|
||||
m_pCpu = NULL;
|
||||
m_sys_game_folder = NULL;
|
||||
|
||||
m_bInitializedSuccessfully = false;
|
||||
m_bShaderCacheGenMode = false;
|
||||
@@ -634,10 +627,6 @@ void CSystem::ShutDown()
|
||||
EBUS_EVENT(CrySystemEventBus, OnCrySystemShutdown, *this);
|
||||
}
|
||||
|
||||
#if defined(ENABLE_LOADING_PROFILER)
|
||||
CLoadingProfilerSystem::ShutDown();
|
||||
#endif
|
||||
|
||||
if (m_pUserCallback)
|
||||
{
|
||||
m_pUserCallback->OnShutdown();
|
||||
@@ -657,7 +646,7 @@ void CSystem::ShutDown()
|
||||
SAFE_DELETE(m_pTextModeConsole);
|
||||
|
||||
KillPhysicsThread();
|
||||
|
||||
|
||||
if (m_sys_firstlaunch)
|
||||
{
|
||||
m_sys_firstlaunch->Set("0");
|
||||
@@ -828,7 +817,7 @@ void CSystem::ShutDown()
|
||||
void CSystem::Quit()
|
||||
{
|
||||
CryLogAlways("CSystem::Quit invoked from thread %" PRI_THREADID " (main is %" PRI_THREADID ")", GetCurrentThreadId(), gEnv->mMainThreadId);
|
||||
|
||||
|
||||
AzFramework::ApplicationRequests::Bus::Broadcast(&AzFramework::ApplicationRequests::ExitMainLoop);
|
||||
|
||||
// If this was set from anywhere but the main thread, bail and let the main thread handle shutdown
|
||||
@@ -857,13 +846,13 @@ void CSystem::Quit()
|
||||
|
||||
/*
|
||||
* TODO: This call to _exit, _Exit, TerminateProcess etc. needs to
|
||||
* eventually be removed. This causes an extremely early exit before we
|
||||
* actually perform cleanup. When this gets called most managers are
|
||||
* eventually be removed. This causes an extremely early exit before we
|
||||
* actually perform cleanup. When this gets called most managers are
|
||||
* simply never deleted and we leave it to the OS to clean up our mess
|
||||
* which is just really bad practice. However there are LOTS of issues
|
||||
* with shutdown at the moment. Removing this will simply cause
|
||||
* a crash when either the Editor or Launcher initiate shutdown. Both
|
||||
* applications crash differently too. Bugs will be logged about those
|
||||
* with shutdown at the moment. Removing this will simply cause
|
||||
* a crash when either the Editor or Launcher initiate shutdown. Both
|
||||
* applications crash differently too. Bugs will be logged about those
|
||||
* issues.
|
||||
*/
|
||||
#if defined(AZ_RESTRICTED_PLATFORM)
|
||||
@@ -1117,7 +1106,7 @@ void CSystem::CreatePhysicsThread()
|
||||
#include AZ_RESTRICTED_FILE(System_cpp)
|
||||
#endif
|
||||
|
||||
{
|
||||
{
|
||||
m_PhysThread = new CPhysicsThreadTask;
|
||||
GetIThreadTaskManager()->RegisterTask(m_PhysThread, threadParams);
|
||||
}
|
||||
@@ -1412,7 +1401,7 @@ bool CSystem::UpdatePreTickBus(int updateFlags, int nPauseMode)
|
||||
ti.xscale = ti.yscale = 1.2f;
|
||||
|
||||
const int viewportHeight = GetViewCamera().GetViewSurfaceZ();
|
||||
|
||||
|
||||
#if defined(AZ_RESTRICTED_PLATFORM)
|
||||
#define AZ_RESTRICTED_SECTION SYSTEM_CPP_SECTION_8
|
||||
#include AZ_RESTRICTED_FILE(System_cpp)
|
||||
@@ -1428,7 +1417,7 @@ bool CSystem::UpdatePreTickBus(int updateFlags, int nPauseMode)
|
||||
switch (stat.GetType())
|
||||
{
|
||||
case AZ::IO::Statistic::Type::FloatingPoint:
|
||||
gEnv->pRenderer->DrawTextQueued(Vec3(10, y, 1.0f), ti,
|
||||
gEnv->pRenderer->DrawTextQueued(Vec3(10, y, 1.0f), ti,
|
||||
AZStd::string::format("%s/%s: %.3f", stat.GetOwner().data(), stat.GetName().data(), stat.GetFloatValue()).c_str());
|
||||
break;
|
||||
case AZ::IO::Statistic::Type::Integer:
|
||||
@@ -2744,10 +2733,10 @@ bool CSystem::HandleMessage([[maybe_unused]] HWND hWnd, UINT uMsg, WPARAM wParam
|
||||
{
|
||||
// System event translation
|
||||
case WM_CLOSE:
|
||||
/*
|
||||
/*
|
||||
Trigger CSystem to call Quit() the next time
|
||||
it calls Update(). HandleMessages can get messages
|
||||
pumped to it from SyncMainWithRender which would
|
||||
pumped to it from SyncMainWithRender which would
|
||||
be called recurively by Quit(). Doing so would
|
||||
cause the render thread to deadlock and the main
|
||||
thread to spin in SRenderThread::WaitFlushFinishedCond.
|
||||
@@ -2897,11 +2886,6 @@ std::shared_ptr<AZ::IO::FileIOBase> CSystem::CreateLocalFileIO()
|
||||
return std::make_shared<AZ::IO::LocalFileIO>();
|
||||
}
|
||||
|
||||
const char* CSystem::GetAssetsPlatform() const
|
||||
{
|
||||
return m_assetPlatform.c_str();
|
||||
}
|
||||
|
||||
IViewSystem* CSystem::GetIViewSystem()
|
||||
{
|
||||
return m_pViewSystem;
|
||||
|
||||
@@ -45,7 +45,6 @@ struct IConsoleCmdArgs;
|
||||
class CServerThrottle;
|
||||
struct ICryFactoryRegistryImpl;
|
||||
struct IZLibCompressor;
|
||||
class CLoadingProfilerSystem;
|
||||
class CWatchdogThread;
|
||||
class CThreadManager;
|
||||
|
||||
@@ -437,11 +436,6 @@ public:
|
||||
|
||||
uint32 GetUsedMemory();
|
||||
|
||||
//! For asset processor, we need to know what kind of assets we're loading. This comes all the way from bootstrap.cfg
|
||||
//! It will be a string like "pc" or "es3" or such and controls what kind of assets we have access to (its used when for example
|
||||
//! attempting to open a file when multiple different assets for different platforms are available.)
|
||||
const char* GetAssetsPlatform() const;
|
||||
|
||||
virtual void DumpMemoryUsageStatistics(bool bUseKB);
|
||||
virtual void DumpMemoryCoverage();
|
||||
void CollectMemInfo(SCryEngineStatsGlobalMemInfo&);
|
||||
@@ -685,7 +679,7 @@ private:
|
||||
bool InitRenderer(WIN_HINSTANCE hinst, WIN_HWND hwnd, const SSystemInitParams& initParams);
|
||||
|
||||
bool InitFont(const SSystemInitParams& initParams);
|
||||
bool InitFileSystem(const SSystemInitParams& initParams);
|
||||
bool InitFileSystem();
|
||||
bool InitFileSystem_LoadEngineFolders(const SSystemInitParams& initParams);
|
||||
bool InitStreamEngine();
|
||||
bool Init3DEngine(const SSystemInitParams& initParams);
|
||||
@@ -792,7 +786,7 @@ public:
|
||||
|
||||
const CTimeValue& GetLastTickTime(void) const { return m_lastTickTime; }
|
||||
const ICVar* GetDedicatedMaxRate(void) const { return m_svDedicatedMaxRate; }
|
||||
|
||||
|
||||
const char* GetRenderingDriverName(void) const
|
||||
{
|
||||
if(m_rDriver)
|
||||
@@ -802,7 +796,7 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::shared_ptr<AZ::IO::FileIOBase> CreateLocalFileIO();
|
||||
|
||||
// Gets the dimensions (in pixels) of the primary physical display.
|
||||
@@ -914,7 +908,6 @@ private: // ------------------------------------------------------
|
||||
|
||||
// DLL names
|
||||
ICVar* m_sys_dll_response_system;
|
||||
ICVar* m_sys_game_folder;
|
||||
#if !defined(_RELEASE)
|
||||
ICVar* m_sys_resource_cache_folder;
|
||||
#endif
|
||||
@@ -950,7 +943,6 @@ private: // ------------------------------------------------------
|
||||
ICVar* m_rFullscreenWindow;
|
||||
ICVar* m_rFullscreenNativeRes;
|
||||
ICVar* m_rDriver;
|
||||
ICVar* m_cvGameName;
|
||||
ICVar* m_rDisplayInfo;
|
||||
ICVar* m_rOverscanBordersDrawDebugView;
|
||||
ICVar* m_sysNoUpdate;
|
||||
@@ -1040,8 +1032,6 @@ private: // ------------------------------------------------------
|
||||
|
||||
uint64 m_nUpdateCounter;
|
||||
|
||||
int sys_ProfileLevelLoading, sys_ProfileLevelLoadingDump;
|
||||
|
||||
bool m_executedCommandLine = false;
|
||||
|
||||
AZStd::unique_ptr<AzFramework::MissingAssetLogger> m_missingAssetLogger;
|
||||
@@ -1072,18 +1062,6 @@ public:
|
||||
void CloseLanguageAudioPak(const char* sLanguage);
|
||||
void UpdateMovieSystem(const int updateFlags, const float fFrameTime, const bool bPreUpdate);
|
||||
|
||||
// level loading profiling
|
||||
virtual void OutputLoadingTimeStats();
|
||||
virtual struct SLoadingTimeContainer* StartLoadingSectionProfiling(CLoadingTimeProfiler* pProfiler, const char* szFuncName);
|
||||
virtual void EndLoadingSectionProfiling(CLoadingTimeProfiler* pProfiler);
|
||||
virtual const char* GetLoadingProfilerCallstack();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
virtual CBootProfilerRecord* StartBootSectionProfiler(const char* name, const char* args);
|
||||
virtual void StopBootSectionProfiler(CBootProfilerRecord* record);
|
||||
virtual void StartBootProfilerSessionFrames(const char* pName);
|
||||
virtual void StopBootProfilerSessionFrames();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CryAssert and error related.
|
||||
virtual bool RegisterErrorObserver(IErrorObserver* errorObserver);
|
||||
@@ -1139,17 +1117,9 @@ protected: // -------------------------------------------------------------
|
||||
ITextModeConsole* m_pTextModeConsole;
|
||||
INotificationNetwork* m_pNotificationNetwork;
|
||||
|
||||
string m_binariesDir;
|
||||
string m_currentLanguageAudio;
|
||||
string m_assetPlatform; // ("es3" / "pc" / etc) describes the KIND of assets we load and controls where they're loaded from
|
||||
string m_systemConfigName; // computed from system_(hardwareplatform)_(assetsPlatform) - eg, system_android_es3.cfg or system_android_opengl.cfg or system_windows_pc.cfg
|
||||
|
||||
// the following variables capture what was set up in the systeminitparams after/during InitFileSystem
|
||||
// They are not actually to be used except to establish aliases like @user@
|
||||
string m_userRootDir;
|
||||
string m_cacheDir;
|
||||
string m_logsDir;
|
||||
|
||||
std::vector< std::pair<CTimeValue, float> > m_updateTimes;
|
||||
|
||||
CMemoryFragmentationProfiler m_MemoryFragmentationProfiler;
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include <AzCore/Console/IConsole.h>
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
#include <AzFramework/StringFunc/StringFunc.h>
|
||||
|
||||
#include "SystemCFG.h"
|
||||
@@ -252,15 +253,8 @@ void CSystem::LogVersion()
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSystem::LogBuildInfo()
|
||||
{
|
||||
ICVar* pGameName = m_env.pConsole->GetCVar("sys_game_name");
|
||||
if (pGameName)
|
||||
{
|
||||
CryLogAlways("GameName: %s", pGameName->GetString());
|
||||
}
|
||||
else
|
||||
{
|
||||
CryLogAlways("Couldn't find game name in cvar sys_game_name");
|
||||
}
|
||||
auto projectName = AZ::Utils::GetProjectName();
|
||||
CryLogAlways("GameName: %s", projectName.c_str());
|
||||
CryLogAlways("BuildTime: " __DATE__ " " __TIME__);
|
||||
}
|
||||
|
||||
|
||||
@@ -68,6 +68,7 @@
|
||||
#include <LoadScreenBus.h>
|
||||
#include <LyShine/Bus/UiSystemBus.h>
|
||||
#include <AzFramework/Logging/MissingAssetLogger.h>
|
||||
#include <AzFramework/Platform/PlatformDefaults.h>
|
||||
#include <AzFramework/API/AtomActiveInterface.h>
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
@@ -115,8 +116,6 @@
|
||||
#include "SystemCFG.h"
|
||||
#include "AutoDetectSpec.h"
|
||||
#include "ResourceManager.h"
|
||||
#include "LoadingProfiler.h"
|
||||
#include "BootProfiler.h"
|
||||
#include "VisRegTest.h"
|
||||
#include "MTSafeAllocator.h"
|
||||
#include "NotificationNetwork.h"
|
||||
@@ -498,7 +497,7 @@ struct SysSpecOverrideSinkConsole
|
||||
else
|
||||
{
|
||||
// If the cvar doesn't exist, calling this function only saves the value in case it's registered later where
|
||||
// at that point it will be set from the stored value. This is required because otherwise registering the
|
||||
// at that point it will be set from the stored value. This is required because otherwise registering the
|
||||
// cvar bypasses any callbacks and uses values directly from the cvar group files.
|
||||
gEnv->pConsole->LoadConfigVar(szKey, szValue);
|
||||
}
|
||||
@@ -618,13 +617,13 @@ static void LoadDetectedSpec(ICVar* pVar)
|
||||
if (gEnv->IsEditor())
|
||||
{
|
||||
ESystemConfigPlatform configPlatform = GetISystem()->GetConfigPlatform();
|
||||
// Check if the config platform is set first.
|
||||
// Check if the config platform is set first.
|
||||
if (configPlatform != CONFIG_INVALID_PLATFORM)
|
||||
{
|
||||
platform = configPlatform;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AZStd::string configFile;
|
||||
GetSpecConfigFileToLoad(pVar, configFile, platform);
|
||||
if (configFile.length())
|
||||
@@ -779,7 +778,7 @@ static void LoadDetectedSpec(ICVar* pVar)
|
||||
MobileSysInspect::GetSpecForGPUAndAPI(adapterDesc, apiver, gpuConfigFile);
|
||||
GetISystem()->LoadConfiguration(gpuConfigFile.c_str(), pSysSpecOverrideSinkConsole);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
if (bMultiGPUEnabled)
|
||||
{
|
||||
@@ -832,23 +831,7 @@ AZStd::unique_ptr<AZ::DynamicModuleHandle> CSystem::LoadDynamiclibrary(const cha
|
||||
{
|
||||
AZStd::unique_ptr<AZ::DynamicModuleHandle> handle = AZ::DynamicModuleHandle::Create(dllName);
|
||||
|
||||
bool libraryLoaded = false;
|
||||
#ifdef WIN32
|
||||
if (m_binariesDir.empty())
|
||||
{
|
||||
libraryLoaded = handle->Load(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
char currentDirectory[1024];
|
||||
AZ::Utils::GetExecutableDirectory(currentDirectory, AZ_ARRAY_SIZE(currentDirectory));
|
||||
SetCurrentDirectory(m_binariesDir.c_str());
|
||||
libraryLoaded = handle->Load(false);
|
||||
SetCurrentDirectory(currentDirectory);
|
||||
}
|
||||
#else
|
||||
libraryLoaded = handle->Load(false);
|
||||
#endif
|
||||
bool libraryLoaded = handle->Load(false);
|
||||
// We need to inject the environment first thing so that allocators are available immediately
|
||||
InjectEnvironmentFunction injectEnv = handle->GetFunction<InjectEnvironmentFunction>(INJECT_ENVIRONMENT_FUNCTION);
|
||||
if (injectEnv)
|
||||
@@ -974,7 +957,7 @@ bool CSystem::InitializeEngineModule(const char* dllName, const char* moduleClas
|
||||
#endif
|
||||
#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED)
|
||||
#undef AZ_RESTRICTED_SECTION_IMPLEMENTED
|
||||
#else
|
||||
#else
|
||||
|
||||
dllfile.append(dllName);
|
||||
|
||||
@@ -1007,7 +990,7 @@ bool CSystem::InitializeEngineModule(const char* dllName, const char* moduleClas
|
||||
if (CryCreateClassInstance(moduleClassName, pModule))
|
||||
{
|
||||
bResult = pModule->Initialize(m_env, initParams);
|
||||
|
||||
|
||||
// After initializing the module, give it a chance to register any AZ console vars
|
||||
// declared within the module.
|
||||
pModule->RegisterConsoleVars();
|
||||
@@ -1453,7 +1436,7 @@ bool CSystem::InitRenderer(WIN_HINSTANCE hinst, WIN_HWND hwnd, const SSystemInit
|
||||
|
||||
displayWidth *= scaleFactor;
|
||||
displayHeight *= scaleFactor;
|
||||
|
||||
|
||||
const int maxWidth = m_rMaxWidth->GetIVal();
|
||||
if (maxWidth > 0 && maxWidth < displayWidth)
|
||||
{
|
||||
@@ -1524,7 +1507,7 @@ bool CSystem::InitRenderer(WIN_HINSTANCE hinst, WIN_HWND hwnd, const SSystemInit
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
bool CSystem::InitFileSystem(const SSystemInitParams& initParams)
|
||||
bool CSystem::InitFileSystem()
|
||||
{
|
||||
LOADING_TIME_PROFILE_SECTION;
|
||||
using namespace AzFramework::AssetSystem;
|
||||
@@ -1549,136 +1532,6 @@ bool CSystem::InitFileSystem(const SSystemInitParams& initParams)
|
||||
}
|
||||
#endif // !defined(_RELEASE)
|
||||
|
||||
bool usingAssetCache = initParams.UseAssetCache();
|
||||
const char* rootPath = usingAssetCache ? initParams.rootPathCache : initParams.rootPath;
|
||||
const char* assetsPath = usingAssetCache ? initParams.assetsPathCache : initParams.assetsPath;
|
||||
|
||||
if (rootPath == 0)
|
||||
{
|
||||
AZ_Assert(false, "No root path specified in SystemInitParams");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (assetsPath == 0)
|
||||
{
|
||||
AZ_Assert(false, "No assets path specified in SystemInitParams");
|
||||
return false;
|
||||
}
|
||||
|
||||
// establish the root folder and assets folder immediately.
|
||||
// Other folders that can be computed from the root can be specified later.
|
||||
m_env.pFileIO->SetAlias("@root@", rootPath);
|
||||
m_env.pFileIO->SetAlias("@assets@", assetsPath);
|
||||
|
||||
if (initParams.userPath[0] == 0)
|
||||
{
|
||||
string outPath = PathUtil::Make(m_env.pFileIO->GetAlias("@root@"), "user");
|
||||
|
||||
m_env.pFileIO->SetAlias("@user@", outPath.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_env.pFileIO->SetAlias("@user@", initParams.userPath);
|
||||
}
|
||||
|
||||
if (initParams.logPath[0] == 0)
|
||||
{
|
||||
char resolveBuffer[AZ_MAX_PATH_LEN] = { 0 };
|
||||
|
||||
m_env.pFileIO->ResolvePath("@user@", resolveBuffer, AZ_MAX_PATH_LEN);
|
||||
string outPath = PathUtil::Make(resolveBuffer, "log");
|
||||
m_env.pFileIO->SetAlias("@log@", outPath.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_env.pFileIO->SetAlias("@log@", initParams.logPath);
|
||||
}
|
||||
|
||||
m_env.pFileIO->CreatePath("@root@");
|
||||
m_env.pFileIO->CreatePath("@user@");
|
||||
m_env.pFileIO->CreatePath("@log@");
|
||||
|
||||
if ((!m_env.IsInToolMode()) || (m_bShaderCacheGenMode)) // in tool mode, the promise is that you won't access @cache@!
|
||||
{
|
||||
string finalCachePath;
|
||||
if (initParams.cachePath[0] == 0)
|
||||
{
|
||||
char resolveBuffer[AZ_MAX_PATH_LEN] = { 0 };
|
||||
|
||||
m_env.pFileIO->ResolvePath("@user@", resolveBuffer, AZ_MAX_PATH_LEN);
|
||||
finalCachePath = PathUtil::Make(resolveBuffer, "cache");
|
||||
}
|
||||
else
|
||||
{
|
||||
finalCachePath = initParams.cachePath;
|
||||
}
|
||||
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
// Search for a non-locked cache directory because shaders require separate caches for each running instance.
|
||||
// We only need to do this check for Windows, because consoles can't have multiple instances running simultaneously.
|
||||
// Ex: running editor and game, running multiple games, or multiple non-interactive editor instances
|
||||
// for parallel level exports.
|
||||
|
||||
string originalPath = finalCachePath;
|
||||
#if defined(REMOTE_ASSET_PROCESSOR)
|
||||
bool allowEngineConnection = !initParams.bToolMode && !initParams.bTestMode;
|
||||
bool allowRemoteIO = allowEngineConnection && initParams.remoteFileIO && !initParams.bEditor;
|
||||
|
||||
if (!allowRemoteIO) // not running on VFS
|
||||
#endif
|
||||
{
|
||||
int attemptNumber = 0;
|
||||
|
||||
// The number of max attempts ultimately dictates the number of Lumberyard instances that can run
|
||||
// simultaneously. This should be a reasonably high number so that it doesn't artificially limit
|
||||
// the number of instances (ex: parallel level exports via multiple Editor runs). It also shouldn't
|
||||
// be set *infinitely* high - each cache folder is GBs in size, and finding a free directory is a
|
||||
// linear search, so the more instances we allow, the longer the search will take.
|
||||
// 128 seems like a reasonable compromise.
|
||||
constexpr int maxAttempts = 128;
|
||||
|
||||
char workBuffer[AZ_MAX_PATH_LEN] = { 0 };
|
||||
while (attemptNumber < maxAttempts)
|
||||
{
|
||||
finalCachePath = originalPath;
|
||||
if (attemptNumber != 0)
|
||||
{
|
||||
azsnprintf(workBuffer, AZ_MAX_PATH_LEN, "%s%i", originalPath.c_str(), attemptNumber);
|
||||
finalCachePath = workBuffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
finalCachePath = originalPath;
|
||||
}
|
||||
|
||||
++attemptNumber; // do this here so we don't forget
|
||||
|
||||
m_env.pFileIO->CreatePath(finalCachePath.c_str());
|
||||
// if the directory already exists, check for locked file
|
||||
string outLockPath = PathUtil::Make(finalCachePath.c_str(), "lockfile.txt");
|
||||
|
||||
// note, the zero here after GENERIC_READ|GENERIC_WRITE indicates no share access at all
|
||||
g_cacheLock = CreateFileA(outLockPath.c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, 0, 0);
|
||||
if (g_cacheLock != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (attemptNumber >= maxAttempts)
|
||||
{
|
||||
AZ_Assert(false, "Couldn't find a valid asset cache folder for the Asset Processor after %i attempts.", attemptNumber);
|
||||
AZ_Printf("FileSystem", "Couldn't find a valid asset cache folder for the Asset Processor after %i attempts.", attemptNumber);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // defined(AZ_PLATFORM_WINDOWS)
|
||||
AZ_Printf("FileSystem", "Using %s folder for asset cache.\n", finalCachePath.c_str());
|
||||
m_env.pFileIO->SetAlias("@cache@", finalCachePath.c_str());
|
||||
m_env.pFileIO->CreatePath("@cache@");
|
||||
}
|
||||
|
||||
m_env.pCryPak = AZ::Interface<AZ::IO::IArchive>::Get();
|
||||
m_env.pFileIO = AZ::IO::FileIOBase::GetInstance();
|
||||
AZ_Assert(m_env.pCryPak, "CryPak has not been initialized on AZ::Interface");
|
||||
@@ -1755,7 +1608,6 @@ void CSystem::ShutdownFileSystem()
|
||||
bool CSystem::InitFileSystem_LoadEngineFolders(const SSystemInitParams& initParams)
|
||||
{
|
||||
LOADING_TIME_PROFILE_SECTION;
|
||||
// Load value of sys_game_folder from system.cfg into the sys_game_folder console variable
|
||||
{
|
||||
ILoadConfigurationEntrySink* pCVarsWhiteListConfigSink = GetCVarsWhiteListConfigSink();
|
||||
LoadConfiguration(m_systemConfigName.c_str(), pCVarsWhiteListConfigSink);
|
||||
@@ -1767,17 +1619,19 @@ bool CSystem::InitFileSystem_LoadEngineFolders(const SSystemInitParams& initPara
|
||||
#endif
|
||||
|
||||
GetISystem()->SetConfigPlatform(GetDevicePlatform());
|
||||
|
||||
|
||||
#if defined(CRY_ENABLE_RC_HELPER)
|
||||
if (!m_env.pResourceCompilerHelper)
|
||||
{
|
||||
m_env.pResourceCompilerHelper = new CResourceCompilerHelper();
|
||||
}
|
||||
#endif
|
||||
// you may not set these in game.cfg or in system.cfg
|
||||
m_sys_game_folder->ForceSet(initParams.gameFolderName);
|
||||
|
||||
AZ_Printf(AZ_TRACE_SYSTEM_WINDOW, "GameDir: %s\n", m_sys_game_folder->GetString());
|
||||
auto projectPath = AZ::Utils::GetProjectPath();
|
||||
AZ_Printf(AZ_TRACE_SYSTEM_WINDOW, "Project Path: %s\n", projectPath.empty() ? "None specified" : projectPath.c_str());
|
||||
|
||||
auto projectName = AZ::Utils::GetProjectName();
|
||||
AZ_Printf(AZ_TRACE_SYSTEM_WINDOW, "Project Name: %s\n", projectName.empty() ? "None specified" : projectName.c_str());
|
||||
|
||||
// simply open all paks if fast load pak can't be found
|
||||
if (!m_pResourceManager->LoadFastLoadPaks(true))
|
||||
@@ -1857,7 +1711,7 @@ bool CSystem::InitFont(const SSystemInitParams& initParams)
|
||||
bool CSystem::Init3DEngine(const SSystemInitParams& initParams)
|
||||
{
|
||||
LOADING_TIME_PROFILE_SECTION(GetISystem());
|
||||
|
||||
|
||||
if (!InitializeEngineModule(DLL_3DENGINE, "EngineModule_Cry3DEngine", initParams))
|
||||
{
|
||||
return false;
|
||||
@@ -1930,7 +1784,7 @@ bool CSystem::InitVTuneProfiler()
|
||||
LOADING_TIME_PROFILE_SECTION(GetISystem());
|
||||
|
||||
#ifdef PROFILE_WITH_VTUNE
|
||||
|
||||
|
||||
WIN_HMODULE hModule = LoadDLL("VTuneApi.dll");
|
||||
if (!hModule)
|
||||
{
|
||||
@@ -2033,7 +1887,7 @@ void CSystem::OpenBasicPaks()
|
||||
bBasicPaksLoaded = true;
|
||||
|
||||
LOADING_TIME_PROFILE_SECTION;
|
||||
|
||||
|
||||
// open pak files
|
||||
constexpr AZStd::string_view paksFolder = "@assets@/*.pak"; // (@assets@ assumed)
|
||||
m_env.pCryPak->OpenPacks(paksFolder);
|
||||
@@ -2188,12 +2042,6 @@ string GetUniqueLogFileName(string logFileName)
|
||||
}
|
||||
|
||||
|
||||
|
||||
void OnLevelLoadingDump([[maybe_unused]] ICVar* pArgs)
|
||||
{
|
||||
gEnv->pSystem->OutputLoadingTimeStats();
|
||||
}
|
||||
|
||||
#if defined(WIN32) || defined(WIN64)
|
||||
static wstring GetErrorStringUnsupportedCPU()
|
||||
{
|
||||
@@ -2415,8 +2263,8 @@ bool CSystem::Init(const SSystemInitParams& startupParams)
|
||||
signal(SIGILL, CryEngineSignalHandler);
|
||||
#endif // AZ_TRAIT_USE_CRY_SIGNAL_HANDLER
|
||||
|
||||
// Temporary Fix for an issue accessing gEnv from this object instance. The gEnv is not resolving to the
|
||||
// global gEnv, instead its resolving an some uninitialized gEnv elsewhere (NULL). Since gEnv is
|
||||
// Temporary Fix for an issue accessing gEnv from this object instance. The gEnv is not resolving to the
|
||||
// global gEnv, instead its resolving an some uninitialized gEnv elsewhere (NULL). Since gEnv is
|
||||
// initialized to this instance's SSystemGlobalEnvironment (m_env), we will force set it again here
|
||||
// to m_env
|
||||
if (!gEnv)
|
||||
@@ -2451,7 +2299,7 @@ bool CSystem::Init(const SSystemInitParams& startupParams)
|
||||
// Linux is all console for now and so no room for dialog boxes!
|
||||
m_env.bNoAssertDialog = true;
|
||||
#endif
|
||||
|
||||
|
||||
m_pCmdLine = new CCmdLine(startupParams.szSystemCmdLine);
|
||||
|
||||
AZCoreLogSink::Connect();
|
||||
@@ -2461,25 +2309,25 @@ bool CSystem::Init(const SSystemInitParams& startupParams)
|
||||
{
|
||||
azConsole->LinkDeferredFunctors(AZ::ConsoleFunctorBase::GetDeferredHead());
|
||||
}
|
||||
|
||||
m_assetPlatform = startupParams.assetsPlatform;
|
||||
|
||||
// compute system config name
|
||||
if (m_assetPlatform.empty())
|
||||
|
||||
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry)
|
||||
{
|
||||
AZ_Error(AZ_TRACE_SYSTEM_WINDOW, false, R"(A valid asset platform is missing in "%s/assets" key in the SettingsRegistry.)""\n"
|
||||
R"(This can be set via the via the --regset "%s/assets=<value>" command line option)"
|
||||
R"(, by setting value at the "%s/assets path" within a *.setreg file that is loaded by the application)"
|
||||
R"( or by setting the "assets" field in the bootstrap.cfg.)",
|
||||
AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey,
|
||||
AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey,
|
||||
AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey);
|
||||
return false;
|
||||
}
|
||||
AZ::SettingsRegistryInterface::FixedValueString assetPlatform;
|
||||
if (!AZ::SettingsRegistryMergeUtils::PlatformGet(*settingsRegistry, assetPlatform,
|
||||
AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey, "assets"))
|
||||
{
|
||||
assetPlatform = AzFramework::OSPlatformToDefaultAssetPlatform(AZ_TRAIT_OS_PLATFORM_CODENAME);
|
||||
AZ_Warning(AZ_TRACE_SYSTEM_WINDOW, false, R"(A valid asset platform is missing in "%s/assets" key in the SettingsRegistry.)""\n"
|
||||
R"(This typically done by setting he "assets" field in the bootstrap.cfg for within a .setreg file)""\n"
|
||||
R"(A fallback of %s will be used.)",
|
||||
AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey,
|
||||
assetPlatform.c_str());
|
||||
}
|
||||
|
||||
m_systemConfigName = "system_" AZ_TRAIT_OS_PLATFORM_CODENAME_LOWER "_";
|
||||
m_systemConfigName += m_assetPlatform;
|
||||
m_systemConfigName += ".cfg";
|
||||
m_systemConfigName = "system_" AZ_TRAIT_OS_PLATFORM_CODENAME_LOWER "_";
|
||||
m_systemConfigName += assetPlatform.c_str();
|
||||
m_systemConfigName += ".cfg";
|
||||
}
|
||||
|
||||
AZ_Assert(CryMemory::IsHeapValid(), "Memory heap must be valid before continuing SystemInit.");
|
||||
|
||||
@@ -2518,11 +2366,6 @@ AZ_POP_DISABLE_WARNING
|
||||
m_hInst = (WIN_HINSTANCE)startupParams.hInstance;
|
||||
m_hWnd = (WIN_HWND)startupParams.hWnd;
|
||||
|
||||
m_userRootDir = startupParams.userPath;
|
||||
m_logsDir = startupParams.logPath;
|
||||
m_cacheDir = startupParams.cachePath;
|
||||
|
||||
m_binariesDir = startupParams.szBinariesDir;
|
||||
m_bEditor = startupParams.bEditor;
|
||||
m_bPreviewMode = startupParams.bPreview;
|
||||
m_bTestMode = startupParams.bTestMode;
|
||||
@@ -2666,17 +2509,13 @@ AZ_POP_DISABLE_WARNING
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// File system, must be very early
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (!InitFileSystem(startupParams))
|
||||
if (!InitFileSystem())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
InlineInitializationProcessing("CSystem::Init InitFileSystem");
|
||||
|
||||
#if defined(ENABLE_LOADING_PROFILER)
|
||||
CLoadingProfilerSystem::Init();
|
||||
#endif
|
||||
|
||||
m_missingAssetLogger = AZStd::make_unique<AzFramework::MissingAssetLogger>();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -2786,10 +2625,6 @@ AZ_POP_DISABLE_WARNING
|
||||
|
||||
GetIRemoteConsole()->RegisterConsoleVariables();
|
||||
|
||||
#ifdef ENABLE_LOADING_PROFILER
|
||||
CBootProfiler::GetInstance().RegisterCVars();
|
||||
#endif
|
||||
|
||||
if (!startupParams.bSkipConsole)
|
||||
{
|
||||
// Register system console variables.
|
||||
@@ -2827,7 +2662,7 @@ AZ_POP_DISABLE_WARNING
|
||||
m_env.pCryPak->OpenPack("@assets@", "Engine.pak");
|
||||
#if defined(AZ_PLATFORM_ANDROID) || defined(AZ_PLATFORM_IOS)
|
||||
MobileSysInspect::LoadDeviceSpecMapping();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
InitFileSystem_LoadEngineFolders(startupParams);
|
||||
|
||||
@@ -3472,10 +3307,6 @@ AZ_POP_DISABLE_WARNING
|
||||
MarkThisThreadForDebugging("Main");
|
||||
}
|
||||
|
||||
#if defined(ENABLE_LOADING_PROFILER)
|
||||
CLoadingProfilerSystem::SaveTimeContainersToFile("EngineStart.crylp", 0.0, true);
|
||||
#endif
|
||||
|
||||
InlineInitializationProcessing("CSystem::Init End");
|
||||
|
||||
#if defined(IS_PROSDK)
|
||||
@@ -4188,7 +4019,7 @@ static void ScreenshotCmd(IConsoleCmdArgs* pParams)
|
||||
}
|
||||
}
|
||||
|
||||
// Helper to maintain backwards compatibility with our CVar but not force our new code to
|
||||
// Helper to maintain backwards compatibility with our CVar but not force our new code to
|
||||
// pull in CryCommon by routing through an environment variable
|
||||
void CmdSetAwsLogLevel(IConsoleCmdArgs* pArgs)
|
||||
{
|
||||
@@ -4424,7 +4255,6 @@ void CSystem::CreateSystemVars()
|
||||
// Register DLL names as cvars before we load them
|
||||
//
|
||||
EVarFlags dllFlags = (EVarFlags)0;
|
||||
m_sys_game_folder = REGISTER_STRING("sys_game_folder", "EmptyTemplate", VF_READONLY, "Specifies the game folder to read all data from. Can be fully pathed for external folders or relative path for folders inside the root.");
|
||||
m_sys_dll_response_system = REGISTER_STRING("sys_dll_response_system", 0, dllFlags, "Specifies the DLL to load for the dynamic response system");
|
||||
|
||||
m_sys_initpreloadpacks = REGISTER_STRING("sys_initpreloadpacks", "", 0, "Specifies the paks for an engine initialization");
|
||||
@@ -4447,8 +4277,6 @@ void CSystem::CreateSystemVars()
|
||||
m_level_load_screen_minimum_time = REGISTER_FLOAT("level_load_screen_minimum_time", 0.0f, 0, "Minimum amount of time to show the level load screen. Important to prevent short loads from flashing the load screen. 0 means there is no limit.");
|
||||
#endif // if AZ_LOADSCREENCOMPONENT_ENABLED
|
||||
|
||||
m_cvGameName = REGISTER_STRING("sys_game_name", "Lumberyard", VF_DUMPTODISK, "Specifies the name to be displayed in the Launcher window title bar");
|
||||
|
||||
REGISTER_INT("cvDoVerboseWindowTitle", 0, VF_NULL, "");
|
||||
|
||||
m_pCVarQuit = REGISTER_INT("ExitOnQuit", 1, VF_NULL, "");
|
||||
@@ -4495,7 +4323,7 @@ void CSystem::CreateSystemVars()
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
attachVariable("sys_PakReadSlice", &g_cvars.archiveVars.nReadSlice, "If non-0, means number of kilobytes to use to read files in portions. Should only be used on Win9x kernels");
|
||||
|
||||
attachVariable("sys_PakInMemorySizeLimit", &g_cvars.archiveVars.nInMemoryPerPakSizeLimit, "Individual pak size limit for being loaded into memory (MB)");
|
||||
@@ -4818,15 +4646,6 @@ void CSystem::CreateSystemVars()
|
||||
"e.g. LoadConfig lowspec.cfg\n"
|
||||
"Usage: LoadConfig <filename>");
|
||||
|
||||
REGISTER_CVAR(sys_ProfileLevelLoading, 0, VF_CHEAT,
|
||||
"Output level loading stats into log\n"
|
||||
"0 = Off\n"
|
||||
"1 = Output basic info about loading time per function\n"
|
||||
"2 = Output full statistics including loading time and memory allocations with call stack info");
|
||||
|
||||
REGISTER_CVAR_CB(sys_ProfileLevelLoadingDump, 0, VF_CHEAT, "Output level loading dump stats into log\n", OnLevelLoadingDump);
|
||||
|
||||
|
||||
assert(m_env.pConsole);
|
||||
m_env.pConsole->CreateKeyBind("alt_keyboard_key_function_F12", "Screenshot");
|
||||
m_env.pConsole->CreateKeyBind("alt_keyboard_key_function_F11", "RecordClip");
|
||||
@@ -4871,7 +4690,7 @@ void CSystem::CreateSystemVars()
|
||||
|
||||
// adding CVAR to toggle assert verbosity level
|
||||
const int defaultAssertValue = 1;
|
||||
REGISTER_CVAR2_CB("sys_asserts", &g_cvars.sys_asserts, defaultAssertValue, VF_CHEAT,
|
||||
REGISTER_CVAR2_CB("sys_asserts", &g_cvars.sys_asserts, defaultAssertValue, VF_CHEAT,
|
||||
"0 = Suppress Asserts\n"
|
||||
"1 = Log Asserts\n"
|
||||
"2 = Show Assert Dialog\n"
|
||||
@@ -4957,78 +4776,6 @@ void CSystem::AddCVarGroupDirectory(const string& sPath)
|
||||
gEnv->pCryPak->FindClose(handle);
|
||||
}
|
||||
|
||||
void CSystem::OutputLoadingTimeStats()
|
||||
{
|
||||
#if defined(ENABLE_LOADING_PROFILER)
|
||||
if (GetIConsole())
|
||||
{
|
||||
if (ICVar* pVar = GetIConsole()->GetCVar("sys_ProfileLevelLoading"))
|
||||
{
|
||||
CLoadingProfilerSystem::OutputLoadingTimeStats(GetILog(), pVar->GetIVal());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
SLoadingTimeContainer* CSystem::StartLoadingSectionProfiling([[maybe_unused]] CLoadingTimeProfiler* pProfiler, [[maybe_unused]] const char* szFuncName)
|
||||
{
|
||||
#if defined(ENABLE_LOADING_PROFILER)
|
||||
return CLoadingProfilerSystem::StartLoadingSectionProfiling(pProfiler, szFuncName);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void CSystem::EndLoadingSectionProfiling([[maybe_unused]] CLoadingTimeProfiler* pProfiler)
|
||||
{
|
||||
#if defined(ENABLE_LOADING_PROFILER)
|
||||
CLoadingProfilerSystem::EndLoadingSectionProfiling(pProfiler);
|
||||
#endif
|
||||
}
|
||||
|
||||
const char* CSystem::GetLoadingProfilerCallstack()
|
||||
{
|
||||
#if defined(ENABLE_LOADING_PROFILER)
|
||||
return CLoadingProfilerSystem::GetLoadingProfilerCallstack();
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
CBootProfilerRecord* CSystem::StartBootSectionProfiler([[maybe_unused]] const char* name, [[maybe_unused]] const char* args)
|
||||
{
|
||||
#if defined(ENABLE_LOADING_PROFILER)
|
||||
CBootProfiler& profiler = CBootProfiler::GetInstance();
|
||||
return profiler.StartBlock(name, args);
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
void CSystem::StopBootSectionProfiler([[maybe_unused]] CBootProfilerRecord* record)
|
||||
{
|
||||
#if defined(ENABLE_LOADING_PROFILER)
|
||||
CBootProfiler& profiler = CBootProfiler::GetInstance();
|
||||
profiler.StopBlock(record);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CSystem::StartBootProfilerSessionFrames([[maybe_unused]] const char* pName)
|
||||
{
|
||||
#if defined(ENABLE_LOADING_PROFILER)
|
||||
CBootProfiler& profiler = CBootProfiler::GetInstance();
|
||||
profiler.StartFrame(pName);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CSystem::StopBootProfilerSessionFrames()
|
||||
{
|
||||
#if defined(ENABLE_LOADING_PROFILER)
|
||||
CBootProfiler& profiler = CBootProfiler::GetInstance();
|
||||
profiler.StopFrame();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool CSystem::RegisterErrorObserver(IErrorObserver* errorObserver)
|
||||
{
|
||||
return stl::push_back_unique(m_errorObservers, errorObserver);
|
||||
|
||||
@@ -92,13 +92,6 @@ static AZStd::vector<AZStd::string> GetModuleNames()
|
||||
moduleNames.push_back("CryFont" MODULE_EXTENSION);
|
||||
moduleNames.push_back("CrySystem" MODULE_EXTENSION);
|
||||
|
||||
if (gEnv && gEnv->pConsole)
|
||||
{
|
||||
string gameModuleNameRaw = gEnv->pConsole->GetCVar("sys_dll_game")->GetString();
|
||||
gameModuleNameRaw.append(MODULE_EXTENSION);
|
||||
moduleNames.push_back(gameModuleNameRaw.c_str());
|
||||
}
|
||||
|
||||
#undef MODULE_EXTENSION
|
||||
|
||||
# if defined(LINUX)
|
||||
@@ -1076,14 +1069,6 @@ void CSystem::FatalError(const char* format, ...)
|
||||
CryLogAlways("<CrySystem> Last System Error: %s", szSysErrorMessage);
|
||||
}
|
||||
|
||||
if (const char* pLoadingProfilerCallstack = GetLoadingProfilerCallstack())
|
||||
{
|
||||
if (pLoadingProfilerCallstack[0])
|
||||
{
|
||||
CryLogAlways("<CrySystem> LoadingProfilerCallstack: %s", pLoadingProfilerCallstack);
|
||||
}
|
||||
}
|
||||
|
||||
if (GetUserCallback())
|
||||
{
|
||||
GetUserCallback()->OnError(szBuffer);
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
/*
|
||||
* 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 "CrySystem_precompiled.h"
|
||||
|
||||
#include <AzTest/AzTest.h>
|
||||
#include <AzCore/UnitTest/UnitTest.h>
|
||||
#include <AzCore/UnitTest/TestTypes.h>
|
||||
#include <AzCore/Memory/AllocatorScope.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <BootProfiler.h>
|
||||
|
||||
#if defined(ENABLE_LOADING_PROFILER)
|
||||
|
||||
namespace UnitTests
|
||||
{
|
||||
using BootProfilerTestAllocatorScope = AZ::AllocatorScope<AZ::LegacyAllocator, CryStringAllocator>;
|
||||
class BootProfilerTest :
|
||||
public ::testing::Test,
|
||||
BootProfilerTestAllocatorScope,
|
||||
UnitTest::TraceBusRedirector
|
||||
{
|
||||
public:
|
||||
BootProfilerTest()
|
||||
{
|
||||
BootProfilerTestAllocatorScope::ActivateAllocators();
|
||||
UnitTest::TraceBusRedirector::BusConnect();
|
||||
}
|
||||
|
||||
~BootProfilerTest()
|
||||
{
|
||||
UnitTest::TraceBusRedirector::BusDisconnect();
|
||||
BootProfilerTestAllocatorScope::DeactivateAllocators();
|
||||
}
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
TEST_F(BootProfilerTest, BootProfilerTest_StartStopBlocksInThreads_Success)
|
||||
{
|
||||
CBootProfiler testProfiler;
|
||||
const char scopeName[] = "TestScope";
|
||||
const char blockArg[] = "TestArg";
|
||||
const int numAttempts = 1000;
|
||||
const int numThreads = 10;
|
||||
|
||||
auto switchSessionFunc = [&]() {
|
||||
for (int sessionNum = 0; sessionNum < numAttempts; ++sessionNum)
|
||||
{
|
||||
auto sessionName = AZStd::string::format("TestSession%d", sessionNum);
|
||||
testProfiler.StartSession(sessionName.c_str());
|
||||
testProfiler.StopSession(sessionName.c_str());
|
||||
}
|
||||
};
|
||||
auto testProfileFunc = [&]() {
|
||||
for (int blockNum = 0; blockNum < numAttempts; ++blockNum)
|
||||
{
|
||||
auto someBlock = testProfiler.StartBlock(scopeName, blockArg);
|
||||
testProfiler.StopBlock(someBlock);
|
||||
}
|
||||
};
|
||||
AZStd::thread threadArray[numThreads];
|
||||
|
||||
AZStd::thread sessionThread = AZStd::thread(switchSessionFunc);
|
||||
for (int i = 0; i < numThreads; ++i)
|
||||
{
|
||||
threadArray[i] = AZStd::thread(testProfileFunc);
|
||||
}
|
||||
for (int i = 0; i < numThreads; ++i)
|
||||
{
|
||||
threadArray[i].join();
|
||||
}
|
||||
sessionThread.join();
|
||||
}
|
||||
|
||||
class FrameTestBootProfiler : public CBootProfiler
|
||||
{
|
||||
public:
|
||||
FrameTestBootProfiler(int frameCount) : CBootProfiler()
|
||||
{
|
||||
SetFrameCount(frameCount);
|
||||
}
|
||||
};
|
||||
TEST_F(BootProfilerTest, BootProfilerTest_FrameStartStop_Success)
|
||||
{
|
||||
const int numTestFrames = 10;
|
||||
FrameTestBootProfiler testProfiler(numTestFrames);
|
||||
|
||||
for (int i = 0; i < numTestFrames; ++i)
|
||||
{
|
||||
testProfiler.StartFrame("TestFrame");
|
||||
|
||||
testProfiler.StopFrame();
|
||||
}
|
||||
}
|
||||
} // namespace UnitTests
|
||||
|
||||
#endif
|
||||
@@ -75,15 +75,10 @@ TEST(CrySystemMaterialUtilsTests, MaterialUtilsTestPrefixes)
|
||||
TEST(CrySystemMaterialUtilsTests, MaterialUtilsTestGameName)
|
||||
{
|
||||
char tempBuffer[AZ_MAX_PATH_LEN];
|
||||
|
||||
ICVar* pGameNameCVar = nullptr;
|
||||
if ((gEnv)&&(gEnv->pConsole))
|
||||
{
|
||||
pGameNameCVar = gEnv->pConsole->GetCVar("sys_game_folder");
|
||||
}
|
||||
|
||||
azsnprintf(tempBuffer, AZ_MAX_PATH_LEN, ".\\%s\\materials\\blahblah.mat.mat.abc.test", pGameNameCVar ? pGameNameCVar->GetString() : "SamplesProject");
|
||||
|
||||
auto projectName = AZ::Utils::GetProjectName();
|
||||
azsnprintf(tempBuffer, AZ_MAX_PATH_LEN, ".\\%s\\materials\\blahblah.mat.mat.abc.test", projectName.c_str());
|
||||
|
||||
MaterialUtils::UnifyMaterialName(tempBuffer);
|
||||
EXPECT_TRUE(strcmp(tempBuffer, "materials/blahblah.mat.mat.abc") == 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace CryPakUnitTests
|
||||
AZ::IO::FileIOBase* fileIo = AZ::IO::FileIOBase::GetInstance();
|
||||
ASSERT_NE(nullptr, fileIo);
|
||||
|
||||
constexpr const char* testPakPath = "@cache@/archivecontainerlevel.pak";
|
||||
constexpr const char* testPakPath = "@usercache@/archivecontainerlevel.pak";
|
||||
|
||||
char resolvedArchivePath[AZ_MAX_PATH_LEN] = { 0 };
|
||||
EXPECT_TRUE(fileIo->ResolvePath(testPakPath, resolvedArchivePath, AZ_MAX_PATH_LEN));
|
||||
@@ -116,7 +116,7 @@ namespace CryPakUnitTests
|
||||
AZStd::this_thread::sleep_for(AZStd::chrono::milliseconds{ 100 });
|
||||
|
||||
// helper paths and strings
|
||||
AZStd::string gameFolder = fileIo->GetAlias("@cache@");
|
||||
AZStd::string gameFolder = fileIo->GetAlias("@usercache@");
|
||||
|
||||
AZStd::string testFile = "unittest.bin";
|
||||
AZStd::string testFilePath = gameFolder + "\\" + testFile;
|
||||
|
||||
@@ -297,7 +297,7 @@ void CVisRegTest::CaptureSample(const SCmd& cmd)
|
||||
if (m_cmdFreq == 1) // Final sample
|
||||
{
|
||||
// Screenshot
|
||||
stack_string filename("@cache@/TestResults/VisReg/"); // the default unaliased assets folder is read-only!
|
||||
stack_string filename("@usercache@/TestResults/VisReg/"); // the default unaliased assets folder is read-only!
|
||||
filename += m_testName + "/" + cmd.args.c_str();
|
||||
gEnv->pRenderer->ScreenShot(filename);
|
||||
|
||||
@@ -335,7 +335,7 @@ void CVisRegTest::Finish()
|
||||
|
||||
bool CVisRegTest::WriteResults()
|
||||
{
|
||||
stack_string filename("@cache@/TestResults/VisReg/");
|
||||
stack_string filename("@usercache@/TestResults/VisReg/");
|
||||
filename += m_testName + "/visreg_results.xml";
|
||||
|
||||
AZ::IO::HandleType fileHandle = fxopen(filename.c_str(), "wb");
|
||||
|
||||
@@ -26,7 +26,6 @@ set(FILES
|
||||
IDebugCallStack.cpp
|
||||
AsyncPakManager.cpp
|
||||
Log.cpp
|
||||
BootProfiler.cpp
|
||||
SystemRender.cpp
|
||||
NotificationNetwork.cpp
|
||||
PhysRenderer.cpp
|
||||
@@ -91,7 +90,6 @@ set(FILES
|
||||
WindowsConsole.h
|
||||
XConsole.h
|
||||
XConsoleVariable.h
|
||||
BootProfiler.h
|
||||
crash_face.bmp
|
||||
ImageHandler.h
|
||||
ImageHandler.cpp
|
||||
@@ -121,11 +119,9 @@ set(FILES
|
||||
XML/WriteXMLSource.cpp
|
||||
ZipFile.h
|
||||
ZipFileFormat_info.h
|
||||
LoadingProfiler.cpp
|
||||
PerfHUD.cpp
|
||||
ProfileLogSystem.cpp
|
||||
Sampler.cpp
|
||||
LoadingProfiler.h
|
||||
PerfHUD.h
|
||||
ProfileLogSystem.h
|
||||
Sampler.h
|
||||
|
||||
Reference in New Issue
Block a user