Merge branch 'r3d/floor' into lang/foundations
This commit is contained in:
commit
a64713fc23
12 changed files with 120 additions and 26 deletions
|
|
@ -82,6 +82,9 @@ function actor_init(render3d_st: mut Render3dState) -> void {
|
|||
# record, matrix and tint then (actor_release gives them back to this pool)
|
||||
if render3d_st.ac_spare == null { render3d_st.ac_spare = new []Actor }
|
||||
let sp = render3d_st.ac_spare
|
||||
if render3d_st.ac_actors == null { render3d_st.ac_actors = new []Actor }
|
||||
actor_room(render3d_st.ac_actors, 4 * ACTOR_POOL)
|
||||
actor_room(sp, 4 * ACTOR_POOL)
|
||||
for i in 0 .. ACTOR_POOL {
|
||||
let a = new Actor
|
||||
a.tint = v3_new(1.0, 1.0, 1.0)
|
||||
|
|
@ -94,7 +97,8 @@ function actor_init(render3d_st: mut Render3dState) -> void {
|
|||
render3d_st.ac_sh_cut = ac_prog_new(render3d_st, "skin.vert", "shadow.frag", "#define SHADOW_PASS\n#define ALPHA_TEST\n")
|
||||
render3d_st.ac_out = ac_prog_new(render3d_st, "skin.vert", "outline.frag", "#define OUTLINE\n")
|
||||
render3d_st.ac_out_cut = ac_prog_new(render3d_st, "skin.vert", "outline.frag", "#define OUTLINE\n#define ALPHA_TEST\n")
|
||||
render3d_st.ac_actors = new []Actor
|
||||
let stage = render3d_st.ac_actors # made above with its room; a new valley starts empty
|
||||
List.clear(stage)
|
||||
}
|
||||
# off the stage: the last actor takes its row, so the list stays dense and nothing is rebuilt
|
||||
# (it was a new list of every other actor per removal, never freed)
|
||||
|
|
@ -475,3 +479,10 @@ function actor_own_skin(a: Actor) -> Skin {
|
|||
a.skin_owned = true
|
||||
return a.skin
|
||||
}
|
||||
|
||||
# room for n more actors in a list, made at start-up: filled and emptied, it keeps what it grew to
|
||||
function actor_room(l: []Actor, n: int) -> void {
|
||||
let have = len(l)
|
||||
for i in 0 .. n { push(l, null) }
|
||||
while len(l) > have { List.pop(l) }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -692,6 +692,7 @@ export state Render3dState {
|
|||
stream_debug_n: int = 0
|
||||
stream_scratch: floats = null
|
||||
gvk_pipe_bufs: words = null # a pipeline's vertex buffers, while it is made
|
||||
gsl_up: floats = floats(3) # the camera's up for DLSS's constants
|
||||
ov_nine_buf: floats = floats(16) # ov_nine's corners and uvs
|
||||
gvk_ac: pointer = null # the VkAllocationCallbacks every create and destroy is given (R3D_ALLOC_VK=1)
|
||||
gvk_prime_b: words = null # buffers made since the frame began, read once so MoltenVK makes their
|
||||
|
|
|
|||
|
|
@ -311,7 +311,7 @@ function gvk_alloc(render3d_st: mut Render3dState, req: bytes, want: int) -> lon
|
|||
# device-local is a preference; host-visible is a need
|
||||
if t < 0 and want == VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT { t = gvk_mem_type(render3d_st, allowed, 0) }
|
||||
let zero: long = 0
|
||||
if t < 0 { print(`r3d: vulkan: no memory type for properties {want}`); return zero }
|
||||
if t < 0 { gvk_say_no_type(want); return zero }
|
||||
let mai = gvk_tmp(render3d_st, VkMemoryAllocateInfo_sizeof)
|
||||
Vk.zero(mai, VkMemoryAllocateInfo_sizeof)
|
||||
Vk.put_i32(mai, VkMemoryAllocateInfo_sType, VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO)
|
||||
|
|
@ -320,7 +320,7 @@ function gvk_alloc(render3d_st: mut Render3dState, req: bytes, want: int) -> lon
|
|||
let out = gvk_tmp(render3d_st, 8)
|
||||
render3d_st.gvk_mk_mem += 1
|
||||
let r = Vk.allocate_memory(render3d_st.gvk_dev, mai, render3d_st.gvk_ac, out)
|
||||
if r != VK_SUCCESS { print(`r3d: vulkan: vkAllocateMemory failed (VkResult {r})`); return zero }
|
||||
if r != VK_SUCCESS { gvk_say_alloc_failed(r); return zero }
|
||||
render3d_st.gvk_n_allocs += 1
|
||||
return gvk_handle(out)
|
||||
}
|
||||
|
|
@ -548,7 +548,7 @@ const GVK_TMP_BYTES: int = 1048576
|
|||
|
||||
function gvk_tmp(render3d_st: mut Render3dState, n: int) -> pointer {
|
||||
let sz = (n + 15) / 16 * 16
|
||||
if sz > GVK_TMP_BYTES { print(`r3d: vulkan: {n} bytes of scratch asked for at once`); return null }
|
||||
if sz > GVK_TMP_BYTES { gvk_say_tmp_big(n); return null }
|
||||
if render3d_st.gvk_tmp_off + sz > GVK_TMP_BYTES { render3d_st.gvk_tmp_off = 0 }
|
||||
let p = mem_off(render3d_st.gvk_tmp_buf, render3d_st.gvk_tmp_off)
|
||||
render3d_st.gvk_tmp_off += sz
|
||||
|
|
@ -746,6 +746,18 @@ function gvk_startup_state(render3d_st: mut Render3dState) -> void {
|
|||
if render3d_st.gvk_buf_spare == null { render3d_st.gvk_buf_spare = new []int }
|
||||
if render3d_st.gvk_retired_frame == null { render3d_st.gvk_retired_frame = new []int }
|
||||
if render3d_st.gvk_buf_gpu == null { render3d_st.gvk_buf_gpu = new []int }
|
||||
if render3d_st.gvk_retired_buf == null { render3d_st.gvk_retired_buf = new []long; render3d_st.gvk_retired_mem = new []long }
|
||||
# room made now in every list play pushes into, so a push never grows one (plan 25.2)
|
||||
gvk_room_int(render3d_st.gvk_retired_frame, GVK_LIST_ROOM)
|
||||
gvk_room_long(render3d_st.gvk_retired_buf, GVK_LIST_ROOM)
|
||||
gvk_room_long(render3d_st.gvk_retired_mem, GVK_LIST_ROOM)
|
||||
gvk_room_int(render3d_st.gvk_fr_blk, GVK_LIST_ROOM)
|
||||
gvk_room_int(render3d_st.gvk_fr_off, GVK_LIST_ROOM)
|
||||
gvk_room_int(render3d_st.gvk_fr_len, GVK_LIST_ROOM)
|
||||
gvk_room_int(render3d_st.gvk_al_spare, GVK_LIST_ROOM)
|
||||
gvk_room_int(render3d_st.gvk_tex_spare, GVK_LIST_ROOM)
|
||||
gvk_room_int(render3d_st.gvk_buf_spare, GVK_LIST_ROOM)
|
||||
gvk_room_int(render3d_st.gvk_buf_gpu, 4 * GVK_LIST_ROOM)
|
||||
render3d_st.gvk_sc_tmp = new []long
|
||||
let sct = render3d_st.gvk_sc_tmp
|
||||
for i in 0 .. 130 { push(sct, zero) }
|
||||
|
|
@ -768,3 +780,27 @@ function gvk_startup_state(render3d_st: mut Render3dState) -> void {
|
|||
for i in 0 .. 32 { render3d_st.gpu_unit_2d[i] = -1 }
|
||||
}
|
||||
}
|
||||
|
||||
# messages, each built in a function of its own so the path that says it holds no allocation
|
||||
@alloc_ok("a message, built only when it is said: a failure, a warning or a debug switch")
|
||||
function gvk_say_no_type(want: int) -> void { print(`r3d: vulkan: no memory type for properties {want}`) }
|
||||
@alloc_ok("a message, built only when it is said: a failure, a warning or a debug switch")
|
||||
function gvk_say_alloc_failed(r: int) -> void { print(`r3d: vulkan: vkAllocateMemory failed (VkResult {r})`) }
|
||||
@alloc_ok("a message, built only when it is said: a failure, a warning or a debug switch")
|
||||
function gvk_say_tmp_big(n: int) -> void { print(`r3d: vulkan: {n} bytes of scratch asked for at once`) }
|
||||
|
||||
const GVK_LIST_ROOM: int = 4096
|
||||
# a list's room for n more, made now: filled and emptied again, it keeps what it grew to
|
||||
function gvk_room_int(l: []int, n: int) -> void {
|
||||
if l == null { return }
|
||||
let have = len(l)
|
||||
for i in 0 .. n { push(l, 0) }
|
||||
while len(l) > have { List.pop(l) }
|
||||
}
|
||||
function gvk_room_long(l: []long, n: int) -> void {
|
||||
if l == null { return }
|
||||
let have = len(l)
|
||||
let zero: long = 0
|
||||
for i in 0 .. n { push(l, zero) }
|
||||
while len(l) > have { List.pop(l) }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1113,7 +1113,7 @@ function gvk_pass_no_compressed(render3d_st: mut Render3dState) -> void {
|
|||
if tex > 0 and tex < len(render3d_st.gvk_tex_glfmt) and gvk_is_compressed(render3d_st.gvk_tex_glfmt[tex]) {
|
||||
if render3d_st.gvk_bc_said < 8 {
|
||||
render3d_st.gvk_bc_said += 1
|
||||
print(`r3d: vulkan: framebuffer {render3d_st.gvk_fb_cur} would draw into compressed texture {tex} ({gvk_tex_w(render3d_st, tex)}x{gvk_tex_h(render3d_st, tex)}); left out`)
|
||||
gvk_say_compressed(render3d_st, tex)
|
||||
}
|
||||
} else {
|
||||
render3d_st.gvk_pass_col[w * 2] = tex; render3d_st.gvk_pass_col[w * 2 + 1] = render3d_st.gvk_pass_col[c * 2 + 1]
|
||||
|
|
@ -1269,7 +1269,7 @@ function gvk_draw(render3d_st: mut Render3dState, p: int, m: Mesh, st: GvkState,
|
|||
# rejected every skinned one) otherwise leaves a whole layer missing from the frame in silence.
|
||||
if p < 4096 and render3d_st.gvk_skip_said[p] == 0 {
|
||||
render3d_st.gvk_skip_said[p] = 1
|
||||
print(`r3d: vulkan: no pipeline for {gpu_program_key(render3d_st, p)}; its draws are skipped`)
|
||||
gvk_say_no_pipeline(render3d_st, p)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
@ -1835,7 +1835,7 @@ function gvk_resize_check(render3d_st: mut Render3dState) -> bool {
|
|||
if w <= 0 or h <= 0 { return false }
|
||||
if w == gl_width() and h == gl_height() and not render3d_st.gvk_swap_stale { return false }
|
||||
# a remake is rare (a resize); said, so one on every frame shows in the log
|
||||
print(`r3d: vulkan: swapchain remade {w}x{h} (was {gl_width()}x{gl_height()}, stale {render3d_st.gvk_swap_stale})`)
|
||||
gvk_say_swap_remade(render3d_st, w, h)
|
||||
gvk_flush(render3d_st)
|
||||
gl_set_drawable(w, h)
|
||||
gvk_screen_make(render3d_st, w, h)
|
||||
|
|
@ -1986,3 +1986,11 @@ function gvk_pipe_build(render3d_st: mut Render3dState, p: int, m: Mesh, st: Gvk
|
|||
if p < 4096 { render3d_st.gvk_pc_last[p] = len(render3d_st.gvk_pc_prog) - 1 }
|
||||
return pipe
|
||||
}
|
||||
|
||||
# messages, each built in a function of its own so the path that says it holds no allocation
|
||||
@alloc_ok("a message, built only when it is said: a failure, a warning or a debug switch")
|
||||
function gvk_say_compressed(render3d_st: Render3dState, tex: int) -> void { print(`r3d: vulkan: framebuffer {render3d_st.gvk_fb_cur} would draw into compressed texture {tex} ({gvk_tex_w(render3d_st, tex)}x{gvk_tex_h(render3d_st, tex)}); left out`) }
|
||||
@alloc_ok("a message, built only when it is said: a failure, a warning or a debug switch")
|
||||
function gvk_say_no_pipeline(render3d_st: Render3dState, p: int) -> void { print(`r3d: vulkan: no pipeline for {gpu_program_key(render3d_st, p)}; its draws are skipped`) }
|
||||
@alloc_ok("a message, built only when it is said: a failure, a warning or a debug switch")
|
||||
function gvk_say_swap_remade(render3d_st: Render3dState, w: int, h: int) -> void { print(`r3d: vulkan: swapchain remade {w}x{h} (was {gl_width()}x{gl_height()}, stale {render3d_st.gvk_swap_stale})`) }
|
||||
|
|
|
|||
|
|
@ -327,7 +327,7 @@ function gvk_tex_upload(render3d_st: mut Render3dState, tex: int, ifmt: int, w:
|
|||
let hv = gvk_half(Vk.get_i32(src, i))
|
||||
buf[o] = hv & 255; buf[o + 1] = (hv >> 8) & 255
|
||||
} else {
|
||||
print(`r3d: vulkan: no conversion from {bin}-byte to {bout}-byte samples`)
|
||||
gvk_say_no_conversion(bin, bout)
|
||||
gvk_staging_free(render3d_st)
|
||||
return false
|
||||
}
|
||||
|
|
@ -448,7 +448,7 @@ function gvk_tex_read(render3d_st: mut Render3dState, tex: int, ifmt: int, w: in
|
|||
# a read may ask for fewer channels than the image has (the height field's R of an RGBA32F
|
||||
# bake), never more, and only in the sample size the image stores
|
||||
if cwant > cout or gvk_gl_type_bytes(ty) != bout {
|
||||
print(`r3d: vulkan: no read-back conversion for GL format {ifmt} as {fmt}/{ty}`)
|
||||
gvk_say_no_readback(ifmt, fmt, ty)
|
||||
return false
|
||||
}
|
||||
let n = w * h * cout * bout
|
||||
|
|
@ -741,7 +741,7 @@ function gvk_buf_reserve(render3d_st: mut Render3dState, b: int, n: int) -> bool
|
|||
let out = gvk_tmp(render3d_st, 8)
|
||||
render3d_st.gvk_mk_buf += 1
|
||||
var r = Vk.create_buffer(render3d_st.gvk_dev, bci, render3d_st.gvk_ac, out)
|
||||
if r != VK_SUCCESS { return gvk_fail(render3d_st, `vkCreateBuffer ({size} bytes)`, r) }
|
||||
if r != VK_SUCCESS { return gvk_fail_create_buffer(render3d_st, size, r) }
|
||||
let buf = gvk_handle(out)
|
||||
let req = gvk_tmp(render3d_st, VkMemoryRequirements_sizeof)
|
||||
Vk.get_buffer_memory_requirements(render3d_st.gvk_dev, buf, req)
|
||||
|
|
@ -831,3 +831,11 @@ function gvk_buf_upload(render3d_st: mut Render3dState, b: int, n: int, data: po
|
|||
if data != null and n > 0 { mem_copy(render3d_st.gvk_buf_map[b], data, n) }
|
||||
return true
|
||||
}
|
||||
|
||||
# messages, each built in a function of its own so the path that says it holds no allocation
|
||||
@alloc_ok("a message, built only when it is said: a failure, a warning or a debug switch")
|
||||
function gvk_say_no_conversion(bin: int, bout: int) -> void { print(`r3d: vulkan: no conversion from {bin}-byte to {bout}-byte samples`) }
|
||||
@alloc_ok("a message, built only when it is said: a failure, a warning or a debug switch")
|
||||
function gvk_say_no_readback(ifmt: int, fmt: int, ty: int) -> void { print(`r3d: vulkan: no read-back conversion for GL format {ifmt} as {fmt}/{ty}`) }
|
||||
@alloc_ok("a message, built only when it is said: a failure, a warning or a debug switch")
|
||||
function gvk_fail_create_buffer(render3d_st: mut Render3dState, size: int, r: int) -> bool { return gvk_fail(render3d_st, `vkCreateBuffer ({size} bytes)`, r) }
|
||||
|
|
|
|||
|
|
@ -57,6 +57,12 @@ function post_set_msaa(render3d_st: mut Render3dState, n: int) -> void {
|
|||
@alloc_ok("a world being set up (a stream, a layer, water, post, a bake): the map loading or swapping, not a frame")
|
||||
function post_init(render3d_st: mut Render3dState, w: int, h: int) -> void {
|
||||
render3d_st.post_w = w; render3d_st.post_h = h
|
||||
# the exposure's two 1x1 targets: made once, here, rather than by the first frame that measured
|
||||
if render3d_st.post_adapt_t == null {
|
||||
render3d_st.post_adapt_t = new []Target
|
||||
for k in 0 .. 2 { push(render3d_st.post_adapt_t, target_new(render3d_st, 1, 1, GL_R32F, GL_RED, GL_FLOAT, false, GL_NEAREST)) }
|
||||
render3d_st.post_adapt_reset = true
|
||||
}
|
||||
render3d_st.post_hdr = target_new(render3d_st, w, h, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, true, GL_LINEAR)
|
||||
if render3d_st.post_ms_samples > 1 {
|
||||
render3d_st.post_ms_fbo = gpu_fb_new(render3d_st)
|
||||
|
|
@ -134,11 +140,6 @@ function post_measure(render3d_st: mut Render3dState) -> void {
|
|||
gpu_tex_bind(render3d_st, GPU_TEX2D, render3d_st.post_hdr.color)
|
||||
gpu_tex_param(render3d_st, GPU_TEX2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR)
|
||||
gpu_tex_mips(render3d_st, GPU_TEX2D)
|
||||
if render3d_st.post_adapt_t == null {
|
||||
render3d_st.post_adapt_t = new []Target
|
||||
for k in 0 .. 2 { push(render3d_st.post_adapt_t, target_new(render3d_st, 1, 1, GL_R32F, GL_RED, GL_FLOAT, false, GL_NEAREST)) }
|
||||
render3d_st.post_adapt_reset = true
|
||||
}
|
||||
if render3d_st.post_p_adapt == 0 { render3d_st.post_p_adapt = r3d_program(render3d_st, "fullscreen.vert", "adapt.frag", "") }
|
||||
let next = 1 - render3d_st.post_adapt_i
|
||||
target_bind(render3d_st, render3d_st.post_adapt_t[next])
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ function r3d_resize(render3d_st: mut Render3dState) -> void {
|
|||
post_free(render3d_st)
|
||||
post_init(render3d_st, gl_width(), gl_height())
|
||||
if render3d_st.water_refl != null { target_free(render3d_st, render3d_st.water_refl); render3d_st.water_refl = null }
|
||||
print(`r3d: resized to {gl_width()}x{gl_height()}`)
|
||||
r3d_say_resized()
|
||||
}
|
||||
function r3d_frame(render3d_st: mut Render3dState, time: float) -> void {
|
||||
outline_frame(render3d_st)
|
||||
|
|
@ -196,7 +196,7 @@ function r3d_frame(render3d_st: mut Render3dState, time: float) -> void {
|
|||
# camera that moves while the hiker stands still from a picture that shakes on its own
|
||||
if render3d_st.r3d_cam_log < 0 { render3d_st.r3d_cam_log = 0; if r3d_env_has(render3d_st, "R3D_CAM_LOG") { render3d_st.r3d_cam_log = 1 } }
|
||||
if render3d_st.r3d_cam_log == 1 {
|
||||
print(`cam {render3d_st.r3d_test_frame} pos {int(render3d_st.cam_pos[0] * 1000.0)} {int(render3d_st.cam_pos[1] * 1000.0)} {int(render3d_st.cam_pos[2] * 1000.0)} yaw {int(render3d_st.cam_yaw * 1000.0)} pitch {int(render3d_st.cam_pitch * 1000.0)} jitter {int(render3d_st.gsl_jitter_x * 1000000.0)} {int(render3d_st.gsl_jitter_y * 1000000.0)} render {render3d_st.post_w}x{render3d_st.post_h} reset {render3d_st.gsl_reset} evalok {render3d_st.gsl_eval_ok} fresh {render3d_st.gsl_fresh}`)
|
||||
r3d_say_test_frame(render3d_st)
|
||||
}
|
||||
# the height-field shadow rebakes as the light moves in steps (daylight), or with the sky yaw when there is no clock
|
||||
if not render3d_st.r3d_plate and ((not render3d_st.day_on and render3d_st.ter_shadow_yaw != render3d_st.sky_yaw) or render3d_st.ter_shadow_gen != render3d_st.day_gen) {
|
||||
|
|
@ -285,3 +285,9 @@ function r3d_frame(render3d_st: mut Render3dState, time: float) -> void {
|
|||
prof_collect(render3d_st)
|
||||
gpu_check(render3d_st, "frame")
|
||||
}
|
||||
|
||||
# messages, each built in a function of its own so the path that says it holds no allocation
|
||||
@alloc_ok("a message, built only when it is said: a failure, a warning or a debug switch")
|
||||
function r3d_say_resized() -> void { print(`r3d: resized to {gl_width()}x{gl_height()}`) }
|
||||
@alloc_ok("a message, built only when it is said: a failure, a warning or a debug switch")
|
||||
function r3d_say_test_frame(render3d_st: Render3dState) -> void { print(`cam {render3d_st.r3d_test_frame} pos {int(render3d_st.cam_pos[0] * 1000.0)} {int(render3d_st.cam_pos[1] * 1000.0)} {int(render3d_st.cam_pos[2] * 1000.0)} yaw {int(render3d_st.cam_yaw * 1000.0)} pitch {int(render3d_st.cam_pitch * 1000.0)} jitter {int(render3d_st.gsl_jitter_x * 1000000.0)} {int(render3d_st.gsl_jitter_y * 1000000.0)} render {render3d_st.post_w}x{render3d_st.post_h} reset {render3d_st.gsl_reset} evalok {render3d_st.gsl_eval_ok} fresh {render3d_st.gsl_fresh}`) }
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ function shadow_set_res(render3d_st: mut Render3dState, r: int) -> void {
|
|||
# that is refused now, rather than ending with no shadow map at all
|
||||
if not gpu_tex_ok(render3d_st, render3d_st.sh_tex) {
|
||||
render3d_st.shadow_refused = r
|
||||
print(`r3d: shadows: no memory for {r} x {r} cascades; keeping {was}`)
|
||||
shadow_say_no_memory(r, was)
|
||||
var size = was
|
||||
render3d_st.shadow_res = size
|
||||
gpu_tex_free(render3d_st, render3d_st.sh_tex)
|
||||
|
|
@ -283,3 +283,7 @@ function shadow_debug_range(render3d_st: mut Render3dState, prog: int) -> void {
|
|||
render3d_st.sh_printed3 = true
|
||||
print(`range {fixed(render3d_st.sh_range[0])} {fixed(render3d_st.sh_range[1])} {fixed(render3d_st.sh_range[2])} {fixed(render3d_st.sh_range[3])} texel*1000 {fixed(render3d_st.sh_texel[0] * 1000.0)} {fixed(render3d_st.sh_texel[1] * 1000.0)} {fixed(render3d_st.sh_texel[2] * 1000.0)} {fixed(render3d_st.sh_texel[3] * 1000.0)} locs {gpu_uniform(render3d_st, prog, "u_cascade_range")} {gpu_uniform(render3d_st, prog, "u_cascade_texel")}`)
|
||||
}
|
||||
|
||||
# messages, each built in a function of its own so the path that says it holds no allocation
|
||||
@alloc_ok("a message, built only when it is said: a failure, a warning or a debug switch")
|
||||
function shadow_say_no_memory(r: int, was: int) -> void { print(`r3d: shadows: no memory for {r} x {r} cascades; keeping {was}`) }
|
||||
|
|
|
|||
|
|
@ -254,7 +254,7 @@ function stream_update(render3d_st: mut Render3dState, s: Stream, cam_x: float,
|
|||
let dt = gl_now_us() - t0
|
||||
render3d_st.stream_us_gen = render3d_st.stream_us_gen + dt
|
||||
prof_chunk(render3d_st, s.kind, band, c.count, dt)
|
||||
if render3d_st.r3d_debug and band == 0 and render3d_st.stream_debug_n < 40 { render3d_st.stream_debug_n += 1; print(`stream kind {s.kind} band {band} chunk {cx},{cz}: {c.count} instances`) }
|
||||
if render3d_st.r3d_debug and band == 0 and render3d_st.stream_debug_n < 40 { render3d_st.stream_debug_n += 1; stream_say_chunk(s.kind, band, cx, cz, c.count) }
|
||||
let need = c.count * INST_FLOATS
|
||||
if s.top + need > len(s.arena) and not render3d_st.stream_no_evict { stream_evict(render3d_st, s) }
|
||||
# If the walk in progress wants more than the cache can hold, there is nothing to
|
||||
|
|
@ -354,3 +354,7 @@ function stream_clear_all(render3d_st: mut Render3dState) -> void {
|
|||
let all = render3d_st.stream_all
|
||||
List.clear(all)
|
||||
}
|
||||
|
||||
# messages, each built in a function of its own so the path that says it holds no allocation
|
||||
@alloc_ok("a message, built only when it is said: a failure, a warning or a debug switch")
|
||||
function stream_say_chunk(kind: int, band: int, cx: int, cz: int, n: int) -> void { print(`stream kind {kind} band {band} chunk {cx},{cz}: {n} instances`) }
|
||||
|
|
|
|||
|
|
@ -68,6 +68,8 @@ function gsl_boot(render3d_st: mut Render3dState) -> void {
|
|||
# After Vk.open(), before vkCreateInstance.
|
||||
@alloc_ok("start-up: the device, its tables, the programs, the passes and the world's first textures are made once, before play")
|
||||
function gsl_init(render3d_st: mut Render3dState) -> void {
|
||||
# the evaluate call's structs, made once with DLSS rather than by the first frame it drew
|
||||
if render3d_st.gsl_res == null { render3d_st.gsl_res = gsl_struct(4 * 112); render3d_st.gsl_tags = gsl_struct(4 * 64); render3d_st.gsl_inputs = bytes(8) }
|
||||
if render3d_st.gsl_on or Vk.sl_active() == 0 { return }
|
||||
render3d_st.gsl_feats = gsl_struct(20)
|
||||
Vk.put_i32(render3d_st.gsl_feats, 0, GSL_DLSS); Vk.put_i32(render3d_st.gsl_feats, 4, GSL_REFLEX); Vk.put_i32(render3d_st.gsl_feats, 8, GSL_PCL)
|
||||
|
|
@ -383,7 +385,7 @@ function gsl_constants(render3d_st: mut Render3dState) -> void {
|
|||
Vk.put_i32(k, 360, float_bits(1.0)) # mvecScale
|
||||
Vk.put_i32(k, 364, float_bits(1.0))
|
||||
gsl_put_v3(k, 376, render3d_st.cam_pos)
|
||||
let up = floats(3)
|
||||
let up = render3d_st.gsl_up # made with the state
|
||||
v3_cross(up, render3d_st.cam_right, render3d_st.cam_fwd)
|
||||
gsl_put_v3(k, 388, up)
|
||||
gsl_put_v3(k, 400, render3d_st.cam_right)
|
||||
|
|
@ -397,7 +399,7 @@ function gsl_constants(render3d_st: mut Render3dState) -> void {
|
|||
# not dilated, not jittered
|
||||
if render3d_st.gsl_reset { Vk.put_i32(k, 444, 256 * 256 * 256) }
|
||||
Vk.put_i32(k, 452, float_bits(40.0)) # minRelativeLinearDepthObjectSeparation
|
||||
free(fix); free(proj); free(v2c); free(c2v); free(cur); free(prev); free(inv_cur); free(c2p); free(p2c); free(ident); free(up)
|
||||
free(fix); free(proj); free(v2c); free(c2v); free(cur); free(prev); free(inv_cur); free(c2p); free(p2c); free(ident)
|
||||
}
|
||||
|
||||
# make the DLSS targets at this frame's sizes
|
||||
|
|
@ -418,7 +420,6 @@ function gsl_targets(render3d_st: mut Render3dState) -> void {
|
|||
render3d_st.post_ldr = target_new(render3d_st, gl_width(), gl_height(), post_ldr_fmt(render3d_st), GL_RGBA, GL_UNSIGNED_BYTE, false, GL_LINEAR)
|
||||
render3d_st.post_ldr_hdr = gpu_hdr_active(render3d_st)
|
||||
}
|
||||
if render3d_st.gsl_res == null { render3d_st.gsl_res = gsl_struct(4 * 112); render3d_st.gsl_tags = gsl_struct(4 * 64); render3d_st.gsl_inputs = bytes(8) }
|
||||
}
|
||||
|
||||
# Upscale post_hdr into gsl_out; the colour the rest of post reads (post_hdr's own if it failed).
|
||||
|
|
@ -450,10 +451,14 @@ function gsl_dlss_eval(render3d_st: mut Render3dState) -> int {
|
|||
# forgetting, because every gvk_draw binds its pipeline, view and set afresh
|
||||
render3d_st.gsl_eval_ok = r == 0
|
||||
if r != 0 {
|
||||
if not render3d_st.gsl_said { print(`r3d: streamline: DLSS evaluate failed ({r}); drawing without it`); render3d_st.gsl_said = true }
|
||||
if not render3d_st.gsl_said { gsl_say_eval_failed(r); render3d_st.gsl_said = true }
|
||||
render3d_st.post_color_w = render3d_st.post_w; render3d_st.post_color_h = render3d_st.post_h
|
||||
return render3d_st.post_hdr.color
|
||||
}
|
||||
render3d_st.post_color_w = gl_width(); render3d_st.post_color_h = gl_height()
|
||||
return render3d_st.gsl_out.color
|
||||
}
|
||||
|
||||
# messages, each built in a function of its own so the path that says it holds no allocation
|
||||
@alloc_ok("a message, built only when it is said: a failure, a warning or a debug switch")
|
||||
function gsl_say_eval_failed(r: int) -> void { print(`r3d: streamline: DLSS evaluate failed ({r}); drawing without it`) }
|
||||
|
|
|
|||
|
|
@ -512,7 +512,7 @@ function terrain_sun_pass(render3d_st: mut Render3dState, w: int, h: int, depth:
|
|||
if not render3d_st.ter_sun_checked {
|
||||
render3d_st.ter_sun_checked = true
|
||||
let st = gpu_fb_status(render3d_st)
|
||||
if st != GL_FRAMEBUFFER_COMPLETE { print(`r3d: sun-visibility framebuffer incomplete {st}`) }
|
||||
if st != GL_FRAMEBUFFER_COMPLETE { terrain_say_sun_fbo(st) }
|
||||
}
|
||||
gpu_depth_test(render3d_st, true)
|
||||
gpu_depth_func(render3d_st, GL_LESS)
|
||||
|
|
@ -585,7 +585,7 @@ function terrain_draw(render3d_st: mut Render3dState) -> void {
|
|||
cdlod_select(render3d_st, CD_LEVELS - 1, 0, 0)
|
||||
if render3d_st.ter_wire { gpu_wireframe(render3d_st, false) }
|
||||
gpu_depth_func(render3d_st, GL_LESS)
|
||||
if render3d_st.r3d_debug and not render3d_st.ter_printed { render3d_st.ter_printed = true; print(`cdlod patches drawn: {render3d_st.cd_draws} (far {render3d_st.cd_far_draws}, near {render3d_st.cd_near_draws}, band {render3d_st.cd_draws - render3d_st.cd_far_draws - render3d_st.cd_near_draws})`) }
|
||||
if render3d_st.r3d_debug and not render3d_st.ter_printed { render3d_st.ter_printed = true; terrain_say_patches(render3d_st) }
|
||||
}
|
||||
|
||||
# ---- CDLOD --------------------------------------------------------------------------
|
||||
|
|
@ -792,3 +792,9 @@ function terrain_reload(render3d_st: mut Render3dState, dem: string, emin: float
|
|||
function ter_scratch(render3d_st: mut Render3dState) -> floats {
|
||||
return render3d_st.ter_scr
|
||||
}
|
||||
|
||||
# messages, each built in a function of its own so the path that says it holds no allocation
|
||||
@alloc_ok("a message, built only when it is said: a failure, a warning or a debug switch")
|
||||
function terrain_say_sun_fbo(st: int) -> void { print(`r3d: sun-visibility framebuffer incomplete {st}`) }
|
||||
@alloc_ok("a message, built only when it is said: a failure, a warning or a debug switch")
|
||||
function terrain_say_patches(render3d_st: Render3dState) -> void { print(`cdlod patches drawn: {render3d_st.cd_draws} (far {render3d_st.cd_far_draws}, near {render3d_st.cd_near_draws}, band {render3d_st.cd_draws - render3d_st.cd_far_draws - render3d_st.cd_near_draws})`) }
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ function water_reflect_visible(render3d_st: mut Render3dState) -> bool {
|
|||
var seen = 0
|
||||
var hidden = 0
|
||||
for i in 0 .. render3d_st.wb_ncells { if wb_cell_visible(render3d_st, i) { seen += 1; if wb_cell_occluded(render3d_st, i) { hidden += 1 } } }
|
||||
print(`water reflection test: {render3d_st.wb_ncells} wet rectangles in {render3d_st.wb_nblocks} blocks (built in {render3d_st.wb_build_us} us), {seen} in view, {hidden} of them behind the ground`)
|
||||
water_say_test(render3d_st, seen, hidden)
|
||||
}
|
||||
# A rectangle in the frustum can still be behind the ground or dry where it shows: standing on a shore
|
||||
# above the lake and looking down at your feet puts water inside the view and none of it on screen.
|
||||
|
|
@ -366,3 +366,7 @@ function water_draw(render3d_st: mut Render3dState, depth_tex: int) -> void {
|
|||
}
|
||||
gpu_blend(render3d_st, false)
|
||||
}
|
||||
|
||||
# messages, each built in a function of its own so the path that says it holds no allocation
|
||||
@alloc_ok("a message, built only when it is said: a failure, a warning or a debug switch")
|
||||
function water_say_test(render3d_st: Render3dState, seen: int, hidden: int) -> void { print(`water reflection test: {render3d_st.wb_ncells} wet rectangles in {render3d_st.wb_nblocks} blocks (built in {render3d_st.wb_build_us} us), {seen} in view, {hidden} of them behind the ground`) }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue