render3d: VkAllocationCallbacks counted (R3D_ALLOC_VK), pipeline create infos freed, actor pool at init
Plan 25.1c: vk_mac.ll's @lvk_ac (posix_memalign under a 16-byte header of scope/offset/size, atomic counters) passed at every render3d create/destroy (49 sites; the caps probe keeps its own null pair); lvk_ac_bytes/_peak/_allocs/_scope_bytes for the fence, Vk.alloc_bytes. vk_win.ll: null and 0. MoltenVK 1.4.2 counted 0 live bytes through them in steady. Fence findings: gvk_pipeline freed its 17 create infos (and reuses one bufs list); actor_init fills ac_spare with 512 records (actor_fresh, m4_new, v3_new at first placement in play). Compiled, not run (the user's call). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
edb33400b3
commit
df6ea046c3
10 changed files with 266 additions and 52 deletions
9
changes/render3d-plan25-vulkan.md
Normal file
9
changes/render3d-plan25-vulkan.md
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
bump: patch
|
||||||
|
type: fix
|
||||||
|
**Vulkan's host allocations can be counted, a pipeline built in play keeps nothing, and actors come
|
||||||
|
from a pool made at start-up.** With `R3D_ALLOC_VK=1` render3d hands one set of
|
||||||
|
`VkAllocationCallbacks` to every create and destroy; the runtime counts live bytes, the peak and
|
||||||
|
bytes per allocation scope (`lvk_ac_bytes`, `lvk_ac_peak`, `lvk_ac_scope_bytes`, `Vk.alloc_bytes`)
|
||||||
|
for the memory fence to read. MoltenVK 1.4.2 routes few of its own objects through them. A pipeline
|
||||||
|
made the first time a variant is drawn frees its seventeen create infos. `actor_init` makes 512 actor
|
||||||
|
records, so an actor first placed in play takes one instead of allocating.
|
||||||
|
|
@ -163,6 +163,18 @@ program Steady {
|
||||||
let am = gltf_load(render3d_st, "packages/ludic.lab/plate", "plate.gltf", "plate")
|
let am = gltf_load(render3d_st, "packages/ludic.lab/plate", "plate.gltf", "plate")
|
||||||
actor_rounds(render3d_st, am, 20)
|
actor_rounds(render3d_st, am, 20)
|
||||||
let grew_a = actor_rounds(render3d_st, am, 2000)
|
let grew_a = actor_rounds(render3d_st, am, 2000)
|
||||||
|
# with R3D_ALLOC_VK=1 MoltenVK's own host allocations are counted (plan 25.1c): what a frame
|
||||||
|
# leaves among them, read the same way
|
||||||
|
var vk_live: long = 0
|
||||||
|
var vk_grew: long = 0
|
||||||
|
if render3d_st.gvk_ac != null {
|
||||||
|
frame_rounds(render3d_st, 60)
|
||||||
|
let v0 = Vk.alloc_bytes()
|
||||||
|
frame_rounds(render3d_st, 600)
|
||||||
|
vk_live = Vk.alloc_bytes()
|
||||||
|
vk_grew = vk_live - v0
|
||||||
|
print(`steady: Vulkan's host allocations {vk_live} bytes live (object {Vk.alloc_scope_bytes(1)}, command {Vk.alloc_scope_bytes(0)}), a frame kept {vk_grew} over 600`)
|
||||||
|
}
|
||||||
let grew_r = ramp_rounds(render3d_st, am)
|
let grew_r = ramp_rounds(render3d_st, am)
|
||||||
let grew_s = stream_rounds(render3d_st, am)
|
let grew_s = stream_rounds(render3d_st, am)
|
||||||
let text = Fs.read_text("packages/ludic.lab/plate/plate.gltf")
|
let text = Fs.read_text("packages/ludic.lab/plate/plate.gltf")
|
||||||
|
|
@ -194,6 +206,11 @@ program Steady {
|
||||||
ok = false
|
ok = false
|
||||||
print("steady: FAILED - a frame drawing more than before leaves memory behind")
|
print("steady: FAILED - a frame drawing more than before leaves memory behind")
|
||||||
}
|
}
|
||||||
|
# MoltenVK 1.4.2 honours the callbacks for few of its objects (it read 0 live): only growth fails
|
||||||
|
if render3d_st.gvk_ac != null and vk_grew > 0 {
|
||||||
|
ok = false
|
||||||
|
print("steady: FAILED - Vulkan's counted host allocations grow with the frame")
|
||||||
|
}
|
||||||
if grew_s >= 4096 {
|
if grew_s >= 4096 {
|
||||||
ok = false
|
ok = false
|
||||||
print("steady: FAILED - streaming new ground leaves memory behind")
|
print("steady: FAILED - streaming new ground leaves memory behind")
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ property Actor {
|
||||||
outline: float = 0.0, # float bits: metres of rim drawn around it (0 = none)
|
outline: float = 0.0, # float bits: metres of rim drawn around it (0 = none)
|
||||||
ocol: floats # the rim's colour (null = white)
|
ocol: floats # the rim's colour (null = white)
|
||||||
}
|
}
|
||||||
|
const ACTOR_POOL: int = 512
|
||||||
# a program and its uniform locations
|
# a program and its uniform locations
|
||||||
property AcProg {
|
property AcProg {
|
||||||
prog: int = 0,
|
prog: int = 0,
|
||||||
|
|
@ -75,6 +76,16 @@ function ac_prog_new(render3d_st: mut Render3dState, vs: string, fs: string, def
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
function actor_init(render3d_st: mut Render3dState) -> void {
|
function actor_init(render3d_st: mut Render3dState) -> void {
|
||||||
|
# the records play takes, made now: an actor first placed in play (a fish, a sign, a bed) made its
|
||||||
|
# record, matrix and tint then (actor_release gives them back to this pool)
|
||||||
|
if render3d_st.ac_spare == null { render3d_st.ac_spare = new []Actor }
|
||||||
|
let sp = render3d_st.ac_spare
|
||||||
|
for i in 0 .. ACTOR_POOL {
|
||||||
|
let a = new Actor
|
||||||
|
a.tint = v3_new(1.0, 1.0, 1.0)
|
||||||
|
a.mat = m4_new()
|
||||||
|
push(sp, a)
|
||||||
|
}
|
||||||
render3d_st.ac_lit = ac_prog_new(render3d_st, "skin.vert", "model.frag", "")
|
render3d_st.ac_lit = ac_prog_new(render3d_st, "skin.vert", "model.frag", "")
|
||||||
render3d_st.ac_lit_cut = ac_prog_new(render3d_st, "skin.vert", "model.frag", "#define ALPHA_TEST\n")
|
render3d_st.ac_lit_cut = ac_prog_new(render3d_st, "skin.vert", "model.frag", "#define ALPHA_TEST\n")
|
||||||
render3d_st.ac_sh = ac_prog_new(render3d_st, "skin.vert", "shadow.frag", "#define SHADOW_PASS\n")
|
render3d_st.ac_sh = ac_prog_new(render3d_st, "skin.vert", "shadow.frag", "#define SHADOW_PASS\n")
|
||||||
|
|
|
||||||
|
|
@ -691,6 +691,8 @@ export state Render3dState {
|
||||||
stream_walks: int = 0 # streams that walked their whole ring this frame
|
stream_walks: int = 0 # streams that walked their whole ring this frame
|
||||||
stream_debug_n: int = 0
|
stream_debug_n: int = 0
|
||||||
stream_scratch: floats = null
|
stream_scratch: floats = null
|
||||||
|
gvk_pipe_bufs: words = null # a pipeline's vertex buffers, while it is made
|
||||||
|
gvk_ac: pointer = null # the VkAllocationCallbacks every create and destroy is given (R3D_ALLOC_VK=1)
|
||||||
gvk_prime_b: words = null # buffers made since the frame began, read once so MoltenVK makes their
|
gvk_prime_b: words = null # buffers made since the frame began, read once so MoltenVK makes their
|
||||||
gvk_prime_h: []long = null # Metal buffers now (gvk_prime), and their handles
|
gvk_prime_h: []long = null # Metal buffers now (gvk_prime), and their handles
|
||||||
gvk_prime_n: int = 0
|
gvk_prime_n: int = 0
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,9 @@ function gvk_no_command_pooling() -> void {
|
||||||
function gvk_init(render3d_st: mut Render3dState) -> bool {
|
function gvk_init(render3d_st: mut Render3dState) -> bool {
|
||||||
if render3d_st.gvk_ready { return true }
|
if render3d_st.gvk_ready { return true }
|
||||||
gvk_no_command_pooling()
|
gvk_no_command_pooling()
|
||||||
|
# MoltenVK's host allocations counted for the memory fence (plan 25.1c); every create and destroy
|
||||||
|
# is given the same callbacks, as Vulkan asks, so it is decided once, before the instance
|
||||||
|
if r3d_env_has(render3d_st, "R3D_ALLOC_VK") { render3d_st.gvk_ac = Vk.alloc_callbacks() }
|
||||||
gsl_boot(render3d_st)
|
gsl_boot(render3d_st)
|
||||||
if Vk.open() == 0 { render3d_st.gvk_why = "no Vulkan loader"; return false }
|
if Vk.open() == 0 { render3d_st.gvk_why = "no Vulkan loader"; return false }
|
||||||
gsl_init(render3d_st)
|
gsl_init(render3d_st)
|
||||||
|
|
@ -106,7 +109,7 @@ function gvk_init(render3d_st: mut Render3dState) -> bool {
|
||||||
Vk.put_ptr(ici, VkInstanceCreateInfo_ppEnabledExtensionNames, iext_names)
|
Vk.put_ptr(ici, VkInstanceCreateInfo_ppEnabledExtensionNames, iext_names)
|
||||||
}
|
}
|
||||||
let out = bytes(8)
|
let out = bytes(8)
|
||||||
var r = Vk.create_instance(ici, null, out)
|
var r = Vk.create_instance(ici, render3d_st.gvk_ac, out)
|
||||||
if r != VK_SUCCESS { return gvk_fail(render3d_st, "vkCreateInstance", r) }
|
if r != VK_SUCCESS { return gvk_fail(render3d_st, "vkCreateInstance", r) }
|
||||||
render3d_st.gvk_inst = Vk.get_ptr(out, 0)
|
render3d_st.gvk_inst = Vk.get_ptr(out, 0)
|
||||||
|
|
||||||
|
|
@ -261,7 +264,7 @@ function gvk_init(render3d_st: mut Render3dState) -> bool {
|
||||||
Vk.put_i32(dci, VkDeviceCreateInfo_enabledExtensionCount, n_dext)
|
Vk.put_i32(dci, VkDeviceCreateInfo_enabledExtensionCount, n_dext)
|
||||||
Vk.put_ptr(dci, VkDeviceCreateInfo_ppEnabledExtensionNames, dext_names)
|
Vk.put_ptr(dci, VkDeviceCreateInfo_ppEnabledExtensionNames, dext_names)
|
||||||
}
|
}
|
||||||
r = Vk.create_device(render3d_st.gvk_pd, dci, null, out)
|
r = Vk.create_device(render3d_st.gvk_pd, dci, render3d_st.gvk_ac, out)
|
||||||
if r != VK_SUCCESS { return gvk_fail(render3d_st, "vkCreateDevice", r) }
|
if r != VK_SUCCESS { return gvk_fail(render3d_st, "vkCreateDevice", r) }
|
||||||
render3d_st.gvk_dev = Vk.get_ptr(out, 0)
|
render3d_st.gvk_dev = Vk.get_ptr(out, 0)
|
||||||
Vk.get_device_queue(render3d_st.gvk_dev, render3d_st.gvk_family, 0, out)
|
Vk.get_device_queue(render3d_st.gvk_dev, render3d_st.gvk_family, 0, out)
|
||||||
|
|
@ -313,7 +316,7 @@ function gvk_alloc(render3d_st: mut Render3dState, req: bytes, want: int) -> lon
|
||||||
Vk.put_i32(mai, VkMemoryAllocateInfo_memoryTypeIndex, t)
|
Vk.put_i32(mai, VkMemoryAllocateInfo_memoryTypeIndex, t)
|
||||||
let out = gvk_tmp(render3d_st, 8)
|
let out = gvk_tmp(render3d_st, 8)
|
||||||
render3d_st.gvk_mk_mem += 1
|
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, render3d_st.gvk_ac, 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
|
||||||
return gvk_handle(out)
|
return gvk_handle(out)
|
||||||
|
|
@ -354,7 +357,7 @@ function gvk_mem_raw(render3d_st: mut Render3dState, t: int, size: int, host: bo
|
||||||
Vk.put_i32(mai, VkMemoryAllocateInfo_memoryTypeIndex, t)
|
Vk.put_i32(mai, VkMemoryAllocateInfo_memoryTypeIndex, t)
|
||||||
let out = gvk_tmp(render3d_st, 8)
|
let out = gvk_tmp(render3d_st, 8)
|
||||||
render3d_st.gvk_mk_mem += 1
|
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, render3d_st.gvk_ac, 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
|
||||||
let mem = gvk_handle(out)
|
let mem = gvk_handle(out)
|
||||||
|
|
@ -473,7 +476,7 @@ function gvk_mem_free(render3d_st: mut Render3dState, a: int) -> void {
|
||||||
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
|
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], render3d_st.gvk_ac)
|
||||||
render3d_st.gvk_n_allocs -= 1
|
render3d_st.gvk_n_allocs -= 1
|
||||||
} else {
|
} else {
|
||||||
var off = render3d_st.gvk_al_off[a]
|
var off = render3d_st.gvk_al_off[a]
|
||||||
|
|
@ -493,7 +496,7 @@ function gvk_mem_free(render3d_st: mut Render3dState, a: int) -> void {
|
||||||
# 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
|
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], render3d_st.gvk_ac)
|
||||||
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
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -515,17 +518,17 @@ function gvk_cmd_init(render3d_st: mut Render3dState) -> bool {
|
||||||
Vk.put_i32(cpi, VkCommandPoolCreateInfo_flags, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)
|
Vk.put_i32(cpi, VkCommandPoolCreateInfo_flags, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)
|
||||||
Vk.put_i32(cpi, VkCommandPoolCreateInfo_queueFamilyIndex, render3d_st.gvk_family)
|
Vk.put_i32(cpi, VkCommandPoolCreateInfo_queueFamilyIndex, render3d_st.gvk_family)
|
||||||
let out = bytes(8)
|
let out = bytes(8)
|
||||||
var r = Vk.create_command_pool(render3d_st.gvk_dev, cpi, null, out)
|
var r = Vk.create_command_pool(render3d_st.gvk_dev, cpi, render3d_st.gvk_ac, out)
|
||||||
if r != VK_SUCCESS { return gvk_fail(render3d_st, "vkCreateCommandPool", r) }
|
if r != VK_SUCCESS { return gvk_fail(render3d_st, "vkCreateCommandPool", r) }
|
||||||
render3d_st.gvk_pool = gvk_handle(out)
|
render3d_st.gvk_pool = gvk_handle(out)
|
||||||
let fci = bytes(VkFenceCreateInfo_sizeof)
|
let fci = bytes(VkFenceCreateInfo_sizeof)
|
||||||
Vk.zero(fci, VkFenceCreateInfo_sizeof)
|
Vk.zero(fci, VkFenceCreateInfo_sizeof)
|
||||||
Vk.put_i32(fci, VkFenceCreateInfo_sType, VK_STRUCTURE_TYPE_FENCE_CREATE_INFO)
|
Vk.put_i32(fci, VkFenceCreateInfo_sType, VK_STRUCTURE_TYPE_FENCE_CREATE_INFO)
|
||||||
render3d_st.gvk_fence = bytes(8)
|
render3d_st.gvk_fence = bytes(8)
|
||||||
r = Vk.create_fence(render3d_st.gvk_dev, fci, null, render3d_st.gvk_fence)
|
r = Vk.create_fence(render3d_st.gvk_dev, fci, render3d_st.gvk_ac, render3d_st.gvk_fence)
|
||||||
if r != VK_SUCCESS { return gvk_fail(render3d_st, "vkCreateFence", r) }
|
if r != VK_SUCCESS { return gvk_fail(render3d_st, "vkCreateFence", r) }
|
||||||
render3d_st.gvk_frame_fence = bytes(8)
|
render3d_st.gvk_frame_fence = bytes(8)
|
||||||
r = Vk.create_fence(render3d_st.gvk_dev, fci, null, render3d_st.gvk_frame_fence)
|
r = Vk.create_fence(render3d_st.gvk_dev, fci, render3d_st.gvk_ac, render3d_st.gvk_frame_fence)
|
||||||
if r != VK_SUCCESS { return gvk_fail(render3d_st, "vkCreateFence", r) }
|
if r != VK_SUCCESS { return gvk_fail(render3d_st, "vkCreateFence", r) }
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
@ -645,12 +648,12 @@ function gvk_shutdown(render3d_st: mut Render3dState) -> void {
|
||||||
gvk_frame_wait(render3d_st)
|
gvk_frame_wait(render3d_st)
|
||||||
Vk.device_wait_idle(render3d_st.gvk_dev)
|
Vk.device_wait_idle(render3d_st.gvk_dev)
|
||||||
gsl_shutdown(render3d_st)
|
gsl_shutdown(render3d_st)
|
||||||
Vk.destroy_fence(render3d_st.gvk_dev, Vk.get_i64(render3d_st.gvk_fence, 0), null)
|
Vk.destroy_fence(render3d_st.gvk_dev, Vk.get_i64(render3d_st.gvk_fence, 0), render3d_st.gvk_ac)
|
||||||
Vk.destroy_fence(render3d_st.gvk_dev, Vk.get_i64(render3d_st.gvk_frame_fence, 0), null)
|
Vk.destroy_fence(render3d_st.gvk_dev, Vk.get_i64(render3d_st.gvk_frame_fence, 0), render3d_st.gvk_ac)
|
||||||
Vk.destroy_command_pool(render3d_st.gvk_dev, render3d_st.gvk_pool, null)
|
Vk.destroy_command_pool(render3d_st.gvk_dev, render3d_st.gvk_pool, render3d_st.gvk_ac)
|
||||||
if render3d_st.gvk_prime_dst != 0 { Vk.destroy_buffer(render3d_st.gvk_dev, render3d_st.gvk_prime_dst, null); render3d_st.gvk_prime_dst = 0 }
|
if render3d_st.gvk_prime_dst != 0 { Vk.destroy_buffer(render3d_st.gvk_dev, render3d_st.gvk_prime_dst, render3d_st.gvk_ac); render3d_st.gvk_prime_dst = 0 }
|
||||||
Vk.destroy_device(render3d_st.gvk_dev, null)
|
Vk.destroy_device(render3d_st.gvk_dev, render3d_st.gvk_ac)
|
||||||
Vk.destroy_instance(render3d_st.gvk_inst, null)
|
Vk.destroy_instance(render3d_st.gvk_inst, render3d_st.gvk_ac)
|
||||||
render3d_st.gvk_ready = false
|
render3d_st.gvk_ready = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -668,7 +671,7 @@ function gvk_query_new(render3d_st: mut Render3dState, n: int, ids: words) -> vo
|
||||||
Vk.put_i32(qci, VkQueryPoolCreateInfo_queryType, VK_QUERY_TYPE_TIMESTAMP)
|
Vk.put_i32(qci, VkQueryPoolCreateInfo_queryType, VK_QUERY_TYPE_TIMESTAMP)
|
||||||
Vk.put_i32(qci, VkQueryPoolCreateInfo_queryCount, n * 2)
|
Vk.put_i32(qci, VkQueryPoolCreateInfo_queryCount, n * 2)
|
||||||
let out = gvk_tmp(render3d_st, 8)
|
let out = gvk_tmp(render3d_st, 8)
|
||||||
if Vk.create_query_pool(render3d_st.gvk_dev, qci, null, out) != VK_SUCCESS { return }
|
if Vk.create_query_pool(render3d_st.gvk_dev, qci, render3d_st.gvk_ac, out) != VK_SUCCESS { return }
|
||||||
render3d_st.gvk_qpool = gvk_handle(out)
|
render3d_st.gvk_qpool = gvk_handle(out)
|
||||||
Vk.reset_query_pool(render3d_st.gvk_dev, render3d_st.gvk_qpool, 0, n * 2)
|
Vk.reset_query_pool(render3d_st.gvk_dev, render3d_st.gvk_qpool, 0, n * 2)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ function gvk_module(render3d_st: mut Render3dState, path: string) -> long {
|
||||||
Vk.put_i64(smci, VkShaderModuleCreateInfo_codeSize, code_size)
|
Vk.put_i64(smci, VkShaderModuleCreateInfo_codeSize, code_size)
|
||||||
Vk.put_ptr(smci, VkShaderModuleCreateInfo_pCode, spv)
|
Vk.put_ptr(smci, VkShaderModuleCreateInfo_pCode, spv)
|
||||||
let out = bytes(8)
|
let out = bytes(8)
|
||||||
let r = Vk.create_shader_module(render3d_st.gvk_dev, smci, null, out)
|
let r = Vk.create_shader_module(render3d_st.gvk_dev, smci, render3d_st.gvk_ac, out)
|
||||||
if r != VK_SUCCESS { gvk_fail(render3d_st, `vkCreateShaderModule {path}`, r); return zero }
|
if r != VK_SUCCESS { gvk_fail(render3d_st, `vkCreateShaderModule {path}`, r); return zero }
|
||||||
return gvk_handle(out)
|
return gvk_handle(out)
|
||||||
}
|
}
|
||||||
|
|
@ -103,7 +103,7 @@ function gvk_program(render3d_st: mut Render3dState, p: int, key: string, spv_di
|
||||||
Vk.put_i32(dslci, VkDescriptorSetLayoutCreateInfo_bindingCount, nb)
|
Vk.put_i32(dslci, VkDescriptorSetLayoutCreateInfo_bindingCount, nb)
|
||||||
Vk.put_ptr(dslci, VkDescriptorSetLayoutCreateInfo_pBindings, binds)
|
Vk.put_ptr(dslci, VkDescriptorSetLayoutCreateInfo_pBindings, binds)
|
||||||
let dsl = bytes(8)
|
let dsl = bytes(8)
|
||||||
var r = Vk.create_descriptor_set_layout(render3d_st.gvk_dev, dslci, null, dsl)
|
var r = Vk.create_descriptor_set_layout(render3d_st.gvk_dev, dslci, render3d_st.gvk_ac, dsl)
|
||||||
if r != VK_SUCCESS { return gvk_fail(render3d_st, `vkCreateDescriptorSetLayout for {key}`, r) }
|
if r != VK_SUCCESS { return gvk_fail(render3d_st, `vkCreateDescriptorSetLayout for {key}`, r) }
|
||||||
let plci = bytes(VkPipelineLayoutCreateInfo_sizeof)
|
let plci = bytes(VkPipelineLayoutCreateInfo_sizeof)
|
||||||
Vk.zero(plci, VkPipelineLayoutCreateInfo_sizeof)
|
Vk.zero(plci, VkPipelineLayoutCreateInfo_sizeof)
|
||||||
|
|
@ -111,7 +111,7 @@ function gvk_program(render3d_st: mut Render3dState, p: int, key: string, spv_di
|
||||||
Vk.put_i32(plci, VkPipelineLayoutCreateInfo_setLayoutCount, 1)
|
Vk.put_i32(plci, VkPipelineLayoutCreateInfo_setLayoutCount, 1)
|
||||||
Vk.put_ptr(plci, VkPipelineLayoutCreateInfo_pSetLayouts, dsl)
|
Vk.put_ptr(plci, VkPipelineLayoutCreateInfo_pSetLayouts, dsl)
|
||||||
let out = bytes(8)
|
let out = bytes(8)
|
||||||
r = Vk.create_pipeline_layout(render3d_st.gvk_dev, plci, null, out)
|
r = Vk.create_pipeline_layout(render3d_st.gvk_dev, plci, render3d_st.gvk_ac, out)
|
||||||
if r != VK_SUCCESS { return gvk_fail(render3d_st, `vkCreatePipelineLayout for {key}`, r) }
|
if r != VK_SUCCESS { return gvk_fail(render3d_st, `vkCreatePipelineLayout for {key}`, r) }
|
||||||
render3d_st.gvk_prog_var[p] = v; render3d_st.gvk_prog_vs[p] = vs; render3d_st.gvk_prog_fs[p] = fs
|
render3d_st.gvk_prog_var[p] = v; render3d_st.gvk_prog_vs[p] = vs; render3d_st.gvk_prog_fs[p] = fs
|
||||||
render3d_st.gvk_prog_dsl[p] = Vk.get_i64(dsl, 0); render3d_st.gvk_prog_layout[p] = gvk_handle(out)
|
render3d_st.gvk_prog_dsl[p] = Vk.get_i64(dsl, 0); render3d_st.gvk_prog_layout[p] = gvk_handle(out)
|
||||||
|
|
@ -153,7 +153,7 @@ function gvk_compute_new_tex(render3d_st: mut Render3dState, name: string, n_buf
|
||||||
Vk.put_i32(dslci, VkDescriptorSetLayoutCreateInfo_bindingCount, nb)
|
Vk.put_i32(dslci, VkDescriptorSetLayoutCreateInfo_bindingCount, nb)
|
||||||
Vk.put_ptr(dslci, VkDescriptorSetLayoutCreateInfo_pBindings, binds)
|
Vk.put_ptr(dslci, VkDescriptorSetLayoutCreateInfo_pBindings, binds)
|
||||||
let dsl = bytes(8)
|
let dsl = bytes(8)
|
||||||
var r = Vk.create_descriptor_set_layout(render3d_st.gvk_dev, dslci, null, dsl)
|
var r = Vk.create_descriptor_set_layout(render3d_st.gvk_dev, dslci, render3d_st.gvk_ac, dsl)
|
||||||
if r != VK_SUCCESS { gvk_fail(render3d_st, `vkCreateDescriptorSetLayout for compute {name}`, r); return 0 }
|
if r != VK_SUCCESS { gvk_fail(render3d_st, `vkCreateDescriptorSetLayout for compute {name}`, r); return 0 }
|
||||||
let plci = bytes(VkPipelineLayoutCreateInfo_sizeof)
|
let plci = bytes(VkPipelineLayoutCreateInfo_sizeof)
|
||||||
Vk.zero(plci, VkPipelineLayoutCreateInfo_sizeof)
|
Vk.zero(plci, VkPipelineLayoutCreateInfo_sizeof)
|
||||||
|
|
@ -161,7 +161,7 @@ function gvk_compute_new_tex(render3d_st: mut Render3dState, name: string, n_buf
|
||||||
Vk.put_i32(plci, VkPipelineLayoutCreateInfo_setLayoutCount, 1)
|
Vk.put_i32(plci, VkPipelineLayoutCreateInfo_setLayoutCount, 1)
|
||||||
Vk.put_ptr(plci, VkPipelineLayoutCreateInfo_pSetLayouts, dsl)
|
Vk.put_ptr(plci, VkPipelineLayoutCreateInfo_pSetLayouts, dsl)
|
||||||
let out = bytes(8)
|
let out = bytes(8)
|
||||||
r = Vk.create_pipeline_layout(render3d_st.gvk_dev, plci, null, out)
|
r = Vk.create_pipeline_layout(render3d_st.gvk_dev, plci, render3d_st.gvk_ac, out)
|
||||||
if r != VK_SUCCESS { gvk_fail(render3d_st, `vkCreatePipelineLayout for compute {name}`, r); return 0 }
|
if r != VK_SUCCESS { gvk_fail(render3d_st, `vkCreatePipelineLayout for compute {name}`, r); return 0 }
|
||||||
let layout = gvk_handle(out)
|
let layout = gvk_handle(out)
|
||||||
let cpci = bytes(VkComputePipelineCreateInfo_sizeof)
|
let cpci = bytes(VkComputePipelineCreateInfo_sizeof)
|
||||||
|
|
@ -173,7 +173,7 @@ function gvk_compute_new_tex(render3d_st: mut Render3dState, name: string, n_buf
|
||||||
Vk.put_i64(cpci, so + VkPipelineShaderStageCreateInfo_module, module)
|
Vk.put_i64(cpci, so + VkPipelineShaderStageCreateInfo_module, module)
|
||||||
Vk.put_ptr(cpci, so + VkPipelineShaderStageCreateInfo_pName, "main")
|
Vk.put_ptr(cpci, so + VkPipelineShaderStageCreateInfo_pName, "main")
|
||||||
Vk.put_i64(cpci, VkComputePipelineCreateInfo_layout, layout)
|
Vk.put_i64(cpci, VkComputePipelineCreateInfo_layout, layout)
|
||||||
r = Vk.create_compute_pipelines(render3d_st.gvk_dev, zero, 1, cpci, null, out)
|
r = Vk.create_compute_pipelines(render3d_st.gvk_dev, zero, 1, cpci, render3d_st.gvk_ac, out)
|
||||||
if r != VK_SUCCESS { gvk_fail(render3d_st, `vkCreateComputePipelines {name}`, r); return 0 }
|
if r != VK_SUCCESS { gvk_fail(render3d_st, `vkCreateComputePipelines {name}`, r); return 0 }
|
||||||
push(render3d_st.gvk_cp_pipe, gvk_handle(out)); push(render3d_st.gvk_cp_layout, layout); push(render3d_st.gvk_cp_dsl, Vk.get_i64(dsl, 0)); push(render3d_st.gvk_cp_nbuf, n_bufs)
|
push(render3d_st.gvk_cp_pipe, gvk_handle(out)); push(render3d_st.gvk_cp_layout, layout); push(render3d_st.gvk_cp_dsl, Vk.get_i64(dsl, 0)); push(render3d_st.gvk_cp_nbuf, n_bufs)
|
||||||
push(render3d_st.gvk_cp_ntex, n_tex)
|
push(render3d_st.gvk_cp_ntex, n_tex)
|
||||||
|
|
@ -393,7 +393,7 @@ function gvk_pipeline(render3d_st: mut Render3dState, p: int, m: Mesh, st: GvkSt
|
||||||
let v = render3d_st.gvk_prog_var[p]
|
let v = render3d_st.gvk_prog_var[p]
|
||||||
if v == null { return zero }
|
if v == null { return zero }
|
||||||
let key = `{p}|{gvk_layout_key(m)}|{st.depth_test},{st.depth_write},{st.depth_func},{st.blend},{st.blend_src},{st.blend_dst},{st.cull},{st.cull_face},{st.color_write},{st.a2c},{st.bias},{st.bias_factor},{st.bias_units},{st.wireframe}|{n_color},{color_fmt},{depth_fmt},{samples}`
|
let key = `{p}|{gvk_layout_key(m)}|{st.depth_test},{st.depth_write},{st.depth_func},{st.blend},{st.blend_src},{st.blend_dst},{st.cull},{st.cull_face},{st.color_write},{st.a2c},{st.bias},{st.bias_factor},{st.bias_units},{st.wireframe}|{n_color},{color_fmt},{depth_fmt},{samples}`
|
||||||
if render3d_st.gvk_pipe_keys == null { render3d_st.gvk_pipe_keys = new []string; render3d_st.gvk_pipe = new []long }
|
if render3d_st.gvk_pipe_keys == null { render3d_st.gvk_pipe_keys = new []string; render3d_st.gvk_pipe = new []long; render3d_st.gvk_pipe_bufs = words(GPU_MAX_VBUFS) }
|
||||||
for i in 0 .. len(render3d_st.gvk_pipe_keys) { if render3d_st.gvk_pipe_keys[i] == key { return render3d_st.gvk_pipe[i] } }
|
for i in 0 .. len(render3d_st.gvk_pipe_keys) { if render3d_st.gvk_pipe_keys[i] == key { return render3d_st.gvk_pipe[i] } }
|
||||||
|
|
||||||
let ss = VkPipelineShaderStageCreateInfo_sizeof
|
let ss = VkPipelineShaderStageCreateInfo_sizeof
|
||||||
|
|
@ -419,7 +419,7 @@ function gvk_pipeline(render3d_st: mut Render3dState, p: int, m: Mesh, st: GvkSt
|
||||||
var na = 0
|
var na = 0
|
||||||
var nbd = 0
|
var nbd = 0
|
||||||
if m != null and m.attrs != null {
|
if m != null and m.attrs != null {
|
||||||
let bufs = words(GPU_MAX_VBUFS)
|
let bufs = render3d_st.gvk_pipe_bufs
|
||||||
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
|
||||||
if m.attrs[o + 1] == 0 { continue }
|
if m.attrs[o + 1] == 0 { continue }
|
||||||
|
|
@ -566,9 +566,12 @@ function gvk_pipeline(render3d_st: mut Render3dState, p: int, m: Mesh, st: GvkSt
|
||||||
Vk.put_ptr(gpci, VkGraphicsPipelineCreateInfo_pDynamicState, dys)
|
Vk.put_ptr(gpci, VkGraphicsPipelineCreateInfo_pDynamicState, dys)
|
||||||
Vk.put_i64(gpci, VkGraphicsPipelineCreateInfo_layout, render3d_st.gvk_prog_layout[p])
|
Vk.put_i64(gpci, VkGraphicsPipelineCreateInfo_layout, render3d_st.gvk_prog_layout[p])
|
||||||
let out = bytes(8)
|
let out = bytes(8)
|
||||||
let r = Vk.create_graphics_pipelines(render3d_st.gvk_dev, zero, 1, gpci, null, out)
|
let r = Vk.create_graphics_pipelines(render3d_st.gvk_dev, zero, 1, gpci, render3d_st.gvk_ac, out)
|
||||||
if r != VK_SUCCESS { gvk_fail(render3d_st, `vkCreateGraphicsPipelines for {v.vs} + {v.fs}`, r); return zero }
|
|
||||||
let pipe = gvk_handle(out)
|
let pipe = gvk_handle(out)
|
||||||
|
# the create infos are read by the create and go with it: a pipeline first met in play kept all of them
|
||||||
|
free(stages); free(attrs); free(bnds); free(vin); free(ias); free(vps); free(rs); free(ms); free(ds)
|
||||||
|
free(cba); free(cbs); free(dyn_states); free(dys); free(formats); free(prci); free(gpci); free(out)
|
||||||
|
if r != VK_SUCCESS { gvk_fail(render3d_st, `vkCreateGraphicsPipelines for {v.vs} + {v.fs}`, r); return zero }
|
||||||
# R3D_VK_PROF names each pipeline as it is made: one made during play is a stall a warm-up missed
|
# R3D_VK_PROF names each pipeline as it is made: one made during play is a stall a warm-up missed
|
||||||
if gvk_prof(render3d_st) { render3d_st.gvk_n_pipe_new += 1; print(`r3d: vulkan pipeline {len(render3d_st.gvk_pipe) + 1}: {v.vs} + {v.fs}, {n_color} colour format {color_fmt}, depth {depth_fmt}, {samples}x`) }
|
if gvk_prof(render3d_st) { render3d_st.gvk_n_pipe_new += 1; print(`r3d: vulkan pipeline {len(render3d_st.gvk_pipe) + 1}: {v.vs} + {v.fs}, {n_color} colour format {color_fmt}, depth {depth_fmt}, {samples}x`) }
|
||||||
push(render3d_st.gvk_pipe_keys, key)
|
push(render3d_st.gvk_pipe_keys, key)
|
||||||
|
|
@ -706,7 +709,7 @@ function gvk_frame_init(render3d_st: mut Render3dState) -> bool {
|
||||||
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
|
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, render3d_st.gvk_ac, 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))
|
||||||
}
|
}
|
||||||
|
|
@ -761,7 +764,7 @@ function gvk_kpool_make(render3d_st: mut Render3dState) -> bool {
|
||||||
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
|
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, render3d_st.gvk_ac, 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)
|
||||||
gvk_sc_clear(render3d_st)
|
gvk_sc_clear(render3d_st)
|
||||||
|
|
@ -1042,7 +1045,7 @@ function gvk_view_of(render3d_st: mut Render3dState, tex: int, layer1: int) -> l
|
||||||
let out = bytes(8)
|
let out = bytes(8)
|
||||||
let zero: long = 0
|
let zero: long = 0
|
||||||
render3d_st.gvk_mk_view += 1
|
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, render3d_st.gvk_ac, 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)
|
push(render3d_st.gvk_layer_view_tex, tex)
|
||||||
|
|
@ -1636,7 +1639,7 @@ function gvk_surface_os(render3d_st: mut Render3dState, out: pointer) -> bool {
|
||||||
Vk.zero(mci, VkMetalSurfaceCreateInfoEXT_sizeof)
|
Vk.zero(mci, VkMetalSurfaceCreateInfoEXT_sizeof)
|
||||||
Vk.put_i32(mci, VkMetalSurfaceCreateInfoEXT_sType, VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT)
|
Vk.put_i32(mci, VkMetalSurfaceCreateInfoEXT_sType, VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT)
|
||||||
Vk.put_ptr(mci, VkMetalSurfaceCreateInfoEXT_pLayer, layer)
|
Vk.put_ptr(mci, VkMetalSurfaceCreateInfoEXT_pLayer, layer)
|
||||||
let rm = Vk.create_metal_surface_ext(render3d_st.gvk_inst, mci, null, out)
|
let rm = Vk.create_metal_surface_ext(render3d_st.gvk_inst, mci, render3d_st.gvk_ac, out)
|
||||||
if rm != VK_SUCCESS { return gvk_fail(render3d_st, "vkCreateMetalSurfaceEXT", rm) }
|
if rm != VK_SUCCESS { return gvk_fail(render3d_st, "vkCreateMetalSurfaceEXT", rm) }
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
@ -1647,7 +1650,7 @@ function gvk_surface_os(render3d_st: mut Render3dState, out: pointer) -> bool {
|
||||||
Vk.put_i32(sci, VkWin32SurfaceCreateInfoKHR_sType, VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR)
|
Vk.put_i32(sci, VkWin32SurfaceCreateInfoKHR_sType, VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR)
|
||||||
Vk.put_ptr(sci, VkWin32SurfaceCreateInfoKHR_hinstance, win_native_instance())
|
Vk.put_ptr(sci, VkWin32SurfaceCreateInfoKHR_hinstance, win_native_instance())
|
||||||
Vk.put_ptr(sci, VkWin32SurfaceCreateInfoKHR_hwnd, hwnd)
|
Vk.put_ptr(sci, VkWin32SurfaceCreateInfoKHR_hwnd, hwnd)
|
||||||
let r = Vk.create_win32_surface_khr(render3d_st.gvk_inst, sci, null, out)
|
let r = Vk.create_win32_surface_khr(render3d_st.gvk_inst, sci, render3d_st.gvk_ac, out)
|
||||||
if r != VK_SUCCESS { return gvk_fail(render3d_st, "vkCreateWin32SurfaceKHR", r) }
|
if r != VK_SUCCESS { return gvk_fail(render3d_st, "vkCreateWin32SurfaceKHR", r) }
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
@ -1665,7 +1668,7 @@ function gvk_surface_make(render3d_st: mut Render3dState) -> bool {
|
||||||
Vk.zero(fci, VkFenceCreateInfo_sizeof)
|
Vk.zero(fci, VkFenceCreateInfo_sizeof)
|
||||||
Vk.put_i32(fci, VkFenceCreateInfo_sType, VK_STRUCTURE_TYPE_FENCE_CREATE_INFO)
|
Vk.put_i32(fci, VkFenceCreateInfo_sType, VK_STRUCTURE_TYPE_FENCE_CREATE_INFO)
|
||||||
render3d_st.gvk_acq_fence = bytes(8)
|
render3d_st.gvk_acq_fence = bytes(8)
|
||||||
return Vk.create_fence(render3d_st.gvk_dev, fci, null, render3d_st.gvk_acq_fence) == VK_SUCCESS
|
return Vk.create_fence(render3d_st.gvk_dev, fci, render3d_st.gvk_ac, render3d_st.gvk_acq_fence) == VK_SUCCESS
|
||||||
}
|
}
|
||||||
|
|
||||||
# (Re)make the swapchain for a w x h client area. The old one is handed over and then destroyed.
|
# (Re)make the swapchain for a w x h client area. The old one is handed over and then destroyed.
|
||||||
|
|
@ -1736,9 +1739,9 @@ function gvk_swap_make(render3d_st: mut Render3dState, w: int, h: int) -> bool {
|
||||||
Vk.put_i32(sci, VkSwapchainCreateInfoKHR_clipped, 1)
|
Vk.put_i32(sci, VkSwapchainCreateInfoKHR_clipped, 1)
|
||||||
Vk.put_i64(sci, VkSwapchainCreateInfoKHR_oldSwapchain, render3d_st.gvk_swap)
|
Vk.put_i64(sci, VkSwapchainCreateInfoKHR_oldSwapchain, render3d_st.gvk_swap)
|
||||||
let out = bytes(8)
|
let out = bytes(8)
|
||||||
let r = Vk.create_swapchain_khr(render3d_st.gvk_dev, sci, null, out)
|
let r = Vk.create_swapchain_khr(render3d_st.gvk_dev, sci, render3d_st.gvk_ac, out)
|
||||||
if r != VK_SUCCESS { return gvk_fail(render3d_st, "vkCreateSwapchainKHR", r) }
|
if r != VK_SUCCESS { return gvk_fail(render3d_st, "vkCreateSwapchainKHR", r) }
|
||||||
if render3d_st.gvk_swap != 0 { Vk.destroy_swapchain_khr(render3d_st.gvk_dev, render3d_st.gvk_swap, null) }
|
if render3d_st.gvk_swap != 0 { Vk.destroy_swapchain_khr(render3d_st.gvk_dev, render3d_st.gvk_swap, render3d_st.gvk_ac) }
|
||||||
render3d_st.gvk_swap = gvk_handle(out)
|
render3d_st.gvk_swap = gvk_handle(out)
|
||||||
if render3d_st.gvk_hdr_on and render3d_st.gvk_has_hdr_meta { gvk_hdr_metadata(render3d_st) }
|
if render3d_st.gvk_hdr_on and render3d_st.gvk_has_hdr_meta { gvk_hdr_metadata(render3d_st) }
|
||||||
Vk.put_i32(cnt, 0, 0)
|
Vk.put_i32(cnt, 0, 0)
|
||||||
|
|
|
||||||
|
|
@ -154,7 +154,7 @@ function gvk_staging(render3d_st: mut Render3dState, n: int, usage: int) -> poin
|
||||||
Vk.put_i32(bci, VkBufferCreateInfo_sharingMode, VK_SHARING_MODE_EXCLUSIVE)
|
Vk.put_i32(bci, VkBufferCreateInfo_sharingMode, VK_SHARING_MODE_EXCLUSIVE)
|
||||||
let out = gvk_tmp(render3d_st, 8)
|
let out = gvk_tmp(render3d_st, 8)
|
||||||
render3d_st.gvk_mk_buf += 1
|
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, render3d_st.gvk_ac, out) != VK_SUCCESS { return null }
|
||||||
render3d_st.gvk_st_buf = gvk_handle(out)
|
render3d_st.gvk_st_buf = gvk_handle(out)
|
||||||
let req = gvk_tmp(render3d_st, VkMemoryRequirements_sizeof)
|
let req = gvk_tmp(render3d_st, VkMemoryRequirements_sizeof)
|
||||||
Vk.get_buffer_memory_requirements(render3d_st.gvk_dev, render3d_st.gvk_st_buf, req)
|
Vk.get_buffer_memory_requirements(render3d_st.gvk_dev, render3d_st.gvk_st_buf, req)
|
||||||
|
|
@ -169,9 +169,9 @@ 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
|
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, render3d_st.gvk_ac)
|
||||||
render3d_st.gvk_mk_x_mem += 1
|
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, render3d_st.gvk_ac)
|
||||||
render3d_st.gvk_n_allocs -= 1
|
render3d_st.gvk_n_allocs -= 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -211,7 +211,7 @@ function gvk_tex_storage(render3d_st: mut Render3dState, tex: int, array: bool,
|
||||||
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
|
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, render3d_st.gvk_ac, out)
|
||||||
# the create infos are read by the call they are handed to and go straight after (a texture
|
# the create infos are read by the call they are handed to and go straight after (a texture
|
||||||
# made in play once left four of them behind)
|
# made in play once left four of them behind)
|
||||||
free(ici)
|
free(ici)
|
||||||
|
|
@ -230,7 +230,7 @@ function gvk_tex_storage(render3d_st: mut Render3dState, tex: int, array: bool,
|
||||||
# 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
|
render3d_st.gvk_mk_x_img += 1
|
||||||
Vk.destroy_image(render3d_st.gvk_dev, image, null)
|
Vk.destroy_image(render3d_st.gvk_dev, image, render3d_st.gvk_ac)
|
||||||
free(out)
|
free(out)
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
@ -250,7 +250,7 @@ function gvk_tex_storage(render3d_st: mut Render3dState, tex: int, array: bool,
|
||||||
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
|
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, render3d_st.gvk_ac, out)
|
||||||
free(vci)
|
free(vci)
|
||||||
let view = gvk_handle(out)
|
let view = gvk_handle(out)
|
||||||
free(out)
|
free(out)
|
||||||
|
|
@ -382,9 +382,9 @@ function gvk_tex_grow_mips(render3d_st: mut Render3dState, tex: int, w: int, h:
|
||||||
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)
|
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
|
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, render3d_st.gvk_ac)
|
||||||
render3d_st.gvk_mk_x_img += 1
|
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, render3d_st.gvk_ac)
|
||||||
gvk_mem_free(render3d_st, gvk_mem_id(old_mem))
|
gvk_mem_free(render3d_st, gvk_mem_id(old_mem))
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
@ -483,9 +483,9 @@ function gvk_tex_release(render3d_st: mut Render3dState, tex: int) -> void {
|
||||||
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
|
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], render3d_st.gvk_ac)
|
||||||
render3d_st.gvk_mk_x_img += 1
|
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], render3d_st.gvk_ac)
|
||||||
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)
|
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
|
||||||
|
|
@ -504,7 +504,7 @@ function gvk_layer_views_drop(render3d_st: mut Render3dState, tex: int) -> void
|
||||||
for i in 0 .. len(keys) {
|
for i in 0 .. len(keys) {
|
||||||
if texs[i] == tex {
|
if texs[i] == tex {
|
||||||
render3d_st.gvk_mk_x_view += 1
|
render3d_st.gvk_mk_x_view += 1
|
||||||
Vk.destroy_image_view(render3d_st.gvk_dev, views[i], null)
|
Vk.destroy_image_view(render3d_st.gvk_dev, views[i], render3d_st.gvk_ac)
|
||||||
} else {
|
} else {
|
||||||
keys[w] = keys[i]; views[w] = views[i]; texs[w] = texs[i]
|
keys[w] = keys[i]; views[w] = views[i]; texs[w] = texs[i]
|
||||||
w += 1
|
w += 1
|
||||||
|
|
@ -615,7 +615,7 @@ function gvk_sampler(render3d_st: mut Render3dState, min_f: int, mag_f: int, wra
|
||||||
let out = bytes(8)
|
let out = bytes(8)
|
||||||
let zero: long = 0
|
let zero: long = 0
|
||||||
render3d_st.gvk_mk_smp += 1
|
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, render3d_st.gvk_ac, 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)
|
||||||
push(ks, min_f); push(ks, mag_f); push(ks, wrap_s); push(ks, wrap_t); push(ks, compare); push(ks, aniso); push(ks, bias)
|
push(ks, min_f); push(ks, mag_f); push(ks, wrap_s); push(ks, wrap_t); push(ks, compare); push(ks, aniso); push(ks, bias)
|
||||||
|
|
@ -673,7 +673,7 @@ function gvk_buf_release(render3d_st: mut Render3dState, b: int) -> void {
|
||||||
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
|
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], render3d_st.gvk_ac)
|
||||||
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]))
|
||||||
}
|
}
|
||||||
render3d_st.gvk_buf[b] = zero; render3d_st.gvk_buf_mem[b] = zero; render3d_st.gvk_buf_size[b] = 0; render3d_st.gvk_buf_map[b] = null; render3d_st.gvk_buf_used[b] = 0
|
render3d_st.gvk_buf[b] = zero; render3d_st.gvk_buf_mem[b] = zero; render3d_st.gvk_buf_size[b] = 0; render3d_st.gvk_buf_map[b] = null; render3d_st.gvk_buf_used[b] = 0
|
||||||
|
|
@ -702,7 +702,7 @@ function gvk_retire_upto(render3d_st: mut Render3dState, done: int) -> void {
|
||||||
w += 1
|
w += 1
|
||||||
} else {
|
} else {
|
||||||
render3d_st.gvk_mk_x_buf += 1
|
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], render3d_st.gvk_ac)
|
||||||
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]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -741,14 +741,14 @@ function gvk_buf_reserve(render3d_st: mut Render3dState, b: int, n: int) -> bool
|
||||||
Vk.put_i32(bci, VkBufferCreateInfo_sharingMode, VK_SHARING_MODE_EXCLUSIVE)
|
Vk.put_i32(bci, VkBufferCreateInfo_sharingMode, VK_SHARING_MODE_EXCLUSIVE)
|
||||||
let out = gvk_tmp(render3d_st, 8)
|
let out = gvk_tmp(render3d_st, 8)
|
||||||
render3d_st.gvk_mk_buf += 1
|
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, render3d_st.gvk_ac, out)
|
||||||
if r != VK_SUCCESS { return gvk_fail(render3d_st, `vkCreateBuffer ({size} bytes)`, r) }
|
if r != VK_SUCCESS { return gvk_fail(render3d_st, `vkCreateBuffer ({size} bytes)`, r) }
|
||||||
let buf = gvk_handle(out)
|
let buf = gvk_handle(out)
|
||||||
let req = gvk_tmp(render3d_st, VkMemoryRequirements_sizeof)
|
let req = gvk_tmp(render3d_st, VkMemoryRequirements_sizeof)
|
||||||
Vk.get_buffer_memory_requirements(render3d_st.gvk_dev, buf, req)
|
Vk.get_buffer_memory_requirements(render3d_st.gvk_dev, buf, req)
|
||||||
let ma = gvk_mem_new(render3d_st, req, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, false)
|
let ma = gvk_mem_new(render3d_st, req, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, false)
|
||||||
let zero: long = 0
|
let zero: long = 0
|
||||||
if ma == 0 { Vk.destroy_buffer(render3d_st.gvk_dev, buf, null); return false }
|
if ma == 0 { Vk.destroy_buffer(render3d_st.gvk_dev, buf, render3d_st.gvk_ac); return false }
|
||||||
let mem: long = ma
|
let mem: long = ma
|
||||||
r = Vk.bind_buffer_memory(render3d_st.gvk_dev, buf, gvk_mem_handle(render3d_st, ma), gvk_mem_offset(render3d_st, ma))
|
r = Vk.bind_buffer_memory(render3d_st.gvk_dev, buf, gvk_mem_handle(render3d_st, ma), gvk_mem_offset(render3d_st, ma))
|
||||||
if r != VK_SUCCESS { return gvk_fail(render3d_st, "vkBindBufferMemory", r) }
|
if r != VK_SUCCESS { return gvk_fail(render3d_st, "vkBindBufferMemory", r) }
|
||||||
|
|
@ -810,13 +810,13 @@ function gvk_prime_target(render3d_st: mut Render3dState) -> bool {
|
||||||
Vk.put_i32(bci, VkBufferCreateInfo_usage, VK_BUFFER_USAGE_TRANSFER_DST_BIT)
|
Vk.put_i32(bci, VkBufferCreateInfo_usage, VK_BUFFER_USAGE_TRANSFER_DST_BIT)
|
||||||
Vk.put_i32(bci, VkBufferCreateInfo_sharingMode, VK_SHARING_MODE_EXCLUSIVE)
|
Vk.put_i32(bci, VkBufferCreateInfo_sharingMode, VK_SHARING_MODE_EXCLUSIVE)
|
||||||
let out = gvk_tmp(render3d_st, 8)
|
let out = gvk_tmp(render3d_st, 8)
|
||||||
if Vk.create_buffer(render3d_st.gvk_dev, bci, null, out) != VK_SUCCESS { return false }
|
if Vk.create_buffer(render3d_st.gvk_dev, bci, render3d_st.gvk_ac, out) != VK_SUCCESS { return false }
|
||||||
let buf = gvk_handle(out)
|
let buf = gvk_handle(out)
|
||||||
let req = gvk_tmp(render3d_st, VkMemoryRequirements_sizeof)
|
let req = gvk_tmp(render3d_st, VkMemoryRequirements_sizeof)
|
||||||
Vk.get_buffer_memory_requirements(render3d_st.gvk_dev, buf, req)
|
Vk.get_buffer_memory_requirements(render3d_st.gvk_dev, buf, req)
|
||||||
let ma = gvk_mem_new(render3d_st, req, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, false)
|
let ma = gvk_mem_new(render3d_st, req, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, false)
|
||||||
if ma == 0 {
|
if ma == 0 {
|
||||||
Vk.destroy_buffer(render3d_st.gvk_dev, buf, null)
|
Vk.destroy_buffer(render3d_st.gvk_dev, buf, render3d_st.gvk_ac)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
Vk.bind_buffer_memory(render3d_st.gvk_dev, buf, gvk_mem_handle(render3d_st, ma), gvk_mem_offset(render3d_st, ma))
|
Vk.bind_buffer_memory(render3d_st.gvk_dev, buf, gvk_mem_handle(render3d_st, ma), gvk_mem_offset(render3d_st, ma))
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,11 @@ import "vk_api.ludic"
|
||||||
extern function vk_frame_pool() = "lvk_frame_pool"
|
extern function vk_frame_pool() = "lvk_frame_pool"
|
||||||
# malloc's live bytes (macOS; 0 elsewhere): a test that a path allocates nothing, frame after frame
|
# malloc's live bytes (macOS; 0 elsewhere): a test that a path allocates nothing, frame after frame
|
||||||
extern function vk_heap_bytes() -> long = "lvk_heap_bytes"
|
extern function vk_heap_bytes() -> long = "lvk_heap_bytes"
|
||||||
|
# the VkAllocationCallbacks that count MoltenVK's host allocations (memory plan 25.1c; null on
|
||||||
|
# Windows), and what they count: live bytes now, and per VkSystemAllocationScope
|
||||||
|
extern function vk_alloc_callbacks() -> pointer = "lvk_ac_ptr"
|
||||||
|
extern function vk_alloc_bytes() -> long = "lvk_ac_bytes"
|
||||||
|
extern function vk_alloc_scope_bytes(scope: int) -> long = "lvk_ac_scope_bytes"
|
||||||
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"
|
||||||
|
|
|
||||||
|
|
@ -264,3 +264,144 @@ entry:
|
||||||
%n = load i64, ptr %p
|
%n = load i64, ptr %p
|
||||||
ret i64 %n
|
ret i64 %n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; VkAllocationCallbacks (memory plan 25.1c): render3d hands @lvk_ac to every Vulkan create and
|
||||||
|
; destroy when R3D_ALLOC_VK=1, so MoltenVK's own host allocations are counted - live bytes, the peak,
|
||||||
|
; allocations made and bytes per VkSystemAllocationScope - for the fence to read (lvk_ac_*).
|
||||||
|
; Metal's own allocations are never seen here. libc underneath, never the fence's allocator. Each
|
||||||
|
; block carries a 16-byte header before it: scope (i32), the offset to malloc's block (i32), size
|
||||||
|
; (i64); the offset is the alignment asked, at least 16, so the block keeps it. The counters are
|
||||||
|
; atomics: MoltenVK allocates from its completion handlers' threads too.
|
||||||
|
@lvk_ac_live = global i64 0
|
||||||
|
@lvk_ac_peak_v = global i64 0
|
||||||
|
@lvk_ac_n = global i64 0
|
||||||
|
@lvk_ac_scope = global [5 x i64] zeroinitializer
|
||||||
|
@lvk_ac = global [6 x ptr] [ptr null, ptr @lvk_ac_alloc, ptr @lvk_ac_realloc, ptr @lvk_ac_free, ptr null, ptr null]
|
||||||
|
declare i32 @posix_memalign(ptr, i64, i64)
|
||||||
|
declare void @free(ptr)
|
||||||
|
declare ptr @memcpy(ptr, ptr, i64)
|
||||||
|
|
||||||
|
define internal void @lvk_ac_count(i32 %scope, i64 %d, i64 %n) {
|
||||||
|
entry:
|
||||||
|
%old = atomicrmw add ptr @lvk_ac_live, i64 %d seq_cst
|
||||||
|
%new = add i64 %old, %d
|
||||||
|
%pk = atomicrmw max ptr @lvk_ac_peak_v, i64 %new seq_cst
|
||||||
|
%nn = atomicrmw add ptr @lvk_ac_n, i64 %n seq_cst
|
||||||
|
%lo = icmp slt i32 %scope, 0
|
||||||
|
%hi = icmp sgt i32 %scope, 4
|
||||||
|
%bad = or i1 %lo, %hi
|
||||||
|
%sc = select i1 %bad, i32 1, i32 %scope
|
||||||
|
%sp = getelementptr [5 x i64], ptr @lvk_ac_scope, i32 0, i32 %sc
|
||||||
|
%sv = atomicrmw add ptr %sp, i64 %d seq_cst
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
define internal ptr @lvk_ac_alloc(ptr %ud, i64 %size, i64 %align, i32 %scope) {
|
||||||
|
entry:
|
||||||
|
%z = icmp eq i64 %size, 0
|
||||||
|
br i1 %z, label %none, label %go
|
||||||
|
none:
|
||||||
|
ret ptr null
|
||||||
|
go:
|
||||||
|
%small = icmp ult i64 %align, 16
|
||||||
|
%a = select i1 %small, i64 16, i64 %align
|
||||||
|
%tot = add i64 %size, %a
|
||||||
|
%slot = alloca ptr, align 8
|
||||||
|
%r = call i32 @posix_memalign(ptr %slot, i64 %a, i64 %tot)
|
||||||
|
%ok = icmp eq i32 %r, 0
|
||||||
|
br i1 %ok, label %have, label %none
|
||||||
|
have:
|
||||||
|
%base = load ptr, ptr %slot
|
||||||
|
%p = getelementptr i8, ptr %base, i64 %a
|
||||||
|
%h = getelementptr i8, ptr %p, i64 -16
|
||||||
|
store i32 %scope, ptr %h
|
||||||
|
%ha = getelementptr i8, ptr %h, i64 4
|
||||||
|
%a32 = trunc i64 %a to i32
|
||||||
|
store i32 %a32, ptr %ha
|
||||||
|
%hs = getelementptr i8, ptr %h, i64 8
|
||||||
|
store i64 %size, ptr %hs
|
||||||
|
call void @lvk_ac_count(i32 %scope, i64 %size, i64 1)
|
||||||
|
ret ptr %p
|
||||||
|
}
|
||||||
|
define internal void @lvk_ac_free(ptr %ud, ptr %p) {
|
||||||
|
entry:
|
||||||
|
%z = icmp eq ptr %p, null
|
||||||
|
br i1 %z, label %done, label %go
|
||||||
|
done:
|
||||||
|
ret void
|
||||||
|
go:
|
||||||
|
%h = getelementptr i8, ptr %p, i64 -16
|
||||||
|
%scope = load i32, ptr %h
|
||||||
|
%ha = getelementptr i8, ptr %h, i64 4
|
||||||
|
%a32 = load i32, ptr %ha
|
||||||
|
%hs = getelementptr i8, ptr %h, i64 8
|
||||||
|
%size = load i64, ptr %hs
|
||||||
|
%neg = sub i64 0, %size
|
||||||
|
call void @lvk_ac_count(i32 %scope, i64 %neg, i64 0)
|
||||||
|
%a = zext i32 %a32 to i64
|
||||||
|
%na = sub i64 0, %a
|
||||||
|
%base = getelementptr i8, ptr %p, i64 %na
|
||||||
|
call void @free(ptr %base)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
; a new block at the asked alignment, the old one's bytes copied, the old one freed: realloc itself
|
||||||
|
; only keeps 16
|
||||||
|
define internal ptr @lvk_ac_realloc(ptr %ud, ptr %old, i64 %size, i64 %align, i32 %scope) {
|
||||||
|
entry:
|
||||||
|
%nold = icmp eq ptr %old, null
|
||||||
|
br i1 %nold, label %fresh, label %chk
|
||||||
|
fresh:
|
||||||
|
%f = call ptr @lvk_ac_alloc(ptr %ud, i64 %size, i64 %align, i32 %scope)
|
||||||
|
ret ptr %f
|
||||||
|
chk:
|
||||||
|
%z = icmp eq i64 %size, 0
|
||||||
|
br i1 %z, label %drop, label %move
|
||||||
|
drop:
|
||||||
|
call void @lvk_ac_free(ptr %ud, ptr %old)
|
||||||
|
ret ptr null
|
||||||
|
move:
|
||||||
|
%nb = call ptr @lvk_ac_alloc(ptr %ud, i64 %size, i64 %align, i32 %scope)
|
||||||
|
%nz = icmp eq ptr %nb, null
|
||||||
|
br i1 %nz, label %fail, label %copy
|
||||||
|
fail:
|
||||||
|
ret ptr null
|
||||||
|
copy:
|
||||||
|
%hs = getelementptr i8, ptr %old, i64 -8
|
||||||
|
%osz = load i64, ptr %hs
|
||||||
|
%less = icmp ult i64 %osz, %size
|
||||||
|
%n = select i1 %less, i64 %osz, i64 %size
|
||||||
|
%cp = call ptr @memcpy(ptr %nb, ptr %old, i64 %n)
|
||||||
|
call void @lvk_ac_free(ptr %ud, ptr %old)
|
||||||
|
ret ptr %nb
|
||||||
|
}
|
||||||
|
define ptr @lvk_ac_ptr() {
|
||||||
|
entry:
|
||||||
|
ret ptr @lvk_ac
|
||||||
|
}
|
||||||
|
define i64 @lvk_ac_bytes() {
|
||||||
|
entry:
|
||||||
|
%v = load atomic i64, ptr @lvk_ac_live seq_cst, align 8
|
||||||
|
ret i64 %v
|
||||||
|
}
|
||||||
|
define i64 @lvk_ac_peak() {
|
||||||
|
entry:
|
||||||
|
%v = load atomic i64, ptr @lvk_ac_peak_v seq_cst, align 8
|
||||||
|
ret i64 %v
|
||||||
|
}
|
||||||
|
define i64 @lvk_ac_allocs() {
|
||||||
|
entry:
|
||||||
|
%v = load atomic i64, ptr @lvk_ac_n seq_cst, align 8
|
||||||
|
ret i64 %v
|
||||||
|
}
|
||||||
|
define i64 @lvk_ac_scope_bytes(i32 %scope) {
|
||||||
|
entry:
|
||||||
|
%lo = icmp slt i32 %scope, 0
|
||||||
|
%hi = icmp sgt i32 %scope, 4
|
||||||
|
%bad = or i1 %lo, %hi
|
||||||
|
br i1 %bad, label %none, label %read
|
||||||
|
none:
|
||||||
|
ret i64 0
|
||||||
|
read:
|
||||||
|
%sp = getelementptr [5 x i64], ptr @lvk_ac_scope, i32 0, i32 %scope
|
||||||
|
%v = load atomic i64, ptr %sp seq_cst, align 8
|
||||||
|
ret i64 %v
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -375,3 +375,26 @@ define i64 @lvk_heap_bytes() {
|
||||||
entry:
|
entry:
|
||||||
ret i64 0
|
ret i64 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; VkAllocationCallbacks (memory plan 25.1c): not measured on Windows yet - render3d gets null and
|
||||||
|
; passes it, and the fence reads 0 (the residual there is a later step).
|
||||||
|
define ptr @lvk_ac_ptr() {
|
||||||
|
entry:
|
||||||
|
ret ptr null
|
||||||
|
}
|
||||||
|
define i64 @lvk_ac_bytes() {
|
||||||
|
entry:
|
||||||
|
ret i64 0
|
||||||
|
}
|
||||||
|
define i64 @lvk_ac_peak() {
|
||||||
|
entry:
|
||||||
|
ret i64 0
|
||||||
|
}
|
||||||
|
define i64 @lvk_ac_allocs() {
|
||||||
|
entry:
|
||||||
|
ret i64 0
|
||||||
|
}
|
||||||
|
define i64 @lvk_ac_scope_bytes(i32 %scope) {
|
||||||
|
entry:
|
||||||
|
ret i64 0
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue