1//===------- Offload API tests - olMemcpy --------------------------===//
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#include "../common/Fixtures.hpp"
10#include <OffloadAPI.h>
11#include <gtest/gtest.h>
12
13using olMemcpyTest = OffloadQueueTest;
14OFFLOAD_TESTS_INSTANTIATE_DEVICE_FIXTURE(olMemcpyTest);
15
16struct olMemcpyGlobalTest : OffloadGlobalTest {
17 void SetUp() override {
18 RETURN_ON_FATAL_FAILURE(OffloadGlobalTest::SetUp());
19 ASSERT_SUCCESS(
20 olGetSymbol(Program, "read", OL_SYMBOL_KIND_KERNEL, &ReadKernel));
21 ASSERT_SUCCESS(
22 olGetSymbol(Program, "write", OL_SYMBOL_KIND_KERNEL, &WriteKernel));
23 ASSERT_SUCCESS(olCreateQueue(Device, &Queue));
24 ASSERT_SUCCESS(olGetSymbolInfo(
25 Global, OL_SYMBOL_INFO_GLOBAL_VARIABLE_ADDRESS, sizeof(Addr), &Addr));
26
27 LaunchArgs.Dimensions = 1;
28 LaunchArgs.GroupSize = {64, 1, 1};
29 LaunchArgs.NumGroups = {1, 1, 1};
30
31 LaunchArgs.DynSharedMemory = 0;
32 }
33
34 ol_kernel_launch_size_args_t LaunchArgs{};
35 void *Addr;
36 ol_symbol_handle_t ReadKernel;
37 ol_symbol_handle_t WriteKernel;
38 ol_queue_handle_t Queue;
39};
40OFFLOAD_TESTS_INSTANTIATE_DEVICE_FIXTURE(olMemcpyGlobalTest);
41
42TEST_P(olMemcpyTest, SuccessHtoD) {
43 constexpr size_t Size = 1024;
44 void *Alloc;
45 ASSERT_SUCCESS(olMemAlloc(Device, OL_ALLOC_TYPE_DEVICE, Size, &Alloc));
46 std::vector<uint8_t> Input(Size, 42);
47 ASSERT_SUCCESS(
48 olMemcpy(Queue, Alloc, Device, Input.data(), Host, Size, nullptr));
49 olWaitQueue(Queue);
50 olMemFree(Alloc);
51}
52
53TEST_P(olMemcpyTest, SuccessDtoH) {
54 constexpr size_t Size = 1024;
55 void *Alloc;
56 std::vector<uint8_t> Input(Size, 42);
57 std::vector<uint8_t> Output(Size, 0);
58
59 ASSERT_SUCCESS(olMemAlloc(Device, OL_ALLOC_TYPE_DEVICE, Size, &Alloc));
60 ASSERT_SUCCESS(
61 olMemcpy(Queue, Alloc, Device, Input.data(), Host, Size, nullptr));
62 ASSERT_SUCCESS(
63 olMemcpy(Queue, Output.data(), Host, Alloc, Device, Size, nullptr));
64 ASSERT_SUCCESS(olWaitQueue(Queue));
65 for (uint8_t Val : Output) {
66 ASSERT_EQ(Val, 42);
67 }
68 ASSERT_SUCCESS(olMemFree(Alloc));
69}
70
71TEST_P(olMemcpyTest, SuccessDtoD) {
72 constexpr size_t Size = 1024;
73 void *AllocA;
74 void *AllocB;
75 std::vector<uint8_t> Input(Size, 42);
76 std::vector<uint8_t> Output(Size, 0);
77
78 ASSERT_SUCCESS(olMemAlloc(Device, OL_ALLOC_TYPE_DEVICE, Size, &AllocA));
79 ASSERT_SUCCESS(olMemAlloc(Device, OL_ALLOC_TYPE_DEVICE, Size, &AllocB));
80 ASSERT_SUCCESS(
81 olMemcpy(Queue, AllocA, Device, Input.data(), Host, Size, nullptr));
82 ASSERT_SUCCESS(
83 olMemcpy(Queue, AllocB, Device, AllocA, Device, Size, nullptr));
84 ASSERT_SUCCESS(
85 olMemcpy(Queue, Output.data(), Host, AllocB, Device, Size, nullptr));
86 ASSERT_SUCCESS(olWaitQueue(Queue));
87 for (uint8_t Val : Output) {
88 ASSERT_EQ(Val, 42);
89 }
90 ASSERT_SUCCESS(olMemFree(AllocA));
91 ASSERT_SUCCESS(olMemFree(AllocB));
92}
93
94TEST_P(olMemcpyTest, SuccessHtoHSync) {
95 constexpr size_t Size = 1024;
96 std::vector<uint8_t> Input(Size, 42);
97 std::vector<uint8_t> Output(Size, 0);
98
99 ASSERT_SUCCESS(olMemcpy(nullptr, Output.data(), Host, Input.data(), Host,
100 Size, nullptr));
101
102 for (uint8_t Val : Output) {
103 ASSERT_EQ(Val, 42);
104 }
105}
106
107TEST_P(olMemcpyTest, SuccessDtoHSync) {
108 constexpr size_t Size = 1024;
109 void *Alloc;
110 std::vector<uint8_t> Input(Size, 42);
111 std::vector<uint8_t> Output(Size, 0);
112
113 ASSERT_SUCCESS(olMemAlloc(Device, OL_ALLOC_TYPE_DEVICE, Size, &Alloc));
114 ASSERT_SUCCESS(
115 olMemcpy(nullptr, Alloc, Device, Input.data(), Host, Size, nullptr));
116 ASSERT_SUCCESS(
117 olMemcpy(nullptr, Output.data(), Host, Alloc, Device, Size, nullptr));
118 for (uint8_t Val : Output) {
119 ASSERT_EQ(Val, 42);
120 }
121 ASSERT_SUCCESS(olMemFree(Alloc));
122}
123
124TEST_P(olMemcpyTest, SuccessSizeZero) {
125 constexpr size_t Size = 1024;
126 std::vector<uint8_t> Input(Size, 42);
127 std::vector<uint8_t> Output(Size, 0);
128
129 // As with std::memcpy, size 0 is allowed. Keep all other arguments valid even
130 // if they aren't used.
131 ASSERT_SUCCESS(
132 olMemcpy(nullptr, Output.data(), Host, Input.data(), Host, 0, nullptr));
133}
134
135TEST_P(olMemcpyGlobalTest, SuccessRoundTrip) {
136 void *SourceMem;
137 ASSERT_SUCCESS(olMemAlloc(Device, OL_ALLOC_TYPE_MANAGED,
138 64 * sizeof(uint32_t), &SourceMem));
139 uint32_t *SourceData = (uint32_t *)SourceMem;
140 for (auto I = 0; I < 64; I++)
141 SourceData[I] = I;
142
143 void *DestMem;
144 ASSERT_SUCCESS(olMemAlloc(Device, OL_ALLOC_TYPE_MANAGED,
145 64 * sizeof(uint32_t), &DestMem));
146
147 ASSERT_SUCCESS(olMemcpy(Queue, Addr, Device, SourceMem, Host,
148 64 * sizeof(uint32_t), nullptr));
149 ASSERT_SUCCESS(olWaitQueue(Queue));
150 ASSERT_SUCCESS(olMemcpy(Queue, DestMem, Host, Addr, Device,
151 64 * sizeof(uint32_t), nullptr));
152 ASSERT_SUCCESS(olWaitQueue(Queue));
153
154 uint32_t *DestData = (uint32_t *)DestMem;
155 for (uint32_t I = 0; I < 64; I++)
156 ASSERT_EQ(DestData[I], I);
157
158 ASSERT_SUCCESS(olMemFree(DestMem));
159 ASSERT_SUCCESS(olMemFree(SourceMem));
160}
161
162TEST_P(olMemcpyGlobalTest, SuccessWrite) {
163 void *SourceMem;
164 ASSERT_SUCCESS(olMemAlloc(Device, OL_ALLOC_TYPE_MANAGED,
165 LaunchArgs.GroupSize.x * sizeof(uint32_t),
166 &SourceMem));
167 uint32_t *SourceData = (uint32_t *)SourceMem;
168 for (auto I = 0; I < 64; I++)
169 SourceData[I] = I;
170
171 void *DestMem;
172 ASSERT_SUCCESS(olMemAlloc(Device, OL_ALLOC_TYPE_MANAGED,
173 LaunchArgs.GroupSize.x * sizeof(uint32_t),
174 &DestMem));
175 struct {
176 void *Mem;
177 } Args{.Mem: DestMem};
178
179 ASSERT_SUCCESS(olMemcpy(Queue, Addr, Device, SourceMem, Host,
180 64 * sizeof(uint32_t), nullptr));
181 ASSERT_SUCCESS(olWaitQueue(Queue));
182 ASSERT_SUCCESS(olLaunchKernel(Queue, Device, ReadKernel, &Args, sizeof(Args),
183 &LaunchArgs, nullptr));
184 ASSERT_SUCCESS(olWaitQueue(Queue));
185
186 uint32_t *DestData = (uint32_t *)DestMem;
187 for (uint32_t I = 0; I < 64; I++)
188 ASSERT_EQ(DestData[I], I);
189
190 ASSERT_SUCCESS(olMemFree(DestMem));
191 ASSERT_SUCCESS(olMemFree(SourceMem));
192}
193
194TEST_P(olMemcpyGlobalTest, SuccessRead) {
195 void *DestMem;
196 ASSERT_SUCCESS(olMemAlloc(Device, OL_ALLOC_TYPE_MANAGED,
197 LaunchArgs.GroupSize.x * sizeof(uint32_t),
198 &DestMem));
199
200 ASSERT_SUCCESS(olLaunchKernel(Queue, Device, WriteKernel, nullptr, 0,
201 &LaunchArgs, nullptr));
202 ASSERT_SUCCESS(olWaitQueue(Queue));
203 ASSERT_SUCCESS(olMemcpy(Queue, DestMem, Host, Addr, Device,
204 64 * sizeof(uint32_t), nullptr));
205 ASSERT_SUCCESS(olWaitQueue(Queue));
206
207 uint32_t *DestData = (uint32_t *)DestMem;
208 for (uint32_t I = 0; I < 64; I++)
209 ASSERT_EQ(DestData[I], I * 2);
210
211 ASSERT_SUCCESS(olMemFree(DestMem));
212}
213

source code of offload/unittests/OffloadAPI/memory/olMemcpy.cpp