diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index 43a1fd3b..a0c8b7a5 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -53,6 +53,9 @@ doxygen autodoc ../include/boost/compute/interop/opengl.hpp [ glob ../include/boost/compute/interop/opengl/*.hpp ] + ../include/boost/compute/image.hpp + [ glob ../include/boost/compute/image/*.hpp ] + ../include/boost/compute/iterator.hpp [ glob ../include/boost/compute/iterator/*.hpp ] diff --git a/doc/reference.qbk b/doc/reference.qbk index 20dbca69..e9e116e6 100644 --- a/doc/reference.qbk +++ b/doc/reference.qbk @@ -154,6 +154,17 @@ Header: `` * [classref boost::compute::transform_iterator transform_iterator] * [classref boost::compute::zip_iterator zip_iterator] +[h3 Images] + +Header: `` + +* [classref boost::compute::image1d image1d] +* [classref boost::compute::image2d image2d] +* [classref boost::compute::image3d image3d] +* [classref boost::compute::image_format image_format] +* [classref boost::compute::image_object image_object] +* [classref boost::compute::image_sampler image_sampler] + [h3 Shared Virtual Memory] * [classref boost::compute::svm_ptr svm_ptr] diff --git a/example/k_means.cpp b/example/k_means.cpp index 2a2b29e1..6441cc8a 100644 --- a/example/k_means.cpp +++ b/example/k_means.cpp @@ -13,8 +13,8 @@ #include #include -#include #include +#include #include #include #include @@ -142,11 +142,7 @@ int main() // create output image compute::image2d image( - context, - CL_MEM_READ_WRITE, - compute::image_format(CL_RGBA, CL_UNSIGNED_INT8), - width, - height + context, width, height, compute::image_format(CL_RGBA, CL_UNSIGNED_INT8) ); // program with two kernels, one to fill the image with white, and then diff --git a/example/opencv_convolution.cpp b/example/opencv_convolution.cpp index 99708740..ab3d4ef0 100644 --- a/example/opencv_convolution.cpp +++ b/example/opencv_convolution.cpp @@ -202,10 +202,10 @@ int main(int argc, char *argv[]) // Be sure what will be your ouput image/frame size compute::image2d dev_output_image( context, - compute::image2d::write_only, - dev_input_image.get_format(), dev_input_image.width(), - dev_input_image.height() + dev_input_image.height(), + dev_input_image.format(), + compute::image2d::write_only ); filter_kernel.set_arg(0, dev_input_image); diff --git a/example/opencv_flip.cpp b/example/opencv_flip.cpp index c02cc359..1c8ede9f 100644 --- a/example/opencv_flip.cpp +++ b/example/opencv_flip.cpp @@ -55,10 +55,10 @@ int main(int argc, char *argv[]) // create output image compute::image2d output_image( context, - compute::image2d::write_only, - input_image.get_format(), input_image.width(), - input_image.height() + input_image.height(), + input_image.format(), + compute::image2d::write_only ); // create flip program diff --git a/example/opencv_optical_flow.cpp b/example/opencv_optical_flow.cpp index 0e0c42b1..7268e07c 100644 --- a/example/opencv_optical_flow.cpp +++ b/example/opencv_optical_flow.cpp @@ -203,10 +203,10 @@ int main(int argc, char *argv[]) // Create output image compute::image2d dev_output_image( context, - compute::image2d::write_only, - dev_previous_image.get_format(), dev_previous_image.width(), - dev_previous_image.height() + dev_previous_image.height(), + dev_previous_image.format(), + compute::image2d::write_only ); compute::program optical_program = diff --git a/example/opencv_sobel_filter.cpp b/example/opencv_sobel_filter.cpp index bf1334e3..d1f1f5d4 100644 --- a/example/opencv_sobel_filter.cpp +++ b/example/opencv_sobel_filter.cpp @@ -192,10 +192,10 @@ int main(int argc, char *argv[]) // Be sure what will be your ouput image/frame size compute::image2d dev_output_image( context, - compute::image2d::write_only, - dev_input_image.get_format(), dev_input_image.width(), - dev_input_image.height() + dev_input_image.height(), + dev_input_image.format(), + compute::image2d::write_only ); filter_kernel.set_arg(0, dev_input_image); diff --git a/example/qimage_blur.cpp b/example/qimage_blur.cpp index 8fc82f88..0e322ffa 100644 --- a/example/qimage_blur.cpp +++ b/example/qimage_blur.cpp @@ -10,7 +10,7 @@ #ifndef Q_MOC_RUN #include -#include +#include #include #include #include @@ -114,12 +114,8 @@ int main(int argc, char *argv[]) compute::qt_qimage_format_to_image_format(qimage.format()); // create input and output images on the gpu - compute::image2d input_image( - context, compute::image2d::read_write, format, width, height - ); - compute::image2d output_image( - context, compute::image2d::read_write, format, width, height - ); + compute::image2d input_image(context, width, height, format); + compute::image2d output_image(context, width, height, format); // copy host qimage to gpu image compute::qt_copy_qimage_to_image2d(qimage, input_image, queue); diff --git a/example/random_walk.cpp b/example/random_walk.cpp index 9a3258f7..7c3a092f 100644 --- a/example/random_walk.cpp +++ b/example/random_walk.cpp @@ -93,11 +93,7 @@ int main() // create output image compute::image2d image( - context, - CL_MEM_READ_WRITE, - compute::image_format(CL_RGBA, CL_UNSIGNED_INT8), - width, - height + context, width, height, compute::image_format(CL_RGBA, CL_UNSIGNED_INT8) ); // program with two kernels, one to fill the image with white, and then diff --git a/example/resize_image.cpp b/example/resize_image.cpp index e153128e..e3a29424 100644 --- a/example/resize_image.cpp +++ b/example/resize_image.cpp @@ -26,8 +26,8 @@ #include #include #include -#include -#include +#include +#include #include #include #include @@ -110,7 +110,7 @@ void ImageWidget::initializeGL() compute::qt_qimage_format_to_image_format(qt_image_.format()); image_ = compute::image2d( - context_, CL_MEM_READ_ONLY, format, qt_image_.width(), qt_image_.height() + context_, qt_image_.width(), qt_image_.height(), format, CL_MEM_READ_ONLY ); // transfer image to the device diff --git a/include/boost/compute.hpp b/include/boost/compute.hpp index 9bce49c2..0de92610 100644 --- a/include/boost/compute.hpp +++ b/include/boost/compute.hpp @@ -22,10 +22,7 @@ #include #include #include -#include -#include -#include -#include +#include #include #include #include diff --git a/include/boost/compute/command_queue.hpp b/include/boost/compute/command_queue.hpp index 5bdf2ca3..43315642 100644 --- a/include/boost/compute/command_queue.hpp +++ b/include/boost/compute/command_queue.hpp @@ -8,10 +8,11 @@ // See http://kylelutz.github.com/compute for more information. //---------------------------------------------------------------------------// -#ifndef BOOST_COMPUTE_COMMAND_QUEUE_H -#define BOOST_COMPUTE_COMMAND_QUEUE_H +#ifndef BOOST_COMPUTE_COMMAND_QUEUE_HPP +#define BOOST_COMPUTE_COMMAND_QUEUE_HPP #include +#include #include @@ -21,9 +22,11 @@ #include #include #include -#include -#include #include +#include +#include +#include +#include #include #include #include @@ -675,51 +678,17 @@ public: /// Enqueues a command to read data from \p image to host memory. /// /// \see_opencl_ref{clEnqueueReadImage} - void enqueue_read_image(const image2d &image, - const size_t origin[2], - const size_t region[2], - size_t row_pitch, - void *host_ptr, - const wait_list &events = wait_list()) + event enqueue_read_image(const image_object& image, + const size_t *origin, + const size_t *region, + size_t row_pitch, + size_t slice_pitch, + void *host_ptr, + const wait_list &events = wait_list()) { BOOST_ASSERT(m_queue != 0); - BOOST_ASSERT(image.get_context() == this->get_context()); - const size_t origin3[3] = { origin[0], origin[1], size_t(0) }; - const size_t region3[3] = { region[0], region[1], size_t(1) }; - - cl_int ret = clEnqueueReadImage( - m_queue, - image.get(), - CL_TRUE, - origin3, - region3, - row_pitch, - 0, - host_ptr, - events.size(), - events.get_event_ptr(), - 0 - ); - - if(ret != CL_SUCCESS){ - BOOST_THROW_EXCEPTION(opencl_error(ret)); - } - } - - /// Enqueues a command to read data from \p image to host memory. - /// - /// \see_opencl_ref{clEnqueueReadImage} - void enqueue_read_image(const image3d &image, - const size_t origin[3], - const size_t region[3], - size_t row_pitch, - size_t slice_pitch, - void *host_ptr, - const wait_list &events = wait_list()) - { - BOOST_ASSERT(m_queue != 0); - BOOST_ASSERT(image.get_context() == this->get_context()); + event event_; cl_int ret = clEnqueueReadImage( m_queue, @@ -732,62 +701,53 @@ public: host_ptr, events.size(), events.get_event_ptr(), - 0 + &event_.get() ); if(ret != CL_SUCCESS){ BOOST_THROW_EXCEPTION(opencl_error(ret)); } + + return event_; } - /// Enqueues a command to write data from host memory to \p image. - /// - /// \see_opencl_ref{clEnqueueWriteImage} - void enqueue_write_image(const image2d &image, - const size_t origin[2], - const size_t region[2], - size_t input_row_pitch, - const void *host_ptr, + /// \overload + template + event enqueue_read_image(const image_object& image, + const extents origin, + const extents region, + void *host_ptr, + size_t row_pitch = 0, + size_t slice_pitch = 0, const wait_list &events = wait_list()) { - BOOST_ASSERT(m_queue != 0); BOOST_ASSERT(image.get_context() == this->get_context()); - const size_t origin3[3] = { origin[0], origin[1], size_t(0) }; - const size_t region3[3] = { region[0], region[1], size_t(1) }; + size_t origin3[3] = { 0, 0, 0 }; + size_t region3[3] = { 1, 1, 1 }; - cl_int ret = clEnqueueWriteImage( - m_queue, - image.get(), - CL_TRUE, - origin3, - region3, - input_row_pitch, - 0, - host_ptr, - events.size(), - events.get_event_ptr(), - 0 + std::copy(origin.data(), origin.data() + N, origin3); + std::copy(region.data(), region.data() + N, region3); + + return enqueue_read_image( + image, origin3, region3, row_pitch, slice_pitch, host_ptr, events ); - - if(ret != CL_SUCCESS){ - BOOST_THROW_EXCEPTION(opencl_error(ret)); - } } /// Enqueues a command to write data from host memory to \p image. /// /// \see_opencl_ref{clEnqueueWriteImage} - void enqueue_write_image(const image3d &image, - const size_t origin[3], - const size_t region[3], - size_t input_row_pitch, - size_t input_slice_pitch, - const void *host_ptr, - const wait_list &events = wait_list()) + event enqueue_write_image(image_object& image, + const size_t *origin, + const size_t *region, + const void *host_ptr, + size_t input_row_pitch = 0, + size_t input_slice_pitch = 0, + const wait_list &events = wait_list()) { BOOST_ASSERT(m_queue != 0); - BOOST_ASSERT(image.get_context() == this->get_context()); + + event event_; cl_int ret = clEnqueueWriteImage( m_queue, @@ -800,45 +760,6 @@ public: host_ptr, events.size(), events.get_event_ptr(), - 0 - ); - - if(ret != CL_SUCCESS){ - BOOST_THROW_EXCEPTION(opencl_error(ret)); - } - } - - /// Enqueues a command to copy data from \p src_image to \p dst_image. - /// - /// \see_opencl_ref{clEnqueueCopyImage} - event enqueue_copy_image(const image2d &src_image, - const image2d &dst_image, - const size_t src_origin[2], - const size_t dst_origin[2], - const size_t region[2], - const wait_list &events = wait_list()) - { - BOOST_ASSERT(m_queue != 0); - BOOST_ASSERT(src_image.get_context() == this->get_context()); - BOOST_ASSERT(dst_image.get_context() == this->get_context()); - BOOST_ASSERT_MSG(src_image.get_format() == dst_image.get_format(), - "Source and destination image formats must match."); - - const size_t src_origin3[3] = { src_origin[0], src_origin[1], size_t(0) }; - const size_t dst_origin3[3] = { dst_origin[0], dst_origin[1], size_t(0) }; - const size_t region3[3] = { region[0], region[1], size_t(1) }; - - event event_; - - cl_int ret = clEnqueueCopyImage( - m_queue, - src_image.get(), - dst_image.get(), - src_origin3, - dst_origin3, - region3, - events.size(), - events.get_event_ptr(), &event_.get() ); @@ -849,101 +770,40 @@ public: return event_; } - /// Enqueues a command to copy data from \p src_image to \p dst_image. - /// - /// \see_opencl_ref{clEnqueueCopyImage} - event enqueue_copy_image(const image2d &src_image, - const image3d &dst_image, - const size_t src_origin[2], - const size_t dst_origin[3], - const size_t region[2], - const wait_list &events = wait_list()) + /// \overload + template + event enqueue_write_image(image_object& image, + const extents origin, + const extents region, + const void *host_ptr, + const size_t input_row_pitch = 0, + const size_t input_slice_pitch = 0, + const wait_list &events = wait_list()) { - BOOST_ASSERT(m_queue != 0); - BOOST_ASSERT(src_image.get_context() == this->get_context()); - BOOST_ASSERT(dst_image.get_context() == this->get_context()); - BOOST_ASSERT_MSG(src_image.get_format() == dst_image.get_format(), - "Source and destination image formats must match."); + BOOST_ASSERT(image.get_context() == this->get_context()); - const size_t src_origin3[3] = { src_origin[0], src_origin[1], size_t(0) }; - const size_t region3[3] = { region[0], region[1], size_t(1) }; + size_t origin3[3] = { 0, 0, 0 }; + size_t region3[3] = { 1, 1, 1 }; - event event_; + std::copy(origin.data(), origin.data() + N, origin3); + std::copy(region.data(), region.data() + N, region3); - cl_int ret = clEnqueueCopyImage( - m_queue, - src_image.get(), - dst_image.get(), - src_origin3, - dst_origin, - region3, - events.size(), - events.get_event_ptr(), - &event_.get() + return enqueue_write_image( + image, origin3, region3, host_ptr, input_row_pitch, input_slice_pitch, events ); - - if(ret != CL_SUCCESS){ - BOOST_THROW_EXCEPTION(opencl_error(ret)); - } - - return event_; } /// Enqueues a command to copy data from \p src_image to \p dst_image. /// /// \see_opencl_ref{clEnqueueCopyImage} - event enqueue_copy_image(const image3d &src_image, - const image2d &dst_image, - const size_t src_origin[3], - const size_t dst_origin[2], - const size_t region[2], + event enqueue_copy_image(const image_object& src_image, + image_object& dst_image, + const size_t *src_origin, + const size_t *dst_origin, + const size_t *region, const wait_list &events = wait_list()) { BOOST_ASSERT(m_queue != 0); - BOOST_ASSERT(src_image.get_context() == this->get_context()); - BOOST_ASSERT(dst_image.get_context() == this->get_context()); - BOOST_ASSERT_MSG(src_image.get_format() == dst_image.get_format(), - "Source and destination image formats must match."); - - const size_t dst_origin3[3] = { dst_origin[0], dst_origin[1], size_t(0) }; - const size_t region3[3] = { region[0], region[1], size_t(1) }; - - event event_; - - cl_int ret = clEnqueueCopyImage( - m_queue, - src_image.get(), - dst_image.get(), - src_origin, - dst_origin3, - region3, - events.size(), - events.get_event_ptr(), - &event_.get() - ); - - if(ret != CL_SUCCESS){ - BOOST_THROW_EXCEPTION(opencl_error(ret)); - } - - return event_; - } - - /// Enqueues a command to copy data from \p src_image to \p dst_image. - /// - /// \see_opencl_ref{clEnqueueCopyImage} - event enqueue_copy_image(const image3d &src_image, - const image3d &dst_image, - const size_t src_origin[3], - const size_t dst_origin[3], - const size_t region[3], - const wait_list &events = wait_list()) - { - BOOST_ASSERT(m_queue != 0); - BOOST_ASSERT(src_image.get_context() == this->get_context()); - BOOST_ASSERT(dst_image.get_context() == this->get_context()); - BOOST_ASSERT_MSG(src_image.get_format() == dst_image.get_format(), - "Source and destination image formats must match."); event event_; @@ -966,57 +826,44 @@ public: return event_; } - /// Enqueues a command to copy data from \p src_image to \p dst_buffer. - /// - /// \see_opencl_ref{clEnqueueCopyImageToBuffer} - event enqueue_copy_image_to_buffer(const image2d &src_image, - const buffer &dst_buffer, - const size_t src_origin[2], - const size_t region[2], - size_t dst_offset, - const wait_list &events = wait_list()) + /// \overload + template + event enqueue_copy_image(const image_object& src_image, + image_object& dst_image, + const extents src_origin, + const extents dst_origin, + const extents region, + const wait_list &events = wait_list()) { - BOOST_ASSERT(m_queue != 0); BOOST_ASSERT(src_image.get_context() == this->get_context()); - BOOST_ASSERT(dst_buffer.get_context() == this->get_context()); + BOOST_ASSERT(dst_image.get_context() == this->get_context()); + BOOST_ASSERT_MSG(src_image.format() == dst_image.format(), + "Source and destination image formats must match."); - const size_t src_origin3[3] = { src_origin[0], src_origin[1], size_t(0) }; - const size_t region3[3] = { region[0], region[1], size_t(1) }; + size_t src_origin3[3] = { 0, 0, 0 }; + size_t dst_origin3[3] = { 0, 0, 0 }; + size_t region3[3] = { 1, 1, 1 }; - event event_; + std::copy(src_origin.data(), src_origin.data() + N, src_origin3); + std::copy(dst_origin.data(), dst_origin.data() + N, dst_origin3); + std::copy(region.data(), region.data() + N, region3); - cl_int ret = clEnqueueCopyImageToBuffer( - m_queue, - src_image.get(), - dst_buffer.get(), - src_origin3, - region3, - dst_offset, - events.size(), - events.get_event_ptr(), - &event_.get() + return enqueue_copy_image( + src_image, dst_image, src_origin3, dst_origin3, region3, events ); - - if(ret != CL_SUCCESS){ - BOOST_THROW_EXCEPTION(opencl_error(ret)); - } - - return event_; } /// Enqueues a command to copy data from \p src_image to \p dst_buffer. /// /// \see_opencl_ref{clEnqueueCopyImageToBuffer} - event enqueue_copy_image_to_buffer(const image3d &src_image, - const buffer &dst_buffer, - const size_t src_origin[3], - const size_t region[3], + event enqueue_copy_image_to_buffer(const image_object& src_image, + memory_object& dst_buffer, + const size_t *src_origin, + const size_t *region, size_t dst_offset, const wait_list &events = wait_list()) { BOOST_ASSERT(m_queue != 0); - BOOST_ASSERT(src_image.get_context() == this->get_context()); - BOOST_ASSERT(dst_buffer.get_context() == this->get_context()); event event_; @@ -1042,54 +889,14 @@ public: /// Enqueues a command to copy data from \p src_buffer to \p dst_image. /// /// \see_opencl_ref{clEnqueueCopyBufferToImage} - event enqueue_copy_buffer_to_image(const buffer &src_buffer, - const image2d &dst_image, + event enqueue_copy_buffer_to_image(const memory_object& src_buffer, + image_object& dst_image, size_t src_offset, - const size_t dst_origin[3], - const size_t region[3], + const size_t *dst_origin, + const size_t *region, const wait_list &events = wait_list()) { BOOST_ASSERT(m_queue != 0); - BOOST_ASSERT(src_buffer.get_context() == this->get_context()); - BOOST_ASSERT(dst_image.get_context() == this->get_context()); - - const size_t dst_origin3[3] = { dst_origin[0], dst_origin[1], size_t(0) }; - const size_t region3[3] = { region[0], region[1], size_t(1) }; - - event event_; - - cl_int ret = clEnqueueCopyBufferToImage( - m_queue, - src_buffer.get(), - dst_image.get(), - src_offset, - dst_origin3, - region3, - events.size(), - events.get_event_ptr(), - &event_.get() - ); - - if(ret != CL_SUCCESS){ - BOOST_THROW_EXCEPTION(opencl_error(ret)); - } - - return event_; - } - - /// Enqueues a command to copy data from \p src_buffer to \p dst_image. - /// - /// \see_opencl_ref{clEnqueueCopyBufferToImage} - event enqueue_copy_buffer_to_image(const buffer &src_buffer, - const image3d &dst_image, - size_t src_offset, - const size_t dst_origin[3], - const size_t region[3], - const wait_list &events = wait_list()) - { - BOOST_ASSERT(m_queue != 0); - BOOST_ASSERT(src_buffer.get_context() == this->get_context()); - BOOST_ASSERT(dst_image.get_context() == this->get_context()); event event_; @@ -1118,51 +925,13 @@ public: /// \see_opencl_ref{clEnqueueFillImage} /// /// \opencl_version_warning{1,2} - event enqueue_fill_image(const image2d &image, + event enqueue_fill_image(image_object& image, const void *fill_color, - const size_t origin[2], - const size_t region[2], + const size_t *origin, + const size_t *region, const wait_list &events = wait_list()) { BOOST_ASSERT(m_queue != 0); - BOOST_ASSERT(image.get_context() == this->get_context()); - - const size_t origin3[3] = { origin[0], origin[1], size_t(0) }; - const size_t region3[3] = { region[0], region[1], size_t(1) }; - - event event_; - - cl_int ret = clEnqueueFillImage( - m_queue, - image.get(), - fill_color, - origin3, - region3, - events.size(), - events.get_event_ptr(), - &event_.get() - ); - - if(ret != CL_SUCCESS){ - BOOST_THROW_EXCEPTION(opencl_error(ret)); - } - - return event_; - } - - /// Enqueues a command to fill \p image with \p fill_color. - /// - /// \see_opencl_ref{clEnqueueFillImage} - /// - /// \opencl_version_warning{1,2} - event enqueue_fill_image(const image3d &image, - const void *fill_color, - const size_t origin[3], - const size_t region[3], - const wait_list &events = wait_list()) - { - BOOST_ASSERT(m_queue != 0); - BOOST_ASSERT(image.get_context() == this->get_context()); event event_; @@ -1184,6 +953,27 @@ public: return event_; } + /// \overload + template + event enqueue_fill_image(image_object& image, + const void *fill_color, + const extents origin, + const extents region, + const wait_list &events = wait_list()) + { + BOOST_ASSERT(image.get_context() == this->get_context()); + + size_t origin3[3] = { 0, 0, 0 }; + size_t region3[3] = { 1, 1, 1 }; + + std::copy(origin.data(), origin.data() + N, origin3); + std::copy(region.data(), region.data() + N, region3); + + return enqueue_fill_image( + image, fill_color, origin3, region3, events + ); + } + /// Enqueues a command to migrate \p mem_objects. /// /// \see_opencl_ref{clEnqueueMigrateMemObjects} @@ -1659,16 +1449,35 @@ inline buffer buffer::clone(command_queue &queue) const return copy; } +inline image1d image1d::clone(command_queue &queue) const +{ + image1d copy( + get_context(), width(), format(), get_memory_flags() + ); + + queue.enqueue_copy_image(*this, copy, origin(), copy.origin(), size()); + + return copy; +} + inline image2d image2d::clone(command_queue &queue) const { image2d copy( - get_context(), get_memory_flags(), get_format(), width(), height(), 0, 0 + get_context(), width(), height(), format(), get_memory_flags() ); - size_t origin[2] = { 0, 0 }; - size_t region[2] = { this->width(), this->height() }; + queue.enqueue_copy_image(*this, copy, origin(), copy.origin(), size()); - queue.enqueue_copy_image(*this, copy, origin, origin, region); + return copy; +} + +inline image3d image3d::clone(command_queue &queue) const +{ + image3d copy( + get_context(), width(), height(), depth(), format(), get_memory_flags() + ); + + queue.enqueue_copy_image(*this, copy, origin(), copy.origin(), size()); return copy; } @@ -1684,4 +1493,4 @@ BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(command_queue, } // end compute namespace } // end boost namespace -#endif // BOOST_COMPUTE_COMMAND_QUEUE_H +#endif // BOOST_COMPUTE_COMMAND_QUEUE_HPP diff --git a/include/boost/compute/core.hpp b/include/boost/compute/core.hpp index 6aa4a8a9..54f8386a 100644 --- a/include/boost/compute/core.hpp +++ b/include/boost/compute/core.hpp @@ -21,10 +21,6 @@ #include #include #include -#include -#include -#include -#include #include #include #include diff --git a/include/boost/compute/detail/meta_kernel.hpp b/include/boost/compute/detail/meta_kernel.hpp index f673101b..2d6bd5de 100644 --- a/include/boost/compute/detail/meta_kernel.hpp +++ b/include/boost/compute/detail/meta_kernel.hpp @@ -26,14 +26,13 @@ #include #include -#include -#include #include #include #include #include #include -#include +#include +#include #include #include #include diff --git a/include/boost/compute/image.hpp b/include/boost/compute/image.hpp new file mode 100644 index 00000000..1c966373 --- /dev/null +++ b/include/boost/compute/image.hpp @@ -0,0 +1,25 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2013-2015 Kyle Lutz +// +// Distributed under the Boost Software License, Version 1.0 +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// +// See http://kylelutz.github.com/compute for more information. +//---------------------------------------------------------------------------// + +#ifndef BOOST_COMPUTE_IMAGE_HPP +#define BOOST_COMPUTE_IMAGE_HPP + +/// \file +/// +/// Meta-header to include all Boost.Compute image headers. + +#include +#include +#include +#include +#include +#include + +#endif // BOOST_COMPUTE_IMAGE_HPP diff --git a/include/boost/compute/image/image1d.hpp b/include/boost/compute/image/image1d.hpp new file mode 100644 index 00000000..59a5f255 --- /dev/null +++ b/include/boost/compute/image/image1d.hpp @@ -0,0 +1,204 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2013-2015 Kyle Lutz +// +// Distributed under the Boost Software License, Version 1.0 +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// +// See http://kylelutz.github.com/compute for more information. +//---------------------------------------------------------------------------// + +#ifndef BOOST_COMPUTE_IMAGE_IMAGE1D_HPP +#define BOOST_COMPUTE_IMAGE_IMAGE1D_HPP + +#include + +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace compute { + +// forward declarations +class command_queue; + +/// \class image1d +/// \brief An OpenCL 1D image object +/// +/// \opencl_version_warning{1,2} +/// +/// \see image_format, image2d +class image1d : public image_object +{ +public: + /// Creates a null image1d object. + image1d() + : image_object() + { + } + + /// Creates a new image1d object. + /// + /// \see_opencl_ref{clCreateImage} + image1d(const context &context, + size_t image_width, + const image_format &format, + cl_mem_flags flags = read_write, + void *host_ptr = 0) + { + #ifdef CL_VERSION_1_2 + cl_image_desc desc; + desc.image_type = CL_MEM_OBJECT_IMAGE1D; + desc.image_width = image_width; + desc.image_height = 1; + desc.image_depth = 1; + desc.image_array_size = 0; + desc.image_row_pitch = 0; + desc.image_slice_pitch = 0; + desc.num_mip_levels = 0; + desc.num_samples = 0; + #ifdef CL_VERSION_2_0 + desc.mem_object = 0; + #else + desc.buffer = 0; + #endif + + cl_int error = 0; + + m_mem = clCreateImage( + context, flags, format.get_format_ptr(), &desc, host_ptr, &error + ); + + if(!m_mem){ + BOOST_THROW_EXCEPTION(opencl_error(error)); + } + #else + // image1d objects are only supported in OpenCL 1.2 and later + BOOST_THROW_EXCEPTION(opencl_error(CL_IMAGE_FORMAT_NOT_SUPPORTED)); + #endif + } + + /// Creates a new image1d as a copy of \p other. + image1d(const image1d &other) + : image_object(other) + { + } + + /// Copies the image1d from \p other. + image1d& operator=(const image1d &other) + { + image_object::operator=(other); + + return *this; + } + + #ifndef BOOST_COMPUTE_NO_RVALUE_REFERENCES + /// Move-constructs a new image object from \p other. + image1d(image1d&& other) BOOST_NOEXCEPT + : image_object(std::move(other)) + { + } + + /// Move-assigns the image from \p other to \c *this. + image1d& operator=(image1d&& other) BOOST_NOEXCEPT + { + image_object::operator=(std::move(other)); + + return *this; + } + #endif // BOOST_COMPUTE_NO_RVALUE_REFERENCES + + /// Destroys the image1d object. + ~image1d() + { + } + + /// Returns the size (width) of the image. + extents<1> size() const + { + extents<1> size; + size[0] = get_info(CL_IMAGE_WIDTH); + return size; + } + + /// Returns the origin of the image (\c 0). + extents<1> origin() const + { + return extents<1>(); + } + + /// Returns information about the image. + /// + /// \see_opencl_ref{clGetImageInfo} + template + T get_info(cl_image_info info) const + { + return get_image_info(info); + } + + /// \overload + template + typename detail::get_object_info_type::type + get_info() const; + + /// Returns the supported image formats for the context. + /// + /// \see_opencl_ref{clGetSupportedImageFormats} + static std::vector + get_supported_formats(const context &context, cl_mem_flags flags = read_write) + { + #ifdef CL_VERSION_1_2 + return image_object::get_supported_formats(context, CL_MEM_OBJECT_IMAGE1D, flags); + #else + return std::vector(); + #endif + } + + /// Returns \c true if \p format is a supported 1D image format for + /// \p context. + static bool is_supported_format(const image_format &format, + const context &context, + cl_mem_flags flags = read_write) + { + #ifdef CL_VERSION_1_2 + return image_object::is_supported_format( + format, context, CL_MEM_OBJECT_IMAGE1D, flags + ); + #else + return false; + #endif + } + + /// Creates a new image with a copy of the data in \c *this. Uses \p queue + /// to perform the copy operation. + image1d clone(command_queue &queue) const; +}; + +/// \internal_ define get_info() specializations for image1d +BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(image1d, + ((cl_image_format, CL_IMAGE_FORMAT)) + ((size_t, CL_IMAGE_ELEMENT_SIZE)) + ((size_t, CL_IMAGE_ROW_PITCH)) + ((size_t, CL_IMAGE_SLICE_PITCH)) + ((size_t, CL_IMAGE_WIDTH)) + ((size_t, CL_IMAGE_HEIGHT)) + ((size_t, CL_IMAGE_DEPTH)) +) + +namespace detail { + +// set_kernel_arg() specialization for image1d +template<> +struct set_kernel_arg : public set_kernel_arg { }; + +} // end detail namespace +} // end compute namespace +} // end boost namespace + +BOOST_COMPUTE_TYPE_NAME(boost::compute::image1d, image1d_t) + +#endif // BOOST_COMPUTE_IMAGE_IMAGE1D_HPP diff --git a/include/boost/compute/image/image2d.hpp b/include/boost/compute/image/image2d.hpp new file mode 100644 index 00000000..cd903fe9 --- /dev/null +++ b/include/boost/compute/image/image2d.hpp @@ -0,0 +1,262 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2013-2015 Kyle Lutz +// +// Distributed under the Boost Software License, Version 1.0 +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// +// See http://kylelutz.github.com/compute for more information. +//---------------------------------------------------------------------------// + +#ifndef BOOST_COMPUTE_IMAGE_IMAGE2D_HPP +#define BOOST_COMPUTE_IMAGE_IMAGE2D_HPP + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace compute { + +// forward declarations +class command_queue; + +/// \class image2d +/// \brief An OpenCL 2D image object +/// +/// For example, to create a 640x480 8-bit RGBA image: +/// +/// \snippet test/test_image2d.cpp create_image +/// +/// \see image_format, image3d +class image2d : public image_object +{ +public: + /// Creates a null image2d object. + image2d() + : image_object() + { + } + + /// Creates a new image2d object. + /// + /// \see_opencl_ref{clCreateImage} + image2d(const context &context, + size_t image_width, + size_t image_height, + const image_format &format, + cl_mem_flags flags = read_write, + void *host_ptr = 0, + size_t image_row_pitch = 0) + { + cl_int error = 0; + + #ifdef CL_VERSION_1_2 + cl_image_desc desc; + desc.image_type = CL_MEM_OBJECT_IMAGE2D; + desc.image_width = image_width; + desc.image_height = image_height; + desc.image_depth = 1; + desc.image_array_size = 0; + desc.image_row_pitch = image_row_pitch; + desc.image_slice_pitch = 0; + desc.num_mip_levels = 0; + desc.num_samples = 0; + #ifdef CL_VERSION_2_0 + desc.mem_object = 0; + #else + desc.buffer = 0; + #endif + + m_mem = clCreateImage(context, + flags, + format.get_format_ptr(), + &desc, + host_ptr, + &error); + #else + m_mem = clCreateImage2D(context, + flags, + format.get_format_ptr(), + image_width, + image_height, + image_row_pitch, + host_ptr, + &error); + #endif + + if(!m_mem){ + BOOST_THROW_EXCEPTION(opencl_error(error)); + } + } + + /// \internal_ (deprecated) + image2d(const context &context, + cl_mem_flags flags, + const image_format &format, + size_t image_width, + size_t image_height, + size_t image_row_pitch = 0, + void *host_ptr = 0) + { + cl_int error = 0; + + #ifdef CL_VERSION_1_2 + cl_image_desc desc; + desc.image_type = CL_MEM_OBJECT_IMAGE2D; + desc.image_width = image_width; + desc.image_height = image_height; + desc.image_depth = 1; + desc.image_array_size = 0; + desc.image_row_pitch = image_row_pitch; + desc.image_slice_pitch = 0; + desc.num_mip_levels = 0; + desc.num_samples = 0; + #ifdef CL_VERSION_2_0 + desc.mem_object = 0; + #else + desc.buffer = 0; + #endif + + m_mem = clCreateImage(context, + flags, + format.get_format_ptr(), + &desc, + host_ptr, + &error); + #else + m_mem = clCreateImage2D(context, + flags, + format.get_format_ptr(), + image_width, + image_height, + image_row_pitch, + host_ptr, + &error); + #endif + + if(!m_mem){ + BOOST_THROW_EXCEPTION(opencl_error(error)); + } + } + + /// Creates a new image2d as a copy of \p other. + image2d(const image2d &other) + : image_object(other) + { + } + + /// Copies the image2d from \p other. + image2d& operator=(const image2d &other) + { + image_object::operator=(other); + + return *this; + } + + #ifndef BOOST_COMPUTE_NO_RVALUE_REFERENCES + /// Move-constructs a new image object from \p other. + image2d(image2d&& other) BOOST_NOEXCEPT + : image_object(std::move(other)) + { + } + + /// Move-assigns the image from \p other to \c *this. + image2d& operator=(image2d&& other) BOOST_NOEXCEPT + { + image_object::operator=(std::move(other)); + + return *this; + } + #endif // BOOST_COMPUTE_NO_RVALUE_REFERENCES + + /// Destroys the image2d object. + ~image2d() + { + } + + /// Returns the size (width, height) of the image. + extents<2> size() const + { + extents<2> size; + size[0] = get_info(CL_IMAGE_WIDTH); + size[1] = get_info(CL_IMAGE_HEIGHT); + return size; + } + + /// Returns the origin of the image (\c 0, \c 0). + extents<2> origin() const + { + return extents<2>(); + } + + /// Returns information about the image. + /// + /// \see_opencl_ref{clGetImageInfo} + template + T get_info(cl_image_info info) const + { + return detail::get_object_info(clGetImageInfo, m_mem, info); + } + + /// \overload + template + typename detail::get_object_info_type::type + get_info() const; + + /// Returns the supported image formats for the context. + /// + /// \see_opencl_ref{clGetSupportedImageFormats} + static std::vector + get_supported_formats(const context &context, cl_mem_flags flags = read_write) + { + return image_object::get_supported_formats(context, CL_MEM_OBJECT_IMAGE2D, flags); + } + + /// Returns \c true if \p format is a supported 2D image format for + /// \p context. + static bool is_supported_format(const image_format &format, + const context &context, + cl_mem_flags flags = read_write) + { + return image_object::is_supported_format( + format, context, CL_MEM_OBJECT_IMAGE2D, flags + ); + } + + /// Creates a new image with a copy of the data in \c *this. Uses \p queue + /// to perform the copy operation. + image2d clone(command_queue &queue) const; +}; + +/// \internal_ define get_info() specializations for image2d +BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(image2d, + ((cl_image_format, CL_IMAGE_FORMAT)) + ((size_t, CL_IMAGE_ELEMENT_SIZE)) + ((size_t, CL_IMAGE_ROW_PITCH)) + ((size_t, CL_IMAGE_SLICE_PITCH)) + ((size_t, CL_IMAGE_WIDTH)) + ((size_t, CL_IMAGE_HEIGHT)) + ((size_t, CL_IMAGE_DEPTH)) +) + +namespace detail { + +// set_kernel_arg() specialization for image2d +template<> +struct set_kernel_arg : public set_kernel_arg { }; + +} // end detail namespace +} // end compute namespace +} // end boost namespace + +BOOST_COMPUTE_TYPE_NAME(boost::compute::image2d, image2d_t) + +#endif // BOOST_COMPUTE_IMAGE_IMAGE2D_HPP diff --git a/include/boost/compute/image/image3d.hpp b/include/boost/compute/image/image3d.hpp new file mode 100644 index 00000000..ee3768ac --- /dev/null +++ b/include/boost/compute/image/image3d.hpp @@ -0,0 +1,262 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2013-2015 Kyle Lutz +// +// Distributed under the Boost Software License, Version 1.0 +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// +// See http://kylelutz.github.com/compute for more information. +//---------------------------------------------------------------------------// + +#ifndef BOOST_COMPUTE_IMAGE_IMAGE3D_HPP +#define BOOST_COMPUTE_IMAGE_IMAGE3D_HPP + +#include + +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace compute { + +/// \class image3d +/// \brief An OpenCL 3D image object +/// +/// \see image_format, image2d +class image3d : public image_object +{ +public: + /// Creates a null image3d object. + image3d() + : image_object() + { + } + + /// Creates a new image3d object. + /// + /// \see_opencl_ref{clCreateImage} + image3d(const context &context, + size_t image_width, + size_t image_height, + size_t image_depth, + const image_format &format, + cl_mem_flags flags = read_write, + void *host_ptr = 0, + size_t image_row_pitch = 0, + size_t image_slice_pitch = 0) + { + cl_int error = 0; + + #ifdef CL_VERSION_1_2 + cl_image_desc desc; + desc.image_type = CL_MEM_OBJECT_IMAGE3D; + desc.image_width = image_width; + desc.image_height = image_height; + desc.image_depth = image_depth; + desc.image_array_size = 0; + desc.image_row_pitch = image_row_pitch; + desc.image_slice_pitch = image_slice_pitch; + desc.num_mip_levels = 0; + desc.num_samples = 0; + #ifdef CL_VERSION_2_0 + desc.mem_object = 0; + #else + desc.buffer = 0; + #endif + + m_mem = clCreateImage(context, + flags, + format.get_format_ptr(), + &desc, + host_ptr, + &error); + #else + m_mem = clCreateImage3D(context, + flags, + format.get_format_ptr(), + image_width, + image_height, + image_depth, + image_row_pitch, + image_slice_pitch, + host_ptr, + &error); + #endif + + if(!m_mem){ + BOOST_THROW_EXCEPTION(opencl_error(error)); + } + } + + /// \internal_ (deprecated) + image3d(const context &context, + cl_mem_flags flags, + const image_format &format, + size_t image_width, + size_t image_height, + size_t image_depth, + size_t image_row_pitch, + size_t image_slice_pitch = 0, + void *host_ptr = 0) + { + cl_int error = 0; + + #ifdef CL_VERSION_1_2 + cl_image_desc desc; + desc.image_type = CL_MEM_OBJECT_IMAGE3D; + desc.image_width = image_width; + desc.image_height = image_height; + desc.image_depth = image_depth; + desc.image_array_size = 0; + desc.image_row_pitch = image_row_pitch; + desc.image_slice_pitch = image_slice_pitch; + desc.num_mip_levels = 0; + desc.num_samples = 0; + #ifdef CL_VERSION_2_0 + desc.mem_object = 0; + #else + desc.buffer = 0; + #endif + + m_mem = clCreateImage(context, + flags, + format.get_format_ptr(), + &desc, + host_ptr, + &error); + #else + m_mem = clCreateImage3D(context, + flags, + format.get_format_ptr(), + image_width, + image_height, + image_depth, + image_row_pitch, + image_slice_pitch, + host_ptr, + &error); + #endif + + if(!m_mem){ + BOOST_THROW_EXCEPTION(opencl_error(error)); + } + } + + /// Creates a new image3d as a copy of \p other. + image3d(const image3d &other) + : image_object(other) + { + } + + /// Copies the image3d from \p other. + image3d& operator=(const image3d &other) + { + image_object::operator=(other); + + return *this; + } + + #ifndef BOOST_COMPUTE_NO_RVALUE_REFERENCES + /// Move-constructs a new image object from \p other. + image3d(image3d&& other) BOOST_NOEXCEPT + : image_object(std::move(other)) + { + } + + /// Move-assigns the image from \p other to \c *this. + image3d& operator=(image3d&& other) BOOST_NOEXCEPT + { + image_object::operator=(std::move(other)); + + return *this; + } + #endif // BOOST_COMPUTE_NO_RVALUE_REFERENCES + + /// Destroys the image3d object. + ~image3d() + { + } + + /// Returns the size (width, height, depth) of the image. + extents<3> size() const + { + extents<3> size; + size[0] = get_info(CL_IMAGE_WIDTH); + size[1] = get_info(CL_IMAGE_HEIGHT); + size[2] = get_info(CL_IMAGE_DEPTH); + return size; + } + + /// Returns the origin of the image (\c 0, \c 0, \c 0). + extents<3> origin() const + { + return extents<3>(); + } + + /// Returns information about the image. + /// + /// \see_opencl_ref{clGetImageInfo} + template + T get_info(cl_image_info info) const + { + return detail::get_object_info(clGetImageInfo, m_mem, info); + } + + /// \overload + template + typename detail::get_object_info_type::type + get_info() const; + + /// Returns the supported 3D image formats for the context. + /// + /// \see_opencl_ref{clGetSupportedImageFormats} + static std::vector + get_supported_formats(const context &context, cl_mem_flags flags = read_write) + { + return image_object::get_supported_formats(context, CL_MEM_OBJECT_IMAGE3D, flags); + } + + /// Returns \c true if \p format is a supported 3D image format for + /// \p context. + static bool is_supported_format(const image_format &format, + const context &context, + cl_mem_flags flags = read_write) + { + return image_object::is_supported_format( + format, context, CL_MEM_OBJECT_IMAGE3D, flags + ); + } + + /// Creates a new image with a copy of the data in \c *this. Uses \p queue + /// to perform the copy operation. + image3d clone(command_queue &queue) const; +}; + +/// \internal_ define get_info() specializations for image3d +BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(image3d, + ((cl_image_format, CL_IMAGE_FORMAT)) + ((size_t, CL_IMAGE_ELEMENT_SIZE)) + ((size_t, CL_IMAGE_ROW_PITCH)) + ((size_t, CL_IMAGE_SLICE_PITCH)) + ((size_t, CL_IMAGE_WIDTH)) + ((size_t, CL_IMAGE_HEIGHT)) + ((size_t, CL_IMAGE_DEPTH)) +) + +namespace detail { + +// set_kernel_arg() specialization for image3d +template<> +struct set_kernel_arg : public set_kernel_arg { }; + +} // end detail namespace +} // end compute namespace +} // end boost namespace + +BOOST_COMPUTE_TYPE_NAME(boost::compute::image3d, image3d_t) + +#endif // BOOST_COMPUTE_IMAGE_IMAGE3D_HPP diff --git a/include/boost/compute/image/image_format.hpp b/include/boost/compute/image/image_format.hpp new file mode 100644 index 00000000..bd7ab0ad --- /dev/null +++ b/include/boost/compute/image/image_format.hpp @@ -0,0 +1,135 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2013-2015 Kyle Lutz +// +// Distributed under the Boost Software License, Version 1.0 +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// +// See http://kylelutz.github.com/compute for more information. +//---------------------------------------------------------------------------// + +#ifndef BOOST_COMPUTE_IMAGE_IMAGE_FORMAT_HPP +#define BOOST_COMPUTE_IMAGE_IMAGE_FORMAT_HPP + +#include + +namespace boost { +namespace compute { + +/// \class image_format +/// \brief A OpenCL image format +/// +/// For example, to create a format for a 8-bit RGBA image: +/// \code +/// boost::compute::image_format rgba8(CL_RGBA, CL_UNSIGNED_INT8); +/// \endcode +/// +/// After being constructed, image_format objects are usually passed to the +/// constructor of the various image classes (e.g. \ref image2d, \ref image3d) +/// to create an image object on a compute device. +/// +/// Image formats supported by a context can be queried with the static +/// get_supported_formats() in each image class. For example: +/// \code +/// std::vector formats = image2d::get_supported_formats(ctx); +/// \endcode +/// +/// \see image2d +class image_format +{ +public: + enum channel_order { + r = CL_R, + a = CL_A, + intensity = CL_INTENSITY, + luminance = CL_LUMINANCE, + rg = CL_RG, + ra = CL_RA, + rgb = CL_RGB, + rgba = CL_RGBA, + argb = CL_ARGB, + bgra = CL_BGRA + }; + + enum channel_data_type { + snorm_int8 = CL_SNORM_INT8, + snorm_int16 = CL_SNORM_INT16, + unorm_int8 = CL_UNORM_INT8, + unorm_int16 = CL_UNORM_INT16, + unorm_short_565 = CL_UNORM_SHORT_565, + unorm_short_555 = CL_UNORM_SHORT_555, + unorm_int_101010 = CL_UNORM_INT_101010, + signed_int8 = CL_SIGNED_INT8, + signed_int16 = CL_SIGNED_INT16, + signed_int32 = CL_SIGNED_INT32, + unsigned_int8 = CL_UNSIGNED_INT8, + unsigned_int16 = CL_UNSIGNED_INT16, + unsigned_int32 = CL_UNSIGNED_INT32, + float16 = CL_HALF_FLOAT, + float32 = CL_FLOAT + }; + + /// Creates a new image format object with \p order and \p type. + explicit image_format(cl_channel_order order, cl_channel_type type) + { + m_format.image_channel_order = order; + m_format.image_channel_data_type = type; + } + + /// Creates a new image format object from \p format. + explicit image_format(const cl_image_format &format) + { + m_format.image_channel_order = format.image_channel_order; + m_format.image_channel_data_type = format.image_channel_data_type; + } + + /// Creates a new image format object as a copy of \p other. + image_format(const image_format &other) + : m_format(other.m_format) + { + } + + /// Copies the format from \p other to \c *this. + image_format& operator=(const image_format &other) + { + if(this != &other){ + m_format = other.m_format; + } + + return *this; + } + + /// Destroys the image format object. + ~image_format() + { + } + + /// Returns a pointer to the \c cl_image_format object. + const cl_image_format* get_format_ptr() const + { + return &m_format; + } + + /// Returns \c true if \c *this is the same as \p other. + bool operator==(const image_format &other) const + { + return m_format.image_channel_order == + other.m_format.image_channel_order && + m_format.image_channel_data_type == + other.m_format.image_channel_data_type; + } + + /// Returns \c true if \c *this is not the same as \p other. + bool operator!=(const image_format &other) const + { + return !(*this == other); + } + +private: + cl_image_format m_format; +}; + +} // end compute namespace +} // end boost namespace + +#endif // BOOST_COMPUTE_IMAGE_IMAGE_FORMAT_HPP diff --git a/include/boost/compute/image/image_object.hpp b/include/boost/compute/image/image_object.hpp new file mode 100644 index 00000000..96fac536 --- /dev/null +++ b/include/boost/compute/image/image_object.hpp @@ -0,0 +1,170 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2013-2015 Kyle Lutz +// +// Distributed under the Boost Software License, Version 1.0 +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// +// See http://kylelutz.github.com/compute for more information. +//---------------------------------------------------------------------------// + +#ifndef BOOST_COMPUTE_IMAGE_IMAGE_OBJECT_HPP +#define BOOST_COMPUTE_IMAGE_IMAGE_OBJECT_HPP + +#include +#include + +#include +#include +#include +#include + +namespace boost { +namespace compute { + +/// \class image_object +/// \brief Base-class for image objects. +/// +/// The image_object class is the base-class for image objects on compute +/// devices. +/// +/// \see image1d, image2d, image3d +class image_object : public memory_object +{ +public: + image_object() + : memory_object() + { + } + + explicit image_object(cl_mem mem, bool retain = true) + : memory_object(mem, retain) + { + } + + image_object(const image_object &other) + : memory_object(other) + { + } + + image_object& operator=(const image_object &other) + { + if(this != &other){ + memory_object::operator=(other); + } + + return *this; + } + + #ifndef BOOST_COMPUTE_NO_RVALUE_REFERENCES + image_object(image_object&& other) BOOST_NOEXCEPT + : memory_object(std::move(other)) + { + } + + /// \internal_ + image_object& operator=(image_object&& other) BOOST_NOEXCEPT + { + memory_object::operator=(std::move(other)); + + return *this; + } + #endif // BOOST_COMPUTE_NO_RVALUE_REFERENCES + + /// Destroys the image object. + ~image_object() + { + } + + /// Returns information about the image object. + /// + /// \see_opencl_ref{clGetImageInfo} + template + T get_image_info(cl_mem_info info) const + { + return detail::get_object_info(clGetImageInfo, m_mem, info); + } + + /// Returns the format for the image. + image_format format() const + { + return image_format(get_image_info(CL_IMAGE_FORMAT)); + } + + /// \internal_ (deprecated) + image_format get_format() const + { + return format(); + } + + /// Returns the width of the image. + size_t width() const + { + return get_image_info(CL_IMAGE_WIDTH); + } + + /// Returns the height of the image. + /// + /// For 1D images, this function will return \c 1. + size_t height() const + { + return get_image_info(CL_IMAGE_HEIGHT); + } + + /// Returns the depth of the image. + /// + /// For 1D and 2D images, this function will return \c 1. + size_t depth() const + { + return get_image_info(CL_IMAGE_DEPTH); + } + + /// Returns the supported image formats for the \p type in \p context. + /// + /// \see_opencl_ref{clGetSupportedImageFormats} + static std::vector + get_supported_formats(const context &context, + cl_mem_object_type type, + cl_mem_flags flags = read_write) + { + cl_uint count = 0; + clGetSupportedImageFormats(context, flags, type, 0, 0, &count); + + std::vector cl_formats(count); + clGetSupportedImageFormats(context, flags, type, count, &cl_formats[0], 0); + + std::vector formats; + formats.reserve(count); + + for(cl_uint i = 0; i < count; i++){ + formats.push_back(image_format(cl_formats[i])); + } + + return formats; + } + + /// Returns \c true if \p format is a supported image format for + /// \p type in \p context with \p flags. + static bool is_supported_format(const image_format &format, + const context &context, + cl_mem_object_type type, + cl_mem_flags flags = read_write) + { + const std::vector formats = + get_supported_formats(context, type, flags); + + return std::find(formats.begin(), formats.end(), format) != formats.end(); + } +}; + +namespace detail { + +// set_kernel_arg() specialization for image_object +template<> +struct set_kernel_arg : public set_kernel_arg { }; + +} // end detail namespace +} // end compute namespace +} // end boost namespace + +#endif // BOOST_COMPUTE_IMAGE_IMAGE_OBJECT_HPP diff --git a/include/boost/compute/image/image_sampler.hpp b/include/boost/compute/image/image_sampler.hpp new file mode 100644 index 00000000..7fdcbade --- /dev/null +++ b/include/boost/compute/image/image_sampler.hpp @@ -0,0 +1,221 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2013-2015 Kyle Lutz +// +// Distributed under the Boost Software License, Version 1.0 +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// +// See http://kylelutz.github.com/compute for more information. +//---------------------------------------------------------------------------// + +#ifndef BOOST_COMPUTE_IMAGE_IMAGE_SAMPLER_HPP +#define BOOST_COMPUTE_IMAGE_IMAGE_SAMPLER_HPP + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace compute { + +/// \class image_sampler +/// \brief An OpenCL image sampler object +/// +/// \see image2d, image_format +class image_sampler +{ +public: + enum addressing_mode { + none = CL_ADDRESS_NONE, + clamp_to_edge = CL_ADDRESS_CLAMP_TO_EDGE, + clamp = CL_ADDRESS_CLAMP, + repeat = CL_ADDRESS_REPEAT + }; + + enum filter_mode { + nearest = CL_FILTER_NEAREST, + linear = CL_FILTER_LINEAR + }; + + image_sampler() + : m_sampler(0) + { + } + + image_sampler(const context &context, + bool normalized_coords, + cl_addressing_mode addressing_mode, + cl_filter_mode filter_mode) + { + cl_int error = 0; + + #ifdef CL_VERSION_2_0 + std::vector sampler_properties; + sampler_properties.push_back(CL_SAMPLER_NORMALIZED_COORDS); + sampler_properties.push_back(cl_sampler_properties(normalized_coords)); + sampler_properties.push_back(CL_SAMPLER_ADDRESSING_MODE); + sampler_properties.push_back(cl_sampler_properties(addressing_mode)); + sampler_properties.push_back(CL_SAMPLER_FILTER_MODE); + sampler_properties.push_back(cl_sampler_properties(filter_mode)); + sampler_properties.push_back(cl_sampler_properties(0)); + + m_sampler = clCreateSamplerWithProperties( + context, &sampler_properties[0], &error + ); + #else + m_sampler = clCreateSampler( + context, normalized_coords, addressing_mode, filter_mode, &error + ); + #endif + + if(!m_sampler){ + BOOST_THROW_EXCEPTION(opencl_error(error)); + } + } + + explicit image_sampler(cl_sampler sampler, bool retain = true) + : m_sampler(sampler) + { + if(m_sampler && retain){ + clRetainSampler(m_sampler); + } + } + + /// Creates a new image sampler object as a copy of \p other. + image_sampler(const image_sampler &other) + : m_sampler(other.m_sampler) + { + if(m_sampler){ + clRetainSampler(m_sampler); + } + } + + /// Copies the image sampler object from \p other to \c *this. + image_sampler& operator=(const image_sampler &other) + { + if(this != &other){ + if(m_sampler){ + clReleaseSampler(m_sampler); + } + + m_sampler = other.m_sampler; + + if(m_sampler){ + clRetainSampler(m_sampler); + } + } + + return *this; + } + + #ifndef BOOST_COMPUTE_NO_RVALUE_REFERENCES + image_sampler(image_sampler&& other) BOOST_NOEXCEPT + : m_sampler(other.m_sampler) + { + other.m_sampler = 0; + } + + image_sampler& operator=(image_sampler&& other) BOOST_NOEXCEPT + { + if(m_sampler){ + clReleaseSampler(m_sampler); + } + + m_sampler = other.m_sampler; + other.m_sampler = 0; + + return *this; + } + #endif // BOOST_COMPUTE_NO_RVALUE_REFERENCES + + /// Destroys the image sampler object. + ~image_sampler() + { + if(m_sampler){ + BOOST_COMPUTE_ASSERT_CL_SUCCESS( + clReleaseSampler(m_sampler) + ); + } + } + + /// Returns the underlying \c cl_sampler object. + cl_sampler& get() const + { + return const_cast(m_sampler); + } + + /// Returns the context for the image sampler object. + context get_context() const + { + return context(get_info(CL_SAMPLER_CONTEXT)); + } + + /// Returns information about the sampler. + /// + /// \see_opencl_ref{clGetSamplerInfo} + template + T get_info(cl_sampler_info info) const + { + return detail::get_object_info(clGetSamplerInfo, m_sampler, info); + } + + /// \overload + template + typename detail::get_object_info_type::type + get_info() const; + + /// Returns \c true if the sampler is the same at \p other. + bool operator==(const image_sampler &other) const + { + return m_sampler == other.m_sampler; + } + + /// Returns \c true if the sampler is different from \p other. + bool operator!=(const image_sampler &other) const + { + return m_sampler != other.m_sampler; + } + + operator cl_sampler() const + { + return m_sampler; + } + +private: + cl_sampler m_sampler; +}; + +/// \internal_ define get_info() specializations for image_sampler +BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(image_sampler, + ((cl_uint, CL_SAMPLER_REFERENCE_COUNT)) + ((cl_context, CL_SAMPLER_CONTEXT)) + ((cl_addressing_mode, CL_SAMPLER_ADDRESSING_MODE)) + ((cl_filter_mode, CL_SAMPLER_FILTER_MODE)) + ((bool, CL_SAMPLER_NORMALIZED_COORDS)) +) + +namespace detail { + +// set_kernel_arg specialization for image samplers +template<> +struct set_kernel_arg +{ + void operator()(kernel &kernel_, size_t index, const image_sampler &sampler) + { + kernel_.set_arg(index, sampler.get()); + } +}; + +} // end detail namespace +} // end compute namespace +} // end boost namespace + +BOOST_COMPUTE_TYPE_NAME(boost::compute::image_sampler, sampler_t) + +#endif // BOOST_COMPUTE_IMAGE_IMAGE_SAMPLER_HPP diff --git a/include/boost/compute/image2d.hpp b/include/boost/compute/image2d.hpp index 896f1fbb..ed889090 100644 --- a/include/boost/compute/image2d.hpp +++ b/include/boost/compute/image2d.hpp @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------// -// Copyright (c) 2013 Kyle Lutz +// Copyright (c) 2013-2015 Kyle Lutz // // Distributed under the Boost Software License, Version 1.0 // See accompanying file LICENSE_1_0.txt or copy at @@ -8,216 +8,5 @@ // See http://kylelutz.github.com/compute for more information. //---------------------------------------------------------------------------// -#ifndef BOOST_COMPUTE_IMAGE2D_HPP -#define BOOST_COMPUTE_IMAGE2D_HPP - -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace compute { - -// forward declarations -class command_queue; - -class image2d : public memory_object -{ -public: - /// Creates a null image2d object. - image2d() - : memory_object() - { - } - - /// Creates a new image2d object. - /// - /// \see_opencl_ref{clCreateImage} - image2d(const context &context, - cl_mem_flags flags, - const image_format &format, - size_t image_width, - size_t image_height, - size_t image_row_pitch = 0, - void *host_ptr = 0) - { - cl_int error = 0; - - #ifdef CL_VERSION_1_2 - cl_image_desc desc; - desc.image_type = CL_MEM_OBJECT_IMAGE2D; - desc.image_width = image_width; - desc.image_height = image_height; - desc.image_depth = 1; - desc.image_array_size = 0; - desc.image_row_pitch = image_row_pitch; - desc.image_slice_pitch = 0; - desc.num_mip_levels = 0; - desc.num_samples = 0; - #ifdef CL_VERSION_2_0 - desc.mem_object = 0; - #else - desc.buffer = 0; - #endif - - m_mem = clCreateImage(context, - flags, - format.get_format_ptr(), - &desc, - host_ptr, - &error); - #else - m_mem = clCreateImage2D(context, - flags, - format.get_format_ptr(), - image_width, - image_height, - image_row_pitch, - host_ptr, - &error); - #endif - - if(!m_mem){ - BOOST_THROW_EXCEPTION(opencl_error(error)); - } - } - - /// Creates a new image2d as a copy of \p other. - image2d(const image2d &other) - : memory_object(other) - { - } - - /// Copies the image2d from \p other. - image2d& operator=(const image2d &other) - { - memory_object::operator=(other); - - return *this; - } - - #ifndef BOOST_COMPUTE_NO_RVALUE_REFERENCES - /// Move-constructs a new image object from \p other. - image2d(image2d&& other) BOOST_NOEXCEPT - : memory_object(std::move(other)) - { - } - - /// Move-assigns the image from \p other to \c *this. - image2d& operator=(image2d&& other) BOOST_NOEXCEPT - { - memory_object::operator=(std::move(other)); - - return *this; - } - #endif // BOOST_COMPUTE_NO_RVALUE_REFERENCES - - /// Destroys the image2d object. - ~image2d() - { - } - - /// Returns the format for the image. - image_format get_format() const - { - return image_format(get_info(CL_IMAGE_FORMAT)); - } - - /// Returns the height of the image. - size_t height() const - { - return get_info(CL_IMAGE_HEIGHT); - } - - /// Returns the width of the image. - size_t width() const - { - return get_info(CL_IMAGE_WIDTH); - } - - /// Returns the size (width, height) of the image. - extents<2> size() const - { - extents<2> size; - size[0] = get_info(CL_IMAGE_WIDTH); - size[1] = get_info(CL_IMAGE_HEIGHT); - return size; - } - - /// Returns information about the image. - /// - /// \see_opencl_ref{clGetImageInfo} - template - T get_info(cl_image_info info) const - { - return detail::get_object_info(clGetImageInfo, m_mem, info); - } - - size_t get_pixel_count() const - { - return height() * width(); - } - - /// Returns the supported image formats for the context. - /// - /// \see_opencl_ref{clGetSupportedImageFormats} - static std::vector get_supported_formats(const context &context, - cl_mem_flags flags) - { - cl_uint count = 0; - clGetSupportedImageFormats(context, - flags, - CL_MEM_OBJECT_IMAGE2D, - 0, - 0, - &count); - - std::vector cl_formats(count); - clGetSupportedImageFormats(context, - flags, - CL_MEM_OBJECT_IMAGE2D, - count, - &cl_formats[0], - 0); - - std::vector formats; - for(size_t i = 0; i < count; i++){ - formats.push_back(image_format(cl_formats[i])); - } - - return formats; - } - - /// Creates a new image with a copy of the data in \c *this. Uses \p queue - /// to perform the copy operation. - image2d clone(command_queue &queue) const; -}; - -namespace detail { - -// set_kernel_arg specialization for image2d -template<> -struct set_kernel_arg -{ - void operator()(kernel &kernel_, size_t index, const image2d &image) - { - kernel_.set_arg(index, image.get()); - } -}; - -} // end detail namespace -} // end compute namespace -} // end boost namespace - -BOOST_COMPUTE_TYPE_NAME(boost::compute::image2d, image2d_t) - -#endif // BOOST_COMPUTE_IMAGE2D_HPP +// deprecated, use instead +#include diff --git a/include/boost/compute/image3d.hpp b/include/boost/compute/image3d.hpp index 052787c0..4b35bcb3 100644 --- a/include/boost/compute/image3d.hpp +++ b/include/boost/compute/image3d.hpp @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------// -// Copyright (c) 2013 Kyle Lutz +// Copyright (c) 2013-2015 Kyle Lutz // // Distributed under the Boost Software License, Version 1.0 // See accompanying file LICENSE_1_0.txt or copy at @@ -8,206 +8,5 @@ // See http://kylelutz.github.com/compute for more information. //---------------------------------------------------------------------------// -#ifndef BOOST_COMPUTE_IMAGE3D_HPP -#define BOOST_COMPUTE_IMAGE3D_HPP - -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace compute { - -class image3d : public memory_object -{ -public: - /// Creates a null image3d object. - image3d() - : memory_object() - { - } - - /// Creates a new image3d object. - /// - /// \see_opencl_ref{clCreateImage} - image3d(const context &context, - cl_mem_flags flags, - const image_format &format, - size_t image_width, - size_t image_height, - size_t image_depth, - size_t image_row_pitch, - size_t image_slice_pitch = 0, - void *host_ptr = 0) - { - cl_int error = 0; - - #ifdef CL_VERSION_1_2 - cl_image_desc desc; - desc.image_type = CL_MEM_OBJECT_IMAGE3D; - desc.image_width = image_width; - desc.image_height = image_height; - desc.image_depth = image_depth; - desc.image_array_size = 0; - desc.image_row_pitch = image_row_pitch; - desc.image_slice_pitch = image_slice_pitch; - desc.num_mip_levels = 0; - desc.num_samples = 0; - #ifdef CL_VERSION_2_0 - desc.mem_object = 0; - #else - desc.buffer = 0; - #endif - - m_mem = clCreateImage(context, - flags, - format.get_format_ptr(), - &desc, - host_ptr, - &error); - #else - m_mem = clCreateImage3D(context, - flags, - format.get_format_ptr(), - image_width, - image_height, - image_depth, - image_row_pitch, - image_slice_pitch, - host_ptr, - &error); - #endif - - if(!m_mem){ - BOOST_THROW_EXCEPTION(opencl_error(error)); - } - } - - /// Creates a new image3d as a copy of \p other. - image3d(const image3d &other) - : memory_object(other) - { - } - - /// Copies the image3d from \p other. - image3d& operator=(const image3d &other) - { - memory_object::operator=(other); - - return *this; - } - - #ifndef BOOST_COMPUTE_NO_RVALUE_REFERENCES - /// Move-constructs a new image object from \p other. - image3d(image3d&& other) BOOST_NOEXCEPT - : memory_object(std::move(other)) - { - } - - /// Move-assigns the image from \p other to \c *this. - image3d& operator=(image3d&& other) BOOST_NOEXCEPT - { - memory_object::operator=(std::move(other)); - - return *this; - } - #endif // BOOST_COMPUTE_NO_RVALUE_REFERENCES - - /// Destroys the image3d object. - ~image3d() - { - } - - /// Returns the format for the image. - image_format get_format() const - { - return image_format(get_info(CL_IMAGE_FORMAT)); - } - - /// Returns information about the image. - /// - /// \see_opencl_ref{clGetImageInfo} - template - T get_info(cl_image_info info) const - { - return detail::get_object_info(clGetImageInfo, m_mem, info); - } - - /// Returns the size (width, height, depth) of the image. - extents<3> size() const - { - extents<3> size; - size[0] = get_info(CL_IMAGE_WIDTH); - size[1] = get_info(CL_IMAGE_HEIGHT); - size[2] = get_info(CL_IMAGE_DEPTH); - return size; - } - - size_t get_pixel_count() const - { - size_t height = get_info(CL_IMAGE_HEIGHT); - size_t width = get_info(CL_IMAGE_WIDTH); - size_t depth = get_info(CL_IMAGE_DEPTH); - - return height * width * depth; - } - - /// Returns the supported image formats for the context. - /// - /// \see_opencl_ref{clGetSupportedImageFormats} - static std::vector get_supported_formats(const context &context, - cl_mem_flags flags) - { - cl_uint count = 0; - clGetSupportedImageFormats(context, - flags, - CL_MEM_OBJECT_IMAGE3D, - 0, - 0, - &count); - - std::vector cl_formats(count); - clGetSupportedImageFormats(context, - flags, - CL_MEM_OBJECT_IMAGE3D, - count, - &cl_formats[0], - 0); - - std::vector formats; - for(size_t i = 0; i < count; i++){ - formats.push_back(image_format(cl_formats[i])); - } - - return formats; - } -}; - -namespace detail { - -// set_kernel_arg specialization for image3d -template<> -struct set_kernel_arg -{ - void operator()(kernel &kernel_, size_t index, const image3d &image) - { - kernel_.set_arg(index, image.get()); - } -}; - -} // end detail namespace -} // end compute namespace -} // end boost namespace - -BOOST_COMPUTE_TYPE_NAME(boost::compute::image3d, image3d_t) - -#endif // BOOST_COMPUTE_IMAGE3D_HPP +// deprecated, use instead +#include diff --git a/include/boost/compute/image_format.hpp b/include/boost/compute/image_format.hpp index 60584441..755f3d06 100644 --- a/include/boost/compute/image_format.hpp +++ b/include/boost/compute/image_format.hpp @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------// -// Copyright (c) 2013 Kyle Lutz +// Copyright (c) 2013-2015 Kyle Lutz // // Distributed under the Boost Software License, Version 1.0 // See accompanying file LICENSE_1_0.txt or copy at @@ -8,105 +8,5 @@ // See http://kylelutz.github.com/compute for more information. //---------------------------------------------------------------------------// -#ifndef BOOST_COMPUTE_IMAGE_FORMAT_HPP -#define BOOST_COMPUTE_IMAGE_FORMAT_HPP - -#include - -namespace boost { -namespace compute { - -class image_format -{ -public: - enum channel_order { - r = CL_R, - a = CL_A, - intensity = CL_INTENSITY, - luminance = CL_LUMINANCE, - rg = CL_RG, - ra = CL_RA, - rgb = CL_RGB, - rgba = CL_RGBA, - argb = CL_ARGB, - bgra = CL_BGRA - }; - - enum channel_data_type { - snorm_int8 = CL_SNORM_INT8, - snorm_int16 = CL_SNORM_INT16, - unorm_int8 = CL_UNORM_INT8, - unorm_int16 = CL_UNORM_INT16, - unorm_short_565 = CL_UNORM_SHORT_565, - unorm_short_555 = CL_UNORM_SHORT_555, - unorm_int_101010 = CL_UNORM_INT_101010, - signed_int8 = CL_SIGNED_INT8, - signed_int16 = CL_SIGNED_INT16, - signed_int32 = CL_SIGNED_INT32, - unsigned_int8 = CL_UNSIGNED_INT8, - unsigned_int16 = CL_UNSIGNED_INT16, - unsigned_int32 = CL_UNSIGNED_INT32, - float16 = CL_HALF_FLOAT, - float32 = CL_FLOAT - }; - - image_format() - { - } - - image_format(cl_channel_order order, cl_channel_type type) - { - m_format.image_channel_order = order; - m_format.image_channel_data_type = type; - } - - explicit image_format(const cl_image_format &format) - { - m_format.image_channel_order = format.image_channel_order; - m_format.image_channel_data_type = format.image_channel_data_type; - } - - image_format(const image_format &other) - : m_format(other.m_format) - { - } - - image_format& operator=(const image_format &other) - { - if(this != &other){ - m_format = other.m_format; - } - - return *this; - } - - ~image_format() - { - } - - const cl_image_format* get_format_ptr() const - { - return &m_format; - } - - bool operator==(const image_format &other) const - { - return m_format.image_channel_order == - other.m_format.image_channel_order && - m_format.image_channel_data_type == - other.m_format.image_channel_data_type; - } - - bool operator!=(const image_format &other) const - { - return !(*this == other); - } - -private: - cl_image_format m_format; -}; - -} // end compute namespace -} // end boost namespace - -#endif // BOOST_COMPUTE_IMAGE_FORMAT_HPP +// deprecated, use instead +#include diff --git a/include/boost/compute/image_sampler.hpp b/include/boost/compute/image_sampler.hpp index a464b983..200ebaa5 100644 --- a/include/boost/compute/image_sampler.hpp +++ b/include/boost/compute/image_sampler.hpp @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------// -// Copyright (c) 2013 Kyle Lutz +// Copyright (c) 2013-2015 Kyle Lutz // // Distributed under the Boost Software License, Version 1.0 // See accompanying file LICENSE_1_0.txt or copy at @@ -8,202 +8,5 @@ // See http://kylelutz.github.com/compute for more information. //---------------------------------------------------------------------------// -#ifndef BOOST_COMPUTE_IMAGE_SAMPLER_HPP -#define BOOST_COMPUTE_IMAGE_SAMPLER_HPP - -#include - -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace compute { - -class image_sampler -{ -public: - enum addressing_mode { - none = CL_ADDRESS_NONE, - clamp_to_edge = CL_ADDRESS_CLAMP_TO_EDGE, - clamp = CL_ADDRESS_CLAMP, - repeat = CL_ADDRESS_REPEAT - }; - - enum filter_mode { - nearest = CL_FILTER_NEAREST, - linear = CL_FILTER_LINEAR - }; - - image_sampler() - : m_sampler(0) - { - } - - image_sampler(const context &context, - bool normalized_coords, - cl_addressing_mode addressing_mode, - cl_filter_mode filter_mode) - { - cl_int error = 0; - - #ifdef CL_VERSION_2_0 - std::vector sampler_properties; - sampler_properties.push_back(CL_SAMPLER_NORMALIZED_COORDS); - sampler_properties.push_back(cl_sampler_properties(normalized_coords)); - sampler_properties.push_back(CL_SAMPLER_ADDRESSING_MODE); - sampler_properties.push_back(cl_sampler_properties(addressing_mode)); - sampler_properties.push_back(CL_SAMPLER_FILTER_MODE); - sampler_properties.push_back(cl_sampler_properties(filter_mode)); - sampler_properties.push_back(cl_sampler_properties(0)); - - m_sampler = clCreateSamplerWithProperties( - context, &sampler_properties[0], &error - ); - #else - m_sampler = clCreateSampler( - context, normalized_coords, addressing_mode, filter_mode, &error - ); - #endif - - if(!m_sampler){ - BOOST_THROW_EXCEPTION(opencl_error(error)); - } - } - - explicit image_sampler(cl_sampler sampler, bool retain = true) - : m_sampler(sampler) - { - if(m_sampler && retain){ - clRetainSampler(m_sampler); - } - } - - image_sampler(const image_sampler &other) - : m_sampler(other.m_sampler) - { - if(m_sampler){ - clRetainSampler(m_sampler); - } - } - - image_sampler& operator=(const image_sampler &other) - { - if(this != &other){ - if(m_sampler){ - clReleaseSampler(m_sampler); - } - - m_sampler = other.m_sampler; - - if(m_sampler){ - clRetainSampler(m_sampler); - } - } - - return *this; - } - - #ifndef BOOST_COMPUTE_NO_RVALUE_REFERENCES - image_sampler(image_sampler&& other) BOOST_NOEXCEPT - : m_sampler(other.m_sampler) - { - other.m_sampler = 0; - } - - image_sampler& operator=(image_sampler&& other) BOOST_NOEXCEPT - { - if(m_sampler){ - clReleaseSampler(m_sampler); - } - - m_sampler = other.m_sampler; - other.m_sampler = 0; - - return *this; - } - #endif // BOOST_COMPUTE_NO_RVALUE_REFERENCES - - ~image_sampler() - { - if(m_sampler){ - BOOST_COMPUTE_ASSERT_CL_SUCCESS( - clReleaseSampler(m_sampler) - ); - } - } - - cl_sampler& get() const - { - return const_cast(m_sampler); - } - - context get_context() const - { - return context(get_info(CL_SAMPLER_CONTEXT)); - } - - template - T get_info(cl_sampler_info info) const - { - return detail::get_object_info(clGetSamplerInfo, m_sampler, info); - } - - /// \overload - template - typename detail::get_object_info_type::type - get_info() const; - - /// Returns \c true if the sampler is the same at \p other. - bool operator==(const image_sampler &other) const - { - return m_sampler == other.m_sampler; - } - - /// Returns \c true if the sampler is different from \p other. - bool operator!=(const image_sampler &other) const - { - return m_sampler != other.m_sampler; - } - - operator cl_sampler() const - { - return m_sampler; - } - -private: - cl_sampler m_sampler; -}; - -/// \internal_ define get_info() specializations for image_sampler -BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(image_sampler, - ((cl_uint, CL_SAMPLER_REFERENCE_COUNT)) - ((cl_context, CL_SAMPLER_CONTEXT)) - ((cl_addressing_mode, CL_SAMPLER_ADDRESSING_MODE)) - ((cl_filter_mode, CL_SAMPLER_FILTER_MODE)) - ((bool, CL_SAMPLER_NORMALIZED_COORDS)) -) - -namespace detail { - -// set_kernel_arg specialization for image samplers -template<> -struct set_kernel_arg -{ - void operator()(kernel &kernel_, size_t index, const image_sampler &sampler) - { - kernel_.set_arg(index, sampler.get()); - } -}; - -} // end detail namespace -} // end compute namespace -} // end boost namespace - -BOOST_COMPUTE_TYPE_NAME(boost::compute::image_sampler, sampler_t) - -#endif // BOOST_COMPUTE_IMAGE_SAMPLER_HPP +// deprecated, use instead +#include diff --git a/include/boost/compute/interop/opencv/core.hpp b/include/boost/compute/interop/opencv/core.hpp index 920e2e45..749d1d8d 100644 --- a/include/boost/compute/interop/opencv/core.hpp +++ b/include/boost/compute/interop/opencv/core.hpp @@ -13,8 +13,12 @@ #include -#include +#include + #include +#include +#include +#include #include namespace boost { @@ -52,10 +56,7 @@ inline void opencv_copy_mat_to_image(const cv::Mat &mat, BOOST_ASSERT(mat.isContinuous()); BOOST_ASSERT(image.get_context() == queue.get_context()); - size_t origin[2] = { 0, 0 }; - size_t region[2] = { image.width(), image.height() }; - - queue.enqueue_write_image(image, origin, region, 0, mat.data); + queue.enqueue_write_image(image, image.origin(), image.size(), mat.data); } inline void opencv_copy_image_to_mat(const image2d &image, @@ -65,10 +66,7 @@ inline void opencv_copy_image_to_mat(const image2d &image, BOOST_ASSERT(mat.isContinuous()); BOOST_ASSERT(image.get_context() == queue.get_context()); - size_t origin[2] = { 0, 0 }; - size_t region[2] = { image.width(), image.height() }; - - queue.enqueue_read_image(image, origin, region, 0, mat.data); + queue.enqueue_read_image(image, image.origin(), image.size(), mat.data); } inline image_format opencv_get_mat_image_format(const cv::Mat &mat) @@ -84,9 +82,9 @@ inline image_format opencv_get_mat_image_format(const cv::Mat &mat) return image_format(CL_RGBA, CL_FLOAT); case CV_8UC1: return image_format(CL_INTENSITY, CL_UNORM_INT8); - default: - return image_format(); } + + BOOST_THROW_EXCEPTION(opencl_error(CL_IMAGE_FORMAT_NOT_SUPPORTED)); } inline cv::Mat opencv_create_mat_with_image2d(const image2d &image, @@ -130,9 +128,7 @@ inline image2d opencv_create_image2d_with_mat(const cv::Mat &mat, const context &context = queue.get_context(); const image_format format = opencv_get_mat_image_format(mat); - image2d image( - context, flags, format, mat.cols, mat.rows - ); + image2d image(context, mat.cols, mat.rows, format, flags); opencv_copy_mat_to_image(mat, image, queue); diff --git a/include/boost/compute/interop/opencv/highgui.hpp b/include/boost/compute/interop/opencv/highgui.hpp index 2acae626..ba8afa52 100644 --- a/include/boost/compute/interop/opencv/highgui.hpp +++ b/include/boost/compute/interop/opencv/highgui.hpp @@ -13,7 +13,6 @@ #include -#include #include namespace boost { diff --git a/include/boost/compute/interop/opengl/opengl_buffer.hpp b/include/boost/compute/interop/opengl/opengl_buffer.hpp index f1645618..16d3b4dc 100644 --- a/include/boost/compute/interop/opengl/opengl_buffer.hpp +++ b/include/boost/compute/interop/opengl/opengl_buffer.hpp @@ -97,13 +97,7 @@ namespace detail { // set_kernel_arg specialization for opengl_buffer template<> -struct set_kernel_arg -{ - void operator()(kernel &kernel_, size_t index, const opengl_buffer &buffer_) - { - kernel_.set_arg(index, buffer_.get()); - } -}; +struct set_kernel_arg : set_kernel_arg { }; } // end detail namespace } // end compute namespace diff --git a/include/boost/compute/interop/opengl/opengl_renderbuffer.hpp b/include/boost/compute/interop/opengl/opengl_renderbuffer.hpp index 55f305fd..17d62035 100644 --- a/include/boost/compute/interop/opengl/opengl_renderbuffer.hpp +++ b/include/boost/compute/interop/opengl/opengl_renderbuffer.hpp @@ -11,9 +11,10 @@ #ifndef BOOST_COMPUTE_INTEROP_OPENGL_OPENGL_RENDERBUFFER_HPP #define BOOST_COMPUTE_INTEROP_OPENGL_OPENGL_RENDERBUFFER_HPP -#include +#include #include #include +#include namespace boost { namespace compute { @@ -21,18 +22,18 @@ namespace compute { /// \class opengl_renderbuffer /// /// A OpenCL buffer for accessing an OpenGL renderbuffer object. -class opengl_renderbuffer : public memory_object +class opengl_renderbuffer : public image_object { public: /// Creates a null OpenGL renderbuffer object. opengl_renderbuffer() - : memory_object() + : image_object() { } /// Creates a new OpenGL renderbuffer object for \p mem. explicit opengl_renderbuffer(cl_mem mem, bool retain = true) - : memory_object(mem, retain) + : image_object(mem, retain) { } @@ -57,7 +58,7 @@ public: /// Creates a new OpenGL renderbuffer object as a copy of \p other. opengl_renderbuffer(const opengl_renderbuffer &other) - : memory_object(other) + : image_object(other) { } @@ -65,7 +66,7 @@ public: opengl_renderbuffer& operator=(const opengl_renderbuffer &other) { if(this != &other){ - memory_object::operator=(other); + image_object::operator=(other); } return *this; @@ -76,6 +77,21 @@ public: { } + /// Returns the size (width, height) of the renderbuffer. + extents<2> size() const + { + extents<2> size; + size[0] = get_image_info(CL_IMAGE_WIDTH); + size[1] = get_image_info(CL_IMAGE_HEIGHT); + return size; + } + + /// Returns the origin of the renderbuffer (\c 0, \c 0). + extents<2> origin() const + { + return extents<2>(); + } + /// Returns the OpenGL memory object ID. /// /// \see_opencl_ref{clGetGLObjectInfo} @@ -99,15 +115,9 @@ public: namespace detail { -// set_kernel_arg specialization for opengl_renderbuffer +// set_kernel_arg() specialization for opengl_renderbuffer template<> -struct set_kernel_arg -{ - void operator()(kernel &kernel_, size_t index, const opengl_renderbuffer &buffer_) - { - kernel_.set_arg(index, buffer_.get()); - } -}; +struct set_kernel_arg : public set_kernel_arg { }; } // end detail namespace } // end compute namespace diff --git a/include/boost/compute/interop/opengl/opengl_texture.hpp b/include/boost/compute/interop/opengl/opengl_texture.hpp index fde7ce4b..262bcc42 100644 --- a/include/boost/compute/interop/opengl/opengl_texture.hpp +++ b/include/boost/compute/interop/opengl/opengl_texture.hpp @@ -11,10 +11,11 @@ #ifndef BOOST_COMPUTE_INTEROP_OPENGL_OPENGL_TEXTURE_HPP #define BOOST_COMPUTE_INTEROP_OPENGL_OPENGL_TEXTURE_HPP -#include +#include #include #include #include +#include namespace boost { namespace compute { @@ -22,18 +23,18 @@ namespace compute { /// \class opengl_texture /// /// A OpenCL image2d for accessing an OpenGL texture object. -class opengl_texture : public memory_object +class opengl_texture : public image_object { public: /// Creates a null OpenGL texture object. opengl_texture() - : memory_object() + : image_object() { } /// Creates a new OpenGL texture object for \p mem. explicit opengl_texture(cl_mem mem, bool retain = true) - : memory_object(mem, retain) + : image_object(mem, retain) { } @@ -72,7 +73,7 @@ public: /// Creates a new OpenGL texture object as a copy of \p other. opengl_texture(const opengl_texture &other) - : memory_object(other) + : image_object(other) { } @@ -80,7 +81,7 @@ public: opengl_texture& operator=(const opengl_texture &other) { if(this != &other){ - memory_object::operator=(other); + image_object::operator=(other); } return *this; @@ -91,6 +92,21 @@ public: { } + /// Returns the size (width, height) of the texture. + extents<2> size() const + { + extents<2> size; + size[0] = get_image_info(CL_IMAGE_WIDTH); + size[1] = get_image_info(CL_IMAGE_HEIGHT); + return size; + } + + /// Returns the origin of the texture (\c 0, \c 0). + extents<2> origin() const + { + return extents<2>(); + } + /// Returns information about the texture. /// /// \see_opencl_ref{clGetGLTextureInfo} @@ -103,15 +119,9 @@ public: namespace detail { -// set_kernel_arg specialization for opengl_texture +// set_kernel_arg() specialization for opengl_texture template<> -struct set_kernel_arg -{ - void operator()(kernel &kernel_, size_t index, const opengl_texture &texture) - { - kernel_.set_arg(index, texture.get()); - } -}; +struct set_kernel_arg : public set_kernel_arg { }; } // end detail namespace } // end compute namespace diff --git a/include/boost/compute/interop/qt/qimage.hpp b/include/boost/compute/interop/qt/qimage.hpp index 034fb8e3..d0da2d81 100644 --- a/include/boost/compute/interop/qt/qimage.hpp +++ b/include/boost/compute/interop/qt/qimage.hpp @@ -11,9 +11,13 @@ #ifndef BOOST_COMPUTE_INTEROP_QT_QIMAGE_HPP #define BOOST_COMPUTE_INTEROP_QT_QIMAGE_HPP -#include -#include +#include + #include +#include +#include +#include +#include #include @@ -26,7 +30,7 @@ inline image_format qt_qimage_format_to_image_format(const QImage::Format &forma return image_format(image_format::bgra, image_format::unorm_int8); } - return image_format(); + BOOST_THROW_EXCEPTION(opencl_error(CL_IMAGE_FORMAT_NOT_SUPPORTED)); } inline QImage::Format qt_image_format_to_qimage_format(const image_format &format) @@ -47,21 +51,16 @@ inline void qt_copy_qimage_to_image2d(const QImage &qimage, image2d &image, command_queue &queue) { - size_t origin[] = { 0, 0 }; - size_t region[] = { image.width(), image.height() }; - - queue.enqueue_write_image(image, origin, region, 0, qimage.constBits()); + queue.enqueue_write_image(image, image.origin(), image.size(), qimage.constBits()); } inline void qt_copy_image2d_to_qimage(const image2d &image, QImage &qimage, command_queue &queue) { - size_t origin[] = { 0, 0 }; - size_t region[] = { static_cast(qimage.width()), - static_cast(qimage.height()) }; - - queue.enqueue_read_image(image, origin, region, 0, qimage.bits()); + queue.enqueue_read_image( + image, dim(0, 0), dim(qimage.width(), qimage.height()), qimage.bits() + ); } } // end compute namespace diff --git a/include/boost/compute/iterator/detail/pixel_input_iterator.hpp b/include/boost/compute/iterator/detail/pixel_input_iterator.hpp deleted file mode 100644 index d4f60a9e..00000000 --- a/include/boost/compute/iterator/detail/pixel_input_iterator.hpp +++ /dev/null @@ -1,205 +0,0 @@ -//---------------------------------------------------------------------------// -// Copyright (c) 2013 Kyle Lutz -// -// Distributed under the Boost Software License, Version 1.0 -// See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt -// -// See http://kylelutz.github.com/compute for more information. -//---------------------------------------------------------------------------// - -#ifndef BOOST_COMPUTE_ITERATOR_DETAIL_PIXEL_INPUT_ITERATOR_HPP -#define BOOST_COMPUTE_ITERATOR_DETAIL_PIXEL_INPUT_ITERATOR_HPP - -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -namespace boost { -namespace compute { -namespace detail { - -// forward declaration for pixel_input_iterator -template class pixel_input_iterator; - -// helper class which defines the iterator_facade super-class -// type for pixel_input_iterator -template -class pixel_input_iterator_base -{ -public: - typedef ::boost::iterator_facade< - pixel_input_iterator, - typename ::boost::compute::make_vector_type::type, - ::std::random_access_iterator_tag - > type; -}; - -template -struct pixel_input_iterator_index_expr -{ - typedef typename make_vector_type::type result_type; - - pixel_input_iterator_index_expr(const image2d &image, const IndexExpr &expr) - : m_image(image), - m_expr(expr) - { - } - - const image2d &m_image; - IndexExpr m_expr; -}; - -template -inline meta_kernel& operator<<(meta_kernel &kernel, - const pixel_input_iterator_index_expr &expr) -{ - std::string image = - kernel.get_image_identifier("__read_only", expr.m_image); - std::string sampler = - kernel.get_sampler_identifier(false, - image_sampler::none, - image_sampler::nearest); - - std::string read_suffix; - if(boost::is_floating_point::value){ - read_suffix = "f"; - } - else if(boost::is_unsigned::value){ - read_suffix = "ui"; - } - else { - read_suffix = "i"; - } - - return kernel << "read_image" << read_suffix << "(" - << image << "," - << sampler << "," - << "(int2)(" - << expr.m_expr << " % get_image_width(" << image << "), " - << expr.m_expr << " / get_image_width(" << image << ")))"; -} - -template -class pixel_input_iterator : public pixel_input_iterator_base::type -{ -public: - typedef typename pixel_input_iterator_base::type super_type; - typedef typename super_type::reference reference; - typedef typename super_type::difference_type difference_type; - - pixel_input_iterator() - : m_image(0), - m_index(0) - { - } - - pixel_input_iterator(const image2d &image, size_t index) - : m_image(&image), - m_index(index) - { - } - - pixel_input_iterator(const pixel_input_iterator &other) - : m_image(other.m_image), - m_index(other.m_index) - { - } - - pixel_input_iterator& operator=(const pixel_input_iterator &other) - { - if(this != &other){ - m_image = other.m_image; - m_index = other.m_index; - } - - return *this; - } - - ~pixel_input_iterator() - { - } - - const image2d& get_image() const - { - return *m_image; - } - - size_t get_index() const - { - return m_index; - } - - template - pixel_input_iterator_index_expr - operator[](const Expr &expr) const - { - return pixel_input_iterator_index_expr(*m_image, expr); - } - -private: - friend class ::boost::iterator_core_access; - - reference dereference() const - { - return T(0); - } - - bool equal(const pixel_input_iterator &other) const - { - return m_image == other.m_image && m_index == other.m_index; - } - - void increment() - { - m_index++; - } - - void decrement() - { - m_index--; - } - - void advance(difference_type n) - { - m_index = static_cast(static_cast(m_index) + n); - } - - difference_type distance_to(const pixel_input_iterator &other) const - { - return static_cast(other.m_index - m_index); - } - -private: - const image2d *m_image; - size_t m_index; -}; - -template -inline pixel_input_iterator -make_pixel_input_iterator(const image2d &image, size_t index = 0) -{ - return pixel_input_iterator(image, index); -} - -} // end detail namespace - -// is_device_iterator specialization for pixel_input_iterator -template -struct is_device_iterator > : boost::true_type {}; - -} // end compute namespace -} // end boost namespace - -#endif // BOOST_COMPUTE_ITERATOR_DETAIL_PIXEL_INPUT_ITERATOR_HPP diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 94e02b60..89619d1e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -50,9 +50,6 @@ add_compute_test("core.context" test_context.cpp) add_compute_test("core.device" test_device.cpp) add_compute_test("core.event" test_event.cpp) add_compute_test("core.function" test_function.cpp) -add_compute_test("core.image2d" test_image2d.cpp) -add_compute_test("core.image3d" test_image3d.cpp) -add_compute_test("core.image_sampler" test_image_sampler.cpp) add_compute_test("core.kernel" test_kernel.cpp) add_compute_test("core.pipe" test_pipe.cpp) add_compute_test("core.platform" test_platform.cpp) @@ -155,6 +152,11 @@ add_compute_test("functional.identity" test_functional_identity.cpp) add_compute_test("functional.popcount" test_functional_popcount.cpp) add_compute_test("functional.unpack" test_functional_unpack.cpp) +add_compute_test("image.image1d" test_image1d.cpp) +add_compute_test("image.image2d" test_image2d.cpp) +add_compute_test("image.image3d" test_image3d.cpp) +add_compute_test("image.image_sampler" test_image_sampler.cpp) + add_compute_test("iterator.buffer_iterator" test_buffer_iterator.cpp) add_compute_test("iterator.constant_iterator" test_constant_iterator.cpp) add_compute_test("iterator.counting_iterator" test_counting_iterator.cpp) diff --git a/test/test_image1d.cpp b/test/test_image1d.cpp new file mode 100644 index 00000000..d7139c16 --- /dev/null +++ b/test/test_image1d.cpp @@ -0,0 +1,68 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2013-2015 Kyle Lutz +// +// Distributed under the Boost Software License, Version 1.0 +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// +// See http://kylelutz.github.com/compute for more information. +//---------------------------------------------------------------------------// + +#define BOOST_TEST_MODULE TestImage1D +#include + +#include + +#include +#include + +#include "quirks.hpp" +#include "context_setup.hpp" + +namespace compute = boost::compute; + +BOOST_AUTO_TEST_CASE(image1d_get_supported_formats) +{ + const std::vector formats = + compute::image1d::get_supported_formats(context); +} + +#ifdef CL_VERSION_1_2 +BOOST_AUTO_TEST_CASE(fill_image1d) +{ + // single-channel unsigned char + compute::image_format format(CL_R, CL_UNSIGNED_INT8); + + if(!compute::image1d::is_supported_format(format, context)){ + std::cerr << "skipping fill_image1d test, image format not supported" << std::endl; + return; + } + + compute::image1d img(context, 64, format); + + BOOST_CHECK_EQUAL(img.width(), 64); + BOOST_CHECK(img.size() == compute::dim(64)); + BOOST_CHECK(img.format() == format); + + // fill image with '128' + compute::uint4_ fill_color(128, 0, 0, 0); + queue.enqueue_fill_image(img, &fill_color, img.origin(), img.size()); + + // read value of first pixel + compute::uchar_ first_pixel = 0; + queue.enqueue_read_image(img, compute::dim(0), compute::dim(1), &first_pixel); + BOOST_CHECK_EQUAL(first_pixel, 128); +} +#endif // CL_VERSION_1_2 + +// check type_name() for image1d +BOOST_AUTO_TEST_CASE(image1d_type_name) +{ + BOOST_CHECK( + std::strcmp( + boost::compute::type_name(), "image1d_t" + ) == 0 + ); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/test/test_image2d.cpp b/test/test_image2d.cpp index fc4e5a5e..61a83e93 100644 --- a/test/test_image2d.cpp +++ b/test/test_image2d.cpp @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------// -// Copyright (c) 2013 Kyle Lutz +// Copyright (c) 2013-2015 Kyle Lutz // // Distributed under the Boost Software License, Version 1.0 // See accompanying file LICENSE_1_0.txt or copy at @@ -14,40 +14,61 @@ #include #include -#include -#include -#include -#include +#include +#include #include "quirks.hpp" #include "context_setup.hpp" -namespace bc = boost::compute; namespace compute = boost::compute; BOOST_AUTO_TEST_CASE(image2d_get_supported_formats) { - REQUIRES_OPENCL_VERSION(1,2); + const std::vector formats = + compute::image2d::get_supported_formats(context); +} - std::vector formats = - bc::image2d::get_supported_formats(context, bc::image2d::read_only); - BOOST_CHECK(!formats.empty()); +BOOST_AUTO_TEST_CASE(create_image_doctest) +{ + try { +//! [create_image] +// create 8-bit RGBA image format +boost::compute::image_format rgba8(CL_RGBA, CL_UNSIGNED_INT8); + +// create 640x480 image object +boost::compute::image2d img(context, 640, 480, rgba8); +//! [create_image] + + // verify image has been created and format is correct + BOOST_CHECK(img.get() != cl_mem()); + BOOST_CHECK(img.format() == rgba8); + BOOST_CHECK_EQUAL(img.width(), 640); + BOOST_CHECK_EQUAL(img.height(), 480); + } + catch(compute::opencl_error &e){ + if(e.error_code() == CL_IMAGE_FORMAT_NOT_SUPPORTED){ + // image format not supported by device + return; + } + + // some other error, rethrow + throw; + } } BOOST_AUTO_TEST_CASE(get_info) { - REQUIRES_OPENCL_VERSION(1,2); + compute::image_format format(CL_RGBA, CL_UNSIGNED_INT8); - bc::image2d image( - context, - bc::image2d::read_only, - bc::image_format( - bc::image_format::rgba, - bc::image_format::unorm_int8 - ), - 48, - 64 + if(!compute::image2d::is_supported_format(format, context)){ + std::cerr << "skipping get_info test, image format not supported" << std::endl; + return; + } + + compute::image2d image( + context, 48, 64, format, compute::image2d::read_only ); + BOOST_CHECK_EQUAL(image.get_info(CL_IMAGE_WIDTH), size_t(48)); BOOST_CHECK_EQUAL(image.get_info(CL_IMAGE_HEIGHT), size_t(64)); BOOST_CHECK_EQUAL(image.get_info(CL_IMAGE_DEPTH), size_t(0)); @@ -55,43 +76,42 @@ BOOST_AUTO_TEST_CASE(get_info) BOOST_CHECK_EQUAL(image.get_info(CL_IMAGE_SLICE_PITCH), size_t(0)); BOOST_CHECK_EQUAL(image.get_info(CL_IMAGE_ELEMENT_SIZE), size_t(4)); + BOOST_CHECK(image.format() == format); BOOST_CHECK_EQUAL(image.width(), size_t(48)); BOOST_CHECK_EQUAL(image.height(), size_t(64)); - - BOOST_CHECK(bc::image_format( - image.get_info(CL_IMAGE_FORMAT)) == - bc::image_format( - bc::image_format::rgba, bc::image_format::unorm_int8)); } BOOST_AUTO_TEST_CASE(clone_image) { - REQUIRES_OPENCL_VERSION(1,2); + compute::image_format format(CL_RGBA, CL_UNORM_INT8); + + if(!compute::image2d::is_supported_format(format, context)){ + std::cerr << "skipping clone_image test, image format not supported" << std::endl; + return; + } // image data unsigned int data[] = { 0x0000ffff, 0xff00ffff, 0x00ff00ff, 0xffffffff }; // create image on the device - compute::image2d image( - context, - CL_MEM_READ_WRITE, - compute::image_format(CL_RGBA, CL_UNORM_INT8), - 2, - 2 - ); + compute::image2d image(context, 2, 2, format); + + // ensure we have a valid image object + BOOST_REQUIRE(image.get() != cl_mem()); // copy image data to the device - size_t origin[2] = { 0, 0 }; - size_t region[2] = { 2, 2 }; - queue.enqueue_write_image(image, origin, region, 0, data); + queue.enqueue_write_image(image, image.origin(), image.size(), data); // clone image compute::image2d copy = image.clone(queue); + // ensure image format is the same + BOOST_CHECK(copy.format() == image.format()); + // read cloned image data back to the host unsigned int cloned_data[4]; - queue.enqueue_read_image(copy, origin, region, 0, cloned_data); + queue.enqueue_read_image(copy, image.origin(), image.size(), cloned_data); // ensure original data and cloned data are the same BOOST_CHECK_EQUAL(cloned_data[0], data[0]); @@ -100,101 +120,43 @@ BOOST_AUTO_TEST_CASE(clone_image) BOOST_CHECK_EQUAL(cloned_data[3], data[3]); } -BOOST_AUTO_TEST_CASE(count_with_pixel_iterator) +#ifdef CL_VERSION_1_2 +BOOST_AUTO_TEST_CASE(fill_image) { - REQUIRES_OPENCL_VERSION(1,2); + compute::image_format format(CL_RGBA, CL_UNSIGNED_INT8); - if(is_pocl_device(device)){ - std::cerr << "skipping count_with_pixel_iterator test" << std::endl; + if(!compute::image2d::is_supported_format(format, context)){ + std::cerr << "skipping fill_image test, image format not supported" << std::endl; return; } - unsigned int data[] = { 0x00000000, 0x000000ff, 0xff0000ff, - 0xffff00ff, 0x000000ff, 0xff0000ff, - 0xff0000ff, 0x00ff00ff, 0x0000ffff }; + compute::image2d img(context, 640, 480, format); - bc::image2d image( - context, - bc::image2d::read_only | bc::image2d::use_host_ptr, - bc::image_format( - bc::image_format::rgba, - bc::image_format::unorm_int8 - ), - 3, - 3, - 3 * 4, - data - ); + // fill image with black + compute::uint4_ black(0, 0, 0, 255); + queue.enqueue_fill_image(img, &black, img.origin(), img.size()); - BOOST_CHECK_EQUAL( - bc::count(bc::detail::make_pixel_input_iterator(image, 0), - bc::detail::make_pixel_input_iterator(image, image.get_pixel_count()), - bc::float4_(0, 0, 0, 0)), - size_t(1)); - BOOST_CHECK_EQUAL( - bc::count(bc::detail::make_pixel_input_iterator(image, 0), - bc::detail::make_pixel_input_iterator(image, image.get_pixel_count()), - bc::float4_(1, 0, 0, 0)), - size_t(2)); - BOOST_CHECK_EQUAL( - bc::count(bc::detail::make_pixel_input_iterator(image, 0), - bc::detail::make_pixel_input_iterator(image, image.get_pixel_count()), - bc::float4_(1, 0, 0, 1)), - size_t(3)); - BOOST_CHECK_EQUAL( - bc::count(bc::detail::make_pixel_input_iterator(image, 0), - bc::detail::make_pixel_input_iterator(image, image.get_pixel_count()), - bc::float4_(1, 1, 0, 0)), - size_t(1)); - BOOST_CHECK_EQUAL( - bc::count(bc::detail::make_pixel_input_iterator(image, 0), - bc::detail::make_pixel_input_iterator(image, image.get_pixel_count()), - bc::float4_(1, 0, 1, 1)), - size_t(1)); -} - -BOOST_AUTO_TEST_CASE(find_with_pixel_iterator) -{ - REQUIRES_OPENCL_VERSION(1,2); - - if(is_pocl_device(device)){ - std::cerr << "skipping find_with_pixel_iterator test" << std::endl; - return; - } - - unsigned int data[] = { 0x00000000, 0x000000ff, 0xff0000ff, - 0xffff00ff, 0x000000ff, 0xff0000ff, - 0xff0000ff, 0x00ff00ff, 0x0000ffff }; - - bc::image2d image( - context, - bc::image2d::read_only | bc::image2d::use_host_ptr, - bc::image_format( - bc::image_format::rgba, - bc::image_format::unorm_int8 - ), - 3, - 3, - 3 * 4, - data - ); - BOOST_CHECK_EQUAL( - std::distance( - bc::detail::make_pixel_input_iterator(image), - bc::find(bc::detail::make_pixel_input_iterator(image, 0), - bc::detail::make_pixel_input_iterator(image, image.get_pixel_count()), - bc::float4_(1, 0, 1, 1)) - ), - ptrdiff_t(3)); + // read value of first pixel + compute::uchar4_ first_pixel; + queue.enqueue_read_image(img, compute::dim(0), compute::dim(1), &first_pixel); + BOOST_CHECK_EQUAL(first_pixel, compute::uchar4_(0, 0, 0, 255)); + + // fill image with white + compute::uint4_ white(255, 255, 255, 255); + queue.enqueue_fill_image(img, &white, img.origin(), img.size()); + + // read value of first pixel + queue.enqueue_read_image(img, compute::dim(0), compute::dim(1), &first_pixel); + BOOST_CHECK_EQUAL(first_pixel, compute::uchar4_(255, 255, 255, 255)); } +#endif // check type_name() for image2d -BOOST_AUTO_TEST_CASE(complex_type_name) +BOOST_AUTO_TEST_CASE(image2d_type_name) { BOOST_CHECK( std::strcmp( - boost::compute::type_name(), - "image2d_t" + boost::compute::type_name(), "image2d_t" ) == 0 ); } diff --git a/test/test_image3d.cpp b/test/test_image3d.cpp index 0826d2d2..15c7cce7 100644 --- a/test/test_image3d.cpp +++ b/test/test_image3d.cpp @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------// -// Copyright (c) 2013 Kyle Lutz +// Copyright (c) 2013-2015 Kyle Lutz // // Distributed under the Boost Software License, Version 1.0 // See accompanying file LICENSE_1_0.txt or copy at @@ -12,25 +12,24 @@ #include #include -#include +#include #include "context_setup.hpp" -namespace bc = boost::compute; +namespace compute = boost::compute; BOOST_AUTO_TEST_CASE(image3d_get_supported_formats) { - std::vector formats = - bc::image3d::get_supported_formats(context, bc::image3d::read_only); + const std::vector formats = + compute::image3d::get_supported_formats(context); } // check type_name() for image3d -BOOST_AUTO_TEST_CASE(complex_type_name) +BOOST_AUTO_TEST_CASE(image3d_type_name) { BOOST_CHECK( std::strcmp( - boost::compute::type_name(), - "image3d_t" + boost::compute::type_name(), "image3d_t" ) == 0 ); } diff --git a/test/test_image_sampler.cpp b/test/test_image_sampler.cpp index 6fe74ec4..fe77708c 100644 --- a/test/test_image_sampler.cpp +++ b/test/test_image_sampler.cpp @@ -14,12 +14,12 @@ #include #include -#include +#include #include "quirks.hpp" #include "context_setup.hpp" -namespace bc = boost::compute; +namespace compute = boost::compute; BOOST_AUTO_TEST_CASE(get_context) { @@ -28,7 +28,7 @@ BOOST_AUTO_TEST_CASE(get_context) return; } - bc::image_sampler sampler(context, true, CL_ADDRESS_NONE, CL_FILTER_NEAREST); + compute::image_sampler sampler(context, true, CL_ADDRESS_NONE, CL_FILTER_NEAREST); BOOST_CHECK(sampler.get_context() == context); } @@ -39,7 +39,7 @@ BOOST_AUTO_TEST_CASE(get_info) return; } - bc::image_sampler sampler(context, true, CL_ADDRESS_NONE, CL_FILTER_NEAREST); + compute::image_sampler sampler(context, true, CL_ADDRESS_NONE, CL_FILTER_NEAREST); BOOST_CHECK_EQUAL(sampler.get_info(CL_SAMPLER_NORMALIZED_COORDS), true); BOOST_CHECK_EQUAL( sampler.get_info(CL_SAMPLER_ADDRESSING_MODE), @@ -50,7 +50,7 @@ BOOST_AUTO_TEST_CASE(get_info) cl_filter_mode(CL_FILTER_NEAREST) ); - sampler = bc::image_sampler(context, false, CL_ADDRESS_CLAMP, CL_FILTER_LINEAR); + sampler = compute::image_sampler(context, false, CL_ADDRESS_CLAMP, CL_FILTER_LINEAR); BOOST_CHECK_EQUAL(sampler.get_info(CL_SAMPLER_NORMALIZED_COORDS), false); BOOST_CHECK_EQUAL( sampler.get_info(CL_SAMPLER_ADDRESSING_MODE),