major gfx refactor from fixed function to shader based
This commit is contained in:
parent
0c0aa792c1
commit
40b385607d
58 changed files with 3681 additions and 2982 deletions
192
pxl8.sh
192
pxl8.sh
|
|
@ -8,7 +8,7 @@ if command -v ccache >/dev/null 2>&1; then
|
|||
CC="ccache $CC"
|
||||
fi
|
||||
|
||||
CFLAGS="-std=c23 -Wall -Wextra"
|
||||
CFLAGS="-std=c23 -Wall -Wextra -Wno-missing-braces"
|
||||
LIBS="-lm"
|
||||
MODE="debug"
|
||||
BUILDDIR=".build"
|
||||
|
|
@ -23,6 +23,7 @@ fi
|
|||
case "$(uname)" in
|
||||
Linux)
|
||||
LINKER_FLAGS="$LINKER_FLAGS -rdynamic"
|
||||
LIBS="$LIBS -ldl"
|
||||
;;
|
||||
Darwin)
|
||||
export MACOSX_DEPLOYMENT_TARGET="$(sw_vers -productVersion | cut -d '.' -f 1)"
|
||||
|
|
@ -32,6 +33,7 @@ case "$(uname)" in
|
|||
;;
|
||||
*)
|
||||
LINKER_FLAGS="$LINKER_FLAGS -rdynamic"
|
||||
LIBS="$LIBS -ldl"
|
||||
;;
|
||||
esac
|
||||
|
||||
|
|
@ -59,6 +61,12 @@ build_luajit() {
|
|||
|
||||
build_server() {
|
||||
local mode="$1"
|
||||
local server_bin
|
||||
if [[ "$mode" == "release" ]]; then
|
||||
server_bin="pxl8d/target/release/pxl8d"
|
||||
else
|
||||
server_bin="pxl8d/target/debug/pxl8d"
|
||||
fi
|
||||
if [[ -d "pxl8d" ]]; then
|
||||
print_info "Building pxl8d ($mode mode)"
|
||||
cd pxl8d
|
||||
|
|
@ -70,6 +78,8 @@ build_server() {
|
|||
local status=$?
|
||||
cd - > /dev/null
|
||||
if [[ $status -eq 0 ]]; then
|
||||
mkdir -p "$BINDIR"
|
||||
cp "$server_bin" "$BINDIR/pxl8d"
|
||||
print_info "Built pxl8d"
|
||||
else
|
||||
print_error "pxl8d build failed"
|
||||
|
|
@ -78,14 +88,7 @@ build_server() {
|
|||
}
|
||||
|
||||
start_server() {
|
||||
local mode="$1"
|
||||
local server_bin
|
||||
if [[ "$mode" == "release" ]]; then
|
||||
server_bin="pxl8d/target/release/pxl8d"
|
||||
else
|
||||
server_bin="pxl8d/target/debug/pxl8d"
|
||||
fi
|
||||
print_info "Server mode: $mode, binary: $server_bin"
|
||||
local server_bin="$BINDIR/pxl8d"
|
||||
if [[ -f "$server_bin" ]]; then
|
||||
print_info "Starting server..."
|
||||
./$server_bin &
|
||||
|
|
@ -94,7 +97,7 @@ start_server() {
|
|||
sleep 0.5
|
||||
else
|
||||
print_error "pxl8d binary not found: $server_bin"
|
||||
print_error "Build pxl8d first with: cd pxl8d && cargo build"
|
||||
print_error "Build first with: ./pxl8.sh build"
|
||||
fi
|
||||
}
|
||||
|
||||
|
|
@ -128,8 +131,17 @@ build_sdl() {
|
|||
}
|
||||
|
||||
prefix_output() {
|
||||
local in_warning=false
|
||||
while IFS= read -r line; do
|
||||
if [[ "$line" == *": warning:"* ]] || [[ "$line" == *": note:"* ]]; then
|
||||
in_warning=true
|
||||
echo -e "${YELLOW}${BOLD}[$(timestamp) WARN]${NC} $line" >&2
|
||||
elif [[ "$line" == *": error:"* ]] || [[ "$line" == *": fatal error:"* ]]; then
|
||||
in_warning=false
|
||||
echo -e "${RED}${BOLD}[$(timestamp) ERROR]${NC} $line" >&2
|
||||
elif [[ "$line" =~ ^[0-9]+\ (warning|error)s?\ generated ]] || [[ -z "$line" ]]; then
|
||||
echo -e "${YELLOW}${BOLD}[$(timestamp) WARN]${NC} $line" >&2
|
||||
elif $in_warning; then
|
||||
echo -e "${YELLOW}${BOLD}[$(timestamp) WARN]${NC} $line" >&2
|
||||
else
|
||||
echo -e "${RED}${BOLD}[$(timestamp) ERROR]${NC} $line" >&2
|
||||
|
|
@ -155,6 +167,54 @@ compile_source_file() {
|
|||
fi
|
||||
}
|
||||
|
||||
compile_shaders() {
|
||||
local build_mode="$1"
|
||||
local shader_dir="src/gfx/shaders/cpu"
|
||||
local so_dir=".build/$build_mode/shaders/cpu"
|
||||
local obj_dir=".build/$build_mode/shaders/cpu/obj"
|
||||
|
||||
if [[ ! -d "$shader_dir" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
[[ "$build_mode" == "debug" ]] && mkdir -p "$so_dir"
|
||||
mkdir -p "$obj_dir"
|
||||
|
||||
local SHADER_INCLUDES="-Isrc/core -Isrc/gfx -Isrc/math"
|
||||
case "$(uname)" in
|
||||
Darwin) SO_EXT="dylib" ;;
|
||||
*) SO_EXT="so" ;;
|
||||
esac
|
||||
|
||||
# Compile C shaders directly
|
||||
for shader in $(find "$shader_dir" -maxdepth 1 -name "*.c" 2>/dev/null); do
|
||||
local shader_name=$(basename "${shader%.c}")
|
||||
local so_file="$so_dir/${shader_name}.$SO_EXT"
|
||||
local obj_file="$obj_dir/${shader_name}.o"
|
||||
|
||||
# Debug: compile to .so for hot-reload
|
||||
if [[ "$build_mode" == "debug" ]]; then
|
||||
if [[ "$shader" -nt "$so_file" ]] || [[ ! -f "$so_file" ]]; then
|
||||
$CC -shared -fPIC -O2 $SHADER_INCLUDES "$shader" -o "$so_file" 2>&1 | prefix_output || {
|
||||
print_error "Shader build failed: $shader_name"
|
||||
}
|
||||
fi
|
||||
fi
|
||||
|
||||
# Compile to .o for release static linking
|
||||
if [[ "$shader" -nt "$obj_file" ]] || [[ ! -f "$obj_file" ]]; then
|
||||
$CC -c -O2 $SHADER_INCLUDES "$shader" -o "$obj_file" 2>&1 | prefix_output || {
|
||||
print_error "Shader compile failed: $shader_name"
|
||||
}
|
||||
fi
|
||||
done
|
||||
|
||||
# Export shader object files for linking
|
||||
SHADER_OBJECTS=""
|
||||
for obj in $(find "$obj_dir" -name "*.o" 2>/dev/null); do
|
||||
SHADER_OBJECTS="$SHADER_OBJECTS $obj"
|
||||
done
|
||||
}
|
||||
|
||||
make_lib_dirs() {
|
||||
mkdir -p lib/linenoise lib/fennel lib/miniz
|
||||
|
|
@ -180,15 +240,17 @@ print_usage() {
|
|||
echo " clean Remove build artifacts"
|
||||
echo " help Show this help message"
|
||||
echo " install Install pxl8 to ~/.local/bin"
|
||||
echo " profile Profile with perf and generate flamegraph (Linux)"
|
||||
echo " run Build and run pxl8 (optional: cart.pxc or folder)"
|
||||
echo " update Download/update all dependencies"
|
||||
echo " vendor Fetch source for dependencies (ex. SDL3)"
|
||||
echo
|
||||
echo -e "${BOLD}OPTIONS:${NC}"
|
||||
echo " --all Clean both build artifacts and dependencies"
|
||||
echo " --cache Clear ccache (use with clean)"
|
||||
echo " --deps Clean only dependencies"
|
||||
echo " --release Build/run/clean in release mode (default: debug)"
|
||||
echo " --all Clean both build artifacts and dependencies"
|
||||
echo " --cache Clear ccache (use with clean)"
|
||||
echo " --deps Clean only dependencies"
|
||||
echo " --duration=N Profile duration in seconds (default: 30)"
|
||||
echo " --release Build/run/clean in release mode (default: debug)"
|
||||
}
|
||||
|
||||
setup_sdl3() {
|
||||
|
|
@ -264,6 +326,20 @@ update_fennel() {
|
|||
fi
|
||||
}
|
||||
|
||||
update_flamegraph() {
|
||||
print_info "Fetching FlameGraph"
|
||||
|
||||
if [[ -d "lib/FlameGraph/.git" ]]; then
|
||||
cd lib/FlameGraph && git pull --quiet origin master
|
||||
cd - > /dev/null
|
||||
else
|
||||
rm -rf lib/FlameGraph
|
||||
git clone --quiet https://github.com/brendangregg/FlameGraph.git lib/FlameGraph
|
||||
fi
|
||||
|
||||
print_info "Updated FlameGraph"
|
||||
}
|
||||
|
||||
update_linenoise() {
|
||||
print_info "Fetching linenoise"
|
||||
|
||||
|
|
@ -328,6 +404,7 @@ update_sdl() {
|
|||
print_info "Updated SDL3"
|
||||
}
|
||||
|
||||
|
||||
COMMAND="$1"
|
||||
shift || true
|
||||
|
||||
|
|
@ -399,7 +476,7 @@ case "$COMMAND" in
|
|||
print_info "Compiler cache: ccache enabled"
|
||||
fi
|
||||
|
||||
INCLUDES="-Isrc/asset -Isrc/bsp -Isrc/core -Isrc/gfx -Isrc/gui -Isrc/hal -Isrc/math -Isrc/net -Isrc/procgen -Isrc/script -Isrc/sfx -Isrc/sim -Isrc/vxl -Isrc/world -Ilib/linenoise -Ilib/luajit/src -Ilib/miniz"
|
||||
INCLUDES="-Isrc/asset -Isrc/bsp -Isrc/core -Isrc/gfx -Isrc/gui -Isrc/hal -Isrc/math -Isrc/net -Isrc/procgen -Isrc/script -Isrc/shader -Isrc/sfx -Isrc/sim -Isrc/vxl -Isrc/world -Ilib/linenoise -Ilib/luajit/src -Ilib/miniz -I.build/shaders/c"
|
||||
COMPILE_FLAGS="$CFLAGS $INCLUDES"
|
||||
DEP_COMPILE_FLAGS="$DEP_CFLAGS $INCLUDES"
|
||||
|
||||
|
|
@ -424,11 +501,12 @@ case "$COMMAND" in
|
|||
src/gfx/pxl8_atlas.c
|
||||
src/gfx/pxl8_blit.c
|
||||
src/gfx/pxl8_colormap.c
|
||||
src/gfx/pxl8_cpu.c
|
||||
src/gfx/pxl8_dither.c
|
||||
src/gfx/pxl8_render.c
|
||||
src/gfx/pxl8_shader_registry.c
|
||||
src/gfx/pxl8_shader_runtime.c
|
||||
src/gfx/pxl8_font.c
|
||||
src/gfx/pxl8_gfx.c
|
||||
src/gfx/pxl8_glows.c
|
||||
src/gfx/pxl8_lightmap.c
|
||||
src/gfx/pxl8_lights.c
|
||||
src/gfx/pxl8_mesh.c
|
||||
|
|
@ -461,11 +539,11 @@ case "$COMMAND" in
|
|||
LUAJIT_LIB="lib/luajit/src/libluajit.a"
|
||||
OBJECT_DIR="$BUILDDIR/obj"
|
||||
mkdir -p "$OBJECT_DIR"
|
||||
|
||||
|
||||
OBJECTS=""
|
||||
NEED_LINK=false
|
||||
SOURCES_COMPILED=""
|
||||
|
||||
|
||||
for src_file in $LIB_SOURCE_FILES; do
|
||||
obj_name=$(basename "$src_file" .c).o
|
||||
obj_file="$OBJECT_DIR/$obj_name"
|
||||
|
|
@ -477,7 +555,9 @@ case "$COMMAND" in
|
|||
SOURCES_COMPILED="yes"
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
compile_shaders "$MODE"
|
||||
|
||||
for src_file in $PXL8_SOURCE_FILES; do
|
||||
obj_name=$(basename "$src_file" .c).o
|
||||
obj_file="$OBJECT_DIR/$obj_name"
|
||||
|
|
@ -509,7 +589,7 @@ case "$COMMAND" in
|
|||
|
||||
if [[ "$LUAJIT_LIB" -nt "$EXECUTABLE" ]] || [[ "$NEED_LINK" == true ]]; then
|
||||
print_info "Linking executable"
|
||||
if ! $CC $LINKER_FLAGS $OBJECTS $LUAJIT_LIB $LIBS -o "$EXECUTABLE"; then
|
||||
if ! $CC $LINKER_FLAGS $OBJECTS $SHADER_OBJECTS $LUAJIT_LIB $LIBS -o "$EXECUTABLE"; then
|
||||
print_error "Linking failed"
|
||||
exit 1
|
||||
fi
|
||||
|
|
@ -578,7 +658,7 @@ case "$COMMAND" in
|
|||
|
||||
if [[ "$CLEAN_ALL" == true ]]; then
|
||||
print_info "Removing build artifacts and dependencies"
|
||||
rm -rf "$BUILD_PATH" "$BIN_PATH" lib
|
||||
rm -rf "$BUILD_PATH" "$BIN_PATH" .build/shaders lib
|
||||
clean_server
|
||||
print_info "Cleaned all"
|
||||
elif [[ "$CLEAN_DEPS" == true ]]; then
|
||||
|
|
@ -587,7 +667,7 @@ case "$COMMAND" in
|
|||
print_info "Cleaned dependencies"
|
||||
else
|
||||
print_info "Removing build artifacts"
|
||||
rm -rf "$BUILD_PATH" "$BIN_PATH"
|
||||
rm -rf "$BUILD_PATH" "$BIN_PATH" .build/shaders
|
||||
clean_server
|
||||
print_info "Cleaned"
|
||||
fi
|
||||
|
|
@ -626,6 +706,72 @@ case "$COMMAND" in
|
|||
bash tools/aseprite/pxl8-ase.sh "$@"
|
||||
;;
|
||||
|
||||
profile)
|
||||
if [[ "$(uname)" != "Linux" ]]; then
|
||||
print_error "Profiling with perf is only supported on Linux"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v perf >/dev/null 2>&1; then
|
||||
print_error "perf not found. Install linux-tools or perf package."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -d "lib/FlameGraph" ]]; then
|
||||
mkdir -p lib
|
||||
update_flamegraph
|
||||
fi
|
||||
|
||||
"$0" build || exit 1
|
||||
|
||||
PROFILE_DIR=".build/debug/profile"
|
||||
mkdir -p "$PROFILE_DIR"
|
||||
|
||||
CART=""
|
||||
PERF_DURATION=30
|
||||
for arg in "$@"; do
|
||||
if [[ "$arg" =~ ^--duration=([0-9]+)$ ]]; then
|
||||
PERF_DURATION="${BASH_REMATCH[1]}"
|
||||
elif [[ "$arg" != "--release" ]] && [[ -z "$CART" ]]; then
|
||||
CART="$arg"
|
||||
fi
|
||||
done
|
||||
|
||||
[[ -z "$CART" ]] && CART="demo"
|
||||
|
||||
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
|
||||
PERF_DATA="$PROFILE_DIR/perf_${TIMESTAMP}.data"
|
||||
PERF_SCRIPT="$PROFILE_DIR/perf_${TIMESTAMP}.perf"
|
||||
FOLDED="$PROFILE_DIR/perf_${TIMESTAMP}.folded"
|
||||
SVG="$PROFILE_DIR/flamegraph_${TIMESTAMP}.svg"
|
||||
|
||||
print_info "Starting server..."
|
||||
./bin/debug/pxl8d &
|
||||
SERVER_PID=$!
|
||||
sleep 0.5
|
||||
|
||||
trap "kill $SERVER_PID 2>/dev/null; wait $SERVER_PID 2>/dev/null" EXIT
|
||||
|
||||
print_info "Profiling pxl8 for ${PERF_DURATION}s (Ctrl+C to stop early)..."
|
||||
perf record -F 99 -g --call-graph dwarf -o "$PERF_DATA" -- \
|
||||
timeout "${PERF_DURATION}s" ./bin/debug/pxl8 "$CART" 2>/dev/null || true
|
||||
|
||||
print_info "Processing profile data..."
|
||||
perf script -i "$PERF_DATA" > "$PERF_SCRIPT"
|
||||
|
||||
print_info "Generating flamegraph..."
|
||||
lib/FlameGraph/stackcollapse-perf.pl "$PERF_SCRIPT" > "$FOLDED"
|
||||
lib/FlameGraph/flamegraph.pl --cp --colors orange --title "pxl8 profile" "$FOLDED" > "$SVG"
|
||||
|
||||
rm -f "$PERF_DATA" "$PERF_SCRIPT" "$FOLDED"
|
||||
|
||||
print_info "Flamegraph: $SVG"
|
||||
|
||||
if command -v xdg-open >/dev/null 2>&1; then
|
||||
xdg-open "$SVG" 2>/dev/null &
|
||||
fi
|
||||
;;
|
||||
|
||||
help|--help|-h|"")
|
||||
print_usage
|
||||
;;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue