diff --git a/.bsp/sbt.json b/.bsp/sbt.json new file mode 100644 index 00000000..d8670b12 --- /dev/null +++ b/.bsp/sbt.json @@ -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"]} \ No newline at end of file diff --git a/.gitignore b/.gitignore index cb00cbb9..b0aa893d 100644 Binary files a/.gitignore and b/.gitignore differ diff --git a/.jvmopts b/.jvmopts new file mode 100644 index 00000000..fb724667 Binary files /dev/null and b/.jvmopts differ diff --git a/build.sbt b/build.sbt index be3ae143..b7231825 100644 --- a/build.sbt +++ b/build.sbt @@ -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( @@ -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" \ No newline at end of file diff --git a/output.log b/output.log new file mode 100644 index 00000000..9aa7c6a3 Binary files /dev/null and b/output.log differ diff --git a/src/main/scala/io/computenode/cyfra/dsl/GMem.scala b/src/main/scala/io/computenode/cyfra/dsl/GMem.scala index e5db230e..c666be23 100644 --- a/src/main/scala/io/computenode/cyfra/dsl/GMem.scala +++ b/src/main/scala/io/computenode/cyfra/dsl/GMem.scala @@ -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 @@ -81,6 +83,13 @@ 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 } @@ -88,8 +97,15 @@ class FloatMem(val size: Int) extends WritableGMem[Float32, Float]: 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) diff --git a/src/main/scala/io/computenode/cyfra/dsl/GSeq.scala b/src/main/scala/io/computenode/cyfra/dsl/GSeq.scala index 9b5daf94..f65b8443 100644 --- a/src/main/scala/io/computenode/cyfra/dsl/GSeq.scala +++ b/src/main/scala/io/computenode/cyfra/dsl/GSeq.scala @@ -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, @@ -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 )) @@ -57,7 +56,7 @@ 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 = @@ -65,25 +64,25 @@ class GSeq[T <: Value : Tag : FromExpr]( 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) { @@ -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[_] @@ -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)) \ No newline at end of file diff --git a/src/main/scala/io/computenode/cyfra/foton/rt/animation/AnimationRtRenderer.scala b/src/main/scala/io/computenode/cyfra/foton/rt/animation/AnimationRtRenderer.scala index f4b42f71..fb0805db 100644 --- a/src/main/scala/io/computenode/cyfra/foton/rt/animation/AnimationRtRenderer.scala +++ b/src/main/scala/io/computenode/cyfra/foton/rt/animation/AnimationRtRenderer.scala @@ -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 diff --git a/src/main/scala/io/computenode/cyfra/samples/PlaygroundMain.scala b/src/main/scala/io/computenode/cyfra/samples/PlaygroundMain.scala new file mode 100644 index 00000000..8741fe7f --- /dev/null +++ b/src/main/scala/io/computenode/cyfra/samples/PlaygroundMain.scala @@ -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}") \ No newline at end of file diff --git a/src/main/scala/io/computenode/cyfra/spirv/compilers/ExpressionCompiler.scala b/src/main/scala/io/computenode/cyfra/spirv/compilers/ExpressionCompiler.scala index a2efe0c1..e90117f7 100644 --- a/src/main/scala/io/computenode/cyfra/spirv/compilers/ExpressionCompiler.scala +++ b/src/main/scala/io/computenode/cyfra/spirv/compilers/ExpressionCompiler.scala @@ -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( diff --git a/vulkan_debug.log b/vulkan_debug.log new file mode 100644 index 00000000..97c609f1 Binary files /dev/null and b/vulkan_debug.log differ