/// <summary>
        /// Builds (compiles and links) a program executable from the program source or binary for all or some of the <see cref="ComputeProgram.Devices"/>.
        /// </summary>
        /// <param name="devices"> A subset or all of <see cref="ComputeProgram.Devices"/>. If <paramref name="devices"/> is <c>null</c>, the executable is built for every item of <see cref="ComputeProgram.Devices"/> for which a source or a binary has been loaded. </param>
        /// <param name="options"> A set of options for the OpenCL compiler. </param>
        /// <param name="notify"> A delegate instance that represents a reference to a notification routine. This routine is a callback function that an application can register and which will be called when the program executable has been built (successfully or unsuccessfully). If <paramref name="notify"/> is not <c>null</c>, <see cref="ComputeProgram.Build"/> does not need to wait for the build to complete and can return immediately. If <paramref name="notify"/> is <c>null</c>, <see cref="ComputeProgram.Build"/> does not return until the build has completed. The callback function may be called asynchronously by the OpenCL implementation. It is the application's responsibility to ensure that the callback function is thread-safe and that the delegate instance doesn't get collected by the Garbage Collector until the build operation triggers the callback. </param>
        /// <param name="notifyDataPtr"> Optional user data that will be passed to <paramref name="notify"/>. </param>
        public void Build(ICollection <ComputeDevice> devices, string options, ComputeProgramBuildNotifier notify, IntPtr notifyDataPtr)
        {
            int handleCount;

            CLDeviceHandle[] deviceHandles = ComputeTools.ExtractHandles(devices, out handleCount);
            buildOptions = (options != null) ? options : "";
            buildNotify  = notify;

            ComputeErrorCode error = CL12.BuildProgram(Handle, handleCount, deviceHandles, options, buildNotify, notifyDataPtr);

#if DEBUG
            if (error != ComputeErrorCode.Success)
            {
                string str  = String.Empty;
                var    ptr  = Marshal.StringToHGlobalAnsi(str);
                IntPtr size = IntPtr.Zero;

                var errorCode = CL12.GetProgramBuildInfo(Handle, deviceHandles[0], ComputeProgramBuildInfo.BuildLog,
                                                         new IntPtr(4096), ptr,
                                                         out size);
                if (errorCode == ComputeErrorCode.Success)
                {
                    Debug.WriteLine($"Build Error:{Marshal.PtrToStringAnsi(ptr, (int) size)}");
                }
            }
#endif

            ComputeException.ThrowOnError(error);
        }
Пример #2
0
        public ComputeContext(ICollection <ComputeDevice> devices, ComputeContextPropertyList properties, ComputeContextNotifier notify, IntPtr notifyDataPtr)
        {
            int handleCount;

            CLDeviceHandle[] deviceHandles = ComputeTools.ExtractHandles(devices, out handleCount);
            IntPtr[]         propertyArray = (properties != null) ? properties.ToIntPtrArray() : null;
            callback = notify;

            ComputeErrorCode error = ComputeErrorCode.Success;

            Handle = CL10.CreateContext(propertyArray, handleCount, deviceHandles, notify, notifyDataPtr, out error);
            ComputeException.ThrowOnError(error);

            SetID(Handle.Value);

            this.properties = properties;
            ComputeContextProperty platformProperty = properties.GetByName(ComputeContextPropertyName.Platform);

            this.platform = ComputePlatform.GetByHandle(platformProperty.Value);
            this.devices  = GetDevices();

#if DEBUG
            Trace.WriteLine("Create " + this + " in Thread(" + Thread.CurrentThread.ManagedThreadId + ").", "Information");
#endif
        }
Пример #3
0
        /// <summary>
        /// Enqueues a command to map a part of a buffer into the host address space.
        /// </summary>
        /// <param name="buffer"> The buffer to map. </param>
        /// <param name="blocking">  The mode of operation of this call. </param>
        /// <param name="flags"> A list of properties for the mapping mode. </param>
        /// <param name="offset"> The <paramref name="buffer"/> element position where mapping starts. </param>
        /// <param name="region"> The region of elements to map. </param>
        /// <param name="events"> A collection of events that need to complete before this particular command can be executed. If <paramref name="events"/> is not <c>null</c> or read-only a new <see cref="ComputeEvent"/> identifying this command is created and attached to the end of the collection. </param>
        /// <remarks> If <paramref name="blocking"/> is <c>true</c> this method will not return until the command completes. If <paramref name="blocking"/> is <c>false</c> this method will return immediately after the command is enqueued. </remarks>
        public IntPtr Map <T>(ComputeBufferBase <T> buffer, bool blocking, ComputeMemoryMappingFlags flags, long offset, long region, ICollection <ComputeEventBase> events) where T : struct
        {
            int sizeofT = HDSPUtils.SizeOf(typeof(T));

            int eventWaitListSize;

            CLEventHandle[] eventHandles   = ComputeTools.ExtractHandles(events, out eventWaitListSize);
            bool            eventsWritable = (events != null && !events.IsReadOnly);

            CLEventHandle[] newEventHandle = (eventsWritable) ? new CLEventHandle[1] : null;

            IntPtr mappedPtr = IntPtr.Zero;

            ComputeErrorCode error = ComputeErrorCode.Success;

            mappedPtr = CL10.EnqueueMapBuffer(Handle, buffer.Handle, blocking, flags, new IntPtr(offset * sizeofT), new IntPtr(region * sizeofT), eventWaitListSize, eventHandles, newEventHandle, out error);
            ComputeException.ThrowOnError(error);

            if (eventsWritable)
            {
                events.Add(new ComputeEvent(newEventHandle[0], this));
            }

            return(mappedPtr);
        }
Пример #4
0
        /// <summary>
        /// Waits on the host thread for the specified events to complete.
        /// </summary>
        /// <param name="events"> The events to be waited for completition. </param>
        public static void Wait(ICollection <ComputeEventBase> events)
        {
            CLEventHandle[]  eventHandles = ComputeTools.ExtractHandles(events, out var eventWaitListSize);
            ComputeErrorCode error        = CL12.WaitForEvents(eventWaitListSize, eventHandles);

            ComputeException.ThrowOnError(error);
        }
Пример #5
0
        internal ComputeDevice(ComputePlatform platform, CLDeviceHandle handle)
        {
            Handle = handle;
            SetID(Handle.Value);

            addressBits            = GetInfo <uint>(ComputeDeviceInfo.AddressBits);
            available              = GetBoolInfo(ComputeDeviceInfo.Available);
            compilerAvailable      = GetBoolInfo(ComputeDeviceInfo.CompilerAvailable);
            driverVersion          = GetStringInfo(ComputeDeviceInfo.DriverVersion);
            endianLittle           = GetBoolInfo(ComputeDeviceInfo.EndianLittle);
            errorCorrectionSupport = GetBoolInfo(ComputeDeviceInfo.ErrorCorrectionSupport);
            executionCapabilities  = (ComputeDeviceExecutionCapabilities)GetInfo <long>(ComputeDeviceInfo.ExecutionCapabilities);

            string extensionString = GetStringInfo(ComputeDeviceInfo.Extensions);

            extensions = new ReadOnlyCollection <string>(extensionString.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries));

            globalMemoryCachelineSize = GetInfo <uint>(ComputeDeviceInfo.GlobalMemoryCachelineSize);
            globalMemoryCacheSize     = (long)GetInfo <ulong>(ComputeDeviceInfo.GlobalMemoryCacheSize);
            globalMemoryCacheType     = (ComputeDeviceMemoryCacheType)GetInfo <long>(ComputeDeviceInfo.GlobalMemoryCacheType);
            globalMemorySize          = (long)GetInfo <ulong>(ComputeDeviceInfo.GlobalMemorySize);
            image2DMaxHeight          = (long)GetInfo <IntPtr>(ComputeDeviceInfo.Image2DMaxHeight);
            image2DMaxWidth           = (long)GetInfo <IntPtr>(ComputeDeviceInfo.Image2DMaxWidth);
            image3DMaxDepth           = (long)GetInfo <IntPtr>(ComputeDeviceInfo.Image3DMaxDepth);
            image3DMaxHeight          = (long)GetInfo <IntPtr>(ComputeDeviceInfo.Image3DMaxHeight);
            image3DMaxWidth           = (long)GetInfo <IntPtr>(ComputeDeviceInfo.Image3DMaxWidth);
            imageSupport          = GetBoolInfo(ComputeDeviceInfo.ImageSupport);
            localMemorySize       = (long)GetInfo <ulong>(ComputeDeviceInfo.LocalMemorySize);
            localMemoryType       = (ComputeDeviceLocalMemoryType)GetInfo <long>(ComputeDeviceInfo.LocalMemoryType);
            maxClockFrequency     = GetInfo <uint>(ComputeDeviceInfo.MaxClockFrequency);
            maxComputeUnits       = GetInfo <uint>(ComputeDeviceInfo.MaxComputeUnits);
            maxConstantArguments  = GetInfo <uint>(ComputeDeviceInfo.MaxConstantArguments);
            maxConstantBufferSize = (long)GetInfo <ulong>(ComputeDeviceInfo.MaxConstantBufferSize);
            maxMemAllocSize       = (long)GetInfo <ulong>(ComputeDeviceInfo.MaxMemoryAllocationSize);
            maxParameterSize      = (long)GetInfo <IntPtr>(ComputeDeviceInfo.MaxParameterSize);
            maxReadImageArgs      = GetInfo <uint>(ComputeDeviceInfo.MaxReadImageArguments);
            maxSamplers           = GetInfo <uint>(ComputeDeviceInfo.MaxSamplers);
            maxWorkGroupSize      = (long)GetInfo <IntPtr>(ComputeDeviceInfo.MaxWorkGroupSize);
            maxWorkItemDimensions = GetInfo <uint>(ComputeDeviceInfo.MaxWorkItemDimensions);
            maxWorkItemSizes      = new ReadOnlyCollection <long>(ComputeTools.ConvertArray(GetArrayInfo <CLDeviceHandle, ComputeDeviceInfo, IntPtr>(Handle, ComputeDeviceInfo.MaxWorkItemSizes, CL10.GetDeviceInfo)));
            maxWriteImageArgs     = GetInfo <uint>(ComputeDeviceInfo.MaxWriteImageArguments);
            memBaseAddrAlign      = GetInfo <uint>(ComputeDeviceInfo.MemoryBaseAddressAlignment);
            minDataTypeAlignSize  = GetInfo <uint>(ComputeDeviceInfo.MinDataTypeAlignmentSize);
            name                      = GetStringInfo(ComputeDeviceInfo.Name);
            this.platform             = platform;
            preferredVectorWidthChar  = GetInfo <uint>(ComputeDeviceInfo.PreferredVectorWidthChar);
            preferredVectorWidthFloat = GetInfo <uint>(ComputeDeviceInfo.PreferredVectorWidthFloat);
            preferredVectorWidthInt   = GetInfo <uint>(ComputeDeviceInfo.PreferredVectorWidthInt);
            preferredVectorWidthLong  = GetInfo <uint>(ComputeDeviceInfo.PreferredVectorWidthLong);
            preferredVectorWidthShort = GetInfo <uint>(ComputeDeviceInfo.PreferredVectorWidthShort);
            profile                   = GetStringInfo(ComputeDeviceInfo.Profile);
            profilingTimerResolution  = (long)GetInfo <IntPtr>(ComputeDeviceInfo.ProfilingTimerResolution);
            queueProperties           = (ComputeCommandQueueFlags)GetInfo <long>(ComputeDeviceInfo.CommandQueueProperties);
            singleCapabilities        = (ComputeDeviceSingleCapabilities)GetInfo <long>(ComputeDeviceInfo.SingleFPConfig);
            type                      = (ComputeDeviceTypes)GetInfo <long>(ComputeDeviceInfo.Type);
            vendor                    = GetStringInfo(ComputeDeviceInfo.Vendor);
            vendorId                  = GetInfo <uint>(ComputeDeviceInfo.VendorId);
            version                   = GetStringInfo(ComputeDeviceInfo.Version);
        }
Пример #6
0
        /// <summary>
        /// Builds (compiles and links) a program executable from the program source or binary for all or some of the devices.
        /// </summary>
        /// <param name="devices"> A subset or all of devices. If devices is <c>null</c>, the executable is built for every item of devices for which a source or a binary has been loaded. </param>
        /// <param name="options"> A set of options for the OpenCL compiler. </param>
        /// <param name="notify"> A delegate instance that represents a reference to a notification routine. This routine is a callback function that an application can register and which will be called when the program executable has been built (successfully or unsuccessfully). If <paramref name="notify"/> is not <c>null</c>, build does not need to wait for the build to complete and can return immediately. If <paramref name="notify"/> is <c>null</c>, build does not return until the build has completed. The callback function may be called asynchronously by the OpenCL implementation. It is the application's responsibility to ensure that the callback function is thread-safe and that the delegate instance doesn't get collected by the Garbage Collector until the build operation triggers the callback. </param>
        /// <param name="notifyDataPtr"> Optional user data that will be passed to <paramref name="notify"/>. </param>
        public void Build(ICollection <IComputeDevice> devices, string options,
                          ComputeProgramBuildNotifier notify, IntPtr notifyDataPtr)
        {
            var deviceHandles = ComputeTools.ExtractHandles(devices, out int handleCount);
            var BuildOptions  = options ?? "";

            OpenCL110.BuildProgramWrapper(Handle, handleCount, deviceHandles, options, notify, notifyDataPtr);
        }
Пример #7
0
        /// <summary>
        ///
        /// </summary>
        protected void Init(long size)
        {
            SetID(Handle.Value);

            Size  = size;
            Count = Size / ComputeTools.SizeOf <T>();

            //Debug.WriteLine("Create " + this + " in Thread(" + Thread.CurrentThread.ManagedThreadId + ").", "Information");
        }
Пример #8
0
        /// <summary>
        ///
        /// </summary>
        protected void Init()
        {
            SetID(Handle.Value);

            Size  = (long)GetInfo <CLMemoryHandle, ComputeMemoryInfo, IntPtr>(Handle, ComputeMemoryInfo.Size, CL12.GetMemObjectInfo);
            Count = Size / ComputeTools.SizeOf <T>();

            //Debug.WriteLine("Create " + this + " in Thread(" + Thread.CurrentThread.ManagedThreadId + ").", "Information");
        }
Пример #9
0
        /// <summary>
        /// Creates a new <see cref="ComputeBuffer{T}"/>.
        /// </summary>
        /// <param name="context"> A <see cref="ComputeContext"/> used to create the <see cref="ComputeBuffer{T}"/>. </param>
        /// <param name="flags"> A bit-field that is used to specify allocation and usage information about the <see cref="ComputeBuffer{T}"/>. </param>
        /// <param name="count"> The number of elements of the <see cref="ComputeBuffer{T}"/>. </param>
        /// <param name="dataPtr"> A pointer to the data for the <see cref="ComputeBuffer{T}"/>. </param>
        public ComputeBuffer(ComputeContext context, ComputeMemoryFlags flags, long count, IntPtr dataPtr)
            : base(context, flags)
        {
            var size = ComputeTools.SizeOf <T>() * count;

            Handle = CL12.CreateBuffer(context.Handle, flags, new IntPtr(size), dataPtr, out var error);
            ComputeException.ThrowOnError(error);
            Init(size, count);
        }
Пример #10
0
        /// <summary>
        /// Enqueues a wait command for a collection of <see cref="ComputeEvent"/>s to complete before any future commands queued in the <see cref="ComputeCommandQueue"/> are executed.
        /// </summary>
        /// <param name="events"> The <see cref="ComputeEvent"/>s that this command will wait for. </param>
        public void Wait(ICollection <ComputeEventBase> events)
        {
            int eventWaitListSize;

            CLEventHandle[] eventHandles = ComputeTools.ExtractHandles(events, out eventWaitListSize);

            ComputeErrorCode error = CL10.EnqueueWaitForEvents(Handle, eventWaitListSize, eventHandles);

            ComputeException.ThrowOnError(error);
        }
Пример #11
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// Builds (compiles and links) a program executable from the program source or binary for all or
        /// some of the <see cref="ComputeProgram.Devices"/>.
        /// </summary>
        ///
        /// <param name="devices">          A subset or all of <see cref="ComputeProgram.Devices"/>. If
        ///                                 <paramref name="devices"/> is <c>null</c>, the executable is
        ///                                 built for every item of <see cref="ComputeProgram.Devices"/> for
        ///                                 which a source or a binary has been loaded. </param>
        /// <param name="options">          A set of options for the OpenCL compiler. </param>
        /// <param name="notify">           A delegate instance that represents a reference to a
        ///                                 notification routine. This routine is a callback function that an
        ///                                 application can register and which will be called when the
        ///                                 program executable has been built (successfully or
        ///                                 unsuccessfully). If <paramref name="notify"/> is not <c>null</c>,
        ///                                 <see cref="ComputeProgram.Build"/> does not need to wait for the
        ///                                 build to complete and can return immediately. If
        ///                                 <paramref name="notify"/> is <c>null</c>,
        ///                                 <see cref="ComputeProgram.Build"/> does not return until the
        ///                                 build has completed. The callback function may be called
        ///                                 asynchronously by the OpenCL implementation. It is the
        ///                                 application's responsibility to ensure that the callback function
        ///                                 is thread-safe and that the delegate instance doesn't get
        ///                                 collected by the Garbage Collector until the build operation
        ///                                 triggers the callback. </param>
        /// <param name="notifyDataPtr">    Optional user data that will be passed to
        ///                                 <paramref name="notify"/>. </param>
        ////////////////////////////////////////////////////////////////////////////////////////////////////

        public void Build(ICollection <ComputeDevice> devices, string options, ComputeProgramBuildNotifier notify, IntPtr notifyDataPtr)
        {
            Ensure.Argument(devices).NotNull("devices is null");

            CLDeviceHandle[] deviceHandles = ComputeTools.ExtractHandles(devices, out var handleCount);
            buildOptions = options ?? "";
            buildNotify  = notify;

            ComputeErrorCode error = CL12.BuildProgram(Handle, handleCount, deviceHandles, options, buildNotify, notifyDataPtr);

            ComputeException.ThrowOnError(error);
        }
Пример #12
0
        /// <summary>
        /// Creates a new <see cref="ComputeSubBuffer{T}"/> from a specified <see cref="ComputeBuffer{T}"/>.
        /// </summary>
        /// <param name="buffer"> The buffer to create the <see cref="ComputeSubBuffer{T}"/> from. </param>
        /// <param name="flags"> A bit-field that is used to specify allocation and usage information about the <see cref="ComputeBuffer{T}"/>. </param>
        /// <param name="offset"> The index of the element of <paramref name="buffer"/>, where the <see cref="ComputeSubBuffer{T}"/> starts. </param>
        /// <param name="count"> The number of elements of <paramref name="buffer"/> to include in the <see cref="ComputeSubBuffer{T}"/>. </param>
        public ComputeSubBuffer(ComputeBuffer <T> buffer, ComputeMemoryFlags flags, long offset, long count)
            : base(buffer.Context, flags)
        {
            var sizeofT = ComputeTools.SizeOf <T>();

            SysIntX2 region = new SysIntX2(offset * sizeofT, count * sizeofT);

            Handle = CL11.CreateSubBuffer(buffer.Handle, flags, ComputeBufferCreateType.Region, ref region, out var error);
            ComputeException.ThrowOnError(error);

            Init();
        }
Пример #13
0
        /// <summary>
        /// Builds (compiles and links) a program executable from the program source or binary for all or some of the <see cref="ComputeProgram.Devices"/>.
        /// </summary>
        /// <param name="devices"> A subset or all of <see cref="ComputeProgram.Devices"/>. If <paramref name="devices"/> is <c>null</c>, the executable is built for every item of <see cref="ComputeProgram.Devices"/> for which a source or a binary has been loaded. </param>
        /// <param name="options"> A set of options for the OpenCL compiler. </param>
        /// <param name="notify"> A delegate instance that represents a reference to a notification routine. This routine is a callback function that an application can register and which will be called when the program executable has been built (successfully or unsuccessfully). If <paramref name="notify"/> is not <c>null</c>, <see cref="ComputeProgram.Build"/> does not need to wait for the build to complete and can return immediately. If <paramref name="notify"/> is <c>null</c>, <see cref="ComputeProgram.Build"/> does not return until the build has completed. The callback function may be called asynchronously by the OpenCL implementation. It is the application's responsibility to ensure that the callback function is thread-safe and that the delegate instance doesn't get collected by the Garbage Collector until the build operation triggers the callback. </param>
        /// <param name="notifyDataPtr"> Optional user data that will be passed to <paramref name="notify"/>. </param>
        public void Build(ICollection <ComputeDevice> devices, string options, ComputeProgramBuildNotifier notify, IntPtr notifyDataPtr)
        {
            int handleCount;

            CLDeviceHandle[] deviceHandles = ComputeTools.ExtractHandles(devices, out handleCount);
            buildOptions = (options != null) ? options : "";
            buildNotify  = notify;

            ComputeErrorCode error = CL10.BuildProgram(Handle, handleCount, deviceHandles, options, buildNotify, notifyDataPtr);

            ComputeException.ThrowOnError(error);
        }
Пример #14
0
        internal ComputeEvent(CLEventHandle handle, ComputeCommandQueue queue)
        {
            Handle = handle;
            SetID(Handle.Value);

            CommandQueue = queue;
            Type         = (ComputeCommandType)GetInfo <CLEventHandle, ComputeEventInfo, int>(Handle, ComputeEventInfo.CommandType, CLInterface.CL12.GetEventInfo);
            Context      = queue.Context;

            if (ComputeTools.ParseVersionString(CommandQueue.Device.Platform.Version, 1) > new Version(1, 0))
            {
                HookNotifier();
            }
        }
Пример #15
0
        /// <summary>
        /// Creates a new <see cref="ComputeProgram"/> from a specified list of binaries.
        /// </summary>
        /// <param name="context"> A <see cref="ComputeContext"/>. </param>
        /// <param name="binaries"> A list of binaries, one for each item in <paramref name="devices"/>. </param>
        /// <param name="devices"> A subset of the <see cref="ComputeContext.Devices"/>. If <paramref name="devices"/> is <c>null</c>, OpenCL will associate every binary from <see cref="ComputeProgram.Binaries"/> with a corresponding <see cref="ComputeDevice"/> from <see cref="ComputeContext.Devices"/>. </param>
        public ComputeProgram(ComputeContext context, IList <byte[]> binaries, IList <ComputeDevice> devices)
        {
            int count;

            CLDeviceHandle[] deviceHandles = (devices != null) ?
                                             ComputeTools.ExtractHandles(devices, out count) :
                                             ComputeTools.ExtractHandles(context.Devices, out count);

            IntPtr[]         binariesPtrs    = new IntPtr[count];
            IntPtr[]         binariesLengths = new IntPtr[count];
            int[]            binariesStats   = new int[count];
            ComputeErrorCode error           = ComputeErrorCode.Success;

            GCHandle[] binariesGCHandles = new GCHandle[count];

            try
            {
                for (int i = 0; i < count; i++)
                {
                    binariesGCHandles[i] = GCHandle.Alloc(binaries[i], GCHandleType.Pinned);
                    binariesPtrs[i]      = binariesGCHandles[i].AddrOfPinnedObject();
                    binariesLengths[i]   = new IntPtr(binaries[i].Length);
                }

                Handle = CL10.CreateProgramWithBinary(
                    context.Handle,
                    count,
                    deviceHandles,
                    binariesLengths,
                    binariesPtrs,
                    binariesStats,
                    out error);
                ComputeException.ThrowOnError(error);
            }
            finally
            {
                for (int i = 0; i < count; i++)
                {
                    binariesGCHandles[i].Free();
                }
            }


            this.binaries = new ReadOnlyCollection <byte[]>(binaries);
            this.context  = context;
            this.devices  = new ReadOnlyCollection <ComputeDevice>(
                (devices != null) ? devices : context.Devices);

            //Console.WriteLine("Create " + this + " in Thread(" + Thread.CurrentThread.ManagedThreadId + ").", "Information");
        }
Пример #16
0
        /// <summary>
        /// Builds (compiles and links) a program executable from the program source or binary for all or some of the devices.
        /// </summary>
        /// <param name="devices"> A subset or all of devices. If devices is <c>null</c>, the executable is built for every item of devices for which a source or a binary has been loaded. </param>
        /// <param name="options"> A set of options for the OpenCL compiler. </param>
        /// <param name="notify"> A delegate instance that represents a reference to a notification routine. This routine is a callback function that an application can register and which will be called when the program executable has been built (successfully or unsuccessfully). If <paramref name="notify"/> is not <c>null</c>, build does not need to wait for the build to complete and can return immediately. If <paramref name="notify"/> is <c>null</c>, build does not return until the build has completed. The callback function may be called asynchronously by the OpenCL implementation. It is the application's responsibility to ensure that the callback function is thread-safe and that the delegate instance doesn't get collected by the Garbage Collector until the build operation triggers the callback. </param>
        /// <param name="notifyDataPtr"> Optional user data that will be passed to <paramref name="notify"/>. </param>
        public void Build(ICollection <IComputeDevice> devices, string options,
                          ComputeProgramBuildNotifier notify, IntPtr notifyDataPtr)
        {
            var deviceHandles = ComputeTools.ExtractHandles(devices, out int handleCount);
            var BuildOptions  = options ?? "";
            var error         = OpenCL100.BuildProgram(
                Handle,
                handleCount,
                deviceHandles,
                options,
                notify,
                notifyDataPtr);

            ComputeException.ThrowOnError(error);
        }
Пример #17
0
        internal ComputeEvent(CLEventHandle handle, ComputeCommandQueue queue)
        {
            Handle = handle;
            SetID(Handle.Value);

            CommandQueue = queue;
            Type         = (ComputeCommandType)GetInfo <CLEventHandle, ComputeEventInfo, int>(Handle, ComputeEventInfo.CommandType, CL12.GetEventInfo);
            Context      = queue.Context;

            if (ComputeTools.ParseVersionString(CommandQueue.Device.Platform.Version, 1) > new Version(1, 0))
            {
                HookNotifier();
            }

            Trace.WriteLine("Create " + this + " in Thread(" + Thread.CurrentThread.ManagedThreadId + ").", "Information");
        }
Пример #18
0
        /// <summary>
        /// Enqueues a command to execute a range of <see cref="ComputeKernel"/>s in parallel.
        /// </summary>
        /// <param name="kernel"> The <see cref="ComputeKernel"/> to execute. </param>
        /// <param name="globalWorkOffset"> An array of values that describe the offset used to calculate the global ID of a work-item instead of having the global IDs always start at offset (0, 0,... 0). </param>
        /// <param name="globalWorkSize"> An array of values that describe the number of global work-items in dimensions that will execute the kernel function. The total number of global work-items is computed as global_work_size[0] *...* global_work_size[work_dim - 1]. </param>
        /// <param name="localWorkSize"> An array of values that describe the number of work-items that make up a work-group (also referred to as the size of the work-group) that will execute the <paramref name="kernel"/>. The total number of work-items in a work-group is computed as local_work_size[0] *... * local_work_size[work_dim - 1]. </param>
        /// <param name="events"> A collection of events that need to complete before this particular command can be executed. If <paramref name="events"/> is not <c>null</c> or read-only a new <see cref="ComputeEvent"/> identifying this command is created and attached to the end of the collection. </param>
        public void Execute(ComputeKernel kernel, long[] globalWorkOffset, long[] globalWorkSize, long[] localWorkSize, ICollection <ComputeEventBase> events)
        {
            int eventWaitListSize;

            CLEventHandle[] eventHandles   = ComputeTools.ExtractHandles(events, out eventWaitListSize);
            bool            eventsWritable = (events != null && !events.IsReadOnly);

            CLEventHandle[] newEventHandle = (eventsWritable) ? new CLEventHandle[1] : null;

            ComputeErrorCode error = CL10.EnqueueNDRangeKernel(Handle, kernel.Handle, globalWorkSize.Length, ComputeTools.ConvertArray(globalWorkOffset), ComputeTools.ConvertArray(globalWorkSize), ComputeTools.ConvertArray(localWorkSize), eventWaitListSize, eventHandles, newEventHandle);

            ComputeException.ThrowOnError(error);

            if (eventsWritable)
            {
                events.Add(new ComputeEvent(newEventHandle[0], this));
            }
        }
Пример #19
0
        /// <summary>
        /// Enqueues a command to copy data between <see cref="ComputeImage"/>s.
        /// </summary>
        /// <param name="source"> The <see cref="ComputeImage"/> to copy from. </param>
        /// <param name="destination"> The <see cref="ComputeImage"/> to copy to. </param>
        /// <param name="sourceOffset"> The <paramref name="source"/> element position where reading starts. </param>
        /// <param name="destinationOffset"> The <paramref name="destination"/> element position where writing starts. </param>
        /// <param name="region"> The region of elements to copy. </param>
        /// <param name="events"> A collection of events that need to complete before this particular command can be executed. If <paramref name="events"/> is not <c>null</c> or read-only a new <see cref="ComputeEvent"/> identifying this command is created and attached to the end of the collection. </param>
        public void Copy(ComputeImage source, ComputeImage destination, SysIntX3 sourceOffset, SysIntX3 destinationOffset, SysIntX3 region, ICollection <ComputeEventBase> events)
        {
            int eventWaitListSize;

            CLEventHandle[] eventHandles   = ComputeTools.ExtractHandles(events, out eventWaitListSize);
            bool            eventsWritable = (events != null && !events.IsReadOnly);

            CLEventHandle[] newEventHandle = (eventsWritable) ? new CLEventHandle[1] : null;

            ComputeErrorCode error = CL10.EnqueueCopyImage(Handle, source.Handle, destination.Handle, ref sourceOffset, ref destinationOffset, ref region, eventWaitListSize, eventHandles, newEventHandle);

            ComputeException.ThrowOnError(error);

            if (eventsWritable)
            {
                events.Add(new ComputeEvent(newEventHandle[0], this));
            }
        }
Пример #20
0
        /// <summary>
        /// Enqueues a command to execute a single <see cref="ComputeKernel"/>.
        /// </summary>
        /// <param name="kernel"> The <see cref="ComputeKernel"/> to execute. </param>
        /// <param name="events"> A collection of events that need to complete before this particular command can be executed. If <paramref name="events"/> is not <c>null</c> or read-only a new <see cref="ComputeEvent"/> identifying this command is created and attached to the end of the collection. </param>
        public void ExecuteTask(ComputeKernel kernel, ICollection <ComputeEventBase> events)
        {
            int eventWaitListSize;

            CLEventHandle[] eventHandles   = ComputeTools.ExtractHandles(events, out eventWaitListSize);
            bool            eventsWritable = (events != null && !events.IsReadOnly);

            CLEventHandle[] newEventHandle = (eventsWritable) ? new CLEventHandle[1] : null;

            ComputeErrorCode error = CL10.EnqueueTask(Handle, kernel.Handle, eventWaitListSize, eventHandles, newEventHandle);

            ComputeException.ThrowOnError(error);

            if (eventsWritable)
            {
                events.Add(new ComputeEvent(newEventHandle[0], this));
            }
        }
Пример #21
0
        /// <summary>
        /// Enqueues a command to write data to a <see cref="ComputeImage"/>.
        /// </summary>
        /// <param name="destination"> The <see cref="ComputeImage"/> to write to. </param>
        /// <param name="blocking"> The mode of operation of this command. If <c>true</c> this call will not return until the command has finished execution. </param>
        /// <param name="destinationOffset"> The <paramref name="destination"/> element position where writing starts. </param>
        /// <param name="region"> The region of elements to write. </param>
        /// <param name="rowPitch"> The <see cref="ComputeImage.RowPitch"/> of <paramref name="destination"/> or 0. </param>
        /// <param name="slicePitch"> The <see cref="ComputeImage.SlicePitch"/> of <paramref name="destination"/> or 0. </param>
        /// <param name="source"> The content written to the <see cref="ComputeImage"/>. </param>
        /// <param name="events"> A collection of events that need to complete before this particular command can be executed. If <paramref name="events"/> is not <c>null</c> or read-only a new <see cref="ComputeEvent"/> identifying this command is created and attached to the end of the collection. </param>
        /// <remarks> If <paramref name="blocking"/> is <c>true</c> this method will not return until the command completes. If <paramref name="blocking"/> is <c>false</c> this method will return immediately after the command is enqueued. </remarks>
        public void Write(ComputeImage destination, bool blocking, SysIntX3 destinationOffset, SysIntX3 region, long rowPitch, long slicePitch, IntPtr source, ICollection <ComputeEventBase> events)
        {
            int eventWaitListSize;

            CLEventHandle[] eventHandles   = ComputeTools.ExtractHandles(events, out eventWaitListSize);
            bool            eventsWritable = (events != null && !events.IsReadOnly);

            CLEventHandle[] newEventHandle = (eventsWritable) ? new CLEventHandle[1] : null;

            ComputeErrorCode error = CL10.EnqueueWriteImage(Handle, destination.Handle, blocking, ref destinationOffset, ref region, new IntPtr(rowPitch), new IntPtr(slicePitch), source, eventWaitListSize, eventHandles, newEventHandle);

            ComputeException.ThrowOnError(error);

            if (eventsWritable)
            {
                events.Add(new ComputeEvent(newEventHandle[0], this));
            }
        }
Пример #22
0
        /// <summary>
        /// Creates a new <see cref="ComputeBuffer{T}"/>.
        /// </summary>
        /// <param name="context"> A <see cref="ComputeContext"/> used to create the <see cref="ComputeBuffer{T}"/>. </param>
        /// <param name="flags"> A bit-field that is used to specify allocation and usage information about the <see cref="ComputeBuffer{T}"/>. </param>
        /// <param name="data"> The data for the <see cref="ComputeBuffer{T}"/>. </param>
        /// <remarks> Note, that <paramref name="data"/> cannot be an "immediate" parameter, i.e.: <c>new T[100]</c>, because it could be quickly collected by the GC causing Cloo to send and invalid reference to OpenCL. </remarks>
        public ComputeBuffer(ComputeContext context, ComputeMemoryFlags flags, T[] data)
            : base(context, flags)
        {
            var size = ComputeTools.SizeOf <T>() * data.Length;

            GCHandle dataPtr = GCHandle.Alloc(data, GCHandleType.Pinned);

            try
            {
                Handle = CL12.CreateBuffer(context.Handle, flags, new IntPtr(size), dataPtr.AddrOfPinnedObject(), out var error);
                ComputeException.ThrowOnError(error);
            }
            finally
            {
                dataPtr.Free();
            }

            Init(size, data.Length);
        }
Пример #23
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// Creates a new <see cref="ComputeContext"/> on a collection of <see cref="ComputeDevice"/>s.
        /// </summary>
        ///
        /// <param name="devices">          A collection of <see cref="ComputeDevice"/>s to associate
        ///                                 with the <see cref="ComputeContext"/>. </param>
        /// <param name="properties">       A <see cref="ComputeContextPropertyList"/> of the
        ///                                 <see cref="ComputeContext"/>. </param>
        /// <param name="notify">           A delegate instance that refers to a notification routine.
        ///                                 This routine is a callback function that will be used by the
        ///                                 OpenCL implementation to report information on errors that occur
        ///                                 in the <see cref="ComputeContext"/>. The callback function may be
        ///                                 called asynchronously by the OpenCL implementation. It is the
        ///                                 application's responsibility to ensure that the callback function
        ///                                 is thread-safe and that the delegate instance doesn't get
        ///                                 collected by the Garbage Collector until
        ///                                 <see cref="ComputeContext"/> is disposed. If
        ///                                 <paramref name="notify"/> is <c>null</c>, no callback function is
        ///                                 registered. </param>
        /// <param name="notifyDataPtr">    Optional user data that will be passed to
        ///                                 <paramref name="notify"/>. </param>
        ////////////////////////////////////////////////////////////////////////////////////////////////////

        public ComputeContext(ICollection <ComputeDevice> devices, ComputeContextPropertyList properties, ComputeContextNotifier notify, IntPtr notifyDataPtr)
        {
            CLDeviceHandle[] deviceHandles = ComputeTools.ExtractHandles(devices, out var handleCount);
            IntPtr[]         propertyArray = properties?.ToIntPtrArray();
            callback = notify;

            Handle = CL12.CreateContext(propertyArray, handleCount, deviceHandles, notify, notifyDataPtr, out var error);
            ComputeException.ThrowOnError(error);

            SetID(Handle.Value);

            this.properties = properties;
            ComputeContextProperty platformProperty = properties.GetByName(ComputeContextPropertyName.Platform);

            platform     = ComputePlatform.GetByHandle(platformProperty.Value);
            this.devices = GetDevices();

            RILogManager.Default?.SendTrace("Create " + this + " in Thread(" + Thread.CurrentThread.ManagedThreadId + ").", "Information");
        }
Пример #24
0
        /// <summary>
        /// Added by Hybrid DSP
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="destinationHandle">The destination.</param>
        /// <param name="blocking">if set to <c>true</c> [blocking].</param>
        /// <param name="destinationOffset">The destination offset.</param>
        /// <param name="region">The region.</param>
        /// <param name="source">The source.</param>
        /// <param name="events">The events.</param>
        public void WriteEx <T>(CLMemoryHandle destinationHandle, bool blocking, long destinationOffset, long region, IntPtr source, ICollection <ComputeEventBase> events) where T : struct
        {
            int sizeofT = HDSPUtils.SizeOf(typeof(T));

            int eventWaitListSize;

            CLEventHandle[] eventHandles   = ComputeTools.ExtractHandles(events, out eventWaitListSize);
            bool            eventsWritable = (events != null && !events.IsReadOnly);

            CLEventHandle[] newEventHandle = (eventsWritable) ? new CLEventHandle[1] : null;

            ComputeErrorCode error = CL10.EnqueueWriteBuffer(Handle, destinationHandle, blocking, new IntPtr(destinationOffset * sizeofT), new IntPtr(region * sizeofT), source, eventWaitListSize, eventHandles, newEventHandle);

            ComputeException.ThrowOnError(error);

            if (eventsWritable)
            {
                events.Add(new ComputeEvent(newEventHandle[0], this));
            }
        }
Пример #25
0
        /// <summary>
        /// Enqueues a command to copy data from <see cref="ComputeImage"/> to buffer.
        /// </summary>
        /// <param name="source"> The image to copy from. </param>
        /// <param name="destination"> The buffer to copy to. </param>
        /// <param name="sourceOffset"> The <paramref name="source"/> element position where reading starts. </param>
        /// <param name="destinationOffset"> The <paramref name="destination"/> element position where writing starts. </param>
        /// <param name="region"> The region of elements to copy. </param>
        /// <param name="events"> A collection of events that need to complete before this particular command can be executed. If <paramref name="events"/> is not <c>null</c> or read-only a new <see cref="ComputeEvent"/> identifying this command is created and attached to the end of the collection. </param>
        public void Copy <T>(ComputeImage source, ComputeBufferBase <T> destination, SysIntX3 sourceOffset, long destinationOffset, SysIntX3 region, ICollection <ComputeEventBase> events) where T : struct
        {
            int sizeofT = HDSPUtils.SizeOf(typeof(T));

            int eventWaitListSize;

            CLEventHandle[] eventHandles   = ComputeTools.ExtractHandles(events, out eventWaitListSize);
            bool            eventsWritable = (events != null && !events.IsReadOnly);

            CLEventHandle[] newEventHandle = (eventsWritable) ? new CLEventHandle[1] : null;

            ComputeErrorCode error = CL10.EnqueueCopyImageToBuffer(Handle, source.Handle, destination.Handle, ref sourceOffset, ref region, new IntPtr(destinationOffset * sizeofT), eventWaitListSize, eventHandles, newEventHandle);

            ComputeException.ThrowOnError(error);

            if (eventsWritable)
            {
                events.Add(new ComputeEvent(newEventHandle[0], this));
            }
        }
Пример #26
0
        /// <summary>
        /// Enqueues a command to unmap a buffer or a <see cref="ComputeImage"/> from the host address space.
        /// </summary>
        /// <param name="memory"> The <see cref="ComputeMemory"/>. </param>
        /// <param name="mappedPtr"> The host address returned by a previous call to <see cref="ComputeCommandQueue.Map"/>. This pointer is <c>IntPtr.Zero</c> after this method returns. </param>
        /// <param name="events"> A collection of events that need to complete before this particular command can be executed. If <paramref name="events"/> is not <c>null</c> or read-only a new <see cref="ComputeEvent"/> identifying this command is created and attached to the end of the collection. </param>
        public void Unmap(ComputeMemory memory, ref IntPtr mappedPtr, ICollection <ComputeEventBase> events)
        {
            int eventWaitListSize;

            CLEventHandle[] eventHandles   = ComputeTools.ExtractHandles(events, out eventWaitListSize);
            bool            eventsWritable = (events != null && !events.IsReadOnly);

            CLEventHandle[] newEventHandle = (eventsWritable) ? new CLEventHandle[1] : null;

            ComputeErrorCode error = CL10.EnqueueUnmapMemObject(Handle, memory.Handle, mappedPtr, eventWaitListSize, eventHandles, newEventHandle);

            ComputeException.ThrowOnError(error);

            mappedPtr = IntPtr.Zero;

            if (eventsWritable)
            {
                events.Add(new ComputeEvent(newEventHandle[0], this));
            }
        }
Пример #27
0
        /// <summary>
        /// Creates a new <see cref="ComputeContext"/> on a collection of <see cref="ComputeDevice"/>s.
        /// </summary>
        /// <param name="devices"> A collection of <see cref="ComputeDevice"/>s to associate with the <see cref="ComputeContext"/>. </param>
        /// <param name="properties"> A <see cref="ComputeContextPropertyList"/> of the <see cref="ComputeContext"/>. </param>
        /// <param name="notify"> A delegate instance that refers to a notification routine. This routine is a callback function that will be used by the OpenCL implementation to report information on errors that occur in the <see cref="ComputeContext"/>. The callback function may be called asynchronously by the OpenCL implementation. It is the application's responsibility to ensure that the callback function is thread-safe and that the delegate instance doesn't get collected by the Garbage Collector until <see cref="ComputeContext"/> is disposed. If <paramref name="notify"/> is <c>null</c>, no callback function is registered. </param>
        /// <param name="notifyDataPtr"> Optional user data that will be passed to <paramref name="notify"/>. </param>
        public ComputeContext(ICollection <ComputeDevice> devices, ComputeContextPropertyList properties, ComputeContextNotifier notify, IntPtr notifyDataPtr)
        {
            int handleCount;

            CLDeviceHandle[] deviceHandles = ComputeTools.ExtractHandles(devices, out handleCount);
            IntPtr[]         propertyArray = (properties != null) ? properties.ToIntPtrArray() : null;
            callback = notify;

            ComputeErrorCode error = ComputeErrorCode.Success;

            Handle = CLInterface.CL12.CreateContext(propertyArray, handleCount, deviceHandles, notify, notifyDataPtr, out error);
            ComputeException.ThrowOnError(error);

            SetID(Handle.Value);

            this.properties = properties;
            ComputeContextProperty platformProperty = properties.GetByName(ComputeContextPropertyName.Platform);

            this.platform = ComputePlatform.GetByHandle(platformProperty.Value);
            this.devices  = GetDevices();
        }
Пример #28
0
        /// <summary>
        /// Enqueues a command to release <see cref="ComputeMemory"/>s that have been created from OpenGL objects.
        /// </summary>
        /// <param name="memObjs"> A collection of <see cref="ComputeMemory"/>s that correspond to OpenGL memory objects. </param>
        /// <param name="events"> A collection of events that need to complete before this particular command can be executed. If <paramref name="events"/> is not <c>null</c> or read-only a new <see cref="ComputeEvent"/> identifying this command is created and attached to the end of the collection. </param>
        public void ReleaseGLObjects(ICollection <ComputeMemory> memObjs, ICollection <ComputeEventBase> events)
        {
            int memObjCount;

            CLMemoryHandle[] memObjHandles = ComputeTools.ExtractHandles(memObjs, out memObjCount);

            int eventWaitListSize;

            CLEventHandle[] eventHandles   = ComputeTools.ExtractHandles(events, out eventWaitListSize);
            bool            eventsWritable = (events != null && !events.IsReadOnly);

            CLEventHandle[] newEventHandle = (eventsWritable) ? new CLEventHandle[1] : null;

            ComputeErrorCode error = CL10.EnqueueReleaseGLObjects(Handle, memObjCount, memObjHandles, eventWaitListSize, eventHandles, newEventHandle);

            ComputeException.ThrowOnError(error);

            if (eventsWritable)
            {
                events.Add(new ComputeEvent(newEventHandle[0], this));
            }
        }
Пример #29
0
        /// <summary>
        /// Enqueues a command to map a part of a <see cref="ComputeImage"/> into the host address space.
        /// </summary>
        /// <param name="image"> The <see cref="ComputeImage"/> to map. </param>
        /// <param name="blocking"> The mode of operation of this command. If <c>true</c> this call will not return until the command has finished execution. </param>
        /// <param name="flags"> A list of properties for the mapping mode. </param>
        /// <param name="offset"> The <paramref name="image"/> element position where mapping starts. </param>
        /// <param name="region"> The region of elements to map. </param>
        /// <param name="events"> A collection of events that need to complete before this particular command can be executed. If <paramref name="events"/> is not <c>null</c> or read-only a new <see cref="ComputeEvent"/> identifying this command is created and attached to the end of the collection. </param>
        /// <remarks> If <paramref name="blocking"/> is <c>true</c> this method will not return until the command completes. If <paramref name="blocking"/> is <c>false</c> this method will return immediately after the command is enqueued. </remarks>
        public IntPtr Map(ComputeImage image, bool blocking, ComputeMemoryMappingFlags flags, SysIntX3 offset, SysIntX3 region, ICollection <ComputeEventBase> events)
        {
            int eventWaitListSize;

            CLEventHandle[] eventHandles   = ComputeTools.ExtractHandles(events, out eventWaitListSize);
            bool            eventsWritable = (events != null && !events.IsReadOnly);

            CLEventHandle[] newEventHandle = (eventsWritable) ? new CLEventHandle[1] : null;

            IntPtr mappedPtr, rowPitch, slicePitch;

            ComputeErrorCode error = ComputeErrorCode.Success;

            mappedPtr = CL10.EnqueueMapImage(Handle, image.Handle, blocking, flags, ref offset, ref region, out rowPitch, out slicePitch, eventWaitListSize, eventHandles, newEventHandle, out error);
            ComputeException.ThrowOnError(error);

            if (eventsWritable)
            {
                events.Add(new ComputeEvent(newEventHandle[0], this));
            }

            return(mappedPtr);
        }
Пример #30
0
        /// <summary>
        /// Enqueues a command to write a 2D or 3D region of elements to a buffer.
        /// </summary>
        /// <typeparam name="T"> The type of the elements of the buffer. </typeparam>
        /// <param name="destination"> The buffer to write to. </param>
        /// <param name="blocking"> The mode of operation of this command. If <c>true</c> this call will not return until the command has finished execution. </param>
        /// <param name="destinationOffset"> The <paramref name="destination"/> element position where writing starts. </param>
        /// <param name="sourceOffset"> The <paramref name="source"/> element position where reading starts. </param>
        /// <param name="region"> The region of elements to copy. </param>
        /// <param name="destinationRowPitch"> The size of the destination buffer row in bytes. If set to zero then <paramref name="destinationRowPitch"/> equals <c>region.X * sizeof(T)</c>. </param>
        /// <param name="destinationSlicePitch"> The size of the destination buffer 2D slice in bytes. If set to zero then <paramref name="destinationSlicePitch"/> equals <c>region.Y * sizeof(T) * destinationRowPitch</c>. </param>
        /// <param name="sourceRowPitch"> The size of the memory area row in bytes. If set to zero then <paramref name="sourceRowPitch"/> equals <c>region.X * sizeof(T)</c>. </param>
        /// <param name="sourceSlicePitch"> The size of the memory area 2D slice in bytes. If set to zero then <paramref name="sourceSlicePitch"/> equals <c>region.Y * sizeof(T) * sourceRowPitch</c>. </param>
        /// <param name="source"> The data written to the buffer. </param>
        /// <param name="events"> A collection of events that need to complete before this particular command can be executed. If <paramref name="events"/> is not <c>null</c> or read-only a new <see cref="ComputeEvent"/> identifying this command is created and attached to the end of the collection. </param>
        /// <remarks> Requires OpenCL 1.1. </remarks>
        private void Write <T>(ComputeBufferBase <T> destination, bool blocking, SysIntX3 sourceOffset, SysIntX3 destinationOffset, SysIntX3 region, long destinationRowPitch, long destinationSlicePitch, long sourceRowPitch, long sourceSlicePitch, IntPtr source, ICollection <ComputeEventBase> events) where T : struct
        {
            int sizeofT = HDSPUtils.SizeOf(typeof(T));

            sourceOffset.X      = new IntPtr(sizeofT * sourceOffset.X.ToInt64());
            destinationOffset.X = new IntPtr(sizeofT * destinationOffset.X.ToInt64());
            region.X            = new IntPtr(sizeofT * region.X.ToInt64());

            int eventWaitListSize;

            CLEventHandle[] eventHandles   = ComputeTools.ExtractHandles(events, out eventWaitListSize);
            bool            eventsWritable = (events != null && !events.IsReadOnly);

            CLEventHandle[] newEventHandle = (eventsWritable) ? new CLEventHandle[1] : null;

            ComputeErrorCode error = CL11.EnqueueWriteBufferRect(this.Handle, destination.Handle, blocking, ref destinationOffset, ref sourceOffset, ref region, new IntPtr(destinationRowPitch), new IntPtr(destinationSlicePitch), new IntPtr(sourceRowPitch), new IntPtr(sourceSlicePitch), source, eventWaitListSize, eventHandles, newEventHandle);

            ComputeException.ThrowOnError(error);

            if (eventsWritable)
            {
                events.Add(new ComputeEvent(newEventHandle[0], this));
            }
        }