internal void Return(VulkanMemorySlice returnSlice)
        {
            DebugHelper.AssertThrow <InvalidOperationException>(returnSlice.vkDeviceMemory.Handle == vkDeviceMemory.Handle);

            //First try to merge with existing free slices
            for (int i = 0; i < freeSlices.Count; i++)
            {
                var   slice         = freeSlices[i];
                ulong sizeWithAlign = returnSlice.size + returnSlice.alignOffset;

                if (slice.startIndex == returnSlice.offset + sizeWithAlign)
                {
                    slice.length     += sizeWithAlign;
                    slice.startIndex -= sizeWithAlign;
                    freeSlices[i]     = slice;
                    return;
                }
            }
            //If not possible insert to the list
            FreeSlice newSlice = new FreeSlice()
            {
                length = returnSlice.size + returnSlice.alignOffset, startIndex = returnSlice.offset - returnSlice.alignOffset
            };

            //freeSlices.Add(newSlice);

            //Add and sort in ascending order by length
            for (int i = 0; i < freeSlices.Count; i++)
            {
                if (freeSlices[i].length > newSlice.length)
                {
                    freeSlices.Insert(i, newSlice);
                    return;
                }
            }
            //If largest, add to the end
            freeSlices.Add(newSlice);
        }
        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));
            }
        }