{.experimental: "codeReordering".} import vulkan , vkTypes , vulkan_utils , ../utils/[lets ] , bitops type Buffer_Object = object of RootObj device_memory*: VkDeviceMemory vk_buffer*: VkBuffer size*: VkDeviceSize data*: ptr char current_data_offset*: Natural Buffer* = ref object of Buffer_Object #[ Buffer& result , VkDevice device , const VkPhysicalDeviceMemoryProperties& memoryProperties , size_t size , VkBufferUsageFlags usage , VkMemoryPropertyFlags memoryFlags ]# proc a_vulkan_buffer*( vk_device: VkDevice , gpu_memory_properties: VkPhysicalDeviceMemoryProperties , buffer_usage_flags: VkBufferUsageFlags , memory_flags: VkMemoryPropertyFlags , allocation_size: VkDeviceSize ): Buffer = result = Buffer( size: allocation_size ) var mem_reqs: VkMemoryRequirements buffer_info = VkBufferCreateInfo( sType: VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO , size: allocation_size ) allocation_info = VkMemoryAllocateInfo(sType: VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO ) memory_allocation_flag_info = VkMemoryAllocateFlagsInfo( sType: VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO_KHR ) assert vkCreateBuffer( vk_device , addr buffer_info , nil , addr result.vk_buffer ) == VK_SUCCESS vkGetBufferMemoryRequirements( vk_device , result.vk_buffer , addr mem_reqs ) allocation_info.allocationSize = mem_reqs.size allocation_info.memoryTypeIndex = gpu_memory_properties.find_memory_with_property( mem_reqs.memoryTypeBits , memory_flags ) if bitand( buffer_usage_flags.int , VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT.ord ) == 1: allocation_info.pNext = addr memory_allocation_flag_info memory_allocation_flag_info.flags = VkMemoryAllocateFlags VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT memory_allocation_flag_info.deviceMask = 1 discard vkAllocateMemory( vk_device , addr allocation_info , nil , addr result.device_memory ) discard vkBindBufferMemory( vk_device , result.vk_buffer , result.device_memory , VkDeviceSize 0 ) if bitand( memory_flags.int , VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT.ord ) == 1: assert vkMapMemory( vk_device , result.device_memory , VkDeviceSize 0 , allocation_size , VkMemoryMapFlags 0 , cast[ptr pointer] (result.data) ) == VK_SUCCESS #[ result.descriptor.buffer = result.vk_buffer result.descriptor.offset = VkDeviceSize 0 result.descriptor.range = VkDeviceSize VK_WHOLE_SIZE ]# return result #[ proc fillDescr*( buffer: Buffer , size: VkDeviceSize = VkDeviceSize VK_WHOLE_SIZE , offset: VkDeviceSize = vk0 ) = buffer.descriptor.offset = offset buffer.descriptor.buffer = buffer.vkbuffer buffer.descriptor.range = size ]# # Map a memory range of this buffer. If successful, mapped points to the specified buffer range. # @param size (Optional) Size of the memory range to map. Pass VK_WHOLE_SIZE to map the complete buffer range. # @param offset (Optional) Byte offset from beginning proc map_memory*( vk_device: VkDevice , memory: VkDeviceMemory , data: var pointer , size: VkDeviceSize = vkWholeSize , offset: VkDeviceSize = vk0 ) = discard vkMapMemory( vk_device , memory , vk0 , size , VkMemoryMapFlags 0 , addr data ) # vkUnmapMemory can't fail (?) proc unMapMem*( buffer: var Buffer , data: var pointer ) = if not data.isNil: data = nil # # Copies the specified data to the mapped buffer # # @param data Pointer to the data to copy # # @param size Size of the data to copy in machine units # proc copyTo*( data: pointer # , buffer: Buffer # , size: Natural # ) = # assert not buffer.mapped.isNil # copyMem(data, addr buffer.mapped, size) proc aVkMappedMemoryRange*( memory: VkDeviceMemory , offset: VkDeviceSize , size: VkDeviceSize , pNext: pointer = nil , sType: VkStructureType = VkStructureTypeMappedMemoryRange ): VkMappedMemoryRange = result.sType = sType result.memory = memory result.offset = offset result.pNext = pNext result.size = size # flush a memory range of the buffer to make it visible to VkDevice # Only required for non-coherent memory (?) proc flushMem*( vk_device: VkDevice , buffer: Buffer , data: pointer , offset: VkDeviceSize , size: VkDeviceSize ) = var r = aVkMappedMemoryRange( memory = buffer.device_memory , offset = offset , size = size ) discard vkFlushMappedMemoryRanges(vk_device, 1.uint32, addr r) # Invalidates a memory range of the buffer # to make it visible to the host # Only required for non-coherent memory (?) proc invalidate*( vk_device: VkDevice , buffer: Buffer , size: VkDeviceSize , offset: VkDeviceSize ) = var r = aVkMappedMemoryRange( memory = buffer.device_memory , offset = offset , size = size ) discard vkInvalidateMappedMemoryRanges(vk_device, 1, addr r) # Release all Vulkan resources held by this buffer proc destroy*( vk_device: VkDevice , buffer: var Buffer ) = vkDestroyBuffer(vk_device, buffer.vkbuffer, nil) vkFreeMemory(vk_device, buffer.device_memory, nil) #[ proc fill_descriptor*( buffer: var Buffer , size: VkDeviceSize = VkDeviceSize VK_WHOLE_SIZE , offset: VkDeviceSize = vk0 ) = buffer.descriptor.offset = offset buffer.descriptor.buffer = buffer.vkbuffer buffer.descriptor.range = size ]# proc create_command_buffers*( device: VkDevice , pool: VkCommandPool , level: VkCommandBufferLevel = VK_COMMAND_BUFFER_LEVEL_PRIMARY , amount: uint32 = 2 ): seq[VkCommandBuffer] = result.setLen amount var allocInfo = VkCommandBufferAllocateInfo( sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO , commandPool: pool , level: level , commandBufferCount: amount ) discard vkAllocateCommandBuffers( device , addr allocInfo , addr result[0] )