Mercurial > games > semicongine
comparison semiconginev2/old/vulkan/memory.nim @ 1218:56781cc0fc7c compiletime-tests
did: renamge main package
author | sam <sam@basx.dev> |
---|---|
date | Wed, 17 Jul 2024 21:01:37 +0700 |
parents | semicongine/old/vulkan/memory.nim@a3eb305bcac2 |
children |
comparison
equal
deleted
inserted
replaced
1217:f819a874058f | 1218:56781cc0fc7c |
---|---|
1 import std/strformat | |
2 | |
3 import ../core | |
4 import ./device | |
5 | |
6 type | |
7 MemoryHeap = object | |
8 size*: uint64 | |
9 flags*: seq[VkMemoryHeapFlagBits] | |
10 index*: uint32 | |
11 MemoryType* = object | |
12 heap*: MemoryHeap | |
13 flags*: seq[VkMemoryPropertyFlagBits] | |
14 index*: uint32 | |
15 PhyscialDeviceMemoryProperties = object | |
16 heaps*: seq[MemoryHeap] | |
17 types*: seq[MemoryType] | |
18 DeviceMemory* = object | |
19 device*: Device | |
20 vk*: VkDeviceMemory | |
21 size*: uint64 | |
22 memoryType*: MemoryType | |
23 case canMap*: bool | |
24 of false: discard | |
25 of true: data*: pointer | |
26 needsFlushing*: bool | |
27 MemoryRequirements* = object | |
28 size*: uint64 | |
29 alignment*: uint64 | |
30 memoryTypes*: seq[MemoryType] | |
31 | |
32 func `$`*(memoryType: MemoryType): string = | |
33 &"Memorytype {memoryType.flags} (heap size: {memoryType.heap.size}, heap flags: {memoryType.heap.flags})" | |
34 | |
35 proc SelectBestMemoryType*(types: seq[MemoryType], requireMappable: bool, preferVRAM: bool, preferAutoFlush: bool): MemoryType = | |
36 # todo: we assume there is always at least one memory type that is mappable | |
37 assert types.len > 0 | |
38 var highestRating = 0'f | |
39 result = types[0] | |
40 for t in types: | |
41 var rating = float(t.heap.size) / 1_000_000'f # select biggest heap if all else equal | |
42 if requireMappable and VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT in t.flags: | |
43 rating += 1000 | |
44 if preferVRAM and VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT in t.flags: | |
45 rating += 500 | |
46 if preferAutoFlush and VK_MEMORY_PROPERTY_HOST_COHERENT_BIT in t.flags: | |
47 rating += 100 | |
48 if rating > highestRating: | |
49 highestRating = rating | |
50 result = t | |
51 | |
52 proc GetMemoryProperties*(physicalDevice: VkPhysicalDevice): PhyscialDeviceMemoryProperties = | |
53 var physicalProperties: VkPhysicalDeviceMemoryProperties | |
54 vkGetPhysicalDeviceMemoryProperties(physicalDevice, addr physicalProperties) | |
55 for i in 0 ..< physicalProperties.memoryHeapCount: | |
56 result.heaps.add MemoryHeap( | |
57 size: physicalProperties.memoryHeaps[i].size, | |
58 flags: toEnums(physicalProperties.memoryHeaps[i].flags), | |
59 index: i, | |
60 ) | |
61 for i in 0 ..< physicalProperties.memoryTypeCount: | |
62 result.types.add MemoryType( | |
63 heap: result.heaps[physicalProperties.memoryTypes[i].heapIndex], | |
64 flags: toEnums(physicalProperties.memoryTypes[i].propertyFlags), | |
65 index: i, | |
66 ) | |
67 | |
68 proc Allocate*(device: Device, size: uint64, memoryType: MemoryType): DeviceMemory = | |
69 assert device.vk.Valid | |
70 assert size > 0 | |
71 result = DeviceMemory( | |
72 device: device, | |
73 size: size, | |
74 memoryType: memoryType, | |
75 canMap: VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT in memoryType.flags, | |
76 needsFlushing: not (VK_MEMORY_PROPERTY_HOST_COHERENT_BIT in memoryType.flags), | |
77 ) | |
78 | |
79 var allocationInfo = VkMemoryAllocateInfo( | |
80 sType: VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, | |
81 allocationSize: size, | |
82 memoryTypeIndex: result.memoryType.index, | |
83 ) | |
84 | |
85 checkVkResult vkAllocateMemory( | |
86 device.vk, | |
87 addr allocationInfo, | |
88 nil, | |
89 addr result.vk | |
90 ) | |
91 | |
92 if result.canMap: | |
93 checkVkResult result.device.vk.vkMapMemory( | |
94 memory = result.vk, | |
95 offset = VkDeviceSize(0), | |
96 size = VkDeviceSize(result.size), | |
97 flags = VkMemoryMapFlags(0), # unused up to Vulkan 1.3 | |
98 ppData = addr(result.data) | |
99 ) | |
100 | |
101 # flush host -> device | |
102 proc Flush*(memory: DeviceMemory, offset = 0'u64, size = 0'u64) = | |
103 assert memory.device.vk.Valid | |
104 assert memory.vk.Valid | |
105 assert memory.needsFlushing | |
106 | |
107 var actualSize = size | |
108 if actualSize == 0: | |
109 actualSize = memory.size | |
110 var flushrange = VkMappedMemoryRange( | |
111 sType: VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, | |
112 memory: memory.vk, | |
113 offset: VkDeviceSize(offset), | |
114 size: VkDeviceSize(size) | |
115 ) | |
116 checkVkResult memory.device.vk.vkFlushMappedMemoryRanges(memoryRangeCount = 1, pMemoryRanges = addr(flushrange)) | |
117 | |
118 # flush device -> host | |
119 proc Invalidate*(memory: DeviceMemory, offset = 0'u64, size = 0'u64) = | |
120 assert memory.device.vk.Valid | |
121 assert memory.vk.Valid | |
122 assert memory.needsFlushing | |
123 | |
124 var actualSize = size | |
125 if actualSize == 0: | |
126 actualSize = memory.size | |
127 var flushrange = VkMappedMemoryRange( | |
128 sType: VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, | |
129 memory: memory.vk, | |
130 offset: VkDeviceSize(offset), | |
131 size: VkDeviceSize(size) | |
132 ) | |
133 checkVkResult memory.device.vk.vkInvalidateMappedMemoryRanges(memoryRangeCount = 1, pMemoryRanges = addr(flushrange)) | |
134 | |
135 proc Free*(memory: var DeviceMemory) = | |
136 assert memory.device.vk.Valid | |
137 assert memory.vk.Valid | |
138 | |
139 memory.device.vk.vkFreeMemory(memory.vk, nil) | |
140 memory.vk.Reset |