288 lines · cpp
1//===------- Offload API tests - olLaunchKernel --------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "../common/Fixtures.hpp"10#include <OffloadAPI.h>11#include <gtest/gtest.h>12 13struct LaunchKernelTestBase : OffloadQueueTest {14 void SetUpProgram(const char *program) {15 RETURN_ON_FATAL_FAILURE(OffloadQueueTest::SetUp());16 ASSERT_TRUE(TestEnvironment::loadDeviceBinary(program, Device, DeviceBin));17 ASSERT_GE(DeviceBin->getBufferSize(), 0lu);18 ASSERT_SUCCESS(olCreateProgram(Device, DeviceBin->getBufferStart(),19 DeviceBin->getBufferSize(), &Program));20 21 LaunchArgs.Dimensions = 1;22 LaunchArgs.GroupSize = {64, 1, 1};23 LaunchArgs.NumGroups = {1, 1, 1};24 25 LaunchArgs.DynSharedMemory = 0;26 }27 28 void TearDown() override {29 if (Program) {30 olDestroyProgram(Program);31 }32 RETURN_ON_FATAL_FAILURE(OffloadQueueTest::TearDown());33 }34 35 std::unique_ptr<llvm::MemoryBuffer> DeviceBin;36 ol_program_handle_t Program = nullptr;37 ol_kernel_launch_size_args_t LaunchArgs{};38};39 40struct LaunchSingleKernelTestBase : LaunchKernelTestBase {41 void SetUpKernel(const char *kernel) {42 RETURN_ON_FATAL_FAILURE(SetUpProgram(kernel));43 ASSERT_SUCCESS(44 olGetSymbol(Program, kernel, OL_SYMBOL_KIND_KERNEL, &Kernel));45 }46 47 ol_symbol_handle_t Kernel = nullptr;48};49 50#define KERNEL_TEST(NAME, KERNEL) \51 struct olLaunchKernel##NAME##Test : LaunchSingleKernelTestBase { \52 void SetUp() override { SetUpKernel(#KERNEL); } \53 }; \54 OFFLOAD_TESTS_INSTANTIATE_DEVICE_FIXTURE(olLaunchKernel##NAME##Test);55 56KERNEL_TEST(Foo, foo)57KERNEL_TEST(NoArgs, noargs)58KERNEL_TEST(Byte, byte)59KERNEL_TEST(LocalMem, localmem)60KERNEL_TEST(LocalMemReduction, localmem_reduction)61KERNEL_TEST(LocalMemStatic, localmem_static)62KERNEL_TEST(GlobalCtor, global_ctor)63KERNEL_TEST(GlobalDtor, global_dtor)64 65struct LaunchMultipleKernelTestBase : LaunchKernelTestBase {66 void SetUpKernels(const char *program, std::vector<const char *> kernels) {67 RETURN_ON_FATAL_FAILURE(SetUpProgram(program));68 69 Kernels.resize(kernels.size());70 size_t I = 0;71 for (auto K : kernels)72 ASSERT_SUCCESS(73 olGetSymbol(Program, K, OL_SYMBOL_KIND_KERNEL, &Kernels[I++]));74 }75 76 std::vector<ol_symbol_handle_t> Kernels;77};78 79#define KERNEL_MULTI_TEST(NAME, PROGRAM, ...) \80 struct olLaunchKernel##NAME##Test : LaunchMultipleKernelTestBase { \81 void SetUp() override { SetUpKernels(#PROGRAM, {__VA_ARGS__}); } \82 }; \83 OFFLOAD_TESTS_INSTANTIATE_DEVICE_FIXTURE(olLaunchKernel##NAME##Test);84 85KERNEL_MULTI_TEST(Global, global, "write", "read")86 87TEST_P(olLaunchKernelFooTest, Success) {88 void *Mem;89 ASSERT_SUCCESS(olMemAlloc(Device, OL_ALLOC_TYPE_MANAGED,90 LaunchArgs.GroupSize.x * sizeof(uint32_t), &Mem));91 struct {92 void *Mem;93 } Args{Mem};94 95 ASSERT_SUCCESS(96 olLaunchKernel(Queue, Device, Kernel, &Args, sizeof(Args), &LaunchArgs));97 98 ASSERT_SUCCESS(olSyncQueue(Queue));99 100 uint32_t *Data = (uint32_t *)Mem;101 for (uint32_t i = 0; i < 64; i++) {102 ASSERT_EQ(Data[i], i);103 }104 105 ASSERT_SUCCESS(olMemFree(Mem));106}107 108TEST_P(olLaunchKernelFooTest, SuccessThreaded) {109 threadify([&](size_t) {110 void *Mem;111 ASSERT_SUCCESS(olMemAlloc(Device, OL_ALLOC_TYPE_MANAGED,112 LaunchArgs.GroupSize.x * sizeof(uint32_t), &Mem));113 struct {114 void *Mem;115 } Args{Mem};116 117 ASSERT_SUCCESS(olLaunchKernel(Queue, Device, Kernel, &Args, sizeof(Args),118 &LaunchArgs));119 120 ASSERT_SUCCESS(olSyncQueue(Queue));121 122 uint32_t *Data = (uint32_t *)Mem;123 for (uint32_t i = 0; i < 64; i++) {124 ASSERT_EQ(Data[i], i);125 }126 127 ASSERT_SUCCESS(olMemFree(Mem));128 });129}130 131TEST_P(olLaunchKernelNoArgsTest, Success) {132 ASSERT_SUCCESS(133 olLaunchKernel(Queue, Device, Kernel, nullptr, 0, &LaunchArgs));134 135 ASSERT_SUCCESS(olSyncQueue(Queue));136}137 138TEST_P(olLaunchKernelFooTest, SuccessSynchronous) {139 void *Mem;140 ASSERT_SUCCESS(olMemAlloc(Device, OL_ALLOC_TYPE_MANAGED,141 LaunchArgs.GroupSize.x * sizeof(uint32_t), &Mem));142 143 struct {144 void *Mem;145 } Args{Mem};146 147 ASSERT_SUCCESS(olLaunchKernel(nullptr, Device, Kernel, &Args, sizeof(Args),148 &LaunchArgs));149 150 uint32_t *Data = (uint32_t *)Mem;151 for (uint32_t i = 0; i < 64; i++) {152 ASSERT_EQ(Data[i], i);153 }154 155 ASSERT_SUCCESS(olMemFree(Mem));156}157 158TEST_P(olLaunchKernelLocalMemTest, Success) {159 LaunchArgs.NumGroups.x = 4;160 LaunchArgs.DynSharedMemory = 64 * sizeof(uint32_t);161 162 void *Mem;163 ASSERT_SUCCESS(olMemAlloc(Device, OL_ALLOC_TYPE_MANAGED,164 LaunchArgs.GroupSize.x * LaunchArgs.NumGroups.x *165 sizeof(uint32_t),166 &Mem));167 struct {168 void *Mem;169 } Args{Mem};170 171 ASSERT_SUCCESS(172 olLaunchKernel(Queue, Device, Kernel, &Args, sizeof(Args), &LaunchArgs));173 174 ASSERT_SUCCESS(olSyncQueue(Queue));175 176 uint32_t *Data = (uint32_t *)Mem;177 for (uint32_t i = 0; i < LaunchArgs.GroupSize.x * LaunchArgs.NumGroups.x; i++)178 ASSERT_EQ(Data[i], (i % 64) * 2);179 180 ASSERT_SUCCESS(olMemFree(Mem));181}182 183TEST_P(olLaunchKernelLocalMemReductionTest, Success) {184 LaunchArgs.NumGroups.x = 4;185 LaunchArgs.DynSharedMemory = 64 * sizeof(uint32_t);186 187 void *Mem;188 ASSERT_SUCCESS(olMemAlloc(Device, OL_ALLOC_TYPE_MANAGED,189 LaunchArgs.NumGroups.x * sizeof(uint32_t), &Mem));190 struct {191 void *Mem;192 } Args{Mem};193 194 ASSERT_SUCCESS(195 olLaunchKernel(Queue, Device, Kernel, &Args, sizeof(Args), &LaunchArgs));196 197 ASSERT_SUCCESS(olSyncQueue(Queue));198 199 uint32_t *Data = (uint32_t *)Mem;200 for (uint32_t i = 0; i < LaunchArgs.NumGroups.x; i++)201 ASSERT_EQ(Data[i], 2 * LaunchArgs.GroupSize.x);202 203 ASSERT_SUCCESS(olMemFree(Mem));204}205 206TEST_P(olLaunchKernelLocalMemStaticTest, Success) {207 LaunchArgs.NumGroups.x = 4;208 LaunchArgs.DynSharedMemory = 0;209 210 void *Mem;211 ASSERT_SUCCESS(olMemAlloc(Device, OL_ALLOC_TYPE_MANAGED,212 LaunchArgs.NumGroups.x * sizeof(uint32_t), &Mem));213 struct {214 void *Mem;215 } Args{Mem};216 217 ASSERT_SUCCESS(218 olLaunchKernel(Queue, Device, Kernel, &Args, sizeof(Args), &LaunchArgs));219 220 ASSERT_SUCCESS(olSyncQueue(Queue));221 222 uint32_t *Data = (uint32_t *)Mem;223 for (uint32_t i = 0; i < LaunchArgs.NumGroups.x; i++)224 ASSERT_EQ(Data[i], 2 * LaunchArgs.GroupSize.x);225 226 ASSERT_SUCCESS(olMemFree(Mem));227}228 229TEST_P(olLaunchKernelGlobalTest, Success) {230 void *Mem;231 ASSERT_SUCCESS(olMemAlloc(Device, OL_ALLOC_TYPE_MANAGED,232 LaunchArgs.GroupSize.x * sizeof(uint32_t), &Mem));233 struct {234 void *Mem;235 } Args{Mem};236 237 ASSERT_SUCCESS(238 olLaunchKernel(Queue, Device, Kernels[0], nullptr, 0, &LaunchArgs));239 ASSERT_SUCCESS(olSyncQueue(Queue));240 ASSERT_SUCCESS(olLaunchKernel(Queue, Device, Kernels[1], &Args, sizeof(Args),241 &LaunchArgs));242 ASSERT_SUCCESS(olSyncQueue(Queue));243 244 uint32_t *Data = (uint32_t *)Mem;245 for (uint32_t i = 0; i < 64; i++) {246 ASSERT_EQ(Data[i], i * 2);247 }248 249 ASSERT_SUCCESS(olMemFree(Mem));250}251 252TEST_P(olLaunchKernelGlobalTest, InvalidNotAKernel) {253 ol_symbol_handle_t Global = nullptr;254 ASSERT_SUCCESS(255 olGetSymbol(Program, "global", OL_SYMBOL_KIND_GLOBAL_VARIABLE, &Global));256 ASSERT_ERROR(OL_ERRC_SYMBOL_KIND,257 olLaunchKernel(Queue, Device, Global, nullptr, 0, &LaunchArgs));258}259 260TEST_P(olLaunchKernelGlobalCtorTest, Success) {261 void *Mem;262 ASSERT_SUCCESS(olMemAlloc(Device, OL_ALLOC_TYPE_MANAGED,263 LaunchArgs.GroupSize.x * sizeof(uint32_t), &Mem));264 struct {265 void *Mem;266 } Args{Mem};267 268 ASSERT_SUCCESS(269 olLaunchKernel(Queue, Device, Kernel, &Args, sizeof(Args), &LaunchArgs));270 ASSERT_SUCCESS(olSyncQueue(Queue));271 272 uint32_t *Data = (uint32_t *)Mem;273 for (uint32_t i = 0; i < 64; i++) {274 ASSERT_EQ(Data[i], i + 100);275 }276 277 ASSERT_SUCCESS(olMemFree(Mem));278}279 280TEST_P(olLaunchKernelGlobalDtorTest, Success) {281 // TODO: We can't inspect the result of a destructor yet, once we282 // find/implement a way, update this test. For now we just check that nothing283 // crashes284 ASSERT_SUCCESS(285 olLaunchKernel(Queue, Device, Kernel, nullptr, 0, &LaunchArgs));286 ASSERT_SUCCESS(olSyncQueue(Queue));287}288