diff --git a/cffi_build.py.in b/cffi_build.py.in index d77594052077c1a17783b0e38c99a6842a357933..f948c8247a124ea40b3770c13da5d4fb14c6539c 100644 --- a/cffi_build.py.in +++ b/cffi_build.py.in @@ -69,6 +69,7 @@ ffi.set_source("pyopencl._cffi", "src/c_wrapper/command_queue.cpp", "src/c_wrapper/event.cpp", "src/c_wrapper/memory_object.cpp", + "src/c_wrapper/svm.cpp", "src/c_wrapper/image.cpp", "src/c_wrapper/gl_obj.cpp", "src/c_wrapper/memory_map.cpp", diff --git a/src/c_wrapper/command_queue.cpp b/src/c_wrapper/command_queue.cpp index c540064fb8dd02dde9f5449fc6b11eaf7a291fcb..b8ecef1ee6b950b23888e37032caf632e3fe9bb4 100644 --- a/src/c_wrapper/command_queue.cpp +++ b/src/c_wrapper/command_queue.cpp @@ -93,7 +93,7 @@ enqueue_marker_with_wait_list(clobj_t *evt, clobj_t _queue, wait_for, event_out(evt)); }); #else - PYOPENCL_UNSUPPORTED(clEnqueueMarkerWithWaitList, "CL 1.1 and below") + PYOPENCL_UNSUPPORTED_BEFORE(clEnqueueMarkerWithWaitList, "CL 1.2") #endif } @@ -109,7 +109,7 @@ enqueue_barrier_with_wait_list(clobj_t *evt, clobj_t _queue, wait_for, event_out(evt)); }); #else - PYOPENCL_UNSUPPORTED(clEnqueueBarrierWithWaitList, "CL 1.1 and below") + PYOPENCL_UNSUPPORTED_BEFORE(clEnqueueBarrierWithWaitList, "CL 1.2") #endif } diff --git a/src/c_wrapper/error.h b/src/c_wrapper/error.h index 30090188399c9fdd1fb54b855379a29c27c5d4d2..0346fcd63def77a08cff6232df001eb21c2bc7e1 100644 --- a/src/c_wrapper/error.h +++ b/src/c_wrapper/error.h @@ -21,6 +21,7 @@ #define PYOPENCL_CL_CASTABLE_THIS data() #endif +// discouraged, assumes 'version linearity', use PYOPENCL_UNSUPPORTED_BEFORE #define PYOPENCL_UNSUPPORTED(ROUTINE, VERSION) \ auto err = (error*)malloc(sizeof(error)); \ err->routine = strdup(#ROUTINE); \ @@ -29,6 +30,14 @@ err->other = 0; \ return err; +#define PYOPENCL_UNSUPPORTED_BEFORE(ROUTINE, VERSION) \ + auto err = (error*)malloc(sizeof(error)); \ + err->routine = strdup(#ROUTINE); \ + err->msg = strdup("unsupported before " VERSION); \ + err->code = CL_INVALID_VALUE; \ + err->other = 0; \ + return err; + class clerror : public std::runtime_error { private: const char *m_routine; diff --git a/src/c_wrapper/memory_object.cpp b/src/c_wrapper/memory_object.cpp index 1c199e7f454ba718d54965e941cb2a653906169c..6f1ba321307931e6194860b9db292aa2a2fa372a 100644 --- a/src/c_wrapper/memory_object.cpp +++ b/src/c_wrapper/memory_object.cpp @@ -111,6 +111,6 @@ enqueue_migrate_mem_objects(clobj_t *evt, clobj_t _queue, mem_obj, flags, wait_for, event_out(evt)); }); #else - PYOPENCL_UNSUPPORTED(clEnqueueMigrateMemObjects, "CL 1.1 and below") + PYOPENCL_UNSUPPORTED_BEFORE(clEnqueueMigrateMemObjects, "CL 1.2") #endif } diff --git a/src/c_wrapper/svm.cpp b/src/c_wrapper/svm.cpp new file mode 100644 index 0000000000000000000000000000000000000000..875c9271b197aaa889689922c2214c2ad1640938 --- /dev/null +++ b/src/c_wrapper/svm.cpp @@ -0,0 +1,173 @@ +#include "context.h" +#include "command_queue.h" +#include "event.h" + +error* +svm_alloc( + clobj_t _ctx, cl_mem_flags flags, size_t size, cl_uint alignment, + void **result) +{ +#if PYOPENCL_CL_VERSION >= 0x2000 + auto ctx = static_cast(_ctx); + return c_handle_retry_mem_error([&] { + *result = clSVMAlloc(ctx->data(), flags, size, alignment); + if (!*result) + throw clerror("clSVMalloc", CL_INVALID_VALUE, + "(allocation failure, unspecified reason)"); + }); +#else + PYOPENCL_UNSUPPORTED_BEFORE(clSVMAlloc, "CL 2.0") +#endif +} + + +error* +svm_free(clobj_t _ctx, void *svm_pointer) +{ +#if PYOPENCL_CL_VERSION >= 0x2000 + auto ctx = static_cast(_ctx); + // no error returns (?!) + clSVMFree(ctx->data(), svm_pointer); + return nullptr; +#else + PYOPENCL_UNSUPPORTED_BEFORE(clSVMFree, "CL 2.0") +#endif +} + + +error* +enqueue_svm_free( + clobj_t *evt, clobj_t _queue, + cl_uint num_svm_pointers, + void *svm_pointers[], + const clobj_t *_wait_for, uint32_t num_wait_for) +{ +#if PYOPENCL_CL_VERSION >= 0x2000 + const auto wait_for = buf_from_class(_wait_for, num_wait_for); + auto queue = static_cast(_queue); + return c_handle_retry_mem_error([&] { + pyopencl_call_guarded( + clEnqueueSVMFree, queue, + num_svm_pointers, svm_pointers, + /* pfn_free_func*/ nullptr, + /* user_data */ nullptr, + wait_for, event_out(evt)); + }); +#else + PYOPENCL_UNSUPPORTED_BEFORE(clEnqueueSVMFree, "CL 2.0") +#endif +} + + +error* +enqueue_svm_memcpy( + clobj_t *evt, clobj_t _queue, + cl_bool is_blocking, + void *dst_ptr, const void *src_ptr, size_t size, + const clobj_t *_wait_for, uint32_t num_wait_for) +{ +#if PYOPENCL_CL_VERSION >= 0x2000 + const auto wait_for = buf_from_class(_wait_for, num_wait_for); + auto queue = static_cast(_queue); + return c_handle_retry_mem_error([&] { + pyopencl_call_guarded( + clEnqueueSVMMemcpy, queue, + is_blocking, + dst_ptr, src_ptr, size, + wait_for, event_out(evt)); + }); +#else + PYOPENCL_UNSUPPORTED_BEFORE(clEnqueueSVMMemcpy, "CL 2.0") +#endif +} + + +error* +enqueue_svm_memfill( + clobj_t *evt, clobj_t _queue, + void *svm_ptr, + const void *pattern, size_t pattern_size, size_t size, + const clobj_t *_wait_for, uint32_t num_wait_for) +{ +#if PYOPENCL_CL_VERSION >= 0x2000 + const auto wait_for = buf_from_class(_wait_for, num_wait_for); + auto queue = static_cast(_queue); + return c_handle_retry_mem_error([&] { + pyopencl_call_guarded( + clEnqueueSVMMemFill, queue, + svm_ptr, + pattern, pattern_size, size, + wait_for, event_out(evt)); + }); +#else + PYOPENCL_UNSUPPORTED_BEFORE(clEnqueueSVMMemFill, "CL 2.0") +#endif +} + + +error* +enqueue_svm_map( + clobj_t *evt, clobj_t _queue, + cl_bool blocking_map, cl_map_flags map_flags, + void *svm_ptr, size_t size, + const clobj_t *_wait_for, uint32_t num_wait_for) +{ +#if PYOPENCL_CL_VERSION >= 0x2000 + const auto wait_for = buf_from_class(_wait_for, num_wait_for); + auto queue = static_cast(_queue); + return c_handle_retry_mem_error([&] { + pyopencl_call_guarded( + clEnqueueSVMMap, queue, + blocking_map, map_flags, + svm_ptr, size, + wait_for, event_out(evt)); + }); +#else + PYOPENCL_UNSUPPORTED_BEFORE(clEnqueueSVMMap, "CL 2.0") +#endif +} + + +error* +enqueue_svm_unmap( + clobj_t *evt, clobj_t _queue, + void *svm_ptr, + const clobj_t *_wait_for, uint32_t num_wait_for) +{ +#if PYOPENCL_CL_VERSION >= 0x2000 + const auto wait_for = buf_from_class(_wait_for, num_wait_for); + auto queue = static_cast(_queue); + return c_handle_retry_mem_error([&] { + pyopencl_call_guarded( + clEnqueueSVMUnmap, queue, + svm_ptr, + wait_for, event_out(evt)); + }); +#else + PYOPENCL_UNSUPPORTED_BEFORE(clEnqueueSVMUnmap, "CL 2.0") +#endif +} + + +error* +enqueue_svm_migrate_mem( + clobj_t *evt, clobj_t _queue, + cl_uint num_svm_pointers, + const void **svm_pointers, + const size_t *sizes, + cl_mem_migration_flags flags, + const clobj_t *_wait_for, uint32_t num_wait_for) +{ +#if PYOPENCL_CL_VERSION >= 0x2010 + const auto wait_for = buf_from_class(_wait_for, num_wait_for); + auto queue = static_cast(_queue); + return c_handle_retry_mem_error([&] { + pyopencl_call_guarded( + clEnqueueSVMMigrateMem, queue, + num_svm_pointers, svm_pointers, sizes, flags, + wait_for, event_out(evt)); + }); +#else + PYOPENCL_UNSUPPORTED_BEFORE(clEnqueueSVMMigrateMem, "CL 2.1") +#endif +} diff --git a/src/c_wrapper/svm.h b/src/c_wrapper/svm.h new file mode 100644 index 0000000000000000000000000000000000000000..c0e39ec47390d543e0ed8e943edaf10522842d33 --- /dev/null +++ b/src/c_wrapper/svm.h @@ -0,0 +1,4 @@ +#ifndef __PYOPENCL_SVM_H +#define __PYOPENCL_SVM_H + +#endif diff --git a/src/c_wrapper/wrap_cl_core.h b/src/c_wrapper/wrap_cl_core.h index 5d8b00efab884449195a8d77fdfd1ea112d2f665..c96b53f189aa526e09893da68800769b8effead2 100644 --- a/src/c_wrapper/wrap_cl_core.h +++ b/src/c_wrapper/wrap_cl_core.h @@ -119,6 +119,7 @@ error *memory_object__get_host_array(clobj_t, void **hostptr, size_t *size); // }}} // {{{ memory map + error *memory_map__release(clobj_t _map, clobj_t _queue, const clobj_t *_wait_for, uint32_t num_wait_for, clobj_t *evt); @@ -127,6 +128,43 @@ void *memory_map__data(clobj_t _map); // }}} // {{{ svm + +error* svm_alloc( + clobj_t _ctx, cl_mem_flags flags, size_t size, cl_uint alignment, + void **result); +error* svm_free(clobj_t _ctx, void *svm_pointer); +error* enqueue_svm_free( + clobj_t *evt, clobj_t _queue, + cl_uint num_svm_pointers, + void *svm_pointers[], + const clobj_t *_wait_for, uint32_t num_wait_for); +error* enqueue_svm_memcpy( + clobj_t *evt, clobj_t _queue, + cl_bool is_blocking, + void *dst_ptr, const void *src_ptr, size_t size, + const clobj_t *_wait_for, uint32_t num_wait_for); +error* enqueue_svm_memfill( + clobj_t *evt, clobj_t _queue, + void *svm_ptr, + const void *pattern, size_t pattern_size, size_t size, + const clobj_t *_wait_for, uint32_t num_wait_for); +error* enqueue_svm_map( + clobj_t *evt, clobj_t _queue, + cl_bool blocking_map, cl_map_flags map_flags, + void *svm_ptr, size_t size, + const clobj_t *_wait_for, uint32_t num_wait_for); +error* enqueue_svm_unmap( + clobj_t *evt, clobj_t _queue, + void *svm_ptr, + const clobj_t *_wait_for, uint32_t num_wait_for); +error* enqueue_svm_migrate_mem( + clobj_t *evt, clobj_t _queue, + cl_uint num_svm_pointers, + const void **svm_pointers, + const size_t *sizes, + cl_mem_migration_flags flags, + const clobj_t *_wait_for, uint32_t num_wait_for); + // }}} // {{{ program