From ed54bd467e42e3c34ea170f428671755653711e2 Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner <inform@tiker.net> Date: Fri, 28 Mar 2014 23:44:40 -0500 Subject: [PATCH] Make cffi branch livable, implement memory pools --- TODOs | 8 + pyopencl/__init__.py | 4 +- pyopencl/_cffi.py | 27 +- {src => pyopencl}/c_wrapper/wrap_cl_core.h | 4 +- pyopencl/cffi_cl.py | 26 +- pyopencl/mempool.py | 272 ++ pyopencl/tools.py | 21 +- setup.py | 61 +- src/c_wrapper/Makefile | 6 - src/c_wrapper/bitlog.cpp | 26 - src/c_wrapper/bitlog.hpp | 50 - src/c_wrapper/wrap_cl.cpp | 2350 +++++++----- src/wrapper/_pvt_struct_v2.cpp | 1613 -------- src/wrapper/_pvt_struct_v3.cpp | 1749 --------- src/wrapper/bitlog.cpp | 27 - src/wrapper/bitlog.hpp | 53 - src/wrapper/mempool.hpp | 376 -- src/wrapper/numpy_init.hpp | 34 - src/wrapper/tools.hpp | 43 - src/wrapper/wrap_cl.cpp | 24 - src/wrapper/wrap_cl.hpp | 4013 -------------------- src/wrapper/wrap_cl_part_1.cpp | 312 -- src/wrapper/wrap_cl_part_2.cpp | 359 -- src/wrapper/wrap_constants.cpp | 868 ----- src/wrapper/wrap_helpers.hpp | 175 - src/wrapper/wrap_mempool.cpp | 290 -- 26 files changed, 1694 insertions(+), 11097 deletions(-) create mode 100644 TODOs rename {src => pyopencl}/c_wrapper/wrap_cl_core.h (98%) create mode 100644 pyopencl/mempool.py delete mode 100644 src/c_wrapper/Makefile delete mode 100644 src/c_wrapper/bitlog.cpp delete mode 100644 src/c_wrapper/bitlog.hpp delete mode 100644 src/wrapper/_pvt_struct_v2.cpp delete mode 100644 src/wrapper/_pvt_struct_v3.cpp delete mode 100644 src/wrapper/bitlog.cpp delete mode 100644 src/wrapper/bitlog.hpp delete mode 100644 src/wrapper/mempool.hpp delete mode 100644 src/wrapper/numpy_init.hpp delete mode 100644 src/wrapper/tools.hpp delete mode 100644 src/wrapper/wrap_cl.cpp delete mode 100644 src/wrapper/wrap_cl.hpp delete mode 100644 src/wrapper/wrap_cl_part_1.cpp delete mode 100644 src/wrapper/wrap_cl_part_2.cpp delete mode 100644 src/wrapper/wrap_constants.cpp delete mode 100644 src/wrapper/wrap_helpers.hpp delete mode 100644 src/wrapper/wrap_mempool.cpp diff --git a/TODOs b/TODOs new file mode 100644 index 00000000..b3b5f4bb --- /dev/null +++ b/TODOs @@ -0,0 +1,8 @@ +- nanny events +- retry-if-mem-error +- subdevices +- Kernel.get_arg_info +- image/buffer copies +- interaction with threading BEGIN_ALLOW_THREADS/END_ALLOW_THREADS +- _pvt_struct +- Incorporate fixes in C++ stuff from after the fork diff --git a/pyopencl/__init__.py b/pyopencl/__init__.py index b9751a66..1f640e33 100644 --- a/pyopencl/__init__.py +++ b/pyopencl/__init__.py @@ -524,7 +524,9 @@ def _add_functionality(): for i, arg in enumerate(args): self.set_arg(i, arg) else: - from pyopencl._pvt_struct import pack + # TODO: + #from pyopencl._pvt_struct import pack + from struct import pack for i, (arg, arg_type_char) in enumerate( zip(args, arg_type_chars)): if arg_type_char and arg_type_char != "V": diff --git a/pyopencl/_cffi.py b/pyopencl/_cffi.py index fdde752c..977376fa 100644 --- a/pyopencl/_cffi.py +++ b/pyopencl/_cffi.py @@ -1,9 +1,5 @@ from cffi import FFI -import os.path -current_directory = os.path.dirname(__file__) - - _ffi = FFI() _cl_header = """ @@ -93,10 +89,23 @@ typedef struct _cl_buffer_region { """ -with open(os.path.join(current_directory, 'wrap_cl_core.h')) as _f: - _wrap_cl_header = _f.read() -_ffi.cdef('%s\n%s' % (_cl_header, _wrap_cl_header)) +def _get_wrap_header(): + from pkg_resources import Requirement, resource_filename + header_name = resource_filename( + Requirement.parse("pyopencl"), "pyopencl/c_wrapper/wrap_cl_core.h") + + with open(header_name, "rt") as f: + return f.read() + +_ffi.cdef(_cl_header + "\n" + _get_wrap_header()) + + +def _get_wrapcl_so_name(): + import os.path + current_directory = os.path.dirname(__file__) + + # TODO: cross platform library extension? + return os.path.join(current_directory, "_wrapcl.so") -# todo: cross platform library extension? -_lib = _ffi.dlopen(os.path.join(current_directory, "_wrapcl.so")) +_lib = _ffi.dlopen(_get_wrapcl_so_name()) diff --git a/src/c_wrapper/wrap_cl_core.h b/pyopencl/c_wrapper/wrap_cl_core.h similarity index 98% rename from src/c_wrapper/wrap_cl_core.h rename to pyopencl/c_wrapper/wrap_cl_core.h index c279df58..0ad5c337 100644 --- a/src/c_wrapper/wrap_cl_core.h +++ b/pyopencl/c_wrapper/wrap_cl_core.h @@ -76,8 +76,8 @@ intptr_t _int_ptr(void*, class_t); void* _from_int_ptr(void **ptr_out, intptr_t int_ptr_value, class_t); error *_get_info(void *ptr, class_t class_, cl_uint param, generic_info *out); void _delete(void *ptr, class_t class_); -void _free(void*); -void _free2(void**, uint32_t size); +void free_pointer(void*); +void free_pointer_array(void**, uint32_t size); unsigned bitlog2(unsigned long v); diff --git a/pyopencl/cffi_cl.py b/pyopencl/cffi_cl.py index 8d450041..094f3e78 100644 --- a/pyopencl/cffi_cl.py +++ b/pyopencl/cffi_cl.py @@ -26,7 +26,6 @@ THE SOFTWARE. """ -#from pyopencl._cl import PooledBuffer, MemoryPool import warnings import np import sys @@ -34,15 +33,12 @@ import sys # TODO: can we do without ctypes? import ctypes -from _cffi import _ffi, _lib +from pyopencl._cffi import _ffi, _lib # are we running on pypy? _PYPY = '__pypy__' in sys.builtin_module_names -bitlog2 = _lib.bitlog2 - - # {{{ wrapper tools # {{{ _CArray helper classes @@ -54,7 +50,7 @@ class _CArray(object): def __del__(self): if self.ptr != _ffi.NULL: - _lib._free(self.ptr[0]) + _lib.free_pointer(self.ptr[0]) def __getitem__(self, key): return self.ptr[0].__getitem__(key) @@ -66,7 +62,7 @@ class _CArray(object): class _CArrays(_CArray): def __del__(self): - _lib._free2(_ffi.cast('void**', self.ptr[0]), self.size[0]) + _lib.free_pointer_array(_ffi.cast('void**', self.ptr[0]), self.size[0]) super(_CArrays, self).__del__() # }}} @@ -99,7 +95,7 @@ def _generic_info_to_python(info): if type_.endswith(']'): ret = map(ci, value) - _lib._free(info.value) + _lib.free_pointer(info.value) return ret else: return ci(value) @@ -107,7 +103,7 @@ def _generic_info_to_python(info): ret = _ffi.string(value) elif type_.startswith('char*['): ret = map(_ffi.string, value) - _lib._free2(info.value, len(value)) + _lib.free_pointer_array(info.value, len(value)) elif type_.endswith(']'): if type_.startswith('char['): ret = ''.join(a[0] for a in value) @@ -124,7 +120,7 @@ def _generic_info_to_python(info): else: ret = value[0] if info.dontfree == 0: - _lib._free(info.value) + _lib.free_pointer(info.value) return ret # }}} @@ -273,8 +269,8 @@ def _handle_error(error): # non-pyopencl exceptions are handled here import exceptions e = exceptions.RuntimeError(_ffi.string(error.msg)) - _lib._free(error.msg) - _lib._free(error) + _lib.free_pointer(error.msg) + _lib.free_pointer(error) raise e if error.code == status_code.MEM_OBJECT_ALLOCATION_FAILURE: klass = MemoryError @@ -286,9 +282,9 @@ def _handle_error(error): klass = Error e = klass(routine=_ffi.string(error.routine), code=error.code, msg=_ffi.string(error.msg)) - _lib._free(error.routine) - _lib._free(error.msg) - _lib._free(error) + _lib.free_pointer(error.routine) + _lib.free_pointer(error.msg) + _lib.free_pointer(error) raise e # }}} diff --git a/pyopencl/mempool.py b/pyopencl/mempool.py new file mode 100644 index 00000000..38c10562 --- /dev/null +++ b/pyopencl/mempool.py @@ -0,0 +1,272 @@ +from __future__ import division + +__copyright__ = """ +Copyright (C) 2014 Andreas Kloeckner +""" + +__license__ = """ +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +""" + + +import numpy as np +import pyopencl as cl + + +# {{{ allocators + +class AllocatorBase(object): + def __call__(self, nbytes): + try_count = 0 + + while try_count < 2: + try: + return self.allocate(nbytes) + except cl.Error, e: + if not e.is_out_of_memory(): + raise + try_count += 1 + if try_count == 2: + raise + + self.try_release_blocks() + + def try_release_blocks(self): + import gc + gc.collect() + + +class DeferredAllocator(AllocatorBase): + is_deferred = True + + def __init__(self, context, mem_flags=cl.mem_flags.READ_WRITE): + self.context = context + self.mem_flags = mem_flags + + def allocate(self, nbytes): + return cl.Buffer(self.context, self.mem_flags, nbytes) + + +_zero = np.array([0, 0, 0, 0], dtype=np.int8) + + +class ImmediateAllocator(AllocatorBase): + is_deferred = False + + def __init__(self, queue, mem_flags=cl.mem_flags.READ_WRITE): + self.context = queue.context + self.queue = queue + self.mem_flags = mem_flags + + def allocate(self, nbytes): + buf = cl.Buffer(self.context, self.mem_flags, nbytes) + + # Make sure the buffer gets allocated right here and right now. + # This looks (and is) expensive. But immediate allocators + # have their main use in memory pools, whose basic assumption + # is that allocation is too expensive anyway--but they rely + # on exact 'out-of-memory' information. + + from pyopencl.cffi_cl import _enqueue_write_buffer + _enqueue_write_buffer( + self.queue, buf, + _zero[:min(len(_zero), nbytes)], + is_blocking=False) + + # No need to wait for completion here. clWaitForEvents (e.g.) + # cannot return mem object allocation failures. This implies that + # the buffer is faulted onto the device on enqueue. + + return buf + +# }}} + + +# {{{ memory pool + +class MemoryPool(object): + mantissa_bits = 2 + mantissa_mask = (1 << mantissa_bits) - 1 + + def __init__(self, allocator): + self.allocator = allocator + + self.bin_nr_to_bin = {} + + if self.allocator.is_deferred: + from warnings import warn + warn("Memory pools expect non-deferred " + "semantics from their allocators. You passed a deferred " + "allocator, i.e. an allocator whose allocations can turn out to " + "be unavailable long after allocation.", statcklevel=2) + + self.active_blocks = 0 + + @classmethod + def bin_number(cls, size): + l = max(size.bit_length(), 1) - 1 + + mantissa_bits = cls.mantissa_bits + if l >= mantissa_bits: + shifted = size >> (l - mantissa_bits) + else: + shifted = size << (mantissa_bits - l) + + assert not (size and (shifted & (1 << mantissa_bits)) == 0) + + chopped = shifted & cls.mantissa_mask + + return l << mantissa_bits | chopped + + @classmethod + def alloc_size(cls, bin_nr): + mantissa_bits = cls.mantissa_bits + + exponent = bin_nr >> mantissa_bits + mantissa = bin_nr & cls.mantissa_mask + + exp_minus_mbits = exponent-mantissa_bits + if exp_minus_mbits >= 0: + ones = (1 << exp_minus_mbits) - 1 + head = ((1 << mantissa_bits) | mantissa) << exp_minus_mbits + else: + ones = 0 + head = ((1 << mantissa_bits) | mantissa) >> -exp_minus_mbits + + assert not (ones & head) + return head | ones + + def allocate(self): + pass + + __call__ = allocate + + def stop_holding(self): + self.stop_holding = True + self.free_held() + + def free_held(self): + for bin_nr, bin_list in self.bin_nr_to_bin.iteritems(): + while bin_list: + self.allocator.free(bin_list.pop()) + + @property + def held_blocks(self): + return sum( + len(bin_list) + for bin_list in self.bin_nr_to_bin.itervalues()) + + def allocate(self, size): + bin_nr = self.bin_number(size) + bin_list = self.bin_nr_to_bin.setdefault(bin_nr, []) + + if bin_list: + # if (m_trace) + # std::cout + # << "[pool] allocation of size " << size + # << " served from bin " << bin_nr + # << " which contained " << bin_list.size() + # << " entries" << std::endl; + self.active_blocks += 1 + return bin_list.pop() + + alloc_sz = self.alloc_size(bin_nr) + + assert self.bin_number(alloc_sz) == bin_nr + + # if (m_trace) + # std::cout << "[pool] allocation of size " << size + # << " required new memory" << std::endl; + + try: + result = self.allocator(alloc_sz) + self.active_blocks += 1 + return result + except cl.MemoryError: + pass + + # if (m_trace) + # std::cout << "[pool] allocation triggered OOM, running GC" << std::endl; + + self.allocator.try_release_blocks() + + if bin_list: + return bin_list.pop() + + # if (m_trace) + # std::cout << "[pool] allocation still OOM after GC" << std::endl; + + for _ in self._try_to_free_memory(): + try: + result = self.allocator(alloc_sz) + self.active_blocks += 1 + return result + except cl.MemoryError: + pass + + raise cl.MemoryError( + "failed to free memory for allocation", + routine="memory_pool::allocate", + code=cl.status_code.MEM_OBJECT_ALLOCATION_FAILURE) + + def free(self, buf, size): + self.active_blocks -= 1 + bin_nr = self.bin_number(size) + + if not self.stop_holding: + self.bin_nr_to_bin.setdefault(bin_nr, []).append(buf) + + # if (m_trace) + # std::cout << "[pool] block of size " << size << " returned to bin " + # << bin_nr << " which now contains " << get_bin(bin_nr).size() + # << " entries" << std::endl; + else: + self.allocator.free(buf) + + def _try_to_free_memory(self): + for bin_nr, bin_list in self.bin_nr_to_bin.iteritems(): + while bin_list: + self.allocator.free(bin_list.pop()) + self.held_blocks -= 1 + yield + + +class PooledBuffer(cl.MemoryObjectHolder): + _id = 'buffer' + + def __init__(self, pool, buf, size): + self.pool = pool + self.buf = buf + self.ptr = buf.ptr + self.size = size + + def release(self): + self.pool.free(self.buf, self.size) + self.buf = None + self.ptr = None + + def __del__(self): + if self.buf is not None: + self.release() + +# }}} + + + +# vim: foldmethod=marker diff --git a/pyopencl/tools.py b/pyopencl/tools.py index 553eb064..5c65edc3 100644 --- a/pyopencl/tools.py +++ b/pyopencl/tools.py @@ -60,25 +60,8 @@ _register_types() # {{{ imported names -bitlog2 = cl.bitlog2 - -PooledBuffer = cl.PooledBuffer - -from pyopencl._cl import _tools_DeferredAllocator as DeferredAllocator -from pyopencl._cl import ( # noqa - _tools_ImmediateAllocator as ImmediateAllocator) - - -class CLAllocator(DeferredAllocator): - def __init__(self, *args, **kwargs): - from warnings import warn - warn("pyopencl.tools.CLAllocator is deprecated. " - "It will be continue to exist throughout the 2013.x " - "versions of PyOpenCL. Use {Deferred,Immediate}Allocator.", - DeprecationWarning, 2) - DeferredAllocator.__init__(self, *args, **kwargs) - -MemoryPool = cl.MemoryPool +from pyopencl.mempool import ( # noqa + PooledBuffer, DeferredAllocator, ImmediateAllocator, MemoryPool) # }}} diff --git a/setup.py b/setup.py index 1a6c3733..26fb709b 100644 --- a/setup.py +++ b/setup.py @@ -1,13 +1,40 @@ #!/usr/bin/env python # -*- coding: latin-1 -*- +__copyright__ = """ +Copyright (C) 2009-14 Andreas Kloeckner +Copyright (C) 2013 Marko Bencun +""" + +__license__ = """ +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +""" + + +import sys + def get_config_schema(): from aksetup_helper import ConfigSchema, Option, \ IncludeDir, LibraryDir, Libraries, \ Switch, StringListOption - import sys if 'darwin' in sys.platform: import platform osx_ver, _, _ = platform.mac_ver() @@ -146,23 +173,15 @@ def main(): from aksetup_helper import count_down_delay count_down_delay(delay=5) - import sys - if sys.version_info >= (3,): - pvt_struct_source = "src/wrapper/_pvt_struct_v3.cpp" - else: - pvt_struct_source = "src/wrapper/_pvt_struct_v2.cpp" - - # wrap_cl_core.h needs to be available in pyopencl/ - # the cffi verifier depends on it. - import shutil - shutil.copyfile("src/c_wrapper/wrap_cl_core.h", "pyopencl/wrap_cl_core.h") - # from pyopencl._cffi import _get_verifier - # import os.path - # current_directory = os.path.dirname(__file__) - # # for development: clean cache such that the extension is rebuilt - # shutil.rmtree(os.path.join(current_directory, 'pyopencl', '__pycache__/'), ignore_errors=True) + # for development: clean cache such that the extension is rebuilt + if 0: + import os.path + current_directory = os.path.dirname(__file__) + + shutil.rmtree(os.path.join(current_directory, + 'pyopencl', '__pycache__/'), ignore_errors=True) setup(name="pyopencl", # metadata @@ -213,9 +232,12 @@ def main(): ["src/c_wrapper/wrap_cl.cpp", "src/c_wrapper/wrap_constants.cpp", #"src/c_wrapper/wrap_mempool.cpp", - "src/c_wrapper/bitlog.cpp", ], - include_dirs=conf["CL_INC_DIR"] + ["src/c_wrapper/"], + include_dirs=( + conf["CL_INC_DIR"] + + ["src/c_wrapper/"] + + ["pyopencl/c_wrapper/"] + ), library_dirs=conf["CL_LIB_DIR"], libraries=conf["CL_LIBNAME"], define_macros=list(EXTRA_DEFINES.items()), @@ -228,8 +250,7 @@ def main(): "pyopencl": [ "cl/*.cl", "cl/*.h", - "wrap_cl_core.h", - "_cl.so", + "c_wrapper/wrap_cl_core.h", ] }, diff --git a/src/c_wrapper/Makefile b/src/c_wrapper/Makefile deleted file mode 100644 index 7424e5de..00000000 --- a/src/c_wrapper/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -all: - g++ -c -Wall -DHAVE_GL=1 -DPYOPENCL_PRETEND_CL_VERSION=4112 -fpic wrap_cl.cpp wrap_constants.cpp bitlog.cpp - #g++ -c -Wall -DPYOPENCL_PRETEND_CL_VERSION=4112 -fpic wrap_cl.cpp wrap_constants.cpp bitlog.cpp - g++ -shared -o libwrapcl.so wrap_cl.o wrap_constants.o bitlog.o - cp libwrapcl.so ../../pyopencl/ - cp wrap_cl_core.h ../../pyopencl/wrap_cl_core.h diff --git a/src/c_wrapper/bitlog.cpp b/src/c_wrapper/bitlog.cpp deleted file mode 100644 index 67b82511..00000000 --- a/src/c_wrapper/bitlog.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "bitlog.hpp" - - - -/* from http://graphics.stanford.edu/~seander/bithacks.html */ -const char pyopencl::log_table_8[] = -{ - 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 -}; - - diff --git a/src/c_wrapper/bitlog.hpp b/src/c_wrapper/bitlog.hpp deleted file mode 100644 index 86e11710..00000000 --- a/src/c_wrapper/bitlog.hpp +++ /dev/null @@ -1,50 +0,0 @@ -// Base-2 logarithm bithack. - - - - -#ifndef _AFJDFJSDFSD_PYOPENCL_HEADER_SEEN_BITLOG_HPP -#define _AFJDFJSDFSD_PYOPENCL_HEADER_SEEN_BITLOG_HPP - - - - -#include <climits> -#include <stdint.h> - -namespace pyopencl -{ - extern const char log_table_8[]; - - inline unsigned bitlog2_16(uint16_t v) - { - if (unsigned long t = v >> 8) - return 8+log_table_8[t]; - else - return log_table_8[v]; - } - - inline unsigned bitlog2_32(uint32_t v) - { - if (uint16_t t = v >> 16) - return 16+bitlog2_16(t); - else - return bitlog2_16(v); - } - - inline unsigned bitlog2(unsigned long v) - { -#if (ULONG_MAX != 4294967295) - if (uint32_t t = v >> 32) - return 32+bitlog2_32(t); - else -#endif - return bitlog2_32(v); - } -} - - - - - -#endif diff --git a/src/c_wrapper/wrap_cl.cpp b/src/c_wrapper/wrap_cl.cpp index 97568cc1..4d976d86 100644 --- a/src/c_wrapper/wrap_cl.cpp +++ b/src/c_wrapper/wrap_cl.cpp @@ -6,11 +6,33 @@ #include <string.h> #include <memory> #include <sstream> -#include "bitlog.hpp" #define MALLOC(TYPE, VAR, N) TYPE *VAR = reinterpret_cast<TYPE*>(malloc(sizeof(TYPE)*(N))); + // {{{ tracing and error reporting + +#define BEGIN_C_HANDLE_ERROR try { +#define END_C_HANDLE_ERROR \ + } \ + catch(const pyopencl::error& e) \ + { \ + MALLOC(::error, error, 1); \ + error->routine = pyopencl::_copy_str(e.routine()); \ + error->msg = pyopencl::_copy_str(e.what()); \ + error->code = e.code(); \ + error->other = 0; \ + return error; \ + } \ + catch(const std::exception& e) \ + { \ + /* non-pyopencl exceptions need to be converted as well */ \ + MALLOC(::error, error, 1); \ + error->other = 1; \ + error->msg = pyopencl::_copy_str(e.what()); \ + return error; \ + } + #ifdef PYOPENCL_TRACE #define PYOPENCL_PRINT_CALL_TRACE(NAME) \ std::cerr << NAME << std::endl; @@ -21,26 +43,6 @@ #define PYOPENCL_PRINT_CALL_TRACE_INFO(NAME, EXTRA_INFO) /*nothing*/ #endif -#define C_HANDLE_ERROR(OPERATION) \ - try { \ - OPERATION \ - } catch(const pyopencl::error& e) { \ - MALLOC(::error, error, 1); \ - error->routine = pyopencl::_copy_str(e.routine()); \ - error->msg = pyopencl::_copy_str(e.what()); \ - error->code = e.code(); \ - error->other = 0; \ - return error; \ - } catch(const std::exception& e) { \ - /* non-pyopencl exceptions shall be */ \ - /* converted as well */ \ - MALLOC(::error, error, 1); \ - error->other = 1; \ - error->msg = pyopencl::_copy_str(e.what()); \ - return error; \ - } \ - - // TODO Py_BEGIN_ALLOW_THREADS \ Py_END_ALLOW_THREADS below #define PYOPENCL_CALL_GUARDED_THREADED(NAME, ARGLIST) \ { \ @@ -77,31 +79,32 @@ // }}} + +// {{{ extension function pointers + #if PYOPENCL_CL_VERSION >= 0x1020 -#define PYOPENCL_GET_EXT_FUN(PLATFORM, NAME, VAR) \ - NAME##_fn VAR \ - = (NAME##_fn) \ - clGetExtensionFunctionAddressForPlatform(PLATFORM, #NAME); \ - \ - if (!VAR) \ - throw error(#NAME, CL_INVALID_VALUE, #NAME \ - "not available"); +#define PYOPENCL_GET_EXT_FUN(PLATFORM, NAME, VAR) \ + NAME##_fn VAR = (NAME##_fn) \ + clGetExtensionFunctionAddressForPlatform(PLATFORM, #NAME); \ + \ + if (!VAR) \ + throw error(#NAME, CL_INVALID_VALUE, #NAME " not available"); #else -#define PYOPENCL_GET_EXT_FUN(PLATFORM, NAME, VAR) \ - NAME##_fn VAR \ - = (NAME##_fn) \ - clGetExtensionFunctionAddress(#NAME); \ - \ - if (!VAR) \ - throw error(#NAME, CL_INVALID_VALUE, #NAME \ - "not available"); +#define PYOPENCL_GET_EXT_FUN(PLATFORM, NAME, VAR) \ + NAME##_fn VAR = (NAME##_fn) clGetExtensionFunctionAddress(#NAME); \ + \ + if (!VAR) \ + throw error(#NAME, CL_INVALID_VALUE, #NAME " not available"); #endif +// }}} + +// {{{ GetInfo helpers #define PYOPENCL_GET_VEC_INFO(WHAT, FIRST_ARG, SECOND_ARG, RES_VEC) \ { \ @@ -193,7 +196,11 @@ return info; \ } -// {{{ event helpers -------------------------------------------------------------- +// }}} + + +// {{{ event helpers + #define PYOPENCL_PARSE_OBJECT_LIST(CLS, TYPE, OUT, NAME, NUM) \ std::vector<TYPE> OUT((NUM)); \ { \ @@ -209,7 +216,7 @@ num_wait_for, event_wait_list.empty( ) ? NULL : &event_wait_list.front() -#define PYOPENCL_RETURN_NEW_EVENT(evt) \ +#define PYOPENCL_RETURN_NEW_EVENT(evt) \ try \ { \ return new event(evt, false); \ @@ -222,61 +229,67 @@ // }}} + // {{{ equality testing -#define PYOPENCL_EQUALITY_TESTS(cls) \ - bool operator==(cls const &other) const \ - { return data() == other.data(); } \ - bool operator!=(cls const &other) const \ - { return data() != other.data(); } \ - long hash() const \ + +#define PYOPENCL_EQUALITY_TESTS(cls) \ + \ + bool operator==(cls const &other) const \ + { return data() == other.data(); } \ + \ + bool operator!=(cls const &other) const \ + { return data() != other.data(); } \ + \ + long hash() const \ { return (long) (intptr_t) data(); } -// }}} +// }}} // {{{ tools + #define PYOPENCL_CAST_BOOL(B) ((B) ? CL_TRUE : CL_FALSE) -#define PYOPENCL_PARSE_PY_DEVICES \ - std::vector<cl_device_id> devices_vec; \ - cl_uint num_devices; \ - cl_device_id *devices; \ - \ +#define PYOPENCL_PARSE_PY_DEVICES \ + std::vector<cl_device_id> devices_vec; \ + cl_uint num_devices; \ + cl_device_id *devices; \ + \ if (py_devices.ptr() == Py_None) \ { \ - num_devices = 0; \ - devices = 0; \ + num_devices = 0; \ + devices = 0; \ } \ else \ { \ PYTHON_FOREACH(py_dev, py_devices) \ devices_vec.push_back( \ - py::extract<device &>(py_dev)().data()); \ - num_devices = devices_vec.size(); \ - devices = devices_vec.empty( ) ? NULL : &devices_vec.front(); \ + py::extract<device &>(py_dev)().data()); \ + num_devices = devices_vec.size(); \ + devices = devices_vec.empty( ) ? NULL : &devices_vec.front(); \ } \ -#define PYOPENCL_RETRY_IF_MEM_ERROR(OPERATION) \ - { \ +#define PYOPENCL_RETRY_IF_MEM_ERROR(OPERATION) \ + { \ bool failed_with_mem_error = false; \ try \ - { \ - OPERATION \ - } \ + { \ + OPERATION \ + } \ catch (pyopencl::error &e) \ - { \ - failed_with_mem_error = true; \ - if (!e.is_out_of_memory()) \ - throw; \ - } \ + { \ + failed_with_mem_error = true; \ + if (!e.is_out_of_memory()) \ + throw; \ + } \ \ if (failed_with_mem_error) \ - { \ - /* If we get here, we got an error from CL. - * We should run the Python GC to try and free up - * some memory references. */ \ + { \ + /* If we get here, we got an error from CL. + * We should run the Python GC to try and free up + * some memory references. */ \ run_python_gc(); \ \ /* Now retry the allocation. If it fails again, @@ -290,6 +303,8 @@ run_python_gc(); \ // }}} +// {{{ more odds and ends + #define SWITCHCLASS(OPERATION) \ switch(class_) { \ case ::CLASS_PLATFORM: OPERATION(PLATFORM, platform); break; \ @@ -321,12 +336,15 @@ run_python_gc(); \ #define PYOPENCL_CL_SAMPLER cl_sampler template<class T> -std::string tostring(const T& v) { -std::ostringstream ostr; - ostr << v; - return ostr.str(); +std::string tostring(const T& v) +{ + std::ostringstream ostr; + ostr << v; + return ostr.str(); } +// }}} + namespace pyopencl { @@ -337,86 +355,99 @@ namespace pyopencl return cstr; } - // {{{ error - class error : public std::runtime_error - { - private: - const char *m_routine; - cl_int m_code; - - public: - error(const char *rout, cl_int c, const char *msg="") - : std::runtime_error(msg), m_routine(rout), m_code(c) - { std::cout << rout <<";" << msg<< ";" << c << std::endl; } - const char *routine() const - { - return m_routine; - } + class noncopyable { + // non-copyable - cl_int code() const - { - return m_code; - } + private: + noncopyable(noncopyable const &) + { } - bool is_out_of_memory() const - { - return (code() == CL_MEM_OBJECT_ALLOCATION_FAILURE - || code() == CL_OUT_OF_RESOURCES - || code() == CL_OUT_OF_HOST_MEMORY); - } + noncopyable &operator=(noncopyable const &) + { + return *this; + } + public: + noncopyable() + { } }; - // }}} + // {{{ error + + class error : public std::runtime_error + { + private: + const char *m_routine; + cl_int m_code; + + public: + error(const char *rout, cl_int c, const char *msg="") + : std::runtime_error(msg), m_routine(rout), m_code(c) + { std::cout << rout <<";" << msg<< ";" << c << std::endl; } + const char *routine() const + { + return m_routine; + } - //#define MAKE_INFO(name, type, value) { } + cl_int code() const + { + return m_code; + } - class _common { + bool is_out_of_memory() const + { + return (code() == CL_MEM_OBJECT_ALLOCATION_FAILURE + || code() == CL_OUT_OF_RESOURCES + || code() == CL_OUT_OF_HOST_MEMORY); + } }; + // }}} + // {{{ platform - class platform : public _common + + class platform : public noncopyable { - private: - cl_platform_id m_platform; + private: + cl_platform_id m_platform; - public: - platform(cl_platform_id pid) - : m_platform(pid) - { } + public: + platform(cl_platform_id pid) + : m_platform(pid) + { } - platform(cl_platform_id pid, bool /*retain (ignored)*/) - : m_platform(pid) - { } + platform(cl_platform_id pid, bool /*retain (ignored)*/) + : m_platform(pid) + { } - cl_platform_id data() const - { - return m_platform; - } + cl_platform_id data() const + { + return m_platform; + } - PYOPENCL_EQUALITY_TESTS(platform); + PYOPENCL_EQUALITY_TESTS(platform); - generic_info get_info(cl_platform_info param_name) const - { - switch (param_name) + generic_info get_info(cl_platform_info param_name) const + { + switch (param_name) { - case CL_PLATFORM_PROFILE: - case CL_PLATFORM_VERSION: - case CL_PLATFORM_NAME: - case CL_PLATFORM_VENDOR: + case CL_PLATFORM_PROFILE: + case CL_PLATFORM_VERSION: + case CL_PLATFORM_NAME: + case CL_PLATFORM_VENDOR: #if !(defined(CL_PLATFORM_NVIDIA) && CL_PLATFORM_NVIDIA == 0x3001) - case CL_PLATFORM_EXTENSIONS: + case CL_PLATFORM_EXTENSIONS: #endif - PYOPENCL_GET_STR_INFO(Platform, m_platform, param_name); + PYOPENCL_GET_STR_INFO(Platform, m_platform, param_name); - default: - throw error("Platform.get_info", CL_INVALID_VALUE); + default: + throw error("Platform.get_info", CL_INVALID_VALUE); } - } + } - std::vector<cl_device_id> get_devices(cl_device_type devtype); + std::vector<cl_device_id> get_devices(cl_device_type devtype); }; @@ -439,47 +470,50 @@ namespace pyopencl // }}} + // {{{ device - class device : public _common // : boost::noncopyable + + class device : public noncopyable { - public: - enum reference_type_t { - REF_NOT_OWNABLE, - REF_FISSION_EXT, + public: + enum reference_type_t { + REF_NOT_OWNABLE, + REF_FISSION_EXT, #if PYOPENCL_CL_VERSION >= 0x1020 - REF_CL_1_2, + REF_CL_1_2, #endif - }; - private: - cl_device_id m_device; - reference_type_t m_ref_type; + }; - public: - device(cl_device_id did) - : m_device(did), m_ref_type(REF_NOT_OWNABLE) - { } + private: + cl_device_id m_device; + reference_type_t m_ref_type; - device(cl_device_id did, bool retain, reference_type_t ref_type=REF_NOT_OWNABLE) - : m_device(did), m_ref_type(ref_type) - { - if (retain && ref_type != REF_NOT_OWNABLE) + public: + device(cl_device_id did) + : m_device(did), m_ref_type(REF_NOT_OWNABLE) + { } + + device(cl_device_id did, bool retain, reference_type_t ref_type=REF_NOT_OWNABLE) + : m_device(did), m_ref_type(ref_type) + { + if (retain && ref_type != REF_NOT_OWNABLE) { if (false) - { } + { } #if (defined(cl_ext_device_fission) && defined(PYOPENCL_USE_DEVICE_FISSION)) else if (ref_type == REF_FISSION_EXT) - { + { #if PYOPENCL_CL_VERSION >= 0x1020 - cl_platform_id plat; - PYOPENCL_CALL_GUARDED(clGetDeviceInfo, (m_device, CL_DEVICE_PLATFORM, - sizeof(plat), &plat, NULL)); + cl_platform_id plat; + PYOPENCL_CALL_GUARDED(clGetDeviceInfo, (m_device, CL_DEVICE_PLATFORM, + sizeof(plat), &plat, NULL)); #endif - PYOPENCL_GET_EXT_FUN(plat, - clRetainDeviceEXT, retain_func); + PYOPENCL_GET_EXT_FUN(plat, + clRetainDeviceEXT, retain_func); - PYOPENCL_CALL_GUARDED(retain_func, (did)); - } + PYOPENCL_CALL_GUARDED(retain_func, (did)); + } #endif #if PYOPENCL_CL_VERSION >= 0x1020 @@ -493,189 +527,189 @@ namespace pyopencl throw error("Device", CL_INVALID_VALUE, "cannot own references to devices when device fission or CL 1.2 is not available"); } - } + } - ~device() - { - if (false) + ~device() + { + if (false) { } #if defined(cl_ext_device_fission) && defined(PYOPENCL_USE_DEVICE_FISSION) - else if (m_ref_type == REF_FISSION_EXT) + else if (m_ref_type == REF_FISSION_EXT) { #if PYOPENCL_CL_VERSION >= 0x1020 cl_platform_id plat; PYOPENCL_CALL_GUARDED(clGetDeviceInfo, (m_device, CL_DEVICE_PLATFORM, - sizeof(plat), &plat, NULL)); + sizeof(plat), &plat, NULL)); #endif PYOPENCL_GET_EXT_FUN(plat, - clReleaseDeviceEXT, release_func); + clReleaseDeviceEXT, release_func); PYOPENCL_CALL_GUARDED_CLEANUP(release_func, (m_device)); } #endif #if PYOPENCL_CL_VERSION >= 0x1020 - else if (m_ref_type == REF_CL_1_2) - PYOPENCL_CALL_GUARDED(clReleaseDevice, (m_device)); + else if (m_ref_type == REF_CL_1_2) + PYOPENCL_CALL_GUARDED(clReleaseDevice, (m_device)); #endif - } + } - cl_device_id data() const - { - return m_device; - } + cl_device_id data() const + { + return m_device; + } - PYOPENCL_EQUALITY_TESTS(device); + PYOPENCL_EQUALITY_TESTS(device); - generic_info get_info(cl_device_info param_name) const - { + generic_info get_info(cl_device_info param_name) const + { #define DEV_GET_INT_INF(TYPE) PYOPENCL_GET_INTEGRAL_INFO(Device, m_device, param_name, TYPE); - switch (param_name) - { - case CL_DEVICE_TYPE: DEV_GET_INT_INF(cl_device_type); - case CL_DEVICE_VENDOR_ID: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_MAX_COMPUTE_UNITS: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_MAX_WORK_GROUP_SIZE: DEV_GET_INT_INF(size_t); - - case CL_DEVICE_MAX_WORK_ITEM_SIZES: + switch (param_name) { - std::vector<size_t> result; - PYOPENCL_GET_VEC_INFO(Device, m_device, param_name, result); - PYOPENCL_GET_ARRAY_INFO(size_t, result); - } + case CL_DEVICE_TYPE: DEV_GET_INT_INF(cl_device_type); + case CL_DEVICE_VENDOR_ID: DEV_GET_INT_INF(cl_uint); + case CL_DEVICE_MAX_COMPUTE_UNITS: DEV_GET_INT_INF(cl_uint); + case CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS: DEV_GET_INT_INF(cl_uint); + case CL_DEVICE_MAX_WORK_GROUP_SIZE: DEV_GET_INT_INF(size_t); - case CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE: DEV_GET_INT_INF(cl_uint); - - case CL_DEVICE_MAX_CLOCK_FREQUENCY: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_ADDRESS_BITS: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_MAX_READ_IMAGE_ARGS: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_MAX_WRITE_IMAGE_ARGS: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_MAX_MEM_ALLOC_SIZE: DEV_GET_INT_INF(cl_ulong); - case CL_DEVICE_IMAGE2D_MAX_WIDTH: DEV_GET_INT_INF(size_t); - case CL_DEVICE_IMAGE2D_MAX_HEIGHT: DEV_GET_INT_INF(size_t); - case CL_DEVICE_IMAGE3D_MAX_WIDTH: DEV_GET_INT_INF(size_t); - case CL_DEVICE_IMAGE3D_MAX_HEIGHT: DEV_GET_INT_INF(size_t); - case CL_DEVICE_IMAGE3D_MAX_DEPTH: DEV_GET_INT_INF(size_t); - case CL_DEVICE_IMAGE_SUPPORT: DEV_GET_INT_INF(cl_bool); - case CL_DEVICE_MAX_PARAMETER_SIZE: DEV_GET_INT_INF(size_t); - case CL_DEVICE_MAX_SAMPLERS: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_MEM_BASE_ADDR_ALIGN: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_SINGLE_FP_CONFIG: DEV_GET_INT_INF(cl_device_fp_config); + case CL_DEVICE_MAX_WORK_ITEM_SIZES: + { + std::vector<size_t> result; + PYOPENCL_GET_VEC_INFO(Device, m_device, param_name, result); + PYOPENCL_GET_ARRAY_INFO(size_t, result); + } + + case CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR: DEV_GET_INT_INF(cl_uint); + case CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT: DEV_GET_INT_INF(cl_uint); + case CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT: DEV_GET_INT_INF(cl_uint); + case CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG: DEV_GET_INT_INF(cl_uint); + case CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT: DEV_GET_INT_INF(cl_uint); + case CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE: DEV_GET_INT_INF(cl_uint); + + case CL_DEVICE_MAX_CLOCK_FREQUENCY: DEV_GET_INT_INF(cl_uint); + case CL_DEVICE_ADDRESS_BITS: DEV_GET_INT_INF(cl_uint); + case CL_DEVICE_MAX_READ_IMAGE_ARGS: DEV_GET_INT_INF(cl_uint); + case CL_DEVICE_MAX_WRITE_IMAGE_ARGS: DEV_GET_INT_INF(cl_uint); + case CL_DEVICE_MAX_MEM_ALLOC_SIZE: DEV_GET_INT_INF(cl_ulong); + case CL_DEVICE_IMAGE2D_MAX_WIDTH: DEV_GET_INT_INF(size_t); + case CL_DEVICE_IMAGE2D_MAX_HEIGHT: DEV_GET_INT_INF(size_t); + case CL_DEVICE_IMAGE3D_MAX_WIDTH: DEV_GET_INT_INF(size_t); + case CL_DEVICE_IMAGE3D_MAX_HEIGHT: DEV_GET_INT_INF(size_t); + case CL_DEVICE_IMAGE3D_MAX_DEPTH: DEV_GET_INT_INF(size_t); + case CL_DEVICE_IMAGE_SUPPORT: DEV_GET_INT_INF(cl_bool); + case CL_DEVICE_MAX_PARAMETER_SIZE: DEV_GET_INT_INF(size_t); + case CL_DEVICE_MAX_SAMPLERS: DEV_GET_INT_INF(cl_uint); + case CL_DEVICE_MEM_BASE_ADDR_ALIGN: DEV_GET_INT_INF(cl_uint); + case CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE: DEV_GET_INT_INF(cl_uint); + case CL_DEVICE_SINGLE_FP_CONFIG: DEV_GET_INT_INF(cl_device_fp_config); #ifdef CL_DEVICE_DOUBLE_FP_CONFIG - case CL_DEVICE_DOUBLE_FP_CONFIG: DEV_GET_INT_INF(cl_device_fp_config); + case CL_DEVICE_DOUBLE_FP_CONFIG: DEV_GET_INT_INF(cl_device_fp_config); #endif #ifdef CL_DEVICE_HALF_FP_CONFIG - case CL_DEVICE_HALF_FP_CONFIG: DEV_GET_INT_INF(cl_device_fp_config); + case CL_DEVICE_HALF_FP_CONFIG: DEV_GET_INT_INF(cl_device_fp_config); #endif - case CL_DEVICE_GLOBAL_MEM_CACHE_TYPE: DEV_GET_INT_INF(cl_device_mem_cache_type); - case CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_GLOBAL_MEM_CACHE_SIZE: DEV_GET_INT_INF(cl_ulong); - case CL_DEVICE_GLOBAL_MEM_SIZE: DEV_GET_INT_INF(cl_ulong); - - case CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE: DEV_GET_INT_INF(cl_ulong); - case CL_DEVICE_MAX_CONSTANT_ARGS: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_LOCAL_MEM_TYPE: DEV_GET_INT_INF(cl_device_local_mem_type); - case CL_DEVICE_LOCAL_MEM_SIZE: DEV_GET_INT_INF(cl_ulong); - case CL_DEVICE_ERROR_CORRECTION_SUPPORT: DEV_GET_INT_INF(cl_bool); - case CL_DEVICE_PROFILING_TIMER_RESOLUTION: DEV_GET_INT_INF(size_t); - case CL_DEVICE_ENDIAN_LITTLE: DEV_GET_INT_INF(cl_bool); - case CL_DEVICE_AVAILABLE: DEV_GET_INT_INF(cl_bool); - case CL_DEVICE_COMPILER_AVAILABLE: DEV_GET_INT_INF(cl_bool); - case CL_DEVICE_EXECUTION_CAPABILITIES: DEV_GET_INT_INF(cl_device_exec_capabilities); - case CL_DEVICE_QUEUE_PROPERTIES: DEV_GET_INT_INF(cl_command_queue_properties); - - case CL_DEVICE_NAME: - case CL_DEVICE_VENDOR: - case CL_DRIVER_VERSION: - case CL_DEVICE_PROFILE: - case CL_DEVICE_VERSION: - case CL_DEVICE_EXTENSIONS: - PYOPENCL_GET_STR_INFO(Device, m_device, param_name); - - case CL_DEVICE_PLATFORM: - PYOPENCL_GET_OPAQUE_INFO(Device, m_device, param_name, cl_platform_id, platform, PLATFORM); + case CL_DEVICE_GLOBAL_MEM_CACHE_TYPE: DEV_GET_INT_INF(cl_device_mem_cache_type); + case CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE: DEV_GET_INT_INF(cl_uint); + case CL_DEVICE_GLOBAL_MEM_CACHE_SIZE: DEV_GET_INT_INF(cl_ulong); + case CL_DEVICE_GLOBAL_MEM_SIZE: DEV_GET_INT_INF(cl_ulong); + + case CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE: DEV_GET_INT_INF(cl_ulong); + case CL_DEVICE_MAX_CONSTANT_ARGS: DEV_GET_INT_INF(cl_uint); + case CL_DEVICE_LOCAL_MEM_TYPE: DEV_GET_INT_INF(cl_device_local_mem_type); + case CL_DEVICE_LOCAL_MEM_SIZE: DEV_GET_INT_INF(cl_ulong); + case CL_DEVICE_ERROR_CORRECTION_SUPPORT: DEV_GET_INT_INF(cl_bool); + case CL_DEVICE_PROFILING_TIMER_RESOLUTION: DEV_GET_INT_INF(size_t); + case CL_DEVICE_ENDIAN_LITTLE: DEV_GET_INT_INF(cl_bool); + case CL_DEVICE_AVAILABLE: DEV_GET_INT_INF(cl_bool); + case CL_DEVICE_COMPILER_AVAILABLE: DEV_GET_INT_INF(cl_bool); + case CL_DEVICE_EXECUTION_CAPABILITIES: DEV_GET_INT_INF(cl_device_exec_capabilities); + case CL_DEVICE_QUEUE_PROPERTIES: DEV_GET_INT_INF(cl_command_queue_properties); + + case CL_DEVICE_NAME: + case CL_DEVICE_VENDOR: + case CL_DRIVER_VERSION: + case CL_DEVICE_PROFILE: + case CL_DEVICE_VERSION: + case CL_DEVICE_EXTENSIONS: + PYOPENCL_GET_STR_INFO(Device, m_device, param_name); + + case CL_DEVICE_PLATFORM: + PYOPENCL_GET_OPAQUE_INFO(Device, m_device, param_name, cl_platform_id, platform, PLATFORM); #if PYOPENCL_CL_VERSION >= 0x1010 - case CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF: DEV_GET_INT_INF(cl_uint); - - case CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_NATIVE_VECTOR_WIDTH_INT: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF: DEV_GET_INT_INF(cl_uint); - - case CL_DEVICE_HOST_UNIFIED_MEMORY: DEV_GET_INT_INF(cl_bool); - case CL_DEVICE_OPENCL_C_VERSION: - PYOPENCL_GET_STR_INFO(Device, m_device, param_name); + case CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF: DEV_GET_INT_INF(cl_uint); + + case CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR: DEV_GET_INT_INF(cl_uint); + case CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT: DEV_GET_INT_INF(cl_uint); + case CL_DEVICE_NATIVE_VECTOR_WIDTH_INT: DEV_GET_INT_INF(cl_uint); + case CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG: DEV_GET_INT_INF(cl_uint); + case CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT: DEV_GET_INT_INF(cl_uint); + case CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE: DEV_GET_INT_INF(cl_uint); + case CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF: DEV_GET_INT_INF(cl_uint); + + case CL_DEVICE_HOST_UNIFIED_MEMORY: DEV_GET_INT_INF(cl_bool); + case CL_DEVICE_OPENCL_C_VERSION: + PYOPENCL_GET_STR_INFO(Device, m_device, param_name); #endif #ifdef CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV - case CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV: - case CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV: - case CL_DEVICE_REGISTERS_PER_BLOCK_NV: - case CL_DEVICE_WARP_SIZE_NV: - DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_GPU_OVERLAP_NV: - case CL_DEVICE_KERNEL_EXEC_TIMEOUT_NV: - case CL_DEVICE_INTEGRATED_MEMORY_NV: - DEV_GET_INT_INF(cl_bool); + case CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV: + case CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV: + case CL_DEVICE_REGISTERS_PER_BLOCK_NV: + case CL_DEVICE_WARP_SIZE_NV: + DEV_GET_INT_INF(cl_uint); + case CL_DEVICE_GPU_OVERLAP_NV: + case CL_DEVICE_KERNEL_EXEC_TIMEOUT_NV: + case CL_DEVICE_INTEGRATED_MEMORY_NV: + DEV_GET_INT_INF(cl_bool); #endif #if defined(cl_ext_device_fission) && defined(PYOPENCL_USE_DEVICE_FISSION) - case CL_DEVICE_PARENT_DEVICE_EXT: - PYOPENCL_GET_OPAQUE_INFO(Device, m_device, param_name, cl_device_id, device, DEVICE); - case CL_DEVICE_PARTITION_TYPES_EXT: - case CL_DEVICE_AFFINITY_DOMAINS_EXT: - case CL_DEVICE_PARTITION_STYLE_EXT: - { - std::vector<cl_device_partition_property_ext> result; - PYOPENCL_GET_VEC_INFO(Device, m_device, param_name, result); - PYOPENCL_GET_ARRAY_INFO(cl_device_partition_property_ext, result); - } - case CL_DEVICE_REFERENCE_COUNT_EXT: DEV_GET_INT_INF(cl_uint); + case CL_DEVICE_PARENT_DEVICE_EXT: + PYOPENCL_GET_OPAQUE_INFO(Device, m_device, param_name, cl_device_id, device, DEVICE); + case CL_DEVICE_PARTITION_TYPES_EXT: + case CL_DEVICE_AFFINITY_DOMAINS_EXT: + case CL_DEVICE_PARTITION_STYLE_EXT: + { + std::vector<cl_device_partition_property_ext> result; + PYOPENCL_GET_VEC_INFO(Device, m_device, param_name, result); + PYOPENCL_GET_ARRAY_INFO(cl_device_partition_property_ext, result); + } + case CL_DEVICE_REFERENCE_COUNT_EXT: DEV_GET_INT_INF(cl_uint); #endif #if PYOPENCL_CL_VERSION >= 0x1020 - case CL_DEVICE_LINKER_AVAILABLE: DEV_GET_INT_INF(cl_bool); - case CL_DEVICE_BUILT_IN_KERNELS: - PYOPENCL_GET_STR_INFO(Device, m_device, param_name); - case CL_DEVICE_IMAGE_MAX_BUFFER_SIZE: DEV_GET_INT_INF(size_t); - case CL_DEVICE_IMAGE_MAX_ARRAY_SIZE: DEV_GET_INT_INF(size_t); - case CL_DEVICE_PARENT_DEVICE: - PYOPENCL_GET_OPAQUE_INFO(Device, m_device, param_name, cl_device_id, device, DEVICE); - case CL_DEVICE_PARTITION_MAX_SUB_DEVICES: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_PARTITION_TYPE: - case CL_DEVICE_PARTITION_PROPERTIES: - { - std::vector<cl_device_partition_property> result; - PYOPENCL_GET_VEC_INFO(Device, m_device, param_name, result); - PYOPENCL_GET_ARRAY_INFO(cl_device_partition_property, result); - } - case CL_DEVICE_PARTITION_AFFINITY_DOMAIN: - { - std::vector<cl_device_affinity_domain> result; - PYOPENCL_GET_VEC_INFO(Device, m_device, param_name, result); - PYOPENCL_GET_ARRAY_INFO(cl_device_affinity_domain, result); - } - case CL_DEVICE_REFERENCE_COUNT: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_PREFERRED_INTEROP_USER_SYNC: DEV_GET_INT_INF(cl_bool); - case CL_DEVICE_PRINTF_BUFFER_SIZE: DEV_GET_INT_INF(cl_bool); + case CL_DEVICE_LINKER_AVAILABLE: DEV_GET_INT_INF(cl_bool); + case CL_DEVICE_BUILT_IN_KERNELS: + PYOPENCL_GET_STR_INFO(Device, m_device, param_name); + case CL_DEVICE_IMAGE_MAX_BUFFER_SIZE: DEV_GET_INT_INF(size_t); + case CL_DEVICE_IMAGE_MAX_ARRAY_SIZE: DEV_GET_INT_INF(size_t); + case CL_DEVICE_PARENT_DEVICE: + PYOPENCL_GET_OPAQUE_INFO(Device, m_device, param_name, cl_device_id, device, DEVICE); + case CL_DEVICE_PARTITION_MAX_SUB_DEVICES: DEV_GET_INT_INF(cl_uint); + case CL_DEVICE_PARTITION_TYPE: + case CL_DEVICE_PARTITION_PROPERTIES: + { + std::vector<cl_device_partition_property> result; + PYOPENCL_GET_VEC_INFO(Device, m_device, param_name, result); + PYOPENCL_GET_ARRAY_INFO(cl_device_partition_property, result); + } + case CL_DEVICE_PARTITION_AFFINITY_DOMAIN: + { + std::vector<cl_device_affinity_domain> result; + PYOPENCL_GET_VEC_INFO(Device, m_device, param_name, result); + PYOPENCL_GET_ARRAY_INFO(cl_device_affinity_domain, result); + } + case CL_DEVICE_REFERENCE_COUNT: DEV_GET_INT_INF(cl_uint); + case CL_DEVICE_PREFERRED_INTEROP_USER_SYNC: DEV_GET_INT_INF(cl_bool); + case CL_DEVICE_PRINTF_BUFFER_SIZE: DEV_GET_INT_INF(cl_bool); #endif // {{{ AMD dev attrs // // types of AMD dev attrs divined from // https://www.khronos.org/registry/cl/api/1.2/cl.hpp #ifdef CL_DEVICE_PROFILING_TIMER_OFFSET_AMD - case CL_DEVICE_PROFILING_TIMER_OFFSET_AMD: DEV_GET_INT_INF(cl_ulong); + case CL_DEVICE_PROFILING_TIMER_OFFSET_AMD: DEV_GET_INT_INF(cl_ulong); #endif /* FIXME #ifdef CL_DEVICE_TOPOLOGY_AMD @@ -683,55 +717,56 @@ namespace pyopencl #endif */ #ifdef CL_DEVICE_BOARD_NAME_AMD - case CL_DEVICE_BOARD_NAME_AMD: ; - PYOPENCL_GET_STR_INFO(Device, m_device, param_name); + case CL_DEVICE_BOARD_NAME_AMD: ; + PYOPENCL_GET_STR_INFO(Device, m_device, param_name); #endif #ifdef CL_DEVICE_GLOBAL_FREE_MEMORY_AMD - case CL_DEVICE_GLOBAL_FREE_MEMORY_AMD: - { - std::vector<size_t> result; - PYOPENCL_GET_VEC_INFO(Device, m_device, param_name, result); - PYOPENCL_GET_ARRAY_INFO(size_t, result); - } + case CL_DEVICE_GLOBAL_FREE_MEMORY_AMD: + { + std::vector<size_t> result; + PYOPENCL_GET_VEC_INFO(Device, m_device, param_name, result); + PYOPENCL_GET_ARRAY_INFO(size_t, result); + } #endif #ifdef CL_DEVICE_SIMD_PER_COMPUTE_UNIT_AMD - case CL_DEVICE_SIMD_PER_COMPUTE_UNIT_AMD: DEV_GET_INT_INF(cl_uint); + case CL_DEVICE_SIMD_PER_COMPUTE_UNIT_AMD: DEV_GET_INT_INF(cl_uint); #endif #ifdef CL_DEVICE_SIMD_WIDTH_AMD - case CL_DEVICE_SIMD_WIDTH_AMD: DEV_GET_INT_INF(cl_uint); + case CL_DEVICE_SIMD_WIDTH_AMD: DEV_GET_INT_INF(cl_uint); #endif #ifdef CL_DEVICE_SIMD_INSTRUCTION_WIDTH_AMD - case CL_DEVICE_SIMD_INSTRUCTION_WIDTH_AMD: DEV_GET_INT_INF(cl_uint); + case CL_DEVICE_SIMD_INSTRUCTION_WIDTH_AMD: DEV_GET_INT_INF(cl_uint); #endif #ifdef CL_DEVICE_WAVEFRONT_WIDTH_AMD - case CL_DEVICE_WAVEFRONT_WIDTH_AMD: DEV_GET_INT_INF(cl_uint); + case CL_DEVICE_WAVEFRONT_WIDTH_AMD: DEV_GET_INT_INF(cl_uint); #endif #ifdef CL_DEVICE_GLOBAL_MEM_CHANNELS_AMD - case CL_DEVICE_GLOBAL_MEM_CHANNELS_AMD: DEV_GET_INT_INF(cl_uint); + case CL_DEVICE_GLOBAL_MEM_CHANNELS_AMD: DEV_GET_INT_INF(cl_uint); #endif #ifdef CL_DEVICE_GLOBAL_MEM_CHANNEL_BANKS_AMD - case CL_DEVICE_GLOBAL_MEM_CHANNEL_BANKS_AMD: DEV_GET_INT_INF(cl_uint); + case CL_DEVICE_GLOBAL_MEM_CHANNEL_BANKS_AMD: DEV_GET_INT_INF(cl_uint); #endif #ifdef CL_DEVICE_GLOBAL_MEM_CHANNEL_BANK_WIDTH_AMD - case CL_DEVICE_GLOBAL_MEM_CHANNEL_BANK_WIDTH_AMD: DEV_GET_INT_INF(cl_uint); + case CL_DEVICE_GLOBAL_MEM_CHANNEL_BANK_WIDTH_AMD: DEV_GET_INT_INF(cl_uint); #endif #ifdef CL_DEVICE_LOCAL_MEM_SIZE_PER_COMPUTE_UNIT_AMD - case CL_DEVICE_LOCAL_MEM_SIZE_PER_COMPUTE_UNIT_AMD: DEV_GET_INT_INF(cl_uint); + case CL_DEVICE_LOCAL_MEM_SIZE_PER_COMPUTE_UNIT_AMD: DEV_GET_INT_INF(cl_uint); #endif #ifdef CL_DEVICE_LOCAL_MEM_BANKS_AMD - case CL_DEVICE_LOCAL_MEM_BANKS_AMD: DEV_GET_INT_INF(cl_uint); + case CL_DEVICE_LOCAL_MEM_BANKS_AMD: DEV_GET_INT_INF(cl_uint); #endif // }}} #ifdef CL_DEVICE_MAX_ATOMIC_COUNTERS_EXT - case CL_DEVICE_MAX_ATOMIC_COUNTERS_EXT: DEV_GET_INT_INF(cl_uint); + case CL_DEVICE_MAX_ATOMIC_COUNTERS_EXT: DEV_GET_INT_INF(cl_uint); #endif - default: - throw error("Device.get_info", CL_INVALID_VALUE); - } - } + default: + throw error("Device.get_info", CL_INVALID_VALUE); + } + } + // TODO: sub-devices // #if PYOPENCL_CL_VERSION >= 0x1020 // py::list create_sub_devices(py::object py_properties) // { @@ -806,57 +841,57 @@ namespace pyopencl // }}} - // {{{ context - class context : public _common // : public boost::noncopyable + + class context : public noncopyable { - private: - cl_context m_context; + private: + cl_context m_context; - public: - context(cl_context ctx, bool retain) - : m_context(ctx) - { - if (retain) - PYOPENCL_CALL_GUARDED(clRetainContext, (ctx)); - } + public: + context(cl_context ctx, bool retain) + : m_context(ctx) + { + if (retain) + PYOPENCL_CALL_GUARDED(clRetainContext, (ctx)); + } - ~context() - { - PYOPENCL_CALL_GUARDED_CLEANUP(clReleaseContext, - (m_context)); - } + ~context() + { + PYOPENCL_CALL_GUARDED_CLEANUP(clReleaseContext, (m_context)); + } - cl_context data() const - { - return m_context; - } + cl_context data() const + { + return m_context; + } - PYOPENCL_EQUALITY_TESTS(context); + PYOPENCL_EQUALITY_TESTS(context); - generic_info get_info(cl_context_info param_name) const - { - switch (param_name) + generic_info get_info(cl_context_info param_name) const + { + switch (param_name) { - case CL_CONTEXT_REFERENCE_COUNT: - PYOPENCL_GET_INTEGRAL_INFO(Context, m_context, param_name, cl_uint); + case CL_CONTEXT_REFERENCE_COUNT: + PYOPENCL_GET_INTEGRAL_INFO(Context, m_context, param_name, cl_uint); - case CL_CONTEXT_DEVICES: - { - std::vector<cl_device_id> result; - PYOPENCL_GET_VEC_INFO(Context, m_context, param_name, result); - PYOPENCL_GET_OPAQUE_ARRAY_INFO(cl_device_id, device, DEVICE, result); + case CL_CONTEXT_DEVICES: + { + std::vector<cl_device_id> result; + PYOPENCL_GET_VEC_INFO(Context, m_context, param_name, result); + PYOPENCL_GET_OPAQUE_ARRAY_INFO(cl_device_id, device, DEVICE, result); - } + } - case CL_CONTEXT_PROPERTIES: - { + case CL_CONTEXT_PROPERTIES: + { + std::vector<cl_context_properties> result; + PYOPENCL_GET_VEC_INFO(Context, m_context, param_name, result); + + std::vector<generic_info> py_result; - std::vector<cl_context_properties> result; - PYOPENCL_GET_VEC_INFO(Context, m_context, param_name, result); - std::vector<generic_info> py_result; - for (size_t i = 0; i < result.size(); i+=2) + for (size_t i = 0; i < result.size(); i+=2) { cl_context_properties key = result[i]; if(key == 0) @@ -865,7 +900,7 @@ namespace pyopencl info.dontfree = 0; info.opaque_class = CLASS_NONE; switch (key) - { + { case CL_CONTEXT_PLATFORM: { info.opaque_class = CLASS_PLATFORM; @@ -893,90 +928,92 @@ namespace pyopencl #endif default: throw error("Context.get_info", CL_INVALID_VALUE, - "unknown context_property key encountered"); - } + "unknown context_property key encountered"); + } py_result.push_back(info); } - PYOPENCL_GET_ARRAY_INFO(generic_info, py_result); - } + PYOPENCL_GET_ARRAY_INFO(generic_info, py_result); + } #if PYOPENCL_CL_VERSION >= 0x1010 - case CL_CONTEXT_NUM_DEVICES: - PYOPENCL_GET_INTEGRAL_INFO(Context, m_context, param_name, cl_uint); + case CL_CONTEXT_NUM_DEVICES: + PYOPENCL_GET_INTEGRAL_INFO(Context, m_context, param_name, cl_uint); #endif - default: - throw error("Context.get_info", CL_INVALID_VALUE); + default: + throw error("Context.get_info", CL_INVALID_VALUE); } - } - - // }}} + } }; + // }}} + + // {{{ command_queue - class command_queue : public _common + + class command_queue : public noncopyable { - private: - cl_command_queue m_queue; + private: + cl_command_queue m_queue; - public: - command_queue(cl_command_queue q, bool retain) - : m_queue(q) - { - if (retain) - PYOPENCL_CALL_GUARDED(clRetainCommandQueue, (q)); - } + public: + command_queue(cl_command_queue q, bool retain) + : m_queue(q) + { + if (retain) + PYOPENCL_CALL_GUARDED(clRetainCommandQueue, (q)); + } - command_queue(command_queue const &src) - : m_queue(src.m_queue) - { - PYOPENCL_CALL_GUARDED(clRetainCommandQueue, (m_queue)); - } + command_queue(command_queue const &src) + : m_queue(src.m_queue) + { + PYOPENCL_CALL_GUARDED(clRetainCommandQueue, (m_queue)); + } - command_queue( - const context &ctx, - const device *py_dev=0, - cl_command_queue_properties props=0) - { - cl_device_id dev; - if (py_dev) - dev = py_dev->data(); - else - { - std::vector<cl_device_id> devs; - PYOPENCL_GET_VEC_INFO(Context, ctx.data(), CL_CONTEXT_DEVICES, devs); - if (devs.size() == 0) - throw pyopencl::error("CommandQueue", CL_INVALID_VALUE, - "context doesn't have any devices? -- don't know which one to default to"); - dev = devs[0]; - } + command_queue( + const context &ctx, + const device *py_dev=0, + cl_command_queue_properties props=0) + { + cl_device_id dev; + if (py_dev) + dev = py_dev->data(); + else + { + std::vector<cl_device_id> devs; + PYOPENCL_GET_VEC_INFO(Context, ctx.data(), CL_CONTEXT_DEVICES, devs); + if (devs.size() == 0) + throw pyopencl::error("CommandQueue", CL_INVALID_VALUE, + "context doesn't have any devices? -- don't know which one to default to"); + dev = devs[0]; + } - cl_int status_code; - PYOPENCL_PRINT_CALL_TRACE("clCreateCommandQueue"); - m_queue = clCreateCommandQueue( - ctx.data(), dev, props, &status_code); + cl_int status_code; + PYOPENCL_PRINT_CALL_TRACE("clCreateCommandQueue"); + m_queue = clCreateCommandQueue( + ctx.data(), dev, props, &status_code); - if (status_code != CL_SUCCESS) { - throw pyopencl::error("CommandQueue", status_code); + if (status_code != CL_SUCCESS) { + throw pyopencl::error("CommandQueue", status_code); + } } - } - ~command_queue() - { - PYOPENCL_CALL_GUARDED_CLEANUP(clReleaseCommandQueue, - (m_queue)); - } + ~command_queue() + { + PYOPENCL_CALL_GUARDED_CLEANUP(clReleaseCommandQueue, + (m_queue)); + } - const cl_command_queue data() const - { return m_queue; } + const cl_command_queue data() const + { return m_queue; } - PYOPENCL_EQUALITY_TESTS(command_queue); + PYOPENCL_EQUALITY_TESTS(command_queue); - generic_info get_info(cl_command_queue_info param_name) const - { - switch (param_name) + generic_info get_info(cl_command_queue_info param_name) const + { + switch (param_name) { case CL_QUEUE_CONTEXT: PYOPENCL_GET_OPAQUE_INFO(CommandQueue, m_queue, param_name, @@ -993,21 +1030,21 @@ namespace pyopencl default: throw error("CommandQueue.get_info", CL_INVALID_VALUE); } - } + } - std::auto_ptr<context> get_context() const - { - cl_context param_value; - PYOPENCL_CALL_GUARDED(clGetCommandQueueInfo, - (m_queue, CL_QUEUE_CONTEXT, sizeof(param_value), ¶m_value, 0)); - return std::auto_ptr<context>( - new context(param_value, /*retain*/ true)); - } + std::auto_ptr<context> get_context() const + { + cl_context param_value; + PYOPENCL_CALL_GUARDED(clGetCommandQueueInfo, + (m_queue, CL_QUEUE_CONTEXT, sizeof(param_value), ¶m_value, 0)); + return std::auto_ptr<context>( + new context(param_value, /*retain*/ true)); + } #if PYOPENCL_CL_VERSION < 0x1010 cl_command_queue_properties set_property( - cl_command_queue_properties prop, - bool enable) + cl_command_queue_properties prop, + bool enable) { cl_command_queue_properties old_prop; PYOPENCL_CALL_GUARDED(clSetCommandQueueProperty, @@ -1018,6 +1055,7 @@ namespace pyopencl void flush() { PYOPENCL_CALL_GUARDED(clFlush, (m_queue)); } + void finish() { // TODO @@ -1028,81 +1066,82 @@ namespace pyopencl // }}} - // {{{ event/synchronization - class event : public _common // : boost::noncopyable + // {{{ event + + class event : public noncopyable { - private: - cl_event m_event; + private: + cl_event m_event; - public: - event(cl_event event, bool retain) - : m_event(event) - { - if (retain) - PYOPENCL_CALL_GUARDED(clRetainEvent, (event)); - } + public: + event(cl_event event, bool retain) + : m_event(event) + { + if (retain) + PYOPENCL_CALL_GUARDED(clRetainEvent, (event)); + } - event(event const &src) - : m_event(src.m_event) - { PYOPENCL_CALL_GUARDED(clRetainEvent, (m_event)); } + event(event const &src) + : m_event(src.m_event) + { PYOPENCL_CALL_GUARDED(clRetainEvent, (m_event)); } - virtual ~event() - { - PYOPENCL_CALL_GUARDED_CLEANUP(clReleaseEvent, - (m_event)); - } + virtual ~event() + { + PYOPENCL_CALL_GUARDED_CLEANUP(clReleaseEvent, + (m_event)); + } - const cl_event data() const - { return m_event; } + const cl_event data() const + { return m_event; } - PYOPENCL_EQUALITY_TESTS(event); + PYOPENCL_EQUALITY_TESTS(event); - generic_info get_info(cl_event_info param_name) const - { - switch (param_name) + generic_info get_info(cl_event_info param_name) const + { + switch (param_name) { - case CL_EVENT_COMMAND_QUEUE: - PYOPENCL_GET_OPAQUE_INFO(Event, m_event, param_name, - cl_command_queue, command_queue, COMMAND_QUEUE); - case CL_EVENT_COMMAND_TYPE: - PYOPENCL_GET_INTEGRAL_INFO(Event, m_event, param_name, - cl_command_type); - case CL_EVENT_COMMAND_EXECUTION_STATUS: - PYOPENCL_GET_INTEGRAL_INFO(Event, m_event, param_name, - cl_int); - case CL_EVENT_REFERENCE_COUNT: - PYOPENCL_GET_INTEGRAL_INFO(Event, m_event, param_name, - cl_uint); + case CL_EVENT_COMMAND_QUEUE: + PYOPENCL_GET_OPAQUE_INFO(Event, m_event, param_name, + cl_command_queue, command_queue, COMMAND_QUEUE); + case CL_EVENT_COMMAND_TYPE: + PYOPENCL_GET_INTEGRAL_INFO(Event, m_event, param_name, + cl_command_type); + case CL_EVENT_COMMAND_EXECUTION_STATUS: + PYOPENCL_GET_INTEGRAL_INFO(Event, m_event, param_name, + cl_int); + case CL_EVENT_REFERENCE_COUNT: + PYOPENCL_GET_INTEGRAL_INFO(Event, m_event, param_name, + cl_uint); #if PYOPENCL_CL_VERSION >= 0x1010 - case CL_EVENT_CONTEXT: - PYOPENCL_GET_OPAQUE_INFO(Event, m_event, param_name, - cl_context, context, CONTEXT); + case CL_EVENT_CONTEXT: + PYOPENCL_GET_OPAQUE_INFO(Event, m_event, param_name, + cl_context, context, CONTEXT); #endif - default: - throw error("Event.get_info", CL_INVALID_VALUE); + default: + throw error("Event.get_info", CL_INVALID_VALUE); } - } + } - generic_info get_profiling_info(cl_profiling_info param_name) const - { - switch (param_name) + generic_info get_profiling_info(cl_profiling_info param_name) const + { + switch (param_name) { - case CL_PROFILING_COMMAND_QUEUED: - case CL_PROFILING_COMMAND_SUBMIT: - case CL_PROFILING_COMMAND_START: - case CL_PROFILING_COMMAND_END: - PYOPENCL_GET_INTEGRAL_INFO(EventProfiling, m_event, param_name, - cl_ulong); - default: - throw error("Event.get_profiling_info", CL_INVALID_VALUE); + case CL_PROFILING_COMMAND_QUEUED: + case CL_PROFILING_COMMAND_SUBMIT: + case CL_PROFILING_COMMAND_START: + case CL_PROFILING_COMMAND_END: + PYOPENCL_GET_INTEGRAL_INFO(EventProfiling, m_event, param_name, + cl_ulong); + default: + throw error("Event.get_profiling_info", CL_INVALID_VALUE); } - } + } - virtual void wait() - { - PYOPENCL_CALL_GUARDED_THREADED(clWaitForEvents, (1, &m_event)); - } + virtual void wait() + { + PYOPENCL_CALL_GUARDED_THREADED(clWaitForEvents, (1, &m_event)); + } }; // }}} @@ -1112,121 +1151,121 @@ namespace pyopencl //py::object create_mem_object_wrapper(cl_mem mem); - class memory_object_holder : public _common + class memory_object_holder : public noncopyable { - public: - virtual const cl_mem data() const = 0; + public: + virtual const cl_mem data() const = 0; - PYOPENCL_EQUALITY_TESTS(memory_object_holder); + PYOPENCL_EQUALITY_TESTS(memory_object_holder); - size_t size() const - { - size_t param_value; - PYOPENCL_CALL_GUARDED(clGetMemObjectInfo, - (data(), CL_MEM_SIZE, sizeof(param_value), ¶m_value, 0)); - return param_value; - } + size_t size() const + { + size_t param_value; + PYOPENCL_CALL_GUARDED(clGetMemObjectInfo, + (data(), CL_MEM_SIZE, sizeof(param_value), ¶m_value, 0)); + return param_value; + } - generic_info get_info(cl_mem_info param_name) { - switch (param_name){ - case CL_MEM_TYPE: - PYOPENCL_GET_INTEGRAL_INFO(MemObject, data(), param_name, - cl_mem_object_type); - case CL_MEM_FLAGS: - PYOPENCL_GET_INTEGRAL_INFO(MemObject, data(), param_name, - cl_mem_flags); - case CL_MEM_SIZE: - PYOPENCL_GET_INTEGRAL_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_INTEGRAL_INFO(MemObject, data(), param_name, - cl_uint); - case CL_MEM_REFERENCE_COUNT: - PYOPENCL_GET_INTEGRAL_INFO(MemObject, data(), param_name, - cl_uint); - case CL_MEM_CONTEXT: - PYOPENCL_GET_OPAQUE_INFO(MemObject, data(), param_name, - cl_context, context, CONTEXT); + generic_info get_info(cl_mem_info param_name) { + switch (param_name){ + case CL_MEM_TYPE: + PYOPENCL_GET_INTEGRAL_INFO(MemObject, data(), param_name, + cl_mem_object_type); + case CL_MEM_FLAGS: + PYOPENCL_GET_INTEGRAL_INFO(MemObject, data(), param_name, + cl_mem_flags); + case CL_MEM_SIZE: + PYOPENCL_GET_INTEGRAL_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_INTEGRAL_INFO(MemObject, data(), param_name, + cl_uint); + case CL_MEM_REFERENCE_COUNT: + PYOPENCL_GET_INTEGRAL_INFO(MemObject, data(), param_name, + cl_uint); + case CL_MEM_CONTEXT: + PYOPENCL_GET_OPAQUE_INFO(MemObject, data(), param_name, + cl_context, 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 py::object(); - // } - - // return create_mem_object_wrapper(param_value); - // } - case CL_MEM_OFFSET: - PYOPENCL_GET_INTEGRAL_INFO(MemObject, data(), param_name, - size_t); + // TODO + // 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 py::object(); + // } + + // return create_mem_object_wrapper(param_value); + // } + case CL_MEM_OFFSET: + PYOPENCL_GET_INTEGRAL_INFO(MemObject, data(), param_name, + size_t); #endif - default: - throw error("MemoryObjectHolder.get_info", CL_INVALID_VALUE); + default: + throw error("MemoryObjectHolder.get_info", CL_INVALID_VALUE); + } } - } }; - class memory_object : /*boost::noncopyable, */ public memory_object_holder + class memory_object : public memory_object_holder { - private: - bool m_valid; - cl_mem m_mem; - void *m_hostbuf; - - public: - memory_object(cl_mem mem, bool retain, void *hostbuf=0) - : m_valid(true), m_mem(mem) - { - if (retain) - PYOPENCL_CALL_GUARDED(clRetainMemObject, (mem)); + private: + bool m_valid; + cl_mem m_mem; + void *m_hostbuf; - if (hostbuf) - m_hostbuf = hostbuf; - } + public: + memory_object(cl_mem mem, bool retain, void *hostbuf=0) + : m_valid(true), m_mem(mem) + { + if (retain) + PYOPENCL_CALL_GUARDED(clRetainMemObject, (mem)); - memory_object(memory_object const &src) - : m_valid(true), m_mem(src.m_mem), m_hostbuf(src.m_hostbuf) - { - PYOPENCL_CALL_GUARDED(clRetainMemObject, (m_mem)); - } + if (hostbuf) + m_hostbuf = hostbuf; + } - memory_object(memory_object_holder const &src) - : m_valid(true), m_mem(src.data()) - { - PYOPENCL_CALL_GUARDED(clRetainMemObject, (m_mem)); - } + memory_object(memory_object const &src) + : m_valid(true), m_mem(src.m_mem), m_hostbuf(src.m_hostbuf) + { + PYOPENCL_CALL_GUARDED(clRetainMemObject, (m_mem)); + } - void release() - { - if (!m_valid) - throw error("MemoryObject.free", CL_INVALID_VALUE, - "trying to double-unref mem object"); - PYOPENCL_CALL_GUARDED_CLEANUP(clReleaseMemObject, (m_mem)); - m_valid = false; - } + memory_object(memory_object_holder const &src) + : m_valid(true), m_mem(src.data()) + { + PYOPENCL_CALL_GUARDED(clRetainMemObject, (m_mem)); + } - virtual ~memory_object() - { - if (m_valid) - release(); - } + void release() + { + if (!m_valid) + throw error("MemoryObject.free", CL_INVALID_VALUE, + "trying to double-unref mem object"); + PYOPENCL_CALL_GUARDED_CLEANUP(clReleaseMemObject, (m_mem)); + m_valid = false; + } - void *hostbuf() - { return m_hostbuf; } + virtual ~memory_object() + { + if (m_valid) + release(); + } - const cl_mem data() const - { return m_mem; } + void *hostbuf() + { return m_hostbuf; } + const cl_mem data() const + { return m_mem; } }; // #if PYOPENCL_CL_VERSION >= 0x1020 @@ -1304,52 +1343,53 @@ namespace pyopencl class image : public memory_object { - public: - image(cl_mem mem, bool retain, void *hostbuf=0) - : memory_object(mem, retain, hostbuf) - { } + public: + image(cl_mem mem, bool retain, void *hostbuf=0) + : memory_object(mem, retain, hostbuf) + { } - generic_info get_image_info(cl_image_info param_name) const - { - switch (param_name) + generic_info get_image_info(cl_image_info param_name) const + { + switch (param_name) { - case CL_IMAGE_FORMAT: - PYOPENCL_GET_INTEGRAL_INFO(Image, data(), param_name, - cl_image_format); - case CL_IMAGE_ELEMENT_SIZE: - case CL_IMAGE_ROW_PITCH: - case CL_IMAGE_SLICE_PITCH: - case CL_IMAGE_WIDTH: - case CL_IMAGE_HEIGHT: - case CL_IMAGE_DEPTH: + case CL_IMAGE_FORMAT: + PYOPENCL_GET_INTEGRAL_INFO(Image, data(), param_name, + cl_image_format); + case CL_IMAGE_ELEMENT_SIZE: + case CL_IMAGE_ROW_PITCH: + case CL_IMAGE_SLICE_PITCH: + case CL_IMAGE_WIDTH: + case CL_IMAGE_HEIGHT: + case CL_IMAGE_DEPTH: #if PYOPENCL_CL_VERSION >= 0x1020 - case CL_IMAGE_ARRAY_SIZE: + case CL_IMAGE_ARRAY_SIZE: #endif - PYOPENCL_GET_INTEGRAL_INFO(Image, data(), param_name, size_t); + PYOPENCL_GET_INTEGRAL_INFO(Image, data(), param_name, size_t); #if PYOPENCL_CL_VERSION >= 0x1020 - // case CL_IMAGE_BUFFER: - // { - // cl_mem param_value; - // PYOPENCL_CALL_GUARDED(clGetImageInfo, (data(), param_name, sizeof(param_value), ¶m_value, 0)); - // if (param_value == 0) - // { - // // no associated memory object? no problem. - // return py::object(); - // } - - // return create_mem_object_wrapper(param_value); - // } - - case CL_IMAGE_NUM_MIP_LEVELS: - case CL_IMAGE_NUM_SAMPLES: - PYOPENCL_GET_INTEGRAL_INFO(Image, data(), param_name, cl_uint); + // TODO: + // case CL_IMAGE_BUFFER: + // { + // cl_mem param_value; + // PYOPENCL_CALL_GUARDED(clGetImageInfo, (data(), param_name, sizeof(param_value), ¶m_value, 0)); + // if (param_value == 0) + // { + // // no associated memory object? no problem. + // return py::object(); + // } + + // return create_mem_object_wrapper(param_value); + // } + + case CL_IMAGE_NUM_MIP_LEVELS: + case CL_IMAGE_NUM_SAMPLES: + PYOPENCL_GET_INTEGRAL_INFO(Image, data(), param_name, cl_uint); #endif - default: - throw error("MemoryObject.get_image_info", CL_INVALID_VALUE); + default: + throw error("MemoryObject.get_image_info", CL_INVALID_VALUE); } - } + } }; @@ -1392,8 +1432,8 @@ namespace pyopencl retained_buf_obj = buffer; PYOPENCL_PRINT_CALL_TRACE("clCreateImage2D"); - // - //PYOPENCL_RETRY_IF_MEM_ERROR( + + // PYOPENCL_RETRY_IF_MEM_ERROR( { mem = clCreateImage2D(ctx.data(), flags, &fmt, width, height, pitch, buffer, &status_code); @@ -1403,14 +1443,14 @@ namespace pyopencl //); try - { - return new image(mem, false, retained_buf_obj); - } + { + return new image(mem, false, retained_buf_obj); + } catch (...) - { - PYOPENCL_CALL_GUARDED(clReleaseMemObject, (mem)); - throw; - } + { + PYOPENCL_CALL_GUARDED(clReleaseMemObject, (mem)); + throw; + } } inline @@ -1829,6 +1869,7 @@ namespace pyopencl + // TODO: // inline // py::tuple get_gl_object_info(memory_object_holder const &mem) // { @@ -1955,7 +1996,6 @@ namespace pyopencl // }}} - // {{{ buffer inline cl_mem create_buffer( @@ -2110,6 +2150,7 @@ namespace pyopencl // }}} // }}} + // {{{ sampler class sampler // : boost::noncopyable { @@ -2181,187 +2222,260 @@ namespace pyopencl // {{{ program - class program : public _common //: boost::noncopyable + class program : public noncopyable { + private: + cl_program m_program; + program_kind_type m_program_kind; - private: - cl_program m_program; - program_kind_type m_program_kind; - - public: - program(cl_program prog, bool retain, program_kind_type progkind=KND_UNKNOWN) - : m_program(prog), m_program_kind(progkind) - { - if (retain) - PYOPENCL_CALL_GUARDED(clRetainProgram, (prog)); - } + public: + program(cl_program prog, bool retain, program_kind_type progkind=KND_UNKNOWN) + : m_program(prog), m_program_kind(progkind) + { + if (retain) + PYOPENCL_CALL_GUARDED(clRetainProgram, (prog)); + } - ~program() - { - PYOPENCL_CALL_GUARDED_CLEANUP(clReleaseProgram, (m_program)); - } + ~program() + { + PYOPENCL_CALL_GUARDED_CLEANUP(clReleaseProgram, (m_program)); + } - cl_program data() const - { - return m_program; - } + cl_program data() const + { + return m_program; + } - program_kind_type kind() const - { - return m_program_kind; - } + program_kind_type kind() const + { + return m_program_kind; + } - PYOPENCL_EQUALITY_TESTS(program); + PYOPENCL_EQUALITY_TESTS(program); - std::vector<cl_device_id> get_info__devices() - { - std::vector<cl_device_id> result; - PYOPENCL_GET_VEC_INFO(Program, m_program, CL_PROGRAM_DEVICES, result); - return result; - } + std::vector<cl_device_id> get_info__devices() + { + std::vector<cl_device_id> result; + PYOPENCL_GET_VEC_INFO(Program, m_program, CL_PROGRAM_DEVICES, result); + return result; + } - generic_info get_info(cl_program_info param_name) const - { - switch (param_name) + generic_info get_info(cl_program_info param_name) const + { + switch (param_name) { - case CL_PROGRAM_REFERENCE_COUNT: - PYOPENCL_GET_INTEGRAL_INFO(Program, m_program, param_name, - cl_uint); - case CL_PROGRAM_CONTEXT: - PYOPENCL_GET_OPAQUE_INFO(Program, m_program, param_name, - cl_context, context, CONTEXT); - case CL_PROGRAM_NUM_DEVICES: - PYOPENCL_GET_INTEGRAL_INFO(Program, m_program, param_name, - cl_uint); - case CL_PROGRAM_DEVICES: - { - std::vector<cl_device_id> result; - PYOPENCL_GET_VEC_INFO(Program, m_program, param_name, result); - PYOPENCL_GET_OPAQUE_ARRAY_INFO(cl_device_id, device, DEVICE, result); - } - case CL_PROGRAM_SOURCE: - PYOPENCL_GET_STR_INFO(Program, m_program, param_name); - case CL_PROGRAM_BINARY_SIZES: - { - std::vector<size_t> result; - PYOPENCL_GET_VEC_INFO(Program, m_program, param_name, result); - PYOPENCL_GET_ARRAY_INFO(size_t, result); - } - case CL_PROGRAM_BINARIES: - { - std::vector<size_t> sizes; - PYOPENCL_GET_VEC_INFO(Program, m_program, CL_PROGRAM_BINARY_SIZES, sizes); - std::vector<char *> result_ptrs(sizes.size()); - for (unsigned i = 0; i < sizes.size(); ++i) { - result_ptrs[i] = new char[sizes[i]]; + case CL_PROGRAM_REFERENCE_COUNT: + PYOPENCL_GET_INTEGRAL_INFO(Program, m_program, param_name, + cl_uint); + case CL_PROGRAM_CONTEXT: + PYOPENCL_GET_OPAQUE_INFO(Program, m_program, param_name, + cl_context, context, CONTEXT); + case CL_PROGRAM_NUM_DEVICES: + PYOPENCL_GET_INTEGRAL_INFO(Program, m_program, param_name, + cl_uint); + case CL_PROGRAM_DEVICES: + { + std::vector<cl_device_id> result; + PYOPENCL_GET_VEC_INFO(Program, m_program, param_name, result); + PYOPENCL_GET_OPAQUE_ARRAY_INFO(cl_device_id, device, DEVICE, result); } - std::vector<generic_info> gis(sizes.size()); - for(unsigned i = 0; i < sizes.size(); ++i) { - gis[i].opaque_class = CLASS_NONE; - gis[i].type = _copy_str(std::string("char[") + tostring(sizes[i]) + "]"); - gis[i].value = result_ptrs[i]; + case CL_PROGRAM_SOURCE: + PYOPENCL_GET_STR_INFO(Program, m_program, param_name); + case CL_PROGRAM_BINARY_SIZES: + { + std::vector<size_t> result; + PYOPENCL_GET_VEC_INFO(Program, m_program, param_name, result); + PYOPENCL_GET_ARRAY_INFO(size_t, result); + } + case CL_PROGRAM_BINARIES: + { + std::vector<size_t> sizes; + PYOPENCL_GET_VEC_INFO(Program, m_program, CL_PROGRAM_BINARY_SIZES, sizes); + std::vector<char *> result_ptrs(sizes.size()); + for (unsigned i = 0; i < sizes.size(); ++i) { + result_ptrs[i] = new char[sizes[i]]; + } + std::vector<generic_info> gis(sizes.size()); + for(unsigned i = 0; i < sizes.size(); ++i) { + gis[i].opaque_class = CLASS_NONE; + gis[i].type = _copy_str(std::string("char[") + tostring(sizes[i]) + "]"); + gis[i].value = result_ptrs[i]; + } + PYOPENCL_CALL_GUARDED(clGetProgramInfo, + (m_program, CL_PROGRAM_BINARIES, sizes.size()*sizeof(char *), + &result_ptrs.front(), 0)); + PYOPENCL_GET_ARRAY_INFO(generic_info, gis); } - PYOPENCL_CALL_GUARDED(clGetProgramInfo, - (m_program, CL_PROGRAM_BINARIES, sizes.size()*sizeof(char *), - &result_ptrs.front(), 0)); - PYOPENCL_GET_ARRAY_INFO(generic_info, gis); - } #if PYOPENCL_CL_VERSION >= 0x1020 - case CL_PROGRAM_NUM_KERNELS: - PYOPENCL_GET_INTEGRAL_INFO(Program, m_program, param_name, - size_t); - case CL_PROGRAM_KERNEL_NAMES: - PYOPENCL_GET_STR_INFO(Program, m_program, param_name); + case CL_PROGRAM_NUM_KERNELS: + PYOPENCL_GET_INTEGRAL_INFO(Program, m_program, param_name, + size_t); + case CL_PROGRAM_KERNEL_NAMES: + PYOPENCL_GET_STR_INFO(Program, m_program, param_name); #endif - default: - throw error("Program.get_info", CL_INVALID_VALUE); + default: + throw error("Program.get_info", CL_INVALID_VALUE); } - } + } - generic_info get_build_info(device const &dev, - cl_program_build_info param_name) const - { - switch (param_name) + generic_info get_build_info(device const &dev, + cl_program_build_info param_name) const + { + switch (param_name) { #define PYOPENCL_FIRST_ARG m_program, dev.data() // hackety hack - case CL_PROGRAM_BUILD_STATUS: - PYOPENCL_GET_INTEGRAL_INFO(ProgramBuild, - PYOPENCL_FIRST_ARG, param_name, - cl_build_status); - case CL_PROGRAM_BUILD_OPTIONS: - case CL_PROGRAM_BUILD_LOG: - PYOPENCL_GET_STR_INFO(ProgramBuild, - PYOPENCL_FIRST_ARG, param_name); + case CL_PROGRAM_BUILD_STATUS: + PYOPENCL_GET_INTEGRAL_INFO(ProgramBuild, + PYOPENCL_FIRST_ARG, param_name, + cl_build_status); + case CL_PROGRAM_BUILD_OPTIONS: + case CL_PROGRAM_BUILD_LOG: + PYOPENCL_GET_STR_INFO(ProgramBuild, + PYOPENCL_FIRST_ARG, param_name); #if PYOPENCL_CL_VERSION >= 0x1020 - case CL_PROGRAM_BINARY_TYPE: - PYOPENCL_GET_INTEGRAL_INFO(ProgramBuild, - PYOPENCL_FIRST_ARG, param_name, - cl_program_binary_type); + case CL_PROGRAM_BINARY_TYPE: + PYOPENCL_GET_INTEGRAL_INFO(ProgramBuild, + PYOPENCL_FIRST_ARG, param_name, + cl_program_binary_type); #endif #undef PYOPENCL_FIRST_ARG - default: - throw error("Program.get_build_info", CL_INVALID_VALUE); + default: + throw error("Program.get_build_info", CL_INVALID_VALUE); } - } + } - void build(char *options, cl_uint num_devices, void **ptr_devices) - { - // todo: this function should get a list of device instances, not raw pointers - // pointers are for the cffi interface and should not be here - std::vector<cl_device_id> devices(num_devices); - for(cl_uint i = 0; i < num_devices; ++i) { - devices[i] = static_cast<device*>(ptr_devices[i])->data(); + void build(char *options, cl_uint num_devices, void **ptr_devices) + { + // todo: this function should get a list of device instances, not raw pointers + // pointers are for the cffi interface and should not be here + std::vector<cl_device_id> devices(num_devices); + for(cl_uint i = 0; i < num_devices; ++i) { + devices[i] = static_cast<device*>(ptr_devices[i])->data(); + } + PYOPENCL_CALL_GUARDED_THREADED(clBuildProgram, + (m_program, num_devices, devices.empty( ) ? NULL : &devices.front(), + options, 0 ,0)); } - PYOPENCL_CALL_GUARDED_THREADED(clBuildProgram, - (m_program, num_devices, devices.empty( ) ? NULL : &devices.front(), - options, 0 ,0)); - } - // #if PYOPENCL_CL_VERSION >= 0x1020 - // void compile(std::string options, py::object py_devices, - // py::object py_headers) - // { - // PYOPENCL_PARSE_PY_DEVICES; + // #if PYOPENCL_CL_VERSION >= 0x1020 + // void compile(std::string options, py::object py_devices, + // py::object py_headers) + // { + // PYOPENCL_PARSE_PY_DEVICES; + + // // {{{ pick apart py_headers + // // py_headers is a list of tuples *(name, program)* + + // std::vector<std::string> header_names; + // std::vector<cl_program> programs; + // PYTHON_FOREACH(name_hdr_tup, py_headers) + // { + // if (py::len(name_hdr_tup) != 2) + // throw error("Program.compile", CL_INVALID_VALUE, + // "epxected (name, header) tuple in headers list"); + // std::string name = py::extract<std::string const &>(name_hdr_tup[0]); + // program &prg = py::extract<program &>(name_hdr_tup[1]); + + // header_names.push_back(name); + // programs.push_back(prg.data()); + // } + + // std::vector<const char *> header_name_ptrs; + // BOOST_FOREACH(std::string const &name, header_names) + // header_name_ptrs.push_back(name.c_str()); + + // // }}} + + // PYOPENCL_CALL_GUARDED_THREADED(clCompileProgram, + // (m_program, num_devices, devices, + // options.c_str(), header_names.size(), + // programs.empty() ? NULL : &programs.front(), + // header_name_ptrs.empty() ? NULL : &header_name_ptrs.front(), + // 0, 0)); + // } + // #endif + }; - // // {{{ pick apart py_headers - // // py_headers is a list of tuples *(name, program)* - // std::vector<std::string> header_names; - // std::vector<cl_program> programs; - // PYTHON_FOREACH(name_hdr_tup, py_headers) - // { - // if (py::len(name_hdr_tup) != 2) - // throw error("Program.compile", CL_INVALID_VALUE, - // "epxected (name, header) tuple in headers list"); - // std::string name = py::extract<std::string const &>(name_hdr_tup[0]); - // program &prg = py::extract<program &>(name_hdr_tup[1]); - - // header_names.push_back(name); - // programs.push_back(prg.data()); - // } + inline + program *create_program_with_source( + context &ctx, + std::string const &src) + { + const char *string = src.c_str(); + size_t length = src.size(); - // std::vector<const char *> header_name_ptrs; - // BOOST_FOREACH(std::string const &name, header_names) - // header_name_ptrs.push_back(name.c_str()); + cl_int status_code; + PYOPENCL_PRINT_CALL_TRACE("clCreateProgramWithSource"); - // // }}} + cl_program result = clCreateProgramWithSource( + ctx.data(), 1, &string, &length, &status_code); - // PYOPENCL_CALL_GUARDED_THREADED(clCompileProgram, - // (m_program, num_devices, devices, - // options.c_str(), header_names.size(), - // programs.empty() ? NULL : &programs.front(), - // header_name_ptrs.empty() ? NULL : &header_name_ptrs.front(), - // 0, 0)); - // } - // #endif - }; + if (status_code != CL_SUCCESS) + throw pyopencl::error("clCreateProgramWithSource", status_code); + + try + { + return new program(result, false, KND_SOURCE); + } + catch (...) + { + clReleaseProgram(result); + throw; + } + } + + + inline + program *create_program_with_binary( + context &ctx, + cl_uint num_devices, + void **ptr_devices, + cl_uint num_binaries, + char **binaries, + size_t *binary_sizes) + { + std::vector<cl_device_id> devices; + std::vector<cl_int> binary_statuses(num_devices); + for (cl_uint i = 0; i < num_devices; ++i) + { + devices.push_back(static_cast<device*>(ptr_devices[i])->data()); + } + cl_int status_code; + PYOPENCL_PRINT_CALL_TRACE("clCreateProgramWithBinary"); + cl_program result = clCreateProgramWithBinary( + ctx.data(), num_devices, + devices.empty( ) ? NULL : &devices.front(), + binary_sizes, + reinterpret_cast<const unsigned char**>(const_cast<const char**>(binaries)), + binary_statuses.empty( ) ? NULL : &binary_statuses.front(), + &status_code); + + // for (cl_uint i = 0; i < num_devices; ++i) + // std::cout << i << ":" << binary_statuses[i] << std::endl; + + if (status_code != CL_SUCCESS) + throw pyopencl::error("clCreateProgramWithBinary", status_code); + + try + { + return new program(result, false, KND_BINARY); + } + catch (...) + { + clReleaseProgram(result); + throw; + } + } // }}} + // {{{ kernel + class local_memory { private: @@ -2379,7 +2493,7 @@ namespace pyopencl - class kernel : public _common // : boost::noncopyable + class kernel : public noncopyable { private: cl_kernel m_kernel; @@ -2418,34 +2532,34 @@ namespace pyopencl void set_arg_null(cl_uint arg_index) { cl_mem m = 0; - PYOPENCL_CALL_GUARDED(clSetKernelArg, (m_kernel, arg_index, - sizeof(cl_mem), &m)); + PYOPENCL_CALL_GUARDED( + clSetKernelArg, (m_kernel, arg_index, sizeof(cl_mem), &m)); } void set_arg_mem(cl_uint arg_index, memory_object_holder &moh) { cl_mem m = moh.data(); - PYOPENCL_CALL_GUARDED(clSetKernelArg, - (m_kernel, arg_index, sizeof(cl_mem), &m)); + PYOPENCL_CALL_GUARDED( + clSetKernelArg, (m_kernel, arg_index, sizeof(cl_mem), &m)); } void set_arg_local(cl_uint arg_index, local_memory const &loc) { - PYOPENCL_CALL_GUARDED(clSetKernelArg, - (m_kernel, arg_index, loc.size(), 0)); + PYOPENCL_CALL_GUARDED( + clSetKernelArg, (m_kernel, arg_index, loc.size(), 0)); } void set_arg_sampler(cl_uint arg_index, sampler const &smp) { cl_sampler s = smp.data(); - PYOPENCL_CALL_GUARDED(clSetKernelArg, - (m_kernel, arg_index, sizeof(cl_sampler), &s)); + PYOPENCL_CALL_GUARDED( + clSetKernelArg, (m_kernel, arg_index, sizeof(cl_sampler), &s)); } void set_arg_buf(cl_uint arg_index, void *buffer, size_t size) { - PYOPENCL_CALL_GUARDED(clSetKernelArg, - (m_kernel, arg_index, size, buffer)); + PYOPENCL_CALL_GUARDED( + clSetKernelArg, (m_kernel, arg_index, size, buffer)); } // void set_arg(cl_uint arg_index, py::object arg) @@ -2574,6 +2688,7 @@ namespace pyopencl // }}} + // {{{ buffer transfers inline @@ -2673,16 +2788,17 @@ namespace pyopencl // }}} + inline event *enqueue_nd_range_kernel( - command_queue &cq, - kernel &knl, - cl_uint work_dim, - const size_t *global_work_offset, - const size_t *global_work_size, - const size_t *local_work_size //, - //py::object py_global_work_offset, - //py::object py_wait_for, - ) + command_queue &cq, + kernel &knl, + cl_uint work_dim, + const size_t *global_work_offset, + const size_t *global_work_size, + const size_t *local_work_size //, + //py::object py_global_work_offset, + //py::object py_wait_for, + ) { // TODO // PYOPENCL_PARSE_WAIT_FOR; @@ -2701,334 +2817,503 @@ namespace pyopencl &evt )); PYOPENCL_RETURN_NEW_EVENT(evt); - } +} - inline - program *create_program_with_source( - context &ctx, - std::string const &src) - { - const char *string = src.c_str(); - size_t length = src.size(); +// {{{ c wrapper - cl_int status_code; - PYOPENCL_PRINT_CALL_TRACE("clCreateProgramWithSource"); - cl_program result = clCreateProgramWithSource( - ctx.data(), 1, &string, &length, &status_code); - if (status_code != CL_SUCCESS) - throw pyopencl::error("clCreateProgramWithSource", status_code); +void free_pointer(void *p) +{ + free(p); +} - try - { - return new program(result, false, KND_SOURCE); - } - catch (...) - { - clReleaseProgram(result); - throw; - } - } +void free_pointer_array(void **p, uint32_t size) +{ + for(uint32_t i = 0; i < size; ++i) + free_pointer(p[i]); +} - inline - program *create_program_with_binary(context &ctx, - cl_uint num_devices, - void **ptr_devices, - cl_uint num_binaries, - char **binaries, - size_t *binary_sizes) - { - std::vector<cl_device_id> devices; - std::vector<cl_int> binary_statuses(num_devices); - for (cl_uint i = 0; i < num_devices; ++i) - { - devices.push_back(static_cast<device*>(ptr_devices[i])->data()); - } - cl_int status_code; - PYOPENCL_PRINT_CALL_TRACE("clCreateProgramWithBinary"); - cl_program result = clCreateProgramWithBinary(ctx.data(), num_devices, - devices.empty( ) ? NULL : &devices.front(), - binary_sizes, - reinterpret_cast<const unsigned char**>(const_cast<const char**>(binaries)), - binary_statuses.empty( ) ? NULL : &binary_statuses.front(), - &status_code); - // for (cl_uint i = 0; i < num_devices; ++i) - // std::cout << i << ":" << binary_statuses[i] << std::endl; - if (status_code != CL_SUCCESS) - throw pyopencl::error("clCreateProgramWithBinary", status_code); +::error *get_platforms(void **ptr_platforms, uint32_t *num_platforms) +{ + BEGIN_C_HANDLE_ERROR - try - { - return new program(result, false, KND_BINARY); - } - catch (...) - { - clReleaseProgram(result); - throw; - } - } + *num_platforms = 0; + PYOPENCL_CALL_GUARDED(clGetPlatformIDs, (0, 0, num_platforms)); + typedef std::vector<cl_platform_id> vec; + vec platforms(*num_platforms); + PYOPENCL_CALL_GUARDED(clGetPlatformIDs, + (*num_platforms, platforms.empty( ) ? NULL : &platforms.front(), num_platforms)); + MALLOC(pyopencl::platform*, _ptr_platforms, *num_platforms); + for(vec::size_type i = 0; i < platforms.size(); ++i) { + _ptr_platforms[i] = new pyopencl::platform(platforms[i]); + } + *ptr_platforms = _ptr_platforms; + + END_C_HANDLE_ERROR + return 0; } +::error *platform__get_devices( + void *ptr_platform, + void **ptr_devices, + uint32_t *num_devices, + cl_device_type devtype) +{ + typedef std::vector<cl_device_id> vec; + + BEGIN_C_HANDLE_ERROR + vec devices = static_cast<pyopencl::platform*>(ptr_platform)->get_devices(devtype); + *num_devices = devices.size(); -::error *get_platforms(void **ptr_platforms, uint32_t *num_platforms) { - C_HANDLE_ERROR( - *num_platforms = 0; - PYOPENCL_CALL_GUARDED(clGetPlatformIDs, (0, 0, num_platforms)); + MALLOC(pyopencl::device*, _ptr_devices, *num_devices); + for(vec::size_type i = 0; i < devices.size(); ++i) { + _ptr_devices[i] = new pyopencl::device(devices[i]); + } + *ptr_devices = _ptr_devices; - typedef std::vector<cl_platform_id> vec; - vec platforms(*num_platforms); - PYOPENCL_CALL_GUARDED(clGetPlatformIDs, - (*num_platforms, platforms.empty( ) ? NULL : &platforms.front(), num_platforms)); + END_C_HANDLE_ERROR - MALLOC(pyopencl::platform*, _ptr_platforms, *num_platforms); - for(vec::size_type i = 0; i < platforms.size(); ++i) { - _ptr_platforms[i] = new pyopencl::platform(platforms[i]); - } - *ptr_platforms = _ptr_platforms; - ); return 0; } -void _free(void *p) { - free(p); -} -void _free2(void **p, uint32_t size) { - for(uint32_t i = 0; i < size; ++i) { - _free(p[i]); +::error *_create_context( + void **ptr_ctx, + cl_context_properties *properties, + cl_uint num_devices, + void **ptr_devices) +{ + BEGIN_C_HANDLE_ERROR + + cl_int status_code; + std::vector<cl_device_id> devices(num_devices); + for(cl_uint i = 0; i < num_devices; ++i) { + devices[i] = static_cast<pyopencl::device*>(ptr_devices[i])->data(); } -} + cl_context ctx = clCreateContext(properties, + num_devices, + devices.empty() ? NULL : &devices.front(), + 0, 0, &status_code); + if (status_code != CL_SUCCESS) { + throw pyopencl::error("Context", status_code); + } + *ptr_ctx = new pyopencl::context(ctx, false); + END_C_HANDLE_ERROR -::error *platform__get_devices(void *ptr_platform, void **ptr_devices, uint32_t *num_devices, cl_device_type devtype) { - typedef std::vector<cl_device_id> vec; - C_HANDLE_ERROR(vec devices = static_cast<pyopencl::platform*>(ptr_platform)->get_devices(devtype); - *num_devices = devices.size(); - - MALLOC(pyopencl::device*, _ptr_devices, *num_devices); - for(vec::size_type i = 0; i < devices.size(); ++i) { - _ptr_devices[i] = new pyopencl::device(devices[i]); - } - *ptr_devices = _ptr_devices; - ); return 0; } -::error *_create_context(void **ptr_ctx, cl_context_properties *properties, cl_uint num_devices, void **ptr_devices) { - C_HANDLE_ERROR( - cl_int status_code; - std::vector<cl_device_id> devices(num_devices); - for(cl_uint i = 0; i < num_devices; ++i) { - devices[i] = static_cast<pyopencl::device*>(ptr_devices[i])->data(); - } - cl_context ctx = clCreateContext(properties, - num_devices, - devices.empty() ? NULL : &devices.front(), - 0, 0, &status_code); - if (status_code != CL_SUCCESS) { - throw pyopencl::error("Context", status_code); - } - *ptr_ctx = new pyopencl::context(ctx, false); - ); - return 0; -} - -::error *_create_command_queue(void **ptr_command_queue, void *ptr_context, void *ptr_device, cl_command_queue_properties properties) { +::error *_create_command_queue( + void **ptr_command_queue, void *ptr_context, void *ptr_device, cl_command_queue_properties properties) +{ pyopencl::context *ctx = static_cast<pyopencl::context*>(ptr_context); pyopencl::device *dev = static_cast<pyopencl::device*>(ptr_device); - C_HANDLE_ERROR( - *ptr_command_queue = new pyopencl::command_queue(*ctx, dev, properties); - ); + BEGIN_C_HANDLE_ERROR + + *ptr_command_queue = new pyopencl::command_queue(*ctx, dev, properties); + + END_C_HANDLE_ERROR + return 0; } -::error *_create_buffer(void **ptr_buffer, void *ptr_context, cl_mem_flags flags, size_t size, void *hostbuf) { + +::error *_create_buffer( + void **ptr_buffer, void *ptr_context, cl_mem_flags flags, + size_t size, void *hostbuf) +{ pyopencl::context *ctx = static_cast<pyopencl::context*>(ptr_context); - C_HANDLE_ERROR( - *ptr_buffer = create_buffer_py(*ctx, flags, size, hostbuf); - ); + + BEGIN_C_HANDLE_ERROR + + *ptr_buffer = create_buffer_py(*ctx, flags, size, hostbuf); + + END_C_HANDLE_ERROR return 0; } -::error *_create_program_with_source(void **ptr_program, void *ptr_context, char *src) { +// {{{ program + +::error *_create_program_with_source(void **ptr_program, void *ptr_context, char *src) +{ pyopencl::context *ctx = static_cast<pyopencl::context*>(ptr_context); - C_HANDLE_ERROR( + + BEGIN_C_HANDLE_ERROR + *ptr_program = create_program_with_source(*ctx, src); - ); + + END_C_HANDLE_ERROR + return 0; } -::error *_create_program_with_binary(void **ptr_program, void *ptr_context, cl_uint num_devices, void **ptr_devices, cl_uint num_binaries, char **binaries, size_t *binary_sizes) { +::error *_create_program_with_binary( + void **ptr_program, void *ptr_context, cl_uint num_devices, void **ptr_devices, cl_uint num_binaries, char **binaries, size_t *binary_sizes) +{ pyopencl::context *ctx = static_cast<pyopencl::context*>(ptr_context); - C_HANDLE_ERROR( - *ptr_program = create_program_with_binary(*ctx, num_devices, ptr_devices, num_binaries, reinterpret_cast<char **>(binaries), binary_sizes); - ); + + BEGIN_C_HANDLE_ERROR + + *ptr_program = create_program_with_binary(*ctx, num_devices, ptr_devices, num_binaries, reinterpret_cast<char **>(binaries), binary_sizes); + + END_C_HANDLE_ERROR + return 0; } -::error *program__build(void *ptr_program, char *options, cl_uint num_devices, void **ptr_devices) { - C_HANDLE_ERROR( - static_cast<pyopencl::program*>(ptr_program)->build(options, num_devices, ptr_devices); - ); +::error *program__build( + void *ptr_program, char *options, cl_uint num_devices, void **ptr_devices) +{ + + BEGIN_C_HANDLE_ERROR + + static_cast<pyopencl::program*>(ptr_program)->build(options, num_devices, ptr_devices); + + END_C_HANDLE_ERROR + return 0; } -::error *program__kind(void *ptr_program, int *kind) { - C_HANDLE_ERROR( - *kind = static_cast<pyopencl::program*>(ptr_program)->kind(); - ); +::error *program__kind(void *ptr_program, int *kind) +{ + BEGIN_C_HANDLE_ERROR + + *kind = static_cast<pyopencl::program*>(ptr_program)->kind(); + + END_C_HANDLE_ERROR + return 0; } -::error *program__get_build_info(void *ptr_program, void *ptr_device, cl_program_build_info param, generic_info *out) { - C_HANDLE_ERROR( - *out = static_cast<pyopencl::program*>(ptr_program)->get_build_info(*static_cast<pyopencl::device*>(ptr_device), - param); - ); +::error *program__get_build_info( + void *ptr_program, void *ptr_device, cl_program_build_info param, generic_info *out) +{ + BEGIN_C_HANDLE_ERROR + + *out = static_cast<pyopencl::program*>(ptr_program) + ->get_build_info( + *static_cast<pyopencl::device*>(ptr_device), + param); + + END_C_HANDLE_ERROR + return 0; } -::error *_create_sampler(void **ptr_sampler, void *ptr_context, int normalized_coordinates, cl_addressing_mode am, cl_filter_mode fm) { - C_HANDLE_ERROR(*ptr_sampler = new pyopencl::sampler(*static_cast<pyopencl::context*>(ptr_context), (bool)normalized_coordinates, am, fm);); +// }}} + + +::error *_create_sampler( + void **ptr_sampler, void *ptr_context, int normalized_coordinates, + cl_addressing_mode am, cl_filter_mode fm) +{ + BEGIN_C_HANDLE_ERROR + + *ptr_sampler = new pyopencl::sampler( + *static_cast<pyopencl::context*>(ptr_context), + (bool)normalized_coordinates, am, fm); + + END_C_HANDLE_ERROR + return 0; } -::error *event__get_profiling_info(void *ptr, cl_profiling_info param, generic_info *out) { - C_HANDLE_ERROR(*out = static_cast<pyopencl::event*>(ptr)->get_profiling_info(param);); +// {{{ event + +::error *event__get_profiling_info( + void *ptr, cl_profiling_info param, generic_info *out) +{ + BEGIN_C_HANDLE_ERROR + + *out = static_cast<pyopencl::event*>(ptr)->get_profiling_info(param); + + END_C_HANDLE_ERROR + return 0; } -::error *event__wait(void *ptr) { - C_HANDLE_ERROR(static_cast<pyopencl::event*>(ptr)->wait();); +::error *event__wait(void *ptr) +{ + BEGIN_C_HANDLE_ERROR + + static_cast<pyopencl::event*>(ptr)->wait(); + + END_C_HANDLE_ERROR + return 0; } +// }}} + + +// {{{ kernel + ::error *_create_kernel(void **ptr_kernel, void *ptr_program, char *name) { pyopencl::program *prg = static_cast<pyopencl::program*>(ptr_program); - C_HANDLE_ERROR( - *ptr_kernel = new pyopencl::kernel(*prg, name); - ); + + BEGIN_C_HANDLE_ERROR + + *ptr_kernel = new pyopencl::kernel(*prg, name); + + END_C_HANDLE_ERROR + return 0; } -::error *kernel__set_arg_null(void *ptr_kernel, cl_uint arg_index) { - C_HANDLE_ERROR(static_cast<pyopencl::kernel*>(ptr_kernel)->set_arg_null(arg_index);); +::error *kernel__set_arg_null(void *ptr_kernel, cl_uint arg_index) +{ + BEGIN_C_HANDLE_ERROR + + static_cast<pyopencl::kernel*>(ptr_kernel)->set_arg_null(arg_index); + + END_C_HANDLE_ERROR + return 0; } -::error *kernel__set_arg_mem(void *ptr_kernel, cl_uint arg_index, void *ptr_mem) { - pyopencl::memory_object_holder *mem = static_cast<pyopencl::memory_object_holder*>(ptr_mem); - C_HANDLE_ERROR(static_cast<pyopencl::kernel*>(ptr_kernel)->set_arg_mem(arg_index, *mem);); +::error *kernel__set_arg_mem(void *ptr_kernel, cl_uint arg_index, void *ptr_mem) +{ + pyopencl::memory_object_holder *mem = + static_cast<pyopencl::memory_object_holder*>(ptr_mem); + + BEGIN_C_HANDLE_ERROR + + static_cast<pyopencl::kernel*>(ptr_kernel)->set_arg_mem(arg_index, *mem); + + END_C_HANDLE_ERROR + return 0; } ::error *kernel__set_arg_sampler(void *ptr_kernel, cl_uint arg_index, void *ptr_sampler) { pyopencl::sampler *sampler = static_cast<pyopencl::sampler*>(ptr_sampler); - C_HANDLE_ERROR(static_cast<pyopencl::kernel*>(ptr_kernel)->set_arg_sampler(arg_index, *sampler);); + + BEGIN_C_HANDLE_ERROR + + static_cast<pyopencl::kernel*>(ptr_kernel)->set_arg_sampler(arg_index, *sampler); + + END_C_HANDLE_ERROR + return 0; } -::error *kernel__set_arg_buf(void *ptr_kernel, cl_uint arg_index, void *buffer, size_t size) { - C_HANDLE_ERROR(static_cast<pyopencl::kernel*>(ptr_kernel)->set_arg_buf(arg_index, buffer, size);); +::error *kernel__set_arg_buf( + void *ptr_kernel, cl_uint arg_index, void *buffer, size_t size) +{ + BEGIN_C_HANDLE_ERROR + + static_cast<pyopencl::kernel*>(ptr_kernel)->set_arg_buf(arg_index, buffer, size); + + END_C_HANDLE_ERROR + return 0; } -::error *kernel__get_work_group_info(void *ptr, cl_kernel_work_group_info param, void *ptr_device, generic_info *out) { - C_HANDLE_ERROR(*out = static_cast<pyopencl::kernel*>(ptr)->get_work_group_info(param, *static_cast<pyopencl::device*>(ptr_device));); +::error *kernel__get_work_group_info( + void *ptr, cl_kernel_work_group_info param, void *ptr_device, generic_info *out) +{ + BEGIN_C_HANDLE_ERROR + + *out = static_cast<pyopencl::kernel*>(ptr)->get_work_group_info(param, *static_cast<pyopencl::device*>(ptr_device)); + + END_C_HANDLE_ERROR + return 0; } -::error *_get_supported_image_formats(void *ptr_context, cl_mem_flags flags, cl_mem_object_type image_type, generic_info *out) { - C_HANDLE_ERROR(*out = get_supported_image_formats(*static_cast<pyopencl::context*>(ptr_context), flags, image_type);); +// }}} + + +// {{{ image + +::error *_get_supported_image_formats( + void *ptr_context, cl_mem_flags flags, cl_mem_object_type image_type, generic_info *out) +{ + BEGIN_C_HANDLE_ERROR + + *out = get_supported_image_formats(*static_cast<pyopencl::context*>(ptr_context), flags, image_type); + + END_C_HANDLE_ERROR + return 0; } -error *_create_image_2d(void **ptr_image, void *ptr_context, cl_mem_flags flags, cl_image_format *fmt, size_t width, size_t height, size_t pitch, void *ptr_buffer, size_t size) { - C_HANDLE_ERROR(*ptr_image = create_image_2d(*static_cast<pyopencl::context*>(ptr_context), flags, *fmt, width, height, pitch, ptr_buffer, size);); +error *_create_image_2d( + void **ptr_image, void *ptr_context, cl_mem_flags flags, + cl_image_format *fmt, size_t width, size_t height, size_t pitch, + void *ptr_buffer, size_t size) +{ + BEGIN_C_HANDLE_ERROR + + *ptr_image = create_image_2d( + *static_cast<pyopencl::context*>(ptr_context), flags, *fmt, + width, height, pitch, ptr_buffer, size); + + END_C_HANDLE_ERROR + return 0; } -error *_create_image_3d(void **ptr_image, void *ptr_context, cl_mem_flags flags, cl_image_format *fmt, size_t width, size_t height, size_t depth, size_t pitch_x, size_t pitch_y, void *ptr_buffer, size_t size) { - C_HANDLE_ERROR(*ptr_image = create_image_3d(*static_cast<pyopencl::context*>(ptr_context), flags, *fmt, width, height, depth, pitch_x, pitch_y, ptr_buffer, size);); +error *_create_image_3d( + void **ptr_image, void *ptr_context, cl_mem_flags flags, + cl_image_format *fmt, size_t width, size_t height, size_t depth, + size_t pitch_x, size_t pitch_y, void *ptr_buffer, size_t size) +{ + BEGIN_C_HANDLE_ERROR + + *ptr_image = create_image_3d( + *static_cast<pyopencl::context*>(ptr_context), + flags, *fmt, width, height, depth, pitch_x, pitch_y, ptr_buffer, size); + + END_C_HANDLE_ERROR + return 0; } -::error *image__get_image_info(void *ptr, cl_image_info param, generic_info *out) { - C_HANDLE_ERROR(*out = static_cast<pyopencl::image*>(ptr)->get_image_info(param);); + +::error *image__get_image_info(void *ptr, cl_image_info param, generic_info *out) +{ + BEGIN_C_HANDLE_ERROR + + *out = static_cast<pyopencl::image*>(ptr)->get_image_info(param); + + END_C_HANDLE_ERROR + return 0; } +// }}} + + +::error *_enqueue_nd_range_kernel( + void **ptr_event, void *ptr_command_queue, void *ptr_kernel, + cl_uint work_dim, const size_t *global_work_offset, + const size_t *global_work_size, const size_t *local_work_size) +{ + BEGIN_C_HANDLE_ERROR + + *ptr_event = enqueue_nd_range_kernel( + *static_cast<pyopencl::command_queue*>(ptr_command_queue), + *static_cast<pyopencl::kernel*>(ptr_kernel), + work_dim, + global_work_offset, + global_work_size, + local_work_size); + + END_C_HANDLE_ERROR -::error *_enqueue_nd_range_kernel(void **ptr_event, void *ptr_command_queue, void *ptr_kernel, cl_uint work_dim, const size_t *global_work_offset, const size_t *global_work_size, const size_t *local_work_size) { - C_HANDLE_ERROR( - *ptr_event = enqueue_nd_range_kernel(*static_cast<pyopencl::command_queue*>(ptr_command_queue), - *static_cast<pyopencl::kernel*>(ptr_kernel), - work_dim, - global_work_offset, - global_work_size, - local_work_size); - ); return 0; } +// {{{ transfer enqueues + +::error *_enqueue_read_buffer( + void **ptr_event, void *ptr_command_queue, void *ptr_memory_object_holder, + void *buffer, size_t size, size_t device_offset, void **wait_for, + uint32_t num_wait_for, int is_blocking) +{ + BEGIN_C_HANDLE_ERROR + + *ptr_event = enqueue_read_buffer( + *static_cast<pyopencl::command_queue*>(ptr_command_queue), + *static_cast<pyopencl::memory_object_holder*>(ptr_memory_object_holder), + buffer, size, device_offset, wait_for, num_wait_for, (bool)is_blocking); + + END_C_HANDLE_ERROR -::error *_enqueue_read_buffer(void **ptr_event, void *ptr_command_queue, void *ptr_memory_object_holder, void *buffer, size_t size, size_t device_offset, void **wait_for, uint32_t num_wait_for, int is_blocking) { - C_HANDLE_ERROR(*ptr_event = enqueue_read_buffer(*static_cast<pyopencl::command_queue*>(ptr_command_queue), - *static_cast<pyopencl::memory_object_holder*>(ptr_memory_object_holder), - buffer, size, device_offset, wait_for, num_wait_for, (bool)is_blocking); - ); return 0; } -::error *_enqueue_write_buffer(void **ptr_event, void *ptr_command_queue, void *ptr_mem, void *buffer, size_t size, size_t device_offset, void **wait_for, uint32_t num_wait_for, int is_blocking) { - C_HANDLE_ERROR(*ptr_event = enqueue_write_buffer(*static_cast<pyopencl::command_queue*>(ptr_command_queue), - *static_cast<pyopencl::memory_object_holder*>(ptr_mem), - buffer, size, device_offset, wait_for, num_wait_for, (bool)is_blocking); - ); + + +::error *_enqueue_write_buffer( + void **ptr_event, void *ptr_command_queue, void *ptr_mem, + void *buffer, size_t size, size_t device_offset, void **wait_for, + uint32_t num_wait_for, int is_blocking) +{ + BEGIN_C_HANDLE_ERROR + + *ptr_event = enqueue_write_buffer( + *static_cast<pyopencl::command_queue*>(ptr_command_queue), + *static_cast<pyopencl::memory_object_holder*>(ptr_mem), + buffer, size, device_offset, wait_for, num_wait_for, (bool)is_blocking); + + END_C_HANDLE_ERROR + return 0; } -::error *_enqueue_copy_buffer(void **ptr_event, void *ptr_command_queue, void *ptr_src, void *ptr_dst, ptrdiff_t byte_count, size_t src_offset, size_t dst_offset, void **wait_for, uint32_t num_wait_for) { - C_HANDLE_ERROR(*ptr_event = enqueue_copy_buffer(*static_cast<pyopencl::command_queue*>(ptr_command_queue), - *static_cast<pyopencl::memory_object_holder*>(ptr_src), - *static_cast<pyopencl::memory_object_holder*>(ptr_dst), - byte_count, src_offset, dst_offset, wait_for, num_wait_for); - ); + +::error *_enqueue_copy_buffer( + void **ptr_event, void *ptr_command_queue, void *ptr_src, + void *ptr_dst, ptrdiff_t byte_count, size_t src_offset, size_t dst_offset, + void **wait_for, uint32_t num_wait_for) +{ + BEGIN_C_HANDLE_ERROR + + *ptr_event = enqueue_copy_buffer( + *static_cast<pyopencl::command_queue*>(ptr_command_queue), + *static_cast<pyopencl::memory_object_holder*>(ptr_src), + *static_cast<pyopencl::memory_object_holder*>(ptr_dst), + byte_count, src_offset, dst_offset, wait_for, num_wait_for); + + END_C_HANDLE_ERROR + return 0; } -::error *_enqueue_read_image(void **ptr_event, void *ptr_command_queue, void *ptr_mem, size_t *origin, size_t *region, void *buffer, size_t size, size_t row_pitch, size_t slice_pitch, void **wait_for, uint32_t num_wait_for, int is_blocking) { - C_HANDLE_ERROR(*ptr_event = enqueue_read_image(*static_cast<pyopencl::command_queue*>(ptr_command_queue), - *static_cast<pyopencl::image*>(ptr_mem), - origin, region, buffer, size, row_pitch, slice_pitch, wait_for, num_wait_for, (bool)is_blocking); - ); + +::error *_enqueue_read_image( + void **ptr_event, void *ptr_command_queue, void *ptr_mem, + size_t *origin, size_t *region, void *buffer, size_t size, size_t row_pitch, + size_t slice_pitch, void **wait_for, uint32_t num_wait_for, int is_blocking) +{ + BEGIN_C_HANDLE_ERROR + + *ptr_event = enqueue_read_image( + *static_cast<pyopencl::command_queue*>(ptr_command_queue), + *static_cast<pyopencl::image*>(ptr_mem), + origin, region, buffer, size, row_pitch, slice_pitch, wait_for, num_wait_for, + (bool)is_blocking); + + END_C_HANDLE_ERROR + return 0; } +// }}} + intptr_t _int_ptr(void* ptr, class_t class_) { #define INT_PTR(CLSU, CLS) return (intptr_t)(static_cast<pyopencl::CLS*>(ptr)->data()); SWITCHCLASS(INT_PTR); } + void* _from_int_ptr(void **ptr_out, intptr_t int_ptr_value, class_t class_) { -#define FROM_INT_PTR(CLSU, CLS) C_HANDLE_ERROR(*ptr_out = new pyopencl::CLS((PYOPENCL_CL_##CLSU)int_ptr_value, /* retain */ true);) +#define FROM_INT_PTR(CLSU, CLS) \ + BEGIN_C_HANDLE_ERROR \ + *ptr_out = new pyopencl::CLS((PYOPENCL_CL_##CLSU)int_ptr_value, /* retain */ true); \ + END_C_HANDLE_ERROR + SWITCHCLASS(FROM_INT_PTR); return 0; } + long _hash(void *ptr, class_t class_) { #define HASH(CLSU, CLS) return static_cast<pyopencl::CLS*>(ptr)->hash(); SWITCHCLASS(HASH); @@ -3036,7 +3321,11 @@ long _hash(void *ptr, class_t class_) { ::error *_get_info(void *ptr, class_t class_, cl_uint param, generic_info *out) { -#define GET_INFO(CLSU, CLS) C_HANDLE_ERROR(*out = static_cast<pyopencl::CLS*>(ptr)->get_info(param);) +#define GET_INFO(CLSU, CLS) \ + BEGIN_C_HANDLE_ERROR \ + *out = static_cast<pyopencl::CLS*>(ptr)->get_info(param); \ + END_C_HANDLE_ERROR + SWITCHCLASS(GET_INFO); return 0; } @@ -3051,11 +3340,8 @@ int get_cl_version(void) { return PYOPENCL_CL_VERSION; } -unsigned bitlog2(unsigned long v) { - return pyopencl::bitlog2(v); -} - // {{{ gl interop + int have_gl() { #ifdef HAVE_GL return 1; @@ -3064,35 +3350,73 @@ int have_gl() { #endif } -error *_create_from_gl_buffer(void **ptr, void *ptr_context, cl_mem_flags flags, GLuint bufobj) { + +error *_create_from_gl_buffer( + void **ptr, void *ptr_context, cl_mem_flags flags, GLuint bufobj) +{ pyopencl::context *ctx = static_cast<pyopencl::context*>(ptr_context); - C_HANDLE_ERROR(*ptr = create_from_gl_buffer(*ctx, flags, bufobj);); + + BEGIN_C_HANDLE_ERROR + + *ptr = create_from_gl_buffer(*ctx, flags, bufobj); + + END_C_HANDLE_ERROR + return 0; } -error *_create_from_gl_renderbuffer(void **ptr, void *ptr_context, cl_mem_flags flags, GLuint bufobj) { + +error *_create_from_gl_renderbuffer( + void **ptr, void *ptr_context, cl_mem_flags flags, GLuint bufobj) +{ pyopencl::context *ctx = static_cast<pyopencl::context*>(ptr_context); - C_HANDLE_ERROR(*ptr = create_from_gl_renderbuffer(*ctx, flags, bufobj);); + + BEGIN_C_HANDLE_ERROR + + *ptr = create_from_gl_renderbuffer(*ctx, flags, bufobj); + + END_C_HANDLE_ERROR + return 0; } -::error *_enqueue_acquire_gl_objects(void **ptr_event, void *ptr_command_queue, void **ptr_mem_objects, uint32_t num_mem_objects, void **wait_for, uint32_t num_wait_for) { - C_HANDLE_ERROR( - *ptr_event = enqueue_acquire_gl_objects(*static_cast<pyopencl::command_queue*>(ptr_command_queue), - ptr_mem_objects, num_mem_objects, - wait_for, num_wait_for); - ); + +::error *_enqueue_acquire_gl_objects( + void **ptr_event, void *ptr_command_queue, + void **ptr_mem_objects, uint32_t num_mem_objects, void **wait_for, + uint32_t num_wait_for) +{ + BEGIN_C_HANDLE_ERROR + + *ptr_event = enqueue_acquire_gl_objects( + *static_cast<pyopencl::command_queue*>(ptr_command_queue), + ptr_mem_objects, num_mem_objects, + wait_for, num_wait_for); + + END_C_HANDLE_ERROR + return 0; } -::error *_enqueue_release_gl_objects(void **ptr_event, void *ptr_command_queue, void **ptr_mem_objects, uint32_t num_mem_objects, void **wait_for, uint32_t num_wait_for) { - C_HANDLE_ERROR( - *ptr_event = enqueue_release_gl_objects(*static_cast<pyopencl::command_queue*>(ptr_command_queue), - ptr_mem_objects, num_mem_objects, - wait_for, num_wait_for); - ); + +::error *_enqueue_release_gl_objects( + void **ptr_event, void *ptr_command_queue, void **ptr_mem_objects, + uint32_t num_mem_objects, void **wait_for, uint32_t num_wait_for) +{ + BEGIN_C_HANDLE_ERROR + + *ptr_event = enqueue_release_gl_objects( + *static_cast<pyopencl::command_queue*>(ptr_command_queue), + ptr_mem_objects, num_mem_objects, + wait_for, num_wait_for); + + END_C_HANDLE_ERROR + return 0; } +// }}} // }}} + +// vim: foldmethod=marker diff --git a/src/wrapper/_pvt_struct_v2.cpp b/src/wrapper/_pvt_struct_v2.cpp deleted file mode 100644 index 23a40781..00000000 --- a/src/wrapper/_pvt_struct_v2.cpp +++ /dev/null @@ -1,1613 +0,0 @@ -/* struct module -- pack values into and (out of) strings */ - -/* New version supporting byte order, alignment and size options, - character strings, and unsigned numbers */ - -/* Compared with vanilla Python's struct module, this adds support - * for packing complex values and only supports native packing. - * (the minimum that's needed for PyOpenCL.) */ - -#define PY_SSIZE_T_CLEAN - -#include "Python.h" -#include "structseq.h" -#include "structmember.h" -#include <ctype.h> -#include "numpy_init.hpp" - -// static PyTypeObject PyStructType; - -/* compatibility macros */ -#if (PY_VERSION_HEX < 0x02050000) -#ifndef PY_SSIZE_T_MIN -typedef long int Py_ssize_t; -#endif - -#define PyInt_FromSsize_t(x) PyInt_FromLong(x) -#define PyInt_AsSsize_t(x) PyInt_AsLong(x) -#endif - -/* If PY_STRUCT_FLOAT_COERCE is defined, the struct module will allow float - arguments for integer formats with a warning for backwards - compatibility. */ - -#define PY_STRUCT_FLOAT_COERCE 1 - -#ifdef PY_STRUCT_FLOAT_COERCE -#define FLOAT_COERCE "integer argument expected, got float" -#endif - -/* Compatibility with Py2.5 and older */ - -#ifndef Py_TYPE -# define Py_TYPE(o) ((o)->ob_type) -#endif - -#ifndef PyVarObject_HEAD_INIT -#define PyVarObject_HEAD_INIT(type, size) \ - PyObject_HEAD_INIT(type) size, -#endif - -#ifndef SIZEOF_SIZE_T -#define SIZEOF_SIZE_T sizeof(size_t) -#endif - -#ifndef PY_SSIZE_T_MAX -#define PY_SSIZE_T_MAX LONG_MAX -#endif - -/* The translation function for each format character is table driven */ -typedef struct _formatdef { - char format; - Py_ssize_t size; - Py_ssize_t alignment; - PyObject* (*unpack)(const char *, - const struct _formatdef *); - int (*pack)(char *, PyObject *, - const struct _formatdef *); -} formatdef; - -typedef struct _formatcode { - const struct _formatdef *fmtdef; - Py_ssize_t offset; - Py_ssize_t size; -} formatcode; - -/* Struct object interface */ - -typedef struct { - PyObject_HEAD - Py_ssize_t s_size; - Py_ssize_t s_len; - formatcode *s_codes; - PyObject *s_format; - PyObject *weakreflist; /* List of weak references */ -} PyStructObject; - - -#define PyStruct_Check(op) PyObject_TypeCheck(op, &PyStructType) -#define PyStruct_CheckExact(op) (Py_TYPE(op) == &PyStructType) - - -/* Exception */ - -static PyObject *StructError; - - -/* Define various structs to figure out the alignments of types */ - - -typedef struct { char c; short x; } st_short; -typedef struct { char c; int x; } st_int; -typedef struct { char c; long x; } st_long; -typedef struct { char c; float x; } st_float; -typedef struct { char c; double x; } st_double; -typedef struct { char c; void *x; } st_void_p; - -#define SHORT_ALIGN (sizeof(st_short) - sizeof(short)) -#define INT_ALIGN (sizeof(st_int) - sizeof(int)) -#define LONG_ALIGN (sizeof(st_long) - sizeof(long)) -#define FLOAT_ALIGN (sizeof(st_float) - sizeof(float)) -#define DOUBLE_ALIGN (sizeof(st_double) - sizeof(double)) -#define VOID_P_ALIGN (sizeof(st_void_p) - sizeof(void *)) - -/* We can't support q and Q in native mode unless the compiler does; - in std mode, they're 8 bytes on all platforms. */ -#ifdef HAVE_LONG_LONG -typedef struct { char c; PY_LONG_LONG x; } s_long_long; -#define LONG_LONG_ALIGN (sizeof(s_long_long) - sizeof(PY_LONG_LONG)) -#endif - -#define BOOL_TYPE bool -typedef struct { char c; bool x; } s_bool; -#define BOOL_ALIGN (sizeof(s_bool) - sizeof(BOOL_TYPE)) - -#define STRINGIFY(x) #x - -#ifdef __powerc -#pragma options align=reset -#endif - -static char *integer_codes = "bBhHiIlLqQ"; - -static void s_dealloc(PyStructObject *s); -static int s_init(PyObject *self, PyObject *args, PyObject *kwds); -static PyObject *s_new(PyTypeObject *type, PyObject *args, PyObject *kwds); -static PyObject *s_pack(PyObject *self, PyObject *args); -static PyObject *s_pack_into(PyObject *self, PyObject *args); -static PyObject *s_unpack(PyObject *self, PyObject *inputstr); -static PyObject *s_unpack_from(PyObject *self, PyObject *args, PyObject *kwds); -static PyObject *s_get_format(PyStructObject *self, void *unused); -static PyObject *s_get_size(PyStructObject *self, void *unused); - -PyDoc_STRVAR(s__doc__, "Compiled struct object"); - -/* List of functions */ - -PyDoc_STRVAR(s_pack__doc__, -"S.pack(v1, v2, ...) -> string\n\ -\n\ -Return a string containing values v1, v2, ... packed according to this\n\ -Struct's format. See struct.__doc__ for more on format strings."); - -PyDoc_STRVAR(s_pack_into__doc__, -"S.pack_into(buffer, offset, v1, v2, ...)\n\ -\n\ -Pack the values v1, v2, ... according to this Struct's format, write \n\ -the packed bytes into the writable buffer buf starting at offset. Note\n\ -that the offset is not an optional argument. See struct.__doc__ for \n\ -more on format strings."); - -PyDoc_STRVAR(s_unpack__doc__, -"S.unpack(str) -> (v1, v2, ...)\n\ -\n\ -Return tuple containing values unpacked according to this Struct's format.\n\ -Requires len(str) == self.size. See struct.__doc__ for more on format\n\ -strings."); - -PyDoc_STRVAR(s_unpack_from__doc__, -"S.unpack_from(buffer[, offset]) -> (v1, v2, ...)\n\ -\n\ -Return tuple containing values unpacked according to this Struct's format.\n\ -Unlike unpack, unpack_from can unpack values from any object supporting\n\ -the buffer API, not just str. Requires len(buffer[offset:]) >= self.size.\n\ -See struct.__doc__ for more on format strings."); - - -static struct PyMethodDef s_methods[] = { - {"pack", s_pack, METH_VARARGS, s_pack__doc__}, - {"pack_into", s_pack_into, METH_VARARGS, s_pack_into__doc__}, - {"unpack", s_unpack, METH_O, s_unpack__doc__}, - {"unpack_from", (PyCFunction)s_unpack_from, METH_VARARGS|METH_KEYWORDS, - s_unpack_from__doc__}, - {NULL, NULL} /* sentinel */ -}; - -#define OFF(x) offsetof(PyStructObject, x) - -static PyGetSetDef s_getsetlist[] = { - {"format", (getter)s_get_format, (setter)NULL, "struct format string", NULL}, - {"size", (getter)s_get_size, (setter)NULL, "struct size in bytes", NULL}, - {NULL} /* sentinel */ -}; - -static -PyTypeObject PyStructType = { - PyVarObject_HEAD_INIT(NULL, 0) - "Struct", - sizeof(PyStructObject), - 0, - (destructor)s_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_compare */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - PyObject_GenericSetAttr, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_WEAKREFS,/* tp_flags */ - s__doc__, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - offsetof(PyStructObject, weakreflist), /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - s_methods, /* tp_methods */ - NULL, /* tp_members */ - s_getsetlist, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - s_init, /* tp_init */ - PyType_GenericAlloc,/* tp_alloc */ - s_new, /* tp_new */ - PyObject_Del, /* tp_free */ -}; - -/* Helper to get a PyLongObject by hook or by crook. Caller should decref. */ - -static PyObject * -get_pylong(PyObject *v) -{ - PyNumberMethods *m; - - assert(v != NULL); - if (PyInt_Check(v)) - return PyLong_FromLong(PyInt_AS_LONG(v)); - if (PyLong_Check(v)) { - Py_INCREF(v); - return v; - } - - m = Py_TYPE(v)->tp_as_number; - if (m != NULL && m->nb_long != NULL) { - v = m->nb_long(v); - if (v == NULL) - return NULL; - if (PyLong_Check(v)) - return v; - Py_DECREF(v); - } - - PyErr_SetString(StructError, - "cannot convert argument to long"); - return NULL; -} - -/* Helper to convert a Python object to a C long. Sets an exception - (struct.error for an inconvertible type, OverflowError for - out-of-range values) and returns -1 on error. */ - -static int -get_long(PyObject *v, long *p) -{ - long x; - - v = get_pylong(v); - if (v == NULL) - return -1; - assert(PyLong_Check(v)); - x = PyLong_AsLong(v); - Py_DECREF(v); - if (x == (long)-1 && PyErr_Occurred()) - return -1; - *p = x; - return 0; -} - -/* Same, but handling unsigned long */ - -static int -get_ulong(PyObject *v, unsigned long *p) -{ - unsigned long x; - - v = get_pylong(v); - if (v == NULL) - return -1; - assert(PyLong_Check(v)); - x = PyLong_AsUnsignedLong(v); - Py_DECREF(v); - if (x == (unsigned long)-1 && PyErr_Occurred()) - return -1; - *p = x; - return 0; -} - -#ifdef HAVE_LONG_LONG - -/* Same, but handling native long long. */ - -static int -get_longlong(PyObject *v, PY_LONG_LONG *p) -{ - PY_LONG_LONG x; - - v = get_pylong(v); - if (v == NULL) - return -1; - assert(PyLong_Check(v)); - x = PyLong_AsLongLong(v); - Py_DECREF(v); - if (x == (PY_LONG_LONG)-1 && PyErr_Occurred()) - return -1; - *p = x; - return 0; -} - -/* Same, but handling native unsigned long long. */ - -static int -get_ulonglong(PyObject *v, unsigned PY_LONG_LONG *p) -{ - unsigned PY_LONG_LONG x; - - v = get_pylong(v); - if (v == NULL) - return -1; - assert(PyLong_Check(v)); - x = PyLong_AsUnsignedLongLong(v); - Py_DECREF(v); - if (x == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred()) - return -1; - *p = x; - return 0; -} - -#endif - -#if (SIZEOF_LONG > SIZEOF_INT) - -/* Helper to format the range error exceptions */ -static int -_range_error(const formatdef *f, int is_unsigned) -{ - /* ulargest is the largest unsigned value with f->size bytes. - * Note that the simpler: - * ((size_t)1 << (f->size * 8)) - 1 - * doesn't work when f->size == sizeof(size_t) because C doesn't - * define what happens when a left shift count is >= the number of - * bits in the integer being shifted; e.g., on some boxes it doesn't - * shift at all when they're equal. - */ - const size_t ulargest = (size_t)-1 >> ((SIZEOF_SIZE_T - f->size)*8); - assert(f->size >= 1 && f->size <= SIZEOF_SIZE_T); - if (is_unsigned) - PyErr_Format(StructError, - "'%c' format requires 0 <= number <= %zu", - f->format, - ulargest); - else { - const Py_ssize_t largest = (Py_ssize_t)(ulargest >> 1); - PyErr_Format(StructError, - "'%c' format requires %zd <= number <= %zd", - f->format, - ~ largest, - largest); - } - return -1; -} - -#endif - - -/* A large number of small routines follow, with names of the form - - [bln][up]_TYPE - - [bln] distiguishes among big-endian, little-endian and native. - [pu] distiguishes between pack (to struct) and unpack (from struct). - TYPE is one of char, byte, ubyte, etc. -*/ - -/* Native mode routines. ****************************************************/ -/* NOTE: - In all n[up]_<type> routines handling types larger than 1 byte, there is - *no* guarantee that the p pointer is properly aligned for each type, - therefore memcpy is called. An intermediate variable is used to - compensate for big-endian architectures. - Normally both the intermediate variable and the memcpy call will be - skipped by C optimisation in little-endian architectures (gcc >= 2.91 - does this). */ - -static PyObject * -nu_char(const char *p, const formatdef *f) -{ - return PyString_FromStringAndSize(p, 1); -} - -static PyObject * -nu_byte(const char *p, const formatdef *f) -{ - return PyInt_FromLong((long) *(signed char *)p); -} - -static PyObject * -nu_ubyte(const char *p, const formatdef *f) -{ - return PyInt_FromLong((long) *(unsigned char *)p); -} - -static PyObject * -nu_short(const char *p, const formatdef *f) -{ - short x; - memcpy((char *)&x, p, sizeof x); - return PyInt_FromLong((long)x); -} - -static PyObject * -nu_ushort(const char *p, const formatdef *f) -{ - unsigned short x; - memcpy((char *)&x, p, sizeof x); - return PyInt_FromLong((long)x); -} - -static PyObject * -nu_int(const char *p, const formatdef *f) -{ - int x; - memcpy((char *)&x, p, sizeof x); - return PyInt_FromLong((long)x); -} - -static PyObject * -nu_uint(const char *p, const formatdef *f) -{ - unsigned int x; - memcpy((char *)&x, p, sizeof x); -#if (SIZEOF_LONG > SIZEOF_INT) - return PyInt_FromLong((long)x); -#else - if (x <= ((unsigned int)LONG_MAX)) - return PyInt_FromLong((long)x); - return PyLong_FromUnsignedLong((unsigned long)x); -#endif -} - -static PyObject * -nu_long(const char *p, const formatdef *f) -{ - long x; - memcpy((char *)&x, p, sizeof x); - return PyInt_FromLong(x); -} - -static PyObject * -nu_ulong(const char *p, const formatdef *f) -{ - unsigned long x; - memcpy((char *)&x, p, sizeof x); - if (x <= LONG_MAX) - return PyInt_FromLong((long)x); - return PyLong_FromUnsignedLong(x); -} - -/* Native mode doesn't support q or Q unless the platform C supports - long long (or, on Windows, __int64). */ - -#ifdef HAVE_LONG_LONG - -static PyObject * -nu_longlong(const char *p, const formatdef *f) -{ - PY_LONG_LONG x; - memcpy((char *)&x, p, sizeof x); - if (x >= LONG_MIN && x <= LONG_MAX) - return PyInt_FromLong(Py_SAFE_DOWNCAST(x, PY_LONG_LONG, long)); - return PyLong_FromLongLong(x); -} - -static PyObject * -nu_ulonglong(const char *p, const formatdef *f) -{ - unsigned PY_LONG_LONG x; - memcpy((char *)&x, p, sizeof x); - if (x <= LONG_MAX) - return PyInt_FromLong(Py_SAFE_DOWNCAST(x, unsigned PY_LONG_LONG, long)); - return PyLong_FromUnsignedLongLong(x); -} - -#endif - -static PyObject * -nu_bool(const char *p, const formatdef *f) -{ - BOOL_TYPE x; - memcpy((char *)&x, p, sizeof x); - return PyBool_FromLong(x != 0); -} - - -static PyObject * -nu_float(const char *p, const formatdef *f) -{ - float x; - memcpy((char *)&x, p, sizeof x); - return PyFloat_FromDouble((double)x); -} - -static PyObject * -nu_double(const char *p, const formatdef *f) -{ - double x; - memcpy((char *)&x, p, sizeof x); - return PyFloat_FromDouble(x); -} - -static PyObject * -nu_complex_float(const char *p, const formatdef *f) -{ - float re, im; - memcpy((char *)&re, p, sizeof re); - memcpy((char *)&im, p+sizeof re, sizeof im); - return PyComplex_FromDoubles((double)re, (double) im); -} - -static PyObject * -nu_complex_double(const char *p, const formatdef *f) -{ - double re, im; - memcpy((char *)&re, p, sizeof re); - memcpy((char *)&im, p+sizeof re, sizeof im); - return PyComplex_FromDoubles(re, im); -} - -static PyObject * -nu_void_p(const char *p, const formatdef *f) -{ - void *x; - memcpy((char *)&x, p, sizeof x); - return PyLong_FromVoidPtr(x); -} - -static int -np_byte(char *p, PyObject *v, const formatdef *f) -{ - long x; - if (get_long(v, &x) < 0) - return -1; - if (x < -128 || x > 127){ - PyErr_SetString(StructError, - "byte format requires -128 <= number <= 127"); - return -1; - } - *p = (char)x; - return 0; -} - -static int -np_ubyte(char *p, PyObject *v, const formatdef *f) -{ - long x; - if (get_long(v, &x) < 0) - return -1; - if (x < 0 || x > 255){ - PyErr_SetString(StructError, - "ubyte format requires 0 <= number <= 255"); - return -1; - } - *p = (char)x; - return 0; -} - -static int -np_char(char *p, PyObject *v, const formatdef *f) -{ - if (!PyString_Check(v) || PyString_Size(v) != 1) { - PyErr_SetString(StructError, - "char format require string of length 1"); - return -1; - } - *p = *PyString_AsString(v); - return 0; -} - -static int -np_short(char *p, PyObject *v, const formatdef *f) -{ - long x; - short y; - if (get_long(v, &x) < 0) - return -1; - if (x < SHRT_MIN || x > SHRT_MAX){ - PyErr_SetString(StructError, - "short format requires " STRINGIFY(SHRT_MIN) - " <= number <= " STRINGIFY(SHRT_MAX)); - return -1; - } - y = (short)x; - memcpy(p, (char *)&y, sizeof y); - return 0; -} - -static int -np_ushort(char *p, PyObject *v, const formatdef *f) -{ - long x; - unsigned short y; - if (get_long(v, &x) < 0) - return -1; - if (x < 0 || x > USHRT_MAX){ - PyErr_SetString(StructError, - "ushort format requires 0 <= number <= " STRINGIFY(USHRT_MAX)); - return -1; - } - y = (unsigned short)x; - memcpy(p, (char *)&y, sizeof y); - return 0; -} - -static int -np_int(char *p, PyObject *v, const formatdef *f) -{ - long x; - int y; - if (get_long(v, &x) < 0) - return -1; -#if (SIZEOF_LONG > SIZEOF_INT) - if ((x < ((long)INT_MIN)) || (x > ((long)INT_MAX))) - return _range_error(f, 0); -#endif - y = (int)x; - memcpy(p, (char *)&y, sizeof y); - return 0; -} - -static int -np_uint(char *p, PyObject *v, const formatdef *f) -{ - unsigned long x; - unsigned int y; - if (get_ulong(v, &x) < 0) - return -1; - y = (unsigned int)x; -#if (SIZEOF_LONG > SIZEOF_INT) - if (x > ((unsigned long)UINT_MAX)) - return _range_error(f, 1); -#endif - memcpy(p, (char *)&y, sizeof y); - return 0; -} - -static int -np_long(char *p, PyObject *v, const formatdef *f) -{ - long x; - if (get_long(v, &x) < 0) - return -1; - memcpy(p, (char *)&x, sizeof x); - return 0; -} - -static int -np_ulong(char *p, PyObject *v, const formatdef *f) -{ - unsigned long x; - if (get_ulong(v, &x) < 0) - return -1; - memcpy(p, (char *)&x, sizeof x); - return 0; -} - -#ifdef HAVE_LONG_LONG - -static int -np_longlong(char *p, PyObject *v, const formatdef *f) -{ - PY_LONG_LONG x; - if (get_longlong(v, &x) < 0) - return -1; - memcpy(p, (char *)&x, sizeof x); - return 0; -} - -static int -np_ulonglong(char *p, PyObject *v, const formatdef *f) -{ - unsigned PY_LONG_LONG x; - if (get_ulonglong(v, &x) < 0) - return -1; - memcpy(p, (char *)&x, sizeof x); - return 0; -} -#endif - - -static int -np_bool(char *p, PyObject *v, const formatdef *f) -{ - BOOL_TYPE y; - y = PyObject_IsTrue(v) != 0; - memcpy(p, (char *)&y, sizeof y); - return 0; -} - -static int -np_float(char *p, PyObject *v, const formatdef *f) -{ - float x = (float)PyFloat_AsDouble(v); - if (x == -1 && PyErr_Occurred()) { - PyErr_SetString(StructError, - "required argument is not a float"); - return -1; - } - memcpy(p, (char *)&x, sizeof x); - return 0; -} - -static int -np_double(char *p, PyObject *v, const formatdef *f) -{ - double x = PyFloat_AsDouble(v); - if (x == -1 && PyErr_Occurred()) { - PyErr_SetString(StructError, - "required argument is not a float"); - return -1; - } - memcpy(p, (char *)&x, sizeof(double)); - return 0; -} - -static int -np_complex_float(char *p, PyObject *v, const formatdef *f) -{ - if (PyArray_IsZeroDim(v)) { - PyObject *v_cast = PyArray_Cast( - reinterpret_cast<PyArrayObject *>(v), - NPY_CFLOAT); - if (!v_cast) - return -1; - memcpy(p, PyArray_DATA(v_cast), PyArray_NBYTES(v_cast)); - Py_DECREF(v_cast); - } - else { - float re = 0.0f; - float im = 0.0f; - Py_complex cplx; -#if (PY_VERSION_HEX < 0x02060000) - if (PyComplex_Check(v)) - cplx = PyComplex_AsCComplex(v); - else if (PyObject_HasAttrString(v, "__complex__")) - { - PyObject *v2 = PyObject_CallMethod(v, "__complex__", ""); - cplx = PyComplex_AsCComplex(v2); - Py_DECREF(v2); - } - else - cplx = PyComplex_AsCComplex(v); -#else - cplx = PyComplex_AsCComplex(v); -#endif - if (PyErr_Occurred()) { - PyErr_SetString(StructError, - "required argument is not a complex"); - return -1; - } - - re = (float)cplx.real; - im = (float)cplx.imag; - memcpy(p, (char *)&re, sizeof re); - memcpy(p+sizeof re, (char *)&im, sizeof im); - } - return 0; -} - -static int -np_complex_double(char *p, PyObject *v, const formatdef *f) -{ - if (PyArray_IsZeroDim(v)) { - PyObject *v_cast = PyArray_Cast( - reinterpret_cast<PyArrayObject *>(v), - NPY_CDOUBLE); - if (!v_cast) - return -1; - memcpy(p, PyArray_DATA(v_cast), PyArray_NBYTES(v_cast)); - Py_DECREF(v_cast); - } - else { - double re = 0.0; - double im = 0.0; - Py_complex cplx; -#if (PY_VERSION_HEX < 0x02060000) - if (PyComplex_Check(v)) - cplx = PyComplex_AsCComplex(v); - else if (PyObject_HasAttrString(v, "__complex__")) - { - PyObject *v2 = PyObject_CallMethod(v, "__complex__", ""); - cplx = PyComplex_AsCComplex(v2); - Py_DECREF(v2); - } - else - cplx = PyComplex_AsCComplex(v); -#else - cplx = PyComplex_AsCComplex(v); -#endif - if (PyErr_Occurred()) { - PyErr_SetString(StructError, - "required argument is not a complex"); - return -1; - } - re = cplx.real; - im = cplx.imag; - memcpy(p, (char *)&re, sizeof re); - memcpy(p+sizeof re, (char *)&im, sizeof im); - } - return 0; -} - -static int -np_void_p(char *p, PyObject *v, const formatdef *f) -{ - void *x; - - v = get_pylong(v); - if (v == NULL) - return -1; - assert(PyLong_Check(v)); - x = PyLong_AsVoidPtr(v); - Py_DECREF(v); - if (x == NULL && PyErr_Occurred()) - return -1; - memcpy(p, (char *)&x, sizeof x); - return 0; -} - -static formatdef native_table[] = { - {'x', sizeof(char), 0, NULL}, - {'b', sizeof(char), 0, nu_byte, np_byte}, - {'B', sizeof(char), 0, nu_ubyte, np_ubyte}, - {'c', sizeof(char), 0, nu_char, np_char}, - {'s', sizeof(char), 0, NULL}, - {'p', sizeof(char), 0, NULL}, - {'h', sizeof(short), SHORT_ALIGN, nu_short, np_short}, - {'H', sizeof(short), SHORT_ALIGN, nu_ushort, np_ushort}, - {'i', sizeof(int), INT_ALIGN, nu_int, np_int}, - {'I', sizeof(int), INT_ALIGN, nu_uint, np_uint}, - {'l', sizeof(long), LONG_ALIGN, nu_long, np_long}, - {'L', sizeof(long), LONG_ALIGN, nu_ulong, np_ulong}, -#ifdef HAVE_LONG_LONG - {'q', sizeof(PY_LONG_LONG), LONG_LONG_ALIGN, nu_longlong, np_longlong}, - {'Q', sizeof(PY_LONG_LONG), LONG_LONG_ALIGN, nu_ulonglong,np_ulonglong}, -#endif - {'?', sizeof(BOOL_TYPE), BOOL_ALIGN, nu_bool, np_bool}, - {'f', sizeof(float), FLOAT_ALIGN, nu_float, np_float}, - {'d', sizeof(double), DOUBLE_ALIGN, nu_double, np_double}, - {'F', 2*sizeof(float), FLOAT_ALIGN, nu_complex_float, np_complex_float}, - {'D', 2*sizeof(double), DOUBLE_ALIGN, nu_complex_double, np_complex_double}, - {'P', sizeof(void *), VOID_P_ALIGN, nu_void_p, np_void_p}, - {0} -}; - -/* Get the table entry for a format code */ - -static const formatdef * -getentry(int c, const formatdef *f) -{ - for (; f->format != '\0'; f++) { - if (f->format == c) { - return f; - } - } - PyErr_SetString(StructError, "bad char in struct format"); - return NULL; -} - - -/* Align a size according to a format code */ - -static Py_ssize_t -align(Py_ssize_t size, char c, const formatdef *e) -{ - if (e->format == c) { - if (e->alignment) { - size = ((size + e->alignment - 1) - / e->alignment) - * e->alignment; - } - } - return size; -} - - -/* calculate the size of a format string */ - -static int -prepare_s(PyStructObject *self) -{ - const formatdef *f; - const formatdef *e; - formatcode *codes; - - const char *s; - const char *fmt; - char c; - Py_ssize_t size, len, num, itemsize, x; - - fmt = PyString_AS_STRING(self->s_format); - - f = native_table; - - s = fmt; - size = 0; - len = 0; - while ((c = *s++) != '\0') { - if (isspace(Py_CHARMASK(c))) - continue; - if ('0' <= c && c <= '9') { - num = c - '0'; - while ('0' <= (c = *s++) && c <= '9') { - x = num*10 + (c - '0'); - if (x/10 != num) { - PyErr_SetString( - StructError, - "overflow in item count"); - return -1; - } - num = x; - } - if (c == '\0') - break; - } - else - num = 1; - - e = getentry(c, f); - if (e == NULL) - return -1; - - switch (c) { - case 's': /* fall through */ - case 'p': len++; break; - case 'x': break; - default: len += num; break; - } - - itemsize = e->size; - size = align(size, c, e); - x = num * itemsize; - size += x; - if (x/itemsize != num || size < 0) { - PyErr_SetString(StructError, - "total struct size too long"); - return -1; - } - } - - /* check for overflow */ - if ((len + 1) > (PY_SSIZE_T_MAX / sizeof(formatcode))) { - PyErr_NoMemory(); - return -1; - } - - self->s_size = size; - self->s_len = len; - codes = (formatcode *) PyMem_MALLOC((len + 1) * sizeof(formatcode)); - if (codes == NULL) { - PyErr_NoMemory(); - return -1; - } - self->s_codes = codes; - - s = fmt; - size = 0; - while ((c = *s++) != '\0') { - if (isspace(Py_CHARMASK(c))) - continue; - if ('0' <= c && c <= '9') { - num = c - '0'; - while ('0' <= (c = *s++) && c <= '9') - num = num*10 + (c - '0'); - if (c == '\0') - break; - } - else - num = 1; - - e = getentry(c, f); - - size = align(size, c, e); - if (c == 's' || c == 'p') { - codes->offset = size; - codes->size = num; - codes->fmtdef = e; - codes++; - size += num; - } else if (c == 'x') { - size += num; - } else { - while (--num >= 0) { - codes->offset = size; - codes->size = e->size; - codes->fmtdef = e; - codes++; - size += e->size; - } - } - } - codes->fmtdef = NULL; - codes->offset = size; - codes->size = 0; - - return 0; -} - -static PyObject * -s_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyObject *self; - - assert(type != NULL && type->tp_alloc != NULL); - - self = type->tp_alloc(type, 0); - if (self != NULL) { - PyStructObject *s = (PyStructObject*)self; - Py_INCREF(Py_None); - s->s_format = Py_None; - s->s_codes = NULL; - s->s_size = -1; - s->s_len = -1; - } - return self; -} - -static int -s_init(PyObject *self, PyObject *args, PyObject *kwds) -{ - PyStructObject *soself = (PyStructObject *)self; - PyObject *o_format = NULL; - int ret = 0; - static char *kwlist[] = {"format", 0}; - - assert(PyStruct_Check(self)); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "S:Struct", kwlist, - &o_format)) - return -1; - - Py_INCREF(o_format); - Py_CLEAR(soself->s_format); - soself->s_format = o_format; - - ret = prepare_s(soself); - return ret; -} - -static void -s_dealloc(PyStructObject *s) -{ - if (s->weakreflist != NULL) - PyObject_ClearWeakRefs((PyObject *)s); - if (s->s_codes != NULL) { - PyMem_FREE(s->s_codes); - } - Py_XDECREF(s->s_format); - Py_TYPE(s)->tp_free((PyObject *)s); -} - -static PyObject * -s_unpack_internal(PyStructObject *soself, char *startfrom) { - formatcode *code; - Py_ssize_t i = 0; - PyObject *result = PyTuple_New(soself->s_len); - if (result == NULL) - return NULL; - - for (code = soself->s_codes; code->fmtdef != NULL; code++) { - PyObject *v; - const formatdef *e = code->fmtdef; - const char *res = startfrom + code->offset; - if (e->format == 's') { - v = PyString_FromStringAndSize(res, code->size); - } else if (e->format == 'p') { - Py_ssize_t n = *(unsigned char*)res; - if (n >= code->size) - n = code->size - 1; - v = PyString_FromStringAndSize(res + 1, n); - } else { - v = e->unpack(res, e); - } - if (v == NULL) - goto fail; - PyTuple_SET_ITEM(result, i++, v); - } - - return result; -fail: - Py_DECREF(result); - return NULL; -} - - -static PyObject * -s_unpack(PyObject *self, PyObject *inputstr) -{ - char *start; - Py_ssize_t len; - PyObject *args=NULL, *result; - PyStructObject *soself = (PyStructObject *)self; - assert(PyStruct_Check(self)); - assert(soself->s_codes != NULL); - if (inputstr == NULL) - goto fail; - if (PyString_Check(inputstr) && - PyString_GET_SIZE(inputstr) == soself->s_size) { - return s_unpack_internal(soself, PyString_AS_STRING(inputstr)); - } - args = PyTuple_Pack(1, inputstr); - if (args == NULL) - return NULL; - if (!PyArg_ParseTuple(args, "s#:unpack", &start, &len)) - goto fail; - if (soself->s_size != len) - goto fail; - result = s_unpack_internal(soself, start); - Py_DECREF(args); - return result; - -fail: - Py_XDECREF(args); - PyErr_Format(StructError, - "unpack requires a string argument of length %zd", - soself->s_size); - return NULL; -} - -static PyObject * -s_unpack_from(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"buffer", "offset", 0}; -#if (PY_VERSION_HEX < 0x02050000) - static char *fmt = "z#|i:unpack_from"; -#else - static char *fmt = "z#|n:unpack_from"; -#endif - Py_ssize_t buffer_len = 0, offset = 0; - char *buffer = NULL; - PyStructObject *soself = (PyStructObject *)self; - assert(PyStruct_Check(self)); - assert(soself->s_codes != NULL); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, fmt, kwlist, - &buffer, &buffer_len, &offset)) - return NULL; - - if (buffer == NULL) { - PyErr_Format(StructError, - "unpack_from requires a buffer argument"); - return NULL; - } - - if (offset < 0) - offset += buffer_len; - - if (offset < 0 || (buffer_len - offset) < soself->s_size) { - PyErr_Format(StructError, - "unpack_from requires a buffer of at least %zd bytes", - soself->s_size); - return NULL; - } - return s_unpack_internal(soself, buffer + offset); -} - - -/* - * Guts of the pack function. - * - * Takes a struct object, a tuple of arguments, and offset in that tuple of - * argument for where to start processing the arguments for packing, and a - * character buffer for writing the packed string. The caller must insure - * that the buffer may contain the required length for packing the arguments. - * 0 is returned on success, 1 is returned if there is an error. - * - */ -static int -s_pack_internal(PyStructObject *soself, PyObject *args, int offset, char* buf) -{ - formatcode *code; - /* XXX(nnorwitz): why does i need to be a local? can we use - the offset parameter or do we need the wider width? */ - Py_ssize_t i; - - memset(buf, '\0', soself->s_size); - i = offset; - for (code = soself->s_codes; code->fmtdef != NULL; code++) { - Py_ssize_t n; - PyObject *v = PyTuple_GET_ITEM(args, i++); - const formatdef *e = code->fmtdef; - char *res = buf + code->offset; - if (e->format == 's') { - if (!PyString_Check(v)) { - if (!PyObject_CheckReadBuffer(v)) - { - PyErr_SetString(StructError, - "argument for 's' must " - "be a string or a buffer"); - return -1; - } - else - { - const void *buf; - Py_ssize_t len; - if (PyObject_AsReadBuffer(v, &buf, &len)) - return -1; - - if (len > code->size) - len = code->size; - if (len > 0) - memcpy(res, buf, len); - } - } - else - { - n = PyString_GET_SIZE(v); - if (n > code->size) - n = code->size; - if (n > 0) - memcpy(res, PyString_AS_STRING(v), n); - } - } else if (e->format == 'p') { - if (!PyString_Check(v)) { - PyErr_SetString(StructError, - "argument for 'p' must " - "be a string"); - return -1; - } - n = PyString_GET_SIZE(v); - if (n > (code->size - 1)) - n = code->size - 1; - if (n > 0) - memcpy(res + 1, PyString_AS_STRING(v), n); - if (n > 255) - n = 255; - *res = Py_SAFE_DOWNCAST(n, Py_ssize_t, unsigned char); - } else if (e->pack(res, v, e) < 0) { - if (strchr(integer_codes, e->format) != NULL && - PyErr_ExceptionMatches(PyExc_OverflowError)) - PyErr_Format(StructError, - "integer out of range for " - "'%c' format code", - e->format); - return -1; - } - } - - /* Success */ - return 0; -} - - -static PyObject * -s_pack(PyObject *self, PyObject *args) -{ - PyStructObject *soself; - PyObject *result; - - /* Validate arguments. */ - soself = (PyStructObject *)self; - assert(PyStruct_Check(self)); - assert(soself->s_codes != NULL); - if (PyTuple_GET_SIZE(args) != soself->s_len) - { - PyErr_Format(StructError, - "pack requires exactly %zd arguments", soself->s_len); - return NULL; - } - - /* Allocate a new string */ - result = PyString_FromStringAndSize((char *)NULL, soself->s_size); - if (result == NULL) - return NULL; - - /* Call the guts */ - if ( s_pack_internal(soself, args, 0, PyString_AS_STRING(result)) != 0 ) { - Py_DECREF(result); - return NULL; - } - - return result; -} - - -static PyObject * -s_pack_into(PyObject *self, PyObject *args) -{ - PyStructObject *soself; - char *buffer; - Py_ssize_t buffer_len, offset; - - /* Validate arguments. +1 is for the first arg as buffer. */ - soself = (PyStructObject *)self; - assert(PyStruct_Check(self)); - assert(soself->s_codes != NULL); - if (PyTuple_GET_SIZE(args) != (soself->s_len + 2)) - { - PyErr_Format(StructError, - "pack_into requires exactly %zd arguments", - (soself->s_len + 2)); - return NULL; - } - - /* Extract a writable memory buffer from the first argument */ - if ( PyObject_AsWriteBuffer(PyTuple_GET_ITEM(args, 0), - (void**)&buffer, &buffer_len) == -1 ) { - return NULL; - } - assert( buffer_len >= 0 ); - - /* Extract the offset from the first argument */ - offset = PyInt_AsSsize_t(PyTuple_GET_ITEM(args, 1)); - if (offset == -1 && PyErr_Occurred()) - return NULL; - - /* Support negative offsets. */ - if (offset < 0) - offset += buffer_len; - - /* Check boundaries */ - if (offset < 0 || (buffer_len - offset) < soself->s_size) { - PyErr_Format(StructError, - "pack_into requires a buffer of at least %zd bytes", - soself->s_size); - return NULL; - } - - /* Call the guts */ - if ( s_pack_internal(soself, args, 2, buffer + offset) != 0 ) { - return NULL; - } - - Py_RETURN_NONE; -} - -static PyObject * -s_get_format(PyStructObject *self, void *unused) -{ - Py_INCREF(self->s_format); - return self->s_format; -} - -static PyObject * -s_get_size(PyStructObject *self, void *unused) -{ - return PyInt_FromSsize_t(self->s_size); -} - -/* ---- Standalone functions ---- */ - -#define MAXCACHE 100 -static PyObject *cache = NULL; - -static PyObject * -cache_struct(PyObject *fmt) -{ - PyObject * s_object; - - if (cache == NULL) { - cache = PyDict_New(); - if (cache == NULL) - return NULL; - } - - s_object = PyDict_GetItem(cache, fmt); - if (s_object != NULL) { - Py_INCREF(s_object); - return s_object; - } - - s_object = PyObject_CallFunctionObjArgs((PyObject *)(&PyStructType), fmt, NULL); - if (s_object != NULL) { - if (PyDict_Size(cache) >= MAXCACHE) - PyDict_Clear(cache); - /* Attempt to cache the result */ - if (PyDict_SetItem(cache, fmt, s_object) == -1) - PyErr_Clear(); - } - return s_object; -} - -PyDoc_STRVAR(clearcache_doc, -"Clear the internal cache."); - -static PyObject * -clearcache(PyObject *self) -{ - Py_CLEAR(cache); - Py_RETURN_NONE; -} - -PyDoc_STRVAR(calcsize_doc, -"Return size of C struct described by format string fmt."); - -static PyObject * -calcsize(PyObject *self, PyObject *fmt) -{ - Py_ssize_t n; - PyObject *s_object = cache_struct(fmt); - if (s_object == NULL) - return NULL; - n = ((PyStructObject *)s_object)->s_size; - Py_DECREF(s_object); - return PyInt_FromSsize_t(n); -} - -PyDoc_STRVAR(pack_doc, -"Return string containing values v1, v2, ... packed according to fmt."); - -static PyObject * -pack(PyObject *self, PyObject *args) -{ - PyObject *s_object, *fmt, *newargs, *result; - Py_ssize_t n = PyTuple_GET_SIZE(args); - - if (n == 0) { - PyErr_SetString(PyExc_TypeError, "missing format argument"); - return NULL; - } - fmt = PyTuple_GET_ITEM(args, 0); - newargs = PyTuple_GetSlice(args, 1, n); - if (newargs == NULL) - return NULL; - - s_object = cache_struct(fmt); - if (s_object == NULL) { - Py_DECREF(newargs); - return NULL; - } - result = s_pack(s_object, newargs); - Py_DECREF(newargs); - Py_DECREF(s_object); - return result; -} - -PyDoc_STRVAR(pack_into_doc, -"Pack the values v1, v2, ... according to fmt.\n\ -Write the packed bytes into the writable buffer buf starting at offset."); - -static PyObject * -pack_into(PyObject *self, PyObject *args) -{ - PyObject *s_object, *fmt, *newargs, *result; - Py_ssize_t n = PyTuple_GET_SIZE(args); - - if (n == 0) { - PyErr_SetString(PyExc_TypeError, "missing format argument"); - return NULL; - } - fmt = PyTuple_GET_ITEM(args, 0); - newargs = PyTuple_GetSlice(args, 1, n); - if (newargs == NULL) - return NULL; - - s_object = cache_struct(fmt); - if (s_object == NULL) { - Py_DECREF(newargs); - return NULL; - } - result = s_pack_into(s_object, newargs); - Py_DECREF(newargs); - Py_DECREF(s_object); - return result; -} - -PyDoc_STRVAR(unpack_doc, -"Unpack the string containing packed C structure data, according to fmt.\n\ -Requires len(string) == calcsize(fmt)."); - -static PyObject * -unpack(PyObject *self, PyObject *args) -{ - PyObject *s_object, *fmt, *inputstr, *result; - - if (!PyArg_UnpackTuple(args, "unpack", 2, 2, &fmt, &inputstr)) - return NULL; - - s_object = cache_struct(fmt); - if (s_object == NULL) - return NULL; - result = s_unpack(s_object, inputstr); - Py_DECREF(s_object); - return result; -} - -PyDoc_STRVAR(unpack_from_doc, -"Unpack the buffer, containing packed C structure data, according to\n\ -fmt, starting at offset. Requires len(buffer[offset:]) >= calcsize(fmt)."); - -static PyObject * -unpack_from(PyObject *self, PyObject *args, PyObject *kwds) -{ - PyObject *s_object, *fmt, *newargs, *result; - Py_ssize_t n = PyTuple_GET_SIZE(args); - - if (n == 0) { - PyErr_SetString(PyExc_TypeError, "missing format argument"); - return NULL; - } - fmt = PyTuple_GET_ITEM(args, 0); - newargs = PyTuple_GetSlice(args, 1, n); - if (newargs == NULL) - return NULL; - - s_object = cache_struct(fmt); - if (s_object == NULL) { - Py_DECREF(newargs); - return NULL; - } - result = s_unpack_from(s_object, newargs, kwds); - Py_DECREF(newargs); - Py_DECREF(s_object); - return result; -} - -static struct PyMethodDef module_functions[] = { - {"_clearcache", (PyCFunction)clearcache, METH_NOARGS, clearcache_doc}, - {"calcsize", calcsize, METH_O, calcsize_doc}, - {"pack", pack, METH_VARARGS, pack_doc}, - {"pack_into", pack_into, METH_VARARGS, pack_into_doc}, - {"unpack", unpack, METH_VARARGS, unpack_doc}, - {"unpack_from", (PyCFunction)unpack_from, - METH_VARARGS|METH_KEYWORDS, unpack_from_doc}, - {NULL, NULL} /* sentinel */ -}; - - -/* Module initialization */ - -PyDoc_STRVAR(module_doc, -"Functions to convert between Python values and C structs represented\n\ -as Python strings. It uses format strings (explained below) as compact\n\ -descriptions of the lay-out of the C structs and the intended conversion\n\ -to/from Python values.\n\ -\n\ -The remaining chars indicate types of args and must match exactly;\n\ -these can be preceded by a decimal repeat count:\n\ - x: pad byte (no data); c:char; b:signed byte; B:unsigned byte;\n\ - ?: _Bool (requires C99; if not available, char is used instead)\n\ - h:short; H:unsigned short; i:int; I:unsigned int;\n\ - l:long; L:unsigned long; f:float; d:double.\n\ -Special cases (preceding decimal count indicates length):\n\ - s:string (array of char); p: pascal string (with count byte).\n\ -Special case (only available in native format):\n\ - P:an integer type that is wide enough to hold a pointer.\n\ -Special case (not in native mode unless 'long long' in platform C):\n\ - q:long long; Q:unsigned long long\n\ -Whitespace between formats is ignored.\n\ -\n\ -The variable struct.error is an exception raised on errors.\n"); - -PyMODINIT_FUNC -init_pvt_struct(void) -{ - PyObject *ver, *m; - - ver = PyString_FromString("0.2"); - if (ver == NULL) - return; - - m = Py_InitModule3("_pvt_struct", module_functions, module_doc); - if (m == NULL) - return; - - Py_TYPE(&PyStructType) = &PyType_Type; - if (PyType_Ready(&PyStructType) < 0) - return; - - /* This speed trick can't be used until overflow masking goes - away, because native endian always raises exceptions - instead of overflow masking. */ - - /* Add some symbolic constants to the module */ - if (StructError == NULL) { - StructError = PyErr_NewException("pyopencl._pvt_struct.error", NULL, NULL); - if (StructError == NULL) - return; - } - - Py_INCREF(StructError); - PyModule_AddObject(m, "error", StructError); - - Py_INCREF((PyObject*)&PyStructType); - PyModule_AddObject(m, "Struct", (PyObject*)&PyStructType); - - PyModule_AddObject(m, "__version__", ver); - - PyModule_AddIntConstant(m, "_PY_STRUCT_RANGE_CHECKING", 1); -#ifdef PY_STRUCT_FLOAT_COERCE - PyModule_AddIntConstant(m, "_PY_STRUCT_FLOAT_COERCE", 1); -#endif - -} - -// vim: noexpandtab:sw=8 diff --git a/src/wrapper/_pvt_struct_v3.cpp b/src/wrapper/_pvt_struct_v3.cpp deleted file mode 100644 index 316062f1..00000000 --- a/src/wrapper/_pvt_struct_v3.cpp +++ /dev/null @@ -1,1749 +0,0 @@ -/* struct module -- pack values into and (out of) bytes objects */ - -/* New version supporting byte order, alignment and size options, - character strings, and unsigned numbers */ - -#define PY_SSIZE_T_CLEAN - -#include "Python.h" -#include "structmember.h" -#include <ctype.h> -#include "numpy_init.hpp" - -namespace { -extern PyTypeObject PyStructType; -} - -/* The translation function for each format character is table driven */ -typedef struct _formatdef { - char format; - Py_ssize_t size; - Py_ssize_t alignment; - PyObject* (*unpack)(const char *, - const struct _formatdef *); - int (*pack)(char *, PyObject *, - const struct _formatdef *); -} formatdef; - -typedef struct _formatcode { - const struct _formatdef *fmtdef; - Py_ssize_t offset; - Py_ssize_t size; -} formatcode; - -/* Struct object interface */ - -typedef struct { - PyObject_HEAD - Py_ssize_t s_size; - Py_ssize_t s_len; - formatcode *s_codes; - PyObject *s_format; - PyObject *weakreflist; /* List of weak references */ -} PyStructObject; - - -#define PyStruct_Check(op) PyObject_TypeCheck(op, &PyStructType) -#define PyStruct_CheckExact(op) (Py_TYPE(op) == &PyStructType) - - -/* Exception */ - -static PyObject *StructError; - - -/* Define various structs to figure out the alignments of types */ - - -typedef struct { char c; short x; } st_short; -typedef struct { char c; int x; } st_int; -typedef struct { char c; long x; } st_long; -typedef struct { char c; float x; } st_float; -typedef struct { char c; double x; } st_double; -typedef struct { char c; void *x; } st_void_p; -typedef struct { char c; size_t x; } st_size_t; - -#define SHORT_ALIGN (sizeof(st_short) - sizeof(short)) -#define INT_ALIGN (sizeof(st_int) - sizeof(int)) -#define LONG_ALIGN (sizeof(st_long) - sizeof(long)) -#define FLOAT_ALIGN (sizeof(st_float) - sizeof(float)) -#define DOUBLE_ALIGN (sizeof(st_double) - sizeof(double)) -#define VOID_P_ALIGN (sizeof(st_void_p) - sizeof(void *)) -#define SIZE_T_ALIGN (sizeof(st_size_t) - sizeof(size_t)) - -/* We can't support q and Q in native mode unless the compiler does; - in std mode, they're 8 bytes on all platforms. */ -#ifdef HAVE_LONG_LONG -typedef struct { char c; PY_LONG_LONG x; } s_long_long; -#define LONG_LONG_ALIGN (sizeof(s_long_long) - sizeof(PY_LONG_LONG)) -#endif - -#if !defined(__cplusplus) && defined(HAVE_C99_BOOL) -#define BOOL_TYPE _Bool -typedef struct { char c; _Bool x; } s_bool; -#define BOOL_ALIGN (sizeof(s_bool) - sizeof(BOOL_TYPE)) -#else -#define BOOL_TYPE char -#define BOOL_ALIGN 0 -#endif - -#define STRINGIFY(x) #x - -#ifdef __powerc -#pragma options align=reset -#endif - -/* Helper for integer format codes: converts an arbitrary Python object to a - PyLongObject if possible, otherwise fails. Caller should decref. */ - -static PyObject * -get_pylong(PyObject *v) -{ - assert(v != NULL); - if (!PyLong_Check(v)) { - /* Not an integer; try to use __index__ to convert. */ - if (PyIndex_Check(v)) { - v = PyNumber_Index(v); - if (v == NULL) - return NULL; - } - else { - PyErr_SetString(StructError, - "required argument is not an integer"); - return NULL; - } - } - else - Py_INCREF(v); - - assert(PyLong_Check(v)); - return v; -} - -/* Helper routine to get a C long and raise the appropriate error if it isn't - one */ - -static int -get_long(PyObject *v, long *p) -{ - long x; - - v = get_pylong(v); - if (v == NULL) - return -1; - assert(PyLong_Check(v)); - x = PyLong_AsLong(v); - Py_DECREF(v); - if (x == (long)-1 && PyErr_Occurred()) { - if (PyErr_ExceptionMatches(PyExc_OverflowError)) - PyErr_SetString(StructError, - "argument out of range"); - return -1; - } - *p = x; - return 0; -} - - -/* Same, but handling unsigned long */ - -static int -get_ulong(PyObject *v, unsigned long *p) -{ - unsigned long x; - - v = get_pylong(v); - if (v == NULL) - return -1; - assert(PyLong_Check(v)); - x = PyLong_AsUnsignedLong(v); - Py_DECREF(v); - if (x == (unsigned long)-1 && PyErr_Occurred()) { - if (PyErr_ExceptionMatches(PyExc_OverflowError)) - PyErr_SetString(StructError, - "argument out of range"); - return -1; - } - *p = x; - return 0; -} - -#ifdef HAVE_LONG_LONG - -/* Same, but handling native long long. */ - -static int -get_longlong(PyObject *v, PY_LONG_LONG *p) -{ - PY_LONG_LONG x; - - v = get_pylong(v); - if (v == NULL) - return -1; - assert(PyLong_Check(v)); - x = PyLong_AsLongLong(v); - Py_DECREF(v); - if (x == (PY_LONG_LONG)-1 && PyErr_Occurred()) { - if (PyErr_ExceptionMatches(PyExc_OverflowError)) - PyErr_SetString(StructError, - "argument out of range"); - return -1; - } - *p = x; - return 0; -} - -/* Same, but handling native unsigned long long. */ - -static int -get_ulonglong(PyObject *v, unsigned PY_LONG_LONG *p) -{ - unsigned PY_LONG_LONG x; - - v = get_pylong(v); - if (v == NULL) - return -1; - assert(PyLong_Check(v)); - x = PyLong_AsUnsignedLongLong(v); - Py_DECREF(v); - if (x == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred()) { - if (PyErr_ExceptionMatches(PyExc_OverflowError)) - PyErr_SetString(StructError, - "argument out of range"); - return -1; - } - *p = x; - return 0; -} - -#endif - -/* Same, but handling Py_ssize_t */ - -static int -get_ssize_t(PyObject *v, Py_ssize_t *p) -{ - Py_ssize_t x; - - v = get_pylong(v); - if (v == NULL) - return -1; - assert(PyLong_Check(v)); - x = PyLong_AsSsize_t(v); - Py_DECREF(v); - if (x == (Py_ssize_t)-1 && PyErr_Occurred()) { - if (PyErr_ExceptionMatches(PyExc_OverflowError)) - PyErr_SetString(StructError, - "argument out of range"); - return -1; - } - *p = x; - return 0; -} - -/* Same, but handling size_t */ - -static int -get_size_t(PyObject *v, size_t *p) -{ - size_t x; - - v = get_pylong(v); - if (v == NULL) - return -1; - assert(PyLong_Check(v)); - x = PyLong_AsSize_t(v); - Py_DECREF(v); - if (x == (size_t)-1 && PyErr_Occurred()) { - if (PyErr_ExceptionMatches(PyExc_OverflowError)) - PyErr_SetString(StructError, - "argument out of range"); - return -1; - } - *p = x; - return 0; -} - - -#define RANGE_ERROR(x, f, flag, mask) return _range_error(f, flag) - - -/* Floating point helpers */ -#if 0 - -static PyObject * -unpack_float(const char *p, /* start of 4-byte string */ - int le) /* true for little-endian, false for big-endian */ -{ - double x; - - x = _PyFloat_Unpack4((unsigned char *)p, le); - if (x == -1.0 && PyErr_Occurred()) - return NULL; - return PyFloat_FromDouble(x); -} - -static PyObject * -unpack_double(const char *p, /* start of 8-byte string */ - int le) /* true for little-endian, false for big-endian */ -{ - double x; - - x = _PyFloat_Unpack8((unsigned char *)p, le); - if (x == -1.0 && PyErr_Occurred()) - return NULL; - return PyFloat_FromDouble(x); -} - -#endif - -/* Helper to format the range error exceptions */ -static int -_range_error(const formatdef *f, int is_unsigned) -{ - /* ulargest is the largest unsigned value with f->size bytes. - * Note that the simpler: - * ((size_t)1 << (f->size * 8)) - 1 - * doesn't work when f->size == sizeof(size_t) because C doesn't - * define what happens when a left shift count is >= the number of - * bits in the integer being shifted; e.g., on some boxes it doesn't - * shift at all when they're equal. - */ - const size_t ulargest = (size_t)-1 >> ((SIZEOF_SIZE_T - f->size)*8); - assert(f->size >= 1 && f->size <= SIZEOF_SIZE_T); - if (is_unsigned) - PyErr_Format(StructError, - "'%c' format requires 0 <= number <= %zu", - f->format, - ulargest); - else { - const Py_ssize_t largest = (Py_ssize_t)(ulargest >> 1); - PyErr_Format(StructError, - "'%c' format requires %zd <= number <= %zd", - f->format, - ~ largest, - largest); - } - - return -1; -} - - - -/* A large number of small routines follow, with names of the form - - [bln][up]_TYPE - - [bln] distiguishes among big-endian, little-endian and native. - [pu] distiguishes between pack (to struct) and unpack (from struct). - TYPE is one of char, byte, ubyte, etc. -*/ - -// {{{ - -/* Native mode routines. ****************************************************/ -/* NOTE: - In all n[up]_<type> routines handling types larger than 1 byte, there is - *no* guarantee that the p pointer is properly aligned for each type, - therefore memcpy is called. An intermediate variable is used to - compensate for big-endian architectures. - Normally both the intermediate variable and the memcpy call will be - skipped by C optimisation in little-endian architectures (gcc >= 2.91 - does this). */ - -static PyObject * -nu_char(const char *p, const formatdef *f) -{ - return PyBytes_FromStringAndSize(p, 1); -} - -static PyObject * -nu_byte(const char *p, const formatdef *f) -{ - return PyLong_FromLong((long) *(signed char *)p); -} - -static PyObject * -nu_ubyte(const char *p, const formatdef *f) -{ - return PyLong_FromLong((long) *(unsigned char *)p); -} - -static PyObject * -nu_short(const char *p, const formatdef *f) -{ - short x; - memcpy((char *)&x, p, sizeof x); - return PyLong_FromLong((long)x); -} - -static PyObject * -nu_ushort(const char *p, const formatdef *f) -{ - unsigned short x; - memcpy((char *)&x, p, sizeof x); - return PyLong_FromLong((long)x); -} - -static PyObject * -nu_int(const char *p, const formatdef *f) -{ - int x; - memcpy((char *)&x, p, sizeof x); - return PyLong_FromLong((long)x); -} - -static PyObject * -nu_uint(const char *p, const formatdef *f) -{ - unsigned int x; - memcpy((char *)&x, p, sizeof x); -#if (SIZEOF_LONG > SIZEOF_INT) - return PyLong_FromLong((long)x); -#else - if (x <= ((unsigned int)LONG_MAX)) - return PyLong_FromLong((long)x); - return PyLong_FromUnsignedLong((unsigned long)x); -#endif -} - -static PyObject * -nu_long(const char *p, const formatdef *f) -{ - long x; - memcpy((char *)&x, p, sizeof x); - return PyLong_FromLong(x); -} - -static PyObject * -nu_ulong(const char *p, const formatdef *f) -{ - unsigned long x; - memcpy((char *)&x, p, sizeof x); - if (x <= LONG_MAX) - return PyLong_FromLong((long)x); - return PyLong_FromUnsignedLong(x); -} - -static PyObject * -nu_ssize_t(const char *p, const formatdef *f) -{ - Py_ssize_t x; - memcpy((char *)&x, p, sizeof x); - return PyLong_FromSsize_t(x); -} - -static PyObject * -nu_size_t(const char *p, const formatdef *f) -{ - size_t x; - memcpy((char *)&x, p, sizeof x); - return PyLong_FromSize_t(x); -} - - -/* Native mode doesn't support q or Q unless the platform C supports - long long (or, on Windows, __int64). */ - -#ifdef HAVE_LONG_LONG - -static PyObject * -nu_longlong(const char *p, const formatdef *f) -{ - PY_LONG_LONG x; - memcpy((char *)&x, p, sizeof x); - if (x >= LONG_MIN && x <= LONG_MAX) - return PyLong_FromLong(Py_SAFE_DOWNCAST(x, PY_LONG_LONG, long)); - return PyLong_FromLongLong(x); -} - -static PyObject * -nu_ulonglong(const char *p, const formatdef *f) -{ - unsigned PY_LONG_LONG x; - memcpy((char *)&x, p, sizeof x); - if (x <= LONG_MAX) - return PyLong_FromLong(Py_SAFE_DOWNCAST(x, unsigned PY_LONG_LONG, long)); - return PyLong_FromUnsignedLongLong(x); -} - -#endif - -static PyObject * -nu_bool(const char *p, const formatdef *f) -{ - BOOL_TYPE x; - memcpy((char *)&x, p, sizeof x); - return PyBool_FromLong(x != 0); -} - - -static PyObject * -nu_float(const char *p, const formatdef *f) -{ - float x; - memcpy((char *)&x, p, sizeof x); - return PyFloat_FromDouble((double)x); -} - -static PyObject * -nu_double(const char *p, const formatdef *f) -{ - double x; - memcpy((char *)&x, p, sizeof x); - return PyFloat_FromDouble(x); -} - -static PyObject * -nu_complex_float(const char *p, const formatdef *f) -{ - float re, im; - memcpy((char *)&re, p, sizeof re); - memcpy((char *)&im, p+sizeof re, sizeof im); - return PyComplex_FromDoubles((double)re, (double) im); -} - -static PyObject * -nu_complex_double(const char *p, const formatdef *f) -{ - double re, im; - memcpy((char *)&re, p, sizeof re); - memcpy((char *)&im, p+sizeof re, sizeof im); - return PyComplex_FromDoubles(re, im); -} - -static PyObject * -nu_void_p(const char *p, const formatdef *f) -{ - void *x; - memcpy((char *)&x, p, sizeof x); - return PyLong_FromVoidPtr(x); -} - -static int -np_byte(char *p, PyObject *v, const formatdef *f) -{ - long x; - if (get_long(v, &x) < 0) - return -1; - if (x < -128 || x > 127){ - PyErr_SetString(StructError, - "byte format requires -128 <= number <= 127"); - return -1; - } - *p = (char)x; - return 0; -} - -static int -np_ubyte(char *p, PyObject *v, const formatdef *f) -{ - long x; - if (get_long(v, &x) < 0) - return -1; - if (x < 0 || x > 255){ - PyErr_SetString(StructError, - "ubyte format requires 0 <= number <= 255"); - return -1; - } - *p = (char)x; - return 0; -} - -static int -np_char(char *p, PyObject *v, const formatdef *f) -{ - if (!PyBytes_Check(v) || PyBytes_Size(v) != 1) { - PyErr_SetString(StructError, - "char format requires a bytes object of length 1"); - return -1; - } - *p = *PyBytes_AsString(v); - return 0; -} - -static int -np_short(char *p, PyObject *v, const formatdef *f) -{ - long x; - short y; - if (get_long(v, &x) < 0) - return -1; - if (x < SHRT_MIN || x > SHRT_MAX){ - PyErr_SetString(StructError, - "short format requires " STRINGIFY(SHRT_MIN) - " <= number <= " STRINGIFY(SHRT_MAX)); - return -1; - } - y = (short)x; - memcpy(p, (char *)&y, sizeof y); - return 0; -} - -static int -np_ushort(char *p, PyObject *v, const formatdef *f) -{ - long x; - unsigned short y; - if (get_long(v, &x) < 0) - return -1; - if (x < 0 || x > USHRT_MAX){ - PyErr_SetString(StructError, - "ushort format requires 0 <= number <= " STRINGIFY(USHRT_MAX)); - return -1; - } - y = (unsigned short)x; - memcpy(p, (char *)&y, sizeof y); - return 0; -} - -static int -np_int(char *p, PyObject *v, const formatdef *f) -{ - long x; - int y; - if (get_long(v, &x) < 0) - return -1; -#if (SIZEOF_LONG > SIZEOF_INT) - if ((x < ((long)INT_MIN)) || (x > ((long)INT_MAX))) - RANGE_ERROR(x, f, 0, -1); -#endif - y = (int)x; - memcpy(p, (char *)&y, sizeof y); - return 0; -} - -static int -np_uint(char *p, PyObject *v, const formatdef *f) -{ - unsigned long x; - unsigned int y; - if (get_ulong(v, &x) < 0) - return -1; - y = (unsigned int)x; -#if (SIZEOF_LONG > SIZEOF_INT) - if (x > ((unsigned long)UINT_MAX)) - RANGE_ERROR(y, f, 1, -1); -#endif - memcpy(p, (char *)&y, sizeof y); - return 0; -} - -static int -np_long(char *p, PyObject *v, const formatdef *f) -{ - long x; - if (get_long(v, &x) < 0) - return -1; - memcpy(p, (char *)&x, sizeof x); - return 0; -} - -static int -np_ulong(char *p, PyObject *v, const formatdef *f) -{ - unsigned long x; - if (get_ulong(v, &x) < 0) - return -1; - memcpy(p, (char *)&x, sizeof x); - return 0; -} - -static int -np_ssize_t(char *p, PyObject *v, const formatdef *f) -{ - Py_ssize_t x; - if (get_ssize_t(v, &x) < 0) - return -1; - memcpy(p, (char *)&x, sizeof x); - return 0; -} - -static int -np_size_t(char *p, PyObject *v, const formatdef *f) -{ - size_t x; - if (get_size_t(v, &x) < 0) - return -1; - memcpy(p, (char *)&x, sizeof x); - return 0; -} - -#ifdef HAVE_LONG_LONG - -static int -np_longlong(char *p, PyObject *v, const formatdef *f) -{ - PY_LONG_LONG x; - if (get_longlong(v, &x) < 0) - return -1; - memcpy(p, (char *)&x, sizeof x); - return 0; -} - -static int -np_ulonglong(char *p, PyObject *v, const formatdef *f) -{ - unsigned PY_LONG_LONG x; - if (get_ulonglong(v, &x) < 0) - return -1; - memcpy(p, (char *)&x, sizeof x); - return 0; -} -#endif - - -static int -np_bool(char *p, PyObject *v, const formatdef *f) -{ - int y; - BOOL_TYPE x; - y = PyObject_IsTrue(v); - if (y < 0) - return -1; - x = y; - memcpy(p, (char *)&x, sizeof x); - return 0; -} - -static int -np_float(char *p, PyObject *v, const formatdef *f) -{ - float x = (float)PyFloat_AsDouble(v); - if (x == -1 && PyErr_Occurred()) { - PyErr_SetString(StructError, - "required argument is not a float"); - return -1; - } - memcpy(p, (char *)&x, sizeof x); - return 0; -} - -static int -np_double(char *p, PyObject *v, const formatdef *f) -{ - double x = PyFloat_AsDouble(v); - if (x == -1 && PyErr_Occurred()) { - PyErr_SetString(StructError, - "required argument is not a float"); - return -1; - } - memcpy(p, (char *)&x, sizeof(double)); - return 0; -} - -static int -np_complex_float(char *p, PyObject *v, const formatdef *f) -{ - if (PyArray_IsZeroDim(v)) { - PyObject *v_cast = PyArray_Cast( - reinterpret_cast<PyArrayObject *>(v), - NPY_CFLOAT); - if (!v_cast) - return -1; - memcpy(p, PyArray_DATA(v_cast), PyArray_NBYTES(v_cast)); - Py_DECREF(v_cast); - } - else { - float re = 0.0f; - float im = 0.0f; - Py_complex cplx = PyComplex_AsCComplex(v); - if (PyErr_Occurred()) { - PyErr_SetString(StructError, - "required argument is not a complex"); - return -1; - } - - re = (float)cplx.real; - im = (float)cplx.imag; - memcpy(p, (char *)&re, sizeof re); - memcpy(p+sizeof re, (char *)&im, sizeof im); - } - return 0; -} - -static int -np_complex_double(char *p, PyObject *v, const formatdef *f) -{ - if (PyArray_IsZeroDim(v)) { - PyObject *v_cast = PyArray_Cast( - reinterpret_cast<PyArrayObject *>(v), - NPY_CDOUBLE); - if (!v_cast) - return -1; - memcpy(p, PyArray_DATA(v_cast), PyArray_NBYTES(v_cast)); - Py_DECREF(v_cast); - } - else { - double re = 0.0; - double im = 0.0; - Py_complex cplx = PyComplex_AsCComplex(v); - if (PyErr_Occurred()) { - PyErr_SetString(StructError, - "required argument is not a complex"); - return -1; - } - re = cplx.real; - im = cplx.imag; - memcpy(p, (char *)&re, sizeof re); - memcpy(p+sizeof re, (char *)&im, sizeof im); - } - return 0; -} - - -static int -np_void_p(char *p, PyObject *v, const formatdef *f) -{ - void *x; - - v = get_pylong(v); - if (v == NULL) - return -1; - assert(PyLong_Check(v)); - x = PyLong_AsVoidPtr(v); - Py_DECREF(v); - if (x == NULL && PyErr_Occurred()) - return -1; - memcpy(p, (char *)&x, sizeof x); - return 0; -} - -static formatdef native_table[] = { - {'x', sizeof(char), 0, NULL}, - {'b', sizeof(char), 0, nu_byte, np_byte}, - {'B', sizeof(char), 0, nu_ubyte, np_ubyte}, - {'c', sizeof(char), 0, nu_char, np_char}, - {'s', sizeof(char), 0, NULL}, - {'p', sizeof(char), 0, NULL}, - {'h', sizeof(short), SHORT_ALIGN, nu_short, np_short}, - {'H', sizeof(short), SHORT_ALIGN, nu_ushort, np_ushort}, - {'i', sizeof(int), INT_ALIGN, nu_int, np_int}, - {'I', sizeof(int), INT_ALIGN, nu_uint, np_uint}, - {'l', sizeof(long), LONG_ALIGN, nu_long, np_long}, - {'L', sizeof(long), LONG_ALIGN, nu_ulong, np_ulong}, - {'n', sizeof(size_t), SIZE_T_ALIGN, nu_ssize_t, np_ssize_t}, - {'N', sizeof(size_t), SIZE_T_ALIGN, nu_size_t, np_size_t}, -#ifdef HAVE_LONG_LONG - {'q', sizeof(PY_LONG_LONG), LONG_LONG_ALIGN, nu_longlong, np_longlong}, - {'Q', sizeof(PY_LONG_LONG), LONG_LONG_ALIGN, nu_ulonglong,np_ulonglong}, -#endif - {'?', sizeof(BOOL_TYPE), BOOL_ALIGN, nu_bool, np_bool}, - {'f', sizeof(float), FLOAT_ALIGN, nu_float, np_float}, - {'d', sizeof(double), DOUBLE_ALIGN, nu_double, np_double}, - {'F', 2*sizeof(float), FLOAT_ALIGN, nu_complex_float, np_complex_float}, - {'D', 2*sizeof(double), DOUBLE_ALIGN, nu_complex_double, np_complex_double}, - {'P', sizeof(void *), VOID_P_ALIGN, nu_void_p, np_void_p}, - {0} -}; - -// }}} - -static const formatdef * -whichtable(char **pfmt) -{ - const char *fmt = (*pfmt)++; /* May be backed out of later */ - switch (*fmt) { - default: - --*pfmt; /* Back out of pointer increment */ - /* Fall through */ - case '@': - return native_table; - } -} - - -/* Get the table entry for a format code */ - -static const formatdef * -getentry(int c, const formatdef *f) -{ - for (; f->format != '\0'; f++) { - if (f->format == c) { - return f; - } - } - PyErr_SetString(StructError, "bad char in struct format"); - return NULL; -} - - -/* Align a size according to a format code. Return -1 on overflow. */ - -static Py_ssize_t -align(Py_ssize_t size, char c, const formatdef *e) -{ - Py_ssize_t extra; - - if (e->format == c) { - if (e->alignment && size > 0) { - extra = (e->alignment - 1) - (size - 1) % (e->alignment); - if (extra > PY_SSIZE_T_MAX - size) - return -1; - size += extra; - } - } - return size; -} - - -/* calculate the size of a format string */ - -static int -prepare_s(PyStructObject *self) -{ - const formatdef *f; - const formatdef *e; - formatcode *codes; - - const char *s; - const char *fmt; - char c; - Py_ssize_t size, len, num, itemsize; - - fmt = PyBytes_AS_STRING(self->s_format); - - f = whichtable((char **)&fmt); - - s = fmt; - size = 0; - len = 0; - while ((c = *s++) != '\0') { - if (isspace(Py_CHARMASK(c))) - continue; - if ('0' <= c && c <= '9') { - num = c - '0'; - while ('0' <= (c = *s++) && c <= '9') { - /* overflow-safe version of - if (num*10 + (c - '0') > PY_SSIZE_T_MAX) { ... } */ - if (num >= PY_SSIZE_T_MAX / 10 && ( - num > PY_SSIZE_T_MAX / 10 || - (c - '0') > PY_SSIZE_T_MAX % 10)) - goto overflow; - num = num*10 + (c - '0'); - } - if (c == '\0') { - PyErr_SetString(StructError, - "repeat count given without format specifier"); - return -1; - } - } - else - num = 1; - - e = getentry(c, f); - if (e == NULL) - return -1; - - switch (c) { - case 's': /* fall through */ - case 'p': len++; break; - case 'x': break; - default: len += num; break; - } - - itemsize = e->size; - size = align(size, c, e); - if (size == -1) - goto overflow; - - /* if (size + num * itemsize > PY_SSIZE_T_MAX) { ... } */ - if (num > (PY_SSIZE_T_MAX - size) / itemsize) - goto overflow; - size += num * itemsize; - } - - /* check for overflow */ - if ((len + 1) > (PY_SSIZE_T_MAX / sizeof(formatcode))) { - PyErr_NoMemory(); - return -1; - } - - self->s_size = size; - self->s_len = len; - codes = (formatcode *) PyMem_MALLOC((len + 1) * sizeof(formatcode)); - if (codes == NULL) { - PyErr_NoMemory(); - return -1; - } - /* Free any s_codes value left over from a previous initialization. */ - if (self->s_codes != NULL) - PyMem_FREE(self->s_codes); - self->s_codes = codes; - - s = fmt; - size = 0; - while ((c = *s++) != '\0') { - if (isspace(Py_CHARMASK(c))) - continue; - if ('0' <= c && c <= '9') { - num = c - '0'; - while ('0' <= (c = *s++) && c <= '9') - num = num*10 + (c - '0'); - if (c == '\0') - break; - } - else - num = 1; - - e = getentry(c, f); - - size = align(size, c, e); - if (c == 's' || c == 'p') { - codes->offset = size; - codes->size = num; - codes->fmtdef = e; - codes++; - size += num; - } else if (c == 'x') { - size += num; - } else { - while (--num >= 0) { - codes->offset = size; - codes->size = e->size; - codes->fmtdef = e; - codes++; - size += e->size; - } - } - } - codes->fmtdef = NULL; - codes->offset = size; - codes->size = 0; - - return 0; - - overflow: - PyErr_SetString(StructError, - "total struct size too long"); - return -1; -} - -static PyObject * -s_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyObject *self; - - assert(type != NULL && type->tp_alloc != NULL); - - self = type->tp_alloc(type, 0); - if (self != NULL) { - PyStructObject *s = (PyStructObject*)self; - Py_INCREF(Py_None); - s->s_format = Py_None; - s->s_codes = NULL; - s->s_size = -1; - s->s_len = -1; - } - return self; -} - -static int -s_init(PyObject *self, PyObject *args, PyObject *kwds) -{ - PyStructObject *soself = (PyStructObject *)self; - PyObject *o_format = NULL; - int ret = 0; - static char *kwlist[] = {"format", 0}; - - assert(PyStruct_Check(self)); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:Struct", kwlist, - &o_format)) - return -1; - - if (PyUnicode_Check(o_format)) { - o_format = PyUnicode_AsASCIIString(o_format); - if (o_format == NULL) - return -1; - } - /* XXX support buffer interface, too */ - else { - Py_INCREF(o_format); - } - - if (!PyBytes_Check(o_format)) { - Py_DECREF(o_format); - PyErr_Format(PyExc_TypeError, - "Struct() argument 1 must be a bytes object, not %.200s", - Py_TYPE(o_format)->tp_name); - return -1; - } - - Py_CLEAR(soself->s_format); - soself->s_format = o_format; - - ret = prepare_s(soself); - return ret; -} - -static void -s_dealloc(PyStructObject *s) -{ - if (s->weakreflist != NULL) - PyObject_ClearWeakRefs((PyObject *)s); - if (s->s_codes != NULL) { - PyMem_FREE(s->s_codes); - } - Py_XDECREF(s->s_format); - Py_TYPE(s)->tp_free((PyObject *)s); -} - -static PyObject * -s_unpack_internal(PyStructObject *soself, char *startfrom) { - formatcode *code; - Py_ssize_t i = 0; - PyObject *result = PyTuple_New(soself->s_len); - if (result == NULL) - return NULL; - - for (code = soself->s_codes; code->fmtdef != NULL; code++) { - PyObject *v; - const formatdef *e = code->fmtdef; - const char *res = startfrom + code->offset; - if (e->format == 's') { - v = PyBytes_FromStringAndSize(res, code->size); - } else if (e->format == 'p') { - Py_ssize_t n = *(unsigned char*)res; - if (n >= code->size) - n = code->size - 1; - v = PyBytes_FromStringAndSize(res + 1, n); - } else { - v = e->unpack(res, e); - } - if (v == NULL) - goto fail; - PyTuple_SET_ITEM(result, i++, v); - } - - return result; -fail: - Py_DECREF(result); - return NULL; -} - - -PyDoc_STRVAR(s_unpack__doc__, -"S.unpack(buffer) -> (v1, v2, ...)\n\ -\n\ -Return a tuple containing values unpacked according to the format\n\ -string S.format. Requires len(buffer) == S.size. See help(struct)\n\ -for more on format strings."); - -static PyObject * -s_unpack(PyObject *self, PyObject *input) -{ - Py_buffer vbuf; - PyObject *result; - PyStructObject *soself = (PyStructObject *)self; - - assert(PyStruct_Check(self)); - assert(soself->s_codes != NULL); - if (PyObject_GetBuffer(input, &vbuf, PyBUF_SIMPLE) < 0) - return NULL; - if (vbuf.len != soself->s_size) { - PyErr_Format(StructError, - "unpack requires a bytes object of length %zd", - soself->s_size); - PyBuffer_Release(&vbuf); - return NULL; - } - result = s_unpack_internal(soself, (char *) vbuf.buf); - PyBuffer_Release(&vbuf); - return result; -} - -PyDoc_STRVAR(s_unpack_from__doc__, -"S.unpack_from(buffer, offset=0) -> (v1, v2, ...)\n\ -\n\ -Return a tuple containing values unpacked according to the format\n\ -string S.format. Requires len(buffer[offset:]) >= S.size. See\n\ -help(struct) for more on format strings."); - -static PyObject * -s_unpack_from(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"buffer", "offset", 0}; - - PyObject *input; - Py_ssize_t offset = 0; - Py_buffer vbuf; - PyObject *result; - PyStructObject *soself = (PyStructObject *)self; - - assert(PyStruct_Check(self)); - assert(soself->s_codes != NULL); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, - "O|n:unpack_from", kwlist, - &input, &offset)) - return NULL; - if (PyObject_GetBuffer(input, &vbuf, PyBUF_SIMPLE) < 0) - return NULL; - if (offset < 0) - offset += vbuf.len; - if (offset < 0 || vbuf.len - offset < soself->s_size) { - PyErr_Format(StructError, - "unpack_from requires a buffer of at least %zd bytes", - soself->s_size); - PyBuffer_Release(&vbuf); - return NULL; - } - result = s_unpack_internal(soself, (char*)vbuf.buf + offset); - PyBuffer_Release(&vbuf); - return result; -} - - -/* - * Guts of the pack function. - * - * Takes a struct object, a tuple of arguments, and offset in that tuple of - * argument for where to start processing the arguments for packing, and a - * character buffer for writing the packed string. The caller must insure - * that the buffer may contain the required length for packing the arguments. - * 0 is returned on success, 1 is returned if there is an error. - * - */ -static int -s_pack_internal(PyStructObject *soself, PyObject *args, int offset, char* buf) -{ - formatcode *code; - /* XXX(nnorwitz): why does i need to be a local? can we use - the offset parameter or do we need the wider width? */ - Py_ssize_t i; - - memset(buf, '\0', soself->s_size); - i = offset; - for (code = soself->s_codes; code->fmtdef != NULL; code++) { - Py_ssize_t n; - PyObject *v = PyTuple_GET_ITEM(args, i++); - const formatdef *e = code->fmtdef; - char *res = buf + code->offset; - if (e->format == 's') { - int isstring; - void *p; - if (PyBytes_Check(v)) { - n = PyBytes_GET_SIZE(v); - p = PyBytes_AS_STRING(v); - - if (n > code->size) - n = code->size; - if (n > 0) - memcpy(res, p, n); - } else if (PyByteArray_Check(v)) { - n = PyByteArray_GET_SIZE(v); - p = PyByteArray_AS_STRING(v); - - if (n > code->size) - n = code->size; - if (n > 0) - memcpy(res, p, n); - } else if (PyObject_CheckBuffer(v)) { - Py_buffer view; - int gb_result = PyObject_GetBuffer(v, &view, PyBUF_SIMPLE); - - if (gb_result == -1) - return gb_result; - - n = view.len; - if (n > code->size) - n = code->size; - if (n > 0) - memcpy(res, view.buf, n); - - PyBuffer_Release(&view); - } else { - PyErr_SetString(StructError, - "argument for 's' must be a bytes object"); - return -1; - } - } else if (e->format == 'p') { - int isstring; - void *p; - isstring = PyBytes_Check(v); - if (!isstring && !PyByteArray_Check(v)) { - PyErr_SetString(StructError, - "argument for 'p' must be a bytes object"); - return -1; - } - if (isstring) { - n = PyBytes_GET_SIZE(v); - p = PyBytes_AS_STRING(v); - } - else { - n = PyByteArray_GET_SIZE(v); - p = PyByteArray_AS_STRING(v); - } - if (n > (code->size - 1)) - n = code->size - 1; - if (n > 0) - memcpy(res + 1, p, n); - if (n > 255) - n = 255; - *res = Py_SAFE_DOWNCAST(n, Py_ssize_t, unsigned char); - } else { - if (e->pack(res, v, e) < 0) { - if (PyLong_Check(v) && PyErr_ExceptionMatches(PyExc_OverflowError)) - PyErr_SetString(StructError, - "long too large to convert to int"); - return -1; - } - } - } - - /* Success */ - return 0; -} - - -PyDoc_STRVAR(s_pack__doc__, -"S.pack(v1, v2, ...) -> bytes\n\ -\n\ -Return a bytes object containing values v1, v2, ... packed according\n\ -to the format string S.format. See help(struct) for more on format\n\ -strings."); - -static PyObject * -s_pack(PyObject *self, PyObject *args) -{ - PyStructObject *soself; - PyObject *result; - - /* Validate arguments. */ - soself = (PyStructObject *)self; - assert(PyStruct_Check(self)); - assert(soself->s_codes != NULL); - if (PyTuple_GET_SIZE(args) != soself->s_len) - { - PyErr_Format(StructError, - "pack requires exactly %zd arguments", soself->s_len); - return NULL; - } - - /* Allocate a new string */ - result = PyBytes_FromStringAndSize((char *)NULL, soself->s_size); - if (result == NULL) - return NULL; - - /* Call the guts */ - if ( s_pack_internal(soself, args, 0, PyBytes_AS_STRING(result)) != 0 ) { - Py_DECREF(result); - return NULL; - } - - return result; -} - -PyDoc_STRVAR(s_pack_into__doc__, -"S.pack_into(buffer, offset, v1, v2, ...)\n\ -\n\ -Pack the values v1, v2, ... according to the format string S.format\n\ -and write the packed bytes into the writable buffer buf starting at\n\ -offset. Note that the offset is a required argument. See\n\ -help(struct) for more on format strings."); - -static PyObject * -s_pack_into(PyObject *self, PyObject *args) -{ - PyStructObject *soself; - char *buffer; - Py_ssize_t buffer_len, offset; - - /* Validate arguments. +1 is for the first arg as buffer. */ - soself = (PyStructObject *)self; - assert(PyStruct_Check(self)); - assert(soself->s_codes != NULL); - if (PyTuple_GET_SIZE(args) != (soself->s_len + 2)) - { - PyErr_Format(StructError, - "pack_into requires exactly %zd arguments", - (soself->s_len + 2)); - return NULL; - } - - /* Extract a writable memory buffer from the first argument */ - if ( PyObject_AsWriteBuffer(PyTuple_GET_ITEM(args, 0), - (void**)&buffer, &buffer_len) == -1 ) { - return NULL; - } - assert( buffer_len >= 0 ); - - /* Extract the offset from the first argument */ - offset = PyNumber_AsSsize_t(PyTuple_GET_ITEM(args, 1), PyExc_IndexError); - if (offset == -1 && PyErr_Occurred()) - return NULL; - - /* Support negative offsets. */ - if (offset < 0) - offset += buffer_len; - - /* Check boundaries */ - if (offset < 0 || (buffer_len - offset) < soself->s_size) { - PyErr_Format(StructError, - "pack_into requires a buffer of at least %zd bytes", - soself->s_size); - return NULL; - } - - /* Call the guts */ - if ( s_pack_internal(soself, args, 2, buffer + offset) != 0 ) { - return NULL; - } - - Py_RETURN_NONE; -} - -static PyObject * -s_get_format(PyStructObject *self, void *unused) -{ - Py_INCREF(self->s_format); - return self->s_format; -} - -static PyObject * -s_get_size(PyStructObject *self, void *unused) -{ - return PyLong_FromSsize_t(self->s_size); -} - -/* List of functions */ - -static struct PyMethodDef s_methods[] = { - {"pack", s_pack, METH_VARARGS, s_pack__doc__}, - {"pack_into", s_pack_into, METH_VARARGS, s_pack_into__doc__}, - {"unpack", s_unpack, METH_O, s_unpack__doc__}, - {"unpack_from", (PyCFunction)s_unpack_from, METH_VARARGS|METH_KEYWORDS, - s_unpack_from__doc__}, - {NULL, NULL} /* sentinel */ -}; - -PyDoc_STRVAR(s__doc__, -"Struct(fmt) --> compiled struct object\n" -"\n" -"Return a new Struct object which writes and reads binary data according to\n" -"the format string fmt. See help(struct) for more on format strings."); - -#define OFF(x) offsetof(PyStructObject, x) - -static PyGetSetDef s_getsetlist[] = { - {"format", (getter)s_get_format, (setter)NULL, "struct format string", NULL}, - {"size", (getter)s_get_size, (setter)NULL, "struct size in bytes", NULL}, - {NULL} /* sentinel */ -}; - -namespace { -PyTypeObject PyStructType = { - PyVarObject_HEAD_INIT(NULL, 0) - "Struct", - sizeof(PyStructObject), - 0, - (destructor)s_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - PyObject_GenericSetAttr, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - s__doc__, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - offsetof(PyStructObject, weakreflist), /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - s_methods, /* tp_methods */ - NULL, /* tp_members */ - s_getsetlist, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - s_init, /* tp_init */ - PyType_GenericAlloc,/* tp_alloc */ - s_new, /* tp_new */ - PyObject_Del, /* tp_free */ -}; -} - - -/* ---- Standalone functions ---- */ - -#define MAXCACHE 100 -static PyObject *cache = NULL; - -static PyObject * -cache_struct(PyObject *fmt) -{ - PyObject * s_object; - - if (cache == NULL) { - cache = PyDict_New(); - if (cache == NULL) - return NULL; - } - - s_object = PyDict_GetItem(cache, fmt); - if (s_object != NULL) { - Py_INCREF(s_object); - return s_object; - } - - s_object = PyObject_CallFunctionObjArgs((PyObject *)(&PyStructType), fmt, NULL); - if (s_object != NULL) { - if (PyDict_Size(cache) >= MAXCACHE) - PyDict_Clear(cache); - /* Attempt to cache the result */ - if (PyDict_SetItem(cache, fmt, s_object) == -1) - PyErr_Clear(); - } - return s_object; -} - -PyDoc_STRVAR(clearcache_doc, -"Clear the internal cache."); - -static PyObject * -clearcache(PyObject *self) -{ - Py_CLEAR(cache); - Py_RETURN_NONE; -} - -PyDoc_STRVAR(calcsize_doc, -"calcsize(fmt) -> integer\n\ -\n\ -Return size in bytes of the struct described by the format string fmt."); - -static PyObject * -calcsize(PyObject *self, PyObject *fmt) -{ - Py_ssize_t n; - PyObject *s_object = cache_struct(fmt); - if (s_object == NULL) - return NULL; - n = ((PyStructObject *)s_object)->s_size; - Py_DECREF(s_object); - return PyLong_FromSsize_t(n); -} - -PyDoc_STRVAR(pack_doc, -"pack(fmt, v1, v2, ...) -> bytes\n\ -\n\ -Return a bytes object containing the values v1, v2, ... packed according\n\ -to the format string fmt. See help(struct) for more on format strings."); - -static PyObject * -pack(PyObject *self, PyObject *args) -{ - PyObject *s_object, *fmt, *newargs, *result; - Py_ssize_t n = PyTuple_GET_SIZE(args); - - if (n == 0) { - PyErr_SetString(PyExc_TypeError, "missing format argument"); - return NULL; - } - fmt = PyTuple_GET_ITEM(args, 0); - newargs = PyTuple_GetSlice(args, 1, n); - if (newargs == NULL) - return NULL; - - s_object = cache_struct(fmt); - if (s_object == NULL) { - Py_DECREF(newargs); - return NULL; - } - result = s_pack(s_object, newargs); - Py_DECREF(newargs); - Py_DECREF(s_object); - return result; -} - -PyDoc_STRVAR(pack_into_doc, -"pack_into(fmt, buffer, offset, v1, v2, ...)\n\ -\n\ -Pack the values v1, v2, ... according to the format string fmt and write\n\ -the packed bytes into the writable buffer buf starting at offset. Note\n\ -that the offset is a required argument. See help(struct) for more\n\ -on format strings."); - -static PyObject * -pack_into(PyObject *self, PyObject *args) -{ - PyObject *s_object, *fmt, *newargs, *result; - Py_ssize_t n = PyTuple_GET_SIZE(args); - - if (n == 0) { - PyErr_SetString(PyExc_TypeError, "missing format argument"); - return NULL; - } - fmt = PyTuple_GET_ITEM(args, 0); - newargs = PyTuple_GetSlice(args, 1, n); - if (newargs == NULL) - return NULL; - - s_object = cache_struct(fmt); - if (s_object == NULL) { - Py_DECREF(newargs); - return NULL; - } - result = s_pack_into(s_object, newargs); - Py_DECREF(newargs); - Py_DECREF(s_object); - return result; -} - -PyDoc_STRVAR(unpack_doc, -"unpack(fmt, buffer) -> (v1, v2, ...)\n\ -\n\ -Return a tuple containing values unpacked according to the format string\n\ -fmt. Requires len(buffer) == calcsize(fmt). See help(struct) for more\n\ -on format strings."); - -static PyObject * -unpack(PyObject *self, PyObject *args) -{ - PyObject *s_object, *fmt, *inputstr, *result; - - if (!PyArg_UnpackTuple(args, "unpack", 2, 2, &fmt, &inputstr)) - return NULL; - - s_object = cache_struct(fmt); - if (s_object == NULL) - return NULL; - result = s_unpack(s_object, inputstr); - Py_DECREF(s_object); - return result; -} - -PyDoc_STRVAR(unpack_from_doc, -"unpack_from(fmt, buffer, offset=0) -> (v1, v2, ...)\n\ -\n\ -Return a tuple containing values unpacked according to the format string\n\ -fmt. Requires len(buffer[offset:]) >= calcsize(fmt). See help(struct)\n\ -for more on format strings."); - -static PyObject * -unpack_from(PyObject *self, PyObject *args, PyObject *kwds) -{ - PyObject *s_object, *fmt, *newargs, *result; - Py_ssize_t n = PyTuple_GET_SIZE(args); - - if (n == 0) { - PyErr_SetString(PyExc_TypeError, "missing format argument"); - return NULL; - } - fmt = PyTuple_GET_ITEM(args, 0); - newargs = PyTuple_GetSlice(args, 1, n); - if (newargs == NULL) - return NULL; - - s_object = cache_struct(fmt); - if (s_object == NULL) { - Py_DECREF(newargs); - return NULL; - } - result = s_unpack_from(s_object, newargs, kwds); - Py_DECREF(newargs); - Py_DECREF(s_object); - return result; -} - -static struct PyMethodDef module_functions[] = { - {"_clearcache", (PyCFunction)clearcache, METH_NOARGS, clearcache_doc}, - {"calcsize", calcsize, METH_O, calcsize_doc}, - {"pack", pack, METH_VARARGS, pack_doc}, - {"pack_into", pack_into, METH_VARARGS, pack_into_doc}, - {"unpack", unpack, METH_VARARGS, unpack_doc}, - {"unpack_from", (PyCFunction)unpack_from, - METH_VARARGS|METH_KEYWORDS, unpack_from_doc}, - {NULL, NULL} /* sentinel */ -}; - - -/* Module initialization */ - -PyDoc_STRVAR(module_doc, -"Functions to convert between Python values and C structs.\n\ -Python bytes objects are used to hold the data representing the C struct\n\ -and also as format strings (explained below) to describe the layout of data\n\ -in the C struct.\n\ -\n\ -The optional first format char indicates byte order, size and alignment:\n\ - @: native order, size & alignment (default)\n\ - =: native order, std. size & alignment\n\ - <: little-endian, std. size & alignment\n\ - >: big-endian, std. size & alignment\n\ - !: same as >\n\ -\n\ -The remaining chars indicate types of args and must match exactly;\n\ -these can be preceded by a decimal repeat count:\n\ - x: pad byte (no data); c:char; b:signed byte; B:unsigned byte;\n\ - ?: _Bool (requires C99; if not available, char is used instead)\n\ - h:short; H:unsigned short; i:int; I:unsigned int;\n\ - l:long; L:unsigned long; f:float; d:double.\n\ -Special cases (preceding decimal count indicates length):\n\ - s:string (array of char); p: pascal string (with count byte).\n\ -Special cases (only available in native format):\n\ - n:ssize_t; N:size_t;\n\ - P:an integer type that is wide enough to hold a pointer.\n\ -Special case (not in native mode unless 'long long' in platform C):\n\ - q:long long; Q:unsigned long long\n\ -Whitespace between formats is ignored.\n\ -\n\ -The variable struct.error is an exception raised on errors.\n"); - - -static struct PyModuleDef _structmodule = { - PyModuleDef_HEAD_INIT, - "_struct", - module_doc, - -1, - module_functions, - NULL, - NULL, - NULL, - NULL -}; - -extern "C" -PyMODINIT_FUNC -PyInit__pvt_struct(void) -{ - PyObject *m; - - m = PyModule_Create(&_structmodule); - if (m == NULL) - return NULL; - - Py_TYPE(&PyStructType) = &PyType_Type; - if (PyType_Ready(&PyStructType) < 0) - return NULL; - - /* Add some symbolic constants to the module */ - if (StructError == NULL) { - StructError = PyErr_NewException("struct.error", NULL, NULL); - if (StructError == NULL) - return NULL; - } - - Py_INCREF(StructError); - PyModule_AddObject(m, "error", StructError); - - Py_INCREF((PyObject*)&PyStructType); - PyModule_AddObject(m, "Struct", (PyObject*)&PyStructType); - - return m; -} - -// vim: fdm=marker diff --git a/src/wrapper/bitlog.cpp b/src/wrapper/bitlog.cpp deleted file mode 100644 index 88b820fa..00000000 --- a/src/wrapper/bitlog.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "bitlog.hpp" - - - - -/* from http://graphics.stanford.edu/~seander/bithacks.html */ -const char pyopencl::log_table_8[] = -{ - 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 -}; - - diff --git a/src/wrapper/bitlog.hpp b/src/wrapper/bitlog.hpp deleted file mode 100644 index 405599e7..00000000 --- a/src/wrapper/bitlog.hpp +++ /dev/null @@ -1,53 +0,0 @@ -// Base-2 logarithm bithack. - - - - -#ifndef _AFJDFJSDFSD_PYOPENCL_HEADER_SEEN_BITLOG_HPP -#define _AFJDFJSDFSD_PYOPENCL_HEADER_SEEN_BITLOG_HPP - - - - -#include <climits> -#include <boost/cstdint.hpp> - - - - -namespace pyopencl -{ - extern const char log_table_8[]; - - inline unsigned bitlog2_16(boost::uint16_t v) - { - if (unsigned long t = v >> 8) - return 8+log_table_8[t]; - else - return log_table_8[v]; - } - - inline unsigned bitlog2_32(boost::uint32_t v) - { - if (boost::uint16_t t = v >> 16) - return 16+bitlog2_16(t); - else - return bitlog2_16(v); - } - - inline unsigned bitlog2(unsigned long v) - { -#if (ULONG_MAX != 4294967295) - if (boost::uint32_t t = v >> 32) - return 32+bitlog2_32(t); - else -#endif - return bitlog2_32(v); - } -} - - - - - -#endif diff --git a/src/wrapper/mempool.hpp b/src/wrapper/mempool.hpp deleted file mode 100644 index be88f13f..00000000 --- a/src/wrapper/mempool.hpp +++ /dev/null @@ -1,376 +0,0 @@ -// Abstract memory pool implementation - - - - -#ifndef _AFJDFJSDFSD_PYGPU_HEADER_SEEN_MEMPOOL_HPP -#define _AFJDFJSDFSD_PYGPU_HEADER_SEEN_MEMPOOL_HPP - - - - -#include <boost/ptr_container/ptr_map.hpp> -#include <boost/foreach.hpp> -#include <boost/format.hpp> -#include "bitlog.hpp" - - - - -namespace PYGPU_PACKAGE -{ - template <class T> - inline T signed_left_shift(T x, signed shift_amount) - { - if (shift_amount < 0) - return x >> -shift_amount; - else - return x << shift_amount; - } - - - - - template <class T> - inline T signed_right_shift(T x, signed shift_amount) - { - if (shift_amount < 0) - return x << -shift_amount; - else - return x >> shift_amount; - } - - - - - template<class Allocator> - class memory_pool - { - public: - typedef typename Allocator::pointer_type pointer_type; - typedef typename Allocator::size_type size_type; - - private: - typedef boost::uint32_t bin_nr_t; - typedef std::vector<pointer_type> bin_t; - - typedef boost::ptr_map<bin_nr_t, bin_t > container_t; - container_t m_container; - typedef typename container_t::value_type bin_pair_t; - - std::auto_ptr<Allocator> m_allocator; - - // A held block is one that's been released by the application, but that - // we are keeping around to dish out again. - unsigned m_held_blocks; - - // An active block is one that is in use by the application. - unsigned m_active_blocks; - - bool m_stop_holding; - int m_trace; - - public: - memory_pool(Allocator const &alloc=Allocator()) - : m_allocator(alloc.copy()), - m_held_blocks(0), m_active_blocks(0), m_stop_holding(false), - m_trace(false) - { - if (m_allocator->is_deferred()) - { - PyErr_WarnEx(PyExc_UserWarning, "Memory pools expect non-deferred " - "semantics from their allocators. You passed a deferred " - "allocator, i.e. an allocator whose allocations can turn out to " - "be unavailable long after allocation.", 1); - } - } - - virtual ~memory_pool() - { free_held(); } - - static const unsigned mantissa_bits = 2; - static const unsigned mantissa_mask = (1 << mantissa_bits) - 1; - - static bin_nr_t bin_number(size_type size) - { - signed l = bitlog2(size); - size_type shifted = signed_right_shift(size, l-signed(mantissa_bits)); - if (size && (shifted & (1 << mantissa_bits)) == 0) - throw std::runtime_error("memory_pool::bin_number: bitlog2 fault"); - size_type chopped = shifted & mantissa_mask; - return l << mantissa_bits | chopped; - } - - void set_trace(bool flag) - { - if (flag) - ++m_trace; - else - --m_trace; - } - - static size_type alloc_size(bin_nr_t bin) - { - bin_nr_t exponent = bin >> mantissa_bits; - bin_nr_t mantissa = bin & mantissa_mask; - - size_type ones = signed_left_shift(1, - signed(exponent)-signed(mantissa_bits) - ); - if (ones) ones -= 1; - - size_type head = signed_left_shift( - (1<<mantissa_bits) | mantissa, - signed(exponent)-signed(mantissa_bits)); - if (ones & head) - throw std::runtime_error("memory_pool::alloc_size: bit-counting fault"); - return head | ones; - } - - protected: - bin_t &get_bin(bin_nr_t bin_nr) - { - typename container_t::iterator it = m_container.find(bin_nr); - if (it == m_container.end()) - { - bin_t *new_bin = new bin_t; - m_container.insert(bin_nr, new_bin); - return *new_bin; - } - else - return *it->second; - } - - void inc_held_blocks() - { - if (m_held_blocks == 0) - start_holding_blocks(); - ++m_held_blocks; - } - - void dec_held_blocks() - { - --m_held_blocks; - if (m_held_blocks == 0) - stop_holding_blocks(); - } - - virtual void start_holding_blocks() - { } - - virtual void stop_holding_blocks() - { } - - public: - pointer_type allocate(size_type size) - { - bin_nr_t bin_nr = bin_number(size); - bin_t &bin = get_bin(bin_nr); - - if (bin.size()) - { - if (m_trace) - std::cout - << "[pool] allocation of size " << size << " served from bin " << bin_nr - << " which contained " << bin.size() << " entries" << std::endl; - return pop_block_from_bin(bin, size); - } - - size_type alloc_sz = alloc_size(bin_nr); - - assert(bin_number(alloc_sz) == bin_nr); - - if (m_trace) - std::cout << "[pool] allocation of size " << size << " required new memory" << std::endl; - - try { return get_from_allocator(alloc_sz); } - catch (PYGPU_PACKAGE::error &e) - { - if (!e.is_out_of_memory()) - throw; - } - - if (m_trace) - std::cout << "[pool] allocation triggered OOM, running GC" << std::endl; - - m_allocator->try_release_blocks(); - if (bin.size()) - return pop_block_from_bin(bin, size); - - if (m_trace) - std::cout << "[pool] allocation still OOM after GC" << std::endl; - - while (try_to_free_memory()) - { - try { return get_from_allocator(alloc_sz); } - catch (PYGPU_PACKAGE::error &e) - { - if (!e.is_out_of_memory()) - throw; - } - } - - throw PYGPU_PACKAGE::error( - "memory_pool::allocate", -#ifdef PYGPU_PYCUDA - CUDA_ERROR_OUT_OF_MEMORY, -#endif -#ifdef PYGPU_PYOPENCL - CL_MEM_OBJECT_ALLOCATION_FAILURE, -#endif - "failed to free memory for allocation"); - } - - void free(pointer_type p, size_type size) - { - --m_active_blocks; - bin_nr_t bin_nr = bin_number(size); - - if (!m_stop_holding) - { - inc_held_blocks(); - get_bin(bin_nr).push_back(p); - - if (m_trace) - std::cout << "[pool] block of size " << size << " returned to bin " - << bin_nr << " which now contains " << get_bin(bin_nr).size() - << " entries" << std::endl; - } - else - m_allocator->free(p); - } - - void free_held() - { - BOOST_FOREACH(bin_pair_t bin_pair, m_container) - { - bin_t &bin = *bin_pair.second; - - while (bin.size()) - { - m_allocator->free(bin.back()); - bin.pop_back(); - - dec_held_blocks(); - } - } - - assert(m_held_blocks == 0); - } - - void stop_holding() - { - m_stop_holding = true; - free_held(); - } - - unsigned active_blocks() - { return m_active_blocks; } - - unsigned held_blocks() - { return m_held_blocks; } - - bool try_to_free_memory() - { - BOOST_FOREACH(bin_pair_t bin_pair, - // free largest stuff first - std::make_pair(m_container.rbegin(), m_container.rend())) - { - bin_t &bin = *bin_pair.second; - - if (bin.size()) - { - m_allocator->free(bin.back()); - bin.pop_back(); - - dec_held_blocks(); - - return true; - } - } - - return false; - } - - private: - pointer_type get_from_allocator(size_type alloc_sz) - { - pointer_type result = m_allocator->allocate(alloc_sz); - ++m_active_blocks; - - return result; - } - - pointer_type pop_block_from_bin(bin_t &bin, size_type size) - { - pointer_type result = bin.back(); - bin.pop_back(); - - dec_held_blocks(); - ++m_active_blocks; - - return result; - } - }; - - - - - - template <class Pool> - class pooled_allocation : public boost::noncopyable - { - public: - typedef Pool pool_type; - typedef typename Pool::pointer_type pointer_type; - typedef typename Pool::size_type size_type; - - private: - boost::shared_ptr<pool_type> m_pool; - - pointer_type m_ptr; - size_type m_size; - bool m_valid; - - public: - pooled_allocation(boost::shared_ptr<pool_type> p, size_type size) - : m_pool(p), m_ptr(p->allocate(size)), m_size(size), m_valid(true) - { } - - ~pooled_allocation() - { - if (m_valid) - free(); - } - - void free() - { - if (m_valid) - { - m_pool->free(m_ptr, m_size); - m_valid = false; - } - else - throw PYGPU_PACKAGE::error( - "pooled_device_allocation::free", -#ifdef PYGPU_PYCUDA - CUDA_ERROR_INVALID_HANDLE -#endif -#ifdef PYGPU_PYOPENCL - CL_INVALID_VALUE -#endif - ); - } - - pointer_type ptr() const - { return m_ptr; } - - size_type size() const - { return m_size; } - }; -} - - - - -#endif diff --git a/src/wrapper/numpy_init.hpp b/src/wrapper/numpy_init.hpp deleted file mode 100644 index 9d34ac57..00000000 --- a/src/wrapper/numpy_init.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef _FAYHVVAAA_PYOPENCL_HEADER_SEEN_NUMPY_INIT_HPP -#define _FAYHVVAAA_PYOPENCL_HEADER_SEEN_NUMPY_INIT_HPP - - - - -#include <numpy/arrayobject.h> -#include <stdexcept> - - - - -namespace -{ - static struct pyublas_array_importer - { - static bool do_import_array() - { - import_array1(false); - return true; - } - - pyublas_array_importer() - { - if (!do_import_array()) - throw std::runtime_error("numpy failed to initialize"); - } - } _array_importer; -} - - - - -#endif diff --git a/src/wrapper/tools.hpp b/src/wrapper/tools.hpp deleted file mode 100644 index 7254ace1..00000000 --- a/src/wrapper/tools.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef _ASDFDAFVVAFF_PYCUDA_HEADER_SEEN_TOOLS_HPP -#define _ASDFDAFVVAFF_PYCUDA_HEADER_SEEN_TOOLS_HPP - - - - -#include <boost/python.hpp> -#include <numeric> -#include "numpy_init.hpp" - - - - -namespace pyopencl -{ - inline - npy_intp size_from_dims(int ndim, const npy_intp *dims) - { - if (ndim != 0) - return std::accumulate(dims, dims+ndim, 1, std::multiplies<npy_intp>()); - else - return 1; - } - - - - - inline void run_python_gc() - { - namespace py = boost::python; - - py::object gc_mod( - py::handle<>( - PyImport_ImportModule("gc"))); - gc_mod.attr("collect")(); - } -} - - - - - -#endif diff --git a/src/wrapper/wrap_cl.cpp b/src/wrapper/wrap_cl.cpp deleted file mode 100644 index 9f680f2d..00000000 --- a/src/wrapper/wrap_cl.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include "wrap_cl.hpp" - - - - -using namespace pyopencl; - - - - -extern void pyopencl_expose_constants(); -extern void pyopencl_expose_part_1(); -extern void pyopencl_expose_part_2(); -extern void pyopencl_expose_mempool(); - -BOOST_PYTHON_MODULE(_cl) -{ - pyopencl_expose_constants(); - pyopencl_expose_part_1(); - pyopencl_expose_part_2(); - pyopencl_expose_mempool(); -} - -// vim: foldmethod=marker diff --git a/src/wrapper/wrap_cl.hpp b/src/wrapper/wrap_cl.hpp deleted file mode 100644 index cce59d66..00000000 --- a/src/wrapper/wrap_cl.hpp +++ /dev/null @@ -1,4013 +0,0 @@ -#ifndef _AFJHAYYTA_PYOPENCL_HEADER_SEEN_WRAP_CL_HPP -#define _AFJHAYYTA_PYOPENCL_HEADER_SEEN_WRAP_CL_HPP - -// CL 1.2 undecided: -// clSetPrintfCallback - -// {{{ includes - -#define CL_USE_DEPRECATED_OPENCL_1_1_APIS - -#ifdef __APPLE__ - -// Mac ------------------------------------------------------------------------ -#include <OpenCL/opencl.h> -#ifdef HAVE_GL - -#define PYOPENCL_GL_SHARING_VERSION 1 - -#include <OpenGL/OpenGL.h> -#include <OpenCL/cl_gl.h> -#include <OpenCL/cl_gl_ext.h> -#endif - -#else - -// elsewhere ------------------------------------------------------------------ -#include <CL/cl.h> -#include <CL/cl_ext.h> - -#if defined(_WIN32) -#define NOMINMAX -#include <windows.h> -#endif - -#ifdef HAVE_GL -#include <GL/gl.h> -#include <CL/cl_gl.h> -#endif - -#if defined(cl_khr_gl_sharing) && (cl_khr_gl_sharing >= 1) -#define PYOPENCL_GL_SHARING_VERSION cl_khr_gl_sharing -#endif - -#endif - -#include <stdexcept> -#include <iostream> -#include <vector> -#include <utility> -#include <numeric> -#include <boost/python/slice.hpp> -#include <boost/foreach.hpp> -#include <boost/scoped_array.hpp> -#include "wrap_helpers.hpp" -#include "numpy_init.hpp" -#include "tools.hpp" - -#ifdef PYOPENCL_PRETEND_CL_VERSION -#define PYOPENCL_CL_VERSION PYOPENCL_PRETEND_CL_VERSION -#else - -#if defined(CL_VERSION_1_2) -#define PYOPENCL_CL_VERSION 0x1020 -#elif defined(CL_VERSION_1_1) -#define PYOPENCL_CL_VERSION 0x1010 -#else -#define PYOPENCL_CL_VERSION 0x1000 -#endif - -#endif - -// }}} - - - - - -// {{{ tools -#if PY_VERSION_HEX >= 0x02050000 - typedef Py_ssize_t PYOPENCL_BUFFER_SIZE_T; -#else - typedef int PYOPENCL_BUFFER_SIZE_T; -#endif - -#define PYOPENCL_CAST_BOOL(B) ((B) ? CL_TRUE : CL_FALSE) - - - - - -#define PYOPENCL_DEPRECATED(WHAT, KILL_VERSION, EXTRA_MSG) \ - { \ - PyErr_Warn( \ - PyExc_DeprecationWarning, \ - WHAT " is deprecated and will stop working in PyOpenCL " KILL_VERSION". " \ - EXTRA_MSG); \ - } - -#if PYOPENCL_CL_VERSION >= 0x1020 - -#define PYOPENCL_GET_EXT_FUN(PLATFORM, NAME, VAR) \ - NAME##_fn VAR \ - = (NAME##_fn) \ - clGetExtensionFunctionAddressForPlatform(PLATFORM, #NAME); \ - \ - if (!VAR) \ - throw error(#NAME, CL_INVALID_VALUE, #NAME \ - "not available"); - -#else - -#define PYOPENCL_GET_EXT_FUN(PLATFORM, NAME, VAR) \ - NAME##_fn VAR \ - = (NAME##_fn) \ - clGetExtensionFunctionAddress(#NAME); \ - \ - if (!VAR) \ - throw error(#NAME, CL_INVALID_VALUE, #NAME \ - "not available"); - -#endif - - -#define PYOPENCL_PARSE_PY_DEVICES \ - std::vector<cl_device_id> devices_vec; \ - cl_uint num_devices; \ - cl_device_id *devices; \ - \ - if (py_devices.ptr() == Py_None) \ - { \ - num_devices = 0; \ - devices = 0; \ - } \ - else \ - { \ - PYTHON_FOREACH(py_dev, py_devices) \ - devices_vec.push_back( \ - py::extract<device &>(py_dev)().data()); \ - num_devices = devices_vec.size(); \ - devices = devices_vec.empty( ) ? NULL : &devices_vec.front(); \ - } \ - - -#define PYOPENCL_RETRY_RETURN_IF_MEM_ERROR(OPERATION) \ - try \ - { \ - OPERATION \ - } \ - catch (pyopencl::error &e) \ - { \ - if (!e.is_out_of_memory()) \ - throw; \ - } \ - \ - /* If we get here, we got an error from CL. - * We should run the Python GC to try and free up - * some memory references. */ \ - run_python_gc(); \ - \ - /* Now retry the allocation. If it fails again, - * let it fail. */ \ - { \ - OPERATION \ - } - - - - -#define PYOPENCL_RETRY_IF_MEM_ERROR(OPERATION) \ - { \ - bool failed_with_mem_error = false; \ - try \ - { \ - OPERATION \ - } \ - catch (pyopencl::error &e) \ - { \ - failed_with_mem_error = true; \ - if (!e.is_out_of_memory()) \ - throw; \ - } \ - \ - if (failed_with_mem_error) \ - { \ - /* If we get here, we got an error from CL. - * We should run the Python GC to try and free up - * some memory references. */ \ - run_python_gc(); \ - \ - /* Now retry the allocation. If it fails again, - * let it fail. */ \ - { \ - OPERATION \ - } \ - } \ - } - -// }}} - -// {{{ tracing and error reporting -#ifdef PYOPENCL_TRACE - #define PYOPENCL_PRINT_CALL_TRACE(NAME) \ - std::cerr << NAME << std::endl; - #define PYOPENCL_PRINT_CALL_TRACE_INFO(NAME, EXTRA_INFO) \ - std::cerr << NAME << " (" << EXTRA_INFO << ')' << std::endl; -#else - #define PYOPENCL_PRINT_CALL_TRACE(NAME) /*nothing*/ - #define PYOPENCL_PRINT_CALL_TRACE_INFO(NAME, EXTRA_INFO) /*nothing*/ -#endif - -#define PYOPENCL_CALL_GUARDED_THREADED_WITH_TRACE_INFO(NAME, ARGLIST, TRACE_INFO) \ - { \ - PYOPENCL_PRINT_CALL_TRACE_INFO(#NAME, TRACE_INFO); \ - cl_int status_code; \ - Py_BEGIN_ALLOW_THREADS \ - status_code = NAME ARGLIST; \ - Py_END_ALLOW_THREADS \ - if (status_code != CL_SUCCESS) \ - throw pyopencl::error(#NAME, status_code);\ - } - -#define PYOPENCL_CALL_GUARDED_WITH_TRACE_INFO(NAME, ARGLIST, TRACE_INFO) \ - { \ - PYOPENCL_PRINT_CALL_TRACE_INFO(#NAME, TRACE_INFO); \ - cl_int status_code; \ - status_code = NAME ARGLIST; \ - if (status_code != CL_SUCCESS) \ - throw pyopencl::error(#NAME, status_code);\ - } - -#define PYOPENCL_CALL_GUARDED_THREADED(NAME, ARGLIST) \ - { \ - PYOPENCL_PRINT_CALL_TRACE(#NAME); \ - cl_int status_code; \ - Py_BEGIN_ALLOW_THREADS \ - status_code = NAME ARGLIST; \ - Py_END_ALLOW_THREADS \ - if (status_code != CL_SUCCESS) \ - throw pyopencl::error(#NAME, status_code);\ - } - -#define PYOPENCL_CALL_GUARDED(NAME, ARGLIST) \ - { \ - PYOPENCL_PRINT_CALL_TRACE(#NAME); \ - cl_int status_code; \ - status_code = NAME ARGLIST; \ - if (status_code != CL_SUCCESS) \ - throw pyopencl::error(#NAME, status_code);\ - } -#define PYOPENCL_CALL_GUARDED_CLEANUP(NAME, ARGLIST) \ - { \ - PYOPENCL_PRINT_CALL_TRACE(#NAME); \ - cl_int status_code; \ - status_code = NAME ARGLIST; \ - if (status_code != CL_SUCCESS) \ - std::cerr \ - << "PyOpenCL WARNING: a clean-up operation failed (dead context maybe?)" \ - << std::endl \ - << #NAME " failed with code " << status_code \ - << std::endl; \ - } - -// }}} - -// {{{ get_info helpers -#define PYOPENCL_GET_OPAQUE_INFO(WHAT, FIRST_ARG, SECOND_ARG, CL_TYPE, TYPE) \ - { \ - CL_TYPE param_value; \ - PYOPENCL_CALL_GUARDED(clGet##WHAT##Info, \ - (FIRST_ARG, SECOND_ARG, sizeof(param_value), ¶m_value, 0)); \ - if (param_value) \ - return py::object(handle_from_new_ptr( \ - new TYPE(param_value, /*retain*/ true))); \ - else \ - return py::object(); \ - } - -#define PYOPENCL_GET_VEC_INFO(WHAT, FIRST_ARG, SECOND_ARG, RES_VEC) \ - { \ - size_t size; \ - PYOPENCL_CALL_GUARDED(clGet##WHAT##Info, \ - (FIRST_ARG, SECOND_ARG, 0, 0, &size)); \ - \ - RES_VEC.resize(size / sizeof(RES_VEC.front())); \ - \ - PYOPENCL_CALL_GUARDED(clGet##WHAT##Info, \ - (FIRST_ARG, SECOND_ARG, size, \ - RES_VEC.empty( ) ? NULL : &RES_VEC.front(), &size)); \ - } - -#define PYOPENCL_GET_STR_INFO(WHAT, FIRST_ARG, SECOND_ARG) \ - { \ - size_t param_value_size; \ - PYOPENCL_CALL_GUARDED(clGet##WHAT##Info, \ - (FIRST_ARG, SECOND_ARG, 0, 0, ¶m_value_size)); \ - \ - std::vector<char> param_value(param_value_size); \ - PYOPENCL_CALL_GUARDED(clGet##WHAT##Info, \ - (FIRST_ARG, SECOND_ARG, param_value_size, \ - param_value.empty( ) ? NULL : ¶m_value.front(), ¶m_value_size)); \ - \ - return py::object( \ - param_value.empty( ) ? "" : std::string(¶m_value.front(), param_value_size-1)); \ - } - - - - -#define PYOPENCL_GET_INTEGRAL_INFO(WHAT, FIRST_ARG, SECOND_ARG, TYPE) \ - { \ - TYPE param_value; \ - PYOPENCL_CALL_GUARDED(clGet##WHAT##Info, \ - (FIRST_ARG, SECOND_ARG, sizeof(param_value), ¶m_value, 0)); \ - return py::object(param_value); \ - } - -// }}} - -// {{{ event helpers -------------------------------------------------------------- -#define PYOPENCL_PARSE_WAIT_FOR \ - cl_uint num_events_in_wait_list = 0; \ - std::vector<cl_event> event_wait_list; \ - \ - if (py_wait_for.ptr() != Py_None) \ - { \ - event_wait_list.resize(len(py_wait_for)); \ - PYTHON_FOREACH(evt, py_wait_for) \ - event_wait_list[num_events_in_wait_list++] = \ - py::extract<event &>(evt)().data(); \ - } - -#define PYOPENCL_WAITLIST_ARGS \ - num_events_in_wait_list, event_wait_list.empty( ) ? NULL : &event_wait_list.front() - -#define PYOPENCL_RETURN_NEW_NANNY_EVENT(evt, obj) \ - try \ - { \ - return new nanny_event(evt, false, obj); \ - } \ - catch (...) \ - { \ - clReleaseEvent(evt); \ - throw; \ - } - -#define PYOPENCL_RETURN_NEW_EVENT(evt) \ - try \ - { \ - return new event(evt, false); \ - } \ - catch (...) \ - { \ - clReleaseEvent(evt); \ - throw; \ - } - -// }}} - -// {{{ equality testing -#define PYOPENCL_EQUALITY_TESTS(cls) \ - bool operator==(cls const &other) const \ - { return data() == other.data(); } \ - bool operator!=(cls const &other) const \ - { return data() != other.data(); } \ - long hash() const \ - { return (long) (intptr_t) data(); } -// }}} - - - -namespace pyopencl -{ - // {{{ error - class error : public std::runtime_error - { - private: - const char *m_routine; - cl_int m_code; - - public: - error(const char *rout, cl_int c, const char *msg="") - : std::runtime_error(msg), m_routine(rout), m_code(c) - { } - - const char *routine() const - { - return m_routine; - } - - cl_int code() const - { - return m_code; - } - - bool is_out_of_memory() const - { - return (code() == CL_MEM_OBJECT_ALLOCATION_FAILURE - || code() == CL_OUT_OF_RESOURCES - || code() == CL_OUT_OF_HOST_MEMORY); - } - - }; - - // }}} - - inline - py::tuple get_cl_header_version() - { - return py::make_tuple( - PYOPENCL_CL_VERSION >> (3*4), - (PYOPENCL_CL_VERSION >> (1*4)) & 0xff - ); - } - - // {{{ platform - class platform : boost::noncopyable - { - private: - cl_platform_id m_platform; - - public: - platform(cl_platform_id pid) - : m_platform(pid) - { } - - platform(cl_platform_id pid, bool /*retain (ignored)*/) - : m_platform(pid) - { } - - cl_platform_id data() const - { - return m_platform; - } - - PYOPENCL_EQUALITY_TESTS(platform); - - py::object get_info(cl_platform_info param_name) const - { - switch (param_name) - { - case CL_PLATFORM_PROFILE: - case CL_PLATFORM_VERSION: - case CL_PLATFORM_NAME: - case CL_PLATFORM_VENDOR: -#if !(defined(CL_PLATFORM_NVIDIA) && CL_PLATFORM_NVIDIA == 0x3001) - case CL_PLATFORM_EXTENSIONS: -#endif - PYOPENCL_GET_STR_INFO(Platform, m_platform, param_name); - - default: - throw error("Platform.get_info", CL_INVALID_VALUE); - } - } - - py::list get_devices(cl_device_type devtype); - }; - - - - - inline - py::list get_platforms() - { - cl_uint num_platforms = 0; - PYOPENCL_CALL_GUARDED(clGetPlatformIDs, (0, 0, &num_platforms)); - - std::vector<cl_platform_id> platforms(num_platforms); - PYOPENCL_CALL_GUARDED(clGetPlatformIDs, - (num_platforms, platforms.empty( ) ? NULL : &platforms.front(), &num_platforms)); - - py::list result; - BOOST_FOREACH(cl_platform_id pid, platforms) - result.append(handle_from_new_ptr( - new platform(pid))); - - return result; - } - - // }}} - - // {{{ device - class device : boost::noncopyable - { - public: - enum reference_type_t { - REF_NOT_OWNABLE, - REF_FISSION_EXT, -#if PYOPENCL_CL_VERSION >= 0x1020 - REF_CL_1_2, -#endif - }; - private: - cl_device_id m_device; - reference_type_t m_ref_type; - - public: - device(cl_device_id did) - : m_device(did), m_ref_type(REF_NOT_OWNABLE) - { } - - device(cl_device_id did, bool retain, reference_type_t ref_type=REF_NOT_OWNABLE) - : m_device(did), m_ref_type(ref_type) - { - if (retain && ref_type != REF_NOT_OWNABLE) - { - if (false) - { } -#if (defined(cl_ext_device_fission) && defined(PYOPENCL_USE_DEVICE_FISSION)) - else if (ref_type == REF_FISSION_EXT) - { -#if PYOPENCL_CL_VERSION >= 0x1020 - cl_platform_id plat; - PYOPENCL_CALL_GUARDED(clGetDeviceInfo, (m_device, CL_DEVICE_PLATFORM, - sizeof(plat), &plat, NULL)); -#endif - - PYOPENCL_GET_EXT_FUN(plat, - clRetainDeviceEXT, retain_func); - - PYOPENCL_CALL_GUARDED(retain_func, (did)); - } -#endif - -#if PYOPENCL_CL_VERSION >= 0x1020 - else if (ref_type == REF_CL_1_2) - { - PYOPENCL_CALL_GUARDED(clRetainDevice, (did)); - } -#endif - - else - throw error("Device", CL_INVALID_VALUE, - "cannot own references to devices when device fission or CL 1.2 is not available"); - } - } - - ~device() - { - if (false) - { } -#if defined(cl_ext_device_fission) && defined(PYOPENCL_USE_DEVICE_FISSION) - else if (m_ref_type == REF_FISSION_EXT) - { -#if PYOPENCL_CL_VERSION >= 0x1020 - cl_platform_id plat; - PYOPENCL_CALL_GUARDED(clGetDeviceInfo, (m_device, CL_DEVICE_PLATFORM, - sizeof(plat), &plat, NULL)); -#endif - - PYOPENCL_GET_EXT_FUN(plat, - clReleaseDeviceEXT, release_func); - - PYOPENCL_CALL_GUARDED_CLEANUP(release_func, (m_device)); - } -#endif - -#if PYOPENCL_CL_VERSION >= 0x1020 - else if (m_ref_type == REF_CL_1_2) - PYOPENCL_CALL_GUARDED(clReleaseDevice, (m_device)); -#endif - } - - cl_device_id data() const - { - return m_device; - } - - PYOPENCL_EQUALITY_TESTS(device); - - py::object get_info(cl_device_info param_name) const - { -#define DEV_GET_INT_INF(TYPE) \ - PYOPENCL_GET_INTEGRAL_INFO(Device, m_device, param_name, TYPE); - - switch (param_name) - { - case CL_DEVICE_TYPE: DEV_GET_INT_INF(cl_device_type); - case CL_DEVICE_VENDOR_ID: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_MAX_COMPUTE_UNITS: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_MAX_WORK_GROUP_SIZE: DEV_GET_INT_INF(size_t); - - case CL_DEVICE_MAX_WORK_ITEM_SIZES: - { - std::vector<size_t> result; - PYOPENCL_GET_VEC_INFO(Device, m_device, param_name, result); - PYOPENCL_RETURN_VECTOR(size_t, result); - } - - case CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE: DEV_GET_INT_INF(cl_uint); - - case CL_DEVICE_MAX_CLOCK_FREQUENCY: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_ADDRESS_BITS: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_MAX_READ_IMAGE_ARGS: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_MAX_WRITE_IMAGE_ARGS: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_MAX_MEM_ALLOC_SIZE: DEV_GET_INT_INF(cl_ulong); - case CL_DEVICE_IMAGE2D_MAX_WIDTH: DEV_GET_INT_INF(size_t); - case CL_DEVICE_IMAGE2D_MAX_HEIGHT: DEV_GET_INT_INF(size_t); - case CL_DEVICE_IMAGE3D_MAX_WIDTH: DEV_GET_INT_INF(size_t); - case CL_DEVICE_IMAGE3D_MAX_HEIGHT: DEV_GET_INT_INF(size_t); - case CL_DEVICE_IMAGE3D_MAX_DEPTH: DEV_GET_INT_INF(size_t); - case CL_DEVICE_IMAGE_SUPPORT: DEV_GET_INT_INF(cl_bool); - case CL_DEVICE_MAX_PARAMETER_SIZE: DEV_GET_INT_INF(size_t); - case CL_DEVICE_MAX_SAMPLERS: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_MEM_BASE_ADDR_ALIGN: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_SINGLE_FP_CONFIG: DEV_GET_INT_INF(cl_device_fp_config); -#ifdef CL_DEVICE_DOUBLE_FP_CONFIG - case CL_DEVICE_DOUBLE_FP_CONFIG: DEV_GET_INT_INF(cl_device_fp_config); -#endif -#ifdef CL_DEVICE_HALF_FP_CONFIG - case CL_DEVICE_HALF_FP_CONFIG: DEV_GET_INT_INF(cl_device_fp_config); -#endif - - case CL_DEVICE_GLOBAL_MEM_CACHE_TYPE: DEV_GET_INT_INF(cl_device_mem_cache_type); - case CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_GLOBAL_MEM_CACHE_SIZE: DEV_GET_INT_INF(cl_ulong); - case CL_DEVICE_GLOBAL_MEM_SIZE: DEV_GET_INT_INF(cl_ulong); - - case CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE: DEV_GET_INT_INF(cl_ulong); - case CL_DEVICE_MAX_CONSTANT_ARGS: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_LOCAL_MEM_TYPE: DEV_GET_INT_INF(cl_device_local_mem_type); - case CL_DEVICE_LOCAL_MEM_SIZE: DEV_GET_INT_INF(cl_ulong); - case CL_DEVICE_ERROR_CORRECTION_SUPPORT: DEV_GET_INT_INF(cl_bool); - case CL_DEVICE_PROFILING_TIMER_RESOLUTION: DEV_GET_INT_INF(size_t); - case CL_DEVICE_ENDIAN_LITTLE: DEV_GET_INT_INF(cl_bool); - case CL_DEVICE_AVAILABLE: DEV_GET_INT_INF(cl_bool); - case CL_DEVICE_COMPILER_AVAILABLE: DEV_GET_INT_INF(cl_bool); - case CL_DEVICE_EXECUTION_CAPABILITIES: DEV_GET_INT_INF(cl_device_exec_capabilities); - case CL_DEVICE_QUEUE_PROPERTIES: DEV_GET_INT_INF(cl_command_queue_properties); - - case CL_DEVICE_NAME: - case CL_DEVICE_VENDOR: - case CL_DRIVER_VERSION: - case CL_DEVICE_PROFILE: - case CL_DEVICE_VERSION: - case CL_DEVICE_EXTENSIONS: - PYOPENCL_GET_STR_INFO(Device, m_device, param_name); - - case CL_DEVICE_PLATFORM: - PYOPENCL_GET_OPAQUE_INFO(Device, m_device, param_name, cl_platform_id, platform); - -#if PYOPENCL_CL_VERSION >= 0x1010 - case CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF: DEV_GET_INT_INF(cl_uint); - - case CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_NATIVE_VECTOR_WIDTH_INT: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF: DEV_GET_INT_INF(cl_uint); - - case CL_DEVICE_HOST_UNIFIED_MEMORY: DEV_GET_INT_INF(cl_bool); - case CL_DEVICE_OPENCL_C_VERSION: - PYOPENCL_GET_STR_INFO(Device, m_device, param_name); -#endif -#ifdef CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV - case CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV: - case CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV: - case CL_DEVICE_REGISTERS_PER_BLOCK_NV: - case CL_DEVICE_WARP_SIZE_NV: - DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_GPU_OVERLAP_NV: - case CL_DEVICE_KERNEL_EXEC_TIMEOUT_NV: - case CL_DEVICE_INTEGRATED_MEMORY_NV: - DEV_GET_INT_INF(cl_bool); -#endif -#if defined(cl_ext_device_fission) && defined(PYOPENCL_USE_DEVICE_FISSION) - case CL_DEVICE_PARENT_DEVICE_EXT: - PYOPENCL_GET_OPAQUE_INFO(Device, m_device, param_name, cl_device_id, device); - case CL_DEVICE_PARTITION_TYPES_EXT: - case CL_DEVICE_AFFINITY_DOMAINS_EXT: - case CL_DEVICE_PARTITION_STYLE_EXT: - { - std::vector<cl_device_partition_property_ext> result; - PYOPENCL_GET_VEC_INFO(Device, m_device, param_name, result); - PYOPENCL_RETURN_VECTOR(cl_device_partition_property_ext, result); - } - case CL_DEVICE_REFERENCE_COUNT_EXT: DEV_GET_INT_INF(cl_uint); -#endif -#if PYOPENCL_CL_VERSION >= 0x1020 - case CL_DEVICE_LINKER_AVAILABLE: DEV_GET_INT_INF(cl_bool); - case CL_DEVICE_BUILT_IN_KERNELS: - PYOPENCL_GET_STR_INFO(Device, m_device, param_name); - case CL_DEVICE_IMAGE_MAX_BUFFER_SIZE: DEV_GET_INT_INF(size_t); - case CL_DEVICE_IMAGE_MAX_ARRAY_SIZE: DEV_GET_INT_INF(size_t); - case CL_DEVICE_PARENT_DEVICE: - PYOPENCL_GET_OPAQUE_INFO(Device, m_device, param_name, cl_device_id, device); - case CL_DEVICE_PARTITION_MAX_SUB_DEVICES: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_PARTITION_TYPE: - case CL_DEVICE_PARTITION_PROPERTIES: - { - std::vector<cl_device_partition_property> result; - PYOPENCL_GET_VEC_INFO(Device, m_device, param_name, result); - PYOPENCL_RETURN_VECTOR(cl_device_partition_property, result); - } - case CL_DEVICE_PARTITION_AFFINITY_DOMAIN: - { - std::vector<cl_device_affinity_domain> result; - PYOPENCL_GET_VEC_INFO(Device, m_device, param_name, result); - PYOPENCL_RETURN_VECTOR(cl_device_affinity_domain, result); - } - case CL_DEVICE_REFERENCE_COUNT: DEV_GET_INT_INF(cl_uint); - case CL_DEVICE_PREFERRED_INTEROP_USER_SYNC: DEV_GET_INT_INF(cl_bool); - case CL_DEVICE_PRINTF_BUFFER_SIZE: DEV_GET_INT_INF(cl_bool); -#endif -// {{{ AMD dev attrs -// -// types of AMD dev attrs divined from -// https://www.khronos.org/registry/cl/api/1.2/cl.hpp -#ifdef CL_DEVICE_PROFILING_TIMER_OFFSET_AMD - case CL_DEVICE_PROFILING_TIMER_OFFSET_AMD: DEV_GET_INT_INF(cl_ulong); -#endif -/* FIXME -#ifdef CL_DEVICE_TOPOLOGY_AMD - case CL_DEVICE_TOPOLOGY_AMD: -#endif -*/ -#ifdef CL_DEVICE_BOARD_NAME_AMD - case CL_DEVICE_BOARD_NAME_AMD: ; - PYOPENCL_GET_STR_INFO(Device, m_device, param_name); -#endif -#ifdef CL_DEVICE_GLOBAL_FREE_MEMORY_AMD - case CL_DEVICE_GLOBAL_FREE_MEMORY_AMD: - { - std::vector<size_t> result; - PYOPENCL_GET_VEC_INFO(Device, m_device, param_name, result); - PYOPENCL_RETURN_VECTOR(size_t, result); - } -#endif -#ifdef CL_DEVICE_SIMD_PER_COMPUTE_UNIT_AMD - case CL_DEVICE_SIMD_PER_COMPUTE_UNIT_AMD: DEV_GET_INT_INF(cl_uint); -#endif -#ifdef CL_DEVICE_SIMD_WIDTH_AMD - case CL_DEVICE_SIMD_WIDTH_AMD: DEV_GET_INT_INF(cl_uint); -#endif -#ifdef CL_DEVICE_SIMD_INSTRUCTION_WIDTH_AMD - case CL_DEVICE_SIMD_INSTRUCTION_WIDTH_AMD: DEV_GET_INT_INF(cl_uint); -#endif -#ifdef CL_DEVICE_WAVEFRONT_WIDTH_AMD - case CL_DEVICE_WAVEFRONT_WIDTH_AMD: DEV_GET_INT_INF(cl_uint); -#endif -#ifdef CL_DEVICE_GLOBAL_MEM_CHANNELS_AMD - case CL_DEVICE_GLOBAL_MEM_CHANNELS_AMD: DEV_GET_INT_INF(cl_uint); -#endif -#ifdef CL_DEVICE_GLOBAL_MEM_CHANNEL_BANKS_AMD - case CL_DEVICE_GLOBAL_MEM_CHANNEL_BANKS_AMD: DEV_GET_INT_INF(cl_uint); -#endif -#ifdef CL_DEVICE_GLOBAL_MEM_CHANNEL_BANK_WIDTH_AMD - case CL_DEVICE_GLOBAL_MEM_CHANNEL_BANK_WIDTH_AMD: DEV_GET_INT_INF(cl_uint); -#endif -#ifdef CL_DEVICE_LOCAL_MEM_SIZE_PER_COMPUTE_UNIT_AMD - case CL_DEVICE_LOCAL_MEM_SIZE_PER_COMPUTE_UNIT_AMD: DEV_GET_INT_INF(cl_uint); -#endif -#ifdef CL_DEVICE_LOCAL_MEM_BANKS_AMD - case CL_DEVICE_LOCAL_MEM_BANKS_AMD: DEV_GET_INT_INF(cl_uint); -#endif -// }}} - -#ifdef CL_DEVICE_MAX_ATOMIC_COUNTERS_EXT - case CL_DEVICE_MAX_ATOMIC_COUNTERS_EXT: DEV_GET_INT_INF(cl_uint); -#endif - - default: - throw error("Device.get_info", CL_INVALID_VALUE); - } - } - -#if PYOPENCL_CL_VERSION >= 0x1020 - py::list create_sub_devices(py::object py_properties) - { - std::vector<cl_device_partition_property> properties; - - COPY_PY_LIST(cl_device_partition_property, properties); - properties.push_back(0); - - cl_device_partition_property *props_ptr - = properties.empty( ) ? NULL : &properties.front(); - - cl_uint num_entries; - PYOPENCL_CALL_GUARDED(clCreateSubDevices, - (m_device, props_ptr, 0, NULL, &num_entries)); - - std::vector<cl_device_id> result; - result.resize(num_entries); - - PYOPENCL_CALL_GUARDED(clCreateSubDevices, - (m_device, props_ptr, num_entries, &result.front(), NULL)); - - py::list py_result; - BOOST_FOREACH(cl_device_id did, result) - py_result.append(handle_from_new_ptr( - new pyopencl::device(did, /*retain*/true, - device::REF_CL_1_2))); - return py_result; - } -#endif - -#if defined(cl_ext_device_fission) && defined(PYOPENCL_USE_DEVICE_FISSION) - py::list create_sub_devices_ext(py::object py_properties) - { - std::vector<cl_device_partition_property_ext> properties; - -#if PYOPENCL_CL_VERSION >= 0x1020 - cl_platform_id plat; - PYOPENCL_CALL_GUARDED(clGetDeviceInfo, (m_device, CL_DEVICE_PLATFORM, - sizeof(plat), &plat, NULL)); -#endif - - PYOPENCL_GET_EXT_FUN(plat, clCreateSubDevicesEXT, create_sub_dev); - - COPY_PY_LIST(cl_device_partition_property_ext, properties); - properties.push_back(CL_PROPERTIES_LIST_END_EXT); - - cl_device_partition_property_ext *props_ptr - = properties.empty( ) ? NULL : &properties.front(); - - cl_uint num_entries; - PYOPENCL_CALL_GUARDED(create_sub_dev, - (m_device, props_ptr, 0, NULL, &num_entries)); - - std::vector<cl_device_id> result; - result.resize(num_entries); - - PYOPENCL_CALL_GUARDED(create_sub_dev, - (m_device, props_ptr, num_entries, &result.front(), NULL)); - - py::list py_result; - BOOST_FOREACH(cl_device_id did, result) - py_result.append(handle_from_new_ptr( - new pyopencl::device(did, /*retain*/true, - device::REF_FISSION_EXT))); - return py_result; - } -#endif - - }; - - - - - inline py::list platform::get_devices(cl_device_type devtype) - { - cl_uint num_devices = 0; - PYOPENCL_CALL_GUARDED(clGetDeviceIDs, - (m_platform, devtype, 0, 0, &num_devices)); - if (num_devices == 0) - return py::list(); - - std::vector<cl_device_id> devices(num_devices); - PYOPENCL_CALL_GUARDED(clGetDeviceIDs, - (m_platform, devtype, - num_devices, devices.empty( ) ? NULL : &devices.front(), &num_devices)); - - py::list result; - BOOST_FOREACH(cl_device_id did, devices) - result.append(handle_from_new_ptr( - new device(did))); - - return result; - } - - // }}} - - // {{{ context - class context : public boost::noncopyable - { - private: - cl_context m_context; - - public: - context(cl_context ctx, bool retain) - : m_context(ctx) - { - if (retain) - PYOPENCL_CALL_GUARDED(clRetainContext, (ctx)); - } - - - ~context() - { - PYOPENCL_CALL_GUARDED_CLEANUP(clReleaseContext, - (m_context)); - } - - cl_context data() const - { - return m_context; - } - - PYOPENCL_EQUALITY_TESTS(context); - - py::object get_info(cl_context_info param_name) const - { - switch (param_name) - { - case CL_CONTEXT_REFERENCE_COUNT: - PYOPENCL_GET_INTEGRAL_INFO( - Context, m_context, param_name, cl_uint); - - case CL_CONTEXT_DEVICES: - { - std::vector<cl_device_id> result; - PYOPENCL_GET_VEC_INFO(Context, m_context, param_name, result); - - py::list py_result; - BOOST_FOREACH(cl_device_id did, result) - py_result.append(handle_from_new_ptr( - new pyopencl::device(did))); - return py_result; - } - - case CL_CONTEXT_PROPERTIES: - { - std::vector<cl_context_properties> result; - PYOPENCL_GET_VEC_INFO(Context, m_context, param_name, result); - - py::list py_result; - for (size_t i = 0; i < result.size(); i+=2) - { - cl_context_properties key = result[i]; - py::object value; - switch (key) - { - case CL_CONTEXT_PLATFORM: - { - value = py::object( - handle_from_new_ptr(new platform( - reinterpret_cast<cl_platform_id>(result[i+1])))); - break; - } - -#if defined(PYOPENCL_GL_SHARING_VERSION) && (PYOPENCL_GL_SHARING_VERSION >= 1) -#if defined(__APPLE__) && defined(HAVE_GL) - case CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE: -#else - case CL_GL_CONTEXT_KHR: - case CL_EGL_DISPLAY_KHR: - case CL_GLX_DISPLAY_KHR: - case CL_WGL_HDC_KHR: - case CL_CGL_SHAREGROUP_KHR: -#endif - value = py::object(result[i+1]); - break; - -#endif - case 0: - break; - - default: - throw error("Context.get_info", CL_INVALID_VALUE, - "unknown context_property key encountered"); - } - - py_result.append(py::make_tuple(result[i], value)); - } - return py_result; - } - -#if PYOPENCL_CL_VERSION >= 0x1010 - case CL_CONTEXT_NUM_DEVICES: - PYOPENCL_GET_INTEGRAL_INFO( - Context, m_context, param_name, cl_uint); -#endif - - default: - throw error("Context.get_info", CL_INVALID_VALUE); - } - } - }; - - - - - inline - std::vector<cl_context_properties> parse_context_properties( - py::object py_properties) - { - std::vector<cl_context_properties> props; - - if (py_properties.ptr() != Py_None) - { - PYTHON_FOREACH(prop_tuple, py_properties) - { - if (len(prop_tuple) != 2) - throw error("Context", CL_INVALID_VALUE, "property tuple must have length 2"); - cl_context_properties prop = - py::extract<cl_context_properties>(prop_tuple[0]); - props.push_back(prop); - - if (prop == CL_CONTEXT_PLATFORM) - { - py::extract<const platform &> value(prop_tuple[1]); - props.push_back( - reinterpret_cast<cl_context_properties>(value().data())); - } -#if defined(PYOPENCL_GL_SHARING_VERSION) && (PYOPENCL_GL_SHARING_VERSION >= 1) -#if defined(_WIN32) - else if (prop == CL_WGL_HDC_KHR) - { - // size_t is a stand-in for HANDLE, hopefully has the same size. - size_t hnd = py::extract<size_t>(prop_tuple[1]); - props.push_back(hnd); - } -#endif - else if ( -#if defined(__APPLE__) && defined(HAVE_GL) - prop == CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE -#else - prop == CL_GL_CONTEXT_KHR - || prop == CL_EGL_DISPLAY_KHR - || prop == CL_GLX_DISPLAY_KHR - || prop == CL_CGL_SHAREGROUP_KHR -#endif - ) - { - py::object ctypes = py::import("ctypes"); - py::object prop = prop_tuple[1], c_void_p = ctypes.attr("c_void_p"); - py::object ptr = ctypes.attr("cast")(prop, c_void_p); - py::extract<cl_context_properties> value(ptr.attr("value")); - props.push_back(value); - } -#endif - else - throw error("Context", CL_INVALID_VALUE, "invalid context property"); - } - props.push_back(0); - } - - return props; - } - - - - - inline - context *create_context_inner(py::object py_devices, py::object py_properties, - py::object py_dev_type) - { - std::vector<cl_context_properties> props - = parse_context_properties(py_properties); - - cl_context_properties *props_ptr - = props.empty( ) ? NULL : &props.front(); - - cl_int status_code; - - cl_context ctx; - - // from device list - if (py_devices.ptr() != Py_None) - { - if (py_dev_type.ptr() != Py_None) - throw error("Context", CL_INVALID_VALUE, - "one of 'devices' or 'dev_type' must be None"); - - std::vector<cl_device_id> devices; - PYTHON_FOREACH(py_dev, py_devices) - { - py::extract<const device &> dev(py_dev); - devices.push_back(dev().data()); - } - - PYOPENCL_PRINT_CALL_TRACE("clCreateContext"); - ctx = clCreateContext( - props_ptr, - devices.size(), - devices.empty( ) ? NULL : &devices.front(), - 0, 0, &status_code); - } - // from dev_type - else - { - cl_device_type dev_type = CL_DEVICE_TYPE_DEFAULT; - if (py_dev_type.ptr() != Py_None) - dev_type = py::extract<cl_device_type>(py_dev_type)(); - - PYOPENCL_PRINT_CALL_TRACE("clCreateContextFromType"); - ctx = clCreateContextFromType(props_ptr, dev_type, 0, 0, &status_code); - } - - if (status_code != CL_SUCCESS) - throw pyopencl::error("Context", status_code); - - try - { - return new context(ctx, false); - } - catch (...) - { - PYOPENCL_CALL_GUARDED(clReleaseContext, (ctx)); - throw; - } - } - - - - - inline - context *create_context(py::object py_devices, py::object py_properties, - py::object py_dev_type) - { - PYOPENCL_RETRY_RETURN_IF_MEM_ERROR( - return create_context_inner(py_devices, py_properties, py_dev_type); - ) - } - - - - - - // }}} - - // {{{ command_queue - class command_queue - { - private: - cl_command_queue m_queue; - - public: - command_queue(cl_command_queue q, bool retain) - : m_queue(q) - { - if (retain) - PYOPENCL_CALL_GUARDED(clRetainCommandQueue, (q)); - } - - command_queue(command_queue const &src) - : m_queue(src.m_queue) - { - PYOPENCL_CALL_GUARDED(clRetainCommandQueue, (m_queue)); - } - - command_queue( - const context &ctx, - const device *py_dev=0, - cl_command_queue_properties props=0) - { - cl_device_id dev; - if (py_dev) - dev = py_dev->data(); - else - { - std::vector<cl_device_id> devs; - PYOPENCL_GET_VEC_INFO(Context, ctx.data(), CL_CONTEXT_DEVICES, devs); - if (devs.size() == 0) - throw pyopencl::error("CommandQueue", CL_INVALID_VALUE, - "context doesn't have any devices? -- don't know which one to default to"); - dev = devs[0]; - } - - cl_int status_code; - PYOPENCL_PRINT_CALL_TRACE("clCreateCommandQueue"); - m_queue = clCreateCommandQueue( - ctx.data(), dev, props, &status_code); - - if (status_code != CL_SUCCESS) - throw pyopencl::error("CommandQueue", status_code); - } - - ~command_queue() - { - PYOPENCL_CALL_GUARDED_CLEANUP(clReleaseCommandQueue, - (m_queue)); - } - - const cl_command_queue data() const - { return m_queue; } - - PYOPENCL_EQUALITY_TESTS(command_queue); - - py::object get_info(cl_command_queue_info param_name) const - { - switch (param_name) - { - case CL_QUEUE_CONTEXT: - PYOPENCL_GET_OPAQUE_INFO(CommandQueue, m_queue, param_name, - cl_context, context); - case CL_QUEUE_DEVICE: - PYOPENCL_GET_OPAQUE_INFO(CommandQueue, m_queue, param_name, - cl_device_id, device); - case CL_QUEUE_REFERENCE_COUNT: - PYOPENCL_GET_INTEGRAL_INFO(CommandQueue, m_queue, param_name, - cl_uint); - case CL_QUEUE_PROPERTIES: - PYOPENCL_GET_INTEGRAL_INFO(CommandQueue, m_queue, param_name, - cl_command_queue_properties); - - default: - throw error("CommandQueue.get_info", CL_INVALID_VALUE); - } - } - - std::auto_ptr<context> get_context() const - { - cl_context param_value; - PYOPENCL_CALL_GUARDED(clGetCommandQueueInfo, - (m_queue, CL_QUEUE_CONTEXT, sizeof(param_value), ¶m_value, 0)); - return std::auto_ptr<context>( - new context(param_value, /*retain*/ true)); - } - -#if PYOPENCL_CL_VERSION < 0x1010 - cl_command_queue_properties set_property( - cl_command_queue_properties prop, - bool enable) - { - cl_command_queue_properties old_prop; - PYOPENCL_CALL_GUARDED(clSetCommandQueueProperty, - (m_queue, prop, PYOPENCL_CAST_BOOL(enable), &old_prop)); - return old_prop; - } -#endif - - void flush() - { PYOPENCL_CALL_GUARDED(clFlush, (m_queue)); } - void finish() - { PYOPENCL_CALL_GUARDED_THREADED(clFinish, (m_queue)); } - }; - - // }}} - - // {{{ event/synchronization - class event : boost::noncopyable - { - private: - cl_event m_event; - - public: - event(cl_event event, bool retain) - : m_event(event) - { - if (retain) - PYOPENCL_CALL_GUARDED(clRetainEvent, (event)); - } - - event(event const &src) - : m_event(src.m_event) - { PYOPENCL_CALL_GUARDED(clRetainEvent, (m_event)); } - - virtual ~event() - { - PYOPENCL_CALL_GUARDED_CLEANUP(clReleaseEvent, - (m_event)); - } - - const cl_event data() const - { return m_event; } - - PYOPENCL_EQUALITY_TESTS(event); - - py::object get_info(cl_event_info param_name) const - { - switch (param_name) - { - case CL_EVENT_COMMAND_QUEUE: - PYOPENCL_GET_OPAQUE_INFO(Event, m_event, param_name, - cl_command_queue, command_queue); - case CL_EVENT_COMMAND_TYPE: - PYOPENCL_GET_INTEGRAL_INFO(Event, m_event, param_name, - cl_command_type); - case CL_EVENT_COMMAND_EXECUTION_STATUS: - PYOPENCL_GET_INTEGRAL_INFO(Event, m_event, param_name, - cl_int); - case CL_EVENT_REFERENCE_COUNT: - PYOPENCL_GET_INTEGRAL_INFO(Event, m_event, param_name, - cl_uint); -#if PYOPENCL_CL_VERSION >= 0x1010 - case CL_EVENT_CONTEXT: - PYOPENCL_GET_OPAQUE_INFO(Event, m_event, param_name, - cl_context, context); -#endif - - default: - throw error("Event.get_info", CL_INVALID_VALUE); - } - } - - py::object get_profiling_info(cl_profiling_info param_name) const - { - switch (param_name) - { - case CL_PROFILING_COMMAND_QUEUED: - case CL_PROFILING_COMMAND_SUBMIT: - case CL_PROFILING_COMMAND_START: - case CL_PROFILING_COMMAND_END: - PYOPENCL_GET_INTEGRAL_INFO(EventProfiling, m_event, param_name, - cl_ulong); - default: - throw error("Event.get_profiling_info", CL_INVALID_VALUE); - } - } - - virtual void wait() - { - PYOPENCL_CALL_GUARDED_THREADED(clWaitForEvents, (1, &m_event)); - } - }; - - class nanny_event : public event - { - // In addition to everything an event does, the nanny event holds a reference - // to a Python object and waits for its own completion upon destruction. - - protected: - py::object m_ward; - - public: - - nanny_event(cl_event evt, bool retain, py::object ward) - : event(evt, retain), m_ward(ward) - { } - - nanny_event(nanny_event const &src) - : event(src), m_ward(src.m_ward) - { } - - ~nanny_event() - { wait(); } - - py::object get_ward() const - { return m_ward; } - - virtual void wait() - { - event::wait(); - m_ward = py::object(); - } - }; - - - - - inline - void wait_for_events(py::object events) - { - cl_uint num_events_in_wait_list = 0; - std::vector<cl_event> event_wait_list(len(events)); - - PYTHON_FOREACH(evt, events) - event_wait_list[num_events_in_wait_list++] = - py::extract<event &>(evt)().data(); - - PYOPENCL_CALL_GUARDED_THREADED(clWaitForEvents, ( - PYOPENCL_WAITLIST_ARGS)); - } - - - - -#if PYOPENCL_CL_VERSION >= 0x1020 - inline - event *enqueue_marker_with_wait_list(command_queue &cq, - py::object py_wait_for) - { - PYOPENCL_PARSE_WAIT_FOR; - cl_event evt; - - PYOPENCL_CALL_GUARDED(clEnqueueMarkerWithWaitList, ( - cq.data(), PYOPENCL_WAITLIST_ARGS, &evt)); - - PYOPENCL_RETURN_NEW_EVENT(evt); - } - - inline - event *enqueue_barrier_with_wait_list(command_queue &cq, - py::object py_wait_for) - { - PYOPENCL_PARSE_WAIT_FOR; - cl_event evt; - - PYOPENCL_CALL_GUARDED(clEnqueueBarrierWithWaitList, - (cq.data(), PYOPENCL_WAITLIST_ARGS, &evt)); - - PYOPENCL_RETURN_NEW_EVENT(evt); - } -#endif - - - // {{{ used internally for pre-OpenCL-1.2 contexts - - inline - event *enqueue_marker(command_queue &cq) - { - cl_event evt; - - PYOPENCL_CALL_GUARDED(clEnqueueMarker, ( - cq.data(), &evt)); - - PYOPENCL_RETURN_NEW_EVENT(evt); - } - - inline - void enqueue_wait_for_events(command_queue &cq, py::object py_events) - { - cl_uint num_events = 0; - std::vector<cl_event> event_list(len(py_events)); - - PYTHON_FOREACH(py_evt, py_events) - event_list[num_events++] = - py::extract<event &>(py_evt)().data(); - - PYOPENCL_CALL_GUARDED(clEnqueueWaitForEvents, ( - cq.data(), num_events, event_list.empty( ) ? NULL : &event_list.front())); - } - - inline - void enqueue_barrier(command_queue &cq) - { - PYOPENCL_CALL_GUARDED(clEnqueueBarrier, (cq.data())); - } - - // }}} - - -#if PYOPENCL_CL_VERSION >= 0x1010 - class user_event : public event - { - public: - user_event(cl_event evt, bool retain) - : event(evt, retain) - { } - - void set_status(cl_int execution_status) - { - PYOPENCL_CALL_GUARDED(clSetUserEventStatus, (data(), execution_status)); - } - }; - - - - - inline - event *create_user_event(context &ctx) - { - cl_int status_code; - PYOPENCL_PRINT_CALL_TRACE("clCreateUserEvent"); - cl_event evt = clCreateUserEvent(ctx.data(), &status_code); - - if (status_code != CL_SUCCESS) - throw pyopencl::error("UserEvent", status_code); - - try - { - return new user_event(evt, false); - } - catch (...) - { - clReleaseEvent(evt); - throw; - } - } - -#endif - - // }}} - - // {{{ memory_object - - py::object create_mem_object_wrapper(cl_mem mem); - - class memory_object_holder - { - public: - virtual const cl_mem data() const = 0; - - PYOPENCL_EQUALITY_TESTS(memory_object_holder); - - size_t size() const - { - size_t param_value; - PYOPENCL_CALL_GUARDED(clGetMemObjectInfo, - (data(), CL_MEM_SIZE, sizeof(param_value), ¶m_value, 0)); - return param_value; - } - - py::object get_info(cl_mem_info param_name) const; - }; - - - - - class memory_object : boost::noncopyable, public memory_object_holder - { - private: - bool m_valid; - cl_mem m_mem; - py::object m_hostbuf; - - public: - memory_object(cl_mem mem, bool retain, py::object *hostbuf=0) - : m_valid(true), m_mem(mem) - { - if (retain) - PYOPENCL_CALL_GUARDED(clRetainMemObject, (mem)); - - if (hostbuf) - m_hostbuf = *hostbuf; - } - - memory_object(memory_object const &src) - : m_valid(true), m_mem(src.m_mem), m_hostbuf(src.m_hostbuf) - { - PYOPENCL_CALL_GUARDED(clRetainMemObject, (m_mem)); - } - - memory_object(memory_object_holder const &src) - : m_valid(true), m_mem(src.data()) - { - PYOPENCL_CALL_GUARDED(clRetainMemObject, (m_mem)); - } - - void release() - { - if (!m_valid) - throw error("MemoryObject.free", CL_INVALID_VALUE, - "trying to double-unref mem object"); - PYOPENCL_CALL_GUARDED_CLEANUP(clReleaseMemObject, (m_mem)); - m_valid = false; - } - - virtual ~memory_object() - { - if (m_valid) - release(); - } - - py::object hostbuf() - { return m_hostbuf; } - - const cl_mem data() const - { return m_mem; } - - }; - -#if PYOPENCL_CL_VERSION >= 0x1020 - inline - event *enqueue_migrate_mem_objects( - command_queue &cq, - py::object py_mem_objects, - cl_mem_migration_flags flags, - py::object py_wait_for) - { - PYOPENCL_PARSE_WAIT_FOR; - - std::vector<cl_mem> mem_objects; - PYTHON_FOREACH(mo, py_mem_objects) - mem_objects.push_back(py::extract<memory_object &>(mo)().data()); - - cl_event evt; - PYOPENCL_RETRY_IF_MEM_ERROR( - PYOPENCL_CALL_GUARDED(clEnqueueMigrateMemObjects, ( - cq.data(), - mem_objects.size(), mem_objects.empty( ) ? NULL : &mem_objects.front(), - flags, - PYOPENCL_WAITLIST_ARGS, &evt - )); - ); - PYOPENCL_RETURN_NEW_EVENT(evt); - } -#endif - -#ifdef cl_ext_migrate_memobject - inline - event *enqueue_migrate_mem_object_ext( - command_queue &cq, - py::object py_mem_objects, - cl_mem_migration_flags_ext flags, - py::object py_wait_for) - { - PYOPENCL_PARSE_WAIT_FOR; - -#if PYOPENCL_CL_VERSION >= 0x1020 - // {{{ get platform - cl_device_id dev; - PYOPENCL_CALL_GUARDED(clGetCommandQueueInfo, (cq.data(), CL_QUEUE_DEVICE, - sizeof(dev), &dev, NULL)); - cl_platform_id plat; - PYOPENCL_CALL_GUARDED(clGetDeviceInfo, (cq.data(), CL_DEVICE_PLATFORM, - sizeof(plat), &plat, NULL)); - // }}} -#endif - - PYOPENCL_GET_EXT_FUN(plat, - clEnqueueMigrateMemObjectEXT, enqueue_migrate_fn); - - std::vector<cl_mem> mem_objects; - PYTHON_FOREACH(mo, py_mem_objects) - mem_objects.push_back(py::extract<memory_object &>(mo)().data()); - - cl_event evt; - PYOPENCL_RETRY_IF_MEM_ERROR( - PYOPENCL_CALL_GUARDED(enqueue_migrate_fn, ( - cq.data(), - mem_objects.size(), mem_objects.empty( ) ? NULL : &mem_objects.front(), - flags, - PYOPENCL_WAITLIST_ARGS, &evt - )); - ); - PYOPENCL_RETURN_NEW_EVENT(evt); - } -#endif - - // }}} - - // {{{ buffer - - inline cl_mem create_buffer( - cl_context ctx, - cl_mem_flags flags, - size_t size, - void *host_ptr) - { - cl_int status_code; - PYOPENCL_PRINT_CALL_TRACE("clCreateBuffer"); - cl_mem mem = clCreateBuffer(ctx, flags, size, host_ptr, &status_code); - - if (status_code != CL_SUCCESS) - throw pyopencl::error("create_buffer", status_code); - - return mem; - } - - - - - inline cl_mem create_buffer_gc( - cl_context ctx, - cl_mem_flags flags, - size_t size, - void *host_ptr) - { - PYOPENCL_RETRY_RETURN_IF_MEM_ERROR( - return create_buffer(ctx, flags, size, host_ptr); - ); - } - - - -#if PYOPENCL_CL_VERSION >= 0x1010 - inline cl_mem create_sub_buffer( - cl_mem buffer, cl_mem_flags flags, cl_buffer_create_type bct, - const void *buffer_create_info) - { - cl_int status_code; - PYOPENCL_PRINT_CALL_TRACE("clCreateSubBuffer"); - cl_mem mem = clCreateSubBuffer(buffer, flags, - bct, buffer_create_info, &status_code); - - if (status_code != CL_SUCCESS) - throw pyopencl::error("clCreateSubBuffer", status_code); - - return mem; - } - - - - - inline cl_mem create_sub_buffer_gc( - cl_mem buffer, cl_mem_flags flags, cl_buffer_create_type bct, - const void *buffer_create_info) - { - PYOPENCL_RETRY_RETURN_IF_MEM_ERROR( - return create_sub_buffer(buffer, flags, bct, buffer_create_info); - ); - } -#endif - - - - class buffer : public memory_object - { - public: - buffer(cl_mem mem, bool retain, py::object *hostbuf=0) - : memory_object(mem, retain, hostbuf) - { } - -#if PYOPENCL_CL_VERSION >= 0x1010 - buffer *get_sub_region( - size_t origin, size_t size, cl_mem_flags flags) const - { - cl_buffer_region region = { origin, size}; - - cl_mem mem = create_sub_buffer_gc( - data(), flags, CL_BUFFER_CREATE_TYPE_REGION, ®ion); - - try - { - return new buffer(mem, false); - } - catch (...) - { - PYOPENCL_CALL_GUARDED(clReleaseMemObject, (mem)); - throw; - } - } - - buffer *getitem(py::slice slc) const - { - PYOPENCL_BUFFER_SIZE_T start, end, stride, length; - - size_t my_length; - PYOPENCL_CALL_GUARDED(clGetMemObjectInfo, - (data(), CL_MEM_SIZE, sizeof(my_length), &my_length, 0)); - -#if PY_VERSION_HEX >= 0x03020000 - if (PySlice_GetIndicesEx(slc.ptr(), -#else - if (PySlice_GetIndicesEx(reinterpret_cast<PySliceObject *>(slc.ptr()), -#endif - my_length, &start, &end, &stride, &length) != 0) - throw py::error_already_set(); - - if (stride != 1) - throw pyopencl::error("Buffer.__getitem__", CL_INVALID_VALUE, - "Buffer slice must have stride 1"); - - cl_mem_flags my_flags; - PYOPENCL_CALL_GUARDED(clGetMemObjectInfo, - (data(), CL_MEM_FLAGS, sizeof(my_flags), &my_flags, 0)); - - my_flags &= ~CL_MEM_COPY_HOST_PTR; - - if (end <= start) - throw pyopencl::error("Buffer.__getitem__", CL_INVALID_VALUE, - "Buffer slice have end > start"); - - return get_sub_region(start, end-start, my_flags); - } -#endif - }; - - // {{{ buffer creation - - inline - buffer *create_buffer_py( - context &ctx, - cl_mem_flags flags, - size_t size, - py::object py_hostbuf - ) - { - if (py_hostbuf.ptr() != Py_None && - !(flags & (CL_MEM_USE_HOST_PTR | CL_MEM_COPY_HOST_PTR))) - PyErr_Warn(PyExc_UserWarning, "'hostbuf' was passed, " - "but no memory flags to make use of it."); - - void *buf = 0; - py::object *retained_buf_obj = 0; - if (py_hostbuf.ptr() != Py_None) - { - PYOPENCL_BUFFER_SIZE_T len; - if ((flags & CL_MEM_USE_HOST_PTR) - && ((flags & CL_MEM_READ_WRITE) - || (flags & CL_MEM_WRITE_ONLY))) - { - if (PyObject_AsWriteBuffer(py_hostbuf.ptr(), &buf, &len)) - throw py::error_already_set(); - } - else - { - if (PyObject_AsReadBuffer( - py_hostbuf.ptr(), const_cast<const void **>(&buf), &len)) - throw py::error_already_set(); - } - - if (flags & CL_MEM_USE_HOST_PTR) - retained_buf_obj = &py_hostbuf; - - if (size > size_t(len)) - throw pyopencl::error("Buffer", CL_INVALID_VALUE, - "specified size is greater than host buffer size"); - if (size == 0) - size = len; - } - - cl_mem mem = create_buffer_gc(ctx.data(), flags, size, buf); - - try - { - return new buffer(mem, false, retained_buf_obj); - } - catch (...) - { - PYOPENCL_CALL_GUARDED(clReleaseMemObject, (mem)); - throw; - } - } - - // }}} - - // {{{ buffer transfers - - // {{{ byte-for-byte transfers - - inline - event *enqueue_read_buffer( - command_queue &cq, - memory_object_holder &mem, - py::object buffer, - size_t device_offset, - py::object py_wait_for, - bool is_blocking) - { - PYOPENCL_PARSE_WAIT_FOR; - - void *buf; - PYOPENCL_BUFFER_SIZE_T len; - - if (PyObject_AsWriteBuffer(buffer.ptr(), &buf, &len)) - throw py::error_already_set(); - - cl_event evt; - PYOPENCL_RETRY_IF_MEM_ERROR( - PYOPENCL_CALL_GUARDED_THREADED(clEnqueueReadBuffer, ( - cq.data(), - mem.data(), - PYOPENCL_CAST_BOOL(is_blocking), - device_offset, len, buf, - PYOPENCL_WAITLIST_ARGS, &evt - )) - ); - PYOPENCL_RETURN_NEW_NANNY_EVENT(evt, buffer); - } - - - - - inline - event *enqueue_write_buffer( - command_queue &cq, - memory_object_holder &mem, - py::object buffer, - size_t device_offset, - py::object py_wait_for, - bool is_blocking) - { - PYOPENCL_PARSE_WAIT_FOR; - - const void *buf; - PYOPENCL_BUFFER_SIZE_T len; - - if (PyObject_AsReadBuffer(buffer.ptr(), &buf, &len)) - throw py::error_already_set(); - - cl_event evt; - PYOPENCL_RETRY_IF_MEM_ERROR( - PYOPENCL_CALL_GUARDED_THREADED(clEnqueueWriteBuffer, ( - cq.data(), - mem.data(), - PYOPENCL_CAST_BOOL(is_blocking), - device_offset, len, buf, - PYOPENCL_WAITLIST_ARGS, &evt - )) - ); - PYOPENCL_RETURN_NEW_NANNY_EVENT(evt, buffer); - } - - - - - inline - event *enqueue_copy_buffer( - command_queue &cq, - memory_object_holder &src, - memory_object_holder &dst, - ptrdiff_t byte_count, - size_t src_offset, - size_t dst_offset, - py::object py_wait_for) - { - PYOPENCL_PARSE_WAIT_FOR; - - if (byte_count < 0) - { - size_t byte_count_src = 0; - size_t byte_count_dst = 0; - PYOPENCL_CALL_GUARDED(clGetMemObjectInfo, - (src.data(), CL_MEM_SIZE, sizeof(byte_count), &byte_count_src, 0)); - PYOPENCL_CALL_GUARDED(clGetMemObjectInfo, - (src.data(), CL_MEM_SIZE, sizeof(byte_count), &byte_count_dst, 0)); - byte_count = std::min(byte_count_src, byte_count_dst); - } - - cl_event evt; - PYOPENCL_RETRY_IF_MEM_ERROR( - PYOPENCL_CALL_GUARDED(clEnqueueCopyBuffer, ( - cq.data(), - src.data(), dst.data(), - src_offset, dst_offset, - byte_count, - PYOPENCL_WAITLIST_ARGS, - &evt - )) - ); - - PYOPENCL_RETURN_NEW_EVENT(evt); - } - - // }}} - - // {{{ rectangular transfers -#if PYOPENCL_CL_VERSION >= 0x1010 - inline - event *enqueue_read_buffer_rect( - command_queue &cq, - memory_object_holder &mem, - py::object buffer, - py::object py_buffer_origin, - py::object py_host_origin, - py::object py_region, - py::object py_buffer_pitches, - py::object py_host_pitches, - py::object py_wait_for, - bool is_blocking - ) - { - PYOPENCL_PARSE_WAIT_FOR; - COPY_PY_COORD_TRIPLE(buffer_origin); - COPY_PY_COORD_TRIPLE(host_origin); - COPY_PY_REGION_TRIPLE(region); - COPY_PY_PITCH_TUPLE(buffer_pitches); - COPY_PY_PITCH_TUPLE(host_pitches); - - void *buf; - PYOPENCL_BUFFER_SIZE_T len; - - if (PyObject_AsWriteBuffer(buffer.ptr(), &buf, &len)) - throw py::error_already_set(); - - cl_event evt; - PYOPENCL_RETRY_IF_MEM_ERROR( - PYOPENCL_CALL_GUARDED_THREADED(clEnqueueReadBufferRect, ( - cq.data(), - mem.data(), - PYOPENCL_CAST_BOOL(is_blocking), - buffer_origin, host_origin, region, - buffer_pitches[0], buffer_pitches[1], - host_pitches[0], host_pitches[1], - buf, - PYOPENCL_WAITLIST_ARGS, &evt - )) - ); - PYOPENCL_RETURN_NEW_NANNY_EVENT(evt, buffer); - } - - - - - inline - event *enqueue_write_buffer_rect( - command_queue &cq, - memory_object_holder &mem, - py::object buffer, - py::object py_buffer_origin, - py::object py_host_origin, - py::object py_region, - py::object py_buffer_pitches, - py::object py_host_pitches, - py::object py_wait_for, - bool is_blocking - ) - { - PYOPENCL_PARSE_WAIT_FOR; - COPY_PY_COORD_TRIPLE(buffer_origin); - COPY_PY_COORD_TRIPLE(host_origin); - COPY_PY_REGION_TRIPLE(region); - COPY_PY_PITCH_TUPLE(buffer_pitches); - COPY_PY_PITCH_TUPLE(host_pitches); - - const void *buf; - PYOPENCL_BUFFER_SIZE_T len; - - if (PyObject_AsReadBuffer(buffer.ptr(), &buf, &len)) - throw py::error_already_set(); - - cl_event evt; - PYOPENCL_RETRY_IF_MEM_ERROR( - PYOPENCL_CALL_GUARDED_THREADED(clEnqueueWriteBufferRect, ( - cq.data(), - mem.data(), - PYOPENCL_CAST_BOOL(is_blocking), - buffer_origin, host_origin, region, - buffer_pitches[0], buffer_pitches[1], - host_pitches[0], host_pitches[1], - buf, - PYOPENCL_WAITLIST_ARGS, &evt - )) - ); - PYOPENCL_RETURN_NEW_NANNY_EVENT(evt, buffer); - } - - - - - inline - event *enqueue_copy_buffer_rect( - command_queue &cq, - memory_object_holder &src, - memory_object_holder &dst, - py::object py_src_origin, - py::object py_dst_origin, - py::object py_region, - py::object py_src_pitches, - py::object py_dst_pitches, - py::object py_wait_for) - { - PYOPENCL_PARSE_WAIT_FOR; - COPY_PY_COORD_TRIPLE(src_origin); - COPY_PY_COORD_TRIPLE(dst_origin); - COPY_PY_REGION_TRIPLE(region); - COPY_PY_PITCH_TUPLE(src_pitches); - COPY_PY_PITCH_TUPLE(dst_pitches); - - cl_event evt; - PYOPENCL_RETRY_IF_MEM_ERROR( - PYOPENCL_CALL_GUARDED(clEnqueueCopyBufferRect, ( - cq.data(), - src.data(), dst.data(), - src_origin, dst_origin, region, - src_pitches[0], src_pitches[1], - dst_pitches[0], dst_pitches[1], - PYOPENCL_WAITLIST_ARGS, - &evt - )) - ); - - PYOPENCL_RETURN_NEW_EVENT(evt); - } - -#endif - - // }}} - - // }}} - -#if PYOPENCL_CL_VERSION >= 0x1020 - inline - event *enqueue_fill_buffer( - command_queue &cq, - memory_object_holder &mem, - py::object pattern, - size_t offset, - size_t size, - py::object py_wait_for - ) - { - PYOPENCL_PARSE_WAIT_FOR; - - const void *pattern_buf; - PYOPENCL_BUFFER_SIZE_T pattern_len; - - if (PyObject_AsReadBuffer(pattern.ptr(), &pattern_buf, &pattern_len)) - throw py::error_already_set(); - - cl_event evt; - PYOPENCL_RETRY_IF_MEM_ERROR( - PYOPENCL_CALL_GUARDED(clEnqueueFillBuffer, ( - cq.data(), - mem.data(), - pattern_buf, pattern_len, offset, size, - PYOPENCL_WAITLIST_ARGS, &evt - )) - ); - PYOPENCL_RETURN_NEW_EVENT(evt); - } -#endif - - // }}} - - // {{{ image - - class image : public memory_object - { - public: - image(cl_mem mem, bool retain, py::object *hostbuf=0) - : memory_object(mem, retain, hostbuf) - { } - - py::object get_image_info(cl_image_info param_name) const - { - switch (param_name) - { - case CL_IMAGE_FORMAT: - PYOPENCL_GET_INTEGRAL_INFO(Image, data(), param_name, - cl_image_format); - case CL_IMAGE_ELEMENT_SIZE: - case CL_IMAGE_ROW_PITCH: - case CL_IMAGE_SLICE_PITCH: - case CL_IMAGE_WIDTH: - case CL_IMAGE_HEIGHT: - case CL_IMAGE_DEPTH: -#if PYOPENCL_CL_VERSION >= 0x1020 - case CL_IMAGE_ARRAY_SIZE: -#endif - PYOPENCL_GET_INTEGRAL_INFO(Image, data(), param_name, size_t); - -#if PYOPENCL_CL_VERSION >= 0x1020 - case CL_IMAGE_BUFFER: - { - cl_mem param_value; - PYOPENCL_CALL_GUARDED(clGetImageInfo, \ - (data(), param_name, sizeof(param_value), ¶m_value, 0)); - if (param_value == 0) - { - // no associated memory object? no problem. - return py::object(); - } - - return create_mem_object_wrapper(param_value); - } - - case CL_IMAGE_NUM_MIP_LEVELS: - case CL_IMAGE_NUM_SAMPLES: - PYOPENCL_GET_INTEGRAL_INFO(Image, data(), param_name, cl_uint); -#endif - - default: - throw error("MemoryObject.get_image_info", CL_INVALID_VALUE); - } - } - }; - - - - - // {{{ image formats - - inline - cl_image_format *make_image_format(cl_channel_order ord, cl_channel_type tp) - { - std::auto_ptr<cl_image_format> result(new cl_image_format); - result->image_channel_order = ord; - result->image_channel_data_type = tp; - return result.release(); - } - - inline - py::list get_supported_image_formats( - context const &ctx, - cl_mem_flags flags, - cl_mem_object_type image_type) - { - cl_uint num_image_formats; - PYOPENCL_CALL_GUARDED(clGetSupportedImageFormats, ( - ctx.data(), flags, image_type, - 0, NULL, &num_image_formats)); - - std::vector<cl_image_format> formats(num_image_formats); - PYOPENCL_CALL_GUARDED(clGetSupportedImageFormats, ( - ctx.data(), flags, image_type, - formats.size(), formats.empty( ) ? NULL : &formats.front(), NULL)); - - PYOPENCL_RETURN_VECTOR(cl_image_format, formats); - } - - inline - cl_uint get_image_format_channel_count(cl_image_format const &fmt) - { - switch (fmt.image_channel_order) - { - case CL_R: return 1; - case CL_A: return 1; - case CL_RG: return 2; - case CL_RA: return 2; - case CL_RGB: return 3; - case CL_RGBA: return 4; - case CL_BGRA: return 4; - case CL_INTENSITY: return 1; - case CL_LUMINANCE: return 1; - default: - throw pyopencl::error("ImageFormat.channel_dtype_size", - CL_INVALID_VALUE, - "unrecognized channel order"); - } - } - - inline - cl_uint get_image_format_channel_dtype_size(cl_image_format const &fmt) - { - switch (fmt.image_channel_data_type) - { - case CL_SNORM_INT8: return 1; - case CL_SNORM_INT16: return 2; - case CL_UNORM_INT8: return 1; - case CL_UNORM_INT16: return 2; - case CL_UNORM_SHORT_565: return 2; - case CL_UNORM_SHORT_555: return 2; - case CL_UNORM_INT_101010: return 4; - case CL_SIGNED_INT8: return 1; - case CL_SIGNED_INT16: return 2; - case CL_SIGNED_INT32: return 4; - case CL_UNSIGNED_INT8: return 1; - case CL_UNSIGNED_INT16: return 2; - case CL_UNSIGNED_INT32: return 4; - case CL_HALF_FLOAT: return 2; - case CL_FLOAT: return 4; - default: - throw pyopencl::error("ImageFormat.channel_dtype_size", - CL_INVALID_VALUE, - "unrecognized channel data type"); - } - } - - inline - cl_uint get_image_format_item_size(cl_image_format const &fmt) - { - return get_image_format_channel_count(fmt) - * get_image_format_channel_dtype_size(fmt); - } - - // }}} - - // {{{ image creation - - inline - image *create_image( - context const &ctx, - cl_mem_flags flags, - cl_image_format const &fmt, - py::object shape, - py::object pitches, - py::object buffer) - { - if (shape.ptr() == Py_None) - throw pyopencl::error("Image", CL_INVALID_VALUE, - "'shape' must be given"); - - void *buf = 0; - PYOPENCL_BUFFER_SIZE_T len; - py::object *retained_buf_obj = 0; - - if (buffer.ptr() != Py_None) - { - if ((flags & CL_MEM_USE_HOST_PTR) - && ((flags & CL_MEM_READ_WRITE) - || (flags & CL_MEM_WRITE_ONLY))) - { - if (PyObject_AsWriteBuffer(buffer.ptr(), &buf, &len)) - throw py::error_already_set(); - } - else - { - if (PyObject_AsReadBuffer( - buffer.ptr(), const_cast<const void **>(&buf), &len)) - throw py::error_already_set(); - } - - if (flags & CL_MEM_USE_HOST_PTR) - retained_buf_obj = &buffer; - } - - unsigned dims = py::len(shape); - cl_int status_code; - cl_mem mem; - if (dims == 2) - { - size_t width = py::extract<size_t>(shape[0]); - size_t height = py::extract<size_t>(shape[1]); - - size_t pitch = 0; - if (pitches.ptr() != Py_None) - { - if (py::len(pitches) != 1) - throw pyopencl::error("Image", CL_INVALID_VALUE, - "invalid length of pitch tuple"); - pitch = py::extract<size_t>(pitches[0]); - } - - // check buffer size - cl_int itemsize = get_image_format_item_size(fmt); - if (buf && std::max(pitch, width*itemsize)*height > cl_uint(len)) - throw pyopencl::error("Image", CL_INVALID_VALUE, - "buffer too small"); - - PYOPENCL_PRINT_CALL_TRACE("clCreateImage2D"); - PYOPENCL_RETRY_IF_MEM_ERROR( - { - mem = clCreateImage2D(ctx.data(), flags, &fmt, - width, height, pitch, buf, &status_code); - if (status_code != CL_SUCCESS) - throw pyopencl::error("clCreateImage2D", status_code); - } ); - - } - else if (dims == 3) - { - size_t width = py::extract<size_t>(shape[0]); - size_t height = py::extract<size_t>(shape[1]); - size_t depth = py::extract<size_t>(shape[2]); - - size_t pitch_x = 0; - size_t pitch_y = 0; - - if (pitches.ptr() != Py_None) - { - if (py::len(pitches) != 2) - throw pyopencl::error("Image", CL_INVALID_VALUE, - "invalid length of pitch tuple"); - - pitch_x = py::extract<size_t>(pitches[0]); - pitch_y = py::extract<size_t>(pitches[1]); - } - - // check buffer size - cl_int itemsize = get_image_format_item_size(fmt); - if (buf && - std::max(std::max(pitch_x, width*itemsize)*height, pitch_y) - * depth > cl_uint(len)) - throw pyopencl::error("Image", CL_INVALID_VALUE, - "buffer too small"); - - PYOPENCL_PRINT_CALL_TRACE("clCreateImage3D"); - PYOPENCL_RETRY_IF_MEM_ERROR( - { - mem = clCreateImage3D(ctx.data(), flags, &fmt, - width, height, depth, pitch_x, pitch_y, buf, &status_code); - if (status_code != CL_SUCCESS) - throw pyopencl::error("clCreateImage3D", status_code); - } ); - } - else - throw pyopencl::error("Image", CL_INVALID_VALUE, - "invalid dimension"); - - try - { - return new image(mem, false, retained_buf_obj); - } - catch (...) - { - PYOPENCL_CALL_GUARDED(clReleaseMemObject, (mem)); - throw; - } - } - -#if PYOPENCL_CL_VERSION >= 0x1020 - - inline - image *create_image_from_desc( - context const &ctx, - cl_mem_flags flags, - cl_image_format const &fmt, - cl_image_desc &desc, - py::object buffer) - { - if (buffer.ptr() != Py_None && - !(flags & (CL_MEM_USE_HOST_PTR | CL_MEM_COPY_HOST_PTR))) - PyErr_Warn(PyExc_UserWarning, "'hostbuf' was passed, " - "but no memory flags to make use of it."); - - void *buf = 0; - PYOPENCL_BUFFER_SIZE_T len; - py::object *retained_buf_obj = 0; - - if (buffer.ptr() != Py_None) - { - if (flags & CL_MEM_USE_HOST_PTR) - { - if (PyObject_AsWriteBuffer(buffer.ptr(), &buf, &len)) - throw py::error_already_set(); - } - else - { - if (PyObject_AsReadBuffer( - buffer.ptr(), const_cast<const void **>(&buf), &len)) - throw py::error_already_set(); - } - - if (flags & CL_MEM_USE_HOST_PTR) - retained_buf_obj = &buffer; - } - - PYOPENCL_PRINT_CALL_TRACE("clCreateImage"); - cl_int status_code; - cl_mem mem = clCreateImage(ctx.data(), flags, &fmt, &desc, buf, &status_code); - if (status_code != CL_SUCCESS) - throw pyopencl::error("clCreateImage", status_code); - - try - { - return new image(mem, false, retained_buf_obj); - } - catch (...) - { - PYOPENCL_CALL_GUARDED(clReleaseMemObject, (mem)); - throw; - } - } - -#endif - - // }}} - - // {{{ image transfers - - inline - event *enqueue_read_image( - command_queue &cq, - image &img, - py::object py_origin, py::object py_region, - py::object buffer, - size_t row_pitch, size_t slice_pitch, - py::object py_wait_for, - bool is_blocking) - { - PYOPENCL_PARSE_WAIT_FOR; - COPY_PY_COORD_TRIPLE(origin); - COPY_PY_REGION_TRIPLE(region); - - void *buf; - PYOPENCL_BUFFER_SIZE_T len; - - if (PyObject_AsWriteBuffer(buffer.ptr(), &buf, &len)) - throw py::error_already_set(); - - cl_event evt; - - PYOPENCL_RETRY_IF_MEM_ERROR( - PYOPENCL_CALL_GUARDED(clEnqueueReadImage, ( - cq.data(), - img.data(), - PYOPENCL_CAST_BOOL(is_blocking), - origin, region, row_pitch, slice_pitch, buf, - PYOPENCL_WAITLIST_ARGS, &evt - )); - ); - PYOPENCL_RETURN_NEW_NANNY_EVENT(evt, buffer); - } - - - - - inline - event *enqueue_write_image( - command_queue &cq, - image &img, - py::object py_origin, py::object py_region, - py::object buffer, - size_t row_pitch, size_t slice_pitch, - py::object py_wait_for, - bool is_blocking) - { - PYOPENCL_PARSE_WAIT_FOR; - COPY_PY_COORD_TRIPLE(origin); - COPY_PY_REGION_TRIPLE(region); - - const void *buf; - PYOPENCL_BUFFER_SIZE_T len; - - if (PyObject_AsReadBuffer(buffer.ptr(), &buf, &len)) - throw py::error_already_set(); - - cl_event evt; - PYOPENCL_RETRY_IF_MEM_ERROR( - PYOPENCL_CALL_GUARDED(clEnqueueWriteImage, ( - cq.data(), - img.data(), - PYOPENCL_CAST_BOOL(is_blocking), - origin, region, row_pitch, slice_pitch, buf, - PYOPENCL_WAITLIST_ARGS, &evt - )); - ); - PYOPENCL_RETURN_NEW_NANNY_EVENT(evt, buffer); - } - - - - - inline - event *enqueue_copy_image( - command_queue &cq, - memory_object_holder &src, - memory_object_holder &dest, - py::object py_src_origin, - py::object py_dest_origin, - py::object py_region, - py::object py_wait_for - ) - { - PYOPENCL_PARSE_WAIT_FOR; - COPY_PY_COORD_TRIPLE(src_origin); - COPY_PY_COORD_TRIPLE(dest_origin); - COPY_PY_REGION_TRIPLE(region); - - cl_event evt; - PYOPENCL_RETRY_IF_MEM_ERROR( - PYOPENCL_CALL_GUARDED(clEnqueueCopyImage, ( - cq.data(), src.data(), dest.data(), - src_origin, dest_origin, region, - PYOPENCL_WAITLIST_ARGS, &evt - )); - ); - PYOPENCL_RETURN_NEW_EVENT(evt); - } - - - - - inline - event *enqueue_copy_image_to_buffer( - command_queue &cq, - memory_object_holder &src, - memory_object_holder &dest, - py::object py_origin, - py::object py_region, - size_t offset, - py::object py_wait_for - ) - { - PYOPENCL_PARSE_WAIT_FOR; - COPY_PY_COORD_TRIPLE(origin); - COPY_PY_REGION_TRIPLE(region); - - cl_event evt; - PYOPENCL_RETRY_IF_MEM_ERROR( - PYOPENCL_CALL_GUARDED(clEnqueueCopyImageToBuffer, ( - cq.data(), src.data(), dest.data(), - origin, region, offset, - PYOPENCL_WAITLIST_ARGS, &evt - )); - ); - PYOPENCL_RETURN_NEW_EVENT(evt); - } - - - - - inline - event *enqueue_copy_buffer_to_image( - command_queue &cq, - memory_object_holder &src, - memory_object_holder &dest, - size_t offset, - py::object py_origin, - py::object py_region, - py::object py_wait_for - ) - { - PYOPENCL_PARSE_WAIT_FOR; - COPY_PY_COORD_TRIPLE(origin); - COPY_PY_REGION_TRIPLE(region); - - cl_event evt; - PYOPENCL_RETRY_IF_MEM_ERROR( - PYOPENCL_CALL_GUARDED(clEnqueueCopyBufferToImage, ( - cq.data(), src.data(), dest.data(), - offset, origin, region, - PYOPENCL_WAITLIST_ARGS, &evt - )); - ); - PYOPENCL_RETURN_NEW_EVENT(evt); - } - - // }}} - -#if PYOPENCL_CL_VERSION >= 0x1020 - inline - event *enqueue_fill_image( - command_queue &cq, - memory_object_holder &mem, - py::object color, - py::object py_origin, py::object py_region, - py::object py_wait_for - ) - { - PYOPENCL_PARSE_WAIT_FOR; - - COPY_PY_COORD_TRIPLE(origin); - COPY_PY_REGION_TRIPLE(region); - - const void *color_buf; - PYOPENCL_BUFFER_SIZE_T color_len; - - if (PyObject_AsReadBuffer(color.ptr(), &color_buf, &color_len)) - throw py::error_already_set(); - - cl_event evt; - PYOPENCL_RETRY_IF_MEM_ERROR( - PYOPENCL_CALL_GUARDED(clEnqueueFillImage, ( - cq.data(), - mem.data(), - color_buf, origin, region, - PYOPENCL_WAITLIST_ARGS, &evt - )); - ); - PYOPENCL_RETURN_NEW_EVENT(evt); - } -#endif - - // }}} - - // {{{ maps - class memory_map - { - private: - bool m_valid; - command_queue m_queue; - memory_object m_mem; - void *m_ptr; - - public: - memory_map(command_queue &cq, memory_object const &mem, void *ptr) - : m_valid(true), m_queue(cq), m_mem(mem), m_ptr(ptr) - { - } - - ~memory_map() - { - if (m_valid) - delete release(0, py::object()); - } - - event *release(command_queue *cq, py::object py_wait_for) - { - PYOPENCL_PARSE_WAIT_FOR; - - if (cq == 0) - cq = &m_queue; - - cl_event evt; - PYOPENCL_CALL_GUARDED(clEnqueueUnmapMemObject, ( - cq->data(), m_mem.data(), m_ptr, - PYOPENCL_WAITLIST_ARGS, &evt - )); - - m_valid = false; - - PYOPENCL_RETURN_NEW_EVENT(evt); - } - }; - - - - - inline - py::object enqueue_map_buffer( - command_queue &cq, - memory_object_holder &buf, - cl_map_flags flags, - size_t offset, - py::object py_shape, py::object dtype, - py::object py_order, py::object py_strides, - py::object py_wait_for, - bool is_blocking - ) - { - PYOPENCL_PARSE_WAIT_FOR; - PYOPENCL_PARSE_NUMPY_ARRAY_SPEC; - - npy_uintp size_in_bytes = tp_descr->elsize; - BOOST_FOREACH(npy_intp sdim, shape) - size_in_bytes *= sdim; - - py::handle<> result; - - cl_event evt; - cl_int status_code; - PYOPENCL_PRINT_CALL_TRACE("clEnqueueMapBuffer"); - void *mapped; - - PYOPENCL_RETRY_IF_MEM_ERROR( - { - Py_BEGIN_ALLOW_THREADS - mapped = clEnqueueMapBuffer( - cq.data(), buf.data(), - PYOPENCL_CAST_BOOL(is_blocking), flags, - offset, size_in_bytes, - PYOPENCL_WAITLIST_ARGS, &evt, - &status_code); - Py_END_ALLOW_THREADS - if (status_code != CL_SUCCESS) - throw pyopencl::error("clEnqueueMapBuffer", status_code); - } ); - - event evt_handle(evt, false); - - std::auto_ptr<memory_map> map; - try - { - result = py::handle<>(PyArray_NewFromDescr( - &PyArray_Type, tp_descr, - shape.size(), - shape.empty() ? NULL : &shape.front(), - strides.empty() ? NULL : &strides.front(), - mapped, ary_flags, /*obj*/NULL)); - - if (size_in_bytes != (npy_uintp) PyArray_NBYTES(result.get())) - throw pyopencl::error("enqueue_map_buffer", CL_INVALID_VALUE, - "miscalculated numpy array size (not contiguous?)"); - - map = std::auto_ptr<memory_map>(new memory_map(cq, buf, mapped)); - } - catch (...) - { - PYOPENCL_CALL_GUARDED_CLEANUP(clEnqueueUnmapMemObject, ( - cq.data(), buf.data(), mapped, 0, 0, 0)); - throw; - } - - py::handle<> map_py(handle_from_new_ptr(map.release())); - PyArray_BASE(result.get()) = map_py.get(); - Py_INCREF(map_py.get()); - - return py::make_tuple( - result, - handle_from_new_ptr(new event(evt_handle))); - } - - - - - inline - py::object enqueue_map_image( - command_queue &cq, - memory_object_holder &img, - cl_map_flags flags, - py::object py_origin, - py::object py_region, - py::object py_shape, py::object dtype, - py::object py_order, py::object py_strides, - py::object py_wait_for, - bool is_blocking - ) - { - PYOPENCL_PARSE_WAIT_FOR; - PYOPENCL_PARSE_NUMPY_ARRAY_SPEC; - COPY_PY_COORD_TRIPLE(origin); - COPY_PY_REGION_TRIPLE(region); - - cl_event evt; - cl_int status_code; - PYOPENCL_PRINT_CALL_TRACE("clEnqueueMapImage"); - size_t row_pitch, slice_pitch; - void *mapped; - PYOPENCL_RETRY_IF_MEM_ERROR( - { - Py_BEGIN_ALLOW_THREADS - mapped = clEnqueueMapImage( - cq.data(), img.data(), - PYOPENCL_CAST_BOOL(is_blocking), flags, - origin, region, &row_pitch, &slice_pitch, - PYOPENCL_WAITLIST_ARGS, &evt, - &status_code); - Py_END_ALLOW_THREADS - if (status_code != CL_SUCCESS) - throw pyopencl::error("clEnqueueMapImage", status_code); - } ); - - event evt_handle(evt, false); - - std::auto_ptr<memory_map> map; - try - { - map = std::auto_ptr<memory_map>(new memory_map(cq, img, mapped)); - } - catch (...) - { - PYOPENCL_CALL_GUARDED_CLEANUP(clEnqueueUnmapMemObject, ( - cq.data(), img.data(), mapped, 0, 0, 0)); - throw; - } - - py::handle<> result = py::handle<>(PyArray_NewFromDescr( - &PyArray_Type, tp_descr, - shape.size(), - shape.empty() ? NULL : &shape.front(), - strides.empty() ? NULL : &strides.front(), - mapped, ary_flags, /*obj*/NULL)); - - py::handle<> map_py(handle_from_new_ptr(map.release())); - PyArray_BASE(result.get()) = map_py.get(); - Py_INCREF(map_py.get()); - - return py::make_tuple( - result, - handle_from_new_ptr(new event(evt_handle)), - row_pitch, slice_pitch); - } - - // }}} - - // {{{ sampler - class sampler : boost::noncopyable - { - private: - cl_sampler m_sampler; - - public: - sampler(context const &ctx, bool normalized_coordinates, - cl_addressing_mode am, cl_filter_mode fm) - { - cl_int status_code; - PYOPENCL_PRINT_CALL_TRACE("clCreateSampler"); - m_sampler = clCreateSampler( - ctx.data(), - normalized_coordinates, - am, fm, &status_code); - - if (status_code != CL_SUCCESS) - throw pyopencl::error("Sampler", status_code); - } - - sampler(cl_sampler samp, bool retain) - : m_sampler(samp) - { - if (retain) - PYOPENCL_CALL_GUARDED(clRetainSampler, (samp)); - } - - ~sampler() - { - PYOPENCL_CALL_GUARDED_CLEANUP(clReleaseSampler, (m_sampler)); - } - - cl_sampler data() const - { - return m_sampler; - } - - PYOPENCL_EQUALITY_TESTS(sampler); - - py::object get_info(cl_sampler_info param_name) const - { - switch (param_name) - { - case CL_SAMPLER_REFERENCE_COUNT: - PYOPENCL_GET_INTEGRAL_INFO(Sampler, m_sampler, param_name, - cl_uint); - case CL_SAMPLER_CONTEXT: - PYOPENCL_GET_OPAQUE_INFO(Sampler, m_sampler, param_name, - cl_context, context); - case CL_SAMPLER_ADDRESSING_MODE: - PYOPENCL_GET_INTEGRAL_INFO(Sampler, m_sampler, param_name, - cl_addressing_mode); - case CL_SAMPLER_FILTER_MODE: - PYOPENCL_GET_INTEGRAL_INFO(Sampler, m_sampler, param_name, - cl_filter_mode); - case CL_SAMPLER_NORMALIZED_COORDS: - PYOPENCL_GET_INTEGRAL_INFO(Sampler, m_sampler, param_name, - cl_bool); - - default: - throw error("Sampler.get_info", CL_INVALID_VALUE); - } - } - }; - - // }}} - - // {{{ program - - class program : boost::noncopyable - { - public: - enum program_kind_type { KND_UNKNOWN, KND_SOURCE, KND_BINARY }; - - private: - cl_program m_program; - program_kind_type m_program_kind; - - public: - program(cl_program prog, bool retain, program_kind_type progkind=KND_UNKNOWN) - : m_program(prog), m_program_kind(progkind) - { - if (retain) - PYOPENCL_CALL_GUARDED(clRetainProgram, (prog)); - } - - ~program() - { - PYOPENCL_CALL_GUARDED_CLEANUP(clReleaseProgram, (m_program)); - } - - cl_program data() const - { - return m_program; - } - - program_kind_type kind() const - { - return m_program_kind; - } - - PYOPENCL_EQUALITY_TESTS(program); - - py::object get_info(cl_program_info param_name) const - { - switch (param_name) - { - case CL_PROGRAM_REFERENCE_COUNT: - PYOPENCL_GET_INTEGRAL_INFO(Program, m_program, param_name, - cl_uint); - case CL_PROGRAM_CONTEXT: - PYOPENCL_GET_OPAQUE_INFO(Program, m_program, param_name, - cl_context, context); - case CL_PROGRAM_NUM_DEVICES: - PYOPENCL_GET_INTEGRAL_INFO(Program, m_program, param_name, - cl_uint); - case CL_PROGRAM_DEVICES: - { - std::vector<cl_device_id> result; - PYOPENCL_GET_VEC_INFO(Program, m_program, param_name, result); - - py::list py_result; - BOOST_FOREACH(cl_device_id did, result) - py_result.append(handle_from_new_ptr( - new pyopencl::device(did))); - return py_result; - } - case CL_PROGRAM_SOURCE: - PYOPENCL_GET_STR_INFO(Program, m_program, param_name); - case CL_PROGRAM_BINARY_SIZES: - { - std::vector<size_t> result; - PYOPENCL_GET_VEC_INFO(Program, m_program, param_name, result); - PYOPENCL_RETURN_VECTOR(size_t, result); - } - case CL_PROGRAM_BINARIES: - // {{{ - { - std::vector<size_t> sizes; - PYOPENCL_GET_VEC_INFO(Program, m_program, CL_PROGRAM_BINARY_SIZES, sizes); - - size_t total_size = std::accumulate(sizes.begin(), sizes.end(), 0); - - boost::scoped_array<unsigned char> result( - new unsigned char[total_size]); - std::vector<unsigned char *> result_ptrs; - - unsigned char *ptr = result.get(); - for (unsigned i = 0; i < sizes.size(); ++i) - { - result_ptrs.push_back(ptr); - ptr += sizes[i]; - } - - PYOPENCL_CALL_GUARDED(clGetProgramInfo, - (m_program, param_name, sizes.size()*sizeof(unsigned char *), - result_ptrs.empty( ) ? NULL : &result_ptrs.front(), 0)); \ - - py::list py_result; - ptr = result.get(); - for (unsigned i = 0; i < sizes.size(); ++i) - { - py::handle<> binary_pyobj( -#if PY_VERSION_HEX >= 0x03000000 - PyBytes_FromStringAndSize( - reinterpret_cast<char *>(ptr), sizes[i]) -#else - PyString_FromStringAndSize( - reinterpret_cast<char *>(ptr), sizes[i]) -#endif - ); - py_result.append(binary_pyobj); - ptr += sizes[i]; - } - return py_result; - } - // }}} -#if PYOPENCL_CL_VERSION >= 0x1020 - case CL_PROGRAM_NUM_KERNELS: - PYOPENCL_GET_INTEGRAL_INFO(Program, m_program, param_name, - size_t); - case CL_PROGRAM_KERNEL_NAMES: - PYOPENCL_GET_STR_INFO(Program, m_program, param_name); -#endif - - default: - throw error("Program.get_info", CL_INVALID_VALUE); - } - } - - py::object get_build_info( - device const &dev, - cl_program_build_info param_name) const - { - switch (param_name) - { -#define PYOPENCL_FIRST_ARG m_program, dev.data() // hackety hack - case CL_PROGRAM_BUILD_STATUS: - PYOPENCL_GET_INTEGRAL_INFO(ProgramBuild, - PYOPENCL_FIRST_ARG, param_name, - cl_build_status); - case CL_PROGRAM_BUILD_OPTIONS: - case CL_PROGRAM_BUILD_LOG: - PYOPENCL_GET_STR_INFO(ProgramBuild, - PYOPENCL_FIRST_ARG, param_name); -#if PYOPENCL_CL_VERSION >= 0x1020 - case CL_PROGRAM_BINARY_TYPE: - PYOPENCL_GET_INTEGRAL_INFO(ProgramBuild, - PYOPENCL_FIRST_ARG, param_name, - cl_program_binary_type); -#endif -#undef PYOPENCL_FIRST_ARG - - default: - throw error("Program.get_build_info", CL_INVALID_VALUE); - } - } - - void build(std::string options, py::object py_devices) - { - PYOPENCL_PARSE_PY_DEVICES; - - PYOPENCL_CALL_GUARDED_THREADED(clBuildProgram, - (m_program, num_devices, devices, - options.c_str(), 0 ,0)); - } - -#if PYOPENCL_CL_VERSION >= 0x1020 - void compile(std::string options, py::object py_devices, - py::object py_headers) - { - PYOPENCL_PARSE_PY_DEVICES; - - // {{{ pick apart py_headers - // py_headers is a list of tuples *(name, program)* - - std::vector<std::string> header_names; - std::vector<cl_program> programs; - PYTHON_FOREACH(name_hdr_tup, py_headers) - { - if (py::len(name_hdr_tup) != 2) - throw error("Program.compile", CL_INVALID_VALUE, - "epxected (name, header) tuple in headers list"); - std::string name = py::extract<std::string const &>(name_hdr_tup[0]); - program &prg = py::extract<program &>(name_hdr_tup[1]); - - header_names.push_back(name); - programs.push_back(prg.data()); - } - - std::vector<const char *> header_name_ptrs; - BOOST_FOREACH(std::string const &name, header_names) - header_name_ptrs.push_back(name.c_str()); - - // }}} - - PYOPENCL_CALL_GUARDED_THREADED(clCompileProgram, - (m_program, num_devices, devices, - options.c_str(), header_names.size(), - programs.empty() ? NULL : &programs.front(), - header_name_ptrs.empty() ? NULL : &header_name_ptrs.front(), - 0, 0)); - } -#endif - }; - - - - - inline - program *create_program_with_source( - context &ctx, - std::string const &src) - { - const char *string = src.c_str(); - size_t length = src.size(); - - cl_int status_code; - PYOPENCL_PRINT_CALL_TRACE("clCreateProgramWithSource"); - cl_program result = clCreateProgramWithSource( - ctx.data(), 1, &string, &length, &status_code); - if (status_code != CL_SUCCESS) - throw pyopencl::error("clCreateProgramWithSource", status_code); - - try - { - return new program(result, false, program::KND_SOURCE); - } - catch (...) - { - clReleaseProgram(result); - throw; - } - } - - - - - - inline - program *create_program_with_binary( - context &ctx, - py::object py_devices, - py::object py_binaries) - { - std::vector<cl_device_id> devices; - std::vector<const unsigned char *> binaries; - std::vector<size_t> sizes; - std::vector<cl_int> binary_statuses; - - int num_devices = len(py_devices); - if (len(py_binaries) != num_devices) - throw error("create_program_with_binary", CL_INVALID_VALUE, - "device and binary counts don't match"); - - for (int i = 0; i < num_devices; ++i) - { - devices.push_back( - py::extract<device const &>(py_devices[i])().data()); - const void *buf; - PYOPENCL_BUFFER_SIZE_T len; - - if (PyObject_AsReadBuffer( - py::object(py_binaries[i]).ptr(), &buf, &len)) - throw py::error_already_set(); - - binaries.push_back(reinterpret_cast<const unsigned char *>(buf)); - sizes.push_back(len); - } - - binary_statuses.resize(num_devices); - - cl_int status_code; - PYOPENCL_PRINT_CALL_TRACE("clCreateProgramWithBinary"); - cl_program result = clCreateProgramWithBinary( - ctx.data(), num_devices, - devices.empty( ) ? NULL : &devices.front(), - sizes.empty( ) ? NULL : &sizes.front(), - binaries.empty( ) ? NULL : &binaries.front(), - binary_statuses.empty( ) ? NULL : &binary_statuses.front(), - &status_code); - if (status_code != CL_SUCCESS) - throw pyopencl::error("clCreateProgramWithBinary", status_code); - - /* - for (int i = 0; i < num_devices; ++i) - printf("%d:%d\n", i, binary_statuses[i]); - */ - - try - { - return new program(result, false, program::KND_BINARY); - } - catch (...) - { - clReleaseProgram(result); - throw; - } - } - - - -#if (PYOPENCL_CL_VERSION >= 0x1020) && \ - ((PYOPENCL_CL_VERSION >= 0x1030) && defined(__APPLE__)) - inline - program *create_program_with_built_in_kernels( - context &ctx, - py::object py_devices, - std::string const &kernel_names) - { - PYOPENCL_PARSE_PY_DEVICES; - - cl_int status_code; - PYOPENCL_PRINT_CALL_TRACE("clCreateProgramWithBuiltInKernels"); - cl_program result = clCreateProgramWithBuiltInKernels( - ctx.data(), num_devices, devices, - kernel_names.c_str(), &status_code); - if (status_code != CL_SUCCESS) - throw pyopencl::error("clCreateProgramWithBuiltInKernels", status_code); - - try - { - return new program(result, false); - } - catch (...) - { - clReleaseProgram(result); - throw; - } - } -#endif - - - -#if PYOPENCL_CL_VERSION >= 0x1020 - inline - program *link_program( - context &ctx, - py::object py_programs, - std::string const &options, - py::object py_devices - ) - { - PYOPENCL_PARSE_PY_DEVICES; - - std::vector<cl_program> programs; - PYTHON_FOREACH(py_prg, py_programs) - { - program &prg = py::extract<program &>(py_prg); - programs.push_back(prg.data()); - } - - cl_int status_code; - PYOPENCL_PRINT_CALL_TRACE("clLinkProgram"); - cl_program result = clLinkProgram( - ctx.data(), num_devices, devices, - options.c_str(), - programs.size(), - programs.empty() ? NULL : &programs.front(), - 0, 0, - &status_code); - - if (status_code != CL_SUCCESS) - throw pyopencl::error("clLinkPorgram", status_code); - - try - { - return new program(result, false); - } - catch (...) - { - clReleaseProgram(result); - throw; - } - } - -#endif - - -#if PYOPENCL_CL_VERSION >= 0x1020 - inline - void unload_platform_compiler(platform &plat) - { - PYOPENCL_CALL_GUARDED(clUnloadPlatformCompiler, (plat.data())); - } -#endif - - // }}} - - // {{{ kernel - class local_memory - { - private: - size_t m_size; - - public: - local_memory(size_t size) - : m_size(size) - { } - - size_t size() const - { return m_size; } - }; - - - - - class kernel : boost::noncopyable - { - private: - cl_kernel m_kernel; - - public: - kernel(cl_kernel knl, bool retain) - : m_kernel(knl) - { - if (retain) - PYOPENCL_CALL_GUARDED(clRetainKernel, (knl)); - } - - kernel(program const &prg, std::string const &kernel_name) - { - cl_int status_code; - - PYOPENCL_PRINT_CALL_TRACE("clCreateKernel"); - m_kernel = clCreateKernel(prg.data(), kernel_name.c_str(), - &status_code); - if (status_code != CL_SUCCESS) - throw pyopencl::error("clCreateKernel", status_code); - } - - ~kernel() - { - PYOPENCL_CALL_GUARDED_CLEANUP(clReleaseKernel, (m_kernel)); - } - - cl_kernel data() const - { - return m_kernel; - } - - PYOPENCL_EQUALITY_TESTS(kernel); - - void set_arg_null(cl_uint arg_index) - { - cl_mem m = 0; - PYOPENCL_CALL_GUARDED(clSetKernelArg, (m_kernel, arg_index, - sizeof(cl_mem), &m)); - } - - void set_arg_mem(cl_uint arg_index, memory_object_holder &moh) - { - cl_mem m = moh.data(); - PYOPENCL_CALL_GUARDED(clSetKernelArg, - (m_kernel, arg_index, sizeof(cl_mem), &m)); - } - - void set_arg_local(cl_uint arg_index, local_memory const &loc) - { - PYOPENCL_CALL_GUARDED(clSetKernelArg, - (m_kernel, arg_index, loc.size(), 0)); - } - - void set_arg_sampler(cl_uint arg_index, sampler const &smp) - { - cl_sampler s = smp.data(); - PYOPENCL_CALL_GUARDED(clSetKernelArg, - (m_kernel, arg_index, sizeof(cl_sampler), &s)); - } - - void set_arg_buf(cl_uint arg_index, py::object py_buffer) - { - const void *buf; - PYOPENCL_BUFFER_SIZE_T len; - - if (PyObject_AsReadBuffer(py_buffer.ptr(), &buf, &len)) - { - PyErr_Clear(); - throw error("Kernel.set_arg", CL_INVALID_VALUE, - "invalid kernel argument"); - } - - PYOPENCL_CALL_GUARDED(clSetKernelArg, - (m_kernel, arg_index, len, buf)); - } - - void set_arg(cl_uint arg_index, py::object arg) - { - if (arg.ptr() == Py_None) - { - set_arg_null(arg_index); - return; - } - - py::extract<memory_object_holder &> ex_mo(arg); - if (ex_mo.check()) - { - set_arg_mem(arg_index, ex_mo()); - return; - } - - py::extract<local_memory const &> ex_loc(arg); - if (ex_loc.check()) - { - set_arg_local(arg_index, ex_loc()); - return; - } - - py::extract<sampler const &> ex_smp(arg); - if (ex_smp.check()) - { - set_arg_sampler(arg_index, ex_smp()); - return; - } - - set_arg_buf(arg_index, arg); - } - - py::object get_info(cl_kernel_info param_name) const - { - switch (param_name) - { - case CL_KERNEL_FUNCTION_NAME: - PYOPENCL_GET_STR_INFO(Kernel, m_kernel, param_name); - case CL_KERNEL_NUM_ARGS: - case CL_KERNEL_REFERENCE_COUNT: - PYOPENCL_GET_INTEGRAL_INFO(Kernel, m_kernel, param_name, - cl_uint); - case CL_KERNEL_CONTEXT: - PYOPENCL_GET_OPAQUE_INFO(Kernel, m_kernel, param_name, - cl_context, context); - case CL_KERNEL_PROGRAM: - PYOPENCL_GET_OPAQUE_INFO(Kernel, m_kernel, param_name, - cl_program, program); -#if PYOPENCL_CL_VERSION >= 0x1020 - case CL_KERNEL_ATTRIBUTES: - PYOPENCL_GET_STR_INFO(Kernel, m_kernel, param_name); -#endif - default: - throw error("Kernel.get_info", CL_INVALID_VALUE); - } - } - - py::object get_work_group_info( - cl_kernel_work_group_info param_name, - device const &dev - ) const - { - switch (param_name) - { -#define PYOPENCL_FIRST_ARG m_kernel, dev.data() // hackety hack - case CL_KERNEL_WORK_GROUP_SIZE: - PYOPENCL_GET_INTEGRAL_INFO(KernelWorkGroup, - PYOPENCL_FIRST_ARG, param_name, - size_t); - case CL_KERNEL_COMPILE_WORK_GROUP_SIZE: - { - std::vector<size_t> result; - PYOPENCL_GET_VEC_INFO(KernelWorkGroup, - PYOPENCL_FIRST_ARG, param_name, result); - - PYOPENCL_RETURN_VECTOR(size_t, result); - } - case CL_KERNEL_LOCAL_MEM_SIZE: -#if PYOPENCL_CL_VERSION >= 0x1010 - case CL_KERNEL_PRIVATE_MEM_SIZE: -#endif - PYOPENCL_GET_INTEGRAL_INFO(KernelWorkGroup, - PYOPENCL_FIRST_ARG, param_name, - cl_ulong); - -#if PYOPENCL_CL_VERSION >= 0x1010 - case CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE: - PYOPENCL_GET_INTEGRAL_INFO(KernelWorkGroup, - PYOPENCL_FIRST_ARG, param_name, - size_t); -#endif - default: - throw error("Kernel.get_work_group_info", CL_INVALID_VALUE); -#undef PYOPENCL_FIRST_ARG - } - } - -#if PYOPENCL_CL_VERSION >= 0x1020 - py::object get_arg_info( - cl_uint arg_index, - cl_kernel_arg_info param_name - ) const - { - switch (param_name) - { -#define PYOPENCL_FIRST_ARG m_kernel, arg_index // hackety hack - case CL_KERNEL_ARG_ADDRESS_QUALIFIER: - PYOPENCL_GET_INTEGRAL_INFO(KernelArg, - PYOPENCL_FIRST_ARG, param_name, - cl_kernel_arg_address_qualifier); - - case CL_KERNEL_ARG_ACCESS_QUALIFIER: - PYOPENCL_GET_INTEGRAL_INFO(KernelArg, - PYOPENCL_FIRST_ARG, param_name, - cl_kernel_arg_access_qualifier); - - case CL_KERNEL_ARG_TYPE_NAME: - case CL_KERNEL_ARG_NAME: - PYOPENCL_GET_STR_INFO(KernelArg, PYOPENCL_FIRST_ARG, param_name); -#undef PYOPENCL_FIRST_ARG - default: - throw error("Kernel.get_arg_info", CL_INVALID_VALUE); - } - } -#endif - }; - - - inline - py::list create_kernels_in_program(program &pgm) - { - cl_uint num_kernels; - PYOPENCL_CALL_GUARDED(clCreateKernelsInProgram, ( - pgm.data(), 0, 0, &num_kernels)); - - std::vector<cl_kernel> kernels(num_kernels); - PYOPENCL_CALL_GUARDED(clCreateKernelsInProgram, ( - pgm.data(), num_kernels, - kernels.empty( ) ? NULL : &kernels.front(), &num_kernels)); - - py::list result; - BOOST_FOREACH(cl_kernel knl, kernels) - result.append(handle_from_new_ptr(new kernel(knl, true))); - - return result; - } - - - - inline - event *enqueue_nd_range_kernel( - command_queue &cq, - kernel &knl, - py::object py_global_work_size, - py::object py_local_work_size, - py::object py_global_work_offset, - py::object py_wait_for, - bool g_times_l) - { - PYOPENCL_PARSE_WAIT_FOR; - - cl_uint work_dim = len(py_global_work_size); - - std::vector<size_t> global_work_size; - COPY_PY_LIST(size_t, global_work_size); - - size_t *local_work_size_ptr = 0; - std::vector<size_t> local_work_size; - if (py_local_work_size.ptr() != Py_None) - { - if (g_times_l) - work_dim = std::max(work_dim, unsigned(len(py_local_work_size))); - else - if (work_dim != unsigned(len(py_local_work_size))) - throw error("enqueue_nd_range_kernel", CL_INVALID_VALUE, - "global/local work sizes have differing dimensions"); - - COPY_PY_LIST(size_t, local_work_size); - - while (local_work_size.size() < work_dim) - local_work_size.push_back(1); - while (global_work_size.size() < work_dim) - global_work_size.push_back(1); - - local_work_size_ptr = local_work_size.empty( ) ? NULL : &local_work_size.front(); - } - - if (g_times_l && local_work_size_ptr) - { - for (cl_uint work_axis = 0; work_axis < work_dim; ++work_axis) - global_work_size[work_axis] *= local_work_size[work_axis]; - } - - size_t *global_work_offset_ptr = 0; - std::vector<size_t> global_work_offset; - if (py_global_work_offset.ptr() != Py_None) - { - if (work_dim != unsigned(len(py_global_work_offset))) - throw error("enqueue_nd_range_kernel", CL_INVALID_VALUE, - "global work size and offset have differing dimensions"); - - COPY_PY_LIST(size_t, global_work_offset); - - if (g_times_l && local_work_size_ptr) - { - for (cl_uint work_axis = 0; work_axis < work_dim; ++work_axis) - global_work_offset[work_axis] *= local_work_size[work_axis]; - } - - global_work_offset_ptr = global_work_offset.empty( ) ? NULL : &global_work_offset.front(); - } - - PYOPENCL_RETRY_RETURN_IF_MEM_ERROR( { - cl_event evt; - PYOPENCL_CALL_GUARDED(clEnqueueNDRangeKernel, ( - cq.data(), - knl.data(), - work_dim, - global_work_offset_ptr, - global_work_size.empty( ) ? NULL : &global_work_size.front(), - local_work_size_ptr, - PYOPENCL_WAITLIST_ARGS, &evt - )); - PYOPENCL_RETURN_NEW_EVENT(evt); - } ); - } - - - - - - - inline - event *enqueue_task( - command_queue &cq, - kernel &knl, - py::object py_wait_for) - { - PYOPENCL_PARSE_WAIT_FOR; - - PYOPENCL_RETRY_RETURN_IF_MEM_ERROR( { - cl_event evt; - PYOPENCL_CALL_GUARDED(clEnqueueTask, ( - cq.data(), - knl.data(), - PYOPENCL_WAITLIST_ARGS, &evt - )); - PYOPENCL_RETURN_NEW_EVENT(evt); - } ); - } - - // }}} - - // {{{ 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, py::object *hostbuf=0) - : memory_object(mem, retain, hostbuf) - { } - }; - - - - - class gl_renderbuffer : public memory_object - { - public: - gl_renderbuffer(cl_mem mem, bool retain, py::object *hostbuf=0) - : memory_object(mem, retain, hostbuf) - { } - }; - - - - - class gl_texture : public image - { - public: - gl_texture(cl_mem mem, bool retain, py::object *hostbuf=0) - : image(mem, retain, hostbuf) - { } - - py::object get_gl_texture_info(cl_gl_texture_info param_name) - { - switch (param_name) - { - case CL_GL_TEXTURE_TARGET: - PYOPENCL_GET_INTEGRAL_INFO(GLTexture, data(), param_name, GLenum); - case CL_GL_MIPMAP_LEVEL: - PYOPENCL_GET_INTEGRAL_INFO(GLTexture, data(), param_name, GLint); - - 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; \ - PYTHON_FOREACH(mo, py_mem_objects) \ - mem_objects.push_back(py::extract<memory_object_holder &>(mo)().data()); \ - \ - cl_event evt; \ - PYOPENCL_CALL_GUARDED(clEnqueue##What##GLObjects, ( \ - cq.data(), \ - mem_objects.size(), mem_objects.empty( ) ? NULL : &mem_objects.front(), \ - 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::extract<platform &>(py_platform); - - 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 - = props.empty( ) ? NULL : &props.front(); - - 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( ) ? NULL : &devices.front(), &size)); - - py::list result; - BOOST_FOREACH(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 - - inline py::object create_mem_object_wrapper(cl_mem mem) - { - 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*/ true))); - 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*/ true))); - default: - return py::object(handle_from_new_ptr( - new memory_object(mem, /*retain*/ true))); - } - } - - inline - py::object memory_object_from_int(intptr_t cl_mem_as_int) - { - return create_mem_object_wrapper((cl_mem) cl_mem_as_int); - } - - - inline - py::object memory_object_holder::get_info(cl_mem_info param_name) const - { - switch (param_name) - { - case CL_MEM_TYPE: - PYOPENCL_GET_INTEGRAL_INFO(MemObject, data(), param_name, - cl_mem_object_type); - case CL_MEM_FLAGS: - PYOPENCL_GET_INTEGRAL_INFO(MemObject, data(), param_name, - cl_mem_flags); - case CL_MEM_SIZE: - PYOPENCL_GET_INTEGRAL_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_INTEGRAL_INFO(MemObject, data(), param_name, - cl_uint); - case CL_MEM_REFERENCE_COUNT: - PYOPENCL_GET_INTEGRAL_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 py::object(); - } - - return create_mem_object_wrapper(param_value); - } - case CL_MEM_OFFSET: - PYOPENCL_GET_INTEGRAL_INFO(MemObject, data(), param_name, - size_t); -#endif - - default: - throw error("MemoryObjectHolder.get_info", CL_INVALID_VALUE); - } - } - - inline - py::handle<> 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 = - py::extract<memory_object_holder const &>(mem_obj_py); - PyArray_Descr *tp_descr; - if (PyArray_DescrConverter(dtype.ptr(), &tp_descr) != NPY_SUCCEED) - throw py::error_already_set(); - - py::extract<npy_intp> shape_as_int(shape); - std::vector<npy_intp> dims; - - if (shape_as_int.check()) - dims.push_back(shape_as_int()); - else - std::copy( - py::stl_input_iterator<npy_intp>(shape), - py::stl_input_iterator<npy_intp>(), - back_inserter(dims)); - - 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::handle<> result = py::handle<>(PyArray_NewFromDescr( - &PyArray_Type, tp_descr, - dims.size(), &dims.front(), /*strides*/ NULL, - host_ptr, ary_flags, /*obj*/NULL)); - - if ((size_t) PyArray_NBYTES(result.get()) > mem_obj_size) - throw pyopencl::error("MemoryObject.get_host_array", - CL_INVALID_VALUE, - "Resulting array is larger than memory object."); - - PyArray_BASE(result.get()) = mem_obj_py.ptr(); - Py_INCREF(mem_obj_py.ptr()); - - return result; - } - - // }}} - -} - - - - -#endif - -// vim: foldmethod=marker diff --git a/src/wrapper/wrap_cl_part_1.cpp b/src/wrapper/wrap_cl_part_1.cpp deleted file mode 100644 index f3448aca..00000000 --- a/src/wrapper/wrap_cl_part_1.cpp +++ /dev/null @@ -1,312 +0,0 @@ -#include "wrap_cl.hpp" - - - - -using namespace pyopencl; - - - - -void pyopencl_expose_part_1() -{ - py::docstring_options doc_op; - doc_op.disable_cpp_signatures(); - - py::def("get_cl_header_version", get_cl_header_version); - - // {{{ platform - DEF_SIMPLE_FUNCTION(get_platforms); - - { - typedef platform cls; - py::class_<cls, boost::noncopyable>("Platform", py::no_init) - .DEF_SIMPLE_METHOD(get_info) - .def("get_devices", &cls::get_devices, - py::arg("device_type")=CL_DEVICE_TYPE_ALL) - .def(py::self == py::self) - .def(py::self != py::self) - .def("__hash__", &cls::hash) - PYOPENCL_EXPOSE_TO_FROM_INT_PTR(cl_platform_id) - ; - } - - // }}} - - // {{{ device - { - typedef device cls; - py::class_<cls, boost::noncopyable>("Device", py::no_init) - .DEF_SIMPLE_METHOD(get_info) - .def(py::self == py::self) - .def(py::self != py::self) - .def("__hash__", &cls::hash) -#if defined(cl_ext_device_fission) && defined(PYOPENCL_USE_DEVICE_FISSION) - .DEF_SIMPLE_METHOD(create_sub_devices_ext) -#endif -#if PYOPENCL_CL_VERSION >= 0x1020 - .DEF_SIMPLE_METHOD(create_sub_devices) -#endif - PYOPENCL_EXPOSE_TO_FROM_INT_PTR(cl_device_id) - ; - } - - // }}} - - // {{{ context - - { - typedef context cls; - py::class_<cls, boost::noncopyable, - boost::shared_ptr<cls> >("Context", py::no_init) - .def("__init__", make_constructor(create_context, - py::default_call_policies(), - (py::arg("devices")=py::object(), - py::arg("properties")=py::object(), - py::arg("dev_type")=py::object() - ))) - .DEF_SIMPLE_METHOD(get_info) - .def(py::self == py::self) - .def(py::self != py::self) - .def("__hash__", &cls::hash) - PYOPENCL_EXPOSE_TO_FROM_INT_PTR(cl_context) - ; - } - - // }}} - - // {{{ command queue - { - typedef command_queue cls; - py::class_<cls, boost::noncopyable>("CommandQueue", - py::init<const context &, - const device *, cl_command_queue_properties> - ((py::arg("context"), py::arg("device")=py::object(), py::arg("properties")=0))) - .DEF_SIMPLE_METHOD(get_info) -#if PYOPENCL_CL_VERSION < 0x1010 - .DEF_SIMPLE_METHOD(set_property) -#endif - .DEF_SIMPLE_METHOD(flush) - .DEF_SIMPLE_METHOD(finish) - .def(py::self == py::self) - .def(py::self != py::self) - .def("__hash__", &cls::hash) - PYOPENCL_EXPOSE_TO_FROM_INT_PTR(cl_command_queue) - ; - } - - // }}} - - // {{{ events/synchronization - { - typedef event cls; - py::class_<cls, boost::noncopyable>("Event", py::no_init) - .DEF_SIMPLE_METHOD(get_info) - .DEF_SIMPLE_METHOD(get_profiling_info) - .DEF_SIMPLE_METHOD(wait) - .def(py::self == py::self) - .def(py::self != py::self) - .def("__hash__", &cls::hash) - PYOPENCL_EXPOSE_TO_FROM_INT_PTR(cl_event) - - // deprecated, remove in 2015.x. - .def("from_cl_event_as_int", from_int_ptr<cls, cl_event>, - py::return_value_policy<py::manage_new_object>()) - .staticmethod("from_cl_event_as_int") - ; - } - { - typedef nanny_event cls; - py::class_<cls, boost::noncopyable, py::bases<event> >("NannyEvent", py::no_init) - .DEF_SIMPLE_METHOD(get_ward) - ; - } - - DEF_SIMPLE_FUNCTION(wait_for_events); - -#if PYOPENCL_CL_VERSION >= 0x1020 - py::def("_enqueue_marker_with_wait_list", enqueue_marker_with_wait_list, - (py::arg("queue"), py::arg("wait_for")=py::object()), - py::return_value_policy<py::manage_new_object>()); -#endif - py::def("_enqueue_marker", enqueue_marker, - (py::arg("queue")), - py::return_value_policy<py::manage_new_object>()); - py::def("_enqueue_wait_for_events", enqueue_wait_for_events, - (py::arg("queue"), py::arg("wait_for")=py::object())); - -#if PYOPENCL_CL_VERSION >= 0x1020 - py::def("_enqueue_barrier_with_wait_list", enqueue_barrier_with_wait_list, - (py::arg("queue"), py::arg("wait_for")=py::object()), - py::return_value_policy<py::manage_new_object>()); -#endif - py::def("_enqueue_barrier", enqueue_barrier, py::arg("queue")); - -#if PYOPENCL_CL_VERSION >= 0x1010 - { - typedef user_event cls; - py::class_<cls, py::bases<event>, boost::noncopyable>("UserEvent", py::no_init) - .def("__init__", make_constructor( - create_user_event, py::default_call_policies(), py::args("context"))) - .DEF_SIMPLE_METHOD(set_status) - ; - } -#endif - - // }}} - - // {{{ memory_object - - { - typedef memory_object_holder cls; - py::class_<cls, boost::noncopyable>( - "MemoryObjectHolder", py::no_init) - .DEF_SIMPLE_METHOD(get_info) - .def("get_host_array", get_mem_obj_host_array, - (py::arg("shape"), py::arg("dtype"), py::arg("order")="C")) - .def(py::self == py::self) - .def(py::self != py::self) - .def("__hash__", &cls::hash) - - .add_property("int_ptr", to_int_ptr<cls>, - "Return an integer corresponding to the pointer value " - "of the underlying :c:type:`cl_mem`. " - "Use :meth:`from_int_ptr` to turn back into a Python object." - "\n\n.. versionadded:: 2013.2\n") - ; - } - { - typedef memory_object cls; - py::class_<cls, boost::noncopyable, py::bases<memory_object_holder> >( - "MemoryObject", py::no_init) - .DEF_SIMPLE_METHOD(release) - .add_property("hostbuf", &cls::hostbuf) - - .def("from_int_ptr", memory_object_from_int, - "(static method) Return a new Python object referencing the C-level " \ - ":c:type:`cl_mem` object at the location pointed to " \ - "by *int_ptr_value*. The relevant :c:func:`clRetain*` function " \ - "will be called." \ - "\n\n.. versionadded:: 2013.2\n") \ - .staticmethod("from_int_ptr") - - // deprecated, remove in 2015.x - .def("from_cl_mem_as_int", memory_object_from_int) - .staticmethod("from_cl_mem_as_int") - ; - } - -#if PYOPENCL_CL_VERSION >= 0x1020 - py::def("enqueue_migrate_mem_objects", enqueue_migrate_mem_objects, - (py::args("queue", "mem_objects"), - py::arg("flags")=0, - py::arg("wait_for")=py::object() - ), - py::return_value_policy<py::manage_new_object>()); -#endif - -#ifdef cl_ext_migrate_memobject - py::def("enqueue_migrate_mem_object_ext", enqueue_migrate_mem_object_ext, - (py::args("queue", "mem_objects"), - py::arg("flags")=0, - py::arg("wait_for")=py::object() - ), - py::return_value_policy<py::manage_new_object>()); -#endif - // }}} - - // {{{ buffer - { - typedef buffer cls; - py::class_<cls, py::bases<memory_object>, boost::noncopyable>( - "Buffer", py::no_init) - .def("__init__", make_constructor(create_buffer_py, - py::default_call_policies(), - (py::args("context", "flags"), - py::arg("size")=0, - py::arg("hostbuf")=py::object() - ))) -#if PYOPENCL_CL_VERSION >= 0x1010 - .def("get_sub_region", &cls::get_sub_region, - (py::args("origin", "size"), py::arg("flags")=0), - py::return_value_policy<py::manage_new_object>()) - .def("__getitem__", &cls::getitem, - py::return_value_policy<py::manage_new_object>()) -#endif - ; - } - - // }}} - - // {{{ transfers - - // {{{ byte-for-byte - py::def("_enqueue_read_buffer", enqueue_read_buffer, - (py::args("queue", "mem", "hostbuf"), - py::arg("device_offset")=0, - py::arg("wait_for")=py::object(), - py::arg("is_blocking")=true - ), - py::return_value_policy<py::manage_new_object>()); - py::def("_enqueue_write_buffer", enqueue_write_buffer, - (py::args("queue", "mem", "hostbuf"), - py::arg("device_offset")=0, - py::arg("wait_for")=py::object(), - py::arg("is_blocking")=true - ), - py::return_value_policy<py::manage_new_object>()); - py::def("_enqueue_copy_buffer", enqueue_copy_buffer, - (py::args("queue", "src", "dst"), - py::arg("byte_count")=-1, - py::arg("src_offset")=0, - py::arg("dst_offset")=0, - py::arg("wait_for")=py::object() - ), - py::return_value_policy<py::manage_new_object>()); - - // }}} - - // {{{ rectangular - -#if PYOPENCL_CL_VERSION >= 0x1010 - py::def("_enqueue_read_buffer_rect", enqueue_read_buffer_rect, - (py::args("queue", "mem", "hostbuf", - "buffer_origin", "host_origin", "region"), - py::arg("buffer_pitches")=py::object(), - py::arg("host_pitches")=py::object(), - py::arg("wait_for")=py::object(), - py::arg("is_blocking")=true - ), - py::return_value_policy<py::manage_new_object>()); - py::def("_enqueue_write_buffer_rect", enqueue_write_buffer_rect, - (py::args("queue", "mem", "hostbuf", - "buffer_origin", "host_origin", "region"), - py::arg("buffer_pitches")=py::object(), - py::arg("host_pitches")=py::object(), - py::arg("wait_for")=py::object(), - py::arg("is_blocking")=true - ), - py::return_value_policy<py::manage_new_object>()); - py::def("_enqueue_copy_buffer_rect", enqueue_copy_buffer_rect, - (py::args("queue", "src", "dst", - "src_origin", "dst_origin", "region"), - py::arg("src_pitches")=py::object(), - py::arg("dst_pitches")=py::object(), - py::arg("wait_for")=py::object() - ), - py::return_value_policy<py::manage_new_object>()); -#endif - - // }}} - - // }}} - -#if PYOPENCL_CL_VERSION >= 0x1020 - py::def("_enqueue_fill_buffer", enqueue_fill_buffer, - (py::args("queue", "mem", "pattern", "offset", "size"), - py::arg("wait_for")=py::object()), - py::return_value_policy<py::manage_new_object>()); -#endif -} - -// vim: foldmethod=marker diff --git a/src/wrapper/wrap_cl_part_2.cpp b/src/wrapper/wrap_cl_part_2.cpp deleted file mode 100644 index 4d010796..00000000 --- a/src/wrapper/wrap_cl_part_2.cpp +++ /dev/null @@ -1,359 +0,0 @@ -#include "wrap_cl.hpp" - - - - -namespace pyopencl { -#if PYOPENCL_CL_VERSION >= 0x1020 - py::object image_desc_dummy_getter(cl_image_desc &desc) - { - return py::object(); - } - - void image_desc_set_shape(cl_image_desc &desc, py::object py_shape) - { - COPY_PY_REGION_TRIPLE(shape); - desc.image_width = shape[0]; - desc.image_height = shape[1]; - desc.image_depth = shape[2]; - desc.image_array_size = shape[2]; - } - - void image_desc_set_pitches(cl_image_desc &desc, py::object py_pitches) - { - COPY_PY_PITCH_TUPLE(pitches); - desc.image_row_pitch = pitches[0]; - desc.image_slice_pitch = pitches[1]; - } - - void image_desc_set_buffer(cl_image_desc &desc, memory_object *mobj) - { - if (mobj) - desc.buffer = mobj->data(); - else - desc.buffer = 0; - } - -#endif -} - - - - -using namespace pyopencl; - - - - -void pyopencl_expose_part_2() -{ - py::docstring_options doc_op; - doc_op.disable_cpp_signatures(); - - // {{{ image - -#if PYOPENCL_CL_VERSION >= 0x1020 - { - typedef cl_image_desc cls; - py::class_<cls>("ImageDescriptor") - .def_readwrite("image_type", &cls::image_type) - .add_property("shape", &image_desc_dummy_getter, image_desc_set_shape) - .def_readwrite("array_size", &cls::image_array_size) - .add_property("pitches", &image_desc_dummy_getter, image_desc_set_pitches) - .def_readwrite("num_mip_levels", &cls::num_mip_levels) - .def_readwrite("num_samples", &cls::num_samples) - .add_property("buffer", &image_desc_dummy_getter, image_desc_set_buffer) - ; - } -#endif - - { - typedef image cls; - py::class_<cls, py::bases<memory_object>, boost::noncopyable>( - "Image", py::no_init) - .def("__init__", make_constructor(create_image, - py::default_call_policies(), - (py::args("context", "flags", "format"), - py::arg("shape")=py::object(), - py::arg("pitches")=py::object(), - py::arg("hostbuf")=py::object() - ))) -#if PYOPENCL_CL_VERSION >= 0x1020 - .def("__init__", make_constructor(create_image_from_desc, - py::default_call_policies(), - (py::args("context", "flags", "format", "desc"), - py::arg("hostbuf")=py::object()))) -#endif - .DEF_SIMPLE_METHOD(get_image_info) - ; - } - - { - typedef cl_image_format cls; - py::class_<cls>("ImageFormat") - .def("__init__", py::make_constructor(make_image_format)) - .def_readwrite("channel_order", &cls::image_channel_order) - .def_readwrite("channel_data_type", &cls::image_channel_data_type) - .add_property("channel_count", &get_image_format_channel_count) - .add_property("dtype_size", &get_image_format_channel_dtype_size) - .add_property("itemsize", &get_image_format_item_size) - ; - } - - DEF_SIMPLE_FUNCTION(get_supported_image_formats); - - py::def("_enqueue_read_image", enqueue_read_image, - (py::args("queue", "mem", "origin", "region", "hostbuf"), - py::arg("row_pitch")=0, - py::arg("slice_pitch")=0, - py::arg("wait_for")=py::object(), - py::arg("is_blocking")=true - ), - py::return_value_policy<py::manage_new_object>()); - py::def("_enqueue_write_image", enqueue_write_image, - (py::args("queue", "mem", "origin", "region", "hostbuf"), - py::arg("row_pitch")=0, - py::arg("slice_pitch")=0, - py::arg("wait_for")=py::object(), - py::arg("is_blocking")=true - ), - py::return_value_policy<py::manage_new_object>()); - - py::def("_enqueue_copy_image", enqueue_copy_image, - (py::args("queue", "src", "dest", "src_origin", "dest_origin", "region"), - py::arg("wait_for")=py::object()), - py::return_value_policy<py::manage_new_object>()); - py::def("_enqueue_copy_image_to_buffer", enqueue_copy_image_to_buffer, - (py::args("queue", "src", "dest", "origin", "region", "offset"), - py::arg("wait_for")=py::object()), - py::return_value_policy<py::manage_new_object>()); - py::def("_enqueue_copy_buffer_to_image", enqueue_copy_buffer_to_image, - (py::args("queue", "src", "dest", "offset", "origin", "region"), - py::arg("wait_for")=py::object()), - py::return_value_policy<py::manage_new_object>()); - -#if PYOPENCL_CL_VERSION >= 0x1020 - py::def("enqueue_fill_image", enqueue_write_image, - (py::args("queue", "mem", "color", "origin", "region"), - py::arg("wait_for")=py::object()), - py::return_value_policy<py::manage_new_object>()); -#endif - - // }}} - - // {{{ memory_map - { - typedef memory_map cls; - py::class_<cls, boost::noncopyable>("MemoryMap", py::no_init) - .def("release", &cls::release, - (py::arg("queue")=0, py::arg("wait_for")=py::object()), - py::return_value_policy<py::manage_new_object>()) - ; - } - - py::def("enqueue_map_buffer", enqueue_map_buffer, - (py::args("queue", "buf", "flags", - "offset", - "shape", "dtype"), - py::arg("order")="C", - py::arg("strides")=py::object(), - py::arg("wait_for")=py::object(), - py::arg("is_blocking")=true)); - py::def("enqueue_map_image", enqueue_map_image, - (py::args("queue", "img", "flags", - "origin", "region", - "shape", "dtype"), - py::arg("order")="C", - py::arg("strides")=py::object(), - py::arg("wait_for")=py::object(), - py::arg("is_blocking")=true)); - - // }}} - - // {{{ sampler - { - typedef sampler cls; - py::class_<cls, boost::noncopyable>("Sampler", - py::init<context const &, bool, cl_addressing_mode, cl_filter_mode>()) - .DEF_SIMPLE_METHOD(get_info) - .def(py::self == py::self) - .def(py::self != py::self) - .def("__hash__", &cls::hash) - PYOPENCL_EXPOSE_TO_FROM_INT_PTR(cl_sampler) - ; - } - - // }}} - - // {{{ program - { - typedef program cls; - py::enum_<cls::program_kind_type>("program_kind") - .value("UNKNOWN", cls::KND_UNKNOWN) - .value("SOURCE", cls::KND_SOURCE) - .value("BINARY", cls::KND_BINARY) - ; - - py::class_<cls, boost::noncopyable>("_Program", py::no_init) - .def("__init__", make_constructor( - create_program_with_source, - py::default_call_policies(), - py::args("context", "src"))) - .def("__init__", make_constructor( - create_program_with_binary, - py::default_call_policies(), - py::args("context", "devices", "binaries"))) -#if (PYOPENCL_CL_VERSION >= 0x1020) && \ - ((PYOPENCL_CL_VERSION >= 0x1030) && defined(__APPLE__)) - .def("create_with_built_in_kernels", - create_program_with_built_in_kernels, - py::args("context", "devices", "kernel_names"), - py::return_value_policy<py::manage_new_object>()) - .staticmethod("create_with_built_in_kernels") -#endif - .DEF_SIMPLE_METHOD(kind) - .DEF_SIMPLE_METHOD(get_info) - .DEF_SIMPLE_METHOD(get_build_info) - .def("_build", &cls::build, - (py::arg("options")="", py::arg("devices")=py::object())) -#if PYOPENCL_CL_VERSION >= 0x1020 - .def("compile", &cls::compile, - (py::arg("options")="", py::arg("devices")=py::object(), - py::arg("headers")=py::list())) - .def("link", &link_program, - (py::arg("context"), - py::arg("programs"), - py::arg("options")="", - py::arg("devices")=py::object()), - py::return_value_policy<py::manage_new_object>()) - .staticmethod("link") -#endif - .def(py::self == py::self) - .def(py::self != py::self) - .def("__hash__", &cls::hash) - .def("all_kernels", create_kernels_in_program) - PYOPENCL_EXPOSE_TO_FROM_INT_PTR(cl_program) - ; - } - -#if PYOPENCL_CL_VERSION >= 0x1020 - py::def("unload_platform_compiler", unload_platform_compiler); -#endif - - // }}} - - // {{{ kernel - - { - typedef kernel cls; - py::class_<cls, boost::noncopyable>("Kernel", - py::init<const program &, std::string const &>()) - .DEF_SIMPLE_METHOD(get_info) - .DEF_SIMPLE_METHOD(get_work_group_info) - .DEF_SIMPLE_METHOD(set_arg) -#if PYOPENCL_CL_VERSION >= 0x1020 - .DEF_SIMPLE_METHOD(get_arg_info) -#endif - .def(py::self == py::self) - .def(py::self != py::self) - .def("__hash__", &cls::hash) - PYOPENCL_EXPOSE_TO_FROM_INT_PTR(cl_kernel) - ; - } - - { - typedef local_memory cls; - py::class_<cls, boost::noncopyable>("LocalMemory", - py::init<size_t>(py::arg("size"))) - .add_property("size", &cls::size) - ; - } - - - py::def("enqueue_nd_range_kernel", enqueue_nd_range_kernel, - (py::args("queue", "kernel"), - py::arg("global_work_size"), - py::arg("local_work_size"), - py::arg("global_work_offset")=py::object(), - py::arg("wait_for")=py::object(), - py::arg("g_times_l")=false - ), - py::return_value_policy<py::manage_new_object>()); - py::def("enqueue_task", enqueue_task, - (py::args("queue", "kernel"), - py::arg("wait_for")=py::object() - ), - py::return_value_policy<py::manage_new_object>()); - - // TODO: clEnqueueNativeKernel - // }}} - - // {{{ GL interop - DEF_SIMPLE_FUNCTION(have_gl); - -#ifdef HAVE_GL - -#ifdef __APPLE__ - DEF_SIMPLE_FUNCTION(get_apple_cgl_share_group); -#endif /* __APPLE__ */ - - { - typedef gl_buffer cls; - py::class_<cls, py::bases<memory_object>, boost::noncopyable>( - "GLBuffer", py::no_init) - .def("__init__", make_constructor(create_from_gl_buffer, - py::default_call_policies(), - (py::args("context", "flags", "bufobj")))) - .def("get_gl_object_info", get_gl_object_info) - ; - } - - { - typedef gl_renderbuffer cls; - py::class_<cls, py::bases<memory_object>, boost::noncopyable>( - "GLRenderBuffer", py::no_init) - .def("__init__", make_constructor(create_from_gl_renderbuffer, - py::default_call_policies(), - (py::args("context", "flags", "bufobj")))) - .def("get_gl_object_info", get_gl_object_info) - ; - } - - { - typedef gl_texture cls; - py::class_<cls, py::bases<image>, boost::noncopyable>( - "GLTexture", py::no_init) - .def("__init__", make_constructor(create_from_gl_texture, - py::default_call_policies(), - (py::args("context", "flags", - "texture_target", "miplevel", - "texture", "dims")))) - .def("get_gl_object_info", get_gl_object_info) - .DEF_SIMPLE_METHOD(get_gl_texture_info) - ; - } - - py::def("enqueue_acquire_gl_objects", enqueue_acquire_gl_objects, - (py::args("queue", "mem_objects"), - py::arg("wait_for")=py::object() - ), - py::return_value_policy<py::manage_new_object>()); - py::def("enqueue_release_gl_objects", enqueue_release_gl_objects, - (py::args("queue", "mem_objects"), - py::arg("wait_for")=py::object() - ), - py::return_value_policy<py::manage_new_object>()); - -#if defined(cl_khr_gl_sharing) && (cl_khr_gl_sharing >= 1) - py::def("get_gl_context_info_khr", get_gl_context_info_khr, - (py::args("properties", "param_name"), py::arg("platform")=py::object())); -#endif - -#endif - // }}} -} - - - - -// vim: foldmethod=marker diff --git a/src/wrapper/wrap_constants.cpp b/src/wrapper/wrap_constants.cpp deleted file mode 100644 index 64511d01..00000000 --- a/src/wrapper/wrap_constants.cpp +++ /dev/null @@ -1,868 +0,0 @@ -#include "wrap_cl.hpp" - - - - -using namespace pyopencl; - - - - -namespace -{ - py::handle<> - CLError, - CLMemoryError, - CLLogicError, - CLRuntimeError; - - - - - void translate_cl_error(const error &err) - { - if (err.code() == CL_MEM_OBJECT_ALLOCATION_FAILURE) - PyErr_SetObject(CLMemoryError.get(), py::object(err).ptr()); - else if (err.code() <= CL_INVALID_VALUE) - PyErr_SetObject(CLLogicError.get(), py::object(err).ptr()); - else if (err.code() > CL_INVALID_VALUE && err.code() < CL_SUCCESS) - PyErr_SetObject(CLRuntimeError.get(), py::object(err).ptr()); - else - PyErr_SetObject(CLError.get(), py::object(err).ptr()); - } - - - - - // {{{ 'fake' constant scopes - class status_code { }; - class platform_info { }; - class device_type { }; - class device_info { }; - class device_fp_config { }; - class device_mem_cache_type { }; - class device_local_mem_type { }; - class device_exec_capabilities { }; - class command_queue_properties { }; - class context_info { }; - class gl_context_info { }; - class context_properties { }; - class command_queue_info { }; - class mem_flags { }; - class channel_order { }; - class channel_type { }; - class mem_object_type { }; - class mem_info { }; - class image_info { }; - class addressing_mode { }; - class filter_mode { }; - class sampler_info { }; - class map_flags { }; - class program_info { }; - class program_build_info { }; - class program_binary_type { }; - class build_status { }; - class kernel_info { }; - class kernel_arg_info { }; - class kernel_arg_address_qualifier { }; - class kernel_arg_access_qualifier { }; - class kernel_work_group_info { }; - class event_info { }; - class command_type { }; - class command_execution_status { }; - class profiling_info { }; - class buffer_create_type { }; - class mem_migration_flags { }; - - class device_partition_property { }; - class device_affinity_domain { }; - - class device_partition_property_ext { }; - class affinity_domain_ext { }; - - class gl_object_type { }; - class gl_texture_info { }; - - class migrate_mem_object_flags_ext {}; - // }}} -} - - - - -void pyopencl_expose_constants() -{ - // {{{ exceptions -#define DECLARE_EXC(NAME, BASE) \ - CL##NAME = py::handle<>(PyErr_NewException("pyopencl." #NAME, BASE, NULL)); \ - py::scope().attr(#NAME) = CL##NAME; - - { - DECLARE_EXC(Error, NULL); - DECLARE_EXC(MemoryError, CLError.get()); - DECLARE_EXC(LogicError, CLError.get()); - DECLARE_EXC(RuntimeError, CLError.get()); - - py::register_exception_translator<error>(translate_cl_error); - } - // }}} - - // {{{ constants -#define ADD_ATTR(PREFIX, NAME) \ - cls.attr(#NAME) = CL_##PREFIX##NAME -#define ADD_ATTR_SUFFIX(PREFIX, NAME, SUFFIX) \ - cls.attr(#NAME) = CL_##PREFIX##NAME##SUFFIX - - { - typedef error cls; - py::class_<error> ("_error", py::no_init) - .DEF_SIMPLE_METHOD(routine) - .DEF_SIMPLE_METHOD(code) - .DEF_SIMPLE_METHOD(what) - ; - } - - { - py::class_<status_code> cls("status_code", py::no_init); - - ADD_ATTR(, SUCCESS); - ADD_ATTR(, DEVICE_NOT_FOUND); - ADD_ATTR(, DEVICE_NOT_AVAILABLE); -#if !(defined(CL_PLATFORM_NVIDIA) && CL_PLATFORM_NVIDIA == 0x3001) - ADD_ATTR(, COMPILER_NOT_AVAILABLE); -#endif - ADD_ATTR(, MEM_OBJECT_ALLOCATION_FAILURE); - ADD_ATTR(, OUT_OF_RESOURCES); - ADD_ATTR(, OUT_OF_HOST_MEMORY); - ADD_ATTR(, PROFILING_INFO_NOT_AVAILABLE); - ADD_ATTR(, MEM_COPY_OVERLAP); - ADD_ATTR(, IMAGE_FORMAT_MISMATCH); - ADD_ATTR(, IMAGE_FORMAT_NOT_SUPPORTED); - ADD_ATTR(, BUILD_PROGRAM_FAILURE); - ADD_ATTR(, MAP_FAILURE); - - ADD_ATTR(, INVALID_VALUE); - ADD_ATTR(, INVALID_DEVICE_TYPE); - ADD_ATTR(, INVALID_PLATFORM); - ADD_ATTR(, INVALID_DEVICE); - ADD_ATTR(, INVALID_CONTEXT); - ADD_ATTR(, INVALID_QUEUE_PROPERTIES); - ADD_ATTR(, INVALID_COMMAND_QUEUE); - ADD_ATTR(, INVALID_HOST_PTR); - ADD_ATTR(, INVALID_MEM_OBJECT); - ADD_ATTR(, INVALID_IMAGE_FORMAT_DESCRIPTOR); - ADD_ATTR(, INVALID_IMAGE_SIZE); - ADD_ATTR(, INVALID_SAMPLER); - ADD_ATTR(, INVALID_BINARY); - ADD_ATTR(, INVALID_BUILD_OPTIONS); - ADD_ATTR(, INVALID_PROGRAM); - ADD_ATTR(, INVALID_PROGRAM_EXECUTABLE); - ADD_ATTR(, INVALID_KERNEL_NAME); - ADD_ATTR(, INVALID_KERNEL_DEFINITION); - ADD_ATTR(, INVALID_KERNEL); - ADD_ATTR(, INVALID_ARG_INDEX); - ADD_ATTR(, INVALID_ARG_VALUE); - ADD_ATTR(, INVALID_ARG_SIZE); - ADD_ATTR(, INVALID_KERNEL_ARGS); - ADD_ATTR(, INVALID_WORK_DIMENSION); - ADD_ATTR(, INVALID_WORK_GROUP_SIZE); - ADD_ATTR(, INVALID_WORK_ITEM_SIZE); - ADD_ATTR(, INVALID_GLOBAL_OFFSET); - ADD_ATTR(, INVALID_EVENT_WAIT_LIST); - ADD_ATTR(, INVALID_EVENT); - ADD_ATTR(, INVALID_OPERATION); - ADD_ATTR(, INVALID_GL_OBJECT); - ADD_ATTR(, INVALID_BUFFER_SIZE); - ADD_ATTR(, INVALID_MIP_LEVEL); - -#if defined(cl_khr_icd) && (cl_khr_icd >= 1) - ADD_ATTR(, PLATFORM_NOT_FOUND_KHR); -#endif - -#if defined(cl_khr_gl_sharing) && (cl_khr_gl_sharing >= 1) - ADD_ATTR(, INVALID_GL_SHAREGROUP_REFERENCE_KHR); -#endif - -#if PYOPENCL_CL_VERSION >= 0x1010 - ADD_ATTR(, MISALIGNED_SUB_BUFFER_OFFSET); - ADD_ATTR(, EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST); - ADD_ATTR(, INVALID_GLOBAL_WORK_SIZE); -#endif - -#if PYOPENCL_CL_VERSION >= 0x1020 - ADD_ATTR(, COMPILE_PROGRAM_FAILURE); - ADD_ATTR(, LINKER_NOT_AVAILABLE); - ADD_ATTR(, LINK_PROGRAM_FAILURE); - ADD_ATTR(, DEVICE_PARTITION_FAILED); - ADD_ATTR(, KERNEL_ARG_INFO_NOT_AVAILABLE); - ADD_ATTR(, INVALID_IMAGE_DESCRIPTOR); - ADD_ATTR(, INVALID_COMPILER_OPTIONS); - ADD_ATTR(, INVALID_LINKER_OPTIONS); - ADD_ATTR(, INVALID_DEVICE_PARTITION_COUNT); -#endif - -#if defined(cl_ext_device_fission) && defined(PYOPENCL_USE_DEVICE_FISSION) - ADD_ATTR(, DEVICE_PARTITION_FAILED_EXT); - ADD_ATTR(, INVALID_PARTITION_COUNT_EXT); - ADD_ATTR(, INVALID_PARTITION_NAME_EXT); -#endif - } - - { - py::class_<platform_info> cls("platform_info", py::no_init); - ADD_ATTR(PLATFORM_, PROFILE); - ADD_ATTR(PLATFORM_, VERSION); - ADD_ATTR(PLATFORM_, NAME); - ADD_ATTR(PLATFORM_, VENDOR); -#if !(defined(CL_PLATFORM_NVIDIA) && CL_PLATFORM_NVIDIA == 0x3001) - ADD_ATTR(PLATFORM_, EXTENSIONS); -#endif - } - - { - py::class_<device_type> cls("device_type", py::no_init); - ADD_ATTR(DEVICE_TYPE_, DEFAULT); - ADD_ATTR(DEVICE_TYPE_, CPU); - ADD_ATTR(DEVICE_TYPE_, GPU); - ADD_ATTR(DEVICE_TYPE_, ACCELERATOR); -#if PYOPENCL_CL_VERSION >= 0x1020 - ADD_ATTR(DEVICE_TYPE_, CUSTOM); -#endif - ADD_ATTR(DEVICE_TYPE_, ALL); - } - - { - py::class_<device_info> cls("device_info", py::no_init); - ADD_ATTR(DEVICE_, TYPE); - ADD_ATTR(DEVICE_, VENDOR_ID); - ADD_ATTR(DEVICE_, MAX_COMPUTE_UNITS); - ADD_ATTR(DEVICE_, MAX_WORK_ITEM_DIMENSIONS); - ADD_ATTR(DEVICE_, MAX_WORK_GROUP_SIZE); - ADD_ATTR(DEVICE_, MAX_WORK_ITEM_SIZES); - ADD_ATTR(DEVICE_, PREFERRED_VECTOR_WIDTH_CHAR); - ADD_ATTR(DEVICE_, PREFERRED_VECTOR_WIDTH_SHORT); - ADD_ATTR(DEVICE_, PREFERRED_VECTOR_WIDTH_INT); - ADD_ATTR(DEVICE_, PREFERRED_VECTOR_WIDTH_LONG); - ADD_ATTR(DEVICE_, PREFERRED_VECTOR_WIDTH_FLOAT); - ADD_ATTR(DEVICE_, PREFERRED_VECTOR_WIDTH_DOUBLE); - ADD_ATTR(DEVICE_, MAX_CLOCK_FREQUENCY); - ADD_ATTR(DEVICE_, ADDRESS_BITS); - ADD_ATTR(DEVICE_, MAX_READ_IMAGE_ARGS); - ADD_ATTR(DEVICE_, MAX_WRITE_IMAGE_ARGS); - ADD_ATTR(DEVICE_, MAX_MEM_ALLOC_SIZE); - ADD_ATTR(DEVICE_, IMAGE2D_MAX_WIDTH); - ADD_ATTR(DEVICE_, IMAGE2D_MAX_HEIGHT); - ADD_ATTR(DEVICE_, IMAGE3D_MAX_WIDTH); - ADD_ATTR(DEVICE_, IMAGE3D_MAX_HEIGHT); - ADD_ATTR(DEVICE_, IMAGE3D_MAX_DEPTH); - ADD_ATTR(DEVICE_, IMAGE_SUPPORT); - ADD_ATTR(DEVICE_, MAX_PARAMETER_SIZE); - ADD_ATTR(DEVICE_, MAX_SAMPLERS); - ADD_ATTR(DEVICE_, MEM_BASE_ADDR_ALIGN); - ADD_ATTR(DEVICE_, MIN_DATA_TYPE_ALIGN_SIZE); - ADD_ATTR(DEVICE_, SINGLE_FP_CONFIG); -#ifdef CL_DEVICE_DOUBLE_FP_CONFIG - ADD_ATTR(DEVICE_, DOUBLE_FP_CONFIG); -#endif -#ifdef CL_DEVICE_HALF_FP_CONFIG - ADD_ATTR(DEVICE_, HALF_FP_CONFIG); -#endif - ADD_ATTR(DEVICE_, GLOBAL_MEM_CACHE_TYPE); - ADD_ATTR(DEVICE_, GLOBAL_MEM_CACHELINE_SIZE); - ADD_ATTR(DEVICE_, GLOBAL_MEM_CACHE_SIZE); - ADD_ATTR(DEVICE_, GLOBAL_MEM_SIZE); - ADD_ATTR(DEVICE_, MAX_CONSTANT_BUFFER_SIZE); - ADD_ATTR(DEVICE_, MAX_CONSTANT_ARGS); - ADD_ATTR(DEVICE_, LOCAL_MEM_TYPE); - ADD_ATTR(DEVICE_, LOCAL_MEM_SIZE); - ADD_ATTR(DEVICE_, ERROR_CORRECTION_SUPPORT); - ADD_ATTR(DEVICE_, PROFILING_TIMER_RESOLUTION); - ADD_ATTR(DEVICE_, ENDIAN_LITTLE); - ADD_ATTR(DEVICE_, AVAILABLE); - ADD_ATTR(DEVICE_, COMPILER_AVAILABLE); - ADD_ATTR(DEVICE_, EXECUTION_CAPABILITIES); - ADD_ATTR(DEVICE_, QUEUE_PROPERTIES); - ADD_ATTR(DEVICE_, NAME); - ADD_ATTR(DEVICE_, VENDOR); - ADD_ATTR(, DRIVER_VERSION); - ADD_ATTR(DEVICE_, VERSION); - ADD_ATTR(DEVICE_, PROFILE); - ADD_ATTR(DEVICE_, VERSION); - ADD_ATTR(DEVICE_, EXTENSIONS); - ADD_ATTR(DEVICE_, PLATFORM); -#if PYOPENCL_CL_VERSION >= 0x1010 - ADD_ATTR(DEVICE_, PREFERRED_VECTOR_WIDTH_HALF); - ADD_ATTR(DEVICE_, HOST_UNIFIED_MEMORY); - ADD_ATTR(DEVICE_, NATIVE_VECTOR_WIDTH_CHAR); - ADD_ATTR(DEVICE_, NATIVE_VECTOR_WIDTH_SHORT); - ADD_ATTR(DEVICE_, NATIVE_VECTOR_WIDTH_INT); - ADD_ATTR(DEVICE_, NATIVE_VECTOR_WIDTH_LONG); - ADD_ATTR(DEVICE_, NATIVE_VECTOR_WIDTH_FLOAT); - ADD_ATTR(DEVICE_, NATIVE_VECTOR_WIDTH_DOUBLE); - ADD_ATTR(DEVICE_, NATIVE_VECTOR_WIDTH_HALF); - ADD_ATTR(DEVICE_, OPENCL_C_VERSION); -#endif -// support for cl_nv_device_attribute_query -#ifdef CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV - ADD_ATTR(DEVICE_, COMPUTE_CAPABILITY_MAJOR_NV); - ADD_ATTR(DEVICE_, COMPUTE_CAPABILITY_MINOR_NV); - ADD_ATTR(DEVICE_, REGISTERS_PER_BLOCK_NV); - ADD_ATTR(DEVICE_, WARP_SIZE_NV); - ADD_ATTR(DEVICE_, GPU_OVERLAP_NV); - ADD_ATTR(DEVICE_, KERNEL_EXEC_TIMEOUT_NV); - ADD_ATTR(DEVICE_, INTEGRATED_MEMORY_NV); -#endif -// {{{ cl_amd_device_attribute_query -#ifdef CL_DEVICE_PROFILING_TIMER_OFFSET_AMD - ADD_ATTR(DEVICE_, PROFILING_TIMER_OFFSET_AMD); -#endif -#ifdef CL_DEVICE_TOPOLOGY_AMD - ADD_ATTR(DEVICE_, TOPOLOGY_AMD); -#endif -#ifdef CL_DEVICE_BOARD_NAME_AMD - ADD_ATTR(DEVICE_, BOARD_NAME_AMD); -#endif -#ifdef CL_DEVICE_GLOBAL_FREE_MEMORY_AMD - ADD_ATTR(DEVICE_, GLOBAL_FREE_MEMORY_AMD); -#endif -#ifdef CL_DEVICE_SIMD_PER_COMPUTE_UNIT_AMD - ADD_ATTR(DEVICE_, SIMD_PER_COMPUTE_UNIT_AMD); -#endif -#ifdef CL_DEVICE_SIMD_WIDTH_AMD - ADD_ATTR(DEVICE_, SIMD_WIDTH_AMD); -#endif -#ifdef CL_DEVICE_SIMD_INSTRUCTION_WIDTH_AMD - ADD_ATTR(DEVICE_, SIMD_INSTRUCTION_WIDTH_AMD); -#endif -#ifdef CL_DEVICE_WAVEFRONT_WIDTH_AMD - ADD_ATTR(DEVICE_, WAVEFRONT_WIDTH_AMD); -#endif -#ifdef CL_DEVICE_GLOBAL_MEM_CHANNELS_AMD - ADD_ATTR(DEVICE_, GLOBAL_MEM_CHANNELS_AMD); -#endif -#ifdef CL_DEVICE_GLOBAL_MEM_CHANNEL_BANKS_AMD - ADD_ATTR(DEVICE_, GLOBAL_MEM_CHANNEL_BANKS_AMD); -#endif -#ifdef CL_DEVICE_GLOBAL_MEM_CHANNEL_BANK_WIDTH_AMD - ADD_ATTR(DEVICE_, GLOBAL_MEM_CHANNEL_BANK_WIDTH_AMD); -#endif -#ifdef CL_DEVICE_LOCAL_MEM_SIZE_PER_COMPUTE_UNIT_AMD - ADD_ATTR(DEVICE_, LOCAL_MEM_SIZE_PER_COMPUTE_UNIT_AMD); -#endif -#ifdef CL_DEVICE_LOCAL_MEM_BANKS_AMD - ADD_ATTR(DEVICE_, LOCAL_MEM_BANKS_AMD); -#endif -// }}} -#ifdef CL_DEVICE_MAX_ATOMIC_COUNTERS_EXT - ADD_ATTR(DEVICE_, MAX_ATOMIC_COUNTERS_EXT); -#endif -#if defined(cl_ext_device_fission) && defined(PYOPENCL_USE_DEVICE_FISSION) - ADD_ATTR(DEVICE_, PARENT_DEVICE_EXT); - ADD_ATTR(DEVICE_, PARTITION_TYPES_EXT); - ADD_ATTR(DEVICE_, AFFINITY_DOMAINS_EXT); - ADD_ATTR(DEVICE_, REFERENCE_COUNT_EXT); - ADD_ATTR(DEVICE_, PARTITION_STYLE_EXT); -#endif -#if PYOPENCL_CL_VERSION >= 0x1020 - ADD_ATTR(DEVICE_, LINKER_AVAILABLE); - ADD_ATTR(DEVICE_, BUILT_IN_KERNELS); - ADD_ATTR(DEVICE_, IMAGE_MAX_BUFFER_SIZE); - ADD_ATTR(DEVICE_, IMAGE_MAX_ARRAY_SIZE); - ADD_ATTR(DEVICE_, PARENT_DEVICE); - ADD_ATTR(DEVICE_, PARTITION_MAX_SUB_DEVICES); - ADD_ATTR(DEVICE_, PARTITION_PROPERTIES); - ADD_ATTR(DEVICE_, PARTITION_AFFINITY_DOMAIN); - ADD_ATTR(DEVICE_, PARTITION_TYPE); - ADD_ATTR(DEVICE_, REFERENCE_COUNT); - ADD_ATTR(DEVICE_, PREFERRED_INTEROP_USER_SYNC); - ADD_ATTR(DEVICE_, PRINTF_BUFFER_SIZE); -#endif -#ifdef cl_khr_image2d_from_buffer - ADD_ATTR(DEVICE_, IMAGE_PITCH_ALIGNMENT); - ADD_ATTR(DEVICE_, IMAGE_BASE_ADDRESS_ALIGNMENT); -#endif - } - - { - py::class_<device_fp_config> cls("device_fp_config", py::no_init); - ADD_ATTR(FP_, DENORM); - ADD_ATTR(FP_, INF_NAN); - ADD_ATTR(FP_, ROUND_TO_NEAREST); - ADD_ATTR(FP_, ROUND_TO_ZERO); - ADD_ATTR(FP_, ROUND_TO_INF); - ADD_ATTR(FP_, FMA); -#if PYOPENCL_CL_VERSION >= 0x1010 - ADD_ATTR(FP_, SOFT_FLOAT); -#endif -#if PYOPENCL_CL_VERSION >= 0x1020 - ADD_ATTR(FP_, CORRECTLY_ROUNDED_DIVIDE_SQRT); -#endif - } - - { - py::class_<device_mem_cache_type> cls("device_mem_cache_type", py::no_init); - ADD_ATTR( , NONE); - ADD_ATTR( , READ_ONLY_CACHE); - ADD_ATTR( , READ_WRITE_CACHE); - } - - { - py::class_<device_local_mem_type> cls("device_local_mem_type", py::no_init); - ADD_ATTR( , LOCAL); - ADD_ATTR( , GLOBAL); - } - - { - py::class_<device_exec_capabilities> cls("device_exec_capabilities", py::no_init); - ADD_ATTR(EXEC_, KERNEL); - ADD_ATTR(EXEC_, NATIVE_KERNEL); -#ifdef CL_EXEC_IMMEDIATE_EXECUTION_INTEL - ADD_ATTR(EXEC_, IMMEDIATE_EXECUTION_INTEL); -#endif - } - - { - py::class_<command_queue_properties> cls("command_queue_properties", py::no_init); - ADD_ATTR(QUEUE_, OUT_OF_ORDER_EXEC_MODE_ENABLE); - ADD_ATTR(QUEUE_, PROFILING_ENABLE); -#ifdef CL_QUEUE_IMMEDIATE_EXECUTION_ENABLE_INTEL - ADD_ATTR(QUEUE_, IMMEDIATE_EXECUTION_ENABLE_INTEL); -#endif - } - - { - py::class_<context_info> cls("context_info", py::no_init); - ADD_ATTR(CONTEXT_, REFERENCE_COUNT); - ADD_ATTR(CONTEXT_, DEVICES); - ADD_ATTR(CONTEXT_, PROPERTIES); -#if PYOPENCL_CL_VERSION >= 0x1010 - ADD_ATTR(CONTEXT_, NUM_DEVICES); -#endif -#if PYOPENCL_CL_VERSION >= 0x1020 - ADD_ATTR(CONTEXT_, INTEROP_USER_SYNC); -#endif - } - - { - py::class_<gl_context_info> cls("gl_context_info", py::no_init); -#if defined(cl_khr_gl_sharing) && (cl_khr_gl_sharing >= 1) - ADD_ATTR(, CURRENT_DEVICE_FOR_GL_CONTEXT_KHR); - ADD_ATTR(, DEVICES_FOR_GL_CONTEXT_KHR); -#endif - } - - { - py::class_<context_properties> cls("context_properties", py::no_init); - ADD_ATTR(CONTEXT_, PLATFORM); -#if defined(cl_khr_gl_sharing) && (cl_khr_gl_sharing >= 1) - ADD_ATTR( ,GL_CONTEXT_KHR); - ADD_ATTR( ,EGL_DISPLAY_KHR); - ADD_ATTR( ,GLX_DISPLAY_KHR); - ADD_ATTR( ,WGL_HDC_KHR); - ADD_ATTR( ,CGL_SHAREGROUP_KHR); -#endif -#if defined(__APPLE__) && defined(HAVE_GL) - ADD_ATTR( ,CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE); -#endif /* __APPLE__ */ -// cl_amd_offline_devices -#ifdef CL_CONTEXT_OFFLINE_DEVICES_AMD - ADD_ATTR(CONTEXT_, OFFLINE_DEVICES_AMD); -#endif - } - - { - py::class_<command_queue_info> cls("command_queue_info", py::no_init); - ADD_ATTR(QUEUE_, CONTEXT); - ADD_ATTR(QUEUE_, DEVICE); - ADD_ATTR(QUEUE_, REFERENCE_COUNT); - ADD_ATTR(QUEUE_, PROPERTIES); - } - - { - py::class_<mem_flags> cls("mem_flags", py::no_init); - ADD_ATTR(MEM_, READ_WRITE); - ADD_ATTR(MEM_, WRITE_ONLY); - ADD_ATTR(MEM_, READ_ONLY); - ADD_ATTR(MEM_, USE_HOST_PTR); - ADD_ATTR(MEM_, ALLOC_HOST_PTR); - ADD_ATTR(MEM_, COPY_HOST_PTR); -#ifdef cl_amd_device_memory_flags - ADD_ATTR(MEM_, USE_PERSISTENT_MEM_AMD); -#endif -#if PYOPENCL_CL_VERSION >= 0x1020 - ADD_ATTR(MEM_, HOST_WRITE_ONLY); - ADD_ATTR(MEM_, HOST_READ_ONLY); - ADD_ATTR(MEM_, HOST_NO_ACCESS); -#endif - } - - { - py::class_<channel_order> cls("channel_order", py::no_init); - ADD_ATTR( , R); - ADD_ATTR( , A); - ADD_ATTR( , RG); - ADD_ATTR( , RA); - ADD_ATTR( , RGB); - ADD_ATTR( , RGBA); - ADD_ATTR( , BGRA); - ADD_ATTR( , INTENSITY); - ADD_ATTR( , LUMINANCE); -#if PYOPENCL_CL_VERSION >= 0x1010 - ADD_ATTR( , Rx); - ADD_ATTR( , RGx); - ADD_ATTR( , RGBx); -#endif - } - - { - py::class_<channel_type> cls("channel_type", py::no_init); - ADD_ATTR( , SNORM_INT8); - ADD_ATTR( , SNORM_INT16); - ADD_ATTR( , UNORM_INT8); - ADD_ATTR( , UNORM_INT16); - ADD_ATTR( , UNORM_SHORT_565); - ADD_ATTR( , UNORM_SHORT_555); - ADD_ATTR( , UNORM_INT_101010); - ADD_ATTR( , SIGNED_INT8); - ADD_ATTR( , SIGNED_INT16); - ADD_ATTR( , SIGNED_INT32); - ADD_ATTR( , UNSIGNED_INT8); - ADD_ATTR( , UNSIGNED_INT16); - ADD_ATTR( , UNSIGNED_INT32); - ADD_ATTR( , HALF_FLOAT); - ADD_ATTR( , FLOAT); - } - - { - py::class_<mem_object_type> cls("mem_object_type", py::no_init); - ADD_ATTR(MEM_OBJECT_, BUFFER); - ADD_ATTR(MEM_OBJECT_, IMAGE2D); - ADD_ATTR(MEM_OBJECT_, IMAGE3D); -#if PYOPENCL_CL_VERSION >= 0x1020 - ADD_ATTR(MEM_OBJECT_, IMAGE2D_ARRAY); - ADD_ATTR(MEM_OBJECT_, IMAGE1D); - ADD_ATTR(MEM_OBJECT_, IMAGE1D_ARRAY); - ADD_ATTR(MEM_OBJECT_, IMAGE1D_BUFFER); -#endif - } - - { - py::class_<mem_info> cls("mem_info", py::no_init); - ADD_ATTR(MEM_, TYPE); - ADD_ATTR(MEM_, FLAGS); - ADD_ATTR(MEM_, SIZE); - ADD_ATTR(MEM_, HOST_PTR); - ADD_ATTR(MEM_, MAP_COUNT); - ADD_ATTR(MEM_, REFERENCE_COUNT); - ADD_ATTR(MEM_, CONTEXT); -#if PYOPENCL_CL_VERSION >= 0x1010 - ADD_ATTR(MEM_, ASSOCIATED_MEMOBJECT); - ADD_ATTR(MEM_, OFFSET); -#endif - } - - { - py::class_<image_info> cls("image_info", py::no_init); - ADD_ATTR(IMAGE_, FORMAT); - ADD_ATTR(IMAGE_, ELEMENT_SIZE); - ADD_ATTR(IMAGE_, ROW_PITCH); - ADD_ATTR(IMAGE_, SLICE_PITCH); - ADD_ATTR(IMAGE_, WIDTH); - ADD_ATTR(IMAGE_, HEIGHT); - ADD_ATTR(IMAGE_, DEPTH); -#if PYOPENCL_CL_VERSION >= 0x1020 - ADD_ATTR(IMAGE_, ARRAY_SIZE); - ADD_ATTR(IMAGE_, BUFFER); - ADD_ATTR(IMAGE_, NUM_MIP_LEVELS); - ADD_ATTR(IMAGE_, NUM_SAMPLES); -#endif - } - - { - py::class_<addressing_mode> cls("addressing_mode", py::no_init); - ADD_ATTR(ADDRESS_, NONE); - ADD_ATTR(ADDRESS_, CLAMP_TO_EDGE); - ADD_ATTR(ADDRESS_, CLAMP); - ADD_ATTR(ADDRESS_, REPEAT); -#if PYOPENCL_CL_VERSION >= 0x1010 - ADD_ATTR(ADDRESS_, MIRRORED_REPEAT); -#endif - } - - { - py::class_<filter_mode> cls("filter_mode", py::no_init); - ADD_ATTR(FILTER_, NEAREST); - ADD_ATTR(FILTER_, LINEAR); - } - - { - py::class_<sampler_info> cls("sampler_info", py::no_init); - ADD_ATTR(SAMPLER_, REFERENCE_COUNT); - ADD_ATTR(SAMPLER_, CONTEXT); - ADD_ATTR(SAMPLER_, NORMALIZED_COORDS); - ADD_ATTR(SAMPLER_, ADDRESSING_MODE); - ADD_ATTR(SAMPLER_, FILTER_MODE); - } - - { - py::class_<map_flags> cls("map_flags", py::no_init); - ADD_ATTR(MAP_, READ); - ADD_ATTR(MAP_, WRITE); -#if PYOPENCL_CL_VERSION >= 0x1020 - ADD_ATTR(MAP_, WRITE_INVALIDATE_REGION); -#endif - } - - { - py::class_<program_info> cls("program_info", py::no_init); - ADD_ATTR(PROGRAM_, REFERENCE_COUNT); - ADD_ATTR(PROGRAM_, CONTEXT); - ADD_ATTR(PROGRAM_, NUM_DEVICES); - ADD_ATTR(PROGRAM_, DEVICES); - ADD_ATTR(PROGRAM_, SOURCE); - ADD_ATTR(PROGRAM_, BINARY_SIZES); - ADD_ATTR(PROGRAM_, BINARIES); -#if PYOPENCL_CL_VERSION >= 0x1020 - ADD_ATTR(PROGRAM_, NUM_KERNELS); - ADD_ATTR(PROGRAM_, KERNEL_NAMES); -#endif - } - - { - py::class_<program_build_info> cls("program_build_info", py::no_init); - ADD_ATTR(PROGRAM_BUILD_, STATUS); - ADD_ATTR(PROGRAM_BUILD_, OPTIONS); - ADD_ATTR(PROGRAM_BUILD_, LOG); -#if PYOPENCL_CL_VERSION >= 0x1020 - ADD_ATTR(PROGRAM_, BINARY_TYPE); -#endif - } - - { - py::class_<program_binary_type> cls("program_binary_type", py::no_init); -#if PYOPENCL_CL_VERSION >= 0x1020 - ADD_ATTR(PROGRAM_BINARY_TYPE_, NONE); - ADD_ATTR(PROGRAM_BINARY_TYPE_, COMPILED_OBJECT); - ADD_ATTR(PROGRAM_BINARY_TYPE_, LIBRARY); - ADD_ATTR(PROGRAM_BINARY_TYPE_, EXECUTABLE); -#endif - } - - { - py::class_<kernel_info> cls("kernel_info", py::no_init); - ADD_ATTR(KERNEL_, FUNCTION_NAME); - ADD_ATTR(KERNEL_, NUM_ARGS); - ADD_ATTR(KERNEL_, REFERENCE_COUNT); - ADD_ATTR(KERNEL_, CONTEXT); - ADD_ATTR(KERNEL_, PROGRAM); -#if PYOPENCL_CL_VERSION >= 0x1020 - ADD_ATTR(KERNEL_, ATTRIBUTES); -#endif - } - - { - py::class_<kernel_arg_info> cls("kernel_arg_info", py::no_init); -#if PYOPENCL_CL_VERSION >= 0x1020 - ADD_ATTR(KERNEL_ARG_, ADDRESS_QUALIFIER); - ADD_ATTR(KERNEL_ARG_, ACCESS_QUALIFIER); - ADD_ATTR(KERNEL_ARG_, TYPE_NAME); - ADD_ATTR(KERNEL_ARG_, NAME); -#endif - } - - { - py::class_<kernel_arg_address_qualifier> cls( - "kernel_arg_address_qualifier", py::no_init); -#if PYOPENCL_CL_VERSION >= 0x1020 - ADD_ATTR(KERNEL_ARG_ADDRESS_, GLOBAL); - ADD_ATTR(KERNEL_ARG_ADDRESS_, LOCAL); - ADD_ATTR(KERNEL_ARG_ADDRESS_, CONSTANT); - ADD_ATTR(KERNEL_ARG_ADDRESS_, PRIVATE); -#endif - } - - { - py::class_<kernel_arg_access_qualifier> cls( - "kernel_arg_access_qualifier", py::no_init); -#if PYOPENCL_CL_VERSION >= 0x1020 - ADD_ATTR(KERNEL_ARG_ACCESS_, READ_ONLY); - ADD_ATTR(KERNEL_ARG_ACCESS_, WRITE_ONLY); - ADD_ATTR(KERNEL_ARG_ACCESS_, READ_WRITE); - ADD_ATTR(KERNEL_ARG_ACCESS_, NONE); -#endif - } - - { - py::class_<kernel_work_group_info> cls("kernel_work_group_info", py::no_init); - ADD_ATTR(KERNEL_, WORK_GROUP_SIZE); - ADD_ATTR(KERNEL_, COMPILE_WORK_GROUP_SIZE); - ADD_ATTR(KERNEL_, LOCAL_MEM_SIZE); -#if PYOPENCL_CL_VERSION >= 0x1010 - ADD_ATTR(KERNEL_, PREFERRED_WORK_GROUP_SIZE_MULTIPLE); - ADD_ATTR(KERNEL_, PRIVATE_MEM_SIZE); -#endif -#if PYOPENCL_CL_VERSION >= 0x1020 - ADD_ATTR(KERNEL_, GLOBAL_WORK_SIZE); -#endif - } - - { - py::class_<event_info> cls("event_info", py::no_init); - ADD_ATTR(EVENT_, COMMAND_QUEUE); - ADD_ATTR(EVENT_, COMMAND_TYPE); - ADD_ATTR(EVENT_, REFERENCE_COUNT); - ADD_ATTR(EVENT_, COMMAND_EXECUTION_STATUS); -#if PYOPENCL_CL_VERSION >= 0x1010 - ADD_ATTR(EVENT_, CONTEXT); -#endif - } - - { - py::class_<command_type> cls("command_type", py::no_init); - ADD_ATTR(COMMAND_, NDRANGE_KERNEL); - ADD_ATTR(COMMAND_, TASK); - ADD_ATTR(COMMAND_, NATIVE_KERNEL); - ADD_ATTR(COMMAND_, READ_BUFFER); - ADD_ATTR(COMMAND_, WRITE_BUFFER); - ADD_ATTR(COMMAND_, COPY_BUFFER); - ADD_ATTR(COMMAND_, READ_IMAGE); - ADD_ATTR(COMMAND_, WRITE_IMAGE); - ADD_ATTR(COMMAND_, COPY_IMAGE); - ADD_ATTR(COMMAND_, COPY_IMAGE_TO_BUFFER); - ADD_ATTR(COMMAND_, COPY_BUFFER_TO_IMAGE); - ADD_ATTR(COMMAND_, MAP_BUFFER); - ADD_ATTR(COMMAND_, MAP_IMAGE); - ADD_ATTR(COMMAND_, UNMAP_MEM_OBJECT); - ADD_ATTR(COMMAND_, MARKER); - ADD_ATTR(COMMAND_, ACQUIRE_GL_OBJECTS); - ADD_ATTR(COMMAND_, RELEASE_GL_OBJECTS); -#if PYOPENCL_CL_VERSION >= 0x1010 - ADD_ATTR(COMMAND_, READ_BUFFER_RECT); - ADD_ATTR(COMMAND_, WRITE_BUFFER_RECT); - ADD_ATTR(COMMAND_, COPY_BUFFER_RECT); - ADD_ATTR(COMMAND_, USER); -#endif -#ifdef cl_ext_migrate_memobject - ADD_ATTR(COMMAND_, MIGRATE_MEM_OBJECT_EXT); -#endif -#if PYOPENCL_CL_VERSION >= 0x1020 - ADD_ATTR(COMMAND_, BARRIER); - ADD_ATTR(COMMAND_, MIGRATE_MEM_OBJECTS); - ADD_ATTR(COMMAND_, FILL_BUFFER); - ADD_ATTR(COMMAND_, FILL_IMAGE); -#endif - } - - { - py::class_<command_execution_status> cls("command_execution_status", py::no_init); - ADD_ATTR(, COMPLETE); - ADD_ATTR(, RUNNING); - ADD_ATTR(, SUBMITTED); - ADD_ATTR(, QUEUED); - } - - { - py::class_<profiling_info> cls("profiling_info", py::no_init); - ADD_ATTR(PROFILING_COMMAND_, QUEUED); - ADD_ATTR(PROFILING_COMMAND_, SUBMIT); - ADD_ATTR(PROFILING_COMMAND_, START); - ADD_ATTR(PROFILING_COMMAND_, END); - } - -/* not needed--filled in automatically by implementation. -#if PYOPENCL_CL_VERSION >= 0x1010 - { - py::class_<buffer_create_type> cls("buffer_create_type", py::no_init); - ADD_ATTR(BUFFER_CREATE_TYPE_, REGION); - } -#endif -*/ - - { - py::class_<mem_migration_flags> cls( - "mem_migration_flags", py::no_init); -#if PYOPENCL_CL_VERSION >= 0x1020 - ADD_ATTR(MIGRATE_MEM_OBJECT_, HOST); - ADD_ATTR(MIGRATE_MEM_OBJECT_, CONTENT_UNDEFINED); -#endif - } - - { - py::class_<device_partition_property_ext> cls( - "device_partition_property_ext", py::no_init); -#if defined(cl_ext_device_fission) && defined(PYOPENCL_USE_DEVICE_FISSION) - ADD_ATTR_SUFFIX(DEVICE_PARTITION_, EQUALLY, _EXT); - ADD_ATTR_SUFFIX(DEVICE_PARTITION_, BY_COUNTS, _EXT); - ADD_ATTR_SUFFIX(DEVICE_PARTITION_, BY_NAMES, _EXT); - ADD_ATTR_SUFFIX(DEVICE_PARTITION_, BY_AFFINITY_DOMAIN, _EXT); - ADD_ATTR_SUFFIX(, PROPERTIES_LIST_END, _EXT); - ADD_ATTR_SUFFIX(, PARTITION_BY_COUNTS_LIST_END, _EXT); - ADD_ATTR_SUFFIX(, PARTITION_BY_NAMES_LIST_END, _EXT); -#endif - } - - { - py::class_<affinity_domain_ext> cls("affinity_domain_ext", py::no_init); -#if defined(cl_ext_device_fission) && defined(PYOPENCL_USE_DEVICE_FISSION) - ADD_ATTR_SUFFIX(AFFINITY_DOMAIN_, L1_CACHE, _EXT); - ADD_ATTR_SUFFIX(AFFINITY_DOMAIN_, L2_CACHE, _EXT); - ADD_ATTR_SUFFIX(AFFINITY_DOMAIN_, L3_CACHE, _EXT); - ADD_ATTR_SUFFIX(AFFINITY_DOMAIN_, L4_CACHE, _EXT); - ADD_ATTR_SUFFIX(AFFINITY_DOMAIN_, NUMA, _EXT); - ADD_ATTR_SUFFIX(AFFINITY_DOMAIN_, NEXT_FISSIONABLE, _EXT); -#endif - } - - { - py::class_<device_partition_property> cls( - "device_partition_property", py::no_init); -#if PYOPENCL_CL_VERSION >= 0x1020 - ADD_ATTR(DEVICE_PARTITION_, EQUALLY); - ADD_ATTR(DEVICE_PARTITION_, BY_COUNTS); - ADD_ATTR(DEVICE_PARTITION_, BY_COUNTS_LIST_END); - ADD_ATTR(DEVICE_PARTITION_, BY_AFFINITY_DOMAIN); -#endif - } - - { - py::class_<device_affinity_domain> cls("device_affinity_domain", py::no_init); -#if PYOPENCL_CL_VERSION >= 0x1020 - ADD_ATTR(DEVICE_AFFINITY_DOMAIN_, NUMA); - ADD_ATTR(DEVICE_AFFINITY_DOMAIN_, L4_CACHE); - ADD_ATTR(DEVICE_AFFINITY_DOMAIN_, L3_CACHE); - ADD_ATTR(DEVICE_AFFINITY_DOMAIN_, L2_CACHE); - ADD_ATTR(DEVICE_AFFINITY_DOMAIN_, L1_CACHE); - ADD_ATTR(DEVICE_AFFINITY_DOMAIN_, NEXT_PARTITIONABLE); -#endif - } - -#ifdef HAVE_GL - { - py::class_<gl_object_type> cls("gl_object_type", py::no_init); - ADD_ATTR(GL_OBJECT_, BUFFER); - ADD_ATTR(GL_OBJECT_, TEXTURE2D); - ADD_ATTR(GL_OBJECT_, TEXTURE3D); - ADD_ATTR(GL_OBJECT_, RENDERBUFFER); - } - - { - py::class_<gl_texture_info> cls("gl_texture_info", py::no_init); - ADD_ATTR(GL_, TEXTURE_TARGET); - ADD_ATTR(GL_, MIPMAP_LEVEL); - } -#endif - - { - py::class_<migrate_mem_object_flags_ext> cls("migrate_mem_object_flags_ext", py::no_init); -#ifdef cl_ext_migrate_memobject - ADD_ATTR_SUFFIX(MIGRATE_MEM_OBJECT_, HOST, _EXT); -#endif - } - - // }}} -} - - - - -// vim: foldmethod=marker diff --git a/src/wrapper/wrap_helpers.hpp b/src/wrapper/wrap_helpers.hpp deleted file mode 100644 index dac179c7..00000000 --- a/src/wrapper/wrap_helpers.hpp +++ /dev/null @@ -1,175 +0,0 @@ -#ifndef PYCUDA_WRAP_HELPERS_HEADER_SEEN -#define PYCUDA_WRAP_HELPERS_HEADER_SEEN - - - - -#include <boost/version.hpp> -#include <boost/python.hpp> -#include <boost/python/stl_iterator.hpp> - - - - -namespace py = boost::python; - - - - -#if (BOOST_VERSION/100) < 1035 -#warning ******************************************************************* -#warning **** Your version of Boost C++ is likely too old for PyOpenCL. **** -#warning ******************************************************************* -#endif - - - - -#define PYTHON_ERROR(TYPE, REASON) \ -{ \ - PyErr_SetString(PyExc_##TYPE, REASON); \ - throw boost::python::error_already_set(); \ -} - -#define ENUM_VALUE(NAME) \ - value(#NAME, NAME) - -#define DEF_SIMPLE_METHOD(NAME) \ - def(#NAME, &cls::NAME) - -#define DEF_SIMPLE_METHOD_WITH_ARGS(NAME, ARGS) \ - def(#NAME, &cls::NAME, boost::python::args ARGS) - -#define DEF_SIMPLE_FUNCTION(NAME) \ - boost::python::def(#NAME, &NAME) - -#define DEF_SIMPLE_FUNCTION_WITH_ARGS(NAME, ARGS) \ - boost::python::def(#NAME, &NAME, boost::python::args ARGS) - -#define DEF_SIMPLE_RO_MEMBER(NAME) \ - def_readonly(#NAME, &cls::m_##NAME) - -#define DEF_SIMPLE_RW_MEMBER(NAME) \ - def_readwrite(#NAME, &cls::m_##NAME) - -#define PYTHON_FOREACH(NAME, ITERABLE) \ - BOOST_FOREACH(boost::python::object NAME, \ - std::make_pair( \ - boost::python::stl_input_iterator<boost::python::object>(ITERABLE), \ - boost::python::stl_input_iterator<boost::python::object>())) - -#define COPY_PY_LIST(TYPE, NAME) \ - std::copy( \ - boost::python::stl_input_iterator<TYPE>(py_##NAME), \ - boost::python::stl_input_iterator<TYPE>(), \ - std::back_inserter(NAME)); - -#define COPY_PY_COORD_TRIPLE(NAME) \ - size_t NAME[3] = {0, 0, 0}; \ - { \ - size_t my_len = len(py_##NAME); \ - if (my_len > 3) \ - throw error("transfer", CL_INVALID_VALUE, #NAME "has too many components"); \ - for (size_t i = 0; i < my_len; ++i) \ - NAME[i] = py::extract<size_t>(py_##NAME[i])(); \ - } - -#define COPY_PY_PITCH_TUPLE(NAME) \ - size_t NAME[2] = {0, 0}; \ - if (py_##NAME.ptr() != Py_None) \ - { \ - size_t my_len = len(py_##NAME); \ - if (my_len > 2) \ - throw error("transfer", CL_INVALID_VALUE, #NAME "has too many components"); \ - for (size_t i = 0; i < my_len; ++i) \ - NAME[i] = py::extract<size_t>(py_##NAME[i])(); \ - } - -#define COPY_PY_REGION_TRIPLE(NAME) \ - size_t NAME[3] = {1, 1, 1}; \ - { \ - size_t my_len = len(py_##NAME); \ - if (my_len > 3) \ - throw error("transfer", CL_INVALID_VALUE, #NAME "has too many components"); \ - for (size_t i = 0; i < my_len; ++i) \ - NAME[i] = py::extract<size_t>(py_##NAME[i])(); \ - } - -#define PYOPENCL_PARSE_NUMPY_ARRAY_SPEC \ - PyArray_Descr *tp_descr; \ - if (PyArray_DescrConverter(dtype.ptr(), &tp_descr) != NPY_SUCCEED) \ - throw py::error_already_set(); \ - \ - py::extract<npy_intp> shape_as_int(py_shape); \ - std::vector<npy_intp> shape; \ - \ - if (shape_as_int.check()) \ - shape.push_back(shape_as_int()); \ - else \ - COPY_PY_LIST(npy_intp, shape); \ - \ - NPY_ORDER order = PyArray_CORDER; \ - PyArray_OrderConverter(py_order.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"); \ - \ - std::vector<npy_intp> strides; \ - if (py_strides.ptr() != Py_None) \ - { \ - COPY_PY_LIST(npy_intp, strides); \ - } - -#define PYOPENCL_RETURN_VECTOR(ITEMTYPE, NAME) \ - { \ - py::list pyopencl_result; \ - BOOST_FOREACH(ITEMTYPE item, NAME) \ - pyopencl_result.append(item); \ - return pyopencl_result; \ - } - -namespace -{ - template <typename T> - inline boost::python::handle<> handle_from_new_ptr(T *ptr) - { - return boost::python::handle<>( - typename boost::python::manage_new_object::apply<T *>::type()(ptr)); - } - - template <typename T, typename ClType> - inline T *from_int_ptr(intptr_t obj_ref) - { - ClType clobj = (ClType) obj_ref; - return new T(clobj, /* retain */ true); - } - - template <typename T> - inline intptr_t to_int_ptr(T const &obj) - { - return (intptr_t) obj.data(); - } -} - -#define PYOPENCL_EXPOSE_TO_FROM_INT_PTR(CL_TYPENAME) \ - .def("from_int_ptr", from_int_ptr<cls, CL_TYPENAME>, \ - py::return_value_policy<py::manage_new_object>(), \ - py::arg("int_ptr_value"), \ - "(static method) Return a new Python object referencing the C-level " \ - ":c:type:`" #CL_TYPENAME "` object at the location pointed to " \ - "by *int_ptr_value*. The relevant :c:func:`clRetain*` function " \ - "will be called." \ - "\n\n.. versionadded:: 2013.2\n") \ - .staticmethod("from_int_ptr") \ - .add_property("int_ptr", to_int_ptr<cls>, \ - "Return an integer corresponding to the pointer value " \ - "of the underlying :c:type:`" #CL_TYPENAME "`. " \ - "Use :meth:`from_int_ptr` to turn back into a Python object." \ - "\n\n.. versionadded:: 2013.2\n") \ - -#endif diff --git a/src/wrapper/wrap_mempool.cpp b/src/wrapper/wrap_mempool.cpp deleted file mode 100644 index 73df3bd1..00000000 --- a/src/wrapper/wrap_mempool.cpp +++ /dev/null @@ -1,290 +0,0 @@ -// Gregor Thalhammer (on Apr 13, 2011) said it's necessary to import Python.h -// first to prevent OS X from overriding a bunch of macros. (e.g. isspace) -#include <Python.h> - -#include <vector> -#include "wrap_helpers.hpp" -#include "wrap_cl.hpp" -#include "mempool.hpp" -#include "tools.hpp" -#include <boost/python/stl_iterator.hpp> - - - - -namespace py = boost::python; - - - - -namespace -{ - class cl_allocator_base - { - protected: - boost::shared_ptr<pyopencl::context> m_context; - cl_mem_flags m_flags; - - public: - cl_allocator_base(boost::shared_ptr<pyopencl::context> const &ctx, - cl_mem_flags flags=CL_MEM_READ_WRITE) - : m_context(ctx), m_flags(flags) - { - if (flags & (CL_MEM_USE_HOST_PTR | CL_MEM_COPY_HOST_PTR)) - throw pyopencl::error("Allocator", CL_INVALID_VALUE, - "cannot specify USE_HOST_PTR or COPY_HOST_PTR flags"); - } - - cl_allocator_base(cl_allocator_base const &src) - : m_context(src.m_context), m_flags(src.m_flags) - { } - - virtual ~cl_allocator_base() - { } - - typedef cl_mem pointer_type; - typedef size_t size_type; - - virtual cl_allocator_base *copy() const = 0; - virtual bool is_deferred() const = 0; - virtual pointer_type allocate(size_type s) = 0; - - void free(pointer_type p) - { - PYOPENCL_CALL_GUARDED(clReleaseMemObject, (p)); - } - - void try_release_blocks() - { - pyopencl::run_python_gc(); - } - }; - - class cl_deferred_allocator : public cl_allocator_base - { - private: - typedef cl_allocator_base super; - - public: - cl_deferred_allocator(boost::shared_ptr<pyopencl::context> const &ctx, - cl_mem_flags flags=CL_MEM_READ_WRITE) - : super(ctx, flags) - { } - - cl_allocator_base *copy() const - { - return new cl_deferred_allocator(*this); - } - - bool is_deferred() const - { return true; } - - pointer_type allocate(size_type s) - { - return pyopencl::create_buffer(m_context->data(), m_flags, s, 0); - } - }; - - const unsigned zero = 0; - - class cl_immediate_allocator : public cl_allocator_base - { - private: - typedef cl_allocator_base super; - pyopencl::command_queue m_queue; - - public: - cl_immediate_allocator(pyopencl::command_queue &queue, - cl_mem_flags flags=CL_MEM_READ_WRITE) - : super(boost::shared_ptr<pyopencl::context>(queue.get_context()), flags), - m_queue(queue.data(), /*retain*/ true) - { } - - cl_immediate_allocator(cl_immediate_allocator const &src) - : super(src), m_queue(src.m_queue) - { } - - cl_allocator_base *copy() const - { - return new cl_immediate_allocator(*this); - } - - bool is_deferred() const - { return false; } - - pointer_type allocate(size_type s) - { - pointer_type ptr = pyopencl::create_buffer( - m_context->data(), m_flags, s, 0); - - // Make sure the buffer gets allocated right here and right now. - // This looks (and is) expensive. But immediate allocators - // have their main use in memory pools, whose basic assumption - // is that allocation is too expensive anyway--but they rely - // on exact 'out-of-memory' information. - unsigned zero = 0; - PYOPENCL_CALL_GUARDED(clEnqueueWriteBuffer, ( - m_queue.data(), - ptr, - /* is blocking */ CL_FALSE, - 0, std::min(s, sizeof(zero)), &zero, - 0, NULL, NULL - )); - - // No need to wait for completion here. clWaitForEvents (e.g.) - // cannot return mem object allocation failures. This implies that - // the buffer is faulted onto the device on enqueue. - - return ptr; - } - }; - - - - - inline - pyopencl::buffer *allocator_call(cl_allocator_base &alloc, size_t size) - { - cl_mem mem; - int try_count = 0; - while (try_count < 2) - { - try - { - mem = alloc.allocate(size); - break; - } - catch (pyopencl::error &e) - { - if (!e.is_out_of_memory()) - throw; - if (++try_count == 2) - throw; - } - - alloc.try_release_blocks(); - } - - try - { - return new pyopencl::buffer(mem, false); - } - catch (...) - { - PYOPENCL_CALL_GUARDED(clReleaseMemObject, (mem)); - throw; - } - } - - - - - class pooled_buffer - : public pyopencl::pooled_allocation<pyopencl::memory_pool<cl_allocator_base> >, - public pyopencl::memory_object_holder - { - private: - typedef - pyopencl::pooled_allocation<pyopencl::memory_pool<cl_allocator_base> > - super; - - public: - pooled_buffer( - boost::shared_ptr<super::pool_type> p, super::size_type s) - : super(p, s) - { } - - const super::pointer_type data() const - { return ptr(); } - }; - - - - - pooled_buffer *device_pool_allocate( - boost::shared_ptr<pyopencl::memory_pool<cl_allocator_base> > pool, - pyopencl::memory_pool<cl_allocator_base>::size_type sz) - { - return new pooled_buffer(pool, sz); - } - - - - - template<class Wrapper> - void expose_memory_pool(Wrapper &wrapper) - { - typedef typename Wrapper::wrapped_type cls; - wrapper - .add_property("held_blocks", &cls::held_blocks) - .add_property("active_blocks", &cls::active_blocks) - .DEF_SIMPLE_METHOD(bin_number) - .DEF_SIMPLE_METHOD(alloc_size) - .DEF_SIMPLE_METHOD(free_held) - .DEF_SIMPLE_METHOD(stop_holding) - .staticmethod("bin_number") - .staticmethod("alloc_size") - ; - } -} - - - - -void pyopencl_expose_mempool() -{ - py::def("bitlog2", pyopencl::bitlog2); - - { - typedef cl_allocator_base cls; - py::class_<cls, boost::noncopyable> wrapper("_tools_AllocatorBase", py::no_init); - wrapper - .def("__call__", allocator_call, - py::return_value_policy<py::manage_new_object>()) - ; - - } - - { - typedef cl_deferred_allocator cls; - py::class_<cls, py::bases<cl_allocator_base> > wrapper("_tools_DeferredAllocator", - py::init< - boost::shared_ptr<pyopencl::context> const &, - py::optional<cl_mem_flags> >()); - } - - { - typedef cl_immediate_allocator cls; - py::class_<cls, py::bases<cl_allocator_base> > wrapper("_tools_ImmediateAllocator", - py::init<pyopencl::command_queue &, py::optional<cl_mem_flags> >()); - } - - { - typedef pyopencl::memory_pool<cl_allocator_base> cls; - - py::class_< - cls, boost::noncopyable, - boost::shared_ptr<cls> > wrapper("MemoryPool", - py::init<cl_allocator_base const &>() - ); - wrapper - .def("allocate", device_pool_allocate, - py::return_value_policy<py::manage_new_object>()) - .def("__call__", device_pool_allocate, - py::return_value_policy<py::manage_new_object>()) - // undoc for now - .DEF_SIMPLE_METHOD(set_trace) - ; - - expose_memory_pool(wrapper); - } - - { - typedef pooled_buffer cls; - py::class_<cls, boost::noncopyable, - py::bases<pyopencl::memory_object_holder> >( - "PooledBuffer", py::no_init) - .def("release", &cls::free) - ; - } -} -- GitLab