Skip to content

Commit

Permalink
Closes #7
Browse files Browse the repository at this point in the history
  • Loading branch information
Laxystem committed Jan 23, 2025
1 parent 5a7734a commit 4aa51b6
Show file tree
Hide file tree
Showing 15 changed files with 416 additions and 138 deletions.
3 changes: 3 additions & 0 deletions core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ plugins {
dependencies {
commonMainApi(projects.math)
commonMainApi(projects.util)

// TODO: change dependency to only include enumerations
commonMainApi(libs.wgpu4k)
}

kotlin {
Expand Down
3 changes: 2 additions & 1 deletion core/src/commonMain/kotlin/Pipeline.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ package quest.laxla.spock
*
* @since 0.0.1-alpha.4
*/
public data class Pipeline<Vertex : Any> @ExperimentalSpockApi constructor(
@ExperimentalSpockApi
public data class Pipeline<Vertex : Any>(
public val mesh: Mesh<Vertex>,
public val vertexShader: VertexShader<Vertex>
)
3 changes: 2 additions & 1 deletion core/src/commonMain/kotlin/Renderer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ package quest.laxla.spock
@SubclassOptInRequired(ExperimentalSpockApi::class)
public interface Renderer : Closer {
/**
* Render a frame.
* Renders a frame.
*
* @since 0.0.1-alpha.4
*/
@Throws(UnsupportedShaderException::class)
public suspend operator fun invoke()
}
112 changes: 98 additions & 14 deletions core/src/commonMain/kotlin/Shader.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
package quest.laxla.spock

import kotlinx.collections.immutable.ImmutableSet

/**
* Any kind of shader.
* Represents a program to be run on the GPU.
*
* Shaders are provided to [Renderer]s via [Pipeline]s, and are defined by two parameters;
* * [Kind], that itself consists of two more parameters;
* * [Language] (e.g. [Wgsl]), accessible via [Shader.language].
* * [FormFactor] (e.g. [StringShader.FormFactor]), accessible via [Shader.formFactor].
* * Type represented by sub-interfaces that are referred to directly by [Pipeline]s (e.g. [VertexShader]).
*
* Shading languages and form factors often require shaders
* to implement an additional interface carrying additional metadata (e.g. [Wgsl.Shader.entrypoint]),
* or in the case of form factors, the code itself (e.g. [StringShader.code]).
*
* [Renderer]s are expected to deduplicate shaders that have same code and [label].
*
* @since 0.0.1-alpha.4
*/
Expand All @@ -10,11 +24,20 @@ public interface Shader {
* The language this [Shader] is written in.
*
* @since 0.0.1-alpha.4
* @see Shader.kind
*/
public val language: Language

/**
* The label the graphics API should refer to this [Shader] under for logging purposes.
* The [FormFactor] of this [Shader].
*
* @since 0.0.1-alpha.4
* @see Shader.kind
*/
public val formFactor: FormFactor

/**
* The label this [Shader] should be referred to as for logging purposes.
*
* @since 0.0.1-alpha.4
*/
Expand Down Expand Up @@ -42,13 +65,48 @@ public interface Shader {
}

/**
* Implemented by [Shader]s dynamically compiled from another shader of a different [Language] or form factor.
* Represents a shader form, e.g., a [StringShader].
*
* Implementations **must** properly implement [equals], [hashCode], and [toString];
* Therefore, it is recommended to use `data object`s.
*
* @since 0.0.1-alpha.4
* @sample StringShader
*/
public interface FormFactor {
/**
* Does this [shader] carry all metadata required by this form factor?
*
* This function always returns `false` if the shader's [FormFactor] is not this one.
*
* @since 0.0.1-alpha.4
* @see Shader.isCarryingRequiredMetadata
*/
public infix fun accepts(shader: Shader): Boolean
}

/**
* Combination of a [FormFactor] and a [Language].
*
* @property formFactor the form factor of [Shader]s of this kind.
* @property language the language [Shader]s of this kind are written in.
* @since 0.0.1-alpha.4
* @see Shader.kind
*/
public data class Kind<out L, out F>(
val language: Language,
val formFactor: FormFactor
) where L : Language, F : FormFactor

/**
* Implemented by [Shader]s dynamically compiled from another shader of a different [Language] or [FormFactor].
*
* @param L the language this shader was transpiled to.
* @param F the form factor this shader was transpiled to.
* @since 0.0.1-alpha.4
* @see Transpiler
*/
public interface Transpiled<L> : Shader where L : Language {
public interface Transpiled<out L, out F> : Shader where L : Language, F : FormFactor {
/**
* The original [Shader] this one was compiled from.
*
Expand All @@ -57,31 +115,57 @@ public interface Shader {
public val original: Shader

override val language: L
override val formFactor: F
}

/**
* Transpiles [Shader] from one [Language] or form factor to another if not supported by the [Renderer].
* Transpiles [Shader]s of one [Kind] to another.
*
* @since 0.0.1-alpha.4
* @see Transpiled
*/
public interface Transpiler<L> where L : Language {
public sealed interface Transpiler<out L, out F> where L : Language, F : FormFactor {
/**
* The [Language] the shaders this transpiler outputs are written in.
* Transpiles the [input]ted [Shader] to one of the [outputKinds].
*
* It is expected but not required that the output [carries all required metadata][Shader.isCarryingRequiredMetadata].
*
* @return `null` if this [Transpiler] does not support the provided [input].
* @since 0.0.1-alpha.4
* @see transpile
*/
public val outputLanguage: L
public suspend operator fun invoke(input: Shader): Transpiled<L, F>?

/**
* Transpiles the [input] [Shader] to the [outputLanguage].
* Transpiles [Shader]s to a single, constant [outputKind].
*
* It is expected but not required that the output is [accept][Language.accepts]ed;
* However, prefer returning an unaccepted shader over `null` when possible and not expensive.
*
* @return `null` if this [Transpiler] does not support this [input].
* @since 0.0.1-alpha.4
* @see Transpiler
* @see Transpiler.Dynamic
*/
public interface SingleTarget<out L, out F> : Transpiler<L, F> where L : Language, F : FormFactor {
/**
* The [Kind] of all [Shader]s outputted by this [Transpiler].
*
* @since 0.0.1-alpha.4
*/
public val outputKind: Kind<L, F>
}

/**
* Transpile [Shader]s to any of the pre-selected [outputKinds].
*
* It is up to the implementation to select the optimal [Kind].
*
* @see 0.0.1-alpha.4
*/
public suspend operator fun invoke(input: Shader): Transpiled<L>?
public interface Dynamic<out L, out F> : Transpiler<L, F> where L : Language, F : FormFactor {
/**
* All [Shader.Kind]s this [Transpiler] can output.
*
* @since 0.0.1-alpha.4
*/
public val outputKinds: ImmutableSet<Kind<L, F>>
}
}
}
Loading

0 comments on commit 4aa51b6

Please sign in to comment.