Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package io.computenode.cyfra.core

import io.computenode.cyfra.core.layout.{Layout, LayoutBinding}
import io.computenode.cyfra.core.layout.Layout
import io.computenode.cyfra.dsl.Value
import io.computenode.cyfra.dsl.Value.FromExpr
import io.computenode.cyfra.dsl.binding.{GBinding, GBuffer, GUniform}
Expand All @@ -10,15 +10,14 @@ import izumi.reflect.Tag
import java.nio.ByteBuffer

trait Allocation:
def submitLayout[L <: Layout: LayoutBinding](layout: L): Unit
def submitLayout[L: Layout](layout: L): Unit

extension (buffer: GBinding[?])
def read(bb: ByteBuffer, offset: Int = 0): Unit

def write(bb: ByteBuffer, offset: Int = 0): Unit

extension [Params, EL <: Layout: LayoutBinding, RL <: Layout: LayoutBinding](execution: GExecution[Params, EL, RL])
def execute(params: Params, layout: EL): RL
extension [Params, EL: Layout, RL: Layout](execution: GExecution[Params, EL, RL]) def execute(params: Params, layout: EL): RL

extension (buffers: GBuffer.type)
def apply[T <: Value: {Tag, FromExpr}](length: Int): GBuffer[T]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package io.computenode.cyfra.core
import io.computenode.cyfra.core.Allocation
import io.computenode.cyfra.core.GBufferRegion.MapRegion
import io.computenode.cyfra.core.GProgram.BufferLengthSpec
import io.computenode.cyfra.core.layout.{Layout, LayoutBinding}
import io.computenode.cyfra.core.layout.Layout
import io.computenode.cyfra.dsl.Value
import io.computenode.cyfra.dsl.Value.FromExpr
import io.computenode.cyfra.dsl.binding.GBuffer
Expand All @@ -12,36 +12,36 @@ import izumi.reflect.Tag
import scala.util.chaining.given
import java.nio.ByteBuffer

sealed trait GBufferRegion[ReqAlloc <: Layout: LayoutBinding, ResAlloc <: Layout: LayoutBinding]:
def reqAllocBinding: LayoutBinding[ReqAlloc] = summon[LayoutBinding[ReqAlloc]]
def resAllocBinding: LayoutBinding[ResAlloc] = summon[LayoutBinding[ResAlloc]]
sealed trait GBufferRegion[ReqAlloc: Layout, ResAlloc: Layout]:
def reqAllocLayout: Layout[ReqAlloc] = summon[Layout[ReqAlloc]]
def resAllocLayout: Layout[ResAlloc] = summon[Layout[ResAlloc]]

def map[NewAlloc <: Layout: LayoutBinding](f: Allocation ?=> ResAlloc => NewAlloc): GBufferRegion[ReqAlloc, NewAlloc] =
def map[NewAlloc: Layout](f: Allocation ?=> ResAlloc => NewAlloc): GBufferRegion[ReqAlloc, NewAlloc] =
MapRegion(this, (alloc: Allocation) => (resAlloc: ResAlloc) => f(using alloc)(resAlloc))

object GBufferRegion:

def allocate[Alloc <: Layout: LayoutBinding]: GBufferRegion[Alloc, Alloc] = AllocRegion()
def allocate[Alloc: Layout]: GBufferRegion[Alloc, Alloc] = AllocRegion()

case class AllocRegion[Alloc <: Layout: LayoutBinding]() extends GBufferRegion[Alloc, Alloc]
case class AllocRegion[Alloc: Layout]() extends GBufferRegion[Alloc, Alloc]

case class MapRegion[ReqAlloc <: Layout: LayoutBinding, BodyAlloc <: Layout: LayoutBinding, ResAlloc <: Layout: LayoutBinding](
case class MapRegion[ReqAlloc: Layout, BodyAlloc: Layout, ResAlloc: Layout](
reqRegion: GBufferRegion[ReqAlloc, BodyAlloc],
f: Allocation => BodyAlloc => ResAlloc,
) extends GBufferRegion[ReqAlloc, ResAlloc]

extension [ReqAlloc <: Layout: LayoutBinding, ResAlloc <: Layout: LayoutBinding](region: GBufferRegion[ReqAlloc, ResAlloc])
extension [ReqAlloc: Layout, ResAlloc: Layout](region: GBufferRegion[ReqAlloc, ResAlloc])
def runUnsafe(init: Allocation ?=> ReqAlloc, onDone: Allocation ?=> ResAlloc => Unit)(using cyfraRuntime: CyfraRuntime): Unit =
cyfraRuntime.withAllocation: allocation =>

// noinspection ScalaRedundantCast
val steps: Seq[(Allocation => Layout => Layout, LayoutBinding[Layout])] = Seq.unfold(region: GBufferRegion[?, ?]):
val steps: Seq[(Allocation => Any => Any, Layout[Any])] = Seq.unfold(region: GBufferRegion[?, ?]):
case AllocRegion() => None
case MapRegion(req, f) =>
Some(((f.asInstanceOf[Allocation => Layout => Layout], req.resAllocBinding.asInstanceOf[LayoutBinding[Layout]]), req))
Some(((f.asInstanceOf[Allocation => Any => Any], req.resAllocLayout.asInstanceOf[Layout[Any]]), req))

val initAlloc = init(using allocation).tap(allocation.submitLayout)
val bodyAlloc = steps.foldLeft[Layout](initAlloc): (acc, step) =>
val bodyAlloc = steps.foldLeft[Any](initAlloc): (acc, step) =>
step._1(allocation)(acc).tap(allocation.submitLayout(_)(using step._2))

onDone(using allocation)(bodyAlloc.asInstanceOf[ResAlloc])
Original file line number Diff line number Diff line change
Expand Up @@ -8,58 +8,54 @@ import io.computenode.cyfra.dsl.struct.{GStruct, GStructSchema}
import izumi.reflect.Tag
import GExecution.*

trait GExecution[-Params, ExecLayout <: Layout: LayoutBinding, ResLayout <: Layout: LayoutBinding]:
trait GExecution[-Params, ExecLayout: Layout, ResLayout: Layout]:

def layoutBinding: LayoutBinding[ExecLayout] = summon[LayoutBinding[ExecLayout]]
def resLayoutBinding: LayoutBinding[ResLayout] = summon[LayoutBinding[ResLayout]]
def execLayout: Layout[ExecLayout] = summon[Layout[ExecLayout]]
def resLayout: Layout[ResLayout] = summon[Layout[ResLayout]]

def flatMap[NRL <: Layout: LayoutBinding, NP <: Params](f: ResLayout => GExecution[NP, ExecLayout, NRL]): GExecution[NP, ExecLayout, NRL] =
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: LayoutBinding](f: ResLayout => NRL): GExecution[Params, ExecLayout, NRL] =
def map[NRL: Layout](f: ResLayout => NRL): GExecution[Params, ExecLayout, NRL] =
Map(this, f, identity, identity)

def contramap[NEL <: Layout: LayoutBinding](f: NEL => ExecLayout): GExecution[Params, NEL, ResLayout] =
def contramap[NEL: Layout](f: NEL => ExecLayout): GExecution[Params, NEL, 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]](
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: LayoutBinding]() =
def apply[Params, L: Layout]() =
Pure[Params, L]()

def forParams[Params, EL <: Layout: LayoutBinding, RL <: Layout: LayoutBinding](
f: Params => GExecution[Params, EL, RL],
): GExecution[Params, EL, RL] =
def forParams[Params, EL: Layout, RL: Layout](f: Params => GExecution[Params, EL, RL]): GExecution[Params, EL, RL] =
FlatMap[Params, EL, EL, RL](Pure[Params, EL](), (params: Params, _: EL) => f(params))

case class Pure[Params, L <: Layout: LayoutBinding]() extends GExecution[Params, L, L]
case class Pure[Params, L: Layout]() extends GExecution[Params, L, L]

case class FlatMap[Params, EL <: Layout: LayoutBinding, RL <: Layout: LayoutBinding, NRL <: Layout: LayoutBinding](
execution: GExecution[Params, EL, RL],
f: (Params, RL) => GExecution[Params, EL, NRL],
) extends GExecution[Params, EL, NRL]
case class FlatMap[Params, EL: Layout, RL: Layout, NRL: Layout](execution: GExecution[Params, EL, RL], f: (Params, RL) => GExecution[Params, EL, NRL])
extends GExecution[Params, EL, NRL]

case class Map[P, NP, EL <: Layout: LayoutBinding, NEL <: Layout: LayoutBinding, RL <: Layout: LayoutBinding, NRL <: Layout: LayoutBinding](
case class Map[P, NP, EL: Layout, NEL: Layout, RL: Layout, NRL: Layout](
execution: GExecution[P, EL, RL],
mapResult: RL => NRL,
contramapLayout: NEL => EL,
contramapParams: NP => P,
) extends GExecution[NP, NEL, NRL]:

override def map[NNRL <: Layout: LayoutBinding](f: NRL => NNRL): GExecution[NP, NEL, NNRL] =
override def map[NNRL: Layout](f: NRL => NNRL): GExecution[NP, NEL, NNRL] =
Map(execution, mapResult andThen f, contramapLayout, contramapParams)

override def contramapParams[NNP](f: NNP => NP): GExecution[NNP, NEL, NRL] =
Map(execution, mapResult, contramapLayout, f andThen contramapParams)

override def contramap[NNL <: Layout: LayoutBinding](f: NNL => NEL): GExecution[NP, NNL, NRL] =
override def contramap[NNL: Layout](f: NNL => NEL): GExecution[NP, NNL, NRL] =
Map(execution, mapResult, f andThen contramapLayout, contramapParams)
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package io.computenode.cyfra.core

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

import java.nio.ByteBuffer
Expand All @@ -16,27 +16,27 @@ import java.io.FileInputStream
import java.nio.file.Path
import scala.util.Using

trait GProgram[Params, L <: Layout: {LayoutBinding, LayoutStruct}] extends GExecution[Params, L, L]:
trait GProgram[Params, L: Layout] extends GExecution[Params, L, L]:
val layout: InitProgramLayout => Params => L
val dispatch: (L, Params) => ProgramDispatch
val workgroupSize: WorkDimensions
def layoutStruct: LayoutStruct[L] = summon[LayoutStruct[L]]
def summonLayout: Layout[L] = summon[Layout[L]]

object GProgram:
type WorkDimensions = (Int, Int, Int)

sealed trait ProgramDispatch
case class DynamicDispatch[L <: Layout](buffer: GBinding[?], offset: Int) extends ProgramDispatch
case class DynamicDispatch[L: Layout](buffer: GBinding[?], offset: Int) extends ProgramDispatch
case class StaticDispatch(size: WorkDimensions) extends ProgramDispatch

def apply[Params, L <: Layout: {LayoutBinding, LayoutStruct}](
def apply[Params, L: Layout](
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)

def fromSpirvFile[Params, L <: Layout: {LayoutBinding, LayoutStruct}](
def fromSpirvFile[Params, L: Layout](
layout: InitProgramLayout ?=> Params => L,
dispatch: (L, Params) => ProgramDispatch,
path: Path,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import io.computenode.cyfra.dsl.Value.GBoolean
import io.computenode.cyfra.dsl.gio.GIO
import izumi.reflect.Tag

case class GioProgram[Params, L <: Layout: {LayoutBinding, LayoutStruct}](
case class GioProgram[Params, L: Layout](
body: L => GIO[?],
layout: InitProgramLayout => Params => L,
dispatch: (L, Params) => ProgramDispatch,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package io.computenode.cyfra.core

import io.computenode.cyfra.core.layout.{Layout, LayoutBinding, LayoutStruct}
import io.computenode.cyfra.core.layout.Layout
import io.computenode.cyfra.core.GProgram.{InitProgramLayout, ProgramDispatch, WorkDimensions}
import io.computenode.cyfra.core.SpirvProgram.Operation.ReadWrite
import io.computenode.cyfra.core.SpirvProgram.{Binding, ShaderLayout}
Expand All @@ -21,7 +21,7 @@ import scala.util.Try
import scala.util.Using
import scala.util.chaining.*

case class SpirvProgram[Params, L <: Layout: {LayoutBinding, LayoutStruct}] private (
case class SpirvProgram[Params, L: Layout] private (
layout: InitProgramLayout => Params => L,
dispatch: (L, Params) => ProgramDispatch,
workgroupSize: WorkDimensions,
Expand All @@ -42,7 +42,7 @@ case class SpirvProgram[Params, L <: Layout: {LayoutBinding, LayoutStruct}] priv
.flatMap(BigInt(_).toByteArray)
.toArray,
)
val layout = shaderBindings(summon[LayoutStruct[L]].layoutRef)
val layout = shaderBindings(summon[Layout[L]].layoutRef)
layout.flatten.foreach: binding =>
md.update(binding.binding.tag.toString.getBytes)
md.update(binding.operation.toString.getBytes)
Expand All @@ -58,7 +58,7 @@ object SpirvProgram:
case Write
case ReadWrite

def apply[Params, L <: Layout: {LayoutBinding, LayoutStruct}](
def apply[Params, L: Layout](
layout: InitProgramLayout ?=> Params => L,
dispatch: (L, Params) => ProgramDispatch,
code: ByteBuffer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import io.computenode.cyfra.core.GBufferRegion.*
import io.computenode.cyfra.core.GProgram.StaticDispatch
import io.computenode.cyfra.core.archive.GFunction
import io.computenode.cyfra.core.archive.GFunction.{GFunctionLayout, GFunctionParams}
import io.computenode.cyfra.core.layout.{Layout, LayoutBinding, LayoutStruct}
import io.computenode.cyfra.core.layout.Layout
import io.computenode.cyfra.dsl.Value.*
import io.computenode.cyfra.dsl.binding.{GBuffer, GUniform}
import io.computenode.cyfra.dsl.collections.{GArray, GArray2D}
Expand Down Expand Up @@ -41,6 +41,7 @@ case class GFunction[G <: GStruct[G]: {GStructSchema, Tag}, H <: Value: {Tag, Fr
val out = BufferUtils.createByteBuffer(outTypeSize * input.size)
val uniform = BufferUtils.createByteBuffer(uniformStride)
gCodec.toByteBuffer(uniform, Array(g))
???

GBufferRegion
.allocate[GFunctionLayout[G, H, R]]
Expand All @@ -56,7 +57,7 @@ case class GFunction[G <: GStruct[G]: {GStructSchema, Tag}, H <: Value: {Tag, Fr
object GFunction:
case class GFunctionParams(size: Int)

case class GFunctionLayout[G <: GStruct[G], H <: Value, R <: Value](in: GBuffer[H], out: GBuffer[R], uniform: GUniform[G]) extends Layout
case class GFunctionLayout[G <: GStruct[G], H <: Value, R <: Value](in: GBuffer[H], out: GBuffer[R], uniform: GUniform[G])

def forEachIndex[G <: GStruct[G]: {GStructSchema, Tag}, H <: Value: {Tag, FromExpr}, R <: Value: {Tag, FromExpr}](
fn: (G, Int32, GBuffer[H]) => R,
Expand All @@ -69,14 +70,15 @@ object GFunction:

val inTypeSize = typeStride(Tag.apply[H])
val outTypeSize = typeStride(Tag.apply[R])
???

GFunction(underlying =
GProgram.apply[GFunctionParams, GFunctionLayout[G, H, R]](
layout = (p: GFunctionParams) => GFunctionLayout[G, H, R](in = GBuffer[H](p.size), out = GBuffer[R](p.size), uniform = GUniform[G]()),
dispatch = (l, p) => StaticDispatch((p.size + 255) / 256, 1, 1),
workgroupSize = (256, 1, 1),
)(body),
)
// GFunction(underlying =
// GProgram.apply[GFunctionParams, GFunctionLayout[G, H, R]](
// layout = (p: GFunctionParams) => GFunctionLayout[G, H, R](in = GBuffer[H](p.size), out = GBuffer[R](p.size), uniform = GUniform[G]()),
// dispatch = (l, p) => StaticDispatch((p.size + 255) / 256, 1, 1),
// workgroupSize = (256, 1, 1),
// )(body),
// )

def apply[H <: Value: {Tag, FromExpr}, R <: Value: {Tag, FromExpr}](fn: H => R): GFunction[GStruct.Empty, H, R] =
GFunction.forEachIndex[GStruct.Empty, H, R]((g: GStruct.Empty, index: Int32, a: GBuffer[H]) => fn(a.read(index)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ 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]
case class BufferRef[T <: Value: {Tag, FromExpr}](layoutOffset: Int) extends GBuffer[T]
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ import io.computenode.cyfra.dsl.struct.{GStruct, GStructSchema}
import izumi.reflect.Tag
import izumi.reflect.macrortti.LightTypeTag

case class UniformRef[T <: GStruct[?]: {Tag, FromExpr, GStructSchema}](layoutOffset: Int, valueTag: Tag[T]) extends GUniform[T]
case class UniformRef[T <: GStruct[?]: {Tag, FromExpr, GStructSchema}](layoutOffset: Int) extends GUniform[T]
Loading