diff --git a/.gitignore b/.gitignore index 622087a..6ba888e 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ atlas.png pdbs/ game_web/ .venv +build/ diff --git a/build_debug.bat b/build_debug.bat deleted file mode 100644 index 58ec917..0000000 --- a/build_debug.bat +++ /dev/null @@ -1,3 +0,0 @@ -@echo off - -odin build main_release -out:game_debug.exe -strict-style -vet -debug diff --git a/build_debug.sh b/build_debug.sh deleted file mode 100755 index b73f406..0000000 --- a/build_debug.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env bash - -odin build main_release -collection:common=./common -collection:game=./game -collection:libs=./libs -out:game_debug.bin -strict-style -vet -debug diff --git a/build_hot_reload.bat b/build_hot_reload.bat deleted file mode 100644 index 0f10cca..0000000 --- a/build_hot_reload.bat +++ /dev/null @@ -1,78 +0,0 @@ -@echo off - -set GAME_RUNNING=false -set EXE=game_hot_reload.exe - -:: Check if game is running -FOR /F %%x IN ('tasklist /NH /FI "IMAGENAME eq %EXE%"') DO IF %%x == %EXE% set GAME_RUNNING=true - -:: If game isn't running then: -:: - delete all game_XXX.dll files -:: - delete all PDBs in pdbs subdir -:: - optionally create the pdbs subdir -:: - write 0 into pdbs\pdb_number so game.dll PDBs start counting from zero -:: -:: This makes sure we start over "fresh" at PDB number 0 when starting up the -:: game and it also makes sure we don't have so many PDBs laying around. -if %GAME_RUNNING% == false ( - del /q game_*.dll 2> nul - - if exist "pdbs" ( - del /q pdbs\*.pdb - ) else ( - mkdir pdbs - ) - - echo 0 > pdbs\pdb_number -) - -:: Load PDB number from file, increment and store back. For as long as the game -:: is running the pdb_number file won't be reset to 0, so we'll get a PDB of a -:: unique name on each hot reload. -set /p PDB_NUMBER= pdbs\pdb_number - -:: Build game dll, use pdbs\game_%PDB_NUMBER%.pdb as PDB name so each dll gets -:: its own PDB. This PDB stuff is done in order to make debugging work. -:: Debuggers tend to lock PDBs or just misbehave if you reuse the same PDB while -:: the debugger is attached. So each time we compile `game.dll` we give the -:: PDB a unique PDB. -:: -:: Note that we could not just rename the PDB after creation; the DLL contains a -:: reference to where the PDB is. -:: -:: Also note that we always write game.dll to the same file. game_hot_reload.exe -:: monitors this file and does the hot reload when it changes. -echo Building game.dll -odin build game -strict-style -vet -debug -define:RAYLIB_SHARED=true -build-mode:dll -out:game.dll -pdb-name:pdbs\game_%PDB_NUMBER%.pdb > nul -IF %ERRORLEVEL% NEQ 0 exit /b 1 - -:: If game.exe already running: Then only compile game.dll and exit cleanly -if %GAME_RUNNING% == true ( - echo Game running, hot reloading... && exit /b 1 -) - -:: Build game.exe, which starts the program and loads game.dll och does the logic for hot reloading. -echo Building %EXE% -odin build main_hot_reload -strict-style -vet -debug -out:%EXE% -IF %ERRORLEVEL% NEQ 0 exit /b 1 - -:: Warning about raylib DLL not existing and where to find it. -if exist "raylib.dll" ( - exit /b 0 -) - -:: Don't name this one ODIN_ROOT as the odin exe will start using that one then. -set ODIN_PATH= - -for /f %%i in ('odin root') do set "ODIN_PATH=%%i" - -if exist "%ODIN_PATH%\vendor\raylib\windows\raylib.dll" ( - echo raylib.dll not found in current directory. Copying from %ODIN_PATH%\vendor\raylib\windows\raylib.dll - copy "%ODIN_PATH%\vendor\raylib\windows\raylib.dll" . - exit /b 0 -) - -echo "Please copy raylib.dll from /vendor/raylib/windows/raylib.dll to the same directory as game.exe" -exit /b 1 \ No newline at end of file diff --git a/build_hot_reload.sh b/build_hot_reload.sh deleted file mode 100755 index 1a6965e..0000000 --- a/build_hot_reload.sh +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env bash - -# NOTE: this is a recent addition to the Odin compiler, if you don't have this command -# you can change this to the path to the Odin folder that contains vendor, eg: "~/Odin". -ROOT=$(odin root) -if [ ! $? -eq 0 ]; then - echo "Your Odin compiler does not have the 'odin root' command, please update or hardcode it in the script." - exit 1 -fi - -set -eu - -# Figure out the mess that is dynamic libraries. -case $(uname) in -"Darwin") - case $(uname -m) in - "arm64") LIB_PATH="macos-arm64" ;; - *) LIB_PATH="macos" ;; - esac - - DLL_EXT=".dylib" - EXTRA_LINKER_FLAGS="-Wl,-rpath $ROOT/vendor/raylib/$LIB_PATH" - ;; -*) - DLL_EXT=".so" - EXTRA_LINKER_FLAGS="'-Wl,-rpath=\$ORIGIN/linux'" - - # Copy the linux libraries into the project automatically. - if [ ! -d "linux" ]; then - mkdir linux - cp -r libs/raylib/src/libraylib*.so* linux - cp -r libs/physfs/libphysfs.so* linux - fi - ;; -esac - -# Build the game. -echo "Building game$DLL_EXT" -odin build game -extra-linker-flags:"$EXTRA_LINKER_FLAGS" -define:RAYLIB_SHARED=true -define:PHYSFS_SHARED=true -define:TRACY_ENABLE=true -collection:libs=./libs -collection:common=./common -collection:game=./game -build-mode:dll -out:game_tmp$DLL_EXT -strict-style -vet -debug -o:speed - -# Need to use a temp file on Linux because it first writes an empty `game.so`, which the game will load before it is actually fully written. -mv game_tmp$DLL_EXT game$DLL_EXT - -# Do not build the game_hot_reload.bin if it is already running. -# -f is there to make sure we match against full name, including .bin -if pgrep -f game_hot_reload.bin > /dev/null; then - echo "Game running, hot reloading..." - exit 1 -else - echo "Building game_hot_reload.bin" - odin build main_hot_reload -define:TRACY_ENABLE=true -collection:libs=./libs -out:game_hot_reload.bin -strict-style -vet -debug -fi diff --git a/build_release.bat b/build_release.bat deleted file mode 100644 index fdfbbec..0000000 --- a/build_release.bat +++ /dev/null @@ -1,3 +0,0 @@ -@echo off - -odin build main_release -out:game_release.exe -strict-style -vet -no-bounds-check -o:speed -subsystem:windows diff --git a/build_release.sh b/build_release.sh deleted file mode 100755 index cf5debe..0000000 --- a/build_release.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env bash - -odin build main_release -collection:common=./common -collection:game=./game -out:game_release.bin -strict-style -vet -no-bounds-check -o:speed -debug diff --git a/build_web.bat b/build_web.bat deleted file mode 100644 index e3d05c4..0000000 --- a/build_web.bat +++ /dev/null @@ -1,19 +0,0 @@ -@echo off - -set EMSCRIPTEN_SDK_DIR=c:\emsdk -set OUT_DIR=game_web - -if not exist %OUT_DIR% mkdir %OUT_DIR% - -set EMSDK_QUIET=1 -call %EMSCRIPTEN_SDK_DIR%\emsdk_env.bat - -odin build main_web -target:freestanding_wasm32 -build-mode:obj -define:RAYLIB_WASM_LIB=env.o -vet -strict-style -out:%OUT_DIR%/game -IF %ERRORLEVEL% NEQ 0 exit /b 1 - -for /f %%i in ('odin root') do set "ODIN_PATH=%%i" - -set files=main_web/main_web.c %OUT_DIR%/game.wasm.o %ODIN_PATH%\vendor\raylib\wasm\libraylib.a -set flags=-sUSE_GLFW=3 -sASYNCIFY -sASSERTIONS -DPLATFORM_WEB -set custom=--shell-file main_web/index_template.html -emcc -o %OUT_DIR%/index.html %files% %flags% %custom% && del %OUT_DIR%\game.wasm.o \ No newline at end of file diff --git a/builder/builder.odin b/builder/builder.odin index 15899e5..0e31952 100644 --- a/builder/builder.odin +++ b/builder/builder.odin @@ -4,7 +4,9 @@ import "core:flags" import "core:fmt" import "core:log" import os "core:os/os2" +import "core:path/filepath" import "core:slice" +import "core:strings" Build_Variant :: enum { Hot_Reload, @@ -20,10 +22,9 @@ Options :: struct { tracy: bool `usage:"Enable tracy profiler"`, } -Error :: union #shared_nil { - Run_Error, - Copy_Error, - os.Error, +temp_concat :: proc(left, right: []string) -> []string { + result := slice.concatenate([][]string{left, right}, context.temp_allocator) + return result } build_deps :: proc(opts: Options) { @@ -39,18 +40,17 @@ build_deps :: proc(opts: Options) { } target := opts.variant == .Web ? "wasm32-emscripten" : "native" - handle_error( - run_cmd( - { - "zig", - "build", - "-p", - out_dir, - fmt.tprintf("-Dshared=%v", shared), - fmt.tprintf("-Dtarget=%s", target), - }, - cwd, - ), + + run_cmd( + { + "zig", + "build", + "-p", + out_dir, + fmt.tprintf("-Dshared=%v", shared), + fmt.tprintf("-Dtarget=%s", target), + }, + cwd, ) } @@ -59,16 +59,33 @@ build_deps :: proc(opts: Options) { cwd := "./libs/physfs" file_name := shared ? "libphysfs.so" : "libphysfs.a" is_built := os.is_file(fmt.tprintf("./libs/physfs/%s", file_name)) - if is_built && force { - handle_error(run_cmd({"make", "clean"}, cwd)) + if force { + remove_all("./libs/physfs/build") } + prepare_cmd := []string { + "cmake", + "-B", + "build", + fmt.tprintf("-DPHYSFS_BUILD_SHARED=%v", shared), + "-DCMAKE_BUILD_TYPE=MinSizeRel", + "./physfs", + } + build_cmd := []string{"cmake", "--build", "build", "--config", "MinSizeRel"} if !is_built || force { - handle_error(run_cmd({"make", file_name}, cwd)) + if opts.variant == .Web { + run_cmd(temp_concat({"emcmake"}, prepare_cmd), cwd) + run_cmd(temp_concat({"emmake"}, build_cmd), cwd) + } else { + run_cmd(prepare_cmd, cwd) + run_cmd(build_cmd, cwd) + } } } // Tracy if opts.tracy { + assert(opts.variant != .Web) + cwd := "./libs/tracy" when ODIN_OS == .Windows { @@ -90,29 +107,27 @@ build_deps :: proc(opts: Options) { } if !is_built || force { - handle_error( - run_cmd( - slice.concatenate( - [][]string { - { - "zig", - "c++", - "-std=c++11", - "-DTRACY_ENABLE", - "-O2", - "vendor/tracy/public/TracyClient.cpp", - "-fPIC", - }, - shared ? {"-shared", "-o", TRACY_NAME_SHARED} : {"-c", "-o", "tracy.o"}, + run_cmd( + slice.concatenate( + [][]string { + { + "zig", + "c++", + "-std=c++11", + "-DTRACY_ENABLE", + "-O2", + "vendor/tracy/public/TracyClient.cpp", + "-fPIC", }, - context.temp_allocator, - ), - cwd, + shared ? {"-shared", "-o", TRACY_NAME_SHARED} : {"-c", "-o", "tracy.o"}, + }, + context.temp_allocator, ), + cwd, ) if !shared { - handle_error(run_cmd({"zig", "ar", "rc", TRACY_NAME_STATIC, "tracy.o"}, cwd)) + run_cmd({"zig", "ar", "rc", TRACY_NAME_STATIC, "tracy.o"}, cwd) } } } @@ -126,6 +141,35 @@ COMMON_FLAGS :: []string { "-vet", } +setup_emsdk_env :: proc() { + when ODIN_OS == .Windows { + PATH_ENV_DELIMITER :: ";" + } else { + PATH_ENV_DELIMITER :: ":" + } + + PATHS :: [2]string{"./libs/emsdk/upstream/bin", "./libs/emsdk/upstream/emscripten"} + + paths: [len(PATHS)]string + for path, i in PATHS { + paths[i] = absolute_path(path) + } + + set_env( + "PATH", + strings.join( + {paths[0], paths[1], os.get_env("PATH", context.temp_allocator)}, + ":", + context.temp_allocator, + ), + ) + + set_env("EMSDK", absolute_path("./libs/emsdk")) +} + +archive_assets :: proc() { +} + main :: proc() { context.logger = log.create_console_logger() opts := Options { @@ -136,6 +180,8 @@ main :: proc() { if opts.variant == .Web { log.warnf("tracy is not supported on Web") opts.tracy = false + + setup_emsdk_env() } tracy_flag: []string = opts.tracy ? {"-define:TRACY_ENABLE=true"} : {} @@ -144,8 +190,10 @@ main :: proc() { build_deps(opts) - #partial switch opts.variant { + switch opts.variant { case .Hot_Reload: + remove_all("./build/hotreload") + mkdir_all("./build/hotreload") cmd := slice.concatenate( [][]string { []string { @@ -155,7 +203,7 @@ main :: proc() { "-define:RAYLIB_SHARED=true", "-define:PHYSFS_SHARED=true", "-build-mode:dll", - "-out:game_tmp.so", + "-out:./build/hotreload/game_tmp.so", }, tracy_flag, debug_flag, @@ -164,12 +212,14 @@ main :: proc() { }, context.temp_allocator, ) - handle_error(run_cmd(cmd, ".")) - handle_error(os.rename("game_tmp.so", "game.so")) + run_cmd(cmd, "") + rename("./build/hotreload/game_tmp.so", "./build/hotreload/game.so") case .Desktop: + remove_all("./build/desktop") + mkdir_all("./build/desktop") cmd := slice.concatenate( [][]string { - []string{"odin", "build", "main_release", "-out:game.bin"}, + []string{"odin", "build", "main_release", "-out:./build/desktop/game"}, tracy_flag, debug_flag, optimize_flag, @@ -177,17 +227,58 @@ main :: proc() { }, context.temp_allocator, ) - handle_error(run_cmd(cmd, ".")) - case: + run_cmd(cmd, "") + case .Web: + remove_all("./build/web") + mkdir_all("./build/web") + + odin_root := run_cmd({"odin", "root"}, "") + cmd := slice.concatenate( [][]string { - []string{"odin", "build", "main_web", "-build-mode:obj", "-out:game_web/game"}, + []string { + "odin", + "build", + "main_web", + "-target:js_wasm32", + "-build-mode:obj", + "-out:main_web/game", + }, COMMON_FLAGS, debug_flag, optimize_flag, }, ) + run_cmd(cmd, "") - handle_error(run_cmd(cmd, ".")) + run_cmd( + { + "emcc", + "-g", + "-o", + "build/web/index.html", + "main_web/game.wasm.o", + "libs/raylib/zig-out-static/lib/libraylib.a", + "libs/physfs/build/libphysfs.a", + "-sUSE_GLFW=3", + "-sWASM_BIGINT", + "-sWARN_ON_UNDEFINED_SYMBOLS=0", + "-sALLOW_MEMORY_GROWTH", + "-sASSERTIONS", + "--shell-file", + "main_web/index_template.html", + "--preload-file", + "assets", + }, + "", + ) + + copy_file( + filepath.join( + {odin_root, "core", "sys", "wasm", "js", "odin.js"}, + context.temp_allocator, + ), + "./build/web/odin.js", + ) } } diff --git a/builder/helpers.odin b/builder/helpers.odin index 0aa9325..879d051 100644 --- a/builder/helpers.odin +++ b/builder/helpers.odin @@ -1,11 +1,14 @@ package builder import "base:intrinsics" +import "core:bufio" import "core:fmt" +import "core:io" import "core:log" import os "core:os/os2" import "core:path/filepath" import "core:strings" +import "core:thread" Process_Error :: enum { OK, @@ -18,37 +21,104 @@ Run_Error :: union #shared_nil { os.Error, } -@(require_results) -run_cmd :: proc(cmd: []string, cwd: string, loc := #caller_location) -> Run_Error { - log.infof( - "running [%s]: %s", - cwd, - strings.join(cmd, " ", context.temp_allocator), - location = loc, - ) +run_cmd_internal :: proc( + cmd: []string, + cwd: string, + loc := #caller_location, +) -> ( + result: string, + err: Run_Error, +) { + if len(cwd) > 0 { + log.infof( + "running [%s]: %s", + cwd, + strings.join(cmd, " ", context.temp_allocator), + location = loc, + ) + } else { + log.infof("running: %s", strings.join(cmd, " ", context.temp_allocator), location = loc) + } + + r, w := os.pipe() or_return + defer os.close(r) desc := os.Process_Desc { command = cmd, working_dir = cwd, stderr = os.stderr, - stdout = os.stdout, + stdout = w, } + + Read_Context :: struct { + r: ^os.File, + result: ^string, + } + + read_ctx := Read_Context { + r = r, + result = &result, + } + + thread_ctx := context + thread_ctx.user_ptr = &read_ctx + read_thread := thread.create_and_start( + proc() { + ctx := cast(^Read_Context)context.user_ptr + + builder: strings.Builder + string_writer := strings.to_writer(&builder) + defer io.destroy(string_writer) + + mw: io.Multi_Writer + w := io.multi_writer_init(&mw, string_writer, os.to_writer(os.stderr)) + + tee: io.Tee_Reader + reader := io.tee_reader_init(&tee, os.to_reader(ctx.r), w) + buf: [1024]u8 + + err: io.Error + for { + n: int + n, err = io.read(reader, buf[:], nil) + if err == .EOF { + break + } + handle_error(err) + } + + // NOTE: mem leak, but who cares + ctx.result^ = strings.clone(strings.to_string(builder)) + }, + thread_ctx, + ) + process := os.process_start(desc) or_return + os.close(w) + state := os.process_wait(process) or_return + thread.join(read_thread) + if !state.success { - return .Crash + return "", .Crash } if state.exit_code != 0 { - return .Invalid_Exit_Code + return "", .Invalid_Exit_Code } - return nil + return result, nil } -Copy_Error :: union #shared_nil { - os.Error, - filepath.Match_Error, +run_cmd :: proc( + cmd: []string, + cwd: string, + expr := #caller_expression, + loc := #caller_location, +) -> string { + result, err := run_cmd_internal(cmd, cwd, loc) + handle_error(err, "", expr, loc) + return result } handle_error :: proc( @@ -78,3 +148,35 @@ remove_all :: proc(path: string, expr := #caller_expression, loc := #caller_loca handle_error(err, fmt.tprintf("failed to remove %s", path), expr = expr, loc = loc) } } + +copy_file :: proc(src, dst: string, expr := #caller_expression, loc := #caller_location) { + log.infof("cp %s %s", src, dst) + handle_error(os.copy_file(dst, src), "", expr, loc) +} + +rename :: proc(src, dst: string, expr := #caller_expression, loc := #caller_location) { + log.infof("rename %s -> %s", src, dst) + handle_error(os.rename(src, dst), "", expr, loc) +} + +mkdir_all :: proc(path: string, expr := #caller_expression, loc := #caller_location) { + log.infof("mkdir -p %s", path) + handle_error(os.mkdir_all(path), "", expr, loc) +} + +absolute_path :: proc( + path: string, + allocator := context.temp_allocator, + expr := #caller_expression, + loc := #caller_location, +) -> string { + abs_path, err := os.get_absolute_path(path, allocator) + handle_error(err, "", expr, loc) + + return abs_path +} + +set_env :: proc(env, val: string) { + log.infof("set_env(%s, %s)", env, val) + handle_error(os.set_env(env, val)) +} diff --git a/game/assets/assets.odin b/game/assets/assets.odin index 8d5487d..3b2762d 100644 --- a/game/assets/assets.odin +++ b/game/assets/assets.odin @@ -1,6 +1,5 @@ package assets -import "core:c" import "core:log" import "core:math" import lg "core:math/linalg" @@ -21,7 +20,7 @@ Loaded_BVH :: struct { aabb: bvh.AABB, // BVH for each mesh in a model bvhs: []bvh.BVH, - modtime: c.long, + modtime: physfs.sint64, } Loaded_Convex :: struct { @@ -198,7 +197,7 @@ assetcache_fetch_or_load :: proc( payload: Asset_Cache_Loader_Payload = nil, ) -> ( value: E, - modtime: i64, + modtime: physfs.sint64, result: Asset_Cache_Result, ) { tracy.Zone() @@ -275,10 +274,10 @@ get_texture :: proc(assetman: ^Asset_Manager, path: cstring) -> rl.Texture2D { get_model_ex :: proc( assetman: ^Asset_Manager, path: cstring, - ref_modtime: c.long = 0, // will check reload status using reference load time. When 0 reloaded will be true only if this call triggered reload + ref_modtime: physfs.sint64 = 0, // will check reload status using reference load time. When 0 reloaded will be true only if this call triggered reload ) -> ( model: rl.Model, - modtime: c.long, + modtime: physfs.sint64, reloaded: bool, ) { tracy.Zone() diff --git a/game/game.odin b/game/game.odin index 3c44911..6d9c52b 100644 --- a/game/game.odin +++ b/game/game.odin @@ -1011,25 +1011,25 @@ draw_world :: proc(world: ^World) { car_matrix = (auto_cast linalg.matrix4_translate_f32(physics.body_get_shape_pos(car_body))) * car_matrix - basic_shader := assets.get_shader( - &g_mem.assetman, - "assets/shaders/lit_vs.glsl", - "assets/shaders/lit_ps.glsl", - {.Ambient, .LightDir, .LightColor}, - ) - light_dir := linalg.normalize(rl.Vector3{1, -1, 0}) - ambient := rl.Vector3{0.1, 0.1, 0.1} - light_color := rl.Vector3{0.816, 0.855, 0.89} - rl.SetShaderValue(basic_shader.shader, basic_shader.locations[.LightDir], &light_dir, .VEC3) - rl.SetShaderValue(basic_shader.shader, basic_shader.locations[.Ambient], &ambient, .VEC3) - rl.SetShaderValue( - basic_shader.shader, - basic_shader.locations[.LightColor], - &light_color, - .VEC3, - ) + // basic_shader := assets.get_shader( + // &g_mem.assetman, + // "assets/shaders/lit_vs.glsl", + // "assets/shaders/lit_ps.glsl", + // {.Ambient, .LightDir, .LightColor}, + // ) + // light_dir := linalg.normalize(rl.Vector3{1, -1, 0}) + // ambient := rl.Vector3{0.1, 0.1, 0.1} + // light_color := rl.Vector3{0.816, 0.855, 0.89} + // rl.SetShaderValue(basic_shader.shader, basic_shader.locations[.LightDir], &light_dir, .VEC3) + // rl.SetShaderValue(basic_shader.shader, basic_shader.locations[.Ambient], &ambient, .VEC3) + // rl.SetShaderValue( + // basic_shader.shader, + // basic_shader.locations[.LightColor], + // &light_color, + // .VEC3, + // ) - render.draw_model(car_model, basic_shader.shader, car_matrix) + render.draw_model(car_model, {}, car_matrix) render.draw_mesh_light( assets.get_model(&g_mem.assetman, "assets/ae86_lights.glb"), @@ -1262,7 +1262,14 @@ game_update :: proc() -> bool { update() draw() - return !rl.WindowShouldClose() + + when ODIN_OS != .JS { + // Never run this proc in browser. It contains a 16 ms sleep on web! + if rl.WindowShouldClose() { + return true + } + } + return true } @(export) diff --git a/game/physics/debug.odin b/game/physics/debug.odin index 58075e6..e805be0 100644 --- a/game/physics/debug.odin +++ b/game/physics/debug.odin @@ -138,7 +138,7 @@ draw_debug_scene :: proc(scene: ^Scene) { } } - if true { + if false { for &contact, contact_idx in sim_state.contact_container.contacts { points_a := contact.manifold.points_a points_b := contact.manifold.points_b diff --git a/game/render/render.odin b/game/render/render.odin index bda2ddf..dc58f89 100644 --- a/game/render/render.odin +++ b/game/render/render.odin @@ -30,9 +30,9 @@ draw_model :: proc( color: rl.Color = rl.WHITE, ) { model := model - for i in 0 ..< model.materialCount { - model.materials[i].shader = shader - } + // for i in 0 ..< model.materialCount { + // model.materials[i].shader = shader + // } model.transform = transform rl.DrawModel(model, rl.Vector3{}, 1, color) @@ -42,7 +42,7 @@ draw_mesh_light :: proc(model: rl.Model, transform: rl.Matrix, color: rl.Color) model := model model.transform = transform - light_shader := assets.get_shader(assetman, nil, "assets/shaders/light_ps.glsl", {}).shader + // light_shader := assets.get_shader(assetman, nil, "assets/shaders/light_ps.glsl", {}).shader rlgl.DrawRenderBatchActive() @@ -56,7 +56,7 @@ draw_mesh_light :: proc(model: rl.Model, transform: rl.Matrix, color: rl.Color) gl.ColorMask(false, false, false, false) rlgl.SetCullFace(.FRONT) - draw_model(model, light_shader, transform, color) + draw_model(model, {}, transform, color) rlgl.DrawRenderBatchActive() } @@ -68,7 +68,7 @@ draw_mesh_light :: proc(model: rl.Model, transform: rl.Matrix, color: rl.Color) gl.ColorMask(true, true, true, true) rlgl.SetCullFace(.BACK) - draw_model(model, light_shader, transform, color) + draw_model(model, {}, transform, color) rlgl.DrawRenderBatchActive() } @@ -78,7 +78,7 @@ draw_mesh_light :: proc(model: rl.Model, transform: rl.Matrix, color: rl.Color) gl.DepthFunc(gl.GREATER) rlgl.SetCullFace(.FRONT) - draw_model(model, light_shader, transform, color) + draw_model(model, {}, transform, color) rlgl.DrawRenderBatchActive() } diff --git a/game/ui/raylib.odin b/game/ui/raylib.odin index d6e4068..17f88fa 100644 --- a/game/ui/raylib.odin +++ b/game/ui/raylib.odin @@ -29,7 +29,7 @@ rl_init :: proc() { rl.SetTextureFilter(default_atlas_texture, .POINT) gl.BindTexture(gl.TEXTURE_2D, default_atlas_texture.id) - gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_SWIZZLE_A, gl.RED) + // gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_SWIZZLE_A, gl.RED) gl.BindTexture(gl.TEXTURE_2D, 0) } diff --git a/libs/physfs/physfs.odin b/libs/physfs/physfs.odin index 3a99264..0668b5a 100644 --- a/libs/physfs/physfs.odin +++ b/libs/physfs/physfs.odin @@ -10,6 +10,8 @@ when ODIN_OS == .Linux || ODIN_OS == .Darwin { } else { foreign import lib "libphysfs.a" } +} else when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 { + foreign import lib "env.o" } @(default_calling_convention = "c", link_prefix = "PHYSFS_") diff --git a/libs/raylib/raylib.odin b/libs/raylib/raylib.odin index eed45af..b3daab9 100644 --- a/libs/raylib/raylib.odin +++ b/libs/raylib/raylib.odin @@ -109,7 +109,7 @@ when ODIN_OS == .Windows { } else when ODIN_OS == .Darwin { foreign import lib {"zig-out-shared/lib/libraylib.dylib" when RAYLIB_SHARED else "zig-out-static/lib/libraylib.a", "system:Cocoa.framework", "system:OpenGL.framework", "system:IOKit.framework"} } else when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 { - foreign import lib "zig-out-static/lib/libraylib.a" + foreign import lib "env.o" } else { foreign import lib "system:raylib" } diff --git a/libs/raylib/rlgl/rlgl.odin b/libs/raylib/rlgl/rlgl.odin index 4e4d7af..16d8b9f 100644 --- a/libs/raylib/rlgl/rlgl.odin +++ b/libs/raylib/rlgl/rlgl.odin @@ -126,6 +126,8 @@ when ODIN_OS == .Windows { foreign import lib {"../zig-out-shared/lib/libraylib.so" when RAYLIB_SHARED else "../zig-out-static/lib/libraylib.a", "system:dl", "system:pthread"} // Note(bumbread): I'm not sure why in `linux/` folder there are// multiple copies of raylib.so, but since these bindings are for// particular version of the library, I better specify it. Ideally,// though, it's best specified in terms of major (.so.4) } else when ODIN_OS == .Darwin { foreign import lib {"../zig-out-shared/lib/libraylib.dylib" when RAYLIB_SHARED else "../zig-out-static/lib/libraylib.a", "system:Cocoa.framework", "system:OpenGL.framework", "system:IOKit.framework"} +} else when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 { + foreign import lib "env.o" } else { foreign import lib "system:raylib" } diff --git a/libs/tracy/allocator.odin b/libs/tracy/allocator.odin index e43b578..72ae51a 100644 --- a/libs/tracy/allocator.odin +++ b/libs/tracy/allocator.odin @@ -3,6 +3,8 @@ package tracy import "core:c" import "core:mem" +_ :: c + ProfiledAllocatorData :: struct { backing_allocator: mem.Allocator, profiled_allocator: mem.Allocator, @@ -14,16 +16,35 @@ MakeProfiledAllocator :: proc( self: ^ProfiledAllocatorData, callstack_size: i32 = TRACY_CALLSTACK, secure: b32 = false, - backing_allocator := context.allocator) -> mem.Allocator { + backing_allocator := context.allocator, +) -> mem.Allocator { self.callstack_size = callstack_size self.secure = secure self.backing_allocator = backing_allocator - self.profiled_allocator = mem.Allocator{ + self.profiled_allocator = mem.Allocator { data = self, - procedure = proc(allocator_data: rawptr, mode: mem.Allocator_Mode, size, alignment: int, old_memory: rawptr, old_size: int, location := #caller_location) -> ([]byte, mem.Allocator_Error) { - using self := cast(^ProfiledAllocatorData) allocator_data - new_memory, error := self.backing_allocator.procedure(self.backing_allocator.data, mode, size, alignment, old_memory, old_size, location) + procedure = proc( + allocator_data: rawptr, + mode: mem.Allocator_Mode, + size, alignment: int, + old_memory: rawptr, + old_size: int, + location := #caller_location, + ) -> ( + []byte, + mem.Allocator_Error, + ) { + using self := cast(^ProfiledAllocatorData)allocator_data + new_memory, error := self.backing_allocator.procedure( + self.backing_allocator.data, + mode, + size, + alignment, + old_memory, + old_size, + location, + ) if error == .None { switch mode { case .Alloc, .Alloc_Non_Zeroed: @@ -31,14 +52,14 @@ MakeProfiledAllocator :: proc( case .Free: EmitFree(old_memory, callstack_size, secure) case .Free_All: - // NOTE: Free_All not supported by this allocator + // NOTE: Free_All not supported by this allocator case .Resize, .Resize_Non_Zeroed: EmitFree(old_memory, callstack_size, secure) EmitAlloc(new_memory, size, callstack_size, secure) case .Query_Info: - // TODO + // TODO case .Query_Features: - // TODO + // TODO } } return new_memory, error @@ -47,31 +68,39 @@ MakeProfiledAllocator :: proc( return self.profiled_allocator } -@(private="file") +@(private = "file") EmitAlloc :: #force_inline proc(new_memory: []byte, size: int, callstack_size: i32, secure: b32) { when TRACY_HAS_CALLSTACK { if callstack_size > 0 { - ___tracy_emit_memory_alloc_callstack(raw_data(new_memory), c.size_t(size), callstack_size, secure) + ___tracy_emit_memory_alloc_callstack( + raw_data(new_memory), + c.size_t(size), + callstack_size, + secure, + ) } else { ___tracy_emit_memory_alloc(raw_data(new_memory), c.size_t(size), secure) } } else { - ___tracy_emit_memory_alloc(raw_data(new_memory), c.size_t(size), secure) + when TRACY_ENABLE { + ___tracy_emit_memory_alloc(raw_data(new_memory), c.size_t(size), secure) + } } } -@(private="file") +@(private = "file") EmitFree :: #force_inline proc(old_memory: rawptr, callstack_size: i32, secure: b32) { - if old_memory == nil { return } - when TRACY_HAS_CALLSTACK { - if callstack_size > 0 { - ___tracy_emit_memory_free_callstack(old_memory, callstack_size, secure) + when TRACY_ENABLE { + if old_memory == nil {return} + + when TRACY_HAS_CALLSTACK { + if callstack_size > 0 { + ___tracy_emit_memory_free_callstack(old_memory, callstack_size, secure) + } else { + ___tracy_emit_memory_free(old_memory, secure) + } } else { ___tracy_emit_memory_free(old_memory, secure) } - } else { - ___tracy_emit_memory_free(old_memory, secure) } } - - diff --git a/libs/tracy/bindings.odin b/libs/tracy/bindings.odin index d412634..cc68aec 100644 --- a/libs/tracy/bindings.odin +++ b/libs/tracy/bindings.odin @@ -2,9 +2,13 @@ package tracy import "core:c" -when ODIN_OS == .Darwin do foreign import tracy "tracy.dylib" -when ODIN_OS == .Windows do foreign import tracy "tracy.lib" -when ODIN_OS == .Linux do foreign import tracy "tracy.so" +_ :: c + +when TRACY_ENABLE { + when ODIN_OS == .Darwin do foreign import tracy "tracy.dylib" + when ODIN_OS == .Windows do foreign import tracy "tracy.lib" + when ODIN_OS == .Linux do foreign import tracy "tracy.so" +} TracyPlotFormatEnum :: enum i32 { TracyPlotFormatNumber, @@ -77,95 +81,96 @@ ___tracy_gpu_time_sync_data :: struct { __tracy_lockable_context_data :: struct {} // NOTE(oskar): opaque -when #config(TRACY_MANUAL_LIFETIME, false) { +when TRACY_ENABLE { + when #config(TRACY_MANUAL_LIFETIME, false) { + @(default_calling_convention = "c") + foreign tracy { + ___tracy_startup_profiler :: proc() --- + ___tracy_shutdown_profiler :: proc() --- + ___tracy_profiler_started :: proc() -> b32 --- + } + } @(default_calling_convention = "c") foreign tracy { - ___tracy_startup_profiler :: proc() --- - ___tracy_shutdown_profiler :: proc() --- - ___tracy_profiler_started :: proc() -> b32 --- - } -} - -@(default_calling_convention = "c") -foreign tracy { - ___tracy_set_thread_name :: proc(name: cstring) --- - - ___tracy_alloc_srcloc :: proc(line: u32, source: cstring, sourceSz: c.size_t, function: cstring, functionSz: c.size_t, color: u32 = 0) -> u64 --- - ___tracy_alloc_srcloc_name :: proc(line: u32, source: cstring, sourceSz: c.size_t, function: cstring, functionSz: c.size_t, name: cstring, nameSz: c.size_t, color: u32 = 0) -> u64 --- - - ___tracy_emit_zone_begin :: proc(srcloc: ^___tracy_source_location_data, active: b32) -> ___tracy_c_zone_context --- - ___tracy_emit_zone_begin_callstack :: proc(srcloc: ^___tracy_source_location_data, depth: i32, active: b32) -> ___tracy_c_zone_context --- - ___tracy_emit_zone_begin_alloc :: proc(srcloc: u64, active: b32) -> ___tracy_c_zone_context --- - ___tracy_emit_zone_begin_alloc_callstack :: proc(srcloc: u64, depth: i32, active: b32) -> ___tracy_c_zone_context --- - ___tracy_emit_zone_end :: proc(ctx: ___tracy_c_zone_context) --- - ___tracy_emit_zone_text :: proc(ctx: ___tracy_c_zone_context, txt: cstring, size: c.size_t) --- - ___tracy_emit_zone_name :: proc(ctx: ___tracy_c_zone_context, txt: cstring, size: c.size_t) --- - ___tracy_emit_zone_color :: proc(ctx: ___tracy_c_zone_context, color: u32) --- - ___tracy_emit_zone_value :: proc(ctx: ___tracy_c_zone_context, value: u64) --- - - ___tracy_emit_gpu_zone_begin :: proc(_: ___tracy_gpu_zone_begin_data) --- - ___tracy_emit_gpu_zone_begin_callstack :: proc(_: ___tracy_gpu_zone_begin_callstack_data) --- - ___tracy_emit_gpu_zone_begin_alloc :: proc(_: ___tracy_gpu_zone_begin_data) --- - ___tracy_emit_gpu_zone_begin_alloc_callstack :: proc(_: ___tracy_gpu_zone_begin_callstack_data) --- - ___tracy_emit_gpu_zone_end :: proc(_: ___tracy_gpu_zone_end_data) --- - ___tracy_emit_gpu_time :: proc(_: ___tracy_gpu_time_data) --- - ___tracy_emit_gpu_new_context :: proc(_: ___tracy_gpu_new_context_data) --- - ___tracy_emit_gpu_context_name :: proc(_: ___tracy_gpu_context_name_data) --- - ___tracy_emit_gpu_calibration :: proc(_: ___tracy_gpu_calibration_data) --- - ___tracy_emit_gpu_time_sync :: proc(_: ___tracy_gpu_time_sync_data) --- - - ___tracy_emit_gpu_zone_begin_serial :: proc(_: ___tracy_gpu_zone_begin_data) --- - ___tracy_emit_gpu_zone_begin_callstack_serial :: proc(_: ___tracy_gpu_zone_begin_callstack_data) --- - ___tracy_emit_gpu_zone_begin_alloc_serial :: proc(_: ___tracy_gpu_zone_begin_data) --- - ___tracy_emit_gpu_zone_begin_alloc_callstack_serial :: proc(_: ___tracy_gpu_zone_begin_callstack_data) --- - ___tracy_emit_gpu_zone_end_serial :: proc(_: ___tracy_gpu_zone_end_data) --- - ___tracy_emit_gpu_time_serial :: proc(_: ___tracy_gpu_time_data) --- - ___tracy_emit_gpu_new_context_serial :: proc(_: ___tracy_gpu_new_context_data) --- - ___tracy_emit_gpu_context_name_serial :: proc(_: ___tracy_gpu_context_name_data) --- - ___tracy_emit_gpu_calibration_serial :: proc(_: ___tracy_gpu_calibration_data) --- - ___tracy_emit_gpu_time_sync_serial :: proc(_: ___tracy_gpu_time_sync_data) --- - - ___tracy_connected :: proc() -> b32 --- - - ___tracy_emit_memory_alloc :: proc(ptr: rawptr, size: c.size_t, secure: b32) --- - ___tracy_emit_memory_alloc_callstack :: proc(ptr: rawptr, size: c.size_t, depth: i32, secure: b32) --- - ___tracy_emit_memory_free :: proc(ptr: rawptr, secure: b32) --- - ___tracy_emit_memory_free_callstack :: proc(ptr: rawptr, depth: i32, secure: b32) --- - ___tracy_emit_memory_alloc_named :: proc(ptr: rawptr, size: c.size_t, secure: b32, name: cstring) --- - ___tracy_emit_memory_alloc_callstack_named :: proc(ptr: rawptr, size: c.size_t, depth: i32, secure: b32, name: cstring) --- - ___tracy_emit_memory_free_named :: proc(ptr: rawptr, secure: b32, name: cstring) --- - ___tracy_emit_memory_free_callstack_named :: proc(ptr: rawptr, depth: i32, secure: b32, name: cstring) --- - - ___tracy_emit_message :: proc(txt: cstring, size: c.size_t, callstack: i32) --- - ___tracy_emit_messageL :: proc(txt: cstring, callstack: i32) --- - ___tracy_emit_messageC :: proc(txt: cstring, size: c.size_t, color: u32, callstack: i32) --- - ___tracy_emit_messageLC :: proc(txt: cstring, color: u32, callstack: i32) --- - - ___tracy_emit_frame_mark :: proc(name: cstring) --- - ___tracy_emit_frame_mark_start :: proc(name: cstring) --- - ___tracy_emit_frame_mark_end :: proc(name: cstring) --- - ___tracy_emit_frame_image :: proc(image: rawptr, w, h: u16, offset: u8, flip: b32) --- - - ___tracy_emit_plot :: proc(name: cstring, val: f64) --- - ___tracy_emit_plot_float :: proc(name: cstring, val: f32) --- - ___tracy_emit_plot_int :: proc(name: cstring, val: i64) --- - ___tracy_emit_plot_config :: proc(name: cstring, type: TracyPlotFormatEnum, step, fill: b32, color: u32) --- - ___tracy_emit_message_appinfo :: proc(txt: cstring, size: c.size_t) --- - - ___tracy_announce_lockable_ctx :: proc(srcloc: ^___tracy_source_location_data) -> ^__tracy_lockable_context_data --- - ___tracy_terminate_lockable_ctx :: proc(lockdata: ^__tracy_lockable_context_data) --- - ___tracy_before_lock_lockable_ctx :: proc(lockdata: ^__tracy_lockable_context_data) -> b32 --- - ___tracy_after_lock_lockable_ctx :: proc(lockdata: ^__tracy_lockable_context_data) --- - ___tracy_after_unlock_lockable_ctx :: proc(lockdata: ^__tracy_lockable_context_data) --- - ___tracy_after_try_lock_lockable_ctx :: proc(lockdata: ^__tracy_lockable_context_data, acquired: b32) --- - ___tracy_mark_lockable_ctx :: proc(lockdata: ^__tracy_lockable_context_data, srcloc: ^___tracy_source_location_data) --- - ___tracy_custom_name_lockable_ctx :: proc(lockdata: ^__tracy_lockable_context_data, name: cstring, nameSz: c.size_t) --- -} - -when #config(TRACY_FIBERS, false) { - @(default_calling_convention = "c") - foreign tracy { - ___tracy_fiber_enter :: proc(fiber: cstring) --- - ___tracy_fiber_leave :: proc() --- + ___tracy_set_thread_name :: proc(name: cstring) --- + + ___tracy_alloc_srcloc :: proc(line: u32, source: cstring, sourceSz: c.size_t, function: cstring, functionSz: c.size_t, color: u32 = 0) -> u64 --- + ___tracy_alloc_srcloc_name :: proc(line: u32, source: cstring, sourceSz: c.size_t, function: cstring, functionSz: c.size_t, name: cstring, nameSz: c.size_t, color: u32 = 0) -> u64 --- + + ___tracy_emit_zone_begin :: proc(srcloc: ^___tracy_source_location_data, active: b32) -> ___tracy_c_zone_context --- + ___tracy_emit_zone_begin_callstack :: proc(srcloc: ^___tracy_source_location_data, depth: i32, active: b32) -> ___tracy_c_zone_context --- + ___tracy_emit_zone_begin_alloc :: proc(srcloc: u64, active: b32) -> ___tracy_c_zone_context --- + ___tracy_emit_zone_begin_alloc_callstack :: proc(srcloc: u64, depth: i32, active: b32) -> ___tracy_c_zone_context --- + ___tracy_emit_zone_end :: proc(ctx: ___tracy_c_zone_context) --- + ___tracy_emit_zone_text :: proc(ctx: ___tracy_c_zone_context, txt: cstring, size: c.size_t) --- + ___tracy_emit_zone_name :: proc(ctx: ___tracy_c_zone_context, txt: cstring, size: c.size_t) --- + ___tracy_emit_zone_color :: proc(ctx: ___tracy_c_zone_context, color: u32) --- + ___tracy_emit_zone_value :: proc(ctx: ___tracy_c_zone_context, value: u64) --- + + ___tracy_emit_gpu_zone_begin :: proc(_: ___tracy_gpu_zone_begin_data) --- + ___tracy_emit_gpu_zone_begin_callstack :: proc(_: ___tracy_gpu_zone_begin_callstack_data) --- + ___tracy_emit_gpu_zone_begin_alloc :: proc(_: ___tracy_gpu_zone_begin_data) --- + ___tracy_emit_gpu_zone_begin_alloc_callstack :: proc(_: ___tracy_gpu_zone_begin_callstack_data) --- + ___tracy_emit_gpu_zone_end :: proc(_: ___tracy_gpu_zone_end_data) --- + ___tracy_emit_gpu_time :: proc(_: ___tracy_gpu_time_data) --- + ___tracy_emit_gpu_new_context :: proc(_: ___tracy_gpu_new_context_data) --- + ___tracy_emit_gpu_context_name :: proc(_: ___tracy_gpu_context_name_data) --- + ___tracy_emit_gpu_calibration :: proc(_: ___tracy_gpu_calibration_data) --- + ___tracy_emit_gpu_time_sync :: proc(_: ___tracy_gpu_time_sync_data) --- + + ___tracy_emit_gpu_zone_begin_serial :: proc(_: ___tracy_gpu_zone_begin_data) --- + ___tracy_emit_gpu_zone_begin_callstack_serial :: proc(_: ___tracy_gpu_zone_begin_callstack_data) --- + ___tracy_emit_gpu_zone_begin_alloc_serial :: proc(_: ___tracy_gpu_zone_begin_data) --- + ___tracy_emit_gpu_zone_begin_alloc_callstack_serial :: proc(_: ___tracy_gpu_zone_begin_callstack_data) --- + ___tracy_emit_gpu_zone_end_serial :: proc(_: ___tracy_gpu_zone_end_data) --- + ___tracy_emit_gpu_time_serial :: proc(_: ___tracy_gpu_time_data) --- + ___tracy_emit_gpu_new_context_serial :: proc(_: ___tracy_gpu_new_context_data) --- + ___tracy_emit_gpu_context_name_serial :: proc(_: ___tracy_gpu_context_name_data) --- + ___tracy_emit_gpu_calibration_serial :: proc(_: ___tracy_gpu_calibration_data) --- + ___tracy_emit_gpu_time_sync_serial :: proc(_: ___tracy_gpu_time_sync_data) --- + + ___tracy_connected :: proc() -> b32 --- + + ___tracy_emit_memory_alloc :: proc(ptr: rawptr, size: c.size_t, secure: b32) --- + ___tracy_emit_memory_alloc_callstack :: proc(ptr: rawptr, size: c.size_t, depth: i32, secure: b32) --- + ___tracy_emit_memory_free :: proc(ptr: rawptr, secure: b32) --- + ___tracy_emit_memory_free_callstack :: proc(ptr: rawptr, depth: i32, secure: b32) --- + ___tracy_emit_memory_alloc_named :: proc(ptr: rawptr, size: c.size_t, secure: b32, name: cstring) --- + ___tracy_emit_memory_alloc_callstack_named :: proc(ptr: rawptr, size: c.size_t, depth: i32, secure: b32, name: cstring) --- + ___tracy_emit_memory_free_named :: proc(ptr: rawptr, secure: b32, name: cstring) --- + ___tracy_emit_memory_free_callstack_named :: proc(ptr: rawptr, depth: i32, secure: b32, name: cstring) --- + + ___tracy_emit_message :: proc(txt: cstring, size: c.size_t, callstack: i32) --- + ___tracy_emit_messageL :: proc(txt: cstring, callstack: i32) --- + ___tracy_emit_messageC :: proc(txt: cstring, size: c.size_t, color: u32, callstack: i32) --- + ___tracy_emit_messageLC :: proc(txt: cstring, color: u32, callstack: i32) --- + + ___tracy_emit_frame_mark :: proc(name: cstring) --- + ___tracy_emit_frame_mark_start :: proc(name: cstring) --- + ___tracy_emit_frame_mark_end :: proc(name: cstring) --- + ___tracy_emit_frame_image :: proc(image: rawptr, w, h: u16, offset: u8, flip: b32) --- + + ___tracy_emit_plot :: proc(name: cstring, val: f64) --- + ___tracy_emit_plot_float :: proc(name: cstring, val: f32) --- + ___tracy_emit_plot_int :: proc(name: cstring, val: i64) --- + ___tracy_emit_plot_config :: proc(name: cstring, type: TracyPlotFormatEnum, step, fill: b32, color: u32) --- + ___tracy_emit_message_appinfo :: proc(txt: cstring, size: c.size_t) --- + + ___tracy_announce_lockable_ctx :: proc(srcloc: ^___tracy_source_location_data) -> ^__tracy_lockable_context_data --- + ___tracy_terminate_lockable_ctx :: proc(lockdata: ^__tracy_lockable_context_data) --- + ___tracy_before_lock_lockable_ctx :: proc(lockdata: ^__tracy_lockable_context_data) -> b32 --- + ___tracy_after_lock_lockable_ctx :: proc(lockdata: ^__tracy_lockable_context_data) --- + ___tracy_after_unlock_lockable_ctx :: proc(lockdata: ^__tracy_lockable_context_data) --- + ___tracy_after_try_lock_lockable_ctx :: proc(lockdata: ^__tracy_lockable_context_data, acquired: b32) --- + ___tracy_mark_lockable_ctx :: proc(lockdata: ^__tracy_lockable_context_data, srcloc: ^___tracy_source_location_data) --- + ___tracy_custom_name_lockable_ctx :: proc(lockdata: ^__tracy_lockable_context_data, name: cstring, nameSz: c.size_t) --- + } + + when #config(TRACY_FIBERS, false) { + @(default_calling_convention = "c") + foreign tracy { + ___tracy_fiber_enter :: proc(fiber: cstring) --- + ___tracy_fiber_leave :: proc() --- + } } } diff --git a/libs/tracy/wrapper.odin b/libs/tracy/wrapper.odin index dedaaa7..46b70a6 100644 --- a/libs/tracy/wrapper.odin +++ b/libs/tracy/wrapper.odin @@ -2,6 +2,8 @@ package tracy import "core:c" +_ :: c + TRACY_ENABLE :: #config(TRACY_ENABLE, false) TRACY_CALLSTACK :: #config(TRACY_CALLSTACK, 1) TRACY_HAS_CALLSTACK :: #config(TRACY_HAS_CALLSTACK, false) @@ -62,19 +64,25 @@ ZoneCS :: ZoneC ZoneNCS :: ZoneNC @(disabled = !TRACY_ENABLE) -ZoneText :: #force_inline proc(ctx: ZoneCtx, text: string) {___tracy_emit_zone_text( - ctx, - _sl(text), - )} +ZoneText :: #force_inline proc( + ctx: ZoneCtx, + text: string, +) {when TRACY_ENABLE {___tracy_emit_zone_text(ctx, _sl(text))}} @(disabled = !TRACY_ENABLE) -ZoneName :: #force_inline proc(ctx: ZoneCtx, name: string) {___tracy_emit_zone_name( - ctx, - _sl(name), - )} +ZoneName :: #force_inline proc( + ctx: ZoneCtx, + name: string, +) {when TRACY_ENABLE {___tracy_emit_zone_name(ctx, _sl(name))}} @(disabled = !TRACY_ENABLE) -ZoneColor :: #force_inline proc(ctx: ZoneCtx, color: u32) {___tracy_emit_zone_color(ctx, color)} +ZoneColor :: #force_inline proc( + ctx: ZoneCtx, + color: u32, +) {when TRACY_ENABLE {___tracy_emit_zone_color(ctx, color)}} @(disabled = !TRACY_ENABLE) -ZoneValue :: #force_inline proc(ctx: ZoneCtx, value: u64) {___tracy_emit_zone_value(ctx, value)} +ZoneValue :: #force_inline proc( + ctx: ZoneCtx, + value: u64, +) {when TRACY_ENABLE {___tracy_emit_zone_value(ctx, value)}} // NOTE: scoped Zone*() procs also exists, no need of calling this directly. ZoneBegin :: proc(active: bool, depth: i32, loc := #caller_location) -> (ctx: ZoneCtx) { @@ -98,7 +106,7 @@ ZoneBegin :: proc(active: bool, depth: i32, loc := #caller_location) -> (ctx: Zo // NOTE: scoped Zone*() procs also exists, no need of calling this directly. @(disabled = !TRACY_ENABLE) -ZoneEnd :: #force_inline proc(ctx: ZoneCtx) {___tracy_emit_zone_end(ctx)} +ZoneEnd :: #force_inline proc(ctx: ZoneCtx) {when TRACY_ENABLE {___tracy_emit_zone_end(ctx)}} // Memory profiling // (See allocator.odin for an implementation of an Odin custom allocator using memory profiling.) @@ -107,89 +115,91 @@ Alloc :: #force_inline proc( ptr: rawptr, size: c.size_t, depth: i32 = TRACY_CALLSTACK, -) {when TRACY_HAS_CALLSTACK {___tracy_emit_memory_alloc_callstack( - ptr, - size, - depth, - false, - )} else {___tracy_emit_memory_alloc(ptr, size, false)}} +) {when TRACY_ENABLE {when TRACY_HAS_CALLSTACK {___tracy_emit_memory_alloc_callstack( + ptr, + size, + depth, + false, + )} else {___tracy_emit_memory_alloc(ptr, size, false)}}} @(disabled = !TRACY_ENABLE) Free :: #force_inline proc( ptr: rawptr, depth: i32 = TRACY_CALLSTACK, -) {when TRACY_HAS_CALLSTACK {___tracy_emit_memory_free_callstack( - ptr, - depth, - false, - )} else {___tracy_emit_memory_free(ptr, false)}} +) {when TRACY_ENABLE {when TRACY_HAS_CALLSTACK {___tracy_emit_memory_free_callstack( + ptr, + depth, + false, + )} else {___tracy_emit_memory_free(ptr, false)}}} @(disabled = !TRACY_ENABLE) SecureAlloc :: #force_inline proc( ptr: rawptr, size: c.size_t, depth: i32 = TRACY_CALLSTACK, -) {when TRACY_HAS_CALLSTACK {___tracy_emit_memory_alloc_callstack( - ptr, - size, - depth, - true, - )} else {___tracy_emit_memory_alloc(ptr, size, true)}} +) {when TRACY_ENABLE {when TRACY_HAS_CALLSTACK {___tracy_emit_memory_alloc_callstack( + ptr, + size, + depth, + true, + )} else {___tracy_emit_memory_alloc(ptr, size, true)}}} @(disabled = !TRACY_ENABLE) SecureFree :: #force_inline proc( ptr: rawptr, depth: i32 = TRACY_CALLSTACK, -) {when TRACY_HAS_CALLSTACK {___tracy_emit_memory_free_callstack( - ptr, - depth, - true, - )} else {___tracy_emit_memory_free(ptr, true)}} +) {when TRACY_ENABLE {when TRACY_HAS_CALLSTACK {___tracy_emit_memory_free_callstack( + ptr, + depth, + true, + )} else {___tracy_emit_memory_free(ptr, true)}}} @(disabled = !TRACY_ENABLE) AllocN :: #force_inline proc( ptr: rawptr, size: c.size_t, name: cstring, depth: i32 = TRACY_CALLSTACK, -) {when TRACY_HAS_CALLSTACK {___tracy_emit_memory_alloc_callstack_named( - ptr, - size, - depth, - false, - name, - )} else {___tracy_emit_memory_alloc_named(ptr, size, false, name)}} +) { + when TRACY_ENABLE { + when TRACY_HAS_CALLSTACK { + ___tracy_emit_memory_alloc_callstack_named(ptr, size, depth, false, name) + } else { + __tracy_emit_memory_alloc_named(ptr, size, false, name) + } + } +} @(disabled = !TRACY_ENABLE) FreeN :: #force_inline proc( ptr: rawptr, name: cstring, depth: i32 = TRACY_CALLSTACK, -) {when TRACY_HAS_CALLSTACK {___tracy_emit_memory_free_callstack_named( - ptr, - depth, - false, - name, - )} else {___tracy_emit_memory_free_named(ptr, false, name)}} +) {when TRACY_ENABLE {when TRACY_HAS_CALLSTACK {___tracy_emit_memory_free_callstack_named( + ptr, + depth, + false, + name, + )} else {___tracy_emit_memory_free_named(ptr, false, name)}}} @(disabled = !TRACY_ENABLE) SecureAllocN :: #force_inline proc( ptr: rawptr, size: c.size_t, name: cstring, depth: i32 = TRACY_CALLSTACK, -) {when TRACY_HAS_CALLSTACK {___tracy_emit_memory_alloc_callstack_named( - ptr, - size, - depth, - true, - name, - )} else {___tracy_emit_memory_alloc_named(ptr, size, true, name)}} +) {when TRACY_ENABLE {when TRACY_HAS_CALLSTACK {___tracy_emit_memory_alloc_callstack_named( + ptr, + size, + depth, + true, + name, + )} else {when TRACY_ENABLE {___tracy_emit_memory_alloc_named(ptr, size, true, name)}}}} @(disabled = !TRACY_ENABLE) SecureFreeN :: #force_inline proc( ptr: rawptr, name: cstring, depth: i32 = TRACY_CALLSTACK, -) {when TRACY_HAS_CALLSTACK {___tracy_emit_memory_free_callstack_named( - ptr, - depth, - true, - name, - )} else {___tracy_emit_memory_free_named(ptr, true, name)}} +) {when TRACY_ENABLE {when TRACY_HAS_CALLSTACK {___tracy_emit_memory_free_callstack_named( + ptr, + depth, + true, + name, + )} else {___tracy_emit_memory_free_named(ptr, true, name)}}} // Dummy aliases to match C API (only difference is the `depth` parameter, // which we declare as optional for the non-S procs.) @@ -204,48 +214,67 @@ SecureFreeNS :: SecureFreeN // Frame markup @(disabled = !TRACY_ENABLE) -FrameMark :: #force_inline proc(name: cstring = nil) {___tracy_emit_frame_mark(name)} +FrameMark :: #force_inline proc(name: cstring = nil) {when TRACY_ENABLE {___tracy_emit_frame_mark( + name, + )}} @(disabled = !TRACY_ENABLE) -FrameMarkStart :: #force_inline proc(name: cstring) {___tracy_emit_frame_mark_start(name)} +FrameMarkStart :: #force_inline proc( + name: cstring, +) {when TRACY_ENABLE {___tracy_emit_frame_mark_start(name)}} @(disabled = !TRACY_ENABLE) -FrameMarkEnd :: #force_inline proc(name: cstring) {___tracy_emit_frame_mark_end(name)} +FrameMarkEnd :: #force_inline proc( + name: cstring, +) {when TRACY_ENABLE {___tracy_emit_frame_mark_end(name)}} @(disabled = !TRACY_ENABLE) FrameImage :: #force_inline proc( image: rawptr, w, h: u16, offset: u8, flip: b32, -) {___tracy_emit_frame_image(image, w, h, offset, flip)} +) {when TRACY_ENABLE {___tracy_emit_frame_image(image, w, h, offset, flip)}} // Plots and messages @(disabled = !TRACY_ENABLE) -Plot :: #force_inline proc(name: cstring, value: f64) {___tracy_emit_plot(name, value)} +Plot :: #force_inline proc(name: cstring, value: f64) {when TRACY_ENABLE {___tracy_emit_plot( + name, + value, + )}} @(disabled = !TRACY_ENABLE) -PlotF :: #force_inline proc(name: cstring, value: f32) {___tracy_emit_plot_float(name, value)} +PlotF :: #force_inline proc( + name: cstring, + value: f32, +) {when TRACY_ENABLE {___tracy_emit_plot_float(name, value)}} @(disabled = !TRACY_ENABLE) -PlotI :: #force_inline proc(name: cstring, value: i64) {___tracy_emit_plot_int(name, value)} +PlotI :: #force_inline proc(name: cstring, value: i64) {when TRACY_ENABLE {___tracy_emit_plot_int( + name, + value, + )}} @(disabled = !TRACY_ENABLE) PlotConfig :: #force_inline proc( name: cstring, type: TracyPlotFormatEnum, step, fill: b32, color: u32, -) {___tracy_emit_plot_config(name, type, step, fill, color)} +) {when TRACY_ENABLE {___tracy_emit_plot_config(name, type, step, fill, color)}} @(disabled = !TRACY_ENABLE) -Message :: #force_inline proc(txt: string) {___tracy_emit_message( - _sl(txt), - TRACY_CALLSTACK when TRACY_HAS_CALLSTACK else 0, - )} +Message :: #force_inline proc(txt: string) {when TRACY_ENABLE {___tracy_emit_message( + _sl(txt), + TRACY_CALLSTACK when TRACY_HAS_CALLSTACK else 0, + )}} @(disabled = !TRACY_ENABLE) -MessageC :: #force_inline proc(txt: string, color: u32) {___tracy_emit_message( - _sl(txt), - TRACY_CALLSTACK when TRACY_HAS_CALLSTACK else 0, - )} +MessageC :: #force_inline proc(txt: string, color: u32) {when TRACY_ENABLE {___tracy_emit_message( + _sl(txt), + TRACY_CALLSTACK when TRACY_HAS_CALLSTACK else 0, + )}} @(disabled = !TRACY_ENABLE) -AppInfo :: #force_inline proc(name: string) {___tracy_emit_message_appinfo(_sl(name))} +AppInfo :: #force_inline proc(name: string) {when TRACY_ENABLE {___tracy_emit_message_appinfo( + _sl(name), + )}} @(disabled = !TRACY_ENABLE) -SetThreadName :: #force_inline proc(name: cstring) {___tracy_set_thread_name(name)} +SetThreadName :: #force_inline proc(name: cstring) {when TRACY_ENABLE {___tracy_set_thread_name( + name, + )}} // Connection status IsConnected :: #force_inline proc() -> bool {return( @@ -299,28 +328,38 @@ LockAnnounce :: #force_inline proc(loc := #caller_location) -> (ctx: LockCtx) { return } @(disabled = !TRACY_ENABLE) -LockTerminate :: #force_inline proc(lock: LockCtx) {___tracy_terminate_lockable_ctx(lock)} +LockTerminate :: #force_inline proc( + lock: LockCtx, +) {when TRACY_ENABLE {___tracy_terminate_lockable_ctx(lock)}} @(disabled = !TRACY_ENABLE) -LockBeforeLock :: #force_inline proc(lock: LockCtx) {___tracy_before_lock_lockable_ctx(lock)} +LockBeforeLock :: #force_inline proc( + lock: LockCtx, +) {when TRACY_ENABLE {___tracy_before_lock_lockable_ctx(lock)}} @(disabled = !TRACY_ENABLE) -LockAfterLock :: #force_inline proc(lock: LockCtx) {___tracy_after_lock_lockable_ctx(lock)} +LockAfterLock :: #force_inline proc( + lock: LockCtx, +) {when TRACY_ENABLE {___tracy_after_lock_lockable_ctx(lock)}} @(disabled = !TRACY_ENABLE) -LockAfterUnlock :: #force_inline proc(lock: LockCtx) {___tracy_after_unlock_lockable_ctx(lock)} +LockAfterUnlock :: #force_inline proc( + lock: LockCtx, +) {when TRACY_ENABLE {___tracy_after_unlock_lockable_ctx(lock)}} @(disabled = !TRACY_ENABLE) LockAfterTryLock :: #force_inline proc( lock: LockCtx, acquired: bool, -) {___tracy_after_try_lock_lockable_ctx(lock, b32(acquired))} +) {when TRACY_ENABLE {___tracy_after_try_lock_lockable_ctx(lock, b32(acquired))}} @(disabled = !TRACY_ENABLE) LockMark :: #force_inline proc(lock: LockCtx, loc := #caller_location) { - id := ___tracy_alloc_srcloc(u32(loc.line), _sl(loc.file_path), _sl(loc.procedure)) - ___tracy_mark_lockable_ctx(lock, (^___tracy_source_location_data)(uintptr(id))) + when TRACY_ENABLE { + id := ___tracy_alloc_srcloc(u32(loc.line), _sl(loc.file_path), _sl(loc.procedure)) + ___tracy_mark_lockable_ctx(lock, (^___tracy_source_location_data)(uintptr(id))) + } } @(disabled = !TRACY_ENABLE) LockCustomName :: #force_inline proc( lock: LockCtx, name: string, -) {___tracy_custom_name_lockable_ctx(lock, _sl(name))} +) {when TRACY_ENABLE {___tracy_custom_name_lockable_ctx(lock, _sl(name))}} // Helper for passing cstring+length to Tracy functions. @(private = "file") diff --git a/main_web/game.wasm.o b/main_web/game.wasm.o new file mode 100644 index 0000000..e052fb9 Binary files /dev/null and b/main_web/game.wasm.o differ diff --git a/main_web/index_template.html b/main_web/index_template.html index 8746dc0..39579c5 100644 --- a/main_web/index_template.html +++ b/main_web/index_template.html @@ -1,78 +1,114 @@ - - - + + + - Odin + Raylib on the web + Odin + Raylib on the web + + + - - - + + + + + + - - - - -

- - {{{ SCRIPT }}} - + // See source/main_web/main_web.odin for main_start, + // main_update and main_end. + e.main_start(); + + function send_resize() { + var canvas = document.getElementById('canvas'); + e.web_window_size_changed(canvas.width, canvas.height); + } + + window.addEventListener('resize', function(event) { + send_resize(); + }, true); + + // This can probably be done better: Ideally we'd feed the + // initial size to `main_start`. But there seems to be a + // race condition. `canvas` doesn't have it's correct size yet. + send_resize(); + + // Runs the "main loop". + function do_main_update() { + if (!e.main_update()) { + e.main_end(); + + // Calls procedures marked with @fini + e._end(); + return; + } + window.requestAnimationFrame(do_main_update); + } + + window.requestAnimationFrame(do_main_update); + }, + print: (function() { + var element = document.getElementById("output"); + if (element) element.value = ''; // clear browser cache + return function(text) { + if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' '); + console.log(text); + if (element) { + element.value += text + "\n"; + element.scrollTop = element.scrollHeight; // focus on bottom + } + }; + })(), + canvas: (function() { + return document.getElementById("canvas"); + })() + }; + + + + {{{ SCRIPT }}} + diff --git a/main_web/main_web.c b/main_web/main_web.c deleted file mode 100644 index e759299..0000000 --- a/main_web/main_web.c +++ /dev/null @@ -1,37 +0,0 @@ -#include -#include -#include - -extern void web_init(); -extern void web_update(); -extern void web_window_size_changed(int w, int h); - -void update_window_size() { - double w, h; - emscripten_get_element_css_size("#canvas", &w, &h); - web_window_size_changed((int)w, (int)h); -} - -static EM_BOOL on_web_display_size_changed( - int event_type, - const EmscriptenUiEvent *event, - void *user_data -) { - update_window_size(); - return 0; -} - -int main(void) { - emscripten_set_resize_callback( - EMSCRIPTEN_EVENT_TARGET_WINDOW, - 0, 0, on_web_display_size_changed - ); - - web_init(); - update_window_size(); - emscripten_set_main_loop(web_update, 0, 1); - - // We don't really "shutdown" the game, since web browser tabs just close. - - return 0; -} \ No newline at end of file diff --git a/main_web/main_web.odin b/main_web/main_web.odin index def0f55..318d90d 100644 --- a/main_web/main_web.odin +++ b/main_web/main_web.odin @@ -29,7 +29,7 @@ main_start :: proc "c" () { web_context = context - game.game_init_window({}) + game.game_init_window({"."}) game.game_init() } diff --git a/main_web/main_web_support.odin b/main_web/main_web_support.odin deleted file mode 100644 index 963f409..0000000 --- a/main_web/main_web_support.odin +++ /dev/null @@ -1,120 +0,0 @@ -/* -This file implements logger and temp allocator for the web build. The logger -is based on the one found here: https://github.com/Aronicu/Raylib-WASM/tree/main -*/ - -#+build wasm32, wasm64p32 - -package main_web - -import "base:runtime" -import "core:c" -import "core:fmt" -import "core:log" -import "core:strings" - - -// WASM logger - -WASM_Logger_Opts :: log.Options{.Level, .Short_File_Path, .Line} - -create_wasm_logger :: proc (lowest := log.Level.Debug, opt := WASM_Logger_Opts) -> log.Logger { - return log.Logger{data = nil, procedure = wasm_logger_proc, lowest_level = lowest, options = opt} -} - -@(private="file") -wasm_logger_proc :: proc( - logger_data: rawptr, - level: log.Level, - text: string, - options: log.Options, - location := #caller_location -) { - b := strings.builder_make(context.temp_allocator) - strings.write_string(&b, Wasm_Logger_Level_Headers[level]) - do_location_header(options, &b, location) - fmt.sbprint(&b, text) - puts(strings.to_cstring(&b)) -} - -@(private="file") -Wasm_Logger_Level_Headers := [?]string { - 0 ..< 10 = "[DEBUG] --- ", - 10 ..< 20 = "[INFO ] --- ", - 20 ..< 30 = "[WARN ] --- ", - 30 ..< 40 = "[ERROR] --- ", - 40 ..< 50 = "[FATAL] --- ", -} - -@(private="file") -do_location_header :: proc(opts: log.Options, buf: ^strings.Builder, location := #caller_location) { - if log.Location_Header_Opts & opts == nil { - return - } - fmt.sbprint(buf, "[") - file := location.file_path - if .Short_File_Path in opts { - last := 0 - for r, i in location.file_path { - if r == '/' { - last = i + 1 - } - } - file = location.file_path[last:] - } - - if log.Location_File_Opts & opts != nil { - fmt.sbprint(buf, file) - } - if .Line in opts { - if log.Location_File_Opts & opts != nil { - fmt.sbprint(buf, ":") - } - fmt.sbprint(buf, location.line) - } - - if .Procedure in opts { - if (log.Location_File_Opts | {.Line}) & opts != nil { - fmt.sbprint(buf, ":") - } - fmt.sbprintf(buf, "%s()", location.procedure) - } - - fmt.sbprint(buf, "] ") -} - -@(default_calling_convention = "c") -foreign { - puts :: proc(buffer: cstring) -> c.int --- -} - - -// Temp Allocator -// More or less a copy from base:runtime (that one is disabled in freestanding -// build mode). - -WASM_Temp_Allocator :: struct { - arena: runtime.Arena, -} - -wasm_temp_allocator_init :: proc(s: ^WASM_Temp_Allocator, size: int, backing_allocator := context.allocator) { - _ = runtime.arena_init(&s.arena, uint(size), backing_allocator) -} - -wasm_temp_allocator_proc :: proc( - allocator_data: rawptr, - mode: runtime.Allocator_Mode, - size, alignment: int, - old_memory: rawptr, - old_size: int, - loc := #caller_location) -> (data: []byte, err: runtime.Allocator_Error) { - s := (^WASM_Temp_Allocator)(allocator_data) - return runtime.arena_allocator_proc(&s.arena, mode, size, alignment, old_memory, old_size, loc) -} - -wasm_temp_allocator :: proc(allocator: ^WASM_Temp_Allocator) -> runtime.Allocator { - return runtime.Allocator{ - procedure = wasm_temp_allocator_proc, - data = allocator, - } -} \ No newline at end of file