Skip to content

Commit

Permalink
fixed & refactored dispatching systems
Browse files Browse the repository at this point in the history
  • Loading branch information
Hugobros3 committed Jan 26, 2020
1 parent 2996589 commit 01a86db
Show file tree
Hide file tree
Showing 8 changed files with 159 additions and 182 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import org.lwjgl.system.MemoryStack
import org.lwjgl.system.MemoryStack.stackPush
import org.lwjgl.vulkan.VK10.*
import org.lwjgl.vulkan.VkCommandBuffer
import org.lwjgl.vulkan.VkCommandBufferBeginInfo
import org.lwjgl.vulkan.VkCommandBufferInheritanceInfo
import org.lwjgl.vulkan.VkSubmitInfo
import xyz.chunkstories.api.entity.traits.serializable.TraitControllable
import xyz.chunkstories.api.graphics.rendergraph.RenderGraphDeclaration
import xyz.chunkstories.api.graphics.representation.Representation
import xyz.chunkstories.api.graphics.structs.Camera
import xyz.chunkstories.graphics.common.Cleanable
import xyz.chunkstories.graphics.common.representations.gatherRepresentations
Expand Down Expand Up @@ -74,11 +75,46 @@ class VulkanRenderGraph(val backend: VulkanGraphicsBackend, val dslCode: RenderG

val l22 = l2.mapValues { it.value.filter { responsibleSystem.drawersInstances.contains(it.second) } }

val `that's work now!` =responsibleSystem.sortAndDraw(frame, l22, metaBucket.maskedBuckets)
val sortedWork = responsibleSystem.sortWork(frame, l22, metaBucket.maskedBuckets)

for((loc, cmdBuf) in `that's work now!`) {
val existing = prepareDrawerCmdBuffers.getOrPut(loc.first) { mutableMapOf() }.put(loc.second, cmdBuf)
if(existing != null)
// Get rid of the work for the drawers that won't do anything
val filteredWork = sortedWork.filter {
!it.value.isEmpty()
}

for (workForDrawer in filteredWork.values) {
val cmdBuf = backend.renderGraph.commandPool.loanSecondaryCommandBuffer()
workForDrawer.cmdBuffer = cmdBuf

stackPush().use {
val inheritInfo = VkCommandBufferInheritanceInfo.callocStack().apply {
sType(VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO)
renderPass(workForDrawer.drawerInstance.first.pass.canonicalRenderPass.handle)
subpass(0)
framebuffer(VK_NULL_HANDLE
/** I don't know, I mean I could but I can't be arsed :P */)
}
val beginInfo = VkCommandBufferBeginInfo.callocStack().apply {
sType(VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO)
flags(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT or VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT)
pInheritanceInfo(inheritInfo)
}
vkBeginCommandBuffer(cmdBuf, beginInfo)
workForDrawer.drawerInstance.first.pass.setScissorAndViewport(cmdBuf, workForDrawer.drawerInstance.first.renderTargetSize)
workForDrawer.drawerInstance.second.registerDrawingCommands(workForDrawer)
vkEndCommandBuffer(cmdBuf)
}
}

frame.recyclingTasks += {
filteredWork.forEach {
backend.renderGraph.commandPool.returnSecondaryCommandBuffer(it.value.cmdBuffer)
}
}

for ((loc, recordedWork) in filteredWork) {
val existing = prepareDrawerCmdBuffers.getOrPut(loc.first) { mutableMapOf() }.put(loc.second, recordedWork.cmdBuffer)
if (existing != null)
throw Exception("oh no this should really not happen!")
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,32 @@ import xyz.chunkstories.graphics.vulkan.graph.VulkanPassInstance
import xyz.chunkstories.graphics.vulkan.graph.VulkanRenderTaskInstance
import xyz.chunkstories.graphics.vulkan.swapchain.VulkanFrame

typealias VulkanDispatchingSystemType = VulkanDispatchingSystem<*>

abstract class VulkanDispatchingSystem<R : Representation>(val backend: VulkanGraphicsBackend) : Cleanable {
val drawersInstances = mutableListOf<Drawer>()

abstract val representationName: String

/** The drawer's job is to draw "things". The term is deliberatly loose: the drawer might directly work with the representations
* the parent system is fed, or it might operate on a different type, perhaps a component of the bigger Representation like it's done
* for ModelInstances or ChunkRepresentations*/
abstract class Drawer(val pass: VulkanPass) : Cleanable, DispatchingSystem {
abstract val system: VulkanDispatchingSystem<*>
abstract val system: VulkanDispatchingSystemType

override val representationName: String
get() = system.representationName

abstract fun registerDrawingCommands(drawerWork: DrawerWork)
}

abstract class DrawerWork(val drawerInstance: Pair<VulkanPassInstance, Drawer>) {
abstract fun isEmpty(): Boolean

lateinit var cmdBuffer: VkCommandBuffer
}

abstract fun createDrawerForPass(pass: VulkanPass, drawerInitCode: Drawer.() -> Unit): Drawer

abstract fun sortAndDraw(frame: VulkanFrame, drawers: Map<VulkanRenderTaskInstance, List<Pair<VulkanPassInstance, Drawer>>>, maskedBuckets: Map<Int, RepresentationsGathered.Bucket>): Map<Pair<VulkanPassInstance, Drawer>, VkCommandBuffer>
abstract fun sortWork(frame: VulkanFrame, drawers: Map<VulkanRenderTaskInstance, List<Pair<VulkanPassInstance, Drawer>>>, maskedBuckets: Map<Int, RepresentationsGathered.Bucket>): Map<Pair<VulkanPassInstance, Drawer>, DrawerWork>
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ fun <T: DispatchingSystem> VulkanGraphicsBackend.getOrCreateDispatchingSystem(li
ChunksRenderer::class.java -> VulkanChunkRepresentationsDispatcher(this)
ModelsRenderer::class.java -> VulkanModelsDispatcher(this)
SpritesRenderer::class.java -> VulkanSpritesDispatcher(this)
//LinesRenderer::class.java -> VulkanLinesDispatcher(this)
//DefferedLightsRenderer::class.java -> VulkanDefferedLightsDispatcher(this)
LinesRenderer::class.java -> VulkanLinesDispatcher(this)
DefferedLightsRenderer::class.java -> VulkanDefferedLightsDispatcher(this)
else -> {
//throw Exception("Unimplemented system on this backend: ${dispatchingSystemRegistration.clazz}")
logger.error("Unimplemented system on this backend: ${dispatchingSystemRegistration.clazz}")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package xyz.chunkstories.graphics.vulkan.systems.lighting

import org.lwjgl.system.MemoryStack
import org.lwjgl.system.MemoryStack.stackLongs
import org.lwjgl.vulkan.VK10.*
import org.lwjgl.vulkan.VkCommandBuffer
import xyz.chunkstories.api.graphics.representation.PointLight
import xyz.chunkstories.api.graphics.systems.dispatching.DefferedLightsRenderer
import xyz.chunkstories.graphics.common.FaceCullingMode
Expand All @@ -21,8 +21,6 @@ import xyz.chunkstories.graphics.vulkan.swapchain.VulkanFrame
import xyz.chunkstories.graphics.vulkan.systems.VulkanDispatchingSystem
import xyz.chunkstories.graphics.vulkan.vertexInputConfiguration

private typealias VkDefferedLightIR = MutableList<PointLight>

class VulkanDefferedLightsDispatcher(backend: VulkanGraphicsBackend) : VulkanDispatchingSystem<PointLight>(backend) {

override val representationName: String
Expand Down Expand Up @@ -67,16 +65,20 @@ class VulkanDefferedLightsDispatcher(backend: VulkanGraphicsBackend) : VulkanDis
private val program = backend.shaderFactory.createProgram("pointLight", ShaderCompilationParameters(outputs = pass.declaration.outputs))
private val pipeline = Pipeline(backend, program, pass, vertexInputConfiguration, Primitive.TRIANGLES, FaceCullingMode.DISABLED)

fun registerDrawingCommands(context: VulkanPassInstance, commandBuffer: VkCommandBuffer, work: VkDefferedLightIR) {
override fun registerDrawingCommands(drawerWork: DrawerWork) {
val work = drawerWork as DefferedLightsDrawerWork
val context = work.drawerInstance.first
val commandBuffer = work.cmdBuffer

val bindingContexts = mutableListOf<VulkanShaderResourcesContext>()

for (light in work) {
for (light in work.pointLights) {
val bindingContext = context.getBindingContext(pipeline)
bindingContexts.add(bindingContext)
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.handle)
context.shaderResources.supplyUniformBlock("light", light)
bindingContext.bindStructuredUBO("light", light)

vkCmdBindVertexBuffers(commandBuffer, 0, MemoryStack.stackLongs(vertexBuffer.handle), MemoryStack.stackLongs(0))
vkCmdBindVertexBuffers(commandBuffer, 0, stackLongs(vertexBuffer.handle), stackLongs(0))
bindingContext.commitAndBind(commandBuffer)

vkCmdDraw(commandBuffer, 3, 1, 0, 0)
Expand Down Expand Up @@ -113,9 +115,31 @@ class VulkanDefferedLightsDispatcher(backend: VulkanGraphicsBackend) : VulkanDis
}
}
}*/
class DefferedLightsDrawerWork(drawerInstance: Pair<VulkanPassInstance, VulkanDispatchingSystem.Drawer>) : DrawerWork(drawerInstance) {
val pointLights = arrayListOf<PointLight>()
override fun isEmpty(): Boolean = pointLights.isEmpty()
}

override fun sortWork(frame: VulkanFrame, drawers: Map<VulkanRenderTaskInstance, List<Pair<VulkanPassInstance, VulkanDispatchingSystem.Drawer>>>, maskedBuckets: Map<Int, RepresentationsGathered.Bucket>): Map<Pair<VulkanPassInstance, VulkanDispatchingSystem.Drawer>, DrawerWork> {
val allDrawersPlusInstances = drawers.values.flatten().filterIsInstance<Pair<VulkanPassInstance, Drawer>>()

val workForDrawers = allDrawersPlusInstances.associateWith {
DefferedLightsDrawerWork(it)
}

for ((mask, bucket) in maskedBuckets) {
@Suppress("UNCHECKED_CAST") val somewhatRelevantDrawers = drawers.filter { it.key.mask and mask != 0 }.flatMap { it.value } as List<Pair<VulkanPassInstance, Drawer>>
@Suppress("UNCHECKED_CAST") val representations = bucket.representations as ArrayList<PointLight>

for (light in representations) {
for (e in somewhatRelevantDrawers) {
val queue = workForDrawers[e]!!
queue.pointLights.add(light)
}
}
}

override fun sortAndDraw(frame: VulkanFrame, drawers: Map<VulkanRenderTaskInstance, List<Pair<VulkanPassInstance, VulkanDispatchingSystem.Drawer>>>, maskedBuckets: Map<Int, RepresentationsGathered.Bucket>): Map<Pair<VulkanPassInstance, VulkanDispatchingSystem.Drawer>, VkCommandBuffer> {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
return workForDrawers.map { Pair(it.key, it.value) }.toMap()
}

override fun cleanup() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ import xyz.chunkstories.graphics.vulkan.swapchain.VulkanFrame
import xyz.chunkstories.graphics.vulkan.systems.VulkanDispatchingSystem
import xyz.chunkstories.graphics.vulkan.vertexInputConfiguration

private typealias VkLinesIR = MutableList<Line>

class VulkanLinesDispatcher(backend: VulkanGraphicsBackend) : VulkanDispatchingSystem<Line>(backend) {

override val representationName: String
Expand Down Expand Up @@ -62,10 +60,14 @@ class VulkanLinesDispatcher(backend: VulkanGraphicsBackend) : VulkanDispatchingS
private val program = backend.shaderFactory.createProgram("colored", ShaderCompilationParameters(outputs = pass.declaration.outputs))
private val pipeline = Pipeline(backend, program, pass, vertexInput, Primitive.LINES, FaceCullingMode.DISABLED)

fun registerDrawingCommands(context: VulkanPassInstance, commandBuffer: VkCommandBuffer, work: VkLinesIR) {
override fun registerDrawingCommands(drawerWork: DrawerWork) {
val work = drawerWork as LinesDrawerWork
val context = work.drawerInstance.first
val commandBuffer = work.cmdBuffer

val buffer = memAlloc(1024 * 1024) // 1Mb buffer
var points = 0
for (line in work) {
for (line in work.lines) {
buffer.putFloat(line.start.x.toFloat())
buffer.putFloat(line.start.y.toFloat())
buffer.putFloat(line.start.z.toFloat())
Expand Down Expand Up @@ -115,10 +117,33 @@ class VulkanLinesDispatcher(backend: VulkanGraphicsBackend) : VulkanDispatchingS

}

class LinesDrawerWork(drawerInstance: Pair<VulkanPassInstance, VulkanDispatchingSystem.Drawer>) : DrawerWork(drawerInstance) {
val lines = arrayListOf<Line>()
override fun isEmpty(): Boolean = lines.isEmpty()
}

override fun createDrawerForPass(pass: VulkanPass, drawerInitCode: VulkanDispatchingSystem.Drawer.() -> Unit) = Drawer(pass, drawerInitCode)

override fun sortAndDraw(frame: VulkanFrame, drawers: Map<VulkanRenderTaskInstance, List<Pair<VulkanPassInstance, VulkanDispatchingSystem.Drawer>>>, maskedBuckets: Map<Int, RepresentationsGathered.Bucket>): Map<Pair<VulkanPassInstance, VulkanDispatchingSystem.Drawer>, VkCommandBuffer> {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
override fun sortWork(frame: VulkanFrame, drawers: Map<VulkanRenderTaskInstance, List<Pair<VulkanPassInstance, VulkanDispatchingSystem.Drawer>>>, maskedBuckets: Map<Int, RepresentationsGathered.Bucket>): Map<Pair<VulkanPassInstance, VulkanDispatchingSystem.Drawer>, DrawerWork> {
val allDrawersPlusInstances = drawers.values.flatten().filterIsInstance<Pair<VulkanPassInstance, Drawer>>()

val workForDrawers = allDrawersPlusInstances.associateWith {
LinesDrawerWork(it)
}

for ((mask, bucket) in maskedBuckets) {
@Suppress("UNCHECKED_CAST") val somewhatRelevantDrawers = drawers.filter { it.key.mask and mask != 0 }.flatMap { it.value } as List<Pair<VulkanPassInstance, Drawer>>
@Suppress("UNCHECKED_CAST") val representations = bucket.representations as ArrayList<Line>

for (line in representations) {
for (e in somewhatRelevantDrawers) {
val queue = workForDrawers[e]!!
queue.lines.add(line)
}
}
}

return workForDrawers.map { Pair(it.key, it.value) }.toMap()
}

override fun cleanup() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,10 @@ class VulkanModelsDispatcher(backend: VulkanGraphicsBackend) : VulkanDispatching

private val ssboBufferSize = 1024 * 1024L

fun registerDrawingCommands(context: VulkanPassInstance, commandBuffer: VkCommandBuffer, work: WorkForDrawerInstance) {
override fun registerDrawingCommands(drawerWork: DrawerWork) {
val work = drawerWork as ModelDrawerWork
val context = work.drawerInstance.first
val commandBuffer = work.cmdBuffer
stackPush()

val modelPositionsBuffer = MemoryUtil.memAlloc(ssboBufferSize.toInt())
Expand Down Expand Up @@ -288,20 +291,20 @@ class VulkanModelsDispatcher(backend: VulkanGraphicsBackend) : VulkanDispatching
sampler.cleanup()
}

class WorkForDrawerInstance(val drawerInstance: Pair<VulkanPassInstance, Drawer>) {
class ModelDrawerWork(drawerInstance: Pair<VulkanPassInstance, Drawer>): DrawerWork(drawerInstance) {
val animationSupported = drawerInstance.second.supportsAnimations

val queuedWork = mutableMapOf<Mesh, MutableMap<MeshMaterial, MeshMaterialInstances>>()
val queuedWorkAnimated = mutableMapOf<Mesh, MutableMap<MeshMaterial, MeshMaterialInstances>>()

lateinit var cmdBuffer: VkCommandBuffer
override fun isEmpty() =queuedWork.isEmpty() && queuedWorkAnimated.isEmpty()
}

override fun sortAndDraw(frame: VulkanFrame, drawers: Map<VulkanRenderTaskInstance, List<Pair<VulkanPassInstance, VulkanDispatchingSystem.Drawer>>>, maskedBuckets: Map<Int, RepresentationsGathered.Bucket>): Map<Pair<VulkanPassInstance, VulkanDispatchingSystem.Drawer>, VkCommandBuffer> {
override fun sortWork(frame: VulkanFrame, drawers: Map<VulkanRenderTaskInstance, List<Pair<VulkanPassInstance, VulkanDispatchingSystem.Drawer>>>, maskedBuckets: Map<Int, RepresentationsGathered.Bucket>): Map<Pair<VulkanPassInstance, VulkanDispatchingSystem.Drawer>, DrawerWork> {
val allDrawersPlusInstances = drawers.values.flatten().filterIsInstance<Pair<VulkanPassInstance, Drawer>>()

var workForDrawers = allDrawersPlusInstances.associateWith {
WorkForDrawerInstance(it)
val workForDrawers = allDrawersPlusInstances.associateWith {
ModelDrawerWork(it)
}

// Very complicated confusing logic here
Expand All @@ -314,7 +317,7 @@ class VulkanModelsDispatcher(backend: VulkanGraphicsBackend) : VulkanDispatching
@Suppress("UNCHECKED_CAST") val somewhatRelevantDrawers = drawers.filter { it.key.mask and mask != 0 }.flatMap { it.value } as List<Pair<VulkanPassInstance, Drawer>>
@Suppress("UNCHECKED_CAST") val representations = bucket.representations as ArrayList<ModelInstance>

val drawerRelevancyMap = mutableMapOf<DrawerRelevancyKey, List<WorkForDrawerInstance>>()
val drawerRelevancyMap = mutableMapOf<DrawerRelevancyKey, List<ModelDrawerWork>>()

for (modelInstance in representations) {
for ((i, mesh) in modelInstance.model.meshes.withIndex()) {
Expand All @@ -338,42 +341,7 @@ class VulkanModelsDispatcher(backend: VulkanGraphicsBackend) : VulkanDispatching
}
}

// Get rid of the work for the drawers that won't do anything
workForDrawers = workForDrawers.filter {
it.value.queuedWork.isNotEmpty() || it.value.queuedWorkAnimated.isNotEmpty()
}

for (workForDrawer in workForDrawers.values) {
val cmdBuf = backend.renderGraph.commandPool.loanSecondaryCommandBuffer()
workForDrawer.cmdBuffer = cmdBuf

stackPush().use {
val inheritInfo = VkCommandBufferInheritanceInfo.callocStack().apply {
sType(VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO)
renderPass(workForDrawer.drawerInstance.first.pass.canonicalRenderPass.handle)
subpass(0)
framebuffer(VK_NULL_HANDLE
/** I don't know, I mean I could but I can't be arsed :P */)
}
val beginInfo = VkCommandBufferBeginInfo.callocStack().apply {
sType(VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO)
flags(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT or VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT)
pInheritanceInfo(inheritInfo)
}
vkBeginCommandBuffer(cmdBuf, beginInfo)
workForDrawer.drawerInstance.first.pass.setScissorAndViewport(cmdBuf, workForDrawer.drawerInstance.first.renderTargetSize)
workForDrawer.drawerInstance.second.registerDrawingCommands(workForDrawer.drawerInstance.first, cmdBuf, workForDrawer)
vkEndCommandBuffer(cmdBuf)
}
}

frame.recyclingTasks += {
workForDrawers.forEach {
backend.renderGraph.commandPool.returnSecondaryCommandBuffer(it.value.cmdBuffer)
}
}

return workForDrawers.map { Pair(it.key, it.value.cmdBuffer) }.toMap()
return workForDrawers.map { Pair(it.key, it.value) }.toMap()
}
}

Expand Down
Loading

0 comments on commit 01a86db

Please sign in to comment.