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 Viewss, 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.

MemberDescription
size_t TotalGPUMemoryThe total GPU memory
size_t PeakGPUMemoryThe biggest GPU memory reached
size_t TotalTexturesGPUMemoryThe total GPU memory of all textures(including Depth-Stencil)
size_t PeakTexturesGPUMemoryThe maximum reached GPU memory of all textures
size_t TotalIBuffersGPUMemoryThe total GPU memory of all Index Buffers
size_t TotalVBuffersGPUMemoryThe total GPU memory of all Vertex Buffers
size_t TotalCBuffersGPUMemoryThe total GPU memory of all Constant Buffers
size_t PeakIBuffersGPUMemoryThe maximum reached GPU memory of all Index Buffers
size_t PeakVBuffersGPUMemoryThe maximum reached GPU memory of all Vertex Buffers
size_t PeakCBuffersGPUMemoryThe 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();