fix(render3d): a refused pipeline is not retried every draw, and an evicted chunk is freed whole

gvk_pipeline_fast cached only pipelines it made, so one the driver refused was attempted again on
every draw, each attempt building its key string and create structs anew; the refusal is cached
too (a Vulkan program's variants are fixed when it is made, so it would fail the same way).
stream_evict made a new chunk list per eviction and never freed the evicted chunks' records; it
compacts the list in place and frees each evicted chunk with its data.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-09-27 23:07:28 +03:00
parent 6dd1810038
commit 70a92a8862
2 changed files with 15 additions and 6 deletions

View file

@ -1903,8 +1903,9 @@ function gvk_pipeline_fast(render3d_st: mut Render3dState, p: int, m: Mesh, st:
return render3d_st.gvk_pc_pipe[k]
}
}
# a pipeline the driver refused is remembered as 0 too: retried on every draw, each try built its
# key and its create structs again and gave none of them back
let pipe = gvk_pipeline(render3d_st, p, m, st, n_color, color_fmt, depth_fmt, samples)
if pipe == 0 { return pipe }
push(render3d_st.gvk_pc_prog, p); push(render3d_st.gvk_pc_layout, layout); push(render3d_st.gvk_pc_state, state)
push(render3d_st.gvk_pc_bias, bias); push(render3d_st.gvk_pc_pass, pass); push(render3d_st.gvk_pc_pipe, pipe)
if p < 4096 { render3d_st.gvk_pc_last[p] = len(render3d_st.gvk_pc_prog) - 1 }

View file

@ -162,16 +162,24 @@ function stream_evict(render3d_st: mut Render3dState, s: Stream) -> void {
}
t = lo
# everything wanted by the walk in progress stays whatever the threshold says
let kept = new []Chunk
# compacted in place, and an evicted chunk goes whole: a new list per eviction and the chunks'
# own records were never given back
var w = 0
var i = 0
while i < s.n {
let c = s.chunks[i]
if c.used >= t or c.used == render3d_st.stream_walk_no { push(kept, c) }
else { if c.data != null { free(c.data) } }
if c.used >= t or c.used == render3d_st.stream_walk_no {
s.chunks[w] = c
w += 1
} else {
if c.data != null { free(c.data) }
free(c)
}
i += 1
}
s.chunks = kept
s.n = len(kept)
let ch = s.chunks
while len(ch) > w { List.pop(ch) }
s.n = w
for h in 0 .. STREAM_HASH { s.htab[h] = 0 }
i = 0
while i < s.n { s.keys[i] = s.chunks[i].key; stream_remember(s, s.chunks[i].key, i); i += 1 }