/// <summary> /// Reads the specified memory object associated with this command queue. /// </summary> /// <param name="memoryObject">The memory object that is to be read.</param> /// <param name="outputSize">The number of array elements that are to be returned.</param> /// <typeparam name="T">The type of the array that is to be returned.</typeparam> /// <returns>Returns the value of the memory object.</param> public void EnqueueWriteBuffer <T>(MemoryObject memoryObject, T[] value) where T : struct { // Tries to read the memory object GCHandle h = GCHandle.Alloc(value, GCHandleType.Pinned); IntPtr resultValuePointer = h.AddrOfPinnedObject(); try { // Allocates enough memory for the result value int size = Marshal.SizeOf <T>() * value.Length; // Reads the memory object, by enqueuing the read operation to the command queue IntPtr waitEventPointer; Result result = EnqueuedCommandsNativeApi.EnqueueWriteBuffer(Handle, memoryObject.Handle, 1, UIntPtr.Zero, new UIntPtr((uint)size), resultValuePointer, 0, null, out waitEventPointer); // Checks if the read operation was queued successfuly, if not, an exception is thrown if (result != Result.Success) { throw new OpenClException("The memory object could not be written to.", result); } } finally { // Finally the allocated memory has to be freed if (resultValuePointer != IntPtr.Zero) { h.Free(); } } }
public void EnqueueWriteBuffer <T>(MemoryObject memoryObject, T[] buffer, int length) { #if UNSAFE switch (buffer) { case long[] longArray: unsafe { fixed(long *longPtr = longArray) { Result result = EnqueuedCommandsNativeApi.EnqueueWriteBuffer(this.Handle, memoryObject.Handle, 1, new UIntPtr(0), new UIntPtr((uint)(length * Marshal.SizeOf <T>())), (IntPtr)((void *)longPtr), 0, null, out IntPtr waitEventPointer); // Checks if the read operation was queued successfuly, if not, an exception is thrown if (result != Result.Success) { throw new OpenClException("The memory object could not be read.", result); } } } break; default: byte[] tempBuffer = new byte[length * Marshal.SizeOf <T>()]; Buffer.BlockCopy(buffer, 0, tempBuffer, 0, tempBuffer.Length); IntPtr bufferPtr = Marshal.AllocHGlobal(tempBuffer.Length); try { Marshal.Copy(tempBuffer, 0, bufferPtr, tempBuffer.Length); Result result = EnqueuedCommandsNativeApi.EnqueueWriteBuffer(this.Handle, memoryObject.Handle, 1, new UIntPtr(0), new UIntPtr((uint)tempBuffer.Length), bufferPtr, 0, null, out IntPtr waitEventPointer); // Checks if the read operation was queued successfuly, if not, an exception is thrown if (result != Result.Success) { throw new OpenClException("The memory object could not be read.", result); } } finally { Marshal.FreeHGlobal(bufferPtr); } break; } #else byte[] tempBuffer = new byte[length * Marshal.SizeOf <T>()]; Buffer.BlockCopy(buffer, 0, tempBuffer, 0, tempBuffer.Length); IntPtr bufferPtr = Marshal.AllocHGlobal(tempBuffer.Length); try { Marshal.Copy(tempBuffer, 0, bufferPtr, tempBuffer.Length); Result result = EnqueuedCommandsNativeApi.EnqueueWriteBuffer(this.Handle, memoryObject.Handle, 1, new UIntPtr(0), new UIntPtr((uint)tempBuffer.Length), bufferPtr, 0, null, out IntPtr waitEventPointer); // Checks if the read operation was queued successfuly, if not, an exception is thrown if (result != Result.Success) { throw new OpenClException("The memory object could not be read.", result); } } #endif }
/// <summary> /// Enqueues a n-dimensional kernel to the command queue, which is executed asynchronously. /// </summary> /// <param name="kernel">The kernel that is to be enqueued.</param> /// <param name="workDimension">The dimensionality of the work.</param> /// <param name="workUnitsPerKernel">The number of work units per kernel.</param> /// <exception cref="OpenClException"> /// If the kernel could not be enqueued, then an <see cref="OpenClException" /> is /// thrown. /// </exception> public Task EnqueueNDRangeKernelAsync(Kernel kernel, int workDimension, int workUnitsPerKernel) { // Creates a new task completion source, which is used to signal when the command has completed TaskCompletionSource <bool> taskCompletionSource = new TaskCompletionSource <bool>(); // Enqueues the kernel Result result = EnqueuedCommandsNativeApi.EnqueueNDRangeKernel( Handle, kernel.Handle, ( uint )workDimension, null, new[] { new IntPtr(workUnitsPerKernel) }, null, 0, null, out IntPtr waitEventPointer ); // Checks if the kernel was enqueued successfully, if not, then an exception is thrown if (result != Result.Success) { throw new OpenClException("The kernel could not be enqueued.", result); } // Subscribes to the completed event of the wait event that was returned, when the command finishes, the task completion source is resolved AwaitableEvent awaitableEvent = new AwaitableEvent(waitEventPointer); awaitableEvent.OnCompleted += (sender, e) => { try { if (awaitableEvent.CommandExecutionStatus == CommandExecutionStatus.Error) { taskCompletionSource.TrySetException( new OpenClException( $"The command completed with the error code {awaitableEvent.CommandExecutionStatusCode}." ) ); } else { taskCompletionSource.TrySetResult(true); } } catch (Exception exception) { taskCompletionSource.TrySetException(exception); } finally { awaitableEvent.Dispose(); } }; return(taskCompletionSource.Task); }
public void EnqueueFillBuffer(MemoryObject memoryObject, int size, IntPtr pattern) { Result result = EnqueuedCommandsNativeApi.EnqueueFillBuffer(this.Handle, memoryObject.Handle, pattern, new UIntPtr(4), UIntPtr.Zero, new UIntPtr((uint)size), 0, null, out IntPtr waitEventPointer); // Checks if the read operation was queued successfuly, if not, an exception is thrown if (result != Result.Success) { throw new OpenClException("The memory object could not be read.", result); } }
public void UploadToMemory(MemoryAllocation mem, int mem_offset, int sizeInBytes, IntPtr data, bool IsBlocking) { IntPtr ev = IntPtr.Zero; var errCodeWrite = EnqueuedCommandsNativeApi.EnqueueWriteBuffer(commandQueue, mem.buffer, IsBlocking ? 1U : 0U, new UIntPtr((uint)mem_offset * 4U), new UIntPtr((uint)sizeInBytes), data, 0, null, out ev); ThrowOnError(errCodeWrite, String.Format("Failed to enqueue write buffer. Write-size:{0}, Target buffer size: {1}", sizeInBytes, mem.bufferSizeInBytes)); var errCodeEv = EventsNativeApi.ReleaseEvent(ev); ThrowOnError(errCodeEv, String.Format("Failed release event (EnqueueWriteBuffer, UploadToMemory_1)")); }
public void EnqueueKernel(string kernelName, IntPtr[] globalWorkSize, IntPtr[] localWorkSize) { IntPtr ev = IntPtr.Zero; var errCodeRunKernel = EnqueuedCommandsNativeApi.EnqueueNDRangeKernel(commandQueue, kernels[kernelName], (uint)globalWorkSize.Length, null, globalWorkSize, localWorkSize, 0, null, out ev); ThrowOnError(errCodeRunKernel, String.Format("Failed to enqueue kernel {0}.", kernelName)); var errCodeEv = EventsNativeApi.ReleaseEvent(ev); ThrowOnError(errCodeEv, String.Format("Failed release event (EnqueueNDRangeKernel)")); }
public void ReadBuffer(MemoryAllocation mem, bool isBlocking, UIntPtr offset, UIntPtr lengthInBytes, IntPtr output) { IntPtr ev = IntPtr.Zero; var errCodeRead = EnqueuedCommandsNativeApi.EnqueueReadBuffer(commandQueue, mem.buffer, isBlocking ? 1U : 0U, offset, lengthInBytes, output, 0, null, out ev); ThrowOnError(errCodeRead, String.Format("Failed to enqueue read buffer. Read Size: {0}, Buffer size: {1}", lengthInBytes, mem.bufferSizeInBytes)); var errCodeEv = EventsNativeApi.ReleaseEvent(ev); ThrowOnError(errCodeEv, String.Format("Failed release event (EnqueueReadBuffer)")); }
/// <summary> /// Enqueues a n-dimensional kernel to the command queue. /// </summary> /// <param name="kernel">The kernel that is to be enqueued.</param> /// <param name="workDimension">The dimensionality of the work.</param> /// <param name="workUnitsPerKernel">The number of work units per kernel.</param> /// <exception cref="OpenClException">If the kernel could not be enqueued, then an <see cref="OpenClException"/> is thrown.</exception> public void EnqueueNDRangeKernel(Kernel kernel, int workDimension, int workUnitsPerKernel) { // Enqueues the kernel IntPtr waitEventPointer; Result result = EnqueuedCommandsNativeApi.EnqueueNDRangeKernel(this.Handle, kernel.Handle, (uint)workDimension, null, new IntPtr[] { new IntPtr(workUnitsPerKernel) }, null, 0, null, out waitEventPointer); // Checks if the kernel was enqueued successfully, if not, then an exception is thrown if (result != Result.Success) { throw new OpenClException("The kernel could not be enqueued.", result); } }
/// <summary> /// Enqueues a n-dimensional kernel to the command queue. /// </summary> /// <param name="kernel">The kernel that is to be enqueued.</param> /// <param name="workDimension">The dimensionality of the work.</param> /// <param name="workUnitsPerKernel">The number of work units per kernel.</param> /// <exception cref="OpenClException">If the kernel could not be enqueued, then an <see cref="OpenClException"/> is thrown.</exception> public void EnqueueNDRangeKernel(Kernel kernel, int workDimension, int globalSize, int localSize, int offset = 0) { // Enqueues the kernel IntPtr waitEventPointer = IntPtr.Zero; Result result = EnqueuedCommandsNativeApi.EnqueueNDRangeKernel(this.Handle, kernel.Handle, (uint)workDimension, new IntPtr[] { new IntPtr(offset) }, new IntPtr[] { new IntPtr(globalSize) }, new IntPtr[] { new IntPtr(localSize) }, 0, null, waitEventPointer); // Checks if the kernel was enqueued successfully, if not, then an exception is thrown if (result != Result.Success) { throw new OpenClException("The kernel could not be enqueued.", result); } }
public MemoryAllocation GetMemoryFor(int requiredSizeInBytes, MemoryFlag flags, IntPtr data, int data_size_in_bytes = -1) { if (!IsInitialized()) { return(null); } var accessFlags = flags & (MemoryFlag.ReadOnly | MemoryFlag.WriteOnly | MemoryFlag.ReadWrite); MemoryAllocation candidate = null; uint bestMatchingSize = uint.MaxValue; int itemToSwap = -1; for (int i = 0; i < freeMemoryAllocations.Count; i++) { var item = freeMemoryAllocations[i]; if (item.flags == accessFlags && item.bufferSizeInBytes >= requiredSizeInBytes && item.bufferSizeInBytes < bestMatchingSize) //Select the smallest sufficient memory allocation from our allocations { bestMatchingSize = item.bufferSizeInBytes; candidate = item; itemToSwap = i; if (item.bufferSizeInBytes == requiredSizeInBytes) { break; } } } if (candidate == null) { candidate = CreateMemoryAllocation(clContext, (uint)requiredSizeInBytes, accessFlags, IntPtr.Zero); usedMemoryAllocations.Add(candidate); } else { freeMemoryAllocations.RemoveAt(itemToSwap); usedMemoryAllocations.Add(candidate); } if (flags.HasFlag(MemoryFlag.CopyHostPointer) && data != IntPtr.Zero) { int upload_size_in_bytes = data_size_in_bytes >= 0 ? data_size_in_bytes : requiredSizeInBytes; IntPtr ev = IntPtr.Zero; var errCodeWrite = EnqueuedCommandsNativeApi.EnqueueWriteBuffer(commandQueue, candidate.buffer, 0U, UIntPtr.Zero, new UIntPtr((uint)upload_size_in_bytes), data, 0, null, out ev); ThrowOnError(errCodeWrite, String.Format("Failed to enqueue write buffer. Write-size:{0}, Target buffer size: {1}", requiredSizeInBytes, candidate.bufferSizeInBytes)); var errCodeEv = EventsNativeApi.ReleaseEvent(ev); ThrowOnError(errCodeEv, String.Format("Failed release event (EnqueueWriteBuffer)")); } return(candidate); }
/// <summary> /// Reads the specified memory object associated with this command queue. /// </summary> /// <param name="memoryObject">The memory object that is to be read.</param> /// <param name="outputSize">The number of array elements that are to be returned.</param> /// <typeparam name="T">The type of the array that is to be returned.</typeparam> /// <returns>Returns the value of the memory object.</param> public T[] EnqueueReadBuffer <T>(MemoryObject memoryObject, int outputSize) where T : struct { // Tries to read the memory object IntPtr resultValuePointer = IntPtr.Zero; try { // Allocates enough memory for the result value int size = Marshal.SizeOf <T>() * outputSize; resultValuePointer = Marshal.AllocHGlobal(size); // Reads the memory object, by enqueuing the read operation to the command queue Result result = EnqueuedCommandsNativeApi.EnqueueReadBuffer( Handle, memoryObject.Handle, 1, UIntPtr.Zero, new UIntPtr(( uint )size), resultValuePointer, 0, null, out IntPtr _ ); // Checks if the read operation was queued successfuly, if not, an exception is thrown if (result != Result.Success) { throw new OpenClException("The memory object could not be read.", result); } // Goes through the result and converts the content of the result to an array T[] resultValue = new T[outputSize]; for (int i = 0; i < outputSize; i++) { resultValue[i] = Marshal.PtrToStructure <T>(IntPtr.Add(resultValuePointer, i * Marshal.SizeOf <T>())); } // Returns the content of the memory object return(resultValue); } finally { // Finally the allocated memory has to be freed if (resultValuePointer != IntPtr.Zero) { Marshal.FreeHGlobal(resultValuePointer); } } }
public unsafe int[] EnqueueReadBufferUnsafe(MemoryObject memoryObject, int outputSize) { IntPtr zero = IntPtr.Zero; int[] array = new int[outputSize]; fixed(int *numPtr = array) { Result result = EnqueuedCommandsNativeApi.EnqueueReadBuffer(this.Handle, memoryObject.Handle, 1U, UIntPtr.Zero, new UIntPtr((uint)(4 * outputSize)), (IntPtr)((void *)numPtr), 0U, (IntPtr[])null, zero); if (result != Result.Success) { throw new OpenClException("The memory object could not be read.", result); } } return(array); }
public void UploadToMemory(MemoryAllocation mem, int mem_offset, int data_offset, float[] data, bool IsBlocking, int size = -1) { uint uploadSize = size < 0 ? ((uint)data.Length * 4U) : (uint)size * 4U; IntPtr ev = IntPtr.Zero; Result errCodeWrite; unsafe { fixed(float *dataPtr = data) { errCodeWrite = EnqueuedCommandsNativeApi.EnqueueWriteBuffer(commandQueue, mem.buffer, IsBlocking ? 1U : 0U, new UIntPtr((uint)mem_offset), new UIntPtr(uploadSize), new IntPtr(dataPtr + data_offset), 0, null, out ev); } } ThrowOnError(errCodeWrite, String.Format("Failed to enqueue write buffer. Write-size:{0}, Target buffer size: {1}, data_offset:{2}", uploadSize, mem.bufferSizeInBytes, data_offset * 4)); var errCodeEv = EventsNativeApi.ReleaseEvent(ev); ThrowOnError(errCodeEv, String.Format("Failed to release event (EnqueueWriteBuffer, UploadToMemory_3)")); }
public int EnqueueReadBufferU32(MemoryObject memoryObject) { try { // Reads the memory object, by enqueuing the read operation to the command queue IntPtr waitEventPointer = IntPtr.Zero; Result result = EnqueuedCommandsNativeApi.EnqueueReadBuffer(this.Handle, memoryObject.Handle, 1, UIntPtr.Zero, new UIntPtr((uint)4), resultValuePointer, 0, null, waitEventPointer); // Checks if the read operation was queued successfuly, if not, an exception is thrown if (result != Result.Success) { throw new OpenClException("The memory object could not be read.", result); } // Goes through the result and converts the content of the result to an array int resU32 = Marshal.ReadInt32(resultValuePointer); // Returns the content of the memory object return(resU32); } finally { } }
public void EnqueueWriteBufferEdges(MemoryObject memoryObject, long[] edges) { IntPtr waitEventPointer = IntPtr.Zero; IntPtr edgesPtr = Marshal.AllocHGlobal(8 * edges.Length); try { Marshal.Copy(edges, 0, edgesPtr, edges.Length); Result result = EnqueuedCommandsNativeApi.EnqueueWriteBuffer(this.Handle, memoryObject.Handle, 1, new UIntPtr((uint)0), new UIntPtr((uint)edges.Length * 8), edgesPtr, 0, null, waitEventPointer); // Checks if the read operation was queued successfuly, if not, an exception is thrown if (result != Result.Success) { throw new OpenClException("The memory object could not be read.", result); } } finally { Marshal.FreeHGlobal(edgesPtr); } }
/// <summary> /// Reads the specified memory object associated with this command queue asynchronously. /// </summary> /// <param name="memoryObject">The memory object that is to be read.</param> /// <param name="outputSize">The number of array elements that are to be returned.</param> /// <typeparam name="T">The type of the array that is to be returned.</typeparam> /// <returns>Returns the value of the memory object.</param> public Task <T[]> EnqueueReadBufferAsync <T>(MemoryObject memoryObject, int outputSize) where T : struct { // Creates a new task completion source, which is used to signal when the command has completed TaskCompletionSource <T[]> taskCompletionSource = new TaskCompletionSource <T[]>(); // Allocates enough memory for the result value IntPtr resultValuePointer = IntPtr.Zero; int size = Marshal.SizeOf <T>() * outputSize; resultValuePointer = Marshal.AllocHGlobal(size); // Reads the memory object, by enqueuing the read operation to the command queue IntPtr waitEventPointer; Result result = EnqueuedCommandsNativeApi.EnqueueReadBuffer(Handle, memoryObject.Handle, 1, UIntPtr.Zero, new UIntPtr((uint)size), resultValuePointer, 0, null, out waitEventPointer); // Checks if the read operation was queued successfuly, if not, an exception is thrown if (result != Result.Success) { throw new OpenClException("The memory object could not be read.", result); } // Subscribes to the completed event of the wait event that was returned, when the command finishes, the task completion source is resolved AwaitableEvent awaitableEvent = new AwaitableEvent(waitEventPointer); awaitableEvent.OnCompleted += (sender, e) => { try { // Checks if the command was executed successfully, if not, then an exception is thrown if (awaitableEvent.CommandExecutionStatus == CommandExecutionStatus.Error) { taskCompletionSource.TrySetException(new OpenClException( $"The command completed with the error code {awaitableEvent.CommandExecutionStatusCode}.")); return; } // Goes through the result and converts the content of the result to an array T[] resultValue = new T[outputSize]; for (int i = 0; i < outputSize; i++) { resultValue[i] = Marshal.PtrToStructure <T>(IntPtr.Add(resultValuePointer, i * Marshal.SizeOf <T>())); } // Sets the result taskCompletionSource.TrySetResult(resultValue); } catch (Exception exception) { taskCompletionSource.TrySetException(exception); } finally { // Finally the allocated memory has to be freed and the allocated resources are disposed of if (resultValuePointer != IntPtr.Zero) { Marshal.FreeHGlobal(resultValuePointer); } awaitableEvent.Dispose(); } }; // Returns the task completion source, which resolves when the command has finished return(taskCompletionSource.Task); }
/// <summary> /// Reads the specified memory object associated with this command queue. /// </summary> /// <param name="memoryObject">The memory object that is to be read.</param> /// <param name="outputLength">The number of array elements that are to be filled.</param> /// <typeparam name="T">The type of the array that is to be returned.</typeparam> /// <returns>Returns the value of the memory object.</param> public unsafe void EnqueueReadBuffer <T>(MemoryObject memoryObject, int outputLength, ref T[] output) { switch (output) { case uint[] uintArray: unsafe { fixed(uint *uintPtr = uintArray) { Result result = EnqueuedCommandsNativeApi.EnqueueReadBuffer(this.Handle, memoryObject.Handle, 1, UIntPtr.Zero, new UIntPtr((uint)(sizeof(uint) * outputLength)), (IntPtr)((void *)uintPtr), 0, null, out IntPtr zero); if (result != Result.Success) { throw new OpenClException("The memory object could not be read.", result); } } break; } case int[] intArray: unsafe { fixed(int *intPtr = intArray) { Result result = EnqueuedCommandsNativeApi.EnqueueReadBuffer(this.Handle, memoryObject.Handle, 1, UIntPtr.Zero, new UIntPtr((uint)(sizeof(int) * outputLength)), (IntPtr)((void *)intPtr), 0, null, out IntPtr zero); if (result != Result.Success) { throw new OpenClException("The memory object could not be read.", result); } } break; } case byte[] byteArray: unsafe { fixed(byte *bytePtr = byteArray) { Result result = EnqueuedCommandsNativeApi.EnqueueReadBuffer(this.Handle, memoryObject.Handle, 1, UIntPtr.Zero, new UIntPtr((uint)(outputLength)), (IntPtr)((void *)bytePtr), 0, null, out IntPtr zero); if (result != Result.Success) { throw new OpenClException("The memory object could not be read.", result); } } break; } case sbyte[] sbyteArray: unsafe { fixed(sbyte *sbytePtr = sbyteArray) { Result result = EnqueuedCommandsNativeApi.EnqueueReadBuffer(this.Handle, memoryObject.Handle, 1, UIntPtr.Zero, new UIntPtr((uint)(outputLength)), (IntPtr)((void *)sbytePtr), 0, null, out IntPtr zero); if (result != Result.Success) { throw new OpenClException("The memory object could not be read.", result); } } break; } case ulong[] ulongArray: unsafe { fixed(ulong *ulongPtr = ulongArray) { Result result = EnqueuedCommandsNativeApi.EnqueueReadBuffer(this.Handle, memoryObject.Handle, 1, UIntPtr.Zero, new UIntPtr((uint)(sizeof(ulong) * outputLength)), (IntPtr)((void *)ulongPtr), 0, null, out IntPtr zero); if (result != Result.Success) { throw new OpenClException("The memory object could not be read.", result); } } break; } case long[] longArray: unsafe { fixed(long *longPtr = longArray) { Result result = EnqueuedCommandsNativeApi.EnqueueReadBuffer(this.Handle, memoryObject.Handle, 1, UIntPtr.Zero, new UIntPtr((uint)(sizeof(long) * outputLength)), (IntPtr)((void *)longPtr), 0, null, out IntPtr zero); if (result != Result.Success) { throw new OpenClException("The memory object could not be read.", result); } } break; } default: throw new NotSupportedException("Non-blittable types are not supported."); } }
/// <summary> /// Reads the specified memory object associated with this command queue. /// </summary> /// <param name="memoryObject">The memory object that is to be read.</param> /// <param name="outputLength">The number of array elements that are to be returned.</param> /// <typeparam name="T">The type of the array that is to be returned.</typeparam> /// <returns>Returns the value of the memory object.</param> public T[] EnqueueReadBuffer <T>(MemoryObject memoryObject, int outputLength) where T : struct { T[] resultValue = new T[outputLength]; #if UNSAFE switch (resultValue) { case int[] intArray: unsafe { fixed(int *intPtr = intArray) { Result result = EnqueuedCommandsNativeApi.EnqueueReadBuffer(this.Handle, memoryObject.Handle, 1, UIntPtr.Zero, new UIntPtr((uint)(sizeof(int) * outputLength)), (IntPtr)((void *)intPtr), 0, null, out IntPtr zero); if (result != Result.Success) { throw new OpenClException("The memory object could not be read.", result); } } return(resultValue); } case uint[] uintArray: unsafe { fixed(uint *uintPtr = uintArray) { Result result = EnqueuedCommandsNativeApi.EnqueueReadBuffer(this.Handle, memoryObject.Handle, 1, UIntPtr.Zero, new UIntPtr((uint)(sizeof(uint) * outputLength)), (IntPtr)((void *)uintPtr), 0, null, out IntPtr zero); if (result != Result.Success) { throw new OpenClException("The memory object could not be read.", result); } } return(resultValue); } default: // Tries to read the memory object IntPtr resultValuePointer = IntPtr.Zero; try { // Allocates enough memory for the result value int size = Marshal.SizeOf <T>() * outputLength; resultValuePointer = Marshal.AllocHGlobal(size); // Reads the memory object, by enqueuing the read operation to the command queue IntPtr waitEventPointer; Result result = EnqueuedCommandsNativeApi.EnqueueReadBuffer(this.Handle, memoryObject.Handle, 1, UIntPtr.Zero, new UIntPtr((uint)size), resultValuePointer, 0, null, out waitEventPointer); // Checks if the read operation was queued successfuly, if not, an exception is thrown if (result != Result.Success) { throw new OpenClException("The memory object could not be read.", result); } // Goes through the result and converts the content of the result to an array for (int i = 0; i < outputLength; i++) { resultValue[i] = Marshal.PtrToStructure <T>(IntPtr.Add(resultValuePointer, i * Marshal.SizeOf <T>())); } // Returns the content of the memory object return(resultValue); } finally { // Finally the allocated memory has to be freed if (resultValuePointer != IntPtr.Zero) { Marshal.FreeHGlobal(resultValuePointer); } } } #else // Tries to read the memory object IntPtr resultValuePointer = IntPtr.Zero; try { // Allocates enough memory for the result value int size = Marshal.SizeOf <T>() * outputLength; resultValuePointer = Marshal.AllocHGlobal(size); // Reads the memory object, by enqueuing the read operation to the command queue IntPtr waitEventPointer; Result result = EnqueuedCommandsNativeApi.EnqueueReadBuffer(this.Handle, memoryObject.Handle, 1, UIntPtr.Zero, new UIntPtr((uint)size), resultValuePointer, 0, null, out waitEventPointer); // Checks if the read operation was queued successfuly, if not, an exception is thrown if (result != Result.Success) { throw new OpenClException("The memory object could not be read.", result); } // Goes through the result and converts the content of the result to an array for (int i = 0; i < outputLength; i++) { resultValue[i] = Marshal.PtrToStructure <T>(IntPtr.Add(resultValuePointer, i * Marshal.SizeOf <T>())); } // Returns the content of the memory object return(resultValue); } finally { // Finally the allocated memory has to be freed if (resultValuePointer != IntPtr.Zero) { Marshal.FreeHGlobal(resultValuePointer); } } #endif }