feat(render3d): 23.4 - model_release, shared textures counted, and scatter layers sized to what they hold
- model_release(model) frees each primitive's mesh, and each texture once no other model uses it: the glTF texture cache counts the primitives using each texture (a path loaded again, and a LOD chain borrowing its LOD0's material, each take a reference); the last one frees the texture and forgets it along with any remembered material naming it, so a later load is a fresh one - a scatter layer's instance and sort arrays start at 256 and double as layer_add or a stream fills them, to the layer's cap, instead of the whole cap up front (0.4 GB in Maroon Lake) - gvk_tex_read's copy struct comes from the scratch ring - examples/rendering/release.ludic holds it (RELEASE OK on Vulkan and OpenGL), in the suite smooth renders pixel-identical before and after (max |d| 0). ludic-dev test 306/306. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
70a92a8862
commit
e634177ca4
10 changed files with 189 additions and 7 deletions
|
|
@ -24,6 +24,7 @@ property Layer {
|
|||
inst: floats, # INST_FLOATS per instance
|
||||
count: int = 0,
|
||||
cap: int = 0,
|
||||
have: int = 0, # instances inst and scratch have room for now: grown toward cap as filled
|
||||
near: float = 0.0, # float bits; instances beyond it draw as impostors (or not at all)
|
||||
cull: float = 0.0, # float bits; instances beyond it are skipped (0 = never)
|
||||
buf: int = 0,
|
||||
|
|
@ -386,8 +387,11 @@ function layer_new(render3d_st: mut Render3dState, model: Model, cap: int, folia
|
|||
l.near = near
|
||||
l.cull = cull
|
||||
l.tint = v3_new(1.0, 1.0, 1.0)
|
||||
l.inst = floats(cap * INST_FLOATS)
|
||||
l.scratch = floats(cap * INST_FLOATS)
|
||||
# room for what the layer holds, not for what it might: 45 layers at full capacity up front were
|
||||
# 0.4 GB, most of it never filled (plan 23 of maroon-lake)
|
||||
l.have = min(cap, 256)
|
||||
l.inst = floats(l.have * INST_FLOATS)
|
||||
l.scratch = floats(l.have * INST_FLOATS)
|
||||
l.last_cam = v3_new(100000.0, 0.0, 0.0)
|
||||
l.buf = gpu_buffer_new(render3d_st)
|
||||
l.imp_buf = gpu_buffer_new(render3d_st)
|
||||
|
|
@ -398,8 +402,23 @@ function layer_new(render3d_st: mut Render3dState, model: Model, cap: int, folia
|
|||
return l
|
||||
}
|
||||
|
||||
# room for n instances (at most the layer's cap), doubling what there is so a fill costs a few copies
|
||||
function layer_room(l: Layer, n: int) -> void {
|
||||
if n <= l.have { return }
|
||||
var want = max(l.have * 2, n)
|
||||
if want > l.cap { want = l.cap }
|
||||
let inst = floats(want * INST_FLOATS)
|
||||
if l.count > 0 { mem_copy(data_of(inst), data_of(l.inst), l.count * INST_FLOATS * 4) }
|
||||
free(l.inst)
|
||||
free(l.scratch)
|
||||
l.inst = inst
|
||||
l.scratch = floats(want * INST_FLOATS)
|
||||
l.have = want
|
||||
}
|
||||
|
||||
function layer_add(l: Layer, x: float, y: float, z: float, scale: float, yaw: float, seed: float, wind: float) -> void {
|
||||
if l.count >= l.cap { return }
|
||||
layer_room(l, l.count + 1)
|
||||
let o = l.count * INST_FLOATS
|
||||
l.inst[o] = x; l.inst[o + 1] = y; l.inst[o + 2] = z; l.inst[o + 3] = scale
|
||||
l.inst[o + 4] = Math.sin(yaw); l.inst[o + 5] = Math.cos(yaw); l.inst[o + 6] = seed; l.inst[o + 7] = wind
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue