| //===-- LanguageLaunch.cpp - Language launch API --------------------------===// |
| // |
| // 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 |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "LanguageLaunch.h" |
| #include "LanguageUtils.h" |
| #include "OffloadErrors.h" |
| #include "State.h" |
| #include "Stream.h" |
| #include <cstdio> |
| |
| using namespace llvm::offload; |
| |
| /// Internal kernel launch implementation |
| ol_result_t __llvmLaunchKernelImpl(const char *KernelID, dim3 GridDim, |
| dim3 BlockDim, void *KernelArgsPtr, |
| size_t DynamicSharedMem, void *Stream) { |
| StateTy &State = StateTy::get(); |
| ThreadStateTy &ThreadState = ThreadStateTy::get(); |
| ol_device_handle_t Device = ThreadState.getDefaultDevice(); |
| ol_symbol_handle_t Kernel = State.getKernel(KernelID); |
| if (!Device) |
| return &InvalidDeviceError; |
| if (!KernelID || !KernelArgsPtr) |
| return &InvalidArgumentError; |
| if (!Kernel) |
| return &InvalidKernelError; |
| |
| if (GridDim.x == 0 || GridDim.y == 0 || GridDim.z == 0 || BlockDim.x == 0 || |
| BlockDim.y == 0 || BlockDim.z == 0) |
| return &InvalidConfigurationError; |
| |
| ol_kernel_launch_size_args_t LaunchSizeArgs; |
| LaunchSizeArgs.Dimensions = |
| 1 + (GridDim.y > 1 || BlockDim.y > 1) + (GridDim.z > 1 || BlockDim.z > 1); |
| LaunchSizeArgs.NumGroups.x = GridDim.x; |
| LaunchSizeArgs.NumGroups.y = GridDim.y; |
| LaunchSizeArgs.NumGroups.z = GridDim.z; |
| LaunchSizeArgs.GroupSize.x = BlockDim.x; |
| LaunchSizeArgs.GroupSize.y = BlockDim.y; |
| LaunchSizeArgs.GroupSize.z = BlockDim.z; |
| LaunchSizeArgs.DynSharedMemory = DynamicSharedMem; |
| |
| ol_queue_handle_t Queue = Stream ? reinterpret_cast<StreamTy *>(Stream)->Queue |
| : ThreadState.getDefaultQueue(); |
| |
| struct OffloadKernelArgs { |
| void **Args; |
| size_t NumArgs; |
| size_t *ArgSizes; |
| }; |
| OffloadKernelArgs *OKA = static_cast<OffloadKernelArgs *>(KernelArgsPtr); |
| if ((!OKA->Args) != (!OKA->ArgSizes)) |
| return &InvalidArgumentError; |
| if (OKA->NumArgs > 0 && !OKA->Args) |
| return &InvalidArgumentError; |
| for (size_t I = 0; I < OKA->NumArgs; ++I) |
| if (!OKA->Args[I] || OKA->ArgSizes[I] == 0) |
| return &InvalidArgumentError; |
| |
| return olLaunchKernel(Queue, Device, Kernel, &LaunchSizeArgs, |
| /*Properties=*/nullptr, OKA->NumArgs, OKA->Args, |
| OKA->ArgSizes); |
| } |
| |
| extern "C" { |
| |
| /// Push call configuration for kernel launch |
| unsigned __llvmPushCallConfiguration(dim3 GridSize, dim3 BlockSize, |
| size_t SharedMemory, void *Stream) { |
| ThreadStateTy &ThreadState = ThreadStateTy::get(); |
| CallConfigurationTy &CC = ThreadState.getCallConfiguration(); |
| |
| CC.GridSize = GridSize; |
| CC.BlockSize = BlockSize; |
| CC.SharedMemory = SharedMemory; |
| CC.Stream = Stream; |
| return 0; |
| } |
| |
| /// Pop call configuration for kernel launch |
| unsigned __llvmPopCallConfiguration(dim3 *GridSize, dim3 *BlockSize, |
| size_t *SharedMemory, void **Stream) { |
| ThreadStateTy &ThreadState = ThreadStateTy::get(); |
| CallConfigurationTy &CC = ThreadState.getCallConfiguration(); |
| *GridSize = CC.GridSize; |
| *BlockSize = CC.BlockSize; |
| *SharedMemory = CC.SharedMemory; |
| *Stream = CC.Stream; |
| return 0; |
| } |
| |
| unsigned llvmLaunchKernel(const char *KernelID, dim3 GridDim, dim3 BlockDim, |
| void *KernelArgsPtr, size_t DynamicSharedMem, |
| void *Stream) { |
| ol_result_t Result = __llvmLaunchKernelImpl( |
| KernelID, GridDim, BlockDim, KernelArgsPtr, DynamicSharedMem, Stream); |
| convertAndSetLastError(Result); |
| return Result ? Result->Code : 0; |
| } |
| |
| } // extern "C" |