Integrating latest from github/staging
Integrating up through commit 5e1bdae
This commit is contained in:
@@ -1080,7 +1080,7 @@ void C3DEngine::WorldStreamUpdate()
|
||||
|
||||
if (GetCVars()->e_StreamSaveStartupResultsIntoXML)
|
||||
{
|
||||
const char* testResultsFile = "@cache@/TestResults/Streaming_Level_Start_Throughput.xml";
|
||||
const char* testResultsFile = "@usercache@/TestResults/Streaming_Level_Start_Throughput.xml";
|
||||
|
||||
AZ::IO::HandleType resultsFile = gEnv->pCryPak->FOpen(testResultsFile, "wb");
|
||||
if (resultsFile != AZ::IO::InvalidHandle)
|
||||
|
||||
@@ -952,7 +952,7 @@ void C3DEngine::ProcessStreamingLatencyTest(const CCamera& camIn, CCamera& camOu
|
||||
|
||||
if (GetCVars()->e_SQTestCount == 0)
|
||||
{
|
||||
const char* testResultsFile = "@cache@/TestResults/Streaming_Latency_Test.xml";
|
||||
const char* testResultsFile = "@usercache@/TestResults/Streaming_Latency_Test.xml";
|
||||
|
||||
AZ::IO::HandleType resultsFile = gEnv->pCryPak->FOpen(testResultsFile, "wb");
|
||||
if (resultsFile != AZ::IO::InvalidHandle)
|
||||
|
||||
@@ -461,7 +461,7 @@ void C3DEngine::UnloadLevel()
|
||||
m_ptexIconLowMemoryUsage = nullptr;
|
||||
m_ptexIconHighMemoryUsage = nullptr;
|
||||
m_ptexIconEditorConnectedToConsole = nullptr;
|
||||
|
||||
|
||||
if (m_pOpticsManager && !gEnv->IsEditor())
|
||||
{
|
||||
m_pOpticsManager->Reset();
|
||||
@@ -656,7 +656,7 @@ bool C3DEngine::LoadLevel(const char* szFolderName, const char* szMissionName)
|
||||
// set default render parameters.
|
||||
// for some reason this is not done later???
|
||||
m_pSkyLightManager->UpdateRenderParams();
|
||||
}
|
||||
}
|
||||
|
||||
// Load LevelData.xml File.
|
||||
XmlNodeRef xmlLevelData = GetSystem()->LoadXmlFromFile(GetLevelFilePath(LEVEL_DATA_FILE));
|
||||
@@ -687,17 +687,7 @@ bool C3DEngine::LoadLevel(const char* szFolderName, const char* szMissionName)
|
||||
// preload level cgfs
|
||||
if (GetCVars()->e_StatObjPreload && !gEnv->IsEditor())
|
||||
{
|
||||
if (GetCVars()->e_StatObjPreload == 2)
|
||||
{
|
||||
GetSystem()->OutputLoadingTimeStats();
|
||||
}
|
||||
|
||||
m_pObjManager->PreloadLevelObjects();
|
||||
|
||||
if (GetCVars()->e_StatObjPreload == 2)
|
||||
{
|
||||
GetSystem()->OutputLoadingTimeStats();
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<struct IStatObj*>* pStatObjTable = NULL;
|
||||
|
||||
@@ -317,7 +317,8 @@ int CLightEntity::UpdateGSMLightSourceDynamicShadowFrustum(int nDynamicLodCount,
|
||||
|
||||
if (bDoGSM)
|
||||
{
|
||||
Vec3 vSunDir = Get3DEngine()->GetSunDir().GetNormalized(); // todo: remove GetNormalized() once GetSunDir() returns the normalized value
|
||||
//Vec3 vSunDir = Get3DEngine()->GetSunDir().GetNormalized(); // todo: remove GetNormalized() once GetSunDir() returns the normalized value
|
||||
Vec3 vSunDir = Vec3(1.0f, 0.0f, 0.0f);
|
||||
Vec3 vCameraDirWithoutDepth = vCameraDir - vCameraDir.Dot(vSunDir) * vSunDir;
|
||||
|
||||
Vec3 vFocusPos = passInfo.GetCamera().GetPosition() + vCameraDirWithoutDepth * fGSMBoxSize;
|
||||
|
||||
@@ -117,10 +117,6 @@ CMatInfo::CMatInfo()
|
||||
|
||||
ZeroStruct(m_streamZoneInfo);
|
||||
|
||||
#ifdef TRACE_MATERIAL_LEAKS
|
||||
m_sLoadingCallstack = GetSystem()->GetLoadingProfilerCallstack();
|
||||
#endif
|
||||
|
||||
// Used to know when a .dccmtl file has been changed,
|
||||
// requiring the source material to be updated
|
||||
m_dccMaterialHash = 0;
|
||||
@@ -341,7 +337,7 @@ ISurfaceType* CMatInfo::GetSurfaceType()
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CMatInfo::SetSubMtlCount(int numSubMtl)
|
||||
{
|
||||
AUTO_LOCK(GetSubMaterialResizeLock());
|
||||
AUTO_LOCK(GetSubMaterialResizeLock());
|
||||
if (numSubMtl > 0)
|
||||
{
|
||||
m_Flags |= MTL_FLAG_MULTI_SUBMTL;
|
||||
@@ -1112,15 +1108,6 @@ void CMatInfo::SetTexelDensityDebug([[maybe_unused]] int mode)
|
||||
#endif
|
||||
}
|
||||
|
||||
const char* CMatInfo::GetLoadingCallstack()
|
||||
{
|
||||
#ifdef TRACE_MATERIAL_LEAKS
|
||||
return m_sLoadingCallstack.c_str();
|
||||
#else
|
||||
return "";
|
||||
#endif
|
||||
}
|
||||
|
||||
void CMatInfo::PrecacheMaterial(const float _fEntDistance, IRenderMesh* pRenderMesh, bool bFullUpdate, bool bDrawNear)
|
||||
{
|
||||
// FUNCTION_PROFILER_3DENGINE;
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#include <IMaterial.h>
|
||||
|
||||
#if !defined(CONSOLE)
|
||||
# define TRACE_MATERIAL_LEAKS
|
||||
# define SUPPORT_MATERIAL_EDITING
|
||||
#endif
|
||||
|
||||
@@ -203,7 +202,7 @@ public:
|
||||
bool SetGetMaterialParamFloat(const char* sParamName, float& v, bool bGet, bool allowShaderParam = false, int materialIndex = 0) override;
|
||||
bool SetGetMaterialParamVec3(const char* sParamName, Vec3& v, bool bGet, bool allowShaderParam = false, int materialIndex = 0) override;
|
||||
bool SetGetMaterialParamVec4(const char* sParamName, Vec4& v, bool bGet, bool allowShaderParam = false, int materialIndex = 0) override;
|
||||
|
||||
|
||||
void SetDirty(bool dirty = true) override;
|
||||
bool IsDirty() const override;
|
||||
|
||||
@@ -264,11 +263,6 @@ public:
|
||||
bool IsForwardRenderingRequired();
|
||||
bool IsNearestCubemapRequired();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Debug routines
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
virtual const char* GetLoadingCallstack(); // trace leaking materials by callstack
|
||||
|
||||
void DisableTextureStreaming() override;
|
||||
virtual void RequestTexturesLoading(const float fMipFactor);
|
||||
|
||||
@@ -286,13 +280,6 @@ public:
|
||||
void SetDccMaterialHash(uint32 hash) override { m_dccMaterialHash = hash; }
|
||||
|
||||
virtual CryCriticalSection& GetSubMaterialResizeLock();
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// for debug purposes
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
#ifdef TRACE_MATERIAL_LEAKS
|
||||
string m_sLoadingCallstack;
|
||||
#endif
|
||||
|
||||
private:
|
||||
friend class CMatMan;
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#pragma once
|
||||
|
||||
#if !defined(CONSOLE)
|
||||
# define TRACE_CGF_LEAKS
|
||||
# define SUPPORT_TERRAIN_AO_PRE_COMPUTATIONS
|
||||
#endif
|
||||
|
||||
@@ -337,13 +336,6 @@ public:
|
||||
std::vector<uint16> m_chunkBoneIds;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// for debug purposes
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
#ifdef TRACE_CGF_LEAKS
|
||||
string m_sLoadingCallstack;
|
||||
#endif
|
||||
|
||||
private:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Sub objects.
|
||||
@@ -419,7 +411,7 @@ public:
|
||||
virtual unsigned int GetBreakableByGame() { return m_bBreakableByGame; };
|
||||
|
||||
//Note: This function checks both the children and root data
|
||||
//It should really be 'has any deformable objects'
|
||||
//It should really be 'has any deformable objects'
|
||||
//Should eventually be refactored as part of an eventual statobj refactor.
|
||||
virtual bool IsDeformable() override;
|
||||
|
||||
|
||||
@@ -56,10 +56,6 @@ CStatObj::CStatObj()
|
||||
m_fLodDistance = 0.0f;
|
||||
|
||||
Init();
|
||||
|
||||
#ifdef TRACE_CGF_LEAKS
|
||||
m_sLoadingCallstack = GetSystem()->GetLoadingProfilerCallstack();
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -1064,7 +1064,7 @@ namespace Audio
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Interface methods
|
||||
virtual bool Initialize(const SSystemInitParams* initParams) = 0;
|
||||
virtual bool Initialize() = 0;
|
||||
virtual void Release() = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -392,7 +392,7 @@ struct IMaterial
|
||||
virtual void SetDirty(bool dirty = true) = 0;
|
||||
virtual bool IsDirty() const = 0;
|
||||
|
||||
//! Returns true if the material is the parent of a group of materials
|
||||
//! Returns true if the material is the parent of a group of materials
|
||||
virtual bool IsMaterialGroup() const = 0;
|
||||
|
||||
//! Returns true if the material is a single material belongs to a material group
|
||||
@@ -411,11 +411,6 @@ struct IMaterial
|
||||
// - 2, fast sketch mode.
|
||||
virtual void SetSketchMode(int mode) = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Debug routines
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
virtual const char* GetLoadingCallstack() = 0; // trace leaking materials by callstack
|
||||
|
||||
// Sets FT_DONT_STREAM flag for all textures used by the material
|
||||
// If a stream is already in process, this will stop the stream and flush the device texture
|
||||
virtual void DisableTextureStreaming() = 0;
|
||||
|
||||
@@ -119,8 +119,6 @@ namespace AZ
|
||||
|
||||
class IResourceCompilerHelper;
|
||||
|
||||
class CBootProfilerRecord;
|
||||
|
||||
namespace Serialization {
|
||||
struct IArchiveHost;
|
||||
}
|
||||
@@ -629,15 +627,7 @@ struct SSystemInitParams
|
||||
void* hWnd; //
|
||||
void* hWndForInputSystem; // the HWND for the input devices, distinct from the hWnd, which the rendering system overrides anyways
|
||||
|
||||
char remoteIP[256];
|
||||
int remotePort;
|
||||
bool remoteFileIO;
|
||||
bool remoteResourceCompiler;
|
||||
bool connectToRemote;
|
||||
bool waitForConnection; // if true, wait for the remote connection to be established before proceeding to system init.
|
||||
char assetsPlatform[64]; // what flavor of assets to load. Corresponds to those in rc.ini and asset processor ini
|
||||
char gameFolderName[256]; // just the name. Not the full path.
|
||||
char branchToken[12]; // information written by the assetprocessor which help determine whether the game/editor are running from the same branch or not
|
||||
|
||||
ILog* pLog; // You can specify your own ILog to be used by System.
|
||||
ILogCallback* pLogCallback; // You can specify your own ILogCallback to be added on log creation (used by Editor).
|
||||
@@ -648,45 +638,6 @@ struct SSystemInitParams
|
||||
IOutputPrintSink* pPrintSync; // Print Sync which can be used to catch all output from engine
|
||||
char szSystemCmdLine[2048]; // Command line.
|
||||
|
||||
|
||||
// set some paths before you create the system.
|
||||
|
||||
// rootPath - (REQUIRED) folder containing root. Must contain system.cfg or bootstrap.cfg basically.
|
||||
// the remainder are optional and if specified should contain prefixes that can be prepended to any file to get to that location:
|
||||
// READ ONLY!
|
||||
char rootPath[256];
|
||||
char rootPathCache[256];
|
||||
|
||||
// assetsPath - (REQUIRED) - where you assets live. The engine config parser will default this to @root@/gamename
|
||||
// READ ONLY!
|
||||
char assetsPath[256];
|
||||
char assetsPathCache[256];
|
||||
|
||||
// userPath - (OPTIONAL) User path contains a folder for preferences persistent storage. May be persisted to the cloud (by things like IOS)
|
||||
// If not specified, this is assumed @root@/User/
|
||||
// WRITABLE
|
||||
char userPath[256];
|
||||
|
||||
// cachePath - (OPTIONAL) a temporary store that can be erased at any time and does not need to be persisted
|
||||
// on the cloud or anything like that. if not specified, this will be @user@/Cache
|
||||
// WRITABLE
|
||||
char cachePath[256];
|
||||
|
||||
// logPath - (OPTIONAL) a log path folder.
|
||||
// If not specified, it will be @cache@/Logs
|
||||
// WRITABLE
|
||||
char logPath[256];
|
||||
|
||||
// the game should never use these values instead, the game should be using crypak or fileio with aliases:
|
||||
// @root@ To get to the folder where system.cfg lives
|
||||
// @assets@ to get to the folder containing game assets (textures and such) - by default, this is @root@/Gamename/
|
||||
// @devroot@ to get to source files that are checked into source control (PC EDITOR ONLY!)
|
||||
// @engroot@ to get to path to the engine root folder
|
||||
// @user@ to access user store
|
||||
// @cache@ to access temporary cache
|
||||
// @log@ to access log file and other forensic storage
|
||||
char szBinariesDir[256];
|
||||
|
||||
bool bEditor; // When running in Editor mode.
|
||||
bool bPreview; // When running in Preview mode (Minimal initialization).
|
||||
bool bTestMode; // When running in Automated testing mode.
|
||||
@@ -730,26 +681,7 @@ struct SSystemInitParams
|
||||
hWnd = NULL;
|
||||
hWndForInputSystem = NULL;
|
||||
|
||||
memset(rootPath, 0, sizeof(rootPath));
|
||||
memset(rootPathCache, 0, sizeof(rootPathCache));
|
||||
memset(userPath, 0, sizeof(userPath));
|
||||
memset(assetsPath, 0, sizeof(assetsPath));
|
||||
memset(assetsPathCache, 0, sizeof(assetsPathCache));
|
||||
memset(cachePath, 0, sizeof(cachePath));
|
||||
memset(logPath, 0, sizeof(logPath));
|
||||
memset(gameFolderName, 0, sizeof(gameFolderName));
|
||||
memset(branchToken, 0, sizeof(branchToken));
|
||||
|
||||
memset(remoteIP, 0, sizeof(remoteIP));
|
||||
azstrcpy(remoteIP, sizeof(remoteIP), "127.0.0.1");
|
||||
memset(assetsPlatform, 0, sizeof(assetsPlatform));
|
||||
azstrcpy(assetsPlatform, sizeof(assetsPlatform), "pc");
|
||||
|
||||
remotePort = 45643;
|
||||
remoteFileIO = false;
|
||||
remoteResourceCompiler = false;
|
||||
connectToRemote = false;
|
||||
waitForConnection = false;
|
||||
|
||||
pLog = NULL;
|
||||
pLogCallback = NULL;
|
||||
@@ -762,7 +694,6 @@ struct SSystemInitParams
|
||||
pValidator = NULL;
|
||||
pPrintSync = NULL;
|
||||
memset(szSystemCmdLine, 0, sizeof(szSystemCmdLine));
|
||||
memset(szBinariesDir, 0, sizeof(szBinariesDir));
|
||||
|
||||
bEditor = false;
|
||||
bPreview = false;
|
||||
@@ -798,17 +729,6 @@ struct SSystemInitParams
|
||||
|
||||
pSharedEnvironment = nullptr;
|
||||
}
|
||||
|
||||
bool UseAssetCache() const
|
||||
{
|
||||
#if defined(AZ_PLATFORM_WINDOWS) || defined(AZ_PLATFORM_MAC) || defined(AZ_PLATFORM_LINUX)
|
||||
char checkPath[AZ_MAX_PATH_LEN] = { 0 };
|
||||
azsnprintf(checkPath, AZ_MAX_PATH_LEN, "%s/engine.json", rootPathCache);
|
||||
return AZ::IO::SystemFile::Exists(checkPath);
|
||||
#else
|
||||
return false;
|
||||
#endif // defined(AZ_PLATFORM_WINDOWS) || AZ_TRAIT_OS_PLATFORM_APPLE
|
||||
}
|
||||
};
|
||||
|
||||
// Notes:
|
||||
@@ -1228,11 +1148,6 @@ struct ISystem
|
||||
// Gets number of CPUs
|
||||
virtual int GetLogicalCPUCount() = 0;
|
||||
|
||||
//! Get the 'kind' of assets you need to load - this describes the flavor of assets you are going to load
|
||||
//! based on the platform you're on - so for example, android on ES3 will be 'es3' but android on opengl might load PC assets or others...
|
||||
//! This is defined in bootstrap.cfg and is read-only during runtime.
|
||||
virtual const char* GetAssetsPlatform() const = 0;
|
||||
|
||||
// Summary:
|
||||
// Return the rendering driver name. GL or Metal
|
||||
virtual const char* GetRenderingDriverName() const = 0;
|
||||
@@ -1406,43 +1321,6 @@ struct ISystem
|
||||
// True if system running in Test mode.
|
||||
virtual bool IsTestMode() const = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Loading time/memory profiling
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Summary:
|
||||
// Starts function loading stats profiling.
|
||||
virtual struct SLoadingTimeContainer* StartLoadingSectionProfiling(CLoadingTimeProfiler* pProfiler, const char* szFuncName) = 0;
|
||||
|
||||
// Summary:
|
||||
// Ends function loading stats profiling.
|
||||
virtual void EndLoadingSectionProfiling(CLoadingTimeProfiler* pProfiler) = 0;
|
||||
|
||||
// Summary:
|
||||
// Starts function profiling with bootprofiler (session must be started).
|
||||
virtual CBootProfilerRecord* StartBootSectionProfiler(const char* name, const char* args) = 0;
|
||||
|
||||
// Summary:
|
||||
// Ends function profiling with bootprofiler.
|
||||
virtual void StopBootSectionProfiler(CBootProfilerRecord* record) = 0;
|
||||
|
||||
|
||||
// Summary:
|
||||
// Starts frame session
|
||||
virtual void StartBootProfilerSessionFrames(const char* pName) = 0;
|
||||
|
||||
// Summary:
|
||||
// Stops frame session
|
||||
virtual void StopBootProfilerSessionFrames() = 0;
|
||||
|
||||
// Summary:
|
||||
// Prints loading stats into log.
|
||||
virtual void OutputLoadingTimeStats() = 0;
|
||||
|
||||
// Summary:
|
||||
// Starts function loading stats profiling.
|
||||
virtual const char* GetLoadingProfilerCallstack() = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// File version.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -1581,10 +1459,10 @@ struct ISystem
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Summary:
|
||||
// Enable/Disable drawing the console
|
||||
// Enable/Disable drawing the console
|
||||
virtual void SetConsoleDrawEnabled(bool enabled) = 0;
|
||||
|
||||
// Enable/Disable drawing the UI
|
||||
// Enable/Disable drawing the UI
|
||||
virtual void SetUIDrawEnabled(bool enabled) = 0;
|
||||
|
||||
// Summary:
|
||||
@@ -1772,79 +1650,19 @@ struct DiskOperationInfo
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(ENABLE_LOADING_PROFILER)
|
||||
|
||||
struct CLoadingTimeProfiler
|
||||
{
|
||||
CLoadingTimeProfiler(ISystem* pSystem, const char* szFuncName)
|
||||
: m_pSystem(pSystem)
|
||||
{
|
||||
m_pSystem = pSystem;
|
||||
m_pTimeContainer = m_pSystem->StartLoadingSectionProfiling(this, szFuncName);
|
||||
}
|
||||
|
||||
~CLoadingTimeProfiler()
|
||||
{
|
||||
m_pSystem->EndLoadingSectionProfiling(this);
|
||||
}
|
||||
|
||||
struct SLoadingTimeContainer* m_pTimeContainer;
|
||||
double m_fConstructorTime;
|
||||
double m_fConstructorMemUsage;
|
||||
|
||||
DiskOperationInfo m_constructorInfo;
|
||||
|
||||
ISystem* m_pSystem;
|
||||
};
|
||||
|
||||
class CSYSBootProfileBlock
|
||||
{
|
||||
ISystem* m_pSystem;
|
||||
CBootProfilerRecord* m_pRecord;
|
||||
public:
|
||||
CSYSBootProfileBlock(ISystem* pSystem, const char* name, const char* args = NULL)
|
||||
: m_pSystem(pSystem)
|
||||
{
|
||||
if (m_pSystem)
|
||||
{
|
||||
m_pRecord = m_pSystem->StartBootSectionProfiler(name, args);
|
||||
}
|
||||
}
|
||||
|
||||
~CSYSBootProfileBlock()
|
||||
{
|
||||
if (m_pSystem)
|
||||
{
|
||||
m_pSystem->StopBootSectionProfiler(m_pRecord);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef AZ_PROFILE_TELEMETRY
|
||||
#if defined(ENABLE_LOADING_PROFILER) && AZ_PROFILE_TELEMETRY
|
||||
|
||||
#define LOADING_TIME_PROFILE_SECTION AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzCore)
|
||||
#define LOADING_TIME_PROFILE_SECTION_ARGS(...) AZ_PROFILE_SCOPE_DYNAMIC(AZ::Debug::ProfileCategory::AzCore, __VA_ARGS__)
|
||||
#define LOADING_TIME_PROFILE_SECTION_NAMED(sectionName) AZ_PROFILE_SCOPE(AZ::Debug::ProfileCategory::AzCore, sectionName)
|
||||
#define LOADING_TIME_PROFILE_SECTION_NAMED_ARGS(sectionName, args) AZ_PROFILE_SCOPE_DYNAMIC(AZ::Debug::ProfileCategory::AzCore, sectionName, args)
|
||||
|
||||
#else
|
||||
|
||||
#define LOADING_TIME_PROFILE_SECTION CSYSBootProfileBlock AZ_JOIN(_profileBlockLine, __LINE__)(gEnv && gEnv->pSystem ? gEnv->pSystem : nullptr, __FUNCTION__);
|
||||
#define LOADING_TIME_PROFILE_SECTION_ARGS(args) CSYSBootProfileBlock AZ_JOIN(_profileBlockLine, __LINE__)(gEnv->pSystem, __FUNCTION__, args);
|
||||
#define LOADING_TIME_PROFILE_SECTION_NAMED(sectionName) CSYSBootProfileBlock AZ_JOIN(_profileBlockLine, __LINE__)(gEnv->pSystem, sectionName);
|
||||
#define LOADING_TIME_PROFILE_SECTION_NAMED_ARGS(sectionName, args) CSYSBootProfileBlock AZ_JOIN(_profileBlockLine, __LINE__)(gEnv->pSystem, sectionName, args);
|
||||
|
||||
#endif // AZ_PROFILE_TELEMETRY
|
||||
#define LOADING_TIME_PROFILE_SECTION_NAMED_ARGS(sectionName, ...) AZ_PROFILE_SCOPE_DYNAMIC(AZ::Debug::ProfileCategory::AzCore, sectionName, __VA_ARGS__)
|
||||
|
||||
#else
|
||||
|
||||
#define LOADING_TIME_PROFILE_SECTION
|
||||
#define LOADING_TIME_PROFILE_SECTION_ARGS(args)
|
||||
#define LOADING_TIME_PROFILE_SECTION_ARGS(...)
|
||||
#define LOADING_TIME_PROFILE_SECTION_NAMED(sectionName)
|
||||
#define LOADING_TIME_PROFILE_SECTION_NAMED_ARGS(sectionName, args)
|
||||
#define LOADING_TIME_PROFILE_SESSION_SECTION(sessionName)
|
||||
#define LOADING_TIME_PROFILE_SESSION_START(sessionName)
|
||||
#define LOADING_TIME_PROFILE_SESSION_STOP(sessionName)
|
||||
#define LOADING_TIME_PROFILE_SECTION_NAMED_ARGS(sectionName, ...)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1865,7 +1683,7 @@ extern SC_API SSystemGlobalEnvironment* gEnv;
|
||||
inline ISystem* GetISystem()
|
||||
{
|
||||
// Some unit tests temporarily install and then uninstall ISystem* mocks.
|
||||
// It is generally okay for runtime and tool systems which call this function to cache the returned pointer,
|
||||
// It is generally okay for runtime and tool systems which call this function to cache the returned pointer,
|
||||
// because their lifetime is usually shorter than the lifetime of the ISystem* implementation.
|
||||
// It is NOT safe for this function to cache it as a static itself, though, as the static it would cache
|
||||
// it inside may outlive the the actual instance implementing ISystem* when unit tests are torn down and then restarted.
|
||||
|
||||
@@ -15,10 +15,12 @@
|
||||
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/IO/SystemFile.h> // for max path len
|
||||
#include <ISystem.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
#include <AzFramework/StringFunc/StringFunc.h>
|
||||
|
||||
#include <ISystem.h>
|
||||
|
||||
namespace MaterialUtils
|
||||
{
|
||||
//! UnifyMaterialName - given a non-unified material name, remove the extension, unify the slashes
|
||||
@@ -75,14 +77,11 @@ namespace MaterialUtils
|
||||
static char cachedGameName[AZ_MAX_PATH_LEN] = { 0 };
|
||||
if (!removals[removalSize - 1])
|
||||
{
|
||||
if ((gEnv) && (gEnv->pConsole))
|
||||
auto projectName = AZ::Utils::GetProjectName();
|
||||
if (!projectName.empty())
|
||||
{
|
||||
ICVar* pGameNameCVar = gEnv->pConsole->GetCVar("sys_game_folder");
|
||||
if (pGameNameCVar)
|
||||
{
|
||||
azstrcpy(cachedGameName, AZ_MAX_PATH_LEN, pGameNameCVar->GetString());
|
||||
azstrcat(cachedGameName, AZ_MAX_PATH_LEN, "/");
|
||||
}
|
||||
azstrcpy(cachedGameName, AZ_MAX_PATH_LEN, projectName.c_str());
|
||||
azstrcat(cachedGameName, AZ_MAX_PATH_LEN, "/");
|
||||
}
|
||||
|
||||
if (cachedGameName[0] == 0)
|
||||
|
||||
@@ -55,8 +55,6 @@ public:
|
||||
int());
|
||||
MOCK_METHOD0(GetLogicalCPUCount,
|
||||
int());
|
||||
MOCK_CONST_METHOD0(GetAssetsPlatform,
|
||||
const char*());
|
||||
MOCK_CONST_METHOD0(GetRenderingDriverName,
|
||||
const char*());
|
||||
MOCK_METHOD1(DumpMemoryUsageStatistics,
|
||||
@@ -206,22 +204,6 @@ public:
|
||||
bool());
|
||||
MOCK_METHOD3(SetFrameProfiler,
|
||||
void(bool on, bool display, char* prefix));
|
||||
MOCK_METHOD2(StartLoadingSectionProfiling,
|
||||
struct SLoadingTimeContainer*(CLoadingTimeProfiler * pProfiler, const char* szFuncName));
|
||||
MOCK_METHOD1(EndLoadingSectionProfiling,
|
||||
void(CLoadingTimeProfiler * pProfiler));
|
||||
MOCK_METHOD2(StartBootSectionProfiler,
|
||||
CBootProfilerRecord * (const char* name, const char* args));
|
||||
MOCK_METHOD1(StopBootSectionProfiler,
|
||||
void(CBootProfilerRecord * record));
|
||||
MOCK_METHOD1(StartBootProfilerSessionFrames,
|
||||
void(const char* pName));
|
||||
MOCK_METHOD0(StopBootProfilerSessionFrames,
|
||||
void());
|
||||
MOCK_METHOD0(OutputLoadingTimeStats,
|
||||
void());
|
||||
MOCK_METHOD0(GetLoadingProfilerCallstack,
|
||||
const char*());
|
||||
MOCK_METHOD0(GetFileVersion,
|
||||
const SFileVersion&());
|
||||
MOCK_METHOD0(GetProductVersion,
|
||||
|
||||
@@ -1,160 +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.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ISystem.h"
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
#include <AzFramework/Platform/PlatformDefaults.h>
|
||||
|
||||
// any of the following tags can be present in the bootstrap.cfg
|
||||
// you can also prefix it with a platform.
|
||||
// so for example, you can specify remote_ip alone to specify it for all platforms
|
||||
// or you could specify android_remote_ip to change it for android only.
|
||||
// the instructions are executed in the order that they appear, so you can set the default
|
||||
// by using the non-platform-specific version, and then later on in the file you
|
||||
// can override specific platforms.
|
||||
|
||||
#define CONFIG_KEY_FOR_REMOTEIP "remote_ip"
|
||||
#define CONFIG_KEY_FOR_REMOTEPORT "remote_port"
|
||||
#define CONFIG_KEY_FOR_GAMEFOLDER "sys_game_folder"
|
||||
#define CONFIG_KEY_FOR_REMOTEFILEIO "remote_filesystem"
|
||||
#define CONFIG_KEY_FOR_CONNECTTOREMOTE "connect_to_remote"
|
||||
#define CONFIG_KEY_WAIT_FOR_CONNECT "wait_for_connect"
|
||||
#define DEFAULT_GAMEDLL "EmptyTemplate"
|
||||
#define DEFAULT_GAMEFOLDER "EmptyTemplate"
|
||||
#define DEFAULT_REMOTEIP "127.0.0.1"
|
||||
#define DEFAULT_REMOTEPORT 45643
|
||||
#define CONFIG_KEY_FOR_ASSETS "assets"
|
||||
#define CONFIG_KEY_FOR_BRANCHTOKEN "assetProcessor_branch_token"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
class CEngineConfig
|
||||
{
|
||||
public:
|
||||
string m_gameFolder; // folder only ("MyGame")
|
||||
string m_assetPlatform; // what platform folder assets are from if more than one is available or using VFS ("pc" / "es3")
|
||||
bool m_connectToRemote;
|
||||
bool m_remoteFileIO;
|
||||
bool m_waitForConnect;
|
||||
string m_remoteIP;
|
||||
int m_remotePort;
|
||||
|
||||
string m_rootFolder; // The engine root folder
|
||||
string m_branchToken;
|
||||
|
||||
CEngineConfig([[maybe_unused]] const char** sourcePaths = nullptr, [[maybe_unused]] size_t numSearchPaths = 0, [[maybe_unused]] size_t numLevelsUp = 3)
|
||||
: m_gameFolder(DEFAULT_GAMEFOLDER)
|
||||
, m_connectToRemote(false)
|
||||
, m_remoteFileIO(false)
|
||||
, m_remotePort(DEFAULT_REMOTEPORT)
|
||||
, m_waitForConnect(false)
|
||||
, m_remoteIP(DEFAULT_REMOTEIP)
|
||||
{
|
||||
m_assetPlatform = AzFramework::OSPlatformToDefaultAssetPlatform(AZ_TRAIT_OS_PLATFORM_CODENAME);
|
||||
|
||||
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
|
||||
{
|
||||
AZ::SettingsRegistryInterface::FixedValueString gameFolder;
|
||||
auto gameFolderKey = AZ::SettingsRegistryInterface::FixedValueString::format("%s/%s",
|
||||
AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey, CONFIG_KEY_FOR_GAMEFOLDER);
|
||||
if (settingsRegistry->Get(gameFolder, gameFolderKey))
|
||||
{
|
||||
m_gameFolder.assign(gameFolder.c_str(), gameFolder.size());
|
||||
}
|
||||
|
||||
AZ::SettingsRegistryInterface::FixedValueString engineRoot;
|
||||
if (settingsRegistry->Get(engineRoot, AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder))
|
||||
{
|
||||
m_rootFolder.assign(engineRoot.c_str(), engineRoot.size());
|
||||
}
|
||||
}
|
||||
|
||||
OnLoadSettings();
|
||||
}
|
||||
|
||||
void CopyToStartupParams(SSystemInitParams& startupParams) const
|
||||
{
|
||||
startupParams.remoteFileIO = m_remoteFileIO;
|
||||
startupParams.remotePort = m_remotePort;
|
||||
startupParams.connectToRemote = m_connectToRemote;
|
||||
startupParams.waitForConnection = m_waitForConnect;
|
||||
|
||||
azstrncpy(startupParams.remoteIP, sizeof(startupParams.remoteIP), m_remoteIP.c_str(), m_remoteIP.length() + 1); // +1 for the null terminator
|
||||
azstrncpy(startupParams.assetsPlatform, sizeof(startupParams.assetsPlatform), m_assetPlatform.c_str(), m_assetPlatform.length() + 1); // +1 for the null terminator
|
||||
azstrncpy(startupParams.rootPath, sizeof(startupParams.rootPath), m_rootFolder.c_str(), m_rootFolder.length() + 1); // +1 for the null terminator
|
||||
azstrncpy(startupParams.gameFolderName, sizeof(startupParams.gameFolderName), m_gameFolder.c_str(), m_gameFolder.length() + 1); // +1 for the null terminator
|
||||
azstrncpy(startupParams.branchToken, sizeof(startupParams.branchToken), m_branchToken.c_str(), m_branchToken.length() + 1); // +1 for the null terminator
|
||||
|
||||
// compute assets path based on game folder name
|
||||
string gameFolderLower(m_gameFolder);
|
||||
gameFolderLower.MakeLower();
|
||||
azsnprintf(startupParams.assetsPath, sizeof(startupParams.assetsPath), "%s/%s", startupParams.rootPath, gameFolderLower.c_str());
|
||||
|
||||
// compute where the cache should be located
|
||||
azsnprintf(startupParams.rootPathCache, sizeof(startupParams.rootPathCache), "%s/Cache/%s/%s", m_rootFolder.c_str(), m_gameFolder.c_str(), m_assetPlatform.c_str());
|
||||
azsnprintf(startupParams.assetsPathCache, sizeof(startupParams.assetsPathCache), "%s/%s", startupParams.rootPathCache, gameFolderLower.c_str());
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
void OnLoadSettings()
|
||||
{
|
||||
auto settingsRegistry = AZ::SettingsRegistry::Get();
|
||||
if (settingsRegistry == nullptr)
|
||||
{
|
||||
AZ_Warning("ParseEngineConfig", false, "Attempting to load configuration data while SettingsRegistry does not exist");
|
||||
return;
|
||||
|
||||
}
|
||||
AZ::SettingsRegistryInterface::FixedValueString settingsKeyPrefix = AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey;
|
||||
AZ::SettingsRegistryInterface::FixedValueString settingsValueString;
|
||||
AZ::s64 settingsValueInt{};
|
||||
|
||||
if (AZ::SettingsRegistryMergeUtils::PlatformGet(*settingsRegistry, settingsValueInt, settingsKeyPrefix, CONFIG_KEY_FOR_REMOTEFILEIO))
|
||||
{
|
||||
m_remoteFileIO = settingsValueInt != 0;
|
||||
}
|
||||
if (AZ::SettingsRegistryMergeUtils::PlatformGet(*settingsRegistry, settingsValueInt, settingsKeyPrefix, CONFIG_KEY_WAIT_FOR_CONNECT))
|
||||
{
|
||||
m_waitForConnect = settingsValueInt != 0;
|
||||
}
|
||||
if (AZ::SettingsRegistryMergeUtils::PlatformGet(*settingsRegistry, settingsValueInt, settingsKeyPrefix, CONFIG_KEY_FOR_CONNECTTOREMOTE))
|
||||
{
|
||||
m_connectToRemote = settingsValueInt != 0;
|
||||
}
|
||||
if (AZ::SettingsRegistryMergeUtils::PlatformGet(*settingsRegistry, settingsValueInt, settingsKeyPrefix, CONFIG_KEY_FOR_REMOTEPORT))
|
||||
{
|
||||
m_remotePort = aznumeric_cast<AZ::u16>(settingsValueInt);
|
||||
}
|
||||
if (settingsValueString = {};
|
||||
AZ::SettingsRegistryMergeUtils::PlatformGet(*settingsRegistry, settingsValueString, settingsKeyPrefix, CONFIG_KEY_FOR_REMOTEIP))
|
||||
{
|
||||
m_remoteIP.assign(settingsValueString.c_str(), settingsValueString.size());
|
||||
}
|
||||
if (settingsValueString = {};
|
||||
AZ::SettingsRegistryMergeUtils::PlatformGet(*settingsRegistry, settingsValueString, settingsKeyPrefix, CONFIG_KEY_FOR_ASSETS))
|
||||
{
|
||||
m_assetPlatform.assign(settingsValueString.c_str(), settingsValueString.size());
|
||||
}
|
||||
if (settingsValueString = {};
|
||||
settingsRegistry->Get(settingsValueString, settingsKeyPrefix + "/" + CONFIG_KEY_FOR_BRANCHTOKEN))
|
||||
{
|
||||
m_branchToken.assign(settingsValueString.c_str(), settingsValueString.size());
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
@@ -293,7 +293,7 @@ typedef uint32 vtx_idx;
|
||||
|
||||
#if defined(ENABLE_PROFILING_CODE)
|
||||
# define USE_DISK_PROFILER
|
||||
//# define ENABLE_LOADING_PROFILER // Not guaranteed to have enough slots for all the threads in the system
|
||||
# define ENABLE_LOADING_PROFILER // requires AZ_PROFILE_TELEMETRY to also be defined
|
||||
#endif
|
||||
|
||||
#if defined(SOFTCODE_ENABLED)
|
||||
|
||||
@@ -110,7 +110,6 @@ set(FILES
|
||||
AzDXGIFormat.h
|
||||
SFunctor.h
|
||||
FunctorBaseFunction.h
|
||||
ParseEngineConfig.h
|
||||
CustomMemoryHeap.h
|
||||
FunctorBaseMember.h
|
||||
stridedptr.h
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -902,7 +902,7 @@ void ShadersOptimizeHelper(CallableT setupParserBin, const char* logString)
|
||||
{
|
||||
setupParserBin();
|
||||
CryLogAlways("\nStarting shaders optimizing for %s...", logString);
|
||||
AZStd::string str = "@cache@/" + gRenDev->m_cEF.m_ShadersCache;
|
||||
AZStd::string str = "@usercache@/" + gRenDev->m_cEF.m_ShadersCache;
|
||||
iLog->Log("Optimize shader cache folder: '%s'", gRenDev->m_cEF.m_ShadersCache.c_str());
|
||||
gRenDev->m_cEF.mfOptimiseShaders(str.c_str(), false);
|
||||
}
|
||||
@@ -2396,7 +2396,7 @@ void CRenderer::InitRenderer()
|
||||
|
||||
CV_r_ShaderCompilerFolderSuffix = REGISTER_STRING("r_ShaderCompilerFolderSuffix", "", VF_NULL,
|
||||
"Usage: r_ShaderCompilerFolderSuffix suffix \n"
|
||||
"Default is empty. Set to some other value to append this suffix to the sys_game_folder when compiling shaders");
|
||||
"Default is empty. Set to some other value to append this suffix to the project name when compiling shaders");
|
||||
|
||||
{
|
||||
const SFileVersion& ver = gEnv->pSystem->GetFileVersion();
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <AzCore/Socket/AzSocket.h>
|
||||
#include <AzCore/NativeUI/NativeUIRequests.h>
|
||||
#include <AzCore/PlatformId/PlatformId.h>
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
#include <AzFramework/Network/SocketConnection.h>
|
||||
#include <AzFramework/Asset/AssetSystemTypes.h>
|
||||
|
||||
@@ -306,23 +307,20 @@ namespace NRemoteCompiler
|
||||
|
||||
m_RequestLineRootFolder = "";
|
||||
|
||||
ICVar* pGameFolder = gEnv->pConsole->GetCVar("sys_game_folder");
|
||||
auto projectName = AZ::Utils::GetProjectName();
|
||||
ICVar* pCompilerFolderSuffix = CRenderer::CV_r_ShaderCompilerFolderSuffix;
|
||||
|
||||
if (pGameFolder)
|
||||
if (!projectName.empty())
|
||||
{
|
||||
string folder = pGameFolder->GetString();
|
||||
folder.Trim();
|
||||
if (!folder.empty())
|
||||
if (pCompilerFolderSuffix)
|
||||
{
|
||||
if (pCompilerFolderSuffix)
|
||||
{
|
||||
string suffix = pCompilerFolderSuffix->GetString();
|
||||
suffix.Trim();
|
||||
folder.append(suffix);
|
||||
}
|
||||
m_RequestLineRootFolder = folder + string("/");
|
||||
string suffix = pCompilerFolderSuffix->GetString();
|
||||
suffix.Trim();
|
||||
projectName.append(suffix);
|
||||
}
|
||||
|
||||
projectName.append("/");
|
||||
m_RequestLineRootFolder.assign(projectName.c_str(), projectName.size());
|
||||
}
|
||||
|
||||
if (m_RequestLineRootFolder.empty())
|
||||
|
||||
@@ -13,16 +13,61 @@
|
||||
#include <AzTest/AzTest.h>
|
||||
#include <AzCore/UnitTest/TestTypes.h>
|
||||
#include <AzCore/Memory/AllocatorScope.h>
|
||||
#include <AzCore/Settings/SettingsRegistry.h>
|
||||
#include <AzCore/UnitTest/UnitTest.h>
|
||||
#include "Mocks/IConsoleMock.h"
|
||||
#include "Mocks/ICVarMock.h"
|
||||
#include "Mocks/ISystemMock.h"
|
||||
#include "RemoteCompiler.h"
|
||||
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
class SettingsRegistrySimpleMock;
|
||||
using NiceSettingsRegistrySimpleMock = ::testing::NiceMock<SettingsRegistrySimpleMock>;
|
||||
|
||||
class SettingsRegistrySimpleMock : public AZ::SettingsRegistryInterface
|
||||
{
|
||||
public:
|
||||
MOCK_CONST_METHOD1(GetType, Type(AZStd::string_view));
|
||||
MOCK_CONST_METHOD2(Visit, bool(Visitor&, AZStd::string_view));
|
||||
MOCK_CONST_METHOD2(Visit, bool(const VisitorCallback&, AZStd::string_view));
|
||||
MOCK_METHOD1(RegisterNotifier, NotifyEventHandler(const NotifyCallback&));
|
||||
MOCK_METHOD1(RegisterNotifier, NotifyEventHandler(NotifyCallback&&));
|
||||
|
||||
MOCK_CONST_METHOD2(Get, bool(bool&, AZStd::string_view));
|
||||
MOCK_CONST_METHOD2(Get, bool(s64&, AZStd::string_view));
|
||||
MOCK_CONST_METHOD2(Get, bool(u64&, AZStd::string_view));
|
||||
MOCK_CONST_METHOD2(Get, bool(double&, AZStd::string_view));
|
||||
MOCK_CONST_METHOD2(Get, bool(AZStd::string&, AZStd::string_view));
|
||||
MOCK_CONST_METHOD2(Get, bool(FixedValueString&, AZStd::string_view));
|
||||
MOCK_CONST_METHOD3(GetObject, bool(void*, Uuid, AZStd::string_view));
|
||||
|
||||
MOCK_METHOD2(Set, bool(AZStd::string_view, bool));
|
||||
MOCK_METHOD2(Set, bool(AZStd::string_view, s64));
|
||||
MOCK_METHOD2(Set, bool(AZStd::string_view, u64));
|
||||
MOCK_METHOD2(Set, bool(AZStd::string_view, double));
|
||||
MOCK_METHOD2(Set, bool(AZStd::string_view, AZStd::string_view));
|
||||
MOCK_METHOD2(Set, bool(AZStd::string_view, const char*));
|
||||
MOCK_METHOD3(SetObject, bool(AZStd::string_view, const void*, Uuid));
|
||||
|
||||
MOCK_METHOD1(Remove, bool(AZStd::string_view));
|
||||
|
||||
MOCK_METHOD3(MergeCommandLineArgument, bool(AZStd::string_view, AZStd::string_view, const CommandLineArgumentSettings&));
|
||||
MOCK_METHOD2(MergeSettings, bool(AZStd::string_view, Format));
|
||||
MOCK_METHOD4(MergeSettingsFile, bool(AZStd::string_view, Format, AZStd::string_view, AZStd::vector<char>*));
|
||||
MOCK_METHOD5(
|
||||
MergeSettingsFolder,
|
||||
bool(AZStd::string_view, const Specializations&, AZStd::string_view, AZStd::string_view, AZStd::vector<char>*));
|
||||
};
|
||||
} // namespace AZ
|
||||
|
||||
|
||||
namespace NRemoteCompiler
|
||||
{
|
||||
using ::testing::NiceMock;
|
||||
using ::testing::Return;
|
||||
using ::testing::DoAll;
|
||||
|
||||
using SystemAllocatorScope = AZ::AllocatorScope<AZ::LegacyAllocator, CryStringAllocator>;
|
||||
|
||||
@@ -65,9 +110,12 @@ namespace NRemoteCompiler
|
||||
SystemAllocatorScope::ActivateAllocators();
|
||||
|
||||
m_priorEnv = gEnv;
|
||||
m_priorSettingsRegistry = AZ::SettingsRegistry::Get();
|
||||
|
||||
m_data.reset(new DataMembers);
|
||||
|
||||
AZ::SettingsRegistry::Register(&m_data->m_settings);
|
||||
|
||||
ON_CALL(m_data->m_console, GetCVar(_))
|
||||
.WillByDefault(Return(&m_data->m_cvarMock));
|
||||
|
||||
@@ -89,6 +137,11 @@ namespace NRemoteCompiler
|
||||
void TearDown() override
|
||||
{
|
||||
gEnv = m_priorEnv;
|
||||
AZ::SettingsRegistry::Unregister(&m_data->m_settings);
|
||||
if (m_priorSettingsRegistry)
|
||||
{
|
||||
AZ::SettingsRegistry::Register(m_priorSettingsRegistry);
|
||||
}
|
||||
m_data.reset();
|
||||
SystemAllocatorScope::DeactivateAllocators();
|
||||
AllocatorsTestFixture::TearDown();
|
||||
@@ -99,12 +152,14 @@ namespace NRemoteCompiler
|
||||
NiceMock<SystemMock> m_system;
|
||||
NiceMock<ConsoleMock> m_console;
|
||||
NiceMock<CVarMock> m_cvarMock;
|
||||
AZ::NiceSettingsRegistrySimpleMock m_settings;
|
||||
SSystemGlobalEnvironment m_stubEnv;
|
||||
};
|
||||
|
||||
AZStd::unique_ptr<DataMembers> m_data;
|
||||
|
||||
SSystemGlobalEnvironment* m_priorEnv = nullptr;
|
||||
AZ::SettingsRegistryInterface* m_priorSettingsRegistry = nullptr;
|
||||
};
|
||||
|
||||
// allow punch through to PRIVATE functions so that they do not need to be made PUBLIC.
|
||||
@@ -130,7 +185,9 @@ namespace NRemoteCompiler
|
||||
|
||||
TEST_F(RemoteCompilerTest, CShaderSrv_Constructor_WithNoGameName_Fails)
|
||||
{
|
||||
EXPECT_CALL(m_data->m_cvarMock, GetString());
|
||||
using namespace ::testing;
|
||||
AZ::SettingsRegistryInterface::FixedValueString regResult;
|
||||
EXPECT_CALL(m_data->m_settings, Get(regResult, _));
|
||||
|
||||
AZ_TEST_START_TRACE_SUPPRESSION;
|
||||
ShaderSrvUnitTestAccessor srv;
|
||||
@@ -140,8 +197,10 @@ namespace NRemoteCompiler
|
||||
TEST_F(RemoteCompilerTest, CShaderSrv_Constructor_WithValidGameName_Succeeds)
|
||||
{
|
||||
// when we construct the server it calls get on the game name
|
||||
EXPECT_CALL(m_data->m_cvarMock, GetString())
|
||||
.WillOnce(Return("StarterGame"));
|
||||
using namespace ::testing;
|
||||
AZ::SettingsRegistryInterface::FixedValueString projectName;
|
||||
EXPECT_CALL(m_data->m_settings, Get(projectName, _))
|
||||
.WillOnce(DoAll(testing::SetArgReferee<0>("StarterGame"), Return(true)));
|
||||
|
||||
ShaderSrvUnitTestAccessor srv;
|
||||
}
|
||||
@@ -149,11 +208,12 @@ namespace NRemoteCompiler
|
||||
TEST_F(RemoteCompilerTest, CShaderSrv_EncapsulateRequestInEngineConnectionProtocol_EmptyData_Fails)
|
||||
{
|
||||
// when we construct the server it calls get on the game name
|
||||
EXPECT_CALL(m_data->m_cvarMock, GetString())
|
||||
.WillOnce(Return("StarterGame"));
|
||||
using namespace ::testing;
|
||||
AZ::SettingsRegistryInterface::FixedValueString projectName;
|
||||
EXPECT_CALL(m_data->m_settings, Get(projectName, _))
|
||||
.WillOnce(DoAll(testing::SetArgReferee<0>("StarterGame"), Return(true)));
|
||||
|
||||
ShaderSrvUnitTestAccessor srv;
|
||||
|
||||
|
||||
std::vector<uint8> testVector;
|
||||
|
||||
@@ -165,11 +225,12 @@ namespace NRemoteCompiler
|
||||
TEST_F(RemoteCompilerTest, CShaderSrv_EncapsulateRequestInEngineConnectionProtocol_ValidData_EmptyServerList_Fails)
|
||||
{
|
||||
// when we construct the server it calls get on the game name
|
||||
EXPECT_CALL(m_data->m_cvarMock, GetString())
|
||||
.WillOnce(Return("StarterGame"));
|
||||
using namespace ::testing;
|
||||
AZ::SettingsRegistryInterface::FixedValueString projectName;
|
||||
EXPECT_CALL(m_data->m_settings, Get(projectName, _))
|
||||
.WillOnce(DoAll(testing::SetArgReferee<0>("StarterGame"), Return(true)));
|
||||
|
||||
ShaderSrvUnitTestAccessor srv;
|
||||
|
||||
|
||||
EXPECT_CALL(m_data->m_cvarMock, GetString())
|
||||
.WillRepeatedly(Return("")); // empty server list
|
||||
@@ -186,11 +247,12 @@ namespace NRemoteCompiler
|
||||
TEST_F(RemoteCompilerTest, CShaderSrv_EncapsulateRequestInEngineConnectionProtocol_ValidInputs_Succeeds)
|
||||
{
|
||||
// when we construct the server it calls get on the game name
|
||||
EXPECT_CALL(m_data->m_cvarMock, GetString())
|
||||
.WillOnce(Return("StarterGame"));
|
||||
using namespace ::testing;
|
||||
AZ::SettingsRegistryInterface::FixedValueString projectName;
|
||||
EXPECT_CALL(m_data->m_settings, Get(projectName, _))
|
||||
.WillOnce(DoAll(testing::SetArgReferee<0>("StarterGame"), Return(true)));
|
||||
|
||||
ShaderSrvUnitTestAccessor srv;
|
||||
|
||||
|
||||
// After this, it will repeatedly call get cvar to get the server address:
|
||||
const char* testList = "10.20.30.40";
|
||||
@@ -207,11 +269,12 @@ namespace NRemoteCompiler
|
||||
TEST_F(RemoteCompilerTest, CShaderSrv_SendRequestViaEngineConnection_EmptyData_Fails)
|
||||
{
|
||||
// when we construct the server it calls get on the game name
|
||||
EXPECT_CALL(m_data->m_cvarMock, GetString())
|
||||
.WillOnce(Return("StarterGame"));
|
||||
using namespace ::testing;
|
||||
AZ::SettingsRegistryInterface::FixedValueString projectName;
|
||||
EXPECT_CALL(m_data->m_settings, Get(projectName, _))
|
||||
.WillOnce(DoAll(testing::SetArgReferee<0>("StarterGame"), Return(true)));
|
||||
|
||||
ShaderSrvUnitTestAccessor srv;
|
||||
|
||||
|
||||
// After this, it will repeatedly call get cvar to get the server address:
|
||||
const char* testList = "10.20.30.40";
|
||||
@@ -221,7 +284,7 @@ namespace NRemoteCompiler
|
||||
std::vector<uint8> testVector;
|
||||
std::string testString("empty");
|
||||
|
||||
// test for empty data - recvfailed expected (error emitted)
|
||||
// test for empty data - RecvFailed expected (error emitted)
|
||||
AZ_TEST_START_TRACE_SUPPRESSION;
|
||||
testString = "empty";
|
||||
testVector.assign(testString.begin(), testString.end());
|
||||
@@ -232,11 +295,12 @@ namespace NRemoteCompiler
|
||||
TEST_F(RemoteCompilerTest, CShaderSrv_SendRequestViaEngineConnection_IncompleteData_Fails)
|
||||
{
|
||||
// when we construct the server it calls get on the game name
|
||||
EXPECT_CALL(m_data->m_cvarMock, GetString())
|
||||
.WillOnce(Return("StarterGame"));
|
||||
using namespace ::testing;
|
||||
AZ::SettingsRegistryInterface::FixedValueString projectName;
|
||||
EXPECT_CALL(m_data->m_settings, Get(projectName, _))
|
||||
.WillOnce(DoAll(testing::SetArgReferee<0>("StarterGame"), Return(true)));
|
||||
|
||||
ShaderSrvUnitTestAccessor srv;
|
||||
|
||||
|
||||
// After this, it will repeatedly call get cvar to get the server address:
|
||||
const char* testList = "10.20.30.40";
|
||||
@@ -247,7 +311,7 @@ namespace NRemoteCompiler
|
||||
std::string testString("incomplete");
|
||||
testVector.assign(testString.begin(), testString.end());
|
||||
|
||||
// test for incomplete data - recvfailed expected
|
||||
// test for incomplete data - RecvFailed expected
|
||||
AZ_TEST_START_TRACE_SUPPRESSION;
|
||||
EXPECT_EQ(srv.SendRequestViaEngineConnection(testVector), EServerError::ESRecvFailed);
|
||||
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
|
||||
@@ -256,11 +320,12 @@ namespace NRemoteCompiler
|
||||
TEST_F(RemoteCompilerTest, CShaderSrv_SendRequestViaEngineConnection_CorruptData_Fails)
|
||||
{
|
||||
// when we construct the server it calls get on the game name
|
||||
EXPECT_CALL(m_data->m_cvarMock, GetString())
|
||||
.WillOnce(Return("StarterGame"));
|
||||
using namespace ::testing;
|
||||
AZ::SettingsRegistryInterface::FixedValueString projectName;
|
||||
EXPECT_CALL(m_data->m_settings, Get(projectName, _))
|
||||
.WillOnce(DoAll(testing::SetArgReferee<0>("StarterGame"), Return(true)));
|
||||
|
||||
ShaderSrvUnitTestAccessor srv;
|
||||
|
||||
|
||||
// After this, it will repeatedly call get cvar to get the server address:
|
||||
const char* testList = "10.20.30.40";
|
||||
@@ -271,7 +336,7 @@ namespace NRemoteCompiler
|
||||
std::string testString("corrupt");
|
||||
testVector.assign(testString.begin(), testString.end());
|
||||
|
||||
// test for incomplete data - recvfailed expected
|
||||
// test for incomplete data - RecvFailed expected
|
||||
AZ_TEST_START_TRACE_SUPPRESSION;
|
||||
EXPECT_EQ(srv.SendRequestViaEngineConnection(testVector), EServerError::ESRecvFailed);
|
||||
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
|
||||
@@ -280,11 +345,12 @@ namespace NRemoteCompiler
|
||||
TEST_F(RemoteCompilerTest, CShaderSrv_SendRequestViaEngineConnection_CompileError_Fails_ReturnsText)
|
||||
{
|
||||
// when we construct the server it calls get on the game name
|
||||
EXPECT_CALL(m_data->m_cvarMock, GetString())
|
||||
.WillOnce(Return("StarterGame"));
|
||||
using namespace ::testing;
|
||||
AZ::SettingsRegistryInterface::FixedValueString projectName;
|
||||
EXPECT_CALL(m_data->m_settings, Get(projectName, _))
|
||||
.WillOnce(DoAll(testing::SetArgReferee<0>("StarterGame"), Return(true)));
|
||||
|
||||
ShaderSrvUnitTestAccessor srv;
|
||||
|
||||
|
||||
// After this, it will repeatedly call get cvar to get the server address:
|
||||
const char* testList = "10.20.30.40";
|
||||
@@ -294,11 +360,11 @@ namespace NRemoteCompiler
|
||||
std::vector<uint8> testVector;
|
||||
std::string testString("corrupt");
|
||||
testVector.assign(testString.begin(), testString.end());
|
||||
// test for an actual compile error - decompressed compile erro rexpected to be attached.
|
||||
// test for an actual compile error - decompressed compile error expected to be attached.
|
||||
testString = "compile_failure";
|
||||
testVector.assign(testString.begin(), testString.end());
|
||||
EXPECT_EQ(srv.SendRequestViaEngineConnection(testVector), EServerError::ESCompileError);
|
||||
// validate hte compile erorr decompressed successfully
|
||||
// validate the compile error decompressed successfully
|
||||
const char* expected_decode = "decompressed_plaintext";
|
||||
EXPECT_EQ(testVector.size(), strlen(expected_decode));
|
||||
EXPECT_EQ(memcmp(testVector.data(), expected_decode, strlen(expected_decode)), 0);
|
||||
@@ -307,11 +373,12 @@ namespace NRemoteCompiler
|
||||
TEST_F(RemoteCompilerTest, CShaderSrv_SendRequestViaEngineConnection_ValidInput_Succeeds_ReturnsText)
|
||||
{
|
||||
// when we construct the server it calls get on the game name
|
||||
EXPECT_CALL(m_data->m_cvarMock, GetString())
|
||||
.WillOnce(Return("StarterGame"));
|
||||
using namespace ::testing;
|
||||
AZ::SettingsRegistryInterface::FixedValueString projectName;
|
||||
EXPECT_CALL(m_data->m_settings, Get(projectName, _))
|
||||
.WillOnce(DoAll(testing::SetArgReferee<0>("StarterGame"), Return(true)));
|
||||
|
||||
ShaderSrvUnitTestAccessor srv;
|
||||
|
||||
|
||||
// After this, it will repeatedly call get cvar to get the server address:
|
||||
const char* testList = "10.20.30.40";
|
||||
|
||||
@@ -375,7 +375,7 @@ void CShaderMan::mfInitShadersCacheMissLog()
|
||||
// create valid path
|
||||
gEnv->pCryPak->MakeDir(g_szTestResults);
|
||||
|
||||
m_ShaderCacheMissPath = string("@cache@\\Shaders\\ShaderCacheMisses.txt"); // do we want this here, or maybe in @log@ ?
|
||||
m_ShaderCacheMissPath = string("@usercache@\\Shaders\\ShaderCacheMisses.txt"); // do we want this here, or maybe in @log@ ?
|
||||
|
||||
// load data which is already stored
|
||||
AZ::IO::HandleType fileHandle = AZ::IO::InvalidHandle;
|
||||
@@ -2175,9 +2175,10 @@ void CShaderMan::mfOptimiseShaders(const char* szFolder, bool bForce)
|
||||
for (i = 0; i < Names.size(); i++)
|
||||
{
|
||||
const char* szName = Names[i].c_str();
|
||||
if (!strncmp(szName, "@cache@/", 7))
|
||||
constexpr AZStd::string_view userCache = "@usercache@/";
|
||||
if (szName == userCache)
|
||||
{
|
||||
szName += 7;
|
||||
szName += userCache.size();
|
||||
}
|
||||
pCache = CHWShader::mfInitCache(szName, NULL, false, 0, false);
|
||||
if (!pCache || !pCache->m_pRes[CACHE_USER])
|
||||
|
||||
@@ -1589,7 +1589,7 @@ void CShaderMan::mfInit (void)
|
||||
#else
|
||||
m_ShadersCache = CONCAT_PATHS(g_shaderCache, "D3D11");
|
||||
#endif
|
||||
m_szCachePath = "@cache@/";
|
||||
m_szCachePath = "@usercache@/";
|
||||
|
||||
if (CRenderer::CV_r_shadersImport == 3)
|
||||
{
|
||||
|
||||
@@ -162,7 +162,7 @@ bool CShaderSerialize::OpenSResource(const char* szName, SSShaderRes* pSR, CSha
|
||||
stack_string szReadOnly = szName;
|
||||
|
||||
// ShaderCacheGen behavior:
|
||||
// CACHE_READONLY is not really used when exporting the .fxb, so we append the @cache@ alias to the relative shader path
|
||||
// CACHE_READONLY is not really used when exporting the .fxb, so we append the @usercache@ alias to the relative shader path
|
||||
// here as well. We cannot just leave this as the relative Shaders/Cache/Foo.fxb value because then it creates a new
|
||||
// file in the asset cache as @assets@/Shaders/Cache/Foo.fxb, which is illegal (since only AP has the authority to write here)
|
||||
// Game runtime behavior:
|
||||
|
||||
@@ -3490,7 +3490,7 @@ void CHWShader_D3D::mfSaveCGFile(const char* scr, const char* path)
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf_s(name, "@cache@/shaders/fxerror/%s(GL%llx)/(LT%x)(RT%llx)/(MD%x)(MDV%x)(PSS%llx)(ST%llx).cg", GetName(), m_pCurInst->m_Ident.m_GLMask, m_pCurInst->m_Ident.m_LightMask, m_pCurInst->m_Ident.m_RTMask, m_pCurInst->m_Ident.m_MDMask, m_pCurInst->m_Ident.m_MDVMask, m_pCurInst->m_Ident.m_pipelineState.opaque, m_pCurInst->m_Ident.m_STMask);
|
||||
sprintf_s(name, "@usercache@/shaders/fxerror/%s(GL%llx)/(LT%x)(RT%llx)/(MD%x)(MDV%x)(PSS%llx)(ST%llx).cg", GetName(), m_pCurInst->m_Ident.m_GLMask, m_pCurInst->m_Ident.m_LightMask, m_pCurInst->m_Ident.m_RTMask, m_pCurInst->m_Ident.m_MDMask, m_pCurInst->m_Ident.m_MDVMask, m_pCurInst->m_Ident.m_pipelineState.opaque, m_pCurInst->m_Ident.m_STMask);
|
||||
}
|
||||
|
||||
AZ::IO::HandleType fileHandle;
|
||||
@@ -4672,7 +4672,7 @@ bool CAsyncShaderTask::CompileAsyncShader(SShaderAsyncInfo* pAsync)
|
||||
CryFixedStringT<1024> hlslPath;
|
||||
|
||||
// Create a directory for this shader type, strip the .fxcb extension from the folder name
|
||||
shaderSourceOutputFolder.Format("@cache@/%s",pAsync->m_pShader->m_pDevCache->m_Name.c_str());
|
||||
shaderSourceOutputFolder.Format("@usercache@/%s",pAsync->m_pShader->m_pDevCache->m_Name.c_str());
|
||||
PathUtil::RemoveExtension(shaderSourceOutputFolder);
|
||||
gEnv->pFileIO->CreatePath(shaderSourceOutputFolder);
|
||||
|
||||
|
||||
@@ -70,6 +70,7 @@
|
||||
#endif
|
||||
|
||||
#include "../Common/RenderCapabilities.h"
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
|
||||
#ifdef WIN32
|
||||
// Count monitors helper
|
||||
@@ -1634,8 +1635,8 @@ WIN_HWND CD3D9Renderer::Init([[maybe_unused]] int x, [[maybe_unused]] int y, int
|
||||
iLog->Log ("Direct3D driver is creating...");
|
||||
iLog->Log ("Crytek Direct3D driver version %4.2f (%s <%s>)", VERSION_D3D, __DATE__, __TIME__);
|
||||
|
||||
const char* sGameName = iConsole->GetCVar("sys_game_name")->GetString();
|
||||
cry_strcpy(m_WinTitle, sGameName);
|
||||
auto projectName = AZ::Utils::GetProjectName();
|
||||
cry_strcpy(m_WinTitle, projectName.c_str());
|
||||
|
||||
iLog->Log ("Creating window called '%s' (%dx%d)", m_WinTitle, width, height);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user