diff --git a/src/Aardvark.SceneGraph/Pools/ManagedPool.fs b/src/Aardvark.SceneGraph/Pools/ManagedPool.fs index 121113fa..85121d38 100644 --- a/src/Aardvark.SceneGraph/Pools/ManagedPool.fs +++ b/src/Aardvark.SceneGraph/Pools/ManagedPool.fs @@ -24,6 +24,16 @@ type AdaptiveGeometry = InstanceAttributes : Map } +[] +type PooledGeometry = + { + FaceVertexCount : int + VertexCount : int + Indices : voption + VertexAttributes : SymbolDict + InstanceAttributes : SymbolDict + } + type GeometrySignature = { IndexType : Type @@ -43,7 +53,7 @@ module GeometrySignature = [] module AdaptiveGeometry = - let ofIndexedGeometry (instanceAttributes : list) (ig : IndexedGeometry) = + let ofIndexedGeometry (instanceAttributes : list) (ig : IndexedGeometry) : AdaptiveGeometry = let anyAtt = (ig.IndexedAttributes |> Seq.head).Value let faceVertexCount, index = @@ -150,9 +160,9 @@ and ManagedPool(runtime : IRuntime, signature : GeometrySignature, static let zero : byte[] = Array.zeroCreate 4096 - let indexManager = LayoutManager * int>() - let vertexManager = LayoutManager>() - let instanceManager = LayoutManager>() + let indexManager = LayoutManager() + let vertexManager = LayoutManager() + let instanceManager = LayoutManager() let toDict f = Map.toSeq >> Seq.map f >> SymDict.ofSeq @@ -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() @@ -243,6 +253,11 @@ and ManagedPool(runtime : IRuntime, signature : GeometrySignature, member x.Add(geometry : AdaptiveGeometry) = x.Add(geometry, 0, geometry.FaceVertexCount) + ///Adds the given geometry to the pool and returns a managed draw call. + ///The geometry to add. + member x.Add(geometry : PooledGeometry) = + x.Add(geometry, 0, geometry.FaceVertexCount) + ///Adds the given geometry to the pool and returns a managed draw call. ///The geometry to add. ///An offset added to the FirstIndex field of the resulting draw call. @@ -321,6 +336,84 @@ and ManagedPool(runtime : IRuntime, signature : GeometrySignature, mdc ) + ///Adds the given geometry to the pool and returns a managed draw call. + ///The geometry to add. + ///An offset added to the FirstIndex field of the resulting draw call. + ///The face vertex count of the resulting draw call. + 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 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() = ()