diff --git a/pyopencl/__init__.py b/pyopencl/__init__.py index 70567a91f056859ae8146b6809d5d3842da83424..c8ade533d51b837d683268886811290c68fb9613 100644 --- a/pyopencl/__init__.py +++ b/pyopencl/__init__.py @@ -642,6 +642,72 @@ def enqueue_copy(queue, dest, src, **kwargs): # }}} +# {{{ image creation + +DTYPE_TO_CHANNEL_TYPE = { + np.dtype(np.float32): channel_type.FLOAT, + np.dtype(np.int16): channel_type.SIGNED_INT16, + np.dtype(np.int32): channel_type.SIGNED_INT32, + np.dtype(np.int8): channel_type.SIGNED_INT8, + np.dtype(np.uint16): channel_type.UNSIGNED_INT16, + np.dtype(np.uint32): channel_type.UNSIGNED_INT32, + np.dtype(np.uint8): channel_type.UNSIGNED_INT8, + } +try: + np.float16 +except: + pass +else: + DTYPE_TO_CHANNEL_TYPE[np.dtype(np.float16)] = channel_type.HALF_FLOAT, + +DTYPE_TO_CHANNEL_TYPE_NORM = { + np.dtype(np.int16): channel_type.SNORM_INT16, + np.dtype(np.int8): channel_type.SNORM_INT8, + np.dtype(np.int16): channel_type.UNORM_INT16, + np.dtype(np.uint8): channel_type.UNORM_INT8, + } + +def image_from_array(ctx, ary, num_channels, mode="r", norm_int=False): + # FIXME what about vector types? + + if num_channels == 1: + shape = ary.shape + strides = ary.strides + else: + if ary.shape[-1] != num_channels: + raise RuntimeError("last dimension must be equal to number of channels") + + shape = ary.shape[:-1] + strides = ary.strides[:-1] + + if mode == "r": + mode_flags = mem_flags.READ_ONLY + elif mode == "r": + mode_flags = mem_flags.WRITE_ONLY + else: + raise ValueError("invalid value '%s' for 'mode'" % mode) + + img_format = { + 1: channel_order.R, + 2: channel_order.RG, + 3: channel_order.RGB, + 4: channel_order.RGBA, + }[num_channels] + + assert ary.strides[-1] == ary.dtype.itemsize + + if norm_int: + channel_type = DTYPE_TO_CHANNEL_TYPE_NORM[ary.dtype] + else: + channel_type = DTYPE_TO_CHANNEL_TYPE[ary.dtype] + + return Image(ctx, mode_flags | mem_flags.COPY_HOST_PTR, + ImageFormat(img_format, channel_type), + shape=shape, pitches=strides[:-1], + hostbuf=ary) + +# }}} + diff --git a/pyopencl/array.py b/pyopencl/array.py index 5cb0ae4e143ac293b20a2f17c731c221e8403af5..258cc32d0f70ffef5a52a60129c868492964a15a 100644 --- a/pyopencl/array.py +++ b/pyopencl/array.py @@ -1093,7 +1093,4 @@ subset_max = _make_subset_minmax_kernel("max") # }}} - - - # vim: foldmethod=marker diff --git a/test/test_wrapper.py b/test/test_wrapper.py index ed8ae6170d56aa674a1a54fd24c6ddc2e8cb91ad..a262137a9dfc1227892ba7781d8dfdc0e2e62164 100644 --- a/test/test_wrapper.py +++ b/test/test_wrapper.py @@ -220,16 +220,18 @@ class TestCL: cl.enqueue_read_buffer(queue, a_buf, a_result).wait() @pytools.test.mark_test.opencl - def test_image_2d(self, device, ctx_factory): + def test_image_2d(self, ctx_factory): context = ctx_factory() + device, = context.devices + if not device.image_support: from py.test import skip skip("images not supported on %s" % device) prg = cl.Program(context, """ __kernel void copy_image( - __global float4 *dest, + __global float *dest, __read_only image2d_t src, sampler_t samp, int width) @@ -242,18 +244,19 @@ class TestCL: | CLK_ADDRESS_CLAMP | CLK_FILTER_NEAREST; */ - dest[x + width*y] = read_imagef(src, samp, (float2)(x, y)); + dest[x + width*y] = read_imagef(src, samp, (float2)(x, y)).x; // dest[x + width*y] = get_image_height(src); } """).build() - a = np.random.rand(1024, 1024, 4).astype(np.float32) + num_channels = 1 + a = np.random.rand(1024, 1024, num_channels).astype(np.float32) + if num_channels == 1: + a = a[:,:,0] + queue = cl.CommandQueue(context) - mf = cl.mem_flags - a_img = cl.Image(context, mf.READ_ONLY | mf.COPY_HOST_PTR, - cl.ImageFormat(cl.channel_order.RGBA, cl.channel_type.FLOAT), - shape=a.shape[:2], hostbuf=a) - a_dest = cl.Buffer(context, mf.READ_WRITE, a.nbytes) + a_img = cl.image_from_array(context, a, num_channels) + a_dest = cl.Buffer(context, cl.mem_flags.READ_WRITE, a.nbytes) samp = cl.Sampler(context, False, cl.addressing_mode.CLAMP, @@ -261,8 +264,7 @@ class TestCL: prg.copy_image(queue, a.shape, None, a_dest, a_img, samp, np.int32(a.shape[0])) a_result = np.empty_like(a) - cl.enqueue_read_buffer(queue, a_dest, a_result, is_blocking=True) - print(a_result.dtype) + cl.enqueue_copy(queue, a_result, a_dest) assert la.norm(a_result - a) == 0