CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
502 lines
17 KiB
C++
502 lines
17 KiB
C++
//===------- Offload API tests - olLaunchKernel --------------------===//
|
|
//
|
|
// 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 "../common/Fixtures.hpp"
|
|
#include <OffloadAPI.h>
|
|
#include <gtest/gtest.h>
|
|
|
|
#define KERNEL_TEST(NAME, KERNEL) \
|
|
struct olLaunchKernel##NAME##Test : LaunchSingleKernelTestBase { \
|
|
void SetUp() override { SetUpKernel(#KERNEL); } \
|
|
}; \
|
|
OFFLOAD_TESTS_INSTANTIATE_DEVICE_FIXTURE(olLaunchKernel##NAME##Test);
|
|
|
|
KERNEL_TEST(Foo, foo)
|
|
KERNEL_TEST(NoArgs, noargs)
|
|
KERNEL_TEST(MultiArgs, multiargs)
|
|
KERNEL_TEST(Composite, composite)
|
|
KERNEL_TEST(Byte, byte)
|
|
KERNEL_TEST(LocalMem, localmem)
|
|
KERNEL_TEST(LocalMemReduction, localmem_reduction)
|
|
KERNEL_TEST(LocalMemStatic, localmem_static)
|
|
KERNEL_TEST(SingleCounterSyncEvent, single_counter)
|
|
KERNEL_TEST(GlobalCtor, global_ctor)
|
|
KERNEL_TEST(GlobalDtor, global_dtor)
|
|
KERNEL_TEST(GridSize, gridsize)
|
|
|
|
struct LaunchMultipleKernelTestBase : LaunchKernelTestBase {
|
|
void SetUpKernels(const char *program, std::vector<const char *> kernels) {
|
|
RETURN_ON_FATAL_FAILURE(SetUpProgram(program));
|
|
|
|
Kernels.resize(kernels.size());
|
|
size_t I = 0;
|
|
for (auto K : kernels)
|
|
ASSERT_SUCCESS(
|
|
olGetSymbol(Program, K, OL_SYMBOL_KIND_KERNEL, &Kernels[I++]));
|
|
}
|
|
|
|
std::vector<ol_symbol_handle_t> Kernels;
|
|
};
|
|
|
|
struct ArgsSingleCounter {
|
|
int32_t InitLoop;
|
|
int32_t Addend;
|
|
uint32_t *InitVal;
|
|
uint32_t *Out;
|
|
};
|
|
|
|
#define KERNEL_MULTI_TEST(NAME, PROGRAM, ...) \
|
|
struct olLaunchKernel##NAME##Test : LaunchMultipleKernelTestBase { \
|
|
void SetUp() override { SetUpKernels(#PROGRAM, {__VA_ARGS__}); } \
|
|
}; \
|
|
OFFLOAD_TESTS_INSTANTIATE_DEVICE_FIXTURE(olLaunchKernel##NAME##Test);
|
|
|
|
KERNEL_MULTI_TEST(Global, global, "write", "read")
|
|
|
|
TEST_P(olLaunchKernelFooTest, Success) {
|
|
void *Mem;
|
|
ASSERT_SUCCESS(olMemAlloc(Device, OL_ALLOC_TYPE_MANAGED,
|
|
LaunchArgs.GroupSize.x * sizeof(uint32_t), &Mem));
|
|
|
|
void *ArgPtrs[] = {&Mem};
|
|
size_t ArgSizes[] = {sizeof(Mem)};
|
|
|
|
ASSERT_SUCCESS(olLaunchKernel(Queue, Device, Kernel, &LaunchArgs, nullptr,
|
|
std::size(ArgPtrs), ArgPtrs, ArgSizes));
|
|
|
|
ASSERT_SUCCESS(olSyncQueue(Queue));
|
|
|
|
uint32_t *Data = (uint32_t *)Mem;
|
|
for (uint32_t i = 0; i < 64; i++) {
|
|
ASSERT_EQ(Data[i], i);
|
|
}
|
|
|
|
ASSERT_SUCCESS(olMemFree(Mem));
|
|
}
|
|
|
|
TEST_P(olLaunchKernelFooTest, SuccessThreaded) {
|
|
SKIP_KNOWN_FAILURE(LevelZero{"thread-safety issues"});
|
|
|
|
threadify([&](size_t) {
|
|
void *DevAlloc, *HstAlloc;
|
|
size_t Size = LaunchArgs.GroupSize.x * sizeof(uint32_t);
|
|
ASSERT_SUCCESS(olMemAlloc(Device, OL_ALLOC_TYPE_DEVICE, Size, &DevAlloc));
|
|
ASSERT_SUCCESS(olMemAlloc(Device, OL_ALLOC_TYPE_HOST, Size, &HstAlloc));
|
|
|
|
void *ArgPtrs[] = {&DevAlloc};
|
|
size_t ArgSizes[] = {sizeof(DevAlloc)};
|
|
|
|
ASSERT_SUCCESS(olLaunchKernel(Queue, Device, Kernel, &LaunchArgs, nullptr,
|
|
std::size(ArgPtrs), ArgPtrs, ArgSizes));
|
|
|
|
ASSERT_SUCCESS(olMemcpy(Queue, HstAlloc, Host, DevAlloc, Device, Size));
|
|
|
|
ASSERT_SUCCESS(olSyncQueue(Queue));
|
|
|
|
uint32_t *Data = static_cast<uint32_t *>(HstAlloc);
|
|
for (uint32_t i = 0; i < LaunchArgs.GroupSize.x; i++) {
|
|
ASSERT_EQ(Data[i], i);
|
|
}
|
|
|
|
ASSERT_SUCCESS(olMemFree(DevAlloc));
|
|
ASSERT_SUCCESS(olMemFree(HstAlloc));
|
|
});
|
|
}
|
|
|
|
TEST_P(olLaunchKernelNoArgsTest, Success) {
|
|
ASSERT_SUCCESS(olLaunchKernel(Queue, Device, Kernel, &LaunchArgs, nullptr, 0,
|
|
nullptr, nullptr));
|
|
|
|
ASSERT_SUCCESS(olSyncQueue(Queue));
|
|
}
|
|
|
|
TEST_P(olLaunchKernelMultiArgsTest, Success) {
|
|
void *Mem;
|
|
ASSERT_SUCCESS(olMemAlloc(Device, OL_ALLOC_TYPE_MANAGED,
|
|
LaunchArgs.GroupSize.x * sizeof(int), &Mem));
|
|
|
|
char A = 3;
|
|
int *B = (int *)Mem;
|
|
short C = 5;
|
|
|
|
void *ArgPtrs[] = {&A, &B, &C};
|
|
size_t ArgSizes[] = {sizeof(A), sizeof(B), sizeof(C)};
|
|
|
|
ASSERT_SUCCESS(olLaunchKernel(Queue, Device, Kernel, &LaunchArgs, nullptr,
|
|
std::size(ArgPtrs), ArgPtrs, ArgSizes));
|
|
|
|
ASSERT_SUCCESS(olSyncQueue(Queue));
|
|
|
|
int *Data = (int *)Mem;
|
|
for (uint32_t i = 0; i < LaunchArgs.GroupSize.x; i++)
|
|
ASSERT_EQ(Data[i], A + C + static_cast<int>(i));
|
|
|
|
ASSERT_SUCCESS(olMemFree(Mem));
|
|
}
|
|
|
|
struct Foo {
|
|
uint32_t a;
|
|
uint32_t b;
|
|
};
|
|
|
|
TEST_P(olLaunchKernelCompositeTest, Success) {
|
|
void *Mem;
|
|
ASSERT_SUCCESS(olMemAlloc(Device, OL_ALLOC_TYPE_MANAGED,
|
|
LaunchArgs.GroupSize.x * sizeof(uint32_t), &Mem));
|
|
|
|
uint8_t N = 1;
|
|
Foo F{2, 3};
|
|
uint32_t *Out = (uint32_t *)Mem;
|
|
|
|
void *ArgPtrs[] = {&N, &F, &Out};
|
|
size_t ArgSizes[] = {sizeof(N), sizeof(F), sizeof(Out)};
|
|
|
|
ASSERT_SUCCESS(olLaunchKernel(Queue, Device, Kernel, &LaunchArgs, nullptr,
|
|
std::size(ArgPtrs), ArgPtrs, ArgSizes));
|
|
|
|
ASSERT_SUCCESS(olSyncQueue(Queue));
|
|
|
|
uint32_t *Data = (uint32_t *)Mem;
|
|
for (uint32_t i = 0; i < LaunchArgs.GroupSize.x; i++)
|
|
ASSERT_EQ(Data[i], N + F.a + F.b + i);
|
|
|
|
ASSERT_SUCCESS(olMemFree(Mem));
|
|
}
|
|
|
|
TEST_P(olLaunchKernelFooTest, SuccessSynchronous) {
|
|
void *Mem;
|
|
ASSERT_SUCCESS(olMemAlloc(Device, OL_ALLOC_TYPE_MANAGED,
|
|
LaunchArgs.GroupSize.x * sizeof(uint32_t), &Mem));
|
|
|
|
void *ArgPtrs[] = {&Mem};
|
|
size_t ArgSizes[] = {sizeof(Mem)};
|
|
|
|
ASSERT_SUCCESS(olLaunchKernel(nullptr, Device, Kernel, &LaunchArgs, nullptr,
|
|
std::size(ArgPtrs), ArgPtrs, ArgSizes));
|
|
|
|
uint32_t *Data = (uint32_t *)Mem;
|
|
for (uint32_t i = 0; i < 64; i++) {
|
|
ASSERT_EQ(Data[i], i);
|
|
}
|
|
|
|
ASSERT_SUCCESS(olMemFree(Mem));
|
|
}
|
|
|
|
TEST_P(olLaunchKernelByteTest, Success) {
|
|
unsigned char C = 42;
|
|
|
|
void *ArgPtrs[] = {&C};
|
|
size_t ArgSizes[] = {sizeof(C)};
|
|
|
|
ASSERT_SUCCESS(olLaunchKernel(Queue, Device, Kernel, &LaunchArgs, nullptr,
|
|
std::size(ArgPtrs), ArgPtrs, ArgSizes));
|
|
|
|
ASSERT_SUCCESS(olSyncQueue(Queue));
|
|
}
|
|
|
|
TEST_P(olLaunchKernelLocalMemTest, Success) {
|
|
SKIP_KNOWN_FAILURE(LevelZero{"unsupported DynSharedMemory"});
|
|
|
|
LaunchArgs.NumGroups.x = 4;
|
|
LaunchArgs.DynSharedMemory = 64 * sizeof(uint32_t);
|
|
|
|
void *Mem;
|
|
ASSERT_SUCCESS(olMemAlloc(Device, OL_ALLOC_TYPE_MANAGED,
|
|
LaunchArgs.GroupSize.x * LaunchArgs.NumGroups.x *
|
|
sizeof(uint32_t),
|
|
&Mem));
|
|
|
|
void *ArgPtrs[] = {&Mem};
|
|
size_t ArgSizes[] = {sizeof(Mem)};
|
|
|
|
ASSERT_SUCCESS(olLaunchKernel(Queue, Device, Kernel, &LaunchArgs, nullptr,
|
|
std::size(ArgPtrs), ArgPtrs, ArgSizes));
|
|
|
|
ASSERT_SUCCESS(olSyncQueue(Queue));
|
|
|
|
uint32_t *Data = (uint32_t *)Mem;
|
|
for (uint32_t i = 0; i < LaunchArgs.GroupSize.x * LaunchArgs.NumGroups.x; i++)
|
|
ASSERT_EQ(Data[i], (i % 64) * 2);
|
|
|
|
ASSERT_SUCCESS(olMemFree(Mem));
|
|
}
|
|
|
|
TEST_P(olLaunchKernelLocalMemReductionTest, Success) {
|
|
SKIP_KNOWN_FAILURE(LevelZero{"unsupported DynSharedMemory"});
|
|
|
|
LaunchArgs.NumGroups.x = 4;
|
|
LaunchArgs.DynSharedMemory = 64 * sizeof(uint32_t);
|
|
|
|
void *Mem;
|
|
ASSERT_SUCCESS(olMemAlloc(Device, OL_ALLOC_TYPE_MANAGED,
|
|
LaunchArgs.NumGroups.x * sizeof(uint32_t), &Mem));
|
|
|
|
void *ArgPtrs[] = {&Mem};
|
|
size_t ArgSizes[] = {sizeof(Mem)};
|
|
|
|
ASSERT_SUCCESS(olLaunchKernel(Queue, Device, Kernel, &LaunchArgs, nullptr,
|
|
std::size(ArgPtrs), ArgPtrs, ArgSizes));
|
|
|
|
ASSERT_SUCCESS(olSyncQueue(Queue));
|
|
|
|
uint32_t *Data = (uint32_t *)Mem;
|
|
for (uint32_t i = 0; i < LaunchArgs.NumGroups.x; i++)
|
|
ASSERT_EQ(Data[i], 2 * LaunchArgs.GroupSize.x);
|
|
|
|
ASSERT_SUCCESS(olMemFree(Mem));
|
|
}
|
|
|
|
TEST_P(olLaunchKernelLocalMemStaticTest, Success) {
|
|
SKIP_KNOWN_FAILURE(LevelZero{"unsupported DynSharedMemory"});
|
|
|
|
LaunchArgs.NumGroups.x = 4;
|
|
LaunchArgs.DynSharedMemory = 0;
|
|
|
|
void *Mem;
|
|
ASSERT_SUCCESS(olMemAlloc(Device, OL_ALLOC_TYPE_MANAGED,
|
|
LaunchArgs.NumGroups.x * sizeof(uint32_t), &Mem));
|
|
|
|
void *ArgPtrs[] = {&Mem};
|
|
size_t ArgSizes[] = {sizeof(Mem)};
|
|
|
|
ASSERT_SUCCESS(olLaunchKernel(Queue, Device, Kernel, &LaunchArgs, nullptr,
|
|
std::size(ArgPtrs), ArgPtrs, ArgSizes));
|
|
|
|
ASSERT_SUCCESS(olSyncQueue(Queue));
|
|
|
|
uint32_t *Data = (uint32_t *)Mem;
|
|
for (uint32_t i = 0; i < LaunchArgs.NumGroups.x; i++)
|
|
ASSERT_EQ(Data[i], 2 * LaunchArgs.GroupSize.x);
|
|
|
|
ASSERT_SUCCESS(olMemFree(Mem));
|
|
}
|
|
|
|
// The test intends to verify the correctness of the current implementation of
|
|
// the event synchronisation.
|
|
TEST_P(olLaunchKernelSingleCounterSyncEventTest, SuccessSyncEvent) {
|
|
void *InitValuePassed;
|
|
void *ResNum;
|
|
|
|
size_t Size = sizeof(uint32_t);
|
|
|
|
ASSERT_SUCCESS(
|
|
olMemAlloc(Device, OL_ALLOC_TYPE_DEVICE, Size, &InitValuePassed));
|
|
ASSERT_SUCCESS(olMemAlloc(Device, OL_ALLOC_TYPE_DEVICE, Size, &ResNum));
|
|
|
|
uint32_t HostInitVal = 0;
|
|
ASSERT_SUCCESS(
|
|
olMemcpy(Queue, InitValuePassed, Device, &HostInitVal, Host, Size));
|
|
ASSERT_SUCCESS(olMemcpy(Queue, ResNum, Device, &HostInitVal, Host, Size));
|
|
ASSERT_SUCCESS(olSyncQueue(Queue));
|
|
|
|
// The execution time of the provided kernel should be high enough to ensure
|
|
// that the read value of the final result is not correct without explicit
|
|
// synchronization: explicit waiting for the event following the submitted
|
|
// operation. LoopRange is arbitrarily set with the goal of prolonging the
|
|
// kernel execution through a high number of loop iterations. In each
|
|
// iteration, NumberToAdd is added to the final sum, which is stored in
|
|
// ResNum.
|
|
int32_t LoopRange = 1000000;
|
|
int32_t NumberToAdd = 2;
|
|
|
|
ArgsSingleCounter Args{LoopRange, NumberToAdd, (uint32_t *)InitValuePassed,
|
|
(uint32_t *)ResNum};
|
|
|
|
void *ArgPtrs[] = {&Args.InitLoop, &Args.Addend, &Args.InitVal, &Args.Out};
|
|
size_t ArgSizes[] = {sizeof(Args.InitLoop), sizeof(Args.Addend),
|
|
sizeof(Args.InitVal), sizeof(Args.Out)};
|
|
|
|
ASSERT_SUCCESS(olLaunchKernel(Queue, Device, Kernel, &LaunchArgs, nullptr,
|
|
std::size(ArgPtrs), ArgPtrs, ArgSizes));
|
|
|
|
uint32_t FinalResVal = 0;
|
|
ASSERT_SUCCESS(olMemcpy(Queue, &FinalResVal, Host, ResNum, Device, Size));
|
|
|
|
ol_event_handle_t Event = nullptr;
|
|
ASSERT_SUCCESS(olCreateEvent(Queue, OL_EVENT_FLAGS_NONE, &Event));
|
|
ASSERT_SUCCESS(olSyncEvent(Event));
|
|
|
|
ASSERT_EQ(FinalResVal, NumberToAdd * LoopRange);
|
|
|
|
ASSERT_SUCCESS(olMemFree(InitValuePassed));
|
|
ASSERT_SUCCESS(olMemFree(ResNum));
|
|
}
|
|
|
|
// The test checks the correctness of the synchronization between queues using
|
|
// events. Enqueueing the kernel on the queue `Q1` should produce `Result1`,
|
|
// which is used as an initial value for the queue `Q2`. Therefore, before
|
|
// executing any future work, `Q2` should wait for the event `Event1`, which is
|
|
// created after submitting work on `Q1`. The required synchronization is
|
|
// ensured by `olWaitEvents(Q2, &Event1, 1)`. If `Q2` uses the value passed as
|
|
// `Result1` before the work on `Q1` has completed, the result of the kernel
|
|
// enqueued on `Q2` would be incorrect.
|
|
TEST_P(olLaunchKernelSingleCounterSyncEventTest, SuccessTwoQueues) {
|
|
void *InitValuePassed;
|
|
void *ResNum1;
|
|
void *ResNum2;
|
|
|
|
size_t Size = sizeof(uint32_t);
|
|
|
|
ASSERT_SUCCESS(
|
|
olMemAlloc(Device, OL_ALLOC_TYPE_DEVICE, Size, &InitValuePassed));
|
|
ASSERT_SUCCESS(olMemAlloc(Device, OL_ALLOC_TYPE_DEVICE, Size, &ResNum1));
|
|
ASSERT_SUCCESS(olMemAlloc(Device, OL_ALLOC_TYPE_DEVICE, Size, &ResNum2));
|
|
|
|
uint32_t HostInitVal = 0;
|
|
ASSERT_SUCCESS(
|
|
olMemcpy(Queue, InitValuePassed, Device, &HostInitVal, Host, Size));
|
|
ASSERT_SUCCESS(olMemcpy(Queue, ResNum1, Device, &HostInitVal, Host, Size));
|
|
ASSERT_SUCCESS(olMemcpy(Queue, ResNum2, Device, &HostInitVal, Host, Size));
|
|
ASSERT_SUCCESS(olSyncQueue(Queue));
|
|
|
|
ol_queue_handle_t Queue2 = nullptr;
|
|
ASSERT_SUCCESS(olCreateQueue(Device, &Queue2));
|
|
|
|
// For the explanation of the reasoning behind particular values assigned to
|
|
// parameters, see the comment in the Success test from the same test suite
|
|
int32_t LoopRange = 1000000;
|
|
int32_t NumberToAdd = 2;
|
|
|
|
ArgsSingleCounter Args{LoopRange, NumberToAdd, (uint32_t *)InitValuePassed,
|
|
(uint32_t *)ResNum1};
|
|
void *ArgPtrs[] = {&Args.InitLoop, &Args.Addend, &Args.InitVal, &Args.Out};
|
|
size_t ArgSizes[] = {sizeof(Args.InitLoop), sizeof(Args.Addend),
|
|
sizeof(Args.InitVal), sizeof(Args.Out)};
|
|
ASSERT_SUCCESS(olLaunchKernel(Queue, Device, Kernel, &LaunchArgs, nullptr,
|
|
std::size(ArgPtrs), ArgPtrs, ArgSizes));
|
|
|
|
ol_event_handle_t Event = nullptr;
|
|
ASSERT_SUCCESS(olCreateEvent(Queue, OL_EVENT_FLAGS_NONE, &Event));
|
|
ASSERT_SUCCESS(olWaitEvents(Queue2, &Event, 1));
|
|
ArgsSingleCounter Args2{LoopRange, NumberToAdd, (uint32_t *)ResNum1,
|
|
(uint32_t *)ResNum2};
|
|
void *ArgPtrs2[] = {&Args2.InitLoop, &Args2.Addend, &Args2.InitVal,
|
|
&Args2.Out};
|
|
|
|
// At the beginning of the kernel, ResNum from the first queue is saved
|
|
// locally as the initial value. If operations enqueued before Event have not
|
|
// been completed by the time the kernel is executed using the second queue,
|
|
// the FinalResVal would be incorrect.
|
|
ASSERT_SUCCESS(olLaunchKernel(Queue2, Device, Kernel, &LaunchArgs, nullptr,
|
|
std::size(ArgPtrs2), ArgPtrs2, ArgSizes));
|
|
|
|
ASSERT_SUCCESS(olSyncQueue(Queue2));
|
|
uint32_t FinalResVal = 0;
|
|
ASSERT_SUCCESS(olMemcpy(Queue2, &FinalResVal, Host, ResNum2, Device, Size));
|
|
ASSERT_SUCCESS(olSyncQueue(Queue2));
|
|
|
|
ASSERT_EQ(FinalResVal, 2 * NumberToAdd * LoopRange);
|
|
|
|
ASSERT_SUCCESS(olMemFree(InitValuePassed));
|
|
ASSERT_SUCCESS(olMemFree(ResNum1));
|
|
ASSERT_SUCCESS(olMemFree(ResNum2));
|
|
}
|
|
|
|
TEST_P(olLaunchKernelGlobalTest, Success) {
|
|
void *Mem;
|
|
ASSERT_SUCCESS(olMemAlloc(Device, OL_ALLOC_TYPE_MANAGED,
|
|
LaunchArgs.GroupSize.x * sizeof(uint32_t), &Mem));
|
|
|
|
void *ArgPtrs[] = {&Mem};
|
|
size_t ArgSizes[] = {sizeof(Mem)};
|
|
|
|
ASSERT_SUCCESS(olLaunchKernel(Queue, Device, Kernels[0], &LaunchArgs, nullptr,
|
|
0, nullptr, nullptr));
|
|
ASSERT_SUCCESS(olSyncQueue(Queue));
|
|
ASSERT_SUCCESS(olLaunchKernel(Queue, Device, Kernels[1], &LaunchArgs, nullptr,
|
|
std::size(ArgPtrs), ArgPtrs, ArgSizes));
|
|
ASSERT_SUCCESS(olSyncQueue(Queue));
|
|
|
|
uint32_t *Data = (uint32_t *)Mem;
|
|
for (uint32_t i = 0; i < 64; i++) {
|
|
ASSERT_EQ(Data[i], i * 2);
|
|
}
|
|
|
|
ASSERT_SUCCESS(olMemFree(Mem));
|
|
}
|
|
|
|
TEST_P(olLaunchKernelGlobalTest, InvalidNotAKernel) {
|
|
ol_symbol_handle_t Global = nullptr;
|
|
ASSERT_SUCCESS(
|
|
olGetSymbol(Program, "global", OL_SYMBOL_KIND_GLOBAL_VARIABLE, &Global));
|
|
ASSERT_ERROR(OL_ERRC_SYMBOL_KIND,
|
|
olLaunchKernel(Queue, Device, Global, &LaunchArgs, nullptr, 0,
|
|
nullptr, nullptr));
|
|
}
|
|
|
|
TEST_P(olLaunchKernelGlobalCtorTest, Success) {
|
|
SKIP_KNOWN_FAILURE(LevelZero{"unsupported feature"});
|
|
|
|
void *Mem;
|
|
ASSERT_SUCCESS(olMemAlloc(Device, OL_ALLOC_TYPE_MANAGED,
|
|
LaunchArgs.GroupSize.x * sizeof(uint32_t), &Mem));
|
|
|
|
void *ArgPtrs[] = {&Mem};
|
|
size_t ArgSizes[] = {sizeof(Mem)};
|
|
|
|
ASSERT_SUCCESS(olLaunchKernel(Queue, Device, Kernel, &LaunchArgs, nullptr,
|
|
std::size(ArgPtrs), ArgPtrs, ArgSizes));
|
|
ASSERT_SUCCESS(olSyncQueue(Queue));
|
|
|
|
uint32_t *Data = (uint32_t *)Mem;
|
|
for (uint32_t i = 0; i < 64; i++) {
|
|
ASSERT_EQ(Data[i], i + 100);
|
|
}
|
|
|
|
ASSERT_SUCCESS(olMemFree(Mem));
|
|
}
|
|
|
|
TEST_P(olLaunchKernelGlobalDtorTest, Success) {
|
|
// TODO: We can't inspect the result of a destructor yet, once we
|
|
// find/implement a way, update this test. For now we just check that nothing
|
|
// crashes
|
|
ASSERT_SUCCESS(olLaunchKernel(Queue, Device, Kernel, &LaunchArgs, nullptr, 0,
|
|
nullptr, nullptr));
|
|
ASSERT_SUCCESS(olSyncQueue(Queue));
|
|
}
|
|
|
|
TEST_P(olLaunchKernelGridSizeTest, Success) {
|
|
void *Mem;
|
|
ASSERT_SUCCESS(
|
|
olMemAlloc(Device, OL_ALLOC_TYPE_MANAGED, 6 * sizeof(uint32_t), &Mem));
|
|
|
|
uint32_t *NumBlocks = static_cast<uint32_t *>(Mem);
|
|
uint32_t *NumThreads = static_cast<uint32_t *>(Mem) + 3;
|
|
|
|
void *ArgPtrs[] = {&NumBlocks, &NumThreads};
|
|
size_t ArgSizes[] = {sizeof(NumBlocks), sizeof(NumThreads)};
|
|
|
|
const uint32_t BaseBlocks[3] = {64, 16, 8};
|
|
const uint32_t BaseThreads[3] = {32, 4, 2};
|
|
|
|
for (uint32_t Dim = 1; Dim <= 3; ++Dim) {
|
|
NumBlocks[0] = NumBlocks[1] = NumBlocks[2] = 0;
|
|
NumThreads[0] = NumThreads[1] = NumThreads[2] = 0;
|
|
|
|
LaunchArgs.Dimensions = 3;
|
|
LaunchArgs.NumGroups = {BaseBlocks[0], Dim >= 2 ? BaseBlocks[1] : 1,
|
|
Dim >= 3 ? BaseBlocks[2] : 1};
|
|
LaunchArgs.GroupSize = {BaseThreads[0], Dim >= 2 ? BaseThreads[1] : 1,
|
|
Dim >= 3 ? BaseThreads[2] : 1};
|
|
|
|
ASSERT_SUCCESS(olLaunchKernel(Queue, Device, Kernel, &LaunchArgs, nullptr,
|
|
std::size(ArgPtrs), ArgPtrs, ArgSizes));
|
|
|
|
ASSERT_SUCCESS(olSyncQueue(Queue));
|
|
|
|
ASSERT_EQ(NumBlocks[0], LaunchArgs.NumGroups.x);
|
|
ASSERT_EQ(NumBlocks[1], LaunchArgs.NumGroups.y);
|
|
ASSERT_EQ(NumBlocks[2], LaunchArgs.NumGroups.z);
|
|
ASSERT_EQ(NumThreads[0], LaunchArgs.GroupSize.x);
|
|
ASSERT_EQ(NumThreads[1], LaunchArgs.GroupSize.y);
|
|
ASSERT_EQ(NumThreads[2], LaunchArgs.GroupSize.z);
|
|
}
|
|
|
|
ASSERT_SUCCESS(olMemFree(Mem));
|
|
}
|