Commit 41b817f3 by John Plate Committed by Angle LUCI CQ

CL: Add buffer enqueue commands

Add buffer enqueue commands to front end and pass-through back end. Bug: angleproject:6015 Change-Id: I936530d31903e395550e4540339ebec2e6702e65 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2928425 Commit-Queue: John Plate <jplate@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCody Northrop <cnorthrop@google.com>
parent daf18594
......@@ -50,6 +50,9 @@ class BitField
return (isSet(bits1) ? 1 : 0) + (isSet(bits2) ? 1 : 0) + (isSet(bits3) ? 1 : 0) <= 1;
}
BitField mask(cl_bitfield bits) const { return BitField(mBits & bits); }
BitField mask(const BitField &other) const { return BitField(mBits & other.mBits); }
void set(cl_bitfield bits) { mBits |= bits; }
void set(const BitField &other) { mBits |= other.mBits; }
void clear(cl_bitfield bits) { mBits &= ~bits; }
......
......@@ -23,6 +23,7 @@ class Buffer final : public Memory
const void *createInfo,
cl_int &errorCode);
bool isRegionValid(size_t offset, size_t size) const;
bool isRegionValid(const cl_buffer_region &region) const;
static bool IsValid(const _cl_mem *buffer);
......@@ -47,6 +48,11 @@ class Buffer final : public Memory
friend class Object;
};
inline bool Buffer::isRegionValid(size_t offset, size_t size) const
{
return offset < mSize && offset + size <= mSize;
}
inline bool Buffer::isRegionValid(const cl_buffer_region &region) const
{
return region.origin < mSize && region.origin + region.size <= mSize;
......
......@@ -31,6 +31,93 @@ class CommandQueue final : public _cl_command_queue, public Object
cl_bool enable,
cl_command_queue_properties *oldProperties);
cl_int enqueueReadBuffer(cl_mem buffer,
cl_bool blockingRead,
size_t offset,
size_t size,
void *ptr,
cl_uint numEventsInWaitList,
const cl_event *eventWaitList,
cl_event *event);
cl_int enqueueWriteBuffer(cl_mem buffer,
cl_bool blockingWrite,
size_t offset,
size_t size,
const void *ptr,
cl_uint numEventsInWaitList,
const cl_event *eventWaitList,
cl_event *event);
cl_int enqueueReadBufferRect(cl_mem buffer,
cl_bool blockingRead,
const size_t *bufferOrigin,
const size_t *hostOrigin,
const size_t *region,
size_t bufferRowPitch,
size_t bufferSlicePitch,
size_t hostRowPitch,
size_t hostSlicePitch,
void *ptr,
cl_uint numEventsInWaitList,
const cl_event *eventWaitList,
cl_event *event);
cl_int enqueueWriteBufferRect(cl_mem buffer,
cl_bool blockingWrite,
const size_t *bufferOrigin,
const size_t *hostOrigin,
const size_t *region,
size_t bufferRowPitch,
size_t bufferSlicePitch,
size_t hostRowPitch,
size_t hostSlicePitch,
const void *ptr,
cl_uint numEventsInWaitList,
const cl_event *eventWaitList,
cl_event *event);
cl_int enqueueCopyBuffer(cl_mem srcBuffer,
cl_mem dstBuffer,
size_t srcOffset,
size_t dstOffset,
size_t size,
cl_uint numEventsInWaitList,
const cl_event *eventWaitList,
cl_event *event);
cl_int enqueueCopyBufferRect(cl_mem srcBuffer,
cl_mem dstBuffer,
const size_t *srcOrigin,
const size_t *dstOrigin,
const size_t *region,
size_t srcRowPitch,
size_t srcSlicePitch,
size_t dstRowPitch,
size_t dstSlicePitch,
cl_uint numEventsInWaitList,
const cl_event *eventWaitList,
cl_event *event);
cl_int enqueueFillBuffer(cl_mem buffer,
const void *pattern,
size_t patternSize,
size_t offset,
size_t size,
cl_uint numEventsInWaitList,
const cl_event *eventWaitList,
cl_event *event);
void *enqueueMapBuffer(cl_mem buffer,
cl_bool blockingMap,
MapFlags mapFlags,
size_t offset,
size_t size,
cl_uint numEventsInWaitList,
const cl_event *eventWaitList,
cl_event *event,
cl_int &errorCode);
public:
using PropArray = std::vector<cl_queue_properties>;
......@@ -38,10 +125,14 @@ class CommandQueue final : public _cl_command_queue, public Object
~CommandQueue() override;
Context &getContext();
const Context &getContext() const;
const Device &getDevice() const;
CommandQueueProperties getProperties() const;
bool isOnHost() const;
bool isOnDevice() const;
bool hasSize() const;
cl_uint getSize() const;
......@@ -71,6 +162,11 @@ class CommandQueue final : public _cl_command_queue, public Object
friend class Object;
};
inline Context &CommandQueue::getContext()
{
return *mContext;
}
inline const Context &CommandQueue::getContext() const
{
return *mContext;
......@@ -86,6 +182,16 @@ inline CommandQueueProperties CommandQueue::getProperties() const
return mProperties;
}
inline bool CommandQueue::isOnHost() const
{
return mProperties.isNotSet(CL_QUEUE_ON_DEVICE);
}
inline bool CommandQueue::isOnDevice() const
{
return mProperties.isSet(CL_QUEUE_ON_DEVICE);
}
inline bool CommandQueue::hasSize() const
{
return mSize != kNoSize;
......
......@@ -292,13 +292,7 @@ cl_event Context::createUserEvent(cl_int &errorCode)
cl_int Context::waitForEvents(cl_uint numEvents, const cl_event *eventList)
{
EventPtrs events;
events.reserve(numEvents);
while (numEvents-- != 0u)
{
events.emplace_back(&(*eventList++)->cast<Event>());
}
return mImpl->waitForEvents(events);
return mImpl->waitForEvents(Event::Cast(numEvents, eventList));
}
Context::~Context() = default;
......
......@@ -71,7 +71,6 @@ cl_int Device::getInfo(DeviceInfo name, size_t valueSize, void *value, size_t *v
case DeviceInfo::MaxPipeArgs:
case DeviceInfo::PipeMaxActiveReservations:
case DeviceInfo::PipeMaxPacketSize:
case DeviceInfo::MemBaseAddrAlign:
case DeviceInfo::MinDataTypeAlignSize:
case DeviceInfo::GlobalMemCacheType:
case DeviceInfo::GlobalMemCachelineSize:
......@@ -221,6 +220,10 @@ cl_int Device::getInfo(DeviceInfo name, size_t valueSize, void *value, size_t *v
copyValue = &mInfo.mImageBaseAddressAlignment;
copySize = sizeof(mInfo.mImageBaseAddressAlignment);
break;
case DeviceInfo::MemBaseAddrAlign:
copyValue = &mInfo.mMemBaseAddrAlign;
copySize = sizeof(mInfo.mMemBaseAddrAlign);
break;
case DeviceInfo::QueueOnDeviceMaxSize:
copyValue = &mInfo.mQueueOnDeviceMaxSize;
copySize = sizeof(mInfo.mQueueOnDeviceMaxSize);
......
......@@ -122,10 +122,31 @@ void Event::callback(cl_int commandStatus)
}
}
EventPtrs Event::Cast(cl_uint numEvents, const cl_event *eventList)
{
EventPtrs events;
events.reserve(numEvents);
while (numEvents-- != 0u)
{
events.emplace_back(&(*eventList++)->cast<Event>());
}
return events;
}
Event::Event(Context &context, cl_int &errorCode)
: mContext(&context),
mImpl(context.getImpl().createUserEvent(*this, errorCode)),
mCommandType(CL_COMMAND_USER)
mCommandType(CL_COMMAND_USER),
mImpl(context.getImpl().createUserEvent(*this, errorCode))
{}
Event::Event(CommandQueue &queue,
cl_command_type commandType,
const rx::CLEventImpl::CreateFunc &createFunc,
cl_int &errorCode)
: mContext(&queue.getContext()),
mCommandQueue(&queue),
mCommandType(commandType),
mImpl(createFunc(*this))
{}
} // namespace cl
......@@ -42,15 +42,22 @@ class Event final : public _cl_event, public Object
void callback(cl_int commandStatus);
static EventPtrs Cast(cl_uint numEvents, const cl_event *eventList);
private:
using CallbackData = std::pair<EventCB, void *>;
Event(Context &context, cl_int &errorCode);
Event(CommandQueue &queue,
cl_command_type commandType,
const rx::CLEventImpl::CreateFunc &createFunc,
cl_int &errorCode);
const ContextPtr mContext;
const CommandQueuePtr mCommandQueue;
const rx::CLEventImpl::Ptr mImpl;
const cl_command_type mCommandType;
const rx::CLEventImpl::Ptr mImpl;
bool mStatusWasChanged = false;
......
......@@ -103,6 +103,30 @@ cl_int Memory::getInfo(MemInfo name, size_t valueSize, void *value, size_t *valu
Memory::~Memory() = default;
MemFlags Memory::getEffectiveFlags() const
{
MemFlags flags = mFlags;
if (mParent)
{
const MemFlags parent = mParent->getFlags();
const MemFlags access(CL_MEM_READ_WRITE | CL_MEM_READ_ONLY | CL_MEM_WRITE_ONLY);
const MemFlags hostAccess(CL_MEM_HOST_WRITE_ONLY | CL_MEM_HOST_READ_ONLY |
CL_MEM_HOST_NO_ACCESS);
const MemFlags hostPtrFlags(CL_MEM_USE_HOST_PTR | CL_MEM_ALLOC_HOST_PTR |
CL_MEM_COPY_HOST_PTR);
if (flags.isNotSet(access))
{
flags.set(parent.mask(access));
}
if (flags.isNotSet(hostAccess))
{
flags.set(parent.mask(hostAccess));
}
flags.set(parent.mask(hostPtrFlags));
}
return flags;
}
Memory::Memory(const Buffer &buffer,
Context &context,
PropArray &&properties,
......
......@@ -39,6 +39,8 @@ class Memory : public _cl_mem, public Object
template <typename T = rx::CLMemoryImpl>
T &getImpl() const;
MemFlags getEffectiveFlags() const;
protected:
Memory(const Buffer &buffer,
Context &context,
......
......@@ -8,7 +8,7 @@
#ifndef LIBANGLE_RENDERER_CLCOMMANDQUEUEIMPL_H_
#define LIBANGLE_RENDERER_CLCOMMANDQUEUEIMPL_H_
#include "libANGLE/renderer/CLtypes.h"
#include "libANGLE/renderer/CLEventImpl.h"
namespace rx
{
......@@ -23,6 +23,85 @@ class CLCommandQueueImpl : angle::NonCopyable
virtual cl_int setProperty(cl::CommandQueueProperties properties, cl_bool enable) = 0;
virtual cl_int enqueueReadBuffer(const cl::Buffer &buffer,
bool blocking,
size_t offset,
size_t size,
void *ptr,
const cl::EventPtrs &waitEvents,
CLEventImpl::CreateFunc *eventCreateFunc) = 0;
virtual cl_int enqueueWriteBuffer(const cl::Buffer &buffer,
bool blocking,
size_t offset,
size_t size,
const void *ptr,
const cl::EventPtrs &waitEvents,
CLEventImpl::CreateFunc *eventCreateFunc) = 0;
virtual cl_int enqueueReadBufferRect(const cl::Buffer &buffer,
bool blocking,
const size_t bufferOrigin[3],
const size_t hostOrigin[3],
const size_t region[3],
size_t bufferRowPitch,
size_t bufferSlicePitch,
size_t hostRowPitch,
size_t hostSlicePitch,
void *ptr,
const cl::EventPtrs &waitEvents,
CLEventImpl::CreateFunc *eventCreateFunc) = 0;
virtual cl_int enqueueWriteBufferRect(const cl::Buffer &buffer,
bool blocking,
const size_t bufferOrigin[3],
const size_t hostOrigin[3],
const size_t region[3],
size_t bufferRowPitch,
size_t bufferSlicePitch,
size_t hostRowPitch,
size_t hostSlicePitch,
const void *ptr,
const cl::EventPtrs &waitEvents,
CLEventImpl::CreateFunc *eventCreateFunc) = 0;
virtual cl_int enqueueCopyBuffer(const cl::Buffer &srcBuffer,
const cl::Buffer &dstBuffer,
size_t srcOffset,
size_t dstOffset,
size_t size,
const cl::EventPtrs &waitEvents,
CLEventImpl::CreateFunc *eventCreateFunc) = 0;
virtual cl_int enqueueCopyBufferRect(const cl::Buffer &srcBuffer,
const cl::Buffer &dstBuffer,
const size_t srcOrigin[3],
const size_t dstOrigin[3],
const size_t region[3],
size_t srcRowPitch,
size_t srcSlicePitch,
size_t dstRowPitch,
size_t dstSlicePitch,
const cl::EventPtrs &waitEvents,
CLEventImpl::CreateFunc *eventCreateFunc) = 0;
virtual cl_int enqueueFillBuffer(const cl::Buffer &buffer,
const void *pattern,
size_t patternSize,
size_t offset,
size_t size,
const cl::EventPtrs &waitEvents,
CLEventImpl::CreateFunc *eventCreateFunc) = 0;
virtual void *enqueueMapBuffer(const cl::Buffer &buffer,
bool blocking,
cl::MapFlags mapFlags,
size_t offset,
size_t size,
const cl::EventPtrs &waitEvents,
CLEventImpl::CreateFunc *eventCreateFunc,
cl_int &errorCode) = 0;
protected:
const cl::CommandQueue &mCommandQueue;
};
......
......@@ -52,6 +52,7 @@ class CLDeviceImpl : angle::NonCopyable
size_t mImageMaxArraySize = 0u;
cl_uint mImagePitchAlignment = 0u;
cl_uint mImageBaseAddressAlignment = 0u;
cl_uint mMemBaseAddrAlign = 0u;
cl_uint mQueueOnDeviceMaxSize = 0u;
std::string mBuiltInKernels;
NameVersionVector mBuiltInKernelsWithVersion;
......
......@@ -16,7 +16,8 @@ namespace rx
class CLEventImpl : angle::NonCopyable
{
public:
using Ptr = std::unique_ptr<CLEventImpl>;
using Ptr = std::unique_ptr<CLEventImpl>;
using CreateFunc = std::function<Ptr(const cl::Event &)>;
CLEventImpl(const cl::Event &event);
virtual ~CLEventImpl();
......
......@@ -22,6 +22,85 @@ class CLCommandQueueCL : public CLCommandQueueImpl
cl_int setProperty(cl::CommandQueueProperties properties, cl_bool enable) override;
cl_int enqueueReadBuffer(const cl::Buffer &buffer,
bool blocking,
size_t offset,
size_t size,
void *ptr,
const cl::EventPtrs &waitEvents,
CLEventImpl::CreateFunc *eventCreateFunc) override;
cl_int enqueueWriteBuffer(const cl::Buffer &buffer,
bool blocking,
size_t offset,
size_t size,
const void *ptr,
const cl::EventPtrs &waitEvents,
CLEventImpl::CreateFunc *eventCreateFunc) override;
cl_int enqueueReadBufferRect(const cl::Buffer &buffer,
bool blocking,
const size_t bufferOrigin[3],
const size_t hostOrigin[3],
const size_t region[3],
size_t bufferRowPitch,
size_t bufferSlicePitch,
size_t hostRowPitch,
size_t hostSlicePitch,
void *ptr,
const cl::EventPtrs &waitEvents,
CLEventImpl::CreateFunc *eventCreateFunc) override;
cl_int enqueueWriteBufferRect(const cl::Buffer &buffer,
bool blocking,
const size_t bufferOrigin[3],
const size_t hostOrigin[3],
const size_t region[3],
size_t bufferRowPitch,
size_t bufferSlicePitch,
size_t hostRowPitch,
size_t hostSlicePitch,
const void *ptr,
const cl::EventPtrs &waitEvents,
CLEventImpl::CreateFunc *eventCreateFunc) override;
cl_int enqueueCopyBuffer(const cl::Buffer &srcBuffer,
const cl::Buffer &dstBuffer,
size_t srcOffset,
size_t dstOffset,
size_t size,
const cl::EventPtrs &waitEvents,
CLEventImpl::CreateFunc *eventCreateFunc) override;
cl_int enqueueCopyBufferRect(const cl::Buffer &srcBuffer,
const cl::Buffer &dstBuffer,
const size_t srcOrigin[3],
const size_t dstOrigin[3],
const size_t region[3],
size_t srcRowPitch,
size_t srcSlicePitch,
size_t dstRowPitch,
size_t dstSlicePitch,
const cl::EventPtrs &waitEvents,
CLEventImpl::CreateFunc *eventCreateFunc) override;
cl_int enqueueFillBuffer(const cl::Buffer &buffer,
const void *pattern,
size_t patternSize,
size_t offset,
size_t size,
const cl::EventPtrs &waitEvents,
CLEventImpl::CreateFunc *eventCreateFunc) override;
void *enqueueMapBuffer(const cl::Buffer &buffer,
bool blocking,
cl::MapFlags mapFlags,
size_t offset,
size_t size,
const cl::EventPtrs &waitEvents,
CLEventImpl::CreateFunc *eventCreateFunc,
cl_int &errorCode) override;
private:
const cl_command_queue mNative;
};
......
......@@ -280,12 +280,7 @@ CLEventImpl::Ptr CLContextCL::createUserEvent(const cl::Event &event, cl_int &er
cl_int CLContextCL::waitForEvents(const cl::EventPtrs &events)
{
std::vector<cl_event> nativeEvents;
nativeEvents.reserve(events.size());
for (const cl::EventPtr &event : events)
{
nativeEvents.emplace_back(event->getImpl<CLEventCL>().getNative());
}
const std::vector<cl_event> nativeEvents = CLEventCL::Cast(events);
return mNative->getDispatch().clWaitForEvents(static_cast<cl_uint>(nativeEvents.size()),
nativeEvents.data());
}
......
......@@ -89,7 +89,8 @@ CLDeviceImpl::Info CLDeviceCL::createInfo(cl::DeviceType type) const
!GetDeviceInfo(mNative, cl::DeviceInfo::Image2D_MaxHeight, info.mImage2D_MaxHeight) ||
!GetDeviceInfo(mNative, cl::DeviceInfo::Image3D_MaxWidth, info.mImage3D_MaxWidth) ||
!GetDeviceInfo(mNative, cl::DeviceInfo::Image3D_MaxHeight, info.mImage3D_MaxHeight) ||
!GetDeviceInfo(mNative, cl::DeviceInfo::Image3D_MaxDepth, info.mImage3D_MaxDepth))
!GetDeviceInfo(mNative, cl::DeviceInfo::Image3D_MaxDepth, info.mImage3D_MaxDepth) ||
!GetDeviceInfo(mNative, cl::DeviceInfo::MemBaseAddrAlign, info.mMemBaseAddrAlign))
{
return Info{};
}
......
......@@ -41,6 +41,17 @@ cl_int CLEventCL::setCallback(cl::Event &event, cl_int commandExecCallbackType)
&event);
}
std::vector<cl_event> CLEventCL::Cast(const cl::EventPtrs &events)
{
std::vector<cl_event> nativeEvents;
nativeEvents.reserve(events.size());
for (const cl::EventPtr &event : events)
{
nativeEvents.emplace_back(event->getImpl<CLEventCL>().getNative());
}
return nativeEvents;
}
void CLEventCL::Callback(cl_event event, cl_int commandStatus, void *userData)
{
static_cast<cl::Event *>(userData)->callback(commandStatus);
......
......@@ -29,6 +29,8 @@ class CLEventCL : public CLEventImpl
cl_int setCallback(cl::Event &event, cl_int commandExecCallbackType) override;
static std::vector<cl_event> Cast(const cl::EventPtrs &events);
private:
static void CL_CALLBACK Callback(cl_event event, cl_int commandStatus, void *userData);
......
......@@ -19,6 +19,8 @@ class CLMemoryCL : public CLMemoryImpl
CLMemoryCL(const cl::Memory &memory, cl_mem native);
~CLMemoryCL() override;
cl_mem getNative();
size_t getSize(cl_int &errorCode) const override;
CLMemoryImpl::Ptr createSubBuffer(const cl::Buffer &buffer,
......@@ -29,6 +31,11 @@ class CLMemoryCL : public CLMemoryImpl
const cl_mem mNative;
};
inline cl_mem CLMemoryCL::getNative()
{
return mNative;
}
} // namespace rx
#endif // LIBANGLE_RENDERER_CL_CLMEMORYCL_H_
......@@ -714,8 +714,8 @@ cl_int EnqueueReadBuffer(cl_command_queue command_queue,
const cl_event *event_wait_list,
cl_event *event)
{
WARN_NOT_SUPPORTED(EnqueueReadBuffer);
return 0;
return command_queue->cast<CommandQueue>().enqueueReadBuffer(
buffer, blocking_read, offset, size, ptr, num_events_in_wait_list, event_wait_list, event);
}
cl_int EnqueueReadBufferRect(cl_command_queue command_queue,
......@@ -733,8 +733,10 @@ cl_int EnqueueReadBufferRect(cl_command_queue command_queue,
const cl_event *event_wait_list,
cl_event *event)
{
WARN_NOT_SUPPORTED(EnqueueReadBufferRect);
return 0;
return command_queue->cast<CommandQueue>().enqueueReadBufferRect(
buffer, blocking_read, buffer_origin, host_origin, region, buffer_row_pitch,
buffer_slice_pitch, host_row_pitch, host_slice_pitch, ptr, num_events_in_wait_list,
event_wait_list, event);
}
cl_int EnqueueWriteBuffer(cl_command_queue command_queue,
......@@ -747,8 +749,8 @@ cl_int EnqueueWriteBuffer(cl_command_queue command_queue,
const cl_event *event_wait_list,
cl_event *event)
{
WARN_NOT_SUPPORTED(EnqueueWriteBuffer);
return 0;
return command_queue->cast<CommandQueue>().enqueueWriteBuffer(
buffer, blocking_write, offset, size, ptr, num_events_in_wait_list, event_wait_list, event);
}
cl_int EnqueueWriteBufferRect(cl_command_queue command_queue,
......@@ -766,8 +768,10 @@ cl_int EnqueueWriteBufferRect(cl_command_queue command_queue,
const cl_event *event_wait_list,
cl_event *event)
{
WARN_NOT_SUPPORTED(EnqueueWriteBufferRect);
return 0;
return command_queue->cast<CommandQueue>().enqueueWriteBufferRect(
buffer, blocking_write, buffer_origin, host_origin, region, buffer_row_pitch,
buffer_slice_pitch, host_row_pitch, host_slice_pitch, ptr, num_events_in_wait_list,
event_wait_list, event);
}
cl_int EnqueueFillBuffer(cl_command_queue command_queue,
......@@ -780,8 +784,9 @@ cl_int EnqueueFillBuffer(cl_command_queue command_queue,
const cl_event *event_wait_list,
cl_event *event)
{
WARN_NOT_SUPPORTED(EnqueueFillBuffer);
return 0;
return command_queue->cast<CommandQueue>().enqueueFillBuffer(
buffer, pattern, pattern_size, offset, size, num_events_in_wait_list, event_wait_list,
event);
}
cl_int EnqueueCopyBuffer(cl_command_queue command_queue,
......@@ -794,8 +799,9 @@ cl_int EnqueueCopyBuffer(cl_command_queue command_queue,
const cl_event *event_wait_list,
cl_event *event)
{
WARN_NOT_SUPPORTED(EnqueueCopyBuffer);
return 0;
return command_queue->cast<CommandQueue>().enqueueCopyBuffer(
src_buffer, dst_buffer, src_offset, dst_offset, size, num_events_in_wait_list,
event_wait_list, event);
}
cl_int EnqueueCopyBufferRect(cl_command_queue command_queue,
......@@ -812,8 +818,9 @@ cl_int EnqueueCopyBufferRect(cl_command_queue command_queue,
const cl_event *event_wait_list,
cl_event *event)
{
WARN_NOT_SUPPORTED(EnqueueCopyBufferRect);
return 0;
return command_queue->cast<CommandQueue>().enqueueCopyBufferRect(
src_buffer, dst_buffer, src_origin, dst_origin, region, src_row_pitch, src_slice_pitch,
dst_row_pitch, dst_slice_pitch, num_events_in_wait_list, event_wait_list, event);
}
cl_int EnqueueReadImage(cl_command_queue command_queue,
......@@ -914,8 +921,9 @@ void *EnqueueMapBuffer(cl_command_queue command_queue,
cl_event *event,
cl_int &errorCode)
{
WARN_NOT_SUPPORTED(EnqueueMapBuffer);
return 0;
return command_queue->cast<CommandQueue>().enqueueMapBuffer(
buffer, blocking_map, map_flags, offset, size, num_events_in_wait_list, event_wait_list,
event, errorCode);
}
void *EnqueueMapImage(cl_command_queue command_queue,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment