Skip to content

Commit c3d5f91

Browse files
committed
[Vulkan] Port memory management to VMA
Sparse image support was not ported as it seems to be unused.
1 parent 411e3f8 commit c3d5f91

39 files changed

+2606
-3424
lines changed

src/Aardvark.Rendering.Vulkan.Wrapper/VMA.fs

Lines changed: 130 additions & 168 deletions
Large diffs are not rendered by default.

src/Aardvark.Rendering.Vulkan.Wrapper/VMA.fsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -450,19 +450,17 @@ module Writer =
450450
blk $"type {name} =" (fun _ ->
451451
blk "{" (fun _ ->
452452
for f in fields do
453-
fn $"{f.name} : {Type.fsharpName f.count f.typ}"
453+
fn $"mutable {f.name} : {Type.fsharpName f.count f.typ}"
454454
)
455455
fn "}"
456456
ln()
457-
blk $"static let empty : {name} =" (fun _ ->
457+
blk $"static member Empty : {name} =" (fun _ ->
458458
blk "{" (fun _ ->
459459
for f in fields do
460460
fn $"{f.name} = Unchecked.defaultof<{Type.fsharpName f.count f.typ}>"
461461
)
462462
fn "}"
463463
)
464-
ln()
465-
fn $"static member Empty = empty"
466464
)
467465

468466
| Array (typ, count) ->

src/Aardvark.Rendering.Vulkan/Aardvark.Rendering.Vulkan.fsproj

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@
3838
<Compile Include="Core\Platform\DebugReport.fs" />
3939
<Compile Include="Core\Interfaces.fs" />
4040
<Compile Include="Core\Memory\ExternalMemory.fs" />
41-
<Compile Include="Core\Memory\Memory.fs" />
41+
<Compile Include="Core\Memory\ExternalMemoryPool.fs" />
42+
<Compile Include="Core\Memory\DevicePtr.fs" />
43+
<Compile Include="Core\Memory\MemoryAllocator.fs" />
4244
<Compile Include="Core\Synchronization\Fence.fs" />
4345
<Compile Include="Core\Synchronization\Semaphore.fs" />
4446
<Compile Include="Core\Synchronization\Event.fs" />

src/Aardvark.Rendering.Vulkan/Core/Common/Features.fs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
namespace Aardvark.Rendering.Vulkan
22

3+
open EXTMemoryPriority
4+
35
type MemoryFeatures =
46
{
57
/// Specifies that accesses to buffers are bounds-checked against the range of the buffer descriptor
@@ -36,6 +38,9 @@ type MemoryFeatures =
3638
/// Specifies whether protected memory is supported.
3739
ProtectedMemory: bool
3840

41+
/// Specifies whether the implementation supports memory priorities specified at memory allocation time via VkMemoryPriorityAllocateInfoEXT.
42+
MemoryPriority: bool
43+
3944
/// Specifies whether the implementation supports accessing buffer memory in shaders as storage buffers via an address queried from vkGetBufferDeviceAddress.
4045
BufferDeviceAddress : bool
4146

@@ -60,6 +65,7 @@ type MemoryFeatures =
6065
l.line "sparse 3D images: %A" x.SparseResidencyImage3D
6166
l.line "sparse aliased data: %A" x.SparseResidencyAliased
6267
l.line "protected memory: %A" x.ProtectedMemory
68+
l.line "memory priority: %A" x.MemoryPriority
6369
l.section "buffer device address: " (fun () ->
6470
l.line "supported: %A" x.BufferDeviceAddress
6571
l.line "capture & replay: %A" x.BufferDeviceAddressCaptureReplay
@@ -544,6 +550,11 @@ module DeviceFeatures =
544550
toVkBool features.Memory.ProtectedMemory
545551
)
546552

553+
let memp =
554+
VkPhysicalDeviceMemoryPriorityFeaturesEXT(
555+
toVkBool features.Memory.MemoryPriority
556+
)
557+
547558
let ycbcr =
548559
VkPhysicalDeviceSamplerYcbcrConversionFeatures(
549560
toVkBool features.Samplers.YcbcrConversion
@@ -685,6 +696,7 @@ module DeviceFeatures =
685696

686697
VkStructChain.empty()
687698
|> VkStructChain.add mem
699+
|> if not memp.IsEmpty then VkStructChain.add memp else id
688700
|> VkStructChain.add ycbcr
689701
|> VkStructChain.add s16
690702
|> VkStructChain.add vp
@@ -697,6 +709,7 @@ module DeviceFeatures =
697709
|> VkStructChain.add features
698710

699711
let create (protectedMemoryFeatures : VkPhysicalDeviceProtectedMemoryFeatures)
712+
(memoryPriorityFeatures : VkPhysicalDeviceMemoryPriorityFeaturesEXT)
700713
(samplerYcbcrConversionFeatures : VkPhysicalDeviceSamplerYcbcrConversionFeatures)
701714
(storage16BitFeatures : VkPhysicalDevice16BitStorageFeatures)
702715
(variablePointerFeatures : VkPhysicalDeviceVariablePointersFeatures)
@@ -722,6 +735,7 @@ module DeviceFeatures =
722735
SparseResidency16Samples = toBool features.sparseResidency16Samples
723736
SparseResidencyAliased = toBool features.sparseResidencyAliased
724737
ProtectedMemory = toBool protectedMemoryFeatures.protectedMemory
738+
MemoryPriority = toBool memoryPriorityFeatures.memoryPriority
725739
BufferDeviceAddress = toBool bufferDeviceAddressFeatures.bufferDeviceAddress
726740
BufferDeviceAddressCaptureReplay = toBool bufferDeviceAddressFeatures.bufferDeviceAddressCaptureReplay
727741
BufferDeviceAddressMultiDevice = toBool bufferDeviceAddressFeatures.bufferDeviceAddressMultiDevice

src/Aardvark.Rendering.Vulkan/Core/Common/Info.fs

Lines changed: 4 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -175,48 +175,26 @@ module QueueFamilyInfo =
175175
[<Flags>]
176176
type MemoryHeapFlags =
177177
| None = 0
178-
| DeviceLocalBit = 0x00000001
178+
| DeviceLocal = 1
179179

180180
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
181181
module MemoryHeapFlags =
182-
let inline deviceLocal (f : MemoryHeapFlags) = f &&& MemoryHeapFlags.DeviceLocalBit <> MemoryHeapFlags.None
182+
let inline deviceLocal (f : MemoryHeapFlags) = f &&& MemoryHeapFlags.DeviceLocal <> MemoryHeapFlags.None
183183

184184

185185
type MemoryHeapInfo(index : int, totalSize : int64, flags : MemoryHeapFlags) =
186-
let mutable allocated = 0L
187-
188-
member x.TryAdd(size : int64) =
189-
Interlocked.Change(&allocated, fun v ->
190-
if v + size > totalSize then (v, false)
191-
else (v + size, true)
192-
)
193-
194-
member inline x.TryAdd(size : VkDeviceSize) = x.TryAdd (int64 size)
195-
member inline x.TryAdd(size : Mem) = x.TryAdd size.Bytes
196-
197-
member x.Remove(size : int64) = Interlocked.Add(&allocated, -size) |> ignore
198-
member inline x.Remove(size : VkDeviceSize) = x.Remove (int64 size)
199-
member inline x.Remove(size : Mem) = x.Remove size.Bytes
200-
201186
member x.Index = index
202187
member x.Capacity = Mem totalSize
203-
member x.Allocated = Mem allocated
204-
member x.Available = Mem (totalSize - allocated)
205188
member x.Flags = flags
206189

207190
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
208191
module MemoryHeapInfo =
209192
let inline index (info : MemoryHeapInfo) = info.Index
210-
let inline capacity (info : MemoryHeapInfo) = info.Capacity
211-
let inline available (info : MemoryHeapInfo) = info.Available
212-
let inline allocated (info : MemoryHeapInfo) = info.Allocated
193+
let inline capacity (info : MemoryHeapInfo) = info.Capacity
213194
let inline flags (info : MemoryHeapInfo) = info.Flags
214195

215196

216197

217-
218-
219-
220198
// =======================================================================
221199
// Memory Info
222200
// =======================================================================
@@ -239,23 +217,6 @@ module MemoryFlags =
239217
let inline lazilyAllocated (f : MemoryFlags) = (f &&& MemoryFlags.LazilyAllocated) <> MemoryFlags.None
240218

241219

242-
let internal deviceScore (f : MemoryFlags) =
243-
if deviceLocal f then
244-
1
245-
else
246-
0
247-
248-
let internal hostScore (f : MemoryFlags) =
249-
if hostVisible f then
250-
let mutable res = 8
251-
if hostCoherent f then res <- res + 4
252-
if hostCached f then res <- res + 2
253-
if lazilyAllocated f then res <- res + 1
254-
res
255-
else
256-
0
257-
258-
259220
type MemoryInfo =
260221
{
261222
index : int
@@ -267,10 +228,4 @@ type MemoryInfo =
267228
module MemoryInfo =
268229
let inline index (info : MemoryInfo) = info.index
269230
let inline heap (info : MemoryInfo) = info.heap
270-
let inline flags (info : MemoryInfo) = info.flags
271-
272-
let internal deviceScore (info : MemoryInfo) =
273-
(MemoryFlags.deviceScore info.flags, info.heap.Capacity.Bytes)
274-
275-
let internal hostScore (info : MemoryInfo) =
276-
(MemoryFlags.hostScore info.flags, info.heap.Capacity.Bytes)
231+
let inline flags (info : MemoryInfo) = info.flags

src/Aardvark.Rendering.Vulkan/Core/Device/CopyEngine.fs

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ open System.Threading
1212
type CopyCommand =
1313
internal
1414
| BufferToBufferCmd of src : VkBuffer * dst : VkBuffer * info : VkBufferCopy
15-
| BufferToImageCmd of src : VkBuffer * dst : VkImage * dstLayout : VkImageLayout * info : VkBufferImageCopy * size : int64
16-
| ImageToBufferCmd of src : VkImage * srcLayout : VkImageLayout * dst : VkBuffer * info : VkBufferImageCopy * size : int64
17-
| ImageToImageCmd of src : VkImage * srcLayout : VkImageLayout * dst : VkImage * dstLayout : VkImageLayout * info : VkImageCopy * size : int64
15+
| BufferToImageCmd of src : VkBuffer * dst : VkImage * dstLayout : VkImageLayout * info : VkBufferImageCopy * size : uint64
16+
| ImageToBufferCmd of src : VkImage * srcLayout : VkImageLayout * dst : VkBuffer * info : VkBufferImageCopy * size : uint64
17+
| ImageToImageCmd of src : VkImage * srcLayout : VkImageLayout * dst : VkImage * dstLayout : VkImageLayout * info : VkImageCopy * size : uint64
1818
| CallbackCmd of (unit -> unit)
19-
| ReleaseBufferCmd of buffer : VkBuffer * offset : int64 * size : int64 * dstQueueFamily : uint32
19+
| ReleaseBufferCmd of buffer : VkBuffer * offset : uint64 * size : uint64 * dstQueueFamily : uint32
2020
| ReleaseImageCmd of image : VkImage * range : VkImageSubresourceRange * srcLayout : VkImageLayout * dstLayout : VkImageLayout * dstQueueFamily : uint32
2121
| TransformLayoutCmd of image : VkImage * range : VkImageSubresourceRange * srcLayout : VkImageLayout * dstLayout : VkImageLayout
2222

@@ -26,19 +26,19 @@ type CopyCommand =
2626
static member SyncImage(image : VkImage, range : VkImageSubresourceRange, layout : VkImageLayout) =
2727
CopyCommand.TransformLayoutCmd(image, range, layout, layout)
2828

29-
static member Copy(src : VkBuffer, srcOffset : int64, dst : VkBuffer, dstOffset : int64, size : int64) =
29+
static member Copy(src : VkBuffer, srcOffset : uint64, dst : VkBuffer, dstOffset : uint64, size : uint64) =
3030
CopyCommand.BufferToBufferCmd(
3131
src,
3232
dst,
33-
VkBufferCopy(uint64 srcOffset, uint64 dstOffset, uint64 size)
33+
VkBufferCopy(srcOffset, dstOffset, size)
3434
)
3535

3636
static member Copy(src : VkBuffer, dst : VkImage, dstLayout : VkImageLayout, format : VkFormat, info : VkBufferImageCopy) =
3737
let sizeInBytes =
38-
int64 info.imageExtent.width *
39-
int64 info.imageExtent.height *
40-
int64 info.imageExtent.depth *
41-
int64 (VkFormat.sizeInBytes format)
38+
uint64 info.imageExtent.width *
39+
uint64 info.imageExtent.height *
40+
uint64 info.imageExtent.depth *
41+
uint64 (VkFormat.sizeInBytes format)
4242

4343
CopyCommand.BufferToImageCmd(
4444
src,
@@ -48,10 +48,10 @@ type CopyCommand =
4848

4949
static member Copy(src : VkImage, srcLayout : VkImageLayout, dst : VkBuffer, format : VkFormat, info : VkBufferImageCopy) =
5050
let sizeInBytes =
51-
int64 info.imageExtent.width *
52-
int64 info.imageExtent.height *
53-
int64 info.imageExtent.depth *
54-
int64 (VkFormat.sizeInBytes format)
51+
uint64 info.imageExtent.width *
52+
uint64 info.imageExtent.height *
53+
uint64 info.imageExtent.depth *
54+
uint64 (VkFormat.sizeInBytes format)
5555

5656
CopyCommand.ImageToBufferCmd(
5757
src, srcLayout,
@@ -62,18 +62,18 @@ type CopyCommand =
6262
static member Callback(cb : unit -> unit) =
6363
CopyCommand.CallbackCmd cb
6464

65-
static member Release(buffer : VkBuffer, offset : int64, size : int64, dstQueueFamily : int) =
65+
static member Release(buffer : VkBuffer, offset : uint64, size : uint64, dstQueueFamily : int) =
6666
CopyCommand.ReleaseBufferCmd(buffer, offset, size, uint32 dstQueueFamily)
6767

6868
static member Release(image : VkImage, range : VkImageSubresourceRange, srcLayout : VkImageLayout, dstLayout : VkImageLayout, dstQueueFamily : int) =
6969
CopyCommand.ReleaseImageCmd(image, range, srcLayout, dstLayout, uint32 dstQueueFamily)
7070

7171
member x.SizeInBytes =
7272
match x with
73-
| BufferToBufferCmd(_,_,i) -> int64 i.size
73+
| BufferToBufferCmd(_,_,i) -> i.size
7474
| BufferToImageCmd(_,_,_,_,s) -> s
7575
| ImageToBufferCmd(_,_,_,_,s) -> s
76-
| _ -> 0L
76+
| _ -> 0UL
7777

7878
and CopyEngine(family: DeviceQueueFamily) =
7979
let familyIndex = family.Index
@@ -83,7 +83,7 @@ and CopyEngine(family: DeviceQueueFamily) =
8383
// queue
8484
let lockObj = obj()
8585
let mutable pending = List<CopyCommand>()
86-
let mutable totalSize = 0L
86+
let mutable totalSize = 0UL
8787
let mutable running = true
8888

8989

@@ -95,8 +95,8 @@ and CopyEngine(family: DeviceQueueFamily) =
9595
let mutable minBatchSize = Mem(1UL <<< 60)
9696
let mutable maxBatchSize = Mem(0UL)
9797
let enqueueMon = obj()
98-
let mutable vEnqueue = 0L
99-
let mutable vDone = -1L
98+
let mutable vEnqueue = 0UL
99+
let mutable vDone = 0UL
100100
let run (_threadName : string) (queue : DeviceQueue) () =
101101
let device = queue.DeviceInterface
102102
let fence = new Fence(device)
@@ -114,19 +114,19 @@ and CopyEngine(family: DeviceQueueFamily) =
114114
lock lockObj (fun () ->
115115

116116
if not running then
117-
empty, 0L, 0L
117+
empty, 0UL, 0UL
118118
else
119119
while pending.Count = 0 && running do Monitor.Wait lockObj |> ignore
120120
if not running then
121-
empty, 0L, 0L
122-
elif totalSize >= 0L then
121+
empty, 0UL, 0UL
122+
elif totalSize >= 0UL then
123123
let mine = pending
124124
let s = totalSize
125125
pending <- List()
126-
totalSize <- 0L
126+
totalSize <- 0UL
127127
mine, vEnqueue, s
128128
else
129-
empty, 0L, 0L
129+
empty, 0UL, 0UL
130130
)
131131

132132
if copies.Count > 0 then
@@ -234,7 +234,7 @@ and CopyEngine(family: DeviceQueueFamily) =
234234
fence.Wait()
235235
sw.Stop()
236236

237-
if totalSize > 0L then
237+
if totalSize > 0UL then
238238
lock statLock (fun () ->
239239
let totalSize = Mem totalSize
240240
maxBatchSize <- max maxBatchSize totalSize
@@ -304,23 +304,23 @@ and CopyEngine(family: DeviceQueueFamily) =
304304
lock lockObj (fun () ->
305305
pending.AddRange commands
306306

307-
let s = commands |> Seq.fold (fun s c -> s + c.SizeInBytes) 0L
307+
let s = commands |> Seq.fold (fun s c -> s + c.SizeInBytes) 0UL
308308
totalSize <- totalSize + s
309309

310310
Monitor.PulseAll lockObj
311311
s
312312
)
313313

314-
if size > 0L then () // trigger.Signal()
314+
if size > 0UL then () // trigger.Signal()
315315

316316
/// Enqueues the commands and waits for them to be submitted.
317317
member x.EnqueueSafe(commands : seq<CopyCommand>) =
318318
let enq, size =
319319
lock lockObj (fun () ->
320-
vEnqueue <- vEnqueue + 1L
320+
vEnqueue <- vEnqueue + 1UL
321321
pending.AddRange commands
322322

323-
let s = commands |> Seq.fold (fun s c -> s + c.SizeInBytes) 0L
323+
let s = commands |> Seq.fold (fun s c -> s + c.SizeInBytes) 0UL
324324
totalSize <- totalSize + s
325325

326326
Monitor.PulseAll lockObj
@@ -332,7 +332,7 @@ and CopyEngine(family: DeviceQueueFamily) =
332332
while vDone < enq do
333333
Monitor.Wait enqueueMon |> ignore
334334
)
335-
if size > 0L then () // trigger.Signal()
335+
if size > 0UL then () // trigger.Signal()
336336

337337
member x.Wait() =
338338
let l = obj()

0 commit comments

Comments
 (0)