Newer
Older
cl_event evt;
PYOPENCL_CALL_GUARDED(clEnqueueMarkerWithWaitList, (
cq.data(), PYOPENCL_WAITLIST_ARGS, &evt));
PYOPENCL_RETURN_NEW_EVENT(evt);
}
#else
// clEnqueueWaitForEvents + clEnqueueMarker is not equivalent
// in the case of an out-of-order queue.
throw error("enqueue_nd_range_kernel", CL_INVALID_VALUE,
"allow_empty_ndrange requires OpenCL 1.2");
#endif
}
PYOPENCL_RETRY_RETURN_IF_MEM_ERROR( {
cl_event evt;
PYOPENCL_CALL_GUARDED(clEnqueueNDRangeKernel, (
cq.data(),
knl.data(),
work_dim,
global_work_offset_ptr,
local_work_size_ptr,
PYOPENCL_WAITLIST_ARGS, &evt
));
PYOPENCL_RETURN_NEW_EVENT(evt);
} );
}
// }}}
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
// {{{ gl interop
inline
bool have_gl()
{
#ifdef HAVE_GL
return true;
#else
return false;
#endif
}
#ifdef HAVE_GL
#ifdef __APPLE__
inline
cl_context_properties get_apple_cgl_share_group()
{
CGLContextObj kCGLContext = CGLGetCurrentContext();
CGLShareGroupObj kCGLShareGroup = CGLGetShareGroup(kCGLContext);
return (cl_context_properties) kCGLShareGroup;
}
#endif /* __APPLE__ */
class gl_buffer : public memory_object
{
public:
gl_buffer(cl_mem mem, bool retain, hostbuf_t hostbuf=hostbuf_t())
: memory_object(mem, retain, std::move(hostbuf))
{ }
};
class gl_renderbuffer : public memory_object
{
public:
gl_renderbuffer(cl_mem mem, bool retain, hostbuf_t hostbuf=hostbuf_t())
: memory_object(mem, retain, std::move(hostbuf))
{ }
};
class gl_texture : public image
{
public:
gl_texture(cl_mem mem, bool retain, hostbuf_t hostbuf=hostbuf_t())
: image(mem, retain, std::move(hostbuf))
{ }
py::object get_gl_texture_info(cl_gl_texture_info param_name)
{
switch (param_name)
{
case CL_GL_TEXTURE_TARGET:
PYOPENCL_GET_TYPED_INFO(GLTexture, data(), param_name, GLenum);
PYOPENCL_GET_TYPED_INFO(GLTexture, data(), param_name, GLint);
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
default:
throw error("MemoryObject.get_gl_texture_info", CL_INVALID_VALUE);
}
}
};
#define PYOPENCL_WRAP_BUFFER_CREATOR(TYPE, NAME, CL_NAME, ARGS, CL_ARGS) \
inline \
TYPE *NAME ARGS \
{ \
cl_int status_code; \
PYOPENCL_PRINT_CALL_TRACE(#CL_NAME); \
cl_mem mem = CL_NAME CL_ARGS; \
\
if (status_code != CL_SUCCESS) \
throw pyopencl::error(#CL_NAME, status_code); \
\
try \
{ \
return new TYPE(mem, false); \
} \
catch (...) \
{ \
PYOPENCL_CALL_GUARDED(clReleaseMemObject, (mem)); \
throw; \
} \
}
PYOPENCL_WRAP_BUFFER_CREATOR(gl_buffer,
create_from_gl_buffer, clCreateFromGLBuffer,
(context &ctx, cl_mem_flags flags, GLuint bufobj),
(ctx.data(), flags, bufobj, &status_code));
PYOPENCL_WRAP_BUFFER_CREATOR(gl_texture,
create_from_gl_texture_2d, clCreateFromGLTexture2D,
(context &ctx, cl_mem_flags flags,
GLenum texture_target, GLint miplevel, GLuint texture),
(ctx.data(), flags, texture_target, miplevel, texture, &status_code));
PYOPENCL_WRAP_BUFFER_CREATOR(gl_texture,
create_from_gl_texture_3d, clCreateFromGLTexture3D,
(context &ctx, cl_mem_flags flags,
GLenum texture_target, GLint miplevel, GLuint texture),
(ctx.data(), flags, texture_target, miplevel, texture, &status_code));
PYOPENCL_WRAP_BUFFER_CREATOR(gl_renderbuffer,
create_from_gl_renderbuffer, clCreateFromGLRenderbuffer,
(context &ctx, cl_mem_flags flags, GLuint renderbuffer),
(ctx.data(), flags, renderbuffer, &status_code));
inline
gl_texture *create_from_gl_texture(
context &ctx, cl_mem_flags flags,
GLenum texture_target, GLint miplevel,
GLuint texture, unsigned dims)
{
if (dims == 2)
return create_from_gl_texture_2d(ctx, flags, texture_target, miplevel, texture);
else if (dims == 3)
return create_from_gl_texture_3d(ctx, flags, texture_target, miplevel, texture);
else
throw pyopencl::error("Image", CL_INVALID_VALUE,
"invalid dimension");
}
inline
py::tuple get_gl_object_info(memory_object_holder const &mem)
{
cl_gl_object_type otype;
GLuint gl_name;
PYOPENCL_CALL_GUARDED(clGetGLObjectInfo, (mem.data(), &otype, &gl_name));
return py::make_tuple(otype, gl_name);
}
#define WRAP_GL_ENQUEUE(what, What) \
inline \
event *enqueue_##what##_gl_objects( \
command_queue &cq, \
py::object py_mem_objects, \
py::object py_wait_for) \
{ \
PYOPENCL_PARSE_WAIT_FOR; \
\
std::vector<cl_mem> mem_objects; \
for (py::handle mo: py_mem_objects) \
mem_objects.push_back((mo).cast<memory_object_holder &>().data()); \
\
cl_event evt; \
PYOPENCL_CALL_GUARDED(clEnqueue##What##GLObjects, ( \
cq.data(), \
mem_objects.size(), mem_objects.empty( ) ? nullptr : &mem_objects.front(), \
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
PYOPENCL_WAITLIST_ARGS, &evt \
)); \
\
PYOPENCL_RETURN_NEW_EVENT(evt); \
}
WRAP_GL_ENQUEUE(acquire, Acquire);
WRAP_GL_ENQUEUE(release, Release);
#endif
#if defined(cl_khr_gl_sharing) && (cl_khr_gl_sharing >= 1)
inline
py::object get_gl_context_info_khr(
py::object py_properties,
cl_gl_context_info param_name,
py::object py_platform
)
{
std::vector<cl_context_properties> props
= parse_context_properties(py_properties);
typedef CL_API_ENTRY cl_int (CL_API_CALL
*func_ptr_type)(const cl_context_properties * /* properties */,
cl_gl_context_info /* param_name */,
size_t /* param_value_size */,
void * /* param_value */,
size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
func_ptr_type func_ptr;
#if PYOPENCL_CL_VERSION >= 0x1020
if (py_platform.ptr() != Py_None)
{
platform &plat = (py_platform).cast<platform &>();
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
func_ptr = (func_ptr_type) clGetExtensionFunctionAddressForPlatform(
plat.data(), "clGetGLContextInfoKHR");
}
else
{
PYOPENCL_DEPRECATED("get_gl_context_info_khr with platform=None", "2013.1", );
func_ptr = (func_ptr_type) clGetExtensionFunctionAddress(
"clGetGLContextInfoKHR");
}
#else
func_ptr = (func_ptr_type) clGetExtensionFunctionAddress(
"clGetGLContextInfoKHR");
#endif
if (!func_ptr)
throw error("Context.get_info", CL_INVALID_PLATFORM,
"clGetGLContextInfoKHR extension function not present");
cl_context_properties *props_ptr
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
switch (param_name)
{
case CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR:
{
cl_device_id param_value;
PYOPENCL_CALL_GUARDED(func_ptr,
(props_ptr, param_name, sizeof(param_value), ¶m_value, 0));
return py::object(handle_from_new_ptr( \
new device(param_value, /*retain*/ true)));
}
case CL_DEVICES_FOR_GL_CONTEXT_KHR:
{
size_t size;
PYOPENCL_CALL_GUARDED(func_ptr,
(props_ptr, param_name, 0, 0, &size));
std::vector<cl_device_id> devices;
devices.resize(size / sizeof(devices.front()));
PYOPENCL_CALL_GUARDED(func_ptr,
(props_ptr, param_name, size,
devices.empty( ) ? nullptr : &devices.front(), &size));
for (cl_device_id did: devices)
result.append(handle_from_new_ptr(
new device(did)));
return result;
}
default:
throw error("get_gl_context_info_khr", CL_INVALID_VALUE);
}
}
#endif
// }}}
// {{{ deferred implementation bits
#if PYOPENCL_CL_VERSION >= 0x2010
inline void context::set_default_device_command_queue(device const &dev, command_queue const &queue)
{
PYOPENCL_CALL_GUARDED(clSetDefaultDeviceCommandQueue,
(m_context, dev.data(), queue.data()));
}
#endif
inline program *error::get_program() const
{
return new program(m_program, /* retain */ true);
}
inline py::object create_mem_object_wrapper(cl_mem mem, bool retain=true)
{
cl_mem_object_type mem_obj_type;
PYOPENCL_CALL_GUARDED(clGetMemObjectInfo, \
(mem, CL_MEM_TYPE, sizeof(mem_obj_type), &mem_obj_type, 0));
switch (mem_obj_type)
{
case CL_MEM_OBJECT_BUFFER:
return py::object(handle_from_new_ptr(
new buffer(mem, retain)));
case CL_MEM_OBJECT_IMAGE2D:
case CL_MEM_OBJECT_IMAGE3D:
#if PYOPENCL_CL_VERSION >= 0x1020
case CL_MEM_OBJECT_IMAGE2D_ARRAY:
case CL_MEM_OBJECT_IMAGE1D:
case CL_MEM_OBJECT_IMAGE1D_ARRAY:
case CL_MEM_OBJECT_IMAGE1D_BUFFER:
#endif
return py::object(handle_from_new_ptr(
new image(mem, retain)));
default:
return py::object(handle_from_new_ptr(
new memory_object(mem, retain)));
py::object memory_object_from_int(intptr_t cl_mem_as_int, bool retain)
return create_mem_object_wrapper((cl_mem) cl_mem_as_int, retain);
}
inline
py::object memory_object_holder::get_info(cl_mem_info param_name) const
{
switch (param_name)
{
case CL_MEM_TYPE:
PYOPENCL_GET_TYPED_INFO(MemObject, data(), param_name,
cl_mem_object_type);
case CL_MEM_FLAGS:
PYOPENCL_GET_TYPED_INFO(MemObject, data(), param_name,
cl_mem_flags);
case CL_MEM_SIZE:
PYOPENCL_GET_TYPED_INFO(MemObject, data(), param_name,
size_t);
case CL_MEM_HOST_PTR:
throw pyopencl::error("MemoryObject.get_info", CL_INVALID_VALUE,
"Use MemoryObject.get_host_array to get host pointer.");
case CL_MEM_MAP_COUNT:
PYOPENCL_GET_TYPED_INFO(MemObject, data(), param_name,
cl_uint);
case CL_MEM_REFERENCE_COUNT:
PYOPENCL_GET_TYPED_INFO(MemObject, data(), param_name,
cl_uint);
case CL_MEM_CONTEXT:
PYOPENCL_GET_OPAQUE_INFO(MemObject, data(), param_name,
cl_context, context);
#if PYOPENCL_CL_VERSION >= 0x1010
case CL_MEM_ASSOCIATED_MEMOBJECT:
{
cl_mem param_value;
PYOPENCL_CALL_GUARDED(clGetMemObjectInfo, \
(data(), param_name, sizeof(param_value), ¶m_value, 0));
if (param_value == 0)
{
// no associated memory object? no problem.
}
return create_mem_object_wrapper(param_value);
}
case CL_MEM_OFFSET:
PYOPENCL_GET_TYPED_INFO(MemObject, data(), param_name,
#if PYOPENCL_CL_VERSION >= 0x2000
case CL_MEM_USES_SVM_POINTER:
PYOPENCL_GET_TYPED_INFO(MemObject, data(), param_name,
cl_bool);
#endif
#if PYOPENCL_CL_VERSION >= 0x3000
case CL_MEM_PROPERTIES:
{
std::vector<cl_mem_properties> result;
PYOPENCL_GET_VEC_INFO(MemObject, data(), param_name, result);
PYOPENCL_RETURN_VECTOR(cl_mem_properties, result);
}
#endif
default:
throw error("MemoryObjectHolder.get_info", CL_INVALID_VALUE);
}
}
// FIXME: Reenable in pypy
#ifndef PYPY_VERSION
py::object get_mem_obj_host_array(
py::object mem_obj_py,
py::object shape, py::object dtype,
py::object order_py)
{
memory_object_holder const &mem_obj =
(mem_obj_py).cast<memory_object_holder const &>();
PyArray_Descr *tp_descr;
if (PyArray_DescrConverter(dtype.ptr(), &tp_descr) != NPY_SUCCEED)
throw py::error_already_set();
cl_mem_flags mem_flags;
PYOPENCL_CALL_GUARDED(clGetMemObjectInfo,
(mem_obj.data(), CL_MEM_FLAGS, sizeof(mem_flags), &mem_flags, 0));
if (!(mem_flags & CL_MEM_USE_HOST_PTR))
throw pyopencl::error("MemoryObject.get_host_array", CL_INVALID_VALUE,
"Only MemoryObject with USE_HOST_PTR "
"is supported.");
std::vector<npy_intp> dims;
try
{
dims.push_back(py::cast<npy_intp>(shape));
}
catch (py::cast_error &)
{
for (auto it: shape)
dims.push_back(it.cast<npy_intp>());
}
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
NPY_ORDER order = PyArray_CORDER;
PyArray_OrderConverter(order_py.ptr(), &order);
int ary_flags = 0;
if (order == PyArray_FORTRANORDER)
ary_flags |= NPY_FARRAY;
else if (order == PyArray_CORDER)
ary_flags |= NPY_CARRAY;
else
throw std::runtime_error("unrecognized order specifier");
void *host_ptr;
size_t mem_obj_size;
PYOPENCL_CALL_GUARDED(clGetMemObjectInfo,
(mem_obj.data(), CL_MEM_HOST_PTR, sizeof(host_ptr),
&host_ptr, 0));
PYOPENCL_CALL_GUARDED(clGetMemObjectInfo,
(mem_obj.data(), CL_MEM_SIZE, sizeof(mem_obj_size),
&mem_obj_size, 0));
py::object result = py::reinterpret_steal<py::object>(PyArray_NewFromDescr(
dims.size(), &dims.front(), /*strides*/ nullptr,
host_ptr, ary_flags, /*obj*/nullptr));
if ((size_t) PyArray_NBYTES(result.ptr()) > mem_obj_size)
throw pyopencl::error("MemoryObject.get_host_array",
CL_INVALID_VALUE,
"Resulting array is larger than memory object.");
PyArray_BASE(result.ptr()) = mem_obj_py.ptr();
Py_INCREF(mem_obj_py.ptr());
return result;
}
// }}}
}
#endif
// vim: foldmethod=marker