Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Client-side preview visualizer #346

Merged
merged 7 commits into from
Feb 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/commonMain/kotlin/baaahs/ShowPlayer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ import baaahs.show.live.ShowOpener

interface ShowPlayer {
val toolchain: Toolchain

/**
* This is for [baaahs.plugin.CorePlugin.ModelInfoDataSource], but we should probably find
* a better way to get it. Don't add more uses.
*/
@Deprecated("Get it some other way", level = DeprecationLevel.WARNING)
val modelInfo: ModelInfo
val dataSources: List<DataSource>

Expand Down
2 changes: 1 addition & 1 deletion src/commonMain/kotlin/baaahs/ShowRunner.kt
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class ShowRunner(
fixtureManager.activePatchSetChanged(openShow.activePatchSet())
}

return fixtureManager.maybeUpdateRenderPlans(openShow)
return fixtureManager.maybeUpdateRenderPlans()
}

fun release() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,35 @@ package baaahs.client

import baaahs.*
import baaahs.gl.Toolchain
import baaahs.model.ModelInfo
import baaahs.model.Model
import baaahs.show.DataSource
import baaahs.show.Show
import baaahs.show.live.ActivePatchSet
import baaahs.show.live.OpenShow
import kotlinx.serialization.json.JsonElement

class ClientShowPlayer(
class ClientStageManager(
toolchain: Toolchain,
private val pubSub: PubSub.Client,
modelInfo: ModelInfo
) : BaseShowPlayer(toolchain, modelInfo) {
model: Model
) : BaseShowPlayer(toolchain, model) {
private val gadgets: MutableMap<String, ClientGadget> = mutableMapOf()
private val listeners = mutableListOf<Listener>()
private var openShow: OpenShow? = null
val activePatchSet: ActivePatchSet
get() = openShow!!.activePatchSet()

private fun checkForChanges() {
listeners.forEach { it.onPatchSetChanged() }
}

override fun openShow(show: Show, showState: ShowState?): OpenShow {
return super.openShow(show, showState)
.also {
openShow = it
checkForChanges()
}
}

override fun <T : Gadget> registerGadget(id: String, gadget: T, controlledDataSource: DataSource?) {
gadgets[id] = ClientGadget(id, pubSub, gadget)
Expand All @@ -23,7 +42,15 @@ class ClientShowPlayer(
return gadgets.getBang(id, "gadget").gadget as T
}

private class ClientGadget(
fun addListener(listener: Listener) {
listeners.add(listener)
}

fun removeListener(listener: Listener) {
listeners.remove(listener)
}

private inner class ClientGadget(
id: String,
pubSub: PubSub.Client,
val gadget: Gadget
Expand All @@ -41,13 +68,19 @@ class ClientShowPlayer(
gadget.withoutTriggering(gadgetListener) {
gadget.state.putAll(json)
gadget.changed()
checkForChanges()
}
}
}

// GadgetListener callback.
fun onGadgetChange(g: Gadget) {
channel.onChange(g.state)
checkForChanges()
}
}

interface Listener {
fun onPatchSetChanged()
}
}
4 changes: 2 additions & 2 deletions src/commonMain/kotlin/baaahs/fixtures/DeviceType.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import baaahs.gl.GlContext
import baaahs.gl.data.ProgramFeed
import baaahs.gl.glsl.GlslProgram
import baaahs.gl.patch.ContentType
import baaahs.gl.render.RenderTarget
import baaahs.gl.render.FixtureRenderTarget
import baaahs.glsl.Uniform
import baaahs.show.DataSourceBuilder
import baaahs.show.Shader
Expand Down Expand Up @@ -108,7 +108,7 @@ class FloatsParamBuffer(val id: String, val stride: Int, private val gl: GlConte
}

fun scoped(
renderTarget: RenderTarget,
renderTarget: FixtureRenderTarget,
callback: ((Int) -> Float)? = null
) = object : BufferView<Float> {
val offset = renderTarget.pixel0Index
Expand Down
18 changes: 7 additions & 11 deletions src/commonMain/kotlin/baaahs/fixtures/FixtureManager.kt
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
package baaahs.fixtures

import baaahs.getBang
import baaahs.gl.glsl.GlslProgram
import baaahs.gl.patch.PatchResolver
import baaahs.gl.render.FixtureRenderTarget
import baaahs.gl.render.RenderManager
import baaahs.gl.render.RenderTarget
import baaahs.show.live.ActivePatchSet
import baaahs.show.live.OpenShow
import baaahs.timeSync
import baaahs.util.Logger

class FixtureManager(
private val renderManager: RenderManager,
private val renderTargets: MutableMap<Fixture, RenderTarget> = hashMapOf()
initialRenderTargets: Map<Fixture, FixtureRenderTarget> = emptyMap()
) {
private val renderTargets: MutableMap<Fixture, FixtureRenderTarget> = initialRenderTargets.toMutableMap()
private val frameListeners: MutableList<() -> Unit> = arrayListOf()
private val changedFixtures = mutableListOf<FixturesChanges>()
private var totalFixtures = 0

private var currentActivePatchSet: ActivePatchSet = ActivePatchSet(emptyList())
private var currentActivePatchSet: ActivePatchSet = ActivePatchSet.Empty
private var activePatchSetChanged = false
internal var currentRenderPlan: RenderPlan? = null
private set

fun addFrameListener(callback: () -> Unit) {
frameListeners.add(callback)
Expand Down Expand Up @@ -88,7 +88,7 @@ class FixtureManager(
}
}

fun maybeUpdateRenderPlans(openShow: OpenShow): Boolean {
fun maybeUpdateRenderPlans(): Boolean {
var remapFixtures = incorporateFixtureChanges()

// Maybe build new shaders.
Expand All @@ -97,11 +97,7 @@ class FixtureManager(
val activePatchSet = currentActivePatchSet

val elapsedMs = timeSync {
val patchResolution = PatchResolver(
openShow.allDataSources, renderManager, renderTargets.values, activePatchSet)
currentRenderPlan = patchResolution.createRenderPlan { _, dataSource ->
openShow.feeds.getBang(dataSource, "data feed")
}
currentRenderPlan = activePatchSet.createRenderPlan(renderManager, renderTargets.values)
}

logger.info {
Expand Down
24 changes: 17 additions & 7 deletions src/commonMain/kotlin/baaahs/fixtures/PixelArrayDevice.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import baaahs.gl.data.*
import baaahs.gl.glsl.GlslProgram
import baaahs.gl.glsl.GlslType
import baaahs.gl.patch.ContentType
import baaahs.gl.render.FixtureRenderTarget
import baaahs.gl.render.RenderTarget
import baaahs.gl.shader.InputPort
import baaahs.glsl.Uniform
Expand All @@ -17,6 +18,7 @@ import baaahs.plugin.classSerializer
import baaahs.show.DataSource
import baaahs.show.DataSourceBuilder
import baaahs.show.Shader
import baaahs.util.Logger
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
Expand Down Expand Up @@ -119,14 +121,18 @@ class PixelLocationFeed(
override val buffer = FloatsParamBuffer(id, 3, gl)

override fun setOnBuffer(renderTarget: RenderTarget) = run {
val pixelLocations = renderTarget.fixture.pixelLocations
buffer.scoped(renderTarget).also { view ->
for (pixelIndex in 0 until min(pixelLocations.size, renderTarget.pixelCount)) {
val location = pixelLocations[pixelIndex]
view[pixelIndex, 0] = location.x
view[pixelIndex, 1] = location.y
view[pixelIndex, 2] = location.z
if (renderTarget is FixtureRenderTarget) {
val pixelLocations = renderTarget.fixture.pixelLocations
buffer.scoped(renderTarget).also { view ->
for (pixelIndex in 0 until min(pixelLocations.size, renderTarget.pixelCount)) {
val location = pixelLocations[pixelIndex]
view[pixelIndex, 0] = location.x
view[pixelIndex, 1] = location.y
view[pixelIndex, 2] = location.z
}
}
} else {
logger.warn { "Attempted to set per-pixel data for a non-FixtureRenderTarget, but that's impossible!" }
}
Unit
}
Expand All @@ -144,4 +150,8 @@ class PixelLocationFeed(
override fun release() {
refCounter.release()
}

companion object {
private val logger = Logger<PixelLocationFeed>()
}
}
3 changes: 0 additions & 3 deletions src/commonMain/kotlin/baaahs/gl/glsl/GlslProgram.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import baaahs.gl.patch.LinkedPatch
import baaahs.gl.render.RenderTarget
import baaahs.glsl.Uniform
import baaahs.show.DataSource
import baaahs.show.OutputPortRef
import baaahs.show.UpdateMode
import baaahs.util.Logger
import com.danielgergely.kgl.Kgl
Expand Down Expand Up @@ -126,8 +125,6 @@ class GlslProgram(
companion object {
private val logger = Logger("GlslProgram")

val PixelColor = OutputPortRef("sm_result")

val vertexShader = """
precision lowp float;

Expand Down
79 changes: 48 additions & 31 deletions src/commonMain/kotlin/baaahs/gl/patch/PatchResolver.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import baaahs.fixtures.RenderPlan
import baaahs.gl.glsl.CompilationException
import baaahs.gl.glsl.FeedResolver
import baaahs.gl.glsl.GlslException
import baaahs.gl.glsl.GlslProgram
import baaahs.gl.render.RenderManager
import baaahs.gl.render.RenderTarget
import baaahs.glsl.GuruMeditationError
Expand All @@ -18,39 +19,72 @@ import baaahs.show.live.OpenPatch
import baaahs.util.Logger

class PatchResolver(
private val dataSources: Map<String, DataSource>,
private val renderManager: RenderManager,
private val renderTargets: Collection<RenderTarget>,
renderTargets: Collection<RenderTarget>,
activePatchSet: ActivePatchSet,
private val renderManager: RenderManager
) : BasePatchResolver(renderTargets, activePatchSet) {
override fun buildProgram(
linkedPatch: LinkedPatch,
deviceType: DeviceType,
feedResolver: FeedResolver
) = try {
renderManager.compile(deviceType, linkedPatch, feedResolver)
} catch (e: GlslException) {
logger.error(e) { "Error preparing program" }
if (e is CompilationException) {
e.source?.let { ShowRunner.logger.info { it } }
}

renderManager.compile(
deviceType, GuruMeditationError(deviceType).linkedPatch, feedResolver
)
}

companion object {
private val logger = Logger<PatchResolver>()

fun buildPortDiagram(vararg patches: OpenPatch) = PortDiagram(patches.toList())
}
}

abstract class BasePatchResolver(
renderTargets: Collection<RenderTarget>,
private val activePatchSet: ActivePatchSet
) {
val portDiagrams =
renderTargets
.groupBy { it.fixture.deviceType }
.mapValues { (deviceType, renderTargets) ->
.mapValues { (_, renderTargets) ->
val patchSetsByKey = mutableMapOf<String, PatchSet>()
val renderTargetsByKey = mutableMapOf<String, MutableList<RenderTarget>>()
val renderTargetsByPatchSetKey = mutableMapOf<String, MutableList<RenderTarget>>()

renderTargets.forEach { renderTarget ->
val patchSet = activePatchSet.activePatches
.filter { patch -> patch.matches(renderTarget.fixture) }
val patchSet = activePatchSet.forFixture(renderTarget.fixture)
val key = patchSet.joinToString(":") { it.serial.toString(16) }

patchSetsByKey[key] = patchSet
renderTargetsByKey.getOrPut(key) { mutableListOf() }
renderTargetsByPatchSetKey.getOrPut(key) { mutableListOf() }
.add(renderTarget)
}

patchSetsByKey.map { (key, patchSet) ->
PortDiagram(dataSources, patchSet) to
renderTargetsByKey[key]!! as List<RenderTarget>
PortDiagram(patchSet) to
renderTargetsByPatchSetKey[key]!! as List<RenderTarget>
}
}

fun createRenderPlan(feedResolver: FeedResolver): RenderPlan {
fun createRenderPlan(
dataSources: Map<String, DataSource>,
feedResolver: FeedResolver
): RenderPlan {
return RenderPlan(
portDiagrams.mapValues { (deviceType, devicePortDiagrams) ->
val programsRenderPlans = devicePortDiagrams.map { (portDiagram, renderTargets) ->
val linkedPatch = portDiagram.resolvePatch(ShaderChannel.Main, deviceType.resultContentType)
val linkedPatch = portDiagram.resolvePatch(
ShaderChannel.Main,
deviceType.resultContentType,
dataSources
)
val program = linkedPatch?.let {
buildProgram(it, deviceType, feedResolver)
}
Expand All @@ -63,28 +97,11 @@ class PatchResolver(
)
}

private fun buildProgram(
abstract fun buildProgram(
linkedPatch: LinkedPatch,
deviceType: DeviceType,
feedResolver: FeedResolver
) = try {
renderManager.compile(deviceType, linkedPatch, feedResolver)
} catch (e: GlslException) {
logger.error(e) { "Error preparing program" }
if (e is CompilationException) {
e.source?.let { ShowRunner.logger.info { it } }
}

renderManager.compile(
deviceType, GuruMeditationError(deviceType).linkedPatch, feedResolver
)
}

companion object {
private val logger = Logger<PatchResolver>()
fun buildPortDiagram(dataSources: Map<String, DataSource>, vararg patches: OpenPatch) =
PortDiagram(dataSources, patches.toList())
}
): GlslProgram
}

private typealias PatchSet = List<OpenPatch>
Loading