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