Mercurial > games > semicongine
view src/semicongine/vulkan/memory.nim @ 588:008592db0442
did: big refactoring
author | Sam <sam@basx.dev> |
---|---|
date | Wed, 12 Apr 2023 01:20:53 +0700 |
parents | 87e500bd528a |
children | a46923cb0790 |
line wrap: on
line source
import std/strformat import std/algorithm import ./api 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 proc getPhysicalDeviceMemoryProperties(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, flags: openArray[VkMemoryPropertyFlagBits]): DeviceMemory = assert device.vk.valid assert size > 0 result.device = device result.size = size var hasAllFlags: bool matchingTypes: seq[MemoryType] for mtype in device.physicalDevice.vk.getPhysicalDeviceMemoryProperties.types: hasAllFlags = true for flag in flags: if not (flag in mtype.flags): hasAllFlags = false break if hasAllFlags: matchingTypes.add mtype if matchingTypes.len == 0: raise newException(Exception, &"No memory with support for {flags}") matchingTypes.sort(cmp= proc(a, b: MemoryType): int = cmp(a.heap.size, b.heap.size)) result.memoryType = matchingTypes[^1] result.canMap = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT in result.memoryType.flags result.needsFlushing = not (VK_MEMORY_PROPERTY_HOST_COHERENT_BIT in result.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) ) proc allocate*(device: Device, size: uint64, useVRAM: bool, mappable: bool, autoFlush: bool): DeviceMemory = var flags: seq[VkMemoryPropertyFlagBits] if useVRAM: flags.add VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT if mappable: flags.add VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT if autoFlush: flags.add VK_MEMORY_PROPERTY_HOST_COHERENT_BIT device.allocate(size=size, flags=flags) # 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