mirror of
https://github.com/intel/compute-runtime.git
synced 2026-01-03 14:55:24 +08:00
Reorganization directory structure [2/n]
Change-Id: I47962d17d755e80dcd9476e1ed75560f433f6115
This commit is contained in:
committed by
Jaroslaw Chodor
parent
d015d3633f
commit
e8852a68c4
36
opencl/test/unit_test/program/CMakeLists.txt
Normal file
36
opencl/test/unit_test/program/CMakeLists.txt
Normal file
@@ -0,0 +1,36 @@
|
||||
#
|
||||
# Copyright (C) 2017-2020 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
|
||||
set(IGDRCL_SRCS_tests_program
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/block_kernel_manager_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/kernel_data.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/kernel_data_OCL2_0.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/kernel_info_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/kernel_info_from_patchtokens_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/printf_handler_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/printf_helper_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/process_debug_data_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/process_elf_binary_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/process_spir_binary_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/program_data_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/program_from_binary.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/program_nonuniform.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/program_spec_constants_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/program_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/program_tests.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/program_with_block_kernels_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/program_with_kernel_debug_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/program_with_source.h
|
||||
)
|
||||
|
||||
get_property(NEO_CORE_SRCS_tests_program GLOBAL PROPERTY NEO_CORE_SRCS_tests_program)
|
||||
list(APPEND IGDRCL_SRCS_tests_program
|
||||
${NEO_CORE_SRCS_tests_program}
|
||||
)
|
||||
|
||||
target_sources(igdrcl_tests PRIVATE ${IGDRCL_SRCS_tests_program})
|
||||
add_subdirectories()
|
||||
88
opencl/test/unit_test/program/block_kernel_manager_tests.cpp
Normal file
88
opencl/test/unit_test/program/block_kernel_manager_tests.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "core/memory_manager/graphics_allocation.h"
|
||||
#include "opencl/source/program/kernel_info.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "mocks/mock_block_kernel_manager.h"
|
||||
#include "mocks/mock_graphics_allocation.h"
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
TEST(BlockKernelManagerTest, pushPrivateSurfaceResizesArray) {
|
||||
MockGraphicsAllocation allocation(0, 0);
|
||||
KernelInfo *blockInfo = new KernelInfo;
|
||||
MockBlockKernelManager blockManager;
|
||||
|
||||
blockManager.addBlockKernelInfo(blockInfo);
|
||||
|
||||
EXPECT_EQ(0u, blockManager.blockPrivateSurfaceArray.size());
|
||||
|
||||
blockManager.pushPrivateSurface(&allocation, 0);
|
||||
|
||||
EXPECT_EQ(1u, blockManager.blockPrivateSurfaceArray.size());
|
||||
}
|
||||
|
||||
TEST(BlockKernelManagerTest, pushPrivateSurfacePlacesAllocationInCorrectPosition) {
|
||||
MockGraphicsAllocation allocation1(0, 0);
|
||||
MockGraphicsAllocation allocation2(0, 0);
|
||||
KernelInfo *blockInfo = new KernelInfo;
|
||||
KernelInfo *blockInfo2 = new KernelInfo;
|
||||
MockBlockKernelManager blockManager;
|
||||
|
||||
blockManager.addBlockKernelInfo(blockInfo);
|
||||
blockManager.addBlockKernelInfo(blockInfo2);
|
||||
|
||||
blockManager.pushPrivateSurface(&allocation1, 0);
|
||||
blockManager.pushPrivateSurface(&allocation2, 1);
|
||||
|
||||
EXPECT_EQ(2u, blockManager.blockPrivateSurfaceArray.size());
|
||||
|
||||
EXPECT_EQ(&allocation1, blockManager.blockPrivateSurfaceArray[0]);
|
||||
EXPECT_EQ(&allocation2, blockManager.blockPrivateSurfaceArray[1]);
|
||||
}
|
||||
|
||||
TEST(BlockKernelManagerTest, pushPrivateSurfaceSetsPrivateSurfaceArrayToNullptrOnFirstCall) {
|
||||
MockGraphicsAllocation allocation(0, 0);
|
||||
KernelInfo *blockInfo = new KernelInfo;
|
||||
KernelInfo *blockInfo2 = new KernelInfo;
|
||||
KernelInfo *blockInfo3 = new KernelInfo;
|
||||
MockBlockKernelManager blockManager;
|
||||
|
||||
blockManager.addBlockKernelInfo(blockInfo);
|
||||
blockManager.addBlockKernelInfo(blockInfo2);
|
||||
blockManager.addBlockKernelInfo(blockInfo3);
|
||||
|
||||
blockManager.pushPrivateSurface(&allocation, 1);
|
||||
|
||||
EXPECT_EQ(3u, blockManager.blockPrivateSurfaceArray.size());
|
||||
|
||||
EXPECT_EQ(nullptr, blockManager.blockPrivateSurfaceArray[0]);
|
||||
EXPECT_EQ(nullptr, blockManager.blockPrivateSurfaceArray[2]);
|
||||
}
|
||||
|
||||
TEST(BlockKernelManagerTest, getPrivateSurface) {
|
||||
MockGraphicsAllocation allocation(0, 0);
|
||||
KernelInfo *blockInfo = new KernelInfo;
|
||||
|
||||
MockBlockKernelManager blockManager;
|
||||
|
||||
blockManager.addBlockKernelInfo(blockInfo);
|
||||
|
||||
blockManager.pushPrivateSurface(&allocation, 0);
|
||||
|
||||
EXPECT_EQ(1u, blockManager.blockPrivateSurfaceArray.size());
|
||||
|
||||
EXPECT_EQ(&allocation, blockManager.getPrivateSurface(0));
|
||||
}
|
||||
|
||||
TEST(BlockKernelManagerTest, getPrivateSurfaceWithOutOfBoundOrdinalRetunrsNullptr) {
|
||||
MockBlockKernelManager blockManager;
|
||||
EXPECT_EQ(nullptr, blockManager.getPrivateSurface(0));
|
||||
EXPECT_EQ(nullptr, blockManager.getPrivateSurface(10));
|
||||
}
|
||||
133
opencl/test/unit_test/program/evaluate_unhandled_token_tests.cpp
Normal file
133
opencl/test/unit_test/program/evaluate_unhandled_token_tests.cpp
Normal file
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "core/device_binary_format/patchtokens_decoder.h"
|
||||
#include "core/execution_environment/execution_environment.h"
|
||||
#include "core/unit_tests/device_binary_format/patchtokens_tests.h"
|
||||
#include "opencl/source/program/create.inl"
|
||||
#include "opencl/source/program/program.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
extern GFXCORE_FAMILY renderCoreFamily;
|
||||
|
||||
template <typename ContainerT, typename TokenT>
|
||||
inline void PushBackToken(ContainerT &container, const TokenT &token) {
|
||||
container.insert(container.end(), reinterpret_cast<const typename ContainerT::value_type *>(&token),
|
||||
reinterpret_cast<const typename ContainerT::value_type *>(&token) + sizeof(token));
|
||||
}
|
||||
|
||||
struct MockProgramRecordUnhandledTokens : public Program {
|
||||
bool allowUnhandledTokens;
|
||||
mutable int lastUnhandledTokenFound;
|
||||
|
||||
MockProgramRecordUnhandledTokens(ExecutionEnvironment &executionEnvironment) : Program(executionEnvironment) {}
|
||||
MockProgramRecordUnhandledTokens(ExecutionEnvironment &executionEnvironment, Context *context, bool isBuiltinKernel) : Program(executionEnvironment, context, isBuiltinKernel) {}
|
||||
|
||||
bool isSafeToSkipUnhandledToken(unsigned int token) const override {
|
||||
lastUnhandledTokenFound = static_cast<int>(token);
|
||||
return allowUnhandledTokens;
|
||||
}
|
||||
|
||||
bool getDefaultIsSafeToSkipUnhandledToken() const {
|
||||
return Program::isSafeToSkipUnhandledToken(iOpenCL::NUM_PATCH_TOKENS);
|
||||
}
|
||||
};
|
||||
|
||||
inline cl_int GetDecodeErrorCode(const std::vector<char> &binary, bool allowUnhandledTokens,
|
||||
int defaultUnhandledTokenId, int &foundUnhandledTokenId) {
|
||||
NEO::ExecutionEnvironment executionEnvironment;
|
||||
using PT = MockProgramRecordUnhandledTokens;
|
||||
std::unique_ptr<PT> prog;
|
||||
cl_int errorCode = CL_INVALID_BINARY;
|
||||
prog.reset(NEO::Program::createFromGenBinary<PT>(executionEnvironment,
|
||||
nullptr,
|
||||
binary.data(),
|
||||
binary.size(),
|
||||
false, &errorCode));
|
||||
prog->allowUnhandledTokens = allowUnhandledTokens;
|
||||
prog->lastUnhandledTokenFound = defaultUnhandledTokenId;
|
||||
auto ret = prog->processGenBinary();
|
||||
foundUnhandledTokenId = prog->lastUnhandledTokenFound;
|
||||
return ret;
|
||||
};
|
||||
|
||||
inline std::vector<char> CreateBinary(bool addUnhandledProgramScopePatchToken, bool addUnhandledKernelScopePatchToken,
|
||||
int32_t unhandledTokenId = static_cast<int32_t>(iOpenCL::NUM_PATCH_TOKENS)) {
|
||||
std::vector<char> ret;
|
||||
|
||||
if (addUnhandledProgramScopePatchToken && addUnhandledKernelScopePatchToken) {
|
||||
return {};
|
||||
}
|
||||
|
||||
if (addUnhandledProgramScopePatchToken) {
|
||||
PatchTokensTestData::ValidProgramWithConstantSurface programWithUnhandledToken;
|
||||
|
||||
iOpenCL::SPatchItemHeader &unhandledToken = *programWithUnhandledToken.constSurfMutable;
|
||||
unhandledToken.Size += programWithUnhandledToken.constSurfMutable->InlineDataSize;
|
||||
unhandledToken.Token = static_cast<uint32_t>(unhandledTokenId);
|
||||
ret.assign(reinterpret_cast<char *>(programWithUnhandledToken.storage.data()),
|
||||
reinterpret_cast<char *>(programWithUnhandledToken.storage.data() + programWithUnhandledToken.storage.size()));
|
||||
} else if (addUnhandledKernelScopePatchToken) {
|
||||
PatchTokensTestData::ValidProgramWithKernelAndArg programWithKernelWithUnhandledToken;
|
||||
iOpenCL::SPatchItemHeader &unhandledToken = *programWithKernelWithUnhandledToken.arg0InfoMutable;
|
||||
unhandledToken.Token = static_cast<uint32_t>(unhandledTokenId);
|
||||
programWithKernelWithUnhandledToken.recalcTokPtr();
|
||||
ret.assign(reinterpret_cast<char *>(programWithKernelWithUnhandledToken.storage.data()),
|
||||
reinterpret_cast<char *>(programWithKernelWithUnhandledToken.storage.data() + programWithKernelWithUnhandledToken.storage.size()));
|
||||
} else {
|
||||
PatchTokensTestData::ValidProgramWithKernel regularProgramTokens;
|
||||
ret.assign(reinterpret_cast<char *>(regularProgramTokens.storage.data()), reinterpret_cast<char *>(regularProgramTokens.storage.data() + regularProgramTokens.storage.size()));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
constexpr int32_t unhandledTokenId = iOpenCL::NUM_PATCH_TOKENS;
|
||||
|
||||
TEST(EvaluateUnhandledToken, ByDefaultSkippingOfUnhandledTokensInUnitTestsIsSafe) {
|
||||
ExecutionEnvironment executionEnvironment;
|
||||
MockProgramRecordUnhandledTokens program(executionEnvironment);
|
||||
EXPECT_TRUE(program.getDefaultIsSafeToSkipUnhandledToken());
|
||||
}
|
||||
|
||||
TEST(EvaluateUnhandledToken, WhenDecodingProgramBinaryIfAllTokensAreSupportedThenDecodingSucceeds) {
|
||||
int lastUnhandledTokenFound = -1;
|
||||
auto retVal = GetDecodeErrorCode(CreateBinary(false, false), false, -7, lastUnhandledTokenFound);
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
EXPECT_EQ(-7, lastUnhandledTokenFound);
|
||||
}
|
||||
|
||||
TEST(EvaluateUnhandledToken, WhenDecodingProgramBinaryIfUnhandledTokenIsFoundAndIsSafeToSkipThenDecodingSucceeds) {
|
||||
int lastUnhandledTokenFound = -1;
|
||||
auto retVal = GetDecodeErrorCode(CreateBinary(true, false, unhandledTokenId), true, -7, lastUnhandledTokenFound);
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
EXPECT_EQ(unhandledTokenId, lastUnhandledTokenFound);
|
||||
}
|
||||
|
||||
TEST(EvaluateUnhandledToken, WhenDecodingProgramBinaryIfUnhandledTokenIsFoundAndIsUnsafeToSkipThenDecodingFails) {
|
||||
int lastUnhandledTokenFound = -1;
|
||||
auto retVal = GetDecodeErrorCode(CreateBinary(true, false, unhandledTokenId), false, -7, lastUnhandledTokenFound);
|
||||
EXPECT_EQ(CL_INVALID_BINARY, retVal);
|
||||
EXPECT_EQ(unhandledTokenId, lastUnhandledTokenFound);
|
||||
}
|
||||
|
||||
TEST(EvaluateUnhandledToken, WhenDecodingKernelBinaryIfUnhandledTokenIsFoundAndIsSafeToSkipThenDecodingSucceeds) {
|
||||
int lastUnhandledTokenFound = -1;
|
||||
auto retVal = GetDecodeErrorCode(CreateBinary(false, true, unhandledTokenId), true, -7, lastUnhandledTokenFound);
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
EXPECT_EQ(unhandledTokenId, lastUnhandledTokenFound);
|
||||
}
|
||||
|
||||
TEST(EvaluateUnhandledToken, WhenDecodingKernelBinaryIfUnhandledTokenIsFoundAndIsUnsafeToSkipThenDecodingFails) {
|
||||
int lastUnhandledTokenFound = -1;
|
||||
auto retVal = GetDecodeErrorCode(CreateBinary(false, true, unhandledTokenId), false, -7, lastUnhandledTokenFound);
|
||||
EXPECT_EQ(CL_INVALID_BINARY, retVal);
|
||||
EXPECT_EQ(unhandledTokenId, lastUnhandledTokenFound);
|
||||
}
|
||||
1479
opencl/test/unit_test/program/kernel_data.cpp
Normal file
1479
opencl/test/unit_test/program/kernel_data.cpp
Normal file
File diff suppressed because it is too large
Load Diff
171
opencl/test/unit_test/program/kernel_data_OCL2_0.cpp
Normal file
171
opencl/test/unit_test/program/kernel_data_OCL2_0.cpp
Normal file
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "fixtures/kernel_data_fixture.h"
|
||||
#include "helpers/gtest_helpers.h"
|
||||
|
||||
TEST_F(KernelDataTest, GIVENpatchTokenAllocateStatelessEventPoolSurfaceWHENdecodeTokensTHENtokenLocatedInPatchInfo) {
|
||||
iOpenCL::SPatchAllocateStatelessEventPoolSurface allocateStatelessEventPoolSurface;
|
||||
allocateStatelessEventPoolSurface.Token = PATCH_TOKEN_ALLOCATE_STATELESS_EVENT_POOL_SURFACE;
|
||||
allocateStatelessEventPoolSurface.Size = sizeof(SPatchAllocateStatelessEventPoolSurface);
|
||||
|
||||
allocateStatelessEventPoolSurface.DataParamSize = 7;
|
||||
allocateStatelessEventPoolSurface.DataParamOffset = 0xABC;
|
||||
allocateStatelessEventPoolSurface.SurfaceStateHeapOffset = 0xDEF;
|
||||
|
||||
pPatchList = &allocateStatelessEventPoolSurface;
|
||||
patchListSize = allocateStatelessEventPoolSurface.Size;
|
||||
|
||||
buildAndDecode();
|
||||
|
||||
EXPECT_EQ_VAL(allocateStatelessEventPoolSurface.Token,
|
||||
pKernelInfo->patchInfo.pAllocateStatelessEventPoolSurface->Token);
|
||||
EXPECT_EQ_VAL(allocateStatelessEventPoolSurface.DataParamOffset,
|
||||
pKernelInfo->patchInfo.pAllocateStatelessEventPoolSurface->DataParamOffset);
|
||||
EXPECT_EQ_VAL(allocateStatelessEventPoolSurface.DataParamSize,
|
||||
pKernelInfo->patchInfo.pAllocateStatelessEventPoolSurface->DataParamSize);
|
||||
EXPECT_EQ_VAL(allocateStatelessEventPoolSurface.SurfaceStateHeapOffset,
|
||||
pKernelInfo->patchInfo.pAllocateStatelessEventPoolSurface->SurfaceStateHeapOffset);
|
||||
}
|
||||
|
||||
TEST_F(KernelDataTest, GIVENpatchTokenAllocateStatelessDefaultDeviceQueueSurfaceWHENdecodeTokensTHENtokenLocatedInPatchInfo) {
|
||||
iOpenCL::SPatchAllocateStatelessDefaultDeviceQueueSurface allocateStatelessDefaultDeviceQueueSurface;
|
||||
allocateStatelessDefaultDeviceQueueSurface.Token = PATCH_TOKEN_ALLOCATE_STATELESS_DEFAULT_DEVICE_QUEUE_SURFACE;
|
||||
allocateStatelessDefaultDeviceQueueSurface.Size = sizeof(SPatchAllocateStatelessDefaultDeviceQueueSurface);
|
||||
|
||||
allocateStatelessDefaultDeviceQueueSurface.DataParamSize = 7;
|
||||
allocateStatelessDefaultDeviceQueueSurface.DataParamOffset = 0xABC;
|
||||
allocateStatelessDefaultDeviceQueueSurface.SurfaceStateHeapOffset = 0xDEF;
|
||||
|
||||
pPatchList = &allocateStatelessDefaultDeviceQueueSurface;
|
||||
patchListSize = allocateStatelessDefaultDeviceQueueSurface.Size;
|
||||
|
||||
buildAndDecode();
|
||||
|
||||
EXPECT_EQ(allocateStatelessDefaultDeviceQueueSurface.Token,
|
||||
pKernelInfo->patchInfo.pAllocateStatelessDefaultDeviceQueueSurface->Token);
|
||||
EXPECT_EQ(allocateStatelessDefaultDeviceQueueSurface.DataParamOffset,
|
||||
pKernelInfo->patchInfo.pAllocateStatelessDefaultDeviceQueueSurface->DataParamOffset);
|
||||
EXPECT_EQ(allocateStatelessDefaultDeviceQueueSurface.DataParamSize,
|
||||
pKernelInfo->patchInfo.pAllocateStatelessDefaultDeviceQueueSurface->DataParamSize);
|
||||
EXPECT_EQ(allocateStatelessDefaultDeviceQueueSurface.SurfaceStateHeapOffset,
|
||||
pKernelInfo->patchInfo.pAllocateStatelessDefaultDeviceQueueSurface->SurfaceStateHeapOffset);
|
||||
}
|
||||
|
||||
TEST_F(KernelDataTest, GIVENpatchTokenStatelessDeviceQueueKernelArgumentWHENdecodeTokensTHENapropriateKernelArgInfoFilled) {
|
||||
iOpenCL::SPatchStatelessDeviceQueueKernelArgument deviceQueueKernelArgument;
|
||||
deviceQueueKernelArgument.Token = PATCH_TOKEN_STATELESS_DEVICE_QUEUE_KERNEL_ARGUMENT;
|
||||
deviceQueueKernelArgument.Size = sizeof(SPatchStatelessDeviceQueueKernelArgument);
|
||||
|
||||
deviceQueueKernelArgument.ArgumentNumber = 3;
|
||||
deviceQueueKernelArgument.DataParamSize = 7;
|
||||
deviceQueueKernelArgument.DataParamOffset = 0xABC;
|
||||
deviceQueueKernelArgument.SurfaceStateHeapOffset = 0xDEF;
|
||||
|
||||
pPatchList = &deviceQueueKernelArgument;
|
||||
patchListSize = deviceQueueKernelArgument.Size;
|
||||
|
||||
buildAndDecode();
|
||||
|
||||
ASSERT_GE(pKernelInfo->kernelArgInfo.size(), size_t(4u));
|
||||
EXPECT_EQ(pKernelInfo->kernelArgInfo[3].isDeviceQueue, true);
|
||||
EXPECT_EQ(pKernelInfo->kernelArgInfo[3].kernelArgPatchInfoVector[0].crossthreadOffset,
|
||||
deviceQueueKernelArgument.DataParamOffset);
|
||||
EXPECT_EQ(pKernelInfo->kernelArgInfo[3].kernelArgPatchInfoVector[0].size,
|
||||
deviceQueueKernelArgument.DataParamSize);
|
||||
EXPECT_EQ(pKernelInfo->kernelArgInfo[3].offsetHeap,
|
||||
deviceQueueKernelArgument.SurfaceStateHeapOffset);
|
||||
}
|
||||
|
||||
TEST_F(KernelDataTest, GIVENdataParameterParentEventWHENdecodeTokensTHENoffsetLocatedInWorkloadInfo) {
|
||||
const uint32_t offsetSimdSize = 0xABC;
|
||||
|
||||
SPatchDataParameterBuffer dataParameterToken;
|
||||
dataParameterToken.Token = PATCH_TOKEN_DATA_PARAMETER_BUFFER;
|
||||
dataParameterToken.Size = sizeof(SPatchDataParameterBuffer);
|
||||
dataParameterToken.Type = DATA_PARAMETER_PARENT_EVENT;
|
||||
dataParameterToken.ArgumentNumber = 0;
|
||||
dataParameterToken.Offset = offsetSimdSize;
|
||||
dataParameterToken.DataSize = sizeof(uint32_t);
|
||||
dataParameterToken.SourceOffset = 0;
|
||||
|
||||
pPatchList = &dataParameterToken;
|
||||
patchListSize = dataParameterToken.Size;
|
||||
|
||||
buildAndDecode();
|
||||
|
||||
EXPECT_EQ(pKernelInfo->workloadInfo.parentEventOffset, offsetSimdSize);
|
||||
}
|
||||
|
||||
TEST_F(KernelDataTest, GIVENdataParameterPreferredWorkgroupMultipleTokenWHENbinaryIsdecodedTHENcorrectOffsetIsAssigned) {
|
||||
const uint32_t offset = 0x100;
|
||||
|
||||
SPatchDataParameterBuffer dataParameterToken;
|
||||
dataParameterToken.Token = PATCH_TOKEN_DATA_PARAMETER_BUFFER;
|
||||
dataParameterToken.Size = sizeof(SPatchDataParameterBuffer);
|
||||
dataParameterToken.Type = DATA_PARAMETER_PREFERRED_WORKGROUP_MULTIPLE;
|
||||
dataParameterToken.ArgumentNumber = 0;
|
||||
dataParameterToken.Offset = offset;
|
||||
dataParameterToken.DataSize = sizeof(uint32_t);
|
||||
dataParameterToken.SourceOffset = 0;
|
||||
|
||||
pPatchList = &dataParameterToken;
|
||||
patchListSize = dataParameterToken.Size;
|
||||
|
||||
buildAndDecode();
|
||||
|
||||
EXPECT_EQ(pKernelInfo->workloadInfo.preferredWkgMultipleOffset, offset);
|
||||
}
|
||||
|
||||
TEST_F(KernelDataTest, GIVENdataParameterObjectIdWHENdecodeTokensTHENoffsetLocatedInKernelArgInfo) {
|
||||
const uint32_t offsetObjectId = 0xABC;
|
||||
const uint32_t argNum = 7;
|
||||
|
||||
SPatchDataParameterBuffer dataParameterToken;
|
||||
dataParameterToken.Token = PATCH_TOKEN_DATA_PARAMETER_BUFFER;
|
||||
dataParameterToken.Size = sizeof(SPatchDataParameterBuffer);
|
||||
dataParameterToken.Type = DATA_PARAMETER_OBJECT_ID;
|
||||
dataParameterToken.ArgumentNumber = argNum;
|
||||
dataParameterToken.Offset = offsetObjectId;
|
||||
dataParameterToken.DataSize = sizeof(uint32_t);
|
||||
dataParameterToken.SourceOffset = 0;
|
||||
|
||||
pPatchList = &dataParameterToken;
|
||||
patchListSize = dataParameterToken.Size;
|
||||
|
||||
buildAndDecode();
|
||||
|
||||
ASSERT_GE(pKernelInfo->kernelArgInfo.size(), size_t(argNum + 1));
|
||||
EXPECT_EQ(pKernelInfo->kernelArgInfo[argNum].offsetObjectId, offsetObjectId);
|
||||
}
|
||||
|
||||
TEST_F(KernelDataTest, GIVENdataParameterChildSimdSizeWHENdecodeTokensTHENchildsIdsStoredInKernelInfoWithOffset) {
|
||||
SPatchDataParameterBuffer patchList[3];
|
||||
uint32_t childrenKernelIds[3] = {7, 14, 21};
|
||||
uint32_t childrenSimdSizeOffsets[3] = {0x77, 0xAB, 0xCD};
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
patchList[i].Token = PATCH_TOKEN_DATA_PARAMETER_BUFFER;
|
||||
patchList[i].Size = sizeof(SPatchDataParameterBuffer);
|
||||
patchList[i].Type = DATA_PARAMETER_CHILD_BLOCK_SIMD_SIZE;
|
||||
patchList[i].ArgumentNumber = childrenKernelIds[i];
|
||||
patchList[i].Offset = childrenSimdSizeOffsets[i];
|
||||
patchList[i].DataSize = sizeof(uint32_t);
|
||||
patchList[i].SourceOffset = 0;
|
||||
}
|
||||
|
||||
pPatchList = patchList;
|
||||
patchListSize = sizeof(patchList);
|
||||
|
||||
buildAndDecode();
|
||||
|
||||
ASSERT_GE(pKernelInfo->childrenKernelsIdOffset.size(), size_t(3u));
|
||||
for (int i = 0; i < 3; i++) {
|
||||
EXPECT_EQ(pKernelInfo->childrenKernelsIdOffset[i].first, childrenKernelIds[i]);
|
||||
EXPECT_EQ(pKernelInfo->childrenKernelsIdOffset[i].second, childrenSimdSizeOffsets[i]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "core/device_binary_format/patchtokens_decoder.h"
|
||||
#include "core/unit_tests/device_binary_format/patchtokens_tests.h"
|
||||
#include "opencl/source/program/kernel_info.h"
|
||||
#include "opencl/source/program/kernel_info_from_patchtokens.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
TEST(KernelInfoFromPatchTokens, GivenValidEmptyKernelFromPatchtokensThenReturnEmptyKernelInfo) {
|
||||
std::vector<uint8_t> storage;
|
||||
auto src = PatchTokensTestData::ValidEmptyKernel::create(storage);
|
||||
NEO::KernelInfo dst = {};
|
||||
NEO::populateKernelInfo(dst, src, 4);
|
||||
|
||||
NEO::KernelInfo expectedKernelInfo = {};
|
||||
expectedKernelInfo.name = std::string(src.name.begin()).c_str();
|
||||
expectedKernelInfo.heapInfo.pKernelHeader = src.header;
|
||||
|
||||
EXPECT_STREQ(expectedKernelInfo.name.c_str(), dst.name.c_str());
|
||||
EXPECT_EQ(expectedKernelInfo.heapInfo.pKernelHeader, dst.heapInfo.pKernelHeader);
|
||||
}
|
||||
|
||||
TEST(KernelInfoFromPatchTokens, GivenValidKernelWithArgThenMetadataIsProperlyPopulated) {
|
||||
PatchTokensTestData::ValidProgramWithKernelAndArg src;
|
||||
NEO::KernelInfo dst = {};
|
||||
NEO::populateKernelInfo(dst, src.kernels[0], 4);
|
||||
ASSERT_EQ(1U, dst.kernelArgInfo.size());
|
||||
EXPECT_EQ(NEO::KernelArgMetadata::AccessQualifier::ReadWrite, dst.kernelArgInfo[0].metadata.accessQualifier);
|
||||
EXPECT_EQ(NEO::KernelArgMetadata::AddressSpaceQualifier::Global, dst.kernelArgInfo[0].metadata.addressQualifier);
|
||||
NEO::KernelArgMetadata::TypeQualifiers typeQualifiers = {};
|
||||
typeQualifiers.constQual = true;
|
||||
EXPECT_EQ(typeQualifiers.packed, dst.kernelArgInfo[0].metadata.typeQualifiers.packed);
|
||||
EXPECT_EQ(0U, dst.kernelArgInfo[0].metadata.argByValSize);
|
||||
ASSERT_NE(nullptr, dst.kernelArgInfo[0].metadataExtended);
|
||||
EXPECT_STREQ("__global", dst.kernelArgInfo[0].metadataExtended->addressQualifier.c_str());
|
||||
EXPECT_STREQ("read_write", dst.kernelArgInfo[0].metadataExtended->accessQualifier.c_str());
|
||||
EXPECT_STREQ("custom_arg", dst.kernelArgInfo[0].metadataExtended->argName.c_str());
|
||||
EXPECT_STREQ("int*", dst.kernelArgInfo[0].metadataExtended->type.c_str());
|
||||
EXPECT_STREQ("const", dst.kernelArgInfo[0].metadataExtended->typeQualifiers.c_str());
|
||||
}
|
||||
|
||||
TEST(KernelInfoFromPatchTokens, GivenValidKernelWithImageArgThenArgAccessQualifierIsPopulatedBasedOnArgInfo) {
|
||||
PatchTokensTestData::ValidProgramWithKernelAndArg src;
|
||||
iOpenCL::SPatchImageMemoryObjectKernelArgument imageArg = {};
|
||||
imageArg.Token = iOpenCL::PATCH_TOKEN_IMAGE_MEMORY_OBJECT_KERNEL_ARGUMENT;
|
||||
imageArg.Writeable = false;
|
||||
src.kernels[0].tokens.kernelArgs[0].objectArg = &imageArg;
|
||||
NEO::KernelInfo dst = {};
|
||||
NEO::populateKernelInfo(dst, src.kernels[0], 4);
|
||||
ASSERT_EQ(1U, dst.kernelArgInfo.size());
|
||||
EXPECT_EQ(NEO::KernelArgMetadata::AccessQualifier::ReadWrite, dst.kernelArgInfo[0].metadata.accessQualifier);
|
||||
}
|
||||
|
||||
TEST(KernelInfoFromPatchTokens, GivenValidKernelWithImageArgWhenArgInfoIsMissingThenArgAccessQualifierIsPopulatedBasedOnImageArgWriteableFlag) {
|
||||
PatchTokensTestData::ValidProgramWithKernelAndArg src;
|
||||
iOpenCL::SPatchImageMemoryObjectKernelArgument imageArg = {};
|
||||
imageArg.Token = iOpenCL::PATCH_TOKEN_IMAGE_MEMORY_OBJECT_KERNEL_ARGUMENT;
|
||||
src.kernels[0].tokens.kernelArgs[0].objectArg = &imageArg;
|
||||
src.kernels[0].tokens.kernelArgs[0].argInfo = nullptr;
|
||||
{
|
||||
imageArg.Writeable = false;
|
||||
NEO::KernelInfo dst = {};
|
||||
NEO::populateKernelInfo(dst, src.kernels[0], 4);
|
||||
ASSERT_EQ(1U, dst.kernelArgInfo.size());
|
||||
EXPECT_EQ(NEO::KernelArgMetadata::AccessQualifier::ReadOnly, dst.kernelArgInfo[0].metadata.accessQualifier);
|
||||
}
|
||||
|
||||
{
|
||||
imageArg.Writeable = true;
|
||||
NEO::KernelInfo dst = {};
|
||||
NEO::populateKernelInfo(dst, src.kernels[0], 4);
|
||||
ASSERT_EQ(1U, dst.kernelArgInfo.size());
|
||||
EXPECT_EQ(NEO::KernelArgMetadata::AccessQualifier::ReadWrite, dst.kernelArgInfo[0].metadata.accessQualifier);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(KernelInfoFromPatchTokens, GivenValidKernelWithNonDelimitedArgTypeThenUsesArgTypeAsIs) {
|
||||
PatchTokensTestData::ValidProgramWithKernelAndArg src;
|
||||
src.arg0TypeMutable[4] = '*';
|
||||
NEO::KernelInfo dst = {};
|
||||
NEO::populateKernelInfo(dst, src.kernels[0], 4);
|
||||
ASSERT_EQ(1U, dst.kernelArgInfo.size());
|
||||
EXPECT_STREQ("int**", dst.kernelArgInfo[0].metadataExtended->type.c_str());
|
||||
}
|
||||
|
||||
TEST(KernelInfoFromPatchTokens, GivenDataParameterStreamWithEmptySizeThenTokenIsIgnored) {
|
||||
std::vector<uint8_t> storage;
|
||||
auto src = PatchTokensTestData::ValidEmptyKernel::create(storage);
|
||||
iOpenCL::SPatchDataParameterStream dataParameterStream = {};
|
||||
src.tokens.dataParameterStream = &dataParameterStream;
|
||||
dataParameterStream.DataParameterStreamSize = 0U;
|
||||
NEO::KernelInfo dst;
|
||||
NEO::populateKernelInfo(dst, src, 4);
|
||||
EXPECT_EQ(nullptr, dst.crossThreadData);
|
||||
}
|
||||
|
||||
TEST(KernelInfoFromPatchTokens, GivenDataParameterStreamWithNonEmptySizeThenCrossthreadDataIsAllocated) {
|
||||
std::vector<uint8_t> storage;
|
||||
auto src = PatchTokensTestData::ValidEmptyKernel::create(storage);
|
||||
iOpenCL::SPatchDataParameterStream dataParameterStream = {};
|
||||
src.tokens.dataParameterStream = &dataParameterStream;
|
||||
dataParameterStream.DataParameterStreamSize = 256U;
|
||||
NEO::KernelInfo dst;
|
||||
NEO::populateKernelInfo(dst, src, 4);
|
||||
EXPECT_NE(nullptr, dst.crossThreadData);
|
||||
}
|
||||
|
||||
TEST(KernelInfoFromPatchTokens, GivenDataParameterStreamWhenTokensRequiringDeviceInfoPayloadConstantsArePresentThenCrossthreadDataIsProperlyPatched) {
|
||||
std::vector<uint8_t> storage;
|
||||
auto src = PatchTokensTestData::ValidEmptyKernel::create(storage);
|
||||
|
||||
iOpenCL::SPatchDataParameterStream dataParameterStream = {};
|
||||
src.tokens.dataParameterStream = &dataParameterStream;
|
||||
dataParameterStream.DataParameterStreamSize = 256U;
|
||||
|
||||
NEO::DeviceInfoKernelPayloadConstants deviceInfoConstants;
|
||||
deviceInfoConstants.computeUnitsUsedForScratch = 128U;
|
||||
deviceInfoConstants.maxWorkGroupSize = 64U;
|
||||
std::unique_ptr<uint8_t> slm = std::make_unique<uint8_t>();
|
||||
deviceInfoConstants.slmWindow = slm.get();
|
||||
deviceInfoConstants.slmWindowSize = 512U;
|
||||
|
||||
iOpenCL::SPatchAllocateStatelessPrivateSurface privateSurface = {};
|
||||
privateSurface.PerThreadPrivateMemorySize = 8U;
|
||||
src.tokens.allocateStatelessPrivateSurface = &privateSurface;
|
||||
|
||||
iOpenCL::SPatchDataParameterBuffer privateMemorySize = {};
|
||||
privateMemorySize.Offset = 8U;
|
||||
src.tokens.crossThreadPayloadArgs.privateMemoryStatelessSize = &privateMemorySize;
|
||||
|
||||
iOpenCL::SPatchDataParameterBuffer localMemoryWindowStartVA = {};
|
||||
localMemoryWindowStartVA.Offset = 16U;
|
||||
src.tokens.crossThreadPayloadArgs.localMemoryStatelessWindowStartAddress = &localMemoryWindowStartVA;
|
||||
|
||||
iOpenCL::SPatchDataParameterBuffer localMemoryWindowsSize = {};
|
||||
localMemoryWindowsSize.Offset = 24U;
|
||||
src.tokens.crossThreadPayloadArgs.localMemoryStatelessWindowSize = &localMemoryWindowsSize;
|
||||
|
||||
iOpenCL::SPatchDataParameterBuffer maxWorkgroupSize = {};
|
||||
maxWorkgroupSize.Offset = 32U;
|
||||
src.tokens.crossThreadPayloadArgs.maxWorkGroupSize = &maxWorkgroupSize;
|
||||
|
||||
NEO::KernelInfo dst;
|
||||
NEO::populateKernelInfo(dst, src, 4);
|
||||
ASSERT_NE(nullptr, dst.crossThreadData);
|
||||
dst.apply(deviceInfoConstants);
|
||||
uint32_t expectedPrivateMemorySize = privateSurface.PerThreadPrivateMemorySize * deviceInfoConstants.computeUnitsUsedForScratch * src.tokens.executionEnvironment->LargestCompiledSIMDSize;
|
||||
EXPECT_EQ(expectedPrivateMemorySize, *reinterpret_cast<uint32_t *>(dst.crossThreadData + privateMemorySize.Offset));
|
||||
EXPECT_EQ(deviceInfoConstants.slmWindowSize, *reinterpret_cast<uint32_t *>(dst.crossThreadData + localMemoryWindowsSize.Offset));
|
||||
EXPECT_EQ(deviceInfoConstants.maxWorkGroupSize, *reinterpret_cast<uint32_t *>(dst.crossThreadData + maxWorkgroupSize.Offset));
|
||||
EXPECT_EQ(reinterpret_cast<uintptr_t>(deviceInfoConstants.slmWindow), *reinterpret_cast<uintptr_t *>(dst.crossThreadData + localMemoryWindowStartVA.Offset));
|
||||
}
|
||||
|
||||
TEST(KernelInfoFromPatchTokens, GivenDataParameterStreamWhenPrivateSurfaceIsNotAllocatedButPrivateSurfaceMemorySizePatchIsNeededThenPatchWithZero) {
|
||||
std::vector<uint8_t> storage;
|
||||
auto src = PatchTokensTestData::ValidEmptyKernel::create(storage);
|
||||
|
||||
iOpenCL::SPatchDataParameterStream dataParameterStream = {};
|
||||
src.tokens.dataParameterStream = &dataParameterStream;
|
||||
dataParameterStream.DataParameterStreamSize = 256U;
|
||||
|
||||
NEO::DeviceInfoKernelPayloadConstants deviceInfoConstants;
|
||||
deviceInfoConstants.computeUnitsUsedForScratch = 128U;
|
||||
deviceInfoConstants.maxWorkGroupSize = 64U;
|
||||
std::unique_ptr<uint8_t> slm = std::make_unique<uint8_t>();
|
||||
deviceInfoConstants.slmWindow = slm.get();
|
||||
deviceInfoConstants.slmWindowSize = 512U;
|
||||
|
||||
iOpenCL::SPatchDataParameterBuffer privateMemorySize = {};
|
||||
privateMemorySize.Offset = 8U;
|
||||
src.tokens.crossThreadPayloadArgs.privateMemoryStatelessSize = &privateMemorySize;
|
||||
|
||||
NEO::KernelInfo dst;
|
||||
NEO::populateKernelInfo(dst, src, 4);
|
||||
ASSERT_NE(nullptr, dst.crossThreadData);
|
||||
dst.apply(deviceInfoConstants);
|
||||
uint32_t expectedPrivateMemorySize = 0U;
|
||||
EXPECT_EQ(expectedPrivateMemorySize, *reinterpret_cast<uint32_t *>(dst.crossThreadData + privateMemorySize.Offset));
|
||||
}
|
||||
|
||||
TEST(KernelInfoFromPatchTokens, GivenKernelWithGtpinInfoTokenThenKernelInfoIsProperlyPopulated) {
|
||||
std::vector<uint8_t> storage;
|
||||
NEO::PatchTokenBinary::KernelFromPatchtokens kernelTokens = PatchTokensTestData::ValidEmptyKernel::create(storage);
|
||||
iOpenCL::SPatchItemHeader gtpinInfo = {};
|
||||
gtpinInfo.Token = iOpenCL::PATCH_TOKEN_GTPIN_INFO;
|
||||
gtpinInfo.Size = sizeof(iOpenCL::SPatchItemHeader);
|
||||
kernelTokens.tokens.gtpinInfo = >pinInfo;
|
||||
|
||||
NEO::KernelInfo kernelInfo = {};
|
||||
NEO::populateKernelInfo(kernelInfo, kernelTokens, sizeof(void *));
|
||||
EXPECT_NE(nullptr, kernelInfo.igcInfoForGtpin);
|
||||
}
|
||||
|
||||
TEST(KernelInfoFromPatchTokens, GivenKernelWithGlobalObjectArgThenKernelInfoIsProperlyPopulated) {
|
||||
std::vector<uint8_t> storage;
|
||||
NEO::PatchTokenBinary::KernelFromPatchtokens kernelTokens = PatchTokensTestData::ValidEmptyKernel::create(storage);
|
||||
|
||||
iOpenCL::SPatchGlobalMemoryObjectKernelArgument globalMemArg = {};
|
||||
globalMemArg.Token = iOpenCL::PATCH_TOKEN_GLOBAL_MEMORY_OBJECT_KERNEL_ARGUMENT;
|
||||
globalMemArg.Size = sizeof(iOpenCL::SPatchGlobalMemoryObjectKernelArgument);
|
||||
globalMemArg.ArgumentNumber = 1;
|
||||
globalMemArg.Offset = 0x40;
|
||||
|
||||
kernelTokens.tokens.kernelArgs.resize(2);
|
||||
kernelTokens.tokens.kernelArgs[1].objectArg = &globalMemArg;
|
||||
NEO::KernelInfo kernelInfo = {};
|
||||
NEO::populateKernelInfo(kernelInfo, kernelTokens, sizeof(void *));
|
||||
EXPECT_TRUE(kernelInfo.usesSsh);
|
||||
EXPECT_EQ(1U, kernelInfo.argumentsToPatchNum);
|
||||
ASSERT_EQ(2U, kernelInfo.kernelArgInfo.size());
|
||||
EXPECT_TRUE(kernelInfo.kernelArgInfo[1].isBuffer);
|
||||
ASSERT_EQ(1U, kernelInfo.kernelArgInfo[1].kernelArgPatchInfoVector.size());
|
||||
EXPECT_EQ(0U, kernelInfo.kernelArgInfo[1].kernelArgPatchInfoVector[0].crossthreadOffset);
|
||||
EXPECT_EQ(0U, kernelInfo.kernelArgInfo[1].kernelArgPatchInfoVector[0].sourceOffset);
|
||||
EXPECT_EQ(0U, kernelInfo.kernelArgInfo[1].kernelArgPatchInfoVector[0].size);
|
||||
EXPECT_EQ(globalMemArg.Offset, kernelInfo.kernelArgInfo[1].offsetHeap);
|
||||
}
|
||||
260
opencl/test/unit_test/program/kernel_info_tests.cpp
Normal file
260
opencl/test/unit_test/program/kernel_info_tests.cpp
Normal file
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "core/execution_environment/execution_environment.h"
|
||||
#include "opencl/source/memory_manager/os_agnostic_memory_manager.h"
|
||||
#include "opencl/source/program/kernel_arg_info.h"
|
||||
#include "opencl/source/program/kernel_info.h"
|
||||
|
||||
#include "fixtures/multi_root_device_fixture.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "mocks/mock_execution_environment.h"
|
||||
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
TEST(KernelInfo, KernelInfoHasCopyMoveAssingmentDisabled) {
|
||||
static_assert(false == std::is_move_constructible<KernelInfo>::value, "");
|
||||
static_assert(false == std::is_copy_constructible<KernelInfo>::value, "");
|
||||
static_assert(false == std::is_move_assignable<KernelInfo>::value, "");
|
||||
static_assert(false == std::is_copy_assignable<KernelInfo>::value, "");
|
||||
}
|
||||
|
||||
TEST(KernelInfo, whenDefaultConstructedThenUsesSshFlagIsNotSet) {
|
||||
KernelInfo kernelInfo;
|
||||
EXPECT_FALSE(kernelInfo.usesSsh);
|
||||
}
|
||||
|
||||
TEST(KernelInfo, decodeConstantMemoryKernelArgument) {
|
||||
uint32_t argumentNumber = 0;
|
||||
auto pKernelInfo = std::make_unique<KernelInfo>();
|
||||
SPatchStatelessConstantMemoryObjectKernelArgument arg;
|
||||
arg.Token = 0xa;
|
||||
arg.Size = 0x20;
|
||||
arg.ArgumentNumber = argumentNumber;
|
||||
arg.SurfaceStateHeapOffset = 0x30;
|
||||
arg.DataParamOffset = 0x40;
|
||||
arg.DataParamSize = 0x4;
|
||||
arg.LocationIndex = static_cast<uint32_t>(-1);
|
||||
arg.LocationIndex2 = static_cast<uint32_t>(-1);
|
||||
|
||||
pKernelInfo->storeKernelArgument(&arg);
|
||||
EXPECT_TRUE(pKernelInfo->usesSsh);
|
||||
|
||||
const auto &argInfo = pKernelInfo->kernelArgInfo[argumentNumber];
|
||||
EXPECT_EQ(arg.SurfaceStateHeapOffset, argInfo.offsetHeap);
|
||||
EXPECT_FALSE(argInfo.isImage);
|
||||
|
||||
const auto &patchInfo = pKernelInfo->patchInfo;
|
||||
EXPECT_EQ(1u, patchInfo.statelessGlobalMemObjKernelArgs.size());
|
||||
}
|
||||
|
||||
TEST(KernelInfo, decodeGlobalMemoryKernelArgument) {
|
||||
uint32_t argumentNumber = 1;
|
||||
auto pKernelInfo = std::make_unique<KernelInfo>();
|
||||
SPatchStatelessGlobalMemoryObjectKernelArgument arg;
|
||||
arg.Token = 0xb;
|
||||
arg.Size = 0x30;
|
||||
arg.ArgumentNumber = argumentNumber;
|
||||
arg.SurfaceStateHeapOffset = 0x40;
|
||||
arg.DataParamOffset = 050;
|
||||
arg.DataParamSize = 0x8;
|
||||
arg.LocationIndex = static_cast<uint32_t>(-1);
|
||||
arg.LocationIndex2 = static_cast<uint32_t>(-1);
|
||||
|
||||
pKernelInfo->storeKernelArgument(&arg);
|
||||
EXPECT_TRUE(pKernelInfo->usesSsh);
|
||||
|
||||
const auto &argInfo = pKernelInfo->kernelArgInfo[argumentNumber];
|
||||
EXPECT_EQ(arg.SurfaceStateHeapOffset, argInfo.offsetHeap);
|
||||
EXPECT_FALSE(argInfo.isImage);
|
||||
|
||||
const auto &patchInfo = pKernelInfo->patchInfo;
|
||||
EXPECT_EQ(1u, patchInfo.statelessGlobalMemObjKernelArgs.size());
|
||||
}
|
||||
|
||||
TEST(KernelInfo, decodeImageKernelArgument) {
|
||||
uint32_t argumentNumber = 1;
|
||||
auto pKernelInfo = std::make_unique<KernelInfo>();
|
||||
SPatchImageMemoryObjectKernelArgument arg;
|
||||
arg.Token = 0xc;
|
||||
arg.Size = 0x20;
|
||||
arg.ArgumentNumber = argumentNumber;
|
||||
arg.Type = 0x4;
|
||||
arg.Offset = 0x40;
|
||||
arg.LocationIndex = static_cast<uint32_t>(-1);
|
||||
arg.LocationIndex2 = static_cast<uint32_t>(-1);
|
||||
arg.Writeable = true;
|
||||
|
||||
pKernelInfo->storeKernelArgument(&arg);
|
||||
EXPECT_TRUE(pKernelInfo->usesSsh);
|
||||
|
||||
const auto &argInfo = pKernelInfo->kernelArgInfo[argumentNumber];
|
||||
EXPECT_EQ(sizeof(cl_mem), static_cast<size_t>(argInfo.metadata.argByValSize));
|
||||
EXPECT_EQ(arg.Offset, argInfo.offsetHeap);
|
||||
EXPECT_TRUE(argInfo.isImage);
|
||||
EXPECT_EQ(KernelArgMetadata::AccessQualifier::ReadWrite, argInfo.metadata.accessQualifier);
|
||||
EXPECT_TRUE(argInfo.metadata.typeQualifiers.empty());
|
||||
}
|
||||
|
||||
TEST(KernelInfoTest, givenKernelInfoWhenCreateKernelAllocationThenCopyWholeKernelHeapToKernelAllocation) {
|
||||
KernelInfo kernelInfo;
|
||||
MockExecutionEnvironment executionEnvironment(*platformDevices);
|
||||
OsAgnosticMemoryManager memoryManager(executionEnvironment);
|
||||
SKernelBinaryHeaderCommon kernelHeader;
|
||||
const size_t heapSize = 0x40;
|
||||
char heap[heapSize];
|
||||
kernelHeader.KernelHeapSize = heapSize;
|
||||
kernelInfo.heapInfo.pKernelHeader = &kernelHeader;
|
||||
kernelInfo.heapInfo.pKernelHeap = &heap;
|
||||
|
||||
for (size_t i = 0; i < heapSize; i++) {
|
||||
heap[i] = static_cast<char>(i);
|
||||
}
|
||||
|
||||
auto retVal = kernelInfo.createKernelAllocation(0, &memoryManager);
|
||||
EXPECT_TRUE(retVal);
|
||||
auto allocation = kernelInfo.kernelAllocation;
|
||||
EXPECT_EQ(0, memcmp(allocation->getUnderlyingBuffer(), heap, heapSize));
|
||||
EXPECT_EQ(heapSize, allocation->getUnderlyingBufferSize());
|
||||
memoryManager.checkGpuUsageAndDestroyGraphicsAllocations(allocation);
|
||||
}
|
||||
|
||||
class MyMemoryManager : public OsAgnosticMemoryManager {
|
||||
public:
|
||||
using OsAgnosticMemoryManager::OsAgnosticMemoryManager;
|
||||
GraphicsAllocation *allocate32BitGraphicsMemoryImpl(const AllocationData &allocationData) override { return nullptr; }
|
||||
};
|
||||
|
||||
TEST(KernelInfoTest, givenKernelInfoWhenCreateKernelAllocationAndCannotAllocateMemoryThenReturnsFalse) {
|
||||
KernelInfo kernelInfo;
|
||||
MockExecutionEnvironment executionEnvironment(*platformDevices);
|
||||
MyMemoryManager memoryManager(executionEnvironment);
|
||||
SKernelBinaryHeaderCommon kernelHeader;
|
||||
kernelInfo.heapInfo.pKernelHeader = &kernelHeader;
|
||||
auto retVal = kernelInfo.createKernelAllocation(0, &memoryManager);
|
||||
EXPECT_FALSE(retVal);
|
||||
}
|
||||
|
||||
TEST(KernelInfo, decodeGlobalMemObjectKernelArgument) {
|
||||
uint32_t argumentNumber = 1;
|
||||
auto pKernelInfo = std::make_unique<KernelInfo>();
|
||||
SPatchGlobalMemoryObjectKernelArgument arg;
|
||||
arg.Token = 0xb;
|
||||
arg.Size = 0x10;
|
||||
arg.ArgumentNumber = argumentNumber;
|
||||
arg.Offset = 0x40;
|
||||
arg.LocationIndex = static_cast<uint32_t>(-1);
|
||||
arg.LocationIndex2 = static_cast<uint32_t>(-1);
|
||||
|
||||
pKernelInfo->storeKernelArgument(&arg);
|
||||
EXPECT_TRUE(pKernelInfo->usesSsh);
|
||||
|
||||
const auto &argInfo = pKernelInfo->kernelArgInfo[argumentNumber];
|
||||
EXPECT_EQ(arg.Offset, argInfo.offsetHeap);
|
||||
EXPECT_TRUE(argInfo.isBuffer);
|
||||
}
|
||||
|
||||
TEST(KernelInfo, decodeSamplerKernelArgument) {
|
||||
uint32_t argumentNumber = 1;
|
||||
auto pKernelInfo = std::make_unique<KernelInfo>();
|
||||
SPatchSamplerKernelArgument arg;
|
||||
|
||||
arg.ArgumentNumber = argumentNumber;
|
||||
arg.Token = 0x10;
|
||||
arg.Size = 0x18;
|
||||
arg.LocationIndex = static_cast<uint32_t>(-1);
|
||||
arg.LocationIndex2 = static_cast<uint32_t>(-1);
|
||||
arg.Offset = 0x40;
|
||||
arg.Type = iOpenCL::SAMPLER_OBJECT_TEXTURE;
|
||||
|
||||
pKernelInfo->usesSsh = true;
|
||||
|
||||
pKernelInfo->storeKernelArgument(&arg);
|
||||
|
||||
const auto &argInfo = pKernelInfo->kernelArgInfo[argumentNumber];
|
||||
EXPECT_EQ(arg.Offset, argInfo.offsetHeap);
|
||||
EXPECT_FALSE(argInfo.isImage);
|
||||
EXPECT_TRUE(argInfo.isSampler);
|
||||
EXPECT_TRUE(pKernelInfo->usesSsh);
|
||||
}
|
||||
|
||||
TEST(KernelInfo, whenStoringArgInfoThenMetadataIsProperlyPopulated) {
|
||||
KernelInfo kernelInfo;
|
||||
NEO::ArgTypeMetadata metadata;
|
||||
metadata.accessQualifier = NEO::KernelArgMetadata::AccessQualifier::WriteOnly;
|
||||
metadata.addressQualifier = NEO::KernelArgMetadata::AddressSpaceQualifier::Global;
|
||||
metadata.argByValSize = sizeof(void *);
|
||||
metadata.typeQualifiers.pipeQual = true;
|
||||
auto metadataExtended = std::make_unique<NEO::ArgTypeMetadataExtended>();
|
||||
auto metadataExtendedPtr = metadataExtended.get();
|
||||
kernelInfo.storeArgInfo(2, metadata, std::move(metadataExtended));
|
||||
|
||||
ASSERT_EQ(3U, kernelInfo.kernelArgInfo.size());
|
||||
EXPECT_EQ(metadata.accessQualifier, kernelInfo.kernelArgInfo[2].metadata.accessQualifier);
|
||||
EXPECT_EQ(metadata.addressQualifier, kernelInfo.kernelArgInfo[2].metadata.addressQualifier);
|
||||
EXPECT_EQ(metadata.argByValSize, kernelInfo.kernelArgInfo[2].metadata.argByValSize);
|
||||
EXPECT_EQ(metadata.typeQualifiers.packed, kernelInfo.kernelArgInfo[2].metadata.typeQualifiers.packed);
|
||||
EXPECT_EQ(metadataExtendedPtr, kernelInfo.kernelArgInfo[2].metadataExtended.get());
|
||||
}
|
||||
|
||||
TEST(KernelInfo, givenKernelInfoWhenStoreTransformableArgThenArgInfoIsTransformable) {
|
||||
uint32_t argumentNumber = 1;
|
||||
auto kernelInfo = std::make_unique<KernelInfo>();
|
||||
SPatchImageMemoryObjectKernelArgument arg;
|
||||
arg.ArgumentNumber = argumentNumber;
|
||||
arg.Transformable = true;
|
||||
|
||||
kernelInfo->storeKernelArgument(&arg);
|
||||
const auto &argInfo = kernelInfo->kernelArgInfo[argumentNumber];
|
||||
EXPECT_TRUE(argInfo.isTransformable);
|
||||
}
|
||||
|
||||
TEST(KernelInfo, givenKernelInfoWhenStoreNonTransformableArgThenArgInfoIsNotTransformable) {
|
||||
uint32_t argumentNumber = 1;
|
||||
auto kernelInfo = std::make_unique<KernelInfo>();
|
||||
SPatchImageMemoryObjectKernelArgument arg;
|
||||
arg.ArgumentNumber = argumentNumber;
|
||||
arg.Transformable = false;
|
||||
|
||||
kernelInfo->storeKernelArgument(&arg);
|
||||
const auto &argInfo = kernelInfo->kernelArgInfo[argumentNumber];
|
||||
EXPECT_FALSE(argInfo.isTransformable);
|
||||
}
|
||||
|
||||
using KernelInfoMultiRootDeviceTests = MultiRootDeviceFixture;
|
||||
|
||||
TEST_F(KernelInfoMultiRootDeviceTests, kernelAllocationHasCorrectRootDeviceIndex) {
|
||||
KernelInfo kernelInfo;
|
||||
SKernelBinaryHeaderCommon kernelHeader;
|
||||
const size_t heapSize = 0x40;
|
||||
char heap[heapSize];
|
||||
kernelHeader.KernelHeapSize = heapSize;
|
||||
kernelInfo.heapInfo.pKernelHeader = &kernelHeader;
|
||||
kernelInfo.heapInfo.pKernelHeap = &heap;
|
||||
|
||||
auto retVal = kernelInfo.createKernelAllocation(expectedRootDeviceIndex, mockMemoryManager);
|
||||
EXPECT_TRUE(retVal);
|
||||
auto allocation = kernelInfo.kernelAllocation;
|
||||
ASSERT_NE(nullptr, allocation);
|
||||
EXPECT_EQ(expectedRootDeviceIndex, allocation->getRootDeviceIndex());
|
||||
mockMemoryManager->checkGpuUsageAndDestroyGraphicsAllocations(allocation);
|
||||
}
|
||||
|
||||
TEST(KernelInfo, whenGetKernelNamesStringIsCalledThenNamesAreProperlyConcatenated) {
|
||||
ExecutionEnvironment execEnv;
|
||||
KernelInfo kernel1 = {};
|
||||
kernel1.name = "kern1";
|
||||
KernelInfo kernel2 = {};
|
||||
kernel2.name = "kern2";
|
||||
std::vector<KernelInfo *> kernelInfoArray;
|
||||
kernelInfoArray.push_back(&kernel1);
|
||||
kernelInfoArray.push_back(&kernel2);
|
||||
EXPECT_STREQ("kern1;kern2", concatenateKernelNames(kernelInfoArray).c_str());
|
||||
}
|
||||
184
opencl/test/unit_test/program/printf_handler_tests.cpp
Normal file
184
opencl/test/unit_test/program/printf_handler_tests.cpp
Normal file
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "opencl/source/program/printf_handler.h"
|
||||
|
||||
#include "fixtures/device_fixture.h"
|
||||
#include "fixtures/multi_root_device_fixture.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "mocks/mock_context.h"
|
||||
#include "mocks/mock_device.h"
|
||||
#include "mocks/mock_graphics_allocation.h"
|
||||
#include "mocks/mock_kernel.h"
|
||||
#include "mocks/mock_mdi.h"
|
||||
#include "mocks/mock_program.h"
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
TEST(PrintfHandlerTest, givenNotPreparedPrintfHandlerWhenGetSurfaceIsCalledThenResultIsNullptr) {
|
||||
MockClDevice *device = new MockClDevice{MockDevice::createWithNewExecutionEnvironment<MockDevice>(nullptr)};
|
||||
MockContext context;
|
||||
SPatchAllocateStatelessPrintfSurface *pPrintfSurface = new SPatchAllocateStatelessPrintfSurface();
|
||||
pPrintfSurface->DataParamOffset = 0;
|
||||
pPrintfSurface->DataParamSize = 8;
|
||||
|
||||
auto pKernelInfo = std::make_unique<KernelInfo>();
|
||||
pKernelInfo->patchInfo.pAllocateStatelessPrintfSurface = pPrintfSurface;
|
||||
|
||||
MockProgram *pProgram = new MockProgram(*device->getExecutionEnvironment(), &context, false, &device->getDevice());
|
||||
MockKernel *pKernel = new MockKernel(pProgram, *pKernelInfo, *device);
|
||||
|
||||
MockMultiDispatchInfo multiDispatchInfo(pKernel);
|
||||
PrintfHandler *printfHandler = PrintfHandler::create(multiDispatchInfo, *device);
|
||||
|
||||
EXPECT_EQ(nullptr, printfHandler->getSurface());
|
||||
|
||||
delete printfHandler;
|
||||
delete pPrintfSurface;
|
||||
delete pKernel;
|
||||
|
||||
delete pProgram;
|
||||
delete device;
|
||||
}
|
||||
|
||||
TEST(PrintfHandlerTest, givenPreparedPrintfHandlerWhenGetSurfaceIsCalledThenResultIsNullptr) {
|
||||
MockClDevice *device = new MockClDevice{MockDevice::createWithNewExecutionEnvironment<MockDevice>(nullptr)};
|
||||
MockContext context;
|
||||
SPatchAllocateStatelessPrintfSurface *pPrintfSurface = new SPatchAllocateStatelessPrintfSurface();
|
||||
pPrintfSurface->DataParamOffset = 0;
|
||||
pPrintfSurface->DataParamSize = 8;
|
||||
|
||||
auto pKernelInfo = std::make_unique<KernelInfo>();
|
||||
pKernelInfo->patchInfo.pAllocateStatelessPrintfSurface = pPrintfSurface;
|
||||
|
||||
MockProgram *pProgram = new MockProgram(*device->getExecutionEnvironment(), &context, false, &device->getDevice());
|
||||
|
||||
uint64_t crossThread[10];
|
||||
MockKernel *pKernel = new MockKernel(pProgram, *pKernelInfo, *device);
|
||||
pKernel->setCrossThreadData(&crossThread, sizeof(uint64_t) * 8);
|
||||
|
||||
MockMultiDispatchInfo multiDispatchInfo(pKernel);
|
||||
PrintfHandler *printfHandler = PrintfHandler::create(multiDispatchInfo, *device);
|
||||
printfHandler->prepareDispatch(multiDispatchInfo);
|
||||
EXPECT_NE(nullptr, printfHandler->getSurface());
|
||||
|
||||
delete printfHandler;
|
||||
delete pPrintfSurface;
|
||||
delete pKernel;
|
||||
|
||||
delete pProgram;
|
||||
delete device;
|
||||
}
|
||||
|
||||
TEST(PrintfHandlerTest, givenParentKernelWihoutPrintfAndBlockKernelWithPrintfWhenPrintfHandlerCreateCalledThenResaultIsAnObject) {
|
||||
|
||||
auto device = std::make_unique<MockClDevice>(MockDevice::createWithNewExecutionEnvironment<MockDevice>(nullptr));
|
||||
MockContext context(device.get());
|
||||
std::unique_ptr<MockParentKernel> parentKernelWithoutPrintf(MockParentKernel::create(context, false, false, false, false));
|
||||
|
||||
MockMultiDispatchInfo multiDispatchInfo(parentKernelWithoutPrintf.get());
|
||||
|
||||
std::unique_ptr<PrintfHandler> printfHandler(PrintfHandler::create(multiDispatchInfo, *device));
|
||||
|
||||
ASSERT_NE(nullptr, printfHandler.get());
|
||||
}
|
||||
|
||||
TEST(PrintfHandlerTest, givenParentKernelAndBlockKernelWithoutPrintfWhenPrintfHandlerCreateCalledThenResaultIsNullptr) {
|
||||
|
||||
auto device = std::make_unique<MockClDevice>(MockDevice::createWithNewExecutionEnvironment<MockDevice>(nullptr));
|
||||
MockContext context(device.get());
|
||||
std::unique_ptr<MockParentKernel> blockKernelWithoutPrintf(MockParentKernel::create(context, false, false, false, false, false));
|
||||
|
||||
MockMultiDispatchInfo multiDispatchInfo(blockKernelWithoutPrintf.get());
|
||||
|
||||
std::unique_ptr<PrintfHandler> printfHandler(PrintfHandler::create(multiDispatchInfo, *device));
|
||||
|
||||
ASSERT_EQ(nullptr, printfHandler.get());
|
||||
}
|
||||
TEST(PrintfHandlerTest, givenParentKernelWithPrintfAndBlockKernelWithoutPrintfWhenPrintfHandlerCreateCalledThenResaultIsAnObject) {
|
||||
|
||||
auto device = std::make_unique<MockClDevice>(MockDevice::createWithNewExecutionEnvironment<MockDevice>(nullptr));
|
||||
MockContext context(device.get());
|
||||
std::unique_ptr<MockParentKernel> parentKernelWithPrintfBlockKernelWithoutPrintf(MockParentKernel::create(context, false, false, false, true, false));
|
||||
|
||||
MockMultiDispatchInfo multiDispatchInfo(parentKernelWithPrintfBlockKernelWithoutPrintf.get());
|
||||
|
||||
std::unique_ptr<PrintfHandler> printfHandler(PrintfHandler::create(multiDispatchInfo, *device));
|
||||
|
||||
ASSERT_NE(nullptr, printfHandler);
|
||||
}
|
||||
|
||||
TEST(PrintfHandlerTest, givenMultiDispatchInfoWithMultipleKernelsWhenCreatingAndDispatchingPrintfHandlerThenPickMainKernel) {
|
||||
MockContext context;
|
||||
auto device = std::make_unique<MockClDevice>(MockDevice::createWithNewExecutionEnvironment<MockDevice>(nullptr));
|
||||
auto program = std::make_unique<MockProgram>(*device->getExecutionEnvironment(), &context, false, &device->getDevice());
|
||||
auto mainKernelInfo = std::make_unique<KernelInfo>();
|
||||
auto kernelInfo = std::make_unique<KernelInfo>();
|
||||
|
||||
auto printfSurface = std::make_unique<SPatchAllocateStatelessPrintfSurface>();
|
||||
printfSurface->DataParamOffset = 0;
|
||||
printfSurface->DataParamSize = 8;
|
||||
|
||||
mainKernelInfo->patchInfo.pAllocateStatelessPrintfSurface = printfSurface.get();
|
||||
|
||||
uint64_t crossThread[8];
|
||||
auto mainKernel = std::make_unique<MockKernel>(program.get(), *mainKernelInfo, *device);
|
||||
auto kernel1 = std::make_unique<MockKernel>(program.get(), *kernelInfo, *device);
|
||||
auto kernel2 = std::make_unique<MockKernel>(program.get(), *kernelInfo, *device);
|
||||
mainKernel->setCrossThreadData(&crossThread, sizeof(uint64_t) * 8);
|
||||
|
||||
DispatchInfo mainDispatchInfo(mainKernel.get(), 1, {1, 1, 1}, {1, 1, 1}, {1, 1, 1});
|
||||
DispatchInfo dispatchInfo1(kernel1.get(), 1, {1, 1, 1}, {1, 1, 1}, {1, 1, 1});
|
||||
DispatchInfo dispatchInfo2(kernel2.get(), 1, {1, 1, 1}, {1, 1, 1}, {1, 1, 1});
|
||||
|
||||
MultiDispatchInfo multiDispatchInfo(mainKernel.get());
|
||||
multiDispatchInfo.push(dispatchInfo1);
|
||||
multiDispatchInfo.push(mainDispatchInfo);
|
||||
multiDispatchInfo.push(dispatchInfo2);
|
||||
|
||||
std::unique_ptr<PrintfHandler> printfHandler(PrintfHandler::create(multiDispatchInfo, *device));
|
||||
ASSERT_NE(nullptr, printfHandler.get());
|
||||
|
||||
printfHandler->prepareDispatch(multiDispatchInfo);
|
||||
EXPECT_NE(nullptr, printfHandler->getSurface());
|
||||
}
|
||||
|
||||
TEST(PrintfHandlerTest, GivenEmptyMultiDispatchInfoWhenCreatingPrintfHandlerThenPrintfHandlerIsNotCreated) {
|
||||
MockClDevice device{new MockDevice};
|
||||
MockKernelWithInternals mockKernelWithInternals{device};
|
||||
MockMultiDispatchInfo multiDispatchInfo{mockKernelWithInternals.mockKernel};
|
||||
multiDispatchInfo.dispatchInfos.resize(0);
|
||||
EXPECT_EQ(nullptr, multiDispatchInfo.peekMainKernel());
|
||||
|
||||
auto printfHandler = PrintfHandler::create(multiDispatchInfo, device);
|
||||
EXPECT_EQ(nullptr, printfHandler);
|
||||
}
|
||||
|
||||
using PrintfHandlerMultiRootDeviceTests = MultiRootDeviceFixture;
|
||||
|
||||
TEST_F(PrintfHandlerMultiRootDeviceTests, printfSurfaceHasCorrectRootDeviceIndex) {
|
||||
auto printfSurface = std::make_unique<SPatchAllocateStatelessPrintfSurface>();
|
||||
printfSurface->DataParamOffset = 0;
|
||||
printfSurface->DataParamSize = 8;
|
||||
|
||||
auto kernelInfo = std::make_unique<KernelInfo>();
|
||||
kernelInfo->patchInfo.pAllocateStatelessPrintfSurface = printfSurface.get();
|
||||
|
||||
auto program = std::make_unique<MockProgram>(*device->getExecutionEnvironment(), context.get(), false, &device->getDevice());
|
||||
|
||||
uint64_t crossThread[10];
|
||||
auto kernel = std::make_unique<MockKernel>(program.get(), *kernelInfo, *device);
|
||||
kernel->setCrossThreadData(&crossThread, sizeof(uint64_t) * 8);
|
||||
|
||||
MockMultiDispatchInfo multiDispatchInfo(kernel.get());
|
||||
std::unique_ptr<PrintfHandler> printfHandler(PrintfHandler::create(multiDispatchInfo, *device));
|
||||
printfHandler->prepareDispatch(multiDispatchInfo);
|
||||
auto surface = printfHandler->getSurface();
|
||||
|
||||
ASSERT_NE(nullptr, surface);
|
||||
EXPECT_EQ(expectedRootDeviceIndex, surface->getRootDeviceIndex());
|
||||
}
|
||||
837
opencl/test/unit_test/program/printf_helper_tests.cpp
Normal file
837
opencl/test/unit_test/program/printf_helper_tests.cpp
Normal file
@@ -0,0 +1,837 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "core/helpers/aligned_memory.h"
|
||||
#include "core/helpers/string.h"
|
||||
#include "core/program/print_formatter.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "mocks/mock_device.h"
|
||||
#include "mocks/mock_graphics_allocation.h"
|
||||
#include "mocks/mock_kernel.h"
|
||||
#include "mocks/mock_program.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
using namespace NEO;
|
||||
using namespace iOpenCL;
|
||||
|
||||
// -------------------- Base Fixture ------------------------
|
||||
class PrintFormatterTest : public testing::Test {
|
||||
public:
|
||||
std::unique_ptr<PrintFormatter> printFormatter;
|
||||
|
||||
std::string format;
|
||||
uint8_t buffer;
|
||||
|
||||
MockGraphicsAllocation *data;
|
||||
MockKernel *kernel;
|
||||
std::unique_ptr<MockProgram> program;
|
||||
std::unique_ptr<KernelInfo> kernelInfo;
|
||||
ClDevice *device;
|
||||
|
||||
uint8_t underlyingBuffer[PrintFormatter::maxPrintfOutputLength];
|
||||
uint32_t offset;
|
||||
|
||||
int maxStringIndex;
|
||||
|
||||
protected:
|
||||
void SetUp() override {
|
||||
offset = 4;
|
||||
maxStringIndex = 0;
|
||||
data = new MockGraphicsAllocation(underlyingBuffer, PrintFormatter::maxPrintfOutputLength);
|
||||
|
||||
kernelInfo = std::make_unique<KernelInfo>();
|
||||
device = new MockClDevice{MockDevice::createWithNewExecutionEnvironment<MockDevice>(nullptr)};
|
||||
program = std::make_unique<MockProgram>(*device->getExecutionEnvironment());
|
||||
kernel = new MockKernel(program.get(), *kernelInfo, *device);
|
||||
|
||||
printFormatter = std::unique_ptr<PrintFormatter>(new PrintFormatter(static_cast<uint8_t *>(data->getUnderlyingBuffer()), PrintFormatter::maxPrintfOutputLength, is32bit, kernelInfo->patchInfo.stringDataMap));
|
||||
|
||||
underlyingBuffer[0] = 0;
|
||||
underlyingBuffer[1] = 0;
|
||||
underlyingBuffer[2] = 0;
|
||||
underlyingBuffer[3] = 0;
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
delete data;
|
||||
delete kernel;
|
||||
delete device;
|
||||
}
|
||||
|
||||
enum class PRINTF_DATA_TYPE : int {
|
||||
INVALID,
|
||||
BYTE,
|
||||
SHORT,
|
||||
INT,
|
||||
FLOAT,
|
||||
STRING,
|
||||
LONG,
|
||||
POINTER,
|
||||
DOUBLE,
|
||||
VECTOR_BYTE,
|
||||
VECTOR_SHORT,
|
||||
VECTOR_INT,
|
||||
VECTOR_LONG,
|
||||
VECTOR_FLOAT,
|
||||
VECTOR_DOUBLE
|
||||
};
|
||||
|
||||
PRINTF_DATA_TYPE getPrintfDataType(int8_t value) { return PRINTF_DATA_TYPE::BYTE; };
|
||||
PRINTF_DATA_TYPE getPrintfDataType(uint8_t value) { return PRINTF_DATA_TYPE::BYTE; };
|
||||
PRINTF_DATA_TYPE getPrintfDataType(int16_t value) { return PRINTF_DATA_TYPE::SHORT; };
|
||||
PRINTF_DATA_TYPE getPrintfDataType(uint16_t value) { return PRINTF_DATA_TYPE::SHORT; };
|
||||
PRINTF_DATA_TYPE getPrintfDataType(int32_t value) { return PRINTF_DATA_TYPE::INT; };
|
||||
PRINTF_DATA_TYPE getPrintfDataType(uint32_t value) { return PRINTF_DATA_TYPE::INT; };
|
||||
PRINTF_DATA_TYPE getPrintfDataType(int64_t value) { return PRINTF_DATA_TYPE::LONG; };
|
||||
PRINTF_DATA_TYPE getPrintfDataType(uint64_t value) { return PRINTF_DATA_TYPE::LONG; };
|
||||
PRINTF_DATA_TYPE getPrintfDataType(float value) { return PRINTF_DATA_TYPE::FLOAT; };
|
||||
PRINTF_DATA_TYPE getPrintfDataType(double value) { return PRINTF_DATA_TYPE::DOUBLE; };
|
||||
PRINTF_DATA_TYPE getPrintfDataType(char *value) { return PRINTF_DATA_TYPE::STRING; };
|
||||
|
||||
template <class T>
|
||||
void injectValue(T value) {
|
||||
storeData(getPrintfDataType(value));
|
||||
storeData(value);
|
||||
}
|
||||
|
||||
void injectStringValue(int value) {
|
||||
storeData(PRINTF_DATA_TYPE::STRING);
|
||||
storeData(value);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void storeData(T value) {
|
||||
T *valuePointer = reinterpret_cast<T *>(underlyingBuffer + offset);
|
||||
|
||||
if (isAligned(valuePointer))
|
||||
*valuePointer = value;
|
||||
else {
|
||||
memcpy_s(valuePointer, sizeof(underlyingBuffer) - offset, &value, sizeof(T));
|
||||
}
|
||||
|
||||
offset += sizeof(T);
|
||||
|
||||
// first four bytes always store the size
|
||||
uint32_t *pointer = reinterpret_cast<uint32_t *>(underlyingBuffer);
|
||||
*pointer = offset;
|
||||
}
|
||||
|
||||
int injectFormatString(std::string str) {
|
||||
size_t strSize = str.length() + 1;
|
||||
|
||||
SPatchString printfString;
|
||||
printfString.Token = PATCH_TOKEN_STRING;
|
||||
printfString.Size = static_cast<uint32_t>(sizeof(SPatchString) + strSize);
|
||||
|
||||
printfString.Index = maxStringIndex++;
|
||||
printfString.StringSize = static_cast<uint32_t>(strSize);
|
||||
|
||||
cl_char *pPrintfString = new cl_char[printfString.Size];
|
||||
memcpy_s(pPrintfString, sizeof(SPatchString), &printfString, sizeof(SPatchString));
|
||||
memcpy_s((cl_char *)pPrintfString + sizeof(printfString), strSize, str.c_str(), strSize);
|
||||
|
||||
kernelInfo->storePatchToken(reinterpret_cast<SPatchString *>(pPrintfString));
|
||||
|
||||
delete[] pPrintfString;
|
||||
return printfString.Index;
|
||||
}
|
||||
};
|
||||
|
||||
// for tests printing a single value
|
||||
template <class T>
|
||||
struct SingleValueTestParam {
|
||||
std::string format;
|
||||
T value;
|
||||
};
|
||||
|
||||
typedef SingleValueTestParam<int8_t> Int8Params;
|
||||
typedef SingleValueTestParam<uint8_t> Uint8Params;
|
||||
typedef SingleValueTestParam<int16_t> Int16Params;
|
||||
typedef SingleValueTestParam<uint16_t> Uint16Params;
|
||||
typedef SingleValueTestParam<int32_t> Int32Params;
|
||||
typedef SingleValueTestParam<uint32_t> Uint32Params;
|
||||
typedef SingleValueTestParam<int64_t> Int64Params;
|
||||
typedef SingleValueTestParam<uint64_t> Uint64Params;
|
||||
typedef SingleValueTestParam<float> FloatParams;
|
||||
typedef SingleValueTestParam<double> DoubleParams;
|
||||
typedef SingleValueTestParam<std::string> StringParams;
|
||||
|
||||
Int8Params byteValues[] = {
|
||||
{"%c", 'a'},
|
||||
};
|
||||
|
||||
class PrintfInt8Test : public PrintFormatterTest,
|
||||
public ::testing::WithParamInterface<Int8Params> {};
|
||||
|
||||
TEST_P(PrintfInt8Test, GivenPrintfFormatWhenConatinsIntThenInstertValueIntoString) {
|
||||
auto input = GetParam();
|
||||
|
||||
auto stringIndex = injectFormatString(input.format);
|
||||
storeData(stringIndex);
|
||||
injectValue(input.value);
|
||||
|
||||
char referenceOutput[PrintFormatter::maxPrintfOutputLength];
|
||||
char actualOutput[PrintFormatter::maxPrintfOutputLength];
|
||||
|
||||
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, PrintFormatter::maxPrintfOutputLength, str, PrintFormatter::maxPrintfOutputLength); });
|
||||
|
||||
snprintf(referenceOutput, sizeof(referenceOutput), input.format.c_str(), input.value);
|
||||
|
||||
EXPECT_STREQ(referenceOutput, actualOutput);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(PrintfInt8Test,
|
||||
PrintfInt8Test,
|
||||
::testing::ValuesIn(byteValues));
|
||||
|
||||
Int32Params intValues[] = {
|
||||
{"%d", 0},
|
||||
{"%d", 1},
|
||||
{"%d", -1},
|
||||
{"%d", INT32_MAX},
|
||||
{"%d", INT32_MIN},
|
||||
{"%5d", 10},
|
||||
{"%-5d", 10},
|
||||
{"%05d", 10},
|
||||
{"%+5d", 10},
|
||||
{"%-+5d", 10},
|
||||
{"%.5i", 100},
|
||||
{"%6.5i", 100},
|
||||
{"%-06i", 100},
|
||||
{"%06.5i", 100}};
|
||||
|
||||
class PrintfInt32Test : public PrintFormatterTest,
|
||||
public ::testing::WithParamInterface<Int32Params> {};
|
||||
|
||||
TEST_P(PrintfInt32Test, GivenPrintfFormatWhenConatinsIntThenInstertValueIntoString) {
|
||||
auto input = GetParam();
|
||||
|
||||
auto stringIndex = injectFormatString(input.format);
|
||||
storeData(stringIndex);
|
||||
injectValue(input.value);
|
||||
|
||||
char referenceOutput[PrintFormatter::maxPrintfOutputLength];
|
||||
char actualOutput[PrintFormatter::maxPrintfOutputLength];
|
||||
|
||||
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, PrintFormatter::maxPrintfOutputLength, str, PrintFormatter::maxPrintfOutputLength); });
|
||||
|
||||
snprintf(referenceOutput, sizeof(referenceOutput), input.format.c_str(), input.value);
|
||||
|
||||
EXPECT_STREQ(referenceOutput, actualOutput);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(PrintfInt32Test,
|
||||
PrintfInt32Test,
|
||||
::testing::ValuesIn(intValues));
|
||||
|
||||
Uint32Params uintValues[] = {
|
||||
{"%u", 0},
|
||||
{"%u", 1},
|
||||
{"%u", UINT32_MAX},
|
||||
{"%.0u", 0},
|
||||
// octal
|
||||
{"%o", 10},
|
||||
{"%.5o", 10},
|
||||
{"%#o", 100000000},
|
||||
{"%04.5o", 10},
|
||||
// hexadecimal
|
||||
{"%#x", 0xABCDEF},
|
||||
{"%#X", 0xABCDEF},
|
||||
{"%#X", 0},
|
||||
{"%8x", 399},
|
||||
{"%04x", 399}};
|
||||
|
||||
class PrintfUint32Test : public PrintFormatterTest,
|
||||
public ::testing::WithParamInterface<Uint32Params> {};
|
||||
|
||||
TEST_P(PrintfUint32Test, GivenPrintfFormatWhenConatinsUintThenInstertValueIntoString) {
|
||||
auto input = GetParam();
|
||||
|
||||
auto stringIndex = injectFormatString(input.format);
|
||||
storeData(stringIndex);
|
||||
injectValue(input.value);
|
||||
|
||||
char referenceOutput[PrintFormatter::maxPrintfOutputLength];
|
||||
char actualOutput[PrintFormatter::maxPrintfOutputLength];
|
||||
|
||||
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, PrintFormatter::maxPrintfOutputLength, str, PrintFormatter::maxPrintfOutputLength); });
|
||||
|
||||
snprintf(referenceOutput, sizeof(referenceOutput), input.format.c_str(), input.value);
|
||||
|
||||
EXPECT_STREQ(referenceOutput, actualOutput);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(PrintfUint32Test,
|
||||
PrintfUint32Test,
|
||||
::testing::ValuesIn(uintValues));
|
||||
|
||||
FloatParams floatValues[] = {
|
||||
{"%f", 10.3456f},
|
||||
{"%.1f", 10.3456f},
|
||||
{"%.2f", 10.3456f},
|
||||
{"%8.3f", 10.3456f},
|
||||
{"%08.2f", 10.3456f},
|
||||
{"%-8.2f", 10.3456f},
|
||||
{"%+8.2f", -10.3456f},
|
||||
{"%.0f", 0.1f},
|
||||
{"%.0f", 0.6f},
|
||||
{"%0f", 0.6f},
|
||||
};
|
||||
|
||||
class PrintfFloatTest : public PrintFormatterTest,
|
||||
public ::testing::WithParamInterface<FloatParams> {};
|
||||
|
||||
TEST_P(PrintfFloatTest, GivenPrintfFormatWhenConatinsFloatThenInstertValueIntoString) {
|
||||
auto input = GetParam();
|
||||
|
||||
auto stringIndex = injectFormatString(input.format);
|
||||
storeData(stringIndex);
|
||||
injectValue(input.value);
|
||||
|
||||
char referenceOutput[PrintFormatter::maxPrintfOutputLength];
|
||||
char actualOutput[PrintFormatter::maxPrintfOutputLength];
|
||||
|
||||
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, PrintFormatter::maxPrintfOutputLength, str, PrintFormatter::maxPrintfOutputLength); });
|
||||
|
||||
snprintf(referenceOutput, sizeof(referenceOutput), input.format.c_str(), input.value);
|
||||
|
||||
EXPECT_STREQ(referenceOutput, actualOutput);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(PrintfFloatTest,
|
||||
PrintfFloatTest,
|
||||
::testing::ValuesIn(floatValues));
|
||||
|
||||
class PrintfDoubleToFloatTest : public PrintFormatterTest,
|
||||
public ::testing::WithParamInterface<DoubleParams> {};
|
||||
|
||||
DoubleParams doubleToFloatValues[] = {
|
||||
{"%f", 10.3456},
|
||||
{"%.1f", 10.3456},
|
||||
{"%.2f", 10.3456},
|
||||
{"%8.3f", 10.3456},
|
||||
{"%08.2f", 10.3456},
|
||||
{"%-8.2f", 10.3456},
|
||||
{"%+8.2f", -10.3456},
|
||||
{"%.0f", 0.1},
|
||||
{"%0f", 0.6},
|
||||
{"%4g", 12345.6789},
|
||||
{"%4.2g", 12345.6789},
|
||||
{"%4G", 0.0000023},
|
||||
{"%4G", 0.023},
|
||||
{"%-#20.15e", 19456120.0},
|
||||
{"%+#21.15E", 19456120.0},
|
||||
{"%.6a", 0.1},
|
||||
{"%10.2a", 9990.235}};
|
||||
|
||||
TEST_P(PrintfDoubleToFloatTest, GivenPrintfFormatWhenConatinsFloatFormatAndDoubleValueThenInstertValueIntoString) {
|
||||
auto input = GetParam();
|
||||
|
||||
auto stringIndex = injectFormatString(input.format);
|
||||
storeData(stringIndex);
|
||||
injectValue(input.value);
|
||||
|
||||
char referenceOutput[PrintFormatter::maxPrintfOutputLength];
|
||||
char actualOutput[PrintFormatter::maxPrintfOutputLength];
|
||||
|
||||
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, PrintFormatter::maxPrintfOutputLength, str, PrintFormatter::maxPrintfOutputLength); });
|
||||
|
||||
snprintf(referenceOutput, sizeof(referenceOutput), input.format.c_str(), input.value);
|
||||
|
||||
EXPECT_STREQ(referenceOutput, actualOutput);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(PrintfDoubleToFloatTest,
|
||||
PrintfDoubleToFloatTest,
|
||||
::testing::ValuesIn(doubleToFloatValues));
|
||||
|
||||
DoubleParams doubleValues[] = {
|
||||
{"%f", 302230.12156260},
|
||||
{"%+f", 2937289102.1562},
|
||||
{"% #F", (double)-1254},
|
||||
{"%6.2f", 0.1562},
|
||||
{"%06.2f", -0.1562},
|
||||
{"%e", 0.1562},
|
||||
{"%E", -1254.0001001},
|
||||
{"%+.10e", 0.1562000102241},
|
||||
{"% E", (double)1254},
|
||||
{"%10.2e", 100230.1562},
|
||||
{"%g", 74010.00001562},
|
||||
{"%G", -1254.0001001},
|
||||
{"%+g", 325001.00001562},
|
||||
{"%+#G", -1254.0001001},
|
||||
{"%8.2g", 19.844},
|
||||
{"%1.5G", -1.1},
|
||||
{"%.13a", 1890.00001562},
|
||||
{"%.13A", -1254.0001001},
|
||||
};
|
||||
|
||||
class PrintfDoubleTest : public PrintFormatterTest,
|
||||
public ::testing::WithParamInterface<DoubleParams> {};
|
||||
|
||||
TEST_P(PrintfDoubleTest, GivenPrintfFormatWhenConatinsDoubleThenInstertValueIntoString) {
|
||||
auto input = GetParam();
|
||||
|
||||
auto stringIndex = injectFormatString(input.format);
|
||||
storeData(stringIndex);
|
||||
injectValue(input.value);
|
||||
|
||||
char referenceOutput[PrintFormatter::maxPrintfOutputLength];
|
||||
char actualOutput[PrintFormatter::maxPrintfOutputLength];
|
||||
|
||||
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, PrintFormatter::maxPrintfOutputLength, str, PrintFormatter::maxPrintfOutputLength); });
|
||||
|
||||
if (input.format[input.format.length() - 1] == 'F')
|
||||
input.format[input.format.length() - 1] = 'f';
|
||||
|
||||
snprintf(referenceOutput, sizeof(referenceOutput), input.format.c_str(), input.value);
|
||||
|
||||
EXPECT_STREQ(referenceOutput, actualOutput);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(PrintfDoubleTest,
|
||||
PrintfDoubleTest,
|
||||
::testing::ValuesIn(doubleValues));
|
||||
|
||||
std::pair<std::string, std::string> specialValues[] = {
|
||||
{"%%", "%"},
|
||||
{"nothing%", "nothing"},
|
||||
};
|
||||
|
||||
class PrintfSpecialTest : public PrintFormatterTest,
|
||||
public ::testing::WithParamInterface<std::pair<std::string, std::string>> {};
|
||||
|
||||
TEST_P(PrintfSpecialTest, DoublePercentageIntoOne) {
|
||||
auto input = GetParam();
|
||||
|
||||
auto stringIndex = injectFormatString(input.first);
|
||||
storeData(stringIndex);
|
||||
|
||||
char actualOutput[PrintFormatter::maxPrintfOutputLength];
|
||||
|
||||
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, PrintFormatter::maxPrintfOutputLength, str, PrintFormatter::maxPrintfOutputLength); });
|
||||
|
||||
EXPECT_STREQ(input.second.c_str(), actualOutput);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(PrintfSpecialTest,
|
||||
PrintfSpecialTest,
|
||||
::testing::ValuesIn(specialValues));
|
||||
|
||||
// ------------------------- Testing Strings only with no Formatting ------------------------
|
||||
|
||||
class PrintfNoArgumentsTest : public PrintFormatterTest,
|
||||
public ::testing::WithParamInterface<std::pair<std::string, std::string>> {};
|
||||
|
||||
// escape/non-escaped strings are specified manually to avoid converting them in code
|
||||
// automatic code would have to do the same thing it is testing and therefore would be prone to mistakes
|
||||
// this is needed because compiler doesn't escape the format strings and provides them exactly as they were typed in kernel source
|
||||
std::pair<std::string, std::string> stringValues[] = {
|
||||
{R"(test)", "test"},
|
||||
{R"(test\n)", "test\n"},
|
||||
};
|
||||
|
||||
TEST_P(PrintfNoArgumentsTest, GivenPrintfFormatWhenNoArgumentsThenEscapeChars) {
|
||||
auto input = GetParam();
|
||||
|
||||
auto stringIndex = injectFormatString(input.first);
|
||||
storeData(stringIndex);
|
||||
|
||||
char actualOutput[PrintFormatter::maxPrintfOutputLength];
|
||||
|
||||
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, PrintFormatter::maxPrintfOutputLength, str, PrintFormatter::maxPrintfOutputLength); });
|
||||
|
||||
EXPECT_STREQ(input.second.c_str(), actualOutput);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(PrintfNoArgumentsTest,
|
||||
PrintfNoArgumentsTest,
|
||||
::testing::ValuesIn(stringValues));
|
||||
|
||||
StringParams stringValues2[] = {
|
||||
{"%s", "foo"},
|
||||
};
|
||||
|
||||
class PrintfStringTest : public PrintFormatterTest,
|
||||
public ::testing::WithParamInterface<StringParams> {};
|
||||
|
||||
TEST_P(PrintfStringTest, GivenPrintfFormatWhenStringArgumentThenInsertValue) {
|
||||
auto input = GetParam();
|
||||
|
||||
auto stringIndex = injectFormatString(input.format);
|
||||
storeData(stringIndex);
|
||||
|
||||
auto inputIndex = injectFormatString(input.value);
|
||||
injectStringValue(inputIndex);
|
||||
|
||||
char referenceOutput[PrintFormatter::maxPrintfOutputLength];
|
||||
char actualOutput[PrintFormatter::maxPrintfOutputLength];
|
||||
|
||||
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, PrintFormatter::maxPrintfOutputLength, str, PrintFormatter::maxPrintfOutputLength); });
|
||||
|
||||
snprintf(referenceOutput, sizeof(referenceOutput), input.format.c_str(), input.value.c_str());
|
||||
|
||||
EXPECT_STREQ(input.value.c_str(), actualOutput);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(PrintfStringTest,
|
||||
PrintfStringTest,
|
||||
::testing::ValuesIn(stringValues2));
|
||||
|
||||
TEST_F(PrintFormatterTest, GivenPrintfFormatWhenStringArgumentButNullTokenThenPrintNull) {
|
||||
auto stringIndex = injectFormatString("%s");
|
||||
storeData(stringIndex);
|
||||
|
||||
storeData(PRINTF_DATA_TYPE::VECTOR_INT);
|
||||
storeData(0);
|
||||
|
||||
char actualOutput[PrintFormatter::maxPrintfOutputLength];
|
||||
|
||||
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, PrintFormatter::maxPrintfOutputLength, str, PrintFormatter::maxPrintfOutputLength); });
|
||||
|
||||
EXPECT_STREQ("(null)", actualOutput);
|
||||
}
|
||||
|
||||
// ----------------------- Vector channel count ---------------------------------
|
||||
TEST_F(PrintFormatterTest, GivenPrintfFormatWhenVector2ThenInsertAllValues) {
|
||||
int channelCount = 2;
|
||||
|
||||
auto stringIndex = injectFormatString("%v2d");
|
||||
storeData(stringIndex);
|
||||
|
||||
storeData(PRINTF_DATA_TYPE::VECTOR_INT);
|
||||
// channel count
|
||||
storeData(channelCount);
|
||||
|
||||
// channel values
|
||||
for (int i = 0; i < channelCount; i++)
|
||||
storeData(i + 1);
|
||||
|
||||
char actualOutput[PrintFormatter::maxPrintfOutputLength];
|
||||
|
||||
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, PrintFormatter::maxPrintfOutputLength, str, PrintFormatter::maxPrintfOutputLength); });
|
||||
|
||||
EXPECT_STREQ("1,2", actualOutput);
|
||||
}
|
||||
|
||||
TEST_F(PrintFormatterTest, GivenPrintfFormatWhenVector4ThenInsertAllValues) {
|
||||
int channelCount = 4;
|
||||
|
||||
auto stringIndex = injectFormatString("%v4d");
|
||||
storeData(stringIndex);
|
||||
|
||||
storeData(PRINTF_DATA_TYPE::VECTOR_INT);
|
||||
// channel count
|
||||
storeData(channelCount);
|
||||
|
||||
// channel values
|
||||
for (int i = 0; i < channelCount; i++)
|
||||
storeData(i + 1);
|
||||
|
||||
char actualOutput[PrintFormatter::maxPrintfOutputLength];
|
||||
|
||||
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, PrintFormatter::maxPrintfOutputLength, str, PrintFormatter::maxPrintfOutputLength); });
|
||||
|
||||
EXPECT_STREQ("1,2,3,4", actualOutput);
|
||||
}
|
||||
|
||||
TEST_F(PrintFormatterTest, GivenPrintfFormatWhenVector8ThenInsertAllValues) {
|
||||
int channelCount = 8;
|
||||
|
||||
auto stringIndex = injectFormatString("%v8d");
|
||||
storeData(stringIndex);
|
||||
|
||||
storeData(PRINTF_DATA_TYPE::VECTOR_INT);
|
||||
// channel count
|
||||
storeData(channelCount);
|
||||
|
||||
// channel values
|
||||
for (int i = 0; i < channelCount; i++)
|
||||
storeData(i + 1);
|
||||
|
||||
char actualOutput[PrintFormatter::maxPrintfOutputLength];
|
||||
|
||||
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, PrintFormatter::maxPrintfOutputLength, str, PrintFormatter::maxPrintfOutputLength); });
|
||||
|
||||
EXPECT_STREQ("1,2,3,4,5,6,7,8", actualOutput);
|
||||
}
|
||||
|
||||
TEST_F(PrintFormatterTest, GivenPrintfFormatWhenVector16ThenInsertAllValues) {
|
||||
int channelCount = 16;
|
||||
|
||||
auto stringIndex = injectFormatString("%v16d");
|
||||
storeData(stringIndex);
|
||||
|
||||
storeData(PRINTF_DATA_TYPE::VECTOR_INT);
|
||||
// channel count
|
||||
storeData(channelCount);
|
||||
|
||||
// channel values
|
||||
for (int i = 0; i < channelCount; i++)
|
||||
storeData(i + 1);
|
||||
|
||||
char actualOutput[PrintFormatter::maxPrintfOutputLength];
|
||||
|
||||
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, PrintFormatter::maxPrintfOutputLength, str, PrintFormatter::maxPrintfOutputLength); });
|
||||
|
||||
EXPECT_STREQ("1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16", actualOutput);
|
||||
}
|
||||
|
||||
// ------------------- vector types ----------------------------
|
||||
TEST_F(PrintFormatterTest, GivenPrintfFormatWhenVectorOfBytesThenInsertAllValues) {
|
||||
int channelCount = 2;
|
||||
|
||||
auto stringIndex = injectFormatString("%v2hhd");
|
||||
storeData(stringIndex);
|
||||
|
||||
storeData(PRINTF_DATA_TYPE::VECTOR_BYTE);
|
||||
// channel count
|
||||
storeData(channelCount);
|
||||
|
||||
storeData<int8_t>(1);
|
||||
storeData<int8_t>(2);
|
||||
|
||||
char actualOutput[PrintFormatter::maxPrintfOutputLength];
|
||||
|
||||
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, PrintFormatter::maxPrintfOutputLength, str, PrintFormatter::maxPrintfOutputLength); });
|
||||
|
||||
EXPECT_STREQ("1,2", actualOutput);
|
||||
}
|
||||
|
||||
TEST_F(PrintFormatterTest, GivenPrintfFormatWhenVectorOfShortsThenInsertAllValues) {
|
||||
int channelCount = 2;
|
||||
|
||||
auto stringIndex = injectFormatString("%v2hd");
|
||||
storeData(stringIndex);
|
||||
|
||||
storeData(PRINTF_DATA_TYPE::VECTOR_SHORT);
|
||||
// channel count
|
||||
storeData(channelCount);
|
||||
|
||||
storeData<int16_t>(1);
|
||||
storeData<int16_t>(2);
|
||||
|
||||
char actualOutput[PrintFormatter::maxPrintfOutputLength];
|
||||
|
||||
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, PrintFormatter::maxPrintfOutputLength, str, PrintFormatter::maxPrintfOutputLength); });
|
||||
|
||||
EXPECT_STREQ("1,2", actualOutput);
|
||||
}
|
||||
|
||||
TEST_F(PrintFormatterTest, GivenPrintfFormatWhenVectorOfIntsThenInsertAllValues) {
|
||||
int channelCount = 2;
|
||||
|
||||
auto stringIndex = injectFormatString("%v2d");
|
||||
storeData(stringIndex);
|
||||
|
||||
storeData(PRINTF_DATA_TYPE::VECTOR_INT);
|
||||
// channel count
|
||||
storeData(channelCount);
|
||||
|
||||
storeData<int32_t>(1);
|
||||
storeData<int32_t>(2);
|
||||
|
||||
char actualOutput[PrintFormatter::maxPrintfOutputLength];
|
||||
|
||||
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, PrintFormatter::maxPrintfOutputLength, str, PrintFormatter::maxPrintfOutputLength); });
|
||||
|
||||
EXPECT_STREQ("1,2", actualOutput);
|
||||
}
|
||||
|
||||
TEST_F(PrintFormatterTest, GivenPrintfSpecialVectorFormatWhenVectorOfIntsThenInsertAllValues) {
|
||||
int channelCount = 2;
|
||||
|
||||
auto stringIndex = injectFormatString("%v2hld");
|
||||
storeData(stringIndex);
|
||||
|
||||
storeData(PRINTF_DATA_TYPE::VECTOR_INT);
|
||||
// channel count
|
||||
storeData(channelCount);
|
||||
|
||||
storeData<int32_t>(1);
|
||||
storeData<int32_t>(2);
|
||||
|
||||
char actualOutput[PrintFormatter::maxPrintfOutputLength];
|
||||
|
||||
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, PrintFormatter::maxPrintfOutputLength, str, PrintFormatter::maxPrintfOutputLength); });
|
||||
|
||||
EXPECT_STREQ("1,2", actualOutput);
|
||||
}
|
||||
TEST_F(PrintFormatterTest, GivenPrintfFormatWhenVectorOfLongsThenInsertAllValues) {
|
||||
int channelCount = 2;
|
||||
|
||||
auto stringIndex = injectFormatString("%v2lld");
|
||||
storeData(stringIndex);
|
||||
|
||||
storeData(PRINTF_DATA_TYPE::VECTOR_LONG);
|
||||
// channel count
|
||||
storeData(channelCount);
|
||||
|
||||
storeData<int64_t>(1);
|
||||
storeData<int64_t>(2);
|
||||
|
||||
char actualOutput[PrintFormatter::maxPrintfOutputLength];
|
||||
|
||||
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, PrintFormatter::maxPrintfOutputLength, str, PrintFormatter::maxPrintfOutputLength); });
|
||||
|
||||
EXPECT_STREQ("1,2", actualOutput);
|
||||
}
|
||||
|
||||
TEST_F(PrintFormatterTest, GivenPrintfFormatWhenVectorOfFloatsThenInsertAllValues) {
|
||||
int channelCount = 2;
|
||||
|
||||
auto stringIndex = injectFormatString("%v2f");
|
||||
storeData(stringIndex);
|
||||
|
||||
storeData(PRINTF_DATA_TYPE::VECTOR_FLOAT);
|
||||
// channel count
|
||||
storeData(channelCount);
|
||||
|
||||
storeData<float>(1.0);
|
||||
storeData<float>(2.0);
|
||||
|
||||
char actualOutput[PrintFormatter::maxPrintfOutputLength];
|
||||
|
||||
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, PrintFormatter::maxPrintfOutputLength, str, PrintFormatter::maxPrintfOutputLength); });
|
||||
|
||||
EXPECT_STREQ("1.000000,2.000000", actualOutput);
|
||||
}
|
||||
|
||||
TEST_F(PrintFormatterTest, GivenPrintfFormatWhenVectorOfDoublesThenInsertAllValues) {
|
||||
int channelCount = 2;
|
||||
|
||||
auto stringIndex = injectFormatString("%v2f");
|
||||
storeData(stringIndex);
|
||||
|
||||
storeData(PRINTF_DATA_TYPE::VECTOR_DOUBLE);
|
||||
// channel count
|
||||
storeData(channelCount);
|
||||
|
||||
storeData<double>(1.0);
|
||||
storeData<double>(2.0);
|
||||
|
||||
char actualOutput[PrintFormatter::maxPrintfOutputLength];
|
||||
|
||||
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, PrintFormatter::maxPrintfOutputLength, str, PrintFormatter::maxPrintfOutputLength); });
|
||||
|
||||
EXPECT_STREQ("1.000000,2.000000", actualOutput);
|
||||
}
|
||||
|
||||
TEST_F(PrintFormatterTest, GivenPrintfFormatWhenPointerThenInsertAddress) {
|
||||
auto stringIndex = injectFormatString("%p");
|
||||
storeData(stringIndex);
|
||||
|
||||
int temp;
|
||||
|
||||
storeData(PRINTF_DATA_TYPE::POINTER);
|
||||
// channel count
|
||||
storeData(reinterpret_cast<void *>(&temp));
|
||||
|
||||
// on 32bit configurations add extra 4 bytes when storing pointers, IGC always stores pointers on 8 bytes
|
||||
if (is32bit) {
|
||||
uint32_t padding = 0;
|
||||
storeData(padding);
|
||||
}
|
||||
|
||||
char actualOutput[PrintFormatter::maxPrintfOutputLength];
|
||||
char referenceOutput[PrintFormatter::maxPrintfOutputLength];
|
||||
|
||||
snprintf(referenceOutput, sizeof(referenceOutput), "%p", reinterpret_cast<void *>(&temp));
|
||||
|
||||
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, PrintFormatter::maxPrintfOutputLength, str, PrintFormatter::maxPrintfOutputLength); });
|
||||
|
||||
EXPECT_STREQ(referenceOutput, actualOutput);
|
||||
}
|
||||
|
||||
TEST_F(PrintFormatterTest, GivenPrintfFormatWhenPointerWith32BitKernelThenPrint32BitPointer) {
|
||||
printFormatter.reset(new PrintFormatter(static_cast<uint8_t *>(data->getUnderlyingBuffer()), PrintFormatter::maxPrintfOutputLength, true, kernelInfo->patchInfo.stringDataMap));
|
||||
auto stringIndex = injectFormatString("%p");
|
||||
storeData(stringIndex);
|
||||
kernelInfo->gpuPointerSize = 4;
|
||||
|
||||
storeData(PRINTF_DATA_TYPE::POINTER);
|
||||
|
||||
// store pointer
|
||||
uint32_t addressValue = 0;
|
||||
storeData(addressValue);
|
||||
|
||||
void *pointer = nullptr;
|
||||
|
||||
// store non zero padding
|
||||
uint32_t padding = 0xdeadbeef;
|
||||
storeData(padding);
|
||||
|
||||
char actualOutput[PrintFormatter::maxPrintfOutputLength];
|
||||
char referenceOutput[PrintFormatter::maxPrintfOutputLength];
|
||||
|
||||
snprintf(referenceOutput, sizeof(referenceOutput), "%p", pointer);
|
||||
|
||||
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, PrintFormatter::maxPrintfOutputLength, str, PrintFormatter::maxPrintfOutputLength); });
|
||||
|
||||
EXPECT_STREQ(referenceOutput, actualOutput);
|
||||
}
|
||||
|
||||
TEST_F(PrintFormatterTest, GivenPrintfFormatWhen2ByteVectorsThenParseDataBufferProperly) {
|
||||
int channelCount = 4;
|
||||
|
||||
auto stringIndex = injectFormatString("%v4hhd %v4hhd");
|
||||
storeData(stringIndex);
|
||||
|
||||
storeData(PRINTF_DATA_TYPE::VECTOR_BYTE);
|
||||
// channel count
|
||||
storeData(channelCount);
|
||||
|
||||
// channel values
|
||||
for (int i = 0; i < channelCount; i++)
|
||||
storeData(static_cast<int8_t>(i + 1));
|
||||
|
||||
// filler, should not be printed
|
||||
for (int i = 0; i < 12; i++)
|
||||
storeData(static_cast<int8_t>(0));
|
||||
|
||||
storeData(PRINTF_DATA_TYPE::VECTOR_BYTE);
|
||||
// channel count
|
||||
storeData(channelCount);
|
||||
|
||||
// channel values
|
||||
for (int i = 0; i < channelCount; i++)
|
||||
storeData(static_cast<int8_t>(i + 1));
|
||||
|
||||
// filler, should not be printed
|
||||
for (int i = 0; i < 12; i++)
|
||||
storeData(static_cast<int8_t>(0));
|
||||
|
||||
char actualOutput[PrintFormatter::maxPrintfOutputLength];
|
||||
|
||||
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, PrintFormatter::maxPrintfOutputLength, str, PrintFormatter::maxPrintfOutputLength); });
|
||||
|
||||
EXPECT_STREQ("1,2,3,4 1,2,3,4", actualOutput);
|
||||
}
|
||||
|
||||
TEST_F(PrintFormatterTest, GivenEmptyBufferWhenPrintingThenFailSafely) {
|
||||
char actualOutput[PrintFormatter::maxPrintfOutputLength];
|
||||
actualOutput[0] = 0;
|
||||
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, PrintFormatter::maxPrintfOutputLength, str, PrintFormatter::maxPrintfOutputLength); });
|
||||
EXPECT_STREQ("", actualOutput);
|
||||
}
|
||||
|
||||
TEST(printToSTDOUTTest, GivenStringWhenPrintingToSTDOUTThenExpectOutput) {
|
||||
testing::internal::CaptureStdout();
|
||||
printToSTDOUT("test");
|
||||
std::string output = testing::internal::GetCapturedStdout();
|
||||
EXPECT_STREQ("test", output.c_str());
|
||||
}
|
||||
|
||||
TEST(simpleSprintf, GivenEmptyFormatStringWhenSimpleSprintfIsCalledThenBailOutWith0) {
|
||||
char out[1024] = {7, 0};
|
||||
auto ret = simple_sprintf<float>(out, sizeof(out), "", 3.0f);
|
||||
EXPECT_EQ(0U, ret);
|
||||
EXPECT_EQ(0, out[0]);
|
||||
EXPECT_EQ(0, out[1]);
|
||||
}
|
||||
95
opencl/test/unit_test/program/process_debug_data_tests.cpp
Normal file
95
opencl/test/unit_test/program/process_debug_data_tests.cpp
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "test.h"
|
||||
|
||||
#include "mocks/mock_program.h"
|
||||
#include "program/program_tests.h"
|
||||
#include "program_debug_data.h"
|
||||
|
||||
#include <memory>
|
||||
using namespace iOpenCL;
|
||||
using namespace NEO;
|
||||
|
||||
TEST_F(ProgramTests, GivenProgramWithDebugDataForTwoKernelsWhenPorcessedThenDebugDataIsSetInKernelInfos) {
|
||||
const char kernelName1[] = "kernel1";
|
||||
const char kernelName2[] = "kernel2";
|
||||
uint32_t kernelNameSize = static_cast<uint32_t>(sizeof(kernelName1));
|
||||
uint32_t genIsaSize = 8;
|
||||
uint32_t visaSize = 8;
|
||||
size_t debugDataSize = sizeof(SProgramDebugDataHeaderIGC) + 2 * (sizeof(SKernelDebugDataHeaderIGC) + kernelNameSize + genIsaSize + visaSize);
|
||||
std::unique_ptr<char[]> debugData(new char[debugDataSize]);
|
||||
|
||||
auto kernelInfo1 = new KernelInfo();
|
||||
kernelInfo1->name = kernelName1;
|
||||
auto kernelInfo2 = new KernelInfo();
|
||||
kernelInfo2->name = kernelName2;
|
||||
auto program = std::make_unique<MockProgram>(*pDevice->getExecutionEnvironment());
|
||||
|
||||
SProgramDebugDataHeaderIGC *programDebugHeader = reinterpret_cast<SProgramDebugDataHeaderIGC *>(debugData.get());
|
||||
programDebugHeader->NumberOfKernels = 2;
|
||||
|
||||
SKernelDebugDataHeaderIGC *kernelDebugHeader = reinterpret_cast<SKernelDebugDataHeaderIGC *>(ptrOffset(programDebugHeader, sizeof(SProgramDebugDataHeaderIGC)));
|
||||
kernelDebugHeader->KernelNameSize = kernelNameSize;
|
||||
kernelDebugHeader->SizeGenIsaDbgInBytes = genIsaSize;
|
||||
kernelDebugHeader->SizeVisaDbgInBytes = visaSize;
|
||||
|
||||
char *kernelName = reinterpret_cast<char *>(ptrOffset(kernelDebugHeader, sizeof(SKernelDebugDataHeaderIGC)));
|
||||
memcpy_s(kernelName, kernelNameSize, kernelName1, kernelNameSize);
|
||||
|
||||
char *vIsa1 = (ptrOffset(kernelName, kernelNameSize));
|
||||
memset(vIsa1, 10, visaSize);
|
||||
|
||||
char *genIsa1 = (ptrOffset(vIsa1, visaSize));
|
||||
memset(genIsa1, 20, genIsaSize);
|
||||
|
||||
kernelDebugHeader = reinterpret_cast<SKernelDebugDataHeaderIGC *>(ptrOffset(vIsa1, genIsaSize + visaSize));
|
||||
kernelDebugHeader->KernelNameSize = kernelNameSize;
|
||||
kernelDebugHeader->SizeGenIsaDbgInBytes = genIsaSize;
|
||||
kernelDebugHeader->SizeVisaDbgInBytes = visaSize;
|
||||
kernelName = reinterpret_cast<char *>(ptrOffset(kernelDebugHeader, sizeof(SKernelDebugDataHeaderIGC)));
|
||||
|
||||
memcpy_s(kernelName, kernelNameSize, kernelName2, kernelNameSize);
|
||||
|
||||
char *vIsa2 = (ptrOffset(kernelName, kernelNameSize));
|
||||
memset(vIsa2, 10, visaSize);
|
||||
|
||||
char *genIsa2 = (ptrOffset(vIsa2, visaSize));
|
||||
memset(genIsa2, 20, genIsaSize);
|
||||
|
||||
program->debugData = makeCopy(debugData.get(), debugDataSize);
|
||||
program->debugDataSize = debugDataSize;
|
||||
|
||||
program->addKernelInfo(kernelInfo1);
|
||||
program->addKernelInfo(kernelInfo2);
|
||||
|
||||
program->processDebugData();
|
||||
EXPECT_EQ(genIsaSize, kernelInfo1->debugData.genIsaSize);
|
||||
EXPECT_EQ(visaSize, kernelInfo1->debugData.vIsaSize);
|
||||
EXPECT_EQ(ptrDiff(vIsa1, debugData.get()), ptrDiff(kernelInfo1->debugData.vIsa, program->getDebugData()));
|
||||
EXPECT_EQ(ptrDiff(genIsa1, debugData.get()), ptrDiff(kernelInfo1->debugData.genIsa, program->getDebugData()));
|
||||
|
||||
EXPECT_EQ(genIsaSize, kernelInfo2->debugData.genIsaSize);
|
||||
EXPECT_EQ(visaSize, kernelInfo2->debugData.vIsaSize);
|
||||
EXPECT_EQ(ptrDiff(vIsa2, debugData.get()), ptrDiff(kernelInfo2->debugData.vIsa, program->getDebugData()));
|
||||
EXPECT_EQ(ptrDiff(genIsa2, debugData.get()), ptrDiff(kernelInfo2->debugData.genIsa, program->getDebugData()));
|
||||
}
|
||||
|
||||
TEST_F(ProgramTests, GivenProgramWithoutDebugDataWhenPorcessedThenDebugDataIsNotSetInKernelInfo) {
|
||||
const char kernelName1[] = "kernel1";
|
||||
|
||||
auto kernelInfo1 = new KernelInfo();
|
||||
kernelInfo1->name = kernelName1;
|
||||
auto program = std::make_unique<MockProgram>(*pDevice->getExecutionEnvironment());
|
||||
|
||||
program->addKernelInfo(kernelInfo1);
|
||||
program->processDebugData();
|
||||
|
||||
EXPECT_EQ(0u, kernelInfo1->debugData.genIsaSize);
|
||||
EXPECT_EQ(0u, kernelInfo1->debugData.vIsaSize);
|
||||
EXPECT_EQ(nullptr, program->getDebugData());
|
||||
}
|
||||
256
opencl/test/unit_test/program/process_elf_binary_tests.cpp
Normal file
256
opencl/test/unit_test/program/process_elf_binary_tests.cpp
Normal file
@@ -0,0 +1,256 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "core/device/device.h"
|
||||
#include "core/device_binary_format/elf/elf.h"
|
||||
#include "core/device_binary_format/elf/elf_decoder.h"
|
||||
#include "core/device_binary_format/elf/ocl_elf.h"
|
||||
#include "core/helpers/file_io.h"
|
||||
#include "core/helpers/string.h"
|
||||
#include "core/unit_tests/device_binary_format/patchtokens_tests.h"
|
||||
|
||||
#include "compiler_options.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "helpers/test_files.h"
|
||||
#include "mocks/mock_device.h"
|
||||
#include "mocks/mock_program.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
class ProcessElfBinaryTests : public ::testing::Test {
|
||||
public:
|
||||
void SetUp() override {
|
||||
device = std::make_unique<MockClDevice>(MockDevice::createWithNewExecutionEnvironment<MockDevice>(nullptr));
|
||||
program = std::make_unique<MockProgram>(*device->getExecutionEnvironment());
|
||||
program->pDevice = &device->getDevice();
|
||||
}
|
||||
|
||||
std::unique_ptr<MockProgram> program;
|
||||
std::unique_ptr<ClDevice> device;
|
||||
};
|
||||
|
||||
TEST_F(ProcessElfBinaryTests, NullBinary) {
|
||||
cl_int retVal = program->createProgramFromBinary(nullptr, 0);
|
||||
EXPECT_EQ(CL_INVALID_BINARY, retVal);
|
||||
}
|
||||
|
||||
TEST_F(ProcessElfBinaryTests, InvalidBinary) {
|
||||
char pBinary[] = "thisistotallyinvalid\0";
|
||||
size_t binarySize = strnlen_s(pBinary, 21);
|
||||
cl_int retVal = program->createProgramFromBinary(pBinary, binarySize);
|
||||
|
||||
EXPECT_EQ(CL_INVALID_BINARY, retVal);
|
||||
}
|
||||
|
||||
TEST_F(ProcessElfBinaryTests, ValidBinary) {
|
||||
std::string filePath;
|
||||
retrieveBinaryKernelFilename(filePath, "CopyBuffer_simd16_", ".bin");
|
||||
|
||||
size_t binarySize = 0;
|
||||
auto pBinary = loadDataFromFile(filePath.c_str(), binarySize);
|
||||
cl_int retVal = program->createProgramFromBinary(pBinary.get(), binarySize);
|
||||
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
EXPECT_EQ(0, memcmp(pBinary.get(), program->packedDeviceBinary.get(), binarySize));
|
||||
}
|
||||
|
||||
TEST_F(ProcessElfBinaryTests, ValidSpirvBinary) {
|
||||
//clCreateProgramWithIL => SPIR-V stored as source code
|
||||
const uint32_t spirvBinary[2] = {0x03022307, 0x07230203};
|
||||
size_t spirvBinarySize = sizeof(spirvBinary);
|
||||
|
||||
//clCompileProgram => SPIR-V stored as IR binary
|
||||
program->isSpirV = true;
|
||||
program->irBinary = makeCopy(spirvBinary, spirvBinarySize);
|
||||
program->irBinarySize = spirvBinarySize;
|
||||
program->programBinaryType = CL_PROGRAM_BINARY_TYPE_LIBRARY;
|
||||
EXPECT_NE(nullptr, program->irBinary);
|
||||
EXPECT_NE(0u, program->irBinarySize);
|
||||
EXPECT_TRUE(program->getIsSpirV());
|
||||
|
||||
//clGetProgramInfo => SPIR-V stored as ELF binary
|
||||
cl_int retVal = program->packDeviceBinary();
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
EXPECT_NE(nullptr, program->packedDeviceBinary);
|
||||
EXPECT_NE(0u, program->packedDeviceBinarySize);
|
||||
|
||||
//use ELF reader to parse and validate ELF binary
|
||||
std::string decodeErrors;
|
||||
std::string decodeWarnings;
|
||||
auto elf = NEO::Elf::decodeElf(ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(program->packedDeviceBinary.get()), program->packedDeviceBinarySize), decodeErrors, decodeWarnings);
|
||||
auto header = elf.elfFileHeader;
|
||||
ASSERT_NE(nullptr, header);
|
||||
|
||||
//check if ELF binary contains section SECTION_HEADER_TYPE_SPIRV
|
||||
bool hasSpirvSection = false;
|
||||
for (const auto &elfSectionHeader : elf.sectionHeaders) {
|
||||
if (elfSectionHeader.header->type == NEO::Elf::SHT_OPENCL_SPIRV) {
|
||||
hasSpirvSection = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
EXPECT_TRUE(hasSpirvSection);
|
||||
|
||||
//clCreateProgramWithBinary => new program should recognize SPIR-V binary
|
||||
program->isSpirV = false;
|
||||
auto elfBinary = makeCopy(program->packedDeviceBinary.get(), program->packedDeviceBinarySize);
|
||||
retVal = program->createProgramFromBinary(elfBinary.get(), program->packedDeviceBinarySize);
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
EXPECT_TRUE(program->getIsSpirV());
|
||||
}
|
||||
|
||||
unsigned int BinaryTypeValues[] = {
|
||||
CL_PROGRAM_BINARY_TYPE_EXECUTABLE,
|
||||
CL_PROGRAM_BINARY_TYPE_LIBRARY,
|
||||
CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT};
|
||||
|
||||
class ProcessElfBinaryTestsWithBinaryType : public ::testing::TestWithParam<unsigned int> {
|
||||
public:
|
||||
void SetUp() override {
|
||||
device = std::make_unique<MockClDevice>(MockDevice::createWithNewExecutionEnvironment<MockDevice>(nullptr));
|
||||
program = std::make_unique<MockProgram>(*device->getExecutionEnvironment());
|
||||
program->pDevice = &device->getDevice();
|
||||
}
|
||||
|
||||
std::unique_ptr<MockProgram> program;
|
||||
std::unique_ptr<ClDevice> device;
|
||||
};
|
||||
|
||||
TEST_P(ProcessElfBinaryTestsWithBinaryType, GivenBinaryTypeWhenResolveProgramThenProgramIsProperlyResolved) {
|
||||
std::string filePath;
|
||||
retrieveBinaryKernelFilename(filePath, "CopyBuffer_simd16_", ".bin");
|
||||
|
||||
size_t binarySize = 0;
|
||||
auto pBinary = loadDataFromFile(filePath.c_str(), binarySize);
|
||||
cl_int retVal = program->createProgramFromBinary(pBinary.get(), binarySize);
|
||||
auto options = program->options;
|
||||
auto genBinary = makeCopy(program->unpackedDeviceBinary.get(), program->unpackedDeviceBinarySize);
|
||||
auto genBinarySize = program->unpackedDeviceBinarySize;
|
||||
auto irBinary = makeCopy(program->irBinary.get(), program->irBinarySize);
|
||||
auto irBinarySize = program->irBinarySize;
|
||||
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
ASSERT_EQ(binarySize, program->packedDeviceBinarySize);
|
||||
EXPECT_EQ(0, memcmp(pBinary.get(), program->packedDeviceBinary.get(), binarySize));
|
||||
|
||||
// delete program's elf reference to force a resolve
|
||||
program->packedDeviceBinary.reset();
|
||||
program->packedDeviceBinarySize = 0U;
|
||||
program->programBinaryType = GetParam();
|
||||
retVal = program->packDeviceBinary();
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
ASSERT_NE(nullptr, program->packedDeviceBinary);
|
||||
|
||||
std::string decodeErrors;
|
||||
std::string decodeWarnings;
|
||||
auto elf = NEO::Elf::decodeElf(ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(program->packedDeviceBinary.get()), program->packedDeviceBinarySize), decodeErrors, decodeWarnings);
|
||||
ASSERT_NE(nullptr, elf.elfFileHeader);
|
||||
ArrayRef<const uint8_t> decodedIr;
|
||||
ArrayRef<const uint8_t> decodedDeviceBinary;
|
||||
ArrayRef<const uint8_t> decodedOptions;
|
||||
for (auto §ion : elf.sectionHeaders) {
|
||||
switch (section.header->type) {
|
||||
default:
|
||||
break;
|
||||
case NEO::Elf::SHT_OPENCL_LLVM_BINARY:
|
||||
decodedIr = section.data;
|
||||
break;
|
||||
case NEO::Elf::SHT_OPENCL_SPIRV:
|
||||
decodedIr = section.data;
|
||||
break;
|
||||
case NEO::Elf::SHT_OPENCL_DEV_BINARY:
|
||||
decodedDeviceBinary = section.data;
|
||||
break;
|
||||
case NEO::Elf::SHT_OPENCL_OPTIONS:
|
||||
decodedDeviceBinary = section.data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ASSERT_EQ(options.size(), decodedOptions.size());
|
||||
ASSERT_EQ(genBinarySize, decodedDeviceBinary.size());
|
||||
ASSERT_EQ(irBinarySize, decodedIr.size());
|
||||
|
||||
EXPECT_EQ(0, memcmp(genBinary.get(), decodedDeviceBinary.begin(), genBinarySize));
|
||||
EXPECT_EQ(0, memcmp(irBinary.get(), decodedIr.begin(), irBinarySize));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(ResolveBinaryTests,
|
||||
ProcessElfBinaryTestsWithBinaryType,
|
||||
::testing::ValuesIn(BinaryTypeValues));
|
||||
|
||||
TEST_F(ProcessElfBinaryTests, BackToBack) {
|
||||
std::string filePath;
|
||||
retrieveBinaryKernelFilename(filePath, "CopyBuffer_simd16_", ".bin");
|
||||
|
||||
size_t binarySize = 0;
|
||||
auto pBinary = loadDataFromFile(filePath.c_str(), binarySize);
|
||||
cl_int retVal = program->createProgramFromBinary(pBinary.get(), binarySize);
|
||||
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
EXPECT_EQ(0, memcmp(pBinary.get(), program->packedDeviceBinary.get(), binarySize));
|
||||
|
||||
std::string filePath2;
|
||||
retrieveBinaryKernelFilename(filePath2, "simple_arg_int_", ".bin");
|
||||
|
||||
pBinary = loadDataFromFile(filePath2.c_str(), binarySize);
|
||||
retVal = program->createProgramFromBinary(pBinary.get(), binarySize);
|
||||
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
EXPECT_EQ(0, memcmp(pBinary.get(), program->packedDeviceBinary.get(), binarySize));
|
||||
}
|
||||
|
||||
TEST_F(ProcessElfBinaryTests, BuildOptionsEmpty) {
|
||||
std::string filePath;
|
||||
retrieveBinaryKernelFilename(filePath, "simple_kernels_", ".bin");
|
||||
|
||||
size_t binarySize = 0;
|
||||
auto pBinary = loadDataFromFile(filePath.c_str(), binarySize);
|
||||
cl_int retVal = program->createProgramFromBinary(pBinary.get(), binarySize);
|
||||
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
const auto &options = program->getOptions();
|
||||
size_t optionsSize = strlen(options.c_str()) + 1;
|
||||
EXPECT_EQ(0, memcmp("", options.c_str(), optionsSize));
|
||||
}
|
||||
|
||||
TEST_F(ProcessElfBinaryTests, BuildOptionsNotEmpty) {
|
||||
std::string filePath;
|
||||
retrieveBinaryKernelFilename(filePath, "simple_kernels_opts_", ".bin");
|
||||
|
||||
size_t binarySize = 0;
|
||||
auto pBinary = loadDataFromFile(filePath.c_str(), binarySize);
|
||||
cl_int retVal = program->createProgramFromBinary(pBinary.get(), binarySize);
|
||||
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
const auto &options = program->getOptions();
|
||||
std::string buildOptionsNotEmpty = CompilerOptions::concatenate(CompilerOptions::optDisable, "-DDEF_WAS_SPECIFIED=1");
|
||||
EXPECT_STREQ(buildOptionsNotEmpty.c_str(), options.c_str());
|
||||
}
|
||||
|
||||
TEST_F(ProcessElfBinaryTests, GivenBinaryWhenIncompatiblePatchtokenVerionThenProramCreationFails) {
|
||||
PatchTokensTestData::ValidEmptyProgram programTokens;
|
||||
{
|
||||
NEO::Elf::ElfEncoder<> elfEncoder;
|
||||
elfEncoder.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
|
||||
elfEncoder.appendSection(NEO::Elf::SHT_OPENCL_DEV_BINARY, NEO::Elf::SectionNamesOpenCl::deviceBinary, programTokens.storage);
|
||||
auto elfBinary = elfEncoder.encode();
|
||||
cl_int retVal = program->createProgramFromBinary(elfBinary.data(), elfBinary.size());
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
}
|
||||
|
||||
{
|
||||
programTokens.headerMutable->Version -= 1;
|
||||
NEO::Elf::ElfEncoder<> elfEncoder;
|
||||
elfEncoder.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
|
||||
elfEncoder.appendSection(NEO::Elf::SHT_OPENCL_DEV_BINARY, NEO::Elf::SectionNamesOpenCl::deviceBinary, programTokens.storage);
|
||||
auto elfBinary = elfEncoder.encode();
|
||||
cl_int retVal = program->createProgramFromBinary(elfBinary.data(), elfBinary.size());
|
||||
EXPECT_EQ(CL_INVALID_BINARY, retVal);
|
||||
}
|
||||
}
|
||||
66
opencl/test/unit_test/program/process_spir_binary_tests.cpp
Normal file
66
opencl/test/unit_test/program/process_spir_binary_tests.cpp
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "core/device/device.h"
|
||||
#include "core/helpers/string.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "mocks/mock_program.h"
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
class ProcessSpirBinaryTests : public ::testing::Test {
|
||||
public:
|
||||
void SetUp() override {
|
||||
executionEnvironment = std::make_unique<ExecutionEnvironment>();
|
||||
program = std::make_unique<MockProgram>(*executionEnvironment);
|
||||
}
|
||||
|
||||
std::unique_ptr<ExecutionEnvironment> executionEnvironment;
|
||||
std::unique_ptr<MockProgram> program;
|
||||
};
|
||||
|
||||
TEST_F(ProcessSpirBinaryTests, NullBinary) {
|
||||
auto retVal = program->processSpirBinary(nullptr, 0, false);
|
||||
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
EXPECT_EQ(true, program->sourceCode.empty());
|
||||
}
|
||||
|
||||
TEST_F(ProcessSpirBinaryTests, InvalidSizeBinary) {
|
||||
char pBinary[] = "somebinary\0";
|
||||
size_t binarySize = 1;
|
||||
auto retVal = program->processSpirBinary(pBinary, binarySize, false);
|
||||
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
EXPECT_EQ(binarySize, program->irBinarySize);
|
||||
}
|
||||
|
||||
TEST_F(ProcessSpirBinaryTests, SomeBinary) {
|
||||
char pBinary[] = "somebinary\0";
|
||||
size_t binarySize = strnlen_s(pBinary, 11);
|
||||
auto retVal = program->processSpirBinary(pBinary, binarySize, false);
|
||||
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
EXPECT_EQ(0, memcmp(pBinary, program->irBinary.get(), program->irBinarySize));
|
||||
EXPECT_EQ(binarySize, program->irBinarySize);
|
||||
|
||||
// Verify no built log is available
|
||||
auto pBuildLog = program->getBuildLog(program->getDevicePtr());
|
||||
EXPECT_EQ(nullptr, pBuildLog);
|
||||
}
|
||||
|
||||
TEST_F(ProcessSpirBinaryTests, SpirvBinary) {
|
||||
const uint32_t pBinary[2] = {0x03022307, 0x07230203};
|
||||
size_t binarySize = sizeof(pBinary);
|
||||
|
||||
program->processSpirBinary(pBinary, binarySize, false);
|
||||
EXPECT_FALSE(program->getIsSpirV());
|
||||
|
||||
program->processSpirBinary(pBinary, binarySize, true);
|
||||
EXPECT_TRUE(program->getIsSpirV());
|
||||
}
|
||||
640
opencl/test/unit_test/program/program_data_tests.cpp
Normal file
640
opencl/test/unit_test/program/program_data_tests.cpp
Normal file
@@ -0,0 +1,640 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "core/helpers/string.h"
|
||||
#include "core/memory_manager/allocations_list.h"
|
||||
#include "core/memory_manager/graphics_allocation.h"
|
||||
#include "core/memory_manager/unified_memory_manager.h"
|
||||
#include "core/program/program_info_from_patchtokens.h"
|
||||
#include "core/unit_tests/compiler_interface/linker_mock.h"
|
||||
#include "core/unit_tests/device_binary_format/patchtokens_tests.h"
|
||||
#include "opencl/source/platform/platform.h"
|
||||
#include "opencl/source/program/program.h"
|
||||
#include "test.h"
|
||||
|
||||
#include "mocks/mock_buffer.h"
|
||||
#include "mocks/mock_csr.h"
|
||||
#include "mocks/mock_execution_environment.h"
|
||||
#include "mocks/mock_memory_manager.h"
|
||||
#include "mocks/mock_program.h"
|
||||
#include "program/program_with_source.h"
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
using namespace iOpenCL;
|
||||
static const char constValue[] = "11223344";
|
||||
static const char globalValue[] = "55667788";
|
||||
|
||||
class ProgramDataTestBase : public testing::Test,
|
||||
public ContextFixture,
|
||||
public PlatformFixture,
|
||||
public ProgramFixture {
|
||||
|
||||
using ContextFixture::SetUp;
|
||||
using PlatformFixture::SetUp;
|
||||
|
||||
public:
|
||||
ProgramDataTestBase() {
|
||||
memset(&programBinaryHeader, 0x00, sizeof(SProgramBinaryHeader));
|
||||
pCurPtr = nullptr;
|
||||
pProgramPatchList = nullptr;
|
||||
programPatchListSize = 0;
|
||||
}
|
||||
|
||||
void buildAndDecodeProgramPatchList();
|
||||
|
||||
void SetUp() override {
|
||||
PlatformFixture::SetUp();
|
||||
cl_device_id device = pPlatform->getClDevice(0);
|
||||
ContextFixture::SetUp(1, &device);
|
||||
ProgramFixture::SetUp();
|
||||
|
||||
CreateProgramWithSource(
|
||||
pContext,
|
||||
&device,
|
||||
"CopyBuffer_simd16.cl");
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
knownSource.reset();
|
||||
ProgramFixture::TearDown();
|
||||
ContextFixture::TearDown();
|
||||
PlatformFixture::TearDown();
|
||||
}
|
||||
|
||||
size_t setupConstantAllocation() {
|
||||
size_t constSize = strlen(constValue) + 1;
|
||||
|
||||
EXPECT_EQ(nullptr, pProgram->getConstantSurface());
|
||||
|
||||
SPatchAllocateConstantMemorySurfaceProgramBinaryInfo allocateConstMemorySurface;
|
||||
allocateConstMemorySurface.Token = PATCH_TOKEN_ALLOCATE_CONSTANT_MEMORY_SURFACE_PROGRAM_BINARY_INFO;
|
||||
allocateConstMemorySurface.Size = static_cast<uint32_t>(sizeof(SPatchAllocateConstantMemorySurfaceProgramBinaryInfo));
|
||||
|
||||
allocateConstMemorySurface.ConstantBufferIndex = 0;
|
||||
allocateConstMemorySurface.InlineDataSize = static_cast<uint32_t>(constSize);
|
||||
|
||||
pAllocateConstMemorySurface.reset(new cl_char[allocateConstMemorySurface.Size + constSize]);
|
||||
|
||||
memcpy_s(pAllocateConstMemorySurface.get(),
|
||||
sizeof(SPatchAllocateConstantMemorySurfaceProgramBinaryInfo),
|
||||
&allocateConstMemorySurface,
|
||||
sizeof(SPatchAllocateConstantMemorySurfaceProgramBinaryInfo));
|
||||
|
||||
memcpy_s((cl_char *)pAllocateConstMemorySurface.get() + sizeof(allocateConstMemorySurface), constSize, constValue, constSize);
|
||||
|
||||
pProgramPatchList = (void *)pAllocateConstMemorySurface.get();
|
||||
programPatchListSize = static_cast<uint32_t>(allocateConstMemorySurface.Size + constSize);
|
||||
return constSize;
|
||||
}
|
||||
|
||||
size_t setupGlobalAllocation() {
|
||||
size_t globalSize = strlen(globalValue) + 1;
|
||||
|
||||
EXPECT_EQ(nullptr, pProgram->getGlobalSurface());
|
||||
|
||||
SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo allocateGlobalMemorySurface;
|
||||
allocateGlobalMemorySurface.Token = PATCH_TOKEN_ALLOCATE_GLOBAL_MEMORY_SURFACE_PROGRAM_BINARY_INFO;
|
||||
allocateGlobalMemorySurface.Size = static_cast<uint32_t>(sizeof(SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo));
|
||||
|
||||
allocateGlobalMemorySurface.GlobalBufferIndex = 0;
|
||||
allocateGlobalMemorySurface.InlineDataSize = static_cast<uint32_t>(globalSize);
|
||||
|
||||
pAllocateGlobalMemorySurface.reset(new cl_char[allocateGlobalMemorySurface.Size + globalSize]);
|
||||
|
||||
memcpy_s(pAllocateGlobalMemorySurface.get(),
|
||||
sizeof(SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo),
|
||||
&allocateGlobalMemorySurface,
|
||||
sizeof(SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo));
|
||||
|
||||
memcpy_s((cl_char *)pAllocateGlobalMemorySurface.get() + sizeof(allocateGlobalMemorySurface), globalSize, globalValue, globalSize);
|
||||
|
||||
pProgramPatchList = pAllocateGlobalMemorySurface.get();
|
||||
programPatchListSize = static_cast<uint32_t>(allocateGlobalMemorySurface.Size + globalSize);
|
||||
return globalSize;
|
||||
}
|
||||
std::unique_ptr<cl_char[]> pAllocateConstMemorySurface;
|
||||
std::unique_ptr<cl_char[]> pAllocateGlobalMemorySurface;
|
||||
char *pCurPtr;
|
||||
SProgramBinaryHeader programBinaryHeader;
|
||||
void *pProgramPatchList;
|
||||
uint32_t programPatchListSize;
|
||||
cl_int patchlistDecodeErrorCode = 0;
|
||||
bool allowDecodeFailure = false;
|
||||
};
|
||||
|
||||
void ProgramDataTestBase::buildAndDecodeProgramPatchList() {
|
||||
size_t headerSize = sizeof(SProgramBinaryHeader);
|
||||
|
||||
cl_int error = CL_SUCCESS;
|
||||
programBinaryHeader.Magic = 0x494E5443;
|
||||
programBinaryHeader.Version = CURRENT_ICBE_VERSION;
|
||||
programBinaryHeader.Device = platformDevices[0]->platform.eRenderCoreFamily;
|
||||
programBinaryHeader.GPUPointerSizeInBytes = 8;
|
||||
programBinaryHeader.NumberOfKernels = 0;
|
||||
programBinaryHeader.PatchListSize = programPatchListSize;
|
||||
|
||||
char *pProgramData = new char[headerSize + programBinaryHeader.PatchListSize];
|
||||
ASSERT_NE(nullptr, pProgramData);
|
||||
|
||||
pCurPtr = pProgramData;
|
||||
|
||||
// program header
|
||||
memset(pCurPtr, 0, sizeof(SProgramBinaryHeader));
|
||||
*(SProgramBinaryHeader *)pCurPtr = programBinaryHeader;
|
||||
|
||||
pCurPtr += sizeof(SProgramBinaryHeader);
|
||||
|
||||
// patch list
|
||||
memcpy_s(pCurPtr, programPatchListSize, pProgramPatchList, programPatchListSize);
|
||||
pCurPtr += programPatchListSize;
|
||||
|
||||
//as we use mock compiler in unit test, replace the genBinary here.
|
||||
pProgram->unpackedDeviceBinary = makeCopy(pProgramData, headerSize + programBinaryHeader.PatchListSize);
|
||||
pProgram->unpackedDeviceBinarySize = headerSize + programBinaryHeader.PatchListSize;
|
||||
|
||||
error = pProgram->processGenBinary();
|
||||
patchlistDecodeErrorCode = error;
|
||||
if (allowDecodeFailure == false) {
|
||||
EXPECT_EQ(CL_SUCCESS, error);
|
||||
}
|
||||
delete[] pProgramData;
|
||||
}
|
||||
|
||||
using ProgramDataTest = ProgramDataTestBase;
|
||||
|
||||
TEST_F(ProgramDataTest, EmptyProgramBinaryHeader) {
|
||||
buildAndDecodeProgramPatchList();
|
||||
}
|
||||
|
||||
TEST_F(ProgramDataTest, AllocateConstantMemorySurfaceProgramBinaryInfo) {
|
||||
|
||||
auto constSize = setupConstantAllocation();
|
||||
|
||||
buildAndDecodeProgramPatchList();
|
||||
|
||||
EXPECT_NE(nullptr, pProgram->getConstantSurface());
|
||||
EXPECT_EQ(0, memcmp(constValue, pProgram->getConstantSurface()->getUnderlyingBuffer(), constSize));
|
||||
}
|
||||
|
||||
TEST_F(ProgramDataTest, whenGlobalConstantsAreExportedThenAllocateSurfacesAsSvm) {
|
||||
if (this->pContext->getSVMAllocsManager() == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
char constantData[128] = {};
|
||||
ProgramInfo programInfo;
|
||||
programInfo.globalConstants.initData = constantData;
|
||||
programInfo.globalConstants.size = sizeof(constantData);
|
||||
std::unique_ptr<WhiteBox<NEO::LinkerInput>> mockLinkerInput = std::make_unique<WhiteBox<NEO::LinkerInput>>();
|
||||
mockLinkerInput->traits.exportsGlobalConstants = true;
|
||||
programInfo.linkerInput = std::move(mockLinkerInput);
|
||||
this->pProgram->processProgramInfo(programInfo);
|
||||
|
||||
ASSERT_NE(nullptr, pProgram->getConstantSurface());
|
||||
EXPECT_NE(nullptr, this->pContext->getSVMAllocsManager()->getSVMAlloc(reinterpret_cast<const void *>(pProgram->getConstantSurface()->getGpuAddress())));
|
||||
}
|
||||
|
||||
TEST_F(ProgramDataTest, whenGlobalConstantsAreNotExportedThenAllocateSurfacesAsNonSvm) {
|
||||
if (this->pContext->getSVMAllocsManager() == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
char constantData[128] = {};
|
||||
ProgramInfo programInfo;
|
||||
programInfo.globalConstants.initData = constantData;
|
||||
programInfo.globalConstants.size = sizeof(constantData);
|
||||
std::unique_ptr<WhiteBox<NEO::LinkerInput>> mockLinkerInput = std::make_unique<WhiteBox<NEO::LinkerInput>>();
|
||||
mockLinkerInput->traits.exportsGlobalConstants = false;
|
||||
programInfo.linkerInput = std::move(mockLinkerInput);
|
||||
this->pProgram->processProgramInfo(programInfo);
|
||||
|
||||
ASSERT_NE(nullptr, pProgram->getConstantSurface());
|
||||
EXPECT_EQ(nullptr, this->pContext->getSVMAllocsManager()->getSVMAlloc(reinterpret_cast<const void *>(pProgram->getConstantSurface()->getGpuAddress())));
|
||||
}
|
||||
|
||||
TEST_F(ProgramDataTest, whenGlobalConstantsAreExportedButContextUnavailableThenAllocateSurfacesAsNonSvm) {
|
||||
if (this->pContext->getSVMAllocsManager() == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
char constantData[128] = {};
|
||||
ProgramInfo programInfo;
|
||||
programInfo.globalConstants.initData = constantData;
|
||||
programInfo.globalConstants.size = sizeof(constantData);
|
||||
std::unique_ptr<WhiteBox<NEO::LinkerInput>> mockLinkerInput = std::make_unique<WhiteBox<NEO::LinkerInput>>();
|
||||
mockLinkerInput->traits.exportsGlobalConstants = true;
|
||||
programInfo.linkerInput = std::move(mockLinkerInput);
|
||||
|
||||
pProgram->context = nullptr;
|
||||
|
||||
this->pProgram->processProgramInfo(programInfo);
|
||||
|
||||
pProgram->context = pContext;
|
||||
|
||||
ASSERT_NE(nullptr, pProgram->getConstantSurface());
|
||||
EXPECT_EQ(nullptr, this->pContext->getSVMAllocsManager()->getSVMAlloc(reinterpret_cast<const void *>(pProgram->getConstantSurface()->getGpuAddress())));
|
||||
}
|
||||
|
||||
TEST_F(ProgramDataTest, whenGlobalVariablesAreExportedThenAllocateSurfacesAsSvm) {
|
||||
if (this->pContext->getSVMAllocsManager() == nullptr) {
|
||||
return;
|
||||
}
|
||||
char globalData[128] = {};
|
||||
ProgramInfo programInfo;
|
||||
programInfo.globalVariables.initData = globalData;
|
||||
programInfo.globalVariables.size = sizeof(globalData);
|
||||
std::unique_ptr<WhiteBox<NEO::LinkerInput>> mockLinkerInput = std::make_unique<WhiteBox<NEO::LinkerInput>>();
|
||||
mockLinkerInput->traits.exportsGlobalVariables = true;
|
||||
programInfo.linkerInput = std::move(mockLinkerInput);
|
||||
this->pProgram->processProgramInfo(programInfo);
|
||||
|
||||
ASSERT_NE(nullptr, pProgram->getGlobalSurface());
|
||||
EXPECT_NE(nullptr, this->pContext->getSVMAllocsManager()->getSVMAlloc(reinterpret_cast<const void *>(pProgram->getGlobalSurface()->getGpuAddress())));
|
||||
}
|
||||
|
||||
TEST_F(ProgramDataTest, whenGlobalVariablesAreExportedButContextUnavailableThenAllocateSurfacesAsNonSvm) {
|
||||
if (this->pContext->getSVMAllocsManager() == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
char globalData[128] = {};
|
||||
ProgramInfo programInfo;
|
||||
programInfo.globalVariables.initData = globalData;
|
||||
programInfo.globalVariables.size = sizeof(globalData);
|
||||
std::unique_ptr<WhiteBox<NEO::LinkerInput>> mockLinkerInput = std::make_unique<WhiteBox<NEO::LinkerInput>>();
|
||||
mockLinkerInput->traits.exportsGlobalVariables = true;
|
||||
programInfo.linkerInput = std::move(mockLinkerInput);
|
||||
|
||||
pProgram->context = nullptr;
|
||||
|
||||
this->pProgram->processProgramInfo(programInfo);
|
||||
|
||||
pProgram->context = pContext;
|
||||
|
||||
ASSERT_NE(nullptr, pProgram->getGlobalSurface());
|
||||
EXPECT_EQ(nullptr, this->pContext->getSVMAllocsManager()->getSVMAlloc(reinterpret_cast<const void *>(pProgram->getGlobalSurface()->getGpuAddress())));
|
||||
}
|
||||
|
||||
TEST_F(ProgramDataTest, whenGlobalVariablesAreNotExportedThenAllocateSurfacesAsNonSvm) {
|
||||
if (this->pContext->getSVMAllocsManager() == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
char globalData[128] = {};
|
||||
ProgramInfo programInfo;
|
||||
programInfo.globalVariables.initData = globalData;
|
||||
programInfo.globalVariables.size = sizeof(globalData);
|
||||
std::unique_ptr<WhiteBox<NEO::LinkerInput>> mockLinkerInput = std::make_unique<WhiteBox<NEO::LinkerInput>>();
|
||||
mockLinkerInput->traits.exportsGlobalVariables = false;
|
||||
programInfo.linkerInput = std::move(mockLinkerInput);
|
||||
this->pProgram->processProgramInfo(programInfo);
|
||||
|
||||
ASSERT_NE(nullptr, pProgram->getGlobalSurface());
|
||||
EXPECT_EQ(nullptr, this->pContext->getSVMAllocsManager()->getSVMAlloc(reinterpret_cast<const void *>(pProgram->getGlobalSurface()->getGpuAddress())));
|
||||
}
|
||||
|
||||
TEST_F(ProgramDataTest, givenConstantAllocationThatIsInUseByGpuWhenProgramIsBeingDestroyedThenItIsAddedToTemporaryAllocationList) {
|
||||
|
||||
setupConstantAllocation();
|
||||
|
||||
buildAndDecodeProgramPatchList();
|
||||
|
||||
auto &csr = *pPlatform->getDevice(0)->getDefaultEngine().commandStreamReceiver;
|
||||
auto tagAddress = csr.getTagAddress();
|
||||
auto constantSurface = pProgram->getConstantSurface();
|
||||
constantSurface->updateTaskCount(*tagAddress + 1, csr.getOsContext().getContextId());
|
||||
|
||||
EXPECT_TRUE(csr.getTemporaryAllocations().peekIsEmpty());
|
||||
delete pProgram;
|
||||
pProgram = nullptr;
|
||||
EXPECT_FALSE(csr.getTemporaryAllocations().peekIsEmpty());
|
||||
EXPECT_EQ(constantSurface, csr.getTemporaryAllocations().peekHead());
|
||||
}
|
||||
|
||||
TEST_F(ProgramDataTest, givenGlobalAllocationThatIsInUseByGpuWhenProgramIsBeingDestroyedThenItIsAddedToTemporaryAllocationList) {
|
||||
setupGlobalAllocation();
|
||||
|
||||
buildAndDecodeProgramPatchList();
|
||||
|
||||
auto &csr = *pPlatform->getDevice(0)->getDefaultEngine().commandStreamReceiver;
|
||||
auto tagAddress = csr.getTagAddress();
|
||||
auto globalSurface = pProgram->getGlobalSurface();
|
||||
globalSurface->updateTaskCount(*tagAddress + 1, csr.getOsContext().getContextId());
|
||||
|
||||
EXPECT_TRUE(csr.getTemporaryAllocations().peekIsEmpty());
|
||||
delete pProgram;
|
||||
pProgram = nullptr;
|
||||
EXPECT_FALSE(csr.getTemporaryAllocations().peekIsEmpty());
|
||||
EXPECT_EQ(globalSurface, csr.getTemporaryAllocations().peekHead());
|
||||
}
|
||||
|
||||
TEST_F(ProgramDataTest, GivenDeviceForcing32BitMessagesWhenConstAllocationIsPresentInProgramBinariesThen32BitStorageIsAllocated) {
|
||||
auto constSize = setupConstantAllocation();
|
||||
this->pContext->getDevice(0)->getMemoryManager()->setForce32BitAllocations(true);
|
||||
|
||||
buildAndDecodeProgramPatchList();
|
||||
|
||||
EXPECT_NE(nullptr, pProgram->getConstantSurface());
|
||||
EXPECT_EQ(0, memcmp(constValue, pProgram->getConstantSurface()->getUnderlyingBuffer(), constSize));
|
||||
|
||||
if (is64bit) {
|
||||
EXPECT_TRUE(pProgram->getConstantSurface()->is32BitAllocation());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ProgramDataTest, AllocateGlobalMemorySurfaceProgramBinaryInfo) {
|
||||
auto globalSize = setupGlobalAllocation();
|
||||
buildAndDecodeProgramPatchList();
|
||||
EXPECT_NE(nullptr, pProgram->getGlobalSurface());
|
||||
EXPECT_EQ(0, memcmp(globalValue, pProgram->getGlobalSurface()->getUnderlyingBuffer(), globalSize));
|
||||
}
|
||||
|
||||
TEST_F(ProgramDataTest, Given32BitDeviceWhenGlobalMemorySurfaceIsPresentThenItHas32BitStorage) {
|
||||
char globalValue[] = "55667788";
|
||||
size_t globalSize = strlen(globalValue) + 1;
|
||||
this->pContext->getDevice(0)->getMemoryManager()->setForce32BitAllocations(true);
|
||||
EXPECT_EQ(nullptr, pProgram->getGlobalSurface());
|
||||
|
||||
SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo allocateGlobalMemorySurface;
|
||||
allocateGlobalMemorySurface.Token = PATCH_TOKEN_ALLOCATE_GLOBAL_MEMORY_SURFACE_PROGRAM_BINARY_INFO;
|
||||
allocateGlobalMemorySurface.Size = static_cast<uint32_t>(sizeof(SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo));
|
||||
|
||||
allocateGlobalMemorySurface.GlobalBufferIndex = 0;
|
||||
allocateGlobalMemorySurface.InlineDataSize = static_cast<uint32_t>(globalSize);
|
||||
|
||||
cl_char *pAllocateGlobalMemorySurface = new cl_char[allocateGlobalMemorySurface.Size + globalSize];
|
||||
|
||||
memcpy_s(pAllocateGlobalMemorySurface,
|
||||
sizeof(SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo),
|
||||
&allocateGlobalMemorySurface,
|
||||
sizeof(SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo));
|
||||
|
||||
memcpy_s((cl_char *)pAllocateGlobalMemorySurface + sizeof(allocateGlobalMemorySurface), globalSize, globalValue, globalSize);
|
||||
|
||||
pProgramPatchList = (void *)pAllocateGlobalMemorySurface;
|
||||
programPatchListSize = static_cast<uint32_t>(allocateGlobalMemorySurface.Size + globalSize);
|
||||
|
||||
buildAndDecodeProgramPatchList();
|
||||
|
||||
EXPECT_NE(nullptr, pProgram->getGlobalSurface());
|
||||
EXPECT_EQ(0, memcmp(globalValue, pProgram->getGlobalSurface()->getUnderlyingBuffer(), globalSize));
|
||||
if (is64bit) {
|
||||
EXPECT_TRUE(pProgram->getGlobalSurface()->is32BitAllocation());
|
||||
}
|
||||
|
||||
delete[] pAllocateGlobalMemorySurface;
|
||||
}
|
||||
|
||||
TEST(ProgramScopeMetadataTest, WhenPatchingGlobalSurfaceThenPickProperSourceBuffer) {
|
||||
MockExecutionEnvironment execEnv;
|
||||
MockClDevice device{new MockDevice};
|
||||
execEnv.memoryManager = std::make_unique<MockMemoryManager>();
|
||||
PatchTokensTestData::ValidProgramWithMixedGlobalVarAndConstSurfacesAndPointers decodedProgram;
|
||||
decodedProgram.globalPointerMutable->GlobalPointerOffset = 0U;
|
||||
decodedProgram.constantPointerMutable->ConstantPointerOffset = 0U;
|
||||
memset(decodedProgram.globalSurfMutable + 1, 0U, sizeof(uintptr_t));
|
||||
memset(decodedProgram.constSurfMutable + 1, 0U, sizeof(uintptr_t));
|
||||
ProgramInfo programInfo;
|
||||
MockProgram program(execEnv);
|
||||
program.pDevice = &device.getDevice();
|
||||
NEO::populateProgramInfo(programInfo, decodedProgram);
|
||||
program.processProgramInfo(programInfo);
|
||||
ASSERT_NE(nullptr, program.globalSurface);
|
||||
ASSERT_NE(nullptr, program.constantSurface);
|
||||
ASSERT_NE(nullptr, program.globalSurface->getUnderlyingBuffer());
|
||||
ASSERT_NE(nullptr, program.constantSurface->getUnderlyingBuffer());
|
||||
EXPECT_EQ(static_cast<uintptr_t>(program.globalSurface->getGpuAddressToPatch()), *reinterpret_cast<uintptr_t *>(program.constantSurface->getUnderlyingBuffer()));
|
||||
EXPECT_EQ(static_cast<uintptr_t>(program.constantSurface->getGpuAddressToPatch()), *reinterpret_cast<uintptr_t *>(program.globalSurface->getUnderlyingBuffer()));
|
||||
}
|
||||
|
||||
TEST_F(ProgramDataTest, GivenProgramWith32bitPointerOptWhenProgramScopeConstantBufferPatchTokensAreReadThenConstantPointerOffsetIsPatchedWith32bitPointer) {
|
||||
cl_device_id device = pPlatform->getClDevice(0);
|
||||
CreateProgramWithSource(pContext, &device, "CopyBuffer_simd16.cl");
|
||||
ASSERT_NE(nullptr, pProgram);
|
||||
|
||||
MockProgram *prog = pProgram;
|
||||
|
||||
// simulate case when constant surface was not allocated
|
||||
EXPECT_EQ(nullptr, prog->getConstantSurface());
|
||||
ProgramInfo programInfo;
|
||||
programInfo.prepareLinkerInputStorage();
|
||||
NEO::LinkerInput::RelocationInfo relocInfo;
|
||||
relocInfo.relocationSegment = NEO::SegmentType::GlobalConstants;
|
||||
relocInfo.symbolSegment = NEO::SegmentType::GlobalConstants;
|
||||
relocInfo.offset = 0U;
|
||||
relocInfo.type = NEO::LinkerInput::RelocationInfo::Type::Address;
|
||||
programInfo.linkerInput->addDataRelocationInfo(relocInfo);
|
||||
programInfo.linkerInput->setPointerSize(LinkerInput::Traits::PointerSize::Ptr32bit);
|
||||
|
||||
MockBuffer constantSurface;
|
||||
ASSERT_LT(8U, constantSurface.getSize());
|
||||
prog->setConstantSurface(&constantSurface.mockGfxAllocation);
|
||||
constantSurface.mockGfxAllocation.set32BitAllocation(true);
|
||||
uint32_t *constantSurfaceStorage = reinterpret_cast<uint32_t *>(constantSurface.getCpuAddress());
|
||||
uint32_t sentinel = 0x17192329U;
|
||||
constantSurfaceStorage[0] = 0U;
|
||||
constantSurfaceStorage[1] = sentinel;
|
||||
|
||||
pProgram->linkerInput = std::move(programInfo.linkerInput);
|
||||
pProgram->linkBinary();
|
||||
uint32_t expectedAddr = static_cast<uint32_t>(constantSurface.getGraphicsAllocation()->getGpuAddressToPatch());
|
||||
EXPECT_EQ(expectedAddr, constantSurfaceStorage[0]);
|
||||
EXPECT_EQ(sentinel, constantSurfaceStorage[1]);
|
||||
constantSurface.mockGfxAllocation.set32BitAllocation(false);
|
||||
prog->setConstantSurface(nullptr);
|
||||
}
|
||||
|
||||
TEST_F(ProgramDataTest, GivenProgramWith32bitPointerOptWhenProgramScopeGlobalPointerPatchTokensAreReadThenGlobalPointerOffsetIsPatchedWith32bitPointer) {
|
||||
cl_device_id device = pPlatform->getClDevice(0);
|
||||
CreateProgramWithSource(pContext, &device, "CopyBuffer_simd16.cl");
|
||||
ASSERT_NE(nullptr, pProgram);
|
||||
|
||||
MockProgram *prog = pProgram;
|
||||
|
||||
// simulate case when constant surface was not allocated
|
||||
EXPECT_EQ(nullptr, prog->getConstantSurface());
|
||||
|
||||
ProgramInfo programInfo;
|
||||
programInfo.prepareLinkerInputStorage();
|
||||
NEO::LinkerInput::RelocationInfo relocInfo;
|
||||
relocInfo.relocationSegment = NEO::SegmentType::GlobalVariables;
|
||||
relocInfo.symbolSegment = NEO::SegmentType::GlobalVariables;
|
||||
relocInfo.offset = 0U;
|
||||
relocInfo.type = NEO::LinkerInput::RelocationInfo::Type::Address;
|
||||
programInfo.linkerInput->addDataRelocationInfo(relocInfo);
|
||||
programInfo.linkerInput->setPointerSize(LinkerInput::Traits::PointerSize::Ptr32bit);
|
||||
|
||||
MockBuffer globalSurface;
|
||||
ASSERT_LT(8U, globalSurface.getSize());
|
||||
prog->setGlobalSurface(&globalSurface.mockGfxAllocation);
|
||||
globalSurface.mockGfxAllocation.set32BitAllocation(true);
|
||||
uint32_t *globalSurfaceStorage = reinterpret_cast<uint32_t *>(globalSurface.getCpuAddress());
|
||||
uint32_t sentinel = 0x17192329U;
|
||||
globalSurfaceStorage[0] = 0U;
|
||||
globalSurfaceStorage[1] = sentinel;
|
||||
|
||||
pProgram->linkerInput = std::move(programInfo.linkerInput);
|
||||
pProgram->linkBinary();
|
||||
uint32_t expectedAddr = static_cast<uint32_t>(globalSurface.getGraphicsAllocation()->getGpuAddressToPatch());
|
||||
EXPECT_EQ(expectedAddr, globalSurfaceStorage[0]);
|
||||
EXPECT_EQ(sentinel, globalSurfaceStorage[1]);
|
||||
globalSurface.mockGfxAllocation.set32BitAllocation(false);
|
||||
prog->setGlobalSurface(nullptr);
|
||||
}
|
||||
|
||||
TEST_F(ProgramDataTest, givenSymbolTablePatchTokenThenLinkerInputIsCreated) {
|
||||
SPatchFunctionTableInfo token;
|
||||
token.Token = PATCH_TOKEN_PROGRAM_SYMBOL_TABLE;
|
||||
token.Size = static_cast<uint32_t>(sizeof(SPatchFunctionTableInfo));
|
||||
token.NumEntries = 0;
|
||||
|
||||
pProgramPatchList = &token;
|
||||
programPatchListSize = token.Size;
|
||||
|
||||
buildAndDecodeProgramPatchList();
|
||||
|
||||
EXPECT_NE(nullptr, pProgram->getLinkerInput());
|
||||
}
|
||||
|
||||
TEST(ProgramLinkBinaryTest, whenLinkerInputEmptyThenLinkSuccessful) {
|
||||
auto linkerInput = std::make_unique<WhiteBox<LinkerInput>>();
|
||||
NEO::ExecutionEnvironment env;
|
||||
MockProgram program{env};
|
||||
program.linkerInput = std::move(linkerInput);
|
||||
auto ret = program.linkBinary();
|
||||
EXPECT_EQ(CL_SUCCESS, ret);
|
||||
}
|
||||
|
||||
TEST(ProgramLinkBinaryTest, whenLinkerUnresolvedExternalThenLinkFailedAndBuildLogAvailable) {
|
||||
auto linkerInput = std::make_unique<WhiteBox<LinkerInput>>();
|
||||
NEO::LinkerInput::RelocationInfo relocation = {};
|
||||
relocation.symbolName = "A";
|
||||
relocation.offset = 0;
|
||||
linkerInput->relocations.push_back(NEO::LinkerInput::Relocations{relocation});
|
||||
linkerInput->traits.requiresPatchingOfInstructionSegments = true;
|
||||
NEO::ExecutionEnvironment env;
|
||||
MockProgram program{env};
|
||||
KernelInfo kernelInfo = {};
|
||||
kernelInfo.name = "onlyKernel";
|
||||
std::vector<char> kernelHeap;
|
||||
kernelHeap.resize(32, 7);
|
||||
kernelInfo.heapInfo.pKernelHeap = kernelHeap.data();
|
||||
iOpenCL::SKernelBinaryHeaderCommon kernelHeader = {};
|
||||
kernelHeader.KernelHeapSize = static_cast<uint32_t>(kernelHeap.size());
|
||||
kernelInfo.heapInfo.pKernelHeader = &kernelHeader;
|
||||
program.getKernelInfoArray().push_back(&kernelInfo);
|
||||
program.linkerInput = std::move(linkerInput);
|
||||
|
||||
EXPECT_EQ(nullptr, program.getBuildLog(nullptr));
|
||||
auto ret = program.linkBinary();
|
||||
EXPECT_NE(CL_SUCCESS, ret);
|
||||
program.getKernelInfoArray().clear();
|
||||
auto buildLog = program.getBuildLog(nullptr);
|
||||
ASSERT_NE(nullptr, buildLog);
|
||||
Linker::UnresolvedExternals expectedUnresolvedExternals;
|
||||
expectedUnresolvedExternals.push_back(Linker::UnresolvedExternal{relocation, 0, false});
|
||||
auto expectedError = constructLinkerErrorMessage(expectedUnresolvedExternals, std::vector<std::string>{"kernel : " + kernelInfo.name});
|
||||
EXPECT_THAT(buildLog, ::testing::HasSubstr(expectedError));
|
||||
}
|
||||
|
||||
TEST_F(ProgramDataTest, whenLinkerInputValidThenIsaIsProperlyPatched) {
|
||||
auto linkerInput = std::make_unique<WhiteBox<LinkerInput>>();
|
||||
linkerInput->symbols["A"] = NEO::SymbolInfo{4U, 4U, NEO::SegmentType::GlobalVariables};
|
||||
linkerInput->symbols["B"] = NEO::SymbolInfo{8U, 4U, NEO::SegmentType::GlobalConstants};
|
||||
linkerInput->symbols["C"] = NEO::SymbolInfo{16U, 4U, NEO::SegmentType::Instructions};
|
||||
|
||||
auto relocationType = NEO::LinkerInput::RelocationInfo::Type::Address;
|
||||
linkerInput->relocations.push_back({NEO::LinkerInput::RelocationInfo{"A", 8U, relocationType},
|
||||
NEO::LinkerInput::RelocationInfo{"B", 16U, relocationType},
|
||||
NEO::LinkerInput::RelocationInfo{"C", 24U, relocationType}});
|
||||
linkerInput->traits.requiresPatchingOfInstructionSegments = true;
|
||||
linkerInput->exportedFunctionsSegmentId = 0;
|
||||
NEO::ExecutionEnvironment env;
|
||||
MockProgram program{env};
|
||||
KernelInfo kernelInfo = {};
|
||||
kernelInfo.name = "onlyKernel";
|
||||
std::vector<char> kernelHeap;
|
||||
kernelHeap.resize(32, 7);
|
||||
kernelInfo.heapInfo.pKernelHeap = kernelHeap.data();
|
||||
iOpenCL::SKernelBinaryHeaderCommon kernelHeader = {};
|
||||
kernelHeader.KernelHeapSize = static_cast<uint32_t>(kernelHeap.size());
|
||||
kernelInfo.heapInfo.pKernelHeader = &kernelHeader;
|
||||
MockGraphicsAllocation kernelIsa(kernelHeap.data(), kernelHeap.size());
|
||||
kernelInfo.kernelAllocation = &kernelIsa;
|
||||
program.getKernelInfoArray().push_back(&kernelInfo);
|
||||
program.linkerInput = std::move(linkerInput);
|
||||
|
||||
program.exportedFunctionsSurface = kernelInfo.kernelAllocation;
|
||||
std::vector<char> globalVariablesBuffer;
|
||||
globalVariablesBuffer.resize(32, 7);
|
||||
std::vector<char> globalConstantsBuffer;
|
||||
globalConstantsBuffer.resize(32, 7);
|
||||
program.globalSurface = new MockGraphicsAllocation(globalVariablesBuffer.data(), globalVariablesBuffer.size());
|
||||
program.constantSurface = new MockGraphicsAllocation(globalConstantsBuffer.data(), globalConstantsBuffer.size());
|
||||
|
||||
program.pDevice = &this->pContext->getDevice(0)->getDevice();
|
||||
|
||||
auto ret = program.linkBinary();
|
||||
EXPECT_EQ(CL_SUCCESS, ret);
|
||||
|
||||
linkerInput.reset(static_cast<WhiteBox<LinkerInput> *>(program.linkerInput.release()));
|
||||
|
||||
for (size_t i = 0; i < linkerInput->relocations.size(); ++i) {
|
||||
auto expectedPatch = program.globalSurface->getGpuAddress() + linkerInput->symbols[linkerInput->relocations[0][0].symbolName].offset;
|
||||
auto relocationAddress = kernelHeap.data() + linkerInput->relocations[0][0].offset;
|
||||
|
||||
EXPECT_EQ(static_cast<uintptr_t>(expectedPatch), *reinterpret_cast<uintptr_t *>(relocationAddress)) << i;
|
||||
}
|
||||
|
||||
program.getKernelInfoArray().clear();
|
||||
delete program.globalSurface;
|
||||
program.globalSurface = nullptr;
|
||||
delete program.constantSurface;
|
||||
program.constantSurface = nullptr;
|
||||
}
|
||||
|
||||
TEST_F(ProgramDataTest, whenRelocationsAreNotNeededThenIsaIsPreserved) {
|
||||
auto linkerInput = std::make_unique<WhiteBox<LinkerInput>>();
|
||||
linkerInput->symbols["A"] = NEO::SymbolInfo{4U, 4U, NEO::SegmentType::GlobalVariables};
|
||||
linkerInput->symbols["B"] = NEO::SymbolInfo{8U, 4U, NEO::SegmentType::GlobalConstants};
|
||||
|
||||
NEO::ExecutionEnvironment env;
|
||||
MockProgram program{env};
|
||||
KernelInfo kernelInfo = {};
|
||||
kernelInfo.name = "onlyKernel";
|
||||
std::vector<char> kernelHeapData;
|
||||
kernelHeapData.resize(32, 7);
|
||||
std::vector<char> kernelHeap(kernelHeapData.begin(), kernelHeapData.end());
|
||||
kernelInfo.heapInfo.pKernelHeap = kernelHeap.data();
|
||||
iOpenCL::SKernelBinaryHeaderCommon kernelHeader = {};
|
||||
kernelHeader.KernelHeapSize = static_cast<uint32_t>(kernelHeap.size());
|
||||
kernelInfo.heapInfo.pKernelHeader = &kernelHeader;
|
||||
MockGraphicsAllocation kernelIsa(kernelHeap.data(), kernelHeap.size());
|
||||
kernelInfo.kernelAllocation = &kernelIsa;
|
||||
program.getKernelInfoArray().push_back(&kernelInfo);
|
||||
program.linkerInput = std::move(linkerInput);
|
||||
|
||||
std::vector<char> globalVariablesBuffer;
|
||||
globalVariablesBuffer.resize(32, 7);
|
||||
std::vector<char> globalConstantsBuffer;
|
||||
globalConstantsBuffer.resize(32, 7);
|
||||
program.globalSurface = new MockGraphicsAllocation(globalVariablesBuffer.data(), globalVariablesBuffer.size());
|
||||
program.constantSurface = new MockGraphicsAllocation(globalConstantsBuffer.data(), globalConstantsBuffer.size());
|
||||
|
||||
program.pDevice = &this->pContext->getDevice(0)->getDevice();
|
||||
|
||||
auto ret = program.linkBinary();
|
||||
EXPECT_EQ(CL_SUCCESS, ret);
|
||||
EXPECT_EQ(kernelHeapData, kernelHeap);
|
||||
|
||||
program.getKernelInfoArray().clear();
|
||||
delete program.globalSurface;
|
||||
program.globalSurface = nullptr;
|
||||
delete program.constantSurface;
|
||||
program.constantSurface = nullptr;
|
||||
}
|
||||
100
opencl/test/unit_test/program/program_from_binary.h
Normal file
100
opencl/test/unit_test/program/program_from_binary.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "opencl/source/built_ins/built_ins.h"
|
||||
|
||||
#include "fixtures/context_fixture.h"
|
||||
#include "fixtures/device_fixture.h"
|
||||
#include "fixtures/program_fixture.h"
|
||||
#include "mocks/mock_context.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace NEO {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// ProgramFromBinaryTest Test Fixture
|
||||
// Used to test the Program class
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class ProgramFromBinaryTest : public DeviceFixture,
|
||||
public ContextFixture,
|
||||
public ProgramFixture,
|
||||
public testing::TestWithParam<std::tuple<const char *, const char *>> {
|
||||
|
||||
using ContextFixture::SetUp;
|
||||
|
||||
protected:
|
||||
ProgramFromBinaryTest() : BinaryFileName(nullptr),
|
||||
KernelName(nullptr),
|
||||
retVal(CL_SUCCESS) {
|
||||
}
|
||||
|
||||
void SetUp() override {
|
||||
std::tie(BinaryFileName, KernelName) = GetParam();
|
||||
|
||||
DeviceFixture::SetUp();
|
||||
|
||||
cl_device_id device = pClDevice;
|
||||
ContextFixture::SetUp(1, &device);
|
||||
ProgramFixture::SetUp();
|
||||
|
||||
if (options.size())
|
||||
CreateProgramFromBinary(pContext, &device, BinaryFileName, options);
|
||||
else
|
||||
CreateProgramFromBinary(pContext, &device, BinaryFileName);
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
knownSource.reset();
|
||||
ProgramFixture::TearDown();
|
||||
ContextFixture::TearDown();
|
||||
DeviceFixture::TearDown();
|
||||
}
|
||||
|
||||
void setOptions(std::string &optionsIn) {
|
||||
options = optionsIn;
|
||||
}
|
||||
|
||||
const char *BinaryFileName;
|
||||
const char *KernelName;
|
||||
cl_int retVal;
|
||||
std::string options;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// ProgramSimpleFixture Test Fixture
|
||||
// Used to test the Program class, but not using parameters
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class ProgramSimpleFixture : public DeviceFixture,
|
||||
public ContextFixture,
|
||||
public ProgramFixture {
|
||||
using ContextFixture::SetUp;
|
||||
|
||||
public:
|
||||
ProgramSimpleFixture() : retVal(CL_SUCCESS) {
|
||||
}
|
||||
|
||||
void SetUp() override {
|
||||
DeviceFixture::SetUp();
|
||||
|
||||
cl_device_id device = pClDevice;
|
||||
ContextFixture::SetUp(1, &device);
|
||||
ProgramFixture::SetUp();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
knownSource.reset();
|
||||
ProgramFixture::TearDown();
|
||||
ContextFixture::TearDown();
|
||||
DeviceFixture::TearDown();
|
||||
}
|
||||
|
||||
protected:
|
||||
cl_int retVal;
|
||||
};
|
||||
} // namespace NEO
|
||||
316
opencl/test/unit_test/program/program_nonuniform.cpp
Normal file
316
opencl/test/unit_test/program/program_nonuniform.cpp
Normal file
@@ -0,0 +1,316 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "core/command_stream/command_stream_receiver_hw.h"
|
||||
#include "core/helpers/aligned_memory.h"
|
||||
#include "core/helpers/hash.h"
|
||||
#include "core/helpers/ptr_math.h"
|
||||
#include "core/memory_manager/graphics_allocation.h"
|
||||
#include "opencl/source/helpers/hardware_commands_helper.h"
|
||||
#include "opencl/source/kernel/kernel.h"
|
||||
#include "test.h"
|
||||
|
||||
#include "fixtures/device_fixture.h"
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "helpers/kernel_binary_helper.h"
|
||||
#include "libult/ult_command_stream_receiver.h"
|
||||
#include "mocks/mock_kernel.h"
|
||||
#include "mocks/mock_program.h"
|
||||
#include "program/program_from_binary.h"
|
||||
#include "program/program_with_source.h"
|
||||
#include "program_tests.h"
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
class MyMockProgram : public MockProgram {
|
||||
public:
|
||||
MyMockProgram() : MockProgram(*new ExecutionEnvironment()), executionEnvironment(&this->peekExecutionEnvironment()) {}
|
||||
|
||||
private:
|
||||
std::unique_ptr<ExecutionEnvironment> executionEnvironment;
|
||||
};
|
||||
|
||||
TEST(ProgramNonUniform, UpdateAllowNonUniform) {
|
||||
MyMockProgram pm;
|
||||
EXPECT_FALSE(pm.getAllowNonUniform());
|
||||
EXPECT_EQ(12u, pm.getProgramOptionVersion());
|
||||
pm.setBuildOptions(nullptr);
|
||||
pm.updateNonUniformFlag();
|
||||
EXPECT_FALSE(pm.getAllowNonUniform());
|
||||
EXPECT_EQ(12u, pm.getProgramOptionVersion());
|
||||
}
|
||||
|
||||
TEST(ProgramNonUniform, UpdateAllowNonUniform12) {
|
||||
MyMockProgram pm;
|
||||
EXPECT_FALSE(pm.getAllowNonUniform());
|
||||
EXPECT_EQ(12u, pm.getProgramOptionVersion());
|
||||
pm.setBuildOptions("-cl-std=CL1.2");
|
||||
pm.updateNonUniformFlag();
|
||||
EXPECT_FALSE(pm.getAllowNonUniform());
|
||||
EXPECT_EQ(12u, pm.getProgramOptionVersion());
|
||||
}
|
||||
|
||||
TEST(ProgramNonUniform, UpdateAllowNonUniform20) {
|
||||
MyMockProgram pm;
|
||||
EXPECT_FALSE(pm.getAllowNonUniform());
|
||||
EXPECT_EQ(12u, pm.getProgramOptionVersion());
|
||||
pm.setBuildOptions("-cl-std=CL2.0");
|
||||
pm.updateNonUniformFlag();
|
||||
EXPECT_TRUE(pm.getAllowNonUniform());
|
||||
EXPECT_EQ(20u, pm.getProgramOptionVersion());
|
||||
}
|
||||
|
||||
TEST(ProgramNonUniform, UpdateAllowNonUniform21) {
|
||||
MyMockProgram pm;
|
||||
EXPECT_FALSE(pm.getAllowNonUniform());
|
||||
EXPECT_EQ(12u, pm.getProgramOptionVersion());
|
||||
pm.setBuildOptions("-cl-std=CL2.1");
|
||||
pm.updateNonUniformFlag();
|
||||
EXPECT_TRUE(pm.getAllowNonUniform());
|
||||
EXPECT_EQ(21u, pm.getProgramOptionVersion());
|
||||
}
|
||||
|
||||
TEST(ProgramNonUniform, UpdateAllowNonUniform20UniformFlag) {
|
||||
MyMockProgram pm;
|
||||
EXPECT_FALSE(pm.getAllowNonUniform());
|
||||
EXPECT_EQ(12u, pm.getProgramOptionVersion());
|
||||
pm.setBuildOptions("-cl-std=CL2.0 -cl-uniform-work-group-size");
|
||||
pm.updateNonUniformFlag();
|
||||
EXPECT_FALSE(pm.getAllowNonUniform());
|
||||
EXPECT_EQ(20u, pm.getProgramOptionVersion());
|
||||
}
|
||||
|
||||
TEST(ProgramNonUniform, UpdateAllowNonUniform21UniformFlag) {
|
||||
MyMockProgram pm;
|
||||
EXPECT_FALSE(pm.getAllowNonUniform());
|
||||
EXPECT_EQ(12u, pm.getProgramOptionVersion());
|
||||
pm.setBuildOptions("-cl-std=CL2.1 -cl-uniform-work-group-size");
|
||||
pm.updateNonUniformFlag();
|
||||
EXPECT_FALSE(pm.getAllowNonUniform());
|
||||
EXPECT_EQ(21u, pm.getProgramOptionVersion());
|
||||
}
|
||||
|
||||
TEST(KernelNonUniform, GetAllowNonUniformFlag) {
|
||||
KernelInfo ki;
|
||||
MockClDevice d{new MockDevice};
|
||||
MockProgram pm(*d.getExecutionEnvironment());
|
||||
struct KernelMock : Kernel {
|
||||
KernelMock(Program *p, KernelInfo &ki, ClDevice &d)
|
||||
: Kernel(p, ki, d) {
|
||||
}
|
||||
};
|
||||
|
||||
KernelMock k{&pm, ki, d};
|
||||
pm.setAllowNonUniform(false);
|
||||
EXPECT_FALSE(k.getAllowNonUniform());
|
||||
pm.setAllowNonUniform(true);
|
||||
EXPECT_TRUE(k.getAllowNonUniform());
|
||||
pm.setAllowNonUniform(false);
|
||||
EXPECT_FALSE(k.getAllowNonUniform());
|
||||
}
|
||||
|
||||
TEST(ProgramNonUniform, UpdateAllowNonUniformOutcomeUniformFlag) {
|
||||
ExecutionEnvironment executionEnvironment;
|
||||
MockProgram pm(executionEnvironment);
|
||||
MockProgram pm1(executionEnvironment);
|
||||
MockProgram pm2(executionEnvironment);
|
||||
const MockProgram *inputPrograms[] = {&pm1, &pm2};
|
||||
cl_uint numInputPrograms = 2;
|
||||
|
||||
pm1.setAllowNonUniform(false);
|
||||
pm2.setAllowNonUniform(false);
|
||||
pm.updateNonUniformFlag((const Program **)inputPrograms, numInputPrograms);
|
||||
EXPECT_FALSE(pm.getAllowNonUniform());
|
||||
|
||||
pm1.setAllowNonUniform(false);
|
||||
pm2.setAllowNonUniform(true);
|
||||
pm.updateNonUniformFlag((const Program **)inputPrograms, numInputPrograms);
|
||||
EXPECT_FALSE(pm.getAllowNonUniform());
|
||||
|
||||
pm1.setAllowNonUniform(true);
|
||||
pm2.setAllowNonUniform(false);
|
||||
pm.updateNonUniformFlag((const Program **)inputPrograms, numInputPrograms);
|
||||
EXPECT_FALSE(pm.getAllowNonUniform());
|
||||
|
||||
pm1.setAllowNonUniform(true);
|
||||
pm2.setAllowNonUniform(true);
|
||||
pm.updateNonUniformFlag((const Program **)inputPrograms, numInputPrograms);
|
||||
EXPECT_TRUE(pm.getAllowNonUniform());
|
||||
}
|
||||
|
||||
#include "opencl/source/kernel/kernel.h"
|
||||
|
||||
#include "command_queue/command_queue_fixture.h"
|
||||
#include "fixtures/context_fixture.h"
|
||||
#include "fixtures/platform_fixture.h"
|
||||
#include "fixtures/program_fixture.h"
|
||||
#include "mocks/mock_program.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace NEO {
|
||||
|
||||
class ProgramNonUniformTest : public ContextFixture,
|
||||
public PlatformFixture,
|
||||
public ProgramFixture,
|
||||
public CommandQueueHwFixture,
|
||||
public testing::Test {
|
||||
|
||||
using ContextFixture::SetUp;
|
||||
using PlatformFixture::SetUp;
|
||||
|
||||
protected:
|
||||
ProgramNonUniformTest() {
|
||||
}
|
||||
|
||||
void SetUp() override {
|
||||
PlatformFixture::SetUp();
|
||||
device = pPlatform->getClDevice(0);
|
||||
ContextFixture::SetUp(1, &device);
|
||||
ProgramFixture::SetUp();
|
||||
CommandQueueHwFixture::SetUp(pPlatform->getClDevice(0), 0);
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
CommandQueueHwFixture::TearDown();
|
||||
ProgramFixture::TearDown();
|
||||
ContextFixture::TearDown();
|
||||
PlatformFixture::TearDown();
|
||||
}
|
||||
cl_device_id device;
|
||||
cl_int retVal = CL_SUCCESS;
|
||||
};
|
||||
|
||||
TEST_F(ProgramNonUniformTest, ExecuteKernelNonUniform21) {
|
||||
if (std::string(pPlatform->getDevice(0)->getDeviceInfo().clVersion).find("OpenCL 2.1") != std::string::npos) {
|
||||
CreateProgramFromBinary(pContext, &device, "kernel_data_param");
|
||||
auto mockProgram = (MockProgram *)pProgram;
|
||||
ASSERT_NE(nullptr, mockProgram);
|
||||
|
||||
mockProgram->setBuildOptions("-cl-std=CL2.1");
|
||||
retVal = mockProgram->build(
|
||||
1,
|
||||
&device,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
false);
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
|
||||
auto pKernelInfo = mockProgram->Program::getKernelInfo("test_get_local_size");
|
||||
EXPECT_NE(nullptr, pKernelInfo);
|
||||
|
||||
// create a kernel
|
||||
auto pKernel = Kernel::create<MockKernel>(mockProgram, *pKernelInfo, &retVal);
|
||||
ASSERT_EQ(CL_SUCCESS, retVal);
|
||||
ASSERT_NE(nullptr, pKernel);
|
||||
|
||||
size_t globalWorkSize[3] = {12, 12, 12};
|
||||
size_t localWorkSize[3] = {11, 12, 1};
|
||||
|
||||
retVal = pCmdQ->enqueueKernel(
|
||||
pKernel,
|
||||
3,
|
||||
nullptr,
|
||||
globalWorkSize,
|
||||
localWorkSize,
|
||||
0,
|
||||
nullptr,
|
||||
nullptr);
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
|
||||
delete pKernel;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ProgramNonUniformTest, ExecuteKernelNonUniform20) {
|
||||
if (std::string(pPlatform->getDevice(0)->getDeviceInfo().clVersion).find("OpenCL 2.0") != std::string::npos) {
|
||||
CreateProgramFromBinary(pContext, &device, "kernel_data_param");
|
||||
auto mockProgram = pProgram;
|
||||
ASSERT_NE(nullptr, mockProgram);
|
||||
|
||||
mockProgram->setBuildOptions("-cl-std=CL2.0");
|
||||
retVal = mockProgram->build(
|
||||
1,
|
||||
&device,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
false);
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
|
||||
auto pKernelInfo = mockProgram->Program::getKernelInfo("test_get_local_size");
|
||||
EXPECT_NE(nullptr, pKernelInfo);
|
||||
|
||||
// create a kernel
|
||||
auto pKernel = Kernel::create<MockKernel>(mockProgram, *pKernelInfo, &retVal);
|
||||
ASSERT_EQ(CL_SUCCESS, retVal);
|
||||
ASSERT_NE(nullptr, pKernel);
|
||||
|
||||
size_t globalWorkSize[3] = {12, 12, 12};
|
||||
size_t localWorkSize[3] = {11, 12, 12};
|
||||
|
||||
retVal = pCmdQ->enqueueKernel(
|
||||
pKernel,
|
||||
3,
|
||||
nullptr,
|
||||
globalWorkSize,
|
||||
localWorkSize,
|
||||
0,
|
||||
nullptr,
|
||||
nullptr);
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
|
||||
delete pKernel;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ProgramNonUniformTest, ExecuteKernelNonUniform12) {
|
||||
CreateProgramFromBinary(pContext, &device, "kernel_data_param");
|
||||
auto mockProgram = pProgram;
|
||||
ASSERT_NE(nullptr, mockProgram);
|
||||
|
||||
mockProgram->setBuildOptions("-cl-std=CL1.2");
|
||||
retVal = mockProgram->build(
|
||||
1,
|
||||
&device,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
false);
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
|
||||
auto pKernelInfo = mockProgram->Program::getKernelInfo("test_get_local_size");
|
||||
EXPECT_NE(nullptr, pKernelInfo);
|
||||
|
||||
// create a kernel
|
||||
auto pKernel = Kernel::create<MockKernel>(mockProgram, *pKernelInfo, &retVal);
|
||||
ASSERT_EQ(CL_SUCCESS, retVal);
|
||||
ASSERT_NE(nullptr, pKernel);
|
||||
|
||||
size_t globalWorkSize[3] = {12, 12, 12};
|
||||
size_t localWorkSize[3] = {11, 12, 12};
|
||||
|
||||
retVal = pCmdQ->enqueueKernel(
|
||||
pKernel,
|
||||
3,
|
||||
nullptr,
|
||||
globalWorkSize,
|
||||
localWorkSize,
|
||||
0,
|
||||
nullptr,
|
||||
nullptr);
|
||||
EXPECT_EQ(CL_INVALID_WORK_GROUP_SIZE, retVal);
|
||||
|
||||
delete pKernel;
|
||||
}
|
||||
} // namespace NEO
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "core/compiler_interface/compiler_interface.h"
|
||||
#include "core/compiler_interface/compiler_interface.inl"
|
||||
#include "core/helpers/file_io.h"
|
||||
#include "core/helpers/hw_info.h"
|
||||
#include "core/unit_tests/helpers/debug_manager_state_restore.h"
|
||||
|
||||
#include "fixtures/device_fixture.h"
|
||||
#include "global_environment.h"
|
||||
#include "gmock/gmock.h"
|
||||
#include "helpers/test_files.h"
|
||||
#include "mocks/mock_cif.h"
|
||||
#include "mocks/mock_compilers.h"
|
||||
#include "mocks/mock_program.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
struct UpdateSpecConstantsTest : public ::testing::Test {
|
||||
void SetUp() override {
|
||||
mockProgram.reset(new MockProgram(executionEnvironment));
|
||||
|
||||
mockProgram->specConstantsIds.reset(new MockCIFBuffer());
|
||||
mockProgram->specConstantsSizes.reset(new MockCIFBuffer());
|
||||
mockProgram->specConstantsValues.reset(new MockCIFBuffer());
|
||||
|
||||
mockProgram->specConstantsIds->PushBackRawCopy(1);
|
||||
mockProgram->specConstantsIds->PushBackRawCopy(2);
|
||||
mockProgram->specConstantsIds->PushBackRawCopy(3);
|
||||
|
||||
mockProgram->specConstantsSizes->PushBackRawCopy(sizeof(char));
|
||||
mockProgram->specConstantsSizes->PushBackRawCopy(sizeof(uint16_t));
|
||||
mockProgram->specConstantsSizes->PushBackRawCopy(sizeof(int));
|
||||
|
||||
mockProgram->specConstantsValues->PushBackRawCopy(&val1);
|
||||
mockProgram->specConstantsValues->PushBackRawCopy(&val2);
|
||||
mockProgram->specConstantsValues->PushBackRawCopy(&val3);
|
||||
|
||||
values = mockProgram->specConstantsValues->GetMemory<const void *>();
|
||||
|
||||
EXPECT_EQ(val1, *reinterpret_cast<const char *>(values[0]));
|
||||
EXPECT_EQ(val2, *reinterpret_cast<const uint16_t *>(values[1]));
|
||||
EXPECT_EQ(val3, *reinterpret_cast<const int *>(values[2]));
|
||||
}
|
||||
ExecutionEnvironment executionEnvironment;
|
||||
std::unique_ptr<MockProgram> mockProgram;
|
||||
|
||||
char val1 = 5;
|
||||
uint16_t val2 = 50;
|
||||
int val3 = 500;
|
||||
const void *const *values;
|
||||
};
|
||||
|
||||
TEST_F(UpdateSpecConstantsTest, givenNewSpecConstValueWhenUpdateSpecializationConstantThenProperValueIsUpdated) {
|
||||
int newSpecConstVal3 = 5000;
|
||||
|
||||
auto ret = mockProgram->updateSpecializationConstant(3, sizeof(int), &newSpecConstVal3);
|
||||
|
||||
EXPECT_EQ(CL_SUCCESS, ret);
|
||||
EXPECT_EQ(val1, *reinterpret_cast<const char *>(values[0]));
|
||||
EXPECT_EQ(val2, *reinterpret_cast<const uint16_t *>(values[1]));
|
||||
EXPECT_EQ(newSpecConstVal3, *reinterpret_cast<const int *>(values[2]));
|
||||
}
|
||||
|
||||
TEST_F(UpdateSpecConstantsTest, givenNewSpecConstValueWithUnproperSizeWhenUpdateSpecializationConstantThenErrorIsReturned) {
|
||||
int newSpecConstVal3 = 5000;
|
||||
|
||||
auto ret = mockProgram->updateSpecializationConstant(3, 10 * sizeof(int), &newSpecConstVal3);
|
||||
|
||||
EXPECT_EQ(CL_INVALID_VALUE, ret);
|
||||
EXPECT_EQ(val1, *reinterpret_cast<const char *>(values[0]));
|
||||
EXPECT_EQ(val2, *reinterpret_cast<const uint16_t *>(values[1]));
|
||||
EXPECT_EQ(val3, *reinterpret_cast<const int *>(values[2]));
|
||||
}
|
||||
|
||||
TEST_F(UpdateSpecConstantsTest, givenNewSpecConstValueWithUnproperIdAndSizeWhenUpdateSpecializationConstantThenErrorIsReturned) {
|
||||
int newSpecConstVal3 = 5000;
|
||||
|
||||
auto ret = mockProgram->updateSpecializationConstant(4, sizeof(int), &newSpecConstVal3);
|
||||
|
||||
EXPECT_EQ(CL_INVALID_SPEC_ID, ret);
|
||||
EXPECT_EQ(val1, *reinterpret_cast<const char *>(values[0]));
|
||||
EXPECT_EQ(val2, *reinterpret_cast<const uint16_t *>(values[1]));
|
||||
EXPECT_EQ(val3, *reinterpret_cast<const int *>(values[2]));
|
||||
}
|
||||
2890
opencl/test/unit_test/program/program_tests.cpp
Normal file
2890
opencl/test/unit_test/program/program_tests.cpp
Normal file
File diff suppressed because it is too large
Load Diff
29
opencl/test/unit_test/program/program_tests.h
Normal file
29
opencl/test/unit_test/program/program_tests.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "fixtures/context_fixture.h"
|
||||
#include "fixtures/device_fixture.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
extern std::vector<const char *> BinaryFileNames;
|
||||
extern std::vector<const char *> SourceFileNames;
|
||||
extern std::vector<const char *> BinaryForSourceFileNames;
|
||||
extern std::vector<const char *> KernelNames;
|
||||
|
||||
class ProgramTests : public NEO::DeviceFixture,
|
||||
public ::testing::Test,
|
||||
public NEO::ContextFixture {
|
||||
|
||||
using NEO::ContextFixture::SetUp;
|
||||
|
||||
public:
|
||||
void SetUp() override;
|
||||
void TearDown() override;
|
||||
};
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "core/compiler_interface/compiler_interface.h"
|
||||
#include "core/device/device.h"
|
||||
#include "opencl/source/device/cl_device.h"
|
||||
#include "opencl/source/program/block_kernel_manager.h"
|
||||
|
||||
#include "fixtures/context_fixture.h"
|
||||
#include "fixtures/platform_fixture.h"
|
||||
#include "fixtures/program_fixture.h"
|
||||
#include "fixtures/run_kernel_fixture.h"
|
||||
#include "mocks/mock_context.h"
|
||||
#include "mocks/mock_program.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace NEO {
|
||||
|
||||
class ProgramWithBlockKernelsTest : public ContextFixture,
|
||||
public PlatformFixture,
|
||||
public ProgramFixture,
|
||||
public testing::Test {
|
||||
|
||||
using ContextFixture::SetUp;
|
||||
using PlatformFixture::SetUp;
|
||||
|
||||
protected:
|
||||
ProgramWithBlockKernelsTest() {
|
||||
}
|
||||
|
||||
void SetUp() override {
|
||||
PlatformFixture::SetUp();
|
||||
device = pPlatform->getClDevice(0);
|
||||
ContextFixture::SetUp(1, &device);
|
||||
ProgramFixture::SetUp();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
ProgramFixture::TearDown();
|
||||
ContextFixture::TearDown();
|
||||
PlatformFixture::TearDown();
|
||||
}
|
||||
cl_device_id device;
|
||||
cl_int retVal = CL_SUCCESS;
|
||||
};
|
||||
|
||||
TEST_F(ProgramWithBlockKernelsTest, GivenKernelWithBlockKernelsWhenProgramIsBuildingThenKernelInfosHaveCorrectNames) {
|
||||
if (std::string(pPlatform->getDevice(0)->getDeviceInfo().clVersion).find("OpenCL 2.") != std::string::npos) {
|
||||
CreateProgramFromBinary(pContext, &device, "simple_block_kernel", "-cl-std=CL2.0");
|
||||
auto mockProgram = (MockProgram *)pProgram;
|
||||
ASSERT_NE(nullptr, mockProgram);
|
||||
|
||||
retVal = mockProgram->build(
|
||||
1,
|
||||
&device,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
false);
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
|
||||
auto kernelInfo = mockProgram->Program::getKernelInfo("simple_block_kernel");
|
||||
EXPECT_NE(nullptr, kernelInfo);
|
||||
|
||||
auto blockKernelInfo = mockProgram->Program::getKernelInfo("simple_block_kernel_dispatch_0");
|
||||
EXPECT_EQ(nullptr, blockKernelInfo);
|
||||
|
||||
std::vector<const KernelInfo *> blockKernelInfos(mockProgram->blockKernelManager->getCount());
|
||||
|
||||
for (size_t i = 0; i < mockProgram->blockKernelManager->getCount(); i++) {
|
||||
const KernelInfo *blockKernelInfo = mockProgram->blockKernelManager->getBlockKernelInfo(i);
|
||||
EXPECT_NE(nullptr, blockKernelInfo);
|
||||
blockKernelInfos[i] = blockKernelInfo;
|
||||
}
|
||||
|
||||
bool blockKernelFound = false;
|
||||
for (size_t i = 0; i < mockProgram->blockKernelManager->getCount(); i++) {
|
||||
if (blockKernelInfos[i]->name.find("simple_block_kernel_dispatch") != std::string::npos) {
|
||||
blockKernelFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_TRUE(blockKernelFound);
|
||||
|
||||
} else {
|
||||
EXPECT_EQ(nullptr, pProgram);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ProgramWithBlockKernelsTest, GivenKernelWithBlockKernelsWhenProgramIsLinkedThenBlockKernelsAreSeparated) {
|
||||
if (std::string(pPlatform->getDevice(0)->getDeviceInfo().clVersion).find("OpenCL 2.0") != std::string::npos) {
|
||||
CreateProgramFromBinary(pContext, &device, "simple_block_kernel", "-cl-std=CL2.0");
|
||||
const char *buildOptions = "-cl-std=CL2.0";
|
||||
|
||||
overwriteBuiltInBinaryName(
|
||||
pPlatform->getDevice(0),
|
||||
"simple_block_kernel", true);
|
||||
|
||||
ASSERT_NE(nullptr, pProgram);
|
||||
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
Program *programLinked = new Program(*pPlatform->peekExecutionEnvironment(), pContext, false, nullptr);
|
||||
cl_program program = pProgram;
|
||||
|
||||
retVal = pProgram->compile(1, &device, buildOptions, 0, nullptr, nullptr, nullptr, nullptr);
|
||||
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
|
||||
retVal = programLinked->link(1, &device, buildOptions, 1, &program, nullptr, nullptr);
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
|
||||
BlockKernelManager *blockManager = programLinked->getBlockKernelManager();
|
||||
|
||||
EXPECT_NE(0u, blockManager->getCount());
|
||||
|
||||
for (uint32_t i = 0; i < blockManager->getCount(); i++) {
|
||||
const KernelInfo *info = blockManager->getBlockKernelInfo(i);
|
||||
if (info->name.find("simple_block_kernel_dispatch") != std::string::npos) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
restoreBuiltInBinaryName(nullptr);
|
||||
delete programLinked;
|
||||
} else {
|
||||
EXPECT_EQ(nullptr, pProgram);
|
||||
}
|
||||
}
|
||||
} // namespace NEO
|
||||
@@ -0,0 +1,279 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "test.h"
|
||||
|
||||
#include "compiler_options.h"
|
||||
#include "fixtures/program_fixture.h"
|
||||
#include "global_environment.h"
|
||||
#include "gmock/gmock.h"
|
||||
#include "helpers/kernel_binary_helper.h"
|
||||
#include "helpers/kernel_filename_helper.h"
|
||||
#include "mocks/mock_program.h"
|
||||
#include "mocks/mock_source_level_debugger.h"
|
||||
#include "program/program_from_binary.h"
|
||||
#include "program/program_tests.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
using namespace NEO;
|
||||
|
||||
TEST_F(ProgramTests, givenDeafultProgramObjectWhenKernelDebugEnabledIsQueriedThenFalseIsReturned) {
|
||||
MockProgram program(*pDevice->getExecutionEnvironment(), pContext, false, pDevice);
|
||||
EXPECT_FALSE(program.isKernelDebugEnabled());
|
||||
}
|
||||
|
||||
TEST_F(ProgramTests, givenProgramObjectWhenEnableKernelDebugIsCalledThenProgramHasKernelDebugEnabled) {
|
||||
MockProgram program(*pDevice->getExecutionEnvironment(), pContext, false, pDevice);
|
||||
program.enableKernelDebug();
|
||||
EXPECT_TRUE(program.isKernelDebugEnabled());
|
||||
}
|
||||
|
||||
class ProgramWithKernelDebuggingTest : public ProgramSimpleFixture,
|
||||
public ::testing::Test {
|
||||
public:
|
||||
void SetUp() override {
|
||||
ProgramSimpleFixture::SetUp();
|
||||
device = pClDevice;
|
||||
if (!pDevice->getHardwareInfo().capabilityTable.debuggerSupported) {
|
||||
GTEST_SKIP();
|
||||
}
|
||||
|
||||
std::string filename;
|
||||
std::string kernelOption(CompilerOptions::debugKernelEnable);
|
||||
KernelFilenameHelper::getKernelFilenameFromInternalOption(kernelOption, filename);
|
||||
|
||||
kbHelper = std::make_unique<KernelBinaryHelper>(filename, false);
|
||||
CreateProgramWithSource(
|
||||
pContext,
|
||||
&device,
|
||||
"copybuffer.cl");
|
||||
mockProgram = reinterpret_cast<MockProgram *>(pProgram);
|
||||
pProgram->enableKernelDebug();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
ProgramSimpleFixture::TearDown();
|
||||
}
|
||||
cl_device_id device;
|
||||
std::unique_ptr<KernelBinaryHelper> kbHelper;
|
||||
MockProgram *mockProgram = nullptr;
|
||||
};
|
||||
|
||||
TEST_F(ProgramWithKernelDebuggingTest, givenEnabledKernelDebugWhenProgramIsCompiledThenInternalOptionsIncludeDebugFlag) {
|
||||
if (pDevice->getHardwareInfo().platform.eRenderCoreFamily >= IGFX_GEN9_CORE) {
|
||||
std::string receivedInternalOptions;
|
||||
|
||||
auto debugVars = NEO::getFclDebugVars();
|
||||
debugVars.receivedInternalOptionsOutput = &receivedInternalOptions;
|
||||
gEnvironment->fclPushDebugVars(debugVars);
|
||||
|
||||
cl_int retVal = pProgram->compile(1, &device, nullptr,
|
||||
0, nullptr, nullptr,
|
||||
nullptr,
|
||||
nullptr);
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
|
||||
EXPECT_TRUE(CompilerOptions::contains(receivedInternalOptions, CompilerOptions::debugKernelEnable)) << receivedInternalOptions;
|
||||
gEnvironment->fclPopDebugVars();
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ProgramWithKernelDebuggingTest, givenEnabledKernelDebugWhenProgramIsCompiledThenInternalOptionsIncludeDashGFlag) {
|
||||
if (pDevice->getHardwareInfo().platform.eRenderCoreFamily >= IGFX_GEN9_CORE) {
|
||||
cl_int retVal = pProgram->compile(1, &device, nullptr,
|
||||
0, nullptr, nullptr,
|
||||
nullptr,
|
||||
nullptr);
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
|
||||
EXPECT_THAT(pProgram->getOptions(), ::testing::HasSubstr("-g"));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ProgramWithKernelDebuggingTest, givenEnabledKernelDebugAndOptDisabledWhenProgramIsCompiledThenOptionsIncludeClOptDisableFlag) {
|
||||
if (pDevice->getHardwareInfo().platform.eRenderCoreFamily >= IGFX_GEN9_CORE) {
|
||||
|
||||
MockActiveSourceLevelDebugger *sourceLevelDebugger = new MockActiveSourceLevelDebugger;
|
||||
sourceLevelDebugger->isOptDisabled = true;
|
||||
pDevice->executionEnvironment->debugger.reset(sourceLevelDebugger);
|
||||
|
||||
cl_int retVal = pProgram->compile(1, &device, nullptr,
|
||||
0, nullptr, nullptr,
|
||||
nullptr,
|
||||
nullptr);
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
EXPECT_THAT(pProgram->getOptions(), ::testing::HasSubstr(CompilerOptions::optDisable.data()));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ProgramWithKernelDebuggingTest, givenEnabledKernelDebugWhenProgramIsCompiledThenOptionsStartsWithDashSFilename) {
|
||||
if (pDevice->getHardwareInfo().platform.eRenderCoreFamily >= IGFX_GEN9_CORE) {
|
||||
MockActiveSourceLevelDebugger *sourceLevelDebugger = new MockActiveSourceLevelDebugger;
|
||||
sourceLevelDebugger->sourceCodeFilename = "debugFileName";
|
||||
pDevice->executionEnvironment->debugger.reset(sourceLevelDebugger);
|
||||
|
||||
cl_int retVal = pProgram->compile(1, &device, nullptr,
|
||||
0, nullptr, nullptr,
|
||||
nullptr,
|
||||
nullptr);
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
EXPECT_THAT(pProgram->getOptions(), ::testing::StartsWith("-s debugFileName"));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ProgramWithKernelDebuggingTest, givenEnabledKernelDebugWhenProgramIsBuiltThenInternalOptionsIncludeDebugFlag) {
|
||||
if (pDevice->getHardwareInfo().platform.eRenderCoreFamily >= IGFX_GEN9_CORE) {
|
||||
std::string receivedInternalOptions;
|
||||
|
||||
auto debugVars = NEO::getFclDebugVars();
|
||||
debugVars.receivedInternalOptionsOutput = &receivedInternalOptions;
|
||||
gEnvironment->fclPushDebugVars(debugVars);
|
||||
|
||||
cl_int retVal = pProgram->build(1, &device, nullptr, nullptr, nullptr, false);
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
|
||||
EXPECT_TRUE(CompilerOptions::contains(receivedInternalOptions, CompilerOptions::debugKernelEnable)) << receivedInternalOptions;
|
||||
gEnvironment->fclPopDebugVars();
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ProgramWithKernelDebuggingTest, givenEnabledKernelDebugWhenProgramIsBuiltThenOptionsIncludeDashGFlag) {
|
||||
if (pDevice->getHardwareInfo().platform.eRenderCoreFamily >= IGFX_GEN9_CORE) {
|
||||
cl_int retVal = pProgram->build(1, &device, nullptr, nullptr, nullptr, false);
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
EXPECT_THAT(pProgram->getOptions(), ::testing::HasSubstr("-g"));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ProgramWithKernelDebuggingTest, givenEnabledKernelDebugAndOptDisabledWhenProgramIsBuiltThenOptionsIncludeClOptDisableFlag) {
|
||||
if (pDevice->getHardwareInfo().platform.eRenderCoreFamily >= IGFX_GEN9_CORE) {
|
||||
|
||||
MockActiveSourceLevelDebugger *sourceLevelDebugger = new MockActiveSourceLevelDebugger;
|
||||
sourceLevelDebugger->isOptDisabled = true;
|
||||
pDevice->executionEnvironment->debugger.reset(sourceLevelDebugger);
|
||||
|
||||
cl_int retVal = pProgram->build(1, &device, nullptr, nullptr, nullptr, false);
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
EXPECT_THAT(pProgram->getOptions(), ::testing::HasSubstr(CompilerOptions::optDisable.data()));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ProgramWithKernelDebuggingTest, givenEnabledKernelDebugWhenProgramIsBuiltThenOptionsStartsWithDashSFilename) {
|
||||
if (pDevice->getHardwareInfo().platform.eRenderCoreFamily >= IGFX_GEN9_CORE) {
|
||||
|
||||
MockActiveSourceLevelDebugger *sourceLevelDebugger = new MockActiveSourceLevelDebugger;
|
||||
sourceLevelDebugger->sourceCodeFilename = "debugFileName";
|
||||
pDevice->executionEnvironment->debugger.reset(sourceLevelDebugger);
|
||||
|
||||
cl_int retVal = pProgram->build(1, &device, nullptr, nullptr, nullptr, false);
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
EXPECT_THAT(pProgram->getOptions(), ::testing::StartsWith("-s debugFileName"));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ProgramWithKernelDebuggingTest, givenEnabledKernelDebugWhenProgramIsLinkedThenKernelDebugOptionsAreAppended) {
|
||||
if (pDevice->getHardwareInfo().platform.eRenderCoreFamily >= IGFX_GEN9_CORE) {
|
||||
|
||||
MockActiveSourceLevelDebugger *sourceLevelDebugger = new MockActiveSourceLevelDebugger;
|
||||
pDevice->executionEnvironment->debugger.reset(sourceLevelDebugger);
|
||||
|
||||
cl_int retVal = pProgram->compile(1, &device, nullptr, 0, nullptr, nullptr, nullptr, nullptr);
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
|
||||
auto program = std::unique_ptr<GMockProgram>(new GMockProgram(*pContext->getDevice(0)->getExecutionEnvironment(), pContext, false, &pContext->getDevice(0)->getDevice()));
|
||||
program->enableKernelDebug();
|
||||
|
||||
EXPECT_CALL(*program, appendKernelDebugOptions()).Times(1);
|
||||
|
||||
cl_program clProgramToLink = pProgram;
|
||||
retVal = program->link(1, &device, nullptr, 1, &clProgramToLink, nullptr, nullptr);
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ProgramWithKernelDebuggingTest, givenEnabledKernelDebugWhenProgramIsBuiltThenDebuggerIsNotifiedWithKernelDebugData) {
|
||||
if (pDevice->getHardwareInfo().platform.eRenderCoreFamily >= IGFX_GEN9_CORE) {
|
||||
|
||||
GMockSourceLevelDebugger *sourceLevelDebugger = new GMockSourceLevelDebugger(nullptr);
|
||||
ON_CALL(*sourceLevelDebugger, notifySourceCode(::testing::_, ::testing::_, ::testing::_)).WillByDefault(::testing::Return(false));
|
||||
ON_CALL(*sourceLevelDebugger, isOptimizationDisabled()).WillByDefault(::testing::Return(false));
|
||||
|
||||
EXPECT_CALL(*sourceLevelDebugger, isOptimizationDisabled()).Times(1);
|
||||
EXPECT_CALL(*sourceLevelDebugger, notifySourceCode(::testing::_, ::testing::_, ::testing::_)).Times(1);
|
||||
EXPECT_CALL(*sourceLevelDebugger, notifyKernelDebugData(::testing::_)).Times(1);
|
||||
|
||||
sourceLevelDebugger->setActive(true);
|
||||
pDevice->executionEnvironment->debugger.reset(sourceLevelDebugger);
|
||||
|
||||
cl_int retVal = pProgram->build(1, &device, nullptr, nullptr, nullptr, false);
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ProgramWithKernelDebuggingTest, givenEnabledKernelDebugWhenProgramIsLinkedThenDebuggerIsNotifiedWithKernelDebugData) {
|
||||
if (pDevice->getHardwareInfo().platform.eRenderCoreFamily >= IGFX_GEN9_CORE) {
|
||||
|
||||
GMockSourceLevelDebugger *sourceLevelDebugger = new GMockSourceLevelDebugger(nullptr);
|
||||
ON_CALL(*sourceLevelDebugger, notifySourceCode(::testing::_, ::testing::_, ::testing::_)).WillByDefault(::testing::Return(false));
|
||||
ON_CALL(*sourceLevelDebugger, isOptimizationDisabled()).WillByDefault(::testing::Return(false));
|
||||
|
||||
EXPECT_CALL(*sourceLevelDebugger, isOptimizationDisabled()).Times(2);
|
||||
EXPECT_CALL(*sourceLevelDebugger, notifySourceCode(::testing::_, ::testing::_, ::testing::_)).Times(1);
|
||||
EXPECT_CALL(*sourceLevelDebugger, notifyKernelDebugData(::testing::_)).Times(1);
|
||||
|
||||
sourceLevelDebugger->setActive(true);
|
||||
pDevice->executionEnvironment->debugger.reset(sourceLevelDebugger);
|
||||
|
||||
cl_int retVal = pProgram->compile(1, &device, nullptr,
|
||||
0, nullptr, nullptr,
|
||||
nullptr,
|
||||
nullptr);
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
|
||||
cl_program program = pProgram;
|
||||
retVal = pProgram->link(1, &device, nullptr,
|
||||
1, &program, nullptr, nullptr);
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ProgramWithKernelDebuggingTest, givenProgramWithKernelDebugEnabledWhenBuiltThenPatchTokenAllocateSipSurfaceHasSizeGreaterThanZero) {
|
||||
if (pDevice->getHardwareInfo().platform.eRenderCoreFamily >= IGFX_GEN9_CORE) {
|
||||
retVal = pProgram->build(1, &device, CompilerOptions::debugKernelEnable, nullptr, nullptr, false);
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
|
||||
auto kernelInfo = pProgram->getKernelInfo("CopyBuffer");
|
||||
EXPECT_NE(0u, kernelInfo->patchInfo.pAllocateSystemThreadSurface->PerThreadSystemThreadSurfaceSize);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ProgramWithKernelDebuggingTest, givenKernelDebugEnabledWhenProgramIsBuiltThenDebugDataIsStored) {
|
||||
if (pDevice->getHardwareInfo().platform.eRenderCoreFamily >= IGFX_GEN9_CORE) {
|
||||
retVal = pProgram->build(1, &device, nullptr, nullptr, nullptr, false);
|
||||
|
||||
auto debugData = mockProgram->getDebugData();
|
||||
EXPECT_NE(nullptr, debugData);
|
||||
EXPECT_NE(0u, mockProgram->getDebugDataSize());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ProgramWithKernelDebuggingTest, givenProgramWithKernelDebugEnabledWhenProcessDebugDataIsCalledThenKernelInfosAreFilledWithDebugData) {
|
||||
if (pDevice->getHardwareInfo().platform.eRenderCoreFamily >= IGFX_GEN9_CORE) {
|
||||
retVal = pProgram->build(1, &device, nullptr, nullptr, nullptr, false);
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
|
||||
pProgram->processDebugData();
|
||||
|
||||
auto kernelInfo = pProgram->getKernelInfo("CopyBuffer");
|
||||
|
||||
EXPECT_NE(0u, kernelInfo->debugData.vIsaSize);
|
||||
EXPECT_NE(nullptr, kernelInfo->debugData.vIsa);
|
||||
}
|
||||
}
|
||||
66
opencl/test/unit_test/program/program_with_source.h
Normal file
66
opencl/test/unit_test/program/program_with_source.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/compiler_interface/compiler_interface.h"
|
||||
|
||||
#include "fixtures/context_fixture.h"
|
||||
#include "fixtures/memory_management_fixture.h"
|
||||
#include "fixtures/platform_fixture.h"
|
||||
#include "fixtures/program_fixture.h"
|
||||
#include "helpers/kernel_binary_helper.h"
|
||||
#include "mocks/mock_context.h"
|
||||
|
||||
namespace NEO {
|
||||
|
||||
// ProgramFromSource Test Fixture
|
||||
// Used to test the Program class
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class ProgramFromSourceTest : public ContextFixture,
|
||||
public PlatformFixture,
|
||||
public ProgramFixture,
|
||||
public testing::TestWithParam<std::tuple<const char *, const char *, const char *>> {
|
||||
|
||||
using ContextFixture::SetUp;
|
||||
using PlatformFixture::SetUp;
|
||||
|
||||
protected:
|
||||
ProgramFromSourceTest()
|
||||
: kbHelper(nullptr), SourceFileName(nullptr), KernelName(nullptr), retVal(CL_SUCCESS) {
|
||||
}
|
||||
|
||||
virtual void SetUp() {
|
||||
std::tie(SourceFileName, BinaryFileName, KernelName) = GetParam();
|
||||
kbHelper = new KernelBinaryHelper(BinaryFileName);
|
||||
|
||||
PlatformFixture::SetUp();
|
||||
cl_device_id device = pPlatform->getClDevice(0);
|
||||
ContextFixture::SetUp(1, &device);
|
||||
ProgramFixture::SetUp();
|
||||
|
||||
CreateProgramWithSource(
|
||||
pContext,
|
||||
&device,
|
||||
SourceFileName);
|
||||
}
|
||||
|
||||
virtual void TearDown() {
|
||||
knownSource.reset();
|
||||
ProgramFixture::TearDown();
|
||||
ContextFixture::TearDown();
|
||||
PlatformFixture::TearDown();
|
||||
delete kbHelper;
|
||||
}
|
||||
|
||||
KernelBinaryHelper *kbHelper;
|
||||
const char *SourceFileName;
|
||||
const char *BinaryFileName;
|
||||
const char *KernelName;
|
||||
cl_int retVal;
|
||||
};
|
||||
} // namespace NEO
|
||||
Reference in New Issue
Block a user