1 /*
2 * Copyright (C) 2018-2021 Intel Corporation
3 *
4 * SPDX-License-Identifier: MIT
5 *
6 */
7
8 #include "shared/source/helpers/string.h"
9 #include "shared/source/memory_manager/allocations_list.h"
10 #include "shared/source/memory_manager/graphics_allocation.h"
11 #include "shared/source/memory_manager/unified_memory_manager.h"
12 #include "shared/source/program/program_info_from_patchtokens.h"
13 #include "shared/test/common/helpers/debug_manager_state_restore.h"
14 #include "shared/test/common/mocks/mock_csr.h"
15 #include "shared/test/common/mocks/mock_execution_environment.h"
16 #include "shared/test/common/mocks/mock_memory_manager.h"
17 #include "shared/test/common/test_macros/test.h"
18 #include "shared/test/unit_test/compiler_interface/linker_mock.h"
19 #include "shared/test/unit_test/device_binary_format/patchtokens_tests.h"
20
21 #include "opencl/source/platform/platform.h"
22 #include "opencl/source/program/program.h"
23 #include "opencl/test/unit_test/mocks/mock_buffer.h"
24 #include "opencl/test/unit_test/mocks/mock_cl_device.h"
25 #include "opencl/test/unit_test/mocks/mock_program.h"
26 #include "opencl/test/unit_test/program/program_with_source.h"
27
28 using namespace NEO;
29
30 using namespace iOpenCL;
31 static const char constValue[] = "11223344";
32 static const char globalValue[] = "55667788";
33
34 class ProgramDataTestBase : public testing::Test,
35 public ContextFixture,
36 public PlatformFixture,
37 public ProgramFixture {
38
39 using ContextFixture::SetUp;
40 using PlatformFixture::SetUp;
41
42 public:
ProgramDataTestBase()43 ProgramDataTestBase() {
44 memset(&programBinaryHeader, 0x00, sizeof(SProgramBinaryHeader));
45 pCurPtr = nullptr;
46 pProgramPatchList = nullptr;
47 programPatchListSize = 0;
48 }
49
50 void buildAndDecodeProgramPatchList();
51
SetUp()52 void SetUp() override {
53 PlatformFixture::SetUp();
54 pClDevice = pPlatform->getClDevice(0);
55 rootDeviceIndex = pClDevice->getRootDeviceIndex();
56 cl_device_id device = pClDevice;
57
58 ContextFixture::SetUp(1, &device);
59 ProgramFixture::SetUp();
60
61 CreateProgramWithSource(
62 pContext,
63 "CopyBuffer_simd16.cl");
64 }
65
TearDown()66 void TearDown() override {
67 knownSource.reset();
68 ProgramFixture::TearDown();
69 ContextFixture::TearDown();
70 PlatformFixture::TearDown();
71 }
72
setupConstantAllocation()73 size_t setupConstantAllocation() {
74 size_t constSize = strlen(constValue) + 1;
75
76 EXPECT_EQ(nullptr, pProgram->getConstantSurface(pContext->getDevice(0)->getRootDeviceIndex()));
77
78 SPatchAllocateConstantMemorySurfaceProgramBinaryInfo allocateConstMemorySurface;
79 allocateConstMemorySurface.Token = PATCH_TOKEN_ALLOCATE_CONSTANT_MEMORY_SURFACE_PROGRAM_BINARY_INFO;
80 allocateConstMemorySurface.Size = static_cast<uint32_t>(sizeof(SPatchAllocateConstantMemorySurfaceProgramBinaryInfo));
81
82 allocateConstMemorySurface.ConstantBufferIndex = 0;
83 allocateConstMemorySurface.InlineDataSize = static_cast<uint32_t>(constSize);
84
85 pAllocateConstMemorySurface.reset(new cl_char[allocateConstMemorySurface.Size + constSize]);
86
87 memcpy_s(pAllocateConstMemorySurface.get(),
88 sizeof(SPatchAllocateConstantMemorySurfaceProgramBinaryInfo),
89 &allocateConstMemorySurface,
90 sizeof(SPatchAllocateConstantMemorySurfaceProgramBinaryInfo));
91
92 memcpy_s((cl_char *)pAllocateConstMemorySurface.get() + sizeof(allocateConstMemorySurface), constSize, constValue, constSize);
93
94 pProgramPatchList = (void *)pAllocateConstMemorySurface.get();
95 programPatchListSize = static_cast<uint32_t>(allocateConstMemorySurface.Size + constSize);
96 return constSize;
97 }
98
setupGlobalAllocation()99 size_t setupGlobalAllocation() {
100 size_t globalSize = strlen(globalValue) + 1;
101
102 EXPECT_EQ(nullptr, pProgram->getGlobalSurface(pContext->getDevice(0)->getRootDeviceIndex()));
103
104 SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo allocateGlobalMemorySurface;
105 allocateGlobalMemorySurface.Token = PATCH_TOKEN_ALLOCATE_GLOBAL_MEMORY_SURFACE_PROGRAM_BINARY_INFO;
106 allocateGlobalMemorySurface.Size = static_cast<uint32_t>(sizeof(SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo));
107
108 allocateGlobalMemorySurface.GlobalBufferIndex = 0;
109 allocateGlobalMemorySurface.InlineDataSize = static_cast<uint32_t>(globalSize);
110
111 pAllocateGlobalMemorySurface.reset(new cl_char[allocateGlobalMemorySurface.Size + globalSize]);
112
113 memcpy_s(pAllocateGlobalMemorySurface.get(),
114 sizeof(SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo),
115 &allocateGlobalMemorySurface,
116 sizeof(SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo));
117
118 memcpy_s((cl_char *)pAllocateGlobalMemorySurface.get() + sizeof(allocateGlobalMemorySurface), globalSize, globalValue, globalSize);
119
120 pProgramPatchList = pAllocateGlobalMemorySurface.get();
121 programPatchListSize = static_cast<uint32_t>(allocateGlobalMemorySurface.Size + globalSize);
122 return globalSize;
123 }
124 std::unique_ptr<cl_char[]> pAllocateConstMemorySurface;
125 std::unique_ptr<cl_char[]> pAllocateGlobalMemorySurface;
126 char *pCurPtr;
127 SProgramBinaryHeader programBinaryHeader;
128 void *pProgramPatchList;
129 uint32_t programPatchListSize;
130 cl_int patchlistDecodeErrorCode = 0;
131 bool allowDecodeFailure = false;
132 ClDevice *pClDevice = nullptr;
133 uint32_t rootDeviceIndex;
134 };
135
buildAndDecodeProgramPatchList()136 void ProgramDataTestBase::buildAndDecodeProgramPatchList() {
137 size_t headerSize = sizeof(SProgramBinaryHeader);
138
139 cl_int error = CL_SUCCESS;
140 programBinaryHeader.Magic = 0x494E5443;
141 programBinaryHeader.Version = CURRENT_ICBE_VERSION;
142 programBinaryHeader.Device = defaultHwInfo->platform.eRenderCoreFamily;
143 programBinaryHeader.GPUPointerSizeInBytes = 8;
144 programBinaryHeader.NumberOfKernels = 0;
145 programBinaryHeader.PatchListSize = programPatchListSize;
146
147 char *pProgramData = new char[headerSize + programBinaryHeader.PatchListSize];
148 ASSERT_NE(nullptr, pProgramData);
149
150 pCurPtr = pProgramData;
151
152 // program header
153 memset(pCurPtr, 0, sizeof(SProgramBinaryHeader));
154 *(SProgramBinaryHeader *)pCurPtr = programBinaryHeader;
155
156 pCurPtr += sizeof(SProgramBinaryHeader);
157
158 // patch list
159 memcpy_s(pCurPtr, programPatchListSize, pProgramPatchList, programPatchListSize);
160 pCurPtr += programPatchListSize;
161
162 auto rootDeviceIndex = pPlatform->getClDevice(0)->getRootDeviceIndex();
163 //as we use mock compiler in unit test, replace the genBinary here.
164 pProgram->buildInfos[rootDeviceIndex].unpackedDeviceBinary = makeCopy(pProgramData, headerSize + programBinaryHeader.PatchListSize);
165 pProgram->buildInfos[rootDeviceIndex].unpackedDeviceBinarySize = headerSize + programBinaryHeader.PatchListSize;
166
167 error = pProgram->processGenBinary(*pClDevice);
168 patchlistDecodeErrorCode = error;
169 if (allowDecodeFailure == false) {
170 EXPECT_EQ(CL_SUCCESS, error);
171 }
172 delete[] pProgramData;
173 }
174
175 using ProgramDataTest = ProgramDataTestBase;
176
TEST_F(ProgramDataTest,GivenEmptyProgramBinaryHeaderWhenBuildingAndDecodingThenSucessIsReturned)177 TEST_F(ProgramDataTest, GivenEmptyProgramBinaryHeaderWhenBuildingAndDecodingThenSucessIsReturned) {
178 buildAndDecodeProgramPatchList();
179 }
180
TEST_F(ProgramDataTest,WhenAllocatingConstantMemorySurfaceThenUnderlyingBufferIsSetCorrectly)181 TEST_F(ProgramDataTest, WhenAllocatingConstantMemorySurfaceThenUnderlyingBufferIsSetCorrectly) {
182
183 auto constSize = setupConstantAllocation();
184
185 buildAndDecodeProgramPatchList();
186
187 EXPECT_NE(nullptr, pProgram->getConstantSurface(pContext->getDevice(0)->getRootDeviceIndex()));
188 EXPECT_EQ(0, memcmp(constValue, pProgram->getConstantSurface(pContext->getDevice(0)->getRootDeviceIndex())->getUnderlyingBuffer(), constSize));
189 }
190
TEST_F(ProgramDataTest,givenProgramWhenAllocatingConstantMemorySurfaceThenProperDeviceBitfieldIsPassed)191 TEST_F(ProgramDataTest, givenProgramWhenAllocatingConstantMemorySurfaceThenProperDeviceBitfieldIsPassed) {
192 auto executionEnvironment = pClDevice->getExecutionEnvironment();
193 auto memoryManager = new MockMemoryManager(*executionEnvironment);
194
195 std::unique_ptr<MemoryManager> memoryManagerBackup(memoryManager);
196 std::swap(memoryManagerBackup, executionEnvironment->memoryManager);
197 EXPECT_NE(pClDevice->getDeviceBitfield(), memoryManager->recentlyPassedDeviceBitfield);
198 setupConstantAllocation();
199 buildAndDecodeProgramPatchList();
200 EXPECT_NE(nullptr, pProgram->getConstantSurface(pContext->getDevice(0)->getRootDeviceIndex()));
201 EXPECT_EQ(pClDevice->getDeviceBitfield(), memoryManager->recentlyPassedDeviceBitfield);
202 std::swap(memoryManagerBackup, executionEnvironment->memoryManager);
203 }
204
TEST_F(ProgramDataTest,whenGlobalConstantsAreExportedThenAllocateSurfacesAsSvm)205 TEST_F(ProgramDataTest, whenGlobalConstantsAreExportedThenAllocateSurfacesAsSvm) {
206 if (this->pContext->getSVMAllocsManager() == nullptr) {
207 return;
208 }
209
210 char constantData[128] = {};
211 ProgramInfo programInfo;
212 programInfo.globalConstants.initData = constantData;
213 programInfo.globalConstants.size = sizeof(constantData);
214 std::unique_ptr<WhiteBox<NEO::LinkerInput>> mockLinkerInput = std::make_unique<WhiteBox<NEO::LinkerInput>>();
215 mockLinkerInput->traits.exportsGlobalConstants = true;
216 programInfo.linkerInput = std::move(mockLinkerInput);
217 this->pProgram->processProgramInfo(programInfo, *pClDevice);
218
219 ASSERT_NE(nullptr, pProgram->getConstantSurface(pContext->getDevice(0)->getRootDeviceIndex()));
220 EXPECT_NE(nullptr, this->pContext->getSVMAllocsManager()->getSVMAlloc(reinterpret_cast<const void *>(pProgram->getConstantSurface(pContext->getDevice(0)->getRootDeviceIndex())->getGpuAddress())));
221 }
222
TEST_F(ProgramDataTest,whenGlobalConstantsAreNotExportedThenAllocateSurfacesAsNonSvm)223 TEST_F(ProgramDataTest, whenGlobalConstantsAreNotExportedThenAllocateSurfacesAsNonSvm) {
224 if (this->pContext->getSVMAllocsManager() == nullptr) {
225 return;
226 }
227
228 char constantData[128] = {};
229 ProgramInfo programInfo;
230 programInfo.globalConstants.initData = constantData;
231 programInfo.globalConstants.size = sizeof(constantData);
232 std::unique_ptr<WhiteBox<NEO::LinkerInput>> mockLinkerInput = std::make_unique<WhiteBox<NEO::LinkerInput>>();
233 mockLinkerInput->traits.exportsGlobalConstants = false;
234 programInfo.linkerInput = std::move(mockLinkerInput);
235 this->pProgram->processProgramInfo(programInfo, *pClDevice);
236
237 ASSERT_NE(nullptr, pProgram->getConstantSurface(pContext->getDevice(0)->getRootDeviceIndex()));
238 EXPECT_EQ(nullptr, this->pContext->getSVMAllocsManager()->getSVMAlloc(reinterpret_cast<const void *>(
239 pProgram->getConstantSurface(pContext->getDevice(0)->getRootDeviceIndex())->getGpuAddress())));
240 }
241
TEST_F(ProgramDataTest,whenGlobalConstantsAreExportedButContextUnavailableThenAllocateSurfacesAsNonSvm)242 TEST_F(ProgramDataTest, whenGlobalConstantsAreExportedButContextUnavailableThenAllocateSurfacesAsNonSvm) {
243 if (this->pContext->getSVMAllocsManager() == nullptr) {
244 return;
245 }
246
247 char constantData[128] = {};
248 ProgramInfo programInfo;
249 programInfo.globalConstants.initData = constantData;
250 programInfo.globalConstants.size = sizeof(constantData);
251 std::unique_ptr<WhiteBox<NEO::LinkerInput>> mockLinkerInput = std::make_unique<WhiteBox<NEO::LinkerInput>>();
252 mockLinkerInput->traits.exportsGlobalConstants = true;
253 programInfo.linkerInput = std::move(mockLinkerInput);
254
255 pProgram->context = nullptr;
256
257 this->pProgram->processProgramInfo(programInfo, *pClDevice);
258
259 pProgram->context = pContext;
260
261 ASSERT_NE(nullptr, pProgram->getConstantSurface(pContext->getDevice(0)->getRootDeviceIndex()));
262 EXPECT_EQ(nullptr, this->pContext->getSVMAllocsManager()->getSVMAlloc(reinterpret_cast<const void *>(
263 pProgram->getConstantSurface(pContext->getDevice(0)->getRootDeviceIndex())->getGpuAddress())));
264 }
265
TEST_F(ProgramDataTest,whenGlobalVariablesAreExportedThenAllocateSurfacesAsSvm)266 TEST_F(ProgramDataTest, whenGlobalVariablesAreExportedThenAllocateSurfacesAsSvm) {
267 if (this->pContext->getSVMAllocsManager() == nullptr) {
268 return;
269 }
270 char globalData[128] = {};
271 ProgramInfo programInfo;
272 programInfo.globalVariables.initData = globalData;
273 programInfo.globalVariables.size = sizeof(globalData);
274 std::unique_ptr<WhiteBox<NEO::LinkerInput>> mockLinkerInput = std::make_unique<WhiteBox<NEO::LinkerInput>>();
275 mockLinkerInput->traits.exportsGlobalVariables = true;
276 programInfo.linkerInput = std::move(mockLinkerInput);
277 this->pProgram->processProgramInfo(programInfo, *pClDevice);
278
279 ASSERT_NE(nullptr, pProgram->getGlobalSurface(pContext->getDevice(0)->getRootDeviceIndex()));
280 EXPECT_NE(nullptr, this->pContext->getSVMAllocsManager()->getSVMAlloc(reinterpret_cast<const void *>(pProgram->getGlobalSurface(pContext->getDevice(0)->getRootDeviceIndex())->getGpuAddress())));
281 }
282
TEST_F(ProgramDataTest,whenGlobalVariablesAreExportedButContextUnavailableThenAllocateSurfacesAsNonSvm)283 TEST_F(ProgramDataTest, whenGlobalVariablesAreExportedButContextUnavailableThenAllocateSurfacesAsNonSvm) {
284 if (this->pContext->getSVMAllocsManager() == nullptr) {
285 return;
286 }
287
288 char globalData[128] = {};
289 ProgramInfo programInfo;
290 programInfo.globalVariables.initData = globalData;
291 programInfo.globalVariables.size = sizeof(globalData);
292 std::unique_ptr<WhiteBox<NEO::LinkerInput>> mockLinkerInput = std::make_unique<WhiteBox<NEO::LinkerInput>>();
293 mockLinkerInput->traits.exportsGlobalVariables = true;
294 programInfo.linkerInput = std::move(mockLinkerInput);
295
296 pProgram->context = nullptr;
297
298 this->pProgram->processProgramInfo(programInfo, *pClDevice);
299
300 pProgram->context = pContext;
301
302 ASSERT_NE(nullptr, pProgram->getGlobalSurface(pContext->getDevice(0)->getRootDeviceIndex()));
303 EXPECT_EQ(nullptr, this->pContext->getSVMAllocsManager()->getSVMAlloc(reinterpret_cast<const void *>(pProgram->getGlobalSurface(pContext->getDevice(0)->getRootDeviceIndex())->getGpuAddress())));
304 }
305
TEST_F(ProgramDataTest,whenGlobalVariablesAreNotExportedThenAllocateSurfacesAsNonSvm)306 TEST_F(ProgramDataTest, whenGlobalVariablesAreNotExportedThenAllocateSurfacesAsNonSvm) {
307 if (this->pContext->getSVMAllocsManager() == nullptr) {
308 return;
309 }
310
311 char globalData[128] = {};
312 ProgramInfo programInfo;
313 programInfo.globalVariables.initData = globalData;
314 programInfo.globalVariables.size = sizeof(globalData);
315 std::unique_ptr<WhiteBox<NEO::LinkerInput>> mockLinkerInput = std::make_unique<WhiteBox<NEO::LinkerInput>>();
316 mockLinkerInput->traits.exportsGlobalVariables = false;
317 programInfo.linkerInput = std::move(mockLinkerInput);
318 this->pProgram->processProgramInfo(programInfo, *pClDevice);
319
320 ASSERT_NE(nullptr, pProgram->getGlobalSurface(pContext->getDevice(0)->getRootDeviceIndex()));
321 EXPECT_EQ(nullptr, this->pContext->getSVMAllocsManager()->getSVMAlloc(reinterpret_cast<const void *>(pProgram->getGlobalSurface(pContext->getDevice(0)->getRootDeviceIndex())->getGpuAddress())));
322 }
323
TEST_F(ProgramDataTest,givenConstantAllocationThatIsInUseByGpuWhenProgramIsBeingDestroyedThenItIsAddedToTemporaryAllocationList)324 TEST_F(ProgramDataTest, givenConstantAllocationThatIsInUseByGpuWhenProgramIsBeingDestroyedThenItIsAddedToTemporaryAllocationList) {
325
326 setupConstantAllocation();
327
328 buildAndDecodeProgramPatchList();
329
330 auto &csr = *pPlatform->getClDevice(0)->getDefaultEngine().commandStreamReceiver;
331 auto tagAddress = csr.getTagAddress();
332 auto constantSurface = pProgram->getConstantSurface(pContext->getDevice(0)->getRootDeviceIndex());
333 constantSurface->updateTaskCount(*tagAddress + 1, csr.getOsContext().getContextId());
334
335 EXPECT_TRUE(csr.getTemporaryAllocations().peekIsEmpty());
336 delete pProgram;
337 pProgram = nullptr;
338 EXPECT_FALSE(csr.getTemporaryAllocations().peekIsEmpty());
339 EXPECT_EQ(constantSurface, csr.getTemporaryAllocations().peekHead());
340 }
341
TEST_F(ProgramDataTest,givenGlobalAllocationThatIsInUseByGpuWhenProgramIsBeingDestroyedThenItIsAddedToTemporaryAllocationList)342 TEST_F(ProgramDataTest, givenGlobalAllocationThatIsInUseByGpuWhenProgramIsBeingDestroyedThenItIsAddedToTemporaryAllocationList) {
343 setupGlobalAllocation();
344
345 buildAndDecodeProgramPatchList();
346
347 auto &csr = *pPlatform->getClDevice(0)->getDefaultEngine().commandStreamReceiver;
348 auto tagAddress = csr.getTagAddress();
349 auto globalSurface = pProgram->getGlobalSurface(pContext->getDevice(0)->getRootDeviceIndex());
350 globalSurface->updateTaskCount(*tagAddress + 1, csr.getOsContext().getContextId());
351
352 EXPECT_TRUE(csr.getTemporaryAllocations().peekIsEmpty());
353 delete pProgram;
354 pProgram = nullptr;
355 EXPECT_FALSE(csr.getTemporaryAllocations().peekIsEmpty());
356 EXPECT_EQ(globalSurface, csr.getTemporaryAllocations().peekHead());
357 }
358
TEST_F(ProgramDataTest,GivenDeviceForcing32BitMessagesWhenConstAllocationIsPresentInProgramBinariesThen32BitStorageIsAllocated)359 TEST_F(ProgramDataTest, GivenDeviceForcing32BitMessagesWhenConstAllocationIsPresentInProgramBinariesThen32BitStorageIsAllocated) {
360 auto constSize = setupConstantAllocation();
361 this->pContext->getDevice(0)->getMemoryManager()->setForce32BitAllocations(true);
362
363 buildAndDecodeProgramPatchList();
364
365 EXPECT_NE(nullptr, pProgram->getConstantSurface(pContext->getDevice(0)->getRootDeviceIndex()));
366 EXPECT_EQ(0, memcmp(constValue, pProgram->getConstantSurface(pContext->getDevice(0)->getRootDeviceIndex())->getUnderlyingBuffer(), constSize));
367
368 if constexpr (is64bit) {
369 EXPECT_TRUE(pProgram->getConstantSurface(pContext->getDevice(0)->getRootDeviceIndex())->is32BitAllocation());
370 }
371 }
372
TEST_F(ProgramDataTest,WhenAllocatingGlobalMemorySurfaceThenUnderlyingBufferIsSetCorrectly)373 TEST_F(ProgramDataTest, WhenAllocatingGlobalMemorySurfaceThenUnderlyingBufferIsSetCorrectly) {
374 auto globalSize = setupGlobalAllocation();
375 buildAndDecodeProgramPatchList();
376 EXPECT_NE(nullptr, pProgram->getGlobalSurface(pContext->getDevice(0)->getRootDeviceIndex()));
377 EXPECT_EQ(0, memcmp(globalValue, pProgram->getGlobalSurface(pContext->getDevice(0)->getRootDeviceIndex())->getUnderlyingBuffer(), globalSize));
378 }
TEST_F(ProgramDataTest,givenProgramWhenAllocatingGlobalMemorySurfaceThenProperDeviceBitfieldIsPassed)379 TEST_F(ProgramDataTest, givenProgramWhenAllocatingGlobalMemorySurfaceThenProperDeviceBitfieldIsPassed) {
380 auto executionEnvironment = pClDevice->getExecutionEnvironment();
381 auto memoryManager = new MockMemoryManager(*executionEnvironment);
382
383 std::unique_ptr<MemoryManager> memoryManagerBackup(memoryManager);
384 std::swap(memoryManagerBackup, executionEnvironment->memoryManager);
385 EXPECT_NE(pClDevice->getDeviceBitfield(), memoryManager->recentlyPassedDeviceBitfield);
386
387 setupGlobalAllocation();
388 buildAndDecodeProgramPatchList();
389 EXPECT_NE(nullptr, pProgram->getGlobalSurface(pContext->getDevice(0)->getRootDeviceIndex()));
390 EXPECT_EQ(pClDevice->getDeviceBitfield(), memoryManager->recentlyPassedDeviceBitfield);
391 std::swap(memoryManagerBackup, executionEnvironment->memoryManager);
392 }
393
TEST_F(ProgramDataTest,Given32BitDeviceWhenGlobalMemorySurfaceIsPresentThenItHas32BitStorage)394 TEST_F(ProgramDataTest, Given32BitDeviceWhenGlobalMemorySurfaceIsPresentThenItHas32BitStorage) {
395 char globalValue[] = "55667788";
396 size_t globalSize = strlen(globalValue) + 1;
397 this->pContext->getDevice(0)->getMemoryManager()->setForce32BitAllocations(true);
398 EXPECT_EQ(nullptr, pProgram->getGlobalSurface(pContext->getDevice(0)->getRootDeviceIndex()));
399
400 SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo allocateGlobalMemorySurface;
401 allocateGlobalMemorySurface.Token = PATCH_TOKEN_ALLOCATE_GLOBAL_MEMORY_SURFACE_PROGRAM_BINARY_INFO;
402 allocateGlobalMemorySurface.Size = static_cast<uint32_t>(sizeof(SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo));
403
404 allocateGlobalMemorySurface.GlobalBufferIndex = 0;
405 allocateGlobalMemorySurface.InlineDataSize = static_cast<uint32_t>(globalSize);
406
407 cl_char *pAllocateGlobalMemorySurface = new cl_char[allocateGlobalMemorySurface.Size + globalSize];
408
409 memcpy_s(pAllocateGlobalMemorySurface,
410 sizeof(SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo),
411 &allocateGlobalMemorySurface,
412 sizeof(SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo));
413
414 memcpy_s((cl_char *)pAllocateGlobalMemorySurface + sizeof(allocateGlobalMemorySurface), globalSize, globalValue, globalSize);
415
416 pProgramPatchList = (void *)pAllocateGlobalMemorySurface;
417 programPatchListSize = static_cast<uint32_t>(allocateGlobalMemorySurface.Size + globalSize);
418
419 buildAndDecodeProgramPatchList();
420
421 EXPECT_NE(nullptr, pProgram->getGlobalSurface(pContext->getDevice(0)->getRootDeviceIndex()));
422 EXPECT_EQ(0, memcmp(globalValue, pProgram->getGlobalSurface(pContext->getDevice(0)->getRootDeviceIndex())->getUnderlyingBuffer(), globalSize));
423 if constexpr (is64bit) {
424 EXPECT_TRUE(pProgram->getGlobalSurface(pContext->getDevice(0)->getRootDeviceIndex())->is32BitAllocation());
425 }
426
427 delete[] pAllocateGlobalMemorySurface;
428 }
429
TEST(ProgramScopeMetadataTest,WhenPatchingGlobalSurfaceThenPickProperSourceBuffer)430 TEST(ProgramScopeMetadataTest, WhenPatchingGlobalSurfaceThenPickProperSourceBuffer) {
431 MockExecutionEnvironment execEnv;
432 execEnv.incRefInternal();
433 MockClDevice device{new MockDevice(&execEnv, 0)};
434 execEnv.memoryManager = std::make_unique<MockMemoryManager>();
435 PatchTokensTestData::ValidProgramWithMixedGlobalVarAndConstSurfacesAndPointers decodedProgram;
436 decodedProgram.globalPointerMutable->GlobalPointerOffset = 0U;
437 decodedProgram.constantPointerMutable->ConstantPointerOffset = 0U;
438 memset(decodedProgram.globalSurfMutable + 1, 0U, sizeof(uintptr_t));
439 memset(decodedProgram.constSurfMutable + 1, 0U, sizeof(uintptr_t));
440 ProgramInfo programInfo;
441 MockProgram program(toClDeviceVector(device));
442 NEO::populateProgramInfo(programInfo, decodedProgram);
443 program.processProgramInfo(programInfo, device);
444 auto &buildInfo = program.buildInfos[device.getRootDeviceIndex()];
445 ASSERT_NE(nullptr, buildInfo.globalSurface);
446 ASSERT_NE(nullptr, buildInfo.constantSurface);
447 ASSERT_NE(nullptr, buildInfo.globalSurface->getUnderlyingBuffer());
448 ASSERT_NE(nullptr, buildInfo.constantSurface->getUnderlyingBuffer());
449 EXPECT_EQ(static_cast<uintptr_t>(buildInfo.globalSurface->getGpuAddressToPatch()), *reinterpret_cast<uintptr_t *>(buildInfo.constantSurface->getUnderlyingBuffer()));
450 EXPECT_EQ(static_cast<uintptr_t>(buildInfo.constantSurface->getGpuAddressToPatch()), *reinterpret_cast<uintptr_t *>(buildInfo.globalSurface->getUnderlyingBuffer()));
451 }
452
TEST_F(ProgramDataTest,GivenProgramWith32bitPointerOptWhenProgramScopeConstantBufferPatchTokensAreReadThenConstantPointerOffsetIsPatchedWith32bitPointer)453 TEST_F(ProgramDataTest, GivenProgramWith32bitPointerOptWhenProgramScopeConstantBufferPatchTokensAreReadThenConstantPointerOffsetIsPatchedWith32bitPointer) {
454 CreateProgramWithSource(pContext, "CopyBuffer_simd16.cl");
455 ASSERT_NE(nullptr, pProgram);
456
457 MockProgram *prog = pProgram;
458
459 // simulate case when constant surface was not allocated
460 EXPECT_EQ(nullptr, prog->getConstantSurface(pContext->getDevice(0)->getRootDeviceIndex()));
461 ProgramInfo programInfo;
462 programInfo.prepareLinkerInputStorage();
463
464 NEO::LinkerInput::RelocationInfo relocInfo;
465 relocInfo.relocationSegment = NEO::SegmentType::GlobalConstants;
466 relocInfo.offset = 0U;
467 relocInfo.type = NEO::LinkerInput::RelocationInfo::Type::Address;
468 relocInfo.symbolName = "GlobalConstantPointer";
469
470 NEO::SymbolInfo symbol = {};
471 symbol.offset = 0U;
472 symbol.size = 8U;
473 symbol.segment = NEO::SegmentType::GlobalConstants;
474
475 programInfo.linkerInput->addSymbol("GlobalConstantPointer", symbol);
476 programInfo.linkerInput->addDataRelocationInfo(relocInfo);
477 programInfo.linkerInput->setPointerSize(LinkerInput::Traits::PointerSize::Ptr32bit);
478
479 MockBuffer constantSurface;
480 ASSERT_LT(8U, constantSurface.getSize());
481 prog->setConstantSurface(&constantSurface.mockGfxAllocation);
482 constantSurface.mockGfxAllocation.set32BitAllocation(true);
483 uint32_t *constantSurfaceStorage = reinterpret_cast<uint32_t *>(constantSurface.getCpuAddress());
484 uint32_t sentinel = 0x17192329U;
485 constantSurfaceStorage[0] = 0U;
486 constantSurfaceStorage[1] = sentinel;
487
488 programInfo.globalConstants.initData = constantSurface.mockGfxAllocation.getUnderlyingBuffer();
489
490 pProgram->setLinkerInput(pClDevice->getRootDeviceIndex(), std::move(programInfo.linkerInput));
491 pProgram->linkBinary(&pClDevice->getDevice(), programInfo.globalConstants.initData, programInfo.globalVariables.initData, {});
492 uint32_t expectedAddr = static_cast<uint32_t>(constantSurface.getGraphicsAllocation(pClDevice->getRootDeviceIndex())->getGpuAddressToPatch());
493 EXPECT_EQ(expectedAddr, constantSurfaceStorage[0]);
494 EXPECT_EQ(sentinel, constantSurfaceStorage[1]);
495 constantSurface.mockGfxAllocation.set32BitAllocation(false);
496 prog->setConstantSurface(nullptr);
497 }
498
TEST_F(ProgramDataTest,GivenProgramWith32bitPointerOptWhenProgramScopeGlobalPointerPatchTokensAreReadThenGlobalPointerOffsetIsPatchedWith32bitPointer)499 TEST_F(ProgramDataTest, GivenProgramWith32bitPointerOptWhenProgramScopeGlobalPointerPatchTokensAreReadThenGlobalPointerOffsetIsPatchedWith32bitPointer) {
500 CreateProgramWithSource(pContext, "CopyBuffer_simd16.cl");
501 ASSERT_NE(nullptr, pProgram);
502
503 MockProgram *prog = pProgram;
504
505 // simulate case when constant surface was not allocated
506 EXPECT_EQ(nullptr, prog->getConstantSurface(pContext->getDevice(0)->getRootDeviceIndex()));
507
508 ProgramInfo programInfo;
509 programInfo.prepareLinkerInputStorage();
510 NEO::LinkerInput::RelocationInfo relocInfo;
511 relocInfo.offset = 0U;
512 relocInfo.type = NEO::LinkerInput::RelocationInfo::Type::Address;
513 relocInfo.relocationSegment = NEO::SegmentType::GlobalVariables;
514 relocInfo.symbolName = "GlobalVariablePointer";
515
516 NEO::SymbolInfo symbol = {};
517 symbol.offset = 0U;
518 symbol.size = 8U;
519 symbol.segment = NEO::SegmentType::GlobalVariables;
520
521 programInfo.linkerInput->addSymbol("GlobalVariablePointer", symbol);
522 programInfo.linkerInput->addDataRelocationInfo(relocInfo);
523 programInfo.linkerInput->setPointerSize(LinkerInput::Traits::PointerSize::Ptr32bit);
524
525 MockBuffer globalSurface;
526 ASSERT_LT(8U, globalSurface.getSize());
527 prog->setGlobalSurface(&globalSurface.mockGfxAllocation);
528 globalSurface.mockGfxAllocation.set32BitAllocation(true);
529 uint32_t *globalSurfaceStorage = reinterpret_cast<uint32_t *>(globalSurface.getCpuAddress());
530 uint32_t sentinel = 0x17192329U;
531 globalSurfaceStorage[0] = 0U;
532 globalSurfaceStorage[1] = sentinel;
533
534 programInfo.globalVariables.initData = globalSurface.mockGfxAllocation.getUnderlyingBuffer();
535
536 pProgram->setLinkerInput(pClDevice->getRootDeviceIndex(), std::move(programInfo.linkerInput));
537 pProgram->linkBinary(&pClDevice->getDevice(), programInfo.globalConstants.initData, programInfo.globalVariables.initData, {});
538 uint32_t expectedAddr = static_cast<uint32_t>(globalSurface.getGraphicsAllocation(pClDevice->getRootDeviceIndex())->getGpuAddressToPatch());
539 EXPECT_EQ(expectedAddr, globalSurfaceStorage[0]);
540 EXPECT_EQ(sentinel, globalSurfaceStorage[1]);
541 globalSurface.mockGfxAllocation.set32BitAllocation(false);
542 prog->setGlobalSurface(nullptr);
543 }
544
TEST_F(ProgramDataTest,givenSymbolTablePatchTokenThenLinkerInputIsCreated)545 TEST_F(ProgramDataTest, givenSymbolTablePatchTokenThenLinkerInputIsCreated) {
546 SPatchFunctionTableInfo token;
547 token.Token = PATCH_TOKEN_PROGRAM_SYMBOL_TABLE;
548 token.Size = static_cast<uint32_t>(sizeof(SPatchFunctionTableInfo));
549 token.NumEntries = 0;
550
551 pProgramPatchList = &token;
552 programPatchListSize = token.Size;
553
554 buildAndDecodeProgramPatchList();
555
556 EXPECT_NE(nullptr, pProgram->getLinkerInput(pContext->getDevice(0)->getRootDeviceIndex()));
557 }
558
TEST(ProgramLinkBinaryTest,whenLinkerInputEmptyThenLinkSuccessful)559 TEST(ProgramLinkBinaryTest, whenLinkerInputEmptyThenLinkSuccessful) {
560 auto linkerInput = std::make_unique<WhiteBox<LinkerInput>>();
561 auto device = std::make_unique<MockClDevice>(MockDevice::createWithNewExecutionEnvironment<MockDevice>(defaultHwInfo.get()));
562 MockProgram program{nullptr, false, toClDeviceVector(*device)};
563 program.setLinkerInput(device->getRootDeviceIndex(), std::move(linkerInput));
564 auto ret = program.linkBinary(&device->getDevice(), nullptr, nullptr, {});
565 EXPECT_EQ(CL_SUCCESS, ret);
566 }
567
TEST(ProgramLinkBinaryTest,whenLinkerUnresolvedExternalThenLinkFailedAndBuildLogAvailable)568 TEST(ProgramLinkBinaryTest, whenLinkerUnresolvedExternalThenLinkFailedAndBuildLogAvailable) {
569 auto linkerInput = std::make_unique<WhiteBox<LinkerInput>>();
570 NEO::LinkerInput::RelocationInfo relocation = {};
571 relocation.symbolName = "A";
572 relocation.offset = 0;
573 linkerInput->relocations.push_back(NEO::LinkerInput::Relocations{relocation});
574 linkerInput->traits.requiresPatchingOfInstructionSegments = true;
575 auto device = std::make_unique<MockClDevice>(MockDevice::createWithNewExecutionEnvironment<MockDevice>(defaultHwInfo.get()));
576 auto rootDeviceIndex = device->getRootDeviceIndex();
577 MockProgram program{nullptr, false, toClDeviceVector(*device)};
578 KernelInfo kernelInfo = {};
579 kernelInfo.kernelDescriptor.kernelMetadata.kernelName = "onlyKernel";
580 std::vector<char> kernelHeap;
581 kernelHeap.resize(32, 7);
582 kernelInfo.heapInfo.pKernelHeap = kernelHeap.data();
583 kernelInfo.heapInfo.KernelHeapSize = static_cast<uint32_t>(kernelHeap.size());
584 program.getKernelInfoArray(rootDeviceIndex).push_back(&kernelInfo);
585 program.setLinkerInput(rootDeviceIndex, std::move(linkerInput));
586
587 std::string buildLog = program.getBuildLog(device->getRootDeviceIndex());
588 EXPECT_TRUE(buildLog.empty());
589 auto ret = program.linkBinary(&device->getDevice(), nullptr, nullptr, {});
590 EXPECT_NE(CL_SUCCESS, ret);
591 program.getKernelInfoArray(rootDeviceIndex).clear();
592 buildLog = program.getBuildLog(rootDeviceIndex);
593 EXPECT_FALSE(buildLog.empty());
594 Linker::UnresolvedExternals expectedUnresolvedExternals;
595 expectedUnresolvedExternals.push_back(Linker::UnresolvedExternal{relocation, 0, false});
596 auto expectedError = constructLinkerErrorMessage(expectedUnresolvedExternals, std::vector<std::string>{"kernel : " + kernelInfo.kernelDescriptor.kernelMetadata.kernelName});
597 EXPECT_THAT(buildLog.c_str(), ::testing::HasSubstr(expectedError));
598 }
599
TEST_F(ProgramDataTest,whenLinkerInputValidThenIsaIsProperlyPatched)600 TEST_F(ProgramDataTest, whenLinkerInputValidThenIsaIsProperlyPatched) {
601 auto linkerInput = std::make_unique<WhiteBox<LinkerInput>>();
602 linkerInput->symbols["A"] = NEO::SymbolInfo{4U, 4U, NEO::SegmentType::GlobalVariables};
603 linkerInput->symbols["B"] = NEO::SymbolInfo{8U, 4U, NEO::SegmentType::GlobalConstants};
604 linkerInput->symbols["C"] = NEO::SymbolInfo{16U, 4U, NEO::SegmentType::Instructions};
605
606 auto relocationType = NEO::LinkerInput::RelocationInfo::Type::Address;
607 linkerInput->relocations.push_back({NEO::LinkerInput::RelocationInfo{"A", 8U, relocationType},
608 NEO::LinkerInput::RelocationInfo{"B", 16U, relocationType},
609 NEO::LinkerInput::RelocationInfo{"C", 24U, relocationType}});
610 linkerInput->traits.requiresPatchingOfInstructionSegments = true;
611 linkerInput->exportedFunctionsSegmentId = 0;
612 auto device = std::make_unique<MockClDevice>(MockDevice::createWithNewExecutionEnvironment<MockDevice>(defaultHwInfo.get()));
613 MockProgram program{nullptr, false, toClDeviceVector(*device)};
614 auto &buildInfo = program.buildInfos[device->getRootDeviceIndex()];
615 KernelInfo kernelInfo = {};
616 kernelInfo.kernelDescriptor.kernelMetadata.kernelName = "onlyKernel";
617 std::vector<char> kernelHeap;
618 kernelHeap.resize(32, 7);
619 kernelInfo.heapInfo.pKernelHeap = kernelHeap.data();
620 kernelInfo.heapInfo.KernelHeapSize = static_cast<uint32_t>(kernelHeap.size());
621 MockGraphicsAllocation kernelIsa(kernelHeap.data(), kernelHeap.size());
622 kernelInfo.kernelAllocation = &kernelIsa;
623 program.getKernelInfoArray(rootDeviceIndex).push_back(&kernelInfo);
624 program.setLinkerInput(device->getRootDeviceIndex(), std::move(linkerInput));
625
626 buildInfo.exportedFunctionsSurface = kernelInfo.kernelAllocation;
627 std::vector<char> globalVariablesBuffer;
628 globalVariablesBuffer.resize(32, 7);
629 std::vector<char> globalConstantsBuffer;
630 globalConstantsBuffer.resize(32, 7);
631 std::vector<char> globalVariablesInitData{32, 0};
632 std::vector<char> globalConstantsInitData{32, 0};
633 buildInfo.globalSurface = new MockGraphicsAllocation(globalVariablesBuffer.data(), globalVariablesBuffer.size());
634 buildInfo.constantSurface = new MockGraphicsAllocation(globalConstantsBuffer.data(), globalConstantsBuffer.size());
635
636 auto ret = program.linkBinary(&pClDevice->getDevice(), globalConstantsInitData.data(), globalVariablesInitData.data(), {});
637 EXPECT_EQ(CL_SUCCESS, ret);
638
639 linkerInput.reset(static_cast<WhiteBox<LinkerInput> *>(buildInfo.linkerInput.release()));
640
641 for (size_t i = 0; i < linkerInput->relocations.size(); ++i) {
642 auto expectedPatch = buildInfo.globalSurface->getGpuAddress() + linkerInput->symbols[linkerInput->relocations[0][0].symbolName].offset;
643 auto relocationAddress = kernelHeap.data() + linkerInput->relocations[0][0].offset;
644
645 EXPECT_EQ(static_cast<uintptr_t>(expectedPatch), *reinterpret_cast<uintptr_t *>(relocationAddress)) << i;
646 }
647
648 program.getKernelInfoArray(rootDeviceIndex).clear();
649 delete buildInfo.globalSurface;
650 buildInfo.globalSurface = nullptr;
651 delete buildInfo.constantSurface;
652 buildInfo.constantSurface = nullptr;
653 }
654
TEST_F(ProgramDataTest,whenRelocationsAreNotNeededThenIsaIsPreserved)655 TEST_F(ProgramDataTest, whenRelocationsAreNotNeededThenIsaIsPreserved) {
656 auto linkerInput = std::make_unique<WhiteBox<LinkerInput>>();
657 linkerInput->symbols["A"] = NEO::SymbolInfo{4U, 4U, NEO::SegmentType::GlobalVariables};
658 linkerInput->symbols["B"] = NEO::SymbolInfo{8U, 4U, NEO::SegmentType::GlobalConstants};
659
660 auto device = std::make_unique<MockClDevice>(MockDevice::createWithNewExecutionEnvironment<MockDevice>(defaultHwInfo.get()));
661 MockProgram program{nullptr, false, toClDeviceVector(*device)};
662 auto &buildInfo = program.buildInfos[device->getRootDeviceIndex()];
663 KernelInfo kernelInfo = {};
664 kernelInfo.kernelDescriptor.kernelMetadata.kernelName = "onlyKernel";
665 std::vector<char> kernelHeapData;
666 kernelHeapData.resize(32, 7);
667 std::vector<char> kernelHeap(kernelHeapData.begin(), kernelHeapData.end());
668 kernelInfo.heapInfo.pKernelHeap = kernelHeap.data();
669 kernelInfo.heapInfo.KernelHeapSize = static_cast<uint32_t>(kernelHeap.size());
670 MockGraphicsAllocation kernelIsa(kernelHeap.data(), kernelHeap.size());
671 kernelInfo.kernelAllocation = &kernelIsa;
672 program.getKernelInfoArray(rootDeviceIndex).push_back(&kernelInfo);
673 program.setLinkerInput(rootDeviceIndex, std::move(linkerInput));
674
675 std::vector<char> globalVariablesBuffer;
676 globalVariablesBuffer.resize(32, 7);
677 std::vector<char> globalConstantsBuffer;
678 globalConstantsBuffer.resize(32, 7);
679 std::vector<char> globalVariablesInitData{32, 0};
680 std::vector<char> globalConstantsInitData{32, 0};
681 buildInfo.globalSurface = new MockGraphicsAllocation(globalVariablesBuffer.data(), globalVariablesBuffer.size());
682 buildInfo.constantSurface = new MockGraphicsAllocation(globalConstantsBuffer.data(), globalConstantsBuffer.size());
683
684 auto ret = program.linkBinary(&pClDevice->getDevice(), globalConstantsInitData.data(), globalVariablesInitData.data(), {});
685 EXPECT_EQ(CL_SUCCESS, ret);
686 EXPECT_EQ(kernelHeapData, kernelHeap);
687
688 program.getKernelInfoArray(rootDeviceIndex).clear();
689 delete buildInfo.globalSurface;
690 buildInfo.globalSurface = nullptr;
691 delete buildInfo.constantSurface;
692 buildInfo.constantSurface = nullptr;
693 }
694
TEST(ProgramStringSectionTest,WhenConstStringBufferIsPresentThenUseItForLinking)695 TEST(ProgramStringSectionTest, WhenConstStringBufferIsPresentThenUseItForLinking) {
696 auto device = std::make_unique<MockClDevice>(MockDevice::createWithNewExecutionEnvironment<MockDevice>(defaultHwInfo.get()));
697 auto rootDeviceIndex = device->getRootDeviceIndex();
698
699 MockProgram program{nullptr, false, toClDeviceVector(*device)};
700
701 uint8_t kernelHeapData[64] = {};
702 MockGraphicsAllocation kernelIsa(kernelHeapData, 64);
703
704 KernelInfo kernelInfo = {};
705 kernelInfo.kernelDescriptor.kernelMetadata.kernelName = "onlyKernel";
706 kernelInfo.heapInfo.pKernelHeap = kernelHeapData;
707 kernelInfo.heapInfo.KernelHeapSize = 64;
708 kernelInfo.kernelAllocation = &kernelIsa;
709
710 program.getKernelInfoArray(rootDeviceIndex).push_back(&kernelInfo);
711
712 auto linkerInput = std::make_unique<WhiteBox<LinkerInput>>();
713 linkerInput->relocations.push_back({{".str", 0x8, LinkerInput::RelocationInfo::Type::Address, SegmentType::Instructions}});
714 linkerInput->symbols.insert({".str", {0x0, 0x8, SegmentType::GlobalStrings}});
715 linkerInput->traits.requiresPatchingOfInstructionSegments = true;
716
717 program.setLinkerInput(rootDeviceIndex, std::move(linkerInput));
718
719 auto isaCpuPtr = reinterpret_cast<char *>(kernelInfo.getGraphicsAllocation()->getUnderlyingBuffer());
720 auto patchAddr = ptrOffset(isaCpuPtr, 0x8);
721
722 const char constStringData[] = "Hello World!\n";
723 auto stringsAddr = reinterpret_cast<uintptr_t>(constStringData);
724
725 auto ret = program.linkBinary(&device->getDevice(), nullptr, nullptr, {constStringData, sizeof(constStringData)});
726 EXPECT_EQ(CL_SUCCESS, ret);
727 EXPECT_EQ(static_cast<size_t>(stringsAddr), *reinterpret_cast<size_t *>(patchAddr));
728
729 program.getKernelInfoArray(rootDeviceIndex).clear();
730 }
731
TEST(ProgramImplicitArgsTest,givenImplicitRelocationAndStackCallsThenKernelRequiresImplicitArgs)732 TEST(ProgramImplicitArgsTest, givenImplicitRelocationAndStackCallsThenKernelRequiresImplicitArgs) {
733 auto device = std::make_unique<MockClDevice>(MockDevice::createWithNewExecutionEnvironment<MockDevice>(defaultHwInfo.get()));
734 auto rootDeviceIndex = device->getRootDeviceIndex();
735 MockProgram program{nullptr, false, toClDeviceVector(*device)};
736 KernelInfo kernelInfo = {};
737 kernelInfo.kernelDescriptor.kernelMetadata.kernelName = "onlyKernel";
738 kernelInfo.kernelDescriptor.kernelAttributes.flags.useStackCalls = true;
739 uint8_t kernelHeapData[64] = {};
740 kernelInfo.heapInfo.pKernelHeap = kernelHeapData;
741 kernelInfo.heapInfo.KernelHeapSize = 64;
742 MockGraphicsAllocation kernelIsa(kernelHeapData, 64);
743 kernelInfo.kernelAllocation = &kernelIsa;
744 program.getKernelInfoArray(rootDeviceIndex).push_back(&kernelInfo);
745
746 auto linkerInput = std::make_unique<WhiteBox<LinkerInput>>();
747 linkerInput->relocations.push_back({{implicitArgsRelocationSymbolName, 0x8, LinkerInput::RelocationInfo::Type::AddressLow, SegmentType::Instructions}});
748 linkerInput->traits.requiresPatchingOfInstructionSegments = true;
749 program.setLinkerInput(rootDeviceIndex, std::move(linkerInput));
750 auto ret = program.linkBinary(&device->getDevice(), nullptr, nullptr, {});
751 EXPECT_EQ(CL_SUCCESS, ret);
752
753 EXPECT_TRUE(kernelInfo.kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs);
754 program.getKernelInfoArray(rootDeviceIndex).clear();
755 }
756
TEST(ProgramImplicitArgsTest,givenImplicitRelocationAndEnabledDebuggerThenKernelRequiresImplicitArgs)757 TEST(ProgramImplicitArgsTest, givenImplicitRelocationAndEnabledDebuggerThenKernelRequiresImplicitArgs) {
758 if (!defaultHwInfo->capabilityTable.debuggerSupported) {
759 GTEST_SKIP();
760 }
761 DebugManagerStateRestore restorer;
762 DebugManager.flags.EnableMockSourceLevelDebugger.set(1);
763 auto device = std::make_unique<MockClDevice>(MockDevice::createWithNewExecutionEnvironment<MockDevice>(defaultHwInfo.get()));
764
765 EXPECT_NE(nullptr, device->getDebugger());
766 auto rootDeviceIndex = device->getRootDeviceIndex();
767 MockProgram program{nullptr, false, toClDeviceVector(*device)};
768 KernelInfo kernelInfo = {};
769 kernelInfo.kernelDescriptor.kernelMetadata.kernelName = "onlyKernel";
770 kernelInfo.kernelDescriptor.kernelAttributes.flags.useStackCalls = false;
771 uint8_t kernelHeapData[64] = {};
772 kernelInfo.heapInfo.pKernelHeap = kernelHeapData;
773 kernelInfo.heapInfo.KernelHeapSize = 64;
774 MockGraphicsAllocation kernelIsa(kernelHeapData, 64);
775 kernelInfo.kernelAllocation = &kernelIsa;
776 program.getKernelInfoArray(rootDeviceIndex).push_back(&kernelInfo);
777
778 auto linkerInput = std::make_unique<WhiteBox<LinkerInput>>();
779 linkerInput->relocations.push_back({{implicitArgsRelocationSymbolName, 0x8, LinkerInput::RelocationInfo::Type::AddressLow, SegmentType::Instructions}});
780 linkerInput->traits.requiresPatchingOfInstructionSegments = true;
781 program.setLinkerInput(rootDeviceIndex, std::move(linkerInput));
782 auto ret = program.linkBinary(&device->getDevice(), nullptr, nullptr, {});
783 EXPECT_EQ(CL_SUCCESS, ret);
784
785 EXPECT_TRUE(kernelInfo.kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs);
786 program.getKernelInfoArray(rootDeviceIndex).clear();
787 }
788
TEST(ProgramImplicitArgsTest,givenImplicitRelocationAndNoStackCallsAndDisabledDebuggerThenKernelDoesntRequireImplicitArgs)789 TEST(ProgramImplicitArgsTest, givenImplicitRelocationAndNoStackCallsAndDisabledDebuggerThenKernelDoesntRequireImplicitArgs) {
790 auto device = std::make_unique<MockClDevice>(MockDevice::createWithNewExecutionEnvironment<MockDevice>(defaultHwInfo.get()));
791 EXPECT_EQ(nullptr, device->getDebugger());
792 auto rootDeviceIndex = device->getRootDeviceIndex();
793 MockProgram program{nullptr, false, toClDeviceVector(*device)};
794 KernelInfo kernelInfo = {};
795 kernelInfo.kernelDescriptor.kernelMetadata.kernelName = "onlyKernel";
796 kernelInfo.kernelDescriptor.kernelAttributes.flags.useStackCalls = false;
797 uint8_t kernelHeapData[64] = {};
798 kernelInfo.heapInfo.pKernelHeap = kernelHeapData;
799 kernelInfo.heapInfo.KernelHeapSize = 64;
800 MockGraphicsAllocation kernelIsa(kernelHeapData, 64);
801 kernelInfo.kernelAllocation = &kernelIsa;
802 program.getKernelInfoArray(rootDeviceIndex).push_back(&kernelInfo);
803
804 auto linkerInput = std::make_unique<WhiteBox<LinkerInput>>();
805 linkerInput->relocations.push_back({{implicitArgsRelocationSymbolName, 0x8, LinkerInput::RelocationInfo::Type::AddressLow, SegmentType::Instructions}});
806 linkerInput->traits.requiresPatchingOfInstructionSegments = true;
807 program.setLinkerInput(rootDeviceIndex, std::move(linkerInput));
808 auto ret = program.linkBinary(&device->getDevice(), nullptr, nullptr, {});
809 EXPECT_EQ(CL_SUCCESS, ret);
810
811 EXPECT_FALSE(kernelInfo.kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs);
812 program.getKernelInfoArray(rootDeviceIndex).clear();
813 }
814