Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
3f95324
[SYCL] Add nd_launch overloads taking kernel arguments as a span
mieshkiwrk Aug 12, 2026
293786f
[SYCL] Let raw_kernel_arg say that an argument is a pointer
mieshkiwrk Aug 19, 2026
8bcaf7d
[SYCL] Pass an argument list given as a container to the span overload
mieshkiwrk Aug 19, 2026
39ac830
[SYCL] Replace the argument sequence note with an Examples section
mieshkiwrk Sep 2, 2026
9986af5
[SYCL] Take the kernel argument sequence as a std::span
mieshkiwrk Sep 2, 2026
c23f975
[SYCL] Apply clang-format to the argument sequence changes
mieshkiwrk Sep 2, 2026
82aca3c
[SYCL] Rewrap the argument sequence dependency paragraph
mieshkiwrk Sep 3, 2026
5502f83
[SYCL] Make the C++20 annotations reach the rendered specification
mieshkiwrk Sep 3, 2026
9608d55
Update sycl/doc/extensions/experimental/sycl_ext_oneapi_raw_kernel_ar…
mieshkiwrk Sep 23, 2026
c01fd9a
[SYCL] Rewrap the applied suggestion for the pointer constructor
mieshkiwrk Sep 23, 2026
89fb407
[SYCL] Use the namespace alias in both raw_kernel_arg examples
mieshkiwrk Sep 23, 2026
5a2f8b8
[SYCL] Say that the byte constructor must not take a pointer argument
mieshkiwrk Sep 23, 2026
34bf2f1
[SYCL] Drop the argument sequence paragraph from the Overview
mieshkiwrk Sep 23, 2026
70e8177
[SYCL] Shorten the version 2 row of the enqueue functions extension
mieshkiwrk Sep 23, 2026
b51e275
[SYCL] Drop the Level Zero justification from the pointer argument note
mieshkiwrk Sep 23, 2026
bd98858
[SYCL] Move the pointer argument requirement to the Overview
mieshkiwrk Sep 23, 2026
a257649
[SYCL] Use the reviewer's wording for the pointer argument requirement
mieshkiwrk Sep 23, 2026
4538a46
[SYCL] Limit the backend support status to the tested backends
mieshkiwrk Sep 23, 2026
5c15db5
[SYCL] Rewrite the argument sequence example as a complete program
mieshkiwrk Sep 23, 2026
551d09a
[SYCL] Constrain the parameter pack overloads instead of describing t…
mieshkiwrk Sep 23, 2026
ccb49bb
[SYCL] Keep the parameter pack literal in the rendered constraint
mieshkiwrk Sep 23, 2026
5317dd6
[SYCL] Add std::span overloads to the remaining kernel object launch …
mieshkiwrk Sep 25, 2026
cff7c04
Review changes
mieshkiwrk Oct 1, 2026
a47e753
comment reduction
mieshkiwrk Oct 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ This extension is written against the SYCL 2020 revision 7 specification. All
references below to the "core SYCL specification" or to section numbers in the
SYCL specification refer to that revision.

The overloads that take the kernel arguments as a `std::span` depend on
version 2 of link:../experimental/sycl_ext_oneapi_raw_kernel_arg.asciidoc[
sycl_ext_oneapi_raw_kernel_arg], which is what lets an element of that sequence
represent a pointer argument. Those overloads use `std::span`, so they are
available only when the application is compiled with C++20 or later.


== Status

Expand Down Expand Up @@ -165,8 +171,11 @@ implementation supports.
|Description

|1
|The APIs of this experimental extension are not versioned, so the
feature-test macro always has this value.
|Initial version of this extension.

|2
|Adds the overloads that take the arguments of a `sycl::kernel` as
a `std::span` of `raw_kernel_arg`.
|===


Expand Down Expand Up @@ -301,19 +310,49 @@ a!
----
namespace sycl::ext::oneapi::experimental {

template <typename Args...>
template <typename... Args>
void single_task(sycl::queue q, const sycl::kernel& k, Args&&... args);

template <typename Args...>
template <typename... Args>
void single_task(sycl::handler &h, const sycl::kernel& k, Args&&... args);

}
----
!====
_Constraints_: `+sizeof...(Args)+` is not one, or the single argument in
`args` is not convertible to `std::span<const raw_kernel_arg>`.

_Effects_: Enqueues a kernel object to the `sycl::queue` or `sycl::handler` as
a single task. The arguments in `args` are passed to the kernel in the same
order.

a|
[frame=all,grid=none]
!====
a!
[source,c++]
----
namespace sycl::ext::oneapi::experimental {

void single_task(sycl::queue q, const sycl::kernel& k, // Requires C++20
std::span<const raw_kernel_arg> args);

void single_task(sycl::handler &h, const sycl::kernel& k, // Requires C++20
std::span<const raw_kernel_arg> args);

}
----
!====
_Effects_: Enqueues a kernel object to the `sycl::queue` or `sycl::handler` as
a single task. The element `args[i]` is passed to the kernel as the argument at
index `i`, as if it had been passed to `set_arg`. The sequence referenced by
`args` need only remain valid until the function returns.

[_Note:_ An element that represents a pointer argument has to be constructed
with the `pointer_arg` overload of `raw_kernel_arg`, as described in
link:../experimental/sycl_ext_oneapi_raw_kernel_arg.asciidoc[sycl_ext_oneapi_raw_kernel_arg].
_end note_]

|====


Expand Down Expand Up @@ -397,6 +436,9 @@ void parallel_for(sycl::handler &h, sycl::range<Dimensions> r,
}
----
!====
_Constraints_: `+sizeof...(Args)+` is not one, or the single argument in
`args` is not convertible to `std::span<const raw_kernel_arg>`.

_Effects_: Enqueues a kernel object to the `sycl::queue` or `sycl::handler`
as a basic kernel, using the number of work-items specified by a `sycl::range`.
The arguments in `args` are passed to the kernel in the same order.
Expand All @@ -409,24 +451,93 @@ a!
----
namespace sycl::ext::oneapi::experimental {

template <int Dimensions> // Requires C++20
void parallel_for(sycl::queue q, sycl::range<Dimensions> r,
const sycl::kernel& k,
std::span<const raw_kernel_arg> args);

template <int Dimensions> // Requires C++20
void parallel_for(sycl::handler &h, sycl::range<Dimensions> r,
const sycl::kernel& k,
std::span<const raw_kernel_arg> args);

}
----
!====
_Effects_: Enqueues a kernel object to the `sycl::queue` or `sycl::handler`
as a basic kernel, using the number of work-items specified by a `sycl::range`.
The element `args[i]` is passed to the kernel as the argument at index `i`, as
if it had been passed to `set_arg`. The sequence referenced by `args` need only
remain valid until the function returns.

[_Note:_ An element that represents a pointer argument has to be constructed
with the `pointer_arg` overload of `raw_kernel_arg`, as described in
link:../experimental/sycl_ext_oneapi_raw_kernel_arg.asciidoc[sycl_ext_oneapi_raw_kernel_arg].
_end note_]

a|
[frame=all,grid=none]
!====
a!
[source,c++]
----
namespace sycl::ext::oneapi::experimental {

template <int Dimensions, typename Properties, typename... Args>
void parallel_for(sycl::queue q,
launch_config<sycl::range<Dimensions>, Properties> c,
const sycl::kernel& k, Args&& args...);
const sycl::kernel& k, Args&&... args);

template <int Dimensions, typename Properties, typename... Args>
void parallel_for(sycl::handler &h,
launch_config<sycl::range<Dimensions>, Properties> c,
const sycl::kernel& k, Args&& args...);
const sycl::kernel& k, Args&&... args);

}
----
!====
_Constraints_: `+sizeof...(Args)+` is not one, or the single argument in
`args` is not convertible to `std::span<const raw_kernel_arg>`.

_Effects_: Enqueues a kernel object to the `sycl::queue` or `sycl::handler`
as a basic kernel, using the launch configuration specified by a
`launch_config`. The arguments in `args` are passed to the kernel in the same
order.

a|
[frame=all,grid=none]
!====
a!
[source,c++]
----
namespace sycl::ext::oneapi::experimental {

template <int Dimensions, typename Properties> // Requires C++20
void parallel_for(sycl::queue q,
launch_config<sycl::range<Dimensions>, Properties> c,
const sycl::kernel& k,
std::span<const raw_kernel_arg> args);

template <int Dimensions, typename Properties> // Requires C++20
void parallel_for(sycl::handler &h,
launch_config<sycl::range<Dimensions>, Properties> c,
const sycl::kernel& k,
std::span<const raw_kernel_arg> args);

}
----
!====
_Effects_: Enqueues a kernel object to the `sycl::queue` or `sycl::handler`
as a basic kernel, using the launch configuration specified by a
`launch_config`. The element `args[i]` is passed to the kernel as the argument
at index `i`, as if it had been passed to `set_arg`. The sequence referenced by
`args` need only remain valid until the function returns.

[_Note:_ An element that represents a pointer argument has to be constructed
with the `pointer_arg` overload of `raw_kernel_arg`, as described in
link:../experimental/sycl_ext_oneapi_raw_kernel_arg.asciidoc[sycl_ext_oneapi_raw_kernel_arg].
_end note_]

|====


Expand Down Expand Up @@ -512,6 +623,9 @@ void nd_launch(sycl::handler &h, sycl::nd_range<Dimensions> r,
}
----
!====
_Constraints_: `+sizeof...(Args)+` is not one, or the single argument in
`args` is not convertible to `std::span<const raw_kernel_arg>`.

_Effects_: Enqueues a kernel object to the `sycl::queue` or `sycl::handler`
as a basic kernel, using the number of work-items specified by a
`sycl::nd_range`. The arguments in `args` are passed to the kernel in the same
Expand All @@ -525,24 +639,89 @@ a!
----
namespace sycl::ext::oneapi::experimental {

template <int Dimensions> // Requires C++20
void nd_launch(sycl::queue q, sycl::nd_range<Dimensions> r,
const sycl::kernel& k, std::span<const raw_kernel_arg> args);

template <int Dimensions> // Requires C++20
void nd_launch(sycl::handler &h, sycl::nd_range<Dimensions> r,
const sycl::kernel& k, std::span<const raw_kernel_arg> args);

}
----
!====
_Effects_: Enqueues a kernel object to the `sycl::queue` or `sycl::handler`
as a basic kernel, using the number of work-items specified by a
`sycl::nd_range`. The element `args[i]` is passed to the kernel as the argument
at index `i`, as if it had been passed to `set_arg`. The sequence referenced by
`args` need only remain valid until the function returns.

[_Note:_ An element that represents a pointer argument has to be constructed
with the `pointer_arg` overload of `raw_kernel_arg`, as described in
link:../experimental/sycl_ext_oneapi_raw_kernel_arg.asciidoc[sycl_ext_oneapi_raw_kernel_arg].
_end note_]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just adding this comment here as a convenient place ... There are several launch functions that take a pack of Args, but you only added a raw_kernel_arg overload for one set. The others are:

  • single_task taking const sycl::kernel& k, Args&&... args.
  • parallel_for taking sycl::range<Dimensions> r, const sycl::kernel& k, Args&&... args
  • parallel_for taking launch_config<sycl::range<Dimensions>, Properties> c, const sycl::kernel& k, Args&& args...
  • nd_launch taking launch_config<sycl::nd_range<Dimensions>, Properties> c, const sycl::kernel& k, Args&& args...

Can you add raw_kernel_arg overloads for those too?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you prefer them in this PR or a separate one?
It is eight more overloads plus spec and tests, and they would go through the handler - the fast path from #22970 only covers nd_launch with an nd_range.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm OK either way. Maybe members of @intel/llvm-reviewers-runtime have a preference?

If you do make a separate PR, I assume you will prioritize it, so it comes soon? I'd like the APIs taking std::span to be consistent before we make our next release.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll start looking into exact needed changes and let you know when it's ready about it's size.
For me it would be easier to keep it within this PR but it would get kinda big for review.

Let me update about the changes size and then we'll see how to handle that

@mieshkiwrk mieshkiwrk Sep 25, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added them here in 5317dd6: single_task, parallel_for with a range, and both launch_config forms, on the queue and on the handler, with spec entries and tests. They bind through the handler, since the handler-less path only covers nd_launch with an nd_range, and add no exported symbols; the extension stays at version 2 as it is not released yet.

It is one big commit, let me know if you prefer as a separate PR.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Friendly reminder bump

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this PR is huge already, I would suggest creating a follow-up PR for extra overloads

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've seen you did review already, not sure to split it now

Let me know if still needed then I'll do that

a|
[frame=all,grid=none]
!====
a!
[source,c++]
----
namespace sycl::ext::oneapi::experimental {

template <int Dimensions, typename Properties, typename... Args>
void nd_launch(sycl::queue q,
launch_config<sycl::nd_range<Dimensions>, Properties> c,
const sycl::kernel& k, Args&& args...);
const sycl::kernel& k, Args&&... args);

template <int Dimensions, typename Properties, typename... Args>
void nd_launch(sycl::handler &h,
launch_config<sycl::nd_range<Dimensions>, Properties> c,
const sycl::kernel& k, Args&& args...);
const sycl::kernel& k, Args&&... args);

}
----
!====
_Constraints_: `+sizeof...(Args)+` is not one, or the single argument in
`args` is not convertible to `std::span<const raw_kernel_arg>`.

_Effects_: Enqueues a kernel object to the `sycl::queue` or `sycl::handler`
as a basic kernel, using the launch configuration specified by a
`launch_config`. The arguments in `args` are passed to the kernel in the same
order.

a|
[frame=all,grid=none]
!====
a!
[source,c++]
----
namespace sycl::ext::oneapi::experimental {

template <int Dimensions, typename Properties> // Requires C++20
void nd_launch(sycl::queue q,
launch_config<sycl::nd_range<Dimensions>, Properties> c,
const sycl::kernel& k, std::span<const raw_kernel_arg> args);

template <int Dimensions, typename Properties> // Requires C++20
void nd_launch(sycl::handler &h,
launch_config<sycl::nd_range<Dimensions>, Properties> c,
const sycl::kernel& k, std::span<const raw_kernel_arg> args);

}
----
!====
_Effects_: Enqueues a kernel object to the `sycl::queue` or `sycl::handler`
as a basic kernel, using the launch configuration specified by a
`launch_config`. The element `args[i]` is passed to the kernel as the argument
at index `i`, as if it had been passed to `set_arg`. The sequence referenced by
`args` need only remain valid until the function returns.

[_Note:_ An element that represents a pointer argument has to be constructed
with the `pointer_arg` overload of `raw_kernel_arg`, as described in
link:../experimental/sycl_ext_oneapi_raw_kernel_arg.asciidoc[sycl_ext_oneapi_raw_kernel_arg].
_end note_]

|====


Expand Down Expand Up @@ -771,6 +950,47 @@ _Effects_: Submits an executable command graph to the `sycl::queue` or `sycl::ha

|====

== Example

The following example launches a kernel whose argument list is assembled at run
time, as a launcher for kernels that are not known at compile time would do, so
the arguments are passed as a sequence rather than as a parameter pack. A
`std::vector<raw_kernel_arg>`, a `std::array` of them and a `std::span` of them
all convert to `std::span<const raw_kernel_arg>`.

[source,c++]
----
#include <sycl/sycl.hpp>
#include <vector>
namespace syclex = sycl::ext::oneapi::experimental;

static constexpr size_t N = 1024;

SYCL_EXT_ONEAPI_FUNCTION_PROPERTY((syclex::nd_range_kernel<1>))
void scale(float *data, int factor) { /* kernel body */ }

int main() {
sycl::queue q;

auto bundle =
syclex::get_kernel_bundle<scale, sycl::bundle_state::executable>(
q.get_context());
sycl::kernel k = bundle.ext_oneapi_get_kernel<scale>();

float *data = sycl::malloc_device<float>(N, q);
int factor = 2;

std::vector<syclex::raw_kernel_arg> args;
args.emplace_back(&data, syclex::pointer_arg);
args.emplace_back(&factor, sizeof(factor));

syclex::nd_launch(q, sycl::nd_range<1>{{N}, {256}}, k, args);
q.wait();

sycl::free(data, q);
}
----

== Issues

. What should `submit_with_event` be called?
Expand Down
Loading
Loading