Skip to content

Commit 741101c

Browse files
committed
[Vulkan] Fix infinite recursion in external memory allocation
1 parent 69f89fd commit 741101c

File tree

3 files changed

+60
-50
lines changed

3 files changed

+60
-50
lines changed

src/Aardvark.Rendering.Vulkan/Core/Memory/MemoryAllocator.fs

Lines changed: 57 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ type IDeviceMemory =
2525
[<Optional; DefaultParameterValue(0.5)>] priority: float *
2626
[<Optional; DefaultParameterValue(false)>] export: bool *
2727
[<Optional; DefaultParameterValue(true)>] bind: bool *
28-
[<Optional; DefaultParameterValue(false)>] mayAlias: bool -> VkBuffer * DevicePtr
28+
[<Optional; DefaultParameterValue(false)>] mayAlias: bool -> struct (VkBuffer * DevicePtr)
2929

3030
abstract member CreateImage : info: VkImageCreateInfo byref *
3131
[<Optional; DefaultParameterValue(0.5)>] priority: float *
3232
[<Optional; DefaultParameterValue(false)>] export: bool *
3333
[<Optional; DefaultParameterValue(true)>] bind: bool *
34-
[<Optional; DefaultParameterValue(false)>] mayAlias: bool -> VkImage * DevicePtr
34+
[<Optional; DefaultParameterValue(false)>] mayAlias: bool -> struct (VkImage * DevicePtr)
3535

3636
type internal MemoryAllocator (device: IDevice) =
3737
let mutable allocator = VmaAllocator.Zero
@@ -71,51 +71,57 @@ type internal MemoryAllocator (device: IDevice) =
7171

7272
let nullPtr = new DevicePtr(device)
7373

74-
let externalMemoryPools = ConcurrentDictionary<uint32, ExternalMemoryPool>()
74+
let externalMemoryPools = ConcurrentDictionary<uint32, Lazy<ExternalMemoryPool>>()
7575

76-
let createBuffer pBufferCreateInfo pAllocationCreateInfo hostVisible alignment export =
76+
let getExternalMemoryPool memoryTypeIndex =
77+
externalMemoryPools.GetOrAdd(memoryTypeIndex, fun index ->
78+
lazy (new ExternalMemoryPool(allocator, index))
79+
).Value
80+
81+
let tryCreateBuffer pBufferCreateInfo pAllocationCreateInfo hostVisible alignment export =
7782
let mutable buffer = VkBuffer.Null
7883
let mutable allocation = VmaAllocation.Zero
7984

80-
Vma.createBufferWithAlignment(
81-
allocator, pBufferCreateInfo, pAllocationCreateInfo, alignment,
82-
&&buffer, &&allocation, NativePtr.zero
83-
)
84-
|> checkf "could not create buffer"
85+
let result =
86+
Vma.createBufferWithAlignment(
87+
allocator, pBufferCreateInfo, pAllocationCreateInfo, alignment,
88+
&&buffer, &&allocation, NativePtr.zero
89+
)
8590

86-
let ptr = new DevicePtr(device, allocator, allocation, hostVisible, export)
87-
buffer, ptr
91+
if result = VkResult.Success then
92+
let ptr = new DevicePtr(device, allocator, allocation, hostVisible, export)
93+
Result.Ok struct (buffer, ptr)
94+
else
95+
Result.Error result
8896

89-
let createImage pImageCreateInfo pAllocationCreateInfo hostVisible export =
97+
let tryCreateImage pImageCreateInfo pAllocationCreateInfo hostVisible export =
9098
let mutable image = VkImage.Null
9199
let mutable allocation = VmaAllocation.Zero
92100

93-
Vma.createImage(
94-
allocator, pImageCreateInfo, pAllocationCreateInfo,
95-
&&image, &&allocation, NativePtr.zero
96-
)
97-
|> checkf "could not allocate memory for image"
101+
let result =
102+
Vma.createImage(
103+
allocator, pImageCreateInfo, pAllocationCreateInfo,
104+
&&image, &&allocation, NativePtr.zero
105+
)
98106

99-
let ptr = new DevicePtr(device, allocator, allocation, hostVisible, export)
100-
image, ptr
107+
if result = VkResult.Success then
108+
let ptr = new DevicePtr(device, allocator, allocation, hostVisible, export)
109+
Result.Ok struct (image, ptr)
110+
else
111+
Result.Error result
101112

102113
let rec createExternalBuffer pBufferCreateInfo (allocationCreateInfo: _ byref) hostVisible alignment =
103114
let mutable memoryTypeIndex = 0u
104115
Vma.findMemoryTypeIndexForBufferInfo(allocator, pBufferCreateInfo, &&allocationCreateInfo, &&memoryTypeIndex)
105116
|> checkf "could not find memory type for buffer"
106117

107-
let pool =
108-
externalMemoryPools.GetOrAdd(memoryTypeIndex, fun index ->
109-
new ExternalMemoryPool(allocator, index)
110-
)
118+
let pool = getExternalMemoryPool memoryTypeIndex
119+
allocationCreateInfo.pool <- pool.Handle
111120

112-
try
113-
allocationCreateInfo.pool <- pool.Handle
114-
createBuffer pBufferCreateInfo &&allocationCreateInfo hostVisible alignment true
115-
116-
with :? VulkanException as e ->
117-
Log.warn $"{e.Message}"
118-
allocationCreateInfo.pool <- VmaPool.Zero
121+
match tryCreateBuffer pBufferCreateInfo &&allocationCreateInfo hostVisible alignment true with
122+
| Result.Ok result -> result
123+
| Result.Error error ->
124+
Log.Vulkan.warn $"could not allocate memory for buffer (Error: {error})"
119125
&allocationCreateInfo.memoryTypeBits &&&= ~~~(1u <<< int32 memoryTypeIndex)
120126
createExternalBuffer pBufferCreateInfo &allocationCreateInfo hostVisible alignment
121127

@@ -124,18 +130,13 @@ type internal MemoryAllocator (device: IDevice) =
124130
Vma.findMemoryTypeIndexForImageInfo(allocator, pImageCreateInfo, &&allocationCreateInfo, &&memoryTypeIndex)
125131
|> checkf "could not find memory type for image"
126132

127-
let pool =
128-
externalMemoryPools.GetOrAdd(memoryTypeIndex, fun index ->
129-
new ExternalMemoryPool(allocator, index)
130-
)
131-
132-
try
133-
allocationCreateInfo.pool <- pool.Handle
134-
createImage pImageCreateInfo &&allocationCreateInfo hostVisible true
133+
let pool = getExternalMemoryPool memoryTypeIndex
134+
allocationCreateInfo.pool <- pool.Handle
135135

136-
with :? VulkanException as e ->
137-
Log.warn $"{e.Message}"
138-
allocationCreateInfo.pool <- VmaPool.Zero
136+
match tryCreateImage pImageCreateInfo &&allocationCreateInfo hostVisible true with
137+
| Result.Ok result -> result
138+
| Result.Error error ->
139+
Log.Vulkan.warn $"could not allocate memory for image (Error: {error})"
139140
&allocationCreateInfo.memoryTypeBits &&&= ~~~(1u <<< int32 memoryTypeIndex)
140141
createExternalImage pImageCreateInfo &allocationCreateInfo hostVisible
141142

@@ -157,9 +158,10 @@ type internal MemoryAllocator (device: IDevice) =
157158
&flags |||= VmaAllocationCreateFlags.CanAliasBit
158159

159160
{ VmaAllocationCreateInfo.Empty with
160-
flags = flags
161-
usage = usage
162-
priority = float32 priority }
161+
flags = flags
162+
usage = usage
163+
priority = float32 priority
164+
memoryTypeBits = ~~~0u }
163165

164166
member _.NullPtr = nullPtr
165167

@@ -174,7 +176,11 @@ type internal MemoryAllocator (device: IDevice) =
174176
if export then
175177
createExternalBuffer &&bufferCreateInfo &allocationCreateInfo hostVisible alignment
176178
else
177-
createBuffer &&bufferCreateInfo &&allocationCreateInfo hostVisible alignment false
179+
match tryCreateBuffer &&bufferCreateInfo &&allocationCreateInfo hostVisible alignment false with
180+
| Result.Ok result -> result
181+
| Result.Error error ->
182+
error |> checkf "could not allocate memory for buffer"
183+
Unchecked.defaultof<_>
178184

179185
with :? VulkanException ->
180186
this.PrintUsage Logger.Default
@@ -191,7 +197,11 @@ type internal MemoryAllocator (device: IDevice) =
191197
if export then
192198
createExternalImage &&imageCreateInfo &allocationCreateInfo hostVisible
193199
else
194-
createImage &&imageCreateInfo &&allocationCreateInfo hostVisible false
200+
match tryCreateImage &&imageCreateInfo &&allocationCreateInfo hostVisible false with
201+
| Result.Ok result -> result
202+
| Result.Error error ->
203+
error |> checkf "could not allocate memory for image"
204+
Unchecked.defaultof<_>
195205

196206
with :? VulkanException ->
197207
this.PrintUsage Logger.Default
@@ -240,7 +250,7 @@ type internal MemoryAllocator (device: IDevice) =
240250
member _.Dispose() =
241251
if allocator <> VmaAllocator.Zero then
242252
for KeyValue(_, pool) in externalMemoryPools do
243-
pool.Dispose()
253+
pool.Value.Dispose()
244254

245255
Vma.destroyAllocator allocator
246256
allocator <- VmaAllocator.Zero

src/Aardvark.Rendering.Vulkan/Resources/Buffers/Buffer.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ module Buffer =
314314
(if concurrent then device.QueueFamilyIndices else NativePtr.zero)
315315
)
316316

317-
let buffer, memory = memory.CreateBuffer(&info, alignment = alignment, export = export)
317+
let struct (buffer, memory) = memory.CreateBuffer(&info, alignment = alignment, export = export)
318318

319319
if export then
320320
new ExportedBuffer(device, buffer, memory, size, usage) :> Buffer

src/Aardvark.Rendering.Vulkan/Resources/Image/Image.fs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,7 +1073,7 @@ module Image =
10731073
)
10741074

10751075
if mayHavePeers then
1076-
let handle, memory = device.DeviceMemory.CreateImage(&info, export = export.IsEnabled, bind = false, mayAlias = true)
1076+
let struct (handle, memory) = device.DeviceMemory.CreateImage(&info, export = export.IsEnabled, bind = false, mayAlias = true)
10771077

10781078
let indices = device.PhysicalDeviceGroup.AllIndicesArr
10791079
let handles = Array.zeroCreate indices.Length
@@ -1115,7 +1115,7 @@ module Image =
11151115
result
11161116

11171117
else
1118-
let handle, memory = device.DeviceMemory.CreateImage(&info, export = export.IsEnabled)
1118+
let struct (handle, memory) = device.DeviceMemory.CreateImage(&info, export = export.IsEnabled)
11191119

11201120
match export with
11211121
| ImageExport.Enable preferArray ->

0 commit comments

Comments
 (0)