Mercurial > games > semicongine
diff semicongine/vulkan/memory.nim @ 840:44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
author | Sam <sam@basx.dev> |
---|---|
date | Sat, 02 Dec 2023 22:23:29 +0700 |
parents | |
children | 904e0a827ef3 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semicongine/vulkan/memory.nim Sat Dec 02 22:23:29 2023 +0700 @@ -0,0 +1,140 @@ +import std/strformat + +import ../core +import ./device + +type + MemoryHeap = object + size*: uint64 + flags*: seq[VkMemoryHeapFlagBits] + index*: uint32 + MemoryType* = object + heap*: MemoryHeap + flags*: seq[VkMemoryPropertyFlagBits] + index*: uint32 + PhyscialDeviceMemoryProperties = object + heaps*: seq[MemoryHeap] + types*: seq[MemoryType] + DeviceMemory* = object + device*: Device + vk*: VkDeviceMemory + size*: uint64 + memoryType*: MemoryType + case canMap*: bool + of false: discard + of true: data*: pointer + needsFlushing*: bool + MemoryRequirements* = object + size*: uint64 + alignment*: uint64 + memoryTypes*: seq[MemoryType] + +func `$`*(memoryType: MemoryType): string = + &"Memorytype {memoryType.flags} (heap size: {memoryType.heap.size}, heap flags: {memoryType.heap.flags})" + +proc selectBestMemoryType*(types: seq[MemoryType], requireMappable: bool, preferVRAM: bool, preferAutoFlush: bool): MemoryType = + # todo: we assume there is always at least one memory type that is mappable + assert types.len > 0 + var highestRating = 0'f + result = types[0] + for t in types: + var rating = float(t.heap.size) / 1_000_000'f # select biggest heap if all else equal + if requireMappable and VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT in t.flags: + rating += 1000 + if preferVRAM and VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT in t.flags: + rating += 500 + if preferAutoFlush and VK_MEMORY_PROPERTY_HOST_COHERENT_BIT in t.flags: + rating += 100 + if rating > highestRating: + highestRating = rating + result = t + +proc getMemoryProperties*(physicalDevice: VkPhysicalDevice): PhyscialDeviceMemoryProperties = + var physicalProperties: VkPhysicalDeviceMemoryProperties + vkGetPhysicalDeviceMemoryProperties(physicalDevice, addr physicalProperties) + for i in 0 ..< physicalProperties.memoryHeapCount: + result.heaps.add MemoryHeap( + size: physicalProperties.memoryHeaps[i].size, + flags: toEnums(physicalProperties.memoryHeaps[i].flags), + index: i, + ) + for i in 0 ..< physicalProperties.memoryTypeCount: + result.types.add MemoryType( + heap: result.heaps[physicalProperties.memoryTypes[i].heapIndex], + flags: toEnums(physicalProperties.memoryTypes[i].propertyFlags), + index: i, + ) + +proc allocate*(device: Device, size: uint64, memoryType: MemoryType): DeviceMemory = + assert device.vk.valid + assert size > 0 + result = DeviceMemory( + device: device, + size: size, + memoryType: memoryType, + canMap: VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT in memoryType.flags, + needsFlushing: not (VK_MEMORY_PROPERTY_HOST_COHERENT_BIT in memoryType.flags), + ) + + var allocationInfo = VkMemoryAllocateInfo( + sType: VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, + allocationSize: size, + memoryTypeIndex: result.memoryType.index, + ) + + checkVkResult vkAllocateMemory( + device.vk, + addr allocationInfo, + nil, + addr result.vk + ) + + if result.canMap: + checkVkResult result.device.vk.vkMapMemory( + memory=result.vk, + offset=VkDeviceSize(0), + size=VkDeviceSize(result.size), + flags=VkMemoryMapFlags(0), # unused up to Vulkan 1.3 + ppData=addr(result.data) + ) + +# flush host -> device +proc flush*(memory: DeviceMemory, offset=0'u64, size=0'u64) = + assert memory.device.vk.valid + assert memory.vk.valid + assert memory.needsFlushing + + var actualSize = size + if actualSize == 0: + actualSize = memory.size + var flushrange = VkMappedMemoryRange( + sType: VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, + memory: memory.vk, + offset: VkDeviceSize(offset), + size: VkDeviceSize(size) + ) + checkVkResult memory.device.vk.vkFlushMappedMemoryRanges(memoryRangeCount=1, pMemoryRanges=addr(flushrange)) + +# flush device -> host +proc invalidate*(memory: DeviceMemory, offset=0'u64, size=0'u64) = + assert memory.device.vk.valid + assert memory.vk.valid + assert memory.needsFlushing + + var actualSize = size + if actualSize == 0: + actualSize = memory.size + var flushrange = VkMappedMemoryRange( + sType: VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, + memory: memory.vk, + offset: VkDeviceSize(offset), + size: VkDeviceSize(size) + ) + checkVkResult memory.device.vk.vkInvalidateMappedMemoryRanges(memoryRangeCount=1, pMemoryRanges=addr(flushrange)) + +proc free*(memory: var DeviceMemory) = + assert memory.device.vk.valid + assert memory.vk.valid + + memory.device.vk.vkFreeMemory(memory.vk, nil) + memory.vk.reset