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