1 //---------------------------------------------------------------------------//
2 // Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
3 //
4 // Distributed under the Boost Software License, Version 1.0
5 // See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt
7 //
8 // See http://boostorg.github.com/compute for more information.
9 //---------------------------------------------------------------------------//
10 
11 #define BOOST_TEST_MODULE TestBuffer
12 #include <boost/test/unit_test.hpp>
13 
14 #include <boost/compute/buffer.hpp>
15 #include <boost/compute/system.hpp>
16 #include <boost/bind.hpp>
17 
18 #ifdef BOOST_COMPUTE_USE_CPP11
19 #include <mutex>
20 #include <future>
21 #endif // BOOST_COMPUTE_USE_CPP11
22 
23 #include "quirks.hpp"
24 #include "context_setup.hpp"
25 
26 namespace bc = boost::compute;
27 
BOOST_AUTO_TEST_CASE(size)28 BOOST_AUTO_TEST_CASE(size)
29 {
30     bc::buffer buffer(context, 100);
31     BOOST_CHECK_EQUAL(buffer.size(), size_t(100));
32     BOOST_VERIFY(buffer.max_size() > buffer.size());
33 }
34 
BOOST_AUTO_TEST_CASE(cl_context)35 BOOST_AUTO_TEST_CASE(cl_context)
36 {
37     bc::buffer buffer(context, 100);
38     BOOST_VERIFY(buffer.get_context() == context);
39 }
40 
BOOST_AUTO_TEST_CASE(equality_operator)41 BOOST_AUTO_TEST_CASE(equality_operator)
42 {
43     bc::buffer a(context, 10);
44     bc::buffer b(context, 10);
45     BOOST_VERIFY(a == a);
46     BOOST_VERIFY(b == b);
47     BOOST_VERIFY(!(a == b));
48     BOOST_VERIFY(a != b);
49 
50     a = b;
51     BOOST_VERIFY(a == b);
52     BOOST_VERIFY(!(a != b));
53 }
54 
BOOST_AUTO_TEST_CASE(construct_from_cl_mem)55 BOOST_AUTO_TEST_CASE(construct_from_cl_mem)
56 {
57     // create cl_mem
58     cl_mem mem = clCreateBuffer(context, CL_MEM_READ_WRITE, 16, 0, 0);
59     BOOST_VERIFY(mem);
60 
61     // create boost::compute::buffer
62     boost::compute::buffer buffer(mem);
63 
64     // check buffer
65     BOOST_CHECK(buffer.get() == mem);
66     BOOST_CHECK(buffer.get_context() == context);
67     BOOST_CHECK_EQUAL(buffer.size(), size_t(16));
68 
69     // cleanup cl_mem
70     clReleaseMemObject(mem);
71 }
72 
BOOST_AUTO_TEST_CASE(reference_count)73 BOOST_AUTO_TEST_CASE(reference_count)
74 {
75     using boost::compute::uint_;
76 
77     boost::compute::buffer buf(context, 16);
78     BOOST_CHECK_GE(buf.reference_count(), uint_(1));
79 }
80 
BOOST_AUTO_TEST_CASE(get_size)81 BOOST_AUTO_TEST_CASE(get_size)
82 {
83     boost::compute::buffer buf(context, 16);
84     BOOST_CHECK_EQUAL(buf.size(), size_t(16));
85     BOOST_CHECK_EQUAL(buf.get_info<CL_MEM_SIZE>(), size_t(16));
86     BOOST_CHECK_EQUAL(buf.get_info<size_t>(CL_MEM_SIZE), size_t(16));
87 }
88 
89 #ifndef BOOST_COMPUTE_NO_RVALUE_REFERENCES
BOOST_AUTO_TEST_CASE(move_constructor)90 BOOST_AUTO_TEST_CASE(move_constructor)
91 {
92     boost::compute::buffer buffer1(context, 16);
93     BOOST_CHECK(buffer1.get() != 0);
94     BOOST_CHECK_EQUAL(buffer1.size(), size_t(16));
95 
96     boost::compute::buffer buffer2(std::move(buffer1));
97     BOOST_CHECK(buffer1.get() == 0);
98     BOOST_CHECK(buffer2.get() != 0);
99     BOOST_CHECK_EQUAL(buffer2.size(), size_t(16));
100 }
101 #endif // BOOST_COMPUTE_NO_RVALUE_REFERENCES
102 
BOOST_AUTO_TEST_CASE(clone_buffer)103 BOOST_AUTO_TEST_CASE(clone_buffer)
104 {
105     boost::compute::buffer buffer1(context, 16);
106     boost::compute::buffer buffer2 = buffer1.clone(queue);
107     BOOST_CHECK(buffer1.get() != buffer2.get());
108     BOOST_CHECK_EQUAL(buffer1.size(), buffer2.size());
109     BOOST_CHECK(buffer1.get_memory_flags() == buffer2.get_memory_flags());
110 }
111 
112 #ifdef BOOST_COMPUTE_CL_VERSION_1_1
113 #ifdef BOOST_COMPUTE_USE_CPP11
114 std::mutex callback_mutex;
115 std::condition_variable callback_condition_variable;
116 
117 static void BOOST_COMPUTE_CL_CALLBACK
destructor_callback_function(cl_mem,void * user_data)118 destructor_callback_function(cl_mem, void *user_data)
119 {
120     std::lock_guard<std::mutex> lock(callback_mutex);
121 
122     bool *flag = static_cast<bool *>(user_data);
123     *flag = true;
124 
125     callback_condition_variable.notify_one();
126 }
127 
BOOST_AUTO_TEST_CASE(destructor_callback)128 BOOST_AUTO_TEST_CASE(destructor_callback)
129 {
130     REQUIRES_OPENCL_VERSION(1,2);
131 
132     if(!supports_destructor_callback(device))
133     {
134         return;
135     }
136 
137     bool invoked = false;
138     {
139         boost::compute::buffer buf(context, 128);
140         buf.set_destructor_callback(destructor_callback_function, &invoked);
141     }
142 
143     std::unique_lock<std::mutex> lock(callback_mutex);
144     callback_condition_variable.wait_for(
145         lock, std::chrono::seconds(1), [&](){ return invoked; }
146     );
147     BOOST_CHECK(invoked == true);
148 }
149 
150 static void BOOST_COMPUTE_CL_CALLBACK
destructor_templated_callback_function(bool * flag)151 destructor_templated_callback_function(bool *flag)
152 {
153     std::lock_guard<std::mutex> lock(callback_mutex);
154     *flag = true;
155     callback_condition_variable.notify_one();
156 }
157 
BOOST_AUTO_TEST_CASE(destructor_templated_callback)158 BOOST_AUTO_TEST_CASE(destructor_templated_callback)
159 {
160     REQUIRES_OPENCL_VERSION(1,2);
161 
162     if(!supports_destructor_callback(device))
163     {
164         return;
165     }
166 
167     bool invoked = false;
168     {
169         boost::compute::buffer buf(context, 128);
170         buf.set_destructor_callback(boost::bind(destructor_templated_callback_function, &invoked));
171     }
172 
173     std::unique_lock<std::mutex> lock(callback_mutex);
174     callback_condition_variable.wait_for(
175         lock, std::chrono::seconds(1), [&](){ return invoked; }
176     );
177 
178     BOOST_CHECK(invoked == true);
179 }
180 
181 #endif // BOOST_COMPUTE_USE_CPP11
182 
BOOST_AUTO_TEST_CASE(create_subbuffer)183 BOOST_AUTO_TEST_CASE(create_subbuffer)
184 {
185     REQUIRES_OPENCL_VERSION(1, 1);
186 
187     size_t base_addr_align = device.get_info<CL_DEVICE_MEM_BASE_ADDR_ALIGN>() / 8;
188     size_t multiplier = 16;
189     size_t buffer_size = base_addr_align * multiplier;
190     size_t subbuffer_size = 64;
191     boost::compute::buffer buffer(context, buffer_size);
192 
193     for(size_t i = 0; i < multiplier; ++i)
194     {
195         boost::compute::buffer subbuffer = buffer.create_subbuffer(
196               boost::compute::buffer::read_write, base_addr_align * i, subbuffer_size);
197         BOOST_CHECK(buffer.get() != subbuffer.get());
198         BOOST_CHECK_EQUAL(subbuffer.size(), subbuffer_size);
199     }
200 }
201 
202 #endif // BOOST_COMPUTE_CL_VERSION_1_1
203 
BOOST_AUTO_TEST_CASE(create_buffer_doctest)204 BOOST_AUTO_TEST_CASE(create_buffer_doctest)
205 {
206 //! [constructor]
207 boost::compute::buffer buf(context, 32 * sizeof(float));
208 //! [constructor]
209 
210     BOOST_CHECK_EQUAL(buf.size(), 32 * sizeof(float));
211 }
212 
213 BOOST_AUTO_TEST_SUITE_END()
214