Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a5354c7

Browse files
committed
Add EngineAllocator
1 parent af1812e commit a5354c7

File tree

7 files changed

+450
-0
lines changed

7 files changed

+450
-0
lines changed

src/engine/renderer-vulkan/GraphicsCore/Decls.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,6 @@ extern GraphicsQueueRingBuffer computeQueue;
6464
extern GraphicsQueueRingBuffer transferQueue;
6565
extern GraphicsQueueRingBuffer sparseQueue;
6666

67+
class EngineAllocator;
68+
6769
#endif // GRAPHICS_CORE_DECLS_H

src/engine/renderer-vulkan/GraphicsCore/GraphicsCoreStore.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4545
#include "QueuesConfig.h"
4646
#include "Queue.h"
4747

48+
#include "Memory/EngineAllocator.h"
49+
4850
#include "GraphicsCoreStore.h"
4951

5052
Surface mainSurface;
@@ -67,3 +69,5 @@ GraphicsQueueRingBuffer sparseQueue;
6769

6870
VkDescriptorSetLayout descriptorSetLayout;
6971
VkDescriptorSet descriptorSet;
72+
73+
EngineAllocator engineAllocator;

src/engine/renderer-vulkan/GraphicsCore/GraphicsCoreStore.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,6 @@ extern GraphicsQueueRingBuffer sparseQueue;
5959
extern VkDescriptorSetLayout descriptorSetLayout;
6060
extern VkDescriptorSet descriptorSet;
6161

62+
extern EngineAllocator engineAllocator;
63+
6264
#endif // GRAPHICS_CORE_STORE_H

src/engine/renderer-vulkan/GraphicsCore/Instance.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5454
#include "GraphicsCoreStore.h"
5555

5656
#include "Memory/DescriptorSet.h"
57+
#include "Memory/EngineAllocator.h"
5758

5859
#include "Instance.h"
5960

@@ -154,4 +155,6 @@ void Instance::Init( const char* engineName, const char* appName ) {
154155
Log::Notice( foundQueues );
155156

156157
AllocDescriptors( engineConfig.maxImages, engineConfig.maxStorageImages );
158+
159+
engineAllocator.Init();
157160
}
Lines changed: 331 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,331 @@
1+
/*
2+
===========================================================================
3+
4+
Daemon BSD Source Code
5+
Copyright (c) 2025 Daemon Developers
6+
All rights reserved.
7+
8+
This file is part of the Daemon BSD Source Code (Daemon Source Code).
9+
10+
Redistribution and use in source and binary forms, with or without
11+
modification, are permitted provided that the following conditions are met:
12+
* Redistributions of source code must retain the above copyright
13+
notice, this list of conditions and the following disclaimer.
14+
* Redistributions in binary form must reproduce the above copyright
15+
notice, this list of conditions and the following disclaimer in the
16+
documentation and/or other materials provided with the distribution.
17+
* Neither the name of the Daemon developers nor the
18+
names of its contributors may be used to endorse or promote products
19+
derived from this software without specific prior written permission.
20+
21+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
22+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24+
DISCLAIMED. IN NO EVENT SHALL DAEMON DEVELOPERS BE LIABLE FOR ANY
25+
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28+
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31+
32+
===========================================================================
33+
*/
34+
// EngineAllocator.cpp
35+
36+
#include "../Vulkan.h"
37+
38+
#include "../../Error.h"
39+
40+
#include "../../Math/Bit.h"
41+
42+
#include "../GraphicsCoreStore.h"
43+
44+
#include "../../GraphicsShared/Bindings.h"
45+
46+
#include "EngineAllocator.h"
47+
48+
constexpr VkSampleCountFlags SamplesToEnum( const uint32 samples ) {
49+
switch ( samples ) {
50+
case 1:
51+
return VK_SAMPLE_COUNT_1_BIT;
52+
case 2:
53+
return VK_SAMPLE_COUNT_2_BIT;
54+
case 4:
55+
return VK_SAMPLE_COUNT_4_BIT;
56+
case 8:
57+
return VK_SAMPLE_COUNT_8_BIT;
58+
case 16:
59+
return VK_SAMPLE_COUNT_16_BIT;
60+
case 32:
61+
return VK_SAMPLE_COUNT_32_BIT;
62+
case 64:
63+
return VK_SAMPLE_COUNT_64_BIT;
64+
default:
65+
Err( "Image sample count must be one of: 1, 2, 4, 8, 16, 32, 64" );
66+
return VK_SAMPLE_COUNT_1_BIT;
67+
}
68+
}
69+
70+
MemoryRequirements GetImageRequirements( const VkImageType type, const VkFormat format, const bool useMipMaps,
71+
const bool storageImage, const uint32 width, const uint32 height, const uint32 depth, const uint32 layers,
72+
const uint32 samples ) {
73+
const uint32 mips = useMipMaps ? log2f( std::max( std::max( width, height ), depth ) ) + 1 : 1;
74+
75+
VkImageCreateInfo imageInfo {
76+
.imageType = type,
77+
.format = format,
78+
.extent = { width, height, depth },
79+
.mipLevels = mips,
80+
.arrayLayers = layers,
81+
.samples = ( VkSampleCountFlagBits ) SamplesToEnum( samples ),
82+
.tiling = VK_IMAGE_TILING_OPTIMAL,
83+
.usage = ( VkFlags ) ( storageImage ? VK_IMAGE_USAGE_STORAGE_BIT : VK_IMAGE_USAGE_SAMPLED_BIT ),
84+
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
85+
.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED
86+
};
87+
88+
VkDeviceImageMemoryRequirements reqs {
89+
.pCreateInfo = &imageInfo
90+
};
91+
92+
VkMemoryDedicatedRequirements dedicatedReqs {};
93+
94+
VkMemoryRequirements2 out { .pNext = &dedicatedReqs };
95+
96+
vkGetDeviceImageMemoryRequirements( device, &reqs, &out );
97+
98+
return {
99+
out.memoryRequirements.size, out.memoryRequirements.alignment, out.memoryRequirements.memoryTypeBits,
100+
( bool ) dedicatedReqs.prefersDedicatedAllocation
101+
};
102+
}
103+
104+
MemoryRequirements GetImage2DRequirements( const VkFormat format, const bool useMipMaps,
105+
const bool storageImage, const uint32 width, const uint32 height ) {
106+
return GetImageRequirements( VK_IMAGE_TYPE_2D, format, useMipMaps, storageImage, width, height, 0, 1, 1 );
107+
}
108+
109+
MemoryRequirements GetImage3DRequirements( const VkFormat format, const bool useMipMaps,
110+
const bool storageImage, const uint32 width, const uint32 depth, const uint32 height ) {
111+
return GetImageRequirements( VK_IMAGE_TYPE_2D, format, useMipMaps, storageImage, width, height, depth, 1, 1 );
112+
}
113+
114+
MemoryRequirements GetBufferRequirements( const VkBufferUsageFlags type, const uint64 size ) {
115+
VkBufferCreateInfo bufferInfo {
116+
.size = size,
117+
.usage = type,
118+
.sharingMode = VK_SHARING_MODE_EXCLUSIVE
119+
};
120+
121+
VkDeviceBufferMemoryRequirements reqs2 {
122+
.pCreateInfo = &bufferInfo
123+
};
124+
125+
VkMemoryRequirements2 out {};
126+
127+
vkGetDeviceBufferMemoryRequirements( device, &reqs2, &out );
128+
129+
return {
130+
out.memoryRequirements.size, out.memoryRequirements.alignment, out.memoryRequirements.memoryTypeBits
131+
};
132+
}
133+
134+
static constexpr VkMemoryPropertyFlags memoryTypeGPU =
135+
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
136+
static constexpr VkMemoryPropertyFlags memoryTypeBAR =
137+
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
138+
static constexpr VkMemoryPropertyFlags memoryTypeGPUToCPU =
139+
VK_MEMORY_PROPERTY_HOST_CACHED_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
140+
141+
static constexpr VkMemoryPropertyFlags memoryTypeUnified =
142+
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
143+
| VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
144+
145+
MemoryHeap EngineAllocator::MemoryHeapForUsage( const MemoryHeap::MemoryType type, const MemoryRequirements& reqs ) {
146+
VkPhysicalDeviceMemoryBudgetPropertiesEXT properties {};
147+
VkPhysicalDeviceMemoryProperties2 properties2 {
148+
.pNext = &properties
149+
};
150+
151+
vkGetPhysicalDeviceMemoryProperties2( physicalDevice, &properties2 );
152+
153+
VkPhysicalDeviceMemoryProperties& memoryProperties = properties2.memoryProperties;
154+
155+
uint32 memoryRegion;
156+
uint32 memoryID;
157+
158+
if ( unifiedMemory ) {
159+
memoryRegion = memoryRegionEngine;
160+
memoryID = memoryIDEngine;
161+
} else {
162+
switch ( type ) {
163+
default:
164+
case MemoryHeap::ENGINE:
165+
memoryRegion = memoryRegionEngine;
166+
memoryID = memoryIDEngine;
167+
break;
168+
case MemoryHeap::CORE_TO_ENGINE:
169+
memoryRegion = memoryRegionBAR;
170+
memoryID = memoryIDCoreToEngine;
171+
break;
172+
case MemoryHeap::ENGINE_TO_CORE:
173+
memoryRegion = memoryRegionCore;
174+
memoryID = memoryIDEngineToCore;
175+
break;
176+
}
177+
}
178+
179+
MemoryHeap memoryHeap {
180+
properties.heapBudget[memoryRegion] - properties.heapUsage[memoryRegion],
181+
properties.heapBudget[memoryRegion],
182+
type
183+
};
184+
185+
uint32 supportedTypes = reqs.type;
186+
187+
while ( supportedTypes ) {
188+
const uint32 id = FindLSB( supportedTypes );
189+
const VkMemoryType& memoryType = memoryProperties.memoryTypes[id];
190+
191+
if ( !BitSet( memoryID, id ) ) {
192+
UnSetBit( &supportedTypes, id );
193+
continue;
194+
}
195+
196+
if ( type == MemoryHeap::ENGINE && memoryType.propertyFlags & memoryTypeGPU ||
197+
type == MemoryHeap::CORE_TO_ENGINE && memoryType.propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
198+
|| type == MemoryHeap::ENGINE_TO_CORE && memoryType.propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT ) {
199+
memoryHeap.id = id;
200+
201+
return memoryHeap;
202+
}
203+
204+
UnSetBit( &supportedTypes, id );
205+
}
206+
207+
Err( "No suitable MemoryHeap found" );
208+
return memoryHeap;
209+
}
210+
211+
void EngineAllocator::Init() {
212+
memoryPoolCount = 0;
213+
214+
VkPhysicalDeviceMemoryBudgetPropertiesEXT properties {};
215+
VkPhysicalDeviceMemoryProperties2 properties2 {
216+
.pNext = &properties
217+
};
218+
219+
vkGetPhysicalDeviceMemoryProperties2( physicalDevice, &properties2 );
220+
221+
VkPhysicalDeviceMemoryProperties& memoryProperties = properties2.memoryProperties;
222+
223+
memoryIDEngine = 0;
224+
memoryIDCoreToEngine = 0;
225+
memoryIDEngineToCore = 0;
226+
227+
if ( memoryProperties.memoryHeapCount == 1 ) {
228+
unifiedMemory = true;
229+
rebar = false;
230+
231+
for ( uint32 i = 0; i < memoryProperties.memoryTypeCount; i++ ) {
232+
const VkMemoryType& memoryType = memoryProperties.memoryTypes[i];
233+
234+
if ( memoryType.propertyFlags & memoryTypeUnified ) {
235+
memoryIDEngine = i;
236+
break;
237+
}
238+
}
239+
240+
if ( memoryIDEngine == UINT_MAX ) {
241+
Err( "Couldn't find memory type for ENGINE" );
242+
}
243+
244+
memoryTypeEngine = memoryTypeUnified;
245+
memoryTypeCoreToEngine = memoryTypeUnified;
246+
memoryTypeEngineToCore = memoryTypeUnified;
247+
248+
memoryIDCoreToEngine = memoryIDEngine;
249+
memoryIDEngineToCore = memoryIDEngine;
250+
} else {
251+
for ( uint32 i = 0; i < memoryProperties.memoryHeapCount; i++ ) {
252+
const VkMemoryHeap& memoryRegion = memoryProperties.memoryHeaps[i];
253+
254+
for ( uint32 j = 0; j < memoryProperties.memoryTypeCount; j++ ) {
255+
const VkMemoryType& memoryType = memoryProperties.memoryTypes[j];
256+
257+
if ( memoryType.heapIndex != i ) {
258+
continue;
259+
}
260+
261+
if ( memoryRegion.flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT ) {
262+
if ( memoryType.propertyFlags & memoryTypeGPU
263+
&& !( memoryType.propertyFlags & ( VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
264+
| VK_MEMORY_PROPERTY_HOST_CACHED_BIT ) ) ) {
265+
if ( memoryRegionEngine == UINT_MAX ) {
266+
memoryRegionEngine = i;
267+
}
268+
269+
SetBit( &memoryIDEngine, j );
270+
continue;
271+
}
272+
273+
if ( memoryType.propertyFlags & memoryTypeBAR
274+
&& !( memoryType.propertyFlags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT ) ) {
275+
if ( memoryRegionBAR == UINT_MAX ) {
276+
memoryRegionBAR = i;
277+
}
278+
279+
SetBit( &memoryIDCoreToEngine, j );
280+
continue;
281+
}
282+
} else {
283+
if ( memoryType.propertyFlags & memoryTypeGPUToCPU ) {
284+
if ( memoryRegionCore == UINT_MAX ) {
285+
memoryRegionCore = i;
286+
}
287+
288+
SetBit( &memoryIDEngineToCore, j );
289+
continue;
290+
}
291+
}
292+
}
293+
}
294+
295+
if ( memoryRegionCore == UINT_MAX ) {
296+
Err( "Couldn't find memory type for ENGINE_TO_CORE" );
297+
}
298+
299+
if ( memoryRegionEngine == UINT_MAX ) {
300+
Err( "Couldn't find memory type for ENGINE" );
301+
}
302+
303+
if ( memoryRegionBAR == UINT_MAX ) {
304+
Err( "Couldn't find memory type for CORE_TO_ENGINE" );
305+
}
306+
307+
if ( memoryRegionEngine == memoryRegionBAR ) {
308+
rebar = true;
309+
}
310+
311+
memoryTypeEngine = memoryTypeGPU;
312+
memoryTypeCoreToEngine = memoryTypeBAR;
313+
memoryTypeEngineToCore = memoryTypeGPUToCPU;
314+
}
315+
316+
MemoryRequirements reqs;
317+
reqs = GetImage2DRequirements( VK_FORMAT_R8G8B8A8_UNORM, true, false, 1024, 1024 );
318+
memoryHeapImages = MemoryHeapForUsage( MemoryHeap::ENGINE, reqs );
319+
320+
reqs = GetImage2DRequirements( VK_FORMAT_R8G8B8A8_UNORM, false, true, 1024, 1024 );
321+
memoryHeapStorageImages = MemoryHeapForUsage( MemoryHeap::ENGINE, reqs );
322+
323+
reqs = GetBufferRequirements( VK_BUFFER_USAGE_TRANSFER_SRC_BIT, 262144 );
324+
memoryHeapStagingBuffer = MemoryHeapForUsage( MemoryHeap::CORE_TO_ENGINE, reqs );
325+
}
326+
327+
void EngineAllocator::Free() {
328+
for ( MemoryPool* memoryPool = memoryPools; memoryPool < memoryPools + memoryPoolCount; memoryPool++ ) {
329+
vkFreeMemory( device, ( VkDeviceMemory ) memoryPool->memory, nullptr );
330+
}
331+
}

0 commit comments

Comments
 (0)