2025-12-17 22:53:03 -09:00
|
|
|
//===--- Level Zero Target RTL Implementation -----------------------------===//
|
|
|
|
|
//
|
|
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
|
//
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
//
|
|
|
|
|
// GenericKernel implementation for SPIR-V/Xe machine.
|
|
|
|
|
//
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
|
|
#ifndef OPENMP_LIBOMPTARGET_PLUGINS_NEXTGEN_LEVEL_ZERO_L0KERNEL_H
|
|
|
|
|
#define OPENMP_LIBOMPTARGET_PLUGINS_NEXTGEN_LEVEL_ZERO_L0KERNEL_H
|
|
|
|
|
|
|
|
|
|
#include "L0Defs.h"
|
|
|
|
|
#include "L0Trace.h"
|
|
|
|
|
#include "PluginInterface.h"
|
|
|
|
|
|
|
|
|
|
namespace llvm::omp::target::plugin {
|
|
|
|
|
|
2026-06-01 10:58:03 -08:00
|
|
|
// Forward declarations.
|
2025-12-17 22:53:03 -09:00
|
|
|
class L0DeviceTy;
|
|
|
|
|
class L0ProgramTy;
|
2026-06-01 12:16:47 -08:00
|
|
|
class L0QueueTy;
|
2025-12-17 22:53:03 -09:00
|
|
|
struct L0LaunchEnvTy;
|
|
|
|
|
|
|
|
|
|
/// Kernel properties.
|
|
|
|
|
struct KernelPropertiesTy {
|
|
|
|
|
uint32_t Width = 0;
|
|
|
|
|
uint32_t SIMDWidth = 0;
|
|
|
|
|
uint32_t MaxThreadGroupSize = 0;
|
2026-04-22 05:58:40 -08:00
|
|
|
uint32_t NumKernelArgs = 0;
|
|
|
|
|
std::unique_ptr<uint32_t[]> ArgSizes;
|
2025-12-17 22:53:03 -09:00
|
|
|
ze_kernel_indirect_access_flags_t IndirectAccessFlags =
|
|
|
|
|
std::numeric_limits<decltype(IndirectAccessFlags)>::max();
|
|
|
|
|
std::mutex Mtx;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct L0LaunchEnvTy {
|
|
|
|
|
ze_group_count_t GroupCounts = {0, 0, 0};
|
2026-06-01 10:58:03 -08:00
|
|
|
ze_group_size_t GroupSizes = {0, 0, 0};
|
2025-12-17 22:53:03 -09:00
|
|
|
KernelPropertiesTy &KernelPR;
|
2026-06-01 10:58:03 -08:00
|
|
|
bool IsCooperative = false;
|
|
|
|
|
void **ArgPtrs = nullptr;
|
2026-03-25 00:50:38 -08:00
|
|
|
std::unique_lock<std::mutex> Lock;
|
2025-12-17 22:53:03 -09:00
|
|
|
|
2026-06-25 12:51:30 -08:00
|
|
|
L0LaunchEnvTy(KernelPropertiesTy &KernelPR, KernelArgsTy &KernelArgs,
|
|
|
|
|
KernelLaunchParamsTy LaunchParams)
|
2026-06-01 10:58:03 -08:00
|
|
|
: KernelPR(KernelPR), IsCooperative(KernelArgs.Flags.Cooperative),
|
2026-07-27 11:44:06 -08:00
|
|
|
ArgPtrs(LaunchParams.Args), Lock(KernelPR.Mtx, std::defer_lock) {}
|
2025-12-17 22:53:03 -09:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class L0KernelTy : public GenericKernelTy {
|
|
|
|
|
// L0 Kernel Handle.
|
|
|
|
|
ze_kernel_handle_t zeKernel;
|
|
|
|
|
// Kernel Properties.
|
|
|
|
|
mutable KernelPropertiesTy Properties;
|
|
|
|
|
|
|
|
|
|
Error buildKernel(L0ProgramTy &Program);
|
|
|
|
|
Error readKernelProperties(L0ProgramTy &Program);
|
|
|
|
|
|
2026-07-27 01:48:47 -08:00
|
|
|
ze_group_size_t createKernelGroups(L0DeviceTy &L0Device, L0LaunchEnvTy &KEnv,
|
[offload] use argument pointer array in olLaunchKernel (#194333)
This PR changes olLaunchKernel to accept an array of pointers to
arguments:
```
void *ArgPtrs[] = {&A, &B, &C};
size_t ArgSizes[] = {sizeof(A), sizeof(B), sizeof(C)};
olLaunchKernel(Queue, Device, Kernel, &LaunchArgs, std::size(ArgPtrs), ArgPtrs, ArgSizes);
```
The newly proposed interface is implementable by existing and
anticipated
backends, is familiar to CUDA programmers, eliminates the extraneous
construction of a contiguous arguments buffer, replacing it with
constructing
an array of pointers, sidesteps the alignment requirements, does not
require reading program image metadata where it's impractical, and
enables
a compliant SYCL implementation to be built on top of it.
The ArgSizes array is required to support OpenCL, which does not have
native support for launching a kernel with an argument pointer array, or
a reliable way of retrieving argument sizes for a kernel.
## Mapping the proposed API to backends
CUDA and Level-Zero both support accepting an array of pointers to
kernel arguments, through `cuLaunchKernel`
(https://docs.nvidia.com/cuda/cuda-driver-api/group__CUDA__EXEC.html#group__CUDA__EXEC_1gb8f3dc3031b40da29d5f9a7139e52e15)
and `zeCommandListAppendLaunchKernelWithArguments`
(https://oneapi-src.github.io/level-zero-spec/level-zero/latest/core/api.html#zecommandlistappendlaunchkernelwitharguments)
respectively.
For OpenCL, which requires the kernel arguments to be set separately
from the kernel launch, a potential implementation can extract the
number of arguments from the OpenCL API, and then iterate over the
argument pointer and size arrays:
```
cl_uint num_args = 0;
cl_int err = clGetKernelInfo(kernel, CL_KERNEL_NUM_ARGS,
sizeof(num_args), &num_args, NULL);
for (cl_uint i = 0; i < num_args; ++i) {
clSetKernelArg(kernel, i, ArgSizes[i], ArgPtrs[i]);
}
```
The AMDGPU plugin needs to construct a contiguous buffer using the array
of argument pointers. To do this conversion, we need to have offsets
at which to place the arguments. Here, luckily, as mentioned before,
the AMD plugin already reads kernel metadata from the program image.
The implementation simply retrieves size and offset for each argument
from the kernel image, and then uses it to populate a buffer.
2026-05-29 09:54:22 -08:00
|
|
|
uint32_t NumThreads[3],
|
|
|
|
|
uint32_t NumBlocks[3]) const;
|
2026-07-27 01:48:47 -08:00
|
|
|
Error setIndirectFlags(L0DeviceTy &L0Device, L0LaunchEnvTy &KEnv) const;
|
2025-12-17 22:53:03 -09:00
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
/// Create a L0 kernel with a name and an execution mode.
|
2026-07-31 11:29:06 -08:00
|
|
|
L0KernelTy(StringRef Name) : GenericKernelTy(Name), zeKernel(nullptr) {}
|
2025-12-17 22:53:03 -09:00
|
|
|
~L0KernelTy() = default;
|
|
|
|
|
L0KernelTy(const L0KernelTy &) = delete;
|
|
|
|
|
L0KernelTy(L0KernelTy &&) = delete;
|
|
|
|
|
L0KernelTy &operator=(const L0KernelTy &) = delete;
|
|
|
|
|
L0KernelTy &operator=(const L0KernelTy &&) = delete;
|
|
|
|
|
|
|
|
|
|
KernelPropertiesTy &getProperties() const { return Properties; }
|
|
|
|
|
|
|
|
|
|
/// Initialize the L0 kernel.
|
|
|
|
|
Error initImpl(GenericDeviceTy &GenericDevice, DeviceImageTy &Image) override;
|
|
|
|
|
/// Launch the L0 kernel function.
|
|
|
|
|
Error launchImpl(GenericDeviceTy &GenericDevice, uint32_t NumThreads[3],
|
2026-03-12 00:13:06 -08:00
|
|
|
uint32_t NumBlocks[3], uint32_t DynBlockMemSize,
|
|
|
|
|
KernelArgsTy &KernelArgs, KernelLaunchParamsTy LaunchParams,
|
2025-12-17 22:53:03 -09:00
|
|
|
AsyncInfoWrapperTy &AsyncInfoWrapper) const override;
|
|
|
|
|
Error deinit() {
|
|
|
|
|
CALL_ZE_RET_ERROR(zeKernelDestroy, zeKernel);
|
|
|
|
|
return Plugin::success();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Expected<uint64_t> maxGroupSize(GenericDeviceTy &GenericDevice,
|
|
|
|
|
uint64_t DynamicMemSize) const override {
|
|
|
|
|
return Plugin::error(ErrorCode::UNIMPLEMENTED,
|
|
|
|
|
"maxGroupSize not implemented yet");
|
|
|
|
|
}
|
|
|
|
|
|
[offload] Add properties parameter to olLaunchKernel (#197897)
Introduce a properties argument to olLaunchKernel to enable future
extensions.
This change adds initial extension for cooperative kernel launch.
The change restores the functionality from:
https://github.com/llvm/llvm-project/pull/184343
which was later reverted in:
https://github.com/llvm/llvm-project/pull/197463
#184343 modified the API, and between the last rebase and the final
merge, additional tests were added
upstream(https://github.com/llvm/llvm-project/pull/193927) that still
relied on the previous API version.
Diff between this PR and #184343
```
diff --git a/offload/unittests/OffloadAPI/kernel/olLaunchKernel.cpp b/offload/unittests/OffloadAPI/kernel/olLaunchKernel.cpp
index 0251bffefe60..cd527f18db38 100644
--- a/offload/unittests/OffloadAPI/kernel/olLaunchKernel.cpp
+++ b/offload/unittests/OffloadAPI/kernel/olLaunchKernel.cpp
@@ -241,8 +241,8 @@ TEST_P(olLaunchKernelSingleCounterSyncEventTest, SuccessSyncEvent) {
ArgsSingleCounter Args{LoopRange, NumberToAdd, (uint32_t *)InitValuePassed,
(uint32_t *)ResNum};
- ASSERT_SUCCESS(
- olLaunchKernel(Queue, Device, Kernel, &Args, sizeof(Args), &LaunchArgs));
+ ASSERT_SUCCESS(olLaunchKernel(Queue, Device, Kernel, &Args, sizeof(Args),
+ &LaunchArgs, nullptr));
uint32_t FinalResVal = 0;
ASSERT_SUCCESS(olMemcpy(Queue, &FinalResVal, Host, ResNum, Device, Size));
@@ -294,8 +294,8 @@ TEST_P(olLaunchKernelSingleCounterSyncEventTest, SuccessTwoQueues) {
ArgsSingleCounter Args{LoopRange, NumberToAdd, (uint32_t *)InitValuePassed,
(uint32_t *)ResNum1};
- ASSERT_SUCCESS(
- olLaunchKernel(Queue, Device, Kernel, &Args, sizeof(Args), &LaunchArgs));
+ ASSERT_SUCCESS(olLaunchKernel(Queue, Device, Kernel, &Args, sizeof(Args),
+ &LaunchArgs, nullptr));
ol_event_handle_t Event = nullptr;
ASSERT_SUCCESS(olCreateEvent(Queue, &Event));
@@ -308,7 +308,7 @@ TEST_P(olLaunchKernelSingleCounterSyncEventTest, SuccessTwoQueues) {
// been completed by the time the kernel is executed using the second queue,
// the FinalResVal would be incorrect.
ASSERT_SUCCESS(olLaunchKernel(Queue2, Device, Kernel, &Args2, sizeof(Args2),
- &LaunchArgs));
+ &LaunchArgs, nullptr));
ASSERT_SUCCESS(olSyncQueue(Queue2));
uint32_t FinalResVal = 0;
```
2026-05-18 07:07:38 -08:00
|
|
|
Expected<uint32_t>
|
|
|
|
|
getMaxCooperativeGroupCount(GenericDeviceTy &GenericDevice,
|
|
|
|
|
const uint32_t NumThreads[3],
|
|
|
|
|
uint32_t DynBlockMemSize) const override;
|
|
|
|
|
|
2025-12-17 22:53:03 -09:00
|
|
|
ze_kernel_handle_t getZeKernel() const { return zeKernel; }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
} // namespace llvm::omp::target::plugin
|
|
|
|
|
|
|
|
|
|
#endif // OPENMP_LIBOMPTARGET_PLUGINS_NEXTGEN_LEVEL_ZERO_L0KERNEL_H
|