Skip to content

Commit 6807c8c

Browse files
committed
[SYCL] Implement buffer constructor with iterators in accordance with spec
This change allows to use this constructor with constant iterators. Data is written back to the same iterator set if the input iterator is not a const iterator - in accordance with spec. Signed-off-by: Mariya Podchishchaeva <mariya.podchishchaeva@intel.com>
1 parent 82fead6 commit 6807c8c

File tree

2 files changed

+71
-22
lines changed

2 files changed

+71
-22
lines changed

sycl/include/CL/sycl/detail/buffer_impl.hpp

+43-14
Original file line numberDiff line numberDiff line change
@@ -99,23 +99,52 @@ template <typename AllocatorT> class buffer_impl {
9999
}
100100
}
101101

102+
template <typename Iterator> struct is_const_iterator {
103+
using pointer = typename std::iterator_traits<Iterator>::pointer;
104+
static constexpr bool value =
105+
std::is_const<typename std::remove_pointer<pointer>::type>::value;
106+
};
107+
108+
template <typename Iterator>
109+
using EnableIfConstIterator =
110+
typename std::enable_if<is_const_iterator<Iterator>::value,
111+
Iterator>::type;
112+
113+
template <typename Iterator>
114+
using EnableIfNotConstIterator =
115+
typename std::enable_if<!is_const_iterator<Iterator>::value,
116+
Iterator>::type;
117+
102118
template <class InputIterator>
103-
buffer_impl(InputIterator first, InputIterator last, const size_t sizeInBytes,
104-
const property_list &propList,
119+
buffer_impl(EnableIfNotConstIterator<InputIterator> first, InputIterator last,
120+
const size_t sizeInBytes, const property_list &propList,
105121
AllocatorT allocator = AllocatorT())
106122
: SizeInBytes(sizeInBytes), Props(propList), MAllocator(allocator) {
107-
if (Props.has_property<property::buffer::use_host_ptr>()) {
108-
// TODO next line looks unsafe
109-
BufPtr = &*first;
110-
} else {
111-
BufData.resize(get_size());
112-
BufPtr = reinterpret_cast<void *>(BufData.data());
113-
// We need cast BufPtr to pointer to the iteration type to get correct
114-
// offset in std::copy when it will increment destination pointer.
115-
auto *Ptr = reinterpret_cast<
116-
typename std::iterator_traits<InputIterator>::pointer>(BufPtr);
117-
std::copy(first, last, Ptr);
118-
}
123+
BufData.resize(get_size());
124+
BufPtr = reinterpret_cast<void *>(BufData.data());
125+
// We need cast BufPtr to pointer to the iteration type to get correct
126+
// offset in std::copy when it will increment destination pointer.
127+
auto *Ptr =
128+
reinterpret_cast<typename std::iterator_traits<InputIterator>::pointer>(
129+
BufPtr);
130+
std::copy(first, last, Ptr);
131+
// Data is written back if InputIterator is not a const iterator.
132+
set_final_data(first);
133+
}
134+
135+
template <class InputIterator>
136+
buffer_impl(EnableIfConstIterator<InputIterator> first, InputIterator last,
137+
const size_t sizeInBytes, const property_list &propList,
138+
AllocatorT allocator = AllocatorT())
139+
: SizeInBytes(sizeInBytes), Props(propList), MAllocator(allocator) {
140+
BufData.resize(get_size());
141+
BufPtr = reinterpret_cast<void *>(BufData.data());
142+
// We need cast BufPtr to pointer to the iteration type to get correct
143+
// offset in std::copy when it will increment destination pointer.
144+
typedef typename std::iterator_traits<InputIterator>::value_type value;
145+
auto *Ptr = reinterpret_cast<typename std::add_pointer<
146+
typename std::remove_const<value>::type>::type>(BufPtr);
147+
std::copy(first, last, Ptr);
119148
}
120149

121150
buffer_impl(cl_mem MemObject, const context &SyclContext,

sycl/test/basic_tests/buffer/buffer.cpp

+28-8
Original file line numberDiff line numberDiff line change
@@ -403,8 +403,29 @@ int main() {
403403
range<1>{3}, [=](id<1> index) { B[index] = 20; });
404404
});
405405
}
406-
// Data is not copied back in the desctruction of the buffer created from
407-
// pair of iterators
406+
// Data is copied back in the desctruction of the buffer created from
407+
// pair of non-const iterators
408+
for (int i = 0; i < 2; i++)
409+
assert(data1[i] == -1);
410+
for (int i = 2; i < 5; i++)
411+
assert(data1[i] == 20);
412+
for (int i = 5; i < 10; i++)
413+
assert(data1[i] == -1);
414+
}
415+
416+
// Check that data is not copied back in the desctruction of the buffer
417+
// created from pair of const iterators
418+
{
419+
std::vector<int> data1(10, -1);
420+
{
421+
buffer<int, 1> b(data1.cbegin() + 2, data1.cbegin() + 5);
422+
queue myQueue;
423+
myQueue.submit([&](handler &cgh) {
424+
auto B = b.get_access<access::mode::read_write>(cgh);
425+
cgh.parallel_for<class const_iter_constuctor>(
426+
range<1>{3}, [=](id<1> index) { B[index] = 20; });
427+
});
428+
}
408429
for (int i = 0; i < 10; i++)
409430
assert(data1[i] == -1);
410431
}
@@ -435,24 +456,23 @@ int main() {
435456
// created from pair of iterators
436457
{
437458
std::vector<int> data1(10, -1);
459+
std::vector<int> data2(10, -1);
438460
{
439461
buffer<int, 1> b(data1.begin() + 2, data1.begin() + 5);
440-
b.set_final_data(data1.begin() + 2);
462+
b.set_final_data(data2.begin() + 2);
441463
queue myQueue;
442464
myQueue.submit([&](handler &cgh) {
443465
auto B = b.get_access<access::mode::read_write>(cgh);
444466
cgh.parallel_for<class iter_constuctor_set_final_data>(
445467
range<1>{3}, [=](id<1> index) { B[index] = 20; });
446468
});
447469
}
448-
// Data is not copied back in the desctruction of the buffer created from
449-
// pair of iterators
450470
for (int i = 0; i < 2; i++)
451-
assert(data1[i] == -1);
471+
assert(data2[i] == -1);
452472
for (int i = 2; i < 5; i++)
453-
assert(data1[i] == 20);
473+
assert(data2[i] == 20);
454474
for (int i = 5; i < 10; i++)
455-
assert(data1[i] == -1);
475+
assert(data2[i] == -1);
456476
}
457477

458478
// Check that data is copied back after forcing write-back using

0 commit comments

Comments
 (0)