internal VulkanMemorySlice(VulkanMemoryPool originPool, ulong size, ulong offset, ulong alignOffset, VkDeviceMemory vkDeviceMemory, uint memoryTypeIndex, VkMemoryPropertyFlags memoryPropertyFlags) { this.originPool = originPool; this.memoryTypeIndex = memoryTypeIndex; this.memoryPropertyFlags = memoryPropertyFlags; this.vkDeviceMemory = vkDeviceMemory; this.size = size; this.offset = offset; this.alignOffset = alignOffset; disposed = false; hostVisible = (memoryPropertyFlags & VkMemoryPropertyFlags.HostVisible) != 0; }
public VulkanMemorySlice Allocate(ulong size, ulong alignment, uint memoryTypeBits, bool hostVisible, bool preferDeviceLocal = true) { VkMemoryPropertyFlags requiredMemProps = VkMemoryPropertyFlags.DeviceLocal; VkMemoryPropertyFlags preferredMemProps = preferDeviceLocal ? VkMemoryPropertyFlags.None : VkMemoryPropertyFlags.DeviceLocal; if (hostVisible) { requiredMemProps = VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent; } if (AllocateFromPools(size, alignment, memoryTypeBits, requiredMemProps, preferredMemProps, hostVisible, out VulkanMemorySlice allocation)) { return(allocation); } uint memoryTypeIndex = GetPreferredMemoryType(memoryTypeBits, requiredMemProps, preferredMemProps); VkMemoryPropertyFlags memProps = device.DeviceMemoryProperties.GetMemoryType(memoryTypeIndex).propertyFlags; VulkanMemoryPool newMemoryPool = new VulkanMemoryPool(device, PoolSize, memoryTypeIndex, memProps, hostVisible); var result = newMemoryPool.AllocateDeviceMemory(); if (result != VkResult.Success) { requiredMemProps = VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent; preferredMemProps = VkMemoryPropertyFlags.None; memoryTypeIndex = GetPreferredMemoryType(memoryTypeBits, requiredMemProps, preferredMemProps); memProps = device.DeviceMemoryProperties.GetMemoryType(memoryTypeIndex).propertyFlags; newMemoryPool = new VulkanMemoryPool(device, PoolSize, memoryTypeIndex, memProps, hostVisible); result = newMemoryPool.AllocateDeviceMemory(); if (result != VkResult.Success) { throw new OutOfMemoryException(result.ToString()); } } memoryPools.Add(newMemoryPool); result = newMemoryPool.Allocate(size, alignment, out allocation); if (result != VkResult.Success) { throw new OutOfMemoryException(result.ToString()); } return(allocation); }
private void CreateNext(ulong newSize) { next = new VulkanMemoryPool(device, newSize, memoryTypeIndex, memoryPropertyFlags, hostVisible); }
public VkResult Allocate(ulong size, ulong alignment, out VulkanMemorySlice outSlice) { if (size > max_size) { CreateNext(size); var allocResult = next.AllocateDeviceMemory(); if (allocResult != VkResult.Success) { next = null; outSlice = null; return(allocResult); } return(next.Allocate(size, alignment, out outSlice)); } VulkanMemorySlice returnSlice = null; for (int i = 0; i < freeSlices.Count; i++) { FreeSlice slice = freeSlices[i]; //align the slice to alignment uint align = slice.startIndex % alignment == 0 ? 0 : ((uint)alignment - ((uint)slice.startIndex % (uint)alignment)); ulong sizeWithAlign = size + align; if (slice.length >= sizeWithAlign) { returnSlice = new VulkanMemorySlice(this, size, slice.startIndex + align, align, vkDeviceMemory, memoryTypeIndex, memoryPropertyFlags); slice.length -= sizeWithAlign; slice.startIndex += sizeWithAlign; if (slice.length == 0) { freeSlices.RemoveAt(i); } else { freeSlices[i] = slice; } break; } } if (returnSlice != null) { outSlice = returnSlice; return(VkResult.Success); } else { CreateNext(max_size); var allocResult = next.AllocateDeviceMemory(); if (allocResult != VkResult.Success) { next = null; outSlice = null; return(allocResult); } return(next.Allocate(size, alignment, out outSlice)); } }
private bool AllocateFromPools(ulong size, ulong alignment, uint memoryTypeBits, VkMemoryPropertyFlags required, VkMemoryPropertyFlags preferred, bool hostVisible, out VulkanMemorySlice allocation) { var physicalMemoryProperties = device.DeviceMemoryProperties; //Match for preferred for (int i = 0; i < memoryPools.Count; i++) { VulkanMemoryPool pool = memoryPools[i]; uint memoryTypeIndex = pool.memoryTypeIndex; if (pool.hostVisible != hostVisible) { continue; } //Match memoryTypeIndex of the pool if ((((int)memoryTypeBits >> (int)memoryTypeIndex) & 1) == 0) { continue; } // Match required memory properties VkMemoryPropertyFlags properties = physicalMemoryProperties.GetMemoryType(memoryTypeIndex).propertyFlags; if ((properties & required) != required) { continue; } // Match preferred if ((properties & preferred) != preferred) { continue; } var result = pool.Allocate(size, alignment, out allocation); if (result != VkResult.Success) { continue; } return(true); } //Match only required for (int i = 0; i < memoryPools.Count; i++) { VulkanMemoryPool pool = memoryPools[i]; uint memoryTypeIndex = pool.memoryTypeIndex; if (pool.hostVisible != hostVisible) { continue; } //Match memoryTypeIndex of the pool if ((((int)memoryTypeBits >> (int)memoryTypeIndex) & 1) == 0) { continue; } // Match required memory properties VkMemoryPropertyFlags properties = physicalMemoryProperties.GetMemoryType(memoryTypeIndex).propertyFlags; if ((properties & required) != required) { continue; } var result = pool.Allocate(size, alignment, out allocation); if (result != VkResult.Success) { continue; } return(true); } allocation = null; return(false); }