Пример #1
0
        /// <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();
                }
            }
        }
Пример #2
0
        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
        }
Пример #3
0
        /// <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);
        }
Пример #4
0
        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);
            }
        }
Пример #5
0
        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)"));
        }
Пример #6
0
        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)"));
        }
Пример #7
0
        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)"));
        }
Пример #8
0
        /// <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);
            }
        }
Пример #9
0
        /// <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);
            }
        }
Пример #10
0
        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);
        }
Пример #11
0
        /// <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);
                }
            }
        }
Пример #12
0
        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);
        }
Пример #13
0
        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)"));
        }
Пример #14
0
        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 { }
        }
Пример #15
0
        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);
            }
        }
Пример #16
0
        /// <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);
        }
Пример #17
0
        /// <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.");
            }
        }
Пример #18
0
        /// <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
        }