FanOutDispatch.kt
src/jvmMain/kotlin/afield/graphics/render/FanOutDispatch.kt · 55 lines
package afield.graphics.render
import afield.graphics.vulkan.Renderer
import afield.graphics.vulkan.buffers.ParallelGeometryPool
import afield.graphics.vulkan.buffers.ParallelGeometryRef
import afield.graphics.vulkan.buffers.Structure
private fun findParallelGeometryRefs(push: Structure): List<ParallelGeometryRef> {
val refs = LinkedHashSet<ParallelGeometryRef>()
push.offsets.keys.forEach { name ->
val resolved = try {
val live = push.bindings[name]
live?.invoke() ?: push.values[name]
} catch (_: Throwable) {
push.values[name]
}
if (resolved is ParallelGeometryRef) {
refs += resolved
}
}
return refs.toList()
}
internal fun forEachFanOutDispatch
internal fun forEachFanOutDispatch(
renderer: Renderer,
push: Structure,
onNoFanOut: () -> Unit,
onWriter: (ParallelGeometryPool.ActiveWriter) -> Unit
) {
val refs = findParallelGeometryRefs(push)
if (refs.isEmpty()) {
onNoFanOut()
return
}
val pools = refs.map { it.pool }.distinct()
require(pools.size == 1) {
"Fan-out push constants must reference exactly one ParallelGeometryPool, found ${pools.size}"
}
val pool = pools.first()
val snapshot = pool.snapshotForFrame(
frameId = renderer.frameCounter,
imageIndex = renderer.currentImage
) ?: return
if (snapshot.writers.isEmpty()) return
snapshot.writers.forEach { writer ->
pool.withDispatchWriter(snapshot.token, writer) {
onWriter(writer)
}
}
}