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(); } }
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); }
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)); }