Fence.kt
src/jvmMain/kotlin/afield/graphics/vulkan/device/Fence.kt · 69 lines
package afield.graphics.vulkan.device
import org.lwjgl.system.MemoryStack
import org.lwjgl.vulkan.VK10
import org.lwjgl.vulkan.VkFenceCreateInfo
import afield.graphics.vulkan.util.vkCheck
import afield.graphics.vulkan.util.AutoDisposer
A Vulkan fence the CPU waits on to learn that submitted GPU work has finished.
Fence creates the fence, optionally already signalled, and registers it with AutoDisposer
under its Device, so a fence that is never cleaned up is still destroyed. fenceWait blocks
without a timeout, reset re-arms it, and isSignaled polls it.
class Fence(private val device: afield.graphics.vulkan.device.Device, signaled: Boolean)
class Fence(private val device: afield.graphics.vulkan.device.Device, signaled: Boolean) {
var vkFence: Long
The raw VkFence handle, for the LWJGL calls Field has no wrapper for. cleanup zeroes it.
@JvmField
var vkFence: Long = 0
private val autoDisposeToken: AutoDisposer.Token
init
init {
MemoryStack.stackPush().use { stack ->
val fenceCreateInfo = VkFenceCreateInfo.calloc(stack)
.sType(VK10.VK_STRUCTURE_TYPE_FENCE_CREATE_INFO)
.flags(if (signaled) VK10.VK_FENCE_CREATE_SIGNALED_BIT else 0)
val lp = stack.mallocLong(1)
vkCheck(
VK10.vkCreateFence(device.vkDevice, fenceCreateInfo, null, lp),
"Failed to create semaphore"
)
vkFence = lp[0]
}
val dev = device.vkDevice
val fence = vkFence
autoDisposeToken = AutoDisposer.register(this, "Fence", owner = device) {
VK10.vkDestroyFence(dev, fence, null)
}
}
fun cleanup()
Destroy the fence and clear vkFence. Safe to call twice: the second call finds the
AutoDisposer registration already taken and returns without a second vkDestroyFence.
fun cleanup() {
if (!autoDisposeToken.disable()) return
VK10.vkDestroyFence(device.vkDevice, vkFence, null)
vkFence = 0L
}
fun fenceWait()
Block the calling thread until the fence signals, with no timeout. A fence that nothing submits work against never signals, so this hangs rather than returning an error.
fun fenceWait() {
VK10.vkWaitForFences(device.vkDevice, vkFence, true, Long.MAX_VALUE)
}
fun reset()
Return the fence to unsignalled, ready for the next submission to signal it.
fun reset() {
VK10.vkResetFences(device.vkDevice, vkFence)
}
fun isSignaled(): Boolean
Whether the fence has signalled, polled without blocking.
fun isSignaled(): Boolean =
VK10.vkGetFenceStatus(device.vkDevice, vkFence) == VK10.VK_SUCCESS
}