* GPU Memory: basic tree view of pools + heaps * GPU Memory: pie charts of overall heap usage * GPU Memory: Implement tabular view * GPU Memory: final cleanup * GPU Memory: use AZ_ENUM macro for string conversion Signed-off-by: Jacob Hilliard <jhlliar@amazon.com>
This commit is contained in:
@@ -10,6 +10,8 @@
|
||||
|
||||
#include <Atom/RHI.Reflect/Format.h>
|
||||
#include <Atom/RHI.Reflect/AttachmentEnums.h>
|
||||
|
||||
#include <AzCore/Preprocessor/Enum.h>
|
||||
#include <AzCore/Utils/TypeHash.h>
|
||||
|
||||
namespace AZ
|
||||
@@ -22,47 +24,44 @@ namespace AZ
|
||||
* A set of combinable flags which inform the system how a buffer is to be
|
||||
* bound to the pipeline at all stages of its lifetime.
|
||||
*/
|
||||
enum class BufferBindFlags : uint32_t
|
||||
{
|
||||
None = 0,
|
||||
AZ_ENUM_CLASS_WITH_UNDERLYING_TYPE(BufferBindFlags, uint32_t,
|
||||
(None , 0),
|
||||
|
||||
/// Supports input assembly access through a IndexBufferView or StreamBufferView. This flag is for buffers that are not updated often
|
||||
InputAssembly = AZ_BIT(0),
|
||||
(InputAssembly , AZ_BIT(0)),
|
||||
|
||||
/// Supports input assembly access through a IndexBufferView or StreamBufferView. This flag is for buffers that are updated frequently
|
||||
DynamicInputAssembly = AZ_BIT(1),
|
||||
(DynamicInputAssembly , AZ_BIT(1)),
|
||||
|
||||
/// Supports constant access through a ShaderResourceGroup.
|
||||
Constant = AZ_BIT(2),
|
||||
(Constant , AZ_BIT(2)),
|
||||
|
||||
/// Supports read access through a ShaderResourceGroup.
|
||||
ShaderRead = AZ_BIT(3),
|
||||
(ShaderRead , AZ_BIT(3)),
|
||||
|
||||
/// Supports write access through ShaderResourceGroup.
|
||||
ShaderWrite = AZ_BIT(4),
|
||||
(ShaderWrite , AZ_BIT(4)),
|
||||
|
||||
/// Supports read-write access through a ShaderResourceGroup.
|
||||
ShaderReadWrite = ShaderRead | ShaderWrite,
|
||||
(ShaderReadWrite , ShaderRead | ShaderWrite),
|
||||
|
||||
/// Supports read access for GPU copy operations.
|
||||
CopyRead = AZ_BIT(5),
|
||||
(CopyRead , AZ_BIT(5)),
|
||||
|
||||
/// Supports write access for GPU copy operations.
|
||||
CopyWrite = AZ_BIT(6),
|
||||
(CopyWrite , AZ_BIT(6)),
|
||||
|
||||
/// Supports predication access for conditional rendering.
|
||||
Predication = AZ_BIT(7),
|
||||
(Predication , AZ_BIT(7)),
|
||||
|
||||
/// Supports indirect buffer access for indirect draw/dispatch.
|
||||
Indirect = AZ_BIT(8),
|
||||
(Indirect , AZ_BIT(8)),
|
||||
|
||||
/// Supports ray tracing acceleration structure usage.
|
||||
RayTracingAccelerationStructure = AZ_BIT(9),
|
||||
(RayTracingAccelerationStructure , AZ_BIT(9)),
|
||||
|
||||
/// Supports ray tracing shader table usage.
|
||||
RayTracingShaderTable = AZ_BIT(10)
|
||||
|
||||
};
|
||||
(RayTracingShaderTable , AZ_BIT(10)));
|
||||
|
||||
AZ_DEFINE_ENUM_BITWISE_OPERATORS(AZ::RHI::BufferBindFlags);
|
||||
|
||||
|
||||
@@ -9,43 +9,43 @@
|
||||
|
||||
#include <Atom/RHI.Reflect/Base.h>
|
||||
|
||||
#include <AzCore/Preprocessor/Enum.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace RHI
|
||||
{
|
||||
//! A set of combinable flags which inform the system how an image is to be
|
||||
//! bound to the pipeline at all stages of its lifetime.
|
||||
enum class ImageBindFlags : uint32_t
|
||||
{
|
||||
None = 0,
|
||||
AZ_ENUM_CLASS_WITH_UNDERLYING_TYPE(ImageBindFlags, uint32_t,
|
||||
(None, 0),
|
||||
|
||||
/// Supports read access through a ShaderResourceGroup.
|
||||
ShaderRead = AZ_BIT(0),
|
||||
(ShaderRead, AZ_BIT(0)),
|
||||
|
||||
/// Supports write access through a ShaderResourceGroup.
|
||||
ShaderWrite = AZ_BIT(1),
|
||||
(ShaderWrite, AZ_BIT(1)),
|
||||
|
||||
/// Supports read-write access through a ShaderResourceGroup.
|
||||
ShaderReadWrite = ShaderRead | ShaderWrite,
|
||||
(ShaderReadWrite, ShaderRead | ShaderWrite),
|
||||
|
||||
/// Supports use as a color attachment on a scope.
|
||||
Color = AZ_BIT(2),
|
||||
(Color, AZ_BIT(2)),
|
||||
|
||||
/// Supports use as depth attachment on a scope.
|
||||
Depth = AZ_BIT(3),
|
||||
(Depth, AZ_BIT(3)),
|
||||
|
||||
/// Supports use as stencil attachment on a scope.
|
||||
Stencil = AZ_BIT(4),
|
||||
(Stencil, AZ_BIT(4)),
|
||||
|
||||
/// Supports use as a depth stencil attachment on a scope.
|
||||
DepthStencil = Depth | Stencil,
|
||||
(DepthStencil, Depth | Stencil),
|
||||
|
||||
/// Supports read access for GPU copy operations.
|
||||
CopyRead = AZ_BIT(5),
|
||||
(CopyRead, AZ_BIT(5)),
|
||||
|
||||
/// Supports write access for GPU copy operations.
|
||||
CopyWrite = AZ_BIT(6),
|
||||
};
|
||||
(CopyWrite, AZ_BIT(6)));
|
||||
|
||||
AZ_DEFINE_ENUM_BITWISE_OPERATORS(AZ::RHI::ImageBindFlags);
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ namespace AZ
|
||||
void ModifyFrameSchedulerStatisticsFlags(RHI::FrameSchedulerStatisticsFlags statisticsFlags, bool enableFlags) override;
|
||||
const RHI::CpuTimingStatistics* GetCpuTimingStatistics() const override;
|
||||
const RHI::TransientAttachmentStatistics* GetTransientAttachmentStatistics() const override;
|
||||
const RHI::MemoryStatistics* GetMemoryStatistics() const override;
|
||||
const RHI::TransientAttachmentPoolDescriptor* GetTransientAttachmentPoolDescriptor() const override;
|
||||
ConstPtr<PlatformLimitsDescriptor> GetPlatformLimitsDescriptor() const override;
|
||||
void QueueRayTracingShaderTableForBuild(RayTracingShaderTable* rayTracingShaderTable) override;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <AzCore/Name/Name.h>
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
#include <Atom/RHI.Reflect/FrameSchedulerEnums.h>
|
||||
#include <Atom/RHI.Reflect/MemoryStatistics.h>
|
||||
#include <Atom/RHI/DrawListTagRegistry.h>
|
||||
|
||||
namespace AZ
|
||||
@@ -55,6 +56,8 @@ namespace AZ
|
||||
|
||||
virtual const RHI::TransientAttachmentStatistics* GetTransientAttachmentStatistics() const = 0;
|
||||
|
||||
virtual const RHI::MemoryStatistics* GetMemoryStatistics() const = 0;
|
||||
|
||||
virtual const RHI::TransientAttachmentPoolDescriptor* GetTransientAttachmentPoolDescriptor() const = 0;
|
||||
|
||||
virtual ConstPtr<PlatformLimitsDescriptor> GetPlatformLimitsDescriptor() const = 0;
|
||||
|
||||
@@ -281,6 +281,11 @@ namespace AZ
|
||||
return m_frameScheduler.GetTransientAttachmentStatistics();
|
||||
}
|
||||
|
||||
const RHI::MemoryStatistics* RHISystem::GetMemoryStatistics() const
|
||||
{
|
||||
return m_frameScheduler.GetMemoryStatistics();
|
||||
}
|
||||
|
||||
const AZ::RHI::TransientAttachmentPoolDescriptor* RHISystem::GetTransientAttachmentPoolDescriptor() const
|
||||
{
|
||||
return m_frameScheduler.GetTransientAttachmentPoolDescriptor();
|
||||
|
||||
@@ -23,7 +23,11 @@ namespace AZ
|
||||
namespace RHI
|
||||
{
|
||||
class ScopeAttachment;
|
||||
enum class BufferBindFlags : uint32_t;
|
||||
// NOTE: see BufferDescriptor.h, AZ_ENUM... macro wraps enum within an outer inline namespace.
|
||||
inline namespace BufferBindFlagsNamespace
|
||||
{
|
||||
enum class BufferBindFlags : uint32_t;
|
||||
}
|
||||
class BufferView;
|
||||
class ImageView;
|
||||
struct BufferSubresourceRange;
|
||||
|
||||
@@ -8,9 +8,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Atom/RHI.Reflect/MemoryStatistics.h>
|
||||
#include <Atom/RPI.Public/GpuQuery/GpuQueryTypes.h>
|
||||
|
||||
#include <AzCore/Name/Name.h>
|
||||
#include <AzCore/std/containers/array.h>
|
||||
#include <AzCore/std/containers/variant.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
|
||||
namespace AZ
|
||||
@@ -250,6 +253,44 @@ namespace AZ
|
||||
|
||||
};
|
||||
|
||||
class ImGuiGpuMemoryView
|
||||
{
|
||||
public:
|
||||
// Draw the overall GPU memory profiling window.
|
||||
void DrawGpuMemoryWindow(bool& draw);
|
||||
|
||||
private:
|
||||
// Draw the heap usage pie chart
|
||||
void DrawPieChart(const AZ::RHI::MemoryStatistics::Heap& heap);
|
||||
|
||||
// Update the saved pointers in m_tableRows according to new data/filters
|
||||
void UpdateTableRows();
|
||||
|
||||
void DrawTable();
|
||||
|
||||
// Sort the table according to the appropriate column.
|
||||
void SortTable(ImGuiTableSortSpecs* sortSpecs);
|
||||
|
||||
struct TableRow
|
||||
{
|
||||
Name m_parentPoolName;
|
||||
Name m_bufImgName;
|
||||
size_t m_sizeInBytes = 0;
|
||||
AZStd::string m_bindFlags;
|
||||
};
|
||||
|
||||
// Table settings
|
||||
bool m_includeBuffers = true;
|
||||
bool m_includeImages = true;
|
||||
bool m_includeTransientAttachments = true;
|
||||
|
||||
ImGuiTextFilter m_nameFilter;
|
||||
|
||||
AZStd::vector<TableRow> m_tableRows;
|
||||
AZStd::vector<AZ::RHI::MemoryStatistics::Pool> m_savedPools;
|
||||
AZStd::vector<AZ::RHI::MemoryStatistics::Heap> m_savedHeaps;
|
||||
};
|
||||
|
||||
class ImGuiGpuProfiler
|
||||
{
|
||||
public:
|
||||
@@ -275,9 +316,11 @@ namespace AZ
|
||||
|
||||
bool m_drawTimestampView = false;
|
||||
bool m_drawPipelineStatisticsView = false;
|
||||
bool m_drawGpuMemoryView = false;
|
||||
|
||||
ImGuiTimestampView m_timestampView;
|
||||
ImGuiPipelineStatisticsView m_pipelineStatisticsView;
|
||||
ImGuiGpuMemoryView m_gpuMemoryView;
|
||||
};
|
||||
} //namespace Render
|
||||
} // namespace AZ
|
||||
|
||||
@@ -6,12 +6,15 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Atom/RHI/RHISystemInterface.h>
|
||||
#include <Atom/RPI.Public/Pass/ParentPass.h>
|
||||
#include <Atom/RPI.Public/Pass/RenderPass.h>
|
||||
#include <Atom/RPI.Public/RenderPipeline.h>
|
||||
#include <Atom/RPI.Public/RPISystemInterface.h>
|
||||
#include <Atom/RPI.Public/Scene.h>
|
||||
|
||||
#include <AzCore/std/sort.h>
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
namespace AZ
|
||||
@@ -87,6 +90,38 @@ namespace AZ
|
||||
}
|
||||
drawList->AddText(font, font->FontSize, pos, ImGui::GetColorU32(ImGuiCol_Text), text, nullptr, size.x);
|
||||
}
|
||||
|
||||
inline static AZStd::string GetImageBindStrings(AZ::RHI::ImageBindFlags imageBindFlags)
|
||||
{
|
||||
AZStd::string imageBindStrings;
|
||||
for (const auto& flag : AZ::RHI::ImageBindFlagsMembers)
|
||||
{
|
||||
if (flag.m_value != AZ::RHI::ImageBindFlags::None && AZ::RHI::CheckBitsAll(imageBindFlags, flag.m_value))
|
||||
{
|
||||
imageBindStrings.append(flag.m_string);
|
||||
imageBindStrings.append(", ");
|
||||
}
|
||||
}
|
||||
return imageBindStrings;
|
||||
}
|
||||
|
||||
inline static AZStd::string GetBufferBindStrings(AZ::RHI::BufferBindFlags bufferBindFlags)
|
||||
{
|
||||
AZStd::string bufferBindStrings;
|
||||
for (const auto& flag : AZ::RHI::BufferBindFlagsMembers)
|
||||
{
|
||||
if (flag.m_value != AZ::RHI::BufferBindFlags::None && AZ::RHI::CheckBitsAll(bufferBindFlags, flag.m_value))
|
||||
{
|
||||
bufferBindStrings.append(flag.m_string);
|
||||
bufferBindStrings.append(", ");
|
||||
}
|
||||
}
|
||||
return bufferBindStrings;
|
||||
}
|
||||
|
||||
static constexpr u64 KB = 1024;
|
||||
static constexpr u64 MB = 1024 * KB;
|
||||
static constexpr u64 GB = 1024 * MB;
|
||||
} // namespace GpuProfilerImGuiHelper
|
||||
|
||||
// --- PassEntry ---
|
||||
@@ -1025,6 +1060,219 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
// --- ImGuiGpuMemoryView ---
|
||||
|
||||
inline void ImGuiGpuMemoryView::SortTable(ImGuiTableSortSpecs* sortSpecs)
|
||||
{
|
||||
const bool ascending = sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending;
|
||||
const ImS16 columnToSort = sortSpecs->Specs->ColumnIndex;
|
||||
|
||||
// Sort by the appropriate column in the table
|
||||
switch (columnToSort)
|
||||
{
|
||||
case (0): // Sorting by parent pool name
|
||||
AZStd::sort(m_tableRows.begin(), m_tableRows.end(),
|
||||
[ascending](const TableRow& lhs, const TableRow& rhs)
|
||||
{
|
||||
const auto lhsParentPool = lhs.m_parentPoolName.GetStringView();
|
||||
const auto rhsParentPool = rhs.m_parentPoolName.GetStringView();
|
||||
return ascending ? lhsParentPool < rhsParentPool : lhsParentPool > rhsParentPool;
|
||||
});
|
||||
break;
|
||||
case (1): // Sort by buffer/image name
|
||||
AZStd::sort(m_tableRows.begin(), m_tableRows.end(),
|
||||
[ascending](const TableRow& lhs, const TableRow& rhs)
|
||||
{
|
||||
const auto lhsName = lhs.m_bufImgName.GetStringView();
|
||||
const auto rhsName = rhs.m_bufImgName.GetStringView();
|
||||
return ascending ? lhsName < rhsName : lhsName > rhsName;
|
||||
});
|
||||
break;
|
||||
case (2): // Sort by memory usage
|
||||
AZStd::sort(m_tableRows.begin(), m_tableRows.end(),
|
||||
[ascending](const TableRow& lhs, const TableRow& rhs)
|
||||
{
|
||||
const float lhsSize = lhs.m_sizeInBytes;
|
||||
const float rhsSize = rhs.m_sizeInBytes;
|
||||
return ascending ? lhsSize < rhsSize : lhsSize > rhsSize;
|
||||
});
|
||||
break;
|
||||
}
|
||||
sortSpecs->SpecsDirty = false;
|
||||
}
|
||||
|
||||
inline void ImGuiGpuMemoryView::DrawTable()
|
||||
{
|
||||
if (ImGui::BeginTable("Table", 4, ImGuiTableFlags_Borders | ImGuiTableFlags_Sortable | ImGuiTableFlags_Resizable))
|
||||
{
|
||||
ImGui::TableSetupColumn("Parent pool");
|
||||
ImGui::TableSetupColumn("Name");
|
||||
ImGui::TableSetupColumn("Size (MB)", 0, 100.0f);
|
||||
ImGui::TableSetupColumn("BindFlags", ImGuiTableColumnFlags_NoSort);
|
||||
ImGui::TableHeadersRow();
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGuiTableSortSpecs* sortSpecs = ImGui::TableGetSortSpecs();
|
||||
if (sortSpecs && sortSpecs->SpecsDirty)
|
||||
{
|
||||
SortTable(sortSpecs);
|
||||
}
|
||||
|
||||
// Draw each row in the table
|
||||
for (const auto& tableRow : m_tableRows)
|
||||
{
|
||||
// Don't draw the row if none of the row's text fields pass the filter
|
||||
if (!m_nameFilter.PassFilter(tableRow.m_parentPoolName.GetCStr())
|
||||
&& !m_nameFilter.PassFilter(tableRow.m_bufImgName.GetCStr())
|
||||
&& !m_nameFilter.PassFilter(tableRow.m_bindFlags.c_str()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ImGui::Text(tableRow.m_parentPoolName.GetCStr());
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text(tableRow.m_bufImgName.GetCStr());
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%.2f", 1.0f * tableRow.m_sizeInBytes / GpuProfilerImGuiHelper::MB);
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text(tableRow.m_bindFlags.c_str());
|
||||
ImGui::TableNextColumn();
|
||||
}
|
||||
}
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
inline void ImGuiGpuMemoryView::UpdateTableRows()
|
||||
{
|
||||
// Update the table according to the latest filters applied
|
||||
m_tableRows.clear();
|
||||
for (const auto& pool : m_savedPools)
|
||||
{
|
||||
Name poolName = pool.m_name.IsEmpty() ? Name("Unnamed pool") : pool.m_name;
|
||||
|
||||
// Ignore transient pools
|
||||
if (!m_includeTransientAttachments && pool.m_name.GetStringView().contains("Transient"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (m_includeBuffers)
|
||||
{
|
||||
for (const auto& buf : pool.m_buffers)
|
||||
{
|
||||
const Name bufName = buf.m_name.IsEmpty() ? Name("Unnamed Buffer") : buf.m_name;
|
||||
const AZStd::string flags = GpuProfilerImGuiHelper::GetBufferBindStrings(buf.m_bindFlags);
|
||||
m_tableRows.push_back({ poolName, bufName, buf.m_sizeInBytes, flags });
|
||||
}
|
||||
}
|
||||
|
||||
if (m_includeImages)
|
||||
{
|
||||
for (const auto& img : pool.m_images)
|
||||
{
|
||||
const Name imgName = img.m_name.IsEmpty() ? Name("Unnamed Image") : img.m_name;
|
||||
const AZStd::string flags = GpuProfilerImGuiHelper::GetImageBindStrings(img.m_bindFlags);
|
||||
m_tableRows.push_back({ poolName, imgName, img.m_sizeInBytes, flags });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void ImGuiGpuMemoryView::DrawPieChart(const AZ::RHI::MemoryStatistics::Heap& heap)
|
||||
{
|
||||
if (ImGui::BeginChild("PieChart", {150, 150}, true))
|
||||
{
|
||||
ImDrawList* drawList = ImGui::GetWindowDrawList();
|
||||
const auto [wx, wy] = ImGui::GetWindowPos();
|
||||
const auto [windowWidth, windowHeight] = ImGui::GetWindowSize();
|
||||
const ImVec2 center = { wx + windowWidth / 2, wy + windowHeight / 2 };
|
||||
const float radius = windowWidth / 2 - 10;
|
||||
|
||||
// Draw the pie chart
|
||||
drawList->AddCircleFilled(center, radius, ImGui::GetColorU32({.3, .3, .3, 1}));
|
||||
const float usagePercent = 1.0f * heap.m_memoryUsage.m_residentInBytes / heap.m_memoryUsage.m_budgetInBytes;
|
||||
drawList->PathArcTo(center, radius, 0, AZ::Constants::TwoPi * usagePercent); // Clockwise starting from rightmost point
|
||||
drawList->PathArcTo(center, 0, 0, 0); // To center
|
||||
drawList->PathArcTo(center, radius, 0, 0); // Back to starting position
|
||||
drawList->PathFillConvex(ImGui::GetColorU32({ .039, .8, 0.556, 1 }));
|
||||
ImGui::Text("%.2f%%", usagePercent * 100);
|
||||
}
|
||||
ImGui::EndChild();
|
||||
}
|
||||
|
||||
inline void ImGuiGpuMemoryView::DrawGpuMemoryWindow(bool& draw)
|
||||
{
|
||||
// Enable GPU memory instrumentation while the window is open. Called every draw frame, but just a bitwise operation so overhead should be low.
|
||||
auto* rhiSystem = AZ::RHI::RHISystemInterface::Get();
|
||||
AZ_Assert(rhiSystem != nullptr, "Error in drawing GPU memory window: RHI System Interface was nullptr");
|
||||
rhiSystem->ModifyFrameSchedulerStatisticsFlags(AZ::RHI::FrameSchedulerStatisticsFlags::GatherMemoryStatistics, draw);
|
||||
|
||||
if (!draw)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui::SetNextWindowSize({ 600, 600 }, ImGuiCond_Once);
|
||||
if (ImGui::Begin("Gpu Memory Profiler", &draw, ImGuiViewportFlags_None))
|
||||
{
|
||||
if (ImGui::Button("Capture"))
|
||||
{
|
||||
// Collect and save new GPU memory usage data
|
||||
const auto* memoryStatistics = rhiSystem->GetMemoryStatistics();
|
||||
if (memoryStatistics)
|
||||
{
|
||||
m_tableRows.clear();
|
||||
m_savedPools = memoryStatistics->m_pools;
|
||||
m_savedHeaps = memoryStatistics->m_heaps;
|
||||
|
||||
// Collect the data into TableRows, ignoring depending on flags
|
||||
UpdateTableRows();
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::Checkbox("Show buffers", &m_includeBuffers)
|
||||
|| ImGui::Checkbox("Show images", &m_includeImages)
|
||||
|| ImGui::Checkbox("Show transient attachments", &m_includeTransientAttachments))
|
||||
{
|
||||
UpdateTableRows();
|
||||
}
|
||||
|
||||
ImGui::Text("Overall heap usage:");
|
||||
for (const auto& savedHeap : m_savedHeaps)
|
||||
{
|
||||
if (ImGui::BeginChild(savedHeap.m_name.GetCStr(), { ImGui::GetWindowWidth() / m_savedHeaps.size(), 250 }), ImGuiWindowFlags_NoScrollbar)
|
||||
{
|
||||
ImGui::Text(savedHeap.m_name.GetCStr());
|
||||
ImGui::Columns(2, "HeapData", true);
|
||||
|
||||
ImGui::Text("Resident (MB): ");
|
||||
ImGui::NextColumn();
|
||||
ImGui::Text("%.2f", 1.0 * savedHeap.m_memoryUsage.m_residentInBytes.load() / GpuProfilerImGuiHelper::MB);
|
||||
ImGui::NextColumn();
|
||||
|
||||
ImGui::Text("Reserved (MB): ");
|
||||
ImGui::NextColumn();
|
||||
ImGui::Text("%.2f", 1.0 * savedHeap.m_memoryUsage.m_reservedInBytes.load() / GpuProfilerImGuiHelper::MB);
|
||||
ImGui::NextColumn();
|
||||
|
||||
ImGui::Text("Budget (MB): ");
|
||||
ImGui::NextColumn();
|
||||
ImGui::Text("%.2f", 1.0 * savedHeap.m_memoryUsage.m_budgetInBytes / GpuProfilerImGuiHelper::MB);
|
||||
|
||||
ImGui::Columns(1, "PieChartColumn");
|
||||
DrawPieChart(savedHeap);
|
||||
}
|
||||
ImGui::EndChild();
|
||||
ImGui::SameLine(ImGui::GetWindowWidth() / m_savedHeaps.size());
|
||||
}
|
||||
ImGui::NewLine();
|
||||
ImGui::Separator();
|
||||
|
||||
m_nameFilter.Draw("Search");
|
||||
DrawTable();
|
||||
}
|
||||
}
|
||||
|
||||
// --- ImGuiGpuProfiler ---
|
||||
|
||||
inline void ImGuiGpuProfiler::Draw(bool& draw, RHI::Ptr<RPI::ParentPass> rootPass)
|
||||
@@ -1045,6 +1293,8 @@ namespace AZ
|
||||
{
|
||||
rootPass->SetPipelineStatisticsQueryEnabled(m_drawPipelineStatisticsView);
|
||||
}
|
||||
ImGui::Spacing();
|
||||
ImGui::Checkbox("Enable GpuMemoryView", &m_drawGpuMemoryView);
|
||||
});
|
||||
|
||||
// Draw the PipelineStatistics window.
|
||||
@@ -1053,6 +1303,9 @@ namespace AZ
|
||||
// Draw the PipelineStatistics window.
|
||||
m_pipelineStatisticsView.DrawPipelineStatisticsWindow(m_drawPipelineStatisticsView, rootPassEntryRef, m_passEntryDatabase, rootPass);
|
||||
|
||||
// Draw the GpuMemory window.
|
||||
m_gpuMemoryView.DrawGpuMemoryWindow(m_drawGpuMemoryView);
|
||||
|
||||
//closing window
|
||||
if (wasDraw && !draw)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user