Web Build!!!
This commit is contained in:
parent
b855732e29
commit
c31ebea3bd
1
.gitignore
vendored
1
.gitignore
vendored
@ -17,3 +17,4 @@ atlas.png
|
|||||||
pdbs/
|
pdbs/
|
||||||
game_web/
|
game_web/
|
||||||
.venv
|
.venv
|
||||||
|
build/
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
@echo off
|
|
||||||
|
|
||||||
odin build main_release -out:game_debug.exe -strict-style -vet -debug
|
|
@ -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
|
|
@ -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
|
|
||||||
set /a PDB_NUMBER=%PDB_NUMBER%+1
|
|
||||||
echo %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 <your_odin_compiler>/vendor/raylib/windows/raylib.dll to the same directory as game.exe"
|
|
||||||
exit /b 1
|
|
@ -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
|
|
@ -1,3 +0,0 @@
|
|||||||
@echo off
|
|
||||||
|
|
||||||
odin build main_release -out:game_release.exe -strict-style -vet -no-bounds-check -o:speed -subsystem:windows
|
|
@ -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
|
|
@ -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
|
|
@ -4,7 +4,9 @@ import "core:flags"
|
|||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
import "core:log"
|
import "core:log"
|
||||||
import os "core:os/os2"
|
import os "core:os/os2"
|
||||||
|
import "core:path/filepath"
|
||||||
import "core:slice"
|
import "core:slice"
|
||||||
|
import "core:strings"
|
||||||
|
|
||||||
Build_Variant :: enum {
|
Build_Variant :: enum {
|
||||||
Hot_Reload,
|
Hot_Reload,
|
||||||
@ -20,10 +22,9 @@ Options :: struct {
|
|||||||
tracy: bool `usage:"Enable tracy profiler"`,
|
tracy: bool `usage:"Enable tracy profiler"`,
|
||||||
}
|
}
|
||||||
|
|
||||||
Error :: union #shared_nil {
|
temp_concat :: proc(left, right: []string) -> []string {
|
||||||
Run_Error,
|
result := slice.concatenate([][]string{left, right}, context.temp_allocator)
|
||||||
Copy_Error,
|
return result
|
||||||
os.Error,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
build_deps :: proc(opts: Options) {
|
build_deps :: proc(opts: Options) {
|
||||||
@ -39,7 +40,7 @@ build_deps :: proc(opts: Options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
target := opts.variant == .Web ? "wasm32-emscripten" : "native"
|
target := opts.variant == .Web ? "wasm32-emscripten" : "native"
|
||||||
handle_error(
|
|
||||||
run_cmd(
|
run_cmd(
|
||||||
{
|
{
|
||||||
"zig",
|
"zig",
|
||||||
@ -50,7 +51,6 @@ build_deps :: proc(opts: Options) {
|
|||||||
fmt.tprintf("-Dtarget=%s", target),
|
fmt.tprintf("-Dtarget=%s", target),
|
||||||
},
|
},
|
||||||
cwd,
|
cwd,
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,16 +59,33 @@ build_deps :: proc(opts: Options) {
|
|||||||
cwd := "./libs/physfs"
|
cwd := "./libs/physfs"
|
||||||
file_name := shared ? "libphysfs.so" : "libphysfs.a"
|
file_name := shared ? "libphysfs.so" : "libphysfs.a"
|
||||||
is_built := os.is_file(fmt.tprintf("./libs/physfs/%s", file_name))
|
is_built := os.is_file(fmt.tprintf("./libs/physfs/%s", file_name))
|
||||||
if is_built && force {
|
if force {
|
||||||
handle_error(run_cmd({"make", "clean"}, cwd))
|
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 {
|
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
|
// Tracy
|
||||||
if opts.tracy {
|
if opts.tracy {
|
||||||
|
assert(opts.variant != .Web)
|
||||||
|
|
||||||
cwd := "./libs/tracy"
|
cwd := "./libs/tracy"
|
||||||
|
|
||||||
when ODIN_OS == .Windows {
|
when ODIN_OS == .Windows {
|
||||||
@ -90,7 +107,6 @@ build_deps :: proc(opts: Options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !is_built || force {
|
if !is_built || force {
|
||||||
handle_error(
|
|
||||||
run_cmd(
|
run_cmd(
|
||||||
slice.concatenate(
|
slice.concatenate(
|
||||||
[][]string {
|
[][]string {
|
||||||
@ -108,11 +124,10 @@ build_deps :: proc(opts: Options) {
|
|||||||
context.temp_allocator,
|
context.temp_allocator,
|
||||||
),
|
),
|
||||||
cwd,
|
cwd,
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if !shared {
|
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",
|
"-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() {
|
main :: proc() {
|
||||||
context.logger = log.create_console_logger()
|
context.logger = log.create_console_logger()
|
||||||
opts := Options {
|
opts := Options {
|
||||||
@ -136,6 +180,8 @@ main :: proc() {
|
|||||||
if opts.variant == .Web {
|
if opts.variant == .Web {
|
||||||
log.warnf("tracy is not supported on Web")
|
log.warnf("tracy is not supported on Web")
|
||||||
opts.tracy = false
|
opts.tracy = false
|
||||||
|
|
||||||
|
setup_emsdk_env()
|
||||||
}
|
}
|
||||||
|
|
||||||
tracy_flag: []string = opts.tracy ? {"-define:TRACY_ENABLE=true"} : {}
|
tracy_flag: []string = opts.tracy ? {"-define:TRACY_ENABLE=true"} : {}
|
||||||
@ -144,8 +190,10 @@ main :: proc() {
|
|||||||
|
|
||||||
build_deps(opts)
|
build_deps(opts)
|
||||||
|
|
||||||
#partial switch opts.variant {
|
switch opts.variant {
|
||||||
case .Hot_Reload:
|
case .Hot_Reload:
|
||||||
|
remove_all("./build/hotreload")
|
||||||
|
mkdir_all("./build/hotreload")
|
||||||
cmd := slice.concatenate(
|
cmd := slice.concatenate(
|
||||||
[][]string {
|
[][]string {
|
||||||
[]string {
|
[]string {
|
||||||
@ -155,7 +203,7 @@ main :: proc() {
|
|||||||
"-define:RAYLIB_SHARED=true",
|
"-define:RAYLIB_SHARED=true",
|
||||||
"-define:PHYSFS_SHARED=true",
|
"-define:PHYSFS_SHARED=true",
|
||||||
"-build-mode:dll",
|
"-build-mode:dll",
|
||||||
"-out:game_tmp.so",
|
"-out:./build/hotreload/game_tmp.so",
|
||||||
},
|
},
|
||||||
tracy_flag,
|
tracy_flag,
|
||||||
debug_flag,
|
debug_flag,
|
||||||
@ -164,12 +212,14 @@ main :: proc() {
|
|||||||
},
|
},
|
||||||
context.temp_allocator,
|
context.temp_allocator,
|
||||||
)
|
)
|
||||||
handle_error(run_cmd(cmd, "."))
|
run_cmd(cmd, "")
|
||||||
handle_error(os.rename("game_tmp.so", "game.so"))
|
rename("./build/hotreload/game_tmp.so", "./build/hotreload/game.so")
|
||||||
case .Desktop:
|
case .Desktop:
|
||||||
|
remove_all("./build/desktop")
|
||||||
|
mkdir_all("./build/desktop")
|
||||||
cmd := slice.concatenate(
|
cmd := slice.concatenate(
|
||||||
[][]string {
|
[][]string {
|
||||||
[]string{"odin", "build", "main_release", "-out:game.bin"},
|
[]string{"odin", "build", "main_release", "-out:./build/desktop/game"},
|
||||||
tracy_flag,
|
tracy_flag,
|
||||||
debug_flag,
|
debug_flag,
|
||||||
optimize_flag,
|
optimize_flag,
|
||||||
@ -177,17 +227,58 @@ main :: proc() {
|
|||||||
},
|
},
|
||||||
context.temp_allocator,
|
context.temp_allocator,
|
||||||
)
|
)
|
||||||
handle_error(run_cmd(cmd, "."))
|
run_cmd(cmd, "")
|
||||||
case:
|
case .Web:
|
||||||
|
remove_all("./build/web")
|
||||||
|
mkdir_all("./build/web")
|
||||||
|
|
||||||
|
odin_root := run_cmd({"odin", "root"}, "")
|
||||||
|
|
||||||
cmd := slice.concatenate(
|
cmd := slice.concatenate(
|
||||||
[][]string {
|
[][]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,
|
COMMON_FLAGS,
|
||||||
debug_flag,
|
debug_flag,
|
||||||
optimize_flag,
|
optimize_flag,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
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",
|
||||||
|
},
|
||||||
|
"",
|
||||||
|
)
|
||||||
|
|
||||||
handle_error(run_cmd(cmd, "."))
|
copy_file(
|
||||||
|
filepath.join(
|
||||||
|
{odin_root, "core", "sys", "wasm", "js", "odin.js"},
|
||||||
|
context.temp_allocator,
|
||||||
|
),
|
||||||
|
"./build/web/odin.js",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
package builder
|
package builder
|
||||||
|
|
||||||
import "base:intrinsics"
|
import "base:intrinsics"
|
||||||
|
import "core:bufio"
|
||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
|
import "core:io"
|
||||||
import "core:log"
|
import "core:log"
|
||||||
import os "core:os/os2"
|
import os "core:os/os2"
|
||||||
import "core:path/filepath"
|
import "core:path/filepath"
|
||||||
import "core:strings"
|
import "core:strings"
|
||||||
|
import "core:thread"
|
||||||
|
|
||||||
Process_Error :: enum {
|
Process_Error :: enum {
|
||||||
OK,
|
OK,
|
||||||
@ -18,37 +21,104 @@ Run_Error :: union #shared_nil {
|
|||||||
os.Error,
|
os.Error,
|
||||||
}
|
}
|
||||||
|
|
||||||
@(require_results)
|
run_cmd_internal :: proc(
|
||||||
run_cmd :: proc(cmd: []string, cwd: string, loc := #caller_location) -> Run_Error {
|
cmd: []string,
|
||||||
|
cwd: string,
|
||||||
|
loc := #caller_location,
|
||||||
|
) -> (
|
||||||
|
result: string,
|
||||||
|
err: Run_Error,
|
||||||
|
) {
|
||||||
|
if len(cwd) > 0 {
|
||||||
log.infof(
|
log.infof(
|
||||||
"running [%s]: %s",
|
"running [%s]: %s",
|
||||||
cwd,
|
cwd,
|
||||||
strings.join(cmd, " ", context.temp_allocator),
|
strings.join(cmd, " ", context.temp_allocator),
|
||||||
location = loc,
|
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 {
|
desc := os.Process_Desc {
|
||||||
command = cmd,
|
command = cmd,
|
||||||
working_dir = cwd,
|
working_dir = cwd,
|
||||||
stderr = os.stderr,
|
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
|
process := os.process_start(desc) or_return
|
||||||
|
os.close(w)
|
||||||
|
|
||||||
state := os.process_wait(process) or_return
|
state := os.process_wait(process) or_return
|
||||||
|
|
||||||
|
thread.join(read_thread)
|
||||||
|
|
||||||
if !state.success {
|
if !state.success {
|
||||||
return .Crash
|
return "", .Crash
|
||||||
}
|
}
|
||||||
|
|
||||||
if state.exit_code != 0 {
|
if state.exit_code != 0 {
|
||||||
return .Invalid_Exit_Code
|
return "", .Invalid_Exit_Code
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
Copy_Error :: union #shared_nil {
|
run_cmd :: proc(
|
||||||
os.Error,
|
cmd: []string,
|
||||||
filepath.Match_Error,
|
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(
|
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)
|
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))
|
||||||
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package assets
|
package assets
|
||||||
|
|
||||||
import "core:c"
|
|
||||||
import "core:log"
|
import "core:log"
|
||||||
import "core:math"
|
import "core:math"
|
||||||
import lg "core:math/linalg"
|
import lg "core:math/linalg"
|
||||||
@ -21,7 +20,7 @@ Loaded_BVH :: struct {
|
|||||||
aabb: bvh.AABB,
|
aabb: bvh.AABB,
|
||||||
// BVH for each mesh in a model
|
// BVH for each mesh in a model
|
||||||
bvhs: []bvh.BVH,
|
bvhs: []bvh.BVH,
|
||||||
modtime: c.long,
|
modtime: physfs.sint64,
|
||||||
}
|
}
|
||||||
|
|
||||||
Loaded_Convex :: struct {
|
Loaded_Convex :: struct {
|
||||||
@ -198,7 +197,7 @@ assetcache_fetch_or_load :: proc(
|
|||||||
payload: Asset_Cache_Loader_Payload = nil,
|
payload: Asset_Cache_Loader_Payload = nil,
|
||||||
) -> (
|
) -> (
|
||||||
value: E,
|
value: E,
|
||||||
modtime: i64,
|
modtime: physfs.sint64,
|
||||||
result: Asset_Cache_Result,
|
result: Asset_Cache_Result,
|
||||||
) {
|
) {
|
||||||
tracy.Zone()
|
tracy.Zone()
|
||||||
@ -275,10 +274,10 @@ get_texture :: proc(assetman: ^Asset_Manager, path: cstring) -> rl.Texture2D {
|
|||||||
get_model_ex :: proc(
|
get_model_ex :: proc(
|
||||||
assetman: ^Asset_Manager,
|
assetman: ^Asset_Manager,
|
||||||
path: cstring,
|
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,
|
model: rl.Model,
|
||||||
modtime: c.long,
|
modtime: physfs.sint64,
|
||||||
reloaded: bool,
|
reloaded: bool,
|
||||||
) {
|
) {
|
||||||
tracy.Zone()
|
tracy.Zone()
|
||||||
|
@ -1011,25 +1011,25 @@ draw_world :: proc(world: ^World) {
|
|||||||
car_matrix =
|
car_matrix =
|
||||||
(auto_cast linalg.matrix4_translate_f32(physics.body_get_shape_pos(car_body))) * car_matrix
|
(auto_cast linalg.matrix4_translate_f32(physics.body_get_shape_pos(car_body))) * car_matrix
|
||||||
|
|
||||||
basic_shader := assets.get_shader(
|
// basic_shader := assets.get_shader(
|
||||||
&g_mem.assetman,
|
// &g_mem.assetman,
|
||||||
"assets/shaders/lit_vs.glsl",
|
// "assets/shaders/lit_vs.glsl",
|
||||||
"assets/shaders/lit_ps.glsl",
|
// "assets/shaders/lit_ps.glsl",
|
||||||
{.Ambient, .LightDir, .LightColor},
|
// {.Ambient, .LightDir, .LightColor},
|
||||||
)
|
// )
|
||||||
light_dir := linalg.normalize(rl.Vector3{1, -1, 0})
|
// light_dir := linalg.normalize(rl.Vector3{1, -1, 0})
|
||||||
ambient := rl.Vector3{0.1, 0.1, 0.1}
|
// ambient := rl.Vector3{0.1, 0.1, 0.1}
|
||||||
light_color := rl.Vector3{0.816, 0.855, 0.89}
|
// 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[.LightDir], &light_dir, .VEC3)
|
||||||
rl.SetShaderValue(basic_shader.shader, basic_shader.locations[.Ambient], &ambient, .VEC3)
|
// rl.SetShaderValue(basic_shader.shader, basic_shader.locations[.Ambient], &ambient, .VEC3)
|
||||||
rl.SetShaderValue(
|
// rl.SetShaderValue(
|
||||||
basic_shader.shader,
|
// basic_shader.shader,
|
||||||
basic_shader.locations[.LightColor],
|
// basic_shader.locations[.LightColor],
|
||||||
&light_color,
|
// &light_color,
|
||||||
.VEC3,
|
// .VEC3,
|
||||||
)
|
// )
|
||||||
|
|
||||||
render.draw_model(car_model, basic_shader.shader, car_matrix)
|
render.draw_model(car_model, {}, car_matrix)
|
||||||
|
|
||||||
render.draw_mesh_light(
|
render.draw_mesh_light(
|
||||||
assets.get_model(&g_mem.assetman, "assets/ae86_lights.glb"),
|
assets.get_model(&g_mem.assetman, "assets/ae86_lights.glb"),
|
||||||
@ -1262,7 +1262,14 @@ game_update :: proc() -> bool {
|
|||||||
|
|
||||||
update()
|
update()
|
||||||
draw()
|
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)
|
@(export)
|
||||||
|
@ -138,7 +138,7 @@ draw_debug_scene :: proc(scene: ^Scene) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if true {
|
if false {
|
||||||
for &contact, contact_idx in sim_state.contact_container.contacts {
|
for &contact, contact_idx in sim_state.contact_container.contacts {
|
||||||
points_a := contact.manifold.points_a
|
points_a := contact.manifold.points_a
|
||||||
points_b := contact.manifold.points_b
|
points_b := contact.manifold.points_b
|
||||||
|
@ -30,9 +30,9 @@ draw_model :: proc(
|
|||||||
color: rl.Color = rl.WHITE,
|
color: rl.Color = rl.WHITE,
|
||||||
) {
|
) {
|
||||||
model := model
|
model := model
|
||||||
for i in 0 ..< model.materialCount {
|
// for i in 0 ..< model.materialCount {
|
||||||
model.materials[i].shader = shader
|
// model.materials[i].shader = shader
|
||||||
}
|
// }
|
||||||
model.transform = transform
|
model.transform = transform
|
||||||
|
|
||||||
rl.DrawModel(model, rl.Vector3{}, 1, color)
|
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 := model
|
||||||
model.transform = transform
|
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()
|
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)
|
gl.ColorMask(false, false, false, false)
|
||||||
rlgl.SetCullFace(.FRONT)
|
rlgl.SetCullFace(.FRONT)
|
||||||
|
|
||||||
draw_model(model, light_shader, transform, color)
|
draw_model(model, {}, transform, color)
|
||||||
rlgl.DrawRenderBatchActive()
|
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)
|
gl.ColorMask(true, true, true, true)
|
||||||
rlgl.SetCullFace(.BACK)
|
rlgl.SetCullFace(.BACK)
|
||||||
|
|
||||||
draw_model(model, light_shader, transform, color)
|
draw_model(model, {}, transform, color)
|
||||||
rlgl.DrawRenderBatchActive()
|
rlgl.DrawRenderBatchActive()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,7 +78,7 @@ draw_mesh_light :: proc(model: rl.Model, transform: rl.Matrix, color: rl.Color)
|
|||||||
gl.DepthFunc(gl.GREATER)
|
gl.DepthFunc(gl.GREATER)
|
||||||
rlgl.SetCullFace(.FRONT)
|
rlgl.SetCullFace(.FRONT)
|
||||||
|
|
||||||
draw_model(model, light_shader, transform, color)
|
draw_model(model, {}, transform, color)
|
||||||
rlgl.DrawRenderBatchActive()
|
rlgl.DrawRenderBatchActive()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ rl_init :: proc() {
|
|||||||
rl.SetTextureFilter(default_atlas_texture, .POINT)
|
rl.SetTextureFilter(default_atlas_texture, .POINT)
|
||||||
|
|
||||||
gl.BindTexture(gl.TEXTURE_2D, default_atlas_texture.id)
|
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)
|
gl.BindTexture(gl.TEXTURE_2D, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,8 @@ when ODIN_OS == .Linux || ODIN_OS == .Darwin {
|
|||||||
} else {
|
} else {
|
||||||
foreign import lib "libphysfs.a"
|
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_")
|
@(default_calling_convention = "c", link_prefix = "PHYSFS_")
|
||||||
|
@ -109,7 +109,7 @@ when ODIN_OS == .Windows {
|
|||||||
} else when ODIN_OS == .Darwin {
|
} 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"}
|
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 {
|
} else when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 {
|
||||||
foreign import lib "zig-out-static/lib/libraylib.a"
|
foreign import lib "env.o"
|
||||||
} else {
|
} else {
|
||||||
foreign import lib "system:raylib"
|
foreign import lib "system:raylib"
|
||||||
}
|
}
|
||||||
|
@ -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)
|
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 {
|
} 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"}
|
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 {
|
} else {
|
||||||
foreign import lib "system:raylib"
|
foreign import lib "system:raylib"
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,8 @@ package tracy
|
|||||||
import "core:c"
|
import "core:c"
|
||||||
import "core:mem"
|
import "core:mem"
|
||||||
|
|
||||||
|
_ :: c
|
||||||
|
|
||||||
ProfiledAllocatorData :: struct {
|
ProfiledAllocatorData :: struct {
|
||||||
backing_allocator: mem.Allocator,
|
backing_allocator: mem.Allocator,
|
||||||
profiled_allocator: mem.Allocator,
|
profiled_allocator: mem.Allocator,
|
||||||
@ -14,16 +16,35 @@ MakeProfiledAllocator :: proc(
|
|||||||
self: ^ProfiledAllocatorData,
|
self: ^ProfiledAllocatorData,
|
||||||
callstack_size: i32 = TRACY_CALLSTACK,
|
callstack_size: i32 = TRACY_CALLSTACK,
|
||||||
secure: b32 = false,
|
secure: b32 = false,
|
||||||
backing_allocator := context.allocator) -> mem.Allocator {
|
backing_allocator := context.allocator,
|
||||||
|
) -> mem.Allocator {
|
||||||
|
|
||||||
self.callstack_size = callstack_size
|
self.callstack_size = callstack_size
|
||||||
self.secure = secure
|
self.secure = secure
|
||||||
self.backing_allocator = backing_allocator
|
self.backing_allocator = backing_allocator
|
||||||
self.profiled_allocator = mem.Allocator {
|
self.profiled_allocator = mem.Allocator {
|
||||||
data = self,
|
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) {
|
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
|
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)
|
new_memory, error := self.backing_allocator.procedure(
|
||||||
|
self.backing_allocator.data,
|
||||||
|
mode,
|
||||||
|
size,
|
||||||
|
alignment,
|
||||||
|
old_memory,
|
||||||
|
old_size,
|
||||||
|
location,
|
||||||
|
)
|
||||||
if error == .None {
|
if error == .None {
|
||||||
switch mode {
|
switch mode {
|
||||||
case .Alloc, .Alloc_Non_Zeroed:
|
case .Alloc, .Alloc_Non_Zeroed:
|
||||||
@ -51,18 +72,27 @@ MakeProfiledAllocator :: proc(
|
|||||||
EmitAlloc :: #force_inline proc(new_memory: []byte, size: int, callstack_size: i32, secure: b32) {
|
EmitAlloc :: #force_inline proc(new_memory: []byte, size: int, callstack_size: i32, secure: b32) {
|
||||||
when TRACY_HAS_CALLSTACK {
|
when TRACY_HAS_CALLSTACK {
|
||||||
if callstack_size > 0 {
|
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 {
|
} else {
|
||||||
___tracy_emit_memory_alloc(raw_data(new_memory), c.size_t(size), secure)
|
___tracy_emit_memory_alloc(raw_data(new_memory), c.size_t(size), secure)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
when TRACY_ENABLE {
|
||||||
___tracy_emit_memory_alloc(raw_data(new_memory), c.size_t(size), secure)
|
___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) {
|
EmitFree :: #force_inline proc(old_memory: rawptr, callstack_size: i32, secure: b32) {
|
||||||
|
when TRACY_ENABLE {
|
||||||
if old_memory == nil {return}
|
if old_memory == nil {return}
|
||||||
|
|
||||||
when TRACY_HAS_CALLSTACK {
|
when TRACY_HAS_CALLSTACK {
|
||||||
if callstack_size > 0 {
|
if callstack_size > 0 {
|
||||||
___tracy_emit_memory_free_callstack(old_memory, callstack_size, secure)
|
___tracy_emit_memory_free_callstack(old_memory, callstack_size, secure)
|
||||||
@ -73,5 +103,4 @@ EmitFree :: #force_inline proc(old_memory: rawptr, callstack_size: i32, secure:
|
|||||||
___tracy_emit_memory_free(old_memory, secure)
|
___tracy_emit_memory_free(old_memory, secure)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -2,9 +2,13 @@ package tracy
|
|||||||
|
|
||||||
import "core:c"
|
import "core:c"
|
||||||
|
|
||||||
|
_ :: c
|
||||||
|
|
||||||
|
when TRACY_ENABLE {
|
||||||
when ODIN_OS == .Darwin do foreign import tracy "tracy.dylib"
|
when ODIN_OS == .Darwin do foreign import tracy "tracy.dylib"
|
||||||
when ODIN_OS == .Windows do foreign import tracy "tracy.lib"
|
when ODIN_OS == .Windows do foreign import tracy "tracy.lib"
|
||||||
when ODIN_OS == .Linux do foreign import tracy "tracy.so"
|
when ODIN_OS == .Linux do foreign import tracy "tracy.so"
|
||||||
|
}
|
||||||
|
|
||||||
TracyPlotFormatEnum :: enum i32 {
|
TracyPlotFormatEnum :: enum i32 {
|
||||||
TracyPlotFormatNumber,
|
TracyPlotFormatNumber,
|
||||||
@ -77,6 +81,7 @@ ___tracy_gpu_time_sync_data :: struct {
|
|||||||
|
|
||||||
__tracy_lockable_context_data :: struct {} // NOTE(oskar): opaque
|
__tracy_lockable_context_data :: struct {} // NOTE(oskar): opaque
|
||||||
|
|
||||||
|
when TRACY_ENABLE {
|
||||||
when #config(TRACY_MANUAL_LIFETIME, false) {
|
when #config(TRACY_MANUAL_LIFETIME, false) {
|
||||||
@(default_calling_convention = "c")
|
@(default_calling_convention = "c")
|
||||||
foreign tracy {
|
foreign tracy {
|
||||||
@ -85,7 +90,6 @@ when #config(TRACY_MANUAL_LIFETIME, false) {
|
|||||||
___tracy_profiler_started :: proc() -> b32 ---
|
___tracy_profiler_started :: proc() -> b32 ---
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@(default_calling_convention = "c")
|
@(default_calling_convention = "c")
|
||||||
foreign tracy {
|
foreign tracy {
|
||||||
___tracy_set_thread_name :: proc(name: cstring) ---
|
___tracy_set_thread_name :: proc(name: cstring) ---
|
||||||
@ -169,3 +173,4 @@ when #config(TRACY_FIBERS, false) {
|
|||||||
___tracy_fiber_leave :: proc() ---
|
___tracy_fiber_leave :: proc() ---
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
@ -2,6 +2,8 @@ package tracy
|
|||||||
|
|
||||||
import "core:c"
|
import "core:c"
|
||||||
|
|
||||||
|
_ :: c
|
||||||
|
|
||||||
TRACY_ENABLE :: #config(TRACY_ENABLE, false)
|
TRACY_ENABLE :: #config(TRACY_ENABLE, false)
|
||||||
TRACY_CALLSTACK :: #config(TRACY_CALLSTACK, 1)
|
TRACY_CALLSTACK :: #config(TRACY_CALLSTACK, 1)
|
||||||
TRACY_HAS_CALLSTACK :: #config(TRACY_HAS_CALLSTACK, false)
|
TRACY_HAS_CALLSTACK :: #config(TRACY_HAS_CALLSTACK, false)
|
||||||
@ -62,19 +64,25 @@ ZoneCS :: ZoneC
|
|||||||
ZoneNCS :: ZoneNC
|
ZoneNCS :: ZoneNC
|
||||||
|
|
||||||
@(disabled = !TRACY_ENABLE)
|
@(disabled = !TRACY_ENABLE)
|
||||||
ZoneText :: #force_inline proc(ctx: ZoneCtx, text: string) {___tracy_emit_zone_text(
|
ZoneText :: #force_inline proc(
|
||||||
ctx,
|
ctx: ZoneCtx,
|
||||||
_sl(text),
|
text: string,
|
||||||
)}
|
) {when TRACY_ENABLE {___tracy_emit_zone_text(ctx, _sl(text))}}
|
||||||
@(disabled = !TRACY_ENABLE)
|
@(disabled = !TRACY_ENABLE)
|
||||||
ZoneName :: #force_inline proc(ctx: ZoneCtx, name: string) {___tracy_emit_zone_name(
|
ZoneName :: #force_inline proc(
|
||||||
ctx,
|
ctx: ZoneCtx,
|
||||||
_sl(name),
|
name: string,
|
||||||
)}
|
) {when TRACY_ENABLE {___tracy_emit_zone_name(ctx, _sl(name))}}
|
||||||
@(disabled = !TRACY_ENABLE)
|
@(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)
|
@(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.
|
// NOTE: scoped Zone*() procs also exists, no need of calling this directly.
|
||||||
ZoneBegin :: proc(active: bool, depth: i32, loc := #caller_location) -> (ctx: ZoneCtx) {
|
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.
|
// NOTE: scoped Zone*() procs also exists, no need of calling this directly.
|
||||||
@(disabled = !TRACY_ENABLE)
|
@(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
|
// Memory profiling
|
||||||
// (See allocator.odin for an implementation of an Odin custom allocator using 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,
|
ptr: rawptr,
|
||||||
size: c.size_t,
|
size: c.size_t,
|
||||||
depth: i32 = TRACY_CALLSTACK,
|
depth: i32 = TRACY_CALLSTACK,
|
||||||
) {when TRACY_HAS_CALLSTACK {___tracy_emit_memory_alloc_callstack(
|
) {when TRACY_ENABLE {when TRACY_HAS_CALLSTACK {___tracy_emit_memory_alloc_callstack(
|
||||||
ptr,
|
ptr,
|
||||||
size,
|
size,
|
||||||
depth,
|
depth,
|
||||||
false,
|
false,
|
||||||
)} else {___tracy_emit_memory_alloc(ptr, size, false)}}
|
)} else {___tracy_emit_memory_alloc(ptr, size, false)}}}
|
||||||
@(disabled = !TRACY_ENABLE)
|
@(disabled = !TRACY_ENABLE)
|
||||||
Free :: #force_inline proc(
|
Free :: #force_inline proc(
|
||||||
ptr: rawptr,
|
ptr: rawptr,
|
||||||
depth: i32 = TRACY_CALLSTACK,
|
depth: i32 = TRACY_CALLSTACK,
|
||||||
) {when TRACY_HAS_CALLSTACK {___tracy_emit_memory_free_callstack(
|
) {when TRACY_ENABLE {when TRACY_HAS_CALLSTACK {___tracy_emit_memory_free_callstack(
|
||||||
ptr,
|
ptr,
|
||||||
depth,
|
depth,
|
||||||
false,
|
false,
|
||||||
)} else {___tracy_emit_memory_free(ptr, false)}}
|
)} else {___tracy_emit_memory_free(ptr, false)}}}
|
||||||
@(disabled = !TRACY_ENABLE)
|
@(disabled = !TRACY_ENABLE)
|
||||||
SecureAlloc :: #force_inline proc(
|
SecureAlloc :: #force_inline proc(
|
||||||
ptr: rawptr,
|
ptr: rawptr,
|
||||||
size: c.size_t,
|
size: c.size_t,
|
||||||
depth: i32 = TRACY_CALLSTACK,
|
depth: i32 = TRACY_CALLSTACK,
|
||||||
) {when TRACY_HAS_CALLSTACK {___tracy_emit_memory_alloc_callstack(
|
) {when TRACY_ENABLE {when TRACY_HAS_CALLSTACK {___tracy_emit_memory_alloc_callstack(
|
||||||
ptr,
|
ptr,
|
||||||
size,
|
size,
|
||||||
depth,
|
depth,
|
||||||
true,
|
true,
|
||||||
)} else {___tracy_emit_memory_alloc(ptr, size, true)}}
|
)} else {___tracy_emit_memory_alloc(ptr, size, true)}}}
|
||||||
@(disabled = !TRACY_ENABLE)
|
@(disabled = !TRACY_ENABLE)
|
||||||
SecureFree :: #force_inline proc(
|
SecureFree :: #force_inline proc(
|
||||||
ptr: rawptr,
|
ptr: rawptr,
|
||||||
depth: i32 = TRACY_CALLSTACK,
|
depth: i32 = TRACY_CALLSTACK,
|
||||||
) {when TRACY_HAS_CALLSTACK {___tracy_emit_memory_free_callstack(
|
) {when TRACY_ENABLE {when TRACY_HAS_CALLSTACK {___tracy_emit_memory_free_callstack(
|
||||||
ptr,
|
ptr,
|
||||||
depth,
|
depth,
|
||||||
true,
|
true,
|
||||||
)} else {___tracy_emit_memory_free(ptr, true)}}
|
)} else {___tracy_emit_memory_free(ptr, true)}}}
|
||||||
@(disabled = !TRACY_ENABLE)
|
@(disabled = !TRACY_ENABLE)
|
||||||
AllocN :: #force_inline proc(
|
AllocN :: #force_inline proc(
|
||||||
ptr: rawptr,
|
ptr: rawptr,
|
||||||
size: c.size_t,
|
size: c.size_t,
|
||||||
name: cstring,
|
name: cstring,
|
||||||
depth: i32 = TRACY_CALLSTACK,
|
depth: i32 = TRACY_CALLSTACK,
|
||||||
) {when TRACY_HAS_CALLSTACK {___tracy_emit_memory_alloc_callstack_named(
|
) {
|
||||||
ptr,
|
when TRACY_ENABLE {
|
||||||
size,
|
when TRACY_HAS_CALLSTACK {
|
||||||
depth,
|
___tracy_emit_memory_alloc_callstack_named(ptr, size, depth, false, name)
|
||||||
false,
|
} else {
|
||||||
name,
|
__tracy_emit_memory_alloc_named(ptr, size, false, name)
|
||||||
)} else {___tracy_emit_memory_alloc_named(ptr, size, false, name)}}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@(disabled = !TRACY_ENABLE)
|
@(disabled = !TRACY_ENABLE)
|
||||||
FreeN :: #force_inline proc(
|
FreeN :: #force_inline proc(
|
||||||
ptr: rawptr,
|
ptr: rawptr,
|
||||||
name: cstring,
|
name: cstring,
|
||||||
depth: i32 = TRACY_CALLSTACK,
|
depth: i32 = TRACY_CALLSTACK,
|
||||||
) {when TRACY_HAS_CALLSTACK {___tracy_emit_memory_free_callstack_named(
|
) {when TRACY_ENABLE {when TRACY_HAS_CALLSTACK {___tracy_emit_memory_free_callstack_named(
|
||||||
ptr,
|
ptr,
|
||||||
depth,
|
depth,
|
||||||
false,
|
false,
|
||||||
name,
|
name,
|
||||||
)} else {___tracy_emit_memory_free_named(ptr, false, name)}}
|
)} else {___tracy_emit_memory_free_named(ptr, false, name)}}}
|
||||||
@(disabled = !TRACY_ENABLE)
|
@(disabled = !TRACY_ENABLE)
|
||||||
SecureAllocN :: #force_inline proc(
|
SecureAllocN :: #force_inline proc(
|
||||||
ptr: rawptr,
|
ptr: rawptr,
|
||||||
size: c.size_t,
|
size: c.size_t,
|
||||||
name: cstring,
|
name: cstring,
|
||||||
depth: i32 = TRACY_CALLSTACK,
|
depth: i32 = TRACY_CALLSTACK,
|
||||||
) {when TRACY_HAS_CALLSTACK {___tracy_emit_memory_alloc_callstack_named(
|
) {when TRACY_ENABLE {when TRACY_HAS_CALLSTACK {___tracy_emit_memory_alloc_callstack_named(
|
||||||
ptr,
|
ptr,
|
||||||
size,
|
size,
|
||||||
depth,
|
depth,
|
||||||
true,
|
true,
|
||||||
name,
|
name,
|
||||||
)} else {___tracy_emit_memory_alloc_named(ptr, size, true, name)}}
|
)} else {when TRACY_ENABLE {___tracy_emit_memory_alloc_named(ptr, size, true, name)}}}}
|
||||||
@(disabled = !TRACY_ENABLE)
|
@(disabled = !TRACY_ENABLE)
|
||||||
SecureFreeN :: #force_inline proc(
|
SecureFreeN :: #force_inline proc(
|
||||||
ptr: rawptr,
|
ptr: rawptr,
|
||||||
name: cstring,
|
name: cstring,
|
||||||
depth: i32 = TRACY_CALLSTACK,
|
depth: i32 = TRACY_CALLSTACK,
|
||||||
) {when TRACY_HAS_CALLSTACK {___tracy_emit_memory_free_callstack_named(
|
) {when TRACY_ENABLE {when TRACY_HAS_CALLSTACK {___tracy_emit_memory_free_callstack_named(
|
||||||
ptr,
|
ptr,
|
||||||
depth,
|
depth,
|
||||||
true,
|
true,
|
||||||
name,
|
name,
|
||||||
)} else {___tracy_emit_memory_free_named(ptr, true, name)}}
|
)} else {___tracy_emit_memory_free_named(ptr, true, name)}}}
|
||||||
|
|
||||||
// Dummy aliases to match C API (only difference is the `depth` parameter,
|
// Dummy aliases to match C API (only difference is the `depth` parameter,
|
||||||
// which we declare as optional for the non-S procs.)
|
// which we declare as optional for the non-S procs.)
|
||||||
@ -204,48 +214,67 @@ SecureFreeNS :: SecureFreeN
|
|||||||
|
|
||||||
// Frame markup
|
// Frame markup
|
||||||
@(disabled = !TRACY_ENABLE)
|
@(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)
|
@(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)
|
@(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)
|
@(disabled = !TRACY_ENABLE)
|
||||||
FrameImage :: #force_inline proc(
|
FrameImage :: #force_inline proc(
|
||||||
image: rawptr,
|
image: rawptr,
|
||||||
w, h: u16,
|
w, h: u16,
|
||||||
offset: u8,
|
offset: u8,
|
||||||
flip: b32,
|
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
|
// Plots and messages
|
||||||
@(disabled = !TRACY_ENABLE)
|
@(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)
|
@(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)
|
@(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)
|
@(disabled = !TRACY_ENABLE)
|
||||||
PlotConfig :: #force_inline proc(
|
PlotConfig :: #force_inline proc(
|
||||||
name: cstring,
|
name: cstring,
|
||||||
type: TracyPlotFormatEnum,
|
type: TracyPlotFormatEnum,
|
||||||
step, fill: b32,
|
step, fill: b32,
|
||||||
color: u32,
|
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)
|
@(disabled = !TRACY_ENABLE)
|
||||||
Message :: #force_inline proc(txt: string) {___tracy_emit_message(
|
Message :: #force_inline proc(txt: string) {when TRACY_ENABLE {___tracy_emit_message(
|
||||||
_sl(txt),
|
_sl(txt),
|
||||||
TRACY_CALLSTACK when TRACY_HAS_CALLSTACK else 0,
|
TRACY_CALLSTACK when TRACY_HAS_CALLSTACK else 0,
|
||||||
)}
|
)}}
|
||||||
@(disabled = !TRACY_ENABLE)
|
@(disabled = !TRACY_ENABLE)
|
||||||
MessageC :: #force_inline proc(txt: string, color: u32) {___tracy_emit_message(
|
MessageC :: #force_inline proc(txt: string, color: u32) {when TRACY_ENABLE {___tracy_emit_message(
|
||||||
_sl(txt),
|
_sl(txt),
|
||||||
TRACY_CALLSTACK when TRACY_HAS_CALLSTACK else 0,
|
TRACY_CALLSTACK when TRACY_HAS_CALLSTACK else 0,
|
||||||
)}
|
)}}
|
||||||
@(disabled = !TRACY_ENABLE)
|
@(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)
|
@(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
|
// Connection status
|
||||||
IsConnected :: #force_inline proc() -> bool {return(
|
IsConnected :: #force_inline proc() -> bool {return(
|
||||||
@ -299,28 +328,38 @@ LockAnnounce :: #force_inline proc(loc := #caller_location) -> (ctx: LockCtx) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
@(disabled = !TRACY_ENABLE)
|
@(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)
|
@(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)
|
@(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)
|
@(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)
|
@(disabled = !TRACY_ENABLE)
|
||||||
LockAfterTryLock :: #force_inline proc(
|
LockAfterTryLock :: #force_inline proc(
|
||||||
lock: LockCtx,
|
lock: LockCtx,
|
||||||
acquired: bool,
|
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)
|
@(disabled = !TRACY_ENABLE)
|
||||||
LockMark :: #force_inline proc(lock: LockCtx, loc := #caller_location) {
|
LockMark :: #force_inline proc(lock: LockCtx, loc := #caller_location) {
|
||||||
|
when TRACY_ENABLE {
|
||||||
id := ___tracy_alloc_srcloc(u32(loc.line), _sl(loc.file_path), _sl(loc.procedure))
|
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)))
|
___tracy_mark_lockable_ctx(lock, (^___tracy_source_location_data)(uintptr(id)))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
@(disabled = !TRACY_ENABLE)
|
@(disabled = !TRACY_ENABLE)
|
||||||
LockCustomName :: #force_inline proc(
|
LockCustomName :: #force_inline proc(
|
||||||
lock: LockCtx,
|
lock: LockCtx,
|
||||||
name: string,
|
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.
|
// Helper for passing cstring+length to Tracy functions.
|
||||||
@(private = "file")
|
@(private = "file")
|
||||||
|
BIN
main_web/game.wasm.o
Normal file
BIN
main_web/game.wasm.o
Normal file
Binary file not shown.
@ -5,24 +5,19 @@
|
|||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||||
|
|
||||||
<title>Odin + Raylib on the web</title>
|
<title>Odin + Raylib on the web</title>
|
||||||
|
|
||||||
<meta name="title" content="Odin + Raylib on the web">
|
<meta name="title" content="Odin + Raylib on the web">
|
||||||
<meta name="description" content="Make games using Odin + Raylib that work in the browser">
|
<meta name="description" content="Make games using Odin + Raylib that work in the browser">
|
||||||
<meta name="viewport" content="width=device-width">
|
<meta name="viewport" content="width=device-width">
|
||||||
|
|
||||||
<!-- Favicon -->
|
|
||||||
<link rel="shortcut icon" href="https://www.raylib.com/favicon.ico">
|
|
||||||
|
|
||||||
<!-- Web Style -->
|
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background-color: black;
|
background-color: black;
|
||||||
}
|
}
|
||||||
canvas.emscripten {
|
canvas.game_canvas {
|
||||||
border: 0px none;
|
border: 0px none;
|
||||||
background-color: black;}
|
background-color: black;
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
padding-right: 0;
|
padding-right: 0;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
@ -30,33 +25,73 @@
|
|||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<script type='text/javascript' src="https://cdn.jsdelivr.net/gh/eligrey/FileSaver.js/dist/FileSaver.min.js"> </script>
|
|
||||||
<script type='text/javascript'>
|
|
||||||
function saveFileFromMEMFSToDisk(memoryFSname, localFSname) // This can be called by C/C++ code
|
|
||||||
{
|
|
||||||
var isSafari = false; // Not supported, navigator.userAgent access is being restricted
|
|
||||||
//var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
|
|
||||||
var data = FS.readFile(memoryFSname);
|
|
||||||
var blob;
|
|
||||||
|
|
||||||
if (isSafari) blob = new Blob([data.buffer], { type: "application/octet-stream" });
|
|
||||||
else blob = new Blob([data.buffer], { type: "application/octet-binary" });
|
|
||||||
|
|
||||||
// NOTE: SaveAsDialog is a browser setting. For example, in Google Chrome,
|
|
||||||
// in Settings/Advanced/Downloads section you have a setting:
|
|
||||||
// 'Ask where to save each file before downloading' - which you can set true/false.
|
|
||||||
// If you enable this setting it would always ask you and bring the SaveAsDialog
|
|
||||||
saveAs(blob, localFSname);
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<canvas class=emscripten id=canvas oncontextmenu=event.preventDefault() tabindex=-1></canvas>
|
<canvas class="game_canvas" id="canvas" oncontextmenu="event.preventDefault()" tabindex="-1" onmousedown="event.target.focus()" onkeydown="event.preventDefault()"></canvas>
|
||||||
<p id="output" />
|
<script type="text/javascript" src="odin.js"></script>
|
||||||
<script>
|
<script>
|
||||||
|
var odinMemoryInterface = new odin.WasmMemoryInterface();
|
||||||
|
odinMemoryInterface.setIntSize(4);
|
||||||
|
var odinImports = odin.setupDefaultImports(odinMemoryInterface);
|
||||||
|
|
||||||
|
// The Module is used as configuration for emscripten.
|
||||||
var Module = {
|
var Module = {
|
||||||
|
// This is called by emscripten when it starts up.
|
||||||
|
instantiateWasm: (imports, successCallback) => {
|
||||||
|
const newImports = {
|
||||||
|
...odinImports,
|
||||||
|
...imports
|
||||||
|
}
|
||||||
|
|
||||||
|
return WebAssembly.instantiateStreaming(fetch("index.wasm"), newImports).then(function(output) {
|
||||||
|
var e = output.instance.exports;
|
||||||
|
odinMemoryInterface.setExports(e);
|
||||||
|
odinMemoryInterface.setMemory(e.memory);
|
||||||
|
return successCallback(output.instance);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// This happens a bit after `instantiateWasm`, when everything is
|
||||||
|
// done setting up. At that point we can run code.
|
||||||
|
onRuntimeInitialized: () => {
|
||||||
|
var e = wasmExports;
|
||||||
|
|
||||||
|
// Calls any procedure marked with @init
|
||||||
|
e._start();
|
||||||
|
|
||||||
|
// 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() {
|
print: (function() {
|
||||||
var element = document.getElementById('output');
|
var element = document.getElementById("output");
|
||||||
if (element) element.value = ''; // clear browser cache
|
if (element) element.value = ''; // clear browser cache
|
||||||
return function(text) {
|
return function(text) {
|
||||||
if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
|
if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
|
||||||
@ -68,11 +103,12 @@
|
|||||||
};
|
};
|
||||||
})(),
|
})(),
|
||||||
canvas: (function() {
|
canvas: (function() {
|
||||||
var canvas = document.getElementById('canvas');
|
return document.getElementById("canvas");
|
||||||
return canvas;
|
|
||||||
})()
|
})()
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<!-- Emscripten injects its javascript here -->
|
||||||
{{{ SCRIPT }}}
|
{{{ SCRIPT }}}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -1,37 +0,0 @@
|
|||||||
#include <stdlib.h>
|
|
||||||
#include <emscripten/emscripten.h>
|
|
||||||
#include <emscripten/html5.h>
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
@ -29,7 +29,7 @@ main_start :: proc "c" () {
|
|||||||
|
|
||||||
web_context = context
|
web_context = context
|
||||||
|
|
||||||
game.game_init_window({})
|
game.game_init_window({"."})
|
||||||
game.game_init()
|
game.game_init()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user