示例#1
0
        public unsafe void Write(CommandQueue commandQueue, ReadOnlySpan <T> data)
        {
            if (_disposed)
            {
                throw new ObjectDisposedException(GetType().FullName);
            }

            if (commandQueue == null)
            {
                throw new ArgumentNullException(nameof(commandQueue));

                fixed(void *ptr = data)
                {
                    var error = Api.BufferApi.clEnqueueWriteBuffer(commandQueue.Id, Id, true, 0, (uint)Size,
                                                                   (IntPtr)ptr, 0, null, out _);

                    error.ThrowOnError();
                }
        }
示例#2
0
        public CommandQueue CreateCommandQueue(Device device, bool enableProfiling, bool enableOutOfOrderExecutionMode)
        {
            if (_disposed)
            {
                throw new ObjectDisposedException(GetType().FullName);
            }

            if (device == null)
            {
                throw new ArgumentNullException(nameof(device));
            }

            if (!Devices.Contains(device))
            {
                throw new ArgumentException("Device is not attached to calling context.", nameof(device));
            }

            var commandQueue = new CommandQueue(this, device, enableProfiling, enableOutOfOrderExecutionMode, _openClApi.CommandQueueApi);

            _attachedCommandQueues.Add(commandQueue);

            return(commandQueue);
        }
示例#3
0
        private unsafe Event Execute(CommandQueue commandQueue, uint workDimensions, ulong[] globalWorkSize, ulong[] globalWorkOffset, ulong[] localWorkSize = null)
        {
            if (workDimensions == 0)
            {
                throw new ArgumentOutOfRangeException(nameof(workDimensions), workDimensions, "Work dimensions must be greater than 0.");
            }

            if (workDimensions > commandQueue.Device.MaxWorkItemDimensions)
            {
                throw new ArgumentOutOfRangeException(nameof(workDimensions), workDimensions, $"Exceeding devices maximum work item dimensions of {commandQueue.Device.MaxWorkItemDimensions}");
            }

            var globalWorkSizeArray = globalWorkSize.ToArray();

            var dimensionsWorkSize = globalWorkSizeArray.Zip(globalWorkOffset.ToArray(), (size, offset) => size + offset).ToArray();
            var maxAddress         = Math.Pow(2, commandQueue.Device.AddressBits) - 1;

            var dimensionWorkSizeExceptions = new List <Exception>();

            for (var i = 0; i < dimensionsWorkSize.Length; i++)
            {
                if (dimensionsWorkSize[i] > maxAddress)
                {
                    dimensionWorkSizeExceptions.Add(new ArgumentException($"Work size + offset of dimension {i} must not exceed devices address width of {maxAddress}"));
                }
            }
            if (dimensionWorkSizeExceptions.Any())
            {
                throw new AggregateException(dimensionWorkSizeExceptions);
            }

            var handles = new List <MemoryHandle>();

            //TODO: EnqueueNDRange expects globalWorkSize-Array of size_t (ulong for 64bit, uint for 32bit!!)
            var globalWorkSizeHandle = globalWorkSize.AsMemory().Pin();

            handles.Add(globalWorkSizeHandle);
            var globalWorkSizePtr = new UIntPtr(globalWorkSizeHandle.Pointer);

            var globalWorkOffsetHandle = globalWorkOffset.AsMemory().Pin();

            handles.Add(globalWorkOffsetHandle);
            var globalWorkOffsetPtr = new UIntPtr(globalWorkOffsetHandle.Pointer);

            var localWorkSizePtr = UIntPtr.Zero;

            if (localWorkSize != null)
            {
                var localWorkSizeArray    = localWorkSize.ToArray();
                var workItemsPerWorkGroup = localWorkSizeArray.Aggregate((ulong)1, (workSize, dimWorkSize) => workSize * dimWorkSize);
                if (workItemsPerWorkGroup > commandQueue.Device.MaxWorkGroupSize)
                {
                    throw new ArgumentException($"Total number of work-items in a work-group must not exceed devices maximum work-group size of {commandQueue.Device.MaxWorkGroupSize}.");
                }

                var workItemSizesExceptions = new List <Exception>();
                for (var i = 0; i < dimensionsWorkSize.Length; i++)
                {
                    if (localWorkSizeArray[i] > commandQueue.Device.MaxWorkItemSizes[i])
                    {
                        workItemSizesExceptions.Add(new ArgumentException($"Number of work-items in a work-group in dimension {i} must not exceed devices maximum of {commandQueue.Device.MaxWorkItemSizes[i]}"));
                    }
                }
                if (workItemSizesExceptions.Any())
                {
                    throw new AggregateException(workItemSizesExceptions);
                }

                var localWorkSizeHandle = localWorkSize.AsMemory().Pin();
                handles.Add(localWorkSizeHandle);
                localWorkSizePtr = new UIntPtr(localWorkSizeHandle.Pointer);
            }

            var error = _api.KernelApi.clEnqueueNDRangeKernel(commandQueue.Id, Id, workDimensions, globalWorkOffsetPtr,
                                                              globalWorkSizePtr, localWorkSizePtr, 0, IntPtr.Zero, out var evt);

            handles.ForEach(m => m.Dispose());
            error.ThrowOnError();

            return(new Event(_api, evt));
        }