Skip to content

Commit

Permalink
made DrawCommand.pipeline non-nullable
Browse files Browse the repository at this point in the history
  • Loading branch information
fabmax committed Feb 21, 2024
1 parent 9d3e14b commit b32ddd8
Show file tree
Hide file tree
Showing 17 changed files with 57 additions and 67 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@ package de.fabmax.kool.modules.ksl.blocks

import de.fabmax.kool.modules.ksl.KslShaderListener
import de.fabmax.kool.modules.ksl.lang.*
import de.fabmax.kool.pipeline.BindGroupScope
import de.fabmax.kool.pipeline.BufferPosition
import de.fabmax.kool.pipeline.ShaderBase
import de.fabmax.kool.pipeline.UniformBufferLayout
import de.fabmax.kool.pipeline.DrawCommand
import de.fabmax.kool.pipeline.*
import de.fabmax.kool.util.positioned

fun KslProgram.cameraData(): CameraData {
Expand Down Expand Up @@ -72,9 +68,8 @@ class CameraData(program: KslProgram) : KslDataBlock, KslShaderListener {
}

override fun onUpdate(cmd: DrawCommand) {
val pipeline = cmd.pipeline ?: return
val bindingLayout = uboLayout ?: return
val viewData = cmd.queue.view.viewPipelineData.getPipelineDataUpdating(pipeline, bindingLayout.bindingIndex) ?: return
val viewData = cmd.queue.view.viewPipelineData.getPipelineDataUpdating(cmd.pipeline, bindingLayout.bindingIndex) ?: return

val q = cmd.queue
val vp = q.view.viewport
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import de.fabmax.kool.math.toMutableMat4f
import de.fabmax.kool.modules.ksl.KslShaderListener
import de.fabmax.kool.modules.ksl.lang.*
import de.fabmax.kool.pipeline.*
import de.fabmax.kool.pipeline.DrawCommand

fun KslProgram.mvpMatrix(): MvpMatrixData {
return (dataBlocks.find { it is MvpMatrixData } as? MvpMatrixData) ?: MvpMatrixData(this)
Expand Down Expand Up @@ -57,16 +56,14 @@ class MvpMatrixData(program: KslProgram) : MeshMatrixData(program, "uMvpMat") {
private val tmpMat4f = MutableMat4f()

override fun onUpdate(cmd: DrawCommand) {
val pipeline = cmd.pipeline ?: return

// Do not use getPipelineDataUpdating() here: MVP matrix needs to be always updated, in case this mesh /
// pipeline combination is drawn in multiple views with different view matrices.
//
// fixme: This also means, that this onUpdate function has to be called in correct order between individual
// views. This is currently the case but might change in future. In that case, using a precomputed MVP matrix
// would not be possible anymore (work around: use separate model and view matrices and multiply them in
// the vertex shader)
val uboData = cmd.mesh.meshPipelineData.getPipelineData(pipeline)
val uboData = cmd.mesh.meshPipelineData.getPipelineData(cmd.pipeline)

if (cmd.queue.isDoublePrecision) {
cmd.queue.viewProjMatD.mul(cmd.modelMatD, tmpMat4d)
Expand All @@ -88,9 +85,8 @@ class ModelMatrixData(program: KslProgram) : MeshMatrixData(program, "uModelMat"
private val tmpMat4f = MutableMat4f()

override fun onUpdate(cmd: DrawCommand) {
val pipeline = cmd.pipeline ?: return
val bindingLayout = uboLayout ?: return
val uboData = cmd.mesh.meshPipelineData.getPipelineDataUpdating(pipeline, bindingLayout.bindingIndex) ?: return
val uboData = cmd.mesh.meshPipelineData.getPipelineDataUpdating(cmd.pipeline, bindingLayout.bindingIndex) ?: return

if (cmd.queue.isDoublePrecision) {
cmd.modelMatD.toMutableMat4f(tmpMat4f)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@ package de.fabmax.kool.modules.ksl.blocks

import de.fabmax.kool.modules.ksl.KslShaderListener
import de.fabmax.kool.modules.ksl.lang.*
import de.fabmax.kool.pipeline.BindGroupScope
import de.fabmax.kool.pipeline.BufferPosition
import de.fabmax.kool.pipeline.ShaderBase
import de.fabmax.kool.pipeline.UniformBufferLayout
import de.fabmax.kool.pipeline.DrawCommand
import de.fabmax.kool.pipeline.*
import de.fabmax.kool.util.positioned
import kotlin.math.min

Expand Down Expand Up @@ -51,9 +47,8 @@ class SceneLightData(program: KslProgram, val maxLightCount: Int) : KslDataBlock
}

override fun onUpdate(cmd: DrawCommand) {
val pipeline = cmd.pipeline ?: return
val bindingLayout = uboLayout ?: return
val viewData = cmd.queue.view.viewPipelineData.getPipelineDataUpdating(pipeline, bindingLayout.bindingIndex) ?: return
val viewData = cmd.queue.view.viewPipelineData.getPipelineDataUpdating(cmd.pipeline, bindingLayout.bindingIndex) ?: return
val ubo = viewData.uniformBufferBindingData(bindingLayout.bindingIndex)
val lighting = cmd.queue.renderPass.lighting

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,22 +36,28 @@ open class DepthMapPass(
}

protected open fun setupDrawCommand(cmd: DrawCommand, updateEvent: UpdateEvent) {
cmd.pipeline = getDepthPipeline(cmd.mesh, updateEvent)
val pipeline = getDepthPipeline(cmd.mesh, updateEvent)
if (pipeline == null) {
cmd.isActive = false
} else {
cmd.pipeline = pipeline
}
}

protected open fun getDepthPipeline(mesh: Mesh, updateEvent: UpdateEvent): DrawPipeline? {
if (!mesh.geometry.hasAttribute(Attribute.POSITIONS)) {
return null
}
return shadowPipelines.getOrPut(mesh.id) {
val depthShader = mesh.depthShader
?: mesh.depthShaderConfig?.let { cfg -> DepthShader(cfg.copy(outputLinearDepth = false, outputNormals = false)) }
?: defaultDepthShader(mesh, updateEvent)
depthShader.getOrCreatePipeline(mesh, updateEvent)
depthShader?.getOrCreatePipeline(mesh, updateEvent)
}
}

private fun defaultDepthShader(mesh: Mesh, updateEvent: UpdateEvent): DepthShader {
private fun defaultDepthShader(mesh: Mesh, updateEvent: UpdateEvent): DepthShader? {
if (!mesh.geometry.hasAttribute(Attribute.POSITIONS)) {
return null
}

val cfg = DepthShader.Config.forMesh(mesh, getMeshCullMethod(mesh, updateEvent))
val key = DepthShaderKey(
vertexLayout = mesh.geometry.vertexAttributes,
Expand Down Expand Up @@ -101,18 +107,19 @@ class NormalLinearDepthMapPass(
}

override fun getDepthPipeline(mesh: Mesh, updateEvent: UpdateEvent): DrawPipeline? {
if (!mesh.geometry.hasAttribute(Attribute.POSITIONS) || !mesh.geometry.hasAttribute(Attribute.NORMALS)) {
return null
}
return shadowPipelines.getOrPut(mesh.id) {
val depthShader = mesh.normalLinearDepthShader
?: mesh.depthShaderConfig?.let { cfg -> DepthShader(cfg.copy(outputLinearDepth = true, outputNormals = true)) }
?: defaultDepthShader(mesh, updateEvent)
depthShader.getOrCreatePipeline(mesh, updateEvent)
depthShader?.getOrCreatePipeline(mesh, updateEvent)
}
}

private fun defaultDepthShader(mesh: Mesh, updateEvent: UpdateEvent): DepthShader {
private fun defaultDepthShader(mesh: Mesh, updateEvent: UpdateEvent): DepthShader? {
if (!mesh.geometry.hasAttribute(Attribute.POSITIONS) || !mesh.geometry.hasAttribute(Attribute.NORMALS)) {
return null
}

val cfg = DepthShader.Config.forMesh(mesh, getMeshCullMethod(mesh, updateEvent)).copy(
outputLinearDepth = true,
outputNormals = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@ import de.fabmax.kool.math.Mat4f
import de.fabmax.kool.scene.Mesh
import de.fabmax.kool.scene.geometry.IndexedVertexList

class DrawCommand(val queue: DrawQueue, mesh: Mesh) {
class DrawCommand(val queue: DrawQueue, mesh: Mesh, var pipeline: DrawPipeline) {

var mesh: Mesh = mesh
private set
var drawGroupId = 0
private set

var geometry: IndexedVertexList = mesh.geometry
var pipeline: DrawPipeline? = null

var isActive = true

/**
* Single precision model matrix of this command's [mesh].
Expand All @@ -25,10 +26,11 @@ class DrawCommand(val queue: DrawQueue, mesh: Mesh) {
*/
val modelMatD: Mat4d get() = mesh.modelMatD

fun setup(mesh: Mesh, drawGroupId: Int, updateEvent: RenderPass.UpdateEvent) {
fun setup(mesh: Mesh, pipeline: DrawPipeline, drawGroupId: Int) {
this.mesh = mesh
this.pipeline = pipeline
this.drawGroupId = drawGroupId
geometry = mesh.geometry
pipeline = mesh.getOrCreatePipeline(updateEvent)
isActive = true
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,13 @@ class DrawQueue(val renderPass: RenderPass, val view: RenderPass.View) {
return prevQueue
}

fun addMesh(mesh: Mesh, updateEvent: RenderPass.UpdateEvent): DrawCommand {
fun addMesh(mesh: Mesh, pipeline: DrawPipeline): DrawCommand {
val cmd = if (commandPool.isNotEmpty()) {
commandPool.removeAt(commandPool.lastIndex)
} else {
DrawCommand(this, mesh)
DrawCommand(this, mesh, pipeline)
}
cmd.setup(mesh, drawGroupId, updateEvent)
cmd.setup(mesh, pipeline, drawGroupId)
getOrderedQueue().commands.add(cmd)
return cmd
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
package de.fabmax.kool.pipeline.backend.gl

import de.fabmax.kool.pipeline.DrawPipeline
import de.fabmax.kool.pipeline.InputRate
import de.fabmax.kool.pipeline.PipelineBackend
import de.fabmax.kool.pipeline.VertexLayout
import de.fabmax.kool.pipeline.DrawCommand
import de.fabmax.kool.pipeline.*
import de.fabmax.kool.scene.Mesh
import de.fabmax.kool.scene.geometry.PrimitiveType

Expand Down Expand Up @@ -98,7 +94,6 @@ class CompiledDrawShader(val pipeline: DrawPipeline, program: GlProgram, backend
}

fun bindMesh(cmd: DrawCommand): DrawInfo {
val pipeline = cmd.pipeline!!
val geom = getOrCreateGpuGeometry(cmd)

users.add(cmd.mesh.id)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,12 @@ abstract class GlRenderPass(val backend: RenderBackendGl) {
}
}

cmd.pipeline?.let { pipeline ->
if (cmd.isActive) {
val drawInfo = backend.shaderMgr.bindDrawShader(cmd)
val isValid = cmd.geometry.numIndices > 0 && drawInfo.isValid && drawInfo.numIndices > 0

if (isValid) {
GlState.setupPipelineAttribs(pipeline, view.renderPass.isReverseDepth, gl)
GlState.setupPipelineAttribs(cmd.pipeline, view.renderPass.isReverseDepth, gl)

val insts = cmd.mesh.instances
if (insts == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ class ShaderManager(val backend: RenderBackendGl) {
private val glComputePrograms = mutableMapOf<ComputeShaderCodeGl, UsedGlProgram>()

fun bindDrawShader(cmd: DrawCommand): CompiledDrawShader.DrawInfo {
val pipeline = checkNotNull(cmd.pipeline)
val shader = pipeline.getCompiledShader()
val shader = cmd.pipeline.getCompiledShader()
val current = boundShader as? CompiledDrawShader

if (shader.program != current?.program) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@ package de.fabmax.kool.pipeline.deferred

import de.fabmax.kool.modules.ksl.KslShaderListener
import de.fabmax.kool.modules.ksl.lang.*
import de.fabmax.kool.pipeline.BindGroupScope
import de.fabmax.kool.pipeline.BufferPosition
import de.fabmax.kool.pipeline.ShaderBase
import de.fabmax.kool.pipeline.UniformBufferLayout
import de.fabmax.kool.pipeline.DrawCommand
import de.fabmax.kool.pipeline.*
import de.fabmax.kool.util.positioned

fun KslProgram.deferredCameraData(): DeferredCamData {
Expand Down Expand Up @@ -56,12 +52,11 @@ class DeferredCamData(program: KslProgram) : KslDataBlock, KslShaderListener {
val q = cmd.queue
val vp = q.view.viewport
val cam = q.view.camera
val pipeline = cmd.pipeline
val bindingLayout = uboLayout

if (pipeline != null && bindingLayout != null) {
if (bindingLayout != null) {
val uboData = cmd.queue.view.viewPipelineData
.getPipelineData(pipeline)
.getPipelineData(cmd.pipeline)
.uniformBufferBindingData(bindingLayout.bindingIndex)

uboData.isBufferDirty = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ class PbrLightingPass(pipeline: DeferredPipeline, suffix: String, val materialPa
scene.mainRenderPass.onAfterCollectDrawCommands += { ev ->
if (isEnabled) {
for (i in materialPass.alphaMeshes.indices) {
scene.mainRenderPass.screenView.drawQueue.addMesh(materialPass.alphaMeshes[i], ev)
val mesh = materialPass.alphaMeshes[i]
mesh.getOrCreatePipeline(ev)?.let { pipeline ->
scene.mainRenderPass.screenView.drawQueue.addMesh(mesh, pipeline)
}
}
}
}
Expand Down
5 changes: 4 additions & 1 deletion kool-core/src/commonMain/kotlin/de/fabmax/kool/scene/Mesh.kt
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,10 @@ open class Mesh(
}
rayTest.onMeshDataChanged(this)
}
updateEvent.view.drawQueue.addMesh(this, updateEvent)

getOrCreatePipeline(updateEvent)?.let { pipeline ->
updateEvent.view.drawQueue.addMesh(this, pipeline)
}
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ class VkRenderBackend(val ctx: Lwjgl3Context) : RenderBackendJvm {
var prevPipeline = 0L
drawQueue.forEach { cmd ->
val pipelineCfg = cmd.pipeline
if (!cmd.mesh.geometry.isEmpty() && pipelineCfg != null) {
if (!cmd.mesh.geometry.isEmpty()) {
pipelineCfg.update(cmd)

if (!sys.pipelineManager.hasPipeline(pipelineCfg, renderPass.vkRenderPass)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class UboDescriptor(binding: Int, graphicsPipeline: GraphicsPipeline, private va
}

override fun update(cmd: DrawCommand, sys: VkSystem) {
val hostBuffer = cmd.pipeline!!.pipelineData.uniformBufferBindingData(binding).buffer as MixedBufferImpl
val hostBuffer = cmd.pipeline.pipelineData.uniformBufferBindingData(binding).buffer as MixedBufferImpl
hostBuffer.useRaw { host ->
buffer.mapped { put(host) }
}
Expand All @@ -85,7 +85,7 @@ class SamplerDescriptor private constructor(binding: Int, private val sampler: T

override fun setDescriptorSet(stack: MemoryStack, vkWriteDescriptorSet: VkWriteDescriptorSet, dstSet: Long, cmd: DrawCommand) {
stack.apply {
val textures = sampler.getTextures(cmd.pipeline!!.pipelineData)
val textures = sampler.getTextures(cmd.pipeline.pipelineData)
val imageInfo = callocVkDescriptorImageInfoN(sampler.arraySize) {
for (i in 0 until sampler.arraySize) {
this[i].apply {
Expand Down Expand Up @@ -118,7 +118,7 @@ class SamplerDescriptor private constructor(binding: Int, private val sampler: T
}
}

val textures = sampler.getTextures(cmd.pipeline!!.pipelineData)
val textures = sampler.getTextures(cmd.pipeline.pipelineData)

var allValid = true
if (boundTex.size != sampler.arraySize) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@ class WgpuPipelineManager(val backend: RenderBackendWebGpu) {
private val computeShaderModules = mutableMapOf<String, UsedShaderModule>()

fun bindDrawPipeline(cmd: DrawCommand, passEncoderState: RenderPassEncoderState<*>): Boolean {
val drawPipeline = cmd.pipeline!!
val gpuPipeline = drawPipeline.getWgpuPipeline()
drawPipeline.update(cmd)
val gpuPipeline = cmd.pipeline.getWgpuPipeline()
cmd.pipeline.update(cmd)
return gpuPipeline.bind(cmd, passEncoderState)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ abstract class WgpuRenderPass<T: RenderPass>(
}
}

val isCmdValid = cmd.pipeline != null && cmd.geometry.numIndices > 0
val isCmdValid = cmd.isActive && cmd.geometry.numIndices > 0
if (isCmdValid && backend.pipelineManager.bindDrawPipeline(cmd, passEncoderState)) {
val insts = cmd.mesh.instances
if (insts == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,12 @@ class SelectionOverlay(editor: KoolEditor) : Node("Selection overlay") {
}

private fun setupDrawCommand(i: Int, cmd: DrawCommand, updateEvent: UpdateEvent) {
cmd.pipeline = null
cmd.isActive = false
if (cmd.mesh in meshSelection) {
getPipeline(cmd.mesh, updateEvent)?.let { (shader, pipeline) ->
shader.color = selectionColors[i % selectionColors.size]
cmd.pipeline = pipeline
cmd.isActive = true
}
}
}
Expand Down

0 comments on commit b32ddd8

Please sign in to comment.