Skip to content

Commit

Permalink
Merge pull request #352 from baaahs/transitions
Browse files Browse the repository at this point in the history
Input ports may be declared as abstract GLSL functions
  • Loading branch information
xian authored Mar 18, 2021
2 parents c47921e + bc8a562 commit 895d9d6
Show file tree
Hide file tree
Showing 45 changed files with 1,051 additions and 558 deletions.
83 changes: 61 additions & 22 deletions src/commonMain/kotlin/baaahs/gl/glsl/GlslCode.kt
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,11 @@ class GlslCode(
fun toGlsl(
namespace: Namespace,
symbolsToNamespace: Set<String>,
symbolMap: Map<String, String>
symbolMap: Map<String, GlslExpr>
): String {
return "${lineNumber?.let { "\n#line $lineNumber\n" }}" +
replaceCodeWords(fullText) {
symbolMap[it]
symbolMap[it]?.s
?: if (it == name || symbolsToNamespace.contains(it)) {
namespace.qualify(it)
} else {
Expand Down Expand Up @@ -146,14 +146,14 @@ class GlslCode(
val type: GlslType
val isVarying: Boolean
val isGlobalInput: Boolean
val isAbstractFunction: Boolean
val hint: Hint?
val lineNumber: Int?

fun toInputPort(plugins: Plugins, parent: GlslFunction?): InputPort {
val contentTypeFromPlugin = try {
hint?.pluginRef
?.let { plugins.findDataSourceBuilder(it) }
?.contentType
?.let { plugins.findDataSourceBuilder(it).contentType }
} catch (e: Exception) {
null
}
Expand All @@ -167,12 +167,15 @@ class GlslCode(
title = title,
pluginRef = hint?.pluginRef,
pluginConfig = hint?.config,
glslArgSite = this
glslArgSite = this,
injectedData = findInjectedData(plugins)
)
}

fun findContentType(plugins: Plugins, parent: GlslFunction?) =
hint?.contentType(plugins)
hint?.contentType("type", plugins)

fun findInjectedData(plugins: Plugins): Map<String, ContentType> = emptyMap()
}

data class GlslVar(
Expand All @@ -187,6 +190,7 @@ class GlslCode(
) : GlslStatement, GlslArgSite {
override val title get() = name.englishize()
override val isGlobalInput: Boolean get() = isUniform || isVarying
override val isAbstractFunction: Boolean get() = false
override val hint: Hint? by lazy { Hint.parse(comments.joinToString(" ") { it.trim() }, lineNumber) }

override fun stripSource() = copy(fullText = "", lineNumber = null)
Expand Down Expand Up @@ -257,26 +261,56 @@ class GlslCode(
val params: List<GlslParam>,
override val fullText: String,
override val lineNumber: Int? = null,
override val comments: List<String> = emptyList()
) : GlslStatement {
val hint: Hint? by lazy { Hint.from(comments, lineNumber) }
override val comments: List<String> = emptyList(),
val isAbstract: Boolean = false
) : GlslStatement, GlslArgSite {
override val title: String get() = name.englishize()
override val type: GlslType get() = returnType
override val isVarying: Boolean get() = true
override val isGlobalInput: Boolean get() = false
override val isAbstractFunction: Boolean get() = isAbstract

override val hint: Hint? by lazy { Hint.from(comments, lineNumber) }

override fun stripSource() = copy(lineNumber = null)

fun invocationGlsl(namespace: Namespace, resultVar: String, portMap: Map<String, String>): String {
val assignment = if (returnType != GlslType.Void) {
"$resultVar = "
} else ""

val args = params.joinToString(", ") { glslParam ->
if (glslParam.isOut)
resultVar
else
portMap[glslParam.name]
?: "/* huh? ${glslParam.name} */"
}
override fun findContentType(plugins: Plugins, parent: GlslFunction?): ContentType? {
return hint?.contentType("return", plugins)
?: super.findContentType(plugins, parent)
}

return assignment + namespace.qualify(name) + "($args)"
override fun findInjectedData(plugins: Plugins): Map<String, ContentType> {
return params.associate { it.name to (it.findContentType(plugins, this) ?: ContentType.Unknown) }
}

override fun toGlsl(
namespace: Namespace,
symbolsToNamespace: Set<String>,
symbolMap: Map<String, GlslExpr>
): String {
// Chomp trailing ';' if it's an abstract method.
return super.toGlsl(namespace, symbolsToNamespace, symbolMap)
.let { if (isAbstract) it.trimEnd(';') else it }
}

fun invoker(namespace: Namespace, portMap: Map<String, GlslExpr>): Invoker {
return object : Invoker {
override fun toGlsl(resultVar: String): String {
val assignment = if (returnType != GlslType.Void) {
"$resultVar = "
} else ""

val args = params.joinToString(", ") { glslParam ->
if (glslParam.isOut)
resultVar
else
portMap[glslParam.name]?.s
?: "/* huh? ${glslParam.name} */"
}

return assignment + namespace.qualify(name) + "($args)"
}
}
}
}

Expand All @@ -292,6 +326,7 @@ class GlslCode(
override val isVarying: Boolean get() = true
override val isGlobalInput: Boolean get() = false
override val hint: Hint? by lazy { Hint.from(comments, lineNumber) }
override val isAbstractFunction: Boolean get() = false

override fun findContentType(plugins: Plugins, parent: GlslFunction?): ContentType? {
return super.findContentType(plugins, parent)
Expand All @@ -312,4 +347,8 @@ class GlslCode(
}
}
}

interface Invoker {
fun toGlsl(resultVar: String): String
}
}
3 changes: 3 additions & 0 deletions src/commonMain/kotlin/baaahs/gl/glsl/GlslExpr.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package baaahs.gl.glsl

data class GlslExpr(val s: String)
8 changes: 7 additions & 1 deletion src/commonMain/kotlin/baaahs/gl/glsl/GlslParser.kt
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@ class GlslParser {
val returnType: GlslType
val name: String
val params = arrayListOf<GlslCode.GlslParam>()
var isAbstract = true

init {
if (tokensSoFar.size != 2)
Expand All @@ -385,8 +386,13 @@ class GlslParser {
name = tokensSoFar[1]
}

override fun visitLeftCurlyBrace(): ParseState {
isAbstract = false
return super.visitLeftCurlyBrace()
}

override fun createStatement(): GlslCode.GlslStatement =
GlslCode.GlslFunction(name, returnType, params, textAsString, lineNumber, comments)
GlslCode.GlslFunction(name, returnType, params, textAsString, lineNumber, comments, isAbstract)

inner class Params(
recipientOfNextComment: Statement? = null
Expand Down
21 changes: 13 additions & 8 deletions src/commonMain/kotlin/baaahs/gl/glsl/GlslType.kt
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
package baaahs.gl.glsl

import baaahs.show.mutable.MutableConstPort
import baaahs.show.mutable.MutablePort

sealed class GlslType constructor(
val glslLiteral: String,
val defaultInitializer: String = "$glslLiteral(0.)"
val defaultInitializer: GlslExpr = GlslExpr("$glslLiteral(0.)")
) {
init {
@Suppress("LeakingThis")
types[glslLiteral] = this
}

val mutableDefaultInitializer: MutablePort get() = MutableConstPort(defaultInitializer.s, this)

private class OtherGlslType(glslLiteral: String) : GlslType(glslLiteral)
class Struct(
val name: String,
val fields: Map<String, GlslType>,
defaultInitializer: String = initializerFor(fields)
defaultInitializer: GlslExpr = initializerFor(fields)
) : GlslType(name, defaultInitializer) {
constructor(glslStruct: GlslCode.GlslStruct)
: this(glslStruct.name, glslStruct.fields)
Expand All @@ -26,7 +31,7 @@ sealed class GlslType constructor(
constructor(
name: String,
vararg fields: Pair<String, GlslType>,
defaultInitializer: String
defaultInitializer: GlslExpr
) : this(name, mapOf(*fields), defaultInitializer)

fun toGlsl(namespace: GlslCode.Namespace?, publicStructNames: Set<String>): String {
Expand Down Expand Up @@ -63,24 +68,24 @@ sealed class GlslType constructor(


companion object {
private fun initializerFor(fields: Map<String, GlslType>): String =
private fun initializerFor(fields: Map<String, GlslType>): GlslExpr =
StringBuilder().apply {
append("{ ")
fields.entries.forEachIndexed { index, (_, glslType) ->
if (index > 0)
append(", ")
append(glslType.defaultInitializer)
append(glslType.defaultInitializer.s)
}
append(" }")
}.toString()
}.toString().let { GlslExpr(it) }
}
}

object Float : GlslType("float", "0.")
object Float : GlslType("float", GlslExpr("0."))
object Vec2 : GlslType("vec2")
object Vec3 : GlslType("vec3")
object Vec4 : GlslType("vec4")
object Int : GlslType("int", "0")
object Int : GlslType("int", GlslExpr("0"))
object Sampler2D : GlslType("sampler2D")
object Void : GlslType("void")

Expand Down
7 changes: 5 additions & 2 deletions src/commonMain/kotlin/baaahs/gl/patch/Component.kt
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
package baaahs.gl.patch

import baaahs.gl.glsl.GlslExpr
import baaahs.gl.glsl.GlslType

interface Component {
val title: String
val outputVar: String?
val resultType: GlslType

val invokeFromMain: Boolean

fun appendStructs(buf: StringBuilder)
fun appendDeclarations(buf: StringBuilder)
fun appendInvokeAndSet(buf: StringBuilder, prefix: String)
fun appendInvokeAndSet(buf: StringBuilder, injectionParams: Map<String, ContentType> = emptyMap())

fun getExpression(): String
fun getExpression(prefix: String): GlslExpr
}
30 changes: 24 additions & 6 deletions src/commonMain/kotlin/baaahs/gl/patch/ContentType.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package baaahs.gl.patch

import baaahs.gl.glsl.GlslCode
import baaahs.gl.glsl.GlslExpr
import baaahs.gl.glsl.GlslType
import baaahs.plugin.core.MovingHeadParams

Expand All @@ -10,12 +11,12 @@ class ContentType(
val glslType: GlslType,
/** If false, this content type won't be suggested for matching GLSL types, it must be explicitly specified. */
val suggest: Boolean = true,
private val typeAdaptations: Map<GlslType, (String) -> String> = emptyMap(),
private val typeAdaptations: Map<GlslType, (GlslExpr) -> GlslExpr> = emptyMap(),
/** If [glslType] is a [GlslType.Struct], we currently need to provide a hint for converting it to a vector. */
val outputRepresentation: GlslType = glslType,
private val defaultInitializer: ((GlslType) -> String)? = null
private val defaultInitializer: ((GlslType) -> GlslExpr)? = null
) {
fun initializer(dataType: GlslType): String =
fun initializer(dataType: GlslType): GlslExpr =
defaultInitializer?.invoke(dataType)
?: officialDefaultInitializer(dataType)

Expand All @@ -26,7 +27,7 @@ class ContentType(
private fun officialDefaultInitializer(dataType: GlslType) =
(if (dataType == glslType) glslType else dataType).defaultInitializer

fun adapt(expression: String, toType: GlslType): String {
fun adapt(expression: GlslExpr, toType: GlslType): GlslExpr {
return typeAdaptations[toType]?.invoke(expression)
?: expression
}
Expand All @@ -35,6 +36,23 @@ class ContentType(
return id == "unknown" || id.startsWith("unknown/")
}

/**
* OpenGL doesn't support struct buffers directly, so emit any struct results to scalar arrays.
*/
fun appendResultAsScalars(buf: StringBuilder, varName: String) {
if (outputRepresentation != glslType) {
// Pass struct members through an output-friendly type.
buf.append(outputRepresentation.glslLiteral, "(")
(glslType as GlslType.Struct).fields.entries.forEachIndexed { index, (name, _) ->
if (index > 0) buf.append(",")
buf.append("\n $varName.$name")
}
buf.append("\n )")
} else {
buf.append(varName)
}
}

override fun toString(): String = "ContentType($id [$glslType])"

override fun equals(other: Any?): Boolean {
Expand Down Expand Up @@ -70,14 +88,14 @@ class ContentType(

val UvCoordinate = ContentType(
"uv-coordinate", "U/V Coordinate", GlslType.Vec2,
typeAdaptations = mapOf(GlslType.Vec4 to { "$it.xy" })
typeAdaptations = mapOf(GlslType.Vec4 to { GlslExpr("${it.s}.xy") })
)
val XyCoordinate = ContentType("xy-coordinate", "X/Y Coordinate", GlslType.Vec2)
val ModelInfo = ContentType("model-info", "Model Info", MoreTypes.ModelInfo.glslType)
val Mouse = ContentType("mouse", "Mouse", GlslType.Vec2)
val XyzCoordinate = ContentType("xyz-coordinate", "X/Y/Z Coordinate", GlslType.Vec3)
val Color = ContentType("color", "Color", GlslType.Vec4) { type ->
if (type == GlslType.Vec4) "vec4(0., 0., 0., 1.)" else type.defaultInitializer
if (type == GlslType.Vec4) GlslExpr("vec4(0., 0., 0., 1.)") else type.defaultInitializer
}
val Time = ContentType("time", "Time", GlslType.Float)
val Float = ContentType("float", "Float", GlslType.Float)
Expand Down
11 changes: 7 additions & 4 deletions src/commonMain/kotlin/baaahs/gl/patch/DataSourceComponent.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package baaahs.gl.patch

import baaahs.gl.glsl.GlslExpr
import baaahs.gl.glsl.GlslType
import baaahs.show.DataSource

Expand All @@ -10,6 +11,8 @@ class DataSourceComponent(val dataSource: DataSource, val varName: String) : Com
get() = null
override val resultType: GlslType
get() = dataSource.getType()
override val invokeFromMain: Boolean
get() = true

override fun appendStructs(buf: StringBuilder) {
val glslType = dataSource.contentType.glslType
Expand All @@ -26,11 +29,11 @@ class DataSourceComponent(val dataSource: DataSource, val varName: String) : Com
}
}

override fun appendInvokeAndSet(buf: StringBuilder, prefix: String) {
dataSource.appendInvokeAndSet(buf, prefix, varName)
override fun appendInvokeAndSet(buf: StringBuilder, injectionParams: Map<String, ContentType>) {
dataSource.appendInvokeAndSet(buf, varName)
}

override fun getExpression(): String {
return dataSource.getVarName(varName)
override fun getExpression(prefix: String): GlslExpr {
return GlslExpr(dataSource.getVarName(varName))
}
}
Loading

0 comments on commit 895d9d6

Please sign in to comment.