From 63433e38ecca4b4b4f8ba5602f7a0fa9cea7891d Mon Sep 17 00:00:00 2001 From: Marcel Koester Date: Thu, 2 Mar 2023 18:35:15 +0100 Subject: [PATCH] Added new VelocityMemoryBuffer to represent memory buffers in Velocity land. --- .../Runtime/Velocity/VelocityMemoryBuffer.cs | 152 ++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 Src/ILGPU/Runtime/Velocity/VelocityMemoryBuffer.cs diff --git a/Src/ILGPU/Runtime/Velocity/VelocityMemoryBuffer.cs b/Src/ILGPU/Runtime/Velocity/VelocityMemoryBuffer.cs new file mode 100644 index 000000000..e82ae0aaa --- /dev/null +++ b/Src/ILGPU/Runtime/Velocity/VelocityMemoryBuffer.cs @@ -0,0 +1,152 @@ +// --------------------------------------------------------------------------------------- +// ILGPU +// Copyright (c) 2022-2023 ILGPU Project +// www.ilgpu.net +// +// File: VelocityMemoryBuffer.cs +// +// This file is part of ILGPU and is distributed under the University of Illinois Open +// Source License. See LICENSE.txt for details. +// --------------------------------------------------------------------------------------- + +using ILGPU.Runtime.CPU; +using ILGPU.Util; +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Threading; + +namespace ILGPU.Runtime.Velocity +{ + /// + /// A memory buffer that lives in CPU space. + /// + public class VelocityMemoryBuffer : MemoryBuffer + { + #region Instance + + /// + /// Initializes this array view source on the CPU. + /// + /// The parent accelerator (if any). + /// The length of this source. + /// The element size. + internal VelocityMemoryBuffer( + Accelerator accelerator, + long length, + int elementSize) + : base(accelerator, length, elementSize) + { + // Ensure that all element accesses will be properly aligned + long nativeLength = length * elementSize; + int alignmentOffset = Interop.ComputeAlignmentOffset( + nativeLength, + elementSize * accelerator.WarpSize); + // Pad the length to ensure a valid buffer size + long paddedLength = nativeLength + alignmentOffset; + + // Allocate resources and assign pointers + NativeBufferPtr = Marshal.AllocHGlobal(new IntPtr(paddedLength)); + NativePtr = NativeBufferPtr + alignmentOffset; + } + + #endregion + + #region Properties + + /// + /// Returns the natively allocated underlying buffer pointer which may not be + /// aligned in all cases. + /// + public IntPtr NativeBufferPtr { get; private set; } + + #endregion + + #region Methods + + /// + protected internal override void MemSet( + AcceleratorStream stream, + byte value, + in ArrayView targetView) => + CPUMemoryBuffer.CPUMemSet( + targetView.LoadEffectiveAddressAsPtr(), + value, + 0L, + targetView.LengthInBytes); + + /// + protected internal override void CopyFrom( + AcceleratorStream stream, + in ArrayView sourceView, + in ArrayView targetView) => + CPUMemoryBuffer.CPUCopyFrom(stream, sourceView, targetView); + + /// + protected internal override void CopyTo( + AcceleratorStream stream, + in ArrayView sourceView, + in ArrayView targetView) => + CPUMemoryBuffer.CPUCopyTo(stream, sourceView, targetView); + + #endregion + + #region IDisposable + + /// + /// Disposes the underlying memory buffer. + /// + protected override void DisposeAcceleratorObject(bool disposing) + { + Marshal.FreeHGlobal(NativeBufferPtr); + NativeBufferPtr = IntPtr.Zero; + NativePtr = IntPtr.Zero; + } + + #endregion + + } + + sealed class VelocityMemoryBufferPool : VelocityMemoryBuffer + { + #region Instance + + private int sharedMemoryOffset; + + public VelocityMemoryBufferPool( + VelocityAccelerator accelerator, + int size) + : base(accelerator, size, 1) + { } + + #endregion + + #region Methods + + /// + /// Resets the internal shared memory offset. + /// + public void Reset() => sharedMemoryOffset = 0; + + /// + /// Gets a chunk of memory of a certain type. + /// + /// The number of elements. + /// The element type to allocate. + /// A view pointing to the right chunk of shared memory. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ArrayView Allocate(int length) + where T : unmanaged + { + int totalElementSize = length * Interop.SizeOf(); + int alignment = Interop.ComputeAlignmentOffset( + sharedMemoryOffset, + totalElementSize); + int newOffset = sharedMemoryOffset + alignment; + sharedMemoryOffset += alignment + totalElementSize; + return new ArrayView(this, newOffset, length); + } + + #endregion + } +}