/// <summary> /// Creates a new memory group, allocating it's buffers with the provided allocator. /// </summary> /// <param name="allocator">The <see cref="MemoryAllocator"/> to use.</param> /// <param name="totalLength">The total length of the buffer.</param> /// <param name="bufferAlignment">The expected alignment (eg. to make sure image rows fit into single buffers).</param> /// <param name="options">The <see cref="AllocationOptions"/>.</param> /// <returns>A new <see cref="MemoryGroup{T}"/>.</returns> /// <exception cref="InvalidMemoryOperationException">Thrown when 'blockAlignment' converted to bytes is greater than the buffer capacity of the allocator.</exception> public static MemoryGroup <T> Allocate( MemoryAllocator allocator, long totalLength, int bufferAlignment, AllocationOptions options = AllocationOptions.None) { Guard.NotNull(allocator, nameof(allocator)); Guard.MustBeGreaterThanOrEqualTo(totalLength, 0, nameof(totalLength)); Guard.MustBeGreaterThanOrEqualTo(bufferAlignment, 0, nameof(bufferAlignment)); int blockCapacityInElements = allocator.GetBufferCapacityInBytes() / ElementSize; if (bufferAlignment > blockCapacityInElements) { throw new InvalidMemoryOperationException( $"The buffer capacity of the provided MemoryAllocator is insufficient for the requested buffer alignment: {bufferAlignment}."); } if (totalLength == 0) { var buffers0 = new IMemoryOwner <T>[1] { allocator.Allocate <T>(0, options) }; return(new Owned(buffers0, 0, 0, true)); } int numberOfAlignedSegments = blockCapacityInElements / bufferAlignment; int bufferLength = numberOfAlignedSegments * bufferAlignment; if (totalLength > 0 && totalLength < bufferLength) { bufferLength = (int)totalLength; } int sizeOfLastBuffer = (int)(totalLength % bufferLength); long bufferCount = totalLength / bufferLength; if (sizeOfLastBuffer == 0) { sizeOfLastBuffer = bufferLength; } else { bufferCount++; } var buffers = new IMemoryOwner <T> [bufferCount]; for (int i = 0; i < buffers.Length - 1; i++) { buffers[i] = allocator.Allocate <T>(bufferLength, options); } if (bufferCount > 0) { buffers[buffers.Length - 1] = allocator.Allocate <T>(sizeOfLastBuffer, options); } return(new Owned(buffers, bufferLength, totalLength, true)); }
/// <summary> /// Allocates padded buffers. Generally used by encoder/decoders. /// </summary> /// <param name="memoryAllocator">The <see cref="MemoryAllocator"/>.</param> /// <param name="width">Pixel count in the row</param> /// <param name="pixelSizeInBytes">The pixel size in bytes, eg. 3 for RGB.</param> /// <param name="paddingInBytes">The padding.</param> /// <returns>A <see cref="IMemoryOwner{Byte}"/>.</returns> internal static IMemoryOwner <byte> AllocatePaddedPixelRowBuffer( this MemoryAllocator memoryAllocator, int width, int pixelSizeInBytes, int paddingInBytes) { int length = (width * pixelSizeInBytes) + paddingInBytes; return(memoryAllocator.Allocate <byte>(length)); }
public static Buffer2D <T> Allocate2D <T>( this MemoryAllocator memoryAllocator, int width, int height, AllocationOptions options = AllocationOptions.None) where T : struct { IMemoryOwner <T> buffer = memoryAllocator.Allocate <T>(width * height, options); var memorySource = new MemorySource <T>(buffer, true); return(new Buffer2D <T>(memorySource, width, height)); }
/// <summary> /// Allocates a buffer of value type objects interpreted as a 2D region /// of <paramref name="width"/> x <paramref name="height"/> elements. /// </summary> /// <typeparam name="T">The type of buffer items to allocate.</typeparam> /// <param name="memoryAllocator">The memory allocator.</param> /// <param name="width">The buffer width.</param> /// <param name="height">The buffer height.</param> /// <param name="preferContiguosImageBuffers">A value indicating whether the allocated buffer should be contiguous, unless bigger than <see cref="int.MaxValue"/>.</param> /// <param name="options">The allocation options.</param> /// <returns>The <see cref="Buffer2D{T}"/>.</returns> public static Buffer2D <T> Allocate2D <T>( this MemoryAllocator memoryAllocator, int width, int height, bool preferContiguosImageBuffers, AllocationOptions options = AllocationOptions.None) where T : struct { long groupLength = (long)width * height; MemoryGroup <T> memoryGroup; if (preferContiguosImageBuffers && groupLength < int.MaxValue) { IMemoryOwner <T> buffer = memoryAllocator.Allocate <T>((int)groupLength, options); memoryGroup = MemoryGroup <T> .CreateContiguous(buffer, false); } else { memoryGroup = memoryAllocator.AllocateGroup <T>(groupLength, width, options); } return(new Buffer2D <T>(memoryGroup, width, height)); }