7#include <imgui/imgui.h>
8#include <imgui_widgets/tooltips.h>
22ImVec4 category_text_color_ex{0.62f, 0.80f, 1.0f, 1.0f};
23ImVec4 muted_text_color_ex{0.55f, 0.55f, 0.55f, 1.0f};
24ImVec4 warn_text_color_ex{0.93f, 0.74f, 0.20f, 1.0f};
25ImVec4 bad_text_color_ex{1.0f, 0.3f, 0.3f, 1.0f};
27std::array<const char*, 4> strategy_names{
"LRU (least recently used)",
28 "LFU (least frequently used)",
32auto clamp_u64(std::int64_t value) -> std::uint64_t
34 return static_cast<std::uint64_t
>(std::max<std::int64_t>(0, value));
37void draw_stat_row(
const char* label,
const char* value,
const ImVec4*
color =
nullptr)
39 ImGui::TableNextRow();
40 ImGui::TableSetColumnIndex(0);
41 ImGui::AlignTextToFramePadding();
42 ImGui::TextUnformatted(label);
43 ImGui::TableSetColumnIndex(1);
44 ImGui::AlignTextToFramePadding();
45 const float offset = ImGui::GetContentRegionAvail().x - ImGui::CalcTextSize(value).x;
48 ImGui::SetCursorPosX(ImGui::GetCursorPosX() + offset);
52 ImGui::TextColored(*
color,
"%s", value);
55 ImGui::TextUnformatted(value);
58void draw_count_bytes_row(
const char* label,
61 const ImVec4*
color =
nullptr)
64 draw_stat_row(label, value.c_str(),
color);
67void draw_count_row(
const char* label, std::uint64_t
count,
const ImVec4*
color =
nullptr)
69 const auto value = fmt::format(
"{}",
count);
70 draw_stat_row(label, value.c_str(),
color);
73void draw_ms_row(
const char* label,
double ms)
75 const auto value = fmt::format(
"{:.3f} ms", ms);
76 draw_stat_row(label, value.c_str());
79void draw_reserve_test_controls(std::uint64_t gpu_max)
83 ImGui::TextColored(category_text_color_ex,
ICON_MDI_MEMORY " Test: GPU memory reserve");
85 static int reserve_mb = 1024;
86 ImGui::SliderInt(
"Reserve (MiB)", &reserve_mb, 64, 16384);
87 ImGui::SetItemTooltipEx(
"Test: reserve raw, non-evictable GPU memory to push device occupancy\n"
88 "toward the limit, so eviction and near-the-limit allocations (e.g. a\n"
89 "large frame buffer) can be exercised on GPUs with plenty of memory.");
93 ev::debug_consume_memory(
static_cast<std::uint64_t
>(std::max(0, reserve_mb)) * 1024ull * 1024ull);
95 ImGui::SetItemTooltipEx(
"Reserve the above amount of non-evictable GPU memory (additive).");
99 ev::debug_release_memory();
101 ImGui::SetItemTooltipEx(
"Free all reserved memory and reclaim its VRAM immediately.");
103 ImGui::TextUnformatted(fmt::format(
"held: {}",
format_bytes(ev::debug_consumed_bytes())).c_str());
110 constexpr std::uint64_t one_gib = 1024ull * 1024ull * 1024ull;
111 constexpr std::array<std::uint32_t, 7> presets{1, 2, 4, 6, 8, 12, 16};
113 ImGui::TextUnformatted(
"Simulate as if GPU had:");
114 ImGui::SetItemTooltipEx(
"Test: reserve real VRAM in one click so the device behaves like a\n"
115 "smaller card. Each preset reserves (GPU max - target) of memory, so\n"
116 "the engine hits genuine out-of-memory behavior at the chosen limit.\n"
117 "Only presets smaller than this GPU are shown.");
118 for(
const auto gb : presets)
120 if(
static_cast<std::uint64_t
>(gb) * one_gib >= gpu_max)
124 const auto label = fmt::format(
"{} GB", gb);
126 if(ImGui::SmallButton(label.c_str()))
128 ev::debug_simulate_budget(
static_cast<std::uint64_t
>(gb) * one_gib);
144 if(!ev::is_supported())
146 ImGui::TextColored(muted_text_color_ex,
148 " Eviction is not supported on this backend\n(it does not report a GPU "
149 "memory budget). Paging is disabled.");
153 ImGui::Checkbox(
"Enabled", &state.
enabled);
154 ImGui::SetItemTooltipEx(
"When enabled, GPU resources are evicted each frame to keep memory\n"
155 "usage under the configured budget. Evicted resources restore\n"
156 "automatically the next time they are used.");
163 ImGui::SetItemTooltipEx(
"Test: evict every evictable resource immediately, ignoring budget and age.");
169 ImGui::SetItemTooltipEx(
"Test: restore every evicted resource immediately.");
171 ImGui::Combo(
"Strategy", &state.
strategy, strategy_names.data(),
static_cast<int>(strategy_names.size()));
172 ImGui::SetItemTooltipEx(
"Policy used to pick eviction victims when over budget.");
174 ImGui::Checkbox(
"Auto budget (GPU memory)", &state.
auto_budget);
175 ImGui::SetItemTooltipEx(
"Derive the budget from the backend's reported GPU memory.\n"
176 "Falls back to the manual budget if the backend does not\n"
177 "report a GPU memory limit.");
180 const std::uint64_t gpu_max = (
bx !=
nullptr) ? clamp_u64(
bx->gpuMemoryMax) : 0;
181 const std::uint64_t gpu_used = (
bx !=
nullptr) ? clamp_u64(
bx->gpuMemoryUsed) : 0;
185 ImGui::SliderFloat(
"Budget %", &state.
budget_fraction, 0.1f, 1.0f,
"%.2f");
186 ImGui::SliderFloat(
"Target %", &state.
target_fraction, 0.1f, 1.0f,
"%.2f");
189 const auto soft =
static_cast<std::uint64_t
>(
static_cast<double>(gpu_max) * state.
budget_fraction);
190 const auto target =
static_cast<std::uint64_t
>(
static_cast<double>(gpu_max) * state.
target_fraction);
191 const bool over = gpu_used > soft;
192 const auto gpu_line = fmt::format(
"GPU: {} / {} budget {}, target {}",
197 ImGui::TextColored(over ? bad_text_color_ex : muted_text_color_ex,
"%s", gpu_line.c_str());
209 ImGui::TextColored(warn_text_color_ex,
"Backend reports no GPU memory limit; using manual budget.");
213 ImGui::SliderInt(
"Min age (frames)", &state.
min_age_frames, 0, 600);
214 ImGui::SetItemTooltipEx(
"Resources used within this many frames are never evicted (anti-thrash).");
215 ImGui::SliderInt(
"Max evictions / frame", &state.
max_evictions, 0, 1024);
216 ImGui::SetItemTooltipEx(
"Caps how many resources may be evicted per frame to bound the cost.\n"
217 "0 means unlimited.");
220 draw_reserve_test_controls(gpu_max);
224 const auto stats = ev::get_stats();
225 constexpr ImGuiTableFlags table_flags =
226 ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_BordersOuter;
227 if(!ImGui::BeginTable(
"##eviction_stats", 2, table_flags))
231 ImGui::TableSetupColumn(
"Stat", ImGuiTableColumnFlags_WidthStretch, 1.0f);
232 ImGui::TableSetupColumn(
"Value", ImGuiTableColumnFlags_WidthFixed, 140.0f);
234 ImGui::TableNextRow();
235 ImGui::TableSetColumnIndex(0);
236 ImGui::TextColored(category_text_color_ex,
"Residency");
238 draw_count_bytes_row(
"Resident", stats.resident_count, stats.resident_bytes);
239 draw_count_bytes_row(
"Evicted", stats.evicted_count, stats.evicted_bytes);
240 draw_count_row(
"Registered", stats.registered_count);
242 ImGui::TableNextRow();
243 ImGui::TableSetColumnIndex(0);
244 ImGui::TextColored(category_text_color_ex,
"Lifetime");
246 draw_count_bytes_row(
"Evictions", stats.total_evictions, stats.total_bytes_evicted);
247 draw_count_bytes_row(
"Restores", stats.total_restores, stats.total_bytes_restored);
248 draw_count_row(
"Failed restores",
249 stats.failed_restores,
250 stats.failed_restores > 0 ? &warn_text_color_ex :
nullptr);
251 draw_count_row(
"Thrash events", stats.thrash_events, stats.thrash_events > 0 ? &warn_text_color_ex :
nullptr);
253 ImGui::TableNextRow();
254 ImGui::TableSetColumnIndex(0);
255 ImGui::TextColored(category_text_color_ex,
"Last pass");
257 draw_count_row(
"Scanned", stats.last_pass_scanned);
258 draw_count_row(
"Evicted", stats.last_pass_evicted);
259 draw_ms_row(
"Sweep time", stats.last_pass_ms);
260 draw_ms_row(
"Last restore", stats.last_restore_ms);
#define ICON_MDI_DELETE_SWEEP
#define ICON_MDI_BACKUP_RESTORE
#define ICON_MDI_PLUS_BOX
#define ICON_MDI_SWAP_HORIZONTAL
const stats * get_stats()
void profiler_draw_eviction_section(eviction_settings &state)
auto format_bytes(std::uint64_t bytes, std::uint8_t num_frac) -> std::string
std::vector< math::color > color
float target_fraction
Evict down to this fraction of the reported maximum (hysteresis; should be < budget).
int manual_budget_mb
Manual budget (MiB) compared against the evictable resident bytes when not using auto budget.
int min_age_frames
Resources used within this many frames are protected from eviction.
float budget_fraction
Start evicting once GPU usage exceeds this fraction of the reported maximum.
int strategy
Selected gfx::eviction::strategy (index).
int max_evictions
Maximum resources evicted per frame (0 = unlimited).
bool enabled
Master toggle: when true the per-frame driver evicts to keep usage under the budget.