1189 lines
78 KiB
C++
1189 lines
78 KiB
C++
/*
|
|
* Copyright (C) 2019 Intel Corporation
|
|
*
|
|
* SPDX-License-Identifier: MIT
|
|
*
|
|
*/
|
|
|
|
#include "core/helpers/hash.h"
|
|
#include "runtime/compiler_interface/patchtokens_decoder.h"
|
|
#include "test.h"
|
|
|
|
#include "patchtokens_tests.h"
|
|
|
|
#include <vector>
|
|
|
|
bool hasEmptyHeaps(const NEO::PatchTokenBinary::KernelFromPatchtokens &kernel) {
|
|
return kernel.heaps.generalState.empty() && kernel.heaps.dynamicState.empty() && kernel.heaps.surfaceState.empty();
|
|
}
|
|
|
|
bool hasEmptyTokensInfo(const NEO::PatchTokenBinary::KernelFromPatchtokens &kernel) {
|
|
auto &toks = kernel.tokens;
|
|
bool empty = true;
|
|
empty &= nullptr == toks.samplerStateArray;
|
|
empty &= nullptr == toks.bindingTableState;
|
|
empty &= nullptr == toks.allocateLocalSurface;
|
|
empty &= nullptr == toks.mediaVfeState[0];
|
|
empty &= nullptr == toks.mediaVfeState[1];
|
|
empty &= nullptr == toks.mediaInterfaceDescriptorLoad;
|
|
empty &= nullptr == toks.interfaceDescriptorData;
|
|
empty &= nullptr == toks.threadPayload;
|
|
empty &= nullptr == toks.executionEnvironment;
|
|
empty &= nullptr == toks.dataParameterStream;
|
|
empty &= nullptr == toks.kernelAttributesInfo;
|
|
empty &= nullptr == toks.allocateStatelessPrivateSurface;
|
|
empty &= nullptr == toks.allocateStatelessConstantMemorySurfaceWithInitialization;
|
|
empty &= nullptr == toks.allocateStatelessGlobalMemorySurfaceWithInitialization;
|
|
empty &= nullptr == toks.allocateStatelessPrintfSurface;
|
|
empty &= nullptr == toks.allocateStatelessEventPoolSurface;
|
|
empty &= nullptr == toks.allocateStatelessDefaultDeviceQueueSurface;
|
|
empty &= nullptr == toks.inlineVmeSamplerInfo;
|
|
empty &= nullptr == toks.gtpinFreeGrfInfo;
|
|
empty &= nullptr == toks.stateSip;
|
|
empty &= nullptr == toks.allocateSystemThreadSurface;
|
|
empty &= nullptr == toks.gtpinInfo;
|
|
empty &= nullptr == toks.programSymbolTable;
|
|
empty &= nullptr == toks.programRelocationTable;
|
|
empty &= toks.kernelArgs.empty();
|
|
empty &= toks.strings.empty();
|
|
for (int i = 0; i < 3; ++i) {
|
|
empty &= nullptr == toks.crossThreadPayloadArgs.localWorkSize[i];
|
|
empty &= nullptr == toks.crossThreadPayloadArgs.localWorkSize[i];
|
|
empty &= nullptr == toks.crossThreadPayloadArgs.localWorkSize2[i];
|
|
empty &= nullptr == toks.crossThreadPayloadArgs.enqueuedLocalWorkSize[i];
|
|
empty &= nullptr == toks.crossThreadPayloadArgs.numWorkGroups[i];
|
|
empty &= nullptr == toks.crossThreadPayloadArgs.globalWorkOffset[i];
|
|
empty &= nullptr == toks.crossThreadPayloadArgs.globalWorkSize[i];
|
|
}
|
|
empty &= nullptr == toks.crossThreadPayloadArgs.maxWorkGroupSize;
|
|
empty &= nullptr == toks.crossThreadPayloadArgs.workDimensions;
|
|
empty &= nullptr == toks.crossThreadPayloadArgs.simdSize;
|
|
empty &= nullptr == toks.crossThreadPayloadArgs.parentEvent;
|
|
empty &= nullptr == toks.crossThreadPayloadArgs.privateMemoryStatelessSize;
|
|
empty &= nullptr == toks.crossThreadPayloadArgs.localMemoryStatelessWindowSize;
|
|
empty &= nullptr == toks.crossThreadPayloadArgs.localMemoryStatelessWindowStartAddress;
|
|
empty &= nullptr == toks.crossThreadPayloadArgs.preferredWorkgroupMultiple;
|
|
empty &= toks.crossThreadPayloadArgs.childBlockSimdSize.empty();
|
|
return empty;
|
|
}
|
|
|
|
bool hasEmptyTokensInfo(const NEO::PatchTokenBinary::ProgramFromPatchtokens &program) {
|
|
auto &toks = program.programScopeTokens;
|
|
bool empty = true;
|
|
empty &= toks.allocateConstantMemorySurface.empty();
|
|
empty &= toks.allocateGlobalMemorySurface.empty();
|
|
empty &= toks.constantPointer.empty();
|
|
empty &= toks.globalPointer.empty();
|
|
empty &= nullptr == toks.symbolTable;
|
|
return empty;
|
|
}
|
|
|
|
template <typename TokenT>
|
|
uint32_t pushBackToken(iOpenCL::PATCH_TOKEN token, std::vector<uint8_t> &storage) {
|
|
auto offset = storage.size();
|
|
TokenT tok = PatchTokensTestData::initToken<TokenT>(token);
|
|
storage.insert(storage.end(), reinterpret_cast<uint8_t *>(&tok), reinterpret_cast<uint8_t *>((&tok) + 1));
|
|
return static_cast<uint32_t>(offset);
|
|
}
|
|
|
|
template <typename TokenT>
|
|
uint32_t pushBackToken(const TokenT &token, std::vector<uint8_t> &storage) {
|
|
auto offset = storage.size();
|
|
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&token), reinterpret_cast<const uint8_t *>(&token) + token.Size);
|
|
return static_cast<uint32_t>(offset);
|
|
}
|
|
|
|
uint32_t pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_TOKEN type, std::vector<uint8_t> &storage, uint32_t sourceIndex = 0, uint32_t argNum = 0) {
|
|
iOpenCL::SPatchDataParameterBuffer tok = PatchTokensTestData::initDataParameterBufferToken(type, sourceIndex, argNum);
|
|
|
|
auto offset = storage.size();
|
|
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&tok), reinterpret_cast<const uint8_t *>(&tok) + tok.Size);
|
|
return static_cast<uint32_t>(offset);
|
|
}
|
|
|
|
bool tokenOffsetMatched(const uint8_t *base, size_t tokenOffset, const iOpenCL::SPatchItemHeader *expectedToken) {
|
|
return (base + tokenOffset) == reinterpret_cast<const uint8_t *>(expectedToken);
|
|
}
|
|
|
|
TEST(GetInlineData, GivenConstantMemorySurfaceTokenThenReturnProperOffsetToInlineData) {
|
|
iOpenCL::SPatchAllocateConstantMemorySurfaceProgramBinaryInfo surfTok[2];
|
|
EXPECT_EQ(reinterpret_cast<uint8_t *>(&surfTok[1]), NEO::PatchTokenBinary::getInlineData(&surfTok[0]));
|
|
}
|
|
|
|
TEST(GetInlineData, GivenGlobalMemorySurfaceTokenThenReturnProperOffsetToInlineData) {
|
|
iOpenCL::SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo surfTok[2];
|
|
EXPECT_EQ(reinterpret_cast<uint8_t *>(&surfTok[1]), NEO::PatchTokenBinary::getInlineData(&surfTok[0]));
|
|
}
|
|
|
|
TEST(GetInlineData, GivenStringTokenThenReturnProperOffsetToInlineData) {
|
|
iOpenCL::SPatchString surfTok[2];
|
|
EXPECT_EQ(reinterpret_cast<uint8_t *>(&surfTok[1]), NEO::PatchTokenBinary::getInlineData(&surfTok[0]));
|
|
}
|
|
|
|
TEST(GetInlineData, GivenKernelArgumentInfoTokenThenReturnDecodedInlineData) {
|
|
std::vector<uint8_t> storage;
|
|
std::string addressQualifier = "__global";
|
|
std::string accessQualifier = "read_write";
|
|
std::string argName = "custom_arg";
|
|
std::string typeName = "int*;";
|
|
std::string typeQualifier = "const";
|
|
|
|
PatchTokensTestData::pushBackArgInfoToken(storage, 0U, addressQualifier, accessQualifier, argName, typeName, typeQualifier);
|
|
|
|
auto inlineData = NEO::PatchTokenBinary::getInlineData(reinterpret_cast<iOpenCL::SPatchKernelArgumentInfo *>(storage.data()));
|
|
EXPECT_STREQ(addressQualifier.c_str(), std::string(inlineData.addressQualifier.begin(), inlineData.addressQualifier.end()).c_str());
|
|
EXPECT_STREQ(accessQualifier.c_str(), std::string(inlineData.accessQualifier.begin(), inlineData.accessQualifier.end()).c_str());
|
|
EXPECT_STREQ(argName.c_str(), std::string(inlineData.argName.begin(), inlineData.argName.end()).c_str());
|
|
EXPECT_STREQ(typeName.c_str(), std::string(inlineData.typeName.begin(), inlineData.typeName.end()).c_str());
|
|
EXPECT_STREQ(typeQualifier.c_str(), std::string(inlineData.typeQualifiers.begin(), inlineData.typeQualifiers.end()).c_str());
|
|
}
|
|
|
|
TEST(GetInlineData, GivenKernelArgumentInfoTokenWhenNotEnoughDataThenArrayIsBoundsProtected) {
|
|
iOpenCL::SPatchKernelArgumentInfo tokInline = {};
|
|
tokInline.AddressQualifierSize = 4;
|
|
tokInline.AccessQualifierSize = 8;
|
|
tokInline.ArgumentNameSize = 32;
|
|
tokInline.TypeNameSize = 16;
|
|
tokInline.TypeQualifierSize = 6;
|
|
tokInline.Size = sizeof(iOpenCL::SPatchKernelArgumentInfo);
|
|
auto inlineData = NEO::PatchTokenBinary::getInlineData(&tokInline);
|
|
EXPECT_EQ(0U, inlineData.addressQualifier.size());
|
|
EXPECT_EQ(0U, inlineData.accessQualifier.size());
|
|
EXPECT_EQ(0U, inlineData.argName.size());
|
|
EXPECT_EQ(0U, inlineData.typeName.size());
|
|
EXPECT_EQ(0U, inlineData.typeQualifiers.size());
|
|
}
|
|
|
|
TEST(KernelChecksum, GivenKernelBlobThenChecksumIsCalculatedBasedOnDataAfterKernelHeader) {
|
|
std::vector<uint8_t> storage;
|
|
auto kernel = PatchTokensTestData::ValidEmptyKernel::create(storage);
|
|
auto calculatedChecksum = NEO::PatchTokenBinary::calcKernelChecksum(kernel.blobs.kernelInfo);
|
|
|
|
auto dataToHash = ArrayRef<const uint8_t>(ptrOffset(storage.data(), sizeof(iOpenCL::SKernelBinaryHeaderCommon)), ptrOffset(storage.data(), storage.size()));
|
|
uint64_t hashValue = NEO::Hash::hash(reinterpret_cast<const char *>(dataToHash.begin()), dataToHash.size());
|
|
uint32_t expectedChecksum = hashValue & 0xFFFFFFFF;
|
|
EXPECT_EQ(expectedChecksum, calculatedChecksum);
|
|
}
|
|
|
|
TEST(KernelChecksum, GivenKernelWithProperChecksumThenValidationSucceeds) {
|
|
std::vector<uint8_t> storage;
|
|
auto kernel = PatchTokensTestData::ValidEmptyKernel::create(storage);
|
|
auto calculatedChecksum = NEO::PatchTokenBinary::calcKernelChecksum(kernel.blobs.kernelInfo);
|
|
EXPECT_EQ(kernel.header->CheckSum, calculatedChecksum);
|
|
EXPECT_FALSE(NEO::PatchTokenBinary::hasInvalidChecksum(kernel));
|
|
}
|
|
|
|
TEST(KernelChecksum, GivenKernelWithInvalidChecksumThenValidationFails) {
|
|
std::vector<uint8_t> storage;
|
|
auto kernel = PatchTokensTestData::ValidEmptyKernel::create(storage);
|
|
auto calculatedChecksum = NEO::PatchTokenBinary::calcKernelChecksum(kernel.blobs.kernelInfo);
|
|
EXPECT_EQ(kernel.header->CheckSum, calculatedChecksum);
|
|
|
|
ASSERT_EQ(storage.data(), kernel.blobs.kernelInfo.begin());
|
|
reinterpret_cast<iOpenCL::SKernelBinaryHeader *>(storage.data())->CheckSum += 1;
|
|
|
|
EXPECT_TRUE(NEO::PatchTokenBinary::hasInvalidChecksum(kernel));
|
|
}
|
|
|
|
TEST(KernelDecoder, GivenValidEmptyKernelThenDecodingOfHeaderSucceeds) {
|
|
std::vector<uint8_t> storage;
|
|
auto kernelToEncode = PatchTokensTestData::ValidEmptyKernel::create(storage);
|
|
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
|
|
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(kernelToEncode.blobs.kernelInfo, decodedKernel);
|
|
EXPECT_TRUE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
|
|
ASSERT_NE(nullptr, decodedKernel.header);
|
|
EXPECT_EQ(kernelToEncode.header, decodedKernel.header);
|
|
EXPECT_EQ(kernelToEncode.name, decodedKernel.name);
|
|
EXPECT_EQ(kernelToEncode.blobs.kernelInfo, decodedKernel.blobs.kernelInfo);
|
|
EXPECT_EQ(0U, decodedKernel.isa.size());
|
|
EXPECT_TRUE(hasEmptyHeaps(decodedKernel));
|
|
EXPECT_EQ(0U, decodedKernel.unhandledTokens.size());
|
|
EXPECT_TRUE(hasEmptyTokensInfo(decodedKernel));
|
|
}
|
|
|
|
TEST(KernelDecoder, GivenEmptyKernelWhenBlobSmallerThanKernelHeaderThenDecodingFails) {
|
|
std::vector<uint8_t> storage;
|
|
auto kernelToEncode = PatchTokensTestData::ValidEmptyKernel::create(storage);
|
|
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
|
|
auto brokenBlob = ArrayRef<const uint8_t>(kernelToEncode.blobs.kernelInfo.begin(),
|
|
kernelToEncode.blobs.kernelInfo.begin() + sizeof(iOpenCL::SKernelBinaryHeader) - 1);
|
|
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(brokenBlob, decodedKernel);
|
|
EXPECT_FALSE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
|
|
}
|
|
|
|
TEST(KernelDecoder, GivenValidKernelWithHeapsThenDecodingSucceedsAndHeapsAreProperlySet) {
|
|
std::vector<uint8_t> storage;
|
|
storage.reserve(512);
|
|
auto kernelToEncode = PatchTokensTestData::ValidEmptyKernel::create(storage);
|
|
|
|
ASSERT_EQ(storage.data(), kernelToEncode.blobs.kernelInfo.begin());
|
|
auto kernelHeader = reinterpret_cast<iOpenCL::SKernelBinaryHeaderCommon *>(storage.data());
|
|
|
|
size_t isaOffset = storage.size();
|
|
kernelHeader->KernelHeapSize = 16U;
|
|
storage.resize(storage.size() + kernelHeader->KernelHeapSize);
|
|
|
|
size_t generalStateHeapOffset = storage.size();
|
|
kernelHeader->GeneralStateHeapSize = 24U;
|
|
storage.resize(storage.size() + kernelHeader->GeneralStateHeapSize);
|
|
|
|
size_t dynamicStateHeapOffset = storage.size();
|
|
kernelHeader->DynamicStateHeapSize = 8U;
|
|
storage.resize(storage.size() + kernelHeader->DynamicStateHeapSize);
|
|
|
|
size_t surfaceStateHeapOffset = storage.size();
|
|
kernelHeader->SurfaceStateHeapSize = 32U;
|
|
storage.resize(storage.size() + kernelHeader->SurfaceStateHeapSize);
|
|
|
|
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
|
|
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
|
EXPECT_TRUE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
|
|
|
|
EXPECT_EQ(kernelToEncode.header, decodedKernel.header);
|
|
EXPECT_EQ(0U, decodedKernel.unhandledTokens.size());
|
|
EXPECT_TRUE(hasEmptyTokensInfo(decodedKernel));
|
|
|
|
EXPECT_EQ(kernelToEncode.name, decodedKernel.name);
|
|
EXPECT_EQ(ArrayRef<const uint8_t>(storage.data() + isaOffset, kernelHeader->KernelHeapSize), decodedKernel.isa);
|
|
EXPECT_EQ(ArrayRef<const uint8_t>(storage.data() + generalStateHeapOffset, kernelHeader->GeneralStateHeapSize), decodedKernel.heaps.generalState);
|
|
EXPECT_EQ(ArrayRef<const uint8_t>(storage.data() + dynamicStateHeapOffset, kernelHeader->DynamicStateHeapSize), decodedKernel.heaps.dynamicState);
|
|
EXPECT_EQ(ArrayRef<const uint8_t>(storage.data() + surfaceStateHeapOffset, kernelHeader->SurfaceStateHeapSize), decodedKernel.heaps.surfaceState);
|
|
}
|
|
|
|
TEST(KernelDecoder, GivenEmptyKernelWhenBlobDoesntHaveEnoughSpaceForHeaderDataThenDecodingFails) {
|
|
std::vector<uint8_t> storage;
|
|
auto kernelToEncode = PatchTokensTestData::ValidEmptyKernel::create(storage);
|
|
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
|
|
|
|
ASSERT_EQ(storage.data(), kernelToEncode.blobs.kernelInfo.begin());
|
|
auto kernelHeader = reinterpret_cast<iOpenCL::SKernelBinaryHeaderCommon *>(storage.data());
|
|
iOpenCL::SKernelBinaryHeaderCommon originalHeader = *kernelToEncode.header;
|
|
uint32_t outOfBoundsSize = static_cast<uint32_t>(storage.size());
|
|
|
|
decodedKernel = {};
|
|
kernelHeader->KernelNameSize = outOfBoundsSize;
|
|
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(kernelToEncode.blobs.kernelInfo, decodedKernel);
|
|
EXPECT_FALSE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
|
|
kernelHeader->KernelNameSize = originalHeader.KernelNameSize;
|
|
|
|
kernelHeader->KernelHeapSize = outOfBoundsSize;
|
|
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(kernelToEncode.blobs.kernelInfo, decodedKernel);
|
|
EXPECT_FALSE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
|
|
kernelHeader->KernelHeapSize = originalHeader.KernelHeapSize;
|
|
|
|
kernelHeader->GeneralStateHeapSize = outOfBoundsSize;
|
|
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(kernelToEncode.blobs.kernelInfo, decodedKernel);
|
|
EXPECT_FALSE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
|
|
kernelHeader->GeneralStateHeapSize = originalHeader.GeneralStateHeapSize;
|
|
|
|
kernelHeader->DynamicStateHeapSize = outOfBoundsSize;
|
|
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(kernelToEncode.blobs.kernelInfo, decodedKernel);
|
|
EXPECT_FALSE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
|
|
kernelHeader->DynamicStateHeapSize = originalHeader.DynamicStateHeapSize;
|
|
|
|
kernelHeader->SurfaceStateHeapSize = outOfBoundsSize;
|
|
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(kernelToEncode.blobs.kernelInfo, decodedKernel);
|
|
EXPECT_FALSE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
|
|
kernelHeader->SurfaceStateHeapSize = originalHeader.SurfaceStateHeapSize;
|
|
|
|
kernelHeader->PatchListSize = outOfBoundsSize;
|
|
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(kernelToEncode.blobs.kernelInfo, decodedKernel);
|
|
EXPECT_FALSE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
|
|
kernelHeader->PatchListSize = originalHeader.PatchListSize;
|
|
}
|
|
|
|
TEST(KernelDecoder, GivenKernelWithValidKernelPatchtokensThenDecodingSucceedsAndTokensAreProperlyAssigned) {
|
|
using namespace iOpenCL;
|
|
|
|
std::vector<uint8_t> storage;
|
|
storage.reserve(1024);
|
|
auto kernelToEncode = PatchTokensTestData::ValidEmptyKernel::create(storage);
|
|
|
|
auto patchListOffset = static_cast<uint32_t>(storage.size());
|
|
auto samplerStateArrayOff = pushBackToken<SPatchSamplerStateArray>(PATCH_TOKEN_SAMPLER_STATE_ARRAY, storage);
|
|
auto bindingTableStateOff = pushBackToken<SPatchBindingTableState>(PATCH_TOKEN_BINDING_TABLE_STATE, storage);
|
|
auto allocateLocalSurfaceOff = pushBackToken<SPatchAllocateLocalSurface>(PATCH_TOKEN_ALLOCATE_LOCAL_SURFACE, storage);
|
|
auto mediaVfeState0Off = pushBackToken<SPatchMediaVFEState>(PATCH_TOKEN_MEDIA_VFE_STATE, storage);
|
|
auto mediaVfeState1Off = pushBackToken<SPatchMediaVFEState>(PATCH_TOKEN_MEDIA_VFE_STATE_SLOT1, storage);
|
|
auto mediaInterfaceDescriptorLoadOff = pushBackToken<SPatchMediaInterfaceDescriptorLoad>(PATCH_TOKEN_MEDIA_INTERFACE_DESCRIPTOR_LOAD, storage);
|
|
auto interfaceDescriptorDataOff = pushBackToken<SPatchInterfaceDescriptorData>(PATCH_TOKEN_INTERFACE_DESCRIPTOR_DATA, storage);
|
|
auto threadPayloadOff = pushBackToken<SPatchThreadPayload>(PATCH_TOKEN_THREAD_PAYLOAD, storage);
|
|
auto executionEnvironmentOff = pushBackToken<SPatchExecutionEnvironment>(PATCH_TOKEN_EXECUTION_ENVIRONMENT, storage);
|
|
auto kernelAttributesInfoOff = pushBackToken<SPatchKernelAttributesInfo>(PATCH_TOKEN_KERNEL_ATTRIBUTES_INFO, storage);
|
|
auto allocatedStatelessPrivateMemoryOff = pushBackToken<SPatchKernelAttributesInfo>(PATCH_TOKEN_ALLOCATE_STATELESS_PRIVATE_MEMORY, storage);
|
|
auto allocateStatelessConstantMemorySurfaceWithInitializationOff = pushBackToken<SPatchAllocateStatelessConstantMemorySurfaceWithInitialization>(PATCH_TOKEN_ALLOCATE_STATELESS_CONSTANT_MEMORY_SURFACE_WITH_INITIALIZATION, storage);
|
|
auto allocateStatelessGlobalMemorySurfaceWithInitializationOff = pushBackToken<SPatchAllocateStatelessGlobalMemorySurfaceWithInitialization>(PATCH_TOKEN_ALLOCATE_STATELESS_GLOBAL_MEMORY_SURFACE_WITH_INITIALIZATION, storage);
|
|
auto allocateStatelessPrintfSurfaceOff = pushBackToken<SPatchAllocateStatelessPrintfSurface>(PATCH_TOKEN_ALLOCATE_STATELESS_PRINTF_SURFACE, storage);
|
|
auto allocateStatelessEventPoolSurfaceOff = pushBackToken<SPatchAllocateStatelessEventPoolSurface>(PATCH_TOKEN_ALLOCATE_STATELESS_EVENT_POOL_SURFACE, storage);
|
|
auto allocateStatelessDefaultDeviceQueueSurfaceOff = pushBackToken<SPatchAllocateStatelessDefaultDeviceQueueSurface>(PATCH_TOKEN_ALLOCATE_STATELESS_DEFAULT_DEVICE_QUEUE_SURFACE, storage);
|
|
auto inlineVmeSamplerInfoOff = pushBackToken<SPatchInlineVMESamplerInfo>(PATCH_TOKEN_INLINE_VME_SAMPLER_INFO, storage);
|
|
auto gtpinFreeGrfInfoOff = pushBackToken<SPatchGtpinFreeGRFInfo>(PATCH_TOKEN_GTPIN_FREE_GRF_INFO, storage);
|
|
auto gtpinInfoOff = pushBackToken<SPatchItemHeader>(PATCH_TOKEN_GTPIN_INFO, storage);
|
|
auto stateSipOff = pushBackToken<SPatchStateSIP>(PATCH_TOKEN_STATE_SIP, storage);
|
|
auto programSymbolTableOff = pushBackToken<SPatchFunctionTableInfo>(PATCH_TOKEN_PROGRAM_SYMBOL_TABLE, storage);
|
|
auto programRelocationTableOff = pushBackToken<SPatchFunctionTableInfo>(PATCH_TOKEN_PROGRAM_RELOCATION_TABLE, storage);
|
|
auto dataParameterStreamOff = pushBackToken<SPatchDataParameterStream>(PATCH_TOKEN_DATA_PARAMETER_STREAM, storage);
|
|
|
|
ASSERT_EQ(storage.data(), kernelToEncode.blobs.kernelInfo.begin());
|
|
auto kernelHeader = reinterpret_cast<iOpenCL::SKernelBinaryHeaderCommon *>(storage.data());
|
|
kernelHeader->PatchListSize = static_cast<uint32_t>(storage.size()) - patchListOffset;
|
|
|
|
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
|
|
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
|
EXPECT_TRUE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
|
|
EXPECT_TRUE(decodedKernel.unhandledTokens.empty());
|
|
EXPECT_EQ(ptrOffset(storage.data(), patchListOffset), decodedKernel.blobs.patchList.begin());
|
|
EXPECT_EQ(ptrOffset(storage.data(), storage.size()), decodedKernel.blobs.patchList.end());
|
|
|
|
auto base = storage.data();
|
|
EXPECT_TRUE(tokenOffsetMatched(base, samplerStateArrayOff, decodedKernel.tokens.samplerStateArray));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, bindingTableStateOff, decodedKernel.tokens.bindingTableState));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, allocateLocalSurfaceOff, decodedKernel.tokens.allocateLocalSurface));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, mediaVfeState0Off, decodedKernel.tokens.mediaVfeState[0]));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, mediaVfeState1Off, decodedKernel.tokens.mediaVfeState[1]));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, mediaInterfaceDescriptorLoadOff, decodedKernel.tokens.mediaInterfaceDescriptorLoad));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, interfaceDescriptorDataOff, decodedKernel.tokens.interfaceDescriptorData));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, threadPayloadOff, decodedKernel.tokens.threadPayload));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, executionEnvironmentOff, decodedKernel.tokens.executionEnvironment));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, kernelAttributesInfoOff, decodedKernel.tokens.kernelAttributesInfo));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, allocatedStatelessPrivateMemoryOff, decodedKernel.tokens.allocateStatelessPrivateSurface));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, allocateStatelessConstantMemorySurfaceWithInitializationOff, decodedKernel.tokens.allocateStatelessConstantMemorySurfaceWithInitialization));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, allocateStatelessGlobalMemorySurfaceWithInitializationOff, decodedKernel.tokens.allocateStatelessGlobalMemorySurfaceWithInitialization));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, allocateStatelessPrintfSurfaceOff, decodedKernel.tokens.allocateStatelessPrintfSurface));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, allocateStatelessEventPoolSurfaceOff, decodedKernel.tokens.allocateStatelessEventPoolSurface));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, allocateStatelessDefaultDeviceQueueSurfaceOff, decodedKernel.tokens.allocateStatelessDefaultDeviceQueueSurface));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, inlineVmeSamplerInfoOff, decodedKernel.tokens.inlineVmeSamplerInfo));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, gtpinFreeGrfInfoOff, decodedKernel.tokens.gtpinFreeGrfInfo));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, gtpinInfoOff, decodedKernel.tokens.gtpinInfo));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, stateSipOff, decodedKernel.tokens.stateSip));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, programSymbolTableOff, decodedKernel.tokens.programSymbolTable));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, programRelocationTableOff, decodedKernel.tokens.programRelocationTable));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, dataParameterStreamOff, decodedKernel.tokens.dataParameterStream));
|
|
}
|
|
|
|
TEST(KernelDecoder, GivenKernelWithValidStringPatchtokensThenDecodingSucceedsAndTokensAreProperlyAssigned) {
|
|
std::vector<uint8_t> storage;
|
|
storage.reserve(512);
|
|
auto kernelToEncode = PatchTokensTestData::ValidEmptyKernel::create(storage);
|
|
|
|
iOpenCL::SPatchString stringTok = {};
|
|
stringTok.Token = iOpenCL::PATCH_TOKEN::PATCH_TOKEN_STRING;
|
|
|
|
auto patchListOffset = static_cast<uint32_t>(storage.size());
|
|
auto string1Off = PatchTokensTestData::pushBackStringToken("str1", 1, storage);
|
|
auto string2Off = PatchTokensTestData::pushBackStringToken("str2", 2, storage);
|
|
auto string0Off = PatchTokensTestData::pushBackStringToken("str0", 0, storage);
|
|
|
|
ASSERT_EQ(storage.data(), kernelToEncode.blobs.kernelInfo.begin());
|
|
auto kernelHeader = reinterpret_cast<iOpenCL::SKernelBinaryHeaderCommon *>(storage.data());
|
|
kernelHeader->PatchListSize = static_cast<uint32_t>(storage.size()) - patchListOffset;
|
|
|
|
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
|
|
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
|
EXPECT_TRUE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
|
|
EXPECT_TRUE(decodedKernel.unhandledTokens.empty());
|
|
|
|
auto base = storage.data();
|
|
ASSERT_EQ(3U, decodedKernel.tokens.strings.size());
|
|
EXPECT_TRUE(tokenOffsetMatched(base, string0Off, decodedKernel.tokens.strings[0]));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, string1Off, decodedKernel.tokens.strings[1]));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, string2Off, decodedKernel.tokens.strings[2]));
|
|
}
|
|
|
|
TEST(KernelDecoder, GivenKernelWithValidArgInfoPatchtokensThenDecodingSucceedsAndTokensAreProperlyAssigned) {
|
|
std::vector<uint8_t> storage;
|
|
storage.reserve(512);
|
|
auto kernelToEncode = PatchTokensTestData::ValidEmptyKernel::create(storage);
|
|
|
|
iOpenCL::SPatchKernelArgumentInfo argInfoTok = {};
|
|
argInfoTok.Token = iOpenCL::PATCH_TOKEN::PATCH_TOKEN_KERNEL_ARGUMENT_INFO;
|
|
|
|
auto patchListOffset = static_cast<uint32_t>(storage.size());
|
|
|
|
auto arg1Off = static_cast<uint32_t>(storage.size());
|
|
argInfoTok.ArgumentNumber = 1;
|
|
auto additionalDataSize = 8;
|
|
argInfoTok.Size = sizeof(argInfoTok) + additionalDataSize;
|
|
storage.insert(storage.end(), reinterpret_cast<uint8_t *>(&argInfoTok), reinterpret_cast<uint8_t *>((&argInfoTok) + 1));
|
|
storage.resize(storage.size() + additionalDataSize);
|
|
|
|
auto arg2Off = static_cast<uint32_t>(storage.size());
|
|
argInfoTok.ArgumentNumber = 2;
|
|
additionalDataSize = 16;
|
|
argInfoTok.Size = sizeof(argInfoTok) + additionalDataSize;
|
|
storage.insert(storage.end(), reinterpret_cast<uint8_t *>(&argInfoTok), reinterpret_cast<uint8_t *>((&argInfoTok) + 1));
|
|
storage.resize(storage.size() + additionalDataSize);
|
|
|
|
auto arg0Off = static_cast<uint32_t>(storage.size());
|
|
argInfoTok.ArgumentNumber = 0;
|
|
additionalDataSize = 24;
|
|
argInfoTok.Size = sizeof(argInfoTok) + additionalDataSize;
|
|
storage.insert(storage.end(), reinterpret_cast<uint8_t *>(&argInfoTok), reinterpret_cast<uint8_t *>((&argInfoTok) + 1));
|
|
storage.resize(storage.size() + additionalDataSize);
|
|
|
|
ASSERT_EQ(storage.data(), kernelToEncode.blobs.kernelInfo.begin());
|
|
auto kernelHeader = reinterpret_cast<iOpenCL::SKernelBinaryHeaderCommon *>(storage.data());
|
|
kernelHeader->PatchListSize = static_cast<uint32_t>(storage.size()) - patchListOffset;
|
|
|
|
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
|
|
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
|
EXPECT_TRUE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
|
|
EXPECT_TRUE(decodedKernel.unhandledTokens.empty());
|
|
|
|
auto base = storage.data();
|
|
ASSERT_EQ(3U, decodedKernel.tokens.kernelArgs.size());
|
|
EXPECT_TRUE(tokenOffsetMatched(base, arg0Off, decodedKernel.tokens.kernelArgs[0].argInfo));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, arg1Off, decodedKernel.tokens.kernelArgs[1].argInfo));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, arg2Off, decodedKernel.tokens.kernelArgs[2].argInfo));
|
|
}
|
|
|
|
TEST(KernelDecoder, GivenKernelWithValidObjectArgPatchtokensThenDecodingSucceedsAndTokensAreProperlyAssigned) {
|
|
std::vector<uint8_t> storage;
|
|
storage.reserve(512);
|
|
auto kernelToEncode = PatchTokensTestData::ValidEmptyKernel::create(storage);
|
|
|
|
auto patchListOffset = static_cast<uint32_t>(storage.size());
|
|
|
|
iOpenCL::SPatchSamplerKernelArgument samplerTok = {};
|
|
samplerTok.Token = iOpenCL::PATCH_TOKEN::PATCH_TOKEN_SAMPLER_KERNEL_ARGUMENT;
|
|
samplerTok.Size = sizeof(samplerTok);
|
|
samplerTok.ArgumentNumber = 3;
|
|
|
|
iOpenCL::SPatchImageMemoryObjectKernelArgument imageTok = {};
|
|
imageTok.Token = iOpenCL::PATCH_TOKEN::PATCH_TOKEN_IMAGE_MEMORY_OBJECT_KERNEL_ARGUMENT;
|
|
imageTok.Size = sizeof(imageTok);
|
|
imageTok.ArgumentNumber = 1;
|
|
|
|
iOpenCL::SPatchGlobalMemoryObjectKernelArgument globalMemTok = {};
|
|
globalMemTok.Token = iOpenCL::PATCH_TOKEN::PATCH_TOKEN_GLOBAL_MEMORY_OBJECT_KERNEL_ARGUMENT;
|
|
globalMemTok.Size = sizeof(globalMemTok);
|
|
globalMemTok.ArgumentNumber = 2;
|
|
|
|
iOpenCL::SPatchStatelessGlobalMemoryObjectKernelArgument statelessGlobalMemTok = {};
|
|
statelessGlobalMemTok.Token = iOpenCL::PATCH_TOKEN::PATCH_TOKEN_STATELESS_GLOBAL_MEMORY_OBJECT_KERNEL_ARGUMENT;
|
|
statelessGlobalMemTok.Size = sizeof(statelessGlobalMemTok);
|
|
statelessGlobalMemTok.ArgumentNumber = 0;
|
|
|
|
iOpenCL::SPatchStatelessConstantMemoryObjectKernelArgument statelessConstantMemTok = {};
|
|
statelessConstantMemTok.Token = iOpenCL::PATCH_TOKEN::PATCH_TOKEN_STATELESS_CONSTANT_MEMORY_OBJECT_KERNEL_ARGUMENT;
|
|
statelessConstantMemTok.Size = sizeof(statelessConstantMemTok);
|
|
statelessConstantMemTok.ArgumentNumber = 5;
|
|
|
|
iOpenCL::SPatchStatelessDeviceQueueKernelArgument statelessDeviceQueueTok = {};
|
|
statelessDeviceQueueTok.Token = iOpenCL::PATCH_TOKEN::PATCH_TOKEN_STATELESS_DEVICE_QUEUE_KERNEL_ARGUMENT;
|
|
statelessDeviceQueueTok.Size = sizeof(iOpenCL::SPatchGlobalMemoryObjectKernelArgument);
|
|
statelessDeviceQueueTok.ArgumentNumber = 4;
|
|
|
|
auto samplerOff = pushBackToken(samplerTok, storage);
|
|
auto imageOff = pushBackToken(imageTok, storage);
|
|
auto globalMemOff = pushBackToken(globalMemTok, storage);
|
|
auto statelessGlobalMemOff = pushBackToken(statelessGlobalMemTok, storage);
|
|
auto statelessConstantMemOff = pushBackToken(statelessConstantMemTok, storage);
|
|
auto statelessDeviceQueueOff = pushBackToken(statelessDeviceQueueTok, storage);
|
|
|
|
ASSERT_EQ(storage.data(), kernelToEncode.blobs.kernelInfo.begin());
|
|
auto kernelHeader = reinterpret_cast<iOpenCL::SKernelBinaryHeaderCommon *>(storage.data());
|
|
kernelHeader->PatchListSize = static_cast<uint32_t>(storage.size()) - patchListOffset;
|
|
|
|
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
|
|
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
|
EXPECT_TRUE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
|
|
EXPECT_TRUE(decodedKernel.unhandledTokens.empty());
|
|
|
|
auto base = storage.data();
|
|
ASSERT_EQ(6U, decodedKernel.tokens.kernelArgs.size());
|
|
EXPECT_TRUE(tokenOffsetMatched(base, samplerOff, decodedKernel.tokens.kernelArgs[samplerTok.ArgumentNumber].objectArg));
|
|
EXPECT_EQ(NEO::PatchTokenBinary::ArgObjectType::Sampler, decodedKernel.tokens.kernelArgs[samplerTok.ArgumentNumber].objectType);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::ArgObjectTypeSpecialized::None, decodedKernel.tokens.kernelArgs[samplerTok.ArgumentNumber].objectTypeSpecialized);
|
|
|
|
EXPECT_TRUE(tokenOffsetMatched(base, imageOff, decodedKernel.tokens.kernelArgs[imageTok.ArgumentNumber].objectArg));
|
|
EXPECT_EQ(NEO::PatchTokenBinary::ArgObjectType::Image, decodedKernel.tokens.kernelArgs[imageTok.ArgumentNumber].objectType);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::ArgObjectTypeSpecialized::None, decodedKernel.tokens.kernelArgs[imageTok.ArgumentNumber].objectTypeSpecialized);
|
|
|
|
EXPECT_TRUE(tokenOffsetMatched(base, globalMemOff, decodedKernel.tokens.kernelArgs[globalMemTok.ArgumentNumber].objectArg));
|
|
EXPECT_EQ(NEO::PatchTokenBinary::ArgObjectType::Buffer, decodedKernel.tokens.kernelArgs[globalMemTok.ArgumentNumber].objectType);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::ArgObjectTypeSpecialized::None, decodedKernel.tokens.kernelArgs[globalMemTok.ArgumentNumber].objectTypeSpecialized);
|
|
|
|
EXPECT_TRUE(tokenOffsetMatched(base, statelessGlobalMemOff, decodedKernel.tokens.kernelArgs[statelessGlobalMemTok.ArgumentNumber].objectArg));
|
|
EXPECT_EQ(NEO::PatchTokenBinary::ArgObjectType::Buffer, decodedKernel.tokens.kernelArgs[statelessGlobalMemTok.ArgumentNumber].objectType);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::ArgObjectTypeSpecialized::None, decodedKernel.tokens.kernelArgs[statelessGlobalMemTok.ArgumentNumber].objectTypeSpecialized);
|
|
|
|
EXPECT_TRUE(tokenOffsetMatched(base, statelessConstantMemOff, decodedKernel.tokens.kernelArgs[statelessConstantMemTok.ArgumentNumber].objectArg));
|
|
EXPECT_EQ(NEO::PatchTokenBinary::ArgObjectType::Buffer, decodedKernel.tokens.kernelArgs[statelessConstantMemTok.ArgumentNumber].objectType);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::ArgObjectTypeSpecialized::None, decodedKernel.tokens.kernelArgs[statelessConstantMemTok.ArgumentNumber].objectTypeSpecialized);
|
|
|
|
EXPECT_TRUE(tokenOffsetMatched(base, statelessDeviceQueueOff, decodedKernel.tokens.kernelArgs[statelessDeviceQueueTok.ArgumentNumber].objectArg));
|
|
EXPECT_EQ(NEO::PatchTokenBinary::ArgObjectType::Buffer, decodedKernel.tokens.kernelArgs[statelessDeviceQueueTok.ArgumentNumber].objectType);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::ArgObjectTypeSpecialized::None, decodedKernel.tokens.kernelArgs[statelessDeviceQueueTok.ArgumentNumber].objectTypeSpecialized);
|
|
|
|
for (int i = 0; i < 6; ++i) {
|
|
EXPECT_EQ(nullptr, decodedKernel.tokens.kernelArgs[i].argInfo);
|
|
EXPECT_EQ(0U, decodedKernel.tokens.kernelArgs[i].byValMap.size());
|
|
EXPECT_EQ(nullptr, decodedKernel.tokens.kernelArgs[i].objectId);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::ArgObjectTypeSpecialized::None, decodedKernel.tokens.kernelArgs[i].objectTypeSpecialized);
|
|
}
|
|
}
|
|
|
|
TEST(KernelDecoder, GivenKernelWithValidNonArgCrossThreadDataPatchtokensThenDecodingSucceedsAndTokensAreProperlyAssigned) {
|
|
using namespace iOpenCL;
|
|
|
|
std::vector<uint8_t> storage;
|
|
storage.reserve(2048);
|
|
auto kernelToEncode = PatchTokensTestData::ValidEmptyKernel::create(storage);
|
|
|
|
auto patchListOffset = static_cast<uint32_t>(storage.size());
|
|
auto localWorkSize0Off = pushBackDataParameterToken(DATA_PARAMETER_LOCAL_WORK_SIZE, storage, 0U);
|
|
auto localWorkSize20Off = pushBackDataParameterToken(DATA_PARAMETER_LOCAL_WORK_SIZE, storage, 0U);
|
|
auto localWorkSize1Off = pushBackDataParameterToken(DATA_PARAMETER_LOCAL_WORK_SIZE, storage, 1U);
|
|
auto localWorkSize2Off = pushBackDataParameterToken(DATA_PARAMETER_LOCAL_WORK_SIZE, storage, 2U);
|
|
auto localWorkSize21Off = pushBackDataParameterToken(DATA_PARAMETER_LOCAL_WORK_SIZE, storage, 1U);
|
|
auto localWorkSize22Off = pushBackDataParameterToken(DATA_PARAMETER_LOCAL_WORK_SIZE, storage, 2U);
|
|
auto globalWorkOffset0Off = pushBackDataParameterToken(DATA_PARAMETER_GLOBAL_WORK_OFFSET, storage, 0U);
|
|
auto globalWorkOffset1Off = pushBackDataParameterToken(DATA_PARAMETER_GLOBAL_WORK_OFFSET, storage, 1U);
|
|
auto globalWorkOffset2Off = pushBackDataParameterToken(DATA_PARAMETER_GLOBAL_WORK_OFFSET, storage, 2U);
|
|
auto enqueuedLocalWorkSize0Off = pushBackDataParameterToken(DATA_PARAMETER_ENQUEUED_LOCAL_WORK_SIZE, storage, 0U);
|
|
auto enqueuedLocalWorkSize1Off = pushBackDataParameterToken(DATA_PARAMETER_ENQUEUED_LOCAL_WORK_SIZE, storage, 1U);
|
|
auto enqueuedLocalWorkSize2Off = pushBackDataParameterToken(DATA_PARAMETER_ENQUEUED_LOCAL_WORK_SIZE, storage, 2U);
|
|
auto globalWorkSize0Off = pushBackDataParameterToken(DATA_PARAMETER_GLOBAL_WORK_SIZE, storage, 0U);
|
|
auto globalWorkSize1Off = pushBackDataParameterToken(DATA_PARAMETER_GLOBAL_WORK_SIZE, storage, 1U);
|
|
auto globalWorkSize2Off = pushBackDataParameterToken(DATA_PARAMETER_GLOBAL_WORK_SIZE, storage, 2U);
|
|
auto numWorkGroups0Off = pushBackDataParameterToken(DATA_PARAMETER_NUM_WORK_GROUPS, storage, 0U);
|
|
auto numWorkGroups1Off = pushBackDataParameterToken(DATA_PARAMETER_NUM_WORK_GROUPS, storage, 1U);
|
|
auto numWorkGroups2Off = pushBackDataParameterToken(DATA_PARAMETER_NUM_WORK_GROUPS, storage, 2U);
|
|
auto maxWorkGroupsOff = pushBackDataParameterToken(DATA_PARAMETER_MAX_WORKGROUP_SIZE, storage);
|
|
auto workDimensionsOff = pushBackDataParameterToken(DATA_PARAMETER_WORK_DIMENSIONS, storage);
|
|
auto simdSizeOff = pushBackDataParameterToken(DATA_PARAMETER_SIMD_SIZE, storage);
|
|
auto privateMemoryStatelessSizeOff = pushBackDataParameterToken(DATA_PARAMETER_PRIVATE_MEMORY_STATELESS_SIZE, storage);
|
|
auto localMemoryStatelessWindowSizeOff = pushBackDataParameterToken(DATA_PARAMETER_LOCAL_MEMORY_STATELESS_WINDOW_SIZE, storage);
|
|
auto localMemoryStatelessWindowStartAddrOff = pushBackDataParameterToken(DATA_PARAMETER_LOCAL_MEMORY_STATELESS_WINDOW_START_ADDRESS, storage);
|
|
auto parentEventOff = pushBackDataParameterToken(DATA_PARAMETER_PARENT_EVENT, storage);
|
|
auto preferredWorkgroupMultipleOff = pushBackDataParameterToken(DATA_PARAMETER_PREFERRED_WORKGROUP_MULTIPLE, storage);
|
|
auto childBlockSimdSize0Off = pushBackDataParameterToken(DATA_PARAMETER_CHILD_BLOCK_SIMD_SIZE, storage);
|
|
auto childBlockSimdSize1Off = pushBackDataParameterToken(DATA_PARAMETER_CHILD_BLOCK_SIMD_SIZE, storage);
|
|
auto childBlockSimdSize2Off = pushBackDataParameterToken(DATA_PARAMETER_CHILD_BLOCK_SIMD_SIZE, storage);
|
|
|
|
ASSERT_EQ(storage.data(), kernelToEncode.blobs.kernelInfo.begin());
|
|
auto kernelHeader = reinterpret_cast<iOpenCL::SKernelBinaryHeaderCommon *>(storage.data());
|
|
kernelHeader->PatchListSize = static_cast<uint32_t>(storage.size()) - patchListOffset;
|
|
|
|
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
|
|
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
|
EXPECT_TRUE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
|
|
EXPECT_TRUE(decodedKernel.unhandledTokens.empty());
|
|
|
|
auto base = storage.data();
|
|
EXPECT_TRUE(tokenOffsetMatched(base, localWorkSize0Off, decodedKernel.tokens.crossThreadPayloadArgs.localWorkSize[0]));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, localWorkSize20Off, decodedKernel.tokens.crossThreadPayloadArgs.localWorkSize2[0]));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, localWorkSize1Off, decodedKernel.tokens.crossThreadPayloadArgs.localWorkSize[1]));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, localWorkSize2Off, decodedKernel.tokens.crossThreadPayloadArgs.localWorkSize[2]));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, localWorkSize21Off, decodedKernel.tokens.crossThreadPayloadArgs.localWorkSize2[1]));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, localWorkSize22Off, decodedKernel.tokens.crossThreadPayloadArgs.localWorkSize2[2]));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, globalWorkOffset0Off, decodedKernel.tokens.crossThreadPayloadArgs.globalWorkOffset[0]));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, globalWorkOffset1Off, decodedKernel.tokens.crossThreadPayloadArgs.globalWorkOffset[1]));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, globalWorkOffset2Off, decodedKernel.tokens.crossThreadPayloadArgs.globalWorkOffset[2]));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, enqueuedLocalWorkSize0Off, decodedKernel.tokens.crossThreadPayloadArgs.enqueuedLocalWorkSize[0]));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, enqueuedLocalWorkSize1Off, decodedKernel.tokens.crossThreadPayloadArgs.enqueuedLocalWorkSize[1]));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, enqueuedLocalWorkSize2Off, decodedKernel.tokens.crossThreadPayloadArgs.enqueuedLocalWorkSize[2]));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, globalWorkSize0Off, decodedKernel.tokens.crossThreadPayloadArgs.globalWorkSize[0]));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, globalWorkSize1Off, decodedKernel.tokens.crossThreadPayloadArgs.globalWorkSize[1]));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, globalWorkSize2Off, decodedKernel.tokens.crossThreadPayloadArgs.globalWorkSize[2]));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, numWorkGroups0Off, decodedKernel.tokens.crossThreadPayloadArgs.numWorkGroups[0]));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, numWorkGroups1Off, decodedKernel.tokens.crossThreadPayloadArgs.numWorkGroups[1]));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, numWorkGroups2Off, decodedKernel.tokens.crossThreadPayloadArgs.numWorkGroups[2]));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, maxWorkGroupsOff, decodedKernel.tokens.crossThreadPayloadArgs.maxWorkGroupSize));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, workDimensionsOff, decodedKernel.tokens.crossThreadPayloadArgs.workDimensions));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, simdSizeOff, decodedKernel.tokens.crossThreadPayloadArgs.simdSize));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, privateMemoryStatelessSizeOff, decodedKernel.tokens.crossThreadPayloadArgs.privateMemoryStatelessSize));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, localMemoryStatelessWindowSizeOff, decodedKernel.tokens.crossThreadPayloadArgs.localMemoryStatelessWindowSize));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, localMemoryStatelessWindowStartAddrOff, decodedKernel.tokens.crossThreadPayloadArgs.localMemoryStatelessWindowStartAddress));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, parentEventOff, decodedKernel.tokens.crossThreadPayloadArgs.parentEvent));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, preferredWorkgroupMultipleOff, decodedKernel.tokens.crossThreadPayloadArgs.preferredWorkgroupMultiple));
|
|
ASSERT_EQ(3U, decodedKernel.tokens.crossThreadPayloadArgs.childBlockSimdSize.size());
|
|
EXPECT_TRUE(tokenOffsetMatched(base, childBlockSimdSize0Off, decodedKernel.tokens.crossThreadPayloadArgs.childBlockSimdSize[0]));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, childBlockSimdSize1Off, decodedKernel.tokens.crossThreadPayloadArgs.childBlockSimdSize[1]));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, childBlockSimdSize2Off, decodedKernel.tokens.crossThreadPayloadArgs.childBlockSimdSize[2]));
|
|
}
|
|
|
|
TEST(KernelDecoder, GivenKernelWithArgCrossThreadDataPatchtokensWhenSourceIndexIsGreaterThan2ThenThenDecodingSucceedsButTokenIsMarkedAsUnhandled) {
|
|
std::vector<uint8_t> storage;
|
|
storage.reserve(128);
|
|
auto kernelToEncode = PatchTokensTestData::ValidEmptyKernel::create(storage);
|
|
|
|
auto patchListOffset = static_cast<uint32_t>(storage.size());
|
|
|
|
auto localWorkSize3Off = pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_LOCAL_WORK_SIZE, storage, 3U);
|
|
auto globalWorkOffset3Off = pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_GLOBAL_WORK_OFFSET, storage, 3U);
|
|
auto enqueuedLocalWorkSize3Off = pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_ENQUEUED_LOCAL_WORK_SIZE, storage, 3U);
|
|
auto globalWorkSize3Off = pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_GLOBAL_WORK_SIZE, storage, 3U);
|
|
auto numWorkGroups3Off = pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_NUM_WORK_GROUPS, storage, 3U);
|
|
ASSERT_EQ(storage.data(), kernelToEncode.blobs.kernelInfo.begin());
|
|
auto kernelHeader = reinterpret_cast<iOpenCL::SKernelBinaryHeaderCommon *>(storage.data());
|
|
kernelHeader->PatchListSize = static_cast<uint32_t>(storage.size()) - patchListOffset;
|
|
|
|
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
|
|
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
|
EXPECT_TRUE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
|
|
ASSERT_EQ(5U, decodedKernel.unhandledTokens.size());
|
|
|
|
auto base = storage.data();
|
|
EXPECT_TRUE(tokenOffsetMatched(base, localWorkSize3Off, decodedKernel.unhandledTokens[0]));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, globalWorkOffset3Off, decodedKernel.unhandledTokens[1]));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, enqueuedLocalWorkSize3Off, decodedKernel.unhandledTokens[2]));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, globalWorkSize3Off, decodedKernel.unhandledTokens[3]));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, numWorkGroups3Off, decodedKernel.unhandledTokens[4]));
|
|
}
|
|
|
|
TEST(KernelDecoder, GivenKernelWithUnkownPatchtokensThenDecodingSucceedsButTokenIsMarkedAsUnhandled) {
|
|
std::vector<uint8_t> storage;
|
|
storage.reserve(128);
|
|
auto kernelToEncode = PatchTokensTestData::ValidEmptyKernel::create(storage);
|
|
|
|
auto patchListOffset = static_cast<uint32_t>(storage.size());
|
|
auto unknownTokOff = pushBackToken<iOpenCL::SPatchItemHeader>(iOpenCL::NUM_PATCH_TOKENS, storage);
|
|
auto unknownCrossThreadTokOff = pushBackDataParameterToken(iOpenCL::NUM_DATA_PARAMETER_TOKENS, storage);
|
|
ASSERT_EQ(storage.data(), kernelToEncode.blobs.kernelInfo.begin());
|
|
auto kernelHeader = reinterpret_cast<iOpenCL::SKernelBinaryHeaderCommon *>(storage.data());
|
|
kernelHeader->PatchListSize = static_cast<uint32_t>(storage.size()) - patchListOffset;
|
|
|
|
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
|
|
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
|
EXPECT_TRUE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
|
|
ASSERT_EQ(2U, decodedKernel.unhandledTokens.size());
|
|
|
|
auto base = storage.data();
|
|
EXPECT_TRUE(tokenOffsetMatched(base, unknownTokOff, decodedKernel.unhandledTokens[0]));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, unknownCrossThreadTokOff, decodedKernel.unhandledTokens[1]));
|
|
}
|
|
|
|
TEST(KernelDecoder, GivenKernelWithValidObjectArgMetadataPatchtokensThenDecodingSucceedsAndTokensAreProperlyAssigned) {
|
|
std::vector<uint8_t> storage;
|
|
storage.reserve(1024);
|
|
auto kernelToEncode = PatchTokensTestData::ValidEmptyKernel::create(storage);
|
|
|
|
auto patchListOffset = static_cast<uint32_t>(storage.size());
|
|
|
|
auto arg0ObjectIdOff = pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_OBJECT_ID, storage, 0U, 0U);
|
|
auto arg0BufferOffsetOff = pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_BUFFER_OFFSET, storage, 0U, 0U);
|
|
auto arg0BufferStatefulOff = pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_BUFFER_STATEFUL, storage, 0U, 0U);
|
|
|
|
auto arg1ObjectIdOff = pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_OBJECT_ID, storage, 0U, 1U);
|
|
auto arg1ImageWidthOff = pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_IMAGE_WIDTH, storage, 0U, 1U);
|
|
auto arg1ImageHeightOff = pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_IMAGE_HEIGHT, storage, 0U, 1U);
|
|
auto arg1ImageDepthOff = pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_IMAGE_DEPTH, storage, 0U, 1U);
|
|
auto arg1ImageChannelDataTypeOff = pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_IMAGE_CHANNEL_DATA_TYPE, storage, 0U, 1U);
|
|
auto arg1ImageChannelOrderOff = pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_IMAGE_CHANNEL_ORDER, storage, 0U, 1U);
|
|
auto arg1ImageArraySizeOff = pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_IMAGE_ARRAY_SIZE, storage, 0U, 1U);
|
|
auto arg1ImageNumSamplesOff = pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_IMAGE_NUM_SAMPLES, storage, 0U, 1U);
|
|
auto arg1ImageNumMipLevelOff = pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_IMAGE_NUM_MIP_LEVELS, storage, 0U, 1U);
|
|
auto arg1FlatImageBaseOffsetOff = pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_FLAT_IMAGE_BASEOFFSET, storage, 0U, 1U);
|
|
auto arg1FlatImageWidthOff = pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_FLAT_IMAGE_WIDTH, storage, 0U, 1U);
|
|
auto arg1FlatImageHeightOff = pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_FLAT_IMAGE_HEIGHT, storage, 0U, 1U);
|
|
auto arg1FlatImagePitchOff = pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_FLAT_IMAGE_PITCH, storage, 0U, 1U);
|
|
|
|
auto arg2SamplerCoordinateSnapWaRequiredOff = pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_SAMPLER_COORDINATE_SNAP_WA_REQUIRED, storage, 0U, 2U);
|
|
auto arg2SamplerAddressModeOff = pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_SAMPLER_ADDRESS_MODE, storage, 0U, 2U);
|
|
auto arg2SamplerNormalizedCoordsOff = pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_SAMPLER_NORMALIZED_COORDS, storage, 0U, 2U);
|
|
|
|
auto arg3SlmTokenOff = pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_SUM_OF_LOCAL_MEMORY_OBJECT_ARGUMENT_SIZES, storage, 0U, 3U);
|
|
|
|
ASSERT_EQ(storage.data(), kernelToEncode.blobs.kernelInfo.begin());
|
|
auto kernelHeader = reinterpret_cast<iOpenCL::SKernelBinaryHeaderCommon *>(storage.data());
|
|
kernelHeader->PatchListSize = static_cast<uint32_t>(storage.size()) - patchListOffset;
|
|
|
|
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
|
|
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
|
EXPECT_TRUE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
|
|
EXPECT_TRUE(decodedKernel.unhandledTokens.empty());
|
|
|
|
ASSERT_EQ(4U, decodedKernel.tokens.kernelArgs.size());
|
|
ASSERT_EQ(NEO::PatchTokenBinary::ArgObjectType::Buffer, decodedKernel.tokens.kernelArgs[0].objectType);
|
|
ASSERT_EQ(NEO::PatchTokenBinary::ArgObjectType::Image, decodedKernel.tokens.kernelArgs[1].objectType);
|
|
ASSERT_EQ(NEO::PatchTokenBinary::ArgObjectType::Sampler, decodedKernel.tokens.kernelArgs[2].objectType);
|
|
ASSERT_EQ(NEO::PatchTokenBinary::ArgObjectType::Slm, decodedKernel.tokens.kernelArgs[3].objectType);
|
|
|
|
EXPECT_EQ(NEO::PatchTokenBinary::ArgObjectTypeSpecialized::None, decodedKernel.tokens.kernelArgs[0].objectTypeSpecialized);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::ArgObjectTypeSpecialized::None, decodedKernel.tokens.kernelArgs[1].objectTypeSpecialized);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::ArgObjectTypeSpecialized::None, decodedKernel.tokens.kernelArgs[2].objectTypeSpecialized);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::ArgObjectTypeSpecialized::None, decodedKernel.tokens.kernelArgs[3].objectTypeSpecialized);
|
|
|
|
auto base = storage.data();
|
|
EXPECT_TRUE(tokenOffsetMatched(base, arg0ObjectIdOff, decodedKernel.tokens.kernelArgs[0].objectId));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, arg0BufferOffsetOff, decodedKernel.tokens.kernelArgs[0].metadata.buffer.bufferOffset));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, arg0BufferStatefulOff, decodedKernel.tokens.kernelArgs[0].metadata.buffer.pureStateful));
|
|
|
|
EXPECT_TRUE(tokenOffsetMatched(base, arg1ObjectIdOff, decodedKernel.tokens.kernelArgs[1].objectId));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, arg1ImageWidthOff, decodedKernel.tokens.kernelArgs[1].metadata.image.width));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, arg1ImageHeightOff, decodedKernel.tokens.kernelArgs[1].metadata.image.height));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, arg1ImageDepthOff, decodedKernel.tokens.kernelArgs[1].metadata.image.depth));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, arg1ImageChannelDataTypeOff, decodedKernel.tokens.kernelArgs[1].metadata.image.channelDataType));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, arg1ImageChannelOrderOff, decodedKernel.tokens.kernelArgs[1].metadata.image.channelOrder));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, arg1ImageArraySizeOff, decodedKernel.tokens.kernelArgs[1].metadata.image.arraySize));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, arg1ImageNumSamplesOff, decodedKernel.tokens.kernelArgs[1].metadata.image.numSamples));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, arg1ImageNumMipLevelOff, decodedKernel.tokens.kernelArgs[1].metadata.image.numMipLevels));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, arg1FlatImageBaseOffsetOff, decodedKernel.tokens.kernelArgs[1].metadata.image.flatBaseOffset));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, arg1FlatImageWidthOff, decodedKernel.tokens.kernelArgs[1].metadata.image.flatWidth));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, arg1FlatImageHeightOff, decodedKernel.tokens.kernelArgs[1].metadata.image.flatHeight));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, arg1FlatImagePitchOff, decodedKernel.tokens.kernelArgs[1].metadata.image.flatPitch));
|
|
|
|
EXPECT_TRUE(tokenOffsetMatched(base, arg2SamplerCoordinateSnapWaRequiredOff, decodedKernel.tokens.kernelArgs[2].metadata.sampler.coordinateSnapWaRequired));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, arg2SamplerAddressModeOff, decodedKernel.tokens.kernelArgs[2].metadata.sampler.addressMode));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, arg2SamplerNormalizedCoordsOff, decodedKernel.tokens.kernelArgs[2].metadata.sampler.normalizedCoords));
|
|
|
|
EXPECT_TRUE(tokenOffsetMatched(base, arg3SlmTokenOff, decodedKernel.tokens.kernelArgs[3].metadata.slm.token));
|
|
}
|
|
|
|
TEST(KernelDecoder, GivenKernelWithMismatchedArgMetadataPatchtokensThenDecodingFails) {
|
|
std::vector<uint8_t> storage;
|
|
storage.reserve(128);
|
|
auto kernelToEncode = PatchTokensTestData::ValidEmptyKernel::create(storage);
|
|
|
|
auto patchListOffset = static_cast<uint32_t>(storage.size());
|
|
|
|
auto arg0Metadata0Off = pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_BUFFER_STATEFUL, storage, 0U, 0U);
|
|
auto arg0Metadata1Off = pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_BUFFER_OFFSET, storage, 0U, 0U);
|
|
|
|
iOpenCL::SPatchDataParameterBuffer *arg0Metadata0 = reinterpret_cast<iOpenCL::SPatchDataParameterBuffer *>(storage.data() + arg0Metadata0Off);
|
|
iOpenCL::SPatchDataParameterBuffer *arg0Metadata1 = reinterpret_cast<iOpenCL::SPatchDataParameterBuffer *>(storage.data() + arg0Metadata1Off);
|
|
|
|
ASSERT_EQ(storage.data(), kernelToEncode.blobs.kernelInfo.begin());
|
|
auto kernelHeader = reinterpret_cast<iOpenCL::SKernelBinaryHeaderCommon *>(storage.data());
|
|
kernelHeader->PatchListSize = static_cast<uint32_t>(storage.size()) - patchListOffset;
|
|
|
|
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
|
|
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
|
EXPECT_TRUE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
|
|
|
|
decodedKernel = {};
|
|
arg0Metadata0->Type = iOpenCL::DATA_PARAMETER_BUFFER_STATEFUL;
|
|
arg0Metadata1->Type = iOpenCL::DATA_PARAMETER_IMAGE_WIDTH;
|
|
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
|
EXPECT_FALSE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
|
|
EXPECT_TRUE(decodedKernel.unhandledTokens.empty());
|
|
|
|
decodedKernel = {};
|
|
arg0Metadata0->Type = iOpenCL::DATA_PARAMETER_BUFFER_STATEFUL;
|
|
arg0Metadata1->Type = iOpenCL::DATA_PARAMETER_SAMPLER_ADDRESS_MODE;
|
|
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
|
EXPECT_FALSE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
|
|
|
|
decodedKernel = {};
|
|
arg0Metadata0->Type = iOpenCL::DATA_PARAMETER_BUFFER_STATEFUL;
|
|
arg0Metadata1->Type = iOpenCL::DATA_PARAMETER_SUM_OF_LOCAL_MEMORY_OBJECT_ARGUMENT_SIZES;
|
|
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
|
EXPECT_FALSE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
|
|
|
|
decodedKernel = {};
|
|
arg0Metadata0->Type = iOpenCL::DATA_PARAMETER_IMAGE_WIDTH;
|
|
arg0Metadata1->Type = iOpenCL::DATA_PARAMETER_BUFFER_STATEFUL;
|
|
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
|
EXPECT_FALSE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
|
|
|
|
decodedKernel = {};
|
|
arg0Metadata0->Type = iOpenCL::DATA_PARAMETER_IMAGE_WIDTH;
|
|
arg0Metadata1->Type = iOpenCL::DATA_PARAMETER_SAMPLER_ADDRESS_MODE;
|
|
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
|
EXPECT_FALSE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
|
|
|
|
decodedKernel = {};
|
|
arg0Metadata0->Type = iOpenCL::DATA_PARAMETER_IMAGE_WIDTH;
|
|
arg0Metadata1->Type = iOpenCL::DATA_PARAMETER_SUM_OF_LOCAL_MEMORY_OBJECT_ARGUMENT_SIZES;
|
|
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
|
EXPECT_FALSE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
|
|
|
|
decodedKernel = {};
|
|
arg0Metadata0->Type = iOpenCL::DATA_PARAMETER_SAMPLER_ADDRESS_MODE;
|
|
arg0Metadata1->Type = iOpenCL::DATA_PARAMETER_BUFFER_STATEFUL;
|
|
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
|
EXPECT_FALSE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
|
|
|
|
decodedKernel = {};
|
|
arg0Metadata0->Type = iOpenCL::DATA_PARAMETER_SAMPLER_ADDRESS_MODE;
|
|
arg0Metadata1->Type = iOpenCL::DATA_PARAMETER_IMAGE_WIDTH;
|
|
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
|
EXPECT_FALSE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
|
|
|
|
decodedKernel = {};
|
|
arg0Metadata0->Type = iOpenCL::DATA_PARAMETER_SAMPLER_ADDRESS_MODE;
|
|
arg0Metadata1->Type = iOpenCL::DATA_PARAMETER_SUM_OF_LOCAL_MEMORY_OBJECT_ARGUMENT_SIZES;
|
|
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
|
EXPECT_FALSE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
|
|
|
|
decodedKernel = {};
|
|
arg0Metadata0->Type = iOpenCL::DATA_PARAMETER_SUM_OF_LOCAL_MEMORY_OBJECT_ARGUMENT_SIZES;
|
|
arg0Metadata1->Type = iOpenCL::DATA_PARAMETER_IMAGE_WIDTH;
|
|
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
|
EXPECT_FALSE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
|
|
|
|
decodedKernel = {};
|
|
arg0Metadata0->Type = iOpenCL::DATA_PARAMETER_SUM_OF_LOCAL_MEMORY_OBJECT_ARGUMENT_SIZES;
|
|
arg0Metadata1->Type = iOpenCL::DATA_PARAMETER_SAMPLER_ADDRESS_MODE;
|
|
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
|
EXPECT_FALSE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
|
|
|
|
decodedKernel = {};
|
|
arg0Metadata0->Type = iOpenCL::DATA_PARAMETER_SUM_OF_LOCAL_MEMORY_OBJECT_ARGUMENT_SIZES;
|
|
arg0Metadata1->Type = iOpenCL::DATA_PARAMETER_BUFFER_STATEFUL;
|
|
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
|
EXPECT_FALSE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
|
|
}
|
|
|
|
TEST(KernelDecoder, GivenKernelWithMismatchedArgMetadataPatchtokensThenDecodingFailsAndStops) {
|
|
std::vector<uint8_t> storage;
|
|
storage.reserve(128);
|
|
auto kernelToEncode = PatchTokensTestData::ValidEmptyKernel::create(storage);
|
|
|
|
auto patchListOffset = static_cast<uint32_t>(storage.size());
|
|
|
|
pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_BUFFER_STATEFUL, storage, 0U, 0U);
|
|
pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_IMAGE_DEPTH, storage, 0U, 0U);
|
|
auto unhandledTokenAfterInvalidOff = pushBackDataParameterToken(iOpenCL::NUM_DATA_PARAMETER_TOKENS, storage, 0U, 0U);
|
|
(void)unhandledTokenAfterInvalidOff;
|
|
|
|
ASSERT_EQ(storage.data(), kernelToEncode.blobs.kernelInfo.begin());
|
|
auto kernelHeader = reinterpret_cast<iOpenCL::SKernelBinaryHeaderCommon *>(storage.data());
|
|
kernelHeader->PatchListSize = static_cast<uint32_t>(storage.size()) - patchListOffset;
|
|
|
|
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
|
|
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
|
EXPECT_FALSE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
|
|
EXPECT_TRUE(decodedKernel.unhandledTokens.empty());
|
|
}
|
|
|
|
TEST(KernelDecoder, GivenKernelWithByValArgMetadataPatchtokensThenDecodingSucceedsAndTokensAreProperlyAssigned) {
|
|
std::vector<uint8_t> storage;
|
|
storage.reserve(128);
|
|
auto kernelToEncode = PatchTokensTestData::ValidEmptyKernel::create(storage);
|
|
|
|
auto patchListOffset = static_cast<uint32_t>(storage.size());
|
|
|
|
auto arg0Val0Off = pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_KERNEL_ARGUMENT, storage, 0U, 0U);
|
|
auto arg0Val1Off = pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_KERNEL_ARGUMENT, storage, 0U, 0U);
|
|
auto arg1SlmOff = pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_SUM_OF_LOCAL_MEMORY_OBJECT_ARGUMENT_SIZES, storage, 0U, 1U);
|
|
|
|
ASSERT_EQ(storage.data(), kernelToEncode.blobs.kernelInfo.begin());
|
|
auto kernelHeader = reinterpret_cast<iOpenCL::SKernelBinaryHeaderCommon *>(storage.data());
|
|
kernelHeader->PatchListSize = static_cast<uint32_t>(storage.size()) - patchListOffset;
|
|
|
|
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
|
|
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
|
EXPECT_TRUE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
|
|
EXPECT_TRUE(decodedKernel.unhandledTokens.empty());
|
|
|
|
ASSERT_EQ(2U, decodedKernel.tokens.kernelArgs.size());
|
|
EXPECT_EQ(NEO::PatchTokenBinary::ArgObjectType::None, decodedKernel.tokens.kernelArgs[0].objectType);
|
|
ASSERT_EQ(NEO::PatchTokenBinary::ArgObjectType::Slm, decodedKernel.tokens.kernelArgs[1].objectType);
|
|
|
|
ASSERT_EQ(2U, decodedKernel.tokens.kernelArgs[0].byValMap.size());
|
|
ASSERT_EQ(1U, decodedKernel.tokens.kernelArgs[1].byValMap.size());
|
|
auto base = storage.data();
|
|
EXPECT_TRUE(tokenOffsetMatched(base, arg0Val0Off, decodedKernel.tokens.kernelArgs[0].byValMap[0]));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, arg0Val1Off, decodedKernel.tokens.kernelArgs[0].byValMap[1]));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, arg1SlmOff, decodedKernel.tokens.kernelArgs[1].metadata.slm.token));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, arg1SlmOff, decodedKernel.tokens.kernelArgs[1].byValMap[0]));
|
|
}
|
|
|
|
TEST(KernelDecoder, GivenKernelWithVmeMetadataPatchtokensThenDecodingSucceedsAndTokensAreProperlyAssigned) {
|
|
std::vector<uint8_t> storage;
|
|
storage.reserve(128);
|
|
auto kernelToEncode = PatchTokensTestData::ValidEmptyKernel::create(storage);
|
|
|
|
auto patchListOffset = static_cast<uint32_t>(storage.size());
|
|
|
|
auto arg0VmeBlockTypeOff = pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_VME_MB_BLOCK_TYPE, storage, 0U, 0U);
|
|
auto arg0VmeSubpixelModeOff = pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_VME_SUBPIXEL_MODE, storage, 0U, 0U);
|
|
auto arg0VmeSadAdjustModeOff = pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_VME_SAD_ADJUST_MODE, storage, 0U, 0U);
|
|
auto arg0VmeSearchPathTypeOff = pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_VME_SEARCH_PATH_TYPE, storage, 0U, 0U);
|
|
|
|
ASSERT_EQ(storage.data(), kernelToEncode.blobs.kernelInfo.begin());
|
|
auto kernelHeader = reinterpret_cast<iOpenCL::SKernelBinaryHeaderCommon *>(storage.data());
|
|
kernelHeader->PatchListSize = static_cast<uint32_t>(storage.size()) - patchListOffset;
|
|
|
|
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
|
|
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
|
EXPECT_TRUE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
|
|
EXPECT_TRUE(decodedKernel.unhandledTokens.empty());
|
|
|
|
ASSERT_EQ(1U, decodedKernel.tokens.kernelArgs.size());
|
|
EXPECT_EQ(NEO::PatchTokenBinary::ArgObjectType::None, decodedKernel.tokens.kernelArgs[0].objectType);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::ArgObjectTypeSpecialized::Vme, decodedKernel.tokens.kernelArgs[0].objectTypeSpecialized);
|
|
;
|
|
|
|
auto base = storage.data();
|
|
EXPECT_TRUE(tokenOffsetMatched(base, arg0VmeBlockTypeOff, decodedKernel.tokens.kernelArgs[0].metadataSpecialized.vme.mbBlockType));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, arg0VmeSubpixelModeOff, decodedKernel.tokens.kernelArgs[0].metadataSpecialized.vme.subpixelMode));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, arg0VmeSadAdjustModeOff, decodedKernel.tokens.kernelArgs[0].metadataSpecialized.vme.sadAdjustMode));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, arg0VmeSearchPathTypeOff, decodedKernel.tokens.kernelArgs[0].metadataSpecialized.vme.searchPathType));
|
|
}
|
|
|
|
TEST(KernelDecoder, GivenKernelWithOutOfBoundsTokenThenDecodingFails) {
|
|
std::vector<uint8_t> storage;
|
|
storage.reserve(128);
|
|
auto kernelToEncode = PatchTokensTestData::ValidEmptyKernel::create(storage);
|
|
|
|
auto patchListOffset = static_cast<uint32_t>(storage.size());
|
|
pushBackToken<iOpenCL::SPatchSamplerStateArray>(iOpenCL::PATCH_TOKEN_SAMPLER_STATE_ARRAY, storage);
|
|
|
|
ASSERT_EQ(storage.data(), kernelToEncode.blobs.kernelInfo.begin());
|
|
auto kernelHeader = reinterpret_cast<iOpenCL::SKernelBinaryHeaderCommon *>(storage.data());
|
|
kernelHeader->PatchListSize = static_cast<uint32_t>(storage.size()) - patchListOffset;
|
|
kernelHeader->PatchListSize -= 1;
|
|
|
|
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
|
|
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
|
EXPECT_FALSE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
|
|
}
|
|
|
|
TEST(ProgramDecoder, GivenValidEmptyProgramThenDecodingOfHeaderSucceeds) {
|
|
std::vector<uint8_t> storage;
|
|
PatchTokensTestData::ValidEmptyProgram programToEncode;
|
|
NEO::PatchTokenBinary::ProgramFromPatchtokens decodedProgram;
|
|
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.blobs.programInfo, decodedProgram);
|
|
EXPECT_TRUE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedProgram.decodeStatus);
|
|
EXPECT_TRUE(decodedProgram.unhandledTokens.empty());
|
|
ASSERT_NE(nullptr, decodedProgram.header);
|
|
EXPECT_EQ(programToEncode.header, decodedProgram.header);
|
|
EXPECT_EQ(programToEncode.blobs.programInfo, decodedProgram.blobs.programInfo);
|
|
EXPECT_TRUE(decodedProgram.blobs.kernelsInfo.empty());
|
|
EXPECT_TRUE(decodedProgram.blobs.patchList.empty());
|
|
EXPECT_TRUE(decodedProgram.kernels.empty());
|
|
EXPECT_TRUE(hasEmptyTokensInfo(decodedProgram));
|
|
}
|
|
|
|
TEST(ProgramDecoder, GivenProgramWhenBlobSmallerThanProgramHeaderThenDecodingFails) {
|
|
PatchTokensTestData::ValidEmptyProgram programToEncode;
|
|
NEO::PatchTokenBinary::ProgramFromPatchtokens decodedProgram;
|
|
auto brokenBlob = ArrayRef<const uint8_t>(programToEncode.blobs.programInfo.begin(),
|
|
programToEncode.blobs.programInfo.begin() + sizeof(iOpenCL::SProgramBinaryHeader) - 1);
|
|
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(brokenBlob, decodedProgram);
|
|
EXPECT_FALSE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedProgram.decodeStatus);
|
|
}
|
|
|
|
TEST(ProgramDecoder, GivenProgramWithInvaidProgramMagicThenDecodingFails) {
|
|
PatchTokensTestData::ValidEmptyProgram programToEncode;
|
|
NEO::PatchTokenBinary::ProgramFromPatchtokens decodedProgram;
|
|
programToEncode.headerMutable->Magic += 1;
|
|
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.blobs.programInfo, decodedProgram);
|
|
EXPECT_FALSE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedProgram.decodeStatus);
|
|
}
|
|
|
|
TEST(ProgramDecoder, GivenProgramWhenBlobDoesntHaveEnoughSpaceForPatchListThenDecodingFails) {
|
|
PatchTokensTestData::ValidEmptyProgram programToEncode;
|
|
NEO::PatchTokenBinary::ProgramFromPatchtokens decodedProgram;
|
|
programToEncode.headerMutable->PatchListSize = static_cast<uint32_t>(programToEncode.blobs.patchList.size() + 1);
|
|
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.blobs.programInfo, decodedProgram);
|
|
EXPECT_FALSE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedProgram.decodeStatus);
|
|
}
|
|
|
|
TEST(ProgramDecoder, GivenValidProgramWithConstantSurfacesThenDecodingSucceedsAndTokensAreProperlyAssigned) {
|
|
PatchTokensTestData::ValidProgramWithConstantSurface programToEncode;
|
|
NEO::PatchTokenBinary::ProgramFromPatchtokens decodedProgram;
|
|
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.blobs.programInfo, decodedProgram);
|
|
EXPECT_TRUE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedProgram.decodeStatus);
|
|
EXPECT_TRUE(decodedProgram.unhandledTokens.empty());
|
|
ASSERT_EQ(1U, decodedProgram.programScopeTokens.allocateConstantMemorySurface.size());
|
|
EXPECT_EQ(programToEncode.programScopeTokens.allocateConstantMemorySurface[0], decodedProgram.programScopeTokens.allocateConstantMemorySurface[0]);
|
|
|
|
decodedProgram = {};
|
|
auto inlineSize = programToEncode.programScopeTokens.allocateConstantMemorySurface[0]->InlineDataSize;
|
|
auto secondConstantSurfaceOff = programToEncode.storage.size();
|
|
programToEncode.storage.insert(programToEncode.storage.end(), reinterpret_cast<uint8_t *>(programToEncode.constSurfMutable),
|
|
reinterpret_cast<uint8_t *>(programToEncode.constSurfMutable + 1));
|
|
programToEncode.storage.resize(programToEncode.storage.size() + inlineSize);
|
|
programToEncode.recalcTokPtr();
|
|
decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.blobs.programInfo, decodedProgram);
|
|
EXPECT_TRUE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedProgram.decodeStatus);
|
|
EXPECT_TRUE(decodedProgram.unhandledTokens.empty());
|
|
|
|
auto base = programToEncode.storage.data();
|
|
ASSERT_EQ(2U, decodedProgram.programScopeTokens.allocateConstantMemorySurface.size());
|
|
EXPECT_EQ(programToEncode.programScopeTokens.allocateConstantMemorySurface[0], decodedProgram.programScopeTokens.allocateConstantMemorySurface[0]);
|
|
EXPECT_TRUE(tokenOffsetMatched(base, secondConstantSurfaceOff, decodedProgram.programScopeTokens.allocateConstantMemorySurface[1]));
|
|
}
|
|
|
|
TEST(ProgramDecoder, GivenProgramWithConstantSurfaceWhenBlobSmallerThanNeededForInlineDataThenDecodingFails) {
|
|
PatchTokensTestData::ValidProgramWithConstantSurface programToEncode;
|
|
NEO::PatchTokenBinary::ProgramFromPatchtokens decodedProgram;
|
|
programToEncode.headerMutable->PatchListSize -= 1;
|
|
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.blobs.programInfo, decodedProgram);
|
|
EXPECT_FALSE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedProgram.decodeStatus);
|
|
}
|
|
|
|
TEST(ProgramDecoder, GivenValidProgramWithGlobalSurfacesThenDecodingSucceedsAndTokensAreProperlyAssigned) {
|
|
PatchTokensTestData::ValidProgramWithGlobalSurface programToEncode;
|
|
NEO::PatchTokenBinary::ProgramFromPatchtokens decodedProgram;
|
|
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.blobs.programInfo, decodedProgram);
|
|
EXPECT_TRUE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedProgram.decodeStatus);
|
|
EXPECT_TRUE(decodedProgram.unhandledTokens.empty());
|
|
ASSERT_EQ(1U, decodedProgram.programScopeTokens.allocateGlobalMemorySurface.size());
|
|
EXPECT_EQ(programToEncode.programScopeTokens.allocateGlobalMemorySurface[0], decodedProgram.programScopeTokens.allocateGlobalMemorySurface[0]);
|
|
|
|
decodedProgram = {};
|
|
auto inlineSize = programToEncode.programScopeTokens.allocateGlobalMemorySurface[0]->InlineDataSize;
|
|
auto secondGlobalSurfaceOff = programToEncode.storage.size();
|
|
programToEncode.storage.insert(programToEncode.storage.end(), reinterpret_cast<uint8_t *>(programToEncode.globalSurfMutable),
|
|
reinterpret_cast<uint8_t *>(programToEncode.globalSurfMutable + 1));
|
|
programToEncode.storage.resize(programToEncode.storage.size() + inlineSize);
|
|
programToEncode.recalcTokPtr();
|
|
decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.blobs.programInfo, decodedProgram);
|
|
EXPECT_TRUE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedProgram.decodeStatus);
|
|
EXPECT_TRUE(decodedProgram.unhandledTokens.empty());
|
|
|
|
auto base = programToEncode.storage.data();
|
|
ASSERT_EQ(2U, decodedProgram.programScopeTokens.allocateGlobalMemorySurface.size());
|
|
EXPECT_EQ(programToEncode.programScopeTokens.allocateGlobalMemorySurface[0], decodedProgram.programScopeTokens.allocateGlobalMemorySurface[0]);
|
|
EXPECT_TRUE(tokenOffsetMatched(base, secondGlobalSurfaceOff, decodedProgram.programScopeTokens.allocateGlobalMemorySurface[1]));
|
|
}
|
|
|
|
TEST(ProgramDecoder, GivenProgramWithGlobalSurfaceWhenBlobSmallerThanNeededForInlineDataThenDecodingFails) {
|
|
PatchTokensTestData::ValidProgramWithGlobalSurface programToEncode;
|
|
NEO::PatchTokenBinary::ProgramFromPatchtokens decodedProgram;
|
|
programToEncode.headerMutable->PatchListSize -= 1;
|
|
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.blobs.programInfo, decodedProgram);
|
|
EXPECT_FALSE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedProgram.decodeStatus);
|
|
}
|
|
|
|
TEST(ProgramDecoder, GivenValidProgramWithPatchtokensThenDecodingSucceedsAndTokensAreProperlyAssinged) {
|
|
using namespace iOpenCL;
|
|
|
|
PatchTokensTestData::ValidProgramWithConstantSurfaceAndPointer programToEncode;
|
|
NEO::PatchTokenBinary::ProgramFromPatchtokens decodedProgram;
|
|
auto constPointer1Off = pushBackToken<SPatchConstantPointerProgramBinaryInfo>(PATCH_TOKEN_CONSTANT_POINTER_PROGRAM_BINARY_INFO, programToEncode.storage);
|
|
auto constPointer2Off = pushBackToken<SPatchConstantPointerProgramBinaryInfo>(PATCH_TOKEN_CONSTANT_POINTER_PROGRAM_BINARY_INFO, programToEncode.storage);
|
|
auto globalPointer0Off = pushBackToken<SPatchGlobalPointerProgramBinaryInfo>(PATCH_TOKEN_GLOBAL_POINTER_PROGRAM_BINARY_INFO, programToEncode.storage);
|
|
auto globalPointer1Off = pushBackToken<SPatchGlobalPointerProgramBinaryInfo>(PATCH_TOKEN_GLOBAL_POINTER_PROGRAM_BINARY_INFO, programToEncode.storage);
|
|
auto symbolTableOff = pushBackToken<SPatchFunctionTableInfo>(PATCH_TOKEN_PROGRAM_SYMBOL_TABLE, programToEncode.storage);
|
|
programToEncode.recalcTokPtr();
|
|
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.blobs.programInfo, decodedProgram);
|
|
EXPECT_TRUE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedProgram.decodeStatus);
|
|
EXPECT_TRUE(decodedProgram.unhandledTokens.empty());
|
|
auto base = programToEncode.storage.data();
|
|
|
|
EXPECT_EQ(1U, programToEncode.programScopeTokens.constantPointer.size());
|
|
ASSERT_EQ(3U, decodedProgram.programScopeTokens.constantPointer.size());
|
|
ASSERT_EQ(2U, decodedProgram.programScopeTokens.globalPointer.size());
|
|
EXPECT_TRUE(tokenOffsetMatched(base, constPointer1Off, decodedProgram.programScopeTokens.constantPointer[1]));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, constPointer2Off, decodedProgram.programScopeTokens.constantPointer[2]));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, globalPointer0Off, decodedProgram.programScopeTokens.globalPointer[0]));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, globalPointer1Off, decodedProgram.programScopeTokens.globalPointer[1]));
|
|
EXPECT_TRUE(tokenOffsetMatched(base, symbolTableOff, decodedProgram.programScopeTokens.symbolTable));
|
|
}
|
|
|
|
TEST(ProgramDecoder, GivenProgramWithUnkownPatchtokensThenDecodingSucceedsButTokenIsMarkedAsUnhandled) {
|
|
PatchTokensTestData::ValidProgramWithConstantSurface programToEncode;
|
|
NEO::PatchTokenBinary::ProgramFromPatchtokens decodedProgram;
|
|
|
|
programToEncode.constSurfMutable->Token = iOpenCL::NUM_PATCH_TOKENS;
|
|
programToEncode.constSurfMutable->Size += programToEncode.constSurfMutable->InlineDataSize;
|
|
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.blobs.programInfo, decodedProgram);
|
|
EXPECT_TRUE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedProgram.decodeStatus);
|
|
ASSERT_EQ(1U, decodedProgram.unhandledTokens.size());
|
|
EXPECT_EQ(programToEncode.constSurfMutable, decodedProgram.unhandledTokens[0]);
|
|
}
|
|
|
|
TEST(ProgramDecoder, GivenValidProgramWithKernelThenDecodingSucceedsAndTokensAreProperlyAssigned) {
|
|
PatchTokensTestData::ValidProgramWithKernelUsingSlm programToEncode;
|
|
NEO::PatchTokenBinary::ProgramFromPatchtokens decodedProgram;
|
|
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.blobs.programInfo, decodedProgram);
|
|
EXPECT_TRUE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedProgram.decodeStatus);
|
|
EXPECT_TRUE(decodedProgram.unhandledTokens.empty());
|
|
ASSERT_EQ(1U, decodedProgram.header->NumberOfKernels);
|
|
ASSERT_EQ(1U, decodedProgram.kernels.size());
|
|
auto decodedKernel = decodedProgram.kernels[0];
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
|
|
EXPECT_TRUE(decodedKernel.unhandledTokens.empty());
|
|
EXPECT_NE(nullptr, decodedKernel.tokens.allocateLocalSurface);
|
|
}
|
|
|
|
TEST(ProgramDecoder, GivenValidProgramWithTwoKernelsWhenThenDecodingSucceeds) {
|
|
PatchTokensTestData::ValidProgramWithKernelUsingSlm programToEncode;
|
|
programToEncode.headerMutable->NumberOfKernels = 2;
|
|
programToEncode.storage.insert(programToEncode.storage.end(), programToEncode.kernels[0].blobs.kernelInfo.begin(), programToEncode.kernels[0].blobs.kernelInfo.end());
|
|
NEO::PatchTokenBinary::ProgramFromPatchtokens decodedProgram;
|
|
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.storage, decodedProgram);
|
|
EXPECT_TRUE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedProgram.decodeStatus);
|
|
EXPECT_TRUE(decodedProgram.unhandledTokens.empty());
|
|
EXPECT_EQ(2U, decodedProgram.header->NumberOfKernels);
|
|
ASSERT_EQ(2U, decodedProgram.kernels.size());
|
|
|
|
auto decodedKernel0 = decodedProgram.kernels[0];
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel0.decodeStatus);
|
|
EXPECT_TRUE(decodedKernel0.unhandledTokens.empty());
|
|
EXPECT_NE(nullptr, decodedKernel0.tokens.allocateLocalSurface);
|
|
|
|
auto decodedKernel1 = decodedProgram.kernels[0];
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel1.decodeStatus);
|
|
EXPECT_TRUE(decodedKernel1.unhandledTokens.empty());
|
|
EXPECT_NE(nullptr, decodedKernel1.tokens.allocateLocalSurface);
|
|
}
|
|
|
|
TEST(ProgramDecoder, GivenPatchTokenWithZeroSizeThenDecodingFailsAndStops) {
|
|
PatchTokensTestData::ValidProgramWithKernelUsingSlm programToEncode;
|
|
programToEncode.slmMutable->Size = 0U;
|
|
NEO::PatchTokenBinary::ProgramFromPatchtokens decodedProgram;
|
|
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.storage, decodedProgram);
|
|
EXPECT_FALSE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedProgram.decodeStatus);
|
|
}
|
|
|
|
TEST(ProgramDecoder, GivenProgramWithMultipleKernelsWhenFailsToDecodeKernelThenDecodingFailsAndStops) {
|
|
PatchTokensTestData::ValidProgramWithKernelUsingSlm programToEncode;
|
|
programToEncode.slmMutable->Size = 0U;
|
|
programToEncode.headerMutable->NumberOfKernels = 2;
|
|
programToEncode.storage.insert(programToEncode.storage.end(), programToEncode.kernels[0].blobs.kernelInfo.begin(), programToEncode.kernels[0].blobs.kernelInfo.end());
|
|
NEO::PatchTokenBinary::ProgramFromPatchtokens decodedProgram;
|
|
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.storage, decodedProgram);
|
|
EXPECT_FALSE(decodeSuccess);
|
|
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedProgram.decodeStatus);
|
|
EXPECT_TRUE(decodedProgram.unhandledTokens.empty());
|
|
EXPECT_EQ(2U, decodedProgram.header->NumberOfKernels);
|
|
EXPECT_EQ(1U, decodedProgram.kernels.size());
|
|
}
|