Skip to content

Commit efe72ea

Browse files
authored
Change Layout from trait to type class (#71)
1 parent 84e1123 commit efe72ea

File tree

21 files changed

+259
-256
lines changed

21 files changed

+259
-256
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,4 @@ out
2626
hs_err_pid*.log
2727
.bsp
2828
metals.sbt
29+
.scala-build

cyfra-core/src/main/scala/io/computenode/cyfra/core/Allocation.scala

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package io.computenode.cyfra.core
22

3-
import io.computenode.cyfra.core.layout.{Layout, LayoutBinding}
3+
import io.computenode.cyfra.core.layout.Layout
44
import io.computenode.cyfra.dsl.Value
55
import io.computenode.cyfra.dsl.Value.FromExpr
66
import io.computenode.cyfra.dsl.binding.{GBinding, GBuffer, GUniform}
@@ -10,15 +10,14 @@ import izumi.reflect.Tag
1010
import java.nio.ByteBuffer
1111

1212
trait Allocation:
13-
def submitLayout[L <: Layout: LayoutBinding](layout: L): Unit
13+
def submitLayout[L: Layout](layout: L): Unit
1414

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

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

20-
extension [Params, EL <: Layout: LayoutBinding, RL <: Layout: LayoutBinding](execution: GExecution[Params, EL, RL])
21-
def execute(params: Params, layout: EL): RL
20+
extension [Params, EL: Layout, RL: Layout](execution: GExecution[Params, EL, RL]) def execute(params: Params, layout: EL): RL
2221

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

cyfra-core/src/main/scala/io/computenode/cyfra/core/GBufferRegion.scala

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package io.computenode.cyfra.core
33
import io.computenode.cyfra.core.Allocation
44
import io.computenode.cyfra.core.GBufferRegion.MapRegion
55
import io.computenode.cyfra.core.GProgram.BufferLengthSpec
6-
import io.computenode.cyfra.core.layout.{Layout, LayoutBinding}
6+
import io.computenode.cyfra.core.layout.Layout
77
import io.computenode.cyfra.dsl.Value
88
import io.computenode.cyfra.dsl.Value.FromExpr
99
import io.computenode.cyfra.dsl.binding.GBuffer
@@ -12,36 +12,36 @@ import izumi.reflect.Tag
1212
import scala.util.chaining.given
1313
import java.nio.ByteBuffer
1414

15-
sealed trait GBufferRegion[ReqAlloc <: Layout: LayoutBinding, ResAlloc <: Layout: LayoutBinding]:
16-
def reqAllocBinding: LayoutBinding[ReqAlloc] = summon[LayoutBinding[ReqAlloc]]
17-
def resAllocBinding: LayoutBinding[ResAlloc] = summon[LayoutBinding[ResAlloc]]
15+
sealed trait GBufferRegion[ReqAlloc: Layout, ResAlloc: Layout]:
16+
def reqAllocLayout: Layout[ReqAlloc] = Layout[ReqAlloc]
17+
def resAllocLayout: Layout[ResAlloc] = Layout[ResAlloc]
1818

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

2222
object GBufferRegion:
2323

24-
def allocate[Alloc <: Layout: LayoutBinding]: GBufferRegion[Alloc, Alloc] = AllocRegion()
24+
def allocate[Alloc: Layout]: GBufferRegion[Alloc, Alloc] = AllocRegion()
2525

26-
case class AllocRegion[Alloc <: Layout: LayoutBinding]() extends GBufferRegion[Alloc, Alloc]
26+
case class AllocRegion[Alloc: Layout]() extends GBufferRegion[Alloc, Alloc]
2727

28-
case class MapRegion[ReqAlloc <: Layout: LayoutBinding, BodyAlloc <: Layout: LayoutBinding, ResAlloc <: Layout: LayoutBinding](
28+
case class MapRegion[ReqAlloc: Layout, BodyAlloc: Layout, ResAlloc: Layout](
2929
reqRegion: GBufferRegion[ReqAlloc, BodyAlloc],
3030
f: Allocation => BodyAlloc => ResAlloc,
3131
) extends GBufferRegion[ReqAlloc, ResAlloc]
3232

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

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

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

4747
onDone(using allocation)(bodyAlloc.asInstanceOf[ResAlloc])

cyfra-core/src/main/scala/io/computenode/cyfra/core/GExecution.scala

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,58 +8,54 @@ import io.computenode.cyfra.dsl.struct.{GStruct, GStructSchema}
88
import izumi.reflect.Tag
99
import GExecution.*
1010

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

13-
def layoutBinding: LayoutBinding[ExecLayout] = summon[LayoutBinding[ExecLayout]]
14-
def resLayoutBinding: LayoutBinding[ResLayout] = summon[LayoutBinding[ResLayout]]
13+
def execLayout: Layout[ExecLayout] = Layout[ExecLayout]
14+
def resLayout: Layout[ResLayout] = Layout[ResLayout]
1515

16-
def flatMap[NRL <: Layout: LayoutBinding, NP <: Params](f: ResLayout => GExecution[NP, ExecLayout, NRL]): GExecution[NP, ExecLayout, NRL] =
16+
def flatMap[NRL: Layout, NP <: Params](f: ResLayout => GExecution[NP, ExecLayout, NRL]): GExecution[NP, ExecLayout, NRL] =
1717
FlatMap(this, (p, r) => f(r))
1818

19-
def map[NRL <: Layout: LayoutBinding](f: ResLayout => NRL): GExecution[Params, ExecLayout, NRL] =
19+
def map[NRL: Layout](f: ResLayout => NRL): GExecution[Params, ExecLayout, NRL] =
2020
Map(this, f, identity, identity)
2121

22-
def contramap[NEL <: Layout: LayoutBinding](f: NEL => ExecLayout): GExecution[Params, NEL, ResLayout] =
22+
def contramap[NEL: Layout](f: NEL => ExecLayout): GExecution[Params, NEL, ResLayout] =
2323
Map(this, identity, f, identity)
2424

2525
def contramapParams[NP](f: NP => Params): GExecution[NP, ExecLayout, ResLayout] =
2626
Map(this, identity, identity, f)
2727

28-
def addProgram[ProgramParams, PP <: Params, ProgramLayout <: Layout, P <: GProgram[ProgramParams, ProgramLayout]](
28+
def addProgram[ProgramParams, PP <: Params, ProgramLayout: Layout, P <: GProgram[ProgramParams, ProgramLayout]](
2929
program: P,
3030
)(mapParams: PP => ProgramParams, mapLayout: ExecLayout => ProgramLayout): GExecution[PP, ExecLayout, ResLayout] =
3131
val adapted = program.contramapParams(mapParams).contramap(mapLayout)
3232
flatMap(r => adapted.map(_ => r))
3333

3434
object GExecution:
3535

36-
def apply[Params, L <: Layout: LayoutBinding]() =
36+
def apply[Params, L: Layout]() =
3737
Pure[Params, L]()
3838

39-
def forParams[Params, EL <: Layout: LayoutBinding, RL <: Layout: LayoutBinding](
40-
f: Params => GExecution[Params, EL, RL],
41-
): GExecution[Params, EL, RL] =
39+
def forParams[Params, EL: Layout, RL: Layout](f: Params => GExecution[Params, EL, RL]): GExecution[Params, EL, RL] =
4240
FlatMap[Params, EL, EL, RL](Pure[Params, EL](), (params: Params, _: EL) => f(params))
4341

44-
case class Pure[Params, L <: Layout: LayoutBinding]() extends GExecution[Params, L, L]
42+
case class Pure[Params, L: Layout]() extends GExecution[Params, L, L]
4543

46-
case class FlatMap[Params, EL <: Layout: LayoutBinding, RL <: Layout: LayoutBinding, NRL <: Layout: LayoutBinding](
47-
execution: GExecution[Params, EL, RL],
48-
f: (Params, RL) => GExecution[Params, EL, NRL],
49-
) extends GExecution[Params, EL, NRL]
44+
case class FlatMap[Params, EL: Layout, RL: Layout, NRL: Layout](execution: GExecution[Params, EL, RL], f: (Params, RL) => GExecution[Params, EL, NRL])
45+
extends GExecution[Params, EL, NRL]
5046

51-
case class Map[P, NP, EL <: Layout: LayoutBinding, NEL <: Layout: LayoutBinding, RL <: Layout: LayoutBinding, NRL <: Layout: LayoutBinding](
47+
case class Map[P, NP, EL: Layout, NEL: Layout, RL: Layout, NRL: Layout](
5248
execution: GExecution[P, EL, RL],
5349
mapResult: RL => NRL,
5450
contramapLayout: NEL => EL,
5551
contramapParams: NP => P,
5652
) extends GExecution[NP, NEL, NRL]:
5753

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

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

64-
override def contramap[NNL <: Layout: LayoutBinding](f: NNL => NEL): GExecution[NP, NNL, NRL] =
60+
override def contramap[NNL: Layout](f: NNL => NEL): GExecution[NP, NNL, NRL] =
6561
Map(execution, mapResult, f andThen contramapLayout, contramapParams)

cyfra-core/src/main/scala/io/computenode/cyfra/core/GProgram.scala

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package io.computenode.cyfra.core
22

3-
import io.computenode.cyfra.core.layout.{Layout, LayoutBinding, LayoutStruct}
3+
import io.computenode.cyfra.core.layout.Layout
44
import io.computenode.cyfra.dsl.gio.GIO
55

66
import java.nio.ByteBuffer
@@ -16,27 +16,27 @@ import java.io.FileInputStream
1616
import java.nio.file.Path
1717
import scala.util.Using
1818

19-
trait GProgram[Params, L <: Layout: {LayoutBinding, LayoutStruct}] extends GExecution[Params, L, L]:
19+
trait GProgram[Params, L: Layout] extends GExecution[Params, L, L]:
2020
val layout: InitProgramLayout => Params => L
2121
val dispatch: (L, Params) => ProgramDispatch
2222
val workgroupSize: WorkDimensions
23-
def layoutStruct: LayoutStruct[L] = summon[LayoutStruct[L]]
23+
def summonLayout: Layout[L] = Layout[L]
2424

2525
object GProgram:
2626
type WorkDimensions = (Int, Int, Int)
2727

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

32-
def apply[Params, L <: Layout: {LayoutBinding, LayoutStruct}](
32+
def apply[Params, L: Layout](
3333
layout: InitProgramLayout ?=> Params => L,
3434
dispatch: (L, Params) => ProgramDispatch,
3535
workgroupSize: WorkDimensions = (128, 1, 1),
3636
)(body: L => GIO[?]): GProgram[Params, L] =
3737
new GioProgram[Params, L](body, s => layout(using s), dispatch, workgroupSize)
3838

39-
def fromSpirvFile[Params, L <: Layout: {LayoutBinding, LayoutStruct}](
39+
def fromSpirvFile[Params, L: Layout](
4040
layout: InitProgramLayout ?=> Params => L,
4141
dispatch: (L, Params) => ProgramDispatch,
4242
path: Path,

cyfra-core/src/main/scala/io/computenode/cyfra/core/GioProgram.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import io.computenode.cyfra.dsl.Value.GBoolean
66
import io.computenode.cyfra.dsl.gio.GIO
77
import izumi.reflect.Tag
88

9-
case class GioProgram[Params, L <: Layout: {LayoutBinding, LayoutStruct}](
9+
case class GioProgram[Params, L: Layout](
1010
body: L => GIO[?],
1111
layout: InitProgramLayout => Params => L,
1212
dispatch: (L, Params) => ProgramDispatch,

cyfra-core/src/main/scala/io/computenode/cyfra/core/SpirvProgram.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package io.computenode.cyfra.core
22

3-
import io.computenode.cyfra.core.layout.{Layout, LayoutBinding, LayoutStruct}
3+
import io.computenode.cyfra.core.layout.Layout
44
import io.computenode.cyfra.core.GProgram.{InitProgramLayout, ProgramDispatch, WorkDimensions}
55
import io.computenode.cyfra.core.SpirvProgram.Operation.ReadWrite
66
import io.computenode.cyfra.core.SpirvProgram.{Binding, ShaderLayout}
@@ -21,7 +21,7 @@ import scala.util.Try
2121
import scala.util.Using
2222
import scala.util.chaining.*
2323

24-
case class SpirvProgram[Params, L <: Layout: {LayoutBinding, LayoutStruct}] private (
24+
case class SpirvProgram[Params, L: Layout] private (
2525
layout: InitProgramLayout => Params => L,
2626
dispatch: (L, Params) => ProgramDispatch,
2727
workgroupSize: WorkDimensions,
@@ -42,7 +42,7 @@ case class SpirvProgram[Params, L <: Layout: {LayoutBinding, LayoutStruct}] priv
4242
.flatMap(BigInt(_).toByteArray)
4343
.toArray,
4444
)
45-
val layout = shaderBindings(summon[LayoutStruct[L]].layoutRef)
45+
val layout = shaderBindings(Layout[L].layoutRef)
4646
layout.flatten.foreach: binding =>
4747
md.update(binding.binding.tag.toString.getBytes)
4848
md.update(binding.operation.toString.getBytes)
@@ -58,7 +58,7 @@ object SpirvProgram:
5858
case Write
5959
case ReadWrite
6060

61-
def apply[Params, L <: Layout: {LayoutBinding, LayoutStruct}](
61+
def apply[Params, L: Layout](
6262
layout: InitProgramLayout ?=> Params => L,
6363
dispatch: (L, Params) => ProgramDispatch,
6464
code: ByteBuffer,

cyfra-core/src/main/scala/io/computenode/cyfra/core/archive/GFunction.scala

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import io.computenode.cyfra.core.GBufferRegion.*
55
import io.computenode.cyfra.core.GProgram.StaticDispatch
66
import io.computenode.cyfra.core.archive.GFunction
77
import io.computenode.cyfra.core.archive.GFunction.{GFunctionLayout, GFunctionParams}
8-
import io.computenode.cyfra.core.layout.{Layout, LayoutBinding, LayoutStruct}
8+
import io.computenode.cyfra.core.layout.Layout
99
import io.computenode.cyfra.dsl.Value.*
1010
import io.computenode.cyfra.dsl.binding.{GBuffer, GUniform}
1111
import io.computenode.cyfra.dsl.collections.{GArray, GArray2D}
@@ -29,6 +29,12 @@ case class GFunction[G <: GStruct[G]: {GStructSchema, Tag}, H <: Value: {Tag, Fr
2929
hCodec: GCodec[H, HS],
3030
rCodec: GCodec[R, RS],
3131
runtime: CyfraRuntime,
32+
gSchema: GStructSchema[G],
33+
gTag: Tag[G],
34+
hTag: Tag[H],
35+
hFromExpr: FromExpr[H],
36+
rTag: Tag[R],
37+
rFromExpr: FromExpr[R],
3238
): Array[RS] =
3339

3440
val inTypeSize = typeStride(Tag.apply[H])
@@ -41,6 +47,7 @@ case class GFunction[G <: GStruct[G]: {GStructSchema, Tag}, H <: Value: {Tag, Fr
4147
val out = BufferUtils.createByteBuffer(outTypeSize * input.size)
4248
val uniform = BufferUtils.createByteBuffer(uniformStride)
4349
gCodec.toByteBuffer(uniform, Array(g))
50+
???
4451

4552
GBufferRegion
4653
.allocate[GFunctionLayout[G, H, R]]
@@ -56,7 +63,7 @@ case class GFunction[G <: GStruct[G]: {GStructSchema, Tag}, H <: Value: {Tag, Fr
5663
object GFunction:
5764
case class GFunctionParams(size: Int)
5865

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

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

7077
val inTypeSize = typeStride(Tag.apply[H])
7178
val outTypeSize = typeStride(Tag.apply[R])
79+
???
7280

73-
GFunction(underlying =
74-
GProgram.apply[GFunctionParams, GFunctionLayout[G, H, R]](
75-
layout = (p: GFunctionParams) => GFunctionLayout[G, H, R](in = GBuffer[H](p.size), out = GBuffer[R](p.size), uniform = GUniform[G]()),
76-
dispatch = (l, p) => StaticDispatch((p.size + 255) / 256, 1, 1),
77-
workgroupSize = (256, 1, 1),
78-
)(body),
79-
)
81+
// GFunction(underlying =
82+
// GProgram.apply[GFunctionParams, GFunctionLayout[G, H, R]](
83+
// layout = (p: GFunctionParams) => GFunctionLayout[G, H, R](in = GBuffer[H](p.size), out = GBuffer[R](p.size), uniform = GUniform[G]()),
84+
// dispatch = (l, p) => StaticDispatch((p.size + 255) / 256, 1, 1),
85+
// workgroupSize = (256, 1, 1),
86+
// )(body),
87+
// )
8088

8189
def apply[H <: Value: {Tag, FromExpr}, R <: Value: {Tag, FromExpr}](fn: H => R): GFunction[GStruct.Empty, H, R] =
8290
GFunction.forEachIndex[GStruct.Empty, H, R]((g: GStruct.Empty, index: Int32, a: GBuffer[H]) => fn(a.read(index)))

cyfra-core/src/main/scala/io/computenode/cyfra/core/binding/BufferRef.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ import io.computenode.cyfra.dsl.binding.GBuffer
66
import izumi.reflect.Tag
77
import izumi.reflect.macrortti.LightTypeTag
88

9-
case class BufferRef[T <: Value: {Tag, FromExpr}](layoutOffset: Int, valueTag: Tag[T]) extends GBuffer[T]
9+
case class BufferRef[T <: Value: {Tag, FromExpr}](layoutOffset: Int) extends GBuffer[T]

cyfra-core/src/main/scala/io/computenode/cyfra/core/binding/UniformRef.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@ import io.computenode.cyfra.dsl.struct.{GStruct, GStructSchema}
77
import izumi.reflect.Tag
88
import izumi.reflect.macrortti.LightTypeTag
99

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

0 commit comments

Comments
 (0)