GPU Memory Tracking
Overview
In version 1.40, Gameface introduces GPU memory tracking. This comes with the ability to extract detailed information about the allocated GPU memory in the View
and Library
and the ability to reset the GPU memory peaks. That makes it easier to check the memory statistics of the allocated resources.
This page provides details about the feature, a list of everything we track, a sample of how to obtain the information, as well as a few general considerations for extracting the information.
How to extract GPU memory information
We have developed a new structure to hold the GPU memory data called GPUMemoryInfo
, which can be filled with all the information using the help of the GetGPUMemoryStats()
method found in the View
and Library
. Keep in mind that the GPUMemoryInfo::Release()
method must be called on the returned renoir::GPUMemoryInfo*
structure to free its allocated memory. The statistics from the Library
include all shared resources across the Views
s, while the statistics from the View
only include the resources allocated for its needs. A list of every member in the GPUMemoryInfo
structure along with a description of what each element tracks is provided below.
How to reset GPU memory peaks
In order to reset the accumulated memory peaks to match the current state, the ResetGPUMemoryTrackerPeaks()
method of the View
and/or Library
needs to be invoked.
A list of all the monitored GPU memory data
All GPU memory is tracked in bytes.
Member | Description |
---|---|
size_t TotalGPUMemory | The total GPU memory |
size_t PeakGPUMemory | The biggest GPU memory reached |
size_t TotalTexturesGPUMemory | The total GPU memory of all textures(including Depth-Stencil) |
size_t PeakTexturesGPUMemory | The maximum reached GPU memory of all textures |
size_t TotalIBuffersGPUMemory | The total GPU memory of all Index Buffers |
size_t TotalVBuffersGPUMemory | The total GPU memory of all Vertex Buffers |
size_t TotalCBuffersGPUMemory | The total GPU memory of all Constant Buffers |
size_t PeakIBuffersGPUMemory | The maximum reached GPU memory of all Index Buffers |
size_t PeakVBuffersGPUMemory | The maximum reached GPU memory of all Vertex Buffers |
size_t PeakCBuffersGPUMemory | The maximum reached GPU memory of all Constant Buffers |
unsigned IBufferPeak[renoir::domains::IBDomain::IB_Count] | An array containing the maximum GPU memory for each Index Buffer type |
unsigned VBufferPeak[renoir::domains::VBDomain::VB_Count] | An array containing the maximum GPU memory for each Vertex Buffer type |
unsigned CBufferPeak[renoir::domains::CBDomain::CB_Count] | An array containing the maximum GPU memory for each Constant Buffer type |
unsigned IBufferTotalGPUMemory[renoir::domains::IBDomain::IB_Count] | An array containing the total GPU memory for each Index Buffer type |
unsigned VBufferTotalGPUMemory[renoir::domains::VBDomain::VB_Count] | An array containing the total GPU memory for each Vertex Buffer type |
unsigned CBufferTotalGPUMemory[renoir::domains::CBDomain::CB_Count] | An array containing the total GPU memory for each Constant Buffer type |
unsigned TexturePeakSize[renoir::domains::TextureDomain::T_Count] | An array containing the maximum GPU memory for each Texture type |
unsigned TexturePeakCount[renoir::domains::TextureDomain::T_Count] | An array containing the maximum amount of allocated textures for each type |
unsigned TextureTotalGPUMemory[renoir::domains::TextureDomain::T_Count] | An array containing the total GPU memory for each Texture type |
unsigned DSTexturePeakSize[renoir::domains::TextureDomain::T_Count] | An array containing the maximum GPU memory for each Depth-Stencil Texture type |
unsigned DSTexturePeakCount[renoir::domains::TextureDomain::T_Count] | An array containing the maximum amount of allocated depth-stencil textures for each type |
unsigned DSTextureTotalGPUMemory[renoir::domains::TextureDomain::T_Count] | An array containing the total GPU memory for each Depth-Stencil Texture type |
ResourceArray Textures[renoir::domains::TextureDomain::T_Count] | An array of ResourceArray structures containing size_t Count and a ResourceInfo* Array , where the Count indicates the amount of elements inside the Array , which contains of an unsigned Id representing the resource’s ID and size_t Size for the size of the specific texture |
ResourceArray DSTextures[renoir::domains::TextureDomain::T_Count] | An array of ResourceArray structures containing size_t Count and a ResourceInfo* Array , where the Count indicates the amount of elements inside the Array , which contains of an unsigned Id representing the resource’s ID and size_t Size for the size of the specific depth-stencil texture |
ResourceArray ConstantBuffers[renoir::domains::CBDomain::CB_Count] | An array of ResourceArray structures containing size_t Count and a ResourceInfo* Array , where the Count indicates the amount of elements inside the Array , which contains of an unsigned Id representing the resource’s ID and size_t Size for the size of the specific constant buffer |
BufferArray IndexBuffers[renoir::domains::IBDomain::IB_Count] | An array BufferArray structures containing size_t Count and a BufferResourceInfo* Array , where the Count indicates the amount of elements inside the Array , which contains of an unsigned Id representing the resource’s ID, a size_t Size for the size of the specific index buffer and a size_t Peak which is the maximum GPU memory used so far from the buffer |
BufferArray VertexBuffers[renoir::domains::VBDomain::VB_Count] | An array BufferArray structures containing size_t Count and a BufferResourceInfo* Array , where the Count indicates the amount of elements inside the Array , which contains of an unsigned Id representing the resource’s ID, a size_t Size for the size of the specific vertex buffer and a size_t Peak which is the maximum GPU memory used so far from the buffer |
Resource domains
enum TextureDomain // Texture Domain
{
T_ScratchTexture = 0,
T_LayerTexture,
T_ImageTexture,
T_SurfaceTexture,
T_CompositorTexture,
T_GlyphAtlas,
T_GradientCacheTexture,
T_Count
};
enum VBDomain // Vertex Buffer Domain
{
VB_GeometryBuffer = 0,
VB_PathBuffer,
VB_GlyphBuffer,
VB_Count
};
enum IBDomain // Index Buffer Domain
{
IB_GeometryBuffer = 0,
IB_PathBuffer,
IB_GlyphBuffer,
IB_Count
};
enum CBDomain // Constant Buffer Domain (same as CBType)
{
// Vertex shader CBs
CB_TransformVS,
CB_RenoirShaderParamsVS,
// Pixel shader CBs
CB_GlobalDataPS,
CB_StandardPrimitivePS,
CB_StandardPrimitiveAdditionalPS,
CB_EffectsPS,
CB_RenoirShaderParamsPS,
CB_Count
};
Example GPU memory information extraction and display
This is an example function of how to display GPU memory information and two sample calls using the Library
and View
stats.
void PrintGPUMemoryStats(const renoir::GPUMemoryInfo* memoryStats)
{
if (memoryStats)
{
std::cout << "---------- GPU Memory Stats ----------" << std::endl;
std::cout << "Total GPU memory: " << memoryStats->TotalGPUMemory << " bytes" << std::endl;
std::cout << "Peak GPU memory: " << memoryStats->PeakGPUMemory << " bytes" << std::endl;
std::cout << "Total Textures memory: " << memoryStats->TotalTexturesGPUMemory << " bytes" << std::endl;
std::cout << "Peak Textures memory: " << memoryStats->PeakTexturesGPUMemory << " bytes" << std::endl;
std::cout << "Total Index Buffers memory: " << memoryStats->TotalIBuffersGPUMemory << " bytes" << std::endl;
std::cout << "Total Vertex Buffers memory: " << memoryStats->TotalVBuffersGPUMemory << " bytes" << std::endl;
std::cout << "Total Constant Buffers memory: " << memoryStats->TotalCBuffersGPUMemory << " bytes" << std::endl;
std::cout << "Peak Index Buffers memory: " << memoryStats->PeakIBuffersGPUMemory << " bytes" << std::endl;
std::cout << "Peak Vertex Buffers memory: " << memoryStats->PeakVBuffersGPUMemory << " bytes" << std::endl;
std::cout << "Peak Constant Buffers memory: " << memoryStats->PeakCBuffersGPUMemory << " bytes" << std::endl;
const char* textureStrings[] = { "Scratch Texture", "Layer Texture", "Image Texture", "Surface Texture", "Compositor Texture", "Glyph Atlas", "Gradient Cache Texture" };
const char* bufferStrings[] = { "Index Geometry Buffer", "Index Path Buffer", "Index Glyph Buffer", "Vertex Geometry Buffer", "Vertex Path Buffer", "Vertex Glyph Buffer",
"CB Transform VS", "CB Renoir Shader Params VS", "CB Global Data PS", "CB Standard Primitive PS", "CB Standard Primitive Additional PS",
"CB Effects PS", "CB Renoir Shader Params PS" };
// Texture stats by type
for (size_t i = 0; i < renoir::domains::T_Count; ++i)
{
std::cout << "Total " << textureStrings[i] << "s memory: " << memoryStats->TextureTotalGPUMemory[i] << " bytes" << std::endl;
std::cout << "Peak " << textureStrings[i] << " memory: " << memoryStats->TexturePeakSize[i] << " bytes" << std::endl;
std::cout << "Peak " << textureStrings[i] << "s count: " << memoryStats->TexturePeakCount[i] << std::endl;
}
// DS Texture stats by type
for (size_t i = 0; i < renoir::domains::T_Count; ++i)
{
std::cout << "Total DS " << textureStrings[i] << "s memory: " << memoryStats->DSTextureTotalGPUMemory[i] << " bytes" << std::endl;
std::cout << "Peak DS " << textureStrings[i] << " memory: " << memoryStats->DSTexturePeakSize[i] << " bytes" << std::endl;
std::cout << "Peak DS " << textureStrings[i] << "s count: " << memoryStats->DSTexturePeakCount[i] << std::endl;
}
// Index Buffer stats by type
for (size_t i = 0; i < renoir::domains::IB_Count; ++i)
{
std::cout << "Total " << bufferStrings[i] << "s memory: " << memoryStats->IBufferTotalGPUMemory[i] << " bytes" << std::endl;
std::cout << "Peak " << bufferStrings[i] << " memory: " << memoryStats->IBufferPeak[i] << " bytes" << std::endl;
}
// Vertex Buffer stats by type
for (size_t i = 0; i < renoir::domains::VB_Count; ++i)
{
std::cout << "Total " << bufferStrings[i + renoir::domains::IB_Count] << "s memory: " << memoryStats->VBufferTotalGPUMemory[i] << " bytes" << std::endl;
std::cout << "Peak " << bufferStrings[i + renoir::domains::IB_Count] << " memory: " << memoryStats->VBufferPeak[i] << " bytes" << std::endl;
}
// Constant Buffer stats by type
for (size_t i = 0; i < renoir::CB_Count; ++i)
{
std::cout << "Total " << bufferStrings[i + renoir::domains::IB_Count + renoir::domains::VB_Count] << " memory: " << memoryStats->CBufferTotalGPUMemory[i] << " bytes" << std::endl;
std::cout << "Peak " << bufferStrings[i + renoir::domains::IB_Count + renoir::domains::VB_Count] << " memory: " << memoryStats->CBufferPeak[i] << " bytes" << std::endl;
}
// All Textures and DS Textures
for (size_t i = 0; i < renoir::domains::T_Count; ++i)
{
if (memoryStats->Textures[i].Count > 0)
{
std::cout << "--- All " << textureStrings[i] << "s ---" << std::endl;
}
for (size_t j = 0; j < memoryStats->Textures[i].Count; ++j)
{
std::cout << "ID: " << memoryStats->Textures[i].Array[j].Id << "; Size: " << memoryStats->Textures[i].Array[j].Size << " bytes" << std::endl;
}
if (memoryStats->DSTextures[i].Count > 0)
{
std::cout << "--- All DS " << textureStrings[i] << "s ---" << std::endl;
}
for (size_t j = 0; j < memoryStats->DSTextures[i].Count; ++j)
{
std::cout << "ID: " << memoryStats->DSTextures[i].Array[j].Id << "; Size: " << memoryStats->DSTextures[i].Array[j].Size << " bytes" << std::endl;
}
}
// All Index Buffers
for (size_t i = 0; i < renoir::domains::IB_Count; ++i)
{
if (memoryStats->IndexBuffers[i].Count > 0)
{
std::cout << "--- All " << bufferStrings[i] << "s ---" << std::endl;
}
for (size_t j = 0; j < memoryStats->IndexBuffers[i].Count; ++j)
{
std::cout << "ID: " << memoryStats->IndexBuffers[i].Array[j].Id << "; Size: " << memoryStats->IndexBuffers[i].Array[j].Size << " bytes" << "; Peak: " << memoryStats->IndexBuffers[i].Array[j].Peak << " bytes" << std::endl;
}
}
// All Vertex Buffers
for (size_t i = 0; i < renoir::domains::VB_Count; ++i)
{
if (memoryStats->VertexBuffers[i].Count > 0)
{
std::cout << "--- All " << bufferStrings[i + renoir::domains::IB_Count] << "s ---" << std::endl;
}
for (size_t j = 0; j < memoryStats->VertexBuffers[i].Count; ++j)
{
std::cout << "ID: " << memoryStats->VertexBuffers[i].Array[j].Id << "; Size: " << memoryStats->VertexBuffers[i].Array[j].Size << " bytes" << "; Peak: " << memoryStats->VertexBuffers[i].Array[j].Peak << " bytes" << std::endl;
}
}
// All Constant Buffers
for (size_t i = 0; i < renoir::CB_Count; ++i)
{
if (memoryStats->ConstantBuffers[i].Count > 0)
{
std::cout << "--- All " << bufferStrings[i + renoir::domains::IB_Count + renoir::domains::VB_Count] << "s ---" << std::endl;
}
for (size_t j = 0; j < memoryStats->ConstantBuffers[i].Count; ++j)
{
std::cout << "ID: " << memoryStats->ConstantBuffers[i].Array[j].Id << "; Size: " << memoryStats->ConstantBuffers[i].Array[j].Size << " bytes" << std::endl;
}
}
}
}
auto viewMemoryStats = m_CohtmlApp->GetView()->GetGPUMemoryStats();
auto libraryMemoryStats = m_CohtmlApp->GetLibrary()->GetGPUMemoryStats();
std::cout << "View stats: " << std::endl;
PrintGPUMemoryStats(viewMemoryStats);
std::cout << "Library stats: " << std::endl;
PrintGPUMemoryStats(libraryMemoryStats);
viewMemoryStats->Release();
libraryMemoryStats->Release();