public Node TryAllocate(ulong size, ulong alignment) { var free = TreeSearch(size + alignment - 1); if (free == null) { return(null); } TreeRemove(free); var offset = GraphicsUtility.AlignUp(free.Offset, alignment); if (offset > free.Offset) { var frag = new Node { Offset = free.Offset, Size = offset - free.Offset }; TreeInsert(frag); ListInsertBefore(free, frag); } if (offset + size < free.Offset + free.Size) { var frag = new Node { Offset = offset + size, Size = free.Offset + free.Size - offset - size }; TreeInsert(frag); ListInsertAfter(free, frag); } free.Offset = offset; free.Size = size; return(free); }
private void FlushOrInvalidateMappedMemoryRange(MemoryAlloc alloc, ulong offset, ulong size, bool flush) { if (alloc.Allocator != this) { throw new ArgumentException(nameof(alloc)); } if (alloc.Size < offset + size) { throw new ArgumentException(); } if (size == 0) { return; } var memoryType = alloc.Memory.Type; var hostCoherent = (memoryType.PropertyFlags & SharpVulkan.MemoryPropertyFlags.HostCoherent) != 0; if (hostCoherent) { return; } var nonCoherentAtomSize = Context.PhysicalDeviceLimits.NonCoherentAtomSize; var rangeStart = GraphicsUtility.AlignDown(alloc.Offset + offset, nonCoherentAtomSize); var rangeEnd = GraphicsUtility.AlignUp(alloc.Offset + offset + size, nonCoherentAtomSize); if (rangeEnd > alloc.Memory.Size) { rangeEnd = alloc.Memory.Size; } var range = new SharpVulkan.MappedMemoryRange { StructureType = SharpVulkan.StructureType.MappedMemoryRange, Memory = alloc.Memory.Memory, Offset = rangeStart, Size = rangeEnd - rangeStart }; if (flush) { Context.Device.FlushMappedMemoryRanges(1, &range); } else { Context.Device.InvalidateMappedMemoryRanges(1, &range); } }
public UploadBufferAlloc Allocate(ulong size, ulong alignment) { var alignedOffset = GraphicsUtility.AlignUp(bufferOffset, alignment); if (alignedOffset + size > bufferSize) { var newBufferSize = bufferSize; while (newBufferSize < size) { newBufferSize *= 2; } ReleaseBuffer(); CreateBuffer(newBufferSize); alignedOffset = 0; } bufferOffset = alignedOffset + size; return(new UploadBufferAlloc(buffer, new IntPtr((byte *)mappedMemory + alignedOffset), alignedOffset, size)); }
private void CreateBuffer() { var alignedSliceSize = GraphicsUtility.AlignUp(sliceSize, sliceAlignment); var bufferSize = sliceCount * alignedSliceSize; var createInfo = new SharpVulkan.BufferCreateInfo { StructureType = SharpVulkan.StructureType.BufferCreateInfo, Size = bufferSize, SharingMode = SharpVulkan.SharingMode.Exclusive, Usage = usage }; buffer = context.Device.CreateBuffer(ref createInfo); memory = context.MemoryAllocator.Allocate(buffer, memoryPropertyFlags); sliceQueue.Clear(); for (ulong i = 0; i < sliceCount; i++) { sliceQueue.Enqueue(new SliceEntry { Offset = i * alignedSliceSize }); } Generation++; }