unify frame, report, cache in profiler
This commit is contained in:
parent
ca6c21ebb8
commit
fa824aec3a
|
@ -62,10 +62,8 @@ actor.__stats = function () {
|
||||||
};
|
};
|
||||||
|
|
||||||
actor.hotreload = function () {
|
actor.hotreload = function () {
|
||||||
profile.cache("hotreload", "check");
|
|
||||||
for (var i in script_times) {
|
for (var i in script_times) {
|
||||||
if (io.mod(i) > script_times[i]) {
|
if (io.mod(i) > script_times[i]) {
|
||||||
say(`HOT RELAODING ${i}`);
|
|
||||||
script_times[i] = io.mod(i);
|
script_times[i] = io.mod(i);
|
||||||
var script = Resources.replstrs(i);
|
var script = Resources.replstrs(i);
|
||||||
script = `(function() {
|
script = `(function() {
|
||||||
|
@ -86,7 +84,6 @@ actor.hotreload = function () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
profile.endcache();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
actor.spawn = function (script, config) {
|
actor.spawn = function (script, config) {
|
||||||
|
|
|
@ -268,14 +268,21 @@ Object.mixin(os.make_seg2d(), {
|
||||||
*/
|
*/
|
||||||
var animcache = {};
|
var animcache = {};
|
||||||
var SpriteAnim = {};
|
var SpriteAnim = {};
|
||||||
|
SpriteAnim.hotreload = function(path) {
|
||||||
|
delete animcache[path];
|
||||||
|
}
|
||||||
SpriteAnim.make = function (path) {
|
SpriteAnim.make = function (path) {
|
||||||
var anim;
|
var anim;
|
||||||
|
if (animcache[path]) return animcache[path];
|
||||||
|
|
||||||
|
profile.report(`animation_${path}`);
|
||||||
if (io.exists(path.set_ext(".ase"))) anim = SpriteAnim.aseprite(path.set_ext(".ase"));
|
if (io.exists(path.set_ext(".ase"))) anim = SpriteAnim.aseprite(path.set_ext(".ase"));
|
||||||
else if (io.exists(path.set_ext(".json"))) anim = SpriteAnim.aseprite(path.set_ext(".json"));
|
else if (io.exists(path.set_ext(".json"))) anim = SpriteAnim.aseprite(path.set_ext(".json"));
|
||||||
else if (path.ext() === "ase") anim = SpriteAnim.aseprite(path);
|
else if (path.ext() === "ase") anim = SpriteAnim.aseprite(path);
|
||||||
else if (path.ext() === "gif") anim = SpriteAnim.gif(path);
|
else if (path.ext() === "gif") anim = SpriteAnim.gif(path);
|
||||||
else anim = undefined;
|
else anim = undefined;
|
||||||
|
|
||||||
|
profile.endreport(`animation_${path}`);
|
||||||
animcache[path] = anim;
|
animcache[path] = anim;
|
||||||
return animcache[path];
|
return animcache[path];
|
||||||
};
|
};
|
||||||
|
|
|
@ -144,6 +144,8 @@ Resources.is_image = function (path) {
|
||||||
return Resources.images.some(x => x === ext);
|
return Resources.images.some(x => x === ext);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var res_cache = {};
|
||||||
|
|
||||||
function find_ext(file, ext, root = "") {
|
function find_ext(file, ext, root = "") {
|
||||||
if (!file) return;
|
if (!file) return;
|
||||||
|
|
||||||
|
@ -171,6 +173,12 @@ function find_ext(file, ext, root = "") {
|
||||||
var hashhit = 0;
|
var hashhit = 0;
|
||||||
var hashmiss = 0;
|
var hashmiss = 0;
|
||||||
|
|
||||||
|
globalThis.hashifier = {};
|
||||||
|
hashifier.stats = function()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
Object.defineProperty(Function.prototype, "hashify", {
|
Object.defineProperty(Function.prototype, "hashify", {
|
||||||
value: function () {
|
value: function () {
|
||||||
var hash = new Map();
|
var hash = new Map();
|
||||||
|
@ -279,20 +287,23 @@ var use_cache = {};
|
||||||
|
|
||||||
globalThis.use = function use(file) {
|
globalThis.use = function use(file) {
|
||||||
file = Resources.find_script(file);
|
file = Resources.find_script(file);
|
||||||
profile.cache("USE", file);
|
|
||||||
|
|
||||||
if (use_cache[file]) {
|
if (use_cache[file]) {
|
||||||
|
profile.report(`use_${file}`);
|
||||||
var ret = use_cache[file]();
|
var ret = use_cache[file]();
|
||||||
profile.endcache(" [cached]");
|
profile.endreport(`use_${file}`);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
profile.report(`compile_${file}`);
|
||||||
var script = Resources.replstrs(file);
|
var script = Resources.replstrs(file);
|
||||||
script = `(function() { var self = this; ${script}; })`;
|
script = `(function() { var self = this; ${script}; })`;
|
||||||
var fn = os.eval(file, script);
|
var fn = os.eval(file, script);
|
||||||
use_cache[file] = fn;
|
use_cache[file] = fn;
|
||||||
var ret = fn();
|
profile.endreport(`compile_${file}`);
|
||||||
|
|
||||||
profile.endcache();
|
profile.report(`use_${file}`);
|
||||||
|
var ret = fn();
|
||||||
|
profile.endreport(`use_${file}`);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
|
@ -309,7 +320,6 @@ function stripped_use(file, script) {
|
||||||
script = `(function() { var self = this; ${script}; })`;
|
script = `(function() { var self = this; ${script}; })`;
|
||||||
var fn = os.eval(file, script);
|
var fn = os.eval(file, script);
|
||||||
var ret = fn();
|
var ret = fn();
|
||||||
profile.endcache();
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -343,10 +353,10 @@ if (!profile.enabled) use = stripped_use;
|
||||||
Object.assign(globalThis, use("scripts/prosperon.js"));
|
Object.assign(globalThis, use("scripts/prosperon.js"));
|
||||||
|
|
||||||
app.interval(_ => {
|
app.interval(_ => {
|
||||||
profile.frame("hotreload");
|
profile.report("hotreload");
|
||||||
actor.hotreload();
|
actor.hotreload();
|
||||||
render.hotreload();
|
render.hotreload();
|
||||||
game.tex_hotreload();
|
game.tex_hotreload();
|
||||||
repl.hotreload();
|
repl.hotreload();
|
||||||
profile.endframe();
|
profile.endreport("hotreload");
|
||||||
}, 1);
|
}, 1);
|
||||||
|
|
|
@ -127,6 +127,7 @@ var entity = {
|
||||||
},
|
},
|
||||||
|
|
||||||
spawn(text, config, callback) {
|
spawn(text, config, callback) {
|
||||||
|
profile.report(`make_${text}`);
|
||||||
var ent = class_use(text, config, entity, function (ent) {
|
var ent = class_use(text, config, entity, function (ent) {
|
||||||
ent.transform = os.make_transform();
|
ent.transform = os.make_transform();
|
||||||
ent.guid = prosperon.guid();
|
ent.guid = prosperon.guid();
|
||||||
|
@ -168,7 +169,6 @@ var entity = {
|
||||||
}
|
}
|
||||||
else if (Array.isArray(text))
|
else if (Array.isArray(text))
|
||||||
for (var path of text) use(path,ent);
|
for (var path of text) use(path,ent);
|
||||||
profile.cache("ENTITY TIME", ent.ur.name);
|
|
||||||
*/
|
*/
|
||||||
ent.reparent(this);
|
ent.reparent(this);
|
||||||
|
|
||||||
|
@ -223,7 +223,7 @@ var entity = {
|
||||||
ent.ur.fresh.objects = {};
|
ent.ur.fresh.objects = {};
|
||||||
for (var i in ent.objects) ent.ur.fresh.objects[i] = ent.objects[i].instance_obj();
|
for (var i in ent.objects) ent.ur.fresh.objects[i] = ent.objects[i].instance_obj();
|
||||||
|
|
||||||
profile.endcache();
|
profile.endreport(`make_${text}`);
|
||||||
|
|
||||||
return ent;
|
return ent;
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
/*
|
/*
|
||||||
TYPES OF PROFILING
|
TYPES OF PROFILING
|
||||||
|
|
||||||
cpu gathering - gets stack frames randomly for a few seconds
|
cpu frames - gets stack frames randomly for a few seconds
|
||||||
|
report - can see specific events that happened. Includes inclusive vs noninclusive times.
|
||||||
frames - user defined to see how long engine takes
|
snapshot - See the amount of something every amount of time
|
||||||
|
|
||||||
cache - can see specific events that happened
|
|
||||||
|
|
||||||
memory - can see how much memory is allocated and from where
|
memory - can see how much memory is allocated and from where
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -50,6 +47,27 @@ profile.ms = function (t) {
|
||||||
var callgraph = {};
|
var callgraph = {};
|
||||||
profile.rawstacks = {};
|
profile.rawstacks = {};
|
||||||
|
|
||||||
|
function add_callgraph_from_stack(err, time)
|
||||||
|
{
|
||||||
|
var stack = err.stack.split("\n").slice(1);
|
||||||
|
var rawstack = stack.join("\n");
|
||||||
|
profile.rawstacks[rawstack] ??= {
|
||||||
|
time: 0,
|
||||||
|
hits: 0,
|
||||||
|
};
|
||||||
|
profile.rawstacks[rawstack].hits++;
|
||||||
|
profile.rawstacks[rawstack].time += time;
|
||||||
|
|
||||||
|
stack = stack.map(x => x.slice(7).split(" "));
|
||||||
|
|
||||||
|
var fns = stack.map(x => x[0]).filter(x => x);
|
||||||
|
var lines = stack.map(x => x[1]).filter(x => x);
|
||||||
|
lines = lines.map(x => x.slice(1, x.length - 1));
|
||||||
|
|
||||||
|
add_callgraph(fns[0], lines[0], time, true);
|
||||||
|
for (var i = 1; i < fns.length; i++) add_callgraph(fns[i], lines[i], time, false);
|
||||||
|
}
|
||||||
|
|
||||||
function add_callgraph(fn, line, time, alone) {
|
function add_callgraph(fn, line, time, alone) {
|
||||||
var cc = callgraph[line];
|
var cc = callgraph[line];
|
||||||
if (!cc) {
|
if (!cc) {
|
||||||
|
@ -82,12 +100,41 @@ profile.cpu_start = undefined;
|
||||||
profile.clear_cpu = function () {
|
profile.clear_cpu = function () {
|
||||||
callgraph = {};
|
callgraph = {};
|
||||||
profile.cpu_instr = undefined;
|
profile.cpu_instr = undefined;
|
||||||
|
profile.gather_stop();
|
||||||
|
profile.cpu_start = undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
profile.start_cpu_gather = function (gathertime = 5) {
|
function cpu_record_frame()
|
||||||
profile.clear_cpu();
|
{
|
||||||
// gather cpu frames for 'time' seconds
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// These values are set to get the most amount of frames without causing a stack overflow
|
||||||
|
var hittar = 450;
|
||||||
|
var hitpct = 0.2;
|
||||||
|
|
||||||
|
profile.start_cpu_gather_fn = function()
|
||||||
|
{
|
||||||
if (profile.cpu_start) return;
|
if (profile.cpu_start) return;
|
||||||
|
profile.clear_cpu();
|
||||||
|
|
||||||
|
profile.cpu_start = profile.now();
|
||||||
|
var st = profile.cpu_start;
|
||||||
|
|
||||||
|
profile.gather(Math.variate(hittar,hitpct), function() {
|
||||||
|
var time = profile.now() - st;
|
||||||
|
var err = new Error();
|
||||||
|
add_callgraph_from_stack(err, time);
|
||||||
|
st = profile.now();
|
||||||
|
profile.gather_rate(Math.variate(hittar,hitpct));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
profile.start_cpu_gather = function (gathertime = 5) {
|
||||||
|
if (profile.cpu_start) return;
|
||||||
|
profile.clear_cpu();
|
||||||
|
|
||||||
|
// gather cpu frames for 'gathertime' seconds
|
||||||
profile.cpu_start = profile.now();
|
profile.cpu_start = profile.now();
|
||||||
var st = profile.cpu_start;
|
var st = profile.cpu_start;
|
||||||
|
|
||||||
|
@ -95,59 +142,51 @@ profile.start_cpu_gather = function (gathertime = 5) {
|
||||||
var time = profile.now() - st;
|
var time = profile.now() - st;
|
||||||
|
|
||||||
var err = new Error();
|
var err = new Error();
|
||||||
var stack = err.stack.split("\n").slice(1);
|
add_callgraph_from_stack(err, time);
|
||||||
var rawstack = stack.join("\n");
|
|
||||||
profile.rawstacks[rawstack] ??= {
|
|
||||||
time: 0,
|
|
||||||
hits: 0,
|
|
||||||
};
|
|
||||||
profile.rawstacks[rawstack].hits++;
|
|
||||||
profile.rawstacks[rawstack].time += time;
|
|
||||||
|
|
||||||
stack = stack.map(x => x.slice(7).split(" "));
|
|
||||||
|
|
||||||
var fns = stack.map(x => x[0]).filter(x => x);
|
|
||||||
var lines = stack.map(x => x[1]).filter(x => x);
|
|
||||||
lines = lines.map(x => x.slice(1, x.length - 1));
|
|
||||||
|
|
||||||
add_callgraph(fns[0], lines[0], time, true);
|
|
||||||
for (var i = 1; i < fns.length; i++) add_callgraph(fns[i], lines[i], time, false);
|
|
||||||
|
|
||||||
st = profile.now();
|
st = profile.now();
|
||||||
if (profile.secs(st - profile.cpu_start) < gathertime) profile.gather_rate(Math.variate(hittar, hitpct));
|
|
||||||
else {
|
|
||||||
profile.gather_stop();
|
|
||||||
profile.cpu_start = undefined;
|
|
||||||
var e = Object.values(callgraph);
|
|
||||||
e = e.filter(x => x.line);
|
|
||||||
|
|
||||||
for (var x of e) {
|
if (profile.secs(st - profile.cpu_start) < gathertime)
|
||||||
var ffs = x.line.split(":");
|
profile.gather_rate(Math.variate(hittar, hitpct));
|
||||||
|
else
|
||||||
x.timestr = profile.best_t(x.time);
|
profile.stop_cpu_measure();
|
||||||
x.timeper = x.time / x.hits;
|
|
||||||
x.timeperstr = profile.best_t(x.timeper);
|
|
||||||
x.pct = (profile.secs(x.time) / gathertime) * 100;
|
|
||||||
x.alone.timestr = profile.best_t(x.alone.time);
|
|
||||||
x.alone.timeper = x.alone.time / x.alone.hits;
|
|
||||||
x.alone.timeperstr = profile.best_t(x.alone.timeper);
|
|
||||||
x.alone.pct = (profile.secs(x.alone.time) / gathertime) * 100;
|
|
||||||
x.fncall = get_line(ffs[0], ffs[1]);
|
|
||||||
x.log = x.line + " " + x.fn + " " + x.fncall;
|
|
||||||
x.incl = {
|
|
||||||
time: x.time,
|
|
||||||
timestr: x.timestr,
|
|
||||||
timeper: x.timeper,
|
|
||||||
timeperstr: x.timeperstr,
|
|
||||||
hits: x.hits,
|
|
||||||
pct: x.pct,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
profile.cpu_instr = e;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
profile.stop_cpu_measure = function()
|
||||||
|
{
|
||||||
|
if (!profile.cpu_start) return;
|
||||||
|
profile.gather_stop();
|
||||||
|
var gathertime = profile.now()-profile.cpu_start;
|
||||||
|
console.info(`gathered for ${profile.best_t(gathertime)}`);
|
||||||
|
profile.cpu_start = undefined;
|
||||||
|
var e = Object.values(callgraph);
|
||||||
|
e = e.filter(x => x.line);
|
||||||
|
|
||||||
|
for (var x of e) {
|
||||||
|
var ffs = x.line.split(":");
|
||||||
|
|
||||||
|
x.timestr = profile.best_t(x.time);
|
||||||
|
x.timeper = x.time / x.hits;
|
||||||
|
x.timeperstr = profile.best_t(x.timeper);
|
||||||
|
x.pct = x.time/gathertime * 100;
|
||||||
|
x.alone.timestr = profile.best_t(x.alone.time);
|
||||||
|
x.alone.timeper = x.alone.time / x.alone.hits;
|
||||||
|
x.alone.timeperstr = profile.best_t(x.alone.timeper);
|
||||||
|
x.alone.pct = x.alone.time / gathertime * 100;
|
||||||
|
x.fncall = get_line(ffs[0], ffs[1]);
|
||||||
|
x.log = x.line + " " + x.fn + " " + x.fncall;
|
||||||
|
x.incl = {
|
||||||
|
time: x.time,
|
||||||
|
timestr: x.timestr,
|
||||||
|
timeper: x.timeper,
|
||||||
|
timeperstr: x.timeperstr,
|
||||||
|
hits: x.hits,
|
||||||
|
pct: x.pct,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
profile.cpu_instr = e;
|
||||||
|
}
|
||||||
|
|
||||||
function push_time(arr, ob, max) {
|
function push_time(arr, ob, max) {
|
||||||
arr.push({
|
arr.push({
|
||||||
time: profile.now(),
|
time: profile.now(),
|
||||||
|
@ -258,94 +297,25 @@ profile.endframe = function profile_endframe() {
|
||||||
profile_cframe = profile_frame_ts.pop();
|
profile_cframe = profile_frame_ts.pop();
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
Cache reporting is to measure how long specific events take, that are NOT every frame
|
|
||||||
Useful to measure things like how long it takes to make a specific creature
|
|
||||||
*/
|
|
||||||
|
|
||||||
var cache_reporting = false;
|
|
||||||
|
|
||||||
var report_cache = {};
|
|
||||||
|
|
||||||
var cachest = 0;
|
|
||||||
var cachegroup;
|
|
||||||
var cachetitle;
|
|
||||||
|
|
||||||
profile.cache_reporting = function () {
|
|
||||||
return cache_reporting;
|
|
||||||
};
|
|
||||||
profile.cache_toggle = function () {
|
|
||||||
cache_reporting = !cache_reporting;
|
|
||||||
};
|
|
||||||
profile.cache_dump = function () {
|
|
||||||
report_cache = {};
|
|
||||||
};
|
|
||||||
|
|
||||||
profile.cache = function profile_cache(group, title) {
|
|
||||||
if (!cache_reporting) return;
|
|
||||||
cachest = profile.now();
|
|
||||||
cachegroup = group;
|
|
||||||
cachetitle = title;
|
|
||||||
};
|
|
||||||
|
|
||||||
profile.endcache = function profile_endcache(tag = "") {
|
|
||||||
return;
|
|
||||||
addreport(cachegroup, cachetitle + tag, cachest);
|
|
||||||
};
|
|
||||||
|
|
||||||
function addreport(group, line, start) {
|
|
||||||
return;
|
|
||||||
if (typeof group !== "string") group = "UNGROUPED";
|
|
||||||
report_cache[group] ??= {};
|
|
||||||
var cache = report_cache[group];
|
|
||||||
cache[line] ??= [];
|
|
||||||
var t = profile.now();
|
|
||||||
cache[line].push(t - start);
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
function printreport(cache, name) {
|
|
||||||
var report = `==${name}==` + "\n";
|
|
||||||
|
|
||||||
var reports = [];
|
|
||||||
for (var i in cache) {
|
|
||||||
var time = cache[i].reduce((a, b) => a + b);
|
|
||||||
reports.push({
|
|
||||||
time: time,
|
|
||||||
name: i,
|
|
||||||
hits: cache[i].length,
|
|
||||||
avg: time / cache[i].length,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
reports = reports.sort((a, b) => {
|
|
||||||
if (a.avg < b.avg) return 1;
|
|
||||||
return -1;
|
|
||||||
});
|
|
||||||
|
|
||||||
for (var rep of reports) report += `${rep.name} ${profile.best_t(rep.avg)} (${rep.hits} hits) (total ${profile.best_t(rep.time)})\n`;
|
|
||||||
|
|
||||||
return report;
|
|
||||||
}
|
|
||||||
|
|
||||||
profile.data = {};
|
profile.data = {};
|
||||||
profile.curframe = 0;
|
profile.curframe = 0;
|
||||||
|
|
||||||
profile.snapshot = {};
|
profile.snapshot = {};
|
||||||
|
|
||||||
|
|
||||||
var classes = ["gameobject", "transform", "dsp_node", "texture", "font", "warp_gravity", "warp_damp", "sg_buffer", "datastream", "cpShape", "cpConstraint", "timer", "skin"];
|
var classes = ["gameobject", "transform", "dsp_node", "texture", "font", "warp_gravity", "warp_damp", "sg_buffer", "datastream", "cpShape", "cpConstraint", "timer", "skin"];
|
||||||
var get_snapshot = function()
|
var get_snapshot = function()
|
||||||
{
|
{
|
||||||
var snap = profile.snapshot;
|
var snap = profile.snapshot;
|
||||||
|
|
||||||
|
for (var monitor of monitors) {
|
||||||
|
var stat = monitor.fn();
|
||||||
|
monitor.hook?.(stat);
|
||||||
|
snap[monitor.path] = stat;
|
||||||
|
}
|
||||||
|
|
||||||
snap.actors = actor.__stats();
|
snap.actors = actor.__stats();
|
||||||
snap.memory = os.mem();
|
|
||||||
snap.memory.textures = game.texture.total_size();
|
snap.memory.textures = game.texture.total_size();
|
||||||
snap.memory.texture_vram = game.texture.total_vram();
|
snap.memory.texture_vram = game.texture.total_vram();
|
||||||
|
|
||||||
snap.rusage = os.rusage();
|
|
||||||
snap.rusage.ru_maxrss *= 1024; // delivered in KB; convert here to B
|
|
||||||
|
|
||||||
snap.mallinfo = os.mallinfo();
|
|
||||||
snap.particles = stat_emitters();
|
snap.particles = stat_emitters();
|
||||||
|
|
||||||
snap.obj ??= {};
|
snap.obj ??= {};
|
||||||
|
@ -357,6 +327,21 @@ var get_snapshot = function()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var monitors = [];
|
||||||
|
|
||||||
|
profile.add_custom_monitor = function(path, fn, hook)
|
||||||
|
{
|
||||||
|
monitors.push({
|
||||||
|
path:path,
|
||||||
|
fn:fn,
|
||||||
|
hook:hook
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
profile.add_custom_monitor('rusage', os.rusage, stat => stat.ru_maxrss *= 1024);
|
||||||
|
profile.add_custom_monitor('mallinfo', os.mallinfo);
|
||||||
|
profile.add_custom_monitor('memory', os.mem);
|
||||||
|
|
||||||
var fps = [];
|
var fps = [];
|
||||||
var frame_lead = 1;
|
var frame_lead = 1;
|
||||||
var fps_t = 0;
|
var fps_t = 0;
|
||||||
|
@ -368,7 +353,33 @@ profile.report_frame = function (t) {
|
||||||
fps_t = profile.now();
|
fps_t = profile.now();
|
||||||
get_snapshot();
|
get_snapshot();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
|
profile.reports = {};
|
||||||
|
|
||||||
|
profile.report = function(path)
|
||||||
|
{
|
||||||
|
profile.reports[path] ??= {
|
||||||
|
report: path,
|
||||||
|
time: 0,
|
||||||
|
hits: 0,
|
||||||
|
avg: 0
|
||||||
|
};
|
||||||
|
if (profile.reports[path].st) return;
|
||||||
|
profile.reports[path].st = profile.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
profile.endreport = function(path)
|
||||||
|
{
|
||||||
|
var rep = profile.reports[path];
|
||||||
|
if (!rep || !rep.st) return;
|
||||||
|
rep.hits++;
|
||||||
|
rep.time += profile.now()-rep.st;
|
||||||
|
delete rep.st;
|
||||||
|
rep.avg = rep.time/rep.hits;
|
||||||
|
|
||||||
|
profile.report_cache = Object.values(profile.reports);
|
||||||
|
}
|
||||||
|
|
||||||
function prof_add_stats(obj, stat) {
|
function prof_add_stats(obj, stat) {
|
||||||
for (var i in stat) {
|
for (var i in stat) {
|
||||||
|
|
|
@ -182,6 +182,7 @@ game.tex_hotreload = function () {
|
||||||
if (io.mod(path) > game.texture.time_cache[path]) {
|
if (io.mod(path) > game.texture.time_cache[path]) {
|
||||||
var tex = game.texture.cache[path];
|
var tex = game.texture.cache[path];
|
||||||
game.texture.time_cache[path] = io.mod(path);
|
game.texture.time_cache[path] = io.mod(path);
|
||||||
|
SpriteAnim.hotreload(path);
|
||||||
os.texture_swap(path, game.texture.cache[path]);
|
os.texture_swap(path, game.texture.cache[path]);
|
||||||
for (var sprite of Object.values(allsprites)) {
|
for (var sprite of Object.values(allsprites)) {
|
||||||
if (sprite.texture == tex) {
|
if (sprite.texture == tex) {
|
||||||
|
@ -331,10 +332,10 @@ var Register = {
|
||||||
var guid = prosperon.guid();
|
var guid = prosperon.guid();
|
||||||
|
|
||||||
var dofn = function (...args) {
|
var dofn = function (...args) {
|
||||||
profile.cache(name, oname);
|
profile.report(`call_${name}_${oname}`);
|
||||||
var st = profile.now();
|
var st = profile.now();
|
||||||
fn(...args);
|
fn(...args);
|
||||||
profile.endcache();
|
profile.endreport(`call_${name}_${oname}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
var left = 0;
|
var left = 0;
|
||||||
|
|
|
@ -299,8 +299,6 @@ function make_shader(shader) {
|
||||||
}
|
}
|
||||||
var writejson = `.prosperon/${file.name()}.shader.json`;
|
var writejson = `.prosperon/${file.name()}.shader.json`;
|
||||||
|
|
||||||
profile.cache("shader", file);
|
|
||||||
|
|
||||||
breakme: if (io.exists(writejson)) {
|
breakme: if (io.exists(writejson)) {
|
||||||
var data = json.decode(io.slurp(writejson));
|
var data = json.decode(io.slurp(writejson));
|
||||||
var filemod = io.mod(writejson);
|
var filemod = io.mod(writejson);
|
||||||
|
@ -311,7 +309,6 @@ function make_shader(shader) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
profile.endcache(" [cached]");
|
|
||||||
var shaderobj = json.decode(io.slurp(writejson));
|
var shaderobj = json.decode(io.slurp(writejson));
|
||||||
var obj = shaderobj[os.sys()];
|
var obj = shaderobj[os.sys()];
|
||||||
obj.pipe = render.pipeline(obj);
|
obj.pipe = render.pipeline(obj);
|
||||||
|
@ -320,6 +317,8 @@ function make_shader(shader) {
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
profile.report(`shader_${file}`);
|
||||||
|
|
||||||
var compiled = create_shader_obj(file);
|
var compiled = create_shader_obj(file);
|
||||||
io.slurpwrite(writejson, json.encode(compiled));
|
io.slurpwrite(writejson, json.encode(compiled));
|
||||||
var obj = compiled[os.sys()];
|
var obj = compiled[os.sys()];
|
||||||
|
@ -328,6 +327,8 @@ function make_shader(shader) {
|
||||||
shader_cache[file] = obj;
|
shader_cache[file] = obj;
|
||||||
shader_times[file] = io.mod(file);
|
shader_times[file] = io.mod(file);
|
||||||
|
|
||||||
|
profile.endreport(`shader_${file}`);
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -524,7 +525,7 @@ render.draw_gizmos = true;
|
||||||
|
|
||||||
render.buckets = [];
|
render.buckets = [];
|
||||||
render.sprites = function render_sprites() {
|
render.sprites = function render_sprites() {
|
||||||
profile.frame("drawing");
|
profile.report("drawing");
|
||||||
render.use_shader(spritessboshader);
|
render.use_shader(spritessboshader);
|
||||||
var buckets = component.sprite_buckets();
|
var buckets = component.sprite_buckets();
|
||||||
for (var l in buckets) {
|
for (var l in buckets) {
|
||||||
|
@ -538,7 +539,7 @@ render.sprites = function render_sprites() {
|
||||||
render.draw(shape.quad, sprite_ssbo, sparray.length);
|
render.draw(shape.quad, sprite_ssbo, sparray.length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
profile.endframe();
|
profile.endreport("drawing");
|
||||||
};
|
};
|
||||||
|
|
||||||
render.circle = function render_circle(pos, radius, color, inner_radius = 1) {
|
render.circle = function render_circle(pos, radius, color, inner_radius = 1) {
|
||||||
|
@ -843,9 +844,9 @@ render.rectangle.doc = "Draw a rectangle, with its corners at lowerleft and uppe
|
||||||
|
|
||||||
render.draw = function render_draw(mesh, ssbo, inst = 1, e_start = 0) {
|
render.draw = function render_draw(mesh, ssbo, inst = 1, e_start = 0) {
|
||||||
sg_bind(mesh, ssbo);
|
sg_bind(mesh, ssbo);
|
||||||
profile.frame("gpu");
|
profile.report("gpu_draw");
|
||||||
render.spdraw(e_start, cur.bind.count, inst);
|
render.spdraw(e_start, cur.bind.count, inst);
|
||||||
profile.endframe();
|
profile.endreport("gpu_draw");
|
||||||
};
|
};
|
||||||
|
|
||||||
// Returns an array in the form of [left, bottom, right, top] in pixels of the camera to render to
|
// Returns an array in the form of [left, bottom, right, top] in pixels of the camera to render to
|
||||||
|
@ -1030,22 +1031,22 @@ var imgui_fn = function () {
|
||||||
};
|
};
|
||||||
|
|
||||||
prosperon.render = function () {
|
prosperon.render = function () {
|
||||||
profile.frame("world");
|
profile.report("world");
|
||||||
render.set_camera(prosperon.camera);
|
render.set_camera(prosperon.camera);
|
||||||
profile.frame("sprites");
|
profile.report("sprites");
|
||||||
if (render.draw_sprites) render.sprites();
|
if (render.draw_sprites) render.sprites();
|
||||||
if (render.draw_particles) draw_emitters();
|
if (render.draw_particles) draw_emitters();
|
||||||
profile.endframe();
|
profile.endreport("sprites");
|
||||||
profile.frame("draws");
|
profile.report("draws");
|
||||||
prosperon.draw();
|
prosperon.draw();
|
||||||
// sgl.draw();
|
// sgl.draw();
|
||||||
profile.endframe();
|
profile.endreport("draws");
|
||||||
|
profile.endreport("world");
|
||||||
prosperon.hudcam.size = prosperon.camera.size;
|
prosperon.hudcam.size = prosperon.camera.size;
|
||||||
prosperon.hudcam.transform.pos = [prosperon.hudcam.size.x / 2, prosperon.hudcam.size.y / 2, -100];
|
prosperon.hudcam.transform.pos = [prosperon.hudcam.size.x / 2, prosperon.hudcam.size.y / 2, -100];
|
||||||
render.set_camera(prosperon.hudcam);
|
render.set_camera(prosperon.hudcam);
|
||||||
|
|
||||||
profile.endframe();
|
profile.report("hud");
|
||||||
profile.frame("hud");
|
|
||||||
if (render.draw_hud) prosperon.hud();
|
if (render.draw_hud) prosperon.hud();
|
||||||
render.flush_text();
|
render.flush_text();
|
||||||
|
|
||||||
|
@ -1055,22 +1056,20 @@ prosperon.render = function () {
|
||||||
|
|
||||||
render.end_pass();
|
render.end_pass();
|
||||||
|
|
||||||
profile.endframe();
|
profile.endreport("hud");
|
||||||
profile.endframe();
|
|
||||||
profile.endframe();
|
|
||||||
/* draw the image of the game world first */
|
/* draw the image of the game world first */
|
||||||
render.glue_pass();
|
render.glue_pass();
|
||||||
profile.frame("frame");
|
profile.report("frame");
|
||||||
profile.frame("render");
|
profile.report("render");
|
||||||
profile.frame("post process");
|
profile.report("post process");
|
||||||
render.viewport(...prosperon.camera.view());
|
render.viewport(...prosperon.camera.view());
|
||||||
render.use_shader(render.postshader);
|
render.use_shader(render.postshader);
|
||||||
render.use_mat({ diffuse: prosperon.screencolor });
|
render.use_mat({ diffuse: prosperon.screencolor });
|
||||||
render.draw(shape.quad);
|
render.draw(shape.quad);
|
||||||
|
|
||||||
profile.endframe();
|
profile.endreport("post process");
|
||||||
|
|
||||||
profile.frame("app");
|
profile.report("app");
|
||||||
|
|
||||||
// Flush & render
|
// Flush & render
|
||||||
prosperon.appcam.transform.pos = [window.size.x / 2, window.size.y / 2, -100];
|
prosperon.appcam.transform.pos = [window.size.x / 2, window.size.y / 2, -100];
|
||||||
|
@ -1089,13 +1088,13 @@ prosperon.render = function () {
|
||||||
|
|
||||||
check_flush();
|
check_flush();
|
||||||
|
|
||||||
profile.endframe();
|
profile.endreport("app");
|
||||||
|
|
||||||
profile.frame("imgui");
|
profile.report("imgui");
|
||||||
|
|
||||||
if (debug.show) imgui_fn();
|
if (debug.show) imgui_fn();
|
||||||
|
|
||||||
profile.endframe();
|
profile.endreport("imgui");
|
||||||
|
|
||||||
render.end_pass();
|
render.end_pass();
|
||||||
|
|
||||||
|
@ -1106,7 +1105,7 @@ prosperon.render = function () {
|
||||||
};
|
};
|
||||||
|
|
||||||
prosperon.process = function process() {
|
prosperon.process = function process() {
|
||||||
profile.frame("frame");
|
profile.report("frame");
|
||||||
var dt = profile.secs(profile.now()) - frame_t;
|
var dt = profile.secs(profile.now()) - frame_t;
|
||||||
frame_t = profile.secs(profile.now());
|
frame_t = profile.secs(profile.now());
|
||||||
|
|
||||||
|
@ -1118,20 +1117,20 @@ prosperon.process = function process() {
|
||||||
var cycles = os.check_cycles();
|
var cycles = os.check_cycles();
|
||||||
if (cycles) say(cycles);
|
if (cycles) say(cycles);
|
||||||
|
|
||||||
profile.frame("app update");
|
profile.report("app update");
|
||||||
prosperon.appupdate(dt);
|
prosperon.appupdate(dt);
|
||||||
profile.endframe();
|
profile.endreport("app update");
|
||||||
|
|
||||||
profile.frame("input");
|
profile.report("input");
|
||||||
input.procdown();
|
input.procdown();
|
||||||
profile.endframe();
|
profile.endreport("input");
|
||||||
|
|
||||||
if (sim.mode === "play" || sim.mode === "step") {
|
if (sim.mode === "play" || sim.mode === "step") {
|
||||||
profile.frame("update");
|
profile.report("update");
|
||||||
prosperon.update(dt * game.timescale);
|
prosperon.update(dt * game.timescale);
|
||||||
update_emitters(dt * game.timescale);
|
update_emitters(dt * game.timescale);
|
||||||
os.update_timers(dt * game.timescale);
|
os.update_timers(dt * game.timescale);
|
||||||
profile.endframe();
|
profile.endreport("update");
|
||||||
if (sim.mode === "step") sim.pause();
|
if (sim.mode === "step") sim.pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1139,7 +1138,7 @@ prosperon.process = function process() {
|
||||||
sst = profile.now();
|
sst = profile.now();
|
||||||
|
|
||||||
if (sim.mode === "play" || sim.mode === "step") {
|
if (sim.mode === "play" || sim.mode === "step") {
|
||||||
profile.frame("physics");
|
profile.report("physics");
|
||||||
physlag += dt;
|
physlag += dt;
|
||||||
|
|
||||||
while (physlag > physics.delta) {
|
while (physlag > physics.delta) {
|
||||||
|
@ -1147,17 +1146,18 @@ prosperon.process = function process() {
|
||||||
prosperon.phys2d_step(physics.delta * game.timescale);
|
prosperon.phys2d_step(physics.delta * game.timescale);
|
||||||
prosperon.physupdate(physics.delta * game.timescale);
|
prosperon.physupdate(physics.delta * game.timescale);
|
||||||
}
|
}
|
||||||
profile.endframe();
|
profile.endreport("physics");
|
||||||
profile.pushdata(profile.data.cpu.physics, profile.now() - sst);
|
profile.pushdata(profile.data.cpu.physics, profile.now() - sst);
|
||||||
sst = profile.now();
|
sst = profile.now();
|
||||||
}
|
}
|
||||||
|
|
||||||
profile.frame("render");
|
profile.report("render");
|
||||||
prosperon.window_render(window.size);
|
prosperon.window_render(window.size);
|
||||||
|
|
||||||
prosperon.render();
|
prosperon.render();
|
||||||
|
profile.endreport("render");
|
||||||
profile.pushdata(profile.data.cpu.render, profile.now() - sst);
|
profile.pushdata(profile.data.cpu.render, profile.now() - sst);
|
||||||
profile.endframe();
|
profile.endreport('frame');
|
||||||
profile.endframe();
|
|
||||||
|
|
||||||
profile.capture_data();
|
profile.capture_data();
|
||||||
};
|
};
|
||||||
|
|
|
@ -115,7 +115,7 @@ Ease.elastic.c5 = (2 * Math.PI) / 4.5;
|
||||||
var tween = function (from, to, time, fn, endfn) {
|
var tween = function (from, to, time, fn, endfn) {
|
||||||
var start = profile.secs(profile.now());
|
var start = profile.secs(profile.now());
|
||||||
var update = function (dt) {
|
var update = function (dt) {
|
||||||
profile.frame("tween");
|
profile.report("tween");
|
||||||
var elapsed = profile.secs(profile.now()) - start;
|
var elapsed = profile.secs(profile.now()) - start;
|
||||||
fn(from.lerp(to, elapsed / time));
|
fn(from.lerp(to, elapsed / time));
|
||||||
if (elapsed >= time) {
|
if (elapsed >= time) {
|
||||||
|
@ -124,7 +124,7 @@ var tween = function (from, to, time, fn, endfn) {
|
||||||
stop();
|
stop();
|
||||||
endfn?.();
|
endfn?.();
|
||||||
}
|
}
|
||||||
profile.endframe();
|
profile.endreport("tween");
|
||||||
};
|
};
|
||||||
var stop = Register.update.register(update);
|
var stop = Register.update.register(update);
|
||||||
return stop;
|
return stop;
|
||||||
|
|
|
@ -23,19 +23,13 @@ struct rect ST_UNIT = {0.f, 0.f, 1.f, 1.f};
|
||||||
|
|
||||||
static inline void write_pixel(unsigned char *data, int idx, rgba color)
|
static inline void write_pixel(unsigned char *data, int idx, rgba color)
|
||||||
{
|
{
|
||||||
data[idx] = color.r;
|
memcpy(data+idx, &color, sizeof(color));
|
||||||
data[idx+1] = color.g;
|
|
||||||
data[idx+2] = color.b;
|
|
||||||
data[idx+3] = color.a;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline rgba get_pixel(unsigned char *data, int idx)
|
static inline rgba get_pixel(unsigned char *data, int idx)
|
||||||
{
|
{
|
||||||
rgba color;
|
rgba color;
|
||||||
color.r = data[idx];
|
memcpy(&color, data+idx, sizeof(color));
|
||||||
color.g = data[idx+1];
|
|
||||||
color.b = data[idx+2];
|
|
||||||
color.a = data[idx+3];
|
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -328,16 +322,16 @@ void texture_save(texture *tex, const char *file)
|
||||||
// sw the width of the destination to take in pixels
|
// sw the width of the destination to take in pixels
|
||||||
// sh the height of the destination to take in pixels
|
// sh the height of the destination to take in pixels
|
||||||
int texture_blit(texture *dst, texture *src, rect dstrect, rect srcrect, int tile) {
|
int texture_blit(texture *dst, texture *src, rect dstrect, rect srcrect, int tile) {
|
||||||
// if (!src || !dst || !src->data || !dst->data) return 0;
|
if (!src || !dst || !src->data || !dst->data) return 0;
|
||||||
|
|
||||||
float scaleX = srcrect.w / dstrect.w;
|
float scaleX = srcrect.w / dstrect.w;
|
||||||
float scaleY = srcrect.h / dstrect.h;
|
float scaleY = srcrect.h / dstrect.h;
|
||||||
|
|
||||||
/* if (srcrect.x < 0 || srcrect.y < 0 || srcrect.x + srcrect.w > src->width ||
|
if (srcrect.x < 0 || srcrect.y < 0 || srcrect.x + srcrect.w > src->width ||
|
||||||
dstrect.x < 0 || dstrect.y < 0 || dstrect.x + dstrect.w > dst->width ||
|
dstrect.x < 0 || dstrect.y < 0 || dstrect.x + dstrect.w > dst->width ||
|
||||||
srcrect.y + srcrect.h > src->height || dstrect.y + dstrect.h > dst->height) {
|
srcrect.y + srcrect.h > src->height || dstrect.y + dstrect.h > dst->height) {
|
||||||
return false; // Rectangles exceed texture bounds
|
return false; // Rectangles exceed texture bounds
|
||||||
}*/
|
}
|
||||||
|
|
||||||
for (int dstY = 0; dstY < dstrect.h; ++dstY) {
|
for (int dstY = 0; dstY < dstrect.h; ++dstY) {
|
||||||
for (int dstX = 0; dstX < dstrect.w; ++dstX) {
|
for (int dstX = 0; dstX < dstrect.w; ++dstX) {
|
||||||
|
|
Loading…
Reference in a new issue