Home Integration Optional features GPU Memory Tracking 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 Library
and the ability to reset the GPU memory peaks. That makes it easier to check the memory statistics of the allocated resources.
NOTE This API is only available in a Developer configuration.
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.
We have developed a structure to hold the GPU memory data called GPUMemoryInfo
, which can be filled with all the tracked information using the help of the GetGPUMemoryStats()
method found in the Library
. As for user textures, which are tracked separately from the rest of the GPU memory, the cohtml::UserGPUMemoryInfo* Library::GetUserGPUMemoryStats()
method can be used to retrieve their information, which is encapsulated in a different structure called UserGPUMemoryInfo
. The GPUMemoryInfo::Release()
method must be called on the returned cohtml::GPUMemoryInfo*
or cohtml::UserGPUMemoryInfo*
pointer to free its allocated memory. The statistics from the Library
include all shared resources across the View
s. A list of every member in the GPUMemoryInfo
and UserGPUMemoryInfo
structures along with a description of what each member 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 Library
needs to be invoked. Resetting the peaks of the Library
will also reset the user textures' peaks.
A list of all the monitored GPU memory data # >
All GPU memory is tracked in bytes .
GPUMemoryInfo
structure # Member Description size_t TotalBytes;
The total GPU memory size_t PeakBytes;
The highest GPU memory reached TextureInfo TexturesInformation[renoir::domains::TextureType::TT_Count];
An array of TextureInfo
objects containing all tracked textures' information separated by their TextureType
BufferInfo BuffersInformation[renoir::domains::BufferType::BT_Count];
An array of BufferInfo
objects containing all tracked buffers' information separated by their BufferType
ExtraColorImageTexturesInfo ExtraColorImageTexturesInformation;
An array of additional information about the texture, like it’s name and which views it is used in. The ArraySize
member is equal to TexturesInformation[renoir::domains::TextureType::TT_ColorTexture].ResourceArray[renoir::domains::TextureDomain::T_ImageTexture].ArraySize
, so the index used to iterate the image color textures can be directly used to iterate the extra information.
In-depth description of TexturesInformation
’s members # Member Description TexturesInformation[TextureType]
Texture statistics by TextureType
. Array size is TextureType::TT_Count
TexturesInformation[TextureType].Total.Bytes
The total GPU memory of all textures from the specified TextureType
TexturesInformation[TextureType].Total.Count
The count of all current textures from the specified TextureType
TexturesInformation[TextureType].Peak.Bytes
The highest reached GPU memory of all textures from the specified TextureType
TexturesInformation[TextureType].Peak.Count
The highest reached count of all textures from the specified TextureType
TexturesInformation[TextureType].ResourceArray[TextureDomain]
Texture statistics by TextureDomain
. Array size is TextureDomain::T_Count
TexturesInformation[TextureType].ResourceArray[TextureDomain].Total.Bytes
The total GPU memory of all textures from the specified TextureDomain
and TextureType
TexturesInformation[TextureType].ResourceArray[TextureDomain].Total.Count
The count of all current textures from the specified TextureDomain
and TextureType
TexturesInformation[TextureType].ResourceArray[TextureDomain].Peak.Bytes
The highest reached GPU memory of all textures from the specified TextureDomain
and TextureType
TexturesInformation[TextureType].ResourceArray[TextureDomain].Peak.Count
The highest reached count of all textures from the specified TextureDomain
and TextureType
TexturesInformation[TextureType].ResourceArray[TextureDomain].Array
Texture statistics of all current textures from the specified TextureDomain
and TextureType
TexturesInformation[TextureType].ResourceArray[TextureDomain].ArraySize
The Array
size. Same as TexturesInformation[TextureType].ResourceArray[TextureDomain].Total.Count
TexturesInformation[TextureType].ResourceArray[TextureDomain].Array[ind].Id
The texture’s ID TexturesInformation[TextureType].ResourceArray[TextureDomain].Array[ind].Bytes
The texture’s size TexturesInformation[TextureType].ResourceArray[TextureDomain].Array[ind].OwnerId
The texture’s scene ID. If it instead belongs to the Library
, the ID will equal unsigned(-1)
aka RENOIR_INVALID
Member Description BuffersInformation[BufferType]
Buffer statistics by BufferType
. Array size is BufferType::BT_Count
BuffersInformation[BufferType].Total.Bytes
The total GPU memory of all buffers from the specified BufferType
BuffersInformation[BufferType].Total.Count
The count of all current buffers from the specified BufferType
BuffersInformation[BufferType].Peak.Bytes
The highest reached GPU memory of all buffers from the specified BufferType
BuffersInformation[BufferType].Peak.Count
The highest reached count of all buffers from the specified BufferType
BuffersInformation[BufferType].ResourceArray[MAX_BUFFER_DOMAIN_COUNT]
Buffer statistics by domain for the specified BufferType
. Size is indicated by the buffer domain’s count (IB_Count
, VB_Count
, CB_Count
) BuffersInformation[BufferType].ResourceArray[BufferDomain].Total.Bytes
The total GPU memory of all buffers from the specified BufferDomain
and BufferType
BuffersInformation[BufferType].ResourceArray[BufferDomain].Total.Count
The count of all current buffers from the specified BufferDomain
and BufferType
BuffersInformation[BufferType].ResourceArray[BufferDomain].Peak.Bytes
The highest reached allocated GPU memory of all buffers from the specified BufferDomain
and BufferType
BuffersInformation[BufferType].ResourceArray[BufferDomain].Peak.Count
The highest reached count of all buffers from the specified BufferDomain
and BufferType
BuffersInformation[BufferType].ResourceArray[BufferDomain].Array
Buffer statistics of all current buffers from the specified BufferDomain
and BufferType
BuffersInformation[BufferType].ResourceArray[BufferDomain].ArraySize
The Array
size. Same as TexturesInformation[TextureType].ResourceArray[TextureDomain].Total.Count
BuffersInformation[BufferType].ResourceArray[BufferDomain].Array[ind].Id
The buffer’s ID BuffersInformation[BufferType].ResourceArray[BufferDomain].Array[ind].Bytes
The buffer’s allocated size BuffersInformation[BufferType].ResourceArray[BufferDomain].Array[ind].PeakUsageBytes
The highest amount of bytes used from the buffer’s allocated memory BuffersInformation[BufferType].ResourceArray[BufferDomain].Array[ind].OwnerId
The buffer’s scene ID. If it instead belongs to the Library
, the ID will equal unsigned(-1)
aka RENOIR_INVALID
Member Description ExtraColorImageTexturesInformation.Array[ind].Name
The name of the texture ExtraColorImageTexturesInformation.Array[ind].ViewClientsCount
The total amount of views this texture is registered in ExtraColorImageTexturesInformation.Array[ind].ViewClients
The array of views this texture is registered in
UserGPUMemoryInfo
structure # Member Description UserTexturesInfo UserTextureInformation
Contains information for all tracked user textures RenderTargetInfo RenderTargetInformation[renoir::domains::TextureType::TT_Count]
An array of RenderTargetInfo
objects containing all tracked render targets' information separated by their TextureType
ExtraUserImageInfo ExtraUserImageInformation
Contains additional information about an image, such as it’s name and how many views it is used in
In-depth description of the UserTexturesInfo
’s members # Member Description GPUMemoryInfo::MemoryInfo TotalUsage
Total GPU memory used by user images GPUMemoryInfo::MemoryInfo PeakUsage
Peak GPU memory used by user images GPUMemoryInfo::MemoryInfo Total
Total GPU memory used by user objects (explanation here) GPUMemoryInfo::MemoryInfo Peak
Peak GPU memory used by user objects (explanation here) size_t ArraySize
Size of Array
UserTextureInformation.Array[ind].Id
The user texture’s ID UserTextureInformation.Array[ind].OwnerId
The user texture’s owner. All user textures belong to the Library
, so the ID equals unsigned(-1)
aka RENOIR_INVALID
UserTextureInformation.Array[ind].Bytes
The size of the user texture in bytes UserTextureInformation.Array[ind].UserObject
The user object data itself UserTextureInformation.Array[ind].UserObjectBytes
The size of the user object data in bytes
In-depth description of the RenderTargetInfo
’s members # Member Description GPUMemoryInfo::MemoryInfo Total
The total render targets' GPU memory (Total.Bytes
) and their current count (Total.Count
) GPUMemoryInfo::MemoryInfo Peak
The highest reached render targets' GPU memory (Peak.Bytes
) and the hightest reached peaks count (Peak.Count
) size_t ArraySize;
Size of Array
RenderTargetInformation.Array[ind].Id
The render target’s ID RenderTargetInformation.Array[ind].OwnerId
The render target’s owner RenderTargetInformation.Array[ind].Bytes
The size of the render target in bytes RenderTargetInformation.Array[ind].UserObject
The actual data RenderTargetInformation.Array[ind].Width
The width of the render target RenderTargetInformation.Array[ind].Height
The height of the render target RenderTargetInformation.Array[ind].SamplesCount
The sample count
Member Description size_t ArraySize;
Size of Array
ExtraUserImageInformation.Array[ind].Name
The name of the user image ExtraUserImageInformation.Array[ind].ViewClientsCount
The total amount of views this user image is registered in ExtraUserImageInformation.Array[ind].ViewClients
The array of views this user image is registered in
Resource domains # namespace domains
{
enum TextureType
{
TT_ColorTexture = 0,
TT_DepthTexture,
TT_Count
};
enum BufferType
{
BT_IndexBuffer = 0,
BT_VertexBuffer,
BT_ConstantBuffer,
BT_Count
};
enum TextureDomain
{
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_DataVS,
// Pixel shader CBs
CB_DataPS,
CB_Count
};
}
Below are example functions that show how to display GPU memory information.
void PrintToLog(const cohtml::GPUMemoryInfo* memoryStats)
{
std::ostringstream oss;
oss << "---------- Total GPU Memory Stats ----------" << std::endl;
oss << "\tTotal GPU Memory: " << memoryStats->TotalBytes << " bytes" << std::endl;
oss << "\tPeak GPU Memory: " << memoryStats->PeakBytes << " bytes" << std::endl;
oss << "\t> Main textures memory info:" << std::endl;
oss << "\tTotal color textures memory: " << memoryStats->TexturesInformation[renoir::domains::TT_ColorTexture].Total.Bytes << " bytes" << std::endl;
oss << "\tTotal depth textures memory: " << memoryStats->TexturesInformation[renoir::domains::TT_DepthTexture].Total.Bytes << " bytes" << std::endl;
oss << "\tPeak color textures memory: " << memoryStats->TexturesInformation[renoir::domains::TT_ColorTexture].Peak.Bytes << " bytes" << std::endl;
oss << "\tPeak depth textures memory: " << memoryStats->TexturesInformation[renoir::domains::TT_DepthTexture].Peak.Bytes << " bytes" << std::endl;
oss << "\t> Main buffers memory info:" << std::endl;
oss << "\tTotal Index Buffers memory: " << memoryStats->BuffersInformation[renoir::domains::BT_IndexBuffer].Total.Bytes << " bytes" << std::endl;
oss << "\tTotal Vertex Buffers memory: " << memoryStats->BuffersInformation[renoir::domains::BT_VertexBuffer].Total.Bytes << " bytes" << std::endl;
oss << "\tTotal Constant Buffers memory: " << memoryStats->BuffersInformation[renoir::domains::BT_ConstantBuffer].Total.Bytes << " bytes" << std::endl;
oss << "\tPeak Index Buffers memory: " << memoryStats->BuffersInformation[renoir::domains::BT_IndexBuffer].Peak.Bytes << " bytes" << std::endl;
oss << "\tPeak Vertex Buffers memory: " << memoryStats->BuffersInformation[renoir::domains::BT_VertexBuffer].Peak.Bytes << " bytes" << std::endl;
oss << "\tPeak Constant Buffers memory: " << memoryStats->BuffersInformation[renoir::domains::BT_ConstantBuffer].Peak.Bytes << " bytes" << std::endl;
oss << "\t> Textures count info:" << std::endl;
oss << "\tTotal count of color textures: " << memoryStats->TexturesInformation[renoir::domains::TT_ColorTexture].Total.Count << std::endl;
oss << "\tTotal count of depth textures: " << memoryStats->TexturesInformation[renoir::domains::TT_DepthTexture].Total.Count << std::endl;
oss << "\tPeak count of color textures: " << memoryStats->TexturesInformation[renoir::domains::TT_ColorTexture].Peak.Count << std::endl;
oss << "\tPeak count of depth textures: " << memoryStats->TexturesInformation[renoir::domains::TT_DepthTexture].Peak.Count << std::endl;
oss << "\t> Buffers count info:" << std::endl;
oss << "\tTotal count of Index Buffers: " << memoryStats->BuffersInformation[renoir::domains::BT_IndexBuffer].Total.Count << std::endl;
oss << "\tTotal count of Vertex Buffers: " << memoryStats->BuffersInformation[renoir::domains::BT_VertexBuffer].Total.Count << std::endl;
oss << "\tTotal count of Constant Buffers: " << memoryStats->BuffersInformation[renoir::domains::BT_ConstantBuffer].Total.Count << std::endl;
oss << "\tPeak count of Index Buffers: " << memoryStats->BuffersInformation[renoir::domains::BT_IndexBuffer].Peak.Count << std::endl;
oss << "\tPeak count of Vertex Buffers: " << memoryStats->BuffersInformation[renoir::domains::BT_VertexBuffer].Peak.Count << std::endl;
oss << "\tPeak count of Constant Buffers: " << memoryStats->BuffersInformation[renoir::domains::BT_ConstantBuffer].Peak.Count << std::endl;
const char* textureTypeStrings[] = { "Color", "Depth" };
const char* textureStrings[] = { "Scratch Texture", "Layer Texture", "Image Texture", "Surface Texture", "Compositor Texture", "Glyph Atlase", "Gradient Cache Texture" };
const char* bufferStrings[] = { "Index Geometry Buffer", "Index Path Buffer", "Index Glyph Buffer",
"Vertex Geometry Buffer", "Vertex Path Buffer", "Vertex Path Instance Data Buffer", "Vertex Glyph Buffer",
"VS Data Constant Buffer", "PS Data Constant Buffer" };
APP_LOG(Info, oss.str().c_str());
oss.str("");
for (size_t texType = 0; texType < renoir::domains::TextureType::TT_Count; ++texType)
{
for (size_t texDomain = 0; texDomain < renoir::domains::TextureDomain::T_Count; ++texDomain)
{
oss << "\t> " << textureTypeStrings[texType] << " " << textureStrings[texDomain] << "s:" << std::endl;
auto& domainInfo = memoryStats->TexturesInformation[texType].ResourceArray[texDomain];
oss << "\tTotal memory: " << domainInfo.Total.Bytes << " bytes" << std::endl;
oss << "\tTotal count: " << domainInfo.Total.Count << std::endl;
oss << "\tPeak memory: " << domainInfo.Peak.Bytes << " bytes" << std::endl;
oss << "\tPeak count: " << domainInfo.Peak.Count << std::endl;
for (size_t i = 0; i < domainInfo.ArraySize; i++)
{
oss << "\tID: " << domainInfo.Array[i].Id << "; Owner: ";
if (domainInfo.Array[i].OwnerId == RENOIR_INVALID)
{
oss << "Shared";
}
else
{
oss << domainInfo.Array[i].OwnerId;
}
oss << "; Size: " << domainInfo.Array[i].Bytes << " bytes";
if (texType == renoir::domains::TextureType::TT_ColorTexture &&
texDomain == renoir::domains::TextureDomain::T_ImageTexture &&
memoryStats->ExtraColorImageTexturesInformation.Array[i].Name)
{
oss << "; View client IDs:";
for (size_t viewCount = 0; viewCount < memoryStats->ExtraColorImageTexturesInformation.Array[i].ViewClientsCount; ++viewCount)
{
oss << " " << memoryStats->ExtraColorImageTexturesInformation.Array[i].ViewClients[viewCount];
}
oss << std::endl << "\t\tTexture Name: " << memoryStats->ExtraColorImageTexturesInformation.Array[i].Name << std::endl;
}
else
{
oss << std::endl;
}
}
APP_LOG(Info, oss.str().c_str());
oss.str("");
}
}
for (size_t buffType = 0; buffType < renoir::domains::BufferType::BT_Count; ++buffType)
{
size_t buffDomainSize = buffType == renoir::domains::BufferType::BT_IndexBuffer ? renoir::domains::IB_Count :
buffType == renoir::domains::BufferType::BT_VertexBuffer ? renoir::domains::VB_Count : renoir::CB_Count;
size_t buffStringsStart = buffType == renoir::domains::BufferType::BT_IndexBuffer ? 0 :
buffType == renoir::domains::BufferType::BT_VertexBuffer ? renoir::domains::IB_Count : renoir::domains::IB_Count + renoir::domains::VB_Count;
for (size_t buffDomain = 0; buffDomain < buffDomainSize; buffDomain++)
{
oss << "\t> " << bufferStrings[buffStringsStart + buffDomain] << "s:" << std::endl;
auto& domainInfo = memoryStats->BuffersInformation[buffType].ResourceArray[buffDomain];
oss << "\tTotal memory: " << domainInfo.Total.Bytes << " bytes" << std::endl;
oss << "\tTotal count: " << domainInfo.Total.Count << std::endl;
oss << "\tPeak memory: " << domainInfo.Peak.Bytes << " bytes" << std::endl;
oss << "\tPeak count: " << domainInfo.Peak.Count << std::endl;
for (size_t i = 0; i < domainInfo.ArraySize; i++)
{
oss << "\tID: " << domainInfo.Array[i].Id << "; Owner: ";
if (domainInfo.Array[i].OwnerId == RENOIR_INVALID)
{
oss << "Shared";
}
else
{
oss << domainInfo.Array[i].OwnerId;
}
oss << "; Size: " << domainInfo.Array[i].Bytes << " bytes";
oss << "; Peak usage: " << domainInfo.Array[i].PeakUsageBytes << " bytes" << std::endl;
}
APP_LOG(Info, oss.str().c_str());
oss.str("");
}
}
}
void PrintToLog(const cohtml::UserGPUMemoryInfo* memoryStats)
{
TmpOSStream oss;
oss << "\t---------- User GPU Memory Stats ----------" << std::endl;
oss << "\tTotal GPU Memory: " << memoryStats->Total.Bytes << " bytes" << std::endl;
oss << "\tPeak GPU Memory: " << memoryStats->Peak.Bytes << " bytes" << std::endl;
oss << "\tTotal texture count: " << memoryStats->Total.Count << std::endl;
oss << "\tPeak texture count: " << memoryStats->Peak.Count << std::endl;
if (memoryStats->ArraySize > 0)
{
oss << "\t---------- Textures ----------" << std::endl;
}
for (size_t i = 0; i < memoryStats->ArraySize; i++)
{
const auto& texture = memoryStats->Array[i];
oss << "\tID: " << texture.Id << ";\tSize: " << texture.Bytes << " bytes" << std::endl;
oss << "\tName: " << texture.Name << std::endl;
oss << "\tView Clients Count: " << texture.ViewClientsCount << std::endl;
for (size_t viewCount = 0; viewCount < texture.ViewClientsCount; ++viewCount)
{
oss << "\tView Client Id: " << texture.ViewClients[viewCount] << std::endl;
}
}
APP_LOG(Info, oss.str().c_str());
}
We have already implemented them and they can be used like this
void PrintGPUMemoryStats()
{
auto combinedMemoryStats = m_CohtmlApp->GetLibrary()->GetGPUMemoryStats();
if (combinedMemoryStats)
{
combinedMemoryStats->PrintToLog();
combinedMemoryStats->Release();
}
}
void PrintUserGPUMemoryStats()
{
auto userMemoryStats = m_CohtmlApp->GetLibrary()->GetUserGPUMemoryStats();
if (userMemoryStats)
{
userMemoryStats->PrintToLog();
userMemoryStats->Release();
}
}