diff --git a/build.sbt b/build.sbt index 8005cccd..a36c04dc 100644 --- a/build.sbt +++ b/build.sbt @@ -76,10 +76,14 @@ lazy val compiler = (project in file("cyfra-compiler")) .settings(commonSettings) .dependsOn(dsl, utility) -lazy val runtime = (project in file("cyfra-runtime")) +lazy val core = (project in file("cyfra-core")) .settings(commonSettings) .dependsOn(compiler, dsl, vulkan, utility, spirvTools) +lazy val runtime = (project in file("cyfra-runtime")) + .settings(commonSettings) + .dependsOn(core) + lazy val foton = (project in file("cyfra-foton")) .settings(commonSettings) .dependsOn(compiler, dsl, runtime, utility) @@ -98,7 +102,7 @@ lazy val e2eTest = (project in file("cyfra-e2e-test")) lazy val root = (project in file(".")) .settings(name := "Cyfra") - .aggregate(compiler, dsl, foton, runtime, vulkan, examples) + .aggregate(compiler, dsl, foton, core, runtime, vulkan, examples) e2eTest / Test / javaOptions ++= Seq("-Dorg.lwjgl.system.stackSize=1024", "-DuniqueLibraryNames=true") diff --git a/cyfra-core/src/main/scala/io/computenode/cyfra/core/Allocation.scala b/cyfra-core/src/main/scala/io/computenode/cyfra/core/Allocation.scala new file mode 100644 index 00000000..194b3a2f --- /dev/null +++ b/cyfra-core/src/main/scala/io/computenode/cyfra/core/Allocation.scala @@ -0,0 +1,28 @@ +package io.computenode.cyfra.core + +import io.computenode.cyfra.core.layout.{Layout, LayoutStruct} +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 +import izumi.reflect.Tag + +import java.nio.ByteBuffer + +trait Allocation: + extension (buffer: GBinding[?]) + def read(bb: ByteBuffer, offset: Int = 0, length: Int = -1): Unit + + def write(bb: ByteBuffer, offset: Int = 0, length: Int = -1): Unit + + extension [Params, L <: Layout, RL <: Layout: LayoutStruct](execution: GExecution[Params, L, RL]) def execute(params: Params, layout: L): RL + + extension (buffers: GBuffer.type) + def apply[T <: Value: {Tag, FromExpr}](size: Int): GBuffer[T] + + def apply[T <: Value: {Tag, FromExpr}](buff: ByteBuffer): GBuffer[T] + + extension (buffers: GUniform.type) + def apply[T <: Value: {Tag, FromExpr}](buff: ByteBuffer): GUniform[T] + + def apply[T <: Value: {Tag, FromExpr}](): GUniform[T] diff --git a/cyfra-core/src/main/scala/io/computenode/cyfra/core/CyfraRuntime.scala b/cyfra-core/src/main/scala/io/computenode/cyfra/core/CyfraRuntime.scala new file mode 100644 index 00000000..a7c029e4 --- /dev/null +++ b/cyfra-core/src/main/scala/io/computenode/cyfra/core/CyfraRuntime.scala @@ -0,0 +1,7 @@ +package io.computenode.cyfra.core + +import io.computenode.cyfra.core.Allocation + +trait CyfraRuntime: + + def allocation(): Allocation diff --git a/cyfra-core/src/main/scala/io/computenode/cyfra/core/GBufferRegion.scala b/cyfra-core/src/main/scala/io/computenode/cyfra/core/GBufferRegion.scala new file mode 100644 index 00000000..2aec9159 --- /dev/null +++ b/cyfra-core/src/main/scala/io/computenode/cyfra/core/GBufferRegion.scala @@ -0,0 +1,47 @@ +package io.computenode.cyfra.core + +import io.computenode.cyfra.core.Allocation +import io.computenode.cyfra.core.GProgram.BufferSizeSpec +import io.computenode.cyfra.core.layout.{Layout, LayoutStruct} +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 java.nio.ByteBuffer + +sealed trait GBufferRegion[ReqAlloc <: Layout: LayoutStruct, ResAlloc <: Layout: LayoutStruct]: + val initAlloc: ReqAlloc + +object GBufferRegion: + + def allocate[Alloc <: Layout: LayoutStruct]: GBufferRegion[Alloc, Alloc] = + AllocRegion(summon[LayoutStruct[Alloc]].layoutRef) + + case class AllocRegion[Alloc <: Layout: LayoutStruct](l: Alloc) extends GBufferRegion[Alloc, Alloc]: + val initAlloc: Alloc = l + + case class MapRegion[ReqAlloc <: Layout: LayoutStruct, BodyAlloc <: Layout: LayoutStruct, ResAlloc <: Layout: LayoutStruct]( + reqRegion: GBufferRegion[ReqAlloc, BodyAlloc], + f: Allocation => BodyAlloc => ResAlloc, + ) extends GBufferRegion[ReqAlloc, ResAlloc]: + val initAlloc: ReqAlloc = reqRegion.initAlloc + + extension [ReqAlloc <: Layout: LayoutStruct, ResAlloc <: Layout: LayoutStruct](region: GBufferRegion[ReqAlloc, ResAlloc]) + def map[NewAlloc <: Layout: LayoutStruct](f: Allocation ?=> ResAlloc => NewAlloc): GBufferRegion[ReqAlloc, NewAlloc] = + MapRegion(region, (alloc: Allocation) => (resAlloc: ResAlloc) => f(using alloc)(resAlloc)) + + def runUnsafe(init: Allocation ?=> ReqAlloc, onDone: Allocation ?=> ResAlloc => Unit)(using cyfraRuntime: CyfraRuntime): Unit = + val allocation = cyfraRuntime.allocation() + init(using allocation) + + // noinspection ScalaRedundantCast + val steps: Seq[Allocation => Layout => Layout] = Seq.unfold(region: GBufferRegion[?, ?]): + case _: AllocRegion[?] => None + case MapRegion(req, f) => + Some((f.asInstanceOf[Allocation => Layout => Layout], req)) + + val bodyAlloc = steps.foldLeft[Layout](region.initAlloc): (acc, step) => + step(allocation)(acc) + + onDone(using allocation)(bodyAlloc.asInstanceOf[ResAlloc]) diff --git a/cyfra-core/src/main/scala/io/computenode/cyfra/core/GExecution.scala b/cyfra-core/src/main/scala/io/computenode/cyfra/core/GExecution.scala new file mode 100644 index 00000000..0caabec6 --- /dev/null +++ b/cyfra-core/src/main/scala/io/computenode/cyfra/core/GExecution.scala @@ -0,0 +1,62 @@ +package io.computenode.cyfra.core + +import io.computenode.cyfra.core.GExecution.* +import io.computenode.cyfra.core.archive.GContext +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.spirv.compilers.ExpressionCompiler.UniformStructRef +import izumi.reflect.Tag +import GExecution.* + +trait GExecution[-Params, ExecLayout <: Layout, +ResLayout <: Layout]: + + def flatMap[NRL <: Layout, NP <: Params](f: ResLayout => GExecution[NP, ExecLayout, NRL]): GExecution[NP, ExecLayout, NRL] = + FlatMap(this, (p, r) => f(r)) + + def map[NRL <: Layout](f: ResLayout => NRL): GExecution[Params, ExecLayout, NRL] = + Map(this, f, identity, identity) + + def contramap[NL <: Layout](f: NL => ExecLayout): GExecution[Params, NL, ResLayout] = + Map(this, identity, f, identity) + + def contramapParams[NP](f: NP => Params): GExecution[NP, ExecLayout, ResLayout] = + Map(this, identity, identity, f) + + def addProgram[ProgramParams, PP <: Params, ProgramLayout <: Layout, P <: GProgram[ProgramParams, ProgramLayout]]( + program: P, + )(mapParams: PP => ProgramParams, mapLayout: ExecLayout => ProgramLayout): GExecution[PP, ExecLayout, ResLayout] = + val adapted = program.contramapParams(mapParams).contramap(mapLayout) + flatMap(r => adapted.map(_ => r)) + +object GExecution: + + def apply[Params, L <: Layout]() = + Pure[Params, L, L]() + + def forParams[Params, L <: Layout, RL <: Layout](f: Params => GExecution[Params, L, RL]): GExecution[Params, L, RL] = + FlatMap[Params, L, RL, RL](Pure[Params, L, RL](), (params: Params, _: RL) => f(params)) + + case class Pure[Params, L <: Layout, RL <: Layout]() extends GExecution[Params, L, RL] + + case class FlatMap[Params, L <: Layout, RL <: Layout, NRL <: Layout]( + execution: GExecution[Params, L, RL], + f: (Params, RL) => GExecution[Params, L, NRL], + ) extends GExecution[Params, L, NRL] + + case class Map[P, NP, L <: Layout, NL <: Layout, RL <: Layout, NRL <: Layout]( + execution: GExecution[P, L, RL], + mapResult: RL => NRL, + contramapLayout: NL => L, + contramapParams: NP => P, + ) extends GExecution[NP, NL, NRL]: + + override def map[NNRL <: Layout](f: NRL => NNRL): GExecution[NP, NL, NNRL] = + Map(execution, mapResult andThen f, contramapLayout, contramapParams) + + override def contramapParams[NNP](f: NNP => NP): GExecution[NNP, NL, NRL] = + Map(execution, mapResult, contramapLayout, f andThen contramapParams) + + override def contramap[NNL <: Layout](f: NNL => NL): GExecution[NP, NNL, NRL] = + Map(execution, mapResult, f andThen contramapLayout, contramapParams) diff --git a/cyfra-core/src/main/scala/io/computenode/cyfra/core/GProgram.scala b/cyfra-core/src/main/scala/io/computenode/cyfra/core/GProgram.scala new file mode 100644 index 00000000..77586f5e --- /dev/null +++ b/cyfra-core/src/main/scala/io/computenode/cyfra/core/GProgram.scala @@ -0,0 +1,70 @@ +package io.computenode.cyfra.core + +import io.computenode.cyfra.core.layout.LayoutStruct +import io.computenode.cyfra.dsl.gio.GIO +import io.computenode.cyfra.core.layout.Layout + +import java.nio.ByteBuffer +import GProgram.* +import io.computenode.cyfra.dsl.{Expression, Value} +import io.computenode.cyfra.dsl.Value.{FromExpr, Int32} +import io.computenode.cyfra.dsl.binding.{GBinding, GBuffer, GUniform} +import io.computenode.cyfra.dsl.struct.GStruct +import io.computenode.cyfra.dsl.struct.GStruct.Empty +import izumi.reflect.Tag + +sealed trait GProgram[Params, L <: Layout: LayoutStruct] extends GExecution[Params, L, L]: + val layout: InitProgramLayout => Params => L + val dispatch: (L, Params) => ProgramDispatch + val workgroupSize: WorkDimensions + +object GProgram: + + class GioProgram[Params, L <: Layout: LayoutStruct]( + val body: L => GIO[?], + val layout: InitProgramLayout => Params => L, + val dispatch: (L, Params) => ProgramDispatch, + val workgroupSize: WorkDimensions, + ) extends GProgram[Params, L]: + private[cyfra] def layoutStruct: LayoutStruct[L] = summon[LayoutStruct[L]] + + class SpirvProgram[Params, L <: Layout: LayoutStruct]( + val code: ByteBuffer, + val layout: InitProgramLayout => Params => L, + val dispatch: (L, Params) => ProgramDispatch, + val workgroupSize: WorkDimensions, + ) extends GProgram[Params, L]: + private[cyfra] def layoutStruct: LayoutStruct[L] = summon[LayoutStruct[L]] + + type WorkDimensions = (Int, Int, Int) + + sealed trait ProgramDispatch + + case class DynamicDispatch[L <: Layout](buffer: GBinding[?], offset: Int) extends ProgramDispatch + + case class StaticDispatch(size: WorkDimensions) extends ProgramDispatch + + private[cyfra] case class BufferSizeSpec[T <: Value: {Tag, FromExpr}](size: Int) extends GBuffer[T] + + private[cyfra] case class ParamUniform[T <: GStruct[T]: {Tag, FromExpr}](value: T) extends GUniform[T] + + private[cyfra] case class DynamicUniform[T <: GStruct[T]: {Tag, FromExpr}]() extends GUniform[T] + + trait InitProgramLayout: + extension (buffers: GBuffer.type) + def apply[T <: Value: {Tag, FromExpr}](size: Int): GBuffer[T] = + BufferSizeSpec[T](size) + + extension (uniforms: GUniform.type) + def apply[T <: GStruct[T]: {Tag, FromExpr}](value: T): GUniform[T] = + ParamUniform[T](value) + + def apply[T <: GStruct[T]: {Tag, FromExpr}](): GUniform[T] = + DynamicUniform[T]() + + def apply[Params, L <: Layout: LayoutStruct]( + 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) diff --git a/cyfra-runtime/src/main/scala/io/computenode/cyfra/runtime/Executable.scala b/cyfra-core/src/main/scala/io/computenode/cyfra/core/archive/Executable.scala similarity index 63% rename from cyfra-runtime/src/main/scala/io/computenode/cyfra/runtime/Executable.scala rename to cyfra-core/src/main/scala/io/computenode/cyfra/core/archive/Executable.scala index b72be392..68e0b273 100644 --- a/cyfra-runtime/src/main/scala/io/computenode/cyfra/runtime/Executable.scala +++ b/cyfra-core/src/main/scala/io/computenode/cyfra/core/archive/Executable.scala @@ -1,7 +1,7 @@ -package io.computenode.cyfra.runtime +package io.computenode.cyfra.core.archive +import io.computenode.cyfra.core.archive.mem.{GMem, RamGMem} import io.computenode.cyfra.dsl.Value -import io.computenode.cyfra.runtime.mem.{GMem, RamGMem} import scala.concurrent.Future diff --git a/cyfra-runtime/src/main/scala/io/computenode/cyfra/runtime/GContext.scala b/cyfra-core/src/main/scala/io/computenode/cyfra/core/archive/GContext.scala similarity index 86% rename from cyfra-runtime/src/main/scala/io/computenode/cyfra/runtime/GContext.scala rename to cyfra-core/src/main/scala/io/computenode/cyfra/core/archive/GContext.scala index 3ebd43d9..c9f32763 100644 --- a/cyfra-runtime/src/main/scala/io/computenode/cyfra/runtime/GContext.scala +++ b/cyfra-core/src/main/scala/io/computenode/cyfra/core/archive/GContext.scala @@ -1,11 +1,12 @@ -package io.computenode.cyfra.runtime +package io.computenode.cyfra.core.archive +import io.computenode.cyfra.core.archive.mem.GMem.totalStride +import io.computenode.cyfra.core.archive.mem.{FloatMem, GMem, IntMem, Vec4FloatMem} +import io.computenode.cyfra.core.archive.{GFunction, UniformContext} import io.computenode.cyfra.dsl.Value import io.computenode.cyfra.dsl.Value.{Float32, FromExpr, Int32, Vec4} import io.computenode.cyfra.dsl.collections.GArray import io.computenode.cyfra.dsl.struct.* -import io.computenode.cyfra.runtime.mem.GMem.totalStride -import io.computenode.cyfra.runtime.mem.{FloatMem, GMem, IntMem, Vec4FloatMem} import io.computenode.cyfra.spirv.SpirvTypes.typeStride import io.computenode.cyfra.spirv.compilers.DSLCompiler import io.computenode.cyfra.spirv.compilers.ExpressionCompiler.{UniformStructRef, WorkerIndex} @@ -27,7 +28,7 @@ class GContext(spirvToolsRunner: SpirvToolsRunner = SpirvToolsRunner()): implicit val ec: ExecutionContextExecutor = ExecutionContext.fromExecutor(Executors.newFixedThreadPool(16)) - def compile[G <: GStruct[G]: Tag: GStructSchema, H <: Value: Tag: FromExpr, R <: Value: Tag: FromExpr]( + def compile[G <: GStruct[G]: {Tag, GStructSchema}, H <: Value: {Tag, FromExpr}, R <: Value: {Tag, FromExpr}]( function: GFunction[G, H, R], ): ComputePipeline = val uniformStructSchema = summon[GStructSchema[G]] @@ -45,7 +46,7 @@ class GContext(spirvToolsRunner: SpirvToolsRunner = SpirvToolsRunner()): val shader = Shader(optimizedShaderCode, org.joml.Vector3i(256, 1, 1), layoutInfo, "main", vkContext.device) ComputePipeline(shader, vkContext) - def execute[G <: GStruct[G]: Tag: GStructSchema, H <: Value, R <: Value](mem: GMem[H], fn: GFunction[G, H, R])(using + def execute[G <: GStruct[G]: {Tag, GStructSchema}, H <: Value, R <: Value](mem: GMem[H], fn: GFunction[G, H, R])(using uniformContext: UniformContext[G], ): GMem[R] = val isUniformEmpty = uniformContext.uniform.schema.fields.isEmpty diff --git a/cyfra-runtime/src/main/scala/io/computenode/cyfra/runtime/GFunction.scala b/cyfra-core/src/main/scala/io/computenode/cyfra/core/archive/GFunction.scala similarity index 64% rename from cyfra-runtime/src/main/scala/io/computenode/cyfra/runtime/GFunction.scala rename to cyfra-core/src/main/scala/io/computenode/cyfra/core/archive/GFunction.scala index 1c85b3fd..c633f909 100644 --- a/cyfra-runtime/src/main/scala/io/computenode/cyfra/runtime/GFunction.scala +++ b/cyfra-core/src/main/scala/io/computenode/cyfra/core/archive/GFunction.scala @@ -1,13 +1,14 @@ -package io.computenode.cyfra.runtime +package io.computenode.cyfra.core.archive -import io.computenode.cyfra.dsl.{*, given} +import io.computenode.cyfra.core.archive.GFunction import io.computenode.cyfra.dsl.Value.* -import io.computenode.cyfra.dsl.struct.* import io.computenode.cyfra.dsl.collections.{GArray, GArray2D} +import io.computenode.cyfra.dsl.struct.* +import io.computenode.cyfra.dsl.{*, given} import io.computenode.cyfra.vulkan.compute.ComputePipeline import izumi.reflect.Tag -case class GFunction[G <: GStruct[G]: GStructSchema: Tag, H <: Value: Tag: FromExpr, R <: Value: Tag: FromExpr](fn: (G, Int32, GArray[H]) => R)( +case class GFunction[G <: GStruct[G]: {GStructSchema, Tag}, H <: Value: {Tag, FromExpr}, R <: Value: {Tag, FromExpr}](fn: (G, Int32, GArray[H]) => R)( implicit context: GContext, ): def arrayInputs: List[Tag[?]] = List(summon[Tag[H]]) @@ -15,10 +16,10 @@ case class GFunction[G <: GStruct[G]: GStructSchema: Tag, H <: Value: Tag: FromE val pipeline: ComputePipeline = context.compile(this) object GFunction: - def apply[H <: Value: Tag: FromExpr, R <: Value: Tag: FromExpr](fn: H => R)(using context: GContext): GFunction[GStruct.Empty, H, R] = + def apply[H <: Value: {Tag, FromExpr}, R <: Value: {Tag, FromExpr}](fn: H => R)(using context: GContext): GFunction[GStruct.Empty, H, R] = new GFunction[GStruct.Empty, H, R]((_, index: Int32, gArray: GArray[H]) => fn(gArray.at(index))) - def from2D[G <: GStruct[G]: GStructSchema: Tag, H <: Value: Tag: FromExpr, R <: Value: Tag: FromExpr]( + def from2D[G <: GStruct[G]: {GStructSchema, Tag}, H <: Value: {Tag, FromExpr}, R <: Value: {Tag, FromExpr}]( width: Int, )(fn: (G, (Int32, Int32), GArray2D[H]) => R)(using context: GContext): GFunction[G, H, R] = GFunction[G, H, R]((g: G, index: Int32, a: GArray[H]) => diff --git a/cyfra-core/src/main/scala/io/computenode/cyfra/core/archive/UniformContext.scala b/cyfra-core/src/main/scala/io/computenode/cyfra/core/archive/UniformContext.scala new file mode 100644 index 00000000..093698ae --- /dev/null +++ b/cyfra-core/src/main/scala/io/computenode/cyfra/core/archive/UniformContext.scala @@ -0,0 +1,13 @@ +package io.computenode.cyfra.core.archive + +import io.computenode.cyfra.core.archive.UniformContext +import io.computenode.cyfra.dsl.struct.* +import io.computenode.cyfra.dsl.struct.GStruct.Empty +import izumi.reflect.Tag + +class UniformContext[G <: GStruct[G]: {Tag, GStructSchema}](val uniform: G) + +object UniformContext: + def withUniform[G <: GStruct[G]: {Tag, GStructSchema}, T](uniform: G)(fn: UniformContext[G] ?=> T): T = + fn(using UniformContext(uniform)) + given empty: UniformContext[Empty] = new UniformContext(Empty()) diff --git a/cyfra-runtime/src/main/scala/io/computenode/cyfra/runtime/mem/FloatMem.scala b/cyfra-core/src/main/scala/io/computenode/cyfra/core/archive/mem/FloatMem.scala similarity index 94% rename from cyfra-runtime/src/main/scala/io/computenode/cyfra/runtime/mem/FloatMem.scala rename to cyfra-core/src/main/scala/io/computenode/cyfra/core/archive/mem/FloatMem.scala index 4264233d..2e51f2ee 100644 --- a/cyfra-runtime/src/main/scala/io/computenode/cyfra/runtime/mem/FloatMem.scala +++ b/cyfra-core/src/main/scala/io/computenode/cyfra/core/archive/mem/FloatMem.scala @@ -1,4 +1,4 @@ -package io.computenode.cyfra.runtime.mem +package io.computenode.cyfra.core.archive.mem import io.computenode.cyfra.dsl.Value.Float32 import org.lwjgl.BufferUtils diff --git a/cyfra-runtime/src/main/scala/io/computenode/cyfra/runtime/mem/GMem.scala b/cyfra-core/src/main/scala/io/computenode/cyfra/core/archive/mem/GMem.scala similarity index 89% rename from cyfra-runtime/src/main/scala/io/computenode/cyfra/runtime/mem/GMem.scala rename to cyfra-core/src/main/scala/io/computenode/cyfra/core/archive/mem/GMem.scala index a6efd211..41961aa4 100644 --- a/cyfra-runtime/src/main/scala/io/computenode/cyfra/runtime/mem/GMem.scala +++ b/cyfra-core/src/main/scala/io/computenode/cyfra/core/archive/mem/GMem.scala @@ -1,9 +1,9 @@ -package io.computenode.cyfra.runtime.mem +package io.computenode.cyfra.core.archive.mem +import io.computenode.cyfra.core.archive.{GContext, GFunction, UniformContext} import io.computenode.cyfra.dsl.Value.FromExpr import io.computenode.cyfra.dsl.struct.* import io.computenode.cyfra.dsl.{*, given} -import io.computenode.cyfra.runtime.{GContext, GFunction, UniformContext} import io.computenode.cyfra.spirv.SpirvTypes.typeStride import izumi.reflect.Tag import org.lwjgl.BufferUtils @@ -13,7 +13,7 @@ import java.nio.ByteBuffer trait GMem[H <: Value]: def size: Int def toReadOnlyBuffer: ByteBuffer - def map[G <: GStruct[G]: Tag: GStructSchema, R <: Value: FromExpr: Tag]( + def map[G <: GStruct[G]: {Tag, GStructSchema}, R <: Value: {FromExpr, Tag}]( fn: GFunction[G, H, R], )(using context: GContext, uc: UniformContext[G]): GMem[R] = context.execute(this, fn) diff --git a/cyfra-runtime/src/main/scala/io/computenode/cyfra/runtime/mem/IntMem.scala b/cyfra-core/src/main/scala/io/computenode/cyfra/core/archive/mem/IntMem.scala similarity index 93% rename from cyfra-runtime/src/main/scala/io/computenode/cyfra/runtime/mem/IntMem.scala rename to cyfra-core/src/main/scala/io/computenode/cyfra/core/archive/mem/IntMem.scala index 72d12a82..ee9e61e8 100644 --- a/cyfra-runtime/src/main/scala/io/computenode/cyfra/runtime/mem/IntMem.scala +++ b/cyfra-core/src/main/scala/io/computenode/cyfra/core/archive/mem/IntMem.scala @@ -1,4 +1,4 @@ -package io.computenode.cyfra.runtime.mem +package io.computenode.cyfra.core.archive.mem import io.computenode.cyfra.dsl.Value.Int32 import org.lwjgl.BufferUtils diff --git a/cyfra-runtime/src/main/scala/io/computenode/cyfra/runtime/mem/RamGMem.scala b/cyfra-core/src/main/scala/io/computenode/cyfra/core/archive/mem/RamGMem.scala similarity index 81% rename from cyfra-runtime/src/main/scala/io/computenode/cyfra/runtime/mem/RamGMem.scala rename to cyfra-core/src/main/scala/io/computenode/cyfra/core/archive/mem/RamGMem.scala index 43e45f30..a136d7d4 100644 --- a/cyfra-runtime/src/main/scala/io/computenode/cyfra/runtime/mem/RamGMem.scala +++ b/cyfra-core/src/main/scala/io/computenode/cyfra/core/archive/mem/RamGMem.scala @@ -1,4 +1,4 @@ -package io.computenode.cyfra.runtime.mem +package io.computenode.cyfra.core.archive.mem import io.computenode.cyfra.dsl.Value diff --git a/cyfra-runtime/src/main/scala/io/computenode/cyfra/runtime/mem/Vec4FloatMem.scala b/cyfra-core/src/main/scala/io/computenode/cyfra/core/archive/mem/Vec4FloatMem.scala similarity index 90% rename from cyfra-runtime/src/main/scala/io/computenode/cyfra/runtime/mem/Vec4FloatMem.scala rename to cyfra-core/src/main/scala/io/computenode/cyfra/core/archive/mem/Vec4FloatMem.scala index ff48aa6b..0fdb63cb 100644 --- a/cyfra-runtime/src/main/scala/io/computenode/cyfra/runtime/mem/Vec4FloatMem.scala +++ b/cyfra-core/src/main/scala/io/computenode/cyfra/core/archive/mem/Vec4FloatMem.scala @@ -1,7 +1,7 @@ -package io.computenode.cyfra.runtime.mem +package io.computenode.cyfra.core.archive.mem +import io.computenode.cyfra.core.archive.mem.GMem.fRGBA import io.computenode.cyfra.dsl.Value.{Float32, Vec4} -import io.computenode.cyfra.runtime.mem.GMem.fRGBA import org.lwjgl.BufferUtils import java.nio.ByteBuffer diff --git a/cyfra-core/src/main/scala/io/computenode/cyfra/core/binding/BufferRef.scala b/cyfra-core/src/main/scala/io/computenode/cyfra/core/binding/BufferRef.scala new file mode 100644 index 00000000..1ad1c3af --- /dev/null +++ b/cyfra-core/src/main/scala/io/computenode/cyfra/core/binding/BufferRef.scala @@ -0,0 +1,9 @@ +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 + +case class BufferRef[T <: Value: {Tag, FromExpr}](layoutOffset: Int, valueTag: Tag[T]) extends GBuffer[T] diff --git a/cyfra-core/src/main/scala/io/computenode/cyfra/core/binding/UniformRef.scala b/cyfra-core/src/main/scala/io/computenode/cyfra/core/binding/UniformRef.scala new file mode 100644 index 00000000..d7c3b308 --- /dev/null +++ b/cyfra-core/src/main/scala/io/computenode/cyfra/core/binding/UniformRef.scala @@ -0,0 +1,10 @@ +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 +import izumi.reflect.Tag +import izumi.reflect.macrortti.LightTypeTag + +case class UniformRef[T <: Value: {Tag, FromExpr}](layoutOffset: Int, valueTag: Tag[T]) extends GUniform[T] diff --git a/cyfra-core/src/main/scala/io/computenode/cyfra/core/layout/Layout.scala b/cyfra-core/src/main/scala/io/computenode/cyfra/core/layout/Layout.scala new file mode 100644 index 00000000..d03d858f --- /dev/null +++ b/cyfra-core/src/main/scala/io/computenode/cyfra/core/layout/Layout.scala @@ -0,0 +1,6 @@ +package io.computenode.cyfra.core.layout + +import io.computenode.cyfra.dsl.Value +import io.computenode.cyfra.dsl.binding.GBuffer + +trait Layout diff --git a/cyfra-core/src/main/scala/io/computenode/cyfra/core/layout/LayoutStruct.scala b/cyfra-core/src/main/scala/io/computenode/cyfra/core/layout/LayoutStruct.scala new file mode 100644 index 00000000..3d79b409 --- /dev/null +++ b/cyfra-core/src/main/scala/io/computenode/cyfra/core/layout/LayoutStruct.scala @@ -0,0 +1,80 @@ +package io.computenode.cyfra.core.layout + +import io.computenode.cyfra.core.binding.{BufferRef, UniformRef} +import io.computenode.cyfra.dsl.Value +import io.computenode.cyfra.dsl.Value.FromExpr +import io.computenode.cyfra.dsl.binding.{GBinding, GBuffer, GUniform} +import izumi.reflect.Tag +import izumi.reflect.macrortti.LightTypeTag + +import scala.compiletime.{error, summonAll} +import scala.deriving.Mirror +import scala.quoted.{Expr, Quotes, Type} + +case class LayoutStruct[T <: Layout: Tag](private[cyfra] val layoutRef: T, private[cyfra] val elementTypes: List[Tag[? <: Value]]) + +object LayoutStruct: + + inline given derived[T <: Layout: Tag]: LayoutStruct[T] = ${ derivedImpl } + + def derivedImpl[T <: Layout: Type](using quotes: Quotes): Expr[LayoutStruct[T]] = + import quotes.reflect.* + + val tpe = TypeRepr.of[T] + val sym = tpe.typeSymbol + + if !sym.isClassDef || !sym.flags.is(Flags.Case) then report.errorAndAbort("LayoutStruct can only be derived for case classes") + + val fieldTypes = sym.caseFields + .map(_.tree) + .map: + case ValDef(_, tpt, _) => tpt.tpe + case _ => report.errorAndAbort("Unexpected field type in case class") + + if !fieldTypes.forall(_ <:< TypeRepr.of[GBinding[?]]) then + report.errorAndAbort("LayoutStruct can only be derived for case classes with GBinding elements") + + val valueTypes = fieldTypes.map: ftype => + (ftype, ftype.typeArgs.headOption.getOrElse(report.errorAndAbort("GBuffer must have a value type"))) + + // summon izumi tags + val typeGivens = valueTypes.map: + case (ftype, farg) => + farg.asType match + case '[type t <: Value; t] => + ( + ftype.asType, + farg.asType, + Expr.summon[Tag[t]] match + case Some(tagExpr) => tagExpr + case None => report.errorAndAbort(s"Cannot summon Tag for type ${tpe.show}"), + Expr.summon[FromExpr[t]] match + case Some(fromExpr) => fromExpr + case None => report.errorAndAbort(s"Cannot summon FromExpr for type ${tpe.show}"), + ) + + val buffers = typeGivens.zipWithIndex.map: + case ((ftype, tpe, tag, fromExpr), i) => + tpe match + case '[type t <: Value; t] => + ftype match + case '[type tg <: GBuffer[?]; tg] => + '{ + BufferRef[t](${ Expr(i) }, ${ tag.asExprOf[Tag[t]] })(using summon[Tag[t]], ${ fromExpr.asExprOf[FromExpr[t]] }) + } + case '[type tg <: GUniform[?]; tg] => + '{ + UniformRef[t](${ Expr(i) }, ${ tag.asExprOf[Tag[t]] })(using summon[Tag[t]], ${ fromExpr.asExprOf[FromExpr[t]] }) + } + + val constructor = sym.primaryConstructor + + val layoutInstance = Apply(Select(New(TypeIdent(sym)), constructor), buffers.map(_.asTerm)) + + val layoutRef = layoutInstance.asExprOf[T] + + val soleTags = typeGivens.map(_._3.asExprOf[Tag[? <: Value]]).toList + + '{ + LayoutStruct[T]($layoutRef, ${ Expr.ofList(soleTags) }) + } diff --git a/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/Expression.scala b/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/Expression.scala index 52b8b844..18f81033 100644 --- a/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/Expression.scala +++ b/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/Expression.scala @@ -1,5 +1,5 @@ package io.computenode.cyfra.dsl -import io.computenode.cyfra.dsl.Expression + import Expression.{Const, treeidState} import io.computenode.cyfra.dsl.library.Functions.* import io.computenode.cyfra.dsl.Value.* @@ -107,6 +107,7 @@ object Expression: case class ExtFunctionCall[R <: Value: Tag](fn: FunctionName, args: List[Value]) extends Expression[R] case class FunctionCall[R <: Value: Tag](fn: FnIdentifier, body: Scope[R], args: List[Value]) extends E[R] + case object InvocationId extends E[Int32] case class Pass[T <: Value: Tag](value: T) extends E[T] diff --git a/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/Value.scala b/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/Value.scala index 03754998..985357e7 100644 --- a/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/Value.scala +++ b/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/Value.scala @@ -18,6 +18,10 @@ object Value: trait FromExpr[T <: Value]: def fromExpr(expr: E[T])(using name: Source): T + object FromExpr: + def fromExpr[T <: Value](expr: E[T])(using f: FromExpr[T]): T = + f.fromExpr(expr) + sealed trait Scalar extends Value trait FloatType extends Scalar diff --git a/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/algebra/ScalarAlgebra.scala b/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/algebra/ScalarAlgebra.scala index 4684c61d..92cbe6ae 100644 --- a/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/algebra/ScalarAlgebra.scala +++ b/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/algebra/ScalarAlgebra.scala @@ -11,7 +11,7 @@ import scala.annotation.targetName object ScalarAlgebra: - trait BasicScalarAlgebra[T <: Scalar: FromExpr: Tag] + trait BasicScalarAlgebra[T <: Scalar: {FromExpr, Tag}] extends ScalarSummable[T] with ScalarDiffable[T] with ScalarMulable[T] @@ -20,54 +20,54 @@ object ScalarAlgebra: with Comparable[T] with ScalarNegatable[T] - trait BasicScalarIntAlgebra[T <: Scalar: FromExpr: Tag] extends BasicScalarAlgebra[T] with BitwiseOperable[T] + trait BasicScalarIntAlgebra[T <: Scalar: {FromExpr, Tag}] extends BasicScalarAlgebra[T] with BitwiseOperable[T] given BasicScalarAlgebra[Float32] = new BasicScalarAlgebra[Float32] {} given BasicScalarIntAlgebra[Int32] = new BasicScalarIntAlgebra[Int32] {} given BasicScalarIntAlgebra[UInt32] = new BasicScalarIntAlgebra[UInt32] {} - trait ScalarSummable[T <: Scalar: FromExpr: Tag]: + trait ScalarSummable[T <: Scalar: {FromExpr, Tag}]: def sum(a: T, b: T)(using name: Source): T = summon[FromExpr[T]].fromExpr(Sum(a, b)) - extension [T <: Scalar: ScalarSummable: Tag](a: T) + extension [T <: Scalar: {ScalarSummable, Tag}](a: T) @targetName("add") inline def +(b: T)(using Source): T = summon[ScalarSummable[T]].sum(a, b) - trait ScalarDiffable[T <: Scalar: FromExpr: Tag]: + trait ScalarDiffable[T <: Scalar: {FromExpr, Tag}]: def diff(a: T, b: T)(using Source): T = summon[FromExpr[T]].fromExpr(Diff(a, b)) - extension [T <: Scalar: ScalarDiffable: Tag](a: T) + extension [T <: Scalar: {ScalarDiffable, Tag}](a: T) @targetName("sub") inline def -(b: T)(using Source): T = summon[ScalarDiffable[T]].diff(a, b) // T and S ??? so two - trait ScalarMulable[T <: Scalar: FromExpr: Tag]: + trait ScalarMulable[T <: Scalar: {FromExpr, Tag}]: def mul(a: T, b: T)(using Source): T = summon[FromExpr[T]].fromExpr(Mul(a, b)) - extension [T <: Scalar: ScalarMulable: Tag](a: T) + extension [T <: Scalar: {ScalarMulable, Tag}](a: T) @targetName("mul") inline def *(b: T)(using Source): T = summon[ScalarMulable[T]].mul(a, b) - trait ScalarDivable[T <: Scalar: FromExpr: Tag]: + trait ScalarDivable[T <: Scalar: {FromExpr, Tag}]: def div(a: T, b: T)(using Source): T = summon[FromExpr[T]].fromExpr(Div(a, b)) - extension [T <: Scalar: ScalarDivable: Tag](a: T) + extension [T <: Scalar: {ScalarDivable, Tag}](a: T) @targetName("div") inline def /(b: T)(using Source): T = summon[ScalarDivable[T]].div(a, b) - trait ScalarNegatable[T <: Scalar: FromExpr: Tag]: + trait ScalarNegatable[T <: Scalar: {FromExpr, Tag}]: def negate(a: T)(using Source): T = summon[FromExpr[T]].fromExpr(Negate(a)) - extension [T <: Scalar: ScalarNegatable: Tag](a: T) + extension [T <: Scalar: {ScalarNegatable, Tag}](a: T) @targetName("negate") inline def unary_-(using Source): T = summon[ScalarNegatable[T]].negate(a) - trait ScalarModable[T <: Scalar: FromExpr: Tag]: + trait ScalarModable[T <: Scalar: {FromExpr, Tag}]: def mod(a: T, b: T)(using Source): T = summon[FromExpr[T]].fromExpr(Mod(a, b)) - extension [T <: Scalar: ScalarModable: Tag](a: T) inline infix def mod(b: T)(using Source): T = summon[ScalarModable[T]].mod(a, b) + extension [T <: Scalar: {ScalarModable, Tag}](a: T) inline infix def mod(b: T)(using Source): T = summon[ScalarModable[T]].mod(a, b) - trait Comparable[T <: Scalar: FromExpr: Tag]: + trait Comparable[T <: Scalar: {FromExpr, Tag}]: def greaterThan(a: T, b: T)(using Source): GBoolean = GBoolean(GreaterThan(a, b)) def lessThan(a: T, b: T)(using Source): GBoolean = GBoolean(LessThan(a, b)) @@ -78,7 +78,7 @@ object ScalarAlgebra: def equal(a: T, b: T)(using Source): GBoolean = GBoolean(Equal(a, b)) - extension [T <: Scalar: Comparable: Tag](a: T) + extension [T <: Scalar: {Comparable, Tag}](a: T) inline def >(b: T)(using Source): GBoolean = summon[Comparable[T]].greaterThan(a, b) inline def <(b: T)(using Source): GBoolean = summon[Comparable[T]].lessThan(a, b) inline def >=(b: T)(using Source): GBoolean = summon[Comparable[T]].greaterThanEqual(a, b) @@ -102,7 +102,7 @@ object ScalarAlgebra: inline def asFloat(using Source): Float32 = Float32(ToFloat32(u32)) inline def signed(using Source): Int32 = Int32(ToInt32(u32)) - trait BitwiseOperable[T <: Scalar: FromExpr: Tag]: + trait BitwiseOperable[T <: Scalar: {FromExpr, Tag}]: def bitwiseAnd(a: T, b: T)(using Source): T = summon[FromExpr[T]].fromExpr(BitwiseAnd(a, b)) def bitwiseOr(a: T, b: T)(using Source): T = summon[FromExpr[T]].fromExpr(BitwiseOr(a, b)) @@ -115,7 +115,7 @@ object ScalarAlgebra: def shiftRight(a: T, by: UInt32)(using Source): T = summon[FromExpr[T]].fromExpr(ShiftRight(a, by)) - extension [T <: Scalar: BitwiseOperable: Tag](a: T) + extension [T <: Scalar: {BitwiseOperable, Tag}](a: T) inline def &(b: T)(using Source): T = summon[BitwiseOperable[T]].bitwiseAnd(a, b) inline def |(b: T)(using Source): T = summon[BitwiseOperable[T]].bitwiseOr(a, b) inline def ^(b: T)(using Source): T = summon[BitwiseOperable[T]].bitwiseXor(a, b) diff --git a/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/algebra/VectorAlgebra.scala b/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/algebra/VectorAlgebra.scala index f307f9b5..1f82a539 100644 --- a/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/algebra/VectorAlgebra.scala +++ b/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/algebra/VectorAlgebra.scala @@ -11,7 +11,7 @@ import scala.annotation.targetName object VectorAlgebra: - trait BasicVectorAlgebra[S <: Scalar, V <: Vec[S]: FromExpr: Tag] + trait BasicVectorAlgebra[S <: Scalar, V <: Vec[S]: {FromExpr, Tag}] extends VectorSummable[V] with VectorDiffable[V] with VectorDotable[S, V] @@ -19,36 +19,36 @@ object VectorAlgebra: with VectorScalarMulable[S, V] with VectorNegatable[V] - given [T <: Scalar: FromExpr: Tag]: BasicVectorAlgebra[T, Vec2[T]] = new BasicVectorAlgebra[T, Vec2[T]] {} - given [T <: Scalar: FromExpr: Tag]: BasicVectorAlgebra[T, Vec3[T]] = new BasicVectorAlgebra[T, Vec3[T]] {} - given [T <: Scalar: FromExpr: Tag]: BasicVectorAlgebra[T, Vec4[T]] = new BasicVectorAlgebra[T, Vec4[T]] {} + given [T <: Scalar: {FromExpr, Tag}]: BasicVectorAlgebra[T, Vec2[T]] = new BasicVectorAlgebra[T, Vec2[T]] {} + given [T <: Scalar: {FromExpr, Tag}]: BasicVectorAlgebra[T, Vec3[T]] = new BasicVectorAlgebra[T, Vec3[T]] {} + given [T <: Scalar: {FromExpr, Tag}]: BasicVectorAlgebra[T, Vec4[T]] = new BasicVectorAlgebra[T, Vec4[T]] {} - trait VectorSummable[V <: Vec[?]: FromExpr: Tag]: + trait VectorSummable[V <: Vec[?]: {FromExpr, Tag}]: def sum(a: V, b: V)(using Source): V = summon[FromExpr[V]].fromExpr(Sum(a, b)) - extension [V <: Vec[?]: VectorSummable: Tag](a: V) + extension [V <: Vec[?]: {VectorSummable, Tag}](a: V) @targetName("addVector") inline def +(b: V)(using Source): V = summon[VectorSummable[V]].sum(a, b) - trait VectorDiffable[V <: Vec[?]: FromExpr: Tag]: + trait VectorDiffable[V <: Vec[?]: {FromExpr, Tag}]: def diff(a: V, b: V)(using Source): V = summon[FromExpr[V]].fromExpr(Diff(a, b)) - extension [V <: Vec[?]: VectorDiffable: Tag](a: V) + extension [V <: Vec[?]: {VectorDiffable, Tag}](a: V) @targetName("subVector") inline def -(b: V)(using Source): V = summon[VectorDiffable[V]].diff(a, b) - trait VectorDotable[S <: Scalar: FromExpr: Tag, V <: Vec[S]: Tag]: + trait VectorDotable[S <: Scalar: {FromExpr, Tag}, V <: Vec[S]: Tag]: def dot(a: V, b: V)(using Source): S = summon[FromExpr[S]].fromExpr(DotProd[S, V](a, b)) extension [S <: Scalar: Tag, V <: Vec[S]: Tag](a: V)(using VectorDotable[S, V]) infix def dot(b: V)(using Source): S = summon[VectorDotable[S, V]].dot(a, b) - trait VectorCrossable[V <: Vec[?]: FromExpr: Tag]: + trait VectorCrossable[V <: Vec[?]: {FromExpr, Tag}]: def cross(a: V, b: V)(using Source): V = summon[FromExpr[V]].fromExpr(ExtFunctionCall(Cross, List(a, b))) - extension [V <: Vec[?]: VectorCrossable: Tag](a: V) infix def cross(b: V)(using Source): V = summon[VectorCrossable[V]].cross(a, b) + extension [V <: Vec[?]: {VectorCrossable, Tag}](a: V) infix def cross(b: V)(using Source): V = summon[VectorCrossable[V]].cross(a, b) - trait VectorScalarMulable[S <: Scalar: Tag, V <: Vec[S]: FromExpr: Tag]: + trait VectorScalarMulable[S <: Scalar: Tag, V <: Vec[S]: {FromExpr, Tag}]: def mul(a: V, b: S)(using Source): V = summon[FromExpr[V]].fromExpr(ScalarProd[S, V](a, b)) extension [S <: Scalar: Tag, V <: Vec[S]: Tag](a: V)(using VectorScalarMulable[S, V]) @@ -56,10 +56,10 @@ object VectorAlgebra: extension [S <: Scalar: Tag, V <: Vec[S]: Tag](s: S)(using VectorScalarMulable[S, V]) def *(v: V)(using Source): V = summon[VectorScalarMulable[S, V]].mul(v, s) - trait VectorNegatable[V <: Vec[?]: FromExpr: Tag]: + trait VectorNegatable[V <: Vec[?]: {FromExpr, Tag}]: def negate(a: V)(using Source): V = summon[FromExpr[V]].fromExpr(Negate(a)) - extension [V <: Vec[?]: VectorNegatable: Tag](a: V) + extension [V <: Vec[?]: {VectorNegatable, Tag}](a: V) @targetName("negateVector") def unary_-(using Source): V = summon[VectorNegatable[V]].negate(a) @@ -92,11 +92,11 @@ object VectorAlgebra: inline def vclamp(v: Vec3[Float32], min: Float32, max: Float32)(using Source): Vec3[Float32] = (clamp(v.x, min, max), clamp(v.y, min, max), clamp(v.z, min, max)) - extension [T <: Scalar: FromExpr: Tag](v2: Vec2[T]) + extension [T <: Scalar: {FromExpr, Tag}](v2: Vec2[T]) inline def x(using Source): T = summon[FromExpr[T]].fromExpr(ExtractScalar(v2, Int32(ConstInt32(0)))) inline def y(using Source): T = summon[FromExpr[T]].fromExpr(ExtractScalar(v2, Int32(ConstInt32(1)))) - extension [T <: Scalar: FromExpr: Tag](v3: Vec3[T]) + extension [T <: Scalar: {FromExpr, Tag}](v3: Vec3[T]) inline def x(using Source): T = summon[FromExpr[T]].fromExpr(ExtractScalar(v3, Int32(ConstInt32(0)))) inline def y(using Source): T = summon[FromExpr[T]].fromExpr(ExtractScalar(v3, Int32(ConstInt32(1)))) inline def z(using Source): T = summon[FromExpr[T]].fromExpr(ExtractScalar(v3, Int32(ConstInt32(2)))) @@ -104,7 +104,7 @@ object VectorAlgebra: inline def g(using Source): T = y inline def b(using Source): T = z - extension [T <: Scalar: FromExpr: Tag](v4: Vec4[T]) + extension [T <: Scalar: {FromExpr, Tag}](v4: Vec4[T]) inline def x(using Source): T = summon[FromExpr[T]].fromExpr(ExtractScalar(v4, Int32(ConstInt32(0)))) inline def y(using Source): T = summon[FromExpr[T]].fromExpr(ExtractScalar(v4, Int32(ConstInt32(1)))) inline def z(using Source): T = summon[FromExpr[T]].fromExpr(ExtractScalar(v4, Int32(ConstInt32(2)))) diff --git a/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/binding/GBinding.scala b/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/binding/GBinding.scala new file mode 100644 index 00000000..d9006d69 --- /dev/null +++ b/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/binding/GBinding.scala @@ -0,0 +1,7 @@ +package io.computenode.cyfra.dsl.binding + +import io.computenode.cyfra.dsl.Value +import io.computenode.cyfra.dsl.Value.FromExpr +import izumi.reflect.Tag + +trait GBinding[T <: Value: {Tag, FromExpr}] diff --git a/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/binding/GBuffer.scala b/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/binding/GBuffer.scala new file mode 100644 index 00000000..b9f849cf --- /dev/null +++ b/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/binding/GBuffer.scala @@ -0,0 +1,13 @@ +package io.computenode.cyfra.dsl.binding + +import io.computenode.cyfra.dsl.Value +import io.computenode.cyfra.dsl.Value.{FromExpr, Int32} +import io.computenode.cyfra.dsl.gio.GIO +import izumi.reflect.Tag + +trait GBuffer[T <: Value: {FromExpr, Tag}] extends GBinding[T]: + def read(index: Int32): T = FromExpr.fromExpr(ReadBuffer(this, index)) + + def write(index: Int32, value: T): GIO[Unit] = GIO.write(this, index, value) + +object GBuffer diff --git a/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/binding/GUniform.scala b/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/binding/GUniform.scala new file mode 100644 index 00000000..9e753e77 --- /dev/null +++ b/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/binding/GUniform.scala @@ -0,0 +1,19 @@ +package io.computenode.cyfra.dsl.binding + +import io.computenode.cyfra.dsl.Value +import io.computenode.cyfra.dsl.Value.FromExpr +import io.computenode.cyfra.dsl.Value.FromExpr.fromExpr +import io.computenode.cyfra.dsl.gio.GIO +import io.computenode.cyfra.dsl.struct.GStruct +import izumi.reflect.Tag + +trait GUniform[T <: Value: {Tag, FromExpr}] extends GBinding[T]: + def read: T = fromExpr(ReadUniform(this)) + + def write(value: T): GIO[Unit] = WriteUniform(this, value) + +object GUniform: + + case class ParamUniform[T <: GStruct[T]: {Tag, FromExpr}]() extends GUniform[T] + + def fromParams[T <: GStruct[T]: {Tag, FromExpr}] = ParamUniform[T]() diff --git a/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/binding/ReadBuffer.scala b/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/binding/ReadBuffer.scala new file mode 100644 index 00000000..e0057720 --- /dev/null +++ b/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/binding/ReadBuffer.scala @@ -0,0 +1,7 @@ +package io.computenode.cyfra.dsl.binding + +import io.computenode.cyfra.dsl.Value.Int32 +import io.computenode.cyfra.dsl.{Expression, Value} +import izumi.reflect.Tag + +case class ReadBuffer[T <: Value: Tag](buffer: GBuffer[T], index: Int32) extends Expression[T] diff --git a/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/binding/ReadUniform.scala b/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/binding/ReadUniform.scala new file mode 100644 index 00000000..9f75a278 --- /dev/null +++ b/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/binding/ReadUniform.scala @@ -0,0 +1,6 @@ +package io.computenode.cyfra.dsl.binding + +import io.computenode.cyfra.dsl.{Expression, Value} +import izumi.reflect.Tag + +case class ReadUniform[T <: Value: Tag](uniform: GUniform[T]) extends Expression[T] diff --git a/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/binding/WriteBuffer.scala b/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/binding/WriteBuffer.scala new file mode 100644 index 00000000..53b0abf9 --- /dev/null +++ b/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/binding/WriteBuffer.scala @@ -0,0 +1,8 @@ +package io.computenode.cyfra.dsl.binding + +import io.computenode.cyfra.dsl.Value +import io.computenode.cyfra.dsl.Value.Int32 +import io.computenode.cyfra.dsl.gio.GIO + +case class WriteBuffer[T <: Value](buffer: GBuffer[T], index: Int32, value: T) extends GIO[Unit]: + override def underlying: Unit = () diff --git a/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/binding/WriteUniform.scala b/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/binding/WriteUniform.scala new file mode 100644 index 00000000..240aa643 --- /dev/null +++ b/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/binding/WriteUniform.scala @@ -0,0 +1,9 @@ +package io.computenode.cyfra.dsl.binding + +import io.computenode.cyfra.dsl.Value +import io.computenode.cyfra.dsl.gio.GIO +import io.computenode.cyfra.dsl.struct.GStruct +import izumi.reflect.Tag + +case class WriteUniform[T <: Value: Tag](uniform: GUniform[T], value: T) extends GIO[Unit]: + override def underlying: Unit = () diff --git a/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/collections/GArray.scala b/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/collections/GArray.scala index f91383a0..6e9daf13 100644 --- a/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/collections/GArray.scala +++ b/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/collections/GArray.scala @@ -6,7 +6,7 @@ import io.computenode.cyfra.dsl.macros.Source import io.computenode.cyfra.dsl.{Expression, Value} import izumi.reflect.Tag -case class GArray[T <: Value: Tag: FromExpr](index: Int): +case class GArray[T <: Value: {Tag, FromExpr}](index: Int): def at(i: Int32)(using Source): T = summon[FromExpr[T]].fromExpr(GArrayElem(index, i.tree)) diff --git a/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/collections/GArray2D.scala b/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/collections/GArray2D.scala index 090797bf..70d6df19 100644 --- a/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/collections/GArray2D.scala +++ b/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/collections/GArray2D.scala @@ -7,6 +7,6 @@ import io.computenode.cyfra.dsl.macros.Source import izumi.reflect.Tag import io.computenode.cyfra.dsl.Value.FromExpr -class GArray2D[T <: Value: Tag: FromExpr](width: Int, val arr: GArray[T]): +class GArray2D[T <: Value: {Tag, FromExpr}](width: Int, val arr: GArray[T]): def at(x: Int32, y: Int32)(using Source): T = arr.at(y * width + x) diff --git a/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/collections/GSeq.scala b/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/collections/GSeq.scala index 103c5050..b4265a1b 100644 --- a/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/collections/GSeq.scala +++ b/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/collections/GSeq.scala @@ -10,7 +10,7 @@ import io.computenode.cyfra.dsl.macros.Source import io.computenode.cyfra.dsl.{Expression, Value} import izumi.reflect.Tag -class GSeq[T <: Value: Tag: FromExpr]( +class GSeq[T <: Value: {Tag, FromExpr}]( val uninitSource: Expression[?] => GSeqStream[?], val elemOps: List[GSeq.ElemOp[?]], val limit: Option[Int], @@ -19,7 +19,7 @@ class GSeq[T <: Value: Tag: FromExpr]( val aggregateElemExprTreeId: Int = 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, @@ -29,9 +29,9 @@ class GSeq[T <: Value: Tag: FromExpr]( private val currentElemExpr = CurrentElem[T](currentElemExprTreeId) val source = uninitSource(currentElemExpr) 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(AggregateElem[R](aggregateElemExprTreeId)) - def map[R <: Value: Tag: FromExpr](fn: T => R): GSeq[R] = + def map[R <: Value: {Tag, FromExpr}](fn: T => R): GSeq[R] = this.copyWithDynamicTrees[R](elemOps = elemOps :+ GSeq.MapOp[T, R](fn(currentElem).tree)) def filter(fn: T => GBoolean): GSeq[T] = @@ -43,7 +43,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 = @@ -54,11 +54,11 @@ class GSeq[T <: Value: Tag: FromExpr]( object GSeq: - def gen[T <: Value: Tag: FromExpr](first: T, next: T => T)(using name: Source) = + def gen[T <: Value: {Tag, FromExpr}](first: T, next: T => T)(using name: Source) = 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 .gen[Int32](0, _ + 1) .map: i => diff --git a/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/control/Pure.scala b/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/control/Pure.scala index 6f0bd5ff..2e517641 100644 --- a/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/control/Pure.scala +++ b/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/control/Pure.scala @@ -7,6 +7,6 @@ import io.computenode.cyfra.dsl.{Expression, Value} import izumi.reflect.Tag object Pure: - def pure[V <: Value: FromExpr: Tag](f: => V)(using fnCall: FnCall): V = + def pure[V <: Value: {FromExpr, Tag}](f: => V)(using fnCall: FnCall): V = val call = FunctionCall[V](fnCall.identifier, Scope(f.tree.asInstanceOf[Expression[V]], isDetached = true), fnCall.params) summon[FromExpr[V]].fromExpr(call) diff --git a/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/control/When.scala b/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/control/When.scala index 33df3207..9e7be3ad 100644 --- a/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/control/When.scala +++ b/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/control/When.scala @@ -7,7 +7,13 @@ import io.computenode.cyfra.dsl.Value.{FromExpr, GBoolean} import io.computenode.cyfra.dsl.macros.Source import izumi.reflect.Tag -case class When[T <: Value: Tag: FromExpr](when: GBoolean, thenCode: T, otherConds: List[Scope[GBoolean]], otherCases: List[Scope[T]], name: Source): +case class When[T <: Value: {Tag, FromExpr}]( + when: GBoolean, + thenCode: T, + otherConds: List[Scope[GBoolean]], + otherCases: List[Scope[T]], + name: Source, +): def elseWhen(cond: GBoolean)(t: T): When[T] = When(when, thenCode, otherConds :+ Scope(cond.tree), otherCases :+ Scope(t.tree.asInstanceOf[E[T]]), name) infix def otherwise(t: T): T = @@ -24,5 +30,5 @@ object When: otherwise: Scope[T], ) extends Expression[T] - def when[T <: Value: Tag: FromExpr](cond: GBoolean)(fn: T)(using name: Source): When[T] = + def when[T <: Value: {Tag, FromExpr}](cond: GBoolean)(fn: T)(using name: Source): When[T] = When(cond, fn, Nil, Nil, name) diff --git a/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/gio/GIO.scala b/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/gio/GIO.scala new file mode 100644 index 00000000..02a018f8 --- /dev/null +++ b/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/gio/GIO.scala @@ -0,0 +1,45 @@ +package io.computenode.cyfra.dsl.gio + +import io.computenode.cyfra.dsl.{*, given} +import io.computenode.cyfra.dsl.Value.{FromExpr, Int32} +import io.computenode.cyfra.dsl.Value.FromExpr.fromExpr +import io.computenode.cyfra.dsl.binding.{GBuffer, ReadBuffer, WriteBuffer} +import io.computenode.cyfra.dsl.collections.GSeq +import io.computenode.cyfra.dsl.gio.GIO.* +import izumi.reflect.Tag + +trait GIO[T]: + + def flatMap[U](f: T => GIO[U]): GIO[U] = FlatMap(this, f(this.underlying)) + + def map[U](f: T => U): GIO[U] = flatMap(t => GIO.pure(f(t))) + + private[cyfra] def underlying: T + +object GIO: + + case class Pure[T](value: T) extends GIO[T]: + override def underlying: T = value + + case class FlatMap[T, U](gio: GIO[T], next: GIO[U]) extends GIO[U]: + override def underlying: U = next.underlying + + // TODO repeat that collects results + case class Repeat(n: Int32, f: Int32 => GIO[?]) extends GIO[Unit]: + override def underlying: Unit = () + + def pure[T](value: T): GIO[T] = Pure(value) + + def value[T](value: T): GIO[T] = Pure(value) + + def repeat(n: Int32)(f: Int32 => GIO[?]): GIO[Unit] = + Repeat(n, f) + + def write[T <: Value](buffer: GBuffer[T], index: Int32, value: T): GIO[Unit] = + WriteBuffer(buffer, index, value) + + def read[T <: Value: {FromExpr, Tag}](buffer: GBuffer[T], index: Int32): T = + fromExpr(ReadBuffer(buffer, index)) + + def invocationId: Int32 = + fromExpr(InvocationId) diff --git a/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/library/Functions.scala b/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/library/Functions.scala index 0de27564..26b4a970 100644 --- a/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/library/Functions.scala +++ b/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/library/Functions.scala @@ -16,7 +16,7 @@ object Functions: case object Cos extends FunctionName def cos(v: Float32)(using Source): Float32 = Float32(ExtFunctionCall(Cos, List(v))) - def cos[V <: Vec[Float32]: Tag: FromExpr](v: V)(using Source): V = + def cos[V <: Vec[Float32]: {Tag, FromExpr}](v: V)(using Source): V = summon[FromExpr[V]].fromExpr(ExtFunctionCall(Cos, List(v))) case object Tan extends FunctionName @@ -43,7 +43,7 @@ object Functions: case object Pow extends FunctionName def pow(v: Float32, p: Float32)(using Source): Float32 = Float32(ExtFunctionCall(Pow, List(v, p))) - def pow[V <: Vec[?]: Tag: FromExpr](v: V, p: V)(using Source): V = + def pow[V <: Vec[?]: {Tag, FromExpr}](v: V, p: V)(using Source): V = summon[FromExpr[V]].fromExpr(ExtFunctionCall(Pow, List(v, p))) case object Smoothstep extends FunctionName @@ -61,48 +61,48 @@ object Functions: case object Exp extends FunctionName def exp(f: Float32)(using Source): Float32 = Float32(ExtFunctionCall(Exp, List(f))) - def exp[V <: Vec[Float32]: Tag: FromExpr](v: V)(using Source): V = + def exp[V <: Vec[Float32]: {Tag, FromExpr}](v: V)(using Source): V = summon[FromExpr[V]].fromExpr(ExtFunctionCall(Exp, List(v))) case object Max extends FunctionName def max(f1: Float32, f2: Float32)(using Source): Float32 = Float32(ExtFunctionCall(Max, List(f1, f2))) def max(f1: Float32, f2: Float32, fx: Float32*)(using Source): Float32 = fx.foldLeft(max(f1, f2))((a, b) => max(a, b)) - def max[V <: Vec[Float32]: Tag: FromExpr](v1: V, v2: V)(using Source): V = + def max[V <: Vec[Float32]: {Tag, FromExpr}](v1: V, v2: V)(using Source): V = summon[FromExpr[V]].fromExpr(ExtFunctionCall(Max, List(v1, v2))) - def max[V <: Vec[Float32]: Tag: FromExpr](v1: V, v2: V, vx: V*)(using Source): V = + def max[V <: Vec[Float32]: {Tag, FromExpr}](v1: V, v2: V, vx: V*)(using Source): V = vx.foldLeft(max(v1, v2))((a, b) => max(a, b)) case object Min extends FunctionName def min(f1: Float32, f2: Float32)(using Source): Float32 = Float32(ExtFunctionCall(Min, List(f1, f2))) def min(f1: Float32, f2: Float32, fx: Float32*)(using Source): Float32 = fx.foldLeft(min(f1, f2))((a, b) => min(a, b)) - def min[V <: Vec[Float32]: Tag: FromExpr](v1: V, v2: V)(using Source): V = + def min[V <: Vec[Float32]: {Tag, FromExpr}](v1: V, v2: V)(using Source): V = summon[FromExpr[V]].fromExpr(ExtFunctionCall(Min, List(v1, v2))) - def min[V <: Vec[Float32]: Tag: FromExpr](v1: V, v2: V, vx: V*)(using Source): V = + def min[V <: Vec[Float32]: {Tag, FromExpr}](v1: V, v2: V, vx: V*)(using Source): V = vx.foldLeft(min(v1, v2))((a, b) => min(a, b)) // todo add F/U/S to all functions that need it case object Abs extends FunctionName def abs(f: Float32)(using Source): Float32 = Float32(ExtFunctionCall(Abs, List(f))) - def abs[V <: Vec[Float32]: Tag: FromExpr](v: V)(using Source): V = + def abs[V <: Vec[Float32]: {Tag, FromExpr}](v: V)(using Source): V = summon[FromExpr[V]].fromExpr(ExtFunctionCall(Abs, List(v))) case object Mix extends FunctionName - def mix[V <: Vec[Float32]: Tag: FromExpr](a: V, b: V, t: V)(using Source) = + def mix[V <: Vec[Float32]: {Tag, FromExpr}](a: V, b: V, t: V)(using Source) = summon[FromExpr[V]].fromExpr(ExtFunctionCall(Mix, List(a, b, t))) def mix(a: Float32, b: Float32, t: Float32)(using Source) = Float32(ExtFunctionCall(Mix, List(a, b, t))) - def mix[V <: Vec[Float32]: Tag: FromExpr](a: V, b: V, t: Float32)(using Source) = + def mix[V <: Vec[Float32]: {Tag, FromExpr}](a: V, b: V, t: Float32)(using Source) = summon[FromExpr[V]].fromExpr(ExtFunctionCall(Mix, List(a, b, vec3(t)))) case object Reflect extends FunctionName - def reflect[I <: Vec[Float32]: Tag: FromExpr, N <: Vec[Float32]: Tag: FromExpr](I: I, N: N)(using Source): I = + def reflect[I <: Vec[Float32]: {Tag, FromExpr}, N <: Vec[Float32]: {Tag, FromExpr}](I: I, N: N)(using Source): I = summon[FromExpr[I]].fromExpr(ExtFunctionCall(Reflect, List(I, N))) case object Refract extends FunctionName - def refract[V <: Vec[Float32]: Tag: FromExpr](I: V, N: V, eta: Float32)(using Source): V = + def refract[V <: Vec[Float32]: {Tag, FromExpr}](I: V, N: V, eta: Float32)(using Source): V = summon[FromExpr[V]].fromExpr(ExtFunctionCall(Refract, List(I, N, eta))) case object Normalize extends FunctionName - def normalize[V <: Vec[Float32]: Tag: FromExpr](v: V)(using Source): V = + def normalize[V <: Vec[Float32]: {Tag, FromExpr}](v: V)(using Source): V = summon[FromExpr[V]].fromExpr(ExtFunctionCall(Normalize, List(v))) case object Log extends FunctionName diff --git a/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/struct/GStruct.scala b/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/struct/GStruct.scala index 6ed56ab0..9ec4199b 100644 --- a/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/struct/GStruct.scala +++ b/cyfra-dsl/src/main/scala/io/computenode/cyfra/dsl/struct/GStruct.scala @@ -10,7 +10,7 @@ import izumi.reflect.Tag import scala.compiletime.* import scala.deriving.Mirror -abstract class GStruct[T <: GStruct[T]: Tag: GStructSchema] extends Value with Product: +abstract class GStruct[T <: GStruct[T]: {Tag, GStructSchema}] extends Value with Product: self: T => private[cyfra] var _schema: GStructSchema[T] = summon[GStructSchema[T]] // a nasty hack def schema: GStructSchema[T] = _schema diff --git a/cyfra-e2e-test/src/test/scala/io/computenode/cyfra/e2e/ArithmeticsE2eTest.scala b/cyfra-e2e-test/src/test/scala/io/computenode/cyfra/e2e/ArithmeticsE2eTest.scala index 3ffd6b71..17797a77 100644 --- a/cyfra-e2e-test/src/test/scala/io/computenode/cyfra/e2e/ArithmeticsE2eTest.scala +++ b/cyfra-e2e-test/src/test/scala/io/computenode/cyfra/e2e/ArithmeticsE2eTest.scala @@ -1,6 +1,6 @@ package io.computenode.cyfra.e2e -import io.computenode.cyfra.runtime.* +import io.computenode.cyfra.core.archive.* import mem.* import GMem.fRGBA import io.computenode.cyfra.dsl.algebra.VectorAlgebra diff --git a/cyfra-e2e-test/src/test/scala/io/computenode/cyfra/e2e/FunctionsE2eTest.scala b/cyfra-e2e-test/src/test/scala/io/computenode/cyfra/e2e/FunctionsE2eTest.scala index 6a332ac8..31966edf 100644 --- a/cyfra-e2e-test/src/test/scala/io/computenode/cyfra/e2e/FunctionsE2eTest.scala +++ b/cyfra-e2e-test/src/test/scala/io/computenode/cyfra/e2e/FunctionsE2eTest.scala @@ -1,6 +1,6 @@ package io.computenode.cyfra.e2e -import io.computenode.cyfra.runtime.*, mem.* +import io.computenode.cyfra.core.archive.*, mem.* import io.computenode.cyfra.dsl.struct.GStruct import io.computenode.cyfra.dsl.{*, given} import GMem.fRGBA diff --git a/cyfra-e2e-test/src/test/scala/io/computenode/cyfra/e2e/GStructE2eTest.scala b/cyfra-e2e-test/src/test/scala/io/computenode/cyfra/e2e/GStructE2eTest.scala index 61b4db15..c1183c2a 100644 --- a/cyfra-e2e-test/src/test/scala/io/computenode/cyfra/e2e/GStructE2eTest.scala +++ b/cyfra-e2e-test/src/test/scala/io/computenode/cyfra/e2e/GStructE2eTest.scala @@ -2,7 +2,7 @@ package io.computenode.cyfra.e2e import io.computenode.cyfra.dsl.collections.GSeq import io.computenode.cyfra.dsl.struct.GStruct -import io.computenode.cyfra.runtime.* +import io.computenode.cyfra.core.archive.* import mem.* import io.computenode.cyfra.dsl.{*, given} diff --git a/cyfra-e2e-test/src/test/scala/io/computenode/cyfra/e2e/GseqE2eTest.scala b/cyfra-e2e-test/src/test/scala/io/computenode/cyfra/e2e/GseqE2eTest.scala index 8b70999e..d10cca51 100644 --- a/cyfra-e2e-test/src/test/scala/io/computenode/cyfra/e2e/GseqE2eTest.scala +++ b/cyfra-e2e-test/src/test/scala/io/computenode/cyfra/e2e/GseqE2eTest.scala @@ -2,7 +2,7 @@ package io.computenode.cyfra.e2e import io.computenode.cyfra.dsl.collections.GSeq import io.computenode.cyfra.dsl.struct.GStruct -import io.computenode.cyfra.runtime.* +import io.computenode.cyfra.core.archive.* import mem.* import io.computenode.cyfra.dsl.{*, given} diff --git a/cyfra-e2e-test/src/test/scala/io/computenode/cyfra/e2e/WhenE2eTest.scala b/cyfra-e2e-test/src/test/scala/io/computenode/cyfra/e2e/WhenE2eTest.scala index 3a53669f..0a374c26 100644 --- a/cyfra-e2e-test/src/test/scala/io/computenode/cyfra/e2e/WhenE2eTest.scala +++ b/cyfra-e2e-test/src/test/scala/io/computenode/cyfra/e2e/WhenE2eTest.scala @@ -1,7 +1,7 @@ package io.computenode.cyfra.e2e import io.computenode.cyfra.dsl.struct.GStruct -import io.computenode.cyfra.runtime.* +import io.computenode.cyfra.core.archive.* import mem.* import io.computenode.cyfra.dsl.{*, given} diff --git a/cyfra-e2e-test/src/test/scala/io/computenode/cyfra/e2e/juliaset/JuliaSet.scala b/cyfra-e2e-test/src/test/scala/io/computenode/cyfra/e2e/juliaset/JuliaSet.scala index 7431960d..df9b0191 100644 --- a/cyfra-e2e-test/src/test/scala/io/computenode/cyfra/e2e/juliaset/JuliaSet.scala +++ b/cyfra-e2e-test/src/test/scala/io/computenode/cyfra/e2e/juliaset/JuliaSet.scala @@ -6,8 +6,8 @@ import io.computenode.cyfra.dsl.collections.GSeq import io.computenode.cyfra.dsl.control.Pure.pure import io.computenode.cyfra.dsl.struct.GStruct.Empty import io.computenode.cyfra.e2e.ImageTests -import io.computenode.cyfra.runtime.mem.Vec4FloatMem -import io.computenode.cyfra.runtime.{GContext, GFunction} +import io.computenode.cyfra.core.archive.mem.Vec4FloatMem +import io.computenode.cyfra.core.archive.{GContext, GFunction} import io.computenode.cyfra.spirvtools.* import io.computenode.cyfra.spirvtools.SpirvTool.{Param, ToFile} import io.computenode.cyfra.utility.ImageUtility diff --git a/cyfra-examples/src/main/resources/gio.scala b/cyfra-examples/src/main/resources/gio.scala new file mode 100644 index 00000000..1ef1889a --- /dev/null +++ b/cyfra-examples/src/main/resources/gio.scala @@ -0,0 +1,12 @@ +import io.computenode.cyfra.dsl.Value.Int32 + +val inBuffer = GBuffer[Int32]() +val outBuffer = GBuffer[Int32]() + +val program = GProgram.on(inBuffer, outBuffer): + case (in, out) => for + index <- GIO.workerIndex + a <- in.read(index) + _ <- out.write(index, a + 1) + _ <- out.write(index * 2, a * 2) + yield () \ No newline at end of file diff --git a/cyfra-examples/src/main/scala/io/computenode/cyfra/samples/TestingStuff.scala b/cyfra-examples/src/main/scala/io/computenode/cyfra/samples/TestingStuff.scala new file mode 100644 index 00000000..d94c895b --- /dev/null +++ b/cyfra-examples/src/main/scala/io/computenode/cyfra/samples/TestingStuff.scala @@ -0,0 +1,109 @@ +package io.computenode.cyfra.samples + +import io.computenode.cyfra.core.archive.GContext +import io.computenode.cyfra.core.{GBufferRegion, GExecution, GProgram} +import io.computenode.cyfra.core.layout.* +import io.computenode.cyfra.dsl.Value.{GBoolean, Int32} +import io.computenode.cyfra.dsl.binding.{GBuffer, GUniform} +import io.computenode.cyfra.dsl.gio.GIO +import io.computenode.cyfra.dsl.struct.GStruct +import io.computenode.cyfra.dsl.{*, given} +import org.lwjgl.BufferUtils +import io.computenode.cyfra.runtime.VkCyfraRuntime +object TestingStuff: + + given GContext = GContext() + + // === Emit program === + + case class EmitProgramParams(inSize: Int, emitN: Int) + + case class EmitProgramUniform(emitN: Int32) extends GStruct[EmitProgramUniform] + + case class EmitProgramLayout( + in: GBuffer[Int32], + out: GBuffer[Int32], + args: GUniform[EmitProgramUniform] = GUniform.fromParams, // todo will be different in the future + ) extends Layout + + val emitProgram = GProgram[EmitProgramParams, EmitProgramLayout]( + layout = params => + EmitProgramLayout( + in = GBuffer[Int32](params.inSize), + out = GBuffer[Int32](params.inSize * params.emitN), + args = GUniform(EmitProgramUniform(params.emitN)), + ), + dispatch = (layout, args) => GProgram.StaticDispatch((args.inSize, 1, 1)), + ): layout => + val EmitProgramUniform(emitN) = layout.args.read + val invocId = GIO.invocationId + val element = GIO.read(layout.in, invocId) + val bufferOffset = invocId * emitN + GIO.repeat(emitN): i => + GIO.write(layout.out, bufferOffset + i, element) + + // === Filter program === + + case class FilterProgramParams(inSize: Int, filterValue: Int) + + case class FilterProgramUniform(filterValue: Int32) extends GStruct[FilterProgramUniform] + + case class FilterProgramLayout(in: GBuffer[Int32], out: GBuffer[GBoolean], params: GUniform[FilterProgramUniform] = GUniform.fromParams) + extends Layout + + val filterProgram = GProgram[FilterProgramParams, FilterProgramLayout]( + layout = params => + FilterProgramLayout( + in = GBuffer[Int32](params.inSize), + out = GBuffer[GBoolean](params.inSize), + params = GUniform(FilterProgramUniform(params.filterValue)), + ), + dispatch = (layout, args) => GProgram.StaticDispatch((args.inSize, 1, 1)), + ): layout => + val invocId = GIO.invocationId + val element = GIO.read(layout.in, invocId) + val isMatch = element === layout.params.read.filterValue + GIO.write(layout.out, invocId, isMatch) + + // === GExecution === + + case class EmitFilterParams(inSize: Int, emitN: Int, filterValue: Int) + + case class EmitFilterLayout(inBuffer: GBuffer[Int32], emitBuffer: GBuffer[Int32], filterBuffer: GBuffer[GBoolean]) extends Layout + + case class EmitFilterResult(out: GBuffer[GBoolean]) extends Layout + + val emitFilterExecution = GExecution[EmitFilterParams, EmitFilterLayout]() + .addProgram(emitProgram)( + params => EmitProgramParams(inSize = params.inSize, emitN = params.emitN), + layout => EmitProgramLayout(in = layout.inBuffer, out = layout.emitBuffer), + ) + .addProgram(filterProgram)( + params => FilterProgramParams(inSize = params.inSize, filterValue = params.filterValue), + layout => FilterProgramLayout(in = layout.emitBuffer, out = layout.filterBuffer), + ) + + @main + def test = + given VkCyfraRuntime = VkCyfraRuntime() + + val emitFilterParams = EmitFilterParams(inSize = 1024, emitN = 2, filterValue = 42) + + val region = GBufferRegion + .allocate[EmitFilterLayout] + .map: region => + emitFilterExecution.execute(emitFilterParams, region) + + val data = (0 to 1024).toArray + val buffer = BufferUtils.createByteBuffer(data.length * 4) + buffer.asIntBuffer().put(data).flip() + + val result = BufferUtils.createByteBuffer(data.length * 2) + region.runUnsafe( + init = EmitFilterLayout( + inBuffer = GBuffer[Int32](buffer), + emitBuffer = GBuffer[Int32](data.length * 2), + filterBuffer = GBuffer[GBoolean](data.length * 2), + ), + onDone = layout => layout.filterBuffer.read(result), + ) diff --git a/cyfra-examples/src/main/scala/io/computenode/samples/cyfra/foton/AnimatedJulia.scala b/cyfra-examples/src/main/scala/io/computenode/cyfra/samples/foton/AnimatedJulia.scala similarity index 97% rename from cyfra-examples/src/main/scala/io/computenode/samples/cyfra/foton/AnimatedJulia.scala rename to cyfra-examples/src/main/scala/io/computenode/cyfra/samples/foton/AnimatedJulia.scala index 200e16a6..99bd6759 100644 --- a/cyfra-examples/src/main/scala/io/computenode/samples/cyfra/foton/AnimatedJulia.scala +++ b/cyfra-examples/src/main/scala/io/computenode/cyfra/samples/foton/AnimatedJulia.scala @@ -1,4 +1,4 @@ -package io.computenode.samples.cyfra.foton +package io.computenode.cyfra.samples.foton import io.computenode.cyfra import io.computenode.cyfra.* diff --git a/cyfra-examples/src/main/scala/io/computenode/samples/cyfra/foton/AnimatedRaytrace.scala b/cyfra-examples/src/main/scala/io/computenode/cyfra/samples/foton/AnimatedRaytrace.scala similarity index 98% rename from cyfra-examples/src/main/scala/io/computenode/samples/cyfra/foton/AnimatedRaytrace.scala rename to cyfra-examples/src/main/scala/io/computenode/cyfra/samples/foton/AnimatedRaytrace.scala index bd2c65de..f478647a 100644 --- a/cyfra-examples/src/main/scala/io/computenode/samples/cyfra/foton/AnimatedRaytrace.scala +++ b/cyfra-examples/src/main/scala/io/computenode/cyfra/samples/foton/AnimatedRaytrace.scala @@ -1,4 +1,4 @@ -package io.computenode.samples.cyfra.foton +package io.computenode.cyfra.samples.foton import io.computenode.cyfra.dsl.{*, given} import io.computenode.cyfra.dsl.library.Color.hex diff --git a/cyfra-examples/src/main/scala/io/computenode/samples/cyfra/oldsamples/Raytracing.scala b/cyfra-examples/src/main/scala/io/computenode/cyfra/samples/oldsamples/Raytracing.scala similarity index 99% rename from cyfra-examples/src/main/scala/io/computenode/samples/cyfra/oldsamples/Raytracing.scala rename to cyfra-examples/src/main/scala/io/computenode/cyfra/samples/oldsamples/Raytracing.scala index b9c2279d..ab35810e 100644 --- a/cyfra-examples/src/main/scala/io/computenode/samples/cyfra/oldsamples/Raytracing.scala +++ b/cyfra-examples/src/main/scala/io/computenode/cyfra/samples/oldsamples/Raytracing.scala @@ -1,10 +1,10 @@ -package io.computenode.samples.cyfra.oldsamples +package io.computenode.cyfra.samples.oldsamples import io.computenode.cyfra.dsl.collections.GSeq import io.computenode.cyfra.dsl.{*, given} import io.computenode.cyfra.dsl.struct.GStruct -import io.computenode.cyfra.runtime.* -import io.computenode.cyfra.runtime.mem.Vec4FloatMem +import io.computenode.cyfra.core.archive.* +import io.computenode.cyfra.core.archive.mem.Vec4FloatMem import io.computenode.cyfra.utility.ImageUtility import java.nio.file.Paths diff --git a/cyfra-examples/src/main/scala/io/computenode/samples/cyfra/slides/1sample.scala b/cyfra-examples/src/main/scala/io/computenode/cyfra/samples/slides/1sample.scala similarity index 69% rename from cyfra-examples/src/main/scala/io/computenode/samples/cyfra/slides/1sample.scala rename to cyfra-examples/src/main/scala/io/computenode/cyfra/samples/slides/1sample.scala index 518687d3..16121da4 100644 --- a/cyfra-examples/src/main/scala/io/computenode/samples/cyfra/slides/1sample.scala +++ b/cyfra-examples/src/main/scala/io/computenode/cyfra/samples/slides/1sample.scala @@ -1,8 +1,8 @@ -package io.computenode.samples.cyfra.slides +package io.computenode.cyfra.samples.slides import io.computenode.cyfra.dsl.{*, given} -import io.computenode.cyfra.runtime.* -import io.computenode.cyfra.runtime.mem.FloatMem +import io.computenode.cyfra.core.archive.* +import io.computenode.cyfra.core.archive.mem.FloatMem given GContext = new GContext() diff --git a/cyfra-examples/src/main/scala/io/computenode/samples/cyfra/slides/2simpleray.scala b/cyfra-examples/src/main/scala/io/computenode/cyfra/samples/slides/2simpleray.scala similarity index 91% rename from cyfra-examples/src/main/scala/io/computenode/samples/cyfra/slides/2simpleray.scala rename to cyfra-examples/src/main/scala/io/computenode/cyfra/samples/slides/2simpleray.scala index 6575bbaa..145fe5e6 100644 --- a/cyfra-examples/src/main/scala/io/computenode/samples/cyfra/slides/2simpleray.scala +++ b/cyfra-examples/src/main/scala/io/computenode/cyfra/samples/slides/2simpleray.scala @@ -1,10 +1,10 @@ -package io.computenode.samples.cyfra.slides +package io.computenode.cyfra.samples.slides import io.computenode.cyfra.dsl.{*, given} import io.computenode.cyfra.dsl.struct.GStruct import io.computenode.cyfra.dsl.struct.GStruct.Empty -import io.computenode.cyfra.runtime.* -import io.computenode.cyfra.runtime.mem.Vec4FloatMem +import io.computenode.cyfra.core.archive.* +import io.computenode.cyfra.core.archive.mem.Vec4FloatMem import io.computenode.cyfra.utility.ImageUtility import java.nio.file.Paths diff --git a/cyfra-examples/src/main/scala/io/computenode/samples/cyfra/slides/3rays.scala b/cyfra-examples/src/main/scala/io/computenode/cyfra/samples/slides/3rays.scala similarity index 97% rename from cyfra-examples/src/main/scala/io/computenode/samples/cyfra/slides/3rays.scala rename to cyfra-examples/src/main/scala/io/computenode/cyfra/samples/slides/3rays.scala index 7784be27..49ff0d46 100644 --- a/cyfra-examples/src/main/scala/io/computenode/samples/cyfra/slides/3rays.scala +++ b/cyfra-examples/src/main/scala/io/computenode/cyfra/samples/slides/3rays.scala @@ -1,12 +1,12 @@ -package io.computenode.samples.cyfra.slides +package io.computenode.cyfra.samples.slides import io.computenode.cyfra.* import io.computenode.cyfra.dsl.collections.GSeq import io.computenode.cyfra.dsl.{*, given} import io.computenode.cyfra.dsl.struct.GStruct import io.computenode.cyfra.dsl.struct.GStruct.Empty -import io.computenode.cyfra.runtime.* -import io.computenode.cyfra.runtime.mem.Vec4FloatMem +import io.computenode.cyfra.core.archive.* +import io.computenode.cyfra.core.archive.mem.Vec4FloatMem import io.computenode.cyfra.utility.ImageUtility import java.nio.file.Paths diff --git a/cyfra-examples/src/main/scala/io/computenode/samples/cyfra/slides/4random.scala b/cyfra-examples/src/main/scala/io/computenode/cyfra/samples/slides/4random.scala similarity index 98% rename from cyfra-examples/src/main/scala/io/computenode/samples/cyfra/slides/4random.scala rename to cyfra-examples/src/main/scala/io/computenode/cyfra/samples/slides/4random.scala index 4ecd8e8b..bac16f3b 100644 --- a/cyfra-examples/src/main/scala/io/computenode/samples/cyfra/slides/4random.scala +++ b/cyfra-examples/src/main/scala/io/computenode/cyfra/samples/slides/4random.scala @@ -1,11 +1,11 @@ -package io.computenode.samples.cyfra.slides +package io.computenode.cyfra.samples.slides import io.computenode.cyfra.dsl.collections.GSeq import io.computenode.cyfra.dsl.{*, given} import io.computenode.cyfra.dsl.struct.GStruct import io.computenode.cyfra.dsl.struct.GStruct.Empty -import io.computenode.cyfra.runtime.* -import io.computenode.cyfra.runtime.mem.Vec4FloatMem +import io.computenode.cyfra.core.archive.* +import io.computenode.cyfra.core.archive.mem.Vec4FloatMem import io.computenode.cyfra.utility.ImageUtility import java.nio.file.Paths diff --git a/cyfra-foton/src/main/scala/io/computenode/cyfra/foton/animation/AnimatedFunctionRenderer.scala b/cyfra-foton/src/main/scala/io/computenode/cyfra/foton/animation/AnimatedFunctionRenderer.scala index d8d6dff5..1e18cd28 100644 --- a/cyfra-foton/src/main/scala/io/computenode/cyfra/foton/animation/AnimatedFunctionRenderer.scala +++ b/cyfra-foton/src/main/scala/io/computenode/cyfra/foton/animation/AnimatedFunctionRenderer.scala @@ -6,9 +6,9 @@ import io.computenode.cyfra.dsl.struct.GStruct import io.computenode.cyfra.dsl.{*, given} import io.computenode.cyfra.foton.animation.AnimatedFunctionRenderer.{AnimationIteration, RenderFn} import io.computenode.cyfra.foton.animation.AnimationFunctions.AnimationInstant -import io.computenode.cyfra.runtime.mem.GMem.fRGBA -import io.computenode.cyfra.runtime.mem.Vec4FloatMem -import io.computenode.cyfra.runtime.{GContext, GFunction, UniformContext} +import io.computenode.cyfra.core.archive.mem.GMem.fRGBA +import io.computenode.cyfra.core.archive.mem.Vec4FloatMem +import io.computenode.cyfra.core.archive.{GContext, GFunction, UniformContext} import scala.concurrent.ExecutionContext import scala.concurrent.ExecutionContext.Implicits diff --git a/cyfra-foton/src/main/scala/io/computenode/cyfra/foton/animation/AnimationRenderer.scala b/cyfra-foton/src/main/scala/io/computenode/cyfra/foton/animation/AnimationRenderer.scala index df4ea7ca..9a262e95 100644 --- a/cyfra-foton/src/main/scala/io/computenode/cyfra/foton/animation/AnimationRenderer.scala +++ b/cyfra-foton/src/main/scala/io/computenode/cyfra/foton/animation/AnimationRenderer.scala @@ -3,8 +3,8 @@ package io.computenode.cyfra.foton.animation import io.computenode.cyfra import io.computenode.cyfra.dsl.Value.* import io.computenode.cyfra.dsl.{*, given} -import io.computenode.cyfra.runtime.GFunction -import io.computenode.cyfra.runtime.mem.GMem.fRGBA +import io.computenode.cyfra.core.archive.GFunction +import io.computenode.cyfra.core.archive.mem.GMem.fRGBA import io.computenode.cyfra.utility.ImageUtility import io.computenode.cyfra.utility.Units.Milliseconds import io.computenode.cyfra.utility.Utility.timed diff --git a/cyfra-foton/src/main/scala/io/computenode/cyfra/foton/rt/ImageRtRenderer.scala b/cyfra-foton/src/main/scala/io/computenode/cyfra/foton/rt/ImageRtRenderer.scala index 6a314eb5..8f4d2b70 100644 --- a/cyfra-foton/src/main/scala/io/computenode/cyfra/foton/rt/ImageRtRenderer.scala +++ b/cyfra-foton/src/main/scala/io/computenode/cyfra/foton/rt/ImageRtRenderer.scala @@ -6,9 +6,9 @@ import io.computenode.cyfra.dsl.Value.* import io.computenode.cyfra.dsl.struct.GStruct import io.computenode.cyfra.dsl.{*, given} import io.computenode.cyfra.foton.rt.ImageRtRenderer.RaytracingIteration -import io.computenode.cyfra.runtime.mem.GMem.fRGBA -import io.computenode.cyfra.runtime.mem.Vec4FloatMem -import io.computenode.cyfra.runtime.{GFunction, UniformContext} +import io.computenode.cyfra.core.archive.mem.GMem.fRGBA +import io.computenode.cyfra.core.archive.mem.Vec4FloatMem +import io.computenode.cyfra.core.archive.{GFunction, UniformContext} import io.computenode.cyfra.utility.ImageUtility import io.computenode.cyfra.utility.Utility.timed diff --git a/cyfra-foton/src/main/scala/io/computenode/cyfra/foton/rt/RtRenderer.scala b/cyfra-foton/src/main/scala/io/computenode/cyfra/foton/rt/RtRenderer.scala index 1c591a71..b59765b1 100644 --- a/cyfra-foton/src/main/scala/io/computenode/cyfra/foton/rt/RtRenderer.scala +++ b/cyfra-foton/src/main/scala/io/computenode/cyfra/foton/rt/RtRenderer.scala @@ -10,7 +10,7 @@ import io.computenode.cyfra.dsl.library.Random import io.computenode.cyfra.dsl.struct.GStruct import io.computenode.cyfra.dsl.{*, given} import io.computenode.cyfra.foton.rt.RtRenderer.RayHitInfo -import io.computenode.cyfra.runtime.GContext +import io.computenode.cyfra.core.archive.GContext import scala.concurrent.ExecutionContext import scala.concurrent.ExecutionContext.Implicits diff --git a/cyfra-foton/src/main/scala/io/computenode/cyfra/foton/rt/animation/AnimationRtRenderer.scala b/cyfra-foton/src/main/scala/io/computenode/cyfra/foton/rt/animation/AnimationRtRenderer.scala index 2674c237..c339bec9 100644 --- a/cyfra-foton/src/main/scala/io/computenode/cyfra/foton/rt/animation/AnimationRtRenderer.scala +++ b/cyfra-foton/src/main/scala/io/computenode/cyfra/foton/rt/animation/AnimationRtRenderer.scala @@ -7,9 +7,9 @@ import io.computenode.cyfra.dsl.{*, given} import io.computenode.cyfra.foton.animation.AnimationRenderer import io.computenode.cyfra.foton.rt.RtRenderer import io.computenode.cyfra.foton.rt.animation.AnimationRtRenderer.RaytracingIteration -import io.computenode.cyfra.runtime.mem.GMem.fRGBA -import io.computenode.cyfra.runtime.mem.Vec4FloatMem -import io.computenode.cyfra.runtime.{GFunction, UniformContext} +import io.computenode.cyfra.core.archive.mem.GMem.fRGBA +import io.computenode.cyfra.core.archive.mem.Vec4FloatMem +import io.computenode.cyfra.core.archive.{GFunction, UniformContext} class AnimationRtRenderer(params: AnimationRtRenderer.Parameters) extends RtRenderer(params) diff --git a/cyfra-foton/src/main/scala/io/computenode/cyfra/foton/rt/shapes/ShapeCollection.scala b/cyfra-foton/src/main/scala/io/computenode/cyfra/foton/rt/shapes/ShapeCollection.scala index efe2c76a..27fce060 100644 --- a/cyfra-foton/src/main/scala/io/computenode/cyfra/foton/rt/shapes/ShapeCollection.scala +++ b/cyfra-foton/src/main/scala/io/computenode/cyfra/foton/rt/shapes/ShapeCollection.scala @@ -36,7 +36,7 @@ class ShapeCollection(val boxes: List[Box], val spheres: List[Sphere], val quads case _ => assert(false, "Unknown shape type: Broken sealed hierarchy") def testRay(rayPos: Vec3[Float32], rayDir: Vec3[Float32], noHit: RayHitInfo): RayHitInfo = - def testShapeType[T <: GStruct[T] & Shape: FromExpr: Tag: TestRay](shapes: List[T], currentHit: RayHitInfo): RayHitInfo = + def testShapeType[T <: GStruct[T] & Shape: {FromExpr, Tag, TestRay}](shapes: List[T], currentHit: RayHitInfo): RayHitInfo = val testRay = summon[TestRay[T]] if shapes.isEmpty then currentHit else GSeq.of(shapes).fold(currentHit, (currentHit, shape) => testRay.testRay(shape, rayPos, rayDir, currentHit)) diff --git a/cyfra-runtime/src/main/scala/io/computenode/cyfra/runtime/ExecutionHandler.scala b/cyfra-runtime/src/main/scala/io/computenode/cyfra/runtime/ExecutionHandler.scala new file mode 100644 index 00000000..df0b470e --- /dev/null +++ b/cyfra-runtime/src/main/scala/io/computenode/cyfra/runtime/ExecutionHandler.scala @@ -0,0 +1,11 @@ +package io.computenode.cyfra.runtime + +import io.computenode.cyfra.core.{GExecution, GProgram} +import io.computenode.cyfra.core.layout.Layout + +object ExecutionHandler: + + def handle[Params, L <: Layout, RL <: Layout](execution: GExecution[Params, L, RL], params: Params): List[BoundProgram[?, ?, ?]] = + ??? + + case class BoundProgram[LParams, Params, L <: Layout](layout: L, paramsMapping: LParams => Params, program: GProgram[Params, L]) diff --git a/cyfra-runtime/src/main/scala/io/computenode/cyfra/runtime/UniformContext.scala b/cyfra-runtime/src/main/scala/io/computenode/cyfra/runtime/UniformContext.scala deleted file mode 100644 index 04df0996..00000000 --- a/cyfra-runtime/src/main/scala/io/computenode/cyfra/runtime/UniformContext.scala +++ /dev/null @@ -1,12 +0,0 @@ -package io.computenode.cyfra.runtime - -import io.computenode.cyfra.dsl.struct.* -import io.computenode.cyfra.dsl.struct.GStruct.Empty -import izumi.reflect.Tag - -class UniformContext[G <: GStruct[G]: Tag: GStructSchema](val uniform: G) - -object UniformContext: - def withUniform[G <: GStruct[G]: Tag: GStructSchema, T](uniform: G)(fn: UniformContext[G] ?=> T): T = - fn(using UniformContext(uniform)) - given empty: UniformContext[Empty] = new UniformContext(Empty()) diff --git a/cyfra-runtime/src/main/scala/io/computenode/cyfra/runtime/VkAllocation.scala b/cyfra-runtime/src/main/scala/io/computenode/cyfra/runtime/VkAllocation.scala new file mode 100644 index 00000000..d1474976 --- /dev/null +++ b/cyfra-runtime/src/main/scala/io/computenode/cyfra/runtime/VkAllocation.scala @@ -0,0 +1,29 @@ +package io.computenode.cyfra.runtime + +import io.computenode.cyfra.core.layout.{Layout, LayoutStruct} +import io.computenode.cyfra.core.{Allocation, GExecution} +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 +import izumi.reflect.Tag + +import java.nio.ByteBuffer + +class VkAllocation extends Allocation: + extension (buffer: GBinding[?]) + def read(bb: ByteBuffer, offset: Int = 0, length: Int = -1): Unit = ??? + + def write(bb: ByteBuffer, offset: Int = 0, length: Int = -1): Unit = ??? + + extension [Params, L <: Layout, RL <: Layout: LayoutStruct](execution: GExecution[Params, L, RL]) def execute(params: Params, layout: L): RL = ??? + + extension (buffers: GBuffer.type) + def apply[T <: Value: {Tag, FromExpr}](size: Int): GBuffer[T] = ??? + + def apply[T <: Value: {Tag, FromExpr}](buff: ByteBuffer): GBuffer[T] = ??? + + extension (buffers: GUniform.type) + def apply[T <: Value: {Tag, FromExpr}](buff: ByteBuffer): GUniform[T] = ??? + + def apply[T <: Value: {Tag, FromExpr}](): GUniform[T] = ??? diff --git a/cyfra-runtime/src/main/scala/io/computenode/cyfra/runtime/VkCyfraRuntime.scala b/cyfra-runtime/src/main/scala/io/computenode/cyfra/runtime/VkCyfraRuntime.scala new file mode 100644 index 00000000..87dbd5ab --- /dev/null +++ b/cyfra-runtime/src/main/scala/io/computenode/cyfra/runtime/VkCyfraRuntime.scala @@ -0,0 +1,8 @@ +package io.computenode.cyfra.runtime + +import io.computenode.cyfra.core.Allocation +import io.computenode.cyfra.core.{Allocation, CyfraRuntime} + +class VkCyfraRuntime extends CyfraRuntime: + override def allocation(): Allocation = + new VkAllocation()