mirror of
https://github.com/djhackersdev/bemanitools.git
synced 2026-03-21 17:44:15 -05:00
feat: d3d9-frame-graph-hook, add frame rate graph view (#330)
Some checks failed
Build bemanitools / build (push) Has been cancelled
Some checks failed
Build bemanitools / build (push) Has been cancelled
Have a checkbox to switch to a frame graph focused view which saves a bunch of math when it’s more useful to focus on the frame/refresh rate than the frame time values. Co-authored-by: icex2 <djh.icex2@gmail.com>
This commit is contained in:
parent
972acb5f0e
commit
e0ff83f664
|
|
@ -11,6 +11,7 @@ typedef struct imgui_debug_frame_perf_graph {
|
|||
float target_time_ms;
|
||||
float y_axis_min_time_ms;
|
||||
float y_axis_max_time_ms;
|
||||
bool show_frame_rate_graph;
|
||||
} imgui_debug_frame_perf_graph_t;
|
||||
|
||||
static const ImVec2 WINDOW_MIN_SIZE = {320, 240};
|
||||
|
|
@ -18,7 +19,224 @@ static const ImVec2 WINDOW_MIN_SIZE = {320, 240};
|
|||
static imgui_debug_time_history_t _imgui_debug_frame_perf_graph_history;
|
||||
static imgui_debug_frame_perf_graph_t _imgui_debug_frame_perf_graph;
|
||||
|
||||
static void _imgui_debug_frame_perf_graph_draw(
|
||||
static void _imgui_debug_frame_perf_frame_rate_graph_draw(
|
||||
imgui_debug_frame_perf_graph_t *graph,
|
||||
const imgui_debug_time_history_t *history)
|
||||
{
|
||||
float current_value;
|
||||
ImVec2 window_size;
|
||||
static bool show_labels = true;
|
||||
static bool show_target_line = true;
|
||||
static bool show_avg_line = true;
|
||||
|
||||
log_assert(history);
|
||||
|
||||
current_value = 1000.0f / imgui_debug_time_history_recent_value_get(history);
|
||||
|
||||
igSetNextWindowSize(WINDOW_MIN_SIZE, ImGuiCond_FirstUseEver);
|
||||
igSetNextWindowSizeConstraints(WINDOW_MIN_SIZE, igGetIO()->DisplaySize, NULL, NULL);
|
||||
|
||||
igBegin("Frame Rate Graph", NULL, ImGuiWindowFlags_MenuBar);
|
||||
|
||||
// Add menu bar
|
||||
if (igBeginMenuBar()) {
|
||||
if (igBeginMenu("Settings", true)) {
|
||||
igPushItemWidth(110);
|
||||
|
||||
float min_fps = 1000.0f / graph->y_axis_max_time_ms;
|
||||
float max_fps = 1000.0f / graph->y_axis_min_time_ms;
|
||||
float target_fps = 1000.0f / graph->target_time_ms;
|
||||
|
||||
if (igDragFloat("y-axis min FPS", &min_fps, 1.0f, 1.0f, max_fps - 1.0f, "%.1f", ImGuiSliderFlags_None)) {
|
||||
graph->y_axis_max_time_ms = 1000.0f / min_fps;
|
||||
}
|
||||
|
||||
if (igDragFloat("y-axis max FPS", &max_fps, 1.0f, min_fps + 1.0f, 1000.0f, "%.1f", ImGuiSliderFlags_None)) {
|
||||
graph->y_axis_min_time_ms = 1000.0f / max_fps;
|
||||
}
|
||||
|
||||
if (igInputFloat("Target FPS", &target_fps, 0.0f, 0.0f, "%.3f", ImGuiInputTextFlags_EnterReturnsTrue)) {
|
||||
if (target_fps >= 1.0f && target_fps <= 1000.0f) {
|
||||
graph->target_time_ms = 1000.0f / target_fps;
|
||||
} else {
|
||||
target_fps = 1000.0f / graph->target_time_ms;
|
||||
}
|
||||
}
|
||||
|
||||
igCheckbox("Show reference line labels", &show_labels);
|
||||
igCheckbox("Show target reference line", &show_target_line);
|
||||
igCheckbox("Show average reference line", &show_avg_line);
|
||||
|
||||
if (igButton("Focus on average", (ImVec2){0, 0})) {
|
||||
float avg_fps = 1000.0f / history->avg_time_ms;
|
||||
graph->y_axis_min_time_ms = 1000.0f / (avg_fps + 10.0f);
|
||||
graph->y_axis_max_time_ms = 1000.0f / fmaxf(avg_fps - 10.0f, 1.0f);
|
||||
}
|
||||
|
||||
igSameLine(0, -1);
|
||||
|
||||
if (igButton("Focus on target", (ImVec2){0, 0})) {
|
||||
float target_fps = 1000.0f / graph->target_time_ms;
|
||||
graph->y_axis_min_time_ms = 1000.0f / (target_fps + 10.0f);
|
||||
graph->y_axis_max_time_ms = 1000.0f / fmaxf(target_fps - 10.0f, 1.0f);
|
||||
}
|
||||
|
||||
igCheckbox("Show frame rate graph", &graph->show_frame_rate_graph);
|
||||
|
||||
igPopItemWidth();
|
||||
igEndMenu();
|
||||
}
|
||||
igEndMenuBar();
|
||||
}
|
||||
|
||||
igGetContentRegionAvail(&window_size);
|
||||
|
||||
igPushStyleColor_Vec4(ImGuiCol_Text, (ImVec4){1, 1, 0, 1});
|
||||
igText("Now %.3f FPS", current_value);
|
||||
igPopStyleColor(1);
|
||||
igSameLine(0, -1);
|
||||
igPushStyleColor_Vec4(ImGuiCol_Text, (ImVec4){1, 0, 0, 1});
|
||||
igText("Target %.3f FPS", 1000.0f / graph->target_time_ms);
|
||||
igPopStyleColor(1);
|
||||
igPushStyleColor_Vec4(ImGuiCol_Text, (ImVec4){0, 1, 0, 1});
|
||||
igText("Avg %.3f FPS", 1000.0f / history->avg_time_ms);
|
||||
igPopStyleColor(1);
|
||||
igSameLine(0, -1);
|
||||
igText(" Min %.3f FPS Max %.3f FPS", 1000.0f / history->max_time_ms, 1000.0f / history->min_time_ms);
|
||||
|
||||
// Setup plot area using actual window size, with extra space at top for "FPS" label
|
||||
ImVec2 plot_pos;
|
||||
igGetCursorScreenPos(&plot_pos);
|
||||
plot_pos.y += 15; // Add space at top for "FPS" label
|
||||
ImVec2 plot_size = {window_size.x - 50, window_size.y - 65}; // Adjusted for extra top space
|
||||
|
||||
// Convert time values to FPS for plotting
|
||||
float fps_values[history->size];
|
||||
for(int i = 0; i < history->size; i++) {
|
||||
fps_values[i] = 1000.0f / history->time_values_ms[i];
|
||||
}
|
||||
|
||||
// Plot FPS values
|
||||
ImVec2 plot_pos_offset = {plot_pos.x + 50, plot_pos.y};
|
||||
igSetCursorScreenPos(plot_pos_offset);
|
||||
|
||||
igPlotLines_FloatPtr("##framegraph",
|
||||
fps_values,
|
||||
history->size,
|
||||
history->current_index,
|
||||
"",
|
||||
1000.0f / graph->y_axis_min_time_ms, // Swapped min/max to invert Y axis
|
||||
1000.0f / graph->y_axis_max_time_ms,
|
||||
plot_size,
|
||||
sizeof(float));
|
||||
|
||||
// Draw Y axis (FPS)
|
||||
ImDrawList* draw_list = igGetWindowDrawList();
|
||||
char y_label[32];
|
||||
ImDrawList_AddLine(draw_list,
|
||||
(ImVec2){plot_pos.x + 50, plot_pos.y},
|
||||
(ImVec2){plot_pos.x + 50, plot_pos.y + plot_size.y},
|
||||
igColorConvertFloat4ToU32((ImVec4){1,1,1,1}), 1.0f);
|
||||
|
||||
// Draw "FPS" label at top of y-axis
|
||||
ImDrawList_AddText_Vec2(draw_list, (ImVec2){plot_pos.x + 5, plot_pos.y - 15},
|
||||
igColorConvertFloat4ToU32((ImVec4){1,1,1,1}), "FPS", NULL);
|
||||
|
||||
// Scale number of reference points based on plot height
|
||||
int num_reference_points = (int)(plot_size.y / 25); // One point per ~40 pixels
|
||||
if (num_reference_points < 4) num_reference_points = 4;
|
||||
|
||||
float fps_min = 1000.0f / graph->y_axis_max_time_ms;
|
||||
float fps_max = 1000.0f / graph->y_axis_min_time_ms;
|
||||
float fps_step = (fps_max - fps_min) / (num_reference_points + 1);
|
||||
|
||||
// Draw min FPS value at bottom of y-axis and reference line
|
||||
snprintf(y_label, sizeof(y_label), "%.3f", fps_min);
|
||||
ImDrawList_AddText_Vec2(draw_list, (ImVec2){plot_pos.x + 5, plot_pos.y + plot_size.y - 10},
|
||||
igColorConvertFloat4ToU32((ImVec4){1,1,1,1}), y_label, NULL);
|
||||
ImDrawList_AddLine(draw_list,
|
||||
(ImVec2){plot_pos.x + 50, plot_pos.y + plot_size.y},
|
||||
(ImVec2){plot_pos.x + plot_size.x + 50, plot_pos.y + plot_size.y},
|
||||
igColorConvertFloat4ToU32((ImVec4){1,1,1,0.3f}), 1.0f);
|
||||
|
||||
// Draw reference points and lines on side of y-axis
|
||||
for (int i = 1; i <= num_reference_points; i++) {
|
||||
float value = fps_min + (fps_step * i);
|
||||
float normalized_pos = 1.0f - ((value - fps_min) / (fps_max - fps_min)); // Inverted normalization
|
||||
float y_pos = plot_pos.y + (plot_size.y * normalized_pos);
|
||||
snprintf(y_label, sizeof(y_label), "%.3f", value);
|
||||
ImDrawList_AddText_Vec2(draw_list, (ImVec2){plot_pos.x + 5, y_pos - 5},
|
||||
igColorConvertFloat4ToU32((ImVec4){1,1,1,1}), y_label, NULL);
|
||||
ImDrawList_AddLine(draw_list,
|
||||
(ImVec2){plot_pos.x + 50, y_pos},
|
||||
(ImVec2){plot_pos.x + plot_size.x + 50, y_pos},
|
||||
igColorConvertFloat4ToU32((ImVec4){1,1,1,0.2f}), 1.0f);
|
||||
}
|
||||
|
||||
// Draw max FPS value at top of y-axis and reference line
|
||||
snprintf(y_label, sizeof(y_label), "%.3f", fps_max);
|
||||
ImDrawList_AddText_Vec2(draw_list, (ImVec2){plot_pos.x + 5, plot_pos.y},
|
||||
igColorConvertFloat4ToU32((ImVec4){1,1,1,1}), y_label, NULL);
|
||||
ImDrawList_AddLine(draw_list,
|
||||
(ImVec2){plot_pos.x + 50, plot_pos.y},
|
||||
(ImVec2){plot_pos.x + plot_size.x + 50, plot_pos.y},
|
||||
igColorConvertFloat4ToU32((ImVec4){1,1,1,0.3f}), 1.0f);
|
||||
|
||||
// Draw target FPS reference line if within plot area
|
||||
float target_fps_value = 1000.0f / graph->target_time_ms;
|
||||
if (show_target_line && target_fps_value >= fps_min && target_fps_value <= fps_max) {
|
||||
float normalized_target = 1.0f - ((target_fps_value - fps_min) / (fps_max - fps_min)); // Inverted normalization
|
||||
float y_pos_target = plot_pos.y + (plot_size.y * normalized_target);
|
||||
ImDrawList_AddLine(draw_list,
|
||||
(ImVec2){plot_pos.x + 50, y_pos_target},
|
||||
(ImVec2){plot_pos.x + plot_size.x + 50, y_pos_target},
|
||||
igColorConvertFloat4ToU32((ImVec4){1,0,0,1.0f}), 1.0f);
|
||||
if (show_labels) {
|
||||
snprintf(y_label, sizeof(y_label), "%.3f", target_fps_value);
|
||||
ImDrawList_AddText_Vec2(draw_list,
|
||||
(ImVec2){plot_pos.x + 50 + plot_size.x/2 - 10, y_pos_target + 5},
|
||||
igColorConvertFloat4ToU32((ImVec4){1,0,0,1}), y_label, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw reference line for current average if within plot area
|
||||
float avg_fps = 1000.0f / history->avg_time_ms;
|
||||
if (show_avg_line && avg_fps >= fps_min && avg_fps <= fps_max) {
|
||||
float normalized_avg = 1.0f - ((avg_fps - fps_min) / (fps_max - fps_min)); // Inverted normalization
|
||||
float y_pos_avg = plot_pos.y + (plot_size.y * normalized_avg);
|
||||
ImDrawList_AddLine(draw_list,
|
||||
(ImVec2){plot_pos.x + 50, y_pos_avg},
|
||||
(ImVec2){plot_pos.x + plot_size.x + 50, y_pos_avg},
|
||||
igColorConvertFloat4ToU32((ImVec4){0,1,0,1.0f}), 1.0f);
|
||||
if (show_labels) {
|
||||
snprintf(y_label, sizeof(y_label), "%.3f", avg_fps);
|
||||
ImDrawList_AddText_Vec2(draw_list,
|
||||
(ImVec2){plot_pos.x + 50 + plot_size.x/2 - 10, y_pos_avg + 5},
|
||||
igColorConvertFloat4ToU32((ImVec4){0,1,0,1}), y_label, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw X axis (time in frames)
|
||||
ImDrawList_AddLine(draw_list,
|
||||
(ImVec2){plot_pos.x + 50, plot_pos.y + plot_size.y},
|
||||
(ImVec2){plot_pos.x + plot_size.x + 50, plot_pos.y + plot_size.y},
|
||||
igColorConvertFloat4ToU32((ImVec4){1,1,1,1}), 1.0f);
|
||||
|
||||
// Draw "frames" label centered on x-axis
|
||||
ImDrawList_AddText_Vec2(draw_list, (ImVec2){plot_pos.x + 50 + (plot_size.x / 2) - 20, plot_pos.y + plot_size.y + 5},
|
||||
igColorConvertFloat4ToU32((ImVec4){1,1,1,1}), "frames ago", NULL);
|
||||
|
||||
char x_label[32];
|
||||
snprintf(x_label, sizeof(x_label), "%d", history->size);
|
||||
ImDrawList_AddText_Vec2(draw_list, (ImVec2){plot_pos.x + 50, plot_pos.y + plot_size.y + 5},
|
||||
igColorConvertFloat4ToU32((ImVec4){1,1,1,1}), x_label, NULL);
|
||||
ImDrawList_AddText_Vec2(draw_list, (ImVec2){plot_pos.x + plot_size.x + 50, plot_pos.y + plot_size.y + 5},
|
||||
igColorConvertFloat4ToU32((ImVec4){1,1,1,1}), "0", NULL);
|
||||
|
||||
igEnd();
|
||||
}
|
||||
|
||||
static void _imgui_debug_frame_perf_frame_time_graph_draw(
|
||||
imgui_debug_frame_perf_graph_t *graph,
|
||||
const imgui_debug_time_history_t *history)
|
||||
{
|
||||
|
|
@ -82,6 +300,8 @@ static void _imgui_debug_frame_perf_graph_draw(
|
|||
graph->y_axis_max_time_ms = 1000.0f / fmaxf(target_fps - 10.0f, 1.0f);
|
||||
}
|
||||
|
||||
igCheckbox("Show frame rate graph", &graph->show_frame_rate_graph);
|
||||
|
||||
igPopItemWidth();
|
||||
igEndMenu();
|
||||
}
|
||||
|
|
@ -238,7 +458,11 @@ static void _imgui_debug_frame_perf_graph_component_frame_update(ImGuiContext *c
|
|||
|
||||
imgui_debug_time_history_update(&_imgui_debug_frame_perf_graph_history, 1000.0f / io->Framerate);
|
||||
|
||||
_imgui_debug_frame_perf_graph_draw(&_imgui_debug_frame_perf_graph, &_imgui_debug_frame_perf_graph_history);
|
||||
if (_imgui_debug_frame_perf_graph.show_frame_rate_graph) {
|
||||
_imgui_debug_frame_perf_frame_rate_graph_draw(&_imgui_debug_frame_perf_graph, &_imgui_debug_frame_perf_graph_history);
|
||||
} else {
|
||||
_imgui_debug_frame_perf_frame_time_graph_draw(&_imgui_debug_frame_perf_graph, &_imgui_debug_frame_perf_graph_history);
|
||||
}
|
||||
}
|
||||
|
||||
void imgui_debug_frame_perf_graph_init(
|
||||
|
|
@ -253,6 +477,7 @@ void imgui_debug_frame_perf_graph_init(
|
|||
_imgui_debug_frame_perf_graph.target_time_ms = 1000.0f / target_fps;
|
||||
_imgui_debug_frame_perf_graph.y_axis_min_time_ms = 1000.0f / fmaxf(0.0f, target_fps - 20.0f);
|
||||
_imgui_debug_frame_perf_graph.y_axis_max_time_ms = 1000.0f / fminf(target_fps + 20.0f, 1000.0f);
|
||||
_imgui_debug_frame_perf_graph.show_frame_rate_graph = false;
|
||||
|
||||
component->frame_update = _imgui_debug_frame_perf_graph_component_frame_update;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user