Skip to content

Commit

Permalink
implemented PooledGeometry for ManagedPool: SymbolDict alternative to…
Browse files Browse the repository at this point in the history
… Map (avoid Symbol boxing in comparer)
  • Loading branch information
luithefirst committed Sep 24, 2024
1 parent 1975927 commit 279f77c
Showing 1 changed file with 99 additions and 6 deletions.
105 changes: 99 additions & 6 deletions src/Aardvark.SceneGraph/Pools/ManagedPool.fs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,16 @@ type AdaptiveGeometry =
InstanceAttributes : Map<Symbol, IAdaptiveValue>
}

[<ReferenceEquality; NoComparison>]
type PooledGeometry =
{
FaceVertexCount : int
VertexCount : int
Indices : voption<BufferView>
VertexAttributes : SymbolDict<BufferView>
InstanceAttributes : SymbolDict<IAdaptiveValue>
}

type GeometrySignature =
{
IndexType : Type
Expand All @@ -43,7 +53,7 @@ module GeometrySignature =
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module AdaptiveGeometry =

let ofIndexedGeometry (instanceAttributes : list<Symbol * IAdaptiveValue>) (ig : IndexedGeometry) =
let ofIndexedGeometry (instanceAttributes : list<Symbol * IAdaptiveValue>) (ig : IndexedGeometry) : AdaptiveGeometry =
let anyAtt = (ig.IndexedAttributes |> Seq.head).Value

let faceVertexCount, index =
Expand Down Expand Up @@ -150,9 +160,9 @@ and ManagedPool(runtime : IRuntime, signature : GeometrySignature,

static let zero : byte[] = Array.zeroCreate 4096

let indexManager = LayoutManager<Option<BufferView> * int>()
let vertexManager = LayoutManager<Map<Symbol, BufferView>>()
let instanceManager = LayoutManager<Map<Symbol, IAdaptiveValue>>()
let indexManager = LayoutManager<struct(obj * int)>()
let vertexManager = LayoutManager<obj>()
let instanceManager = LayoutManager<obj>()

let toDict f = Map.toSeq >> Seq.map f >> SymDict.ofSeq

Expand All @@ -177,8 +187,8 @@ and ManagedPool(runtime : IRuntime, signature : GeometrySignature,
k, createManagedBuffer t usage (instanceBufferStorage k)
)

let vertexBufferTypes = Map.toArray signature.VertexAttributeTypes
let uniformTypes = Map.toArray signature.InstanceAttributeTypes
let vertexBufferTypes = Map.toArray signature.VertexAttributeTypes |> Array.map (fun (a,b) -> struct(a, b))
let uniformTypes = Map.toArray signature.InstanceAttributeTypes |> Array.map (fun (a,b) -> struct(a, b))

let drawCalls = HashSet<ManagedDrawCall>()

Expand Down Expand Up @@ -243,6 +253,11 @@ and ManagedPool(runtime : IRuntime, signature : GeometrySignature,
member x.Add(geometry : AdaptiveGeometry) =
x.Add(geometry, 0, geometry.FaceVertexCount)

///<summary>Adds the given geometry to the pool and returns a managed draw call.</summary>
///<param name="geometry">The geometry to add.</param>
member x.Add(geometry : PooledGeometry) =
x.Add(geometry, 0, geometry.FaceVertexCount)

///<summary>Adds the given geometry to the pool and returns a managed draw call.</summary>
///<param name="geometry">The geometry to add.</param>
///<param name="indexOffset">An offset added to the FirstIndex field of the resulting draw call.</param>
Expand Down Expand Up @@ -321,6 +336,84 @@ and ManagedPool(runtime : IRuntime, signature : GeometrySignature,
mdc
)

///<summary>Adds the given geometry to the pool and returns a managed draw call.</summary>
///<param name="geometry">The geometry to add.</param>
///<param name="indexOffset">An offset added to the FirstIndex field of the resulting draw call.</param>
///<param name="faceVertexCount">The face vertex count of the resulting draw call.</param>
member x.Add(geometry : PooledGeometry, indexOffset : int, faceVertexCount : int) =
let faceVertexCount = min faceVertexCount geometry.FaceVertexCount

if faceVertexCount <= 0 then
ManagedDrawCall.Empty
else
lock x (fun () ->
let ds = List()
let fvc = geometry.FaceVertexCount
let vertexCount = geometry.VertexCount

let vertexPtr = vertexManager.Alloc(geometry.VertexAttributes, vertexCount)
let vertexRange = Range1l(int64 vertexPtr.Offset, int64 vertexPtr.Offset + int64 vertexCount - 1L)
for (k,_) in vertexBufferTypes do
let target = vertexBuffers.[k]
match geometry.VertexAttributes.TryGetValue k with
| (true, v) ->
try
target.Add(v, vertexRange) |> ds.Add
with
| :? Aardvark.Base.PrimitiveValueConverter.InvalidConversionException as exn ->
failf "cannot convert vertex attribute '%A' from %A to %A" k exn.Source exn.Target

| _ ->
target.Set(zero, vertexRange)

let instancePtr = instanceManager.Alloc(geometry.InstanceAttributes, 1)
let instanceIndex = int instancePtr.Offset
for (k,_) in uniformTypes do
let target = instanceBuffers.[k]
match geometry.InstanceAttributes.TryGetValue k with
| (true, v) ->
try
target.Add(v, instanceIndex) |> ds.Add
with
| :? Aardvark.Base.PrimitiveValueConverter.InvalidConversionException as exn ->
failf "cannot convert instance attribute '%A' from %A to %A" k exn.Source exn.Target

| _ ->
target.Set(zero, Range1l(int64 instanceIndex, int64 instanceIndex))

let isNew, indexPtr = indexManager.TryAlloc((geometry.Indices, fvc), fvc)
let indexRange = Range1l(int64 indexPtr.Offset, int64 indexPtr.Offset + int64 fvc - 1L)
match geometry.Indices with
| ValueSome v -> indexBuffer.Add(v, indexRange) |> ds.Add
| ValueNone ->
if isNew then
let conv = Aardvark.Base.PrimitiveValueConverter.getArrayConverter typeof<int> signature.IndexType
let data = Array.init fvc id |> conv
indexBuffer.Set(data, indexRange)

let resources =
{
Pool = x
IndexPtr = indexPtr
VertexPtr = vertexPtr
InstancePtr = instancePtr
Disposables = ds
}

let call =
DrawCallInfo(
FaceVertexCount = faceVertexCount,
FirstIndex = int indexPtr.Offset + indexOffset,
FirstInstance = int instancePtr.Offset,
InstanceCount = 1,
BaseVertex = int vertexPtr.Offset
)

let mdc = new ManagedDrawCall(call, resources)
drawCalls.Add(mdc) |> ignore
mdc
)

member x.VertexAttributes =
{ new IAttributeProvider with
member x.Dispose() = ()
Expand Down

0 comments on commit 279f77c

Please sign in to comment.