fix(render3d): the Vulkan renderer stops leaking as it loads and draws
- every texture upload malloc'd a CPU copy of its pixels and never freed it (236 MB over the valley's boot, and again for every model loaded later): the pixels are converted straight into the mapped staging buffer - the per-level and per-layer views gvk_view_of made outlived their texture, and on MoltenVK a view keeps its Metal texture alive: a released texture takes its views with it, and the cache is keyed by numbers instead of a string built on every call - the Vulkan structs filled for a draw, pass, barrier, descriptor set, buffer, allocation or upload (about sixty call sites) come from a reused 1 MB scratch ring (gvk_tmp) - the descriptor-set cache and the retired buffers are emptied in place, not replaced; the grass cull's dispatch arguments are made once - macOS drains an autorelease pool each frame (Vk.frame_pool, lvk_frame_pool in vk_mac.ll) - R3D_VK_PROF reports Vulkan objects made and destroyed by kind, and every cache's length - examples/rendering/smooth presents through render3d, so it runs on Vulkan too The full valley on headless Vulkan loads to 2.18 GB and holds (it passed 8 GB while loading before). ludic-dev test 305/305, selfhost-test 33/33. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
9539f7bcec
commit
80764f85c1
11 changed files with 284 additions and 113 deletions
|
|
@ -102,9 +102,14 @@ function gg_cull_frame(render3d_st: mut Render3dState) -> void {
|
|||
gg_tiles(render3d_st, 4, 0.0, 16.0)
|
||||
gg_tiles(render3d_st, 8, 16.0, 40.0)
|
||||
gg_tiles(render3d_st, 16, 40.0, render3d_st.grass_radius)
|
||||
let rb = words(4)
|
||||
# made once: a words() a frame is a calloc nothing frees
|
||||
if render3d_st.gg_rb == null {
|
||||
render3d_st.gg_rb = words(4); render3d_st.gg_cb = words(1); render3d_st.gg_bufs = words(3)
|
||||
render3d_st.gg_texs = words(2); render3d_st.gg_pr = words(48)
|
||||
}
|
||||
let rb = render3d_st.gg_rb
|
||||
rb[0] = GG_BANDS; rb[1] = 0; rb[2] = 0; rb[3] = 0
|
||||
let cb = words(1)
|
||||
let cb = render3d_st.gg_cb
|
||||
cb[0] = render3d_st.gg_cmds
|
||||
gpu_dispatch(render3d_st, render3d_st.gg_reset, data_of(rb), 16, cb, 1)
|
||||
if render3d_st.gg_n == 0 { return }
|
||||
|
|
@ -112,16 +117,16 @@ function gg_cull_frame(render3d_st: mut Render3dState) -> void {
|
|||
let tb = render3d_st.gg_tiles_buf[render3d_st.r3d_test_frame % 2]
|
||||
gpu_buffer_upload(render3d_st, tb, render3d_st.gg_n * 16, data_of(render3d_st.gg_tv), GPU_DYNAMIC)
|
||||
let pr = gg_params(render3d_st)
|
||||
let bufs = words(3)
|
||||
let bufs = render3d_st.gg_bufs
|
||||
bufs[0] = tb; bufs[1] = render3d_st.gg_out; bufs[2] = render3d_st.gg_cmds
|
||||
let texs = words(2)
|
||||
let texs = render3d_st.gg_texs
|
||||
texs[0] = render3d_st.ter_height_tex; texs[1] = render3d_st.ter_ortho_tex
|
||||
gpu_dispatch_tex(render3d_st, render3d_st.gg_cull, data_of(pr), 192, bufs, texs, (render3d_st.gg_max + 63) / 64, render3d_st.gg_n)
|
||||
}
|
||||
|
||||
# grass_cull.comp's Params, std140: 12 vec4s
|
||||
function gg_params(render3d_st: Render3dState) -> words {
|
||||
let pr = words(48)
|
||||
# grass_cull.comp's Params, std140: 12 vec4s, into the block made once in gg_cull_frame
|
||||
function gg_params(render3d_st: mut Render3dState) -> words {
|
||||
let pr = render3d_st.gg_pr
|
||||
for i in 0 .. 48 { pr[i] = 0 }
|
||||
if render3d_st.cam_planes != null { for i in 0 .. 16 { pr[i] = float_bits(render3d_st.cam_planes[i]) } }
|
||||
pr[16] = float_bits(render3d_st.cam_pos[0]); pr[17] = float_bits(render3d_st.cam_pos[1]); pr[18] = float_bits(render3d_st.cam_pos[2]); pr[19] = float_bits(render3d_st.grass_radius)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue