ludic/packages/ludic.render3d/terrain_pages_fill.ludic

74 lines
3.4 KiB
Text

# terrain_pages_fill.ludic — a tile's three layers written into the staging, border and all, and the
# frame's copies recorded (terrain_pages_frame.ludic). The staging half is laid out as the page table,
# then TP_BUDGET heights, TP_BUDGET normals and TP_BUDGET photographs.
# the k-th load of the frame: tile t's heights and normals, (TT_TEX + 2) a side, each texel the one
# the whole copy held at that place, clamped at the map's edge
function tp_fill(render3d_st: mut Render3dState, t: int, base: int, k: int) -> void {
let n = render3d_st.tt_n
let hs = TT_TEX + 2
let hb = hs * hs * 4
let ho = base + n * n * 4 + k * hb
let no = base + n * n * 4 + TP_BUDGET * hb + k * hb
let i0 = (t % n) * TT_TEX - 1
let j0 = (t / n) * TT_TEX - 1
let p = render3d_st.tp_st_ptr
for b in 0 .. hs {
let tz = min(max(j0 + b, 0), TERRAIN_RES - 1)
for a in 0 .. hs {
let tx = min(max(i0 + a, 0), TERRAIN_RES - 1)
let o = (b * hs + a) * 4
Vk.put_i32(p, ho + o, float_bits(tt_h_load(render3d_st, tx, tz)))
Vk.put_i32(p, no + o, tt_n_load(render3d_st, tx, tz))
}
}
tp_fill_ortho(render3d_st, t, base + n * n * 4 + 2 * TP_BUDGET * hb, k)
}
# ... and its photograph, (tt_oside + 2) a side, as sRGB RGBA8 bytes with alpha 255
function tp_fill_ortho(render3d_st: mut Render3dState, t: int, at: int, k: int) -> void {
let n = render3d_st.tt_n
let side = render3d_st.tt_oside
let os = side + 2
let top = n * side - 1
let o0 = at + k * os * os * 4
let i0 = (t % n) * side - 1
let j0 = (t / n) * side - 1
let p: pointer = render3d_st.tp_st_ptr
for b in 0 .. os {
let pz = min(max(j0 + b, 0), top)
for a in 0 .. os {
let v = tt_o_load(render3d_st, min(max(i0 + a, 0), top), pz)
let o = o0 + (b * os + a) * 4
p[o] = (v >> 16) & 255
p[o + 1] = (v >> 8) & 255
p[o + 2] = v & 255
p[o + 3] = 255
}
}
}
# the frame's k loads into their slots, then the page table if it changed: all in cb, no submit
function tp_upload(render3d_st: mut Render3dState, cb: pointer, base: int, k: int) -> void {
let n = render3d_st.tt_n
let hs = TT_TEX + 2
let hb = hs * hs * 4
let os = render3d_st.tt_oside + 2
let p0 = base + n * n * 4
let slots = render3d_st.tp_cand_s
gpu_layers_copy(render3d_st, cb, render3d_st.tp_h_tex, hs, hs, p0, hb, slots, k)
gpu_layers_copy(render3d_st, cb, render3d_st.tp_n_tex, hs, hs, p0 + TP_BUDGET * hb, hb, slots, k)
gpu_layers_copy(render3d_st, cb, render3d_st.tp_o_tex, os, os, p0 + 2 * TP_BUDGET * hb, os * os * 4, slots, k)
if not render3d_st.tp_dirty { return }
mem_copy(mem_off(render3d_st.tp_st_ptr, base), data_of(render3d_st.tp_page), n * n * 4)
gpu_layers_copy(render3d_st, cb, render3d_st.tp_page_tex, n, n, base, 0, render3d_st.tp_zero, 1)
render3d_st.tp_dirty = false
}
# R3D_VKMEM: one line on the pool, next to the rest of the report
function tp_report(render3d_st: Render3dState) -> void {
if not render3d_st.tp_on { return }
tp_say_report(render3d_st.tp_slots - render3d_st.tp_nfree, render3d_st.tp_slots, render3d_st.tp_frame_loads, render3d_st.tp_loads, render3d_st.tp_bytes, render3d_st.tp_reach)
}
@alloc_ok("a report printed once, under R3D_VKMEM")
function tp_say_report(res: int, slots: int, now: int, all: int, bytes: int, r: float) -> void { print(`vkmem: terrain pages: {res} of {slots} slots resident, {now} loaded this frame, {all} over the run, {bytes / 1024} KB on the GPU, {int(r)} m round the camera`) }