wip: uncommitted work gathered before the branch is merged into main
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
cc384efee0
commit
737d6e1859
30 changed files with 307 additions and 120 deletions
|
|
@ -192,7 +192,7 @@ program Smooth {
|
||||||
handler Draw(render3d_st: mut Render3dState, smooth_st: mut SmoothState) phase Render {
|
handler Draw(render3d_st: mut Render3dState, smooth_st: mut SmoothState) phase Render {
|
||||||
r3d_frame(render3d_st, float(Time.elapsed()))
|
r3d_frame(render3d_st, float(Time.elapsed()))
|
||||||
smooth_st.frame += 1
|
smooth_st.frame += 1
|
||||||
if smooth_st.frame == smooth_st.shot_at { Gl.screenshot(path: "build/smooth.ppm") }
|
if smooth_st.frame == smooth_st.shot_at { r3d_screenshot(render3d_st, "build/smooth.ppm") }
|
||||||
Gl.swap()
|
r3d_present(render3d_st)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -189,6 +189,9 @@ export state Render3dState {
|
||||||
gvk_pool: long = 0
|
gvk_pool: long = 0
|
||||||
gvk_fence: bytes = null
|
gvk_fence: bytes = null
|
||||||
gvk_frame_fence: bytes = null # the presented frame still on the GPU (one frame in flight)
|
gvk_frame_fence: bytes = null # the presented frame still on the GPU (one frame in flight)
|
||||||
|
gvk_tmp_buf: pointer = null # the per-call scratch ring (gvk_tmp)
|
||||||
|
gvk_tmp_off: int = 0
|
||||||
|
gvk_seen: words = null # gvk_draw's vertex buffers already bound, reused
|
||||||
gvk_frame_pending: bool = false
|
gvk_frame_pending: bool = false
|
||||||
gvk_frame_pending_cb: pointer = null
|
gvk_frame_pending_cb: pointer = null
|
||||||
gvk_frame_pending_no: int = -1 # which frame it is (gvk_frame_no when it was submitted)
|
gvk_frame_pending_no: int = -1 # which frame it is (gvk_frame_no when it was submitted)
|
||||||
|
|
@ -197,6 +200,20 @@ export state Render3dState {
|
||||||
gvk_retired_frame: []int = null # the last frame that read each retired buffer
|
gvk_retired_frame: []int = null # the last frame that read each retired buffer
|
||||||
gvk_labels: bool = false # R3D_VK_LABELS: each profiled pass is a debug label (Metal System Trace)
|
gvk_labels: bool = false # R3D_VK_LABELS: each profiled pass is a debug label (Metal System Trace)
|
||||||
gvk_inflight: int = -1
|
gvk_inflight: int = -1
|
||||||
|
gvk_nopool: bool = false
|
||||||
|
# R3D_VK_PROF: Vulkan objects made and destroyed, reported every 120 frames
|
||||||
|
gvk_mk_img: int = 0
|
||||||
|
gvk_mk_view: int = 0
|
||||||
|
gvk_mk_buf: int = 0
|
||||||
|
gvk_mk_mem: int = 0
|
||||||
|
gvk_mk_smp: int = 0
|
||||||
|
gvk_mk_set: int = 0
|
||||||
|
gvk_mk_cmd: int = 0
|
||||||
|
gvk_mk_dpool: int = 0
|
||||||
|
gvk_mk_x_img: int = 0
|
||||||
|
gvk_mk_x_view: int = 0
|
||||||
|
gvk_mk_x_buf: int = 0
|
||||||
|
gvk_mk_x_mem: int = 0
|
||||||
gvk_label_depth: int = 0 # -1 until asked: 1 leaves the presented frame in flight
|
gvk_label_depth: int = 0 # -1 until asked: 1 leaves the presented frame in flight
|
||||||
gvk_has_hqr: bool = false
|
gvk_has_hqr: bool = false
|
||||||
gvk_ts_period: float = 0.0 # float bits: nanoseconds per timestamp tick
|
gvk_ts_period: float = 0.0 # float bits: nanoseconds per timestamp tick
|
||||||
|
|
@ -269,8 +286,9 @@ export state Render3dState {
|
||||||
gvk_screen_depth: int = 0
|
gvk_screen_depth: int = 0
|
||||||
gvk_screen_w: int = 0
|
gvk_screen_w: int = 0
|
||||||
gvk_screen_h: int = 0
|
gvk_screen_h: int = 0
|
||||||
gvk_layer_views: []string = null # "tex:layer" -> index into gvk_layer_view
|
gvk_layer_views: []int = null # generation * 4096 + layer, beside gvk_layer_view_tex
|
||||||
gvk_layer_view: []long = null
|
gvk_layer_view: []long = null
|
||||||
|
gvk_layer_view_tex: []int = null # the texture each cached view is of, so a release drops them
|
||||||
gvk_fb_ncolor: words = null # per framebuffer: colour slots drawn (draw buffers; 0 = none)
|
gvk_fb_ncolor: words = null # per framebuffer: colour slots drawn (draw buffers; 0 = none)
|
||||||
gvk_hdr_want: bool = false # r3d_hdr: the setting
|
gvk_hdr_want: bool = false # r3d_hdr: the setting
|
||||||
gvk_hdr_on: bool = false # the swapchain is HDR10 now
|
gvk_hdr_on: bool = false # the swapchain is HDR10 now
|
||||||
|
|
@ -377,6 +395,11 @@ export state Render3dState {
|
||||||
gg_mesh: []Mesh = null
|
gg_mesh: []Mesh = null
|
||||||
gg_n: int = 0
|
gg_n: int = 0
|
||||||
gg_max: int = 0
|
gg_max: int = 0
|
||||||
|
gg_rb: words = null # the per-frame dispatch arguments, made once (grass_gpu.ludic)
|
||||||
|
gg_cb: words = null
|
||||||
|
gg_bufs: words = null
|
||||||
|
gg_texs: words = null
|
||||||
|
gg_pr: words = null
|
||||||
grass_band_mesh: []Mesh = null # per band: the blade it draws (rows fall with distance)
|
grass_band_mesh: []Mesh = null # per band: the blade it draws (rows fall with distance)
|
||||||
grass_mesh3: Mesh = null # three rows: the middle distance
|
grass_mesh3: Mesh = null # three rows: the middle distance
|
||||||
grass_mesh2: Mesh = null # two rows, one quad: far enough that the arch is under a pixel
|
grass_mesh2: Mesh = null # two rows, one quad: far enough that the arch is under a pixel
|
||||||
|
|
|
||||||
|
|
@ -201,7 +201,7 @@ function gpu_query_new(render3d_st: mut Render3dState, n: int, ids: words) -> vo
|
||||||
function gpu_query_begin(render3d_st: mut Render3dState, id: int) -> void { if render3d_st.gpu_kind == GPU_VK { gvk_query_begin(render3d_st, id); return }; gl_begin_query(GL_TIME_ELAPSED, id) }
|
function gpu_query_begin(render3d_st: mut Render3dState, id: int) -> void { if render3d_st.gpu_kind == GPU_VK { gvk_query_begin(render3d_st, id); return }; gl_begin_query(GL_TIME_ELAPSED, id) }
|
||||||
function gpu_query_end(render3d_st: mut Render3dState) -> void { if render3d_st.gpu_kind == GPU_VK { gvk_query_end(render3d_st); return }; gl_end_query(GL_TIME_ELAPSED) }
|
function gpu_query_end(render3d_st: mut Render3dState) -> void { if render3d_st.gpu_kind == GPU_VK { gvk_query_end(render3d_st); return }; gl_end_query(GL_TIME_ELAPSED) }
|
||||||
# true once the query has its result; the nanoseconds (low 32 bits) are then in out[0]
|
# true once the query has its result; the nanoseconds (low 32 bits) are then in out[0]
|
||||||
function gpu_query_result(render3d_st: Render3dState, id: int, out: words) -> bool {
|
function gpu_query_result(render3d_st: mut Render3dState, id: int, out: words) -> bool {
|
||||||
if render3d_st.gpu_kind == GPU_VK { return gvk_query_result(render3d_st, id, out) }
|
if render3d_st.gpu_kind == GPU_VK { return gvk_query_result(render3d_st, id, out) }
|
||||||
gl_get_query_objectiv(id, GL_QUERY_RESULT_AVAILABLE, out)
|
gl_get_query_objectiv(id, GL_QUERY_RESULT_AVAILABLE, out)
|
||||||
if out[0] == 0 { return false }
|
if out[0] == 0 { return false }
|
||||||
|
|
|
||||||
|
|
@ -298,6 +298,7 @@ function gvk_alloc(render3d_st: mut Render3dState, req: bytes, want: int) -> lon
|
||||||
Vk.put_i64(mai, VkMemoryAllocateInfo_allocationSize, Vk.get_i64(req, VkMemoryRequirements_size))
|
Vk.put_i64(mai, VkMemoryAllocateInfo_allocationSize, Vk.get_i64(req, VkMemoryRequirements_size))
|
||||||
Vk.put_i32(mai, VkMemoryAllocateInfo_memoryTypeIndex, t)
|
Vk.put_i32(mai, VkMemoryAllocateInfo_memoryTypeIndex, t)
|
||||||
let out = bytes(8)
|
let out = bytes(8)
|
||||||
|
render3d_st.gvk_mk_mem += 1
|
||||||
let r = Vk.allocate_memory(render3d_st.gvk_dev, mai, null, out)
|
let r = Vk.allocate_memory(render3d_st.gvk_dev, mai, null, out)
|
||||||
if r != VK_SUCCESS { print(`r3d: vulkan: vkAllocateMemory failed (VkResult {r})`); return zero }
|
if r != VK_SUCCESS { print(`r3d: vulkan: vkAllocateMemory failed (VkResult {r})`); return zero }
|
||||||
render3d_st.gvk_n_allocs += 1
|
render3d_st.gvk_n_allocs += 1
|
||||||
|
|
@ -338,6 +339,7 @@ function gvk_mem_raw(render3d_st: mut Render3dState, t: int, size: int, host: bo
|
||||||
Vk.put_i64(mai, VkMemoryAllocateInfo_allocationSize, size_l)
|
Vk.put_i64(mai, VkMemoryAllocateInfo_allocationSize, size_l)
|
||||||
Vk.put_i32(mai, VkMemoryAllocateInfo_memoryTypeIndex, t)
|
Vk.put_i32(mai, VkMemoryAllocateInfo_memoryTypeIndex, t)
|
||||||
let out = bytes(8)
|
let out = bytes(8)
|
||||||
|
render3d_st.gvk_mk_mem += 1
|
||||||
let r = Vk.allocate_memory(render3d_st.gvk_dev, mai, null, out)
|
let r = Vk.allocate_memory(render3d_st.gvk_dev, mai, null, out)
|
||||||
if r != VK_SUCCESS { gvk_note(render3d_st, `r3d: vulkan: vkAllocateMemory of {size} bytes failed (VkResult {r}, {render3d_st.gvk_n_allocs} allocations live)`); return zero }
|
if r != VK_SUCCESS { gvk_note(render3d_st, `r3d: vulkan: vkAllocateMemory of {size} bytes failed (VkResult {r}, {render3d_st.gvk_n_allocs} allocations live)`); return zero }
|
||||||
render3d_st.gvk_n_allocs += 1
|
render3d_st.gvk_n_allocs += 1
|
||||||
|
|
@ -447,6 +449,7 @@ function gvk_mem_free(render3d_st: mut Render3dState, a: int) -> void {
|
||||||
let zero: long = 0
|
let zero: long = 0
|
||||||
if b < 0 {
|
if b < 0 {
|
||||||
if render3d_st.gvk_al_map[a] != null { Vk.unmap_memory(render3d_st.gvk_dev, render3d_st.gvk_al_mem[a]) }
|
if render3d_st.gvk_al_map[a] != null { Vk.unmap_memory(render3d_st.gvk_dev, render3d_st.gvk_al_mem[a]) }
|
||||||
|
render3d_st.gvk_mk_x_mem += 1
|
||||||
Vk.free_memory(render3d_st.gvk_dev, render3d_st.gvk_al_mem[a], null)
|
Vk.free_memory(render3d_st.gvk_dev, render3d_st.gvk_al_mem[a], null)
|
||||||
render3d_st.gvk_n_allocs -= 1
|
render3d_st.gvk_n_allocs -= 1
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -466,6 +469,7 @@ function gvk_mem_free(render3d_st: mut Render3dState, a: int) -> void {
|
||||||
if off == 0 and n == render3d_st.gvk_blk_size[b] {
|
if off == 0 and n == render3d_st.gvk_blk_size[b] {
|
||||||
# the block is empty again: give it back, or a world swapped out keeps its memory for good
|
# the block is empty again: give it back, or a world swapped out keeps its memory for good
|
||||||
if render3d_st.gvk_blk_map[b] != null { Vk.unmap_memory(render3d_st.gvk_dev, render3d_st.gvk_blk_mem[b]) }
|
if render3d_st.gvk_blk_map[b] != null { Vk.unmap_memory(render3d_st.gvk_dev, render3d_st.gvk_blk_mem[b]) }
|
||||||
|
render3d_st.gvk_mk_x_mem += 1
|
||||||
Vk.free_memory(render3d_st.gvk_dev, render3d_st.gvk_blk_mem[b], null)
|
Vk.free_memory(render3d_st.gvk_dev, render3d_st.gvk_blk_mem[b], null)
|
||||||
render3d_st.gvk_n_allocs -= 1
|
render3d_st.gvk_n_allocs -= 1
|
||||||
render3d_st.gvk_blk_mem[b] = zero; render3d_st.gvk_blk_map[b] = null; render3d_st.gvk_blk_kind[b] = -1; render3d_st.gvk_blk_size[b] = 0
|
render3d_st.gvk_blk_mem[b] = zero; render3d_st.gvk_blk_map[b] = null; render3d_st.gvk_blk_kind[b] = -1; render3d_st.gvk_blk_size[b] = 0
|
||||||
|
|
@ -503,17 +507,35 @@ function gvk_cmd_init(render3d_st: mut Render3dState) -> bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
# a command buffer, begun
|
# a command buffer, begun
|
||||||
function gvk_once_begin(render3d_st: Render3dState) -> pointer {
|
# ---- scratch -------------------------------------------------------------------------------
|
||||||
let cbai = bytes(VkCommandBufferAllocateInfo_sizeof)
|
# The structs a Vulkan call reads are copied before it returns, so the ones built for a draw, a
|
||||||
|
# pass, a barrier or a submit need not outlive it. They were each a bytes() - a malloc nothing
|
||||||
|
# freed, several per draw: about 0.5 MB a frame, and one windowed run grew past 150 GB. They
|
||||||
|
# come from this ring instead: one block, handed out in order and wrapped when it is used up.
|
||||||
|
const GVK_TMP_BYTES: int = 1048576
|
||||||
|
|
||||||
|
function gvk_tmp(render3d_st: mut Render3dState, n: int) -> pointer {
|
||||||
|
if render3d_st.gvk_tmp_buf == null { render3d_st.gvk_tmp_buf = bytes(GVK_TMP_BYTES) }
|
||||||
|
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 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
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
function gvk_once_begin(render3d_st: mut Render3dState) -> pointer {
|
||||||
|
let cbai = gvk_tmp(render3d_st, VkCommandBufferAllocateInfo_sizeof)
|
||||||
Vk.zero(cbai, VkCommandBufferAllocateInfo_sizeof)
|
Vk.zero(cbai, VkCommandBufferAllocateInfo_sizeof)
|
||||||
Vk.put_i32(cbai, VkCommandBufferAllocateInfo_sType, VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO)
|
Vk.put_i32(cbai, VkCommandBufferAllocateInfo_sType, VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO)
|
||||||
Vk.put_i64(cbai, VkCommandBufferAllocateInfo_commandPool, render3d_st.gvk_pool)
|
Vk.put_i64(cbai, VkCommandBufferAllocateInfo_commandPool, render3d_st.gvk_pool)
|
||||||
Vk.put_i32(cbai, VkCommandBufferAllocateInfo_level, VK_COMMAND_BUFFER_LEVEL_PRIMARY)
|
Vk.put_i32(cbai, VkCommandBufferAllocateInfo_level, VK_COMMAND_BUFFER_LEVEL_PRIMARY)
|
||||||
Vk.put_i32(cbai, VkCommandBufferAllocateInfo_commandBufferCount, 1)
|
Vk.put_i32(cbai, VkCommandBufferAllocateInfo_commandBufferCount, 1)
|
||||||
let cbs = bytes(8)
|
let cbs = gvk_tmp(render3d_st, 8)
|
||||||
|
render3d_st.gvk_mk_cmd += 1
|
||||||
if Vk.allocate_command_buffers(render3d_st.gvk_dev, cbai, cbs) != VK_SUCCESS { return null }
|
if Vk.allocate_command_buffers(render3d_st.gvk_dev, cbai, cbs) != VK_SUCCESS { return null }
|
||||||
let cb = Vk.get_ptr(cbs, 0)
|
let cb = Vk.get_ptr(cbs, 0)
|
||||||
let cbbi = bytes(VkCommandBufferBeginInfo_sizeof)
|
let cbbi = gvk_tmp(render3d_st, VkCommandBufferBeginInfo_sizeof)
|
||||||
Vk.zero(cbbi, VkCommandBufferBeginInfo_sizeof)
|
Vk.zero(cbbi, VkCommandBufferBeginInfo_sizeof)
|
||||||
Vk.put_i32(cbbi, VkCommandBufferBeginInfo_sType, VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO)
|
Vk.put_i32(cbbi, VkCommandBufferBeginInfo_sType, VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO)
|
||||||
Vk.put_i32(cbbi, VkCommandBufferBeginInfo_flags, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT)
|
Vk.put_i32(cbbi, VkCommandBufferBeginInfo_flags, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT)
|
||||||
|
|
@ -525,10 +547,10 @@ function gvk_once_end(render3d_st: mut Render3dState, cb: pointer) -> bool {
|
||||||
gvk_frame_wait(render3d_st)
|
gvk_frame_wait(render3d_st)
|
||||||
var r = Vk.end_command_buffer(cb)
|
var r = Vk.end_command_buffer(cb)
|
||||||
if r != VK_SUCCESS { return gvk_fail(render3d_st, "vkEndCommandBuffer", r) }
|
if r != VK_SUCCESS { return gvk_fail(render3d_st, "vkEndCommandBuffer", r) }
|
||||||
let cbs = bytes(8)
|
let cbs = gvk_tmp(render3d_st, 8)
|
||||||
Vk.put_ptr(cbs, 0, cb)
|
Vk.put_ptr(cbs, 0, cb)
|
||||||
Vk.reset_fences(render3d_st.gvk_dev, 1, render3d_st.gvk_fence)
|
Vk.reset_fences(render3d_st.gvk_dev, 1, render3d_st.gvk_fence)
|
||||||
let si = bytes(VkSubmitInfo_sizeof)
|
let si = gvk_tmp(render3d_st, VkSubmitInfo_sizeof)
|
||||||
Vk.zero(si, VkSubmitInfo_sizeof)
|
Vk.zero(si, VkSubmitInfo_sizeof)
|
||||||
Vk.put_i32(si, VkSubmitInfo_sType, VK_STRUCTURE_TYPE_SUBMIT_INFO)
|
Vk.put_i32(si, VkSubmitInfo_sType, VK_STRUCTURE_TYPE_SUBMIT_INFO)
|
||||||
Vk.put_i32(si, VkSubmitInfo_commandBufferCount, 1)
|
Vk.put_i32(si, VkSubmitInfo_commandBufferCount, 1)
|
||||||
|
|
@ -556,6 +578,7 @@ function gvk_inflight_on(render3d_st: mut Render3dState) -> bool {
|
||||||
if render3d_st.gvk_inflight < 0 {
|
if render3d_st.gvk_inflight < 0 {
|
||||||
render3d_st.gvk_inflight = 0
|
render3d_st.gvk_inflight = 0
|
||||||
if Os.platform() == "macos" { render3d_st.gvk_inflight = 1 }
|
if Os.platform() == "macos" { render3d_st.gvk_inflight = 1 }
|
||||||
|
render3d_st.gvk_nopool = r3d_env_has(render3d_st, "R3D_VK_NOPOOL")
|
||||||
if r3d_env_has(render3d_st, "R3D_VK_INFLIGHT") { render3d_st.gvk_inflight = Text.to_int(r3d_env(render3d_st, "R3D_VK_INFLIGHT")) }
|
if r3d_env_has(render3d_st, "R3D_VK_INFLIGHT") { render3d_st.gvk_inflight = Text.to_int(r3d_env(render3d_st, "R3D_VK_INFLIGHT")) }
|
||||||
}
|
}
|
||||||
return render3d_st.gvk_inflight == 1
|
return render3d_st.gvk_inflight == 1
|
||||||
|
|
@ -565,10 +588,10 @@ function gvk_frame_submit(render3d_st: mut Render3dState, cb: pointer) -> bool {
|
||||||
gvk_frame_wait(render3d_st)
|
gvk_frame_wait(render3d_st)
|
||||||
var r = Vk.end_command_buffer(cb)
|
var r = Vk.end_command_buffer(cb)
|
||||||
if r != VK_SUCCESS { return gvk_fail(render3d_st, "vkEndCommandBuffer", r) }
|
if r != VK_SUCCESS { return gvk_fail(render3d_st, "vkEndCommandBuffer", r) }
|
||||||
let cbs = bytes(8)
|
let cbs = gvk_tmp(render3d_st, 8)
|
||||||
Vk.put_ptr(cbs, 0, cb)
|
Vk.put_ptr(cbs, 0, cb)
|
||||||
Vk.reset_fences(render3d_st.gvk_dev, 1, render3d_st.gvk_frame_fence)
|
Vk.reset_fences(render3d_st.gvk_dev, 1, render3d_st.gvk_frame_fence)
|
||||||
let si = bytes(VkSubmitInfo_sizeof)
|
let si = gvk_tmp(render3d_st, VkSubmitInfo_sizeof)
|
||||||
Vk.zero(si, VkSubmitInfo_sizeof)
|
Vk.zero(si, VkSubmitInfo_sizeof)
|
||||||
Vk.put_i32(si, VkSubmitInfo_sType, VK_STRUCTURE_TYPE_SUBMIT_INFO)
|
Vk.put_i32(si, VkSubmitInfo_sType, VK_STRUCTURE_TYPE_SUBMIT_INFO)
|
||||||
Vk.put_i32(si, VkSubmitInfo_commandBufferCount, 1)
|
Vk.put_i32(si, VkSubmitInfo_commandBufferCount, 1)
|
||||||
|
|
@ -585,7 +608,7 @@ function gvk_frame_wait(render3d_st: mut Render3dState) -> void {
|
||||||
if not render3d_st.gvk_frame_pending { return }
|
if not render3d_st.gvk_frame_pending { return }
|
||||||
let forever: long = -1
|
let forever: long = -1
|
||||||
Vk.wait_for_fences(render3d_st.gvk_dev, 1, render3d_st.gvk_frame_fence, 1, forever)
|
Vk.wait_for_fences(render3d_st.gvk_dev, 1, render3d_st.gvk_frame_fence, 1, forever)
|
||||||
let cbs = bytes(8)
|
let cbs = gvk_tmp(render3d_st, 8)
|
||||||
Vk.put_ptr(cbs, 0, render3d_st.gvk_frame_pending_cb)
|
Vk.put_ptr(cbs, 0, render3d_st.gvk_frame_pending_cb)
|
||||||
Vk.free_command_buffers(render3d_st.gvk_dev, render3d_st.gvk_pool, 1, cbs)
|
Vk.free_command_buffers(render3d_st.gvk_dev, render3d_st.gvk_pool, 1, cbs)
|
||||||
render3d_st.gvk_frame_pending = false
|
render3d_st.gvk_frame_pending = false
|
||||||
|
|
@ -636,9 +659,9 @@ function gvk_query_end(render3d_st: mut Render3dState) -> void {
|
||||||
Vk.cmd_write_timestamp(gvk_frame_cb(render3d_st), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, render3d_st.gvk_qpool, render3d_st.gvk_q_active * 2 + 1)
|
Vk.cmd_write_timestamp(gvk_frame_cb(render3d_st), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, render3d_st.gvk_qpool, render3d_st.gvk_q_active * 2 + 1)
|
||||||
render3d_st.gvk_q_active = -1
|
render3d_st.gvk_q_active = -1
|
||||||
}
|
}
|
||||||
function gvk_query_result(render3d_st: Render3dState, id: int, out: words) -> bool {
|
function gvk_query_result(render3d_st: mut Render3dState, id: int, out: words) -> bool {
|
||||||
if render3d_st.gvk_qpool == 0 { return false }
|
if render3d_st.gvk_qpool == 0 { return false }
|
||||||
let data = bytes(16)
|
let data = gvk_tmp(render3d_st, 16)
|
||||||
let size: long = 16
|
let size: long = 16
|
||||||
let stride: long = 8
|
let stride: long = 8
|
||||||
if Vk.get_query_pool_results(render3d_st.gvk_dev, render3d_st.gvk_qpool, id * 2, 2, size, data, stride, VK_QUERY_RESULT_64_BIT) != VK_SUCCESS { return false }
|
if Vk.get_query_pool_results(render3d_st.gvk_dev, render3d_st.gvk_qpool, id * 2, 2, size, data, stride, VK_QUERY_RESULT_64_BIT) != VK_SUCCESS { return false }
|
||||||
|
|
@ -653,7 +676,7 @@ function gvk_label_begin(render3d_st: mut Render3dState, name: pointer) -> void
|
||||||
# only inside a frame: a pass the load profiles comes before the frame's pools exist
|
# only inside a frame: a pass the load profiles comes before the frame's pools exist
|
||||||
if render3d_st.gpu_kind != GPU_VK or render3d_st.gvk_cb == null { return }
|
if render3d_st.gpu_kind != GPU_VK or render3d_st.gvk_cb == null { return }
|
||||||
let cb = render3d_st.gvk_cb
|
let cb = render3d_st.gvk_cb
|
||||||
let li = bytes(VkDebugUtilsLabelEXT_sizeof)
|
let li = gvk_tmp(render3d_st, VkDebugUtilsLabelEXT_sizeof)
|
||||||
Vk.zero(li, VkDebugUtilsLabelEXT_sizeof)
|
Vk.zero(li, VkDebugUtilsLabelEXT_sizeof)
|
||||||
Vk.put_i32(li, VkDebugUtilsLabelEXT_sType, VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT)
|
Vk.put_i32(li, VkDebugUtilsLabelEXT_sType, VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT)
|
||||||
Vk.put_ptr(li, VkDebugUtilsLabelEXT_pLabelName, name)
|
Vk.put_ptr(li, VkDebugUtilsLabelEXT_pLabelName, name)
|
||||||
|
|
|
||||||
|
|
@ -195,15 +195,16 @@ function gvk_dispatch_tex(render3d_st: mut Render3dState, c: int, params: pointe
|
||||||
let nb = render3d_st.gvk_cp_nbuf[c]
|
let nb = render3d_st.gvk_cp_nbuf[c]
|
||||||
var nt = 0
|
var nt = 0
|
||||||
if render3d_st.gvk_cp_ntex != null and c < len(render3d_st.gvk_cp_ntex) { nt = render3d_st.gvk_cp_ntex[c] }
|
if render3d_st.gvk_cp_ntex != null and c < len(render3d_st.gvk_cp_ntex) { nt = render3d_st.gvk_cp_ntex[c] }
|
||||||
let dsai = bytes(VkDescriptorSetAllocateInfo_sizeof)
|
let dsai = gvk_tmp(render3d_st, VkDescriptorSetAllocateInfo_sizeof)
|
||||||
Vk.zero(dsai, VkDescriptorSetAllocateInfo_sizeof)
|
Vk.zero(dsai, VkDescriptorSetAllocateInfo_sizeof)
|
||||||
Vk.put_i32(dsai, VkDescriptorSetAllocateInfo_sType, VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO)
|
Vk.put_i32(dsai, VkDescriptorSetAllocateInfo_sType, VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO)
|
||||||
Vk.put_i64(dsai, VkDescriptorSetAllocateInfo_descriptorPool, render3d_st.gvk_dpool)
|
Vk.put_i64(dsai, VkDescriptorSetAllocateInfo_descriptorPool, render3d_st.gvk_dpool)
|
||||||
Vk.put_i32(dsai, VkDescriptorSetAllocateInfo_descriptorSetCount, 1)
|
Vk.put_i32(dsai, VkDescriptorSetAllocateInfo_descriptorSetCount, 1)
|
||||||
let layouts = bytes(8)
|
let layouts = gvk_tmp(render3d_st, 8)
|
||||||
Vk.put_i64(layouts, 0, render3d_st.gvk_cp_dsl[c])
|
Vk.put_i64(layouts, 0, render3d_st.gvk_cp_dsl[c])
|
||||||
Vk.put_ptr(dsai, VkDescriptorSetAllocateInfo_pSetLayouts, layouts)
|
Vk.put_ptr(dsai, VkDescriptorSetAllocateInfo_pSetLayouts, layouts)
|
||||||
let sets = bytes(8)
|
let sets = gvk_tmp(render3d_st, 8)
|
||||||
|
render3d_st.gvk_mk_set += 1
|
||||||
let r = Vk.allocate_descriptor_sets(render3d_st.gvk_dev, dsai, sets)
|
let r = Vk.allocate_descriptor_sets(render3d_st.gvk_dev, dsai, sets)
|
||||||
if r != VK_SUCCESS { gvk_fail(render3d_st, "vkAllocateDescriptorSets (compute)", r); return }
|
if r != VK_SUCCESS { gvk_fail(render3d_st, "vkAllocateDescriptorSets (compute)", r); return }
|
||||||
let set = Vk.get_i64(sets, 0)
|
let set = Vk.get_i64(sets, 0)
|
||||||
|
|
@ -212,11 +213,11 @@ function gvk_dispatch_tex(render3d_st: mut Render3dState, c: int, params: pointe
|
||||||
let ww = VkWriteDescriptorSet_sizeof
|
let ww = VkWriteDescriptorSet_sizeof
|
||||||
let bw = VkDescriptorBufferInfo_sizeof
|
let bw = VkDescriptorBufferInfo_sizeof
|
||||||
let iw = VkDescriptorImageInfo_sizeof
|
let iw = VkDescriptorImageInfo_sizeof
|
||||||
let writes = bytes(ww * (nb + 1 + nt))
|
let writes = gvk_tmp(render3d_st, ww * (nb + 1 + nt))
|
||||||
Vk.zero(writes, ww * (nb + 1 + nt))
|
Vk.zero(writes, ww * (nb + 1 + nt))
|
||||||
let infos = bytes(bw * (nb + 1))
|
let infos = gvk_tmp(render3d_st, bw * (nb + 1))
|
||||||
Vk.zero(infos, bw * (nb + 1))
|
Vk.zero(infos, bw * (nb + 1))
|
||||||
let iis = bytes(iw * (nt + 1))
|
let iis = gvk_tmp(render3d_st, iw * (nt + 1))
|
||||||
Vk.zero(iis, iw * (nt + 1))
|
Vk.zero(iis, iw * (nt + 1))
|
||||||
for k in 0 .. nb + 1 {
|
for k in 0 .. nb + 1 {
|
||||||
var buf = render3d_st.gvk_ring_buf
|
var buf = render3d_st.gvk_ring_buf
|
||||||
|
|
@ -254,7 +255,7 @@ function gvk_dispatch_tex(render3d_st: mut Render3dState, c: int, params: pointe
|
||||||
Vk.cmd_bind_pipeline(cb, VK_PIPELINE_BIND_POINT_COMPUTE, render3d_st.gvk_cp_pipe[c])
|
Vk.cmd_bind_pipeline(cb, VK_PIPELINE_BIND_POINT_COMPUTE, render3d_st.gvk_cp_pipe[c])
|
||||||
Vk.cmd_bind_descriptor_sets(cb, VK_PIPELINE_BIND_POINT_COMPUTE, render3d_st.gvk_cp_layout[c], 0, 1, sets, 0, null)
|
Vk.cmd_bind_descriptor_sets(cb, VK_PIPELINE_BIND_POINT_COMPUTE, render3d_st.gvk_cp_layout[c], 0, 1, sets, 0, null)
|
||||||
Vk.cmd_dispatch(cb, gx, gy, gz)
|
Vk.cmd_dispatch(cb, gx, gy, gz)
|
||||||
let mb = bytes(VkMemoryBarrier_sizeof)
|
let mb = gvk_tmp(render3d_st, VkMemoryBarrier_sizeof)
|
||||||
Vk.zero(mb, VkMemoryBarrier_sizeof)
|
Vk.zero(mb, VkMemoryBarrier_sizeof)
|
||||||
Vk.put_i32(mb, VkMemoryBarrier_sType, VK_STRUCTURE_TYPE_MEMORY_BARRIER)
|
Vk.put_i32(mb, VkMemoryBarrier_sType, VK_STRUCTURE_TYPE_MEMORY_BARRIER)
|
||||||
Vk.put_i32(mb, VkMemoryBarrier_srcAccessMask, VK_ACCESS_SHADER_WRITE_BIT)
|
Vk.put_i32(mb, VkMemoryBarrier_srcAccessMask, VK_ACCESS_SHADER_WRITE_BIT)
|
||||||
|
|
@ -704,6 +705,7 @@ function gvk_frame_init(render3d_st: mut Render3dState) -> bool {
|
||||||
let out = bytes(8)
|
let out = bytes(8)
|
||||||
render3d_st.gvk_dpools = new []long
|
render3d_st.gvk_dpools = new []long
|
||||||
for k in 0 .. 2 {
|
for k in 0 .. 2 {
|
||||||
|
render3d_st.gvk_mk_dpool += 1
|
||||||
let r = Vk.create_descriptor_pool(render3d_st.gvk_dev, dpci, null, out)
|
let r = Vk.create_descriptor_pool(render3d_st.gvk_dev, dpci, null, out)
|
||||||
if r != VK_SUCCESS { return gvk_fail(render3d_st, "vkCreateDescriptorPool", r) }
|
if r != VK_SUCCESS { return gvk_fail(render3d_st, "vkCreateDescriptorPool", r) }
|
||||||
push(render3d_st.gvk_dpools, gvk_handle(out))
|
push(render3d_st.gvk_dpools, gvk_handle(out))
|
||||||
|
|
@ -717,6 +719,8 @@ function gvk_frame_init(render3d_st: mut Render3dState) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
function gvk_frame_reset(render3d_st: mut Render3dState) -> void {
|
function gvk_frame_reset(render3d_st: mut Render3dState) -> void {
|
||||||
|
# what MoltenVK autoreleased last frame goes back here (a no-op off macOS); R3D_VK_NOPOOL=1 for an A/B
|
||||||
|
if not render3d_st.gvk_nopool { Vk.frame_pool() }
|
||||||
let slot = render3d_st.gvk_frame_no & 1
|
let slot = render3d_st.gvk_frame_no & 1
|
||||||
render3d_st.gvk_ring_off = slot * GVK_RING_BYTES
|
render3d_st.gvk_ring_off = slot * GVK_RING_BYTES
|
||||||
render3d_st.gvk_ring_end = (slot + 1) * GVK_RING_BYTES
|
render3d_st.gvk_ring_end = (slot + 1) * GVK_RING_BYTES
|
||||||
|
|
@ -756,6 +760,7 @@ function gvk_kpool_make(render3d_st: mut Render3dState) -> bool {
|
||||||
Vk.put_i32(dpci, VkDescriptorPoolCreateInfo_poolSizeCount, 2)
|
Vk.put_i32(dpci, VkDescriptorPoolCreateInfo_poolSizeCount, 2)
|
||||||
Vk.put_ptr(dpci, VkDescriptorPoolCreateInfo_pPoolSizes, sizes)
|
Vk.put_ptr(dpci, VkDescriptorPoolCreateInfo_pPoolSizes, sizes)
|
||||||
let out = bytes(8)
|
let out = bytes(8)
|
||||||
|
render3d_st.gvk_mk_dpool += 1
|
||||||
let r = Vk.create_descriptor_pool(render3d_st.gvk_dev, dpci, null, out)
|
let r = Vk.create_descriptor_pool(render3d_st.gvk_dev, dpci, null, out)
|
||||||
if r != VK_SUCCESS { return gvk_fail(render3d_st, "vkCreateDescriptorPool (kept sets)", r) }
|
if r != VK_SUCCESS { return gvk_fail(render3d_st, "vkCreateDescriptorPool (kept sets)", r) }
|
||||||
render3d_st.gvk_kpool = gvk_handle(out)
|
render3d_st.gvk_kpool = gvk_handle(out)
|
||||||
|
|
@ -764,8 +769,13 @@ function gvk_kpool_make(render3d_st: mut Render3dState) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
function gvk_sc_clear(render3d_st: mut Render3dState) -> void {
|
function gvk_sc_clear(render3d_st: mut Render3dState) -> void {
|
||||||
|
# emptied, not replaced: five fresh lists each time the pool filled were never given back
|
||||||
|
if render3d_st.gvk_sc_prog == null {
|
||||||
render3d_st.gvk_sc_prog = new []int; render3d_st.gvk_sc_koff = new []int; render3d_st.gvk_sc_set = new []long; render3d_st.gvk_sc_next = new []int
|
render3d_st.gvk_sc_prog = new []int; render3d_st.gvk_sc_koff = new []int; render3d_st.gvk_sc_set = new []long; render3d_st.gvk_sc_next = new []int
|
||||||
render3d_st.gvk_sc_keys = new []long
|
render3d_st.gvk_sc_keys = new []long
|
||||||
|
}
|
||||||
|
List.clear(render3d_st.gvk_sc_prog); List.clear(render3d_st.gvk_sc_koff); List.clear(render3d_st.gvk_sc_set); List.clear(render3d_st.gvk_sc_next)
|
||||||
|
List.clear(render3d_st.gvk_sc_keys)
|
||||||
if render3d_st.gvk_sc_head == null { render3d_st.gvk_sc_head = words(4096) }
|
if render3d_st.gvk_sc_head == null { render3d_st.gvk_sc_head = words(4096) }
|
||||||
for i in 0 .. 4096 { render3d_st.gvk_sc_head[i] = -1 }
|
for i in 0 .. 4096 { render3d_st.gvk_sc_head[i] = -1 }
|
||||||
}
|
}
|
||||||
|
|
@ -863,6 +873,7 @@ function gvk_sc_make(render3d_st: mut Render3dState, p: int, nt: int) -> long {
|
||||||
Vk.put_i32(dsai, VkDescriptorSetAllocateInfo_descriptorSetCount, 1)
|
Vk.put_i32(dsai, VkDescriptorSetAllocateInfo_descriptorSetCount, 1)
|
||||||
Vk.put_i64(layouts, 0, render3d_st.gvk_prog_dsl[p])
|
Vk.put_i64(layouts, 0, render3d_st.gvk_prog_dsl[p])
|
||||||
Vk.put_ptr(dsai, VkDescriptorSetAllocateInfo_pSetLayouts, layouts)
|
Vk.put_ptr(dsai, VkDescriptorSetAllocateInfo_pSetLayouts, layouts)
|
||||||
|
render3d_st.gvk_mk_set += 1
|
||||||
r = Vk.allocate_descriptor_sets(render3d_st.gvk_dev, dsai, sets)
|
r = Vk.allocate_descriptor_sets(render3d_st.gvk_dev, dsai, sets)
|
||||||
if r == VK_SUCCESS { tries = 2 } else { gvk_kpool_reset(render3d_st); tries += 1 }
|
if r == VK_SUCCESS { tries = 2 } else { gvk_kpool_reset(render3d_st); tries += 1 }
|
||||||
}
|
}
|
||||||
|
|
@ -1011,9 +1022,10 @@ function gvk_frame_cb(render3d_st: mut Render3dState) -> pointer {
|
||||||
# on its own. Keyed by the image's generation, so a replaced image never reuses a stale view.
|
# on its own. Keyed by the image's generation, so a replaced image never reuses a stale view.
|
||||||
function gvk_view_of(render3d_st: mut Render3dState, tex: int, layer1: int) -> long {
|
function gvk_view_of(render3d_st: mut Render3dState, tex: int, layer1: int) -> long {
|
||||||
if layer1 == 0 and render3d_st.gvk_tex_levels[tex] <= 1 and render3d_st.gvk_tex_layers[tex] <= 1 { return render3d_st.gvk_tex_view[tex] }
|
if layer1 == 0 and render3d_st.gvk_tex_levels[tex] <= 1 and render3d_st.gvk_tex_layers[tex] <= 1 { return render3d_st.gvk_tex_view[tex] }
|
||||||
let key = `{tex}:{render3d_st.gvk_tex_gen[tex]}:{layer1}`
|
# keyed by numbers, not a string built on every call: the texture, its generation and the layer
|
||||||
if render3d_st.gvk_layer_views == null { render3d_st.gvk_layer_views = new []string; render3d_st.gvk_layer_view = new []long }
|
let key = render3d_st.gvk_tex_gen[tex] * 4096 + layer1
|
||||||
for i in 0 .. len(render3d_st.gvk_layer_views) { if render3d_st.gvk_layer_views[i] == key { return render3d_st.gvk_layer_view[i] } }
|
if render3d_st.gvk_layer_views == null { render3d_st.gvk_layer_views = new []int; render3d_st.gvk_layer_view = new []long; render3d_st.gvk_layer_view_tex = new []int }
|
||||||
|
for i in 0 .. len(render3d_st.gvk_layer_views) { if render3d_st.gvk_layer_view_tex[i] == tex and render3d_st.gvk_layer_views[i] == key { return render3d_st.gvk_layer_view[i] } }
|
||||||
let depth = render3d_st.gvk_tex_vkfmt[tex] == VK_FORMAT_D32_SFLOAT
|
let depth = render3d_st.gvk_tex_vkfmt[tex] == VK_FORMAT_D32_SFLOAT
|
||||||
let vci = bytes(VkImageViewCreateInfo_sizeof)
|
let vci = bytes(VkImageViewCreateInfo_sizeof)
|
||||||
Vk.zero(vci, VkImageViewCreateInfo_sizeof)
|
Vk.zero(vci, VkImageViewCreateInfo_sizeof)
|
||||||
|
|
@ -1028,16 +1040,18 @@ function gvk_view_of(render3d_st: mut Render3dState, tex: int, layer1: int) -> l
|
||||||
Vk.put_i32(vci, sr + VkImageSubresourceRange_layerCount, 1)
|
Vk.put_i32(vci, sr + VkImageSubresourceRange_layerCount, 1)
|
||||||
let out = bytes(8)
|
let out = bytes(8)
|
||||||
let zero: long = 0
|
let zero: long = 0
|
||||||
|
render3d_st.gvk_mk_view += 1
|
||||||
if Vk.create_image_view(render3d_st.gvk_dev, vci, null, out) != VK_SUCCESS { return zero }
|
if Vk.create_image_view(render3d_st.gvk_dev, vci, null, out) != VK_SUCCESS { return zero }
|
||||||
push(render3d_st.gvk_layer_views, key)
|
push(render3d_st.gvk_layer_views, key)
|
||||||
push(render3d_st.gvk_layer_view, gvk_handle(out))
|
push(render3d_st.gvk_layer_view, gvk_handle(out))
|
||||||
|
push(render3d_st.gvk_layer_view_tex, tex)
|
||||||
return gvk_handle(out)
|
return gvk_handle(out)
|
||||||
}
|
}
|
||||||
# the layer range a barrier for an attachment covers: the whole image unless one layer is drawn
|
# the layer range a barrier for an attachment covers: the whole image unless one layer is drawn
|
||||||
function gvk_att_barrier(render3d_st: Render3dState, cb: pointer, tex: int, layer1: int, depth: bool, old_layout: int, new_layout: int) -> void {
|
function gvk_att_barrier(render3d_st: mut Render3dState, cb: pointer, tex: int, layer1: int, depth: bool, old_layout: int, new_layout: int) -> void {
|
||||||
# an attachment whose image was never made (no memory for it) has nothing to transition
|
# an attachment whose image was never made (no memory for it) has nothing to transition
|
||||||
if tex <= 0 or tex >= len(render3d_st.gvk_tex_image) or render3d_st.gvk_tex_image[tex] == 0 { return }
|
if tex <= 0 or tex >= len(render3d_st.gvk_tex_image) or render3d_st.gvk_tex_image[tex] == 0 { return }
|
||||||
let b = bytes(VkImageMemoryBarrier_sizeof)
|
let b = gvk_tmp(render3d_st, VkImageMemoryBarrier_sizeof)
|
||||||
Vk.zero(b, VkImageMemoryBarrier_sizeof)
|
Vk.zero(b, VkImageMemoryBarrier_sizeof)
|
||||||
Vk.put_i32(b, VkImageMemoryBarrier_sType, VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER)
|
Vk.put_i32(b, VkImageMemoryBarrier_sType, VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER)
|
||||||
Vk.put_i32(b, VkImageMemoryBarrier_srcAccessMask, gvk_layout_access(old_layout))
|
Vk.put_i32(b, VkImageMemoryBarrier_srcAccessMask, gvk_layout_access(old_layout))
|
||||||
|
|
@ -1085,7 +1099,7 @@ function gvk_pass_begin(render3d_st: mut Render3dState, rec: words, rec_o: int)
|
||||||
let cb = gvk_frame_cb(render3d_st)
|
let cb = gvk_frame_cb(render3d_st)
|
||||||
gvk_pass_collect(render3d_st, render3d_st.gvk_fb_cur, rec, rec_o)
|
gvk_pass_collect(render3d_st, render3d_st.gvk_fb_cur, rec, rec_o)
|
||||||
let aw = VkRenderingAttachmentInfo_sizeof
|
let aw = VkRenderingAttachmentInfo_sizeof
|
||||||
let catt = bytes(aw * 3)
|
let catt = gvk_tmp(render3d_st, aw * 3)
|
||||||
Vk.zero(catt, aw * 3)
|
Vk.zero(catt, aw * 3)
|
||||||
render3d_st.gvk_pass_w = 0
|
render3d_st.gvk_pass_w = 0
|
||||||
render3d_st.gvk_pass_h = 0
|
render3d_st.gvk_pass_h = 0
|
||||||
|
|
@ -1108,7 +1122,7 @@ function gvk_pass_begin(render3d_st: mut Render3dState, rec: words, rec_o: int)
|
||||||
render3d_st.gvk_pass_samples = gvk_tex_samples_of(render3d_st, tex)
|
render3d_st.gvk_pass_samples = gvk_tex_samples_of(render3d_st, tex)
|
||||||
if render3d_st.gvk_pass_w == 0 { render3d_st.gvk_pass_w = gvk_tex_w(render3d_st, tex); render3d_st.gvk_pass_h = gvk_tex_h(render3d_st, tex) }
|
if render3d_st.gvk_pass_w == 0 { render3d_st.gvk_pass_w = gvk_tex_w(render3d_st, tex); render3d_st.gvk_pass_h = gvk_tex_h(render3d_st, tex) }
|
||||||
}
|
}
|
||||||
let datt = bytes(aw)
|
let datt = gvk_tmp(render3d_st, aw)
|
||||||
Vk.zero(datt, aw)
|
Vk.zero(datt, aw)
|
||||||
let dtex = render3d_st.gvk_pass_dep[0]
|
let dtex = render3d_st.gvk_pass_dep[0]
|
||||||
if dtex > 0 {
|
if dtex > 0 {
|
||||||
|
|
@ -1126,7 +1140,7 @@ function gvk_pass_begin(render3d_st: mut Render3dState, rec: words, rec_o: int)
|
||||||
if render3d_st.gvk_pass_w == 0 { render3d_st.gvk_pass_w = gvk_tex_w(render3d_st, dtex); render3d_st.gvk_pass_h = gvk_tex_h(render3d_st, dtex) }
|
if render3d_st.gvk_pass_w == 0 { render3d_st.gvk_pass_w = gvk_tex_w(render3d_st, dtex); render3d_st.gvk_pass_h = gvk_tex_h(render3d_st, dtex) }
|
||||||
}
|
}
|
||||||
render3d_st.gvk_clear_bits = 0
|
render3d_st.gvk_clear_bits = 0
|
||||||
let ri = bytes(VkRenderingInfo_sizeof)
|
let ri = gvk_tmp(render3d_st, VkRenderingInfo_sizeof)
|
||||||
Vk.zero(ri, VkRenderingInfo_sizeof)
|
Vk.zero(ri, VkRenderingInfo_sizeof)
|
||||||
Vk.put_i32(ri, VkRenderingInfo_sType, VK_STRUCTURE_TYPE_RENDERING_INFO)
|
Vk.put_i32(ri, VkRenderingInfo_sType, VK_STRUCTURE_TYPE_RENDERING_INFO)
|
||||||
Vk.put_i32(ri, VkRenderingInfo_renderArea + VkRect2D_extent + VkExtent2D_width, render3d_st.gvk_pass_w)
|
Vk.put_i32(ri, VkRenderingInfo_renderArea + VkRect2D_extent + VkExtent2D_width, render3d_st.gvk_pass_w)
|
||||||
|
|
@ -1157,7 +1171,7 @@ function gvk_clear(render3d_st: mut Render3dState, mask: int, rec: words, rec_o:
|
||||||
if not render3d_st.gvk_in_pass { render3d_st.gvk_clear_bits = render3d_st.gvk_clear_bits | mask; return }
|
if not render3d_st.gvk_in_pass { render3d_st.gvk_clear_bits = render3d_st.gvk_clear_bits | mask; return }
|
||||||
let cb = render3d_st.gvk_cb
|
let cb = render3d_st.gvk_cb
|
||||||
let caw = VkClearAttachment_sizeof
|
let caw = VkClearAttachment_sizeof
|
||||||
let atts = bytes(caw * 4)
|
let atts = gvk_tmp(render3d_st, caw * 4)
|
||||||
Vk.zero(atts, caw * 4)
|
Vk.zero(atts, caw * 4)
|
||||||
var n = 0
|
var n = 0
|
||||||
if (mask & GL_COLOR_BUFFER_BIT) != 0 {
|
if (mask & GL_COLOR_BUFFER_BIT) != 0 {
|
||||||
|
|
@ -1174,7 +1188,7 @@ function gvk_clear(render3d_st: mut Render3dState, mask: int, rec: words, rec_o:
|
||||||
n += 1
|
n += 1
|
||||||
}
|
}
|
||||||
if n == 0 { return }
|
if n == 0 { return }
|
||||||
let rect = bytes(VkClearRect_sizeof)
|
let rect = gvk_tmp(render3d_st, VkClearRect_sizeof)
|
||||||
Vk.zero(rect, VkClearRect_sizeof)
|
Vk.zero(rect, VkClearRect_sizeof)
|
||||||
Vk.put_i32(rect, VkClearRect_rect + VkRect2D_extent + VkExtent2D_width, render3d_st.gvk_pass_w)
|
Vk.put_i32(rect, VkClearRect_rect + VkRect2D_extent + VkExtent2D_width, render3d_st.gvk_pass_w)
|
||||||
Vk.put_i32(rect, VkClearRect_rect + VkRect2D_extent + VkExtent2D_height, render3d_st.gvk_pass_h)
|
Vk.put_i32(rect, VkClearRect_rect + VkRect2D_extent + VkExtent2D_height, render3d_st.gvk_pass_h)
|
||||||
|
|
@ -1187,8 +1201,8 @@ function gvk_tex_h(render3d_st: Render3dState, tex: int) -> int { return render3
|
||||||
|
|
||||||
# viewport and scissor for the draw; OpenGL's rows count from the bottom and so do a Vulkan
|
# viewport and scissor for the draw; OpenGL's rows count from the bottom and so do a Vulkan
|
||||||
# target's here (no y flip), so both pass straight through
|
# target's here (no y flip), so both pass straight through
|
||||||
function gvk_set_view(render3d_st: Render3dState, cb: pointer) -> void {
|
function gvk_set_view(render3d_st: mut Render3dState, cb: pointer) -> void {
|
||||||
let vp = bytes(VkViewport_sizeof)
|
let vp = gvk_tmp(render3d_st, VkViewport_sizeof)
|
||||||
Vk.zero(vp, VkViewport_sizeof)
|
Vk.zero(vp, VkViewport_sizeof)
|
||||||
Vk.put_i32(vp, VkViewport_x, float_bits(float(render3d_st.gvk_vp[0])))
|
Vk.put_i32(vp, VkViewport_x, float_bits(float(render3d_st.gvk_vp[0])))
|
||||||
Vk.put_i32(vp, VkViewport_y, float_bits(float(render3d_st.gvk_vp[1])))
|
Vk.put_i32(vp, VkViewport_y, float_bits(float(render3d_st.gvk_vp[1])))
|
||||||
|
|
@ -1196,7 +1210,7 @@ function gvk_set_view(render3d_st: Render3dState, cb: pointer) -> void {
|
||||||
Vk.put_i32(vp, VkViewport_height, float_bits(float(render3d_st.gvk_vp[3])))
|
Vk.put_i32(vp, VkViewport_height, float_bits(float(render3d_st.gvk_vp[3])))
|
||||||
Vk.put_i32(vp, VkViewport_maxDepth, 0x3F800000)
|
Vk.put_i32(vp, VkViewport_maxDepth, 0x3F800000)
|
||||||
Vk.cmd_set_viewport(cb, 0, 1, vp)
|
Vk.cmd_set_viewport(cb, 0, 1, vp)
|
||||||
let sc = bytes(VkRect2D_sizeof)
|
let sc = gvk_tmp(render3d_st, VkRect2D_sizeof)
|
||||||
Vk.zero(sc, VkRect2D_sizeof)
|
Vk.zero(sc, VkRect2D_sizeof)
|
||||||
if render3d_st.gvk_sc[0] == 1 {
|
if render3d_st.gvk_sc[0] == 1 {
|
||||||
Vk.put_i32(sc, VkRect2D_offset + VkOffset2D_x, render3d_st.gvk_sc[1])
|
Vk.put_i32(sc, VkRect2D_offset + VkOffset2D_x, render3d_st.gvk_sc[1])
|
||||||
|
|
@ -1238,16 +1252,17 @@ function gvk_draw(render3d_st: mut Render3dState, p: int, m: Mesh, st: GvkState,
|
||||||
let set = gvk_draw_set(render3d_st, p, tx, tx_w, tx_cap)
|
let set = gvk_draw_set(render3d_st, p, tx, tx_w, tx_cap)
|
||||||
if set == 0 { return }
|
if set == 0 { return }
|
||||||
if prof { render3d_st.gvk_us_set = render3d_st.gvk_us_set + (gl_now_us() - t1) }
|
if prof { render3d_st.gvk_us_set = render3d_st.gvk_us_set + (gl_now_us() - t1) }
|
||||||
let sets = bytes(8)
|
let sets = gvk_tmp(render3d_st, 8)
|
||||||
Vk.put_i64(sets, 0, set)
|
Vk.put_i64(sets, 0, set)
|
||||||
Vk.cmd_bind_descriptor_sets(cb, VK_PIPELINE_BIND_POINT_GRAPHICS, render3d_st.gvk_prog_layout[p], 0, 1, sets, render3d_st.gvk_set_ndyn, render3d_st.gvk_set_offs)
|
Vk.cmd_bind_descriptor_sets(cb, VK_PIPELINE_BIND_POINT_GRAPHICS, render3d_st.gvk_prog_layout[p], 0, 1, sets, render3d_st.gvk_set_ndyn, render3d_st.gvk_set_offs)
|
||||||
let v = render3d_st.gvk_prog_var[p]
|
let v = render3d_st.gvk_prog_var[p]
|
||||||
if m != null and m.attrs != null {
|
if m != null and m.attrs != null {
|
||||||
# the same bindings, in the same order, as gvk_pipeline gave the layout
|
# the same bindings, in the same order, as gvk_pipeline gave the layout
|
||||||
let bufs = bytes(8 * (GPU_MAX_VBUFS + 1))
|
let bufs = gvk_tmp(render3d_st, 8 * (GPU_MAX_VBUFS + 1))
|
||||||
let offs = bytes(8 * (GPU_MAX_VBUFS + 1))
|
let offs = gvk_tmp(render3d_st, 8 * (GPU_MAX_VBUFS + 1))
|
||||||
Vk.zero(offs, 8 * (GPU_MAX_VBUFS + 1))
|
Vk.zero(offs, 8 * (GPU_MAX_VBUFS + 1))
|
||||||
let seen = words(GPU_MAX_VBUFS)
|
if render3d_st.gvk_seen == null { render3d_st.gvk_seen = words(GPU_MAX_VBUFS) }
|
||||||
|
let seen = render3d_st.gvk_seen
|
||||||
var nbd = 0
|
var nbd = 0
|
||||||
for i in 0 .. m.n_attrs {
|
for i in 0 .. m.n_attrs {
|
||||||
let o = i * GPU_ATTR_W
|
let o = i * GPU_ATTR_W
|
||||||
|
|
@ -1510,7 +1525,7 @@ function gvk_resolve(render3d_st: mut Render3dState, cb: pointer, src: int, dst:
|
||||||
gvk_att_barrier(render3d_st, cb, src, 0, depth, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, layout)
|
gvk_att_barrier(render3d_st, cb, src, 0, depth, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, layout)
|
||||||
gvk_att_barrier(render3d_st, cb, dst, 0, depth, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, layout)
|
gvk_att_barrier(render3d_st, cb, dst, 0, depth, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, layout)
|
||||||
let aw = VkRenderingAttachmentInfo_sizeof
|
let aw = VkRenderingAttachmentInfo_sizeof
|
||||||
let att = bytes(aw)
|
let att = gvk_tmp(render3d_st, aw)
|
||||||
Vk.zero(att, aw)
|
Vk.zero(att, aw)
|
||||||
Vk.put_i32(att, VkRenderingAttachmentInfo_sType, VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO)
|
Vk.put_i32(att, VkRenderingAttachmentInfo_sType, VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO)
|
||||||
Vk.put_i64(att, VkRenderingAttachmentInfo_imageView, gvk_view_of(render3d_st, src, 0))
|
Vk.put_i64(att, VkRenderingAttachmentInfo_imageView, gvk_view_of(render3d_st, src, 0))
|
||||||
|
|
@ -1520,7 +1535,7 @@ function gvk_resolve(render3d_st: mut Render3dState, cb: pointer, src: int, dst:
|
||||||
Vk.put_i32(att, VkRenderingAttachmentInfo_resolveImageLayout, layout)
|
Vk.put_i32(att, VkRenderingAttachmentInfo_resolveImageLayout, layout)
|
||||||
Vk.put_i32(att, VkRenderingAttachmentInfo_loadOp, VK_ATTACHMENT_LOAD_OP_LOAD)
|
Vk.put_i32(att, VkRenderingAttachmentInfo_loadOp, VK_ATTACHMENT_LOAD_OP_LOAD)
|
||||||
Vk.put_i32(att, VkRenderingAttachmentInfo_storeOp, VK_ATTACHMENT_STORE_OP_STORE)
|
Vk.put_i32(att, VkRenderingAttachmentInfo_storeOp, VK_ATTACHMENT_STORE_OP_STORE)
|
||||||
let ri = bytes(VkRenderingInfo_sizeof)
|
let ri = gvk_tmp(render3d_st, VkRenderingInfo_sizeof)
|
||||||
Vk.zero(ri, VkRenderingInfo_sizeof)
|
Vk.zero(ri, VkRenderingInfo_sizeof)
|
||||||
Vk.put_i32(ri, VkRenderingInfo_sType, VK_STRUCTURE_TYPE_RENDERING_INFO)
|
Vk.put_i32(ri, VkRenderingInfo_sType, VK_STRUCTURE_TYPE_RENDERING_INFO)
|
||||||
Vk.put_i32(ri, VkRenderingInfo_renderArea + VkRect2D_extent + VkExtent2D_width, w)
|
Vk.put_i32(ri, VkRenderingInfo_renderArea + VkRect2D_extent + VkExtent2D_width, w)
|
||||||
|
|
@ -1536,9 +1551,9 @@ function gvk_resolve(render3d_st: mut Render3dState, cb: pointer, src: int, dst:
|
||||||
function gvk_copy(render3d_st: mut Render3dState, cb: pointer, src: int, dst: int, depth: bool, w: int, h: int) -> void {
|
function gvk_copy(render3d_st: mut Render3dState, cb: pointer, src: int, dst: int, depth: bool, w: int, h: int) -> void {
|
||||||
if src <= 0 or dst <= 0 or render3d_st.gvk_tex_image[src] == 0 or render3d_st.gvk_tex_image[dst] == 0 { return }
|
if src <= 0 or dst <= 0 or render3d_st.gvk_tex_image[src] == 0 or render3d_st.gvk_tex_image[dst] == 0 { return }
|
||||||
if gvk_tex_samples_of(render3d_st, src) > 1 and gvk_tex_samples_of(render3d_st, dst) == 1 { gvk_resolve(render3d_st, cb, src, dst, depth, w, h); return }
|
if gvk_tex_samples_of(render3d_st, src) > 1 and gvk_tex_samples_of(render3d_st, dst) == 1 { gvk_resolve(render3d_st, cb, src, dst, depth, w, h); return }
|
||||||
gvk_barrier(cb, render3d_st.gvk_tex_image[src], depth, 0, 1, render3d_st.gvk_tex_layers[src], VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)
|
gvk_barrier(render3d_st, cb, render3d_st.gvk_tex_image[src], depth, 0, 1, render3d_st.gvk_tex_layers[src], VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)
|
||||||
gvk_barrier(cb, render3d_st.gvk_tex_image[dst], depth, 0, 1, render3d_st.gvk_tex_layers[dst], VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
|
gvk_barrier(render3d_st, cb, render3d_st.gvk_tex_image[dst], depth, 0, 1, render3d_st.gvk_tex_layers[dst], VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
|
||||||
let ic = bytes(VkImageCopy_sizeof)
|
let ic = gvk_tmp(render3d_st, VkImageCopy_sizeof)
|
||||||
Vk.zero(ic, VkImageCopy_sizeof)
|
Vk.zero(ic, VkImageCopy_sizeof)
|
||||||
var aspect = VK_IMAGE_ASPECT_COLOR_BIT
|
var aspect = VK_IMAGE_ASPECT_COLOR_BIT
|
||||||
if depth { aspect = VK_IMAGE_ASPECT_DEPTH_BIT }
|
if depth { aspect = VK_IMAGE_ASPECT_DEPTH_BIT }
|
||||||
|
|
@ -1550,8 +1565,8 @@ function gvk_copy(render3d_st: mut Render3dState, cb: pointer, src: int, dst: in
|
||||||
Vk.put_i32(ic, VkImageCopy_extent + VkExtent3D_height, h)
|
Vk.put_i32(ic, VkImageCopy_extent + VkExtent3D_height, h)
|
||||||
Vk.put_i32(ic, VkImageCopy_extent + VkExtent3D_depth, 1)
|
Vk.put_i32(ic, VkImageCopy_extent + VkExtent3D_depth, 1)
|
||||||
Vk.cmd_copy_image(cb, render3d_st.gvk_tex_image[src], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, render3d_st.gvk_tex_image[dst], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ic)
|
Vk.cmd_copy_image(cb, render3d_st.gvk_tex_image[src], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, render3d_st.gvk_tex_image[dst], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ic)
|
||||||
gvk_barrier(cb, render3d_st.gvk_tex_image[src], depth, 0, 1, render3d_st.gvk_tex_layers[src], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
|
gvk_barrier(render3d_st, cb, render3d_st.gvk_tex_image[src], depth, 0, 1, render3d_st.gvk_tex_layers[src], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
|
||||||
gvk_barrier(cb, render3d_st.gvk_tex_image[dst], depth, 0, 1, render3d_st.gvk_tex_layers[dst], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
|
gvk_barrier(render3d_st, cb, render3d_st.gvk_tex_image[dst], depth, 0, 1, render3d_st.gvk_tex_layers[dst], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
|
||||||
}
|
}
|
||||||
function gvk_blit(render3d_st: mut Render3dState, w: int, h: int, mask: int) -> void {
|
function gvk_blit(render3d_st: mut Render3dState, w: int, h: int, mask: int) -> void {
|
||||||
gvk_pass_end(render3d_st)
|
gvk_pass_end(render3d_st)
|
||||||
|
|
@ -1725,20 +1740,20 @@ function gvk_present_window(render3d_st: mut Render3dState) -> void {
|
||||||
Time.sleep_us(16000)
|
Time.sleep_us(16000)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if render3d_st.gvk_swap_stale { gvk_once_end(render3d_st, cb); render3d_st.gvk_cb = null; gvk_swap_make(render3d_st, render3d_st.gvk_swap_w, render3d_st.gvk_swap_h); return }
|
if render3d_st.gvk_swap_stale { gvk_once_end(render3d_st, cb); render3d_st.gvk_cb = null; print("r3d: vulkan: swapchain remade at acquire"); gvk_swap_make(render3d_st, render3d_st.gvk_swap_w, render3d_st.gvk_swap_h); return }
|
||||||
let idx = bytes(4)
|
let idx = gvk_tmp(render3d_st, 4)
|
||||||
Vk.reset_fences(render3d_st.gvk_dev, 1, render3d_st.gvk_acq_fence)
|
Vk.reset_fences(render3d_st.gvk_dev, 1, render3d_st.gvk_acq_fence)
|
||||||
let forever: long = -1
|
let forever: long = -1
|
||||||
let zero: long = 0
|
let zero: long = 0
|
||||||
var r = Vk.acquire_next_image_khr(render3d_st.gvk_dev, render3d_st.gvk_swap, forever, zero, Vk.get_i64(render3d_st.gvk_acq_fence, 0), idx)
|
var r = Vk.acquire_next_image_khr(render3d_st.gvk_dev, render3d_st.gvk_swap, forever, zero, Vk.get_i64(render3d_st.gvk_acq_fence, 0), idx)
|
||||||
if r == VK_ERROR_OUT_OF_DATE_KHR { gvk_once_end(render3d_st, cb); render3d_st.gvk_cb = null; gvk_swap_make(render3d_st, render3d_st.gvk_swap_w, render3d_st.gvk_swap_h); return }
|
if r == VK_ERROR_OUT_OF_DATE_KHR { gvk_once_end(render3d_st, cb); render3d_st.gvk_cb = null; print("r3d: vulkan: swapchain remade at acquire"); gvk_swap_make(render3d_st, render3d_st.gvk_swap_w, render3d_st.gvk_swap_h); return }
|
||||||
Vk.wait_for_fences(render3d_st.gvk_dev, 1, render3d_st.gvk_acq_fence, 1, forever)
|
Vk.wait_for_fences(render3d_st.gvk_dev, 1, render3d_st.gvk_acq_fence, 1, forever)
|
||||||
let i = Vk.get_i32(idx, 0)
|
let i = Vk.get_i32(idx, 0)
|
||||||
let dst = Vk.get_i64(render3d_st.gvk_swap_images, i * 8)
|
let dst = Vk.get_i64(render3d_st.gvk_swap_images, i * 8)
|
||||||
let src = render3d_st.gvk_tex_image[render3d_st.gvk_screen_color]
|
let src = render3d_st.gvk_tex_image[render3d_st.gvk_screen_color]
|
||||||
gvk_barrier(cb, src, false, 0, 1, 1, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)
|
gvk_barrier(render3d_st, cb, src, false, 0, 1, 1, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)
|
||||||
gvk_barrier(cb, dst, false, 0, 1, 1, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
|
gvk_barrier(render3d_st, cb, dst, false, 0, 1, 1, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
|
||||||
let blit = bytes(VkImageBlit_sizeof)
|
let blit = gvk_tmp(render3d_st, VkImageBlit_sizeof)
|
||||||
Vk.zero(blit, VkImageBlit_sizeof)
|
Vk.zero(blit, VkImageBlit_sizeof)
|
||||||
Vk.put_i32(blit, VkImageBlit_srcSubresource + VkImageSubresourceLayers_aspectMask, VK_IMAGE_ASPECT_COLOR_BIT)
|
Vk.put_i32(blit, VkImageBlit_srcSubresource + VkImageSubresourceLayers_aspectMask, VK_IMAGE_ASPECT_COLOR_BIT)
|
||||||
Vk.put_i32(blit, VkImageBlit_srcSubresource + VkImageSubresourceLayers_layerCount, 1)
|
Vk.put_i32(blit, VkImageBlit_srcSubresource + VkImageSubresourceLayers_layerCount, 1)
|
||||||
|
|
@ -1752,14 +1767,14 @@ function gvk_present_window(render3d_st: mut Render3dState) -> void {
|
||||||
Vk.put_i32(blit, VkImageBlit_dstOffsets + VkOffset3D_sizeof + VkOffset3D_y, render3d_st.gvk_swap_h)
|
Vk.put_i32(blit, VkImageBlit_dstOffsets + VkOffset3D_sizeof + VkOffset3D_y, render3d_st.gvk_swap_h)
|
||||||
Vk.put_i32(blit, VkImageBlit_dstOffsets + VkOffset3D_sizeof + VkOffset3D_z, 1)
|
Vk.put_i32(blit, VkImageBlit_dstOffsets + VkOffset3D_sizeof + VkOffset3D_z, 1)
|
||||||
Vk.cmd_blit_image(cb, src, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, blit, VK_FILTER_LINEAR)
|
Vk.cmd_blit_image(cb, src, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, blit, VK_FILTER_LINEAR)
|
||||||
gvk_barrier(cb, src, false, 0, 1, 1, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
|
gvk_barrier(render3d_st, cb, src, false, 0, 1, 1, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
|
||||||
gvk_barrier(cb, dst, false, 0, 1, 1, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)
|
gvk_barrier(render3d_st, cb, dst, false, 0, 1, 1, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)
|
||||||
if gvk_inflight_on(render3d_st) { gvk_frame_submit(render3d_st, cb) } else { gvk_once_end(render3d_st, cb) }
|
if gvk_inflight_on(render3d_st) { gvk_frame_submit(render3d_st, cb) } else { gvk_once_end(render3d_st, cb) }
|
||||||
render3d_st.gvk_cb = null
|
render3d_st.gvk_cb = null
|
||||||
let pi = bytes(VkPresentInfoKHR_sizeof)
|
let pi = gvk_tmp(render3d_st, VkPresentInfoKHR_sizeof)
|
||||||
Vk.zero(pi, VkPresentInfoKHR_sizeof)
|
Vk.zero(pi, VkPresentInfoKHR_sizeof)
|
||||||
Vk.put_i32(pi, VkPresentInfoKHR_sType, VK_STRUCTURE_TYPE_PRESENT_INFO_KHR)
|
Vk.put_i32(pi, VkPresentInfoKHR_sType, VK_STRUCTURE_TYPE_PRESENT_INFO_KHR)
|
||||||
let chains = bytes(8)
|
let chains = gvk_tmp(render3d_st, 8)
|
||||||
Vk.put_i64(chains, 0, render3d_st.gvk_swap)
|
Vk.put_i64(chains, 0, render3d_st.gvk_swap)
|
||||||
Vk.put_i32(pi, VkPresentInfoKHR_swapchainCount, 1)
|
Vk.put_i32(pi, VkPresentInfoKHR_swapchainCount, 1)
|
||||||
Vk.put_ptr(pi, VkPresentInfoKHR_pSwapchains, chains)
|
Vk.put_ptr(pi, VkPresentInfoKHR_pSwapchains, chains)
|
||||||
|
|
@ -1779,6 +1794,8 @@ function gvk_resize_check(render3d_st: mut Render3dState) -> bool {
|
||||||
let h = render3d_st.gvk_size_buf[1]
|
let h = render3d_st.gvk_size_buf[1]
|
||||||
if w <= 0 or h <= 0 { return false }
|
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 }
|
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_flush(render3d_st)
|
gvk_flush(render3d_st)
|
||||||
gl_set_drawable(w, h)
|
gl_set_drawable(w, h)
|
||||||
gvk_screen_make(render3d_st, w, h)
|
gvk_screen_make(render3d_st, w, h)
|
||||||
|
|
@ -1816,11 +1833,26 @@ function gvk_prof_frame(render3d_st: mut Render3dState) -> void {
|
||||||
if render3d_st.gvk_n_asked != render3d_st.gvk_n_draws {
|
if render3d_st.gvk_n_asked != render3d_st.gvk_n_draws {
|
||||||
print(`r3d: vulkan: {(render3d_st.gvk_n_asked - render3d_st.gvk_n_draws) / f} draws a frame were asked for and not made ({render3d_st.gvk_n_asked / f} asked, {render3d_st.gvk_n_draws / f} made)`)
|
print(`r3d: vulkan: {(render3d_st.gvk_n_asked - render3d_st.gvk_n_draws) / f} draws a frame were asked for and not made ({render3d_st.gvk_n_asked / f} asked, {render3d_st.gvk_n_draws / f} made)`)
|
||||||
}
|
}
|
||||||
|
gvk_prof_made(render3d_st)
|
||||||
let zero: long = 0
|
let zero: long = 0
|
||||||
render3d_st.gvk_us_pipe = zero; render3d_st.gvk_us_set = zero; render3d_st.gvk_us_draw = zero
|
render3d_st.gvk_us_pipe = zero; render3d_st.gvk_us_set = zero; render3d_st.gvk_us_draw = zero
|
||||||
render3d_st.gvk_n_draws = 0; render3d_st.gvk_n_asked = 0; render3d_st.gvk_n_flush = 0; render3d_st.gvk_prof_frames = 0; render3d_st.gvk_n_pipe_new = 0
|
render3d_st.gvk_n_draws = 0; render3d_st.gvk_n_asked = 0; render3d_st.gvk_n_flush = 0; render3d_st.gvk_prof_frames = 0; render3d_st.gvk_n_pipe_new = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# what was made and destroyed over those frames, and how long the caches are: a kind made every
|
||||||
|
# frame and never destroyed, or a cache that only grows, is a leak
|
||||||
|
function gvk_prof_made(render3d_st: mut Render3dState) -> void {
|
||||||
|
let r = render3d_st
|
||||||
|
print(`r3d: vulkan made/destroyed: images {r.gvk_mk_img}/{r.gvk_mk_x_img}, views {r.gvk_mk_view}/{r.gvk_mk_x_view}, buffers {r.gvk_mk_buf}/{r.gvk_mk_x_buf}, memory {r.gvk_mk_mem}/{r.gvk_mk_x_mem}, samplers {r.gvk_mk_smp}, sets {r.gvk_mk_set}, pools {r.gvk_mk_dpool}, cmds {r.gvk_mk_cmd}`)
|
||||||
|
print(`r3d: vulkan caches: layer views {gvk_len_i(r.gvk_layer_views)}, pipelines {gvk_len_s(r.gvk_pipe_keys)}, layouts {gvk_len_s(r.gvk_layout_keys)}, pipe cache {gvk_len_i(r.gvk_pc_prog)}, retired {gvk_len_l(r.gvk_retired_buf)}, buffers {gvk_len_l(r.gvk_buf)}, allocs {r.gvk_n_allocs}`)
|
||||||
|
render3d_st.gvk_mk_img = 0; render3d_st.gvk_mk_x_img = 0; render3d_st.gvk_mk_view = 0; render3d_st.gvk_mk_x_view = 0
|
||||||
|
render3d_st.gvk_mk_buf = 0; render3d_st.gvk_mk_x_buf = 0; render3d_st.gvk_mk_mem = 0; render3d_st.gvk_mk_x_mem = 0
|
||||||
|
render3d_st.gvk_mk_smp = 0; render3d_st.gvk_mk_set = 0; render3d_st.gvk_mk_dpool = 0; render3d_st.gvk_mk_cmd = 0
|
||||||
|
}
|
||||||
|
function gvk_len_s(xs: []string) -> int { if xs == null { return 0 }; return len(xs) }
|
||||||
|
function gvk_len_i(xs: []int) -> int { if xs == null { return 0 }; return len(xs) }
|
||||||
|
function gvk_len_l(xs: []long) -> int { if xs == null { return 0 }; return len(xs) }
|
||||||
|
|
||||||
# ---- the pipeline cache, by integers -----------------------------------------------------------
|
# ---- the pipeline cache, by integers -----------------------------------------------------------
|
||||||
# gvk_pipeline builds and keys pipelines by a string; a draw only needs to find one it already has.
|
# gvk_pipeline builds and keys pipelines by a string; a draw only needs to find one it already has.
|
||||||
# A mesh carries an interned layout id (its recorded layout, buffers named by order), the render
|
# A mesh carries an interned layout id (its recorded layout, buffers named by order), the render
|
||||||
|
|
|
||||||
|
|
@ -88,10 +88,10 @@ function gvk_layout_access(layout: int) -> int {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
# levels [base, base + n) of every layer of an image, from one layout to another
|
# levels [base, base + n) of every layer of an image, from one layout to another
|
||||||
function gvk_barrier(cb: pointer, image: long, depth: bool, base: int, n: int, layers: int, old_layout: int, new_layout: int) -> void {
|
function gvk_barrier(render3d_st: mut Render3dState, cb: pointer, image: long, depth: bool, base: int, n: int, layers: int, old_layout: int, new_layout: int) -> void {
|
||||||
# an image that was never made (its memory could not be had) has nothing to transition
|
# an image that was never made (its memory could not be had) has nothing to transition
|
||||||
if image == 0 { return }
|
if image == 0 { return }
|
||||||
let b = bytes(VkImageMemoryBarrier_sizeof)
|
let b = gvk_tmp(render3d_st, VkImageMemoryBarrier_sizeof)
|
||||||
Vk.zero(b, VkImageMemoryBarrier_sizeof)
|
Vk.zero(b, VkImageMemoryBarrier_sizeof)
|
||||||
Vk.put_i32(b, VkImageMemoryBarrier_sType, VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER)
|
Vk.put_i32(b, VkImageMemoryBarrier_sType, VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER)
|
||||||
Vk.put_i32(b, VkImageMemoryBarrier_srcAccessMask, gvk_layout_access(old_layout))
|
Vk.put_i32(b, VkImageMemoryBarrier_srcAccessMask, gvk_layout_access(old_layout))
|
||||||
|
|
@ -122,6 +122,7 @@ function gvk_staging(render3d_st: mut Render3dState, n: int, usage: int) -> poin
|
||||||
Vk.put_i32(bci, VkBufferCreateInfo_usage, usage)
|
Vk.put_i32(bci, VkBufferCreateInfo_usage, usage)
|
||||||
Vk.put_i32(bci, VkBufferCreateInfo_sharingMode, VK_SHARING_MODE_EXCLUSIVE)
|
Vk.put_i32(bci, VkBufferCreateInfo_sharingMode, VK_SHARING_MODE_EXCLUSIVE)
|
||||||
let out = bytes(8)
|
let out = bytes(8)
|
||||||
|
render3d_st.gvk_mk_buf += 1
|
||||||
if Vk.create_buffer(render3d_st.gvk_dev, bci, null, out) != VK_SUCCESS { return null }
|
if Vk.create_buffer(render3d_st.gvk_dev, bci, null, out) != VK_SUCCESS { return null }
|
||||||
render3d_st.gvk_st_buf = gvk_handle(out)
|
render3d_st.gvk_st_buf = gvk_handle(out)
|
||||||
let req = bytes(VkMemoryRequirements_sizeof)
|
let req = bytes(VkMemoryRequirements_sizeof)
|
||||||
|
|
@ -136,7 +137,9 @@ function gvk_staging(render3d_st: mut Render3dState, n: int, usage: int) -> poin
|
||||||
function gvk_staging_free(render3d_st: mut Render3dState) -> void {
|
function gvk_staging_free(render3d_st: mut Render3dState) -> void {
|
||||||
gvk_frame_wait(render3d_st) # the frame in flight may still read it
|
gvk_frame_wait(render3d_st) # the frame in flight may still read it
|
||||||
Vk.unmap_memory(render3d_st.gvk_dev, render3d_st.gvk_st_mem)
|
Vk.unmap_memory(render3d_st.gvk_dev, render3d_st.gvk_st_mem)
|
||||||
|
render3d_st.gvk_mk_x_buf += 1
|
||||||
Vk.destroy_buffer(render3d_st.gvk_dev, render3d_st.gvk_st_buf, null)
|
Vk.destroy_buffer(render3d_st.gvk_dev, render3d_st.gvk_st_buf, null)
|
||||||
|
render3d_st.gvk_mk_x_mem += 1
|
||||||
Vk.free_memory(render3d_st.gvk_dev, render3d_st.gvk_st_mem, null)
|
Vk.free_memory(render3d_st.gvk_dev, render3d_st.gvk_st_mem, null)
|
||||||
render3d_st.gvk_n_allocs -= 1
|
render3d_st.gvk_n_allocs -= 1
|
||||||
}
|
}
|
||||||
|
|
@ -175,6 +178,7 @@ function gvk_tex_storage(render3d_st: mut Render3dState, tex: int, array: bool,
|
||||||
Vk.put_i32(ici, VkImageCreateInfo_sharingMode, VK_SHARING_MODE_EXCLUSIVE)
|
Vk.put_i32(ici, VkImageCreateInfo_sharingMode, VK_SHARING_MODE_EXCLUSIVE)
|
||||||
Vk.put_i32(ici, VkImageCreateInfo_initialLayout, VK_IMAGE_LAYOUT_UNDEFINED)
|
Vk.put_i32(ici, VkImageCreateInfo_initialLayout, VK_IMAGE_LAYOUT_UNDEFINED)
|
||||||
let out = bytes(8)
|
let out = bytes(8)
|
||||||
|
render3d_st.gvk_mk_img += 1
|
||||||
var r = Vk.create_image(render3d_st.gvk_dev, ici, null, out)
|
var r = Vk.create_image(render3d_st.gvk_dev, ici, null, out)
|
||||||
if r != VK_SUCCESS { return gvk_fail(render3d_st, `vkCreateImage {w}x{h}x{layers} format {vkfmt}`, r) }
|
if r != VK_SUCCESS { return gvk_fail(render3d_st, `vkCreateImage {w}x{h}x{layers} format {vkfmt}`, r) }
|
||||||
let image = gvk_handle(out)
|
let image = gvk_handle(out)
|
||||||
|
|
@ -186,6 +190,7 @@ function gvk_tex_storage(render3d_st: mut Render3dState, tex: int, array: bool,
|
||||||
# no memory for it (one allocation per resource meets the driver's allocation limit long before
|
# no memory for it (one allocation per resource meets the driver's allocation limit long before
|
||||||
# the card is full): say so instead of binding a null allocation, which the driver may accept
|
# the card is full): say so instead of binding a null allocation, which the driver may accept
|
||||||
if mem == 0 {
|
if mem == 0 {
|
||||||
|
render3d_st.gvk_mk_x_img += 1
|
||||||
Vk.destroy_image(render3d_st.gvk_dev, image, null)
|
Vk.destroy_image(render3d_st.gvk_dev, image, null)
|
||||||
return gvk_fail(render3d_st, `no device memory for a {w}x{h}x{layers} image ({render3d_st.gvk_n_allocs} allocations live)`, VK_ERROR_OUT_OF_DEVICE_MEMORY)
|
return gvk_fail(render3d_st, `no device memory for a {w}x{h}x{layers} image ({render3d_st.gvk_n_allocs} allocations live)`, VK_ERROR_OUT_OF_DEVICE_MEMORY)
|
||||||
}
|
}
|
||||||
|
|
@ -201,6 +206,7 @@ function gvk_tex_storage(render3d_st: mut Render3dState, tex: int, array: bool,
|
||||||
if depth { Vk.put_i32(vci, sr + VkImageSubresourceRange_aspectMask, VK_IMAGE_ASPECT_DEPTH_BIT) } else { Vk.put_i32(vci, sr + VkImageSubresourceRange_aspectMask, VK_IMAGE_ASPECT_COLOR_BIT) }
|
if depth { Vk.put_i32(vci, sr + VkImageSubresourceRange_aspectMask, VK_IMAGE_ASPECT_DEPTH_BIT) } else { Vk.put_i32(vci, sr + VkImageSubresourceRange_aspectMask, VK_IMAGE_ASPECT_COLOR_BIT) }
|
||||||
Vk.put_i32(vci, sr + VkImageSubresourceRange_levelCount, levels)
|
Vk.put_i32(vci, sr + VkImageSubresourceRange_levelCount, levels)
|
||||||
Vk.put_i32(vci, sr + VkImageSubresourceRange_layerCount, layers)
|
Vk.put_i32(vci, sr + VkImageSubresourceRange_layerCount, layers)
|
||||||
|
render3d_st.gvk_mk_view += 1
|
||||||
r = Vk.create_image_view(render3d_st.gvk_dev, vci, null, out)
|
r = Vk.create_image_view(render3d_st.gvk_dev, vci, null, out)
|
||||||
if r != VK_SUCCESS { return gvk_fail(render3d_st, "vkCreateImageView", r) }
|
if r != VK_SUCCESS { return gvk_fail(render3d_st, "vkCreateImageView", r) }
|
||||||
render3d_st.gvk_tex_image[tex] = image; render3d_st.gvk_tex_view[tex] = gvk_handle(out); render3d_st.gvk_tex_mem[tex] = mem
|
render3d_st.gvk_tex_image[tex] = image; render3d_st.gvk_tex_view[tex] = gvk_handle(out); render3d_st.gvk_tex_mem[tex] = mem
|
||||||
|
|
@ -211,7 +217,7 @@ function gvk_tex_storage(render3d_st: mut Render3dState, tex: int, array: bool,
|
||||||
if array { render3d_st.gvk_tex_array[tex] = 1 } else { render3d_st.gvk_tex_array[tex] = 0 }
|
if array { render3d_st.gvk_tex_array[tex] = 1 } else { render3d_st.gvk_tex_array[tex] = 0 }
|
||||||
# a target starts cleared-to-nothing but readable: every level in the layout samplers expect
|
# a target starts cleared-to-nothing but readable: every level in the layout samplers expect
|
||||||
let cb = gvk_once_begin(render3d_st)
|
let cb = gvk_once_begin(render3d_st)
|
||||||
gvk_barrier(cb, image, depth, 0, levels, layers, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
|
gvk_barrier(render3d_st, cb, image, depth, 0, levels, layers, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
|
||||||
return gvk_once_end(render3d_st, cb)
|
return gvk_once_end(render3d_st, cb)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -248,7 +254,8 @@ function gvk_tex_upload(render3d_st: mut Render3dState, tex: int, ifmt: int, w:
|
||||||
let n = texels * cout * bout
|
let n = texels * cout * bout
|
||||||
let dst = gvk_staging(render3d_st, n, VK_BUFFER_USAGE_TRANSFER_SRC_BIT)
|
let dst = gvk_staging(render3d_st, n, VK_BUFFER_USAGE_TRANSFER_SRC_BIT)
|
||||||
if dst == null { print("r3d: vulkan: no staging buffer for an upload"); return false }
|
if dst == null { print("r3d: vulkan: no staging buffer for an upload"); return false }
|
||||||
let buf = bytes(n)
|
# written straight into the mapped staging memory: a copy of its own was never freed
|
||||||
|
let buf: pointer = dst
|
||||||
if cin == cout and bin == bout and not (bin == 2 and render3d_st.gvk_unpack_swap) {
|
if cin == cout and bin == bout and not (bin == 2 and render3d_st.gvk_unpack_swap) {
|
||||||
mem_copy(buf, data, n)
|
mem_copy(buf, data, n)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -281,12 +288,11 @@ function gvk_tex_upload(render3d_st: mut Render3dState, tex: int, ifmt: int, w:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mem_copy(dst, buf, n)
|
|
||||||
let image = render3d_st.gvk_tex_image[tex]
|
let image = render3d_st.gvk_tex_image[tex]
|
||||||
let depth = gvk_is_depth(ifmt)
|
let depth = gvk_is_depth(ifmt)
|
||||||
let levels = render3d_st.gvk_tex_levels[tex]
|
let levels = render3d_st.gvk_tex_levels[tex]
|
||||||
let cb = gvk_once_begin(render3d_st)
|
let cb = gvk_once_begin(render3d_st)
|
||||||
gvk_barrier(cb, image, depth, 0, levels, layers, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
|
gvk_barrier(render3d_st, cb, image, depth, 0, levels, layers, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
|
||||||
let bic = bytes(VkBufferImageCopy_sizeof)
|
let bic = bytes(VkBufferImageCopy_sizeof)
|
||||||
Vk.zero(bic, VkBufferImageCopy_sizeof)
|
Vk.zero(bic, VkBufferImageCopy_sizeof)
|
||||||
if depth { Vk.put_i32(bic, VkBufferImageCopy_imageSubresource + VkImageSubresourceLayers_aspectMask, VK_IMAGE_ASPECT_DEPTH_BIT) }
|
if depth { Vk.put_i32(bic, VkBufferImageCopy_imageSubresource + VkImageSubresourceLayers_aspectMask, VK_IMAGE_ASPECT_DEPTH_BIT) }
|
||||||
|
|
@ -296,7 +302,7 @@ function gvk_tex_upload(render3d_st: mut Render3dState, tex: int, ifmt: int, w:
|
||||||
Vk.put_i32(bic, VkBufferImageCopy_imageExtent + VkExtent3D_height, h)
|
Vk.put_i32(bic, VkBufferImageCopy_imageExtent + VkExtent3D_height, h)
|
||||||
Vk.put_i32(bic, VkBufferImageCopy_imageExtent + VkExtent3D_depth, 1)
|
Vk.put_i32(bic, VkBufferImageCopy_imageExtent + VkExtent3D_depth, 1)
|
||||||
Vk.cmd_copy_buffer_to_image(cb, render3d_st.gvk_st_buf, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, bic)
|
Vk.cmd_copy_buffer_to_image(cb, render3d_st.gvk_st_buf, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, bic)
|
||||||
gvk_barrier(cb, image, depth, 0, levels, layers, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
|
gvk_barrier(render3d_st, cb, image, depth, 0, levels, layers, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
|
||||||
let ok = gvk_once_end(render3d_st, cb)
|
let ok = gvk_once_end(render3d_st, cb)
|
||||||
gvk_staging_free(render3d_st)
|
gvk_staging_free(render3d_st)
|
||||||
return ok
|
return ok
|
||||||
|
|
@ -315,8 +321,8 @@ function gvk_tex_grow_mips(render3d_st: mut Render3dState, tex: int, w: int, h:
|
||||||
render3d_st.gvk_tex_image[tex] = zero
|
render3d_st.gvk_tex_image[tex] = zero
|
||||||
if not gvk_tex_storage(render3d_st, tex, render3d_st.gvk_tex_array[tex] == 1, render3d_st.gvk_tex_glfmt[tex], w, h, layers, true) { return false }
|
if not gvk_tex_storage(render3d_st, tex, render3d_st.gvk_tex_array[tex] == 1, render3d_st.gvk_tex_glfmt[tex], w, h, layers, true) { return false }
|
||||||
let cb = gvk_once_begin(render3d_st)
|
let cb = gvk_once_begin(render3d_st)
|
||||||
gvk_barrier(cb, old_image, false, 0, 1, layers, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)
|
gvk_barrier(render3d_st, cb, old_image, false, 0, 1, layers, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)
|
||||||
gvk_barrier(cb, render3d_st.gvk_tex_image[tex], false, 0, 1, layers, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
|
gvk_barrier(render3d_st, cb, render3d_st.gvk_tex_image[tex], false, 0, 1, layers, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
|
||||||
let ic = bytes(VkImageCopy_sizeof)
|
let ic = bytes(VkImageCopy_sizeof)
|
||||||
Vk.zero(ic, VkImageCopy_sizeof)
|
Vk.zero(ic, VkImageCopy_sizeof)
|
||||||
Vk.put_i32(ic, VkImageCopy_srcSubresource + VkImageSubresourceLayers_aspectMask, VK_IMAGE_ASPECT_COLOR_BIT)
|
Vk.put_i32(ic, VkImageCopy_srcSubresource + VkImageSubresourceLayers_aspectMask, VK_IMAGE_ASPECT_COLOR_BIT)
|
||||||
|
|
@ -327,9 +333,11 @@ function gvk_tex_grow_mips(render3d_st: mut Render3dState, tex: int, w: int, h:
|
||||||
Vk.put_i32(ic, VkImageCopy_extent + VkExtent3D_height, h)
|
Vk.put_i32(ic, VkImageCopy_extent + VkExtent3D_height, h)
|
||||||
Vk.put_i32(ic, VkImageCopy_extent + VkExtent3D_depth, 1)
|
Vk.put_i32(ic, VkImageCopy_extent + VkExtent3D_depth, 1)
|
||||||
Vk.cmd_copy_image(cb, old_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, render3d_st.gvk_tex_image[tex], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ic)
|
Vk.cmd_copy_image(cb, old_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, render3d_st.gvk_tex_image[tex], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ic)
|
||||||
gvk_barrier(cb, render3d_st.gvk_tex_image[tex], false, 0, 1, layers, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
|
gvk_barrier(render3d_st, cb, render3d_st.gvk_tex_image[tex], false, 0, 1, layers, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
|
||||||
let ok = gvk_once_end(render3d_st, cb)
|
let ok = gvk_once_end(render3d_st, cb)
|
||||||
|
render3d_st.gvk_mk_x_view += 1
|
||||||
Vk.destroy_image_view(render3d_st.gvk_dev, old_view, null)
|
Vk.destroy_image_view(render3d_st.gvk_dev, old_view, null)
|
||||||
|
render3d_st.gvk_mk_x_img += 1
|
||||||
Vk.destroy_image(render3d_st.gvk_dev, old_image, null)
|
Vk.destroy_image(render3d_st.gvk_dev, old_image, null)
|
||||||
gvk_mem_free(render3d_st, gvk_mem_id(old_mem))
|
gvk_mem_free(render3d_st, gvk_mem_id(old_mem))
|
||||||
return ok
|
return ok
|
||||||
|
|
@ -346,7 +354,7 @@ function gvk_tex_mips(render3d_st: mut Render3dState, tex: int, w: int, h: int)
|
||||||
return gvk_once_end(render3d_st, cb)
|
return gvk_once_end(render3d_st, cb)
|
||||||
}
|
}
|
||||||
# the chain's blits and barriers recorded into cb (the frame's own, when one is open)
|
# the chain's blits and barriers recorded into cb (the frame's own, when one is open)
|
||||||
function gvk_tex_mips_into(render3d_st: Render3dState, cb: pointer, tex: int, w: int, h: int) -> void {
|
function gvk_tex_mips_into(render3d_st: mut Render3dState, cb: pointer, tex: int, w: int, h: int) -> void {
|
||||||
let levels = render3d_st.gvk_tex_levels[tex]
|
let levels = render3d_st.gvk_tex_levels[tex]
|
||||||
if levels <= 1 { return }
|
if levels <= 1 { return }
|
||||||
let image = render3d_st.gvk_tex_image[tex]
|
let image = render3d_st.gvk_tex_image[tex]
|
||||||
|
|
@ -358,8 +366,8 @@ function gvk_tex_mips_into(render3d_st: Render3dState, cb: pointer, tex: int, w:
|
||||||
if dw < 1 { dw = 1 }
|
if dw < 1 { dw = 1 }
|
||||||
var dh = sh / 2
|
var dh = sh / 2
|
||||||
if dh < 1 { dh = 1 }
|
if dh < 1 { dh = 1 }
|
||||||
gvk_barrier(cb, image, false, lv - 1, 1, layers, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)
|
gvk_barrier(render3d_st, cb, image, false, lv - 1, 1, layers, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)
|
||||||
gvk_barrier(cb, image, false, lv, 1, layers, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
|
gvk_barrier(render3d_st, cb, image, false, lv, 1, layers, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
|
||||||
let blit = bytes(VkImageBlit_sizeof)
|
let blit = bytes(VkImageBlit_sizeof)
|
||||||
Vk.zero(blit, VkImageBlit_sizeof)
|
Vk.zero(blit, VkImageBlit_sizeof)
|
||||||
Vk.put_i32(blit, VkImageBlit_srcSubresource + VkImageSubresourceLayers_aspectMask, VK_IMAGE_ASPECT_COLOR_BIT)
|
Vk.put_i32(blit, VkImageBlit_srcSubresource + VkImageSubresourceLayers_aspectMask, VK_IMAGE_ASPECT_COLOR_BIT)
|
||||||
|
|
@ -375,8 +383,8 @@ function gvk_tex_mips_into(render3d_st: Render3dState, cb: pointer, tex: int, w:
|
||||||
Vk.put_i32(blit, VkImageBlit_dstOffsets + VkOffset3D_sizeof + VkOffset3D_y, dh)
|
Vk.put_i32(blit, VkImageBlit_dstOffsets + VkOffset3D_sizeof + VkOffset3D_y, dh)
|
||||||
Vk.put_i32(blit, VkImageBlit_dstOffsets + VkOffset3D_sizeof + VkOffset3D_z, 1)
|
Vk.put_i32(blit, VkImageBlit_dstOffsets + VkOffset3D_sizeof + VkOffset3D_z, 1)
|
||||||
Vk.cmd_blit_image(cb, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, blit, VK_FILTER_LINEAR)
|
Vk.cmd_blit_image(cb, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, blit, VK_FILTER_LINEAR)
|
||||||
gvk_barrier(cb, image, false, lv - 1, 1, layers, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
|
gvk_barrier(render3d_st, cb, image, false, lv - 1, 1, layers, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
|
||||||
gvk_barrier(cb, image, false, lv, 1, layers, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
|
gvk_barrier(render3d_st, cb, image, false, lv, 1, layers, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
|
||||||
sw = dw
|
sw = dw
|
||||||
sh = dh
|
sh = dh
|
||||||
}
|
}
|
||||||
|
|
@ -400,7 +408,7 @@ function gvk_tex_read(render3d_st: mut Render3dState, tex: int, ifmt: int, w: in
|
||||||
let image = render3d_st.gvk_tex_image[tex]
|
let image = render3d_st.gvk_tex_image[tex]
|
||||||
let depth = gvk_is_depth(ifmt)
|
let depth = gvk_is_depth(ifmt)
|
||||||
let cb = gvk_once_begin(render3d_st)
|
let cb = gvk_once_begin(render3d_st)
|
||||||
gvk_barrier(cb, image, depth, 0, 1, 1, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)
|
gvk_barrier(render3d_st, cb, image, depth, 0, 1, 1, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)
|
||||||
let bic = bytes(VkBufferImageCopy_sizeof)
|
let bic = bytes(VkBufferImageCopy_sizeof)
|
||||||
Vk.zero(bic, VkBufferImageCopy_sizeof)
|
Vk.zero(bic, VkBufferImageCopy_sizeof)
|
||||||
if depth { Vk.put_i32(bic, VkBufferImageCopy_imageSubresource + VkImageSubresourceLayers_aspectMask, VK_IMAGE_ASPECT_DEPTH_BIT) }
|
if depth { Vk.put_i32(bic, VkBufferImageCopy_imageSubresource + VkImageSubresourceLayers_aspectMask, VK_IMAGE_ASPECT_DEPTH_BIT) }
|
||||||
|
|
@ -410,7 +418,7 @@ function gvk_tex_read(render3d_st: mut Render3dState, tex: int, ifmt: int, w: in
|
||||||
Vk.put_i32(bic, VkBufferImageCopy_imageExtent + VkExtent3D_height, h)
|
Vk.put_i32(bic, VkBufferImageCopy_imageExtent + VkExtent3D_height, h)
|
||||||
Vk.put_i32(bic, VkBufferImageCopy_imageExtent + VkExtent3D_depth, 1)
|
Vk.put_i32(bic, VkBufferImageCopy_imageExtent + VkExtent3D_depth, 1)
|
||||||
Vk.cmd_copy_image_to_buffer(cb, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, render3d_st.gvk_st_buf, 1, bic)
|
Vk.cmd_copy_image_to_buffer(cb, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, render3d_st.gvk_st_buf, 1, bic)
|
||||||
gvk_barrier(cb, image, depth, 0, 1, 1, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
|
gvk_barrier(render3d_st, cb, image, depth, 0, 1, 1, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
|
||||||
let ok = gvk_once_end(render3d_st, cb)
|
let ok = gvk_once_end(render3d_st, cb)
|
||||||
if ok and cwant == cout { mem_copy(out, src, n) }
|
if ok and cwant == cout { mem_copy(out, src, n) }
|
||||||
if ok and cwant < cout {
|
if ok and cwant < cout {
|
||||||
|
|
@ -426,14 +434,39 @@ function gvk_tex_release(render3d_st: mut Render3dState, tex: int) -> void {
|
||||||
gvk_frame_wait(render3d_st) # the frame in flight may still read it
|
gvk_frame_wait(render3d_st) # the frame in flight may still read it
|
||||||
if render3d_st.gvk_tex_image[tex] == 0 { return }
|
if render3d_st.gvk_tex_image[tex] == 0 { return }
|
||||||
let zero: long = 0
|
let zero: long = 0
|
||||||
|
render3d_st.gvk_mk_x_view += 1
|
||||||
Vk.destroy_image_view(render3d_st.gvk_dev, render3d_st.gvk_tex_view[tex], null)
|
Vk.destroy_image_view(render3d_st.gvk_dev, render3d_st.gvk_tex_view[tex], null)
|
||||||
|
render3d_st.gvk_mk_x_img += 1
|
||||||
Vk.destroy_image(render3d_st.gvk_dev, render3d_st.gvk_tex_image[tex], null)
|
Vk.destroy_image(render3d_st.gvk_dev, render3d_st.gvk_tex_image[tex], null)
|
||||||
gvk_mem_free(render3d_st, gvk_mem_id(render3d_st.gvk_tex_mem[tex]))
|
gvk_mem_free(render3d_st, gvk_mem_id(render3d_st.gvk_tex_mem[tex]))
|
||||||
|
gvk_layer_views_drop(render3d_st, tex)
|
||||||
render3d_st.gvk_tex_image[tex] = zero; render3d_st.gvk_tex_view[tex] = zero; render3d_st.gvk_tex_mem[tex] = zero
|
render3d_st.gvk_tex_image[tex] = zero; render3d_st.gvk_tex_view[tex] = zero; render3d_st.gvk_tex_mem[tex] = zero
|
||||||
render3d_st.gvk_tex_levels[tex] = 0; render3d_st.gvk_tex_layers[tex] = 0; render3d_st.gvk_tex_vkfmt[tex] = 0
|
render3d_st.gvk_tex_levels[tex] = 0; render3d_st.gvk_tex_layers[tex] = 0; render3d_st.gvk_tex_vkfmt[tex] = 0
|
||||||
render3d_st.gvk_tex_gen[tex] = render3d_st.gvk_tex_gen[tex] + 1
|
render3d_st.gvk_tex_gen[tex] = render3d_st.gvk_tex_gen[tex] + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# the per-level and per-layer views gvk_view_of made of a texture go with it: kept, each held its
|
||||||
|
# old Metal texture alive, so every rebuild of the screen targets left the last set's memory behind
|
||||||
|
function gvk_layer_views_drop(render3d_st: mut Render3dState, tex: int) -> void {
|
||||||
|
if render3d_st.gvk_layer_views == null { return }
|
||||||
|
let keys = render3d_st.gvk_layer_views
|
||||||
|
let views = render3d_st.gvk_layer_view
|
||||||
|
let texs = render3d_st.gvk_layer_view_tex
|
||||||
|
var w = 0
|
||||||
|
for i in 0 .. len(keys) {
|
||||||
|
if texs[i] == tex {
|
||||||
|
render3d_st.gvk_mk_x_view += 1
|
||||||
|
Vk.destroy_image_view(render3d_st.gvk_dev, views[i], null)
|
||||||
|
} else {
|
||||||
|
keys[w] = keys[i]; views[w] = views[i]; texs[w] = texs[i]
|
||||||
|
w += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while len(keys) > w { List.pop(keys) }
|
||||||
|
while len(views) > w { List.pop(views) }
|
||||||
|
while len(texs) > w { List.pop(texs) }
|
||||||
|
}
|
||||||
|
|
||||||
# ---- samplers -----------------------------------------------------------------------------
|
# ---- samplers -----------------------------------------------------------------------------
|
||||||
# One VkSampler per distinct way of reading a texture, made the first time it is asked for.
|
# One VkSampler per distinct way of reading a texture, made the first time it is asked for.
|
||||||
# The arguments are what the renderer set through gpu_tex_param (0 where it set nothing, which
|
# The arguments are what the renderer set through gpu_tex_param (0 where it set nothing, which
|
||||||
|
|
@ -526,6 +559,7 @@ function gvk_sampler(render3d_st: mut Render3dState, min_f: int, mag_f: int, wra
|
||||||
Vk.put_i32(sci, VkSamplerCreateInfo_borderColor, VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE)
|
Vk.put_i32(sci, VkSamplerCreateInfo_borderColor, VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE)
|
||||||
let out = bytes(8)
|
let out = bytes(8)
|
||||||
let zero: long = 0
|
let zero: long = 0
|
||||||
|
render3d_st.gvk_mk_smp += 1
|
||||||
let r = Vk.create_sampler(render3d_st.gvk_dev, sci, null, out)
|
let r = Vk.create_sampler(render3d_st.gvk_dev, sci, null, out)
|
||||||
if r != VK_SUCCESS { gvk_fail(render3d_st, "vkCreateSampler", r); return zero }
|
if r != VK_SUCCESS { gvk_fail(render3d_st, "vkCreateSampler", r); return zero }
|
||||||
let s = gvk_handle(out)
|
let s = gvk_handle(out)
|
||||||
|
|
@ -564,6 +598,7 @@ function gvk_buf_release(render3d_st: mut Render3dState, b: int) -> void {
|
||||||
while len(render3d_st.gvk_retired_frame) < len(render3d_st.gvk_retired_buf) - 1 { push(render3d_st.gvk_retired_frame, 0) }
|
while len(render3d_st.gvk_retired_frame) < len(render3d_st.gvk_retired_buf) - 1 { push(render3d_st.gvk_retired_frame, 0) }
|
||||||
push(render3d_st.gvk_retired_frame, render3d_st.gvk_buf_used[b])
|
push(render3d_st.gvk_retired_frame, render3d_st.gvk_buf_used[b])
|
||||||
} else {
|
} else {
|
||||||
|
render3d_st.gvk_mk_x_buf += 1
|
||||||
Vk.destroy_buffer(render3d_st.gvk_dev, render3d_st.gvk_buf[b], null)
|
Vk.destroy_buffer(render3d_st.gvk_dev, render3d_st.gvk_buf[b], null)
|
||||||
gvk_mem_free(render3d_st, gvk_mem_id(render3d_st.gvk_buf_mem[b]))
|
gvk_mem_free(render3d_st, gvk_mem_id(render3d_st.gvk_buf_mem[b]))
|
||||||
}
|
}
|
||||||
|
|
@ -582,22 +617,27 @@ function gvk_retire_flush(render3d_st: mut Render3dState) -> void { gvk_retire_u
|
||||||
# the frame being recorded read stays
|
# the frame being recorded read stays
|
||||||
function gvk_retire_upto(render3d_st: mut Render3dState, done: int) -> void {
|
function gvk_retire_upto(render3d_st: mut Render3dState, done: int) -> void {
|
||||||
if render3d_st.gvk_retired_buf == null { return }
|
if render3d_st.gvk_retired_buf == null { return }
|
||||||
let keep_buf = new []long
|
if render3d_st.gvk_retired_frame == null { render3d_st.gvk_retired_frame = new []int }
|
||||||
let keep_mem = new []long
|
while len(render3d_st.gvk_retired_frame) < len(render3d_st.gvk_retired_buf) { push(render3d_st.gvk_retired_frame, 0) }
|
||||||
let keep_frame = new []int
|
# compacted in place: three fresh lists a frame were never given back
|
||||||
|
var w = 0
|
||||||
for i in 0 .. len(render3d_st.gvk_retired_buf) {
|
for i in 0 .. len(render3d_st.gvk_retired_buf) {
|
||||||
var f = 0
|
let f = render3d_st.gvk_retired_frame[i]
|
||||||
if render3d_st.gvk_retired_frame != null and i < len(render3d_st.gvk_retired_frame) { f = render3d_st.gvk_retired_frame[i] }
|
|
||||||
if f > done {
|
if f > done {
|
||||||
push(keep_buf, render3d_st.gvk_retired_buf[i]); push(keep_mem, render3d_st.gvk_retired_mem[i]); push(keep_frame, f)
|
render3d_st.gvk_retired_buf[w] = render3d_st.gvk_retired_buf[i]; render3d_st.gvk_retired_mem[w] = render3d_st.gvk_retired_mem[i]; render3d_st.gvk_retired_frame[w] = f
|
||||||
|
w += 1
|
||||||
} else {
|
} else {
|
||||||
|
render3d_st.gvk_mk_x_buf += 1
|
||||||
Vk.destroy_buffer(render3d_st.gvk_dev, render3d_st.gvk_retired_buf[i], null)
|
Vk.destroy_buffer(render3d_st.gvk_dev, render3d_st.gvk_retired_buf[i], null)
|
||||||
gvk_mem_free(render3d_st, gvk_mem_id(render3d_st.gvk_retired_mem[i]))
|
gvk_mem_free(render3d_st, gvk_mem_id(render3d_st.gvk_retired_mem[i]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
render3d_st.gvk_retired_buf = keep_buf
|
let rb = render3d_st.gvk_retired_buf
|
||||||
render3d_st.gvk_retired_mem = keep_mem
|
let rm = render3d_st.gvk_retired_mem
|
||||||
render3d_st.gvk_retired_frame = keep_frame
|
let rf = render3d_st.gvk_retired_frame
|
||||||
|
while len(rb) > w { List.pop(rb) }
|
||||||
|
while len(rm) > w { List.pop(rm) }
|
||||||
|
while len(rf) > w { List.pop(rf) }
|
||||||
}
|
}
|
||||||
|
|
||||||
# A buffer a compute pass writes: a draw later in the same frame reads what the GPU put there,
|
# A buffer a compute pass writes: a draw later in the same frame reads what the GPU put there,
|
||||||
|
|
@ -626,6 +666,7 @@ function gvk_buf_reserve(render3d_st: mut Render3dState, b: int, n: int) -> bool
|
||||||
Vk.put_i32(bci, VkBufferCreateInfo_usage, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)
|
Vk.put_i32(bci, VkBufferCreateInfo_usage, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)
|
||||||
Vk.put_i32(bci, VkBufferCreateInfo_sharingMode, VK_SHARING_MODE_EXCLUSIVE)
|
Vk.put_i32(bci, VkBufferCreateInfo_sharingMode, VK_SHARING_MODE_EXCLUSIVE)
|
||||||
let out = bytes(8)
|
let out = bytes(8)
|
||||||
|
render3d_st.gvk_mk_buf += 1
|
||||||
var r = Vk.create_buffer(render3d_st.gvk_dev, bci, null, out)
|
var r = Vk.create_buffer(render3d_st.gvk_dev, bci, null, out)
|
||||||
if r != VK_SUCCESS { return gvk_fail(render3d_st, `vkCreateBuffer ({size} bytes)`, r) }
|
if r != VK_SUCCESS { return gvk_fail(render3d_st, `vkCreateBuffer ({size} bytes)`, r) }
|
||||||
let buf = gvk_handle(out)
|
let buf = gvk_handle(out)
|
||||||
|
|
|
||||||
|
|
@ -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, 4, 0.0, 16.0)
|
||||||
gg_tiles(render3d_st, 8, 16.0, 40.0)
|
gg_tiles(render3d_st, 8, 16.0, 40.0)
|
||||||
gg_tiles(render3d_st, 16, 40.0, render3d_st.grass_radius)
|
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
|
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
|
cb[0] = render3d_st.gg_cmds
|
||||||
gpu_dispatch(render3d_st, render3d_st.gg_reset, data_of(rb), 16, cb, 1)
|
gpu_dispatch(render3d_st, render3d_st.gg_reset, data_of(rb), 16, cb, 1)
|
||||||
if render3d_st.gg_n == 0 { return }
|
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]
|
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)
|
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 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
|
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
|
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)
|
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
|
# grass_cull.comp's Params, std140: 12 vec4s, into the block made once in gg_cull_frame
|
||||||
function gg_params(render3d_st: Render3dState) -> words {
|
function gg_params(render3d_st: mut Render3dState) -> words {
|
||||||
let pr = words(48)
|
let pr = render3d_st.gg_pr
|
||||||
for i in 0 .. 48 { pr[i] = 0 }
|
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]) } }
|
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)
|
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)
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ vec3 bladeField(vec2 xz, float y) {
|
||||||
// dry and green patches a few metres across, and the tussocks' own shade of the same green
|
// dry and green patches a few metres across, and the tussocks' own shade of the same green
|
||||||
float dryp = smoothstep(0.2, 0.8, gnoise(xz * 0.33 + 17.0) * 0.5 + 0.5);
|
float dryp = smoothstep(0.2, 0.8, gnoise(xz * 0.33 + 17.0) * 0.5 + 0.5);
|
||||||
t *= mix(vec3(0.92, 1.0, 0.95), vec3(1.30, 1.10, 0.62), dryp);
|
t *= mix(vec3(0.92, 1.0, 0.95), vec3(1.30, 1.10, 0.62), dryp);
|
||||||
return t * (0.72 + 0.56 * (gnoise(xz * 1.9 + 41.0) * 0.5 + 0.5));
|
return t * (0.55 + 0.80 * (gnoise(xz * 1.9 + 41.0) * 0.5 + 0.5));
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ vec3 bladeField(vec2 xz, float y) {
|
||||||
t *= mix(vec3(0.7, 0.8, 0.55), vec3(1.1, 1.05, 0.85), patchy);
|
t *= mix(vec3(0.7, 0.8, 0.55), vec3(1.1, 1.05, 0.85), patchy);
|
||||||
float dryp = smoothstep(0.2, 0.8, gnoise(xz * 0.33 + 17.0) * 0.5 + 0.5);
|
float dryp = smoothstep(0.2, 0.8, gnoise(xz * 0.33 + 17.0) * 0.5 + 0.5);
|
||||||
t *= mix(vec3(0.92, 1.0, 0.95), vec3(1.30, 1.10, 0.62), dryp);
|
t *= mix(vec3(0.92, 1.0, 0.95), vec3(1.30, 1.10, 0.62), dryp);
|
||||||
return t * (0.72 + 0.56 * (gnoise(xz * 1.9 + 41.0) * 0.5 + 0.5));
|
return t * (0.55 + 0.80 * (gnoise(xz * 1.9 + 41.0) * 0.5 + 0.5));
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
|
@ -118,6 +118,13 @@ void main() {
|
||||||
uint o = (pr.base[b] + slot) * 4u;
|
uint o = (pr.base[b] + slot) * 4u;
|
||||||
outv[o] = vec4(xz.x, h - 0.02, xz.y, seed);
|
outv[o] = vec4(xz.x, h - 0.02, xz.y, seed);
|
||||||
outv[o + 1u] = vec4(sin(ang), cos(ang), tall, bw);
|
outv[o + 1u] = vec4(sin(ang), cos(ang), tall, bw);
|
||||||
outv[o + 2u] = vec4(bladeField(xz, h), 0.6 + 0.8 * h4);
|
// each blade its own: a hue a little toward olive or toward blue-green, and in a dry patch more
|
||||||
|
// of them gone to straw - a meadow is mixed blade by blade, not tinted as one
|
||||||
|
vec3 field = bladeField(xz, h);
|
||||||
|
float hj = bladeHash(ci, j, 7) - 0.5;
|
||||||
|
field *= vec3(1.0 + 0.30 * hj, 1.0, 1.0 - 0.30 * hj);
|
||||||
|
float dryp = smoothstep(0.2, 0.8, gnoise(xz * 0.33 + 17.0) * 0.5 + 0.5);
|
||||||
|
if (bladeHash(ci, j, 8) < 0.10 + 0.45 * dryp) field *= vec3(1.45, 1.18, 0.52);
|
||||||
|
outv[o + 2u] = vec4(field, 0.6 + 0.8 * h4);
|
||||||
outv[o + 3u] = vec4(gn, dist);
|
outv[o + 3u] = vec4(gn, dist);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -142,7 +142,9 @@ void main() {
|
||||||
// an occlusion term; grass albedo is capped near 0.5 and this was dividing it by five.
|
// an occlusion term; grass albedo is capped near 0.5 and this was dividing it by five.
|
||||||
// A blade is a thin thing standing in open air: shaded at the root by its neighbours,
|
// A blade is a thin thing standing in open air: shaded at the root by its neighbours,
|
||||||
// not buried.
|
// not buried.
|
||||||
arm = vec3(mix(0.55, 1.0, t), 0.85, 0.0);
|
// the inside of a sward is its own shade: a blade's base sits among its neighbours (the old clumps
|
||||||
|
// got this from the shadow maps, at 4.5 ms; seen from above it is most of a meadow's texture)
|
||||||
|
arm = vec3(mix(0.30, 1.0, smoothstep(0.0, 0.8, t)), 0.85, 0.0);
|
||||||
#elif defined(CARD)
|
#elif defined(CARD)
|
||||||
// thin grass is lit from either side: face the card toward the sun before shading
|
// thin grass is lit from either side: face the card toward the sun before shading
|
||||||
if (dot(N, u_sun_dir) < 0.0) N = -N;
|
if (dot(N, u_sun_dir) < 0.0) N = -N;
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -2996,10 +2996,11 @@ U 2e2908c8 frag u_half 828 float 1 0
|
||||||
U 2e2908c8 frag u_texel 832 float 1 0
|
U 2e2908c8 frag u_texel 832 float 1 0
|
||||||
U 2e2908c8 frag u_ortho_on 836 float 1 0
|
U 2e2908c8 frag u_ortho_on 836 float 1 0
|
||||||
U 2e2908c8 frag u_carpet_on 840 float 1 0
|
U 2e2908c8 frag u_carpet_on 840 float 1 0
|
||||||
U 2e2908c8 frag u_snow_line 844 float 1 0
|
U 2e2908c8 frag u_grass_reach 844 float 1 0
|
||||||
U 2e2908c8 frag u_lake_level 848 float 1 0
|
U 2e2908c8 frag u_snow_line 848 float 1 0
|
||||||
U 2e2908c8 frag u_wet 852 float 1 0
|
U 2e2908c8 frag u_lake_level 852 float 1 0
|
||||||
U 2e2908c8 frag u_sea_level 856 float 1 0
|
U 2e2908c8 frag u_wet 856 float 1 0
|
||||||
|
U 2e2908c8 frag u_sea_level 860 float 1 0
|
||||||
U 2e2908c8 frag u_lake 864 vec4 1 0
|
U 2e2908c8 frag u_lake 864 vec4 1 0
|
||||||
U 2e2908c8 frag u_origin 880 vec2 1 0
|
U 2e2908c8 frag u_origin 880 vec2 1 0
|
||||||
U 2e2908c8 frag u_view 896 mat4 1 0
|
U 2e2908c8 frag u_view 896 mat4 1 0
|
||||||
|
|
@ -3073,10 +3074,11 @@ U 1f95f31b frag u_half 828 float 1 0
|
||||||
U 1f95f31b frag u_texel 832 float 1 0
|
U 1f95f31b frag u_texel 832 float 1 0
|
||||||
U 1f95f31b frag u_ortho_on 836 float 1 0
|
U 1f95f31b frag u_ortho_on 836 float 1 0
|
||||||
U 1f95f31b frag u_carpet_on 840 float 1 0
|
U 1f95f31b frag u_carpet_on 840 float 1 0
|
||||||
U 1f95f31b frag u_snow_line 844 float 1 0
|
U 1f95f31b frag u_grass_reach 844 float 1 0
|
||||||
U 1f95f31b frag u_lake_level 848 float 1 0
|
U 1f95f31b frag u_snow_line 848 float 1 0
|
||||||
U 1f95f31b frag u_wet 852 float 1 0
|
U 1f95f31b frag u_lake_level 852 float 1 0
|
||||||
U 1f95f31b frag u_sea_level 856 float 1 0
|
U 1f95f31b frag u_wet 856 float 1 0
|
||||||
|
U 1f95f31b frag u_sea_level 860 float 1 0
|
||||||
U 1f95f31b frag u_lake 864 vec4 1 0
|
U 1f95f31b frag u_lake 864 vec4 1 0
|
||||||
U 1f95f31b frag u_origin 880 vec2 1 0
|
U 1f95f31b frag u_origin 880 vec2 1 0
|
||||||
U 1f95f31b frag u_view 896 mat4 1 0
|
U 1f95f31b frag u_view 896 mat4 1 0
|
||||||
|
|
@ -3150,10 +3152,11 @@ U f4382918 frag u_half 828 float 1 0
|
||||||
U f4382918 frag u_texel 832 float 1 0
|
U f4382918 frag u_texel 832 float 1 0
|
||||||
U f4382918 frag u_ortho_on 836 float 1 0
|
U f4382918 frag u_ortho_on 836 float 1 0
|
||||||
U f4382918 frag u_carpet_on 840 float 1 0
|
U f4382918 frag u_carpet_on 840 float 1 0
|
||||||
U f4382918 frag u_snow_line 844 float 1 0
|
U f4382918 frag u_grass_reach 844 float 1 0
|
||||||
U f4382918 frag u_lake_level 848 float 1 0
|
U f4382918 frag u_snow_line 848 float 1 0
|
||||||
U f4382918 frag u_wet 852 float 1 0
|
U f4382918 frag u_lake_level 852 float 1 0
|
||||||
U f4382918 frag u_sea_level 856 float 1 0
|
U f4382918 frag u_wet 856 float 1 0
|
||||||
|
U f4382918 frag u_sea_level 860 float 1 0
|
||||||
U f4382918 frag u_lake 864 vec4 1 0
|
U f4382918 frag u_lake 864 vec4 1 0
|
||||||
U f4382918 frag u_origin 880 vec2 1 0
|
U f4382918 frag u_origin 880 vec2 1 0
|
||||||
U f4382918 frag u_view 896 mat4 1 0
|
U f4382918 frag u_view 896 mat4 1 0
|
||||||
|
|
@ -3227,10 +3230,11 @@ U f2952361 frag u_half 828 float 1 0
|
||||||
U f2952361 frag u_texel 832 float 1 0
|
U f2952361 frag u_texel 832 float 1 0
|
||||||
U f2952361 frag u_ortho_on 836 float 1 0
|
U f2952361 frag u_ortho_on 836 float 1 0
|
||||||
U f2952361 frag u_carpet_on 840 float 1 0
|
U f2952361 frag u_carpet_on 840 float 1 0
|
||||||
U f2952361 frag u_snow_line 844 float 1 0
|
U f2952361 frag u_grass_reach 844 float 1 0
|
||||||
U f2952361 frag u_lake_level 848 float 1 0
|
U f2952361 frag u_snow_line 848 float 1 0
|
||||||
U f2952361 frag u_wet 852 float 1 0
|
U f2952361 frag u_lake_level 852 float 1 0
|
||||||
U f2952361 frag u_sea_level 856 float 1 0
|
U f2952361 frag u_wet 856 float 1 0
|
||||||
|
U f2952361 frag u_sea_level 860 float 1 0
|
||||||
U f2952361 frag u_lake 864 vec4 1 0
|
U f2952361 frag u_lake 864 vec4 1 0
|
||||||
U f2952361 frag u_origin 880 vec2 1 0
|
U f2952361 frag u_origin 880 vec2 1 0
|
||||||
U f2952361 frag u_view 896 mat4 1 0
|
U f2952361 frag u_view 896 mat4 1 0
|
||||||
|
|
@ -3304,10 +3308,11 @@ U a0f2dbac frag u_half 828 float 1 0
|
||||||
U a0f2dbac frag u_texel 832 float 1 0
|
U a0f2dbac frag u_texel 832 float 1 0
|
||||||
U a0f2dbac frag u_ortho_on 836 float 1 0
|
U a0f2dbac frag u_ortho_on 836 float 1 0
|
||||||
U a0f2dbac frag u_carpet_on 840 float 1 0
|
U a0f2dbac frag u_carpet_on 840 float 1 0
|
||||||
U a0f2dbac frag u_snow_line 844 float 1 0
|
U a0f2dbac frag u_grass_reach 844 float 1 0
|
||||||
U a0f2dbac frag u_lake_level 848 float 1 0
|
U a0f2dbac frag u_snow_line 848 float 1 0
|
||||||
U a0f2dbac frag u_wet 852 float 1 0
|
U a0f2dbac frag u_lake_level 852 float 1 0
|
||||||
U a0f2dbac frag u_sea_level 856 float 1 0
|
U a0f2dbac frag u_wet 856 float 1 0
|
||||||
|
U a0f2dbac frag u_sea_level 860 float 1 0
|
||||||
U a0f2dbac frag u_lake 864 vec4 1 0
|
U a0f2dbac frag u_lake 864 vec4 1 0
|
||||||
U a0f2dbac frag u_origin 880 vec2 1 0
|
U a0f2dbac frag u_origin 880 vec2 1 0
|
||||||
U a0f2dbac frag u_view 896 mat4 1 0
|
U a0f2dbac frag u_view 896 mat4 1 0
|
||||||
|
|
@ -3381,10 +3386,11 @@ U 5e4589a1 frag u_half 828 float 1 0
|
||||||
U 5e4589a1 frag u_texel 832 float 1 0
|
U 5e4589a1 frag u_texel 832 float 1 0
|
||||||
U 5e4589a1 frag u_ortho_on 836 float 1 0
|
U 5e4589a1 frag u_ortho_on 836 float 1 0
|
||||||
U 5e4589a1 frag u_carpet_on 840 float 1 0
|
U 5e4589a1 frag u_carpet_on 840 float 1 0
|
||||||
U 5e4589a1 frag u_snow_line 844 float 1 0
|
U 5e4589a1 frag u_grass_reach 844 float 1 0
|
||||||
U 5e4589a1 frag u_lake_level 848 float 1 0
|
U 5e4589a1 frag u_snow_line 848 float 1 0
|
||||||
U 5e4589a1 frag u_wet 852 float 1 0
|
U 5e4589a1 frag u_lake_level 852 float 1 0
|
||||||
U 5e4589a1 frag u_sea_level 856 float 1 0
|
U 5e4589a1 frag u_wet 856 float 1 0
|
||||||
|
U 5e4589a1 frag u_sea_level 860 float 1 0
|
||||||
U 5e4589a1 frag u_lake 864 vec4 1 0
|
U 5e4589a1 frag u_lake 864 vec4 1 0
|
||||||
U 5e4589a1 frag u_origin 880 vec2 1 0
|
U 5e4589a1 frag u_origin 880 vec2 1 0
|
||||||
U 5e4589a1 frag u_view 896 mat4 1 0
|
U 5e4589a1 frag u_view 896 mat4 1 0
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ uniform float u_ortho_on;
|
||||||
uniform sampler2D u_rock_d; uniform sampler2D u_rock_n; uniform sampler2D u_rock_a;
|
uniform sampler2D u_rock_d; uniform sampler2D u_rock_n; uniform sampler2D u_rock_a;
|
||||||
uniform sampler2D u_snow_d; uniform sampler2D u_carpet; // the clump cards baked straight down (alpha = coverage)
|
uniform sampler2D u_snow_d; uniform sampler2D u_carpet; // the clump cards baked straight down (alpha = coverage)
|
||||||
uniform float u_carpet_on;
|
uniform float u_carpet_on;
|
||||||
|
uniform float u_grass_reach; // where the GPU blades stop (0: none): the ground under them is in their shade
|
||||||
uniform float u_snow_line;
|
uniform float u_snow_line;
|
||||||
uniform float u_lake_level; // the ground just above the water is wet and dark
|
uniform float u_lake_level; // the ground just above the water is wet and dark
|
||||||
// ---- RAIN THAT LEAVES SOMETHING BEHIND -----------------------------------------------------
|
// ---- RAIN THAT LEAVES SOMETHING BEHIND -----------------------------------------------------
|
||||||
|
|
@ -339,6 +340,18 @@ vec3 groundShade(vec3 p, vec3 N, float slope, float dist, float viewDepth, bool
|
||||||
vec3 cc = cp.rgb * vec3(0.5, 0.57, 0.45) * mix(vec3(0.85, 0.92, 0.9), vec3(1.1, 1.05, 0.85), smoothstep(-0.35, 0.35, N.z)) * (0.75 + 0.35 * lush);
|
vec3 cc = cp.rgb * vec3(0.5, 0.57, 0.45) * mix(vec3(0.85, 0.92, 0.9), vec3(1.1, 1.05, 0.85), smoothstep(-0.35, 0.35, N.z)) * (0.75 + 0.35 * lush);
|
||||||
gA = mix(gA, cc, max(cp.a, 0.35) * carpetW * 0.97);
|
gA = mix(gA, cc, max(cp.a, 0.35) * carpetW * 0.97);
|
||||||
}
|
}
|
||||||
|
// The blades' own patches (grass_cull.comp's bladeField): patchiness and dry patches, so where
|
||||||
|
// the blades thin out the ground they stand on carries the same meadow, not a lawn
|
||||||
|
{
|
||||||
|
float patchy = fbmC(cheap, p.xz * 0.045, 3) * 0.5 + 0.5;
|
||||||
|
float dryp = smoothstep(0.2, 0.8, gnoise(p.xz * 0.33 + 17.0) * 0.5 + 0.5);
|
||||||
|
vec3 pf = mix(vec3(0.7, 0.8, 0.55), vec3(1.1, 1.05, 0.85), patchy) * mix(vec3(0.92, 1.0, 0.95), vec3(1.30, 1.10, 0.62), dryp);
|
||||||
|
// and the tussocks' own shade, half a metre across: where blades stand a pixel wide the ground
|
||||||
|
// is most of what shows, and it has to carry the same light and dark as the blades on it
|
||||||
|
float tus = 0.55 + 0.80 * (gnoise(p.xz * 1.9 + 41.0) * 0.5 + 0.5);
|
||||||
|
gA *= mix(vec3(1.0), pf / vec3(0.95, 0.96, 0.72) * tus, grassW);
|
||||||
|
if (u_grass_reach > 0.0) gA *= mix(1.0, mix(0.50, 1.0, smoothstep(u_grass_reach * 0.25, u_grass_reach, dist)), grassW);
|
||||||
|
}
|
||||||
// Subalpine forest floor: dark duff where the stands are dense. The photograph-driven
|
// Subalpine forest floor: dark duff where the stands are dense. The photograph-driven
|
||||||
// term marks duff only where the survey actually shows dense conifer, and is the same
|
// term marks duff only where the survey actually shows dense conifer, and is the same
|
||||||
// at any distance — ground shading must not depend on where the viewer is.
|
// at any distance — ground shading must not depend on where the viewer is.
|
||||||
|
|
|
||||||
|
|
@ -418,6 +418,9 @@ function terrain_bind_prog(render3d_st: mut Render3dState, p: int) -> void {
|
||||||
r3d_bind_2d(render3d_st, p, "u_snow_d", 10, render3d_st.ter_tex[9])
|
r3d_bind_2d(render3d_st, p, "u_snow_d", 10, render3d_st.ter_tex[9])
|
||||||
if render3d_st.ter_carpet != 0 { r3d_bind_2d(render3d_st, p, "u_carpet", 11, render3d_st.ter_carpet); u_f(render3d_st, gpu_uniform(render3d_st, p, "u_carpet_on"), 1.0) }
|
if render3d_st.ter_carpet != 0 { r3d_bind_2d(render3d_st, p, "u_carpet", 11, render3d_st.ter_carpet); u_f(render3d_st, gpu_uniform(render3d_st, p, "u_carpet_on"), 1.0) }
|
||||||
else { r3d_bind_2d(render3d_st, p, "u_carpet", 11, render3d_st.ter_tex[0]); u_f(render3d_st, gpu_uniform(render3d_st, p, "u_carpet_on"), 0.0) }
|
else { r3d_bind_2d(render3d_st, p, "u_carpet", 11, render3d_st.ter_tex[0]); u_f(render3d_st, gpu_uniform(render3d_st, p, "u_carpet_on"), 0.0) }
|
||||||
|
var reach = 0.0
|
||||||
|
if grass_live(render3d_st) { reach = render3d_st.grass_radius }
|
||||||
|
u_f(render3d_st, gpu_uniform(render3d_st, p, "u_grass_reach"), reach)
|
||||||
u_f(render3d_st, gpu_uniform(render3d_st, p, "u_half"), float(render3d_st.TERRAIN_HALF))
|
u_f(render3d_st, gpu_uniform(render3d_st, p, "u_half"), float(render3d_st.TERRAIN_HALF))
|
||||||
u_f(render3d_st, gpu_uniform(render3d_st, p, "u_texel"), 1.0 / float(TERRAIN_RES))
|
u_f(render3d_st, gpu_uniform(render3d_st, p, "u_texel"), 1.0 / float(TERRAIN_RES))
|
||||||
u_f(render3d_st, gpu_uniform(render3d_st, p, "u_snow_line"), render3d_st.ter_snow_line)
|
u_f(render3d_st, gpu_uniform(render3d_st, p, "u_snow_line"), render3d_st.ter_snow_line)
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,9 @@ import "vk_api.ludic"
|
||||||
# Vk.sl_active() says whether it was. Each Vk.sl_* is the sl* export of the same name and returns
|
# Vk.sl_active() says whether it was. Each Vk.sl_* is the sl* export of the same name and returns
|
||||||
# its sl::Result (0 is eOk); -1 means there is no Streamline (macOS, or the DLL missing). The
|
# its sl::Result (0 is eOk); -1 means there is no Streamline (macOS, or the DLL missing). The
|
||||||
# structs are plain memory, laid out as the SDK headers (include/sl_*.h, SDK 2.14.1) declare them.
|
# structs are plain memory, laid out as the SDK headers (include/sl_*.h, SDK 2.14.1) declare them.
|
||||||
|
# Once a frame: on macOS drains what MoltenVK and the layer autoreleased during the last one (a
|
||||||
|
# program pumping its own events has no other pool); nothing elsewhere.
|
||||||
|
extern function vk_frame_pool() = "lvk_frame_pool"
|
||||||
extern function vk_sl_prefer(on: int) = "lvk_sl_prefer"
|
extern function vk_sl_prefer(on: int) = "lvk_sl_prefer"
|
||||||
extern function vk_sl_active() -> int = "lvk_sl_active"
|
extern function vk_sl_active() -> int = "lvk_sl_active"
|
||||||
extern function vk_sl_init(pref: pointer, sdk_version: long) -> int = "lsl_slInit"
|
extern function vk_sl_init(pref: pointer, sdk_version: long) -> int = "lsl_slInit"
|
||||||
|
|
|
||||||
|
|
@ -225,3 +225,26 @@ entry:
|
||||||
%r = call i64 %fn(ptr %a0, ptr %a1)
|
%r = call i64 %fn(ptr %a0, ptr %a1)
|
||||||
ret i64 %r
|
ret i64 %r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; ---- the frame's autorelease pool --------------------------------------------------------------
|
||||||
|
; MoltenVK and CAMetalLayer autorelease objects on every frame (the drawable, each render pass's
|
||||||
|
; descriptor), and a program that pumps its own events never drains a pool: without this they are
|
||||||
|
; kept for the life of the process - 160 MB/s of small allocations in a windowed valley.
|
||||||
|
; lvk_frame_pool() pops the pool the last frame pushed and pushes the next one.
|
||||||
|
declare ptr @objc_autoreleasePoolPush()
|
||||||
|
declare void @objc_autoreleasePoolPop(ptr)
|
||||||
|
@lvk_pool = internal global ptr null
|
||||||
|
|
||||||
|
define void @lvk_frame_pool() {
|
||||||
|
entry:
|
||||||
|
%old = load ptr, ptr @lvk_pool
|
||||||
|
%have = icmp ne ptr %old, null
|
||||||
|
br i1 %have, label %pop, label %push
|
||||||
|
pop:
|
||||||
|
call void @objc_autoreleasePoolPop(ptr %old)
|
||||||
|
br label %push
|
||||||
|
push:
|
||||||
|
%p = call ptr @objc_autoreleasePoolPush()
|
||||||
|
store ptr %p, ptr @lvk_pool
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -363,3 +363,9 @@ entry:
|
||||||
%r = call i64 %fn(ptr %a0, ptr %a1)
|
%r = call i64 %fn(ptr %a0, ptr %a1)
|
||||||
ret i64 %r
|
ret i64 %r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; the frame's autorelease pool is a macOS matter (vk_mac.ll); Windows has nothing to drain
|
||||||
|
define void @lvk_frame_pool() {
|
||||||
|
entry:
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue