This document describes the process for creating and maintaining SYCL extension documents over their lifetime.
Start by making a copy of the template extension specification document,
and follow the instructions in that document. Your extension should also
follow the rules in chapter 6 of the SYCL specification, including the
"Guidelines for portable extensions". These rules require you to choose a
<vendorstring>
. For DPC++, we use the string "oneapi" unless the extension
is very specific to Intel hardware in which case we use the string "intel".
The template uses the string "oneapi", so you must change occurrences of that
string if your extension is specific to Intel hardware.
Some sections in the template are optional. Remove these sections if they are not needed. You should also remove any of the explanatory text (generally in italics).
Each extension must have a name. The template uses "sycl_ext_oneapi_myextension", but you must change the "myextension" to something appropriate. Use lower case, and separate words with underbars. Each extension also has a feature-test macro, which is the same as the extension's name, except it uses all upper case. Finally, the name of the specification file should match the name of the extension, for example "sycl_ext_oneapi_myextension.asciidoc".
Usually new extensions are first created in the "proposed" state, so the document should be added to that directory. However, it is also possible to add a new extension at the same time as its implementation, in which case the specification should be added to either the "supported" or "experimental" directories.
While an extension is in the "proposed" state, it is perfectly OK to make further modifications to its specification. There is no need to change the version of the extension's feature-test macro when this occurs.
When proposing a new extension targeting a particular backend, consider
which other backends may be likely to use similar architecture features
and may be able to support the extension. Some types of devices, such as
GPU accelerators (e.g. devices using level_zero
, ext_oneapi_cuda
, and
ext_oneapi_hip
backends) are often designed to target similar sets of
programming patterns. For example, a common set of applications and
patterns that are targeted by gpu accelerators includes AI algorithms and
data analytics, quantum or classical particle based simulations, and quantum
or classical field based simulations. This is important to consider
early on in order to make sure that the extension design takes account of
the requirements of all supportable backends. If unsure about the
applicability of an extension to a backend, it is recommended to seek advice
from one of the developers responsible for that backend. When an extension
API is not supported on some backends or devices, one option is to treat the
API as an "optional kernel feature" and tie it to a device
aspect (or to one of the architecture enums).
In this case, the application must do one of two things:
- The host code can test the device and only submit the kernel to the device if it has the required aspect, or
- The device code can use the experimental
if_architecture_is
function to call the API conditionally based on the device architecture. (This only works for AOT compilation currently.)
Often, an extension is implemented sometime after it is proposed. When this happens, the PR that implements the extension should also move the specification to either the "supported" or "experimental" directory, as appropriate. It is common to make small change to the specification when it is implemented, so the PR that implements the extension may also make modifications to the specification document.
Be sure to change the text in the "Status" section when the extension is implemented. See the template for the proper text.
Sometimes an extension is implemented with multiple PRs. When this happens, the last PR that implements the extension should also move the specification document. We want the specification document to reflect the features that are implemented in DPC++, so a specification should not be moved to "supported" or "experimental" before the final PR that implements it.
Ideally, all APIs in an extension should be implemented by the time we announce support. If this is not possible, something must be done to ensure that the specification is an accurate description of what is implemented. Following are some techniques to accomplish this.
This is the preferred technique if the first release of an extension implements some APIs but not others. In this case, the extension document should be copied to the "supported" (or "experimental") directory, but the description of the unimplemented APIs should be removed from this copy. Thus, the document in that directory is an accurate description of the implementation.
The original version of the specification in the "proposed" folder should remain. In addition, a new "version" row should be added to the table that describes the feature-test macro, and all the unimplemented APIs become part of "version 2" of the specification. These APIs can be implemented later, following the normal process of adding a new version to an existing extension.
Sometimes all of the APIs in an extension are implemented, but they are not yet implemented for all devices or backends. When this happens, we prefer to add non-normative "notes" to the extension specification indicating what is not yet implemented. The placement of these notes depends on the nature of the unimplemented thing. For example, if the entire extension is unimplemented on a certain backend, a note should be added in the "Status" section of the document, as demonstrated in the template. If there are restrictions with certain APIs, a note should be added near the description of each such API.
It is common to add new APIs to an extension after it is first released. When this happens, the new APIs should be protected by a new version of the extension's feature-test macro. This allows an application to test the value of the macro to know whether the implementation supports the API.
Assuming the extension document is currently in the "supported" directory, make a copy of that document in the "proposed" directory. Update the "Status" section as shown in the template, and add a new "version" row to the table that describes the feature-test macro with a short summary of the new APIs enabled in that version. The description of each new API should contain a statement saying which version adds the API. For example,
This API is available starting in version 2 of this specification.
Avoid unnecessary reformatting of the extension after it is copied. It should be possible to see the new APIs that are proposed in the new version by using a command like:
$ git diff {supported,proposed}/sycl_ext_oneapi_myextension.asciidoc
When the new version of the extension is implemented, the "proposed" version of the specification should be moved back to the "supported" directory, overwriting the previous version.
Note that a new version of a supported extension should never remove any functionality from the previous version. We expect existing code that uses the old version to still work with the new version.
Occasionally, we may decide to deprecate a supported extension. For example, this might happen if an extension is adopted into a new version of the core SYCL specification. When this happens, the specification is moved from the "supported" directory to the "deprecated" directory, and the "Status" section is changed as shown in the template. A signpost file is also added to the "supported" directory with the same name as the original file and content that looks like:
This extension has been deprecated, but the specification is still available
link:../deprecated/sycl_ext_oneapi_myextension.asciidoc[here].
The purpose of the signpost file is to ensure that external links to the extension are not broken, while still making it obvious that the extension is now deprecated.
Note that a deprecated extension is still supported, so the implementation is not removed.
We usually do not deprecate experimental extensions since there is no guarantee that these extension remain supported from one DPC++ release to the next. Instead, these extensions can be removed without a deprecation period.
Eventually, we typically remove an extension some time after it is deprecated. When this happens, we move the specification file to the "removed" directory and update the "Status" section as shown in the template. We also remove the signpost file. This typically happens in the same PR that removes the implementation of the extension.
The process of creating and implementing an "experimental" extension has mostly been described already, but there are some additional things to keep in mind. Even though an extension may be experimental, we still want the specification to accurately describe the API. Usually, the extension document is the main user-facing description of the API, so it must be accurate in order for customers to use the extension. Therefore, even an experimental extension specification must contain NOTEs describing any APIs that are not yet implemented.
Since experimental extensions have no guaranteed compatibility from one DPC++ release to another, we typically do not bother to add versions to the feature-test macro. This is still allowed, of course, but it is also OK to add, remove, or modify APIs without changing the version.