Merge commit 'db7c21e' into lang/foundations
This commit is contained in:
commit
22a384a76a
6 changed files with 107 additions and 4 deletions
|
|
@ -382,6 +382,11 @@ export state Render3dState {
|
||||||
gvk_buf_size: []int = null
|
gvk_buf_size: []int = null
|
||||||
gvk_buf_map: []pointer = null # host-visible buffers stay mapped for their whole life
|
gvk_buf_map: []pointer = null # host-visible buffers stay mapped for their whole life
|
||||||
gvk_buf_used: []int = null # the frame (gvk_frame_no) a draw last bound the buffer in
|
gvk_buf_used: []int = null # the frame (gvk_frame_no) a draw last bound the buffer in
|
||||||
|
gvk_bsp_buf: []long = null # per handle, a second buffer a re-filled one swaps with (gvk_buf_reserve)
|
||||||
|
gvk_bsp_mem: []long = null
|
||||||
|
gvk_bsp_size: []int = null
|
||||||
|
gvk_bsp_map: []pointer = null
|
||||||
|
gvk_bsp_used: []int = null
|
||||||
gvk_frame_no: int = 1
|
gvk_frame_no: int = 1
|
||||||
@max(4096) gvk_retired_buf: []long = null
|
@max(4096) gvk_retired_buf: []long = null
|
||||||
@max(4096) gvk_retired_mem: []long = null
|
@max(4096) gvk_retired_mem: []long = null
|
||||||
|
|
|
||||||
|
|
@ -643,8 +643,11 @@ function gvk_buf_new(render3d_st: mut Render3dState) -> int {
|
||||||
if render3d_st.gvk_buf == null {
|
if render3d_st.gvk_buf == null {
|
||||||
render3d_st.gvk_buf = new []long; render3d_st.gvk_buf_mem = new []long; render3d_st.gvk_buf_size = new []int; render3d_st.gvk_buf_map = new []pointer
|
render3d_st.gvk_buf = new []long; render3d_st.gvk_buf_mem = new []long; render3d_st.gvk_buf_size = new []int; render3d_st.gvk_buf_map = new []pointer
|
||||||
render3d_st.gvk_buf_used = new []int; render3d_st.gvk_retired_buf = new []long; render3d_st.gvk_retired_mem = new []long
|
render3d_st.gvk_buf_used = new []int; render3d_st.gvk_retired_buf = new []long; render3d_st.gvk_retired_mem = new []long
|
||||||
|
render3d_st.gvk_bsp_buf = new []long; render3d_st.gvk_bsp_mem = new []long; render3d_st.gvk_bsp_size = new []int
|
||||||
|
render3d_st.gvk_bsp_map = new []pointer; render3d_st.gvk_bsp_used = new []int
|
||||||
# handle 0 is "no buffer", as it is on OpenGL
|
# handle 0 is "no buffer", as it is on OpenGL
|
||||||
push(render3d_st.gvk_buf, zero); push(render3d_st.gvk_buf_mem, zero); push(render3d_st.gvk_buf_size, 0); push(render3d_st.gvk_buf_map, null); push(render3d_st.gvk_buf_used, 0)
|
push(render3d_st.gvk_buf, zero); push(render3d_st.gvk_buf_mem, zero); push(render3d_st.gvk_buf_size, 0); push(render3d_st.gvk_buf_map, null); push(render3d_st.gvk_buf_used, 0)
|
||||||
|
gvk_bsp_grow(render3d_st)
|
||||||
}
|
}
|
||||||
# a handle a deleted buffer gave back first (gvk_buf_delete)
|
# a handle a deleted buffer gave back first (gvk_buf_delete)
|
||||||
if render3d_st.gvk_buf_spare != null and len(render3d_st.gvk_buf_spare) > 0 {
|
if render3d_st.gvk_buf_spare != null and len(render3d_st.gvk_buf_spare) > 0 {
|
||||||
|
|
@ -654,6 +657,7 @@ function gvk_buf_new(render3d_st: mut Render3dState) -> int {
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
push(render3d_st.gvk_buf, zero); push(render3d_st.gvk_buf_mem, zero); push(render3d_st.gvk_buf_size, 0); push(render3d_st.gvk_buf_map, null); push(render3d_st.gvk_buf_used, 0)
|
push(render3d_st.gvk_buf, zero); push(render3d_st.gvk_buf_mem, zero); push(render3d_st.gvk_buf_size, 0); push(render3d_st.gvk_buf_map, null); push(render3d_st.gvk_buf_used, 0)
|
||||||
|
gvk_bsp_grow(render3d_st)
|
||||||
return len(render3d_st.gvk_buf) - 1
|
return len(render3d_st.gvk_buf) - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -670,6 +674,7 @@ function gvk_buf_delete(render3d_st: mut Render3dState, b: int) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
function gvk_buf_release(render3d_st: mut Render3dState, b: int) -> void {
|
function gvk_buf_release(render3d_st: mut Render3dState, b: int) -> void {
|
||||||
|
gvk_bsp_drop(render3d_st, b)
|
||||||
if render3d_st.gvk_buf[b] == 0 { return }
|
if render3d_st.gvk_buf[b] == 0 { return }
|
||||||
let zero: long = 0
|
let zero: long = 0
|
||||||
if gvk_buf_busy(render3d_st, b) {
|
if gvk_buf_busy(render3d_st, b) {
|
||||||
|
|
@ -740,7 +745,15 @@ function gvk_buf_reserve(render3d_st: mut Render3dState, b: int, n: int) -> bool
|
||||||
if b <= 0 or b >= len(render3d_st.gvk_buf) { return false }
|
if b <= 0 or b >= len(render3d_st.gvk_buf) { return false }
|
||||||
# already big enough, and no draw this frame reads what is there: fill it in place
|
# already big enough, and no draw this frame reads what is there: fill it in place
|
||||||
if render3d_st.gvk_buf[b] != 0 and render3d_st.gvk_buf_size[b] >= n and (not gvk_buf_busy(render3d_st, b) or gvk_buf_is_gpu(render3d_st, b)) { return true }
|
if render3d_st.gvk_buf[b] != 0 and render3d_st.gvk_buf_size[b] >= n and (not gvk_buf_busy(render3d_st, b) or gvk_buf_is_gpu(render3d_st, b)) { return true }
|
||||||
|
# big enough but read by a frame still on the GPU: its second buffer, when that one is free, and
|
||||||
|
# else the busy one becomes the second and a new one is made - a buffer re-filled every frame (the
|
||||||
|
# interface's vertices) ping-pongs between two, where it was made and destroyed every frame
|
||||||
|
if render3d_st.gvk_buf[b] != 0 and render3d_st.gvk_buf_size[b] >= n {
|
||||||
|
if gvk_bsp_swap(render3d_st, b, n) { return true }
|
||||||
|
gvk_bsp_park(render3d_st, b)
|
||||||
|
} else {
|
||||||
gvk_buf_release(render3d_st, b)
|
gvk_buf_release(render3d_st, b)
|
||||||
|
}
|
||||||
var size = n
|
var size = n
|
||||||
if size < 64 { size = 64 }
|
if size < 64 { size = 64 }
|
||||||
let size_l: long = size
|
let size_l: long = size
|
||||||
|
|
@ -853,3 +866,65 @@ function gvk_prime_tables(render3d_st: mut Render3dState) -> void {
|
||||||
let none: long = 0
|
let none: long = 0
|
||||||
for i in 0 .. GVK_PRIME_MAX { push(hs, none) }
|
for i in 0 .. GVK_PRIME_MAX { push(hs, none) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ---- a re-filled buffer's second: gvk_buf_reserve swaps to it while the first is still being read ----
|
||||||
|
@alloc_ok("one slot per buffer handle, beside the handle's own (gvk_buf_new)")
|
||||||
|
function gvk_bsp_grow(render3d_st: mut Render3dState) -> void {
|
||||||
|
let zero: long = 0
|
||||||
|
push(render3d_st.gvk_bsp_buf, zero)
|
||||||
|
push(render3d_st.gvk_bsp_mem, zero)
|
||||||
|
push(render3d_st.gvk_bsp_size, 0)
|
||||||
|
push(render3d_st.gvk_bsp_map, null)
|
||||||
|
push(render3d_st.gvk_bsp_used, 0)
|
||||||
|
}
|
||||||
|
function gvk_bsp_busy(render3d_st: Render3dState, b: int) -> bool {
|
||||||
|
let u = render3d_st.gvk_bsp_used[b]
|
||||||
|
return u == render3d_st.gvk_frame_no or (render3d_st.gvk_frame_pending and u == render3d_st.gvk_frame_pending_no)
|
||||||
|
}
|
||||||
|
# the second in place of the first when it is there, big enough and read by nothing still running
|
||||||
|
function gvk_bsp_swap(render3d_st: mut Render3dState, b: int, n: int) -> bool {
|
||||||
|
if render3d_st.gvk_bsp_buf == null or b >= len(render3d_st.gvk_bsp_buf) { return false }
|
||||||
|
if render3d_st.gvk_bsp_buf[b] == 0 or render3d_st.gvk_bsp_size[b] < n or gvk_bsp_busy(render3d_st, b) { return false }
|
||||||
|
let tb = render3d_st.gvk_buf[b]
|
||||||
|
let tm = render3d_st.gvk_buf_mem[b]
|
||||||
|
let ts = render3d_st.gvk_buf_size[b]
|
||||||
|
let tp = render3d_st.gvk_buf_map[b]
|
||||||
|
let tu = render3d_st.gvk_buf_used[b]
|
||||||
|
render3d_st.gvk_buf[b] = render3d_st.gvk_bsp_buf[b]; render3d_st.gvk_buf_mem[b] = render3d_st.gvk_bsp_mem[b]
|
||||||
|
render3d_st.gvk_buf_size[b] = render3d_st.gvk_bsp_size[b]; render3d_st.gvk_buf_map[b] = render3d_st.gvk_bsp_map[b]
|
||||||
|
render3d_st.gvk_buf_used[b] = render3d_st.gvk_bsp_used[b]
|
||||||
|
render3d_st.gvk_bsp_buf[b] = tb; render3d_st.gvk_bsp_mem[b] = tm; render3d_st.gvk_bsp_size[b] = ts
|
||||||
|
render3d_st.gvk_bsp_map[b] = tp; render3d_st.gvk_bsp_used[b] = tu
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
# the busy first becomes the second (the old second let go), leaving the handle empty for a new one
|
||||||
|
function gvk_bsp_park(render3d_st: mut Render3dState, b: int) -> void {
|
||||||
|
let zero: long = 0
|
||||||
|
gvk_bsp_drop(render3d_st, b)
|
||||||
|
render3d_st.gvk_bsp_buf[b] = render3d_st.gvk_buf[b]; render3d_st.gvk_bsp_mem[b] = render3d_st.gvk_buf_mem[b]
|
||||||
|
render3d_st.gvk_bsp_size[b] = render3d_st.gvk_buf_size[b]; render3d_st.gvk_bsp_map[b] = render3d_st.gvk_buf_map[b]
|
||||||
|
render3d_st.gvk_bsp_used[b] = render3d_st.gvk_buf_used[b]
|
||||||
|
render3d_st.gvk_buf[b] = zero; render3d_st.gvk_buf_mem[b] = zero; render3d_st.gvk_buf_size[b] = 0
|
||||||
|
render3d_st.gvk_buf_map[b] = null; render3d_st.gvk_buf_used[b] = 0
|
||||||
|
}
|
||||||
|
# the second let go: destroyed now, or retired until the frame that read it has finished
|
||||||
|
function gvk_bsp_drop(render3d_st: mut Render3dState, b: int) -> void {
|
||||||
|
if render3d_st.gvk_bsp_buf == null or b >= len(render3d_st.gvk_bsp_buf) or render3d_st.gvk_bsp_buf[b] == 0 { return }
|
||||||
|
let zero: long = 0
|
||||||
|
if gvk_bsp_busy(render3d_st, b) {
|
||||||
|
@alloc_ok("within the retire lists' room made at start-up (@max 4096)")
|
||||||
|
push(render3d_st.gvk_retired_buf, render3d_st.gvk_bsp_buf[b])
|
||||||
|
@alloc_ok("within the retire lists' room made at start-up (@max 4096)")
|
||||||
|
push(render3d_st.gvk_retired_mem, render3d_st.gvk_bsp_mem[b])
|
||||||
|
@alloc_ok("within the retire lists' room made at start-up (@max 4096)")
|
||||||
|
while len(render3d_st.gvk_retired_frame) < len(render3d_st.gvk_retired_buf) - 1 { push(render3d_st.gvk_retired_frame, 0) }
|
||||||
|
@alloc_ok("within the retire lists' room made at start-up (@max 4096)")
|
||||||
|
push(render3d_st.gvk_retired_frame, render3d_st.gvk_bsp_used[b])
|
||||||
|
} else {
|
||||||
|
render3d_st.gvk_mk_x_buf += 1
|
||||||
|
Vk.destroy_buffer(render3d_st.gvk_dev, render3d_st.gvk_bsp_buf[b], render3d_st.gvk_ac)
|
||||||
|
gvk_mem_free(render3d_st, gvk_mem_id(render3d_st.gvk_bsp_mem[b]))
|
||||||
|
}
|
||||||
|
render3d_st.gvk_bsp_buf[b] = zero; render3d_st.gvk_bsp_mem[b] = zero; render3d_st.gvk_bsp_size[b] = 0
|
||||||
|
render3d_st.gvk_bsp_map[b] = null; render3d_st.gvk_bsp_used[b] = 0
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,29 @@ function overlay_init(render3d_st: mut Render3dState, font_dir: string) -> bool
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# The atlas is white glyphs on alpha, and the overlay reads only the coverage: it is kept as one
|
||||||
|
# byte a texel (R8). As RGBA a 3072 x 2688 atlas was 44 MB with its mips, the most of any UI texture.
|
||||||
|
@alloc_ok("loading a font: a load, not a frame")
|
||||||
|
function ov_font_tex(render3d_st: mut Render3dState, path: string) -> int {
|
||||||
|
let px = png_decode(render3d_st, path)
|
||||||
|
if px == null { return 0 }
|
||||||
|
if render3d_st.tex_channels != 4 or render3d_st.tex_depth != 8 {
|
||||||
|
let id0 = tex_upload(render3d_st, px, false, true)
|
||||||
|
free(px)
|
||||||
|
tex_note_size(render3d_st, id0)
|
||||||
|
return id0
|
||||||
|
}
|
||||||
|
let n = render3d_st.tex_w * render3d_st.tex_h
|
||||||
|
let a = bytes(n)
|
||||||
|
for i in 0 .. n { a[i] = px[i * 4 + 3] }
|
||||||
|
free(px)
|
||||||
|
render3d_st.tex_channels = 1
|
||||||
|
let id = tex_upload(render3d_st, a, false, true)
|
||||||
|
free(a)
|
||||||
|
tex_note_size(render3d_st, id)
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
|
||||||
# Load (or swap to) the font atlas in `font_dir`: font.png and font.json. A game calls it
|
# Load (or swap to) the font atlas in `font_dir`: font.png and font.json. A game calls it
|
||||||
# again to change fonts at run time - a language whose script the default atlas does not
|
# again to change fonts at run time - a language whose script the default atlas does not
|
||||||
# carry brings its own. Returns false, and keeps the font it had, if there is none there.
|
# carry brings its own. Returns false, and keeps the font it had, if there is none there.
|
||||||
|
|
@ -74,7 +97,7 @@ function overlay_init(render3d_st: mut Render3dState, font_dir: string) -> bool
|
||||||
function overlay_font(render3d_st: mut Render3dState, font_dir: string) -> bool {
|
function overlay_font(render3d_st: mut Render3dState, font_dir: string) -> bool {
|
||||||
let meta = Fs.read_text(font_dir + "/font.json")
|
let meta = Fs.read_text(font_dir + "/font.json")
|
||||||
if meta == null { return false }
|
if meta == null { return false }
|
||||||
let tex = tex_load_ex(render3d_st, font_dir + "/font.png", false, 0)
|
let tex = ov_font_tex(render3d_st, font_dir + "/font.png")
|
||||||
if tex == 0 { return false }
|
if tex == 0 { return false }
|
||||||
let j = Json.parse(meta)
|
let j = Json.parse(meta)
|
||||||
render3d_st.ov_font_cols = jint(j, "cols", 16); render3d_st.ov_font_rows = jint(j, "rows", 6)
|
render3d_st.ov_font_cols = jint(j, "cols", 16); render3d_st.ov_font_rows = jint(j, "rows", 6)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// 2D overlay: an image texture, the font atlas (white glyphs on alpha) or a flat colour, times a
|
// 2D overlay: an image texture, the font atlas (glyph coverage, R8) or a flat colour, times a
|
||||||
// colour. Which one is the vertex's own: v carries 4 x the mode (0 image, 1 font, 2 flat) on top of
|
// colour. Which one is the vertex's own: v carries 4 x the mode (0 image, 1 font, 2 flat) on top of
|
||||||
// its real coordinate, so text, panels and an image's quads share a draw (overlay.ludic, ov_use_tex).
|
// its real coordinate, so text, panels and an image's quads share a draw (overlay.ludic, ov_use_tex).
|
||||||
in vec2 v_uv;
|
in vec2 v_uv;
|
||||||
|
|
@ -27,7 +27,7 @@ void main() {
|
||||||
if (mode > 1.5) {
|
if (mode > 1.5) {
|
||||||
o_color = v_col;
|
o_color = v_col;
|
||||||
} else if (mode > 0.5) {
|
} else if (mode > 0.5) {
|
||||||
o_color = vec4(v_col.rgb, v_col.a * texture(u_font, uv).a);
|
o_color = vec4(v_col.rgb, v_col.a * texture(u_font, uv).r); // the atlas is its coverage alone (R8)
|
||||||
} else {
|
} else {
|
||||||
vec4 t = texture(u_tex, uv);
|
vec4 t = texture(u_tex, uv);
|
||||||
o_color = vec4(v_col.rgb * t.rgb, v_col.a * t.a);
|
o_color = vec4(v_col.rgb * t.rgb, v_col.a * t.a);
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue