diff --git a/source/conf.py b/source/conf.py index 44a5a0a1..c5b7d9d2 100644 --- a/source/conf.py +++ b/source/conf.py @@ -127,6 +127,12 @@ def make_ref(ref_str, ref_view, ref_sufix): "#_unified_shared_memory_pointer_queries", ) + make_ref("SYCL_SPEC_USM_ALLOC", "Section 4.8.3", "#_usm_allocations") + + make_ref("SYCL_BUFF_PROP", "Section 4.7.2.2", "#sec:buffer-properties") + + make_ref( + "SYCL_SPEC_COMMON_REFERENCE", + "Section 4.5.2", + "#sec:reference-semantics", + ) + make_ref( "SYCL_SPEC_COMMON_BYVAL", "Section 4.5.3", "#sec:byval-semantics" ) @@ -141,6 +147,7 @@ def make_ref(ref_str, ref_view, ref_sufix): "Section 3.11.2", "#sec:multi-dim-subscript", ) + + make_ref("SYCL_SPEC_BUFFER", "Section 4.7.2", "#subsec:buffers") + f""" .. _`SYCL Specification`: {sycl_ref_url} .. |true| replace:: ``true`` @@ -149,7 +156,6 @@ def make_ref(ref_str, ref_view, ref_sufix): .. _oneAPI: https://oneapi.com .. _SYCL: https://www.khronos.org/sycl/ .. |SYCL_SPEC| replace:: `SYCL Specification`_ -.. |SYCL_SPEC_BUFFER| replace:: `SYCL Specification`_ Section 4.7.2 .. |SYCL_SPEC_IMAGE| replace:: `SYCL Specification`_ Section 4.7.3 .. |SYCL_SPEC_BUFFER_ACCESSOR| replace:: `SYCL Specification`_ Section 4.7.6.9 .. |SYCL_SPEC_LOCAL_ACCESSOR| replace:: `SYCL Specification`_ Section 4.7.6.11 diff --git a/source/examples/creating-sub-buffers.cpp b/source/examples/creating-sub-buffers.cpp new file mode 100644 index 00000000..e50d4034 --- /dev/null +++ b/source/examples/creating-sub-buffers.cpp @@ -0,0 +1,59 @@ +// SPDX-FileCopyrightText: 2023 The Khronos Group Inc. +// +// SPDX-License-Identifier: Apache-2.0 + +#include + +#include + +int main() { + + // Create 2-d buffer with 8x8 ints + sycl::buffer parent_buffer{sycl::range<2>{8, 8}}; + + try { + // OK: Contiguous region from middle of buffer + sycl::buffer sub_buf1{parent_buffer, + /*offset*/ sycl::range<2>{2, 0}, + /*size*/ sycl::range<2>{2, 8}}; + + std::cout << "sub_buf1 created successfully" << std::endl; + } catch (const sycl::exception &e) { + std::cerr << "Exception while creating sub_buf1: " << e.what() << std::endl; + } + + try { + // invalid exception: Non-contiguous regions of 2-d buffer + sycl::buffer sub_buf2{parent_buffer, + /*offset*/ sycl::range<2>{2, 0}, + /*size*/ sycl::range<2>{2, 2}}; + + std::cout << "sub_buf2 created successfully" << std::endl; + } catch (const sycl::exception &e) { + std::cerr << "Exception while creating sub_buf2: " << e.what() << std::endl; + } + + try { + // invalid exception: Non-contiguous regions of 2-d buffer + sycl::buffer sub_buf3{parent_buffer, + /*offset*/ sycl::range<2>{2, 2}, + /*size*/ sycl::range<2>{2, 6}}; + + std::cout << "sub_buf3 created successfully" << std::endl; + } catch (const sycl::exception &e) { + std::cerr << "Exception while creating sub_buf3: " << e.what() << std::endl; + } + + try { + // invalid exception: Out-of-bounds size + sycl::buffer sub_buf4{parent_buffer, + /*offset*/ sycl::range<2>{2, 2}, + /*size*/ sycl::range<2>{2, 8}}; + + std::cout << "sub_buf4 created successfully" << std::endl; + } catch (const sycl::exception &e) { + std::cerr << "Exception while creating sub_buf4: " << e.what() << std::endl; + } + + return 0; +} diff --git a/source/examples/creating-sub-buffers.out b/source/examples/creating-sub-buffers.out new file mode 100644 index 00000000..4699cb70 --- /dev/null +++ b/source/examples/creating-sub-buffers.out @@ -0,0 +1,8 @@ +# SPDX-FileCopyrightText: 2020 The Khronos Group Inc. +# +# SPDX-License-Identifier: CC-BY-4.0 + +sub_buf1 created successfully +Exception while creating sub_buf2: Requested sub-buffer region is not contiguous -30 (PI_ERROR_INVALID_VALUE) +Exception while creating sub_buf3: Requested sub-buffer region is not contiguous -30 (PI_ERROR_INVALID_VALUE) +Exception while creating sub_buf4: Requested sub-buffer size exceeds the size of the parent buffer -30 (PI_ERROR_INVALID_VALUE) diff --git a/source/iface/buffer.rst b/source/iface/buffer.rst index d0b748d2..20657640 100644 --- a/source/iface/buffer.rst +++ b/source/iface/buffer.rst @@ -4,10 +4,9 @@ .. _iface-buffers: -********* - Buffers -********* - +******* +Buffers +******* .. _buffer: @@ -17,143 +16,381 @@ :: - template - class buffer; + template >> + class buffer; .. rubric:: Template parameters ================ ========== -``T`` Type of data in buffer -``dimensions`` Dimensionality of data: 1, 2, or 3 -``AllocatorT`` Allocator for buffer data +``T`` Type of data in buffer. +``Dimensions`` Dimensionality of data: 1, 2, or 3. +``AllocatorT`` Allocator for buffer data. ================ ========== -Buffers are containers for data that can be read/written by both -kernel and host. Data in a buffer cannot be directly accessed via -pointers. Instead, a program creates an `buffer-accessor` that -references the buffer. The accessor provides array-like interfaces to -read/write actual data. Accessors indicate when they read or write -data. When a program creates an accessor for a buffer, the SYCL -runtime copies the data to where it is needed, either the host or the -device. If the accessor is part of a device command group, then the -runtime delays execution of the kernel until the data movement is -complete. If the host creates an accessor, it will pause until the -data is available on the host. As a result data and kernels can -execute asynchronously and in parallel, only requiring the program to -specify the data dependencies. - -Initialization - Buffers can be automatically initialized via host data, iterator, or - as a slice of another buffer. The constructor determines the - initialization method. - -Write back - The destructor for a buffer can optionally write the data back to - host memory, either by pointer or iterator. set_final_data_ and - set_write_back_ control the write back of data. - -Memory allocation - The SYCL runtimes uses the default allocator for buffer memory - allocation, unless the constructor provides an allocator. - - -.. rubric:: Member types - -=================== ========== -``value_type`` type of buffer element -``reference`` reference type of buffer element -``const_reference`` ``const`` reference type of buffer element -``allocator_type`` type of allocator for buffer data -=================== ========== +The ``sycl::buffer`` class defines a shared array of one, +two or three dimensions that can be used by the SYCL kernel +and has to be accessed using :ref:`accessor classes `. +Buffers are templated on both the type of their data, and the number +of dimensions that the data is stored and accessed through. + +A ``sycl::buffer`` does not map to only one underlying backend object, +and all SYCL backend memory objects may be temporary for use within a +command group on a specific device. + +The underlying data type of a buffer ``T`` must be device copyable. +Some overloads of the ``sycl::buffer`` constructor initialize the buffer +contents by copying objects from host memory while other overloads +construct the buffer without copying objects from the host. For the +overloads that do not copy host objects, the initial state of the +objects in the buffer depends on whether ``T`` is an implicit-lifetime +type (as defined in the C++ core language). + +* If ``T`` is an implicit-lifetime type, objects of that type are + implicitly created in the buffer with indeterminate values. +* For other types, these constructor overloads merely allocate uninitialized + memory, and the application is responsible for constructing objects by + calling placement-new and for destroying them later by manually calling + the object's destructor. + +The SYCL buffer class template provides the :ref:`common-reference`. + +The ``sycl::buffer`` class template takes a template parameter ``AllocatorT`` +for specifying an allocator which is used by the SYCL runtime when allocating +temporary memory on the host. If no template argument is provided, +then the default allocator for the ``sycl::buffer`` +class ``buffer_allocator`` will be used. + +.. seealso:: |SYCL_SPEC_BUFFER| + +Member Types +============ -.. seealso:: +.. list-table:: + :header-rows: 1 - |SYCL_SPEC_BUFFER| + * - Type + - Description + * - ``value_type`` + - Type of buffer elements (``T``). + * - ``reference`` + - Reference type of buffer elements (``value_type&``). + * - ``const_reference`` + - Constant reference type of buffer element (``const value_type&``). + * - ``allocator_type`` + - Type of allocator for buffer data (``AllocatorT``). .. _buffer-constructors: (constructors) ============== -.. parsed-literal:: - - buffer(const sycl::range &bufferRange, - const sycl::property_list &propList = {}); - buffer(const sycl::range &bufferRange, AllocatorT allocator, - const sycl::property_list &propList = {}); - buffer(T *hostData, const sycl::range &bufferRange, - const sycl::property_list &propList = {}); - buffer(T *hostData, const sycl::range &bufferRange, - AllocatorT allocator, const sycl::property_list &propList = {}); - buffer(const T *hostData, const sycl::range &bufferRange, - const sycl::property_list &propList = {}); - buffer(const T *hostData, const sycl::range &bufferRange, - AllocatorT allocator, const sycl::property_list &propList = {}); - buffer(const shared_ptr_class &hostData, - const sycl::range &bufferRange, AllocatorT allocator, - const sycl::property_list &propList = {}); - buffer(const shared_ptr_class &hostData, - const sycl::range &bufferRange, - const sycl::property_list &propList = {}); - buffer(buffer b, const id &baseIndex, - const sycl::range &subRange); - - *Available only when: - dimensions == 1* - - template - buffer(InputIterator first, InputIterator last, AllocatorT allocator, - const sycl::property_list &propList = {}); - template - buffer(InputIterator first, InputIterator last, - const sycl::property_list &propList = {}); - buffer(cl_mem clMemObject, const sycl::context &syclContext, - event availableEvent = {}); - -Construct a buffer. - -Buffers can be initialized by a host data pointer. While the buffer -exists, it *owns* the host data and direct access of the host data -pointer during that time is undefined. The SYCL runtime performs a -write back of the buffer data back to the host data pointer when the -buffer is destroyed. Buffers can also be initialized as a slice of -another buffer, by specifying the origin of the data and the -dimensions. - -A constructor can also accept ``cl_mem`` or iterators to initialize a -buffer. +Each constructor takes as the last parameter an optional +``sycl::property_list`` to provide properties to the ``sycl::buffer``. +Zero or more properties can be provided to the +constructed ``sycl::buffer`` via an instance of ``sycl::property_list``. + +For the overloads that do copy objects from host memory, the ``hostData`` +pointer must point to at least `N` bytes of memory where `N` is +``sizeof(T) * bufferRange.size()``. +If `N` is zero, ``hostData`` is permitted to be a null pointer. + +.. rubric:: Constructors 1-2 + +:: + + buffer(const sycl::range& bufferRange, + const sycl::property_list& propList = {}); + + buffer(const sycl::range& bufferRange, + AllocatorT allocator, + const sycl::property_list& propList = {}); + +Construct a ``sycl::buffer`` instance with uninitialized memory. + +The constructed ``sycl::buffer`` will use the ``allocator`` +parameter provided when allocating memory on the host. +If this parameter is not specified, the constructed +``sycl::buffer`` will use a default constructed +``AllocatorT`` when allocating memory on the host. + +Data is not written back to the host on destruction of the buffer +unless the buffer has a valid non-null pointer specified via +the member function ``set_final_data()``. + + +.. rubric:: Constructors 3-4 + +:: + + buffer(T* hostData, + const sycl::range& bufferRange, + const sycl::property_list& propList = {}); + + buffer(T* hostData, + const sycl::range& bufferRange, + AllocatorT allocator, + const sycl::property_list& propList = {}); + +Construct a ``sycl::buffer`` instance with the +``hostData`` parameter provided. +The buffer is initialized with the memory specified by ``hostData``, +and the buffer assumes exclusive access to this memory for the +duration of its lifetime. + +The constructed ``sycl::buffer`` will use the ``allocator`` +parameter provided when allocating memory on the host. +If this parameter is not specified, the constructed +``sycl::buffer`` will use a default constructed +``AllocatorT`` when allocating memory on the host. + + +.. rubric:: Constructors 5-6 + +:: + + buffer(const T* hostData, + const sycl::range& bufferRange, + const sycl::property_list& propList = {}); + + buffer(const T* hostData, + const sycl::range& bufferRange, + AllocatorT allocator, + const sycl::property_list& propList = {}); + +Construct a ``sycl::buffer`` instance with the ``hostData`` parameter +provided. The buffer assumes exclusive access to this memory for +the duration of its lifetime. + +The constructed ``sycl::buffer`` will use the ``allocator`` +parameter provided when allocating memory on the host. +If this parameter is not specified, the constructed +``sycl::buffer`` will use a default constructed +``AllocatorT`` when allocating memory on the host. + +The host address is ``const T``, so the host accesses can be +read-only. However, the ``typename T`` is not ``const`` so the +device accesses can be both read and write accesses. + +Since the ``hostData`` is ``const``, this buffer is only initialized +with this memory and there is no write back after its destruction, +unless the ``sycl::buffer`` has another valid non-null final data +address specified via the member function ``set_final_data()`` +after construction of the ``sycl::buffer``. + + +.. rubric:: Constructors 7-8 + +:: + + template + buffer(Container& container, + const sycl::property_list& propList = {}); + + template + buffer(Container& container, + AllocatorT allocator, + const sycl::property_list& propList = {}); + +Construct a one dimensional ``sycl::buffer`` instance from the +elements starting at ``std::data(container)`` and containing +``std::size(container)`` number of elements. +The buffer is initialized with the contents of ``container``, +and the buffer assumes exclusive access to ``container`` for +the duration of its lifetime. + +Data is written back to ``container`` before the completion of +``sycl::buffer`` destruction if the return type of +``std::data(container)`` is not ``const``. + +The constructed ``sycl::buffer`` will use the ``allocator`` +parameter provided when allocating memory on the host. +If this parameter is not specified, the constructed +``sycl::buffer`` will use a default constructed +``AllocatorT`` when allocating memory on the host. + +This constructor is only defined for a buffer parameterized +with ``Dimensions == 1``, and when ``std::data(container)`` +is convertible to ``T*``. + + +.. rubric:: Constructors 9-12 + +:: + + buffer(const std::shared_ptr& hostData, + const sycl::range& bufferRange, + const sycl::property_list& propList = {}); + + buffer(const std::shared_ptr& hostData, + const sycl::range& bufferRange, + const sycl::property_list& propList = {}); + + buffer(const std::shared_ptr& hostData, + const sycl::range& bufferRange, + AllocatorT allocator, + const sycl::property_list& propList = {}); + + buffer(const std::shared_ptr& hostData, + const sycl::range& bufferRange, + AllocatorT allocator, + const sycl::property_list& propList = {}); + +When ``hostData`` is not empty, construct a ``sycl::buffer`` +with the contents of its stored pointer. The buffer assumes +exclusive access to this memory for the duration of its lifetime. + +The buffer also creates its own internal copy of the ``std::shared_ptr`` +that shares ownership of the ``hostData`` memory, which means the +application can safely release ownership of this ``std::shared_ptr`` +when the constructor returns. + +When ``hostData`` is empty, construct a SYCL +buffer with uninitialized memory. + +The constructed ``sycl::buffer`` will use the ``allocator`` +parameter provided when allocating memory on the host. +If this parameter is not specified, the constructed +``sycl::buffer`` will use a default constructed +``AllocatorT`` when allocating memory on the host. + + +.. rubric:: Constructors 13-14 + +:: + + template + buffer(InputIterator first, InputIterator last, + const sycl::property_list& propList = {}); + + template + buffer(InputIterator first, InputIterator last, + AllocatorT allocator = {}, + const sycl::property_list& propList = {}); + +Create a new allocated one dimension ``sycl::buffer`` initialized +from the given elements ranging from ``first`` up to one before ``last``. + +The data is copied to an intermediate memory position by the runtime. + +Data is not written back to the same iterator set provided. +However, if the ``sycl::buffer`` has a valid non-constant iterator +specified via the member function ``set_final_data()``, +data will be copied back to that iterator. + +The constructed ``sycl::buffer`` will use the ``allocator`` +parameter provided when allocating memory on the host. +If this parameter is not specified, the constructed +``sycl::buffer`` will use a default constructed +``AllocatorT`` when allocating memory on the host. + + +.. rubric:: Constructor 15 + +:: + + buffer(sycl::buffer& b, + const sycl::id& baseIndex, + const sycl::range& subRange) + +Create a new sub-buffer without allocation to have +separate accessors later. + +``b`` is the buffer with the real data, which must not +be a sub-buffer. + +``baseIndex`` specifies the origin of the sub-buffer +inside the buffer ``b``. +``subRange`` specifies the size of the sub-buffer. +The offset and range specified by ``baseIndex`` and ``subRange`` +together must represent a contiguous region of the +original ``sycl::buffer``. + +The origin (based on ``baseIndex``) of the sub-buffer being +constructed must be a multiple of the memory base address +alignment of each :ref:`device` which accesses data from +the buffer. This value is retrievable via the :ref:`device` +class info query ``sycl::info::device::mem_base_addr_align``. + +Violating this requirement causes the implementation to throw +an ``exception`` with the ``errc::invalid`` error code from +the :ref:`command-accessor` constructor (if the accessor +is not a placeholder) or from ``sycl::handler::require()`` +(if the accessor is a placeholder). +If the accessor is bound to a command group with a secondary +queue, the sub-buffer's alignment must be compatible with +both the primary queue's device and the secondary queue's +device, otherwise this exception is thrown. .. rubric:: Template parameters ================= ========== -``InputIterator`` type of iterator used to initialize the buffer +``Container`` Type of the ``container`` used to + initialize the buffer. +``InputIterator`` Type of iterator used to initialize the buffer. ================= ========== .. rubric:: Parameters ================ ========== -``bufferRange`` :ref:`range` specifies the dimensions of the buffer -``allocator`` Allocator for buffer data -``propList`` See `Buffer properties`_ -``hostData`` Pointer to host memory to hold data -``first`` Iterator to initialize buffer -``last`` Iterator to initialize buffer -``b`` Buffer used to initialize this buffer -``baseIndx`` Origin of sub-buffer -``subRange`` Dimensions of sub-buffer +``bufferRange`` :ref:`range` specifies the dimensions of the buffer. +``allocator`` Allocator for the buffer data. In case this parameter + is absent, the ``sycl::buffer`` will use a default + constructed ``AllocatorT`` when allocating memory + on the host. +``propList`` See `Buffer properties`_. +``hostData`` Pointer to host memory to hold data. +``first`` Beginning iterator to initialize the buffer. +``last`` Ending iterator to initialize the buffer. +``b`` Parent buffer used to initialize this buffer. +``baseIndx`` Origin of the sub-buffer. +``subRange`` Dimensions of the sub-buffer. ================ ========== +.. rubric:: Exceptions + +``errc::invalid`` + An exception with this error code will be thrown in + the constructor 15 in such cases: + + 1. If the sum of ``baseIndex`` and ``subRange`` in any dimension + exceeds the parent buffer (``b``) size (``bufferRange``) + in that dimension. + 2. If a non-contiguous region of a buffer is requested + when constructing a sub-buffer. + 3. If ``b`` is a sub-buffer. + +.. rubric:: Example + +See :ref:`sub_buf_example`. + +================ +Member functions +================ ``get_range`` ============= :: - sycl::range get_range() const; + sycl::range get_range() const; + +Return a :ref:`range` object representing the size of the +buffer in terms of number of elements in each dimension as +passed to the constructor. + + +``size`` +======== + +:: + + size_t size() const noexcept; + +Returns the total number of elements in the buffer. +Equal to ``get_range()[0] * ... * get_range()[Dimensions-1]``. -Returns the dimensions of the buffer. ``get_count`` ============= @@ -162,7 +399,19 @@ Returns the dimensions of the buffer. size_t get_count() const; -Returns the total number of elements in the buffer. +Deprecated. Returns the same value as size(). + + +``byte_size`` +============= + +:: + + size_t byte_size() const noexcept; + +Returns the size of the buffer storage in bytes. + +Equal to ``size()*sizeof(T)``. ``get_size`` @@ -172,8 +421,7 @@ Returns the total number of elements in the buffer. size_t get_size() const; - -Returns the size of the buffer storage in bytes. +Deprecated. Returns the same value as ``byte_size()``. ``get_allocator`` @@ -181,11 +429,11 @@ Returns the size of the buffer storage in bytes. :: - AllocatorT get_allocator() const; - + AllocatorT get_allocator() const Returns the allocator provided to the buffer. + .. _buffer-get_access: ``get_access`` @@ -193,36 +441,104 @@ Returns the allocator provided to the buffer. :: - template - accessor get_access( - sycl::handler &commandGroupHandler); - template - accessor get_access(); - template - accessor get_access( - sycl::handler &commandGroupHandler, sycl::range accessRange, - id accessOffset = {}); - template - accessor get_access( - sycl::range accessRange, sycl::id accessOffset = {}); + template + sycl::accessor get_access(sycl::handler& commandGroupHandler); -Returns a accessor to the buffer. +Returns a valid :ref:`command-accessor` to the buffer with the specified access +mode and target in the command group buffer. + +The value of target can be ``sycl::target::device`` or +``sycl::target::constant_buffer``. + +:: + + template + sycl::accessor get_access(sycl::handler& commandGroupHandler, + sycl::range accessRange, + sycl::id accessOffset = {}); + +Returns a valid :ref:`command-accessor` to the buffer with the specified +access mode and target in the command group buffer. +The accessor is a ranged accessor, where the range starts at the given +offset from the beginning of the buffer. + +The value of target can be ``sycl::target::device`` or +``sycl::target::constant_buffer``. + +:: + + template + auto get_access(Ts... args); + +Returns a valid :ref:`command-accessor` as if constructed via passing the +buffer and all provided arguments to the ``sycl::accessor`` constructor. + +Possible implementation: ``return sycl::accessor{*this, args...};`` + +.. rubric:: Deprecated in SYCL 2020 + +:: + + template + sycl::accessor get_access(); + +Deprecated in SYCL 2020. Use ``get_host_access()`` instead. + +Returns a valid host ``sycl::accessor`` to the buffer with the +specified access mode and target. + +:: + + template + sycl::accessor + get_access(sycl::range accessRange, + sycl::id accessOffset = {}); + +Deprecated in SYCL 2020. Use ``get_host_access()`` instead. + +Returns a valid host ``sycl::accessor`` to the buffer with the specified +access mode and target. +The accessor is a ranged accessor, where the range starts at the given +offset from the beginning of the buffer. + +The value of target can only be ``sycl::target::host_buffer``. .. rubric:: Template parameters ================ ========== -``mode`` See :ref:`access-mode` -``target`` See :ref:`access-target` +``mode`` See :ref:`access-mode`. +``target`` See :ref:`access-target`. ================ ========== .. rubric:: Parameters ======================= ========== -``commandGroupHandler`` Command group that uses the accessor -``accessRange`` Dimensions of the sub-buffer that is accessed -``accessOffset`` Origin of the sub-buffer that is accessed +``commandGroupHandler`` Command group that uses the accessor. +``accessRange`` Dimensions of the sub-buffer that is accessed. +``accessOffset`` Origin of the sub-buffer that is accessed. ======================= ========== +.. rubric:: Exceptions + +``errc::invalid`` + If the sum of ``accessRange`` and ``accessOffset`` exceeds + the range of the buffer in any dimension. + + +``get_host_access`` +=================== + +:: + + template + auto get_host_access(Ts... args); + +Returns a valid :ref:`host_accessor` as if constructed via passing the +buffer and all provided arguments to the ``sycl::host_accessor`` constructor. + +Possible implementation: ``return sycl::host_accessor{*this, args...};`` ``set_final_data`` ================== @@ -232,21 +548,30 @@ Returns a accessor to the buffer. template void set_final_data(Destination finalData = nullptr); +The ``finalData`` points to where the outcome of all the buffer +processing is going to be copied to at destruction time, if the buffer +was involved with a write accessor + +Note that a raw pointer is a special case of output iterator and thus +defines the host memory to which the result is to be copied. + +In the case of a weak pointer, the output is not updated if the weak +pointer has expired. + +If ``Destination`` is ``std::nullptr_t``, then the copy back will not happen. + .. rubric:: Template parameters =================== ========== -``Destination`` ``std::weak_ptr`` or output iterator +``Destination`` Output iterator or ``std::weak_ptr``. =================== ========== .. rubric:: Parameters =================== ========== -``finalData`` Indicates where data is copied at destruction time +``finalData`` Indicates where data is copied at destruction time. =================== ========== -Set the final data location. Final data controls the location for -write back when the buffer is destroyed. - ``set_write_back`` ================== @@ -255,13 +580,15 @@ write back when the buffer is destroyed. void set_write_back(bool flag = true); -.. rubric:: Parameters +This member function allows dynamically forcing or canceling the +write-back of the data of a buffer on destruction according to +the value of ``flag``. -=================== ========== -``flag`` True to force write back -=================== ========== +Forcing the write-back is similar to what happens during a normal write-back. + +If there is nowhere to write-back, using this function does +not have any effect. -Set the write back. ``is_sub_buffer`` ================= @@ -270,55 +597,128 @@ Set the write back. bool is_sub_buffer() const; -Returns True if this is a sub-buffer. +Returns ``true`` if this ``sycl::buffer`` is a sub-buffer, +otherwise returns ``false``. ``reinterpret`` =============== +A ``sycl::buffer`` can construct an instance of a ``sycl::buffer`` +that reinterprets the original ``sycl::buffer`` with a different +type, dimensionality and range using the member function ``reinterpret``. + :: template - buffer - reinterpret(range reinterpretRange) const; + sycl::buffer::template rebind_alloc< + std::remove_const_t>> + reinterpret(sycl::range reinterpretRange) const; + +Creates and returns a reinterpreted ``sycl::buffer`` with the +type specified by ``ReinterpretT``, dimensions specified by +``ReinterpretDim`` and range specified by ``reinterpretRange``. + +The buffer object being reinterpreted can be a SYCL sub-buffer +that was created from a ``sycl::buffer``. + +Reinterpreting a sub-buffer provides a reinterpreted view of the +sub-buffer only, and does not change the offset or size of the +sub-buffer view (in bytes) relative to the parent ``sycl::buffer``. + +:: + + template + sycl::buffer::template rebind_alloc< + std::remove_const_t>> + reinterpret() const; + +Creates and returns a reinterpreted ``sycl::buffer`` with the type specified by +``ReinterpretT`` and dimensions specified by ``ReinterpretDim``. + +Only valid when ``(ReinterpretDim == 1)`` or when +``((ReinterpretDim == Dimensions) && (sizeof(ReinterpretT) == sizeof(T)))``. + +The buffer object being reinterpreted can be a SYCL sub-buffer that was created +from a SYCL buffer. + +Reinterpreting a sub-buffer provides a reinterpreted view of the +sub-buffer only, and does not change the offset or size of the +sub-buffer view (in bytes) relative to the parent ``sycl::buffer``. .. rubric:: Template parameters =================== ========== -``ReinterpretT`` Type of new buffer element -``ReinterpretDim`` Dimensions of new buffer +``ReinterpretT`` Type of the new buffer element. +``ReinterpretDim`` Dimensions of the new buffer. =================== ========== .. rubric:: Parameters ==================== ========== -``ReinterpretRange`` Dimensionality of new buffer +``reinterpretRange`` Dimensionality of the new buffer. ==================== ========== -Creates a new buffer with the requested element type and -dimensionality, containing the data of the passed buffer or -sub-buffer. - .. rubric:: Exceptions -``errc::invalid_object_error`` - Size in bytes of new buffer does not match original buffer. +``errc::invalid`` + 1. If the total size in bytes represented by the type and range of + the reinterpreted ``sycl::buffer`` (or sub-buffer) does not equal + the total size in bytes represented by the type and range of this + ``sycl::buffer`` (or sub-buffer). + 2. If the total size in bytes represented by this ``sycl::buffer`` + (or sub-buffer) is not evenly divisible by ``sizeof(ReinterpretT)``. -================== - Buffer properties -================== +================= +Buffer properties +================= -.. rst-class:: api-class +The properties that can be provided when +constructing the ``sycl::buffer``. + +:: -``sycl::property::buffer:use_host_ptr`` -======================================= + namespace sycl::property { + + namespace buffer { + + class use_host_ptr; + + class use_mutex; + + class context_bound; + + } // namespace buffer + + } // namespace sycl::property + + +``sycl::property::buffer::use_host_ptr`` +======================================== :: - class use_host_ptr; + namespace sycl::property::buffer { + + class use_host_ptr { + public: + use_host_ptr() = default; + }; + + } // namespace sycl::property::buffer + +The ``sycl::property::buffer::use_host_ptr`` property adds the requirement +that the SYCL runtime must not allocate any memory for the ``sycl::buffer`` +and instead uses the provided host pointer directly. This prevents the SYCL +runtime from allocating additional temporary storage on the host. -Use the provided host pointer and do not allocate new data on the -host. +This property has a special guarantee for buffers that are constructed +from a ``hostData`` pointer. If a ``sycl::host_accessor`` is constructed from +such a buffer, then the address of the reference type returned from the +accessor's member functions such as ``operator[](id<>)`` will be the same +as the corresponding ``hostData`` address. .. _use_host_ptr-constructors: @@ -327,21 +727,37 @@ host. :: - use_host_ptr(); + sycl::property::buffer::use_host_ptr::use_host_ptr(); +Constructs a ``sycl::property::buffer::use_host_ptr`` property instance. -.. rst-class:: api-class -``sycl::property::use_mutex`` -============================= +``sycl::property::buffer::use_mutex`` +===================================== :: - class use_mutex; + namespace sycl::property::buffer { -Adds the requirement that the memory owned by the SYCL buffer can be -shared with the application via a ``std::mutex`` provided to the -property. + class use_mutex { + public: + use_mutex(std::mutex& mutexRef); + + std::mutex* get_mutex_ptr() const; + }; + + } // namespace sycl::property::buffer + +The ``sycl::property::buffer::use_mutex`` property is valid for the +``sycl::buffer``, `unsampled_image` and `sampled_image` classes. + +The property adds the requirement that the memory which is owned by +the ``sycl::buffer`` can be shared with the application via a +``std::mutex`` provided to the property. + +The mutex is locked by the runtime whenever the data is in use and +unlocked otherwise. Data is synchronized with ``hostData``, when +the mutex is unlocked by the runtime. .. _use_mutex-constructors: @@ -350,43 +766,200 @@ property. :: - use_mutex(); + sycl::property::buffer::use_mutex::use_mutex(std::mutex& mutexRef); +Constructs a ``sycl::property::buffer::use_mutex`` property instance +with a reference to ``mutexRef`` parameter provided. ``get_mutex_ptr`` ----------------- :: - sycl::mutex_class *get_mutex_ptr() const; + std::mutex* sycl::property::buffer::use_mutex::get_mutex_ptr() const; + +Returns the ``std::mutex`` which was specified when constructing +this ``sycl::property::buffer::use_mutex`` property. ``sycl::property::buffer::context_bound`` ========================================= - :: - class context_bound; + namespace sycl::property::buffer { + + class context_bound { + public: + context_bound(context boundContext); + + context get_context() const; + }; + } // namespace sycl::property::buffer -The buffer can only be associated with a single SYCL context provided -to the property. + +The ``sycl::property::buffer::context_bound`` property adds the +requirement that the ``sycl::buffer`` can only be associated +with a single :ref:`context` that is provided to the property. .. _context_bound-constructors: (constructors) -------------- - :: - use_mutex(); + sycl::property::buffer::context_bound(sycl::context boundContext); +Constructs a ``sycl::property::buffer::context_bound`` property +instance with a copy of a :ref:`context`. ``get_context`` --------------- :: - sycl::context get_context() const; + sycl::context sycl::property::buffer::context_bound::get_context() const; + +Returns the :ref:`context` which was specified when constructing +this ``sycl::property::buffer::context_bound`` property. + +============================ +Buffer synchronization rules +============================ + +Buffer lifetime and destruction +=============================== + +Buffers are reference-counted. When a buffer value is constructed +from another buffer, the two values reference the same buffer and +a reference count is incremented. When a buffer value is destroyed, +the reference count is decremented. Only when there are no more +buffer values that reference a specific buffer is the actual buffer +destroyed and the buffer destruction behavior defined below is followed. + +If any error occurs on buffer destruction, it is reported via the +associated queue's asynchronous error handling mechanism. + +The basic rule for the blocking behavior of a buffer destructor is that +it blocks if there is some data to write back because a write accessor +on it has been created, or if the buffer was constructed with attached +host memory and is still in use. + +More precisely: + + 1. A buffer can be constructed from a :ref:`range` + (and without a ``hostData`` pointer). The memory + management for this type of buffer is entirely handled + by the SYCL system. The destructor for this type of buffer + does not need to block, even if work on the buffer has not + completed. Instead, the SYCL system frees any storage + required for the buffer asynchronously when it is no longer + in use in queues. The initial contents of the buffer are unspecified. + 2. A buffer can be constructed from a ``hostData`` pointer. The buffer + will use this host memory for its full lifetime, but the contents of + this host memory are unspecified for the lifetime of the buffer. + If the host memory is modified on the host or if it is used to + construct another buffer or image during the lifetime of this + buffer, then the results are undefined. The initial contents of + the buffer will be the contents of the host memory at the time + of construction. + + When the buffer is destroyed, the destructor will block until all + work in queues on the buffer have completed, then copy the contents + of the buffer back to the host memory (if required) and then return. + + a. If the type of the host data is ``const``, then the buffer is + read-only; only read accessors are allowed on the buffer and + no-copy-back to host memory is performed (although the host + memory must still be kept available for use by SYCL). When + using the default buffer allocator, the constantness of the + type will be removed in order to allow host allocation of + memory, which will allow temporary host copies of the data + by the SYCL runtime, for example for speeding up host accesses. + b. If the type of the host data is not ``const`` but the pointer + to host data is ``const``, then the read-only restriction + applies only on host and not on device accesses. + + When the buffer is destroyed, the destructor will block until + all work in queues on the buffer have completed. + 3. A buffer can be constructed using a ``std::shared_ptr`` to host + data. This pointer is shared between the SYCL application and + the runtime. In order to allow synchronization between the + application and the runtime a ``std::mutex`` is used which will be + locked by the runtime whenever the data is in use, and unlocked + when it is no longer needed. + + The ``std::shared_ptr`` reference counting is used in order to + prevent destroying the buffer host data prematurely. If the + ``std::shared_ptr`` is deleted from the user application + before buffer destruction, the buffer can continue securely + because the pointer hasn't been destroyed yet. It will not + copy data back to the host before destruction, however, as + the application side has already deleted its copy. + + .. note:: + Since there is an implicit conversion of a ``std::unique_ptr`` + to a ``std::shared_ptr``, a ``std::unique_ptr`` can also be + used to pass the ownership to the SYCL runtime. + 4. A buffer can be constructed from a pair of iterator values. In this + case, the buffer construction will copy the data from the data range + defined by the iterator pair. The destructor will not copy back any + data and does not need to block. + 5. A buffer can be constructed from a container on which + ``std::data(container)`` and ``std::size(container)`` are well-formed. + The initial contents of the buffer will be the contents of the + container at the time of construction. + + The buffer may use the memory within the container for its + full lifetime, and the contents of this memory are unspecified + for the lifetime of the buffer. If the container memory is modified + by the host during the lifetime of this buffer, then the results are + undefined. + + When the buffer is destroyed, the destructor will block until all + work in queues on the buffer have completed. If the return type of + ``std::data(container)`` is not ``const`` then the destructor will + also copy the contents of the buffer to the container (if required). + +If ``set_final_data()`` is used to change where to write the data +back to, then the destructor of the buffer will block if a write +accessor on it has been created. + +Sub-buffers +=========== + +A sub-buffer object can be created, which is a sub-range reference +to a base buffer. This sub-buffer can be used to create accessors +to the base buffer, which have access to the range specified at +time of construction of the sub-buffer. Sub-buffers cannot be +created from sub-buffers, but only from a base buffer which is +not already a sub-buffer. + +Sub-buffers must be constructed from a contiguous region of +memory in a buffer. This requirement is potentially non-intuitive +when working with buffers that have dimensionality larger than one, +but maps to one-dimensional SYCL backend native allocations without +performance cost due to index mapping computation. + +.. rubric:: Example + +See :ref:`sub_buf_example`. + +.. _sub_buf_example: + +========= +Example 1 +========= + +An example of creating sub-buffers from a parent buffer: + +.. literalinclude:: /examples/creating-sub-buffers.cpp + :lines: 5- + :linenos: + +Output: + +.. literalinclude:: /examples/creating-sub-buffers.out + :lines: 5- diff --git a/source/iface/command-group-handler.rst b/source/iface/command-group-handler.rst index 696a09ea..092a768f 100644 --- a/source/iface/command-group-handler.rst +++ b/source/iface/command-group-handler.rst @@ -4,11 +4,9 @@ .. _handler: -.. rst-class:: api-class - -================= +***************** ``sycl::handler`` -================= +***************** :: @@ -21,9 +19,13 @@ A ``handler`` can only be constructed by the SYCL runtime and is passed as an argument to the command group function. The command group function is an argument to :ref:`queue-submit`. - .. seealso:: |SYCL_SPEC_HANDLER| + +================= +Member functions +================= + ``require`` =========== @@ -71,7 +73,6 @@ usage. .. _handler-parallel_for: - ``parallel_for`` ================ diff --git a/source/iface/command-group.rst b/source/iface/command-group.rst deleted file mode 100644 index b23bd880..00000000 --- a/source/iface/command-group.rst +++ /dev/null @@ -1,46 +0,0 @@ -.. - Copyright 2020 The Khronos Group Inc. - SPDX-License-Identifier: CC-BY-4.0 - -.. _command_group: - -.. rst-class:: api-class - -======================= -``sycl::command_group`` -======================= -:: - - class command_group; - -(constructors) -============== - -:: - - template - command_group(sycl::queue &primaryQueue, const functorT &lambda); - template - command_group(sycl::queue &primaryQueue, sycl::queue &secondaryQueue, - const functorT &lambda); - -``start_event`` -=============== - -:: - - sycl::event start_event(); - -``kernel_event`` -================ - -:: - - sycl::event kernel_event(); - -``complete_event`` -================== - -:: - - sycl::event complete_event(); diff --git a/source/iface/common-reference.rst b/source/iface/common-reference.rst index e3ad2375..f75b7724 100644 --- a/source/iface/common-reference.rst +++ b/source/iface/common-reference.rst @@ -4,30 +4,162 @@ .. _common-reference: -===================== - Reference Semantics -===================== +************************** +Common Reference Semantics +************************** -Classes: :ref:`sycl::accessor`, -:ref:`sycl::buffer`, :ref:`context`, :ref:`device`, +.. + Add missing references after updating Data Access + and Expressing Parallelism chapter structure + +Each of the following SYCL runtime classes: +`sycl::accessor`, `sycl::buffer`, :ref:`context`, :ref:`device`, `device_image`, :ref:`event`, `host_accessor`, `host_sampled_image_accessor`, `host_unsampled_image_accessor`, :ref:`kernel`, `kernel_id`, `kernel_bundle`, `local_accessor`, :ref:`platform`, :ref:`queue`, `sampled_image`, -`sampled_image_accessor`, `unsampled_image` and `unsampled_image_accessor`. +`sampled_image_accessor`, `unsampled_image` and `unsampled_image_accessor` +must obey the following statements, where ``T`` is the runtime class type: + +* ``T`` must be copy constructible and copy assignable in the host application + and within SYCL kernel functions in the case that ``T`` is a valid kernel argument. + Any instance of ``T`` that is constructed as a copy of another instance, + via either the copy constructor or copy assignment operator, must behave as-if it + were the original instance and as-if any action performed on it were also performed + on the original instance and must represent the same underlying native backend object + as the original instance where applicable. +* ``T`` must be destructible in the host application and within SYCL kernel functions + in the case that ``T`` is a valid kernel argument. When any instance of ``T`` is + destroyed, including as a result of the copy assignment operator, any behavior + specific to T that is specified as performed on destruction is only performed + if this instance is the last remaining host copy, in accordance with the above + definition of a copy. +* ``T`` must be move constructible and move assignable in the host application + and within SYCL kernel functions in the case that T is a valid kernel argument. + Any instance of T that is constructed as a move of another instance, via either + the move constructor or move assignment operator, must replace the original + instance rendering said instance invalid and must represent the same underlying + native backend object as the original instance where applicable. +* ``T`` must be equality comparable in the host application. Equality between two + instances of T (i.e. ``a == b``) must be true if one instance is a copy of the + other and non-equality between two instances of ``T`` (i.e. ``a != b``) must + be true if neither instance is a copy of the other, in accordance with the + above definition of a copy, unless either instance has become invalidated + by a move operation. By extension of the requirements above, equality on ``T`` + must guarantee to be reflexive (i.e. ``a == a``), symmetric (i.e. ``a == b`` + implies ``b == a`` and ``a != b`` implies ``b != a``) and + transitive (i.e. ``a == b && b == c`` implies ``c == a``). +* A specialization of ``std::hash`` for ``T`` must exist on the host application + that returns a unique value such that if two instances of T are equal, in + accordance with the above definition, then their resulting hash values are + also equal and subsequently if two hash values are not equal, then their + corresponding instances are also not equal, in accordance with the above definition. -Classes with reference semantics support the following methods. An -instance that is constructed as a copy of another instance must behave -as-if it were the same instance. +Some SYCL runtime classes will have additional behavior associated with copy, +movement, assignment or destruction semantics. If these are specified they are +in addition to those specified above unless stated otherwise. + +Each of the runtime classes mentioned above must provide a common interface +of special member functions in order to fulfill the copy, move, destruction +requirements and hidden friend functions in order to fulfill the equality +requirements. :: + namespace sycl { + class T { - public: - T(const T &rhs); - T(T &&rhs); - T &operator=(const T &rhs); - T &operator=(T &&rhs); + ... + + public: + + T(const T& rhs); + + T(T&& rhs); + + T& operator=(const T& rhs); + + T& operator=(T&& rhs); + ~T(); - friend bool operator==(const T &lhs, const T &rhs) { /* ... */ } - friend bool operator!=(const T &lhs, const T &rhs) { /* ... */ } + + ... + + friend bool operator==(const T& lhs, const T& rhs) { /* ... */ } + + friend bool operator!=(const T& lhs, const T& rhs) { /* ... */ } + + ... }; + + } // namespace sycl + +.. seealso:: |SYCL_SPEC_COMMON_REFERENCE| + +.. _ref_special_member_func: + +======================================================= +Common special member functions for reference semantics +======================================================= + +.. list-table:: + :header-rows: 1 + + * - Special member function + - Description + * - ``T(const T& rhs);`` + - Constructs a SYCL ``T`` instance as a copy of the RHS SYCL + ``T`` in accordance with the requirements set out above. + * - ``T(T&& rhs);`` + - Constructs a SYCL ``T`` instance as a move of the RHS SYCL + ``T`` in accordance with the requirements set out above. + * - ``T& operator=(const T& rhs);`` + - Assigns this SYCL ``T`` instance with a copy of the RHS + SYCL ``T`` in accordance with the requirements set out above. + * - ``T& operator=(T&& rhs);`` + - Assigns this SYCL ``T`` instance with a move of the RHS SYCL + ``T`` in accordance with the requirements set out above. + * - ``~T();`` + - Destroys this SYCL ``T`` instance in accordance with the + requirements set out above. + On destruction of the last copy, may perform additional + lifetime related operations required for the underlying + native backend object specified in the SYCL backend specification + document, if this SYCL T instance was originally constructed + using one of the backend interoperability ``sycl::make_*`` functions. + See the relevant backend specification for details. + + +.. _ref_hidden_friend_func: + +====================================================== +Common hidden friend functions for reference semantics +====================================================== + +A hidden friend function is a function first declared via a ``friend`` +declaration with no additional out of class or namespace scope declarations. + +Hidden friend functions are only visible to ADL (Argument Dependent Lookup) +and are hidden from qualified and unqualified lookup. + +Hidden friend functions have the benefits of avoiding accidental implicit +conversions and faster compilation. + +.. list-table:: + :header-rows: 1 + + * - Hidden friend function + - Description + * - :: + + friend bool operator==(const T& lhs, const T& rhs); + + - Returns ``true`` if this LHS SYCL ``T`` is equal to the RHS + SYCL ``T`` in accordance with the requirements set out above, + otherwise returns ``false``. + * - :: + + friend bool operator!=(const T& lhs, const T& rhs); + + - Returns ``true`` if this LHS SYCL ``T`` is not equal to the + RHS SYCL ``T`` in accordance with the requirements set out + above, otherwise returns ``false``. diff --git a/source/iface/defining-kernels.rst b/source/iface/defining-kernels.rst new file mode 100644 index 00000000..0b95df04 --- /dev/null +++ b/source/iface/defining-kernels.rst @@ -0,0 +1,9 @@ +.. + Copyright 2023 The Khronos Group Inc. + SPDX-License-Identifier: CC-BY-4.0 + +.. _defining-kernels: + +**************** +Defining Kernels +**************** diff --git a/source/iface/device-event.rst b/source/iface/device-event.rst index 5960b02b..42e7b4cf 100644 --- a/source/iface/device-event.rst +++ b/source/iface/device-event.rst @@ -2,6 +2,8 @@ Copyright 2020 The Khronos Group Inc. SPDX-License-Identifier: CC-BY-4.0 +.. Moved to Synchronization and atomics + .. rst-class:: api-class ====================== diff --git a/source/iface/device_image.rst b/source/iface/device_image.rst new file mode 100644 index 00000000..3a58517d --- /dev/null +++ b/source/iface/device_image.rst @@ -0,0 +1,9 @@ +.. + Copyright 2023 The Khronos Group Inc. + SPDX-License-Identifier: CC-BY-4.0 + +.. _device_image: + +********************** +``sycl::device_image`` +********************** diff --git a/source/iface/id.rst b/source/iface/id.rst index 733fb00c..b9f28eec 100644 --- a/source/iface/id.rst +++ b/source/iface/id.rst @@ -17,7 +17,7 @@ The ``id`` is an abstraction that describes the location of a point in a :ref:`range`. Examples includes use as an index in an -`buffer-accessor` and as an argument to a kernel function in a +:ref:`command-accessor` and as an argument to a kernel function in a :ref:`handler-parallel_for` to identify the work item. .. seealso:: |SYCL_SPEC_ID| diff --git a/source/iface/item-classes.rst b/source/iface/item-classes.rst new file mode 100644 index 00000000..5ad99bb2 --- /dev/null +++ b/source/iface/item-classes.rst @@ -0,0 +1,16 @@ +.. + Copyright 2023 The Khronos Group Inc. + SPDX-License-Identifier: CC-BY-4.0 + +.. _iface-item-classes: + +************ +Item Classes +************ + +.. toctree:: + :maxdepth: 1 + + item + h_item + nd_item diff --git a/source/iface/program.rst b/source/iface/kernel-bundles.rst similarity index 98% rename from source/iface/program.rst rename to source/iface/kernel-bundles.rst index 47def128..89495aa0 100644 --- a/source/iface/program.rst +++ b/source/iface/kernel-bundles.rst @@ -2,9 +2,9 @@ Copyright 2020 The Khronos Group Inc. SPDX-License-Identifier: CC-BY-4.0 -******** -Programs -******** +************** +Kernel Bundles +************** .. _program: diff --git a/source/iface/kernel.rst b/source/iface/kernel.rst index c4c0c176..cb31e6d0 100644 --- a/source/iface/kernel.rst +++ b/source/iface/kernel.rst @@ -2,13 +2,11 @@ Copyright 2020 The Khronos Group Inc. SPDX-License-Identifier: CC-BY-4.0 -.. rst-class:: api-class - .. _kernel: -================ +**************** ``sycl::kernel`` -================ +**************** :: diff --git a/source/iface/properties.rst b/source/iface/properties.rst index 6ae64a45..d193c049 100644 --- a/source/iface/properties.rst +++ b/source/iface/properties.rst @@ -2,20 +2,192 @@ Copyright 2020 The Khronos Group Inc. SPDX-License-Identifier: CC-BY-4.0 -.. _property_list: +.. _properties: +********** +Properties +********** + +Each of the following SYCL runtime classes: ``accessor``, ``buffer``, +``host_accessor``, ``host_sampled_image_accessor``, +``host_unsampled_image_accessor``, ``context``, +``local_accessor``, ``queue``, ``sampled_image``, +``sampled_image_accessor``, ``stream``, ``unsampled_image``, +``unsampled_image_accessor`` and ``usm_allocator`` +provide an optional parameter in each of their constructors +to provide a ``property_list`` which contains zero or more properties. +Each of those properties augments the semantics of the class with +a particular feature. Each of those classes must also provide +``has_property`` and ``get_property`` member functions +for querying for a particular property. + +Using properties does not affect the +type of the object, thus, does not prevent the usage of SYCL objects +in containers. + +See `buffer-properties-example`_. + +.. seealso:: |SYCL_BUFF_PROP| + +Each property is represented by a unique class and an instance of a property +is an instance of that type. Some properties can be default constructed while +others will require an argument on construction. A property may be applicable +to more than one class, however some properties may not be compatible +with each other. + +.. _property_list`: + +``sycl::property_list`` +======================= + +Each of the runtime classes mentioned above must provide a common interface of +member functions in order to fulfill the property interface requirements. + +A synopsis of the common properties interface, the SYCL ``property_list`` +class and the SYCL property classes is provided below. + +:: + + + namespace sycl { + + template struct is_property; + + template + inline constexpr bool is_property_v = is_property::value; + + template struct is_property_of; + + template + inline constexpr bool is_property_of_v = + is_property_of::value; + + class T { + ... + + template + bool has_property() const noexcept; + + template Property get_property() const; + + ... + }; + + class property_list { + public: + template property_list(Properties... props); + }; + } // namespace sycl + +(constructor) of `sycl::property_list` +====================================== + +:: + + template property_list(PropertyN... props) + +Available only when: ``is_property::value`` evaluates to +``true`` where ``property`` is each property in ``PropertyN``. + +Construct a SYCL ``property_list`` with zero or more properties. + +.. _traits_for_properties : + +Traits for properties +===================== + +``is_property`` =============== - property_list -=============== :: - class property_list; + template struct is_property + +An explicit specialization of ``is_property`` that inherits from +``std::true_type`` must be provided for each property, where +``Property`` is the class defining the property. This includes both +standard properties described in this specification and any additional +non-standard properties defined by an implementation. All other +specializations of ``is_property`` must inherit from ``std::false_type``. + +``is_property_v`` +================= + +:: + + template inline constexpr bool is_property_v; + +Variable containing value of ``is_property``. + +``is_property_of`` +================== + +:: + + template struct is_property_of + +An explicit specialization of ``is_property_of`` that inherits from +``std::true_type`` must be provided for each property that can be used +in constructing a given SYCL class, where ``Property`` is the class defining +the property and ``SyclObject`` is the SYCL class. This includes both standard +properties described in this specification and any additional non-standard +properties defined by an implementation. All other specializations of +``is_property_of`` must inherit from ``std::false_type``. -property_list -============= +``is_property_of_v`` +==================== :: - template - property_list(propertyTN... props); + template inline constexpr bool is_property_of_v; + +Variable containing value of ``is_property_of``. + +Member functions of the SYCL common property interface +====================================================== + +``has_property`` +================ + +:: + + template bool has_property() const noexcept + +Returns true if ``T`` was constructed with the property specified +by ``Property``. Returns false if it was not. + +``get_property`` +================ + +:: + + template Property get_property() const + +Returns a copy of the property of type ``Property`` that ``T`` was +constructed with. Must throw an ``exception`` with the +``errc::invalid`` error code if ``T`` was not constructed +with the ``Property`` property. + +.. _ buffer-properties-example: + +buffer-properties-example +========================= + +:: + + { + context myContext; + + std::vector> bufferList { + buffer { ptr, rng }, + buffer { ptr, rng, property::use_host_ptr {} }, + buffer { ptr, rng, property::context_bound { myContext } } + }; + + for (auto& buf : bufferList) { + if (buf.has_property()) { + auto prop = buf.get_property(); + assert(myContext == prop.get_context()); + } + } + } diff --git a/source/iface/ranges.rst b/source/iface/ranges.rst new file mode 100644 index 00000000..079c0475 --- /dev/null +++ b/source/iface/ranges.rst @@ -0,0 +1,15 @@ +.. + Copyright 2023 The Khronos Group Inc. + SPDX-License-Identifier: CC-BY-4.0 + +.. _iface-ranges: + +************* +Range Classes +************* + +.. toctree:: + :maxdepth: 1 + + range + nd_range diff --git a/source/iface/reduction-variables.rst b/source/iface/reduction-variables.rst new file mode 100644 index 00000000..ac595288 --- /dev/null +++ b/source/iface/reduction-variables.rst @@ -0,0 +1,9 @@ +.. + Copyright 2023 The Khronos Group Inc. + SPDX-License-Identifier: CC-BY-4.0 + +.. _reduction-variables: + +******************* +Reduction Variables +******************* diff --git a/source/iface/specialization-constants.rst b/source/iface/specialization-constants.rst new file mode 100644 index 00000000..654a9a3a --- /dev/null +++ b/source/iface/specialization-constants.rst @@ -0,0 +1,9 @@ +.. + Copyright 2023 The Khronos Group Inc. + SPDX-License-Identifier: CC-BY-4.0 + +.. _specialization-constants: + +************************ +Specialization Constants +************************ diff --git a/source/iface/sub_group.rst b/source/iface/sub_group.rst new file mode 100644 index 00000000..fc09be68 --- /dev/null +++ b/source/iface/sub_group.rst @@ -0,0 +1,9 @@ +.. + Copyright 2023 The Khronos Group Inc. + SPDX-License-Identifier: CC-BY-4.0 + +.. _sub_group: + +******************* +``sycl::sub_group`` +******************* diff --git a/source/parallelism.rst b/source/parallelism.rst index 9294b182..4f118212 100644 --- a/source/parallelism.rst +++ b/source/parallelism.rst @@ -10,15 +10,15 @@ Expressing parallelism .. toctree:: :maxdepth: 1 - iface/range - iface/group + iface/defining-kernels + iface/ranges iface/id - iface/item - iface/h_item - iface/nd_item - iface/nd_range - iface/device-event - iface/command-group + iface/item-classes + iface/group + iface/sub_group iface/command-group-handler + iface/specialization-constants + iface/kernel-bundles iface/kernel - iface/program + iface/device_image + iface/reduction-variables diff --git a/source/spelling_wordlist.txt b/source/spelling_wordlist.txt index 78bebcf8..642487c7 100644 --- a/source/spelling_wordlist.txt +++ b/source/spelling_wordlist.txt @@ -43,3 +43,6 @@ pinnable constructible unsampled linearizes +copyable +mutex +constantness diff --git a/source/synchronization.rst b/source/synchronization.rst index 392255bd..705af218 100644 --- a/source/synchronization.rst +++ b/source/synchronization.rst @@ -8,6 +8,12 @@ .. rst-class:: api-class +.. toctree:: + :maxdepth: 1 + + iface/device-event + + ``sycl::atomic_ref`` ====================