Skip to content
Open
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
1 change: 1 addition & 0 deletions .bsp/sbt.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"name":"sbt","version":"1.9.7","bspVersion":"2.1.0-M1","languages":["scala"],"argv":["C:\\Program Files\\Eclipse Adoptium\\jdk-21.0.2.13-hotspot/bin/java","-Xms100m","-Xmx100m","-classpath","C:\\Program Files (x86)\\sbt\\\\bin\\sbt-launch.jar","-Dsbt.script=C:\\Program%20Files%20(x86)\\sbt\\bin\\sbt.bat","xsbt.boot.Boot","-bsp"]}
Binary file modified .gitignore
Binary file not shown.
Binary file added .jvmopts
Binary file not shown.
5 changes: 2 additions & 3 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ lazy val lwjglNatives = {

val lwjglVersion = "3.3.3"
val jomlVersion = "1.10.0"

javaOptions += "-Xmx8G"

lazy val root = (project in file("."))
.settings(
Expand All @@ -56,5 +56,4 @@ lazy val root = (project in file("."))
)

lazy val vulkanSdk = System.getenv("VULKAN_SDK")
javaOptions += s"-Dorg.lwjgl.vulkan.libname=$vulkanSdk/lib/libvulkan.1.dylib"

javaOptions += s"-Dorg.lwjgl.vulkan.libname=$vulkanSdk/lib/libvulkan.1.dylib"
Binary file added output.log
Binary file not shown.
18 changes: 17 additions & 1 deletion src/main/scala/io/computenode/cyfra/dsl/GMem.scala
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ trait WritableGMem[T <: Value, R] extends GMem[T]:
data.putFloat(x)
data.putFloat(y)
case illegal =>
throw new IllegalArgumentException(s"Uniform must be constructed from constants (got field $illegal)")
val errorMessage = s"Error: Unsupported uniform type encountered -> $illegal. Expected only constant values."
println(errorMessage) // Add logging for better debugging
throw new IllegalArgumentException(errorMessage)
}
data.rewind()
data
Expand All @@ -81,15 +83,29 @@ class FloatMem(val size: Int) extends WritableGMem[Float32, Float]:
val res = buffer.asFloatBuffer()
val result = new Array[Float](size)
res.get(result)

// Debugging: Print first few values read
println("DEBUG: First few values read from FloatMem:")
for (i <- 0 until math.min(10, result.length)) {
println(s" Read Value $i: ${result(i)}")
}

result
}

def write(floats: Array[Float]): Unit = {
data.rewind()
data.asFloatBuffer().put(floats)
data.rewind()

// Debugging: Print first few values after writing
println("DEBUG: First few values written to FloatMem:")
for (i <- 0 until math.min(10, floats.length)) {
println(s" Value $i: ${floats(i)}")
}
}


object FloatMem {
def apply(floats: Array[Float]): FloatMem = {
val floatMem = new FloatMem(floats.length)
Expand Down
84 changes: 41 additions & 43 deletions src/main/scala/io/computenode/cyfra/dsl/GSeq.scala
Original file line number Diff line number Diff line change
@@ -1,31 +1,29 @@
package io.computenode.cyfra.dsl

import io.computenode.cyfra.dsl.Algebra.{*, given}
import io.computenode.cyfra.dsl.Algebra.{*, given}
import io.computenode.cyfra.dsl.Control.{Scope, when}
import io.computenode.cyfra.dsl.Expression.{ConstInt32, E}
import io.computenode.cyfra.dsl.GSeq.*
import io.computenode.cyfra.dsl.Value.*
import io.computenode.cyfra.dsl.{Expression, GSeq, PhantomExpression}
import izumi.reflect.Tag
import org.slf4j.{Logger, LoggerFactory}

import java.util.Base64
import scala.util.Random
import java.util.concurrent.atomic.AtomicInteger

class GSeq[T <: Value : Tag : FromExpr](
val uninitSource: Expression[_] => GSeqStream[_],
class GSeq[T <: Value: Tag: FromExpr](
val uninitSource: Expression[_] => GSeq.GSeqStream[_], // Fixed: Use GSeq.GSeqStream
val elemOps: List[GSeq.ElemOp[_]],
val limit: Option[Int],
val name: sourcecode.Name,
val currentElemExprTreeId: Int = treeidState.getAndIncrement(),
val aggregateElemExprTreeId: Int = treeidState.getAndIncrement()
val currentElemExprTreeId: Int = GSeq.treeidState.getAndIncrement(),
val aggregateElemExprTreeId: Int = GSeq.treeidState.getAndIncrement()
):

def copyWithDynamicTrees[R <: Value : Tag : FromExpr](
def copyWithDynamicTrees[R <: Value: Tag: FromExpr](
elemOps: List[GSeq.ElemOp[_]] = elemOps,
limit: Option[Int] = limit,
currentElemExprTreeId: Int = currentElemExprTreeId,
aggregateElemExprTreeId: Int = aggregateElemExprTreeId
) = GSeq[R](
): GSeq[R] = GSeq[R](
uninitSource,
elemOps,
limit,
Expand All @@ -34,13 +32,14 @@ class GSeq[T <: Value : Tag : FromExpr](
aggregateElemExprTreeId
)

private val currentElemExpr = CurrentElem[T](currentElemExprTreeId)
val source = uninitSource(currentElemExpr)
private val currentElemExpr = GSeq.CurrentElem[T](currentElemExprTreeId)
val source: GSeq.GSeqStream[_] = uninitSource(currentElemExpr) // Fixed: Use GSeq.GSeqStream

private def currentElem: T = summon[FromExpr[T]].fromExpr(currentElemExpr)
private def aggregateElem[R <: Value : Tag: FromExpr]: R = summon[FromExpr[R]].fromExpr(AggregateElem[R](aggregateElemExprTreeId))
private def aggregateElem[R <: Value: Tag: FromExpr]: R = summon[FromExpr[R]].fromExpr(GSeq.AggregateElem[R](aggregateElemExprTreeId))

def map[R <: Value : Tag : FromExpr](fn: T => R): GSeq[R] =
this.copyWithDynamicTrees[R](elemOps = elemOps :+ GSeq.MapOp[T,R](
def map[R <: Value: Tag: FromExpr](fn: T => R): GSeq[R] =
this.copyWithDynamicTrees[R](elemOps = elemOps :+ GSeq.MapOp[T, R](
fn(currentElem).tree
))

Expand All @@ -57,33 +56,33 @@ class GSeq[T <: Value : Tag : FromExpr](
def limit(n: Int): GSeq[T] =
this.copyWithDynamicTrees(limit = Some(n))

def fold[R <: Value : Tag : FromExpr](zero: R, fn: (R, T) => R): R =
def fold[R <: Value: Tag: FromExpr](zero: R, fn: (R, T) => R): R =
summon[FromExpr[R]].fromExpr(GSeq.FoldSeq(zero, fn(aggregateElem, currentElem).tree, this))

def count: Int32 =
fold(0, (acc: Int32, _: T) => acc + 1)

def lastOr(t: T): T =
fold(t, (_: T, elem: T) => elem)



object GSeq:
private val treeidState = new AtomicInteger(0)
private val logger: Logger = LoggerFactory.getLogger(getClass)

def gen[T <: Value : Tag : FromExpr](first: T, next: T => T)(using name: sourcecode.Name) = GSeq(
def gen[T <: Value: Tag: FromExpr](first: T, next: T => T)(using name: sourcecode.Name): GSeq[T] = GSeq(
ce => GSeqStream(first, next(summon[FromExpr[T]].fromExpr(ce.asInstanceOf[E[T]])).tree),
Nil,
None,
name
)

// REALLY naive implementation, should be replaced with dynamic array (O(1)) access
def of[T <: Value : Tag : FromExpr](xs: List[T]) =
def of[T <: Value: Tag: FromExpr](xs: List[T]): GSeq[T] =
GSeq.gen[Int32](0, _ + 1).map { i =>
val first = when(i === 0) {
xs(0)
}
(if(xs.length == 1) {
(if (xs.length == 1) {
first
} else {
xs.init.zipWithIndex.tail.foldLeft(first) {
Expand All @@ -94,14 +93,14 @@ object GSeq:
}
}).otherwise(xs.last)
}.limit(xs.length)
case class CurrentElem[T <: Value : Tag](tid: Int) extends PhantomExpression[T] with CustomTreeId:

case class CurrentElem[T <: Value: Tag](tid: Int) extends PhantomExpression[T] with CustomTreeId:
override val treeid: Int = tid
case class AggregateElem[T <: Value : Tag](tid: Int) extends PhantomExpression[T] with CustomTreeId:

case class AggregateElem[T <: Value: Tag](tid: Int) extends PhantomExpression[T] with CustomTreeId:
override val treeid: Int = tid
sealed trait ElemOp[T <: Value : Tag]:

sealed trait ElemOp[T <: Value: Tag]:
def tag: Tag[T] = summon[Tag[T]]
def fn: Expression[_]

Expand All @@ -111,20 +110,19 @@ object GSeq:

sealed trait GSeqSource[T <: Value: Tag]
case class GSeqStream[T <: Value: Tag](init: T, next: Expression[_]) extends GSeqSource[T]

case class FoldSeq[R <: Value : Tag, T <: Value : Tag](zero: R, fn: Expression[_], seq: GSeq[T]) extends Expression[R]:
val zeroExpr = zero.tree
val fnExpr = fn
val streamInitExpr = seq.source.init.tree
val streamNextExpr = seq.source.next
val seqExprs = seq.elemOps.map(_.fn)

val limitExpr = ConstInt32(seq.limit.getOrElse(throw new IllegalArgumentException("Reduce on infinite stream is not supported")))

override val exprDependencies: List[E[_]] = List(zeroExpr, streamInitExpr, limitExpr)
override val introducedScopes: List[Scope[_]] = Scope(fnExpr)(using fnExpr.tag) :: Scope(streamNextExpr)(using streamNextExpr.tag) :: seqExprs.map(e => Scope(e)(using e.tag))



case class FoldSeq[R <: Value: Tag, T <: Value: Tag](zero: R, fn: Expression[_], seq: GSeq[T]) extends Expression[R]:
val zeroExpr: Expression[_] = zero.tree
val fnExpr: Expression[_] = fn
val streamInitExpr: Expression[_] = seq.source.init.tree
val streamNextExpr: Expression[_] = seq.source.next
val seqExprs: List[Expression[_]] = seq.elemOps.map(_.fn)

// Ensure a limit is set to avoid infinite stream errors
val limitExpr: ConstInt32 = ConstInt32(seq.limit.getOrElse {
logger.warn("No limit set on GSeq. This may result in an infinite stream. Call .limit(n) to set a limit.")
throw new IllegalArgumentException("Reduce on infinite stream is not supported. Call .limit(n) first.")
})

override val exprDependencies: List[E[_]] = List(zeroExpr, streamInitExpr, limitExpr)
override val introducedScopes: List[Scope[_]] = Scope(fnExpr)(using fnExpr.tag) :: Scope(streamNextExpr)(using streamNextExpr.tag) :: seqExprs.map(e => Scope(e)(using e.tag))
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class AnimationRtRenderer(params: AnimationRtRenderer.Parameters) extends RtRend
List.iterate((initialMem, 0), params.iterations + 1) { case (mem, render) =>
UniformContext.withUniform(RaytracingIteration(render, time)):
val fmem = Vec4FloatMem(mem)
val result = Await.result(fmem.map(fn), 1.minute)
val result = Await.result(fmem.map(fn), 5.minute)
(result, render + 1)
}.map(_._1).last

Expand Down
13 changes: 13 additions & 0 deletions src/main/scala/io/computenode/cyfra/samples/PlaygroundMain.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package io.computenode.cyfra.samples

import io.computenode.cyfra.dsl.Value.Float32
import io.computenode.cyfra.dsl.Value.given
import io.computenode.cyfra.dsl.Algebra.*
import io.computenode.cyfra.dsl.Algebra.given

object PlaygroundMain:

def main(args: Array[String]): Unit = // Use a traditional main method
val exampleFloat: Float32 = 3.14f
println("HI")
println(s"Example float: ${exampleFloat.toString}")
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ private[cyfra] object ExpressionCompiler:
case (from, _: ToUInt32[_]) if from.tag =:= Float32Tag.tag => Op.OpConvertFToU
case (from, _: ToInt32[_]) if from.tag =:= UInt32Tag.tag => Op.OpBitcast
case (from, _: ToUInt32[_]) if from.tag =:= Int32Tag.tag => Op.OpBitcast
case _ => throw new MatchError(s"Unexpected input: (${cexpr.fromTag}, $cexpr)")
}
val instructions = List(
Instruction(tfOpcode, List(
Expand Down
Binary file added vulkan_debug.log
Binary file not shown.