Skip to content

Commit 800d949

Browse files
authored
[Offload] Implement the remaining initial Offload API (llvm#122106)
Implement the complete initial version of the Offload API, to the extent that is usable for simple offloading programs. Tested with a basic SYCL program. As far as possible, these are simple wrappers over existing functionality in the plugins. * Allocating and freeing memory (host, device, shared). * Creating a program * Creating a queue (wrapper over asynchronous stream resource) * Enqueuing memcpy operations * Enqueuing kernel executions * Waiting on (optional) output events from the enqueue operations * Waiting on a queue to finish Objects created with the API have reference counting semantics to handle their lifetime. They are created with an initial reference count of 1, which can be incremented and decremented with retain and release functions. They are freed when their reference count reaches 0. Platform and device objects are not reference counted, as they are expected to persist as long as the library is in use, and it's not meaningful for users to create or destroy them. Tests have been added to `offload.unittests`, including device code for testing program and kernel related functionality. The API should still be considered unstable and it's very likely we will need to change the existing entry points.
1 parent fcb3097 commit 800d949

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+3016
-800
lines changed

offload/liboffload/API/APIDefs.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ class Typedef : APIObject { string value; }
199199

200200
class FptrTypedef : APIObject {
201201
list<Param> params;
202-
list<Return> returns;
202+
string return;
203203
}
204204

205205
class Macro : APIObject {

offload/liboffload/API/Common.td

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,19 +62,39 @@ def : Handle {
6262
let desc = "Handle of context object";
6363
}
6464

65+
def : Handle {
66+
let name = "ol_queue_handle_t";
67+
let desc = "Handle of queue object";
68+
}
69+
70+
def : Handle {
71+
let name = "ol_event_handle_t";
72+
let desc = "Handle of event object";
73+
}
74+
75+
def : Handle {
76+
let name = "ol_program_handle_t";
77+
let desc = "Handle of program object";
78+
}
79+
80+
def : Typedef {
81+
let name = "ol_kernel_handle_t";
82+
let desc = "Handle of kernel object";
83+
let value = "void *";
84+
}
85+
6586
def : Enum {
6687
let name = "ol_errc_t";
6788
let desc = "Defines Return/Error codes";
6889
let etors =[
6990
Etor<"SUCCESS", "Success">,
7091
Etor<"INVALID_VALUE", "Invalid Value">,
7192
Etor<"INVALID_PLATFORM", "Invalid platform">,
72-
Etor<"DEVICE_NOT_FOUND", "Device not found">,
7393
Etor<"INVALID_DEVICE", "Invalid device">,
74-
Etor<"DEVICE_LOST", "Device hung, reset, was removed, or driver update occurred">,
75-
Etor<"UNINITIALIZED", "plugin is not initialized or specific entry-point is not implemented">,
94+
Etor<"INVALID_QUEUE", "Invalid queue">,
95+
Etor<"INVALID_EVENT", "Invalid event">,
96+
Etor<"INVALID_KERNEL_NAME", "Named kernel not found in the program binary">,
7697
Etor<"OUT_OF_RESOURCES", "Out of resources">,
77-
Etor<"UNSUPPORTED_VERSION", "generic error code for unsupported versions">,
7898
Etor<"UNSUPPORTED_FEATURE", "generic error code for unsupported features">,
7999
Etor<"INVALID_ARGUMENT", "generic error code for invalid arguments">,
80100
Etor<"INVALID_NULL_HANDLE", "handle argument is not valid">,

offload/liboffload/API/Device.td

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
def : Enum {
1414
let name = "ol_device_type_t";
15-
let desc = "Supported device types";
15+
let desc = "Supported device types.";
1616
let etors =[
1717
Etor<"DEFAULT", "The default device type as preferred by the runtime">,
1818
Etor<"ALL", "Devices of all types">,
@@ -23,7 +23,7 @@ def : Enum {
2323

2424
def : Enum {
2525
let name = "ol_device_info_t";
26-
let desc = "Supported device info";
26+
let desc = "Supported device info.";
2727
let is_typed = 1;
2828
let etors =[
2929
TaggedEtor<"TYPE", "ol_device_type_t", "type of the device">,
@@ -34,39 +34,34 @@ def : Enum {
3434
];
3535
}
3636

37-
def : Function {
38-
let name = "olGetDeviceCount";
39-
let desc = "Retrieves the number of available devices within a platform";
37+
def : FptrTypedef {
38+
let name = "ol_device_iterate_cb_t";
39+
let desc = "User-provided function to be used with `olIterateDevices`";
4040
let params = [
41-
Param<"ol_platform_handle_t", "Platform", "handle of the platform instance", PARAM_IN>,
42-
Param<"uint32_t*", "NumDevices", "pointer to the number of devices.", PARAM_OUT>
41+
Param<"ol_device_handle_t", "Device", "the device handle of the current iteration", PARAM_IN>,
42+
Param<"void*", "UserData", "optional user data", PARAM_IN_OPTIONAL>
4343
];
44-
let returns = [];
44+
let return = "bool";
4545
}
4646

4747
def : Function {
48-
let name = "olGetDevice";
49-
let desc = "Retrieves devices within a platform";
48+
let name = "olIterateDevices";
49+
let desc = "Iterates over all available devices, calling the callback for each device.";
5050
let details = [
51-
"Multiple calls to this function will return identical device handles, in the same order.",
51+
"If the user-provided callback returns `false`, the iteration is stopped."
5252
];
5353
let params = [
54-
Param<"ol_platform_handle_t", "Platform", "handle of the platform instance", PARAM_IN>,
55-
Param<"uint32_t", "NumEntries", "the number of devices to be added to phDevices, which must be greater than zero", PARAM_IN>,
56-
RangedParam<"ol_device_handle_t*", "Devices", "Array of device handles. "
57-
"If NumEntries is less than the number of devices available, then this function shall only retrieve that number of devices.", PARAM_OUT,
58-
Range<"0", "NumEntries">>
54+
Param<"ol_device_iterate_cb_t", "Callback", "User-provided function called for each available device", PARAM_IN>,
55+
Param<"void*", "UserData", "Optional user data to pass to the callback", PARAM_IN_OPTIONAL>
5956
];
6057
let returns = [
61-
Return<"OL_ERRC_INVALID_SIZE", [
62-
"`NumEntries == 0`"
63-
]>
58+
Return<"OL_ERRC_INVALID_DEVICE">
6459
];
6560
}
6661

6762
def : Function {
6863
let name = "olGetDeviceInfo";
69-
let desc = "Queries the given property of the device";
64+
let desc = "Queries the given property of the device.";
7065
let details = [];
7166
let params = [
7267
Param<"ol_device_handle_t", "Device", "handle of the device instance", PARAM_IN>,
@@ -90,7 +85,7 @@ def : Function {
9085

9186
def : Function {
9287
let name = "olGetDeviceInfoSize";
93-
let desc = "Returns the storage size of the given device query";
88+
let desc = "Returns the storage size of the given device query.";
9489
let details = [];
9590
let params = [
9691
Param<"ol_device_handle_t", "Device", "handle of the device instance", PARAM_IN>,

offload/liboffload/API/Event.td

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//===-- Event.td - Event definitions for Offload -----------*- tablegen -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file contains Offload API definitions related to the event handle
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
def : Function {
14+
let name = "olDestroyEvent";
15+
let desc = "Destroy the event and free all underlying resources.";
16+
let details = [];
17+
let params = [
18+
Param<"ol_event_handle_t", "Event", "handle of the event", PARAM_IN>
19+
];
20+
let returns = [];
21+
}
22+
23+
def : Function {
24+
let name = "olWaitEvent";
25+
let desc = "Wait for the event to be complete.";
26+
let details = [];
27+
let params = [
28+
Param<"ol_event_handle_t", "Event", "handle of the event", PARAM_IN>
29+
];
30+
let returns = [];
31+
}

offload/liboffload/API/Kernel.td

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
//===-- Kernel.td - Kernel definitions for Offload ---------*- tablegen -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file contains Offload API definitions related to the kernel handle
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
def : Function {
14+
let name = "olGetKernel";
15+
let desc = "Get a kernel from the function identified by `KernelName` in the given program.";
16+
let details = [
17+
"The kernel handle returned is owned by the device so does not need to be destroyed."
18+
];
19+
let params = [
20+
Param<"ol_program_handle_t", "Program", "handle of the program", PARAM_IN>,
21+
Param<"const char*", "KernelName", "name of the kernel entry point in the program", PARAM_IN>,
22+
Param<"ol_kernel_handle_t*", "Kernel", "output pointer for the fetched kernel", PARAM_OUT>
23+
];
24+
let returns = [];
25+
}
26+
27+
def : Struct {
28+
let name = "ol_kernel_launch_size_args_t";
29+
let desc = "Size-related arguments for a kernel launch.";
30+
let members = [
31+
StructMember<"size_t", "Dimensions", "Number of work dimensions">,
32+
StructMember<"size_t", "NumGroupsX", "Number of work groups on the X dimension">,
33+
StructMember<"size_t", "NumGroupsY", "Number of work groups on the Y dimension">,
34+
StructMember<"size_t", "NumGroupsZ", "Number of work groups on the Z dimension">,
35+
StructMember<"size_t", "GroupSizeX", "Size of a work group on the X dimension.">,
36+
StructMember<"size_t", "GroupSizeY", "Size of a work group on the Y dimension.">,
37+
StructMember<"size_t", "GroupSizeZ", "Size of a work group on the Z dimension.">,
38+
StructMember<"size_t", "DynSharedMemory", "Size of dynamic shared memory in bytes.">
39+
];
40+
}
41+
42+
def : Function {
43+
let name = "olLaunchKernel";
44+
let desc = "Enqueue a kernel launch with the specified size and parameters.";
45+
let details = [
46+
"If a queue is not specified, kernel execution happens synchronously"
47+
];
48+
let params = [
49+
Param<"ol_queue_handle_t", "Queue", "handle of the queue", PARAM_IN_OPTIONAL>,
50+
Param<"ol_device_handle_t", "Device", "handle of the device to execute on", PARAM_IN>,
51+
Param<"ol_kernel_handle_t", "Kernel", "handle of the kernel", PARAM_IN>,
52+
Param<"const void*", "ArgumentsData", "pointer to the kernel argument struct", PARAM_IN>,
53+
Param<"size_t", "ArgumentsSize", "size of the kernel argument struct", PARAM_IN>,
54+
Param<"const ol_kernel_launch_size_args_t*", "LaunchSizeArgs", "pointer to the struct containing launch size parameters", PARAM_IN>,
55+
Param<"ol_event_handle_t*", "EventOut", "optional recorded event for the enqueued operation", PARAM_OUT_OPTIONAL>
56+
];
57+
let returns = [
58+
Return<"OL_ERRC_INVALID_ARGUMENT", ["`Queue == NULL && EventOut != NULL`"]>,
59+
Return<"OL_ERRC_INVALID_DEVICE", ["If Queue is non-null but does not belong to Device"]>,
60+
];
61+
}

offload/liboffload/API/Memory.td

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
//===-- Memory.td - Memory definitions for Offload ---------*- tablegen -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file contains Offload API definitions related to memory allocations
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
def : Enum {
14+
let name = "ol_alloc_type_t";
15+
let desc = "Represents the type of allocation made with olMemAlloc.";
16+
let etors = [
17+
Etor<"HOST", "Host allocation">,
18+
Etor<"DEVICE", "Device allocation">,
19+
Etor<"MANAGED", "Managed allocation">
20+
];
21+
}
22+
23+
def : Function {
24+
let name = "olMemAlloc";
25+
let desc = "Creates a memory allocation on the specified device.";
26+
let params = [
27+
Param<"ol_device_handle_t", "Device", "handle of the device to allocate on", PARAM_IN>,
28+
Param<"ol_alloc_type_t", "Type", "type of the allocation", PARAM_IN>,
29+
Param<"size_t", "Size", "size of the allocation in bytes", PARAM_IN>,
30+
Param<"void**", "AllocationOut", "output for the allocated pointer", PARAM_OUT>
31+
];
32+
let returns = [
33+
Return<"OL_ERRC_INVALID_SIZE", [
34+
"`Size == 0`"
35+
]>
36+
];
37+
}
38+
39+
def : Function {
40+
let name = "olMemFree";
41+
let desc = "Frees a memory allocation previously made by olMemAlloc.";
42+
let params = [
43+
Param<"void*", "Address", "address of the allocation to free", PARAM_IN>,
44+
];
45+
let returns = [];
46+
}
47+
48+
def : Function {
49+
let name = "olMemcpy";
50+
let desc = "Enqueue a memcpy operation.";
51+
let details = [
52+
"For host pointers, use the host device belonging to the OL_PLATFORM_BACKEND_HOST platform.",
53+
"If a queue is specified, at least one device must be a non-host device",
54+
"If a queue is not specified, the memcpy happens synchronously"
55+
];
56+
let params = [
57+
Param<"ol_queue_handle_t", "Queue", "handle of the queue.", PARAM_IN_OPTIONAL>,
58+
Param<"void*", "DstPtr", "pointer to copy to", PARAM_IN>,
59+
Param<"ol_device_handle_t", "DstDevice", "device that DstPtr belongs to", PARAM_IN>,
60+
Param<"void*", "SrcPtr", "pointer to copy from", PARAM_IN>,
61+
Param<"ol_device_handle_t", "SrcDevice", "device that SrcPtr belongs to", PARAM_IN>,
62+
Param<"size_t", "Size", "size in bytes of data to copy", PARAM_IN>,
63+
Param<"ol_event_handle_t*", "EventOut", "optional recorded event for the enqueued operation", PARAM_OUT_OPTIONAL>
64+
];
65+
let returns = [
66+
Return<"OL_ERRC_INVALID_ARGUMENT", ["`Queue == NULL && EventOut != NULL`"]>
67+
];
68+
}

offload/liboffload/API/OffloadAPI.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,8 @@ include "APIDefs.td"
1313
include "Common.td"
1414
include "Platform.td"
1515
include "Device.td"
16+
include "Memory.td"
17+
include "Queue.td"
18+
include "Event.td"
19+
include "Program.td"
20+
include "Kernel.td"

offload/liboffload/API/Platform.td

Lines changed: 5 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -9,44 +9,10 @@
99
// This file contains Offload API definitions related to the Platform handle
1010
//
1111
//===----------------------------------------------------------------------===//
12-
def : Function {
13-
let name = "olGetPlatform";
14-
let desc = "Retrieves all available platforms";
15-
let details = [
16-
"Multiple calls to this function will return identical platforms handles, in the same order.",
17-
];
18-
let params = [
19-
Param<"uint32_t", "NumEntries",
20-
"The number of platforms to be added to Platforms. NumEntries must be "
21-
"greater than zero.",
22-
PARAM_IN>,
23-
RangedParam<"ol_platform_handle_t*", "Platforms",
24-
"Array of handle of platforms. If NumEntries is less than the number of "
25-
"platforms available, then olGetPlatform shall only retrieve that "
26-
"number of platforms.",
27-
PARAM_OUT, Range<"0", "NumEntries">>
28-
];
29-
let returns = [
30-
Return<"OL_ERRC_INVALID_SIZE", [
31-
"`NumEntries == 0`"
32-
]>
33-
];
34-
}
35-
36-
def : Function {
37-
let name = "olGetPlatformCount";
38-
let desc = "Retrieves the number of available platforms";
39-
let params = [
40-
Param<"uint32_t*",
41-
"NumPlatforms", "returns the total number of platforms available.",
42-
PARAM_OUT>
43-
];
44-
let returns = [];
45-
}
4612

4713
def : Enum {
4814
let name = "ol_platform_info_t";
49-
let desc = "Supported platform info";
15+
let desc = "Supported platform info.";
5016
let is_typed = 1;
5117
let etors = [
5218
TaggedEtor<"NAME", "char[]", "The string denoting name of the platform. The size of the info needs to be dynamically queried.">,
@@ -58,17 +24,18 @@ def : Enum {
5824

5925
def : Enum {
6026
let name = "ol_platform_backend_t";
61-
let desc = "Identifies the native backend of the platform";
27+
let desc = "Identifies the native backend of the platform.";
6228
let etors =[
6329
Etor<"UNKNOWN", "The backend is not recognized">,
6430
Etor<"CUDA", "The backend is CUDA">,
6531
Etor<"AMDGPU", "The backend is AMDGPU">,
32+
Etor<"HOST", "The backend is the host">,
6633
];
6734
}
6835

6936
def : Function {
7037
let name = "olGetPlatformInfo";
71-
let desc = "Queries the given property of the platform";
38+
let desc = "Queries the given property of the platform.";
7239
let details = [
7340
"`olGetPlatformInfoSize` can be used to query the storage size "
7441
"required for the given query."
@@ -96,7 +63,7 @@ def : Function {
9663

9764
def : Function {
9865
let name = "olGetPlatformInfoSize";
99-
let desc = "Returns the storage size of the given platform query";
66+
let desc = "Returns the storage size of the given platform query.";
10067
let details = [];
10168
let params = [
10269
Param<"ol_platform_handle_t", "Platform", "handle of the platform", PARAM_IN>,

0 commit comments

Comments
 (0)