3168 lines
101 KiB
C++
3168 lines
101 KiB
C++
/////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// FILE : scene/debug/StreamingDebugGraph.cpp
|
|
// PURPOSE :
|
|
// AUTHOR :
|
|
// CREATED :
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "streaming/streamingdebuggraph.h"
|
|
#include "streaming/streaming_channel.h"
|
|
#include "system/stack.h"
|
|
|
|
STREAMING_OPTIMISATIONS();
|
|
SCENE_OPTIMISATIONS();
|
|
|
|
#if __BANK
|
|
|
|
#include "bank/bank.h"
|
|
#include "bank/bkmgr.h"
|
|
#include "debug/debugscene.h"
|
|
#include "debug/TextureViewer/TextureViewer.h"
|
|
#include "debug/TextureViewer/TextureViewerSearch.h"
|
|
#include "fwdebug/debugdraw.h"
|
|
#include "fwscene/stores/drawablestore.h"
|
|
#include "fwscene/stores/fragmentstore.h"
|
|
#include "input/mouse.h"
|
|
|
|
#include "text/text.h"
|
|
#include "text/textconversion.h"
|
|
|
|
#include "grcore/viewport.h"
|
|
#include "fwmaths/Rect.h"
|
|
#include "vector/color32.h"
|
|
|
|
#include "streaming/packfilemanager.h"
|
|
#include "system/controlmgr.h"
|
|
#include "system/AutoGPUCapture.h"
|
|
#include "fwsys/timer.h"
|
|
|
|
#include "streaming/streamingdebug.h"
|
|
|
|
#include "entity/archetype.h"
|
|
#include "objects/DummyObject.h"
|
|
#include "scene/Building.h"
|
|
|
|
#include "script/script.h"
|
|
#include "script/streamedscripts.h"
|
|
|
|
#include "frontend/Scaleform/ScaleFormStore.h"
|
|
#include "streamingdebuggraphextensions.h"
|
|
// Bounds
|
|
#include "phbound/support.h"
|
|
#include "phbound/boundgrid.h"
|
|
#include "phbound/boundribbon.h"
|
|
#include "phbound/boundsurface.h"
|
|
#include "phbound/OptimizedBvh.h"
|
|
|
|
//CStreamGraph g_DebugStreamGraph;
|
|
|
|
extern void GetSizesSafe(strIndex, strStreamingInfo &, int &, int &, bool);
|
|
extern void GetActiveEntityAssets(atMap<strIndex, bool> &outAssetList);
|
|
extern const char *CreateFlagString(u32 flags, char *outBuffer, size_t bufferSize);
|
|
|
|
extern atMap<strIndex, bool> s_SceneMap;
|
|
extern bool s_DumpExcludeSceneAssetsInGraph;
|
|
extern bool s_ExcludeSceneAssetsForRendering;
|
|
extern bool s_ExcludeSceneAssetsForNonRendering;
|
|
|
|
|
|
void GetLoadedSizes(strStreamingModule *pModule, strLocalIndex objIndex, int &virt, int &phys)
|
|
{
|
|
virt += (int) pModule->GetVirtualMemoryOfLoadedObj(objIndex, false);
|
|
phys += (int) pModule->GetPhysicalMemoryOfLoadedObj(objIndex, false);
|
|
}
|
|
|
|
|
|
void CStreamGraphSelectedFileData::CollectDependents(strIndex index)
|
|
{
|
|
int finalCount = 0;
|
|
int maxCount = NELEM(m_Dependents);
|
|
|
|
strLoadedInfoIterator it;
|
|
strIndex loadIndex = it.GetNextIndex();
|
|
|
|
while (loadIndex.IsValid())
|
|
{
|
|
strIndex deps[STREAMING_MAX_DEPENDENCIES];
|
|
strStreamingModule* pModule = strStreamingEngine::GetInfo().GetModule(loadIndex);
|
|
strLocalIndex objectIdx = pModule->GetObjectIndex(loadIndex);
|
|
s32 numDeps = pModule->GetDependencies(objectIdx, &deps[0], STREAMING_MAX_DEPENDENCIES);
|
|
|
|
bool hasDeps = false;
|
|
|
|
while (numDeps--)
|
|
{
|
|
if (deps[numDeps] == index)
|
|
{
|
|
hasDeps = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( hasDeps )
|
|
{
|
|
m_Dependents[finalCount++] = loadIndex;
|
|
|
|
// Don't write outside the array bounds!
|
|
if (finalCount == maxCount)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
loadIndex = it.GetNextIndex();
|
|
}
|
|
|
|
m_DependentCount = finalCount;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// FUNCTION:
|
|
// PURPOSE:
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
void CStreamGraph::Init(unsigned /*initMode*/)
|
|
{
|
|
USE_DEBUG_MEMORY();
|
|
|
|
INIT_DEBUGSTREAMGRAPH;
|
|
}
|
|
|
|
void CStreamGraph::Shutdown(unsigned /*shutdownMode*/)
|
|
{
|
|
USE_DEBUG_MEMORY();
|
|
|
|
SHUTDOWN_DEBUGSTREAMGRAPH;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// FUNCTION:
|
|
// PURPOSE:
|
|
//////////////////////////////////////////////////////////////////////////
|
|
CStreamGraph::CStreamGraph()
|
|
{
|
|
m_ShowMemoryTracker = false;
|
|
m_ShowMemoryTrackerToggle = false;
|
|
|
|
m_ShowMemoryTrackerDependentsInScene = false;
|
|
m_OnlyShowMemoryTrackerDependentsInScene = false;
|
|
|
|
m_TrackTxd = false;
|
|
m_ShowVirtualMemory = true;
|
|
m_ShowPhysicalMemory = true;
|
|
m_ShowTemporaryMemory = false;
|
|
m_IncludeReferencedObjects = true;
|
|
m_IncludeDontDeleteObjects = true;
|
|
m_IncludeCachedObjects = false;
|
|
m_IncludeRequestedObjects = false;
|
|
m_IncludeDontDeleteObjects = true;
|
|
m_OnlyIncludeCutsceneRequestedObjects = false;
|
|
m_ExcludeCutsceneRequestedObjects = false;
|
|
m_OnlyIncludeScriptRequestedObjects = false;
|
|
m_ShowCategoryBreakdown = false;
|
|
m_ShowLODBreakdown = false;
|
|
m_TransposeGraph = false;
|
|
m_ShowFileInfo = true;
|
|
m_ShowExtendedFileInfo = true;
|
|
m_bMove = false;
|
|
m_OrderByName = false;
|
|
|
|
m_MemoryLocationCompareIndex = 0;
|
|
|
|
m_vPos.Set(500, 40);
|
|
m_nMaxMemMB = 75;
|
|
m_AssetFilterStr[0] = '\0';
|
|
|
|
m_pTxdLodCounts = NULL;
|
|
m_pDwdLodCounts = NULL;
|
|
m_pDrawableLodCounts = NULL;
|
|
|
|
// Create the extensions manager
|
|
m_pStreamGraphExtManager = rage_new CStreamGraphExtensionManager;
|
|
|
|
|
|
}
|
|
|
|
CStreamGraph::~CStreamGraph()
|
|
{
|
|
delete m_pStreamGraphExtManager;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// FUNCTION:
|
|
// PURPOSE:
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CStreamGraph::AddWidgets(bkBank* pBank)
|
|
{
|
|
pBank->PushGroup("Stream Graph", false);
|
|
pBank->AddToggle("Show memory usage", &m_ShowMemoryTracker);
|
|
|
|
pBank->AddText("Filter Asset Name Containing", m_AssetFilterStr, 64);
|
|
|
|
pBank->AddToggle("Show Dependents In Scene", &m_ShowMemoryTrackerDependentsInScene);
|
|
pBank->AddToggle("Show ONLY Dependents In Scene", &m_OnlyShowMemoryTrackerDependentsInScene);
|
|
|
|
pBank->AddToggle("Track TXD in Texture Viewer", &m_TrackTxd);
|
|
|
|
// Make sure the list of debug locations is resident.
|
|
if (CStreamingDebug::GetMemoryProfileLocationNames() == NULL)
|
|
{
|
|
CStreamingDebug::LoadMemoryProfileLocations();
|
|
}
|
|
|
|
int locationCount = CStreamingDebug::GetMemoryProfileLocationCount();
|
|
pBank->AddCombo("Compare Against", &m_MemoryLocationCompareIndex, locationCount, CStreamingDebug::GetMemoryProfileLocationNames());
|
|
|
|
pBank->AddTitle("Types of memory to include");
|
|
pBank->AddToggle("Main memory", &m_ShowVirtualMemory);
|
|
pBank->AddToggle("Vram memory", &m_ShowPhysicalMemory);
|
|
pBank->AddToggle("Temporary memory", &m_ShowTemporaryMemory, NullCB, "Show temporary memory as well");
|
|
pBank->AddToggle("Break down by category", &m_ShowCategoryBreakdown);
|
|
pBank->AddToggle("Transpose", &m_TransposeGraph );
|
|
pBank->AddToggle("Show file info", &m_ShowFileInfo);
|
|
pBank->AddToggle("Show extended file info", &m_ShowExtendedFileInfo);
|
|
pBank->AddToggle("Order by name", &m_OrderByName);
|
|
|
|
pBank->AddToggle("Break down by LOD", &m_ShowLODBreakdown );
|
|
|
|
pBank->AddTitle("Types of streamed objects to include");
|
|
pBank->AddToggle("REFERENCED objects", &m_IncludeReferencedObjects);
|
|
pBank->AddToggle("DONTDELETE objects", &m_IncludeDontDeleteObjects);
|
|
pBank->AddToggle("CACHED objects", &m_IncludeCachedObjects);
|
|
pBank->AddToggle("REQUESTED objects", &m_IncludeRequestedObjects);
|
|
pBank->AddToggle("Exclude objects in scene", &s_DumpExcludeSceneAssetsInGraph);
|
|
pBank->AddToggle("Exclude objects for rendering only", &s_ExcludeSceneAssetsForRendering);
|
|
pBank->AddToggle("Exclude objects for non-rendering only", &s_ExcludeSceneAssetsForNonRendering);
|
|
pBank->AddToggle("(only) CUTSCENE REQUESTED objects", &m_OnlyIncludeCutsceneRequestedObjects);
|
|
pBank->AddToggle("Exclude CUTSCENE REQUESTED objects", &m_ExcludeCutsceneRequestedObjects);
|
|
pBank->AddToggle("(only) SCRIPT REQUESTED objects", &m_OnlyIncludeScriptRequestedObjects);
|
|
|
|
pBank->AddSlider("Max Mem (mb)", &m_nMaxMemMB, 1, 512, 1);
|
|
|
|
// Add widgets for extensions
|
|
m_pStreamGraphExtManager->AddWidgets(pBank);
|
|
|
|
pBank->PopGroup();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// FUNCTION:
|
|
// PURPOSE:
|
|
//////////////////////////////////////////////////////////////////////////
|
|
static const struct
|
|
{
|
|
u32 category;
|
|
const char *label;
|
|
} sAssetCategoryLegend[] =
|
|
{
|
|
{ CDataFileMgr::CONTENTS_DEFAULT, "Default" },
|
|
{ CDataFileMgr::CONTENTS_PROPS, "Props" },
|
|
{ CDataFileMgr::CONTENTS_MAP, "Map" },
|
|
{ CDataFileMgr::CONTENTS_LODS, "Lods" },
|
|
{ CDataFileMgr::CONTENTS_PEDS, "Peds" },
|
|
{ CDataFileMgr::CONTENTS_VEHICLES, "Vehicles" },
|
|
{ CDataFileMgr::CONTENTS_ANIMATION, "Animation" },
|
|
{ CDataFileMgr::CONTENTS_CUTSCENE, "Cutscene" },
|
|
{ CDataFileMgr::CONTENTS_DLC_MAP_DATA, "DLC" },
|
|
{ CDataFileMgr::CONTENTS_DEBUG_ONLY, "DebugOnly"}
|
|
};
|
|
|
|
static const struct
|
|
{
|
|
u32 lod;
|
|
const char *label;
|
|
} sAssetLODLegend[] =
|
|
{
|
|
{ LODTYPES_DEPTH_HD, "HD" },
|
|
{ LODTYPES_DEPTH_LOD, "LOD" },
|
|
{ LODTYPES_DEPTH_SLOD1, "SLOD1" },
|
|
{ LODTYPES_DEPTH_SLOD2, "SLOD2" },
|
|
{ LODTYPES_DEPTH_SLOD3, "SLOD3" },
|
|
{ LODTYPES_DEPTH_ORPHANHD, "ORPHANHD" },
|
|
{ LODTYPES_DEPTH_SLOD4, "SLOD4" },
|
|
{ LODTYPES_DEPTH_TOTAL, "Unknown" },
|
|
};
|
|
|
|
|
|
static const Color32 sLegendColours[] =
|
|
{
|
|
Color32(0,255,255),
|
|
Color32(255,255,0),
|
|
Color32(0,0,255),
|
|
Color32(255,0,255),
|
|
Color32(255,0,0),
|
|
Color32(0,255,0),
|
|
Color32(255,255,255),
|
|
Color32(128,255,255),
|
|
Color32(128,0,255),
|
|
Color32(255,128,255),
|
|
Color32(255,128,0),
|
|
Color32(128,255,0),
|
|
Color32(128,128,255),
|
|
Color32(255,128,255),
|
|
Color32(255,128,128),
|
|
Color32(128,255,128),
|
|
Color32(128,64,64),
|
|
Color32(255,128,64),
|
|
Color32(64,128,0),
|
|
Color32(128,64,0),
|
|
Color32(128,128,64),
|
|
Color32(64,128,255),
|
|
Color32(255,128,64),
|
|
Color32(128,64,128),
|
|
Color32(128,64,64),
|
|
Color32(64,128,64),
|
|
Color32(64,128,64),
|
|
Color32(128,64,64),
|
|
Color32(128,64,64),
|
|
Color32(64,128,64),
|
|
Color32(64,128,64),
|
|
Color32(64,64,128)
|
|
};
|
|
|
|
Color32 GetLegendColour( u32 index )
|
|
{
|
|
index = index % ( sizeof(sLegendColours)/sizeof(sLegendColours[0]) );
|
|
return sLegendColours[ index ];
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// FUNCTION:
|
|
// PURPOSE:
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CStreamGraph::DrawTitle()
|
|
{
|
|
char titleText[200];
|
|
sprintf(titleText, m_ShowVirtualMemory ? (m_ShowPhysicalMemory ? "Main + Vram Memory" : "Main Memory") : "Vram Memory");
|
|
|
|
u32 x = (u32)m_vPos.x;
|
|
u32 y = (u32)m_vPos.y;
|
|
|
|
CTextLayout DebugTextLayout;
|
|
DebugTextLayout.SetScale(Vector2(0.4f, 0.4f));
|
|
DebugTextLayout.SetColor(Color32(0, 255, 255, 255));
|
|
DebugTextLayout.Render(STREAMGRAPH_SCREEN_COORDS(x, y-STREAMGRAPH_TITLE_SPACING()), titleText);
|
|
}
|
|
|
|
void CStreamGraph::DrawBackground()
|
|
{
|
|
float x = m_vPos.x;
|
|
float y = m_vPos.y;
|
|
fwRect bgRect(x, y + STREAMGRAPH_BACKGROUND_HEIGHT(), x + GetWindowWidth(), y);
|
|
|
|
Color32 bgColour(0, 0, 0, 128);
|
|
CSprite2d::DrawRectSlow(bgRect, bgColour );
|
|
}
|
|
|
|
float CStreamGraph::DrawMasterMemoryBar(float x, float y)
|
|
{
|
|
CTextLayout DebugTextLayout;
|
|
|
|
|
|
DrawMemoryMarkers(x, y);
|
|
|
|
// Get some numbers.
|
|
ptrdiff_t totalMemory = 0;
|
|
ptrdiff_t usedByModules = 0;
|
|
ptrdiff_t usedByExternalAlloc = 0;
|
|
ptrdiff_t unaccountedFor = 0;
|
|
ptrdiff_t freeMemory = 0;
|
|
CStreamGraphBuffer & buffer = m_statBuffers[SCENESTREAMINGMEMORYTRACKER_BUFFER_RENDER];
|
|
|
|
ptrdiff_t usedByModulesVirt = 0;
|
|
ptrdiff_t usedByModulesPhys = 0;
|
|
|
|
ptrdiff_t unfilteredUsedByModulesVirt = 0;
|
|
ptrdiff_t unfilteredUsedByModulesPhys = 0;
|
|
|
|
if ( buffer.m_Transposed )
|
|
{
|
|
usedByModulesVirt = (ptrdiff_t) buffer.m_UsedByModulesVirt;
|
|
usedByModulesPhys = (ptrdiff_t) buffer.m_UsedByModulesPhys;
|
|
}
|
|
else
|
|
{
|
|
for (int x=0; x<GetNumTrackedModules(); x++)
|
|
{
|
|
usedByModulesVirt += (ptrdiff_t) buffer.m_Modules[x].m_FilteredTotalCostVirt;
|
|
usedByModulesPhys += (ptrdiff_t) buffer.m_Modules[x].m_FilteredTotalCostPhys;
|
|
|
|
unfilteredUsedByModulesVirt += (ptrdiff_t) buffer.m_Modules[x].m_TotalCostVirt;
|
|
unfilteredUsedByModulesPhys += (ptrdiff_t) buffer.m_Modules[x].m_TotalCostPhys;
|
|
}
|
|
}
|
|
|
|
if (m_ShowVirtualMemory)
|
|
{
|
|
totalMemory += (ptrdiff_t) strStreamingEngine::GetAllocator().GetVirtualMemoryAvailable();
|
|
freeMemory += (ptrdiff_t) strStreamingEngine::GetAllocator().GetVirtualMemoryFree() + unfilteredUsedByModulesVirt - usedByModulesVirt;
|
|
usedByExternalAlloc += (ptrdiff_t) strStreamingEngine::GetAllocator().GetExternalVirtualMemoryUsed();
|
|
usedByModules += (ptrdiff_t) usedByModulesVirt;
|
|
|
|
unaccountedFor += (ptrdiff_t) (strStreamingEngine::GetAllocator().GetVirtualMemoryUsed() - strStreamingEngine::GetAllocator().GetExternalVirtualMemoryUsed());
|
|
unaccountedFor -= (ptrdiff_t) (unfilteredUsedByModulesVirt);
|
|
}
|
|
|
|
if (m_ShowPhysicalMemory)
|
|
{
|
|
totalMemory += (ptrdiff_t) strStreamingEngine::GetAllocator().GetPhysicalMemoryAvailable();
|
|
freeMemory += (ptrdiff_t) strStreamingEngine::GetAllocator().GetPhysicalMemoryFree() + unfilteredUsedByModulesPhys - usedByModulesPhys;
|
|
usedByExternalAlloc += (ptrdiff_t) strStreamingEngine::GetAllocator().GetExternalPhysicalMemoryUsed();
|
|
usedByModules += (ptrdiff_t) usedByModulesPhys;
|
|
|
|
unaccountedFor += (ptrdiff_t) (strStreamingEngine::GetAllocator().GetPhysicalMemoryUsed() - strStreamingEngine::GetAllocator().GetExternalPhysicalMemoryUsed());
|
|
unaccountedFor -= (ptrdiff_t) (unfilteredUsedByModulesPhys);
|
|
}
|
|
|
|
|
|
usedByModules /= 1024;
|
|
totalMemory /= 1024;
|
|
usedByExternalAlloc /= 1024;
|
|
unaccountedFor /= 1024;
|
|
freeMemory /= 1024;
|
|
|
|
float totalMemoryf = (float) totalMemory;
|
|
|
|
// The left bar is what's used by modules.
|
|
float x1 = x + float( usedByModules ) / totalMemoryf * GetGraphWidth();
|
|
float x2 = x + float(usedByModules+usedByExternalAlloc) / totalMemoryf * GetGraphWidth();
|
|
float x3 = x2 + float(Max(unaccountedFor, (ptrdiff_t) 0)) / totalMemoryf * GetGraphWidth();
|
|
|
|
char line[256];
|
|
|
|
formatf(line, "Modules: %.2fMB, Ext: %.2fMB, ?: %.2fMB, Free: %.2fMB", float(usedByModules) / 1024.0f,
|
|
float(usedByExternalAlloc) / 1024.0f, float(unaccountedFor) / 1024.0f, float(freeMemory) / 1024.0f);
|
|
|
|
float fScreenX = (float)x;
|
|
float fScreenY = y;
|
|
|
|
float y1 = y + STREAMGRAPH_BAR_SPACING() - STREAMGRAPH_BAR_HEIGHT();
|
|
float y2 = y + STREAMGRAPH_BAR_SPACING();
|
|
|
|
fwRect modMemRect(x, y1, x1, y2);
|
|
CSprite2d::DrawRectSlow(modMemRect, Color32(0xffff0000));
|
|
|
|
fwRect extMemRect(x1, y1, x2, y2);
|
|
CSprite2d::DrawRectSlow(extMemRect, Color32(0xffffff00));
|
|
|
|
fwRect mysteryMemRect(x2, y1, x3, y2);
|
|
CSprite2d::DrawRectSlow(mysteryMemRect, Color32(0xffff00ff));
|
|
|
|
fwRect freeMemRect(x3, y1, x + GetGraphWidth(), y2);
|
|
CSprite2d::DrawRectSlow(freeMemRect, Color32(0xff00ff00));
|
|
|
|
DebugTextLayout.SetScale(Vector2(0.3f, 0.3f));
|
|
DebugTextLayout.SetColor(Color32(255, 255, 255, 255));
|
|
DebugTextLayout.Render(STREAMGRAPH_SCREEN_COORDS(fScreenX, fScreenY-5.0f), line);
|
|
|
|
return STREAMGRAPH_BAR_SPACING();
|
|
}
|
|
|
|
float CStreamGraph::DrawMemoryBar(int memoryBarIndex, int numDivisions, float x, float y)
|
|
{
|
|
float heightOfBarDrawn = 0.0f;
|
|
|
|
CStreamGraphBuffer & buffer = m_statBuffers[SCENESTREAMINGMEMORYTRACKER_BUFFER_RENDER];
|
|
strStreamingModuleMgr& moduleMgr = strStreamingEngine::GetInfo().GetModuleMgr();
|
|
|
|
char achMsg[200];
|
|
bool bDoneBackground = false;
|
|
float curX = float(x + STREAMGRAPH_X_BORDER);
|
|
|
|
CTextLayout DebugTextLayout;
|
|
DebugTextLayout.SetScale(Vector2(0.3f, 0.3f));
|
|
DebugTextLayout.SetColor(Color32(255, 255, 255, 255));
|
|
|
|
u32 totalBarVirtMemory = 0;
|
|
u32 totalBarPhysMemory = 0;
|
|
|
|
size_t totalModuleMemory = 0;
|
|
size_t memoryBudgetKB = 0;
|
|
bool overMemoryBudget = false;
|
|
float budgetMarker = 0.0f;
|
|
|
|
if (!buffer.m_Transposed)
|
|
{
|
|
for (int div=0; div<numDivisions; div++)
|
|
{
|
|
if (m_ShowVirtualMemory)
|
|
{
|
|
totalModuleMemory += buffer.m_Modules[memoryBarIndex].m_CostVirt[div];
|
|
}
|
|
|
|
if (m_ShowPhysicalMemory)
|
|
{
|
|
totalModuleMemory += buffer.m_Modules[memoryBarIndex].m_CostPhys[div];
|
|
}
|
|
}
|
|
|
|
// Find out the reference value.
|
|
if ((u32) CStreamingDebug::GetMemoryProfileLocationList().m_Locations.GetCount() > (u32) m_MemoryLocationCompareIndex)
|
|
{
|
|
const MemoryFootprint &footprint = CStreamingDebug::GetMemoryProfileLocationList().m_Locations[m_MemoryLocationCompareIndex].m_MemoryFootprint;
|
|
const MemoryProfileModuleStat *stat = footprint.m_ModuleMemoryStatsMap.SafeGet(atStringHash(moduleMgr.GetModule(memoryBarIndex)->GetModuleName()));
|
|
|
|
if (stat)
|
|
{
|
|
if (m_ShowVirtualMemory)
|
|
{
|
|
memoryBudgetKB += stat->m_VirtualMemory;
|
|
}
|
|
|
|
if (m_ShowPhysicalMemory)
|
|
{
|
|
memoryBudgetKB += stat->m_PhysicalMemory;
|
|
}
|
|
|
|
overMemoryBudget = (totalModuleMemory / 1024 > memoryBudgetKB);
|
|
budgetMarker = (x+STREAMGRAPH_X_BORDER) + ((float)GetGraphWidth() * (float) (memoryBudgetKB / 1024) / m_nMaxMemMB);
|
|
}
|
|
}
|
|
}
|
|
|
|
for ( s32 xAxisIdx = 0; xAxisIdx < numDivisions; xAxisIdx++ )
|
|
{
|
|
s32 moduleId = memoryBarIndex;
|
|
s32 categoryIdx = xAxisIdx;
|
|
if ( buffer.m_Transposed )
|
|
{
|
|
std::swap( moduleId, categoryIdx );
|
|
}
|
|
|
|
strStreamingModule* pModule = moduleMgr.GetModule(moduleId);
|
|
|
|
u32 memoryInBar = 0;
|
|
if ( m_ShowPhysicalMemory )
|
|
{
|
|
totalBarPhysMemory += buffer.m_Modules[ moduleId ].m_CostPhys[ categoryIdx ];
|
|
memoryInBar += buffer.m_Modules[ moduleId ].m_CostPhys[ categoryIdx ];
|
|
}
|
|
if ( m_ShowVirtualMemory )
|
|
{
|
|
totalBarVirtMemory += buffer.m_Modules[ moduleId ].m_CostVirt[ categoryIdx ];
|
|
memoryInBar += buffer.m_Modules[ moduleId ].m_CostVirt[ categoryIdx ];
|
|
}
|
|
|
|
if ( !buffer.m_Transposed && memoryInBar == 0 )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
float barWidth = ( (float)(memoryInBar) / (float)( m_nMaxMemMB * 1024 * 1024 ) ) * GetGraphWidth();
|
|
bool overBudget = ( curX - x ) + barWidth > GetGraphWidth();
|
|
|
|
Color32 barColour1 = Color32(0,255,0,255);
|
|
Color32 barColour2 = GetLegendColour( xAxisIdx );
|
|
|
|
if ( overMemoryBudget )
|
|
{
|
|
barColour1.Set( 255, 0, 0, 255 );
|
|
barColour2.Set( 255, 0, 0, 255 );
|
|
}
|
|
|
|
if ( !bDoneBackground )
|
|
{
|
|
bDoneBackground = true;
|
|
|
|
char const * textToRender = buffer.m_Transposed ?
|
|
sAssetCategoryLegend[memoryBarIndex].label : pModule->GetModuleName();
|
|
|
|
DebugTextLayout.SetColor(Color32(255, 255, 255, 255));
|
|
DebugTextLayout.Render(STREAMGRAPH_SCREEN_COORDS(x, y), textToRender);
|
|
|
|
DrawMemoryMarkers(x, y);
|
|
|
|
// Show the budget marker, if available.
|
|
if (memoryBudgetKB > 0)
|
|
{
|
|
Vector2 p1(STREAMGRAPH_SCREEN_COORDS(budgetMarker, y+STREAMGRAPH_BAR_SPACING()-STREAMGRAPH_BAR_HEIGHT()));
|
|
Vector2 p2(STREAMGRAPH_SCREEN_COORDS(budgetMarker, y+STREAMGRAPH_BAR_SPACING()));
|
|
grcDebugDraw::Line(p1, p2, Color32(255, 0, 255, 255));
|
|
}
|
|
}
|
|
|
|
if( overBudget )
|
|
{
|
|
barWidth = GetGraphWidth() - ( curX - x );
|
|
barColour1.Set( 255, 0, 0, 255 );
|
|
barColour2.Set( 255, 0, 0, 255 );
|
|
}
|
|
else if ( !m_ShowCategoryBreakdown && !buffer.m_Transposed )
|
|
{
|
|
barColour2.Set( 0, 255, 0, 255 );
|
|
}
|
|
|
|
fwRect barRect1((float) curX,(float) y + STREAMGRAPH_BAR_SPACING(), (float) curX + barWidth,(float) y + STREAMGRAPH_BAR_SPACING() - STREAMGRAPH_BAR_HEIGHT()*(2.0f/3.0f) );
|
|
fwRect barRect2((float) curX,(float) y + STREAMGRAPH_BAR_SPACING() - STREAMGRAPH_BAR_HEIGHT()*(2.0f/3.0f),(float) curX + barWidth,(float) y + STREAMGRAPH_BAR_SPACING() - STREAMGRAPH_BAR_HEIGHT());
|
|
|
|
CSprite2d::DrawRectSlow(barRect1, barColour1);
|
|
CSprite2d::DrawRectSlow(barRect2, barColour2);
|
|
|
|
curX += barWidth;
|
|
}
|
|
|
|
if ( budgetMarker > 0.0f )
|
|
{
|
|
if ( !overMemoryBudget )
|
|
{
|
|
fwRect compareRect((float) curX, y + STREAMGRAPH_BAR_SPACING() - STREAMGRAPH_BAR_HEIGHT() + 5.0f, budgetMarker, y + STREAMGRAPH_BAR_SPACING());
|
|
CSprite2d::DrawRectSlow(compareRect, Color32(0xff000080));
|
|
}
|
|
else
|
|
{
|
|
fwRect compareRect(budgetMarker, y + STREAMGRAPH_BAR_SPACING() - STREAMGRAPH_BAR_HEIGHT(), (float) curX, y + STREAMGRAPH_BAR_SPACING());
|
|
CSprite2d::DrawRectSlow(compareRect, Color32(0xffff00ff));
|
|
}
|
|
}
|
|
|
|
if ( buffer.m_Transposed || totalBarVirtMemory+totalBarPhysMemory > 0 )
|
|
{
|
|
heightOfBarDrawn = STREAMGRAPH_BAR_SPACING();
|
|
|
|
#if __PS3
|
|
sprintf( achMsg, "%.3f MB (M), %.3f MB (V)", (float)totalBarVirtMemory / (1024.0f*1024.0f), (float)totalBarPhysMemory / (1024.0f*1024.0f) );
|
|
#else
|
|
sprintf( achMsg, "%.3f MB", (float)(totalBarVirtMemory+totalBarPhysMemory) / (1024.0f*1024.0f) );
|
|
#endif
|
|
DebugTextLayout.SetColor(Color32(255, 255, 255, 255));
|
|
DebugTextLayout.Render(STREAMGRAPH_SCREEN_COORDS(x + 150, y), achMsg);
|
|
}
|
|
|
|
// Don't draw the file selector if we're looking at an extension
|
|
if ( !m_pStreamGraphExtManager->m_bExtensionSelected[SCENESTREAMINGMEMORYTRACKER_BUFFER_RENDER] &&
|
|
((!buffer.m_Transposed && ( memoryBarIndex == buffer.m_CurrentlySelectedModuleIdx )) ||
|
|
( buffer.m_Transposed && ( memoryBarIndex == buffer.m_CurrentlySelectedCategoryIdx))) )
|
|
{
|
|
DebugTextLayout.SetColor(Color32(255, 255, 255, 255));
|
|
DebugTextLayout.Render(STREAMGRAPH_SCREEN_COORDS(x - 40, y), ">>");
|
|
|
|
// Draw in white the contribution of the currently selected asset
|
|
|
|
u32 selectedSegmentMemorySize = 0;
|
|
u32 accumulatedMemoryBeforeSelected = 0;
|
|
if ( m_ShowPhysicalMemory )
|
|
{
|
|
selectedSegmentMemorySize += buffer.m_SelectedFileData.m_PhysicalSize;
|
|
accumulatedMemoryBeforeSelected += buffer.m_SelectedFileData.m_AccumulatedPhysMemoryBeforeSelectedFile;
|
|
}
|
|
if ( m_ShowVirtualMemory )
|
|
{
|
|
selectedSegmentMemorySize += buffer.m_SelectedFileData.m_VirtualSize;
|
|
accumulatedMemoryBeforeSelected += buffer.m_SelectedFileData.m_AccumulatedVirtMemoryBeforeSelectedFile;
|
|
}
|
|
|
|
float selectedFileSegmentXStart = x + STREAMGRAPH_X_BORDER + ( (float)(accumulatedMemoryBeforeSelected) / (float)( m_nMaxMemMB * 1024 * 1024 ) ) * GetGraphWidth();
|
|
float selectedFileSegmentXEnd = selectedFileSegmentXStart + ( (float)(selectedSegmentMemorySize) / (float)( m_nMaxMemMB * 1024 * 1024 ) ) * GetGraphWidth();
|
|
|
|
// Never draw the segment smaller than one pixel, or it's kind of confusing.
|
|
selectedFileSegmentXEnd = Max( selectedFileSegmentXStart + 1, selectedFileSegmentXEnd );
|
|
|
|
fwRect selectedFileSegmentRect
|
|
(
|
|
(float) selectedFileSegmentXStart, // left
|
|
(float) y + STREAMGRAPH_BAR_SPACING(), // bottom
|
|
(float) selectedFileSegmentXEnd, // right
|
|
(float) y + STREAMGRAPH_BAR_SPACING() - STREAMGRAPH_BAR_HEIGHT() // top
|
|
);
|
|
|
|
Color32 selectedFileSegmentColor( 255, 255, 255, 255 );
|
|
|
|
CSprite2d::DrawRectSlow( selectedFileSegmentRect, selectedFileSegmentColor );
|
|
}
|
|
|
|
return heightOfBarDrawn;
|
|
}
|
|
|
|
void CStreamGraph::DrawMemoryMarkers(float x, float y)
|
|
{
|
|
Vector2 p1(STREAMGRAPH_SCREEN_COORDS(x+STREAMGRAPH_X_BORDER, y+STREAMGRAPH_BAR_SPACING()));
|
|
Vector2 p2(STREAMGRAPH_SCREEN_COORDS(x+STREAMGRAPH_X_BORDER+GetGraphWidth(), y+STREAMGRAPH_BAR_SPACING()));
|
|
grcDebugDraw::Line(p1, p2, Color32(255, 255, 255, 255));
|
|
|
|
if (m_nMaxMemMB<=20)
|
|
{
|
|
// draw marker for each mb
|
|
float fDiv = (float)GetGraphWidth() / m_nMaxMemMB;
|
|
for (u32 i=0; i<m_nMaxMemMB+1; i++)
|
|
{
|
|
Vector2 p1(STREAMGRAPH_SCREEN_COORDS(x+STREAMGRAPH_X_BORDER+i*fDiv, y+STREAMGRAPH_BAR_SPACING()-STREAMGRAPH_BAR_HEIGHT()*0.25f));
|
|
Vector2 p2(STREAMGRAPH_SCREEN_COORDS(x+STREAMGRAPH_X_BORDER+i*fDiv, y+STREAMGRAPH_BAR_SPACING()));
|
|
grcDebugDraw::Line(p1, p2, Color32(255, 255, 255, 255));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// draw marker for every 10mb
|
|
float fDiv = (float)GetGraphWidth() / m_nMaxMemMB;
|
|
for (u32 i=0; i<(m_nMaxMemMB/10)+1; i++)
|
|
{
|
|
Vector2 p1(STREAMGRAPH_SCREEN_COORDS(x+STREAMGRAPH_X_BORDER+i*fDiv*10, y+STREAMGRAPH_BAR_SPACING()-STREAMGRAPH_BAR_HEIGHT()*0.25f));
|
|
Vector2 p2(STREAMGRAPH_SCREEN_COORDS(x+STREAMGRAPH_X_BORDER+i*fDiv*10, y+STREAMGRAPH_BAR_SPACING()));
|
|
grcDebugDraw::Line(p1, p2, Color32(255, 255, 255, 255));
|
|
}
|
|
}
|
|
}
|
|
|
|
float CStreamGraph::DrawLegend(float x, float y)
|
|
{
|
|
const float fBoxW = 10.0f;
|
|
|
|
CTextLayout DebugTextLayout;
|
|
DebugTextLayout.SetScale(Vector2(0.3f, 0.3f));
|
|
DebugTextLayout.SetColor(Color32(255, 255, 255, 255));
|
|
|
|
float yEnd = y;
|
|
|
|
if(m_ShowLODBreakdown)
|
|
{
|
|
s32 numCategories = sizeof(sAssetLODLegend)/sizeof(sAssetLODLegend[0]);
|
|
|
|
for (u32 i=0; i<numCategories; i++)
|
|
{
|
|
Color32 boxColor = GetLegendColour(i);
|
|
const char* label = sAssetLODLegend[i].label;
|
|
|
|
float fScreenX = (float)x;
|
|
float fScreenY = y + i * 20.0f;
|
|
|
|
fwRect boxRect(fScreenX,fScreenY + fBoxW,fScreenX + fBoxW,fScreenY);
|
|
CSprite2d::DrawRectSlow(boxRect, boxColor);
|
|
DebugTextLayout.Render(STREAMGRAPH_SCREEN_COORDS(fScreenX+10.0f, fScreenY-5.0f), label);
|
|
}
|
|
yEnd = y + (numCategories + 1) * 20;
|
|
}
|
|
else
|
|
|
|
if ( m_statBuffers[ SCENESTREAMINGMEMORYTRACKER_BUFFER_RENDER ].m_Transposed )
|
|
{
|
|
strStreamingModuleMgr& moduleMgr = strStreamingEngine::GetInfo().GetModuleMgr();
|
|
|
|
u32 numModules = GetNumTrackedModules();
|
|
|
|
u32 visibleModuleIdx = 0;
|
|
for ( u32 i = 0; i < numModules; i++ )
|
|
{
|
|
if ( !m_statBuffers[ SCENESTREAMINGMEMORYTRACKER_BUFFER_RENDER ].m_Modules[ i ].HasNonZeroCategory( m_ShowVirtualMemory, m_ShowPhysicalMemory ) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
strStreamingModule* pModule = moduleMgr.GetModule(i);
|
|
|
|
Color32 boxColor = GetLegendColour( i );
|
|
const char* label = pModule->GetModuleName();
|
|
|
|
float fScreenX = (float)x;
|
|
float fScreenY = y + visibleModuleIdx * 20.0f;
|
|
|
|
fwRect boxRect(fScreenX,fScreenY + fBoxW,fScreenX + fBoxW,fScreenY);
|
|
CSprite2d::DrawRectSlow(boxRect, boxColor);
|
|
DebugTextLayout.Render(STREAMGRAPH_SCREEN_COORDS(fScreenX+10.0f, fScreenY-4.0f), label);
|
|
visibleModuleIdx++;
|
|
}
|
|
|
|
yEnd = y + (visibleModuleIdx + 1) * 20;
|
|
}
|
|
else
|
|
{
|
|
if ( m_ShowCategoryBreakdown )
|
|
{
|
|
s32 numCategories = sizeof(sAssetCategoryLegend)/sizeof(sAssetCategoryLegend[0]);
|
|
|
|
for (u32 i=0; i<numCategories; i++)
|
|
{
|
|
Color32 boxColor = GetLegendColour(i);
|
|
const char* label = sAssetCategoryLegend[i].label;
|
|
|
|
float fScreenX = (float)x;
|
|
float fScreenY = y + i * 20.0f;
|
|
|
|
fwRect boxRect(fScreenX,fScreenY + fBoxW,fScreenX + fBoxW,fScreenY);
|
|
CSprite2d::DrawRectSlow(boxRect, boxColor);
|
|
DebugTextLayout.Render(STREAMGRAPH_SCREEN_COORDS(fScreenX+10.0f, fScreenY-5.0f), label);
|
|
}
|
|
|
|
yEnd = y + (numCategories + 1) * 20;
|
|
}
|
|
}
|
|
|
|
return yEnd;
|
|
}
|
|
|
|
void CStreamGraph::DrawFileList(float x, float y)
|
|
{
|
|
CTextLayout DebugTextLayout;
|
|
DebugTextLayout.SetScale(Vector2(0.3f, 0.3f));
|
|
|
|
CStreamGraphBuffer & buffer = m_statBuffers[ SCENESTREAMINGMEMORYTRACKER_BUFFER_RENDER ];
|
|
|
|
const float headerSize = 16.0f*STREAMGRAPH_FONTSCALE_FACTOR();
|
|
float xStart= x;
|
|
float xEnd = x + GetFileListWidth();
|
|
float yStart = y + 5 + headerSize;
|
|
float yEnd = yStart + buffer.m_NumListEntries * 16;
|
|
float yLength = yEnd - yStart;
|
|
float y0 = yStart + yLength * (float)buffer.m_ListOffset / (float)buffer.m_NumFilesInSelectedBar;
|
|
float y1 = y0 + yLength * (float)buffer.m_NumListEntries / (float)buffer.m_NumFilesInSelectedBar;
|
|
|
|
fwRect scrollBarThumb(xEnd - 14, y1, xEnd - 4, y0);
|
|
CSprite2d::DrawRectSlow(scrollBarThumb, Color_white);
|
|
fwRect scrollBarThumbInner(xEnd - 12, y1, xEnd - 6, y0);
|
|
CSprite2d::DrawRectSlow(scrollBarThumbInner, Color_black);
|
|
|
|
if(m_statBuffers[ SCENESTREAMINGMEMORYTRACKER_BUFFER_RENDER ].m_Transposed)
|
|
{
|
|
float trackLeft = xEnd - 11;
|
|
float trackRight = xEnd - 7;
|
|
|
|
u32 totalFiles = buffer.m_NumFilesInSelectedBar;
|
|
u32 totalFilesSoFar = 0;
|
|
s32 numModules = GetNumTrackedModules();
|
|
|
|
for (u32 i=0; i<numModules; i++)
|
|
{
|
|
u32 numFiles = buffer.m_NumFilesInSelectedCategoryModule[i];
|
|
|
|
float yStartFraction = (float)totalFilesSoFar / (float)totalFiles;
|
|
float yEndFraction = (float)(totalFilesSoFar + numFiles) / (float)totalFiles;
|
|
float yStartCategory = Lerp(yStartFraction, yStart, yEnd);
|
|
float yEndCategory = Lerp(yEndFraction, yStart, yEnd);
|
|
|
|
Color32 categoryColor = GetLegendColour(i);
|
|
fwRect scrollBarTrack(trackLeft,yEndCategory, trackRight, yStartCategory);
|
|
CSprite2d::DrawRectSlow(scrollBarTrack, categoryColor);
|
|
|
|
totalFilesSoFar += numFiles;
|
|
}
|
|
}
|
|
else if(m_ShowCategoryBreakdown)
|
|
{
|
|
float trackLeft = xEnd - 11;
|
|
float trackRight = xEnd - 7;
|
|
|
|
u32 totalFiles = buffer.m_NumFilesInSelectedBar;
|
|
u32 totalFilesSoFar = 0;
|
|
s32 numCategories = sizeof(sAssetCategoryLegend)/sizeof(sAssetCategoryLegend[0]);
|
|
|
|
for (u32 i=0; i<numCategories; i++)
|
|
{
|
|
u32 numFiles = buffer.m_NumFilesInSelectedModuleCategory[i];
|
|
|
|
float yStartFraction = (float)totalFilesSoFar / (float)totalFiles;
|
|
float yEndFraction = (float)(totalFilesSoFar + numFiles) / (float)totalFiles;
|
|
float yStartCategory = Lerp(yStartFraction, yStart, yEnd);
|
|
float yEndCategory = Lerp(yEndFraction, yStart, yEnd);
|
|
|
|
Color32 categoryColor = GetLegendColour(i);
|
|
fwRect scrollBarTrack(trackLeft,yEndCategory, trackRight, yStartCategory);
|
|
CSprite2d::DrawRectSlow(scrollBarTrack, categoryColor);
|
|
|
|
totalFilesSoFar += numFiles;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fwRect scrollBarTrack(xEnd - 11,yEnd, xEnd - 7, yStart);
|
|
CSprite2d::DrawRectSlow(scrollBarTrack, Color_white);
|
|
}
|
|
|
|
// header
|
|
Color32 color = Color_white;
|
|
DebugTextLayout.SetColor(color);
|
|
char fileListHeader[128];
|
|
const char * barName = buffer.m_Transposed ? sAssetCategoryLegend[ buffer.m_CurrentlySelectedCategoryIdx ].label : GetSelectedModule(buffer)->GetModuleName();
|
|
formatf(fileListHeader, 128, "%s: %i files", barName, buffer.m_NumFilesInSelectedBar);
|
|
DebugTextLayout.Render(STREAMGRAPH_SCREEN_COORDS(xStart, yStart - headerSize), fileListHeader);
|
|
|
|
// Show the size of the currently selected item.
|
|
char sizeInfo[64];
|
|
formatf(sizeInfo, "Selected: %dKB (M), %dKB (V)", buffer.m_SelectedFileData.m_VirtualSize / 1024, buffer.m_SelectedFileData.m_PhysicalSize / 1024);
|
|
DebugTextLayout.SetColor(Color_green);
|
|
DebugTextLayout.Render(STREAMGRAPH_SCREEN_COORDS(xStart, yStart), sizeInfo);
|
|
yStart += 18*STREAMGRAPH_FONTSCALE_FACTOR();
|
|
|
|
fwRect headerUnderline(xStart,yStart - 2,xEnd - 4,yStart - 1);
|
|
CSprite2d::DrawRectSlow(headerUnderline, Color_white);
|
|
|
|
// list
|
|
for(int i = 0; i < buffer.m_NumListEntries; ++i)
|
|
{
|
|
Color32 color = i == (buffer.m_SelectedListEntry - buffer.m_ListOffset) ? Color_green : Color_white;
|
|
DebugTextLayout.SetColor(color);
|
|
DebugTextLayout.Render(STREAMGRAPH_SCREEN_COORDS(xStart, i * 16 + yStart), buffer.m_ListBuffer[i].m_fileName);
|
|
|
|
// Draw the memory size to the right
|
|
char textBuffer[256];
|
|
sprintf(textBuffer, "%dK(M), %dK(V)", buffer.m_ListBuffer[i].m_vSize / 1024, buffer.m_ListBuffer[i].m_pSize / 1024);
|
|
Vector2 textWrap(0.0f, (xEnd-24.0f)/grcViewport::GetDefaultScreen()->GetWidth());
|
|
DebugTextLayout.SetWrap(textWrap);
|
|
DebugTextLayout.SetOrientation(FONT_RIGHT);
|
|
DebugTextLayout.Render(STREAMGRAPH_SCREEN_COORDS(0.0f, i * 16 + yStart), textBuffer);
|
|
DebugTextLayout.SetOrientation(FONT_LEFT);
|
|
}
|
|
}
|
|
|
|
void CStreamGraph::CreateAssetInfoString(strIndex index, char *outBuffer, size_t bufferSize)
|
|
{
|
|
char flagString[256];
|
|
char refCntString[32];
|
|
|
|
strStreamingInfo &info = strStreamingEngine::GetInfo().GetStreamingInfoRef(index);
|
|
strStreamingModule *module = strStreamingEngine::GetInfo().GetModule(index);
|
|
|
|
CreateFlagString(info.GetFlags(), flagString, sizeof(flagString));
|
|
module->GetRefCountString(module->GetObjectIndex(index), refCntString, sizeof(refCntString));
|
|
|
|
formatf(outBuffer, bufferSize, "%-40s %s dp=%d %s", strStreamingEngine::GetObjectName(index), refCntString, info.GetDependentCount(), flagString);
|
|
}
|
|
|
|
void CStreamGraph::DrawFileInfo(float x, float y)
|
|
{
|
|
char achMsg[400];
|
|
CTextLayout DebugTextLayout;
|
|
DebugTextLayout.SetScale(Vector2(0.3f, 0.3f));
|
|
|
|
CStreamGraphBuffer & buffer = m_statBuffers[ SCENESTREAMINGMEMORYTRACKER_BUFFER_RENDER ];
|
|
const CStreamGraphSelectedFileData &fileData = buffer.m_SelectedFileData;
|
|
|
|
y += STREAMGRAPH_MODULE_SPACING();
|
|
|
|
// hack so drawable data fits on screen
|
|
{
|
|
x = 80;
|
|
y = 80;
|
|
}
|
|
|
|
// Finally draw the current file from the current module being enumerated with the direction keys
|
|
u32 flags = buffer.m_SelectedFileData.m_Flags;
|
|
|
|
strStreamingModule* selectedModule = GetSelectedModule(buffer);
|
|
if(selectedModule)
|
|
{
|
|
strLocalIndex objIdx = strLocalIndex(buffer.m_CurrentlySelectedFileObjIdx);
|
|
strIndex streamIndex = selectedModule->GetStreamingIndex(objIdx);
|
|
int dependentCount = strStreamingEngine::GetInfo().GetStreamingInfoRef(streamIndex).GetDependentCount();
|
|
|
|
snprintf( achMsg, NELEM(achMsg) - 1, "(%s), file %s main = %d vram = %d\nstrIndex=%d objIndex=%d\n%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s dp=%d",
|
|
selectedModule->GetModuleName(),
|
|
buffer.m_SelectedFileData.m_Name,
|
|
buffer.m_SelectedFileData.m_VirtualSize,
|
|
buffer.m_SelectedFileData.m_PhysicalSize,
|
|
streamIndex.Get(), objIdx.Get(),
|
|
flags & STRFLAG_DONTDELETE ? "DONT_DELETE" : "",
|
|
flags & STRFLAG_FORCE_LOAD ? "FORCE_LOAD" : "",
|
|
flags & STRFLAG_PRIORITY_LOAD ? "PRIORITY_LOAD" : "",
|
|
flags & STRFLAG_LOADSCENE ? "LOAD_SCENE" : "",
|
|
flags & STRFLAG_MISSION_REQUIRED ? "MISSION_REQUIRED" : "",
|
|
flags & STRFLAG_CUTSCENE_REQUIRED ? "CUTSCENE_REQUIRED" : "",
|
|
flags & STRFLAG_INTERIOR_REQUIRED ? "INTERIOR_REQUIRED" : "",
|
|
flags & STRFLAG_ZONEDASSET_REQUIRED ? "ZONEDASSET_REQUIRED" : "",
|
|
flags & STRFLAG_INTERNAL_LIVE ? "LIVE" : "",
|
|
flags & STRFLAG_INTERNAL_DUMMY ? "DUMMY" : "",
|
|
flags & STRFLAG_INTERNAL_COMPRESSED ? "COMPRESSED" : "",
|
|
flags & STRFLAG_INTERNAL_RESOURCE ? "RESOURCE" : "",
|
|
flags & STRFLAG_INTERNAL_DEFRAGGING ? "DEFRAGGING" : "",
|
|
flags & STRFLAG_INTERNAL_DONT_DEFRAG ? "DONT_DEFRAG" : "",
|
|
flags & STRFLAG_INTERNAL_PLACING ? "PLACING" : "",
|
|
flags & STRFLAG_INTERNAL_UNUSED_2 ? "UNUSED2" : "",
|
|
dependentCount
|
|
);
|
|
|
|
DebugTextLayout.SetColor(Color32(255, 255, 255, 255));
|
|
DebugTextLayout.Render(STREAMGRAPH_SCREEN_COORDS(x, y), achMsg);
|
|
|
|
// Add ref count information
|
|
if (m_ShowExtendedFileInfo)
|
|
{
|
|
y+= 48*STREAMGRAPH_FONTSCALE_FACTOR();
|
|
|
|
// Show dependencies
|
|
char refCountInfo[256] = "Ref Cnt: ";
|
|
selectedModule->GetRefCountString(objIdx, &refCountInfo[9], sizeof(refCountInfo));
|
|
DebugTextLayout.Render(STREAMGRAPH_SCREEN_COORDS(x, y), refCountInfo);
|
|
|
|
char assetString[256];
|
|
strIndex deps[256];
|
|
int depCount = selectedModule->GetDependencies(objIdx, deps, NELEM(deps));
|
|
|
|
if (depCount)
|
|
{
|
|
y+= 16*STREAMGRAPH_FONTSCALE_FACTOR();
|
|
DebugTextLayout.Render(STREAMGRAPH_SCREEN_COORDS(x, y), "IMMEDIATE DEPENDENCIES:");
|
|
|
|
for (int i=0; i<depCount; i++)
|
|
{
|
|
if(strStreamingEngine::GetInfo().HasObjectLoaded(deps[i]))
|
|
{
|
|
y+= 16*STREAMGRAPH_FONTSCALE_FACTOR();
|
|
CreateAssetInfoString(deps[i], assetString, sizeof(assetString));
|
|
DebugTextLayout.Render(STREAMGRAPH_SCREEN_COORDS(x + 32, y), assetString);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Show dependents
|
|
if (fileData.m_DependentCount)
|
|
{
|
|
y+= 16*STREAMGRAPH_FONTSCALE_FACTOR();
|
|
DebugTextLayout.Render(STREAMGRAPH_SCREEN_COORDS(x, y), "IMMEDIATE DEPENDENTS:");
|
|
|
|
for (int i=0; i<fileData.m_DependentCount; i++)
|
|
{
|
|
if(strStreamingEngine::GetInfo().HasObjectLoaded(fileData.m_Dependents[i]))
|
|
{
|
|
y+= 16*STREAMGRAPH_FONTSCALE_FACTOR();
|
|
CreateAssetInfoString(fileData.m_Dependents[i], assetString, sizeof(assetString));
|
|
DebugTextLayout.Render(STREAMGRAPH_SCREEN_COORDS(x + 32, y), assetString);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Color32 color = Color_white;
|
|
DebugTextLayout.SetColor(color);
|
|
|
|
for(int i = 0; i < buffer.m_NumFileInfoEntries; ++i)
|
|
{
|
|
DebugTextLayout.Render(STREAMGRAPH_SCREEN_COORDS(x, i * 16 + y + 32), buffer.m_FileInfoBuffer[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CStreamGraph::DrawDebug()
|
|
{
|
|
if ( !m_ShowMemoryTracker || ( !m_ShowPhysicalMemory && !m_ShowVirtualMemory ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if( m_ShowLODBreakdown )
|
|
{
|
|
DrawLODStats();
|
|
return;
|
|
}
|
|
|
|
CTextLayout DebugTextLayout;
|
|
DebugTextLayout.SetScale(Vector2(0.3f, 0.3f));
|
|
|
|
CStreamGraphBuffer & buffer = m_statBuffers[ SCENESTREAMINGMEMORYTRACKER_BUFFER_RENDER ];
|
|
s32 numModules = GetNumTrackedModules();
|
|
|
|
DrawTitle();
|
|
DrawBackground();
|
|
|
|
s32 yAxisCount = numModules;
|
|
s32 xAxisCount = sizeof(sAssetCategoryLegend)/sizeof(sAssetCategoryLegend[0]);
|
|
if ( buffer.m_Transposed )
|
|
{
|
|
std::swap( xAxisCount, yAxisCount );
|
|
}
|
|
|
|
float barOffset = 0.0f;
|
|
|
|
// Start off with the master memory display
|
|
barOffset += DrawMasterMemoryBar(m_vPos.x, m_vPos.y + barOffset);
|
|
|
|
// Draw streaming graph bars
|
|
for ( s32 yAxisIdx = 0; yAxisIdx < yAxisCount; yAxisIdx++ )
|
|
{
|
|
barOffset += DrawMemoryBar(yAxisIdx, xAxisCount, m_vPos.x, m_vPos.y + barOffset);
|
|
}
|
|
|
|
// Draw any extension bars
|
|
for(int i=0;i<m_pStreamGraphExtManager->GetNumExtensions();i++)
|
|
{
|
|
CStreamGraphExtensionBase *pExtension = m_pStreamGraphExtManager->GetExtension(i);
|
|
if( pExtension->IsActive() )
|
|
{
|
|
barOffset += pExtension->DrawMemoryBar(m_vPos.x, m_vPos.y + barOffset);
|
|
}
|
|
}
|
|
|
|
if(!m_pStreamGraphExtManager->m_bExtensionSelected[SCENESTREAMINGMEMORYTRACKER_BUFFER_RENDER])
|
|
{
|
|
// Normal streamgraph selected
|
|
float legendBottom = DrawLegend(m_vPos.x + GetGraphWidth() + 20, m_vPos.y + 5);
|
|
DrawFileList(m_vPos.x + GetWindowWidth() - GetFileListWidth(), legendBottom);
|
|
if (m_ShowFileInfo)
|
|
{
|
|
DrawFileInfo(m_vPos.x, m_vPos.y + 540*STREAMGRAPH_FONTSCALE_FACTOR());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Extension selected
|
|
CStreamGraphExtensionBase *pExtension = m_pStreamGraphExtManager->GetSelectedExt(SCENESTREAMINGMEMORYTRACKER_BUFFER_RENDER);
|
|
float legendBottom = pExtension->DrawLegend(m_vPos.x + GetGraphWidth() + 20, m_vPos.y + 5);
|
|
pExtension->DrawFileList(m_vPos.x + GetWindowWidth() - GetFileListWidth(), legendBottom);
|
|
if (m_ShowFileInfo)
|
|
{
|
|
pExtension->DrawFileInfo(80*STREAMGRAPH_FONTSCALE_FACTOR(),80*STREAMGRAPH_FONTSCALE_FACTOR());
|
|
}
|
|
}
|
|
}
|
|
|
|
void CStreamGraph::SetFirstSelected()
|
|
{
|
|
CStreamGraphBuffer &buffer = m_statBuffers[ SCENESTREAMINGMEMORYTRACKER_BUFFER_UPDATE ];
|
|
|
|
buffer.m_CurrentlySelectedCategoryIdx = 0;
|
|
|
|
buffer.m_CurrentlySelectedModuleIdx = 0;
|
|
while( !buffer.m_Modules[ buffer.m_CurrentlySelectedModuleIdx ].HasNonZeroCategory( m_ShowVirtualMemory, m_ShowPhysicalMemory ) )
|
|
{
|
|
buffer.m_CurrentlySelectedModuleIdx++;
|
|
}
|
|
|
|
buffer.m_CurrentlySelectedFileIdx = 0;
|
|
buffer.m_CurrentlySelectedFileObjIdx = 0;
|
|
}
|
|
|
|
void CStreamGraph::SetLastSelected()
|
|
{
|
|
CStreamGraphBuffer &buffer = m_statBuffers[ SCENESTREAMINGMEMORYTRACKER_BUFFER_UPDATE ];
|
|
|
|
buffer.m_CurrentlySelectedCategoryIdx = GetNumTrackedCategories() - 1;
|
|
// Assumes at least one module will have some data, or it's going to go badly wrong!
|
|
buffer.m_CurrentlySelectedModuleIdx = strStreamingEngine::GetInfo().GetModuleMgr().GetNumberOfModules() - 1;
|
|
while( !buffer.m_Modules[ buffer.m_CurrentlySelectedModuleIdx ].HasNonZeroCategory( m_ShowVirtualMemory, m_ShowPhysicalMemory ) )
|
|
{
|
|
buffer.m_CurrentlySelectedModuleIdx--;
|
|
}
|
|
buffer.m_CurrentlySelectedFileIdx = 0;
|
|
buffer.m_CurrentlySelectedFileObjIdx = 0;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CStreamGraph::UpdateMemoryBarSelection()
|
|
{
|
|
CStreamGraphBuffer &buffer = m_statBuffers[ SCENESTREAMINGMEMORYTRACKER_BUFFER_UPDATE ];
|
|
|
|
if(m_pStreamGraphExtManager->m_bExtensionSelected[SCENESTREAMINGMEMORYTRACKER_BUFFER_UPDATE])
|
|
{
|
|
// Selecting Extension
|
|
if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_UP, KEYBOARD_MODE_DEBUG, "move up in extension lists"))
|
|
{
|
|
// Next one up
|
|
s32 next = m_pStreamGraphExtManager->GetPrevActive();
|
|
if( next != -1)
|
|
{
|
|
m_pStreamGraphExtManager->SetSelected(next);
|
|
}
|
|
else
|
|
{
|
|
// Setup whatever we need to transition back to the main bars
|
|
|
|
// Set the streamgraph normal bars to be the last one
|
|
SetLastSelected();
|
|
|
|
m_pStreamGraphExtManager->m_bExtensionSelected[SCENESTREAMINGMEMORYTRACKER_BUFFER_UPDATE] = false;
|
|
m_pStreamGraphExtManager->SetSelected(-1);
|
|
}
|
|
}
|
|
else if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_DOWN, KEYBOARD_MODE_DEBUG, "move down in extension lists") )
|
|
{
|
|
// Next one down
|
|
s32 next = m_pStreamGraphExtManager->GetNextActive();
|
|
if( next != -1)
|
|
{
|
|
m_pStreamGraphExtManager->SetSelected(next);
|
|
}
|
|
else
|
|
{
|
|
// Setup whatever we need to transition back to the main bars
|
|
|
|
// Set the streamgraph normal bars to be the first one
|
|
SetFirstSelected();
|
|
|
|
m_pStreamGraphExtManager->m_bExtensionSelected[SCENESTREAMINGMEMORYTRACKER_BUFFER_UPDATE] = false;
|
|
m_pStreamGraphExtManager->SetSelected(-1);
|
|
}
|
|
}
|
|
|
|
// A shit bodge incase someone decides to use the transpose button when on the category screen,
|
|
// because the category screen part uses m_CurrentlySelectedModuleIdx for other functionality and and can set it to be -1.
|
|
buffer.m_CurrentlySelectedModuleIdx = Clamp( buffer.m_CurrentlySelectedModuleIdx, 0, strStreamingEngine::GetInfo().GetModuleMgr().GetNumberOfModules() - 1 );
|
|
}
|
|
else
|
|
|
|
if(m_TransposeGraph)
|
|
{
|
|
s32 originalCategorySelection = buffer.m_CurrentlySelectedCategoryIdx;
|
|
|
|
if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_UP, KEYBOARD_MODE_DEBUG, "move up in category lists"))
|
|
{
|
|
--buffer.m_CurrentlySelectedCategoryIdx;
|
|
}
|
|
if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_DOWN, KEYBOARD_MODE_DEBUG, "move down in category lists") )
|
|
{
|
|
++buffer.m_CurrentlySelectedCategoryIdx;
|
|
}
|
|
|
|
if( buffer.m_CurrentlySelectedCategoryIdx < 0 )
|
|
{
|
|
if( m_pStreamGraphExtManager->GetActiveCount() )
|
|
{
|
|
m_pStreamGraphExtManager->SetLastSelected();
|
|
m_pStreamGraphExtManager->m_bExtensionSelected[SCENESTREAMINGMEMORYTRACKER_BUFFER_UPDATE] = true;
|
|
//return;
|
|
}
|
|
}
|
|
else if( buffer.m_CurrentlySelectedCategoryIdx >= GetNumTrackedCategories() )
|
|
{
|
|
if( m_pStreamGraphExtManager->GetActiveCount() )
|
|
{
|
|
m_pStreamGraphExtManager->SetFirstSelected();
|
|
m_pStreamGraphExtManager->m_bExtensionSelected[SCENESTREAMINGMEMORYTRACKER_BUFFER_UPDATE] = true;
|
|
//return;
|
|
}
|
|
}
|
|
|
|
|
|
buffer.m_CurrentlySelectedCategoryIdx = Clamp(buffer.m_CurrentlySelectedCategoryIdx, 0, GetNumTrackedCategories() - 1);
|
|
|
|
if ( originalCategorySelection != buffer.m_CurrentlySelectedCategoryIdx )
|
|
{
|
|
buffer.m_CurrentlySelectedFileIdx = 0;
|
|
buffer.m_CurrentlySelectedFileObjIdx = 0;
|
|
buffer.m_CurrentlySelectedModuleIdx = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
buffer.m_CurrentlySelectedModuleIdx = Clamp( buffer.m_CurrentlySelectedModuleIdx, 0, strStreamingEngine::GetInfo().GetModuleMgr().GetNumberOfModules() - 1 );
|
|
|
|
s32 nextModuleSelection = buffer.m_CurrentlySelectedModuleIdx;
|
|
|
|
if( !buffer.m_Modules[ buffer.m_CurrentlySelectedModuleIdx ].HasNonZeroCategory( m_ShowVirtualMemory, m_ShowPhysicalMemory ) ||
|
|
CControlMgr::GetKeyboard().GetKeyJustDown(KEY_UP, KEYBOARD_MODE_DEBUG, "move up in category lists"))
|
|
{
|
|
do
|
|
{
|
|
nextModuleSelection--;
|
|
if ( nextModuleSelection < 0 )
|
|
{
|
|
// We've gone off the end, does this push us into the Extensions?
|
|
if( m_pStreamGraphExtManager->GetActiveCount() )
|
|
{
|
|
m_pStreamGraphExtManager->SetLastSelected();
|
|
m_pStreamGraphExtManager->m_bExtensionSelected[SCENESTREAMINGMEMORYTRACKER_BUFFER_UPDATE] = true;
|
|
return;
|
|
}
|
|
|
|
nextModuleSelection += strStreamingEngine::GetInfo().GetModuleMgr().GetNumberOfModules();
|
|
}
|
|
|
|
if ( buffer.m_Modules[ nextModuleSelection ].HasNonZeroCategory( m_ShowVirtualMemory, m_ShowPhysicalMemory ) )
|
|
{
|
|
break;
|
|
}
|
|
|
|
} while ( buffer.m_CurrentlySelectedModuleIdx != nextModuleSelection );
|
|
}
|
|
|
|
if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_DOWN, KEYBOARD_MODE_DEBUG, "move down in category lists") )
|
|
{
|
|
do
|
|
{
|
|
nextModuleSelection++;
|
|
if ( nextModuleSelection >= strStreamingEngine::GetInfo().GetModuleMgr().GetNumberOfModules() )
|
|
{
|
|
// We've gone off the end, does this push us into the Extensions?
|
|
if( m_pStreamGraphExtManager->GetActiveCount() )
|
|
{
|
|
m_pStreamGraphExtManager->SetFirstSelected();
|
|
m_pStreamGraphExtManager->m_bExtensionSelected[SCENESTREAMINGMEMORYTRACKER_BUFFER_UPDATE] = true;
|
|
return;
|
|
}
|
|
|
|
nextModuleSelection -= strStreamingEngine::GetInfo().GetModuleMgr().GetNumberOfModules();
|
|
}
|
|
|
|
if ( buffer.m_Modules[ nextModuleSelection ].HasNonZeroCategory( m_ShowVirtualMemory, m_ShowPhysicalMemory ) )
|
|
{
|
|
break;
|
|
}
|
|
|
|
} while ( buffer.m_CurrentlySelectedModuleIdx != nextModuleSelection );
|
|
}
|
|
|
|
if ( nextModuleSelection != buffer.m_CurrentlySelectedModuleIdx )
|
|
{
|
|
buffer.m_CurrentlySelectedFileIdx = 0;
|
|
buffer.m_CurrentlySelectedFileObjIdx = 0;
|
|
buffer.m_CurrentlySelectedModuleIdx = nextModuleSelection;
|
|
buffer.m_CurrentlySelectedCategoryIdx = 0;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CStreamGraph::UpdateRepositionWindow()
|
|
{
|
|
// handle mouse click
|
|
const Vector2 mousePosition = Vector2( static_cast<float>(ioMouse::GetX()), static_cast<float>(ioMouse::GetY()) );
|
|
|
|
if (m_bMove)
|
|
{
|
|
// already dragging so adjust position of results boxSTREAMGRAPH_TITLE_HEIGHT
|
|
m_vPos = mousePosition - m_vClickDragDelta;
|
|
if (m_vPos.x<0.0f)
|
|
{
|
|
m_vPos.Set(0.0f, m_vPos.y);
|
|
m_vClickDragDelta = mousePosition - m_vPos;
|
|
}
|
|
if (m_vPos.y<0.0f)
|
|
{
|
|
m_vPos.Set(0.0f, m_vPos.y);
|
|
m_vClickDragDelta = mousePosition - m_vPos;
|
|
}
|
|
|
|
// check for button release
|
|
if ((ioMouse::GetButtons()&ioMouse::MOUSE_LEFT) == false)
|
|
{
|
|
m_bMove = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// check for player clicking on title bar
|
|
if (ioMouse::GetButtons()&ioMouse::MOUSE_LEFT)
|
|
{
|
|
fwRect rect
|
|
(
|
|
m_vPos.x,
|
|
m_vPos.y,
|
|
m_vPos.x + GetGraphWidth(),
|
|
m_vPos.y + STREAMGRAPH_TITLE_HEIGHT()
|
|
);
|
|
|
|
if (rect.IsInside(mousePosition))
|
|
{
|
|
m_bMove = true;
|
|
m_vClickDragDelta = mousePosition - m_vPos;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CStreamGraph::CheckToggleOnOff()
|
|
{
|
|
if( m_ShowMemoryTracker && !m_ShowMemoryTrackerToggle )
|
|
{
|
|
// We just turned on
|
|
AllocateMemoryForLODDisplay();
|
|
}
|
|
else if(!m_ShowMemoryTracker && m_ShowMemoryTrackerToggle)
|
|
{
|
|
// Just just turned off
|
|
FreeMemoryForLODDisplay();
|
|
}
|
|
|
|
m_ShowMemoryTrackerToggle = m_ShowMemoryTracker;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CStreamGraph::Update()
|
|
{
|
|
// Keyboard shortcut
|
|
if (CControlMgr::GetKeyboard().GetKeyJustDown(KEY_S, KEYBOARD_MODE_DEBUG_SHIFT, "show stream graph"))
|
|
{
|
|
// On PS3, we'll toggle between memory types.
|
|
#if __PPU
|
|
if (m_ShowMemoryTracker)
|
|
{
|
|
// Here's a funny idea - let's turn the two bools into a two-bit integer.
|
|
int memStatValue = (int) m_ShowVirtualMemory | ((int) m_ShowPhysicalMemory << 1);
|
|
|
|
if (memStatValue < 2)
|
|
{
|
|
// Turn it off again if we went through all combinations.
|
|
m_ShowMemoryTracker = false;
|
|
m_ShowVirtualMemory = m_ShowPhysicalMemory = true;
|
|
}
|
|
else
|
|
{
|
|
// Create the next combination.
|
|
memStatValue--;
|
|
m_ShowVirtualMemory = (memStatValue & 1) != 0;
|
|
m_ShowPhysicalMemory = (memStatValue & 2) != 0;
|
|
}
|
|
}
|
|
else
|
|
#endif // __PPU
|
|
m_ShowMemoryTracker = !m_ShowMemoryTracker;
|
|
}
|
|
|
|
CheckToggleOnOff();
|
|
|
|
if ( !m_ShowMemoryTracker || ( !m_ShowPhysicalMemory && !m_ShowVirtualMemory ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
CStreamGraphBuffer &buffer = m_statBuffers[ SCENESTREAMINGMEMORYTRACKER_BUFFER_UPDATE ];
|
|
#if __DEV
|
|
s32 originalSelectedModule = buffer.m_CurrentlySelectedModuleIdx;
|
|
s32 originalSelectedObjectIndex = buffer.m_CurrentlySelectedFileObjIdx;
|
|
#endif
|
|
|
|
UpdateRepositionWindow();
|
|
UpdateMemoryBarSelection();
|
|
CompareFunc compareFunc = GetCompareFunc();
|
|
ResetFileList();
|
|
|
|
BuildDependentOnList();
|
|
|
|
if(m_pStreamGraphExtManager->m_bExtensionSelected[SCENESTREAMINGMEMORYTRACKER_BUFFER_UPDATE])
|
|
{
|
|
// Do the keys left and right here
|
|
m_pStreamGraphExtManager->Update();
|
|
}
|
|
|
|
if( m_ShowLODBreakdown )
|
|
{
|
|
UpdateLodStats( );
|
|
}
|
|
else
|
|
if(m_TransposeGraph)
|
|
{
|
|
s32 numCategories = GetNumTrackedCategories();
|
|
|
|
// update just one module each time round, in addition to the currently selected module
|
|
static int updateCategory = 0;
|
|
s32 categoryId = updateCategory % numCategories;
|
|
++updateCategory;
|
|
|
|
if(categoryId == buffer.m_CurrentlySelectedCategoryIdx)
|
|
{
|
|
UpdateCategoryStats(categoryId, compareFunc);
|
|
}
|
|
else
|
|
{
|
|
UpdateCategoryStats(categoryId, NULL);
|
|
UpdateCategoryStats(buffer.m_CurrentlySelectedCategoryIdx, compareFunc);
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
{
|
|
s32 numModules = GetNumTrackedModules();
|
|
|
|
// update just one module each time round, in addition to the currently selected module
|
|
static int updateModule = 0;
|
|
s32 moduleId = updateModule % numModules;
|
|
++updateModule;
|
|
//for ( s32 moduleId = 0; moduleId < numModules; moduleId++ )
|
|
{
|
|
// Not actually necessary to sort anything but the one we're looking at, as the sorting is only obvious when moving through the files on the
|
|
// currently selected module with left/right.
|
|
UpdateModuleStats( moduleId, moduleId == buffer.m_CurrentlySelectedModuleIdx ? compareFunc : NULL );
|
|
}
|
|
|
|
if( buffer.m_CurrentlySelectedModuleIdx != -1)
|
|
{
|
|
if(moduleId != buffer.m_CurrentlySelectedModuleIdx)
|
|
{
|
|
UpdateModuleStats(buffer.m_CurrentlySelectedModuleIdx, compareFunc);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Render settings
|
|
buffer.m_Transposed = m_TransposeGraph;
|
|
|
|
#if __DEV
|
|
|
|
if ( buffer.m_CurrentlySelectedModuleIdx != originalSelectedModule || buffer.m_CurrentlySelectedFileObjIdx != originalSelectedObjectIndex )
|
|
{
|
|
strStreamingInfoManager & strInfoManager = strStreamingEngine::GetInfo();
|
|
if(buffer.m_CurrentlySelectedModuleIdx >= 0)
|
|
{
|
|
strIndex streamingIndex = strInfoManager.GetModuleMgr().GetModule(buffer.m_CurrentlySelectedModuleIdx)
|
|
->GetStreamingIndex(strLocalIndex(buffer.m_CurrentlySelectedFileObjIdx));
|
|
if(strInfoManager.IsObjectInImage(streamingIndex))
|
|
{
|
|
CStreamingDebug::SetResourceForEntityFraming(streamingIndex);
|
|
}
|
|
}
|
|
}
|
|
|
|
CStreamingDebug::UpdateObjectFraming();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CStreamGraph::SetSelectedFileName(CStreamGraphBuffer & buffer, const char * name)
|
|
{
|
|
strncpy(buffer.m_SelectedFileData.m_Name, name, CStreamGraphSelectedFileData::MAX_FILE_NAME_LENGTH);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
int CStreamGraph::GetNumTrackedCategories()
|
|
{
|
|
return CDataFileMgr::CONTENTS_MAX;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
int CStreamGraph::GetNumTrackedModules()
|
|
{
|
|
return Min(strStreamingEngine::GetInfo().GetModuleMgr().GetNumberOfModules(), CStreamGraphBuffer::MAX_TRACKED_MODULES);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
CStreamGraph::CompareFunc CStreamGraph::GetCompareFunc()
|
|
{
|
|
if (m_OrderByName)
|
|
{
|
|
return CompareStreamingInfoByName;
|
|
}
|
|
else
|
|
{
|
|
if ( m_ShowCategoryBreakdown )
|
|
{
|
|
if ( m_ShowPhysicalMemory && m_ShowVirtualMemory )
|
|
{
|
|
return CompareStreamingInfoByCategoryTotalSize;
|
|
}
|
|
else if ( m_ShowVirtualMemory )
|
|
{
|
|
return CompareStreamingInfoByCategoryVirtSize;
|
|
}
|
|
else
|
|
{
|
|
return CompareStreamingInfoByCategoryPhysSize;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( m_ShowPhysicalMemory && m_ShowVirtualMemory )
|
|
{
|
|
return CompareStreamingInfoByTotalSize;
|
|
}
|
|
else if ( m_ShowVirtualMemory )
|
|
{
|
|
return CompareStreamingInfoByVirtSize;
|
|
}
|
|
else
|
|
{
|
|
return CompareStreamingInfoByPhysSize;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
strStreamingModule * CStreamGraph::GetSelectedModule(const CStreamGraphBuffer & buffer)
|
|
{
|
|
s32 moduleId = buffer.m_CurrentlySelectedModuleIdx;
|
|
|
|
if(moduleId < 0 )
|
|
{
|
|
return NULL;
|
|
}
|
|
else
|
|
{
|
|
return strStreamingEngine::GetInfo().GetModuleMgr().GetModule(moduleId);
|
|
}
|
|
}
|
|
|
|
void CStreamGraph::GetDrawableInfo(const Drawable & drawable, u32 & vertexCount, int & textureCount)
|
|
{
|
|
vertexCount = 0;
|
|
const rmcLodGroup& lodGroup = drawable.GetLodGroup();
|
|
int lodIndex=0;
|
|
while (lodIndex < rage::LOD_COUNT && lodGroup.ContainsLod(lodIndex) )
|
|
{
|
|
const rmcLod& lod = lodGroup.GetLod(lodIndex);
|
|
|
|
int modelCount = lod.GetCount();
|
|
for (int i=0; i<modelCount; ++i)
|
|
{
|
|
grmModel* model = lod.GetModel(i);
|
|
|
|
int geomCount = model->GetGeometryCount();
|
|
for (int j=0; j<geomCount; ++j)
|
|
{
|
|
grmGeometry& geometry = model->GetGeometry(j);
|
|
vertexCount += geometry.GetVertexCount();
|
|
|
|
}
|
|
}
|
|
lodIndex++;
|
|
}
|
|
|
|
textureCount = 0;
|
|
const fwTxd * txd = drawable.GetShaderGroup().GetTexDict();
|
|
|
|
if(txd)
|
|
{
|
|
textureCount = txd->GetCount();
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CStreamGraph::SwapBuffers()
|
|
{
|
|
if(!m_ShowMemoryTracker)
|
|
return;
|
|
|
|
// copy dbl buffer stat vals
|
|
sysMemCpy
|
|
(
|
|
&m_statBuffers[SCENESTREAMINGMEMORYTRACKER_BUFFER_RENDER],
|
|
&m_statBuffers[SCENESTREAMINGMEMORYTRACKER_BUFFER_UPDATE],
|
|
sizeof(CStreamGraphBuffer)
|
|
);
|
|
|
|
// Copy LOD info buffers
|
|
sysMemCpy( &m_MemoryByLOD[SCENESTREAMINGMEMORYTRACKER_BUFFER_RENDER], &m_MemoryByLOD[SCENESTREAMINGMEMORYTRACKER_BUFFER_UPDATE], sizeof(MemoryByLODBuffer));
|
|
|
|
m_pStreamGraphExtManager->SwapBuffers();
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CStreamGraph::CollectResultsForAutoCapture( atArray<streamingMemoryResult*> &results )
|
|
{
|
|
USE_DEBUG_MEMORY();
|
|
|
|
m_statBuffers[ SCENESTREAMINGMEMORYTRACKER_BUFFER_UPDATE ].m_CurrentlySelectedFileIdx = -1;
|
|
m_statBuffers[ SCENESTREAMINGMEMORYTRACKER_BUFFER_UPDATE ].m_CurrentlySelectedModuleIdx = -1;
|
|
|
|
s32 numModules = GetNumTrackedModules();
|
|
for ( s32 moduleId = 0; moduleId < numModules; moduleId++ )
|
|
{
|
|
UpdateModuleStats( moduleId, NULL );
|
|
}
|
|
|
|
for ( s32 moduleId = 0; moduleId < numModules; moduleId++ )
|
|
{
|
|
streamingMemoryResult *result = rage_new streamingMemoryResult;
|
|
strStreamingModule* pModule = strStreamingEngine::GetInfo().GetModuleMgr().GetModule(moduleId);
|
|
result->moduleName.Set( pModule->GetModuleName(), istrlen(pModule->GetModuleName()), 0, -1 );
|
|
|
|
for ( u32 categoryIdx = 0; categoryIdx < CDataFileMgr::CONTENTS_MAX; categoryIdx++ )
|
|
{
|
|
result->categories[ categoryIdx ].categoryName.Set( sAssetCategoryLegend[ categoryIdx ].label, istrlen( sAssetCategoryLegend[ categoryIdx ].label ), 0, -1 );
|
|
result->categories[ categoryIdx ].physicalMemory = m_statBuffers[ SCENESTREAMINGMEMORYTRACKER_BUFFER_UPDATE ].m_Modules[ moduleId ].m_CostPhys[ categoryIdx ];
|
|
result->categories[ categoryIdx ].virtualMemory = m_statBuffers[ SCENESTREAMINGMEMORYTRACKER_BUFFER_UPDATE ].m_Modules[ moduleId ].m_CostVirt[ categoryIdx ];
|
|
}
|
|
|
|
results.Grow() = result;
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
int CStreamGraph::CompareStreamingInfoByVirtSize(const void* pVoidA, const void* pVoidB)
|
|
{
|
|
GraphEntry* pA = (GraphEntry*)pVoidA;
|
|
GraphEntry* pB = (GraphEntry*)pVoidB;
|
|
return pB->virtualSize - pA->virtualSize;
|
|
}
|
|
|
|
int CStreamGraph::CompareStreamingInfoByPhysSize(const void* pVoidA, const void* pVoidB)
|
|
{
|
|
GraphEntry* pA = (GraphEntry*)pVoidA;
|
|
GraphEntry* pB = (GraphEntry*)pVoidB;
|
|
return pB->physicalSize - pA->physicalSize;
|
|
}
|
|
|
|
int CStreamGraph::CompareStreamingInfoByTotalSize(const void* pVoidA, const void* pVoidB)
|
|
{
|
|
GraphEntry* pA = (GraphEntry*)pVoidA;
|
|
GraphEntry* pB = (GraphEntry*)pVoidB;
|
|
return (pB->virtualSize+pB->physicalSize) - (pA->virtualSize+pA->physicalSize);
|
|
}
|
|
|
|
int CStreamGraph::CompareStreamingInfoByCategoryPhysSize(const void* pVoidA, const void* pVoidB)
|
|
{
|
|
GraphEntry* pA = (GraphEntry*)pVoidA;
|
|
GraphEntry* pB = (GraphEntry*)pVoidB;
|
|
if ( pA->category == pB->category )
|
|
{
|
|
return CompareStreamingInfoByPhysSize( pVoidA, pVoidB );
|
|
}
|
|
return pA->category - pB->category;
|
|
}
|
|
|
|
int CStreamGraph::CompareStreamingInfoByCategoryVirtSize(const void* pVoidA, const void* pVoidB)
|
|
{
|
|
GraphEntry* pA = (GraphEntry*)pVoidA;
|
|
GraphEntry* pB = (GraphEntry*)pVoidB;
|
|
if ( pA->category == pB->category )
|
|
{
|
|
return CompareStreamingInfoByVirtSize( pVoidA, pVoidB );
|
|
}
|
|
return pA->category - pB->category;
|
|
}
|
|
|
|
int CStreamGraph::CompareStreamingInfoByCategoryTotalSize(const void* pVoidA, const void* pVoidB)
|
|
{
|
|
GraphEntry* pA = (GraphEntry*)pVoidA;
|
|
GraphEntry* pB = (GraphEntry*)pVoidB;
|
|
if ( pA->category == pB->category )
|
|
{
|
|
return CompareStreamingInfoByTotalSize( pVoidA, pVoidB );
|
|
}
|
|
return pA->category - pB->category;
|
|
}
|
|
|
|
int CStreamGraph::CompareStreamingInfoByName(const void* pVoidA, const void* pVoidB)
|
|
{
|
|
GraphEntry* pA = (GraphEntry*)pVoidA;
|
|
GraphEntry* pB = (GraphEntry*)pVoidB;
|
|
return strcmp(pA->name, pB->name);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
u32 CStreamGraph::GetStreamingCategory( strStreamingInfo *info )
|
|
{
|
|
s32 imageIndex = strPackfileManager::GetImageFileIndexFromHandle(info->GetHandle()).Get();
|
|
strStreamingFile* file = NULL;
|
|
if (imageIndex != -1)
|
|
{
|
|
file = strPackfileManager::GetImageFile( imageIndex );
|
|
}
|
|
u32 categoryIdx = CDataFileMgr::CONTENTS_DEFAULT;
|
|
if ( file )
|
|
{
|
|
if ( file->m_contentsType < CDataFileMgr::CONTENTS_MAX )
|
|
{
|
|
categoryIdx = file->m_contentsType;
|
|
}
|
|
}
|
|
return ( categoryIdx );
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CStreamGraph::ResetFileList()
|
|
{
|
|
CStreamGraphBuffer &updateBuffer = m_statBuffers[ SCENESTREAMINGMEMORYTRACKER_BUFFER_UPDATE ];
|
|
|
|
updateBuffer.m_NumListEntries = 0;
|
|
updateBuffer.m_SelectedListEntry = -1;
|
|
updateBuffer.m_NumFilesInSelectedBar = 0;
|
|
memset( updateBuffer.m_NumFilesInSelectedModuleCategory, 0, sizeof(updateBuffer.m_NumFilesInSelectedModuleCategory));
|
|
memset( updateBuffer.m_NumFilesInSelectedCategoryModule, 0, sizeof(updateBuffer.m_NumFilesInSelectedCategoryModule));
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
void CStreamGraph::AddDependenciesToMap(strIndex index, atMap<strIndex, bool> &outMap)
|
|
{
|
|
if (outMap.Access(index) == NULL)
|
|
{
|
|
outMap.Insert(index, true);
|
|
|
|
strIndex deps[256];
|
|
strStreamingModule* pModule = strStreamingEngine::GetInfo().GetModule(index);
|
|
strLocalIndex objIndex = pModule->GetObjectIndex(index);
|
|
|
|
int depCount = pModule->GetDependencies(objIndex, deps, NELEM(deps));
|
|
|
|
for (int x=0; x<depCount; x++)
|
|
{
|
|
AddDependenciesToMap(deps[x], outMap);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CStreamGraph::BuildDependentOnList()
|
|
{
|
|
USE_DEBUG_MEMORY();
|
|
|
|
if( m_OnlyIncludeCutsceneRequestedObjects || m_ExcludeCutsceneRequestedObjects /*|| m_OnlyIncludeScriptRequestedObjects*/ )
|
|
{
|
|
// Clear out the list of files
|
|
m_CutsceneRequired.Reset();
|
|
|
|
for(int moduleId = 0; moduleId < GetNumTrackedModules(); ++moduleId)
|
|
{
|
|
strStreamingModule* pModule = strStreamingEngine::GetInfo().GetModuleMgr().GetModule(moduleId);
|
|
|
|
for(s32 objIdx = 0; objIdx < pModule->GetCount(); ++objIdx)
|
|
{
|
|
strStreamingInfoManager & strInfoManager = strStreamingEngine::GetInfo();
|
|
strIndex streamingIndex = pModule->GetStreamingIndex(strLocalIndex(objIdx));
|
|
|
|
if ( strInfoManager.IsObjectInImage(streamingIndex) )
|
|
{
|
|
bool bLoaded = strInfoManager.HasObjectLoaded(streamingIndex);
|
|
bool bRequested = strInfoManager.IsObjectRequested(streamingIndex) || strInfoManager.IsObjectLoading(streamingIndex);
|
|
|
|
if( bLoaded || ( bRequested && m_IncludeRequestedObjects ) )
|
|
{
|
|
strStreamingInfo* info = strInfoManager.GetStreamingInfo(streamingIndex);
|
|
|
|
bool isCutsceneRequired = (info->GetFlags() & STRFLAG_CUTSCENE_REQUIRED) != 0;
|
|
|
|
// if( m_OnlyIncludeCutsceneRequestedObjects == isCutsceneRequired && m_ExcludeCutsceneRequestedObjects != isCutsceneRequired )
|
|
if (isCutsceneRequired)
|
|
{
|
|
// Add to list
|
|
AddDependenciesToMap(streamingIndex, m_CutsceneRequired);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if( m_OnlyIncludeScriptRequestedObjects )
|
|
{
|
|
// Clear out the list of files
|
|
m_ScriptDependentOnList.clear();
|
|
// Get the list of items and all the dependencies (minus ignored items)
|
|
CTheScripts::GetScriptHandlerMgr().GetScriptDependencyList(m_ScriptDependentOnList);
|
|
}
|
|
|
|
}
|
|
|
|
// Whizz through the list m_DependantOnList, to see if this object is a dependancy of one of them.
|
|
bool CStreamGraph::CheckIfDependency(atArray<strIndex> &dependentList, strIndex streamingIndex)
|
|
{
|
|
for(int i=0;i<dependentList.size();i++)
|
|
{
|
|
// Get the dependents of the parent
|
|
strIndex parentDeps[STREAMING_MAX_DEPENDENCIES];
|
|
strStreamingModule* pParentModule = strStreamingEngine::GetInfo().GetModule(dependentList[i]);
|
|
strLocalIndex parentObjIDX = pParentModule->GetObjectIndex(dependentList[i]);
|
|
s32 parentDepsCount = pParentModule->GetDependencies(parentObjIDX, &parentDeps[0], STREAMING_MAX_DEPENDENCIES);
|
|
|
|
for(int j=0;j<parentDepsCount;j++)
|
|
{
|
|
if(parentDeps[j] == streamingIndex)
|
|
return true;
|
|
else
|
|
{
|
|
if( CheckChildren(parentDeps[j], streamingIndex ) )
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool CStreamGraph::CheckChildren(strIndex parentStrIdx, strIndex thisStrIdx)
|
|
{
|
|
strIndex parentDeps[STREAMING_MAX_DEPENDENCIES];
|
|
|
|
strStreamingModule *pParentModule = strStreamingEngine::GetInfo().GetModule(parentStrIdx);
|
|
strLocalIndex parentObjIdx = pParentModule->GetObjectIndex(parentStrIdx);
|
|
s32 parentDepsCount = pParentModule->GetDependencies(parentObjIdx, &parentDeps[0], STREAMING_MAX_DEPENDENCIES);
|
|
|
|
for(int i=0;i<parentDepsCount;i++)
|
|
{
|
|
if(parentDeps[i] == thisStrIdx)
|
|
return true;
|
|
else
|
|
{
|
|
if( CheckChildren(parentDeps[i], thisStrIdx) )
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CStreamGraph::UpdateFileList(const GraphEntry * sortedEntries, const int entryCount)
|
|
{
|
|
int fileCount = 0;
|
|
CStreamGraphBuffer &updateBuffer = m_statBuffers[ SCENESTREAMINGMEMORYTRACKER_BUFFER_UPDATE ];
|
|
|
|
if(m_TransposeGraph)
|
|
{
|
|
for (int i = 0; i < entryCount; i++ )
|
|
{
|
|
const GraphEntry & entry = sortedEntries[i];
|
|
strStreamingModule* module = strStreamingEngine::GetInfo().GetModuleMgr().GetModule(entry.module);
|
|
strIndex sortedIndex = entry.index;
|
|
strLocalIndex sortedObjectIndex = module->GetObjectIndex(sortedIndex);
|
|
++updateBuffer.m_NumFilesInSelectedCategoryModule[entry.module];
|
|
|
|
if(sortedObjectIndex == updateBuffer.m_CurrentlySelectedFileObjIdx && entry.module == updateBuffer.m_CurrentlySelectedModuleIdx)
|
|
{
|
|
updateBuffer.m_SelectedListEntry = updateBuffer.m_NumFilesInSelectedBar + fileCount;
|
|
|
|
// scroll the selected file in to view
|
|
if(updateBuffer.m_SelectedListEntry < updateBuffer.m_ListOffset)
|
|
{
|
|
updateBuffer.m_ListOffset = updateBuffer.m_SelectedListEntry;
|
|
}
|
|
else if(updateBuffer.m_SelectedListEntry >= updateBuffer.m_ListOffset + updateBuffer.MAX_LIST_ENTRIES_TRANSPOSED)
|
|
{
|
|
updateBuffer.m_ListOffset = updateBuffer.m_SelectedListEntry - (updateBuffer.MAX_LIST_ENTRIES_TRANSPOSED - 1);
|
|
}
|
|
|
|
UpdateFileInfo(entry, module);
|
|
}
|
|
|
|
if((updateBuffer.m_NumFilesInSelectedBar + fileCount) >= updateBuffer.m_ListOffset && updateBuffer.m_NumListEntries != updateBuffer.MAX_LIST_ENTRIES_TRANSPOSED)
|
|
{
|
|
const char *fileName = strStreamingEngine::GetObjectName(sortedIndex);
|
|
|
|
CStreamGraphBuffer::listBufferContents *pListBuffer = &updateBuffer.m_ListBuffer[updateBuffer.m_NumListEntries++];
|
|
char * lineBuffer = pListBuffer->m_fileName;
|
|
strncpy(lineBuffer, fileName, updateBuffer.MAX_LIST_ENTRY_LENGTH);
|
|
strStreamingInfo* info = module->GetStreamingInfo( sortedObjectIndex );
|
|
GetSizesSafe(sortedIndex, *info, pListBuffer->m_vSize, pListBuffer->m_pSize, false );
|
|
}
|
|
|
|
++fileCount;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
strStreamingModule* module = strStreamingEngine::GetInfo().GetModuleMgr().GetModule(updateBuffer.m_CurrentlySelectedModuleIdx);
|
|
|
|
for (int i = 0; i < entryCount; i++ )
|
|
{
|
|
strIndex sortedIndex = sortedEntries[i].index;
|
|
++updateBuffer.m_NumFilesInSelectedModuleCategory[sortedEntries[i].category];
|
|
|
|
if(i == updateBuffer.m_CurrentlySelectedFileIdx)
|
|
{
|
|
updateBuffer.m_SelectedListEntry = fileCount;
|
|
|
|
// scroll the selected file in to view
|
|
if(updateBuffer.m_SelectedListEntry < updateBuffer.m_ListOffset)
|
|
{
|
|
updateBuffer.m_ListOffset = updateBuffer.m_SelectedListEntry;
|
|
}
|
|
else if(updateBuffer.m_SelectedListEntry >= updateBuffer.m_ListOffset + updateBuffer.MAX_LIST_ENTRIES)
|
|
{
|
|
updateBuffer.m_ListOffset = updateBuffer.m_SelectedListEntry - (updateBuffer.MAX_LIST_ENTRIES - 1);
|
|
}
|
|
|
|
UpdateFileInfo(sortedEntries[updateBuffer.m_CurrentlySelectedFileIdx], module);
|
|
}
|
|
|
|
if(fileCount >= updateBuffer.m_ListOffset && updateBuffer.m_NumListEntries != updateBuffer.MAX_LIST_ENTRIES)
|
|
{
|
|
const char *fileName = strStreamingEngine::GetObjectName(sortedIndex);
|
|
|
|
CStreamGraphBuffer::listBufferContents *pListBuffer = &updateBuffer.m_ListBuffer[updateBuffer.m_NumListEntries++];
|
|
char * lineBuffer = pListBuffer->m_fileName;
|
|
strncpy(lineBuffer, fileName, updateBuffer.MAX_LIST_ENTRY_LENGTH);
|
|
strStreamingInfo* info = strStreamingEngine::GetInfo().GetStreamingInfo( sortedIndex );
|
|
GetSizesSafe(sortedIndex, *info, pListBuffer->m_vSize, pListBuffer->m_pSize, false );
|
|
}
|
|
|
|
++fileCount;
|
|
}
|
|
}
|
|
|
|
updateBuffer.m_NumFilesInSelectedBar += fileCount;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CStreamGraph::UpdateFileInfo(const GraphEntry & file, strStreamingModule* pModule)
|
|
{
|
|
CStreamGraphBuffer &updateBuffer = m_statBuffers[ SCENESTREAMINGMEMORYTRACKER_BUFFER_UPDATE ];
|
|
|
|
updateBuffer.m_NumFileInfoEntries = 0;
|
|
if(pModule == &g_TxdStore)
|
|
{
|
|
strLocalIndex txdObjectIndex = strLocalIndex(pModule->GetObjectIndex(file.index));
|
|
fwTxd * txd = g_TxdStore.GetSafeFromIndex(txdObjectIndex);
|
|
if(txd)
|
|
{
|
|
int texCount = txd->GetCount();
|
|
formatf(updateBuffer.m_FileInfoBuffer[updateBuffer.m_NumFileInfoEntries], updateBuffer.MAX_FILE_INFO_ENTRY_LENGTH, texCount == 1 ? "%i texture" : "%i textures", texCount);
|
|
++updateBuffer.m_NumFileInfoEntries;
|
|
|
|
if(m_TrackTxd)
|
|
{
|
|
CTxdRef ref(AST_TxdStore, txdObjectIndex.Get(), INDEX_NONE, "");
|
|
CDebugTextureViewerInterface::SelectTxd(ref, false, true, false);
|
|
}
|
|
}
|
|
}
|
|
|
|
else if(pModule == &g_DrawableStore)
|
|
{
|
|
u32 vertexCount = 0;
|
|
int textureCount = 0;
|
|
|
|
strLocalIndex drawableObjectIndex = pModule->GetObjectIndex(file.index);
|
|
Drawable * drawable = g_DrawableStore.GetSafeFromIndex(drawableObjectIndex);
|
|
if(drawable)
|
|
{
|
|
GetDrawableInfo(*drawable, vertexCount, textureCount);
|
|
if(m_TrackTxd)
|
|
{
|
|
CTxdRef ref(AST_DrawableStore, drawableObjectIndex.Get(), INDEX_NONE, "");
|
|
CDebugTextureViewerInterface::SelectTxd(ref, false, true, false);
|
|
}
|
|
}
|
|
|
|
formatf(updateBuffer.m_FileInfoBuffer[updateBuffer.m_NumFileInfoEntries],
|
|
updateBuffer.MAX_FILE_INFO_ENTRY_LENGTH,
|
|
"%u vertices, %i texture(s)", vertexCount, textureCount);
|
|
++updateBuffer.m_NumFileInfoEntries;
|
|
}
|
|
else if(pModule == &g_DwdStore)
|
|
{
|
|
strLocalIndex dwdObjectIndex = pModule->GetObjectIndex(file.index);
|
|
Dwd * dwd = g_DwdStore.GetSafeFromIndex(dwdObjectIndex);
|
|
if(dwd)
|
|
{
|
|
int drawableCount = dwd->GetCount();
|
|
formatf(updateBuffer.m_FileInfoBuffer[updateBuffer.m_NumFileInfoEntries], updateBuffer.MAX_FILE_INFO_ENTRY_LENGTH, drawableCount == 1 ? "%i drawable" : "%i drawables", drawableCount);
|
|
++updateBuffer.m_NumFileInfoEntries;
|
|
for(int drawableIndex = 0; drawableIndex < drawableCount; ++drawableIndex)
|
|
{
|
|
Drawable * drawable = dwd->GetEntry(drawableIndex);
|
|
if(drawable && updateBuffer.m_NumFileInfoEntries < CStreamGraphBuffer::MAX_FILE_INFO_ENTRIES)
|
|
{
|
|
u32 vertexCount = 0;
|
|
int textureCount = 0;
|
|
GetDrawableInfo(*drawable, vertexCount, textureCount);
|
|
formatf(updateBuffer.m_FileInfoBuffer[updateBuffer.m_NumFileInfoEntries],
|
|
updateBuffer.MAX_FILE_INFO_ENTRY_LENGTH,
|
|
"%u vertices, %i texture(s)", vertexCount, textureCount);
|
|
++updateBuffer.m_NumFileInfoEntries;
|
|
}
|
|
}
|
|
if(m_TrackTxd)
|
|
{
|
|
CTxdRef ref(AST_DwdStore, dwdObjectIndex.Get(), 0, "");
|
|
CDebugTextureViewerInterface::SelectTxd(ref, false, true, false);
|
|
}
|
|
}
|
|
}
|
|
else if(pModule == &g_FragmentStore)
|
|
{
|
|
strLocalIndex fragObjectIndex = pModule->GetObjectIndex(file.index);
|
|
Fragment * fragment = g_FragmentStore.GetSafeFromIndex(fragObjectIndex);
|
|
if(fragment && fragment->GetCommonDrawable())
|
|
{
|
|
u32 vertexCount = 0;
|
|
const rmcLodGroup& lodGroup = fragment->GetCommonDrawable()->GetLodGroup();
|
|
int lodIndex=0;
|
|
while (lodGroup.ContainsLod(lodIndex))
|
|
{
|
|
const rmcLod& lod = lodGroup.GetLod(lodIndex);
|
|
|
|
int modelCount = lod.GetCount();
|
|
for (int i=0; i<modelCount; ++i)
|
|
{
|
|
grmModel* model = lod.GetModel(i);
|
|
|
|
int geomCount = model->GetGeometryCount();
|
|
for (int j=0; j<geomCount; ++j)
|
|
{
|
|
grmGeometry& geometry = model->GetGeometry(j);
|
|
vertexCount += geometry.GetVertexCount();
|
|
|
|
}
|
|
}
|
|
lodIndex++;
|
|
}
|
|
|
|
formatf(updateBuffer.m_FileInfoBuffer[updateBuffer.m_NumFileInfoEntries],
|
|
updateBuffer.MAX_FILE_INFO_ENTRY_LENGTH,
|
|
"%i vertices", vertexCount);
|
|
++updateBuffer.m_NumFileInfoEntries;
|
|
|
|
fwTxd * txd = fragment->GetCommonDrawable()->GetShaderGroup().GetTexDict();
|
|
if(txd)
|
|
{
|
|
int texCount = txd->GetCount();
|
|
formatf(updateBuffer.m_FileInfoBuffer[updateBuffer.m_NumFileInfoEntries], updateBuffer.MAX_FILE_INFO_ENTRY_LENGTH, texCount == 1 ? "%i texture" : "%i textures", texCount);
|
|
++updateBuffer.m_NumFileInfoEntries;
|
|
|
|
if(m_TrackTxd)
|
|
{
|
|
CTxdRef ref(AST_FragmentStore, fragObjectIndex.Get(), INDEX_NONE, "");
|
|
CDebugTextureViewerInterface::SelectTxd(ref, false, true, false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#if __STATS
|
|
else if (pModule == &g_ScaleformStore)
|
|
{
|
|
strLocalIndex scaleformObjectIdx = pModule->GetObjectIndex(file.index);
|
|
CScaleformMovieObject* movie = g_ScaleformStore.GetSafeFromIndex(scaleformObjectIdx);
|
|
if (movie)
|
|
{
|
|
s32 scaleformMovieIdx = CScaleformMgr::FindMovieByFilename(g_ScaleformStore.GetName(strLocalIndex(scaleformObjectIdx)));
|
|
if (scaleformMovieIdx >= 0 && CScaleformMgr::IsMovieActive(scaleformMovieIdx))
|
|
{
|
|
ScaleformMemoryStats stats;
|
|
CScaleformMgr::GatherMemoryStats(scaleformMovieIdx, stats);
|
|
|
|
formatf(updateBuffer.m_FileInfoBuffer[updateBuffer.m_NumFileInfoEntries], updateBuffer.MAX_FILE_INFO_ENTRY_LENGTH,
|
|
"MovieDef: %.3fk in-use (%dk total)", (float)stats.m_MovieDefUsed / 1024.0f, stats.m_MovieDefTotal / 1024);
|
|
++updateBuffer.m_NumFileInfoEntries;
|
|
|
|
formatf(updateBuffer.m_FileInfoBuffer[updateBuffer.m_NumFileInfoEntries], updateBuffer.MAX_FILE_INFO_ENTRY_LENGTH,
|
|
"MovieView %.3fk in-use (%dk total)", (float)stats.m_MovieViewUsed / 1024.0f, stats.m_MovieViewTotal / 1024);
|
|
++updateBuffer.m_NumFileInfoEntries;
|
|
|
|
formatf(updateBuffer.m_FileInfoBuffer[updateBuffer.m_NumFileInfoEntries], updateBuffer.MAX_FILE_INFO_ENTRY_LENGTH,
|
|
"Prealloc: %dk in-use", stats.m_PreallocUsed / 1024);
|
|
++updateBuffer.m_NumFileInfoEntries;
|
|
|
|
formatf(updateBuffer.m_FileInfoBuffer[updateBuffer.m_NumFileInfoEntries], updateBuffer.MAX_FILE_INFO_ENTRY_LENGTH,
|
|
" (%dk total, %dk peak)", stats.m_PreallocTotal / 1024, stats.m_PreallocPeak / 1024);
|
|
++updateBuffer.m_NumFileInfoEntries;
|
|
|
|
formatf(updateBuffer.m_FileInfoBuffer[updateBuffer.m_NumFileInfoEntries], updateBuffer.MAX_FILE_INFO_ENTRY_LENGTH,
|
|
"Overalloc: %dk", stats.m_Overalloc / 1024);
|
|
++updateBuffer.m_NumFileInfoEntries;
|
|
}
|
|
}
|
|
}
|
|
#endif // __STATS
|
|
else if (pModule == &g_StreamedScripts)
|
|
{
|
|
strLocalIndex scriptObjectIdx = pModule->GetObjectIndex(file.index);
|
|
scrProgram * prog = g_StreamedScripts.GetSafeFromIndex(scriptObjectIdx);
|
|
if (prog)
|
|
{
|
|
int used, total;
|
|
scrThread::GetStackSummary(used,total);
|
|
formatf(updateBuffer.m_FileInfoBuffer[updateBuffer.m_NumFileInfoEntries++], updateBuffer.MAX_FILE_INFO_ENTRY_LENGTH,
|
|
"%dk total stacks in use, %dk total allocated",used >> 10,total >> 10);
|
|
formatf(updateBuffer.m_FileInfoBuffer[updateBuffer.m_NumFileInfoEntries++], updateBuffer.MAX_FILE_INFO_ENTRY_LENGTH,
|
|
"Code %0.3fk + Strings %0.3fk", prog->GetOpcodeSize() / 1024.0f, prog->GetStringHeapSize() / 1024.0f);
|
|
atArray<scrThread*> &threads = scrThread::GetScriptThreads();
|
|
int copiesRunning = 0;
|
|
for (int i=0; i<threads.GetCount(); i++)
|
|
{
|
|
scrThread *t = threads[i];
|
|
if (t && scrProgram::GetProgram(t->GetProgram()) == prog)
|
|
{
|
|
++copiesRunning;
|
|
formatf(updateBuffer.m_FileInfoBuffer[updateBuffer.m_NumFileInfoEntries++], updateBuffer.MAX_FILE_INFO_ENTRY_LENGTH,
|
|
"Copy %d: %.3fk used / %.3fk total stack", copiesRunning, t->GetStackSize() / 1024.0f, t->GetTotalStackSize() / 1024.0f);
|
|
}
|
|
}
|
|
formatf(updateBuffer.m_FileInfoBuffer[updateBuffer.m_NumFileInfoEntries++], updateBuffer.MAX_FILE_INFO_ENTRY_LENGTH,
|
|
"%d cop%s of this thread currently running", copiesRunning, copiesRunning==1?"y":"ies");
|
|
if (copiesRunning)
|
|
formatf(updateBuffer.m_FileInfoBuffer[updateBuffer.m_NumFileInfoEntries++], updateBuffer.MAX_FILE_INFO_ENTRY_LENGTH,
|
|
"%.3fk of each thread stack is statics", prog->GetStaticSize() * sizeof(scrValue) / 1024.0f);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// Recursive for to be able to handle composite types
|
|
u32 CStreamGraph::GetBoundSize(phBound *pBound)
|
|
{
|
|
u32 thisSize = 0;
|
|
|
|
// Calculate the size
|
|
switch(pBound->GetType())
|
|
{
|
|
case phBound::SPHERE:
|
|
{
|
|
thisSize = sizeof(rage::phBoundSphere);
|
|
}
|
|
break;
|
|
|
|
case phBound::CAPSULE:
|
|
{
|
|
thisSize = sizeof(rage::phBoundCapsule);
|
|
}
|
|
break;
|
|
|
|
#if USE_TAPERED_CAPSULE
|
|
case phBound::TAPERED_CAPSULE:
|
|
{
|
|
thisSize = sizeof(rage::phBoundTaperedCapsule);
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
case phBound::BOX:
|
|
{
|
|
thisSize = sizeof(rage::phBoundBox);
|
|
}
|
|
break;
|
|
|
|
#if USE_GEOMETRY_CURVED
|
|
case phBound::GEOMETRY_CURVED:
|
|
{
|
|
thisSize = sizeof(rage::phBoundCurvedGeometry);
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
#if USE_GRIDS
|
|
case phBound::GRID:
|
|
{
|
|
thisSize = sizeof(rage::phBoundGrid);
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
#if USE_RIBBONS
|
|
case phBound::RIBBON:
|
|
{
|
|
thisSize = sizeof(rage::phBoundRibbon);
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
#if USE_SURFACES
|
|
case phBound::SURFACE:
|
|
{
|
|
thisSize = sizeof(rage::phBoundSurface);
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
case phBound::TRIANGLE:
|
|
{
|
|
thisSize = sizeof(rage::TriangleShape);
|
|
}
|
|
break;
|
|
|
|
case phBound::DISC:
|
|
{
|
|
thisSize = sizeof(rage::phBoundDisc);
|
|
}
|
|
break;
|
|
|
|
case phBound::CYLINDER:
|
|
{
|
|
thisSize = sizeof(rage::phBoundCylinder);
|
|
}
|
|
break;
|
|
|
|
// These require extra processing
|
|
case phBound::GEOMETRY:
|
|
{
|
|
rage::phBoundGeometry * pGeom = (rage::phBoundGeometry*)pBound;
|
|
|
|
int iNumPolys = pGeom->GetNumPolygons();
|
|
int iNumVerts = pGeom->GetNumVertices();
|
|
|
|
int vertSize = 3*sizeof(CompressedVertexType);
|
|
int polySize = sizeof(phPolygon);
|
|
|
|
thisSize = sizeof(rage::phBoundGeometry);
|
|
thisSize += iNumVerts * vertSize; // Verts
|
|
thisSize += iNumPolys * polySize; // Polygons
|
|
thisSize += pGeom->m_NumMaterials * sizeof(phMaterialMgr::Id); // Materials
|
|
thisSize += iNumPolys * sizeof(u8); // index numbers into this bound's list of material ids, one for each polygon
|
|
// No access to SecondSurfaceVertexDisplacement
|
|
// No access to OctantVertmap
|
|
|
|
}
|
|
break;
|
|
|
|
case phBound::COMPOSITE:
|
|
{
|
|
rage::phBoundComposite * pComposite = (rage::phBoundComposite*)pBound;
|
|
|
|
thisSize = sizeof(rage::phBoundComposite);
|
|
|
|
// Some other stuff to add later:-
|
|
//(between 17 and 35, depending on whether there are composite flags and last matrices) * number of sub bounds
|
|
|
|
int iNumBounds = pComposite->GetNumBounds();
|
|
for(int b=0; b<iNumBounds; b++)
|
|
{
|
|
phBound * pCompositeBound = pComposite->GetBound(b);
|
|
thisSize += GetBoundSize(pCompositeBound);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case phBound::BVH:
|
|
{
|
|
rage::phBoundBVH * pBVH = (rage::phBoundBVH*)pBound;
|
|
|
|
thisSize += sizeof(rage::phBoundBVH);
|
|
|
|
int iNumPolys = pBVH->GetNumPolygons();
|
|
int polySize = sizeof(phPolygon);
|
|
thisSize += iNumPolys * polySize; // Polys?
|
|
|
|
int vertSize = 3*sizeof(CompressedVertexType);
|
|
int iNumVerts = pBVH->GetNumVertices();
|
|
thisSize += iNumVerts * vertSize; // Verts
|
|
|
|
int numNodes = pBVH->GetBVH()->GetNumNodes();
|
|
thisSize += numNodes * sizeof(phOptimizedBvhNode);
|
|
|
|
/*
|
|
int curNodeIndex = 0;
|
|
while(curNodeIndex < numNodes)
|
|
{
|
|
const phOptimizedBvhNode &curNode = pBVH->GetBVH()->GetNode(curNodeIndex);
|
|
thisSize += sizeof(phOptimizedBvhNode);
|
|
// Do we need to include the polygon indices array?.. No, just one start index.
|
|
++curNodeIndex;
|
|
}
|
|
*/
|
|
|
|
}
|
|
break;
|
|
|
|
}
|
|
return thisSize;
|
|
}
|
|
|
|
|
|
|
|
void CStreamGraph::UpdateCategoryStats(s32 categoryId, CompareFunc compareFunc)
|
|
{
|
|
USE_DEBUG_MEMORY();
|
|
|
|
CStreamGraphBuffer &updateBuffer = m_statBuffers[ SCENESTREAMINGMEMORYTRACKER_BUFFER_UPDATE ];
|
|
|
|
bool isSelectedCategory = categoryId == updateBuffer.m_CurrentlySelectedCategoryIdx;
|
|
if (isSelectedCategory)
|
|
{
|
|
// update the selected file if there's been a keypress
|
|
if( CControlMgr::GetKeyboard().GetKeyJustDown(KEY_RIGHT, KEYBOARD_MODE_DEBUG, "move forward in file list") )
|
|
{
|
|
++updateBuffer.m_CurrentlySelectedFileIdx;
|
|
}
|
|
|
|
if( CControlMgr::GetKeyboard().GetKeyJustDown(KEY_LEFT, KEYBOARD_MODE_DEBUG, "move back in file list") )
|
|
{
|
|
--updateBuffer.m_CurrentlySelectedFileIdx;
|
|
}
|
|
|
|
// stop selected index dropping below zero, upper clamp will be applied later when the
|
|
// total number of filtered files is known
|
|
updateBuffer.m_CurrentlySelectedFileIdx = Max(updateBuffer.m_CurrentlySelectedFileIdx, 0);
|
|
}
|
|
|
|
int totalCategoryFileCount = 0;
|
|
int totalPhysicalSize = 0;
|
|
int totalVirtualSize = 0;
|
|
|
|
// keep track of the last known filtered file in case the selected file index is less than the totalCategoryFileCount
|
|
const char * lastFileName = "";
|
|
strIndex lastIndex;
|
|
u16 lastFileFlags = 0;
|
|
int lastFileModule = -1;
|
|
int lastFileObjIdx = -1;
|
|
int lastFilePhysicalSize = 0;
|
|
int lastFileVirtualSize = 0;
|
|
|
|
// reset selected file info
|
|
if (isSelectedCategory)
|
|
{
|
|
updateBuffer.m_SelectedFileData.m_Name[0] = '\0';
|
|
updateBuffer.m_SelectedFileData.m_VirtualSize = 0;
|
|
updateBuffer.m_SelectedFileData.m_PhysicalSize = 0;
|
|
updateBuffer.m_SelectedFileData.m_Flags = 0;
|
|
}
|
|
|
|
size_t totalCostPhys = 0;
|
|
size_t totalCostVirt = 0;
|
|
|
|
for(int moduleId = 0; moduleId < GetNumTrackedModules(); ++moduleId)
|
|
{
|
|
CStreamGraphModuleBuffer &moduleBuffer = updateBuffer.m_Modules[ moduleId ];
|
|
moduleBuffer.m_CostPhys[categoryId] = 0;
|
|
moduleBuffer.m_CostVirt[categoryId] = 0;
|
|
|
|
strStreamingModule* pModule = strStreamingEngine::GetInfo().GetModuleMgr().GetModule(moduleId);
|
|
|
|
int filteredCount = 0;
|
|
int unfilteredCount = pModule->GetCount();
|
|
GraphEntry * sortedObjOrder = rage_new GraphEntry[unfilteredCount];
|
|
|
|
for(s32 objIdx = 0; objIdx < unfilteredCount; ++objIdx)
|
|
{
|
|
strStreamingInfo * info = pModule->GetStreamingInfo(strLocalIndex(objIdx));
|
|
strIndex index = pModule->GetStreamingIndex(strLocalIndex(objIdx));
|
|
|
|
if (ObjectPassesCategoryFilter(pModule, categoryId, strLocalIndex(objIdx)))
|
|
{
|
|
GraphEntry & entry = sortedObjOrder[filteredCount];
|
|
entry.index = index;
|
|
entry.module = moduleId;
|
|
GetLoadedSizes(pModule, strLocalIndex(objIdx), entry.virtualSize, entry.physicalSize);
|
|
++filteredCount;
|
|
}
|
|
|
|
switch (info->GetStatus())
|
|
{
|
|
case STRINFO_LOADING:
|
|
totalCostVirt += info->ComputeOccupiedVirtualSize(index, true);
|
|
totalCostPhys += info->ComputePhysicalSize(index, true);
|
|
break;
|
|
|
|
case STRINFO_LOADED:
|
|
totalCostVirt += pModule->GetVirtualMemoryOfLoadedObj(strLocalIndex(objIdx), false);
|
|
totalCostPhys += pModule->GetPhysicalMemoryOfLoadedObj(strLocalIndex(objIdx), false);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
updateBuffer.m_UsedByModulesVirt = totalCostVirt;
|
|
updateBuffer.m_UsedByModulesPhys = totalCostPhys;
|
|
|
|
bool blockContainsSelectedFile =
|
|
isSelectedCategory &&
|
|
(totalCategoryFileCount <= updateBuffer.m_CurrentlySelectedFileIdx) &&
|
|
(updateBuffer.m_CurrentlySelectedFileIdx < (totalCategoryFileCount + filteredCount));
|
|
|
|
// if sorting everything is too slow, sorting just the block containing the selected
|
|
// file is an option but it would mean the file list behaves a bit strangely
|
|
if(compareFunc)
|
|
{
|
|
qsort(sortedObjOrder, filteredCount, sizeof(GraphEntry), compareFunc);
|
|
}
|
|
|
|
// update the memory count
|
|
for(s32 objIdx = 0; objIdx < filteredCount; ++objIdx)
|
|
{
|
|
GraphEntry & entry = sortedObjOrder[objIdx];
|
|
|
|
if (blockContainsSelectedFile && (totalCategoryFileCount + objIdx) == updateBuffer.m_CurrentlySelectedFileIdx)
|
|
{
|
|
strIndex streamingIndex = entry.index;
|
|
const char *fileName = strStreamingEngine::GetObjectName(streamingIndex);
|
|
SetSelectedFileName(updateBuffer, fileName);
|
|
updateBuffer.m_SelectedFileData.m_Flags = strStreamingEngine::GetInfo().GetStreamingInfo(streamingIndex)->GetFlags();
|
|
updateBuffer.m_SelectedFileData.m_AccumulatedPhysMemoryBeforeSelectedFile = totalPhysicalSize;
|
|
updateBuffer.m_SelectedFileData.m_AccumulatedVirtMemoryBeforeSelectedFile = totalVirtualSize;
|
|
updateBuffer.m_SelectedFileData.m_PhysicalSize = entry.physicalSize;
|
|
updateBuffer.m_SelectedFileData.m_VirtualSize = entry.virtualSize;
|
|
if (m_ShowExtendedFileInfo)
|
|
{
|
|
updateBuffer.m_SelectedFileData.CollectDependents(streamingIndex);
|
|
}
|
|
|
|
updateBuffer.m_CurrentlySelectedModuleIdx = entry.module;
|
|
updateBuffer.m_CurrentlySelectedFileObjIdx = pModule->GetObjectIndex(streamingIndex).Get();
|
|
}
|
|
|
|
totalPhysicalSize += entry.physicalSize;
|
|
totalVirtualSize += entry.virtualSize;
|
|
|
|
moduleBuffer.m_CostPhys[categoryId] += entry.physicalSize;
|
|
moduleBuffer.m_CostVirt[categoryId] += entry.virtualSize;
|
|
}
|
|
|
|
totalCategoryFileCount += filteredCount;
|
|
|
|
// update the stats for the last good file
|
|
if(filteredCount > 0)
|
|
{
|
|
GraphEntry & lastFileGraphEntry = sortedObjOrder[filteredCount - 1];
|
|
strIndex index = lastFileGraphEntry.index;
|
|
strStreamingInfo *info = strStreamingEngine::GetInfo().GetStreamingInfo(index);
|
|
lastFileName = strStreamingEngine::GetObjectName(index);
|
|
lastIndex = index;
|
|
lastFileFlags = info->GetFlags();
|
|
lastFileModule = moduleId;
|
|
lastFileObjIdx = pModule->GetObjectIndex(index).Get();
|
|
lastFilePhysicalSize = lastFileGraphEntry.physicalSize;
|
|
lastFileVirtualSize = lastFileGraphEntry.virtualSize;
|
|
}
|
|
|
|
if(isSelectedCategory)
|
|
{
|
|
UpdateFileList(sortedObjOrder, filteredCount);
|
|
}
|
|
|
|
delete[] sortedObjOrder;
|
|
}
|
|
|
|
// if the selected file is outside the total number of filtered files across all modules clamp it to the last file
|
|
if(isSelectedCategory && totalCategoryFileCount <= updateBuffer.m_CurrentlySelectedFileIdx )
|
|
{
|
|
updateBuffer.m_CurrentlySelectedFileIdx = totalCategoryFileCount - 1;
|
|
updateBuffer.m_CurrentlySelectedModuleIdx = lastFileModule;
|
|
updateBuffer.m_CurrentlySelectedFileObjIdx = lastFileObjIdx;
|
|
|
|
SetSelectedFileName(updateBuffer, lastFileName);
|
|
updateBuffer.m_SelectedFileData.m_Flags = lastFileFlags;
|
|
updateBuffer.m_SelectedFileData.m_AccumulatedPhysMemoryBeforeSelectedFile = totalPhysicalSize - lastFilePhysicalSize;
|
|
updateBuffer.m_SelectedFileData.m_AccumulatedVirtMemoryBeforeSelectedFile = totalVirtualSize - lastFileVirtualSize;
|
|
updateBuffer.m_SelectedFileData.m_PhysicalSize = lastFilePhysicalSize;
|
|
updateBuffer.m_SelectedFileData.m_VirtualSize = lastFileVirtualSize;
|
|
if (m_ShowExtendedFileInfo)
|
|
{
|
|
updateBuffer.m_SelectedFileData.CollectDependents(lastIndex);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CStreamGraph::UpdateModuleStats( s32 moduleId, CompareFunc compareFunc )
|
|
{
|
|
USE_DEBUG_MEMORY();
|
|
|
|
CStreamGraphModuleBuffer &moduleBuffer = m_statBuffers[ SCENESTREAMINGMEMORYTRACKER_BUFFER_UPDATE ].m_Modules[ moduleId ];
|
|
|
|
memset( moduleBuffer.m_CostPhys, 0, sizeof( moduleBuffer.m_CostPhys ) );
|
|
memset( moduleBuffer.m_CostVirt, 0, sizeof( moduleBuffer.m_CostVirt ) );
|
|
|
|
strStreamingModule* pModule = strStreamingEngine::GetInfo().GetModuleMgr().GetModule(moduleId);
|
|
CStreamGraphBuffer &updateBuffer = m_statBuffers[ SCENESTREAMINGMEMORYTRACKER_BUFFER_UPDATE ];
|
|
|
|
int filteredCount = 0;
|
|
GraphEntry * sortedObjOrder = rage_new GraphEntry[ pModule->GetCount() ];
|
|
|
|
size_t totalVirtUsed = 0;
|
|
size_t totalPhysUsed = 0;
|
|
|
|
size_t filteredTotalVirtUsed = 0;
|
|
size_t filteredTotalPhysUsed = 0;
|
|
|
|
for(s32 objIdx = 0; objIdx < pModule->GetCount(); ++objIdx)
|
|
{
|
|
strStreamingInfo * info = pModule->GetStreamingInfo(strLocalIndex(objIdx));
|
|
strIndex index = pModule->GetStreamingIndex(strLocalIndex(objIdx));
|
|
|
|
if ( ObjectPassesFilter( pModule, strLocalIndex(objIdx) ) )
|
|
{
|
|
char lowerName[128];
|
|
strcpy(lowerName, pModule->GetName(strLocalIndex(objIdx)));
|
|
strlwr(lowerName);
|
|
if (strlen(m_AssetFilterStr) > 0)
|
|
{
|
|
strlwr(m_AssetFilterStr);
|
|
|
|
// We skip if the asset name doesn't contain the filter
|
|
if (strstr(lowerName, m_AssetFilterStr) == NULL)
|
|
continue;
|
|
}
|
|
GraphEntry & entry = sortedObjOrder[filteredCount];
|
|
entry.index = pModule->GetStreamingIndex(strLocalIndex(objIdx));
|
|
entry.category = GetStreamingCategory(info);
|
|
entry.virtualSize = (int)pModule->GetVirtualMemoryOfLoadedObj(strLocalIndex(objIdx), m_ShowTemporaryMemory);
|
|
entry.physicalSize = (int)pModule->GetPhysicalMemoryOfLoadedObj(strLocalIndex(objIdx), m_ShowTemporaryMemory);
|
|
strcpy(entry.name, lowerName);
|
|
|
|
filteredTotalVirtUsed += (size_t) entry.virtualSize;
|
|
filteredTotalPhysUsed += (size_t) entry.physicalSize;
|
|
++filteredCount;
|
|
}
|
|
|
|
switch (info->GetStatus())
|
|
{
|
|
case STRINFO_LOADING:
|
|
totalVirtUsed += info->ComputeOccupiedVirtualSize(index, true);
|
|
totalPhysUsed += info->ComputePhysicalSize(index, true);
|
|
break;
|
|
|
|
case STRINFO_LOADED:
|
|
totalVirtUsed += pModule->GetVirtualMemoryOfLoadedObj(strLocalIndex(objIdx), false);
|
|
totalPhysUsed += pModule->GetPhysicalMemoryOfLoadedObj(strLocalIndex(objIdx), false);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
moduleBuffer.m_TotalCostVirt = totalVirtUsed;
|
|
moduleBuffer.m_TotalCostPhys = totalPhysUsed;
|
|
|
|
moduleBuffer.m_FilteredTotalCostVirt = filteredTotalVirtUsed;
|
|
moduleBuffer.m_FilteredTotalCostPhys = filteredTotalPhysUsed;
|
|
|
|
if ( compareFunc != NULL )
|
|
{
|
|
qsort(sortedObjOrder, filteredCount, sizeof(GraphEntry), compareFunc);
|
|
}
|
|
|
|
// if this is the currently selected module there's more to do
|
|
if(moduleId == updateBuffer.m_CurrentlySelectedModuleIdx && filteredCount)
|
|
{
|
|
// update the selected file if there's been a keypress
|
|
if( CControlMgr::GetKeyboard().GetKeyJustDown(KEY_RIGHT, KEYBOARD_MODE_DEBUG, "move forward in file list") )
|
|
{
|
|
++updateBuffer.m_CurrentlySelectedFileIdx;
|
|
}
|
|
|
|
if( CControlMgr::GetKeyboard().GetKeyJustDown(KEY_LEFT, KEYBOARD_MODE_DEBUG, "move back in file list") )
|
|
{
|
|
--updateBuffer.m_CurrentlySelectedFileIdx;
|
|
}
|
|
|
|
// clamp the index of the selected file to total number of files after filtering
|
|
updateBuffer.m_CurrentlySelectedFileIdx = Clamp( updateBuffer.m_CurrentlySelectedFileIdx, 0, Max(filteredCount - 1,0) );
|
|
|
|
// sync the selected object index with the selected sorted index
|
|
updateBuffer.m_CurrentlySelectedFileObjIdx = pModule->GetObjectIndex(sortedObjOrder[updateBuffer.m_CurrentlySelectedFileIdx].index).Get();
|
|
updateBuffer.m_CurrentlySelectedCategoryIdx = sortedObjOrder[updateBuffer.m_CurrentlySelectedFileIdx].category;
|
|
|
|
// update the selected file data
|
|
if ( filteredCount == 0 )
|
|
{
|
|
updateBuffer.m_SelectedFileData.m_Name[0] = '\0';
|
|
updateBuffer.m_SelectedFileData.m_VirtualSize = 0;
|
|
updateBuffer.m_SelectedFileData.m_PhysicalSize = 0;
|
|
updateBuffer.m_SelectedFileData.m_Flags = 0;
|
|
}
|
|
else
|
|
{
|
|
strLocalIndex selectedFileModuleIdx = pModule->GetObjectIndex( sortedObjOrder[updateBuffer.m_CurrentlySelectedFileIdx].index );
|
|
strStreamingInfo* info = pModule->GetStreamingInfo( selectedFileModuleIdx );
|
|
strIndex index = pModule->GetStreamingIndex( selectedFileModuleIdx );
|
|
const char *fileName = strStreamingEngine::GetObjectName( index );
|
|
SetSelectedFileName(updateBuffer, fileName);
|
|
int v,p;
|
|
GetSizesSafe( index, *info, v, p, false );
|
|
updateBuffer.m_SelectedFileData.m_VirtualSize = v;
|
|
updateBuffer.m_SelectedFileData.m_PhysicalSize = p;
|
|
updateBuffer.m_SelectedFileData.m_Flags = info->GetFlags();
|
|
|
|
if (m_ShowExtendedFileInfo)
|
|
{
|
|
updateBuffer.m_SelectedFileData.CollectDependents(pModule->GetStreamingIndex( selectedFileModuleIdx ));
|
|
}
|
|
}
|
|
|
|
UpdateFileList(sortedObjOrder, filteredCount);
|
|
}
|
|
|
|
// add up memory
|
|
u32 totalPhysMemory = 0;
|
|
u32 totalVirtMemory = 0;
|
|
for(s32 objIdx = 0; objIdx < filteredCount; ++objIdx)
|
|
{
|
|
GraphEntry & entry = sortedObjOrder[objIdx];
|
|
|
|
if ( moduleId == m_statBuffers[ SCENESTREAMINGMEMORYTRACKER_BUFFER_UPDATE ].m_CurrentlySelectedModuleIdx && objIdx == m_statBuffers[ SCENESTREAMINGMEMORYTRACKER_BUFFER_UPDATE ].m_CurrentlySelectedFileIdx )
|
|
{
|
|
m_statBuffers[ SCENESTREAMINGMEMORYTRACKER_BUFFER_UPDATE ].m_SelectedFileData.m_AccumulatedPhysMemoryBeforeSelectedFile = totalPhysMemory;
|
|
m_statBuffers[ SCENESTREAMINGMEMORYTRACKER_BUFFER_UPDATE ].m_SelectedFileData.m_AccumulatedVirtMemoryBeforeSelectedFile = totalVirtMemory;
|
|
}
|
|
|
|
totalVirtMemory += entry.virtualSize;
|
|
totalPhysMemory += entry.physicalSize;
|
|
|
|
moduleBuffer.m_CostPhys[entry.category] += entry.physicalSize;
|
|
moduleBuffer.m_CostVirt[entry.category] += entry.virtualSize;
|
|
}
|
|
|
|
delete [] sortedObjOrder;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CStreamGraph::AllocateMemoryForLODDisplay()
|
|
{
|
|
// Debug Heap
|
|
sysMemAutoUseDebugMemory debug;
|
|
|
|
// Create some storage for lod level counts for the buffers we're interested in
|
|
m_pTxdLodCounts = rage_new int[g_TxdStore.GetMaxSize() * LODTYPES_DEPTH_TOTAL];
|
|
m_pDwdLodCounts = rage_new int[g_DwdStore.GetMaxSize() * LODTYPES_DEPTH_TOTAL];
|
|
m_pDrawableLodCounts = rage_new int[g_DrawableStore.GetMaxSize() * LODTYPES_DEPTH_TOTAL];
|
|
}
|
|
|
|
void CStreamGraph::FreeMemoryForLODDisplay()
|
|
{
|
|
// Debug Heap
|
|
sysMemAutoUseDebugMemory debug;
|
|
|
|
delete [] m_pTxdLodCounts;
|
|
m_pTxdLodCounts = NULL;
|
|
|
|
delete [] m_pDwdLodCounts;
|
|
m_pDwdLodCounts = NULL;
|
|
|
|
delete [] m_pDrawableLodCounts;
|
|
m_pDrawableLodCounts = NULL;
|
|
}
|
|
|
|
void CStreamGraph::UpdateLodStats()
|
|
{
|
|
// Clear out buffer storage
|
|
ResetMemoryByLODBuffer(&m_MemoryByLOD[SCENESTREAMINGMEMORYTRACKER_BUFFER_UPDATE]);
|
|
|
|
// If the buffers aren't allocated, exit
|
|
if(m_pTxdLodCounts == NULL)
|
|
return;
|
|
|
|
memset(m_pTxdLodCounts,0, sizeof(int) * g_TxdStore.GetMaxSize() * LODTYPES_DEPTH_TOTAL );
|
|
memset(m_pDwdLodCounts,0, sizeof(int) * g_DwdStore.GetMaxSize() * LODTYPES_DEPTH_TOTAL);
|
|
memset(m_pDrawableLodCounts,0, sizeof(int) * g_DrawableStore.GetMaxSize() * LODTYPES_DEPTH_TOTAL);
|
|
|
|
CDummyObject::Pool* pDPool = CDummyObject::GetPool();
|
|
for(s32 i=0;i<pDPool->GetSize();i++)
|
|
{
|
|
CDummyObject* pObject = pDPool->GetSlot(i);
|
|
CEntity *pEntity = (CEntity*)pObject;
|
|
if(pEntity && CModelInfo::IsValidModelInfo(pEntity->GetModelIndex()))
|
|
{
|
|
BuildTxdLODCounts(pEntity, m_pTxdLodCounts);
|
|
BuildDwdLODCounts(pEntity, m_pDwdLodCounts);
|
|
BuildDrawableLODCounts(pEntity, m_pDrawableLodCounts);
|
|
}
|
|
}
|
|
|
|
// BUILDINGS
|
|
CBuilding::Pool* pBPool = CBuilding::GetPool();
|
|
for(s32 i=0;i<pBPool->GetSize();i++)
|
|
{
|
|
CBuilding* pObject = pBPool->GetSlot(i);
|
|
CEntity *pEntity = (CEntity*)pObject;
|
|
if(pEntity && pEntity->IsArchetypeSet() && CModelInfo::IsValidModelInfo(pEntity->GetModelIndex()))
|
|
{
|
|
BuildTxdLODCounts(pEntity, m_pTxdLodCounts);
|
|
BuildDwdLODCounts(pEntity, m_pDwdLodCounts);
|
|
BuildDrawableLODCounts(pEntity, m_pDrawableLodCounts);
|
|
}
|
|
}
|
|
|
|
BuildTxdLODData(m_pTxdLodCounts);
|
|
BuildDwdLODData(m_pDwdLodCounts);
|
|
BuildDrawableLODData(m_pDrawableLodCounts);
|
|
|
|
}
|
|
|
|
int CStreamGraph::GetLodFromCountArray(int idx, int *pLodCounts)
|
|
{
|
|
int lodLevel = LODTYPES_DEPTH_TOTAL; // UNKNOWN!
|
|
int maxCount = 0;
|
|
int *pBaseCountsForThisAsset = &pLodCounts[idx*LODTYPES_DEPTH_TOTAL];
|
|
for(int j=0;j<LODTYPES_DEPTH_TOTAL;j++)
|
|
{
|
|
if( pBaseCountsForThisAsset[j] > maxCount )
|
|
{
|
|
maxCount = pBaseCountsForThisAsset[j];
|
|
lodLevel = j;
|
|
}
|
|
}
|
|
return lodLevel;
|
|
}
|
|
|
|
void CStreamGraph::BuildTxdLODCounts(CEntity *pEntity, int *pTxdLodCounts)
|
|
{
|
|
CBaseModelInfo* pModelInfo = pEntity->GetBaseModelInfo();
|
|
u32 lodType = pEntity->GetLodData().GetLodType();
|
|
|
|
if(pModelInfo->GetHasLoaded())
|
|
{
|
|
// Get the textures used for this LOD?
|
|
s32 txdDictIndex = pModelInfo->GetAssetParentTxdIndex();
|
|
if( txdDictIndex != -1 )
|
|
{
|
|
pTxdLodCounts[ (txdDictIndex*LODTYPES_DEPTH_TOTAL) + lodType ]++;
|
|
|
|
strLocalIndex parentTxdIndex = g_TxdStore.GetParentTxdSlot(strLocalIndex(txdDictIndex));
|
|
while (parentTxdIndex!=-1)
|
|
{
|
|
pTxdLodCounts[ (parentTxdIndex.Get()*LODTYPES_DEPTH_TOTAL) + lodType ]++;
|
|
parentTxdIndex = g_TxdStore.GetParentTxdSlot(parentTxdIndex);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CStreamGraph::BuildTxdLODData(int *pLodCounts)
|
|
{
|
|
MemoryByLODBuffer *pLODBuffer = &m_MemoryByLOD[SCENESTREAMINGMEMORYTRACKER_BUFFER_UPDATE];
|
|
|
|
for(int i=0; i<g_TxdStore.GetSize(); i++)
|
|
{
|
|
if(g_TxdStore.GetPtr(strLocalIndex(i)) != NULL)
|
|
{
|
|
int lodLevel = GetLodFromCountArray(i,pLodCounts);
|
|
|
|
// update mem counts
|
|
strIndex streamingIndex = g_TxdStore.GetStreamingIndex(strLocalIndex(i));
|
|
strStreamingInfo *info = strStreamingEngine::GetInfo().GetStreamingInfo(streamingIndex);
|
|
|
|
int v,m;
|
|
GetSizesSafe(streamingIndex, *info, v, m, false);
|
|
pLODBuffer->m_TxdStoreMemoryByLod[lodLevel].phys += m;
|
|
pLODBuffer->m_TxdStoreMemoryByLod[lodLevel].virt += v;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CStreamGraph::BuildDwdLODCounts(CEntity *pEntity, int *pDwdLodCounts)
|
|
{
|
|
CBaseModelInfo* pModelInfo = pEntity->GetBaseModelInfo();
|
|
u32 lodType = pEntity->GetLodData().GetLodType();
|
|
|
|
if(pModelInfo->GetHasLoaded())
|
|
{
|
|
u32 dwdDictIndex = (pModelInfo->GetDrawableType()==fwArchetype::DT_DRAWABLEDICTIONARY) ? pModelInfo->GetDrawDictIndex() : INVALID_DRAWDICT_IDX;
|
|
if (dwdDictIndex!=INVALID_DRAWDICT_IDX)
|
|
{
|
|
pDwdLodCounts[ (dwdDictIndex*LODTYPES_DEPTH_TOTAL) + lodType ]++;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CStreamGraph::BuildDwdLODData(int *pLodCounts)
|
|
{
|
|
MemoryByLODBuffer *pLODBuffer = &m_MemoryByLOD[SCENESTREAMINGMEMORYTRACKER_BUFFER_UPDATE];
|
|
|
|
for(int i=0; i<g_DwdStore.GetSize(); i++)
|
|
{
|
|
if(g_DwdStore.GetPtr(strLocalIndex(i)) != NULL)
|
|
{
|
|
int lodLevel = GetLodFromCountArray(i,pLodCounts);
|
|
|
|
// update mem counts
|
|
strIndex streamingIndex = g_DwdStore.GetStreamingIndex(strLocalIndex(i));
|
|
strStreamingInfo *info = strStreamingEngine::GetInfo().GetStreamingInfo(streamingIndex);
|
|
|
|
int v,m;
|
|
GetSizesSafe(streamingIndex, *info, v, m, false);
|
|
pLODBuffer->m_DwdStoreMemoryByLod[lodLevel].phys += m;
|
|
pLODBuffer->m_DwdStoreMemoryByLod[lodLevel].virt += v;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CStreamGraph::BuildDrawableLODCounts(CEntity *pEntity, int *pDrawableLodCounts)
|
|
{
|
|
CBaseModelInfo* pModelInfo = pEntity->GetBaseModelInfo();
|
|
u32 lodType = pEntity->GetLodData().GetLodType();
|
|
|
|
if(pModelInfo->GetHasLoaded())
|
|
{
|
|
u32 drawableIndex = (pModelInfo->GetDrawableType()==fwArchetype::DT_DRAWABLE) ? pModelInfo->GetDrawableIndex() : INVALID_DRAWABLE_IDX;
|
|
if (drawableIndex!=INVALID_DRAWABLE_IDX)
|
|
{
|
|
pDrawableLodCounts[ (drawableIndex*LODTYPES_DEPTH_TOTAL) + lodType ]++;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CStreamGraph::BuildDrawableLODData(int *pLodCounts)
|
|
{
|
|
MemoryByLODBuffer *pLODBuffer = &m_MemoryByLOD[SCENESTREAMINGMEMORYTRACKER_BUFFER_UPDATE];
|
|
|
|
for(int i=0; i<g_DrawableStore.GetSize(); i++)
|
|
{
|
|
if(g_DrawableStore.GetPtr(strLocalIndex(i)) != NULL)
|
|
{
|
|
int lodLevel = GetLodFromCountArray(i,pLodCounts);
|
|
|
|
// update mem counts
|
|
strIndex streamingIndex = g_DrawableStore.GetStreamingIndex(strLocalIndex(i));
|
|
strStreamingInfo *info = strStreamingEngine::GetInfo().GetStreamingInfo(streamingIndex);
|
|
|
|
int v,m;
|
|
GetSizesSafe(streamingIndex, *info, v, m, false);
|
|
pLODBuffer->m_DrawablesStoreMemoryByLod[lodLevel].phys += m;
|
|
pLODBuffer->m_DrawablesStoreMemoryByLod[lodLevel].virt += v;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CStreamGraph::DrawLODStats()
|
|
{
|
|
DrawTitle();
|
|
DrawBackground();
|
|
DrawLegend(m_vPos.x + GetGraphWidth() + 20, m_vPos.y + 5);
|
|
|
|
// Draw the memory bars
|
|
s32 xAxisCount = sizeof(sAssetLODLegend)/sizeof(sAssetLODLegend[0]);
|
|
float barOffset = 0.0f;
|
|
for ( s32 yAxisIdx = 0; yAxisIdx < 3; yAxisIdx++ )
|
|
{
|
|
barOffset += DrawLODMemoryBar(yAxisIdx, xAxisCount, m_vPos.x, m_vPos.y + barOffset);
|
|
}
|
|
}
|
|
|
|
float CStreamGraph::DrawLODMemoryBar(int memoryBarIndex, int numDivisions, float x, float y)
|
|
{
|
|
char achMsg[200];
|
|
float heightOfBarDrawn = 0.0f;
|
|
|
|
MemoryByLODBuffer *pBuffer = &m_MemoryByLOD[SCENESTREAMINGMEMORYTRACKER_BUFFER_RENDER];
|
|
|
|
s32 moduleId = -1;
|
|
MemoryByLOD *pMemoryByLODBuffer = NULL;
|
|
switch(memoryBarIndex)
|
|
{
|
|
case 0:
|
|
pMemoryByLODBuffer = pBuffer->m_TxdStoreMemoryByLod;
|
|
moduleId = g_TxdStore.GetStreamingModuleId();
|
|
break;
|
|
case 1:
|
|
pMemoryByLODBuffer = pBuffer->m_DwdStoreMemoryByLod;
|
|
moduleId = g_DwdStore.GetStreamingModuleId();
|
|
break;
|
|
case 2:
|
|
pMemoryByLODBuffer = pBuffer->m_DrawablesStoreMemoryByLod;
|
|
moduleId = g_DrawableStore.GetStreamingModuleId();
|
|
break;
|
|
}
|
|
|
|
bool bDoneBackground = false;
|
|
float curX = float(x + STREAMGRAPH_X_BORDER);
|
|
|
|
CTextLayout DebugTextLayout;
|
|
DebugTextLayout.SetScale(Vector2(0.3f, 0.3f));
|
|
DebugTextLayout.SetColor(Color32(255, 255, 255, 255));
|
|
|
|
u32 totalBarVirtMemory = 0;
|
|
u32 totalBarPhysMemory = 0;
|
|
|
|
for ( s32 xAxisIdx = 0; xAxisIdx < numDivisions; xAxisIdx++ )
|
|
{
|
|
strStreamingModule* pModule = strStreamingEngine::GetInfo().GetModuleMgr().GetModule(moduleId);
|
|
|
|
u32 memoryInBar = 0;
|
|
if ( m_ShowPhysicalMemory )
|
|
{
|
|
totalBarPhysMemory += pMemoryByLODBuffer[ xAxisIdx ].phys;
|
|
memoryInBar += pMemoryByLODBuffer[ xAxisIdx ].phys;
|
|
}
|
|
if ( m_ShowVirtualMemory )
|
|
{
|
|
totalBarVirtMemory += pMemoryByLODBuffer[ xAxisIdx ].virt;
|
|
memoryInBar += pMemoryByLODBuffer[ xAxisIdx ].virt;
|
|
}
|
|
|
|
if ( memoryInBar == 0 )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if ( !bDoneBackground )
|
|
{
|
|
bDoneBackground = true;
|
|
|
|
DebugTextLayout.SetColor(Color32(255, 255, 255, 255));
|
|
DebugTextLayout.Render(STREAMGRAPH_SCREEN_COORDS(x, y), pModule->GetModuleName());
|
|
|
|
DrawMemoryMarkers(x, y);
|
|
}
|
|
|
|
float barWidth = ( (float)(memoryInBar) / (float)( m_nMaxMemMB * 1024 * 1024 ) ) * GetGraphWidth();
|
|
|
|
Color32 barColour1 = Color32(0,255,0,255);
|
|
Color32 barColour2 = GetLegendColour( xAxisIdx );
|
|
if( ( curX - x ) + barWidth > GetGraphWidth() )
|
|
{
|
|
barWidth = GetGraphWidth() - ( curX - x );
|
|
barColour1.Set( 255, 0, 0, 255 );
|
|
barColour2.Set( 255, 0, 0, 255 );
|
|
}
|
|
|
|
fwRect barRect1((float) curX,(float) y + STREAMGRAPH_BAR_SPACING(), (float) curX + barWidth,(float) y + STREAMGRAPH_BAR_SPACING() - STREAMGRAPH_BAR_HEIGHT()*(2.0f/3.0f) );
|
|
fwRect barRect2((float) curX,(float) y + STREAMGRAPH_BAR_SPACING() - STREAMGRAPH_BAR_HEIGHT()*(2.0f/3.0f),(float) curX + barWidth,(float) y + STREAMGRAPH_BAR_SPACING() - STREAMGRAPH_BAR_HEIGHT());
|
|
|
|
CSprite2d::DrawRectSlow(barRect1, barColour1);
|
|
CSprite2d::DrawRectSlow(barRect2, barColour2);
|
|
|
|
curX += barWidth;
|
|
}
|
|
|
|
if ( totalBarVirtMemory+totalBarPhysMemory > 0 )
|
|
{
|
|
heightOfBarDrawn = STREAMGRAPH_BAR_SPACING();
|
|
|
|
#if __PS3
|
|
sprintf( achMsg, "%.3f MB (M), %.3f MB (V)", (float)totalBarVirtMemory / (1024.0f*1024.0f), (float)totalBarPhysMemory / (1024.0f*1024.0f) );
|
|
#else
|
|
sprintf( achMsg, "%.3f MB", (float)(totalBarVirtMemory+totalBarPhysMemory) / (1024.0f*1024.0f) );
|
|
#endif
|
|
|
|
DebugTextLayout.SetColor(Color32(255, 255, 255, 255));
|
|
DebugTextLayout.Render(STREAMGRAPH_SCREEN_COORDS(x + 150, y), achMsg);
|
|
}
|
|
|
|
return heightOfBarDrawn;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool CStreamGraph::ObjectPassesFilter( strStreamingModule* pModule, strLocalIndex objIdx )
|
|
{
|
|
strStreamingInfoManager & strInfoManager = strStreamingEngine::GetInfo();
|
|
strIndex streamingIndex = pModule->GetStreamingIndex(objIdx);
|
|
|
|
if ( strInfoManager.IsObjectInImage(streamingIndex) )
|
|
{
|
|
bool bLoaded = strInfoManager.HasObjectLoaded(streamingIndex);
|
|
bool bRequested = strInfoManager.IsObjectRequested(streamingIndex) || strInfoManager.IsObjectLoading(streamingIndex);
|
|
|
|
if( bLoaded || ( bRequested && m_IncludeRequestedObjects ) )
|
|
{
|
|
strStreamingInfo* info = strInfoManager.GetStreamingInfo(streamingIndex);
|
|
|
|
bool bReferenced = ( pModule->GetNumRefs( objIdx ) > 0 || info->GetDependentCount() > 0 );
|
|
bool bRequired = pModule->IsObjectRequired( objIdx );
|
|
bool bCached = bLoaded && (!bReferenced && !bRequired);
|
|
|
|
bool includeByState = ( (bReferenced && m_IncludeReferencedObjects) ||
|
|
(bRequired && m_IncludeDontDeleteObjects) ||
|
|
(bCached && m_IncludeCachedObjects) ||
|
|
(bRequested && m_IncludeRequestedObjects) );
|
|
|
|
if (includeByState)
|
|
{
|
|
if (s_DumpExcludeSceneAssetsInGraph)
|
|
{
|
|
if (s_SceneMap.Access(streamingIndex) != NULL)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if ( m_ExcludeCutsceneRequestedObjects)
|
|
{
|
|
if ( info->GetFlags() & STRFLAG_CUTSCENE_REQUIRED )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (m_CutsceneRequired.Access(streamingIndex) != NULL)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if ( m_OnlyIncludeCutsceneRequestedObjects && !( info->GetFlags() & STRFLAG_CUTSCENE_REQUIRED ) )
|
|
{
|
|
if (m_CutsceneRequired.Access(streamingIndex) == NULL)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
else if ( m_OnlyIncludeScriptRequestedObjects )
|
|
{
|
|
if( m_ScriptDependentOnList.Find(streamingIndex) != -1 )
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool CStreamGraph::ObjectPassesCategoryFilter( strStreamingModule* pModule, s32 categoryIdx, strLocalIndex objIdx )
|
|
{
|
|
strStreamingInfoManager & strInfoManager = strStreamingEngine::GetInfo();
|
|
strIndex streamingIndex = pModule->GetStreamingIndex(objIdx);
|
|
|
|
if ( strInfoManager.IsObjectInImage(streamingIndex) )
|
|
{
|
|
strStreamingInfo* info = strInfoManager.GetStreamingInfo(streamingIndex);
|
|
|
|
if(GetStreamingCategory(info) != (u32)categoryIdx)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return ObjectPassesFilter(pModule, objIdx);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "debug/TextureViewer/TextureViewer.h"
|
|
#include "debug/TextureViewer/TextureViewerSearch.h" // for CTxdRef, GetAssociatedTxds_ModelInfo
|
|
|
|
extern void GetTxdRefsUsedByEntity(atMap<CTxdRef, u32>& txdRefMap, const CEntity* pEntity);
|
|
|
|
bool CStreamGraph::IsSelectedUsedByCB(CEntity *pEntity)
|
|
{
|
|
// exclude anything selected in an extension.
|
|
if(m_ShowMemoryTracker && !m_pStreamGraphExtManager->m_bExtensionSelected[SCENESTREAMINGMEMORYTRACKER_BUFFER_RENDER] )
|
|
{
|
|
CStreamGraphBuffer &updateBuffer = m_statBuffers[ SCENESTREAMINGMEMORYTRACKER_BUFFER_RENDER ];
|
|
strStreamingInfoManager & strInfoManager = strStreamingEngine::GetInfo();
|
|
strStreamingModuleMgr& moduleMgr = strInfoManager.GetModuleMgr();
|
|
strStreamingModule* pModule = moduleMgr.GetModule(updateBuffer.m_CurrentlySelectedModuleIdx);
|
|
|
|
if(pModule == NULL)
|
|
return false;
|
|
|
|
if(pModule == &g_TxdStore)
|
|
{
|
|
strIndex streamingIndex = pModule->GetStreamingIndex(strLocalIndex(updateBuffer.m_CurrentlySelectedFileObjIdx));
|
|
|
|
atMap<CTxdRef, u32> txdRefMap;
|
|
GetTxdRefsUsedByEntity(txdRefMap, pEntity);
|
|
|
|
for (atMap<CTxdRef, u32>::Iterator iter = txdRefMap.CreateIterator(); !iter.AtEnd(); iter.Next())
|
|
{
|
|
const CTxdRef& ref = iter.GetKey();
|
|
|
|
strIndex strIDX = pModule->GetStreamingIndex(ref.GetAssetIndex());
|
|
|
|
if( strIDX == streamingIndex )
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
strIndex streamingIndex = pModule->GetStreamingIndex(strLocalIndex(updateBuffer.m_CurrentlySelectedFileObjIdx));
|
|
|
|
strIndex deps[STREAMING_MAX_DEPENDENCIES];
|
|
strStreamingModule *pModelInfoStreamingModule = fwArchetypeManager::GetStreamingModule();
|
|
int depsCount = pModelInfoStreamingModule->GetDependencies(strLocalIndex(pEntity->GetModelIndex()), deps, STREAMING_MAX_DEPENDENCIES );
|
|
for(int i=0;i<depsCount;i++)
|
|
{
|
|
if( deps[i] == streamingIndex)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
#endif //__BANK
|