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 |
