massively add plotting functions

This commit is contained in:
John Alanbrook 2024-09-24 14:12:59 -05:00
parent d62a1ca0db
commit 0666f4d949
7 changed files with 182 additions and 57 deletions

View file

@ -171,20 +171,7 @@ function get_line(file, line) {
profile.stop_cpu_instr = function() profile.stop_cpu_instr = function()
{ {
say("===CPU INSTRUMENTATION===\n"); return;
var gather_time = profile.now()-start_gather;
var e = Object.values(callgraph);
e = e.sort((a,b) => {
if (a.time > b.time) return -1;
return 1;
});
e.forEach(x => {
var ffs = x.line.split(':');
var time = profile.best_t(x.time);
var pct = x.time/gather_time*100;
say(`${x.line}::${x.fn}:: ${time} (${pct.toPrecision(3)}%) (${x.hits} hits) --> ${get_line(ffs[0], ffs[1])}`);
});
} }
profile.best_t = function (t) { profile.best_t = function (t) {
@ -220,10 +207,7 @@ profile.start_frame_avg = function()
profile.stop_frame_avg = function() profile.stop_frame_avg = function()
{ {
if (!frame_avg) return;
frame_avg = false; frame_avg = false;
profile.print_frame_avg();
} }
profile.toggle_frame_avg = function() profile.toggle_frame_avg = function()
@ -320,15 +304,6 @@ profile.endcache = function profile_endcache(tag = "")
addreport(cachegroup, cachetitle + tag, cachest); addreport(cachegroup, cachetitle + tag, cachest);
} }
profile.print_cache_report = function()
{
var str = "===START CACHE REPORTS===\n";
for (var i in report_cache)
str += printreport(report_cache[i], i) + "\n";
say(str);
}
function addreport(group, line, start) { function addreport(group, line, start) {
if (typeof group !== 'string') group = 'UNGROUPED'; if (typeof group !== 'string') group = 'UNGROUPED';
report_cache[group] ??= {}; report_cache[group] ??= {};
@ -363,6 +338,25 @@ function printreport(cache, name) {
return report; return report;
}; };
profile.data = {};
profile.data.cpu = {};
profile.data.gpu = {};
profile.data.physics = {};
profile.data.script = {};
var frame = 0;
profile.capture_data = function()
{
var mem = os.mem();
var memo = profile.data.script;
for (var i in mem) {
memo[i] ??= [];
if (memo[i].last() !== mem[i])
memo[i][frame] = mem[i];
}
frame++;
}
profile.best_mem = function(bytes) profile.best_mem = function(bytes)
{ {
var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']; var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];

View file

@ -272,9 +272,6 @@ prosperon.touchrelease = function (touches) {};
prosperon.touchmove = function (touches) {}; prosperon.touchmove = function (touches) {};
prosperon.clipboardpaste = function (str) {}; prosperon.clipboardpaste = function (str) {};
prosperon.quit = function () { prosperon.quit = function () {
profile.print_cache_report();
profile.stop_frame_avg()
profile.stop_cpu_instr();
prosperon.quit_hook?.(); prosperon.quit_hook?.();
}; };

View file

@ -1225,8 +1225,9 @@ prosperon.process = function process() {
prosperon.window_render(window.size); prosperon.window_render(window.size);
prosperon.render(); prosperon.render();
profile.endframe(); profile.endframe();
profile.endframe(); profile.endframe();
profile.capture_data();
} }
return {render}; return {render};

View file

@ -69,42 +69,93 @@ JSC_SCALL(imgui_plot,
ImPlot::EndPlot(); ImPlot::EndPlot();
) )
JSC_SCALL(imgui_lineplot, #define PLOT_FN(NAME, FN, ADD) JSC_SCALL(imgui_##NAME, \
HMM_Vec2 data[js_arrlen(argv[1])]; fill_plotdata(argv[1]); \
for (int i = 0; i < js_arrlen(argv[1]); i++) ImPlot::FN(str, &plotdata[0].x, &plotdata[0].y, arrlen(plotdata), ADD 0, 0, sizeof(HMM_Vec2)); \
data[i] = js2vec2(js_getpropidx(argv[1], i)); ) \
ImPlot::PlotLine(str, &data[0].x, &data[0].y, js_arrlen(argv[1]), 0, 0, sizeof(HMM_Vec2));
)
JSC_SCALL(imgui_scatterplot, static HMM_Vec2 *plotdata = NULL;
HMM_Vec2 data[js_arrlen(argv[1])];
for (int i = 0; i < js_arrlen(argv[1]); i++)
data[i] = js2vec2(js_getpropidx(argv[1], i));
ImPlot::PlotScatter(str, &data[0].x, &data[0].y, js_arrlen(argv[1]), 0, 0, sizeof(HMM_Vec2)); void fill_plotdata(JSValue v)
) {
arrsetlen(plotdata, 0);
JSC_SCALL(imgui_stairplot, if (JS_IsArray(js,js_getpropidx(v, 0))) {
HMM_Vec2 data[js_arrlen(argv[1])]; for (int i = 0; i < js_arrlen(v); i++)
for (int i = 0; i < js_arrlen(argv[1]); i++) arrput(plotdata, js2vec2(js_getpropidx(v, i)));
data[i] = js2vec2(js_getpropidx(argv[1], i)); }
else {
ImPlot::PlotStairs(str, &data[0].x, &data[0].y, js_arrlen(argv[1]), 0, 0, sizeof(HMM_Vec2)); // Fill it with the x axis being the array index
) for (int i = 0; i < js_arrlen(v); i++) {
if (JS_IsUndefined(js_getpropidx(v,i))) continue;
HMM_Vec2 c = (HMM_Vec2){i, js2number(js_getpropidx(v,i))};
arrput(plotdata, c);
}
}
}
PLOT_FN(lineplot, PlotLine,)
PLOT_FN(scatterplot, PlotScatter,)
PLOT_FN(stairplot, PlotStairs,)
PLOT_FN(digitalplot, PlotDigital,)
JSC_SCALL(imgui_barplot, JSC_SCALL(imgui_barplot,
HMM_Vec2 data[js_arrlen(argv[1])]; fill_plotdata(argv[1]);
for (int i = 0; i < js_arrlen(argv[1]); i++) ImPlot::PlotBars(str, &plotdata[0].x, &plotdata[0].y, js_arrlen(argv[1]), js2number(argv[2]), 0, 0, sizeof(HMM_Vec2));
data[i] = js2vec2(js_getpropidx(argv[1], i)); )
ImPlot::PlotBars(str, &data[0].x, &data[0].y, js_arrlen(argv[1]), js2number(argv[2]), 0, 0, sizeof(HMM_Vec2)); static double *histodata = NULL;
void fill_histodata(JSValue v)
{
arrsetlen(histodata, js_arrlen(v));
for (int i = 0; i < js_arrlen(v); i++)
histodata[i] = js2number(js_getpropidx(v, i));
}
JSC_SCALL(imgui_histogramplot,
fill_histodata(argv[1]);
ImPlot::PlotHistogram(str, histodata, js_arrlen(argv[1]));
)
JSC_SCALL(imgui_heatplot,
fill_histodata(argv[1]);
int rows = js2number(argv[2]);
int cols = js2number(argv[3]);
if (rows*cols == (int)js_arrlen(argv[1]))
ImPlot::PlotHeatmap(str, histodata, rows, cols);
)
JSC_CCALL(imgui_pieplot,
if (js_arrlen(argv[0]) != js_arrlen(argv[1])) return;
char *labels[js_arrlen(argv[0])];
for (int i = 0; i < js_arrlen(argv[0]); i++)
labels[i] = js2str(js_getpropidx(argv[0], i));
fill_histodata(argv[1]);
ImPlot::PlotPieChart(labels, histodata, js_arrlen(argv[1]), js2number(argv[2]), js2number(argv[3]), js2number(argv[4]));
for (int i = 0; i < js_arrlen(argv[0]); i++)
JS_FreeCString(js,labels[i]);
)
JSC_SCALL(imgui_textplot,
HMM_Vec2 v = js2vec2(argv[1]);
ImPlot::PlotText(str, v.x, v.y);
)
JSC_CCALL(imgui_plothovered,
return boolean2js(ImPlot::IsPlotHovered());
) )
JSC_SSCALL(imgui_plotaxes, JSC_SSCALL(imgui_plotaxes,
ImPlot::SetupAxes(str,str2); ImPlot::SetupAxes(str,str2);
) )
JSC_CCALL(imgui_plotmousepos,
ImPlotPoint p = ImPlot::GetPlotMousePos();
return vec22js(HMM_Vec2{p.x,p.y});
)
JSC_CCALL(imgui_axeslimits, JSC_CCALL(imgui_axeslimits,
ImPlot::SetupAxesLimits(js2number(argv[0]), js2number(argv[1]), js2number(argv[2]), js2number(argv[3])); ImPlot::SetupAxesLimits(js2number(argv[0]), js2number(argv[1]), js2number(argv[2]), js2number(argv[3]));
) )
@ -520,6 +571,22 @@ ImVec2 js2imvec2(JSValue v)
return ImVec2(va.x,va.y); return ImVec2(va.x,va.y);
} }
JSValue imvec22js(ImVec2 v)
{
return vec22js(HMM_Vec2({v.x,v.y}));
}
ImPlotPoint js2plotvec2(JSValue v)
{
HMM_Vec2 va = js2vec2(v);
return ImPlotPoint(va.x,va.y);
}
JSValue plotvec22js(ImPlotPoint v)
{
return vec22js(HMM_Vec2{v.x,v.y});
}
ImVec4 js2imvec4(JSValue v) ImVec4 js2imvec4(JSValue v)
{ {
HMM_Vec4 va = js2vec4(v); HMM_Vec4 va = js2vec4(v);
@ -539,6 +606,10 @@ JSC_CCALL(imgui_line,
ImGui::GetWindowDrawList()->AddLine(js2imvec2(argv[0]), js2imvec2(argv[1]),js2imu32(argv[2])); ImGui::GetWindowDrawList()->AddLine(js2imvec2(argv[0]), js2imvec2(argv[1]),js2imu32(argv[2]));
) )
JSC_CCALL(imgui_point,
ImGui::GetWindowDrawList()->AddCircleFilled(js2imvec2(argv[0]), js2number(argv[1]), js2imu32(argv[2]));
)
JSC_CCALL(imgui_cursorscreenpos, JSC_CCALL(imgui_cursorscreenpos,
ImVec2 v = ImGui::GetCursorScreenPos(); ImVec2 v = ImGui::GetCursorScreenPos();
HMM_Vec2 va; HMM_Vec2 va;
@ -612,7 +683,58 @@ JSC_CCALL(imgui_width,
ImGui::PushItemWidth(js2number(argv[0])); ImGui::PushItemWidth(js2number(argv[0]));
) )
JSC_CCALL(imgui_windowpos,
return imvec22js(ImGui::GetWindowPos());
)
JSC_CCALL(imgui_plotpos,
return plotvec22js(ImPlot::GetPlotPos());
)
JSC_CCALL(imgui_plot2pixels,
return imvec22js(ImPlot::PlotToPixels(js2plotvec2(argv[0])));
)
JSC_CCALL(imgui_plotlimits,
ImPlotRect lim = ImPlot::GetPlotLimits();
JSValue xlim = JS_NewObject(js);
js_setpropstr(xlim, "min", number2js(lim.X.Min));
js_setpropstr(xlim, "max", number2js(lim.X.Max));
JSValue ylim = JS_NewObject(js);
js_setpropstr(ylim, "min", number2js(lim.Y.Min));
js_setpropstr(ylim, "max", number2js(lim.Y.Max));
JSValue limits = JS_NewObject(js);
js_setpropstr(limits, "x", xlim);
js_setpropstr(limits, "y", ylim);
return limits;
)
static JSValue axis_formatter = JS_UNDEFINED;
void jsformatter(double value, char *buff, int size, void *usr_data)
{
JSValue v = number2js(value);
char *str = js2str(script_call_sym_ret(axis_formatter, 1, &v));
strncpy(buff,str, size);
JS_FreeCString(js, str);
}
JSC_CCALL(imgui_axisfmt,
if (!JS_IsUndefined(axis_formatter)) {
JS_FreeValue(js, axis_formatter);
axis_formatter = JS_UNDEFINED;
}
axis_formatter = JS_DupValue(js,argv[1]);
ImPlot::SetupAxisFormat(js2boolean(argv[0]) ? ImAxis_Y1 : ImAxis_X1, jsformatter);
)
static const JSCFunctionListEntry js_imgui_funcs[] = { static const JSCFunctionListEntry js_imgui_funcs[] = {
MIST_FUNC_DEF(imgui, windowpos, 0),
MIST_FUNC_DEF(imgui, plot2pixels, 1),
MIST_FUNC_DEF(imgui, plotpos, 0),
MIST_FUNC_DEF(imgui, plotlimits, 0),
MIST_FUNC_DEF(imgui, window, 2), MIST_FUNC_DEF(imgui, window, 2),
MIST_FUNC_DEF(imgui, menu, 2), MIST_FUNC_DEF(imgui, menu, 2),
MIST_FUNC_DEF(imgui, sameline, 1), MIST_FUNC_DEF(imgui, sameline, 1),
@ -637,7 +759,12 @@ static const JSCFunctionListEntry js_imgui_funcs[] = {
MIST_FUNC_DEF(imgui, scatterplot, 2), MIST_FUNC_DEF(imgui, scatterplot, 2),
MIST_FUNC_DEF(imgui, stairplot, 2), MIST_FUNC_DEF(imgui, stairplot, 2),
MIST_FUNC_DEF(imgui, barplot, 3), MIST_FUNC_DEF(imgui, barplot, 3),
MIST_FUNC_DEF(imgui, pieplot, 5),
MIST_FUNC_DEF(imgui, textplot, 2),
MIST_FUNC_DEF(imgui, histogramplot, 2),
MIST_FUNC_DEF(imgui, plotaxes, 2), MIST_FUNC_DEF(imgui, plotaxes, 2),
MIST_FUNC_DEF(imgui, plotmousepos, 0),
MIST_FUNC_DEF(imgui, plothovered, 0),
MIST_FUNC_DEF(imgui, axeslimits, 4), MIST_FUNC_DEF(imgui, axeslimits, 4),
MIST_FUNC_DEF(imgui, fitaxis, 1), MIST_FUNC_DEF(imgui, fitaxis, 1),
MIST_FUNC_DEF(imgui, sokol_gfx, 0), MIST_FUNC_DEF(imgui, sokol_gfx, 0),
@ -646,6 +773,7 @@ static const JSCFunctionListEntry js_imgui_funcs[] = {
MIST_FUNC_DEF(imgui, collapsingheader, 1), MIST_FUNC_DEF(imgui, collapsingheader, 1),
MIST_FUNC_DEF(imgui, tree, 2), MIST_FUNC_DEF(imgui, tree, 2),
MIST_FUNC_DEF(imgui, listbox, 3), MIST_FUNC_DEF(imgui, listbox, 3),
MIST_FUNC_DEF(imgui, axisfmt, 2),
MIST_FUNC_DEF(imgui, tabbar, 2), MIST_FUNC_DEF(imgui, tabbar, 2),
MIST_FUNC_DEF(imgui, tab, 2), MIST_FUNC_DEF(imgui, tab, 2),
MIST_FUNC_DEF(imgui, open_popup, 1), MIST_FUNC_DEF(imgui, open_popup, 1),
@ -680,6 +808,7 @@ static const JSCFunctionListEntry js_imgui_funcs[] = {
MIST_FUNC_DEF(imgui, line, 3), MIST_FUNC_DEF(imgui, line, 3),
MIST_FUNC_DEF(imgui, bezierquad, 5), MIST_FUNC_DEF(imgui, bezierquad, 5),
MIST_FUNC_DEF(imgui, beziercubic, 6), MIST_FUNC_DEF(imgui, beziercubic, 6),
MIST_FUNC_DEF(imgui, point, 3),
MIST_FUNC_DEF(imgui, drawtext, 3), MIST_FUNC_DEF(imgui, drawtext, 3),
MIST_FUNC_DEF(imgui, cursorscreenpos, 0), MIST_FUNC_DEF(imgui, cursorscreenpos, 0),
MIST_FUNC_DEF(imgui, setcursorscreenpos, 1), MIST_FUNC_DEF(imgui, setcursorscreenpos, 1),

View file

@ -91,6 +91,12 @@ void script_call_sym(JSValue sym, int argc, JSValue *argv) {
JS_FreeValue(js, ret); JS_FreeValue(js, ret);
} }
JSValue script_call_sym_ret(JSValue sym, int argc, JSValue *argv) {
if (!JS_IsFunction(js, sym)) return JS_UNDEFINED;
JSValue ret = JS_Call(js, sym, JS_UNDEFINED, argc, argv);
return ret;
}
void out_memusage(const char *file) void out_memusage(const char *file)
{ {
FILE *f = fopen(file, "w"); FILE *f = fopen(file, "w");

View file

@ -28,7 +28,7 @@ void script_evalf(const char *format, ...);
JSValue script_eval(const char *file, const char *script); JSValue script_eval(const char *file, const char *script);
void script_call_sym(JSValue sym, int argc, JSValue *argv); void script_call_sym(JSValue sym, int argc, JSValue *argv);
JSValue script_call_sym_ret(JSValue sym, int argc, JSValue *argv);
void script_gc(); void script_gc();
void script_mem_limit(size_t limit); void script_mem_limit(size_t limit);
void script_gc_threshold(size_t threshold); void script_gc_threshold(size_t threshold);
@ -37,8 +37,6 @@ void script_max_stacksize(size_t size);
void _script_gcstart(); void _script_gcstart();
void _script_gcend(); void _script_gcend();
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -111,7 +111,7 @@
// Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices). // Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices).
// Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer. // Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer.
// Read about ImGuiBackendFlags_RendererHasVtxOffset for details. // Read about ImGuiBackendFlags_RendererHasVtxOffset for details.
//#define ImDrawIdx unsigned int // #define ImDrawIdx unsigned int
//---- Override ImDrawCallback signature (will need to modify renderer backends accordingly) //---- Override ImDrawCallback signature (will need to modify renderer backends accordingly)
//struct ImDrawList; //struct ImDrawList;