Files
GTASource/game/streaming/streamingdebuggraphextensions.cpp
expvintl 419f2e4752 init
2025-02-23 17:40:52 +08:00

900 lines
29 KiB
C++

#include "bank/bank.h"
#include "bank/bkmgr.h"
#include "streamingdebuggraph.h"
#include "streamingdebuggraphextensions.h"
#include "streaming/streamingdebug.h"
#include "text/text.h"
#include "text/textconversion.h"
#include "fwdebug/debugdraw.h"
#include "grcore/viewport.h"
#include "fwmaths/Rect.h"
#include "vector/color32.h"
#include "vector/colors.h"
#include "renderer/sprite2d.h"
#include "system/controlMgr.h"
#if __BANK
STREAMING_OPTIMISATIONS()
/////////////////////////////////////////////////////////////////////////////////////
// CStreamGraphExtensionBase
/////////////////////////////////////////////////////////////////////////////////////
float CStreamGraphExtensionBase::backtraceX;
float CStreamGraphExtensionBase::backtraceY;
void CStreamGraphExtensionBase::DisplayBacktraceLine(size_t addr,const char* sym,size_t displacement)
{
char achMsg[512];
CTextLayout DebugTextLayout;
DebugTextLayout.SetScale(Vector2(0.3f, 0.3f));
Color32 color = Color_white;
sprintf(achMsg,"0x%" SIZETFMT "x - %s - %" SIZETFMT "u", addr, sym, displacement );
DebugTextLayout.SetColor(color);
DebugTextLayout.Render(STREAMGRAPH_SCREEN_COORDS(backtraceX, backtraceY), achMsg);
backtraceY += 16.0f;
}
/////////////////////////////////////////////////////////////////////////////////////
// CStreamGraphExternalAllocations
/////////////////////////////////////////////////////////////////////////////////////
void CStreamGraphExternalAllocations::Update()
{
if( CControlMgr::GetKeyboard().GetKeyJustDown(KEY_RIGHT, KEYBOARD_MODE_DEBUG, "move forward in file list") )
{
m_CurrentSelection++;
}
if( CControlMgr::GetKeyboard().GetKeyJustDown(KEY_LEFT, KEYBOARD_MODE_DEBUG, "move back in file list") )
{
m_CurrentSelection--;
}
m_CurrentSelection = Clamp( m_CurrentSelection, 0, m_MaxSelection-1 );
}
float CStreamGraphExternalAllocations::DrawMemoryBar(float x, float y)
{
float heightOfBarDrawn = 0.0f;
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;
for ( s32 xAxisIdx = 0; xAxisIdx<NUM_EXT_ALLOC_BUCKETS; xAxisIdx++ )
{
atArray<strExternalAlloc> &thisBucket = m_Allocations[xAxisIdx];
u32 memoryInBar = 0;
for(int i=0;i<thisBucket.size();i++)
{
if ( DEBUGSTREAMGRAPH.m_ShowPhysicalMemory && thisBucket[i].IsVRAM() )
{
totalBarPhysMemory += thisBucket[i].m_Size;
memoryInBar += thisBucket[i].m_Size;
}
if ( DEBUGSTREAMGRAPH.m_ShowVirtualMemory && thisBucket[i].IsMAIN() )
{
totalBarVirtMemory += thisBucket[i].m_Size;
memoryInBar += thisBucket[i].m_Size;
}
}
if ( !bDoneBackground )
{
bDoneBackground = true;
DebugTextLayout.SetColor(Color32(255, 255, 255, 255));
DebugTextLayout.Render(STREAMGRAPH_SCREEN_COORDS(x, y), "ExternalAllocations");
DEBUGSTREAMGRAPH.DrawMemoryMarkers(x, y);
}
float barWidth = ( (float)(memoryInBar) / (float)( DEBUGSTREAMGRAPH.GetMaxMemMB() * 1024 * 1024 ) ) * DEBUGSTREAMGRAPH.GetGraphWidth();
Color32 barColour1 = Color32(0,255,0,255);
Color32 barColour2 = GetLegendColour( xAxisIdx );
if( ( curX - x ) + barWidth > DEBUGSTREAMGRAPH.GetGraphWidth() )
{
barWidth = DEBUGSTREAMGRAPH.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();
#ifdef __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);
}
if( DEBUGSTREAMGRAPH.m_pStreamGraphExtManager->GetSelectedExt( SCENESTREAMINGMEMORYTRACKER_BUFFER_RENDER ) == this )
{
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;
s32 count = 0;
for(int i=0;i<NUM_EXT_ALLOC_BUCKETS;i++)
{
atArray<strExternalAlloc> &thisBucket = m_Allocations[i];
for(int j=0;j<thisBucket.size();j++)
{
if ( DEBUGSTREAMGRAPH.m_ShowPhysicalMemory && thisBucket[j].IsVRAM() )
{
selectedSegmentMemorySize = thisBucket[j].m_Size;
}
if ( DEBUGSTREAMGRAPH.m_ShowVirtualMemory && thisBucket[j].IsMAIN() )
{
selectedSegmentMemorySize = thisBucket[j].m_Size;
}
if(count == m_CurrentSelection)
{
i = NUM_EXT_ALLOC_BUCKETS;
break;
}
count++;
if ( DEBUGSTREAMGRAPH.m_ShowPhysicalMemory && thisBucket[j].IsVRAM() )
{
accumulatedMemoryBeforeSelected += thisBucket[j].m_Size;
}
if ( DEBUGSTREAMGRAPH.m_ShowVirtualMemory && thisBucket[j].IsMAIN() )
{
accumulatedMemoryBeforeSelected += thisBucket[j].m_Size;
}
}
}
float selectedFileSegmentXStart = x + STREAMGRAPH_X_BORDER + ( (float)(accumulatedMemoryBeforeSelected) / (float)( DEBUGSTREAMGRAPH.GetMaxMemMB() * 1024 * 1024 ) ) * DEBUGSTREAMGRAPH.GetGraphWidth();
float selectedFileSegmentXEnd = selectedFileSegmentXStart + ( (float)(selectedSegmentMemorySize) / (float)( DEBUGSTREAMGRAPH.GetMaxMemMB() * 1024 * 1024 ) ) * DEBUGSTREAMGRAPH.GetGraphWidth();
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;
}
float CStreamGraphExternalAllocations::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));
y += (grcViewport::GetDefaultScreen()->GetHeight() < 1042 ? 0.0f : 16.0f);
float yEnd = y;
s32 numCategories = NUM_EXT_ALLOC_BUCKETS;
for (u32 i=0; i<numCategories; i++)
{
Color32 boxColor = GetLegendColour(i);
const char* label = strStreamingEngine::GetAllocator().GetBucketName(i); // sBucketLegend[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 CStreamGraphExternalAllocations::DrawFileList(float x, float y)
{
if(m_CurrentSelection < 0)
return;
CTextLayout DebugTextLayout;
DebugTextLayout.SetScale(Vector2(0.3f, 0.3f));
s32 NumListEntries = 10;
// Incase the list can't be filled.
NumListEntries = Clamp(NumListEntries, 0, m_MaxSelection);
// Calc the offset into the list
s32 ListOffset = m_CurrentSelection - (NumListEntries>>1);
if( ListOffset >= (m_MaxSelection - NumListEntries) )
{
ListOffset = m_MaxSelection - (NumListEntries);
}
if( ListOffset < 0 )
{
ListOffset = 0;
}
const float headerSize = 16*STREAMGRAPH_FONTSCALE_FACTOR();
float xStart= x;
float xEnd = x + DEBUGSTREAMGRAPH.GetFileListWidth();
float yStart = y + 5 + headerSize;
float yEnd = yStart + NumListEntries * 16;
float yLength = yEnd - yStart;
float y0 = yStart + yLength * (float)ListOffset / (float)m_MaxSelection;
float y1 = y0 + yLength * (float)NumListEntries / (float)m_MaxSelection;
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);
float trackLeft = xEnd - 11;
float trackRight = xEnd - 7;
u32 totalFiles = m_MaxSelection;
u32 totalFilesSoFar = 0;
s32 nBuckets = NUM_EXT_ALLOC_BUCKETS;
for (u32 i=0; i<nBuckets; i++)
{
u32 numFiles = GetExtAllocsInCurrentBucket(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;
}
strExternalAlloc *pAlloc = GetExtAlloc(m_CurrentSelection);
if(!pAlloc)
return;
// header
Color32 color = Color_white;
DebugTextLayout.SetColor(color);
char fileListHeader[128];
const char * barName = strStreamingEngine::GetAllocator().GetBucketName(pAlloc->m_BucketID); //sBucketLegend[ pAlloc->m_BucketID ].label;
snprintf(fileListHeader, 128, "%s: %i allocations out of %d", barName, GetExtAllocsInCurrentBucket(pAlloc->m_BucketID), m_MaxSelection);
DebugTextLayout.Render(STREAMGRAPH_SCREEN_COORDS(xStart, yStart - headerSize), fileListHeader);
fwRect headerUnderline(xStart,yStart - 2,xEnd - 4,yStart - 1);
CSprite2d::DrawRectSlow(headerUnderline, Color_white);
// list
for(int i = 0; i < NumListEntries; ++i)
{
char buffer[128];
Color32 color = i == (m_CurrentSelection - ListOffset) ? Color_green : Color_white;
strExternalAlloc *pThisAlloc = GetExtAlloc(ListOffset + i);
sprintf(buffer,"%p - Size = %d - %s",pThisAlloc->m_pMemory, pThisAlloc->m_Size, pThisAlloc->IsMAIN() ? "MAIN" : "VRAM" );
DebugTextLayout.SetColor(color);
DebugTextLayout.Render(STREAMGRAPH_SCREEN_COORDS(xStart, i * 16 + yStart), buffer);
}
}
void CStreamGraphExternalAllocations::DrawFileInfo( float x, float y )
{
if(m_CurrentSelection < 0)
return;
backtraceX = x;
backtraceY = y;
strExternalAlloc *pThisAlloc = GetExtAlloc(m_CurrentSelection);
if(pThisAlloc)
{
sysStack::PrintRegisteredBacktrace(pThisAlloc->m_BackTraceHandle, DisplayBacktraceLine);
}
}
// Sorts by size (largest first)
int CStreamGraphExternalAllocations::CompareExtAllocBySize(const strExternalAlloc* pA, const strExternalAlloc* pB)
{
return pB->m_Size - pA->m_Size;
}
void CStreamGraphExternalAllocations::SwapBuffers()
{
// Copy into the array array of external allocations
// Clear out each bucket
for(int i=0;i<NUM_EXT_ALLOC_BUCKETS;i++)
{
m_Allocations[i].Reset();
}
// Fill each bucket with appropriate data
m_MaxSelection = 0;
atArray<strExternalAlloc> &Allocs = strStreamingEngine::GetAllocator().m_ExtAllocTracker.m_Allocations;
for(int i=0;i<Allocs.size();i++)
{
if( Allocs[i].IsMAIN() && !DEBUGSTREAMGRAPH.m_ShowVirtualMemory)
continue;
if( Allocs[i].IsVRAM() && !DEBUGSTREAMGRAPH.m_ShowPhysicalMemory)
continue;
m_Allocations[Allocs[i].m_BucketID].PushAndGrow(Allocs[i]);
m_MaxSelection++;
}
// Now sort by size
for(int i=0;i<NUM_EXT_ALLOC_BUCKETS;i++)
{
m_Allocations[i].QSort(0,-1,CompareExtAllocBySize);
}
// Now clamp to the max value.
m_CurrentSelection = Clamp( m_CurrentSelection, 0, m_MaxSelection-1 );
}
void CStreamGraphExternalAllocations::AddWidgets(bkBank* pBank)
{
pBank->AddToggle("Display External Allocations from Streaming Module", &m_bActive);
}
/////////////////////////////////////////////////////////////////////////////////////
// CStreamGraphAllocationsToResGameVirt
/////////////////////////////////////////////////////////////////////////////////////
void CStreamGraphAllocationsToResGameVirt::Update()
{
if( CControlMgr::GetKeyboard().GetKeyJustDown(KEY_RIGHT, KEYBOARD_MODE_DEBUG, "move forward in file list") )
{
m_CurrentSelection++;
}
if( CControlMgr::GetKeyboard().GetKeyJustDown(KEY_LEFT, KEYBOARD_MODE_DEBUG, "move back in file list") )
{
m_CurrentSelection--;
}
m_CurrentSelection = Clamp( m_CurrentSelection, 0, m_MaxSelection-1 );
}
CStreamGraphAllocationsToResGameVirt::~CStreamGraphAllocationsToResGameVirt()
{
streamAssert(false);
}
float CStreamGraphAllocationsToResGameVirt::DrawMemoryBar(float x, float y)
{
float heightOfBarDrawn = 0.0f;
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;
atFixedArray<ModuleAllocations, CStreamGraphBuffer::MAX_TRACKED_MODULES> &Allocations = GetRenderAllocations();
for ( s32 xAxisIdx = 0; xAxisIdx<Allocations.size(); xAxisIdx++ )
{
atArray<ObjectAndSize> &thisModule = Allocations[xAxisIdx].m_AllocationsByObject;
u32 memoryInBar = 0;
for(int i=0;i<thisModule.size();i++)
{
// Ensure this doesn't go negative (as there is a bug where sometimes they are)
int size = thisModule[i].m_size;
if(size < 0)
size = 0;
totalBarVirtMemory += size;
memoryInBar += size;
}
if ( !bDoneBackground )
{
bDoneBackground = true;
DebugTextLayout.SetColor(Color32(255, 255, 255, 255));
DebugTextLayout.Render(STREAMGRAPH_SCREEN_COORDS(x, y), "AllocationsToGameResVirt");
DEBUGSTREAMGRAPH.DrawMemoryMarkers(x, y);
}
float barWidth = ( (float)(memoryInBar) / (float)( DEBUGSTREAMGRAPH.GetMaxMemMB() * 1024 * 1024 ) ) * DEBUGSTREAMGRAPH.GetGraphWidth();
Color32 barColour1 = Color32(0,255,0,255);
Color32 barColour2 = GetLegendColour( xAxisIdx );
if( ( curX - x ) + barWidth > DEBUGSTREAMGRAPH.GetGraphWidth() )
{
barWidth = DEBUGSTREAMGRAPH.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();
#ifdef __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);
}
if( DEBUGSTREAMGRAPH.m_pStreamGraphExtManager->GetSelectedExt( SCENESTREAMINGMEMORYTRACKER_BUFFER_RENDER ) == this )
{
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;
s32 count = 0;
for(int i=0;i<Allocations.size();i++)
{
ModuleAllocations &modAllocs = Allocations[i];
selectedSegmentMemorySize = Max(0,modAllocs.m_totalSize,0,modAllocs.m_totalSize);
if(count == m_CurrentSelection)
{
i = Allocations.size();
break;
}
count++;
accumulatedMemoryBeforeSelected += Max(0,modAllocs.m_totalSize,0,modAllocs.m_totalSize);
}
float selectedFileSegmentXStart = x + STREAMGRAPH_X_BORDER + ( (float)(accumulatedMemoryBeforeSelected) / (float)( DEBUGSTREAMGRAPH.GetMaxMemMB() * 1024 * 1024 ) ) * DEBUGSTREAMGRAPH.GetGraphWidth();
float selectedFileSegmentXEnd = selectedFileSegmentXStart + ( (float)(selectedSegmentMemorySize) / (float)( DEBUGSTREAMGRAPH.GetMaxMemMB() * 1024 * 1024 ) ) * DEBUGSTREAMGRAPH.GetGraphWidth();
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;
}
float CStreamGraphAllocationsToResGameVirt::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;
int maxModules = strStreamingEngine::GetInfo().GetModuleMgr().GetNumberOfModules();
s32 numCategories = maxModules;
for (u32 i=0; i<numCategories; i++)
{
strStreamingModule* pModule = strStreamingEngine::GetInfo().GetModuleMgr().GetModule(i);
Color32 boxColor = GetLegendColour(i);
const char* label = pModule->GetModuleName();
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) * 20;
return yEnd;
}
void CStreamGraphAllocationsToResGameVirt::DrawFileList(float x, float y)
{
if(m_CurrentSelection < 0)
return;
CTextLayout DebugTextLayout;
DebugTextLayout.SetScale(Vector2(0.3f, 0.3f));
s32 NumListEntries = 6;
// Incase the list can't be filled.
NumListEntries = Clamp(NumListEntries, 0, m_MaxSelection);
// Calc the offset into the list
s32 ListOffset = m_CurrentSelection - (NumListEntries>>1);
if( ListOffset >= (m_MaxSelection - NumListEntries) )
{
ListOffset = m_MaxSelection - (NumListEntries);
}
if( ListOffset < 0 )
{
ListOffset = 0;
}
const float headerSize = 16;
float xStart= x;
float xEnd = x + DEBUGSTREAMGRAPH.GetFileListWidth();
float yStart = y + 5 + headerSize;
float yEnd = yStart + NumListEntries * 16;
float yLength = yEnd - yStart;
float y0 = yStart + yLength * (float)ListOffset / (float)m_MaxSelection;
float y1 = y0 + yLength * (float)NumListEntries / (float)m_MaxSelection;
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);
float trackLeft = xEnd - 11;
float trackRight = xEnd - 7;
u32 totalFiles = m_MaxSelection;
u32 totalFilesSoFar = 0;
s32 nBuckets = strStreamingEngine::GetInfo().GetModuleMgr().GetNumberOfModules();
for (u32 i=0; i<nBuckets; i++)
{
u32 numFiles = 1;
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;
}
// header
Color32 color = Color_white;
DebugTextLayout.SetColor(color);
char fileListHeader[128];
//const char * barName = strStreamingEngine::GetInfo().GetModuleMgr().GetModule(m_CurrentSelection)->GetModuleName();
snprintf(fileListHeader, 128, "Module:");
DebugTextLayout.Render(STREAMGRAPH_SCREEN_COORDS(xStart, yStart - headerSize), fileListHeader);
fwRect headerUnderline(xStart,yStart - 2,xEnd - 4,yStart - 1);
CSprite2d::DrawRectSlow(headerUnderline, Color_white);
// list
for(int i = 0; i < NumListEntries; ++i)
{
char buffer[128];
Color32 color = i == (m_CurrentSelection - ListOffset) ? Color_green : Color_white;
const char * barName = strStreamingEngine::GetInfo().GetModuleMgr().GetModule(ListOffset + i)->GetModuleName();
sprintf(buffer,"%s",barName);
DebugTextLayout.SetColor(color);
DebugTextLayout.Render(STREAMGRAPH_SCREEN_COORDS(xStart, i * 16 + yStart), buffer);
}
}
// Sorts by size (largest first)
int CStreamGraphAllocationsToResGameVirt::CompareObjectBySize(const ObjectAndSize* pA, const ObjectAndSize* pB)
{
return pB->m_size - pA->m_size;
}
void CStreamGraphAllocationsToResGameVirt::DrawFileInfo(float x, float y)
{
if(m_CurrentSelection < 0)
return;
char buffer[200];
CTextLayout DebugTextLayout;
DebugTextLayout.SetScale(Vector2(0.3f, 0.3f));
DebugTextLayout.SetColor(Color_white);
int numTopAllocs = 20;
atFixedArray<ModuleAllocations, CStreamGraphBuffer::MAX_TRACKED_MODULES> &Allocations = GetRenderAllocations();
ModuleAllocations &modAllocs = Allocations[m_CurrentSelection];
modAllocs.m_AllocationsByObject.QSort(0,-1,CompareObjectBySize);
strStreamingModule* pModule = strStreamingEngine::GetInfo().GetModuleMgr().GetModule(m_CurrentSelection);
// Header
sprintf(buffer,"Total Objects: %d = %d total (bytes)", modAllocs.m_AllocationsByObject.size(), modAllocs.m_totalSize );
DebugTextLayout.Render(STREAMGRAPH_SCREEN_COORDS(x, y), buffer);
y+=18;
if( modAllocs.m_AllocationsByObject.size() )
{
sprintf(buffer,"Top %d Allocations by size:", numTopAllocs );
DebugTextLayout.Render(STREAMGRAPH_SCREEN_COORDS(x, y), buffer);
y+=18;
// Draw the top allocs
for(int i=0;i<modAllocs.m_AllocationsByObject.size() && i<numTopAllocs;i++)
{
ObjectAndSize &objAndSize = modAllocs.m_AllocationsByObject[i];
sprintf(buffer,"Object:- %s = %d instances = %d (bytes)", pModule->GetName(strLocalIndex(objAndSize.m_objIdx)), objAndSize.m_Count, objAndSize.m_size );
DebugTextLayout.Render(STREAMGRAPH_SCREEN_COORDS(x, i * 16 + y), buffer);
}
}
}
void CStreamGraphAllocationsToResGameVirt::SwapBuffers()
{
USE_DEBUG_MEMORY();
m_Allocations[SCENESTREAMINGMEMORYTRACKER_BUFFER_RENDER].Reset();
m_Allocations[SCENESTREAMINGMEMORYTRACKER_BUFFER_RENDER] = m_Allocations[SCENESTREAMINGMEMORYTRACKER_BUFFER_UPDATE];
m_MaxSelection = strStreamingEngine::GetInfo().GetModuleMgr().GetNumberOfModules();
}
void CStreamGraphAllocationsToResGameVirt::AddWidgets(bkBank* pBank)
{
pBank->AddToggle("Display Allocations To Game Resource Virtual by Module", &m_bActive);
}
struct sStreamGraphAllocationsWatermark
{
int moduleId;
size_t size;
};
__THREAD sStreamGraphAllocationsWatermark m_ResourceMemoryUse[16];
__THREAD int m_ResourceMemoryUseHead = -1;
void CStreamGraphAllocationsToResGameVirt::PreChange(int moduleID, int UNUSED_PARAM(objIndex), bool)
{
if(CSystem::IsThisThreadId(SYS_THREAD_UPDATE))
{
++m_ResourceMemoryUseHead;
if(m_ResourceMemoryUseHead < NELEM(m_ResourceMemoryUse))
{
m_ResourceMemoryUse[m_ResourceMemoryUseHead].moduleId = moduleID;
m_ResourceMemoryUse[m_ResourceMemoryUseHead].size = sysMemAllocator::GetMaster().GetAllocator(MEMTYPE_GAME_VIRTUAL)->GetMemoryUsed(MEMBUCKET_RESOURCE);
/*
if ( m_ResourceMemoryUseHead > 0 )
{
streamDisplayf("-=[ Recursion detected - IN @ %d ]=-", m_ResourceMemoryUseHead);
}
*/
}
}
}
void CStreamGraphAllocationsToResGameVirt::PostChange(int moduleID, int objIndex, bool UNUSED_PARAM(isLoading))
{
if(CSystem::IsThisThreadId(SYS_THREAD_UPDATE))
{
if(m_ResourceMemoryUseHead < NELEM(m_ResourceMemoryUse))
{
size_t postSize = sysMemAllocator::GetMaster().GetAllocator(MEMTYPE_GAME_VIRTUAL)->GetMemoryUsed(MEMBUCKET_RESOURCE);
int diff = ptrdiff_t_to_int(postSize - m_ResourceMemoryUse[m_ResourceMemoryUseHead].size);
if( diff )
{
streamAssertf( moduleID == m_ResourceMemoryUse[m_ResourceMemoryUseHead].moduleId, "Difference in modules %p vs %p",
strStreamingEngine::GetInfo().GetModuleMgr().GetModule(m_ResourceMemoryUse[m_ResourceMemoryUseHead].moduleId), strStreamingEngine::GetInfo().GetModuleMgr().GetModule(moduleID) );
/*
strStreamingModule* pModule = strStreamingEngine::GetInfo().GetModuleMgr().GetModule(moduleID);
streamDisplayf("%s PostChange:: Module %s, objIndex %d = %s - Size diff = %d (%d - %d)", isLoading ? "Loading":"Removing", pModule->GetModuleName(), objIndex,
pModule->GetName(objIndex), diff, postSize,m_ResourceMemoryUse[m_ResourceMemoryUseHead].size );
*/
//streamAssert( (diff >= 0 && isLoading) || (diff <= 0 && !isLoading) );
if(g_pResVirtAllocs)
g_pResVirtAllocs->RecordAllocationChange(moduleID, objIndex, diff);
}
int prevHead = m_ResourceMemoryUseHead-1;
if ( prevHead >= 0)
{
// streamDisplayf("-=[ Recursion detected - OUT - adding %d to %d ]=-", diff,m_ResourceMemoryUse[prevHead].size );
m_ResourceMemoryUse[prevHead].size += diff;
}
}
--m_ResourceMemoryUseHead;
streamAssert( m_ResourceMemoryUseHead >= -1 );
}
}
void CStreamGraphAllocationsToResGameVirt::RecordAllocationChange(int moduleID, int objIndex, int size)
{
USE_DEBUG_MEMORY();
atFixedArray<ModuleAllocations, CStreamGraphBuffer::MAX_TRACKED_MODULES> &updateSizes = GetUpdateAllocations();
// Update
bool found = false;
ModuleAllocations &ModuleAllocs = updateSizes[moduleID];
for(int i=0;i<ModuleAllocs.m_AllocationsByObject.size();i++)
{
ObjectAndSize &ObjSize = ModuleAllocs.m_AllocationsByObject[i];
if( ObjSize.m_objIdx == objIndex )
{
ObjSize.m_size += size;
ObjSize.m_Count++;
found = true;
break;
}
}
// Didn't find a record, add a new one
if(!found)
{
ObjectAndSize thisObject;
thisObject.m_objIdx = objIndex;
thisObject.m_size = size;
thisObject.m_Count = 1;
updateSizes[moduleID].m_AllocationsByObject.Grow(128) = thisObject;
}
updateSizes[moduleID].m_totalSize += size;
//streamAssertf(updateSizes[moduleID].m_totalSize >=0, "ERROR: module allocations to the resource bucket have gone -ve!");
}
CStreamGraphAllocationsToResGameVirt *g_pResVirtAllocs = NULL;
/////////////////////////////////////////////////////////////////////////////////////
// CStreamGraphExtensionManager
/////////////////////////////////////////////////////////////////////////////////////
CStreamGraphExtensionManager::CStreamGraphExtensionManager()
{
m_bExtensionSelected[SCENESTREAMINGMEMORYTRACKER_BUFFER_UPDATE] = false;
m_bExtensionSelected[SCENESTREAMINGMEMORYTRACKER_BUFFER_RENDER] = false;
m_CurrentSelected[SCENESTREAMINGMEMORYTRACKER_BUFFER_UPDATE] = -1;
m_CurrentSelected[SCENESTREAMINGMEMORYTRACKER_BUFFER_RENDER] = -1;
// Create and add extensions
m_pExtAllocs = rage_new CStreamGraphExternalAllocations;
g_pResVirtAllocs = rage_new CStreamGraphAllocationsToResGameVirt; // Needs to be a global pointer as it's referenced externally
// Add the extensions
AddExtension(m_pExtAllocs);
AddExtension(g_pResVirtAllocs);
}
CStreamGraphExtensionManager::~CStreamGraphExtensionManager()
{
delete m_pExtAllocs;
delete g_pResVirtAllocs;
g_pResVirtAllocs = NULL;
}
// Keys left and right
void CStreamGraphExtensionManager::Update()
{
// Keep in a loop incase we want to update unselected, but active bars in the future.
for(int i=0;i<m_Extensions.size();i++)
{
CStreamGraphExtensionBase *pExtension = m_Extensions[i];
if(pExtension->IsActive() && IsSelected( pExtension, SCENESTREAMINGMEMORYTRACKER_BUFFER_UPDATE ))
{
pExtension->Update();
}
}
}
void CStreamGraphExtensionManager::SwapBuffers()
{
m_bExtensionSelected[SCENESTREAMINGMEMORYTRACKER_BUFFER_RENDER] = m_bExtensionSelected[SCENESTREAMINGMEMORYTRACKER_BUFFER_UPDATE];
m_CurrentSelected[SCENESTREAMINGMEMORYTRACKER_BUFFER_RENDER] = m_CurrentSelected[SCENESTREAMINGMEMORYTRACKER_BUFFER_UPDATE];
for(int i=0;i<m_Extensions.size();i++)
{
CStreamGraphExtensionBase *pExtension = m_Extensions[i];
if(pExtension->IsActive())
{
pExtension->SwapBuffers();
}
}
}
// Probably won't be used
void CStreamGraphExtensionManager::DebugDraw()
{
}
void CStreamGraphExtensionManager::AddWidgets(bkBank* pBank)
{
pBank->AddTitle("Extensions");
for(int i=0;i<m_Extensions.size();i++)
{
CStreamGraphExtensionBase *pExtension = m_Extensions[i];
pExtension->AddWidgets(pBank);
}
}
void CStreamGraphExtensionManager::AddExtension(CStreamGraphExtensionBase *pExtension)
{
m_Extensions.PushAndGrow(pExtension);
}
//CStreamGraphExtensionManager g_StreamGraphExtManager;
/////////////////////////////////////////////////////////////////////////////////////
#endif //__BANK