render3d: 671 frame-reachable allocation sites to 161 - declared, split, or made nothing

@alloc_ok with its reason on what is made once per resource and kept (textures, programs, samplers,
views, layouts, memory blocks, the pipeline cache in gvk_pipe_build), on resize and swapchain
remakes, on screenshots and dumps, on a world being set up (streams, layers, water, post, bakes), on
loads (gltf_load, skin_load, tex_load*, png_decode, fonts) and on R3D_PROF / drawstats.
gltf_cached's hit path is its own and makes nothing; the miss (gltf_cached_load) is declared.
m4_look_at (now over m4_look_at_xyz) and m4_inverse work on scalars, and cam_update makes no scratch.
Left: lazy first-use starts, error and debug prints, and scratch made and freed each call (churn,
plan 25.3). Compiled (steady, and ludic deps over the game).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-09-28 15:58:18 +03:00
parent f2dd27f443
commit 5d0f83b81c
21 changed files with 118 additions and 42 deletions

View file

@ -94,6 +94,7 @@ function sc_model_layout(render3d_st: Render3dState, m: Mesh) -> void {
# Two crossed unit quads (x in [-0.5, 0.5], y in [0, 1]), attribute 0 = pos,
# 1 = the quad's facing normal, 2 = uv. Scaled per layer to the atlas card size.
@alloc_ok("a world being set up (a stream, a layer, water, post, a bake): the map loading or swapping, not a frame")
function model_cross_card(render3d_st: mut Render3dState) -> Model {
let model = new Model
model.prims = new []Prim
@ -378,6 +379,7 @@ function scatter_attach(render3d_st: Render3dState, m: Mesh, buf: int) -> void {
gpu_mesh_done(render3d_st, m)
}
@alloc_ok("a world being set up (a stream, a layer, water, post, a bake): the map loading or swapping, not a frame")
function layer_new(render3d_st: mut Render3dState, model: Model, cap: int, foliage: bool, wind: float, near: float, cull: float) -> Layer {
let l = new Layer
l.model = model
@ -428,6 +430,7 @@ function layer_add(l: Layer, x: float, y: float, z: float, scale: float, yaw: fl
}
# ---- impostors ---------------------------------------------------------------------
@alloc_ok("a world being set up (a stream, a layer, water, post, a bake): the map loading or swapping, not a frame")
function impostor_bake(render3d_st: mut Render3dState, model: Model, tiles: int, tw: int, th: int) -> Impostor {
let im = new Impostor
im.tiles = tiles
@ -583,6 +586,7 @@ function layer_arena_ok(render3d_st: Render3dState, l: Layer) -> bool {
return true
}
@alloc_ok("a world being set up (a stream, a layer, water, post, a bake): the map loading or swapping, not a frame")
function layer_arena_build(render3d_st: mut Render3dState, l: Layer) -> void {
let n_mat = len(l.lods[0].prims)
l.g_arena = new []Prim
@ -706,6 +710,7 @@ function layer_gpu_cull(render3d_st: mut Render3dState, l: Layer) -> void {
# Sort a static layer's instances into square cells (call once, after placement; a
# large layer that was never gridded gets a 96 m grid on its first update). The
# shadow buffer is uploaded here once — casters are never culled by the view.
@alloc_ok("a world being set up (a stream, a layer, water, post, a bake): the map loading or swapping, not a frame")
function layer_grid_build(render3d_st: mut Render3dState, l: Layer, cell: float) -> void {
if l.count == 0 { return }
var minx = l.inst[0]; var maxx = minx; var minz = l.inst[2]; var maxz = minz