tracy is cell level now
This commit is contained in:
@@ -148,7 +148,6 @@ if host_machine.system() != 'emscripten'
|
|||||||
deps += dependency('enet', static:true)
|
deps += dependency('enet', static:true)
|
||||||
src += 'qjs_enet.c'
|
src += 'qjs_enet.c'
|
||||||
|
|
||||||
src += 'qjs_tracy.c'
|
|
||||||
tracy_opts = ['fibers=true', 'on_demand=true']
|
tracy_opts = ['fibers=true', 'on_demand=true']
|
||||||
add_project_arguments('-DTRACY_ENABLE', language:['c','cpp'])
|
add_project_arguments('-DTRACY_ENABLE', language:['c','cpp'])
|
||||||
deps += dependency('tracy', static:true, default_options:tracy_opts)
|
deps += dependency('tracy', static:true, default_options:tracy_opts)
|
||||||
|
|||||||
@@ -440,12 +440,12 @@ $_.contact = function(callback, record) {
|
|||||||
$_.contact[prosperon.DOC] = `The contact function sends a message to a portal on another machine to obtain an actor object.
|
$_.contact[prosperon.DOC] = `The contact function sends a message to a portal on another machine to obtain an actor object.
|
||||||
The callback is a function with a actor input and a reason input. If successful, actor is bound to an actor object. If not successful, actor is null and reason may contain an explanation.`
|
The callback is a function with a actor input and a reason input. If successful, actor is bound to an actor object. If not successful, actor is null and reason may contain an explanation.`
|
||||||
|
|
||||||
$_.receiver = function(fn) {
|
$_.receiver = function receiver(fn) {
|
||||||
receive_fn = fn
|
receive_fn = fn
|
||||||
}
|
}
|
||||||
$_.receiver[prosperon.DOC] = "registers a function that will receive all messages..."
|
$_.receiver[prosperon.DOC] = "registers a function that will receive all messages..."
|
||||||
|
|
||||||
$_.start = function(cb, prg, arg) {
|
$_.start = function start(cb, prg, arg) {
|
||||||
if (dying) {
|
if (dying) {
|
||||||
console.warn(`Cannot start an underling in the same turn as we're stopping`)
|
console.warn(`Cannot start an underling in the same turn as we're stopping`)
|
||||||
return
|
return
|
||||||
@@ -460,7 +460,7 @@ $_.start = function(cb, prg, arg) {
|
|||||||
}
|
}
|
||||||
$_.start[prosperon.DOC] = "The start function creates a new actor..."
|
$_.start[prosperon.DOC] = "The start function creates a new actor..."
|
||||||
|
|
||||||
$_.stop = function(actor) {
|
$_.stop = function stop(actor) {
|
||||||
if (!actor) {
|
if (!actor) {
|
||||||
destroyself()
|
destroyself()
|
||||||
return
|
return
|
||||||
@@ -474,19 +474,23 @@ $_.stop = function(actor) {
|
|||||||
}
|
}
|
||||||
$_.stop[prosperon.DOC] = "The stop function stops an underling."
|
$_.stop[prosperon.DOC] = "The stop function stops an underling."
|
||||||
|
|
||||||
$_.unneeded = function(fn, seconds) {
|
$_.unneeded = function unneeded(fn, seconds) {
|
||||||
actor_mod.unneeded(fn, seconds)
|
actor_mod.unneeded(fn, seconds)
|
||||||
}
|
}
|
||||||
$_.unneeded[prosperon.DOC] = "registers a function that is called when the actor..."
|
$_.unneeded[prosperon.DOC] = "registers a function that is called when the actor..."
|
||||||
|
|
||||||
$_.delay = function(fn, seconds) {
|
$_.delay = function delay(fn, seconds) {
|
||||||
var id = actor_mod.delay(fn, seconds)
|
function delay_turn() {
|
||||||
|
fn()
|
||||||
|
send_messages()
|
||||||
|
}
|
||||||
|
var id = actor_mod.delay(delay_turn, seconds)
|
||||||
return function() { actor_mod.removetimer(id) }
|
return function() { actor_mod.removetimer(id) }
|
||||||
}
|
}
|
||||||
$_.delay[prosperon.DOC] = "used to schedule the invocation of a function..."
|
$_.delay[prosperon.DOC] = "used to schedule the invocation of a function..."
|
||||||
|
|
||||||
var couplings = new Set()
|
var couplings = new Set()
|
||||||
$_.couple = function(actor) {
|
$_.couple = function couple(actor) {
|
||||||
console.log(`coupled to ${actor.__ACTORDATA__.id}`)
|
console.log(`coupled to ${actor.__ACTORDATA__.id}`)
|
||||||
couplings.add(actor.__ACTORDATA__.id)
|
couplings.add(actor.__ACTORDATA__.id)
|
||||||
}
|
}
|
||||||
@@ -604,15 +608,18 @@ else prosperon.id = prosperon.args.id
|
|||||||
|
|
||||||
$_.__ACTORDATA__.id = prosperon.id
|
$_.__ACTORDATA__.id = prosperon.id
|
||||||
|
|
||||||
actor_mod.register_actor(prosperon.id, function(msg) {
|
function turn(msg)
|
||||||
|
{
|
||||||
try {
|
try {
|
||||||
handle_message(msg)
|
handle_message(msg)
|
||||||
send_messages()
|
send_messages()
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
message_queue = []
|
message_queue = []
|
||||||
throw err
|
throw err
|
||||||
}
|
}
|
||||||
}, prosperon.args.main)
|
}
|
||||||
|
|
||||||
|
actor_mod.register_actor(prosperon.id, turn, prosperon.args.main)
|
||||||
|
|
||||||
if (prosperon.args.overling) overling = json.decode(prosperon.args.overling)
|
if (prosperon.args.overling) overling = json.decode(prosperon.args.overling)
|
||||||
|
|
||||||
@@ -626,6 +633,8 @@ if (!prosperon.args.program)
|
|||||||
|
|
||||||
if (typeof prosperon.args.program !== 'string')
|
if (typeof prosperon.args.program !== 'string')
|
||||||
prosperon.args.program = 'main.js';
|
prosperon.args.program = 'main.js';
|
||||||
|
|
||||||
|
actor_mod.setname(prosperon.args.program)
|
||||||
|
|
||||||
function destroyself() {
|
function destroyself() {
|
||||||
console.log(`Got the message to destroy self.`)
|
console.log(`Got the message to destroy self.`)
|
||||||
@@ -699,12 +708,10 @@ function enet_check()
|
|||||||
{
|
{
|
||||||
if (portal) portal.service(handle_host)
|
if (portal) portal.service(handle_host)
|
||||||
|
|
||||||
send_messages();
|
|
||||||
|
|
||||||
$_.delay(enet_check, service_delay);
|
$_.delay(enet_check, service_delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
enet_check();
|
//enet_check();
|
||||||
|
|
||||||
// Finally, run the program
|
// Finally, run the program
|
||||||
var prog = io.slurp(prosperon.args.program)
|
var prog = io.slurp(prosperon.args.program)
|
||||||
@@ -712,5 +719,7 @@ var prog_script = `(function ${prosperon.args.program.name()}($_) { ${prog} })`
|
|||||||
var val = js.eval(prosperon.args.program, prog_script)($_)
|
var val = js.eval(prosperon.args.program, prog_script)($_)
|
||||||
if (val)
|
if (val)
|
||||||
throw new Error('Program must not return anything');
|
throw new Error('Program must not return anything');
|
||||||
|
|
||||||
|
send_messages()
|
||||||
|
|
||||||
})()
|
})()
|
||||||
@@ -18,7 +18,7 @@ function within_wedge(dx, dy, start, end, full_circle) {
|
|||||||
return t >= start || t <= end
|
return t >= start || t <= end
|
||||||
}
|
}
|
||||||
|
|
||||||
rasterize.ellipse = function(pos, radii, opt) {
|
rasterize.ellipse = function ellipse(pos, radii, opt) {
|
||||||
opt = opt || {}
|
opt = opt || {}
|
||||||
var rx = radii[0], ry = radii[1]
|
var rx = radii[0], ry = radii[1]
|
||||||
if (rx <= 0 || ry <= 0) return []
|
if (rx <= 0 || ry <= 0) return []
|
||||||
@@ -104,11 +104,11 @@ rasterize.ellipse = function(pos, radii, opt) {
|
|||||||
return {type: 'rects', data: strips}
|
return {type: 'rects', data: strips}
|
||||||
}
|
}
|
||||||
|
|
||||||
rasterize.circle = function(pos, radius, opt) {
|
rasterize.circle = function circle(pos, radius, opt) {
|
||||||
return rasterize.ellipse(pos, [radius, radius], opt)
|
return rasterize.ellipse(pos, [radius, radius], opt)
|
||||||
}
|
}
|
||||||
|
|
||||||
rasterize.outline_rect = function(rect, thickness) {
|
rasterize.outline_rect = function outline_rect(rect, thickness) {
|
||||||
if (thickness <= 0) {
|
if (thickness <= 0) {
|
||||||
return {type: 'rect', data: rect}
|
return {type: 'rect', data: rect}
|
||||||
}
|
}
|
||||||
@@ -133,7 +133,7 @@ rasterize.outline_rect = function(rect, thickness) {
|
|||||||
]}
|
]}
|
||||||
}
|
}
|
||||||
|
|
||||||
rasterize.round_rect = function(rect, radius, thickness) {
|
rasterize.round_rect = function round_rect(rect, radius, thickness) {
|
||||||
thickness = thickness || 1
|
thickness = thickness || 1
|
||||||
|
|
||||||
if (thickness <= 0) {
|
if (thickness <= 0) {
|
||||||
@@ -187,7 +187,7 @@ rasterize.round_rect = function(rect, radius, thickness) {
|
|||||||
return {type: 'rects', data: rects.concat(strips)}
|
return {type: 'rects', data: rects.concat(strips)}
|
||||||
}
|
}
|
||||||
|
|
||||||
rasterize.fill_round_rect = function(rect, radius) {
|
rasterize.fill_round_rect = function fill_round_rect(rect, radius) {
|
||||||
radius = Math.min(radius, rect.width >> 1, rect.height >> 1)
|
radius = Math.min(radius, rect.width >> 1, rect.height >> 1)
|
||||||
|
|
||||||
var x0 = rect.x,
|
var x0 = rect.x,
|
||||||
|
|||||||
@@ -1487,10 +1487,6 @@ JS_SetPrototype(js, js_##NAME, PARENT); \
|
|||||||
JSValue js_layout_use(JSContext *js);
|
JSValue js_layout_use(JSContext *js);
|
||||||
JSValue js_miniz_use(JSContext *js);
|
JSValue js_miniz_use(JSContext *js);
|
||||||
|
|
||||||
#ifdef TRACY_ENABLE
|
|
||||||
JSValue js_tracy_use(JSContext *js);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
JSValue js_graphics_use(JSContext *js) {
|
JSValue js_graphics_use(JSContext *js) {
|
||||||
JSValue mod = JS_NewObject(js);
|
JSValue mod = JS_NewObject(js);
|
||||||
JS_SetPropertyFunctionList(js,mod,js_graphics_funcs,countof(js_graphics_funcs));
|
JS_SetPropertyFunctionList(js,mod,js_graphics_funcs,countof(js_graphics_funcs));
|
||||||
@@ -1573,10 +1569,6 @@ void ffi_load(JSContext *js)
|
|||||||
arrput(rt->module_registry, MISTLINE(sprite));
|
arrput(rt->module_registry, MISTLINE(sprite));
|
||||||
arrput(rt->module_registry, MISTLINE(transform));
|
arrput(rt->module_registry, MISTLINE(transform));
|
||||||
|
|
||||||
#ifdef TRACY_ENABLE
|
|
||||||
arrput(rt->module_registry, MISTLINE(tracy));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef NSTEAM
|
#ifndef NSTEAM
|
||||||
arrput(rt->module_registry, MISTLINE(steam));
|
arrput(rt->module_registry, MISTLINE(steam));
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -331,7 +331,7 @@ void actor_turn(prosperon_rt *actor, int greedy)
|
|||||||
{
|
{
|
||||||
SDL_LockMutex(actor->turn);
|
SDL_LockMutex(actor->turn);
|
||||||
#ifdef TRACY_ENABLE
|
#ifdef TRACY_ENABLE
|
||||||
// TracyCFiberEnter(actor->id);
|
TracyCFiberEnter(actor->name);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SDL_LockMutex(actor->msg_mutex);
|
SDL_LockMutex(actor->msg_mutex);
|
||||||
@@ -420,7 +420,7 @@ void actor_turn(prosperon_rt *actor, int greedy)
|
|||||||
|
|
||||||
END:
|
END:
|
||||||
#ifdef TRACY_ENABLE
|
#ifdef TRACY_ENABLE
|
||||||
// TracyCFiberLeave(actor->id);
|
TracyCFiberLeave(actor->name);
|
||||||
#endif
|
#endif
|
||||||
SDL_UnlockMutex(actor->turn);
|
SDL_UnlockMutex(actor->turn);
|
||||||
set_actor_state(actor);
|
set_actor_state(actor);
|
||||||
@@ -428,7 +428,7 @@ void actor_turn(prosperon_rt *actor, int greedy)
|
|||||||
|
|
||||||
KILL:
|
KILL:
|
||||||
#ifdef TRACY_ENABLE
|
#ifdef TRACY_ENABLE
|
||||||
// TracyCFiberLeave(actor->id);
|
TracyCFiberLeave(actor->id);
|
||||||
#endif
|
#endif
|
||||||
SDL_UnlockMutex(actor->turn);
|
SDL_UnlockMutex(actor->turn);
|
||||||
actor_free(actor);
|
actor_free(actor);
|
||||||
@@ -581,6 +581,56 @@ JSValue js_actor_removetimer(JSContext *js, JSValue self, int argc, JSValue *arg
|
|||||||
return JS_UNDEFINED;
|
return JS_UNDEFINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wrapper struct to keep the array pointer stable
|
||||||
|
typedef struct {
|
||||||
|
TracyCZoneCtx *arr; // stb_ds dynamic array
|
||||||
|
} tracy_stack_t;
|
||||||
|
|
||||||
|
// Global TLS ID for the Tracy stack
|
||||||
|
static SDL_TLSID tracy_stack_id = {0};
|
||||||
|
|
||||||
|
// Cleanup function for the wrapper struct
|
||||||
|
static void tracy_cleanup_stack(void *value)
|
||||||
|
{
|
||||||
|
tracy_stack_t *stack = value;
|
||||||
|
if (stack) {
|
||||||
|
arrfree(stack->arr);
|
||||||
|
free(stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get or initialize the thread-local Tracy stack
|
||||||
|
static tracy_stack_t *get_tracy_stack(void)
|
||||||
|
{
|
||||||
|
tracy_stack_t *stack = SDL_GetTLS(&tracy_stack_id);
|
||||||
|
if (!stack) {
|
||||||
|
stack = malloc(sizeof(tracy_stack_t));
|
||||||
|
stack->arr = NULL; // stb_ds starts with NULL
|
||||||
|
arrsetcap(stack->arr, 5); // Initial capacity
|
||||||
|
SDL_SetTLS(&tracy_stack_id, stack, tracy_cleanup_stack);
|
||||||
|
}
|
||||||
|
return stack;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tracy_call_hook(JSContext *js, JSValue fn)
|
||||||
|
{
|
||||||
|
tracy_stack_t *stack = get_tracy_stack();
|
||||||
|
js_debug debug;
|
||||||
|
js_debug_info(js, fn, &debug);
|
||||||
|
|
||||||
|
uint64_t srcloc = ___tracy_alloc_srcloc(debug.line, debug.filename, strlen(debug.filename), debug.name, strlen(debug.name), debug.unique);
|
||||||
|
arrput(stack->arr, ___tracy_emit_zone_begin_alloc(srcloc, 1));
|
||||||
|
|
||||||
|
free_js_debug_info(js, &debug);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tracy_end_hook(JSContext *js, JSValue fn)
|
||||||
|
{
|
||||||
|
tracy_stack_t *stack = get_tracy_stack();
|
||||||
|
if (arrlen(stack->arr) > 0)
|
||||||
|
___tracy_emit_zone_end(arrpop(stack->arr));
|
||||||
|
}
|
||||||
|
|
||||||
void script_startup(prosperon_rt *prt, void (*hook)(JSContext*))
|
void script_startup(prosperon_rt *prt, void (*hook)(JSContext*))
|
||||||
{
|
{
|
||||||
JSRuntime *rt;
|
JSRuntime *rt;
|
||||||
@@ -590,6 +640,12 @@ void script_startup(prosperon_rt *prt, void (*hook)(JSContext*))
|
|||||||
rt = JS_NewRuntime();
|
rt = JS_NewRuntime();
|
||||||
#endif
|
#endif
|
||||||
JSContext *js = JS_NewContextRaw(rt);
|
JSContext *js = JS_NewContextRaw(rt);
|
||||||
|
|
||||||
|
#ifdef TRACY_ENABLE
|
||||||
|
js_debug_sethook(js, tracy_call_hook, JS_HOOK_CALL);
|
||||||
|
js_debug_sethook(js, tracy_end_hook, JS_HOOK_RET);
|
||||||
|
#endif
|
||||||
|
|
||||||
JS_AddIntrinsicBaseObjects(js);
|
JS_AddIntrinsicBaseObjects(js);
|
||||||
JS_AddIntrinsicEval(js);
|
JS_AddIntrinsicEval(js);
|
||||||
JS_AddIntrinsicRegExp(js);
|
JS_AddIntrinsicRegExp(js);
|
||||||
@@ -1440,6 +1496,8 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
/* Create the initial actor from the main command line. */
|
/* Create the initial actor from the main command line. */
|
||||||
create_actor(argc, argv, NULL);
|
create_actor(argc, argv, NULL);
|
||||||
|
|
||||||
|
cores = 1;
|
||||||
|
|
||||||
/* Start the thread that pumps ready actors, one per logical core. */
|
/* Start the thread that pumps ready actors, one per logical core. */
|
||||||
for (int i = 0; i < cores; i++) {
|
for (int i = 0; i < cores; i++) {
|
||||||
|
|||||||
@@ -67,6 +67,8 @@ typedef struct prosperon_rt {
|
|||||||
int main_thread_only;
|
int main_thread_only;
|
||||||
|
|
||||||
JSValue actor_sym;
|
JSValue actor_sym;
|
||||||
|
|
||||||
|
const char *name; // human friendly name
|
||||||
} prosperon_rt;
|
} prosperon_rt;
|
||||||
|
|
||||||
extern SDL_ThreadID main_thread;
|
extern SDL_ThreadID main_thread;
|
||||||
|
|||||||
@@ -156,6 +156,11 @@ JSC_CCALL(os_destroy,
|
|||||||
rt->need_stop = 1;
|
rt->need_stop = 1;
|
||||||
)
|
)
|
||||||
|
|
||||||
|
JSC_SCALL(actor_setname,
|
||||||
|
prosperon_rt *rt = JS_GetContextOpaque(js);
|
||||||
|
rt->name = strdup(str);
|
||||||
|
)
|
||||||
|
|
||||||
static const JSCFunctionListEntry js_actor_funcs[] = {
|
static const JSCFunctionListEntry js_actor_funcs[] = {
|
||||||
MIST_FUNC_DEF(os, createactor, 1),
|
MIST_FUNC_DEF(os, createactor, 1),
|
||||||
MIST_FUNC_DEF(os, mailbox_push, 2),
|
MIST_FUNC_DEF(os, mailbox_push, 2),
|
||||||
@@ -165,6 +170,7 @@ static const JSCFunctionListEntry js_actor_funcs[] = {
|
|||||||
MIST_FUNC_DEF(os, register_actor, 2),
|
MIST_FUNC_DEF(os, register_actor, 2),
|
||||||
MIST_FUNC_DEF(os, unneeded, 2),
|
MIST_FUNC_DEF(os, unneeded, 2),
|
||||||
MIST_FUNC_DEF(os, destroy, 0),
|
MIST_FUNC_DEF(os, destroy, 0),
|
||||||
|
MIST_FUNC_DEF(actor, setname, 1),
|
||||||
};
|
};
|
||||||
|
|
||||||
JSValue js_actor_use(JSContext *js) {
|
JSValue js_actor_use(JSContext *js) {
|
||||||
|
|||||||
@@ -260,6 +260,37 @@ static JSValue js_os_rusage(JSContext *js, JSValue self, int argc, JSValue *argv
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef TRACY_ENABLE
|
||||||
|
#include <tracy/TracyC.h>
|
||||||
|
JSC_CCALL(os_frame,
|
||||||
|
TracyCFrameMark
|
||||||
|
)
|
||||||
|
|
||||||
|
JSC_CCALL(os_trace_img,
|
||||||
|
size_t len;
|
||||||
|
double width, height;
|
||||||
|
JS_ToFloat64(js,&width,argv[1]);
|
||||||
|
JS_ToFloat64(js,&height,argv[2]);
|
||||||
|
___tracy_emit_frame_image(JS_GetArrayBuffer(js, &len, argv[0]), width, height, 0, 0);
|
||||||
|
)
|
||||||
|
|
||||||
|
JSC_CCALL(os_trace_message,
|
||||||
|
size_t len;
|
||||||
|
const char *str = JS_ToCStringLen(js, &len, argv[0]);
|
||||||
|
TracyCMessage(str,len);
|
||||||
|
JS_FreeCString(js,str);
|
||||||
|
)
|
||||||
|
#else
|
||||||
|
JSC_CCALL(os_frame,
|
||||||
|
)
|
||||||
|
|
||||||
|
JSC_CCALL(os_trace_img,
|
||||||
|
)
|
||||||
|
|
||||||
|
JSC_CCALL(os_trace_message,
|
||||||
|
)
|
||||||
|
#endif
|
||||||
|
|
||||||
static const JSCFunctionListEntry js_os_funcs[] = {
|
static const JSCFunctionListEntry js_os_funcs[] = {
|
||||||
MIST_FUNC_DEF(os, platform, 0),
|
MIST_FUNC_DEF(os, platform, 0),
|
||||||
MIST_FUNC_DEF(os, arch, 0),
|
MIST_FUNC_DEF(os, arch, 0),
|
||||||
@@ -275,6 +306,7 @@ static const JSCFunctionListEntry js_os_funcs[] = {
|
|||||||
MIST_FUNC_DEF(os, rusage, 0),
|
MIST_FUNC_DEF(os, rusage, 0),
|
||||||
MIST_FUNC_DEF(os, mallinfo, 0),
|
MIST_FUNC_DEF(os, mallinfo, 0),
|
||||||
MIST_FUNC_DEF(os, buffer2string, 1),
|
MIST_FUNC_DEF(os, buffer2string, 1),
|
||||||
|
MIST_FUNC_DEF(os, frame, 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
JSValue js_os_use(JSContext *js) {
|
JSValue js_os_use(JSContext *js) {
|
||||||
|
|||||||
@@ -1,591 +0,0 @@
|
|||||||
#include <quickjs.h>
|
|
||||||
#include <tracy/TracyC.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include "render.h"
|
|
||||||
#include <SDL3/SDL.h>
|
|
||||||
#include "stb_ds.h"
|
|
||||||
|
|
||||||
static JSValue js_tracy_fiber_enter(JSContext *js, JSValue self, int argc, JSValue *argv)
|
|
||||||
{
|
|
||||||
return JS_UNDEFINED;
|
|
||||||
#ifdef TRACY_ON_DEMAND
|
|
||||||
if (!TracyCIsConnected) {
|
|
||||||
JS_Call(js,argv[0], JS_UNDEFINED,0,NULL);
|
|
||||||
return JS_UNDEFINED;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
JSValue jsname = JS_GetPropertyStr(js, argv[0], "name");
|
|
||||||
const char *fnname = JS_ToCString(js,jsname);
|
|
||||||
TracyCFiberEnter(fnname);
|
|
||||||
JS_Call(js, argv[0], JS_UNDEFINED, 0, NULL);
|
|
||||||
TracyCFiberLeave(fnname);
|
|
||||||
JS_FreeCString(js, fnname);
|
|
||||||
JS_FreeValue(js,jsname);
|
|
||||||
}
|
|
||||||
|
|
||||||
static JSValue js_tracy_fiber_leave(JSContext *js, JSValue self, int argc, JSValue *argv)
|
|
||||||
{
|
|
||||||
return JS_UNDEFINED;
|
|
||||||
#ifdef TRACY_ON_DEMAND
|
|
||||||
if (!TracyCIsConnected)
|
|
||||||
return JS_UNDEFINED;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
JSAtom atom = JS_ValueToAtom(js,argv[0]);
|
|
||||||
const char *str = JS_AtomToCString(js, atom);
|
|
||||||
TracyCFiberLeave(str);
|
|
||||||
JS_FreeAtom(js,atom);
|
|
||||||
return JS_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
static JSValue js_tracy_plot(JSContext *js, JSValue self, int argc, JSValue *argv)
|
|
||||||
{
|
|
||||||
#ifdef TRACY_ON_DEMAND
|
|
||||||
if (!TracyCIsConnected)
|
|
||||||
return JS_UNDEFINED;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const char *str = JS_ToCString(js, argv[0]);
|
|
||||||
double n;
|
|
||||||
JS_ToFloat64(js, &n, argv[1]);
|
|
||||||
TracyCPlot(str, n);
|
|
||||||
JS_FreeCString(js,str);
|
|
||||||
return JS_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
static JSValue js_tracy_plot_config(JSContext *js, JSValue self, int argc, JSValue *argv)
|
|
||||||
{
|
|
||||||
#ifdef TRACY_ON_DEMAND
|
|
||||||
if (!TracyCIsConnected)
|
|
||||||
return JS_UNDEFINED;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const char *str = JS_ToCString(js,argv[0]);
|
|
||||||
|
|
||||||
uint32_t type, color;
|
|
||||||
|
|
||||||
JS_ToUint32(js,&type, argv[1]);
|
|
||||||
JS_ToUint32(js,&color,argv[4]);
|
|
||||||
TracyCPlotConfig(str, type, JS_ToBool(js,argv[2]), JS_ToBool(js,argv[3]), color);
|
|
||||||
JS_FreeCString(js,str);
|
|
||||||
|
|
||||||
return JS_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
static JSValue js_tracy_frame_mark(JSContext *js, JSValue self, int argc, JSValue *argv)
|
|
||||||
{
|
|
||||||
#ifdef TRACY_ON_DEMAND
|
|
||||||
if (!TracyCIsConnected)
|
|
||||||
return JS_UNDEFINED;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
TracyCFrameMark
|
|
||||||
|
|
||||||
return JS_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
static JSValue js_tracy_message(JSContext *js, JSValue self, int argc, JSValue *argv)
|
|
||||||
{
|
|
||||||
#ifdef TRACY_ON_DEMAND
|
|
||||||
if (!TracyCIsConnected)
|
|
||||||
return JS_UNDEFINED;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
size_t len;
|
|
||||||
const char *str = JS_ToCStringLen(js, &len, argv[0]);
|
|
||||||
TracyCMessage(str,len);
|
|
||||||
JS_FreeCString(js,str);
|
|
||||||
return JS_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
static JSValue js_tracy_zone_begin(JSContext *js, JSValue self, int argc, JSValue *argv)
|
|
||||||
{
|
|
||||||
#ifdef TRACY_ON_DEMAND
|
|
||||||
if (!TracyCIsConnected) {
|
|
||||||
JS_Call(js,argv[0], JS_UNDEFINED,0,NULL);
|
|
||||||
return JS_UNDEFINED;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const char *fn_src = JS_AtomToCString(js, js_fn_filename(js, argv[0]));
|
|
||||||
const char *js_fn_name = get_func_name(js, argv[0]);
|
|
||||||
const char *fn_name;
|
|
||||||
if (!js_fn_name || js_fn_name[0] == 0)
|
|
||||||
fn_name = "<anonymous>";
|
|
||||||
else
|
|
||||||
fn_name = js_fn_name;
|
|
||||||
// TracyCZoneCtx TCTX = ___tracy_emit_zone_begin_alloc(___tracy_alloc_srcloc(js_fn_linenum(js,argv[0]), fn_src, strlen(fn_src), fn_name, strlen(fn_name), (int)fn_src),1);
|
|
||||||
JS_FreeCString(js,js_fn_name);
|
|
||||||
|
|
||||||
JS_Call(js, argv[0], JS_UNDEFINED, 0, NULL);
|
|
||||||
// TracyCZoneEnd(TCTX);
|
|
||||||
return JS_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef SOKOL_GLCORE
|
|
||||||
#include "glad.h"
|
|
||||||
GLuint *ids;
|
|
||||||
static GLsizei query_count = 64*1024;
|
|
||||||
static int qhead = 0;
|
|
||||||
static int qtail = 0;
|
|
||||||
|
|
||||||
static JSValue js_tracy_gpu_init(JSContext *js, JSValue self, int argc, JSValue *argv)
|
|
||||||
{
|
|
||||||
printf("GLAD LOAD %d\n", gladLoadGL());
|
|
||||||
ids = malloc(sizeof(GLuint)*query_count);
|
|
||||||
glGenQueries(query_count, ids); // generate new query ids
|
|
||||||
int64_t tgpu;
|
|
||||||
glGetInteger64v(GL_TIMESTAMP, &tgpu);
|
|
||||||
|
|
||||||
float period = 1.f;
|
|
||||||
struct ___tracy_gpu_new_context_data gpuctx = {
|
|
||||||
.gpuTime = tgpu,
|
|
||||||
.period = period,
|
|
||||||
.context = 0,
|
|
||||||
.flags = 0,
|
|
||||||
.type = 1
|
|
||||||
};
|
|
||||||
___tracy_emit_gpu_new_context(gpuctx);
|
|
||||||
|
|
||||||
return JS_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
static JSValue js_tracy_gpu_zone_begin(JSContext *js, JSValue self, int argc, JSValue *argv)
|
|
||||||
{
|
|
||||||
#ifdef TRACY_ON_DEMAND
|
|
||||||
if (!TracyCIsConnected) {
|
|
||||||
JS_Call(js,argv[0], JS_UNDEFINED, 0, NULL);
|
|
||||||
return JS_UNDEFINED;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
glQueryCounter(ids[qhead], GL_TIMESTAMP);
|
|
||||||
struct ___tracy_gpu_zone_begin_data data;
|
|
||||||
|
|
||||||
const char *fn_src = JS_AtomToCString(js, js_fn_filename(js, argv[0]));
|
|
||||||
const char *js_fn_name = get_func_name(js, argv[0]);
|
|
||||||
const char *fn_name;
|
|
||||||
if (!js_fn_name || js_fn_name[0] == 0)
|
|
||||||
fn_name = "<anonymous>";
|
|
||||||
else
|
|
||||||
fn_name = js_fn_name;
|
|
||||||
data.srcloc = ___tracy_alloc_srcloc(js_fn_linenum(js,argv[0]), fn_src, strlen(fn_src), fn_name, strlen(fn_name), (int)fn_src);
|
|
||||||
|
|
||||||
data.queryId = ids[qhead];
|
|
||||||
data.context = 0;
|
|
||||||
___tracy_emit_gpu_zone_begin_alloc(data);
|
|
||||||
JS_FreeCString(js,js_fn_name);
|
|
||||||
JS_FreeCString(js, fn_src);
|
|
||||||
|
|
||||||
qhead = (qhead+1)%query_count;
|
|
||||||
|
|
||||||
JSValue ret = JS_Call(js, argv[0], JS_UNDEFINED, 0, NULL);
|
|
||||||
|
|
||||||
glQueryCounter(ids[qhead], GL_TIMESTAMP);
|
|
||||||
struct ___tracy_gpu_zone_end_data enddata = {
|
|
||||||
.queryId = ids[qhead],
|
|
||||||
.context = 0
|
|
||||||
};
|
|
||||||
___tracy_emit_gpu_zone_end(enddata);
|
|
||||||
qhead = (qhead+1)%query_count;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static JSValue js_tracy_gpu_sync(JSContext *js, JSValue self, int argc, JSValue *argv)
|
|
||||||
{
|
|
||||||
#ifdef TRACY_ON_DEMAND
|
|
||||||
if (!TracyCIsConnected)
|
|
||||||
return JS_UNDEFINED;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int64_t tgpu;
|
|
||||||
glGetInteger64v(GL_TIMESTAMP, &tgpu);
|
|
||||||
|
|
||||||
struct ___tracy_gpu_time_sync_data data = {
|
|
||||||
.context = 0,
|
|
||||||
.gpuTime = tgpu
|
|
||||||
};
|
|
||||||
___tracy_emit_gpu_time_sync(data);
|
|
||||||
return JS_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
static JSValue js_tracy_gpu_collect(JSContext *js, JSValue self, int argc, JSValue *argv)
|
|
||||||
{
|
|
||||||
#ifdef TRACY_ON_DEMAND
|
|
||||||
if (!TracyCIsConnected)
|
|
||||||
return JS_UNDEFINED;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
GLint available;
|
|
||||||
while (qtail != qhead) {
|
|
||||||
glGetQueryObjectiv(ids[qtail], GL_QUERY_RESULT_AVAILABLE, &available);
|
|
||||||
if (!available) return JS_UNDEFINED;
|
|
||||||
|
|
||||||
uint64_t time;
|
|
||||||
glGetQueryObjectui64v(ids[qtail], GL_QUERY_RESULT, &time);
|
|
||||||
struct ___tracy_gpu_time_data gtime = {
|
|
||||||
.gpuTime = time,
|
|
||||||
.queryId = ids[qtail],
|
|
||||||
.context = 0
|
|
||||||
};
|
|
||||||
qtail = (qtail+1)%query_count;
|
|
||||||
___tracy_emit_gpu_time(gtime);
|
|
||||||
}
|
|
||||||
return JS_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
static JSValue js_tracy_image(JSContext *js, JSValue self, int argc, JSValue *argv)
|
|
||||||
{
|
|
||||||
size_t len;
|
|
||||||
double width, height;
|
|
||||||
JS_ToFloat64(js,&width,argv[1]);
|
|
||||||
JS_ToFloat64(js,&height,argv[2]);
|
|
||||||
___tracy_emit_frame_image(JS_GetArrayBuffer(js, &len, argv[0]), width, height, 0, 0);
|
|
||||||
return JS_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined(SOKOL_D3D11)
|
|
||||||
#include <d3d11.h>
|
|
||||||
static int query_count = 64*1024;
|
|
||||||
|
|
||||||
ID3D11Device *device = NULL;
|
|
||||||
ID3D11DeviceContext *context = NULL;
|
|
||||||
ID3D11RenderTargetView *render_view = NULL;
|
|
||||||
ID3D11Query *disjoint_query = NULL;
|
|
||||||
ID3D11Query **queries;
|
|
||||||
|
|
||||||
int qtail = 0;
|
|
||||||
int qhead = 1;
|
|
||||||
|
|
||||||
static JSValue js_tracy_gpu_init(JSContext *js, JSValue self, int argc, JSValue *argv)
|
|
||||||
{
|
|
||||||
HRESULT hr;
|
|
||||||
queries = malloc(sizeof(ID3D11Query*) * query_count);
|
|
||||||
device = sapp_d3d11_get_device();
|
|
||||||
context = sapp_d3d11_get_device_context();
|
|
||||||
render_view = sapp_d3d11_get_render_view();
|
|
||||||
|
|
||||||
D3D11_QUERY_DESC disjoint_desc = {0};
|
|
||||||
disjoint_desc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
|
|
||||||
|
|
||||||
if (FAILED(hr = device->lpVtbl->CreateQuery(device, &disjoint_desc, &disjoint_query)))
|
|
||||||
return JS_ThrowReferenceError(js,"Failed to create disjoint query, HRESULT: 0x%X\n", hr);
|
|
||||||
|
|
||||||
D3D11_QUERY_DESC timestamp_desc = {0};
|
|
||||||
timestamp_desc.Query = D3D11_QUERY_TIMESTAMP;
|
|
||||||
|
|
||||||
for (int i = 0; i < query_count; ++i)
|
|
||||||
if (FAILED(hr = device->lpVtbl->CreateQuery(device, ×tamp_desc, &queries[i])))
|
|
||||||
return JS_ThrowReferenceError(js,"Failed to create query %d, HRESULT: 0x%X\n", i, hr);
|
|
||||||
|
|
||||||
UINT64 tgpu = 0;
|
|
||||||
D3D11_QUERY_DATA_TIMESTAMP_DISJOINT disjoint_data;
|
|
||||||
|
|
||||||
context->lpVtbl->Begin(context, disjoint_query);
|
|
||||||
context->lpVtbl->End(context, queries[0]);
|
|
||||||
context->lpVtbl->End(context, disjoint_query);
|
|
||||||
while (context->lpVtbl->GetData(context, disjoint_query, &disjoint_data, sizeof(disjoint_data), 0) != S_OK);
|
|
||||||
while (context->lpVtbl->GetData(context, queries[0], &tgpu, sizeof(tgpu), 0) != S_OK);
|
|
||||||
|
|
||||||
struct ___tracy_gpu_new_context_data gpuctx = {
|
|
||||||
.gpuTime = tgpu * (1000000000 / disjoint_data.Frequency),
|
|
||||||
.period = 1.0f,
|
|
||||||
.context = 0,
|
|
||||||
.flags = 0,
|
|
||||||
.type = 2
|
|
||||||
};
|
|
||||||
___tracy_emit_gpu_new_context(gpuctx);
|
|
||||||
|
|
||||||
context->lpVtbl->Begin(context, disjoint_query);
|
|
||||||
qtail = qhead = 0;
|
|
||||||
|
|
||||||
return JS_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
static JSValue js_tracy_gpu_zone_begin(JSContext *js, JSValue self, int argc, JSValue *argv)
|
|
||||||
{
|
|
||||||
#ifdef TRACY_ON_DEMAND
|
|
||||||
if (!TracyCIsConnected) {
|
|
||||||
JS_Call(js,argv[0], JS_UNDEFINED, 0, NULL);
|
|
||||||
return JS_UNDEFINED;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
context->lpVtbl->End(context, queries[qhead]);
|
|
||||||
struct ___tracy_gpu_zone_begin_data data;
|
|
||||||
|
|
||||||
const char *fn_src = JS_AtomToCString(js, js_fn_filename(js, argv[0]));
|
|
||||||
const char *js_fn_name = get_func_name(js, argv[0]);
|
|
||||||
const char *fn_name;
|
|
||||||
if (!js_fn_name || js_fn_name[0] == 0)
|
|
||||||
fn_name = "<anonymous>";
|
|
||||||
else
|
|
||||||
fn_name = js_fn_name;
|
|
||||||
data.srcloc = ___tracy_alloc_srcloc(js_fn_linenum(js,argv[0]), fn_src, strlen(fn_src), fn_name, strlen(fn_name), (int)fn_src);
|
|
||||||
|
|
||||||
data.queryId = qhead;
|
|
||||||
data.context = 0;
|
|
||||||
___tracy_emit_gpu_zone_begin_alloc(data);
|
|
||||||
JS_FreeCString(js,js_fn_name);
|
|
||||||
JS_FreeCString(js, fn_src);
|
|
||||||
qhead = (qhead+1)%query_count;
|
|
||||||
|
|
||||||
JSValue ret = JS_Call(js, argv[0], JS_UNDEFINED, 0, NULL);
|
|
||||||
context->lpVtbl->End(context, queries[qhead]);
|
|
||||||
struct ___tracy_gpu_zone_end_data enddata = {
|
|
||||||
.queryId = qhead,
|
|
||||||
.context = 0
|
|
||||||
};
|
|
||||||
___tracy_emit_gpu_zone_end(enddata);
|
|
||||||
qhead = (qhead+1)%query_count;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static JSValue js_tracy_gpu_sync(JSContext *js, JSValue self, int argc, JSValue *argv)
|
|
||||||
{
|
|
||||||
#ifdef TRACY_ON_DEMAND
|
|
||||||
if (!TracyCIsConnected)
|
|
||||||
return JS_UNDEFINED;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return JS_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
static JSValue js_tracy_gpu_collect(JSContext *js, JSValue self, int argc, JSValue *argv)
|
|
||||||
{
|
|
||||||
#ifdef TRACY_ON_DEMAND
|
|
||||||
if (!TracyCIsConnected)
|
|
||||||
return JS_UNDEFINED;
|
|
||||||
#endif
|
|
||||||
HRESULT hr;
|
|
||||||
// Use the current head to get a sync value
|
|
||||||
context->lpVtbl->End(context, queries[qhead]);
|
|
||||||
context->lpVtbl->End(context, disjoint_query);
|
|
||||||
|
|
||||||
D3D11_QUERY_DATA_TIMESTAMP_DISJOINT disjoint_data;
|
|
||||||
while(context->lpVtbl->GetData(context, disjoint_query, &disjoint_data, sizeof(disjoint_data), 0) != S_OK);
|
|
||||||
|
|
||||||
if (disjoint_data.Disjoint) {
|
|
||||||
qtail = qhead;
|
|
||||||
return JS_ThrowReferenceError(js,"disjoint timestamps detected; dropping.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* uint64_t synctime = 0;
|
|
||||||
while (context->lpVtbl->GetData(context, queries[qhead], &synctime, sizeof(synctime), 0) != S_OK);
|
|
||||||
___tracy_emit_gpu_time_sync((struct ___tracy_gpu_time_sync_data) {
|
|
||||||
.context = 0,
|
|
||||||
.gpuTime = synctime * 1000000000 / disjoint_data.Frequency
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
|
|
||||||
while (qtail != qhead) {
|
|
||||||
uint64_t time = 0;
|
|
||||||
while(context->lpVtbl->GetData(context, queries[qtail], &time, sizeof(time), 0) != S_OK);
|
|
||||||
|
|
||||||
struct ___tracy_gpu_time_data gtime = {
|
|
||||||
.gpuTime = time * (1000000000 / disjoint_data.Frequency),
|
|
||||||
.queryId = qtail,
|
|
||||||
.context = 0
|
|
||||||
};
|
|
||||||
qtail = (qtail+1)%query_count;
|
|
||||||
___tracy_emit_gpu_time(gtime);
|
|
||||||
}
|
|
||||||
|
|
||||||
qtail = qhead;
|
|
||||||
context->lpVtbl->Begin(context, disjoint_query);
|
|
||||||
|
|
||||||
return JS_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <stb_image_resize2.h>
|
|
||||||
#include <stb_image_write.h>
|
|
||||||
|
|
||||||
static JSValue js_tracy_image(JSContext *js, JSValue self, int argc, JSValue *argv)
|
|
||||||
{
|
|
||||||
if (!TracyCIsConnected) return JS_UNDEFINED;
|
|
||||||
|
|
||||||
HRESULT hr;
|
|
||||||
// create staging texture
|
|
||||||
// Get render target texture
|
|
||||||
ID3D11Texture2D *render_target_tex = NULL;
|
|
||||||
render_view->lpVtbl->GetResource(sapp_d3d11_get_render_view(), &render_target_tex);
|
|
||||||
// if (FAILED(hr)) return JS_ThrowReferenceError(js, "Failed to query texture from render target");
|
|
||||||
|
|
||||||
D3D11_TEXTURE2D_DESC render_tex_desc;
|
|
||||||
render_target_tex->lpVtbl->GetDesc(render_target_tex, &render_tex_desc);
|
|
||||||
|
|
||||||
render_tex_desc.Usage = D3D11_USAGE_STAGING;
|
|
||||||
render_tex_desc.BindFlags = 0;
|
|
||||||
render_tex_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
|
|
||||||
render_tex_desc.MiscFlags = 0;
|
|
||||||
render_tex_desc.SampleDesc = (DXGI_SAMPLE_DESC){ .Count = 1, .Quality = 0, };
|
|
||||||
|
|
||||||
ID3D11Texture2D *staging_tex = NULL;
|
|
||||||
hr = device->lpVtbl->CreateTexture2D(device, &render_tex_desc, NULL, &staging_tex);
|
|
||||||
if (FAILED(hr)) return JS_ThrowReferenceError(js, "Failed to create staging texture: 0x%08X\n", hr);
|
|
||||||
|
|
||||||
context->lpVtbl->CopyResource(context, staging_tex, render_target_tex);
|
|
||||||
|
|
||||||
D3D11_MAPPED_SUBRESOURCE mapped_res;
|
|
||||||
hr = context->lpVtbl->Map(context, staging_tex, 0, D3D11_MAP_READ, 0, &mapped_res);
|
|
||||||
if (FAILED(hr)) return JS_ThrowReferenceError(js, "Failed to map subresource");
|
|
||||||
|
|
||||||
// resize
|
|
||||||
int newwidth = 320;
|
|
||||||
int newheight = 180;
|
|
||||||
void *newdata = malloc(320*180*4);
|
|
||||||
stbir_resize_uint8_linear(mapped_res.pData, render_tex_desc.Width, render_tex_desc.Height, 0, newdata, newwidth, newheight, 0, 4);
|
|
||||||
|
|
||||||
___tracy_emit_frame_image(newdata, newwidth, newheight, 0, 0);
|
|
||||||
|
|
||||||
context->lpVtbl->Unmap(context, staging_tex, 0);
|
|
||||||
staging_tex->lpVtbl->Release(staging_tex);
|
|
||||||
render_target_tex->lpVtbl->Release(render_target_tex);
|
|
||||||
free(newdata);
|
|
||||||
|
|
||||||
return JS_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
static JSValue js_tracy_gpu_init(JSContext *js, JSValue self, int argc, JSValue *argv)
|
|
||||||
{
|
|
||||||
return JS_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
static JSValue js_tracy_gpu_zone_begin(JSContext *js, JSValue self, int argc, JSValue *argv)
|
|
||||||
{
|
|
||||||
return JS_Call(js,argv[0], JS_UNDEFINED, 0, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static JSValue js_tracy_gpu_sync(JSContext *js, JSValue self, int argc, JSValue *argv)
|
|
||||||
{
|
|
||||||
return JS_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
static JSValue js_tracy_gpu_collect(JSContext *js, JSValue self, int argc, JSValue *argv)
|
|
||||||
{
|
|
||||||
return JS_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
static JSValue js_tracy_image(JSContext *js, JSValue self, int argc, JSValue *argv)
|
|
||||||
{
|
|
||||||
/* SDL_Surface *img = js2SDL_Surface(js,argv[0]);
|
|
||||||
SDL_Surface *scaled = SDL_ScaleSurface(img, 320,180,SDL_SCALEMODE_LINEAR);
|
|
||||||
___tracy_emit_frame_image(scaled->pixels, scaled->w,scaled->h, 0,0);
|
|
||||||
SDL_DestroySurface(scaled);*/
|
|
||||||
return JS_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Wrapper struct to keep the array pointer stable
|
|
||||||
typedef struct {
|
|
||||||
TracyCZoneCtx *arr; // stb_ds dynamic array
|
|
||||||
} tracy_stack_t;
|
|
||||||
|
|
||||||
// Global TLS ID for the Tracy stack
|
|
||||||
static SDL_TLSID tracy_stack_id = {0};
|
|
||||||
|
|
||||||
// Cleanup function for the wrapper struct
|
|
||||||
static void tracy_cleanup_stack(void *value)
|
|
||||||
{
|
|
||||||
tracy_stack_t *stack = value;
|
|
||||||
if (stack) {
|
|
||||||
arrfree(stack->arr);
|
|
||||||
free(stack);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get or initialize the thread-local Tracy stack
|
|
||||||
static tracy_stack_t *get_tracy_stack(void)
|
|
||||||
{
|
|
||||||
tracy_stack_t *stack = SDL_GetTLS(&tracy_stack_id);
|
|
||||||
if (!stack) {
|
|
||||||
stack = malloc(sizeof(tracy_stack_t));
|
|
||||||
stack->arr = NULL; // stb_ds starts with NULL
|
|
||||||
arrsetcap(stack->arr, 5); // Initial capacity
|
|
||||||
SDL_SetTLS(&tracy_stack_id, stack, tracy_cleanup_stack);
|
|
||||||
}
|
|
||||||
return stack;
|
|
||||||
}
|
|
||||||
|
|
||||||
void tracy_call_hook(JSContext *js, JSValue fn)
|
|
||||||
{
|
|
||||||
tracy_stack_t *stack = get_tracy_stack();
|
|
||||||
js_debug debug;
|
|
||||||
js_debug_info(js, fn, &debug);
|
|
||||||
|
|
||||||
uint64_t srcloc = ___tracy_alloc_srcloc(debug.line, debug.filename, strlen(debug.filename), debug.name, strlen(debug.name), debug.unique);
|
|
||||||
arrput(stack->arr, ___tracy_emit_zone_begin_alloc(srcloc, 1));
|
|
||||||
|
|
||||||
free_js_debug_info(js, &debug);
|
|
||||||
}
|
|
||||||
|
|
||||||
void tracy_end_hook(JSContext *js, JSValue fn)
|
|
||||||
{
|
|
||||||
tracy_stack_t *stack = get_tracy_stack();
|
|
||||||
if (arrlen(stack->arr) > 0)
|
|
||||||
___tracy_emit_zone_end(arrpop(stack->arr));
|
|
||||||
}
|
|
||||||
|
|
||||||
JSValue js_tracy_level(JSContext *js, JSValue self, int argc, JSValue *argv)
|
|
||||||
{
|
|
||||||
int32_t level;
|
|
||||||
JS_ToInt32(js,&level, argv[0]);
|
|
||||||
if (JS_IsUndefined(argv[0]) || level == 0) {
|
|
||||||
js_debug_sethook(js,NULL,JS_HOOK_CALL);
|
|
||||||
js_debug_sethook(js,NULL,JS_HOOK_RET);
|
|
||||||
} else {
|
|
||||||
js_debug_sethook(js, tracy_call_hook, JS_HOOK_CALL);
|
|
||||||
js_debug_sethook(js, tracy_end_hook, JS_HOOK_RET);
|
|
||||||
}
|
|
||||||
|
|
||||||
return JS_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const JSCFunctionListEntry js_tracy_funcs[] = {
|
|
||||||
JS_CFUNC_DEF("fiber", 1, js_tracy_fiber_enter),
|
|
||||||
JS_CFUNC_DEF("fiber_leave", 1, js_tracy_fiber_leave),
|
|
||||||
JS_CFUNC_DEF("gpu_zone", 1, js_tracy_gpu_zone_begin),
|
|
||||||
JS_CFUNC_DEF("gpu_collect", 1, js_tracy_gpu_collect),
|
|
||||||
JS_CFUNC_DEF("gpu_init", 0, js_tracy_gpu_init),
|
|
||||||
JS_CFUNC_DEF("gpu_sync", 0, js_tracy_gpu_sync),
|
|
||||||
JS_CFUNC_DEF("end_frame", 0, js_tracy_frame_mark),
|
|
||||||
JS_CFUNC_DEF("zone", 1, js_tracy_zone_begin),
|
|
||||||
JS_CFUNC_DEF("message", 1, js_tracy_message),
|
|
||||||
JS_CFUNC_DEF("plot", 2, js_tracy_plot),
|
|
||||||
JS_CFUNC_DEF("image", 3, js_tracy_image),
|
|
||||||
JS_CFUNC_DEF("level", 1, js_tracy_level),
|
|
||||||
JS_CFUNC_DEF("plot_config", 5, js_tracy_plot_config),
|
|
||||||
};
|
|
||||||
|
|
||||||
JSValue js_tracy_use(JSContext *js)
|
|
||||||
{
|
|
||||||
JSValue expy = JS_NewObject(js);
|
|
||||||
JS_SetPropertyFunctionList(js, expy, js_tracy_funcs, sizeof(js_tracy_funcs)/sizeof(JSCFunctionListEntry));
|
|
||||||
return expy;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int js_tracy_init(JSContext *js, JSModuleDef *m) {
|
|
||||||
js_tracy_use(js);
|
|
||||||
JS_SetModuleExportList(js, m, js_tracy_funcs, sizeof(js_tracy_funcs)/sizeof(JSCFunctionListEntry));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef JS_SHARED_LIBRARY
|
|
||||||
#define JS_INIT_MODULE js_init_module
|
|
||||||
#else
|
|
||||||
#define JS_INIT_MODULE js_init_module_tracy
|
|
||||||
#endif
|
|
||||||
|
|
||||||
JSModuleDef *JS_INIT_MODULE(JSContext *ctx, const char *module_name) {
|
|
||||||
JSModuleDef *m = JS_NewCModule(ctx, module_name, js_tracy_init);
|
|
||||||
if (!m) return NULL;
|
|
||||||
JS_AddModuleExportList(ctx, m, js_tracy_funcs, sizeof(js_tracy_funcs)/sizeof(JSCFunctionListEntry));
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
@@ -7,7 +7,6 @@ var os = use('os');
|
|||||||
var io = use('io');
|
var io = use('io');
|
||||||
var transform = use('transform');
|
var transform = use('transform');
|
||||||
var rasterize = use('rasterize');
|
var rasterize = use('rasterize');
|
||||||
|
|
||||||
var video_actor = use('sdl_video')
|
var video_actor = use('sdl_video')
|
||||||
|
|
||||||
var window
|
var window
|
||||||
@@ -119,6 +118,7 @@ function translate_draw_commands(commands) {
|
|||||||
|
|
||||||
case "draw_circle":
|
case "draw_circle":
|
||||||
case "draw_ellipse":
|
case "draw_ellipse":
|
||||||
|
break
|
||||||
// Rasterize ellipse to points or rects
|
// Rasterize ellipse to points or rects
|
||||||
var radii = cmd.radii || [cmd.radius, cmd.radius]
|
var radii = cmd.radii || [cmd.radius, cmd.radius]
|
||||||
var raster_result = rasterize.ellipse(cmd.pos, radii, cmd.opt || {})
|
var raster_result = rasterize.ellipse(cmd.pos, radii, cmd.opt || {})
|
||||||
@@ -177,6 +177,7 @@ function translate_draw_commands(commands) {
|
|||||||
|
|
||||||
function loop()
|
function loop()
|
||||||
{
|
{
|
||||||
|
os.frame()
|
||||||
var now = os.now()
|
var now = os.now()
|
||||||
var dt = now - last
|
var dt = now - last
|
||||||
last = now
|
last = now
|
||||||
@@ -212,9 +213,10 @@ function loop()
|
|||||||
id: render,
|
id: render,
|
||||||
op: "batch",
|
op: "batch",
|
||||||
data: batch_commands
|
data: batch_commands
|
||||||
|
}, _ => {
|
||||||
|
var diff = os.now() - now
|
||||||
|
$_.delay(loop,1/240)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
$_.delay(loop, 1/60)
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user