Skip to content

Commit b19d5f8

Browse files
feature: add appendHostFunction api (#425)
Signed-off-by: Kamil Kopryk <kamil.kopryk@intel.com>
1 parent 3d7eb96 commit b19d5f8

4 files changed

Lines changed: 120 additions & 0 deletions

File tree

scripts/core/PROG.rst

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1118,6 +1118,49 @@ The following pseudo-code demonstrates appending kernel with pointer, SLM and im
11181118
11191119
...
11201120
1121+
Appending Host Functions
1122+
~~~~~~~~~~~~~~~~~~~~~~~~
1123+
1124+
Host functions enable inserting host-side function calls into a command list.
1125+
When the device reaches a host function entry during command list execution, it invokes the specified callback on the host before proceeding with subsequent commands.
1126+
The runtime invokes the callback on the host asynchronously with respect to API calls.
1127+
1128+
.. note::
1129+
- The host function callback must match the `pfnHostFunction` parameter type accepted by ${x}CommandListAppendHostFunction.
1130+
- The host function must **not** call any Level Zero API functions.
1131+
- The host function may access USM shared and USM host allocations.
1132+
- In contrast to event-based synchronization - where the application must call ${x}EventHostSynchronize and block its own thread until the device reaches that point - a host function lets the runtime invoke the host-side work asynchronously, without blocking any application thread.
1133+
1134+
The following example demonstrates a simplified producer-consumer pattern using an in-order immediate
1135+
command list for image processing. A kernel processes each frame on the GPU, and a host
1136+
function notifies a consumer thread that the frame is ready. The consumer thread can begin
1137+
displaying or saving the frame while the GPU is already processing the next one:
1138+
1139+
.. parsed-literal::
1140+
1141+
// Host function - signals consumer thread
1142+
void ${X}_CALLBACK_CONV onFrameReady(void* pUserData)
1143+
{
1144+
FrameContext* frame = static_cast<FrameContext*>(pUserData);
1145+
frame->ready = true;
1146+
signalConsumer(frame);
1147+
}
1148+
1149+
// ...
1150+
// Create in-order immediate command list
1151+
// Create consumer thread that waits for frames
1152+
1153+
for (int i = 0; i < nFrames; i++) {
1154+
// GPU processes frame i
1155+
${x}CommandListAppendLaunchKernel(hImmCmdList, hKernel, &launchArgs[i], nullptr, 0, nullptr);
1156+
1157+
// Host function notifies consumer thread that frame i is ready
1158+
${x}CommandListAppendHostFunction(hImmCmdList, onFrameReady, &frames[i], nullptr, 0, nullptr);
1159+
}
1160+
1161+
// Wait for all GPU work to complete
1162+
${x}CommandListHostSynchronize(hImmCmdList, UINT64_MAX);
1163+
11211164
Synchronization Primitives
11221165
==========================
11231166

scripts/core/common.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,13 @@ value: __cdecl
3333
altvalue: ""
3434
--- #--------------------------------------------------------------------------
3535
type: macro
36+
desc: "Callback function calling convention"
37+
condition: "defined(_WIN32)"
38+
name: $X_CALLBACK_CONV
39+
value: __stdcall
40+
altvalue: ""
41+
--- #--------------------------------------------------------------------------
42+
type: macro
3643
desc: "Microsoft-specific dllexport storage-class attribute"
3744
condition: "defined(_WIN32)"
3845
name: $X_APIEXPORT

scripts/core/hostFunction.yml

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#
2+
# Copyright (C) 2026 Intel Corporation
3+
#
4+
# SPDX-License-Identifier: MIT
5+
#
6+
# See YaML.md for syntax definition
7+
#
8+
--- #--------------------------------------------------------------------------
9+
type: header
10+
desc: "Intel $OneApi Level-Zero APIs for Append Host Function"
11+
version: "1.17"
12+
--- #--------------------------------------------------------------------------
13+
type: callback
14+
desc: "Host Function callback type"
15+
version: "1.17"
16+
convention: $X_CALLBACK_CONV
17+
returntype: void
18+
name: $x_host_function_callback_t
19+
params:
20+
- type: void*
21+
name: pUserData
22+
desc: "[in][optional] user data pointer"
23+
--- #--------------------------------------------------------------------------
24+
type: function
25+
desc: "Appends a host function call into a command list."
26+
version: "1.17"
27+
class: $xCommandList
28+
name: AppendHostFunction
29+
details:
30+
- "The application must ensure the events are accessible by the device on which the command list was created."
31+
- "The host function will be executed on the host when the command list reaches this point during execution."
32+
- "The host function callback must be of type $x_host_function_callback_t."
33+
- "The host function must **not** call any Level Zero API functions."
34+
- "The host function may access USM shared and USM host allocations."
35+
- "The runtime invokes the host function asynchronously to API calls."
36+
- "Device may wait for preceding commands to finish before invoking the callback (i.e. callbacks may introduce implicit synchronization point on the device)."
37+
- "Device will wait for all phWaitEvents to be signaled before executing the host function."
38+
- "The application must **not** call this function from simultaneous threads with the same command list handle."
39+
params:
40+
- type: $x_command_list_handle_t
41+
name: hCommandList
42+
desc: "[in] handle of the command list"
43+
- type: $x_host_function_callback_t
44+
name: pfnHostFunction
45+
desc: "[in] host function to call, expected to be lightweight and non-blocking"
46+
- type: void*
47+
name: pUserData
48+
desc: "[in][optional] user specific data that would be passed to function; neither the runtime nor the device will dereference it"
49+
- type: "const void*"
50+
name: pNext
51+
desc: "[in][optional] additional extensions passed to the function"
52+
- type: $x_event_handle_t
53+
name: hSignalEvent
54+
desc: "[in][optional] handle of the event to signal on completion"
55+
- type: uint32_t
56+
name: numWaitEvents
57+
desc: "[in][optional] count of phWaitEvents; must be 0 if `nullptr == phWaitEvents`"
58+
- type: "$x_event_handle_t*"
59+
name: phWaitEvents
60+
desc: "[in][optional][range(0, numWaitEvents)] handle of the events to wait on before launching"
61+
returns:
62+
- $X_RESULT_ERROR_INVALID_SYNCHRONIZATION_OBJECT
63+
- $X_RESULT_ERROR_INVALID_SIZE:
64+
- "`(nullptr == phWaitEvents) && (0 < numWaitEvents)`"
65+
- $X_RESULT_ERROR_UNSUPPORTED_FEATURE:
66+
- "an extension passed via pNext is not supported"

scripts/templates/api.h.mako

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,11 @@ extern "C" {
7373
typedef ${th.subt(n, tags, obj['value'])} ${th.make_type_name(n, tags, obj)};
7474
## CALLBACK ####################################################################
7575
%elif re.match(r"callback", obj['type']):
76+
%if 'convention' in obj:
77+
typedef ${th.subt(n, tags, obj['returntype'])} (${th.subt(n, tags, obj['convention'])} *${th.subt(n, tags, obj['name'])})(
78+
%else:
7679
typedef ${th.subt(n, tags, obj['returntype'])} (*${th.subt(n, tags, obj['name'])})(
80+
%endif
7781
%for line in th.make_param_lines(n, tags, obj):
7882
${line}
7983
%endfor

0 commit comments

Comments
 (0)