From ace80633c7b6df2999ab8f7c2a4e8faf05356c7f Mon Sep 17 00:00:00 2001 From: Lukasz Stalmirski Date: Sun, 5 Apr 2026 23:10:48 +0200 Subject: [PATCH 1/3] Add option to control overlay opacity. --- .../imgui_widgets/imgui_breakdown_ex.cpp | 4 ++++ .../imgui_widgets/imgui_histogram_ex.cpp | 14 ++++++++++++-- .../profiler_overlay/lang/en_us.h | 1 + .../profiler_overlay/profiler_overlay.cpp | 17 +++++++++++++++++ .../profiler_overlay/profiler_overlay.h | 2 ++ 5 files changed, 36 insertions(+), 2 deletions(-) diff --git a/VkLayer_profiler_layer/profiler_overlay/imgui_widgets/imgui_breakdown_ex.cpp b/VkLayer_profiler_layer/profiler_overlay/imgui_widgets/imgui_breakdown_ex.cpp index 9dc6ac0e..e19202a3 100644 --- a/VkLayer_profiler_layer/profiler_overlay/imgui_widgets/imgui_breakdown_ex.cpp +++ b/VkLayer_profiler_layer/profiler_overlay/imgui_widgets/imgui_breakdown_ex.cpp @@ -130,6 +130,10 @@ namespace ImGuiX else color = col_base + random(); + ImU32 alpha = ( color & IM_COL32_A_MASK ) >> IM_COL32_A_SHIFT; + alpha *= style.Alpha; + color = ( color & ~IM_COL32_A_MASK ) | ( alpha << IM_COL32_A_SHIFT ); + window->DrawList->AddRectFilled( rect.Min, rect.Max, color ); t0 = t1; diff --git a/VkLayer_profiler_layer/profiler_overlay/imgui_widgets/imgui_histogram_ex.cpp b/VkLayer_profiler_layer/profiler_overlay/imgui_widgets/imgui_histogram_ex.cpp index c4147e4d..f6957a2f 100644 --- a/VkLayer_profiler_layer/profiler_overlay/imgui_widgets/imgui_histogram_ex.cpp +++ b/VkLayer_profiler_layer/profiler_overlay/imgui_widgets/imgui_histogram_ex.cpp @@ -238,11 +238,16 @@ namespace ImGuiX const float x_pos = inner_bb.Min.x + prev_pos; const float y_pos = inner_bb.Min.y + inner_bb.GetHeight() * ( scale_min / ( scale_max - scale_min ) ) - 5.0f; + ImU32 color = data.color; + ImU32 alpha = ( color & IM_COL32_A_MASK ) >> IM_COL32_A_SHIFT; + alpha *= style.Alpha; + color = ( color & ~IM_COL32_A_MASK ) | ( alpha << IM_COL32_A_SHIFT ); + window->DrawList->AddTriangleFilled( { x_pos - 5.0f * g.IO.FontGlobalScale, y_pos }, { x_pos + 5.0f * g.IO.FontGlobalScale, y_pos }, { x_pos, y_pos + 5.0f * g.IO.FontGlobalScale }, - data.color ); + color ); // Check if mouse is over the event const ImRect event_bb( @@ -292,10 +297,15 @@ namespace ImGuiX ( data.flags & HistogramColumnFlags_NoHover ) == 0 && column_bb.ContainsWithPad( g.IO.MousePos, style.TouchExtraPadding ); + ImU32 color = data.color; + ImU32 alpha = ( color & IM_COL32_A_MASK ) >> IM_COL32_A_SHIFT; + alpha *= style.Alpha; + color = ( color & ~IM_COL32_A_MASK ) | ( alpha << IM_COL32_A_SHIFT ); + window->DrawList->AddRectFilled( column_bb.Min, column_bb.Max, - hovered_column ? ColorSaturation( data.color, 1.5f ) : data.color ); + hovered_column ? ColorSaturation( color, 1.5f ) : color ); if( hovered_column ) { diff --git a/VkLayer_profiler_layer/profiler_overlay/lang/en_us.h b/VkLayer_profiler_layer/profiler_overlay/lang/en_us.h index 51e347ee..4a0b9937 100644 --- a/VkLayer_profiler_layer/profiler_overlay/lang/en_us.h +++ b/VkLayer_profiler_layer/profiler_overlay/lang/en_us.h @@ -171,6 +171,7 @@ namespace Profiler inline static constexpr char SamplingMode[] = "Sampling mode"; inline static constexpr char FrameDelimiter[] = "Frame delimiter"; inline static constexpr char InterfaceScale[] = "Interface scale"; + inline static constexpr char InterfaceOpacity[] = "Interface opacity"; inline static constexpr char CollectedFrameCount[] = "Collected frame count"; inline static constexpr char ShowDebugLabels[] = "Show debug labels"; inline static constexpr char ShowShaderCapabilities[] = "Show shader capabilities"; diff --git a/VkLayer_profiler_layer/profiler_overlay/profiler_overlay.cpp b/VkLayer_profiler_layer/profiler_overlay/profiler_overlay.cpp index ee09c5c0..7d443b2f 100644 --- a/VkLayer_profiler_layer/profiler_overlay/profiler_overlay.cpp +++ b/VkLayer_profiler_layer/profiler_overlay/profiler_overlay.cpp @@ -634,6 +634,8 @@ namespace Profiler m_HasNewSnapshots = false; m_pData = nullptr; + + m_Opacity = 0.9f; m_Pause = false; m_Fullscreen = false; m_ShowDebugLabels = true; @@ -925,6 +927,7 @@ namespace Profiler // Begin main window ImGui::PushFont( m_Resources.GetDefaultFont() ); + ImGui::PushStyleVar( ImGuiStyleVar_Alpha, m_Opacity ); ImGui::Begin( m_Title.c_str(), nullptr, mainWindowFlags ); if( !m_Fullscreen ) @@ -1163,6 +1166,7 @@ namespace Profiler pForegroundDrawList->AddCircleFilled( ImGui::GetIO().MousePos, 2.f, 0xffffffff, 4 ); } + ImGui::PopStyleVar(); ImGui::PopFont(); ImGui::Render(); @@ -1185,6 +1189,12 @@ namespace Profiler // Round window corners style.WindowRounding = 7.f; + // Disable default window transparency + for( ImGuiCol col : { ImGuiCol_WindowBg, ImGuiCol_TitleBg, ImGuiCol_TitleBgActive } ) + { + style.Colors[col].w = 1.0f; + } + // Performance graph colors m_RenderPassColumnColor = ImGui::GetColorU32( { 0.9f, 0.7f, 0.0f, 1.0f } ); // #e6b200 m_GraphicsPipelineColumnColor = ImGui::GetColorU32( { 0.9f, 0.7f, 0.0f, 1.0f } ); // #e6b200 @@ -6455,6 +6465,13 @@ namespace Profiler ImGui::GetIO().FontGlobalScale = std::clamp( interfaceScale, 0.25f, 4.0f ); } + // Set interface opacity. + float interfaceOpacity = m_Opacity; + if( ImGui::InputFloat( Lang::InterfaceOpacity, &interfaceOpacity, 0.1f, 0, "%.1f", ImGuiInputTextFlags_CharsDecimal ) ) + { + m_Opacity = std::clamp( interfaceOpacity, 0.1f, 1.0f ); + } + // Set number of collected frames int maxFrameCount = static_cast( m_MaxFrameCount ); if( ImGui::InputInt( Lang::CollectedFrameCount, &maxFrameCount ) ) diff --git a/VkLayer_profiler_layer/profiler_overlay/profiler_overlay.h b/VkLayer_profiler_layer/profiler_overlay/profiler_overlay.h index cc5a9c00..68267400 100644 --- a/VkLayer_profiler_layer/profiler_overlay/profiler_overlay.h +++ b/VkLayer_profiler_layer/profiler_overlay/profiler_overlay.h @@ -160,6 +160,8 @@ namespace Profiler bool m_HasNewSnapshots; std::shared_ptr m_pData; + + float m_Opacity; bool m_Pause; bool m_Fullscreen; bool m_ShowDebugLabels; From d08a14e5ca87763d2473f76f05fa77eec823e6cd Mon Sep 17 00:00:00 2001 From: Lukasz Stalmirski Date: Mon, 6 Apr 2026 09:52:19 +0200 Subject: [PATCH 2/3] Fix sparse residency map rendering. --- .../imgui_widgets/imgui_breakdown_ex.cpp | 5 ++--- .../imgui_widgets/imgui_ex.cpp | 22 +++++++++++++++---- .../profiler_overlay/imgui_widgets/imgui_ex.h | 9 +++++++- .../imgui_widgets/imgui_histogram_ex.cpp | 17 +++++--------- .../profiler_overlay/profiler_overlay.cpp | 15 ++++++++----- 5 files changed, 44 insertions(+), 24 deletions(-) diff --git a/VkLayer_profiler_layer/profiler_overlay/imgui_widgets/imgui_breakdown_ex.cpp b/VkLayer_profiler_layer/profiler_overlay/imgui_widgets/imgui_breakdown_ex.cpp index e19202a3..9cd73b9a 100644 --- a/VkLayer_profiler_layer/profiler_overlay/imgui_widgets/imgui_breakdown_ex.cpp +++ b/VkLayer_profiler_layer/profiler_overlay/imgui_widgets/imgui_breakdown_ex.cpp @@ -22,6 +22,7 @@ #define IMGUI_DEFINE_MATH_OPERATORS #include "imgui_breakdown_ex.h" +#include "imgui_ex.h" #include #include @@ -130,9 +131,7 @@ namespace ImGuiX else color = col_base + random(); - ImU32 alpha = ( color & IM_COL32_A_MASK ) >> IM_COL32_A_SHIFT; - alpha *= style.Alpha; - color = ( color & ~IM_COL32_A_MASK ) | ( alpha << IM_COL32_A_SHIFT ); + color = ColorAlpha( color, style.Alpha, ColorAlphaOp_Multiply ); window->DrawList->AddRectFilled( rect.Min, rect.Max, color ); diff --git a/VkLayer_profiler_layer/profiler_overlay/imgui_widgets/imgui_ex.cpp b/VkLayer_profiler_layer/profiler_overlay/imgui_widgets/imgui_ex.cpp index 02c6ded2..0b65306a 100644 --- a/VkLayer_profiler_layer/profiler_overlay/imgui_widgets/imgui_ex.cpp +++ b/VkLayer_profiler_layer/profiler_overlay/imgui_widgets/imgui_ex.cpp @@ -182,11 +182,25 @@ namespace ImGuiX Set color alpha. \*************************************************************************/ - ImU32 ColorAlpha( ImU32 color, float alpha ) + ImU32 ColorAlpha( ImU32 color, float alpha, ColorAlphaOp op ) { - ImU32 c = color & 0x00FFFFFF; - ImU8 a = ImClamp( 255.f * alpha, 0.f, 255.f ); - return ( c & 0x00FFFFFF ) | ( a << 24 ); + ImU32 a = ( color & IM_COL32_A_MASK ) >> IM_COL32_A_SHIFT; + switch( op ) + { + case ColorAlphaOp_Set: + a = ImClamp( 255 * alpha, 0, 255 ); + break; + case ColorAlphaOp_Add: + a = ImClamp( a + 255 * alpha, 0, 255 ); + break; + case ColorAlphaOp_Multiply: + a = ImClamp( a * alpha, 0, 255 ); + break; + default: + IM_ASSERT( false ); + break; + } + return ( color & ~IM_COL32_A_MASK ) | ( a << IM_COL32_A_SHIFT ); } /*************************************************************************\ diff --git a/VkLayer_profiler_layer/profiler_overlay/imgui_widgets/imgui_ex.h b/VkLayer_profiler_layer/profiler_overlay/imgui_widgets/imgui_ex.h index df7b490f..32945a73 100644 --- a/VkLayer_profiler_layer/profiler_overlay/imgui_widgets/imgui_ex.h +++ b/VkLayer_profiler_layer/profiler_overlay/imgui_widgets/imgui_ex.h @@ -23,6 +23,13 @@ namespace ImGuiX { + enum ColorAlphaOp + { + ColorAlphaOp_Set, + ColorAlphaOp_Add, + ColorAlphaOp_Multiply + }; + /*************************************************************************\ Function: @@ -87,7 +94,7 @@ namespace ImGuiX Set color alpha. \*************************************************************************/ - ImU32 ColorAlpha( ImU32, float ); + ImU32 ColorAlpha( ImU32, float, ColorAlphaOp = ColorAlphaOp_Set ); /*************************************************************************\ diff --git a/VkLayer_profiler_layer/profiler_overlay/imgui_widgets/imgui_histogram_ex.cpp b/VkLayer_profiler_layer/profiler_overlay/imgui_widgets/imgui_histogram_ex.cpp index f6957a2f..418fab02 100644 --- a/VkLayer_profiler_layer/profiler_overlay/imgui_widgets/imgui_histogram_ex.cpp +++ b/VkLayer_profiler_layer/profiler_overlay/imgui_widgets/imgui_histogram_ex.cpp @@ -22,6 +22,7 @@ #define IMGUI_DEFINE_MATH_OPERATORS #include "imgui_histogram_ex.h" +#include "imgui_ex.h" #include #include @@ -238,16 +239,11 @@ namespace ImGuiX const float x_pos = inner_bb.Min.x + prev_pos; const float y_pos = inner_bb.Min.y + inner_bb.GetHeight() * ( scale_min / ( scale_max - scale_min ) ) - 5.0f; - ImU32 color = data.color; - ImU32 alpha = ( color & IM_COL32_A_MASK ) >> IM_COL32_A_SHIFT; - alpha *= style.Alpha; - color = ( color & ~IM_COL32_A_MASK ) | ( alpha << IM_COL32_A_SHIFT ); - window->DrawList->AddTriangleFilled( { x_pos - 5.0f * g.IO.FontGlobalScale, y_pos }, { x_pos + 5.0f * g.IO.FontGlobalScale, y_pos }, { x_pos, y_pos + 5.0f * g.IO.FontGlobalScale }, - color ); + ColorAlpha( data.color, style.Alpha, ColorAlphaOp_Multiply ) ); // Check if mouse is over the event const ImRect event_bb( @@ -297,15 +293,14 @@ namespace ImGuiX ( data.flags & HistogramColumnFlags_NoHover ) == 0 && column_bb.ContainsWithPad( g.IO.MousePos, style.TouchExtraPadding ); - ImU32 color = data.color; - ImU32 alpha = ( color & IM_COL32_A_MASK ) >> IM_COL32_A_SHIFT; - alpha *= style.Alpha; - color = ( color & ~IM_COL32_A_MASK ) | ( alpha << IM_COL32_A_SHIFT ); + ImU32 color = ColorAlpha( data.color, style.Alpha, ColorAlphaOp_Multiply ); + if( hovered_column ) + color = ColorSaturation( color, 1.5f ); window->DrawList->AddRectFilled( column_bb.Min, column_bb.Max, - hovered_column ? ColorSaturation( color, 1.5f ) : color ); + color ); if( hovered_column ) { diff --git a/VkLayer_profiler_layer/profiler_overlay/profiler_overlay.cpp b/VkLayer_profiler_layer/profiler_overlay/profiler_overlay.cpp index 7d443b2f..0529e2cb 100644 --- a/VkLayer_profiler_layer/profiler_overlay/profiler_overlay.cpp +++ b/VkLayer_profiler_layer/profiler_overlay/profiler_overlay.cpp @@ -4921,6 +4921,11 @@ namespace Profiler ImGui::PushStyleColor( ImGuiCol_ChildBg, ImGui::GetStyleColorVec4( ImGuiCol_ScrollbarBg ) ); ImGui::PushStyleColor( ImGuiCol_ScrollbarBg, 0 ); + const ImU32 gridColor = ImGuiX::ColorAlpha( IM_COL32( 128, 128, 128, 64 ), m_Opacity, ImGuiX::ColorAlphaOp_Multiply ); + const ImU32 blockColor = ImGuiX::ColorAlpha( m_GraphicsPipelineColumnColor, m_Opacity, ImGuiX::ColorAlphaOp_Multiply ); + const ImU32 hoveredBlockColor = ImGuiX::ColorAlpha( ImGuiX::Darker( m_GraphicsPipelineColumnColor, 1.5f ), m_Opacity, ImGuiX::ColorAlphaOp_Multiply ); + const ImU32 blockBorderColor = ImGuiX::ColorAlpha( ImGuiX::Darker( m_GraphicsPipelineColumnColor ), m_Opacity, ImGuiX::ColorAlphaOp_Multiply ); + if( ImGui::BeginChild( "##ImageMemoryMap", ImVec2( 0, blockMapSize.y + 25.f * interfaceScale ), ImGuiChildFlags_Border, @@ -4937,7 +4942,7 @@ namespace Profiler lt.x += x * blockSize; lt.y += y * blockSize; ImVec2 rb = ImVec2( lt.x + blockSize, lt.y + blockSize ); - dl->AddRect( lt, rb, IM_COL32( 128, 128, 128, 64 ) ); + dl->AddRect( lt, rb, gridColor ); } } @@ -4963,12 +4968,12 @@ namespace Profiler rb.x += ( (float)binding.m_Block.m_ImageExtent.width / formatProperties.imageGranularity.width ) * blockSize; rb.y += ( (float)binding.m_Block.m_ImageExtent.height / formatProperties.imageGranularity.height ) * blockSize; ImRect bb( lt, rb ); - dl->AddRect( lt, rb, ImGuiX::Darker( m_GraphicsPipelineColumnColor ) ); + dl->AddRect( lt, rb, blockBorderColor ); - ImU32 color = m_GraphicsPipelineColumnColor; + ImU32 color = blockColor; bool hovered = bb.Contains( mousePos ); if( hovered ) - color = ImGuiX::Darker( color, 1.5f ); + color = hoveredBlockColor; bb.Expand( ImVec2( -1, -1 ) ); dl->AddRectFilled( bb.Min, bb.Max, color ); @@ -5023,7 +5028,7 @@ namespace Profiler rb.y += formatProperties.imageGranularity.height * blockSize - 2; ImRect bb( lt, rb ); - dl->AddRectFilled( bb.Min, bb.Max, m_GraphicsPipelineColumnColor ); + dl->AddRectFilled( bb.Min, bb.Max, blockColor ); ImVec2 cp = ImGui::GetMousePos(); if( bb.Contains( cp ) ) From b695d9ed56a6073127b2b1358f3f8baec7384e70 Mon Sep 17 00:00:00 2001 From: Lukasz Stalmirski Date: Thu, 16 Apr 2026 16:48:52 +0200 Subject: [PATCH 3/3] Update implot submodule --- .gitmodules | 2 +- External/implot | 2 +- .../profiler_overlay/profiler_overlay.cpp | 26 +++++++++++++------ 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/.gitmodules b/.gitmodules index 8f09baa2..740cde66 100644 --- a/.gitmodules +++ b/.gitmodules @@ -45,7 +45,7 @@ url = https://github.com/nothings/stb [submodule "External/implot"] path = External/implot - url = https://github.com/epezent/implot + url = https://github.com/lstalmir/implot [submodule "External/tabler-icons"] path = External/tabler-icons url = https://github.com/tabler/tabler-icons diff --git a/External/implot b/External/implot index 062bee67..2d7b3c0e 160000 --- a/External/implot +++ b/External/implot @@ -1 +1 @@ -Subproject commit 062bee670e285d0b0ec4f48f50f0e154bf29bf0a +Subproject commit 2d7b3c0e35cfed6e85819c63f38996ba9c9f09a9 diff --git a/VkLayer_profiler_layer/profiler_overlay/profiler_overlay.cpp b/VkLayer_profiler_layer/profiler_overlay/profiler_overlay.cpp index 0529e2cb..4a882d16 100644 --- a/VkLayer_profiler_layer/profiler_overlay/profiler_overlay.cpp +++ b/VkLayer_profiler_layer/profiler_overlay/profiler_overlay.cpp @@ -2984,7 +2984,9 @@ namespace Profiler const size_t samplesCount = m_pData->m_PerformanceCounters.m_StreamTimestamps.size(); const size_t metricCount = m_pActivePerformanceQueryMetricsSet->m_Metrics.size(); - ImPlot::PushStyleVar( ImPlotStyleVar_FillAlpha, 0.5f ); + ImPlotSpec plotSpec; + plotSpec.FillAlpha = 0.5f; + ImPlot::PushStyleVar( ImPlotStyleVar_PlotBorderSize, 0.0f ); for( size_t i = 0; i < metricCount; ++i ) @@ -3060,19 +3062,21 @@ namespace Profiler &plotData, PlotZeroFunction, &plotData, - samplesCount ); + samplesCount, + plotSpec ); ImPlot::PlotLineG( properties.shortName, plotValueFunction, &plotData, - samplesCount ); + samplesCount, + plotSpec ); ImPlot::EndPlot(); } } - ImPlot::PopStyleVar( 2 ); + ImPlot::PopStyleVar(); } /***********************************************************************************\ @@ -3896,6 +3900,11 @@ namespace Profiler if( !m_MemoryConsumptionHistoryTimePoints.empty() ) { + ImPlotSpec plotSpec; + plotSpec.FillAlpha = 0.5f; + plotSpec.FillColor = color; + plotSpec.LineColor = color; + ImPlot::SetupAxis( ImAxis_X1, nullptr, ImPlotAxisFlags_NoHighlight | ImPlotAxisFlags_NoSideSwitch ); ImPlot::SetupAxis( ImAxis_Y1, nullptr, ImPlotAxisFlags_NoHighlight | ImPlotAxisFlags_NoSideSwitch ); ImPlot::SetupAxisLimitsConstraints( ImAxis_X1, 0.0, m_MemoryConsumptionHistoryTimePoints.back() + 30.0 ); @@ -3913,17 +3922,18 @@ namespace Profiler ImPlot::SetupFinish(); - ImPlot::SetNextFillStyle( color, 0.5f ); ImPlot::PlotShaded( "Allocated", m_MemoryConsumptionHistoryTimePoints.data(), m_MemoryConsumptionHistory[i].data(), - m_MemoryConsumptionHistory[i].size() ); + m_MemoryConsumptionHistory[i].size(), + 0.0, + plotSpec ); - ImPlot::SetNextLineStyle( color ); ImPlot::PlotLine( "Allocated", m_MemoryConsumptionHistoryTimePoints.data(), m_MemoryConsumptionHistory[i].data(), - m_MemoryConsumptionHistory[i].size() ); + m_MemoryConsumptionHistory[i].size(), + plotSpec ); } ImPlot::EndPlot();