From 6b94349a644f65d55d4b6a096775be2196faaf2e Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Sun, 29 Sep 2024 06:10:42 -0500 Subject: [PATCH] fix rendering --- Makefile | 2 +- scripts/base.js | 5 + scripts/profile.js | 33 ++++- scripts/prosperon.js | 16 ++- scripts/render.js | 35 +++--- shaders/poly_ssbo.cg | 4 +- shaders/sprite_ssbo.cg | 3 +- source/engine/HandmadeMath.h | 5 + source/engine/jsffi.c | 229 ++++++++++++++++++++++++++++------- source/engine/jsffi.h | 23 +++- source/engine/nota.c | 2 +- source/engine/nota.h | 2 +- source/engine/render.c | 6 +- source/engine/texture.c | 11 +- source/engine/texture.h | 3 +- source/engine/transform.h | 3 + source/engine/window.c | 1 + source/engine/yugine.c | 1 + 18 files changed, 304 insertions(+), 80 deletions(-) diff --git a/Makefile b/Makefile index 4f1d852..b053529 100755 --- a/Makefile +++ b/Makefile @@ -77,7 +77,7 @@ endif CXXFLAGS += -std=c++14 -CPPFLAGS += -DHAVE_CEIL -DCP_USE_CGTYPES=0 -DCP_USE_DOUBLES=0 -DHAVE_FLOOR -DHAVE_FMOD -DHAVE_LRINT -DHAVE_LRINTF $(includeflag) $(WARNING_FLAGS) -I. -DVER=\"$(SEM)\" -DCOM=\"$(COM)\" -DDATE=\"$(DATE)\" -DINFO=\"$(INFO)\" -Wno-narrowing #-DENABLE_SINC_MEDIUM_CONVERTER -DENABLE_SINC_FAST_CONVERTER -DCP_COLLISION_TYPE_TYPE=uintptr_t -DCP_BITMASK_TYPE=uintptr_t +CPPFLAGS += -DHAVE_CEIL -DCP_USE_CGTYPES=0 -DCP_USE_DOUBLES=0 -DHAVE_FLOOR -DHAVE_FMOD -DHAVE_LRINT -DHAVE_LRINTF $(includeflag) $(WARNING_FLAGS) -I. -DVER=\"$(SEM)\" -DCOM=\"$(COM)\" -DDATE=\"$(DATE)\" -DINFO=\"$(INFO)\" -Wno-narrowing -Wno-int-conversion #-DENABLE_SINC_MEDIUM_CONVERTER -DENABLE_SINC_FAST_CONVERTER -DCP_COLLISION_TYPE_TYPE=uintptr_t -DCP_BITMASK_TYPE=uintptr_t CPPFLAGS += -DCONFIG_VERSION=\"2024-02-14\" -DCONFIG_BIGNUM #for quickjs # ENABLE_SINC_[BEST|FAST|MEDIUM]_CONVERTER diff --git a/scripts/base.js b/scripts/base.js index d2cae87..6d51042 100644 --- a/scripts/base.js +++ b/scripts/base.js @@ -1209,6 +1209,11 @@ Math.mean = vector.mean; Math.sigma = vector.sigma; Math.median = vector.median; +vector.v2one = [1,1]; +vector.v3one = [1,1,1]; +vector.v2zero = [0,0]; +vector.v3zero = [0,0,0]; + Math.variance = function (series) { var mean = Math.mean(series); var vnce = 0; diff --git a/scripts/profile.js b/scripts/profile.js index 95b45b9..cda7269 100644 --- a/scripts/profile.js +++ b/scripts/profile.js @@ -332,12 +332,41 @@ profile.curframe = 0; profile.snapshot = {}; var fps = []; +var frame_lead = 240; + +var classes = ["gameobject", "transform", "dsp_node", "texture", "font", "warp_gravity", "warp_damp", "sg_buffer", "datastream", "cpShape", "cpConstraint", "timer", "skin"]; +var get_snapshot = function() +{ + var snap = profile.snapshot; + snap.actors ??= {}; + Object.assign(snap.actors, actor.__stats()); + snap.memory ??= {}; + Object.assign(snap.memory, os.mem()); + snap.memory.textures = game.texture.total_size(); + snap.memory.texture_vram = game.texture.total_vram(); + + snap.rusage ??= {}; + var rusage = os.rusage(); + rusage.ru_maxrss *= 1024; // delivered in KB; convert here to B + Object.assign(snap.rusage, rusage); + + snap.mallinfo ??= {}; + Object.assign(snap.mallinfo, os.mallinfo()); + + snap.obj ??= {}; + for (var i of classes) { + var proto = globalThis[`${i}_proto`]; + if (!proto) continue; + snap.obj[i] = proto._count(); + } +} profile.report_frame = function (t) { fps.push(t); - if (fps.length > 15) { + if (fps.length > frame_lead) { profile.snapshot.fps = Math.mean(fps); - fps = []; + fps.length = 0; + get_snapshot(); } }; diff --git a/scripts/prosperon.js b/scripts/prosperon.js index 80fdb19..b45afe2 100644 --- a/scripts/prosperon.js +++ b/scripts/prosperon.js @@ -193,7 +193,7 @@ game.tex_hotreload = function () { }; game.texture = function (path) { - if (!path) return game.texture("icons/no_text.gif"); + if (!path) return game.texture("icons/no_tex.gif"); path = Resources.find_image(path); if (!io.exists(path)) { @@ -210,6 +210,20 @@ game.texture = function (path) { game.texture.cache = {}; game.texture.time_cache = {}; +game.texture.total_size = function() +{ + var size = 0; + Object.values(game.texture.cache).forEach(x => size += x.inram() ? x.width*x.height*4 : 0); + return size; +} + +game.texture.total_vram = function() +{ + var vram = 0; + Object.values(game.texture.cache).forEach(x => vram += x.vram); + return vram; +} + prosperon.semver = {}; prosperon.semver.valid = function (v, range) { v = v.split("."); diff --git a/scripts/render.js b/scripts/render.js index 2738211..c666ec7 100644 --- a/scripts/render.js +++ b/scripts/render.js @@ -533,11 +533,9 @@ render.sprites = function render_sprites() { var sparray = layer[img]; if (sparray.length === 0) continue; var ss = sparray[0]; -// render.use_mat(ss); - cur.images = [ss.diffuse]; - render.make_sprite_ssbo(sparray, sprite_ssbo); + ss.baseinstance = render.make_sprite_ssbo(sparray, sprite_ssbo); + render.use_mat(ss); render.draw(shape.quad, sprite_ssbo, sparray.length); - if (debug.sprite_nums) render.text(ss.diffuse.getid(), ss.transform.pos); } } profile.endframe(); @@ -586,6 +584,10 @@ function check_flush(flush_fn) { } render.flush = check_flush; +render.forceflush = function() +{ + if (nextflush) nextflush(); +} var poly_cache = []; var poly_idx = 0; @@ -610,14 +612,12 @@ function poly_e() { function flush_poly() { if (poly_idx === 0) return; render.use_shader(polyssboshader); - render.use_mat({}); - render.make_particle_ssbo(poly_cache.slice(0, poly_idx), poly_ssbo); + var base = render.make_particle_ssbo(poly_cache.slice(0, poly_idx), poly_ssbo); + render.use_mat({baseinstance:base}); render.draw(shape.centered_quad, poly_ssbo, poly_idx); poly_idx = 0; } -function flush_image() {} - render.line = function render_line(points, color = Color.white, thickness = 1) { for (var i = 0; i < points.length - 1; i++) { var a = points[i]; @@ -719,10 +719,10 @@ var img_idx = 0; function flush_img() { if (img_idx === 0) return; render.use_shader(spritessboshader); - //render.use_mat({ diffuse: lasttex }); - render.make_sprite_ssbo(img_cache.slice(0, img_idx), poly_ssbo); + var startidx = render.make_sprite_ssbo(img_cache.slice(0, img_idx), sprite_ssbo); + render.use_mat({ baseinstance:startidx}); cur.images = [lasttex]; - render.draw(shape.quad, poly_ssbo, img_idx); + render.draw(shape.quad, sprite_ssbo, img_idx); lasttex = undefined; img_idx = 0; } @@ -745,8 +745,11 @@ render.image = function image(tex, pos, scale, rotation = 0, color = Color.white if (typeof tex === "string") tex = game.texture(tex); - scale ??= [tex.width,tex.height]; - + if (scale) + scale = scale.div([tex.width, tex.height]); + else + scale = vector.v3one; + if (!tex) return; if (!lasttex) { @@ -763,7 +766,7 @@ render.image = function image(tex, pos, scale, rotation = 0, color = Color.white e.transform.trs(pos, undefined, scale); e.shade = color; e.texture = tex; - + return; var bb = {}; bb.b = pos.y; @@ -1035,6 +1038,7 @@ prosperon.render = function () { profile.endframe(); profile.frame("draws"); prosperon.draw(); +// sgl.draw(); profile.endframe(); prosperon.hudcam.size = prosperon.camera.size; prosperon.hudcam.transform.pos = [prosperon.hudcam.size.x / 2, prosperon.hudcam.size.y / 2, -100]; @@ -1095,9 +1099,8 @@ prosperon.render = function () { render.end_pass(); - profile.report_frame(profile.secs(profile.now()) - frame_t); - render.commit(); + profile.report_frame(profile.secs(profile.now()) - frame_t); endframe(); }; diff --git a/shaders/poly_ssbo.cg b/shaders/poly_ssbo.cg index 47fcb57..ee85156 100644 --- a/shaders/poly_ssbo.cg +++ b/shaders/poly_ssbo.cg @@ -17,8 +17,10 @@ readonly buffer ssbo { poly polys[]; }; +uniform float baseinstance; + void main() { - poly p = polys[gl_InstanceIndex]; + poly p = polys[int(baseinstance)+gl_InstanceIndex]; gl_Position = vp * p.model * vec4(a_pos, 1); shade = p.color; } diff --git a/shaders/sprite_ssbo.cg b/shaders/sprite_ssbo.cg index 5ad0c8a..0e12718 100644 --- a/shaders/sprite_ssbo.cg +++ b/shaders/sprite_ssbo.cg @@ -22,10 +22,11 @@ readonly buffer ssbo { }; uniform mat4 vp; +uniform float baseinstance; void main() { - sprite s = sprites[gl_InstanceIndex]; + sprite s = sprites[int(baseinstance)+gl_InstanceIndex]; pos = a_pos; uv = a_uv; pos *= vec3(s.rect.zw,1); diff --git a/source/engine/HandmadeMath.h b/source/engine/HandmadeMath.h index e20bd89..69b17f7 100644 --- a/source/engine/HandmadeMath.h +++ b/source/engine/HandmadeMath.h @@ -195,6 +195,9 @@ #define FMT_VEC4 "[%g,%g,%g,%g]" #define PRINT_VEC4(vec) vec.x, vec.y, vec.z, vec.w +#define FMT_M4 "[%g,%g,%g,%g\n%g,%g,%g,%g\n%g,%g,%g,%g\n%g,%g,%g,%g]" +#define PRINT_M4(m) m.e[0][0], m.e[0][1], m.e[0][2], m.e[0][3], m.e[1][0], m.e[1][1], m.e[1][2], m.e[1][3], m.e[2][0], m.e[2][1], m.e[2][2], m.e[2][3], m.e[3][0], m.e[3][1], m.e[3][2], m.e[3][3] + typedef union HMM_Vec2 { struct { @@ -383,6 +386,8 @@ typedef union HMM_Vec4 { HMM_Quat quat; struct {float x, y, z, w; }; + struct {float r, g, b, a; }; + struct {float u0, u1, v0, v1;}; float Elements[4]; float e[4]; diff --git a/source/engine/jsffi.c b/source/engine/jsffi.c index 2ab850d..17a74ec 100644 --- a/source/engine/jsffi.c +++ b/source/engine/jsffi.c @@ -32,11 +32,15 @@ #include "par/par_streamlines.h" #include "par/par_shapes.h" #include "sokol_glue.h" +#define SOKOL_GL_IMPL +#include "sokol/util/sokol_gl.h" #include #include #include #include "gui.h" #include "timer.h" +#include +#include #if (defined(_WIN32) || defined(__WIN32__)) #include @@ -45,9 +49,6 @@ static JSValue globalThis; -static JSClassID js_ptr_id; -static JSClassDef js_ptr_class = { "POINTER" }; - JSValue str2js(const char *c, ...) { if (!c) return JS_UNDEFINED; char *result = NULL; @@ -69,7 +70,7 @@ const char *js2str(JSValue v) { } char *js2strdup(JSValue v) { - char *str = JS_ToCString(js, v); + const char *str = JS_ToCString(js, v); char *ret = strdup(str); JS_FreeCString(js, str); return ret; @@ -228,14 +229,6 @@ double js2angle(JSValue v) { return n * HMM_TurnToRad; } -void *js2ptr(JSValue v) { return JS_GetOpaque(v,js_ptr_id); } - -JSValue ptr2js(void *ptr) { - JSValue obj = JS_NewObjectClass(js, js_ptr_id); - JS_SetOpaque(obj, ptr); - return obj; -} - int js_arrlen(JSValue v) { if (JS_IsUndefined(v)) return 0; int len; @@ -302,7 +295,7 @@ char *js_do_nota_decode(JSValue *tmp, char *nota) char *js_do_nota_encode(JSValue v, char *nota) { int tag = JS_VALUE_GET_TAG(v); - char *str = NULL; + const char *str = NULL; JSPropertyEnum *ptab; uint32_t plen; int n; @@ -764,7 +757,10 @@ JSC_CCALL(render_glue_pass, ) // Set the portion of the window to be rendered to -JSC_CCALL(render_viewport, sg_apply_viewportf(js2number(argv[0]), js2number(argv[1]), js2number(argv[2]), js2number(argv[3]), 0)) +JSC_CCALL(render_viewport, + sg_apply_viewportf(js2number(argv[0]), js2number(argv[1]), js2number(argv[2]), js2number(argv[3]), 0); +// sgl_viewportf(js2number(argv[0]), js2number(argv[1]), js2number(argv[2]), js2number(argv[3]), 0); +) JSC_CCALL(render_commit, sg_commit()) JSC_CCALL(render_end_pass, sg_end_pass()) @@ -841,12 +837,12 @@ sg_shader js2shader(JSValue v) desc.label = js2strdup(js_getpropstr(v, "name")); JSValue vs = js_getpropstr(prog, "vs"); JSValue fs = js_getpropstr(prog, "fs"); - char *vsf = js2str(js_getpropstr(vs, "code")); - char *fsf = js2str(js_getpropstr(fs, "code")); + const char *vsf = js2str(js_getpropstr(vs, "code")); + const char *fsf = js2str(js_getpropstr(fs, "code")); desc.vs.source = vsf; desc.fs.source = fsf; - char *vsmain = js2str(js_getpropstr(vs, "entry_point")); - char *fsmain = js2str(js_getpropstr(fs, "entry_point")); + const char *vsmain = js2str(js_getpropstr(vs, "entry_point")); + const char *fsmain = js2str(js_getpropstr(fs, "entry_point")); desc.vs.entry = vsmain; desc.fs.entry = fsmain; desc.vs.d3d11_target = "vs_4_0"; @@ -994,6 +990,7 @@ JSC_CCALL(render_setuniv3, sg_apply_uniforms(js2number(argv[0]), js2number(argv[1]), SG_RANGE_REF(f.e)); ) + JSC_CCALL(render_setuniv4, HMM_Vec4 v = {0}; if (JS_IsArray(js, argv[2])) { @@ -1059,10 +1056,12 @@ JSC_CCALL(render_make_particle_ssbo, particle_ss ms[js_arrlen(array)]; if (sg_query_buffer_will_overflow(*b, size)) { + sg_buffer_desc desc = sg_query_buffer_desc(*b); sg_destroy_buffer(*b); + *b = sg_make_buffer(&(sg_buffer_desc){ .type = SG_BUFFERTYPE_STORAGEBUFFER, - .size = size, + .size = size+desc.size, .usage = SG_USAGE_STREAM, .label = "transform buffer" }); @@ -1074,10 +1073,12 @@ JSC_CCALL(render_make_particle_ssbo, ms[i].color = js2vec4(js_getpropstr(sub,"color")); } - sg_append_buffer(*b, (&(sg_range){ + int offset = sg_append_buffer(*b, (&(sg_range){ .ptr = ms, .size = size })); + + ret = number2js(offset/sizeof(particle_ss)); ) typedef struct sprite_ss { @@ -1095,10 +1096,11 @@ JSC_CCALL(render_make_sprite_ssbo, sprite_ss ms[js_arrlen(array)]; if (sg_query_buffer_will_overflow(*b, size)) { + sg_buffer_desc desc = sg_query_buffer_desc(*b); sg_destroy_buffer(*b); *b = sg_make_buffer(&(sg_buffer_desc){ .type = SG_BUFFERTYPE_STORAGEBUFFER, - .size = size, + .size = size+desc.size, .usage = SG_USAGE_STREAM, .label = "transform buffer" }); @@ -1117,14 +1119,8 @@ JSC_CCALL(render_make_sprite_ssbo, tscale.z = 1; tr->scale = HMM_MulV3(tr->scale, tscale); } - - tr->scale.x = 100; - tr->scale.y = 100; - tr->scale.z = 1; - tr->pos.x = 100; - tr->pos.y = 100; - tr->pos.z = 0; - ms[i].model = transform2mat(t); + + ms[i].model = transform2mat(tr); ms[i].rect = js2vec4(js_getpropstr(sub,"rect")); ms[i].shade = js2vec4(js_getpropstr(sub,"shade")); @@ -1132,10 +1128,12 @@ JSC_CCALL(render_make_sprite_ssbo, tr->scale = HMM_DivV3(tr->scale, tscale); } - sg_append_buffer(*b, (&(sg_range){ + int offset = sg_append_buffer(*b, (&(sg_range){ .ptr = ms, .size = size })); + + ret = number2js(offset/96); ) JSC_CCALL(render_make_t_ssbo, @@ -1218,7 +1216,107 @@ static const JSCFunctionListEntry js_render_funcs[] = { MIST_FUNC_DEF(render, make_sprite_ssbo, 2) }; -JSC_CCALL(gui_scissor, sg_apply_scissor_rect(js2number(argv[0]), js2number(argv[1]), js2number(argv[2]), js2number(argv[3]), 0)) +JSC_DCALL(sgl_enable_texture) +JSC_DCALL(sgl_disable_texture) +JSC_CCALL(sgl_texture, sgl_texture(js2texture(argv[0])->id, std_sampler)) +JSC_DCALL(sgl_matrix_mode_modelview) +JSC_DCALL(sgl_matrix_mode_projection) +JSC_DCALL(sgl_matrix_mode_texture) +JSC_DCALL(sgl_load_identity) +JSC_CCALL(sgl_translate, + HMM_Vec3 v = js2vec3(argv[0]); + sgl_translate(v.x,v.y,v.z); +) +JSC_CCALL(sgl_rotate, + float rad = js2angle(argv[0]); + HMM_Vec3 axis = js2vec3(argv[1]); + sgl_rotate(rad, axis.x, axis.y, axis.z); +) + +JSC_CCALL(sgl_scale, + HMM_Vec3 v = js2vec3(argv[0]); + sgl_scale(v.x, v.y, v.z); +) + +JSC_CCALL(sgl_load_matrix, + transform *t = js2transform(argv[0]); + sgl_load_matrix(t->cache.e); +) + +JSC_6CALL(sgl_frustum) +JSC_6CALL(sgl_ortho) +JSC_4CALL(sgl_perspective) +JSC_DCALL(sgl_push_matrix) +JSC_DCALL(sgl_pop_matrix) +JSC_1CALL(sgl_point_size) +JSC_DCALL(sgl_begin_points) +JSC_DCALL(sgl_begin_lines) +JSC_DCALL(sgl_begin_line_strip) +JSC_DCALL(sgl_begin_triangles) +JSC_DCALL(sgl_begin_triangle_strip) +JSC_DCALL(sgl_begin_quads) +JSC_DCALL(sgl_end) +JSC_DCALL(sgl_draw) +JSC_1CALL(sgl_layer) +JSC_1CALL(sgl_draw_layer) + +JSC_CCALL(sgl_image, + texture *t = js2texture(argv[0]); +// transform *tr = js2transform(argv[1]); + HMM_Vec4 rect = js2vec4(argv[2]); + HMM_Vec4 color = js2vec4(argv[3]); + sgl_begin_quads(); + sgl_c4f(color.r, color.g, color.b, color.a); + sgl_v2f(0,0); + sgl_v2f(0,1); + sgl_v2f(1,1); + sgl_v2f(1,0); + sgl_end(); +// sgl_defaults(); +) + +JSC_CCALL(sgl_image_array, + JSValue array = argv[0]; + sgl_begin_quads(); + for (int i = 0; i < js_arrlen(array); i++) { + sgl_v2f(0,0); + sgl_v2f(0,1); + sgl_v2f(1,1); + sgl_v2f(1,0); + } + sgl_end(); +) + +static const JSCFunctionListEntry js_sgl_funcs[] = { + MIST_FUNC_DEF(sgl, enable_texture, 0), + MIST_FUNC_DEF(sgl, disable_texture, 0), + MIST_FUNC_DEF(sgl, texture, 1), + MIST_FUNC_DEF(sgl, matrix_mode_modelview, 0), + MIST_FUNC_DEF(sgl, matrix_mode_projection, 0), + MIST_FUNC_DEF(sgl, matrix_mode_texture, 0), + MIST_FUNC_DEF(sgl, load_identity, 0), + MIST_FUNC_DEF(sgl, translate, 1), + MIST_FUNC_DEF(sgl, rotate, 2), + MIST_FUNC_DEF(sgl, scale, 1), + MIST_FUNC_DEF(sgl, load_matrix, 1), + MIST_FUNC_DEF(sgl, frustum, 6), + MIST_FUNC_DEF(sgl, ortho, 6), + MIST_FUNC_DEF(sgl, perspective, 4), + MIST_FUNC_DEF(sgl, push_matrix, 0), + MIST_FUNC_DEF(sgl, pop_matrix, 0), + MIST_FUNC_DEF(sgl, point_size, 1), + MIST_FUNC_DEF(sgl, draw, 0), + MIST_FUNC_DEF(sgl, layer, 1), + MIST_FUNC_DEF(sgl, draw_layer, 1), + MIST_FUNC_DEF(sgl, image, 4), + MIST_FUNC_DEF(sgl, image_array, 1), +}; + +JSC_CCALL(gui_scissor, + sg_apply_scissor_rect(js2number(argv[0]), js2number(argv[1]), js2number(argv[2]), js2number(argv[3]), 0); +// sgl_scissor_rectf(js2number(argv[0]), js2number(argv[1]), js2number(argv[2]), js2number(argv[3]), 0); +) + JSC_CCALL(gui_text, const char *s = JS_ToCString(js, argv[0]); HMM_Vec2 pos = js2vec2(argv[1]); @@ -1422,12 +1520,12 @@ JSC_CCALL(vector_clamp, JSC_SSCALL(vector_trimchr, int len = js2number(js_getpropstr(argv[0], "length")); - char *start = str; + const char *start = str; while (*start == *str2) start++; - char *end = str + len-1; + const char *end = str + len-1; while(*end == *str2) end--; @@ -1656,6 +1754,9 @@ static const JSCFunctionListEntry js_prosperon_funcs[] = { MIST_FUNC_DEF(prosperon, guid, 0), }; +static const JSCFunctionListEntry js_sg_buffer_funcs[] = { +}; + JSC_CCALL(time_now, struct timeval ct; gettimeofday(&ct, NULL); @@ -1760,7 +1861,7 @@ JSC_SCALL(io_mkdir, ret = number2js(mkdir(str,0777))) JSValue js_io_slurpbytes(JSContext *js, JSValue self, int argc, JSValue *argv) { - char *f = js2str(argv[0]); + const char *f = js2str(argv[0]); size_t len; unsigned char *d = slurp_file(f,&len); if (!d) { @@ -1776,7 +1877,7 @@ JSValue js_io_slurpbytes(JSContext *js, JSValue self, int argc, JSValue *argv) JSValue js_io_slurp(JSContext *js, JSValue self, int argc, JSValue *argv) { - char *f = js2str(argv[0]); + const char *f = js2str(argv[0]); size_t len; char *s = slurp_text(f,&len); @@ -1791,11 +1892,11 @@ JSValue js_io_slurp(JSContext *js, JSValue self, int argc, JSValue *argv) JSValue js_io_slurpwrite(JSContext *js, JSValue self, int argc, JSValue *argv) { - char *f = js2str(argv[0]); + const char *f = js2str(argv[0]); size_t len; JSValue ret; if (JS_IsString(argv[1])) { - char *data = JS_ToCStringLen(js, &len, argv[1]); + const char *data = JS_ToCStringLen(js, &len, argv[1]); ret = number2js(slurp_write(data, f, len)); JS_FreeCString(js,data); } else { @@ -1808,7 +1909,7 @@ JSValue js_io_slurpwrite(JSContext *js, JSValue self, int argc, JSValue *argv) JSValue js_io_chmod(JSContext *js, JSValue self, int argc, JSValue *argv) { - char *f = js2str(argv[0]); + const char *f = js2str(argv[0]); int mod = js2number(argv[1]); chmod(f, mod); return JS_UNDEFINED; @@ -2037,7 +2138,7 @@ JSC_CCALL(transform_trs, transform *t = js2transform(self); t->pos = JS_IsUndefined(argv[0]) ? v3zero : js2vec3(argv[0]); t->rotation = JS_IsUndefined(argv[1]) ? QUAT1 : js2quat(argv[1]); - t->scale = JS_IsUndefined(argv[2]) ? v3one : js2vec3(argv[1]); + t->scale = JS_IsUndefined(argv[2]) ? v3one : js2vec3(argv[2]); ) static const JSCFunctionListEntry js_transform_funcs[] = { @@ -2538,8 +2639,7 @@ JSC_GET(texture, width, number) JSC_GET(texture, height, number) JSC_GET(texture, frames, number) JSC_GET(texture, delays, ints) -JSC_GET(texture, size, number) -JSC_GET(texture, gpusize, number) +JSC_GET(texture, vram, number) JSC_SCALL(texture_save, texture_save(js2texture(self), str)); @@ -2552,16 +2652,18 @@ JSC_CCALL(texture_getid, return number2js(tex->id.id); ) +JSC_CCALL(texture_inram, return boolean2js(js2texture(self)->data)); + static const JSCFunctionListEntry js_texture_funcs[] = { MIST_GET(texture, width), MIST_GET(texture, height), MIST_GET(texture, frames), MIST_GET(texture, delays), - MIST_GET(texture, gpusize), - MIST_GET(texture, size), + MIST_GET(texture, vram), MIST_FUNC_DEF(texture, save, 1), MIST_FUNC_DEF(texture, blit, 5), MIST_FUNC_DEF(texture, getid, 0), + MIST_FUNC_DEF(texture, inram, 0), }; static const JSCFunctionListEntry js_timer_funcs[] = { @@ -2725,6 +2827,40 @@ JSC_CCALL(os_memstate, JSJMEMRET(gc_threshold) ) +JSC_CCALL(os_mallinfo, + struct mallinfo jsmem = mallinfo(); + ret = JS_NewObject(js); + JSJMEMRET(arena); + JSJMEMRET(ordblks); + JSJMEMRET(smblks); + JSJMEMRET(hblks); + JSJMEMRET(hblkhd); + JSJMEMRET(usmblks); + JSJMEMRET(uordblks); + JSJMEMRET(fordblks); + JSJMEMRET(keepcost); +) + +JSC_CCALL(os_rusage, + struct rusage jsmem; + getrusage(RUSAGE_SELF, &jsmem); + ret = JS_NewObject(js); + JSJMEMRET(ru_maxrss); + JSJMEMRET(ru_ixrss); + JSJMEMRET(ru_idrss); + JSJMEMRET(ru_isrss); + JSJMEMRET(ru_minflt); + JSJMEMRET(ru_majflt); + JSJMEMRET(ru_nswap); + JSJMEMRET(ru_inblock); + JSJMEMRET(ru_oublock); + JSJMEMRET(ru_msgsnd); + JSJMEMRET(ru_msgrcv); + JSJMEMRET(ru_nsignals); + JSJMEMRET(ru_nvcsw); + JSJMEMRET(ru_nivcsw); +) + JSC_CCALL(os_mem, JSMemoryUsage jsmem; JS_ComputeMemoryUsage(rt, &jsmem); @@ -3221,6 +3357,8 @@ JSC_CCALL(os_skin_calculate, static const JSCFunctionListEntry js_os_funcs[] = { MIST_FUNC_DEF(os, cwd, 0), + MIST_FUNC_DEF(os, rusage, 0), + MIST_FUNC_DEF(os, mallinfo, 0), MIST_FUNC_DEF(os, env, 1), MIST_FUNC_DEF(os, sys, 0), MIST_FUNC_DEF(os, system, 1), @@ -3283,11 +3421,11 @@ void ffi_load() { globalThis = JS_GetGlobalObject(js); - QJSCLASSPREP(ptr); - QJSCLASSPREP(sg_buffer); + QJSGLOBALCLASS(os); QJSCLASSPREP_FUNCS(gameobject); + QJSCLASSPREP_FUNCS(sg_buffer); QJSCLASSPREP_FUNCS(transform); QJSCLASSPREP_FUNCS(dsp_node); QJSCLASSPREP_FUNCS(warp_gravity); @@ -3311,6 +3449,7 @@ void ffi_load() { QJSGLOBALCLASS(game); QJSGLOBALCLASS(gui); QJSGLOBALCLASS(render); +// QJSGLOBALCLASS(sgl); QJSGLOBALCLASS(physics); QJSGLOBALCLASS(vector); QJSGLOBALCLASS(spline); diff --git a/source/engine/jsffi.h b/source/engine/jsffi.h index 965fa5f..0c9f16d 100644 --- a/source/engine/jsffi.h +++ b/source/engine/jsffi.h @@ -52,6 +52,16 @@ extern JSValue cpShape2js(cpShape *s); return ret; \ } \ +#define JSC_DCALL(FN) JSValue js_##FN (JSContext *js, JSValue self, int argc, JSValue *argv) { FN(); } + +#define JSC_1CALL(FN) JSValue js_##FN (JSContext *js, JSValue self, int argc, JSValue *argv) { FN(js2number(argv[0])); } +#define JSC_2CALL(FN) JSValue js_##FN (JSContext *js, JSValue self, int argc, JSValue *argv) { FN(js2number(argv[0]), js2number(argv[1])); } +#define JSC_3CALL(FN) JSValue js_##FN (JSContext *js, JSValue self, int argc, JSValue *argv) { FN(js2number(argv[0]), js2number(argv[1]), js2number(argv[2])); } +#define JSC_4CALL(FN) JSValue js_##FN (JSContext *js, JSValue self, int argc, JSValue *argv) { FN(js2number(argv[0]), js2number(argv[1]), js2number(argv[2]), js2number(argv[3])); } +#define JSC_5CALL(FN) JSValue js_##FN (JSContext *js, JSValue self, int argc, JSValue *argv) { FN(js2number(argv[0]), js2number(argv[1]), js2number(argv[2]), js2number(argv[3]), js2number(argv[4])); } +#define JSC_6CALL(FN) JSValue js_##FN (JSContext *js, JSValue self, int argc, JSValue *argv) { FN(js2number(argv[0]), js2number(argv[1]), js2number(argv[2]), js2number(argv[3]), js2number(argv[4]), js2number(argv[5])); } +#define JSC_7CALL(FN) JSValue js_##FN (JSContext *js, JSValue self, int argc, JSValue *argv) { FN(js2number(argv[0]), js2number(argv[1]), js2number(argv[2]), js2number(argv[3]), js2number(argv[4]), js2number(argv[5]), js2number(argv[6])); } + #define GETSETPAIR(ID, ENTRY, TYPE, FN) \ JSValue js_##ID##_set_##ENTRY (JS_SETSIG) { \ js2##ID (self)->ENTRY = js2##TYPE (val); \ @@ -95,8 +105,10 @@ JSValue js_##ID##_get_##ENTRY (JSContext *js, JSValue self) { \ #define QJSCLASS(TYPE)\ static JSClassID js_##TYPE##_id;\ +static int js_##TYPE##_count = 0; \ static void js_##TYPE##_finalizer(JSRuntime *rt, JSValue val){\ TYPE *n = JS_GetOpaque(val, js_##TYPE##_id);\ +js_##TYPE##_count--; \ TYPE##_free(n);}\ static JSClassDef js_##TYPE##_class = {\ #TYPE,\ @@ -110,27 +122,28 @@ TYPE *js2##TYPE (JSValue val) { \ JSValue TYPE##2js(TYPE *n) { \ JSValue j = JS_NewObjectClass(js,js_##TYPE##_id);\ JS_SetOpaque(j,n);\ + js_##TYPE##_count++; \ return j; }\ \ static JSValue js_##TYPE##_memid (JSContext *js, JSValue self) { return str2js("%p", js2##TYPE(self)); } \ static JSValue js_##TYPE##_memsize (JSContext *js, JSValue self) { return number2js(sizeof(TYPE)); } \ +static JSValue js_##TYPE##__count (JSContext *js, JSValue self) { return number2js(js_##TYPE##_count); } \ #define QJSGLOBALCLASS(NAME) \ JSValue NAME = JS_NewObject(js); \ JS_SetPropertyFunctionList(js, NAME, js_##NAME##_funcs, countof(js_##NAME##_funcs)); \ JS_SetPropertyStr(js, globalThis, #NAME, NAME); \ -#define QJSCLASSPREP(TYPE) \ -JS_NewClassID(&js_##TYPE##_id);\ -JS_NewClass(JS_GetRuntime(js), js_##TYPE##_id, &js_##TYPE##_class);\ - /* Defines a class and uses its function list as its prototype */ #define QJSCLASSPREP_FUNCS(TYPE) \ -QJSCLASSPREP(TYPE); \ +JS_NewClassID(&js_##TYPE##_id);\ +JS_NewClass(JS_GetRuntime(js), js_##TYPE##_id, &js_##TYPE##_class);\ JSValue TYPE##_proto = JS_NewObject(js); \ JS_SetPropertyFunctionList(js, TYPE##_proto, js_##TYPE##_funcs, countof(js_##TYPE##_funcs)); \ JS_SetPropertyStr(js, TYPE##_proto, "memid", JS_NewCFunction(js, &js_##TYPE##_memid, "memid", 0)); \ JS_SetPropertyStr(js, TYPE##_proto, "memsize", JS_NewCFunction(js, &js_##TYPE##_memsize, "memsize", 0)); \ +JS_SetPropertyStr(js, TYPE##_proto, "_count", JS_NewCFunction(js, &js_##TYPE##__count, "_count", 0)); \ +JS_SetPropertyStr(js, globalThis, #TYPE "_proto", JS_DupValue(js,TYPE##_proto)); \ JS_SetClassProto(js, js_##TYPE##_id, TYPE##_proto); \ #define countof(x) (sizeof(x)/sizeof((x)[0])) diff --git a/source/engine/nota.c b/source/engine/nota.c index 86ef85d..ea17472 100644 --- a/source/engine/nota.c +++ b/source/engine/nota.c @@ -270,7 +270,7 @@ char *nota_read_text(char **text, char *nota) return nota; } -char *nota_write_text(char *s, char *nota) +char *nota_write_text(const char *s, char *nota) { nota[0] = NOTA_TEXT; diff --git a/source/engine/nota.h b/source/engine/nota.h index 173e3b5..69b2861 100644 --- a/source/engine/nota.h +++ b/source/engine/nota.h @@ -33,7 +33,7 @@ char *nota_read_sym(int *sym, char *nota); void print_nota_hex(char *nota); char *nota_write_blob(unsigned long long n, char *nota); -char *nota_write_text(char *s, char *nota); +char *nota_write_text(const char *s, char *nota); char *nota_write_array(unsigned long long n, char *nota); char *nota_write_record(unsigned long long n, char *nota); char *nota_write_float(double n, char *nota); diff --git a/source/engine/render.c b/source/engine/render.c index 380821c..fd130a2 100644 --- a/source/engine/render.c +++ b/source/engine/render.c @@ -16,7 +16,7 @@ #include "stb_image_write.h" #include "sokol/sokol_gfx.h" - +#include "sokol/util/sokol_gl.h" #include "gui.h" static HMM_Vec2 lastuse = {0}; @@ -151,6 +151,10 @@ void render_init() { .buffer_pool_size = 1024, .image_pool_size = 1024, }); + +// sgl_setup(&(sgl_desc_t){ +// .logger.func = sg_logging +// }); std_sampler = sg_make_sampler(&(sg_sampler_desc){}); tex_sampler = sg_make_sampler(&(sg_sampler_desc){ diff --git a/source/engine/texture.c b/source/engine/texture.c index 818217f..a9ed668 100644 --- a/source/engine/texture.c +++ b/source/engine/texture.c @@ -117,8 +117,7 @@ struct texture *texture_from_file(const char *path) { return NULL; tex->data = data; - tex->size = tex->width*tex->height*4; - tex->gpusize = tex->size; + tex->vram = tex->width*tex->height*4; unsigned int nw = next_pow2(tex->width); unsigned int nh = next_pow2(tex->height); @@ -144,7 +143,7 @@ struct texture *texture_from_file(const char *path) { mipdata[i] = malloc(w * h * 4); stbir_resize_uint8_linear(mipdata[i-1], mipw, miph, 0, mipdata[i], w, h, 0, 4); sg_img_data.subimage[0][i] = (sg_range){ .ptr = mipdata[i], .size = w*h*4 }; - tex->gpusize += w*h*4; + tex->vram += w*h*4; mipw = w; miph = h; @@ -161,6 +160,9 @@ struct texture *texture_from_file(const char *path) { for (int i = 1; i < mips; i++) free(mipdata[i]); + + free(tex->data); + tex->data = NULL; return tex; } @@ -286,6 +288,8 @@ double grad (int hash, double x, double y, double z) void texture_save(texture *tex, const char *file) { + if (!tex->data) return; + char *ext = strrchr(file, '.'); if (!strcmp(ext, ".png")) stbi_write_png(file, tex->width, tex->height, 4, tex->data, 4*tex->width); @@ -339,6 +343,7 @@ void blit_image(uint8_t* src, uint8_t* dest, int src_width, int src_height, int // Function to draw source image pixels on top of a destination image // x,y are the pixel coordinates in the destination image, w,h are the amount of pixels to take from the src image. void texture_blit(texture *dest, texture *src, int x, int y, int w, int h) { + if (!dest->data || !src->data) return; blit_image(src->data, dest->data, src->width, src->height, dest->width, dest->height, x, y, w, h); } diff --git a/source/engine/texture.h b/source/engine/texture.h index 085d5a8..32a1b2f 100644 --- a/source/engine/texture.h +++ b/source/engine/texture.h @@ -26,10 +26,9 @@ struct texture { int width; int height; unsigned char *data; - int size; - int gpusize; int frames; int *delays; + int vram; }; typedef struct texture texture; diff --git a/source/engine/transform.h b/source/engine/transform.h index 4783179..30f4f26 100644 --- a/source/engine/transform.h +++ b/source/engine/transform.h @@ -18,6 +18,9 @@ void transform_free(transform *t); #define VEC2_FMT "[%g,%g]" #define VEC2_MEMS(s) (s).x, (s).y +#define TR_FMT "(pos) " HMMFMT_VEC3 " scale " HMMFMT_VEC3 +#define TR_PRINT(tr) HMMPRINT_VEC3(tr->pos), HMMPRINT_VEC3(tr->scale) + void transform_move(transform *t, HMM_Vec3 v); HMM_Vec3 transform_direction(transform *t, HMM_Vec3 dir); diff --git a/source/engine/window.c b/source/engine/window.c index d987710..0e06285 100644 --- a/source/engine/window.c +++ b/source/engine/window.c @@ -66,6 +66,7 @@ void window_setfullscreen(window *w, int f) void window_seticon(struct window *w, struct texture *tex) { + if (!tex->data) return; struct isize { int size; unsigned char *data; diff --git a/source/engine/yugine.c b/source/engine/yugine.c index 6150305..e1b3a93 100644 --- a/source/engine/yugine.c +++ b/source/engine/yugine.c @@ -215,6 +215,7 @@ static sapp_desc start_desc = { .height = 1080, .high_dpi = 0, .sample_count = 1, + .swap_interval = 0, .fullscreen = 1, .window_title = NULL, .enable_clipboard = false,