Skip to content

Commit 2a72cad

Browse files
DuncanMcBainRuyman
authored andcommitted
Add proposal for default-constructible buffers (#97)
* Add proposal for default-constructible buffers Default constructible buffers would be a useful addition for generic code. This proposal adds a zero-argument constructor and functions for determining whether or not a buffer is usable. * Updated with review feedback. * Assigned CP021 extension ID
1 parent b15fa36 commit 2a72cad

File tree

2 files changed

+97
-0
lines changed

2 files changed

+97
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,4 @@ Each proposal in the table below will be tagged with one of the following states
5757
| CP017 | [Host Access](host_access/index.md) | SYCL 1.2.1 vendor extension | 17 September 2018 | 13 December 2018 | _Available since CE 1.0.3_ |
5858
| CP018 | [Built-in kernels](builtin_kernels/index.md) | SYCL 1.2.1 vendor extension | 12 October 2018 | 12 October 2018 | _Available since CE 1.0.3_ |
5959
| CP019 | [On-chip Memory Allocation](onchip-memory/index.md) | SYCL 1.2.1 vendor extension | 03 December 2018 | 03 December 2018 | _Available since CE 1.0.3_ |
60+
| CP021 | [Default-Constructed Buffers](default-constructed-buffers/default-constructed-buffers.md) | SYCL 1.2.1 | 27 August 2019 | 5 September 2019 | _Draft_ |
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# Default-constructed Buffers
2+
3+
Proposal ID | CP021
4+
---------------- | ---------------------------
5+
Name | Default-constructed Buffers
6+
Date of Creation | 2019-08-20
7+
Target | SYCL 1.2.1
8+
Status | _Draft_
9+
Author | Duncan McBain [Duncan McBain](mailto:duncan@codeplay.com)
10+
Contributors | Duncan McBain, [Gordon Brown](mailto:gordon@codeplay.com)
11+
12+
## Description
13+
14+
In SYCL, there are no buffer constructors that take no arguments, which means
15+
that `cl::sycl::buffer` cannot be default-constructed. However, this limits the
16+
use of buffers in some interfaces. Consider a library function that has an
17+
optional user-provided allocation for temporary data. The library can avoid
18+
allocations if the library user so desires by providing a buffer here, but how
19+
should the user indicate that allocation is allowed? A natural way would be to
20+
provide a default argument in the API function:
21+
22+
```c++
23+
template <typename Allocation_t>
24+
void foo(Allocation_t input_a,
25+
Allocation_t input_b,
26+
Allocation_t temp = Allocation_t{});
27+
```
28+
29+
For `Allocation_t` types that are pointer-like, the library can check for
30+
`nullptr` and allocate if this condition is true. A similar mechanism that
31+
allows `cl::sycl::buffer` to be constructed and checked for usability would
32+
aid their use in this style of generic interface.
33+
34+
## Proposal
35+
36+
The `cl::sycl::buffer` class should be augmented with an additional constructor
37+
that takes no arguments, which initialises the buffer with a zero-size range.
38+
```c++
39+
namespace cl {
40+
namespace sycl {
41+
template <typename T, int dimensions = 1,
42+
typename AllocatorT = cl::sycl::buffer_allocator>
43+
class buffer {
44+
buffer();
45+
46+
bool is_valid() const noexcept;
47+
48+
explicit operator bool() const noexcept;
49+
};
50+
} // namespace sycl
51+
} // namespace cl
52+
```
53+
The template arguments should remain the same, so that the argument can be
54+
rebound to a new `buffer` instance later using the copy constructor.
55+
56+
The `is_valid()` call would allow the programmer to query whether or not
57+
the buffer can be used, i.e. whether or not it was constructed with a range of
58+
size zero. The explicit conversion operator would call this same function but
59+
allow its use in `if` statements.
60+
61+
Requesting access from a default-constructed buffer should throw an exception.
62+
It is not meaningful to use a zero-sized allocation on-device. Since there is
63+
no allocation associated with the `buffer`, `cl::sycl::buffer::set_final_data`
64+
and `cl::sycl::buffer::set_write_back` should behave as if the `buffer` had a
65+
final pointer of `nullptr` at all times. The other functions in the `buffer`
66+
API should behave as though the buffer were constructed with a `range` of size
67+
zero and otherwise behave normally.
68+
69+
## Sample code
70+
71+
```c++
72+
#include <CL/sycl.hpp>
73+
using namespace sycl = cl::sycl;
74+
using namespace access = sycl::access;
75+
76+
class name;
77+
78+
void api_func(sycl::queue& q,
79+
sycl::buffer<float, 1> input, sycl::buffer<float, 1> output,
80+
sycl::buffer<float, 1> workspace = sycl::buffer<float, 1>{}) {
81+
if (!workspace) {
82+
// calculate required size for workspace
83+
constexper auto size = 2048llu;
84+
workspace = sycl::buffer<float, 1>{sycl::range<1>{size}};
85+
}
86+
// use buffer
87+
q.submit([&] (sycl::handler& cgh) {
88+
auto acc_in = input.get_access<access::mode::read>(cgh);
89+
auto acc_out = input.get_access<access::mode::write>(cgh);
90+
auto acc_workspace = input.get_access<access::mode::read_write>(cgh);
91+
cgh.single_task<name>([=]() {
92+
// uses accessors
93+
});
94+
});
95+
}
96+
```

0 commit comments

Comments
 (0)