Skip to content
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
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package io.computenode.cyfra.core

import io.computenode.cyfra.core.binding.{GBinding, GBuffer, GUniform}
import io.computenode.cyfra.core.expression.Value
import io.computenode.cyfra.core.layout.{Layout, LayoutBinding}
import io.computenode.cyfra.dsl.Value
import io.computenode.cyfra.dsl.Value.FromExpr
import io.computenode.cyfra.dsl.binding.{GBinding, GBuffer, GUniform}
import io.computenode.cyfra.dsl.struct.{GStruct, GStructSchema}
import izumi.reflect.Tag

import java.nio.ByteBuffer
Expand All @@ -21,11 +19,11 @@ trait Allocation:
def execute(params: Params, layout: EL): RL

extension (buffers: GBuffer.type)
def apply[T <: Value: {Tag, FromExpr}](length: Int): GBuffer[T]
def apply[T: Value](length: Int): GBuffer[T]

def apply[T <: Value: {Tag, FromExpr}](buff: ByteBuffer): GBuffer[T]
def apply[T: Value](buff: ByteBuffer): GBuffer[T]

extension (buffers: GUniform.type)
def apply[T <: GStruct[T]: {Tag, FromExpr, GStructSchema}](buff: ByteBuffer): GUniform[T]
def apply[T: Value](buff: ByteBuffer): GUniform[T]

def apply[T <: GStruct[T]: {Tag, FromExpr, GStructSchema}](): GUniform[T]
def apply[T: Value](): GUniform[T]
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@ package io.computenode.cyfra.core

import io.computenode.cyfra.core.GProgram.*
import io.computenode.cyfra.core.layout.*
import io.computenode.cyfra.dsl.Value.GBoolean
import io.computenode.cyfra.dsl.gio.GIO
import io.computenode.cyfra.core.expression.ExpressionBlock
import izumi.reflect.Tag

case class GioProgram[Params, L <: Layout: {LayoutBinding, LayoutStruct}](
body: L => GIO[?],
case class ExpressionProgram[Params, L <: Layout: {LayoutBinding, LayoutStruct}](
body: L => ExpressionBlock[Unit],
layout: InitProgramLayout => Params => L,
dispatch: (L, Params) => ProgramDispatch,
workgroupSize: WorkDimensions,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ import io.computenode.cyfra.core.Allocation
import io.computenode.cyfra.core.GBufferRegion.MapRegion
import io.computenode.cyfra.core.GProgram.BufferLengthSpec
import io.computenode.cyfra.core.layout.{Layout, LayoutBinding}
import io.computenode.cyfra.dsl.Value
import io.computenode.cyfra.dsl.Value.FromExpr
import io.computenode.cyfra.dsl.binding.GBuffer
import io.computenode.cyfra.core.expression.Value
import io.computenode.cyfra.core.binding.GBuffer
import izumi.reflect.Tag

import scala.util.chaining.given
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ package io.computenode.cyfra.core

import io.computenode.cyfra.core.GExecution.*
import io.computenode.cyfra.core.layout.*
import io.computenode.cyfra.dsl.binding.GBuffer
import io.computenode.cyfra.dsl.gio.GIO
import io.computenode.cyfra.dsl.struct.{GStruct, GStructSchema}
import io.computenode.cyfra.core.binding.GBuffer
import izumi.reflect.Tag
import GExecution.*

Expand Down
24 changes: 11 additions & 13 deletions cyfra-core/src/main/scala/io/computenode/cyfra/core/GProgram.scala
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
package io.computenode.cyfra.core

import io.computenode.cyfra.core.layout.{Layout, LayoutBinding, LayoutStruct}
import io.computenode.cyfra.dsl.gio.GIO

import java.nio.ByteBuffer
import GProgram.*
import io.computenode.cyfra.dsl.{Expression, Value}
import io.computenode.cyfra.dsl.Value.{FromExpr, GBoolean, Int32}
import io.computenode.cyfra.dsl.binding.{GBinding, GBuffer, GUniform}
import io.computenode.cyfra.dsl.struct.{GStruct, GStructSchema}
import io.computenode.cyfra.dsl.struct.GStruct.Empty
import io.computenode.cyfra.core.binding.GUniform
import io.computenode.cyfra.core.binding.GBuffer
import io.computenode.cyfra.core.binding.GBinding
import io.computenode.cyfra.core.expression.{ExpressionBlock, Value}
import izumi.reflect.Tag

import java.io.FileInputStream
Expand All @@ -33,8 +31,8 @@ object GProgram:
layout: InitProgramLayout ?=> Params => L,
dispatch: (L, Params) => ProgramDispatch,
workgroupSize: WorkDimensions = (128, 1, 1),
)(body: L => GIO[?]): GProgram[Params, L] =
new GioProgram[Params, L](body, s => layout(using s), dispatch, workgroupSize)
)(body: L => ExpressionBlock[Unit]): GProgram[Params, L] =
new ExpressionProgram[Params, L](body, s => layout(using s), dispatch, workgroupSize)

def fromSpirvFile[Params, L <: Layout: {LayoutBinding, LayoutStruct}](
layout: InitProgramLayout ?=> Params => L,
Expand All @@ -49,16 +47,16 @@ object GProgram:
bb.flip()
SpirvProgram(layout, dispatch, bb)

private[cyfra] class BufferLengthSpec[T <: Value: {Tag, FromExpr}](val length: Int) extends GBuffer[T]:
private[cyfra] class BufferLengthSpec[T: Value](val length: Int) extends GBuffer[T]:
private[cyfra] def materialise()(using Allocation): GBuffer[T] = GBuffer.apply[T](length)
private[cyfra] class DynamicUniform[T <: GStruct[T]: {Tag, FromExpr, GStructSchema}]() extends GUniform[T]
private[cyfra] class DynamicUniform[T: Value]() extends GUniform[T]

trait InitProgramLayout:
extension (_buffers: GBuffer.type)
def apply[T <: Value: {Tag, FromExpr}](length: Int): GBuffer[T] =
def apply[T: Value](length: Int): GBuffer[T] =
BufferLengthSpec[T](length)

extension (_uniforms: GUniform.type)
def apply[T <: GStruct[T]: {Tag, FromExpr, GStructSchema}](): GUniform[T] =
def apply[T: Value](): GUniform[T] =
DynamicUniform[T]()
def apply[T <: GStruct[?]: {Tag, FromExpr, GStructSchema}](value: T): GUniform[T]
def apply[T: Value](value: T): GUniform[T]
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@ import io.computenode.cyfra.core.layout.{Layout, LayoutBinding, LayoutStruct}
import io.computenode.cyfra.core.GProgram.{InitProgramLayout, ProgramDispatch, WorkDimensions}
import io.computenode.cyfra.core.SpirvProgram.Operation.ReadWrite
import io.computenode.cyfra.core.SpirvProgram.{Binding, ShaderLayout}
import io.computenode.cyfra.dsl.Value
import io.computenode.cyfra.dsl.Value.{FromExpr, GBoolean}
import io.computenode.cyfra.dsl.binding.GBinding
import io.computenode.cyfra.dsl.gio.GIO
import io.computenode.cyfra.core.expression.Value
import io.computenode.cyfra.core.binding.GBinding
import izumi.reflect.Tag

import java.io.File
Expand Down Expand Up @@ -44,7 +42,7 @@ case class SpirvProgram[Params, L <: Layout: {LayoutBinding, LayoutStruct}] priv
)
val layout = shaderBindings(summon[LayoutStruct[L]].layoutRef)
layout.flatten.foreach: binding =>
md.update(binding.binding.tag.toString.getBytes)
// md.update(binding.binding.tag.toString.getBytes)
md.update(binding.operation.toString.getBytes)
val digest = md.digest()
val bb = java.nio.ByteBuffer.wrap(digest)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
package io.computenode.cyfra.core.binding

import io.computenode.cyfra.dsl.Value
import io.computenode.cyfra.dsl.Value.FromExpr
import io.computenode.cyfra.dsl.binding.GBuffer
import izumi.reflect.Tag
import izumi.reflect.macrortti.LightTypeTag
import io.computenode.cyfra.core.expression.Value

case class BufferRef[T <: Value: {Tag, FromExpr}](layoutOffset: Int, valueTag: Tag[T]) extends GBuffer[T]
case class BufferRef[T: Value](layoutOffset: Int, valueTag: Tag[T]) extends GBuffer[T]
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package io.computenode.cyfra.core.binding

import io.computenode.cyfra.core.expression.Value

sealed trait GBinding[T: Value]

object GBinding

trait GBuffer[T: Value] extends GBinding[T]

object GBuffer

trait GUniform[T: Value] extends GBinding[T]

object GUniform:
class ParamUniform[T: Value] extends GUniform[T]
def fromParams[T: Value]: ParamUniform[T] = ParamUniform[T]()
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
package io.computenode.cyfra.core.binding

import io.computenode.cyfra.dsl.Value
import io.computenode.cyfra.dsl.Value.FromExpr
import io.computenode.cyfra.dsl.binding.{GBuffer, GUniform}
import io.computenode.cyfra.dsl.struct.{GStruct, GStructSchema}
import izumi.reflect.Tag
import izumi.reflect.macrortti.LightTypeTag
import io.computenode.cyfra.core.expression.Value

case class UniformRef[T <: GStruct[?]: {Tag, FromExpr, GStructSchema}](layoutOffset: Int, valueTag: Tag[T]) extends GUniform[T]
case class UniformRef[T: Value](layoutOffset: Int, valueTag: Tag[T]) extends GUniform[T]
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package io.computenode.cyfra.core.expression

import io.computenode.cyfra.core.expression.*

abstract class BuildInFunction[-R](val isPure: Boolean):
override def toString: String = s"builtin ${this.getClass.getSimpleName.replace("$", "")}"

object BuildInFunction:
abstract class BuildInFunction0[-R](isPure: Boolean) extends BuildInFunction[R](isPure)
abstract class BuildInFunction1[-A1, -R](isPure: Boolean) extends BuildInFunction[R](isPure)
abstract class BuildInFunction1R[-R](isPure: Boolean) extends BuildInFunction1[R, R](isPure)
abstract class BuildInFunction2[-A1, -A2, -R](isPure: Boolean) extends BuildInFunction[R](isPure)
abstract class BuildInFunction2R[-R](isPure: Boolean) extends BuildInFunction2[R, R, R](isPure)
abstract class BuildInFunction3[-A1, -A2, -A3, -R](isPure: Boolean) extends BuildInFunction[R](isPure)
abstract class BuildInFunction4[-A1, -A2, -A3, -A4, -R](isPure: Boolean) extends BuildInFunction[R](isPure)

// Concreate type operations
case object Add extends BuildInFunction2R[Any](true)
case object Sub extends BuildInFunction2R[Any](true)
case object Mul extends BuildInFunction2R[Any](true)
case object Div extends BuildInFunction2R[Any](true)
case object Mod extends BuildInFunction2R[Any](true)

// Negative type operations
case object Neg extends BuildInFunction1R[Any](true)
case object Rem extends BuildInFunction2R[Any](true)

// Vector/Matrix operations
case object VectorTimesScalar extends BuildInFunction2[Any, Any, Any](true)
case object MatrixTimesScalar extends BuildInFunction2[Any, Any, Any](true)
case object VectorTimesMatrix extends BuildInFunction2[Any, Any, Any](true)
case object MatrixTimesVector extends BuildInFunction2[Any, Any, Any](true)
case object MatrixTimesMatrix extends BuildInFunction2R[Any](true)
case object OuterProduct extends BuildInFunction2[Any, Any, Any](true)
case object Dot extends BuildInFunction2[Any, Any, Any](true)

// Bitwise operations
case object ShiftRightLogical extends BuildInFunction2R[Any](true)
case object ShiftRightArithmetic extends BuildInFunction2R[Any](true)
case object ShiftLeftLogical extends BuildInFunction2R[Any](true)
case object BitwiseOr extends BuildInFunction2R[Any](true)
case object BitwiseXor extends BuildInFunction2R[Any](true)
case object BitwiseAnd extends BuildInFunction2R[Any](true)
case object BitwiseNot extends BuildInFunction1R[Any](true)
case object BitFieldInsert extends BuildInFunction4[Any, Any, Any, Any, Any](true)
case object BitFieldSExtract extends BuildInFunction3[Any, Any, Any, Any](true)
case object BitFieldUExtract extends BuildInFunction3[Any, Any, Any, Any](true)
case object BitReverse extends BuildInFunction1R[Any](true)
case object BitCount extends BuildInFunction1[Any, Any](true)

// Logical operations on booleans
case object LogicalAny extends BuildInFunction1[Any, Bool](true)
case object LogicalAll extends BuildInFunction1[Any, Bool](true)
case object LogicalEqual extends BuildInFunction2R[Any](true)
case object LogicalNotEqual extends BuildInFunction2R[Any](true)
case object LogicalOr extends BuildInFunction2R[Any](true)
case object LogicalAnd extends BuildInFunction2R[Any](true)
case object LogicalNot extends BuildInFunction1R[Any](true)

// Floating-point checks
case object IsNan extends BuildInFunction1[Any, Any](true)
case object IsInf extends BuildInFunction1[Any, Any](true)
case object IsFinite extends BuildInFunction1[Any, Any](true)
case object IsNormal extends BuildInFunction1[Any, Any](true)
case object SignBitSet extends BuildInFunction1[Any, Any](true)

// Comparisons
case object Equal extends BuildInFunction2[Any, Any, Any](true)
case object NotEqual extends BuildInFunction2[Any, Any, Any](true)
case object LessThan extends BuildInFunction2[Any, Any, Any](true)
case object GreaterThan extends BuildInFunction2[Any, Any, Any](true)
case object LessThanEqual extends BuildInFunction2[Any, Any, Any](true)
case object GreaterThanEqual extends BuildInFunction2[Any, Any, Any](true)

// Select
case object Select extends BuildInFunction3[Any, Any, Any, Any](true)
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package io.computenode.cyfra.core.expression

import io.computenode.cyfra.utility.Utility.nextId

case class CustomFunction[A: Value] private[cyfra] (name: String, arg: List[Var[?]], body: ExpressionBlock[A]):
def v : Value[A] = summon[Value[A]]
val id: Int = nextId()
lazy val isPure: Boolean = body.isPureWith(arg.map(_.id).toSet)

object CustomFunction:
def apply[A: Value, B: Value](func: Var[A] => ExpressionBlock[B]): CustomFunction[B] =
val arg = Var[A]()
val body = func(arg)
CustomFunction(s"custom${nextId() + 1}", List(arg), body)
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package io.computenode.cyfra.core.expression

import io.computenode.cyfra.core.binding.{GBuffer, GUniform}
import io.computenode.cyfra.core.expression.given
import io.computenode.cyfra.utility.Utility.nextId
import io.computenode.cyfra.core.expression.{Bool, Float16, Float32, Int16, Int32, UInt16, UInt32, given}

sealed trait Expression[A: Value]:
val id: Int = nextId()
def v: Value[A] = summon[Value[A]]

object Expression:
case class Constant[A: Value](value: Any) extends Expression[A]
case class VarDeclare[A: Value](variable: Var[A]) extends Expression[Unit]:
def v2: Value[A] = summon[Value[A]]
case class VarRead[A: Value](variable: Var[A]) extends Expression[A]
case class VarWrite[A: Value](variable: Var[A], value: Expression[A]) extends Expression[Unit]:
def v2: Value[A] = summon[Value[A]]
case class ReadBuffer[A: Value](buffer: GBuffer[A], index: Expression[UInt32]) extends Expression[A]
case class WriteBuffer[A: Value](buffer: GBuffer[A], index: Expression[UInt32], value: Expression[A]) extends Expression[Unit]:
def v2: Value[A] = summon[Value[A]]
case class ReadUniform[A: Value](uniform: GUniform[A]) extends Expression[A]
case class WriteUniform[A: Value](uniform: GUniform[A], value: Expression[A]) extends Expression[Unit]:
def v2: Value[A] = summon[Value[A]]
case class BuildInOperation[A: Value](func: BuildInFunction[A], args: List[Expression[?]]) extends Expression[A]
case class CustomCall[A: Value](func: CustomFunction[A], args: List[Var[?]]) extends Expression[A]
case class Branch[T: Value](cond: Expression[Bool], ifTrue: ExpressionBlock[T], ifFalse: ExpressionBlock[T], break: JumpTarget[T])
extends Expression[T]
case class Loop(mainBody: ExpressionBlock[Unit], continueBody: ExpressionBlock[Unit], break: JumpTarget[Unit], continue: JumpTarget[Unit])
extends Expression[Unit]
case class Jump[A: Value](target: JumpTarget[A], value: Expression[A]) extends Expression[Unit]:
def v2: Value[A] = summon[Value[A]]
case class ConditionalJump[A: Value](cond: Expression[Bool], target: JumpTarget[A], value: Expression[A]) extends Expression[Unit]:
def v2: Value[A] = summon[Value[A]]
Loading
Loading