Hi,
I have been doing some digging and found a few UDN threads on this topic with answers from Epic regarding the use of rhi.dumpresourcememory:
- [Content removed] “The rhi.DumpResourceMemory is designed to show a total of all memory resources, so it should not be used to take a snapshot of how much memory is in use at a given point in time.”
- [Content removed] (the information is in Japanese, but you can translate this to English by right-clicking the page in Chrome) states: “The information displayed by rhi.dumpresourcememory, such as Nanite.StreamingManager.ClusterPageData, indicates the maximum buffer size. In reality, an appropriate amount of buffer is allocated and used. Due to these behaviors, rhi.dumpresourcememory is not very suitable for measuring the amount of memory used by a process. We recommend using Memory Insights or RDGInsights.”
- [Content removed]
I asked my colleagues and the consensus was that using vendor specific profiling tools (PIX, AMD’s Radeon Memory Visualizer and Nvidia Nsight) can provide more accurate results, with PIX being the preferred tool for DirectX12 projects.
With respect to your question on stat D3D12Resources not matching stat D3D12Memory, could you clarify which numbers don’t match? I did some experiments and found that some resources like UAV Textures and Render Targets report identical numbers and the UAV buffers are off by a few percent. Please see the screenshot below where both stats are enabled:
[Image Removed]
With respect to your question on `stat RHITransientMemory`, I checked the code that’s responsible for calculating these stats (copied below from Engine\Source\Runtime\RHICore\Private\RHICoreTransientResourceCoreAllocator.cpp). Memory Requested is calculated as Buffer Memory Requested + Texture Memory Requested
`void FRHITransientMemoryStats::Submit(uint64 UsedSize)
{
const int32 CreateResourceCount = Textures.CreateCount + Buffers.CreateCount;
const int64 MemoryUsed = UsedSize;
const int64 MemoryRequested = AliasedSize;
const float ToMB = 1.0f / (1024.0f * 1024.0f);
TRACE_COUNTER_SET(TransientResourceCreateCount, CreateResourceCount);
TRACE_COUNTER_SET(TransientTextureCreateCount, Textures.CreateCount);
TRACE_COUNTER_SET(TransientBufferCreateCount, Buffers.CreateCount);
TRACE_COUNTER_SET(TransientMemoryUsed, MemoryUsed);
TRACE_COUNTER_SET(TransientMemoryRequested, MemoryRequested);
CSV_CUSTOM_STAT_GLOBAL(TransientResourceCreateCount, CreateResourceCount, ECsvCustomStatOp::Set);
CSV_CUSTOM_STAT_GLOBAL(TransientMemoryUsedMB, static_cast(MemoryUsed * ToMB) , ECsvCustomStatOp::Set);
CSV_CUSTOM_STAT_GLOBAL(TransientMemoryAliasedMB, static_cast(MemoryRequested * ToMB), ECsvCustomStatOp::Set);
SET_MEMORY_STAT(STAT_RHITransientMemoryUsed, UsedSize);
SET_MEMORY_STAT(STAT_RHITransientMemoryAliased, AliasedSize);
SET_MEMORY_STAT(STAT_RHITransientMemoryRequested, Textures.AllocatedSize + Buffers.AllocatedSize);
SET_MEMORY_STAT(STAT_RHITransientBufferMemoryRequested, Buffers.AllocatedSize);
SET_MEMORY_STAT(STAT_RHITransientTextureMemoryRequested, Textures.AllocatedSize);
SET_DWORD_STAT(STAT_RHITransientTextures, Textures.AllocationCount);
SET_DWORD_STAT(STAT_RHITransientBuffers, Buffers.AllocationCount);
SET_DWORD_STAT(STAT_RHITransientResources, Textures.AllocationCount + Buffers.AllocationCount);
Reset();
}`Hopefully the above helps. Please let me know if you have any further questions.
Thanks,
Sam