Program refactor

* decouple program_info
* move global allocations relocation to linker
* remove obsolete tests
* initial cleanup to kernel_info kernelInfo
* unified patchtoken validation

Change-Id: I0567cd6d607b4f3cf44e6caf33681f6210760f76
This commit is contained in:
Jaroslaw Chodor
2020-01-11 18:25:26 +01:00
committed by sys_ocldev
parent 570b09850d
commit f057712fa7
68 changed files with 3442 additions and 1705 deletions

2
Jenkinsfile vendored
View File

@@ -1,5 +1,5 @@
#!groovy
dependenciesRevision='8a86a70513be57f370417793c63ca03d55824432-1362'
strategy='EQUAL'
allowedCD=257
allowedCD=253
allowedF=11

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017-2019 Intel Corporation
* Copyright (C) 2017-2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -29,13 +29,14 @@ bool LinkerInput::decodeGlobalVariablesSymbolTable(const void *data, uint32_t nu
switch (symbolEntryIt->s_type) {
default:
DEBUG_BREAK_IF(true);
this->valid = false;
return false;
case vISA::S_GLOBAL_VAR:
symbolInfo.type = SymbolInfo::GlobalVariable;
symbolInfo.segment = SegmentType::GlobalVariables;
traits.exportsGlobalVariables = true;
break;
case vISA::S_GLOBAL_VAR_CONST:
symbolInfo.type = SymbolInfo::GlobalConstant;
symbolInfo.segment = SegmentType::GlobalConstants;
traits.exportsGlobalConstants = true;
break;
}
@@ -54,17 +55,18 @@ bool LinkerInput::decodeExportedFunctionsSymbolTable(const void *data, uint32_t
switch (symbolEntryIt->s_type) {
default:
DEBUG_BREAK_IF(true);
this->valid = false;
return false;
case vISA::S_GLOBAL_VAR:
symbolInfo.type = SymbolInfo::GlobalVariable;
symbolInfo.segment = SegmentType::GlobalVariables;
traits.exportsGlobalVariables = true;
break;
case vISA::S_GLOBAL_VAR_CONST:
symbolInfo.type = SymbolInfo::GlobalConstant;
symbolInfo.segment = SegmentType::GlobalConstants;
traits.exportsGlobalConstants = true;
break;
case vISA::S_FUNC:
symbolInfo.type = SymbolInfo::Function;
symbolInfo.segment = SegmentType::Instructions;
traits.exportsFunctions = true;
UNRECOVERABLE_IF((this->exportedFunctionsSegmentId != -1) && (this->exportedFunctionsSegmentId != static_cast<int32_t>(instructionsSegmentId)));
this->exportedFunctionsSegmentId = static_cast<int32_t>(instructionsSegmentId);
@@ -89,9 +91,12 @@ bool LinkerInput::decodeRelocationTable(const void *data, uint32_t numEntries, u
RelocationInfo relocInfo{};
relocInfo.offset = relocEntryIt->r_offset;
relocInfo.symbolName = relocEntryIt->r_symbol;
relocInfo.symbolSegment = SegmentType::Unknown;
relocInfo.relocationSegment = SegmentType::Instructions;
switch (relocEntryIt->r_type) {
default:
DEBUG_BREAK_IF(true);
this->valid = false;
return false;
case vISA::R_SYM_ADDR:
relocInfo.type = RelocationInfo::Type::Address;
@@ -108,21 +113,30 @@ bool LinkerInput::decodeRelocationTable(const void *data, uint32_t numEntries, u
return true;
}
bool Linker::processRelocations(const Segment &globalVariables, const Segment &globalConstants, const Segment &exportedFunctions) {
void LinkerInput::addDataRelocationInfo(const RelocationInfo &relocationInfo) {
DEBUG_BREAK_IF((relocationInfo.relocationSegment != SegmentType::GlobalConstants) && (relocationInfo.relocationSegment != SegmentType::GlobalVariables));
DEBUG_BREAK_IF((relocationInfo.symbolSegment != SegmentType::GlobalConstants) && (relocationInfo.symbolSegment != SegmentType::GlobalVariables));
DEBUG_BREAK_IF(relocationInfo.type == LinkerInput::RelocationInfo::Type::AddressHigh);
this->traits.requiresPatchingOfGlobalVariablesBuffer |= (relocationInfo.relocationSegment == SegmentType::GlobalVariables);
this->traits.requiresPatchingOfGlobalConstantsBuffer |= (relocationInfo.relocationSegment == SegmentType::GlobalConstants);
this->dataRelocations.push_back(relocationInfo);
}
bool Linker::processRelocations(const SegmentInfo &globalVariables, const SegmentInfo &globalConstants, const SegmentInfo &exportedFunctions) {
relocatedSymbols.reserve(data.getSymbols().size());
for (auto &symbol : data.getSymbols()) {
const Segment *seg = nullptr;
switch (symbol.second.type) {
const SegmentInfo *seg = nullptr;
switch (symbol.second.segment) {
default:
DEBUG_BREAK_IF(true);
return false;
case SymbolInfo::GlobalVariable:
case SegmentType::GlobalVariables:
seg = &globalVariables;
break;
case SymbolInfo::GlobalConstant:
case SegmentType::GlobalConstants:
seg = &globalConstants;
break;
case SymbolInfo::Function:
case SegmentType::Instructions:
seg = &exportedFunctions;
break;
}
@@ -136,28 +150,33 @@ bool Linker::processRelocations(const Segment &globalVariables, const Segment &g
return true;
}
uint32_t addressSizeInBytes(LinkerInput::RelocationInfo::Type relocationtype) {
return (relocationtype == LinkerInput::RelocationInfo::Type::Address) ? sizeof(uintptr_t) : sizeof(uint32_t);
}
bool Linker::patchInstructionsSegments(const std::vector<PatchableSegment> &instructionsSegments, std::vector<UnresolvedExternal> &outUnresolvedExternals) {
if (false == data.getTraits().requiresPatchingOfInstructionSegments) {
return true;
}
UNRECOVERABLE_IF(data.getRelocations().size() > instructionsSegments.size());
std::vector<UnresolvedExternal> unresolvedExternals;
UNRECOVERABLE_IF(data.getRelocationsInInstructionSegments().size() > instructionsSegments.size());
auto unresolvedExternalsPrev = outUnresolvedExternals.size();
auto segIt = instructionsSegments.begin();
for (auto relocsIt = data.getRelocations().begin(), relocsEnd = data.getRelocations().end();
for (auto relocsIt = data.getRelocationsInInstructionSegments().begin(), relocsEnd = data.getRelocationsInInstructionSegments().end();
relocsIt != relocsEnd; ++relocsIt, ++segIt) {
auto &thisSegmentRelocs = *relocsIt;
const PatchableSegment &instSeg = *segIt;
for (const auto &relocation : thisSegmentRelocs) {
auto relocAddress = ptrOffset(instSeg.hostPointer, relocation.offset);
UNRECOVERABLE_IF(nullptr == instSeg.hostPointer);
auto relocAddress = ptrOffset(instSeg.hostPointer, static_cast<uintptr_t>(relocation.offset));
auto symbolIt = relocatedSymbols.find(relocation.symbolName);
bool invalidOffset = relocation.offset + sizeof(uintptr_t) > instSeg.segmentSize;
bool invalidOffset = relocation.offset + addressSizeInBytes(relocation.type) > instSeg.segmentSize;
bool unresolvedExternal = (symbolIt == relocatedSymbols.end());
DEBUG_BREAK_IF(invalidOffset);
if (invalidOffset || unresolvedExternal) {
uint32_t segId = static_cast<uint32_t>(segIt - instructionsSegments.begin());
unresolvedExternals.push_back(UnresolvedExternal{relocation, segId, invalidOffset});
outUnresolvedExternals.push_back(UnresolvedExternal{relocation, segId, invalidOffset});
continue;
}
@@ -176,8 +195,71 @@ bool Linker::patchInstructionsSegments(const std::vector<PatchableSegment> &inst
}
}
}
outUnresolvedExternals.swap(unresolvedExternals);
return outUnresolvedExternals.size() == 0;
return outUnresolvedExternals.size() == unresolvedExternalsPrev;
}
bool Linker::patchDataSegments(const SegmentInfo &globalVariablesSegInfo, const SegmentInfo &globalConstantsSegInfo,
PatchableSegment &globalVariablesSeg, PatchableSegment &globalConstantsSeg,
std::vector<UnresolvedExternal> &outUnresolvedExternals) {
if (false == (data.getTraits().requiresPatchingOfGlobalConstantsBuffer || data.getTraits().requiresPatchingOfGlobalVariablesBuffer)) {
return true;
}
auto unresolvedExternalsPrev = outUnresolvedExternals.size();
for (const auto &relocation : data.getDataRelocations()) {
const SegmentInfo *src = nullptr;
const PatchableSegment *dst = nullptr;
switch (relocation.symbolSegment) {
default:
outUnresolvedExternals.push_back(UnresolvedExternal{relocation});
continue;
case SegmentType::GlobalVariables:
src = &globalVariablesSegInfo;
break;
case SegmentType::GlobalConstants:
src = &globalConstantsSegInfo;
break;
}
switch (relocation.relocationSegment) {
default:
outUnresolvedExternals.push_back(UnresolvedExternal{relocation});
continue;
case SegmentType::GlobalVariables:
dst = &globalVariablesSeg;
break;
case SegmentType::GlobalConstants:
dst = &globalConstantsSeg;
break;
}
UNRECOVERABLE_IF(nullptr == dst->hostPointer);
if (RelocationInfo::Type::AddressHigh == relocation.type) {
outUnresolvedExternals.push_back(UnresolvedExternal{relocation});
continue;
}
auto relocType = (LinkerInput::Traits::PointerSize::Ptr32bit == data.getTraits().pointerSize) ? RelocationInfo::Type::AddressLow : relocation.type;
bool invalidOffset = relocation.offset + addressSizeInBytes(relocType) > dst->segmentSize;
DEBUG_BREAK_IF(invalidOffset);
if (invalidOffset) {
outUnresolvedExternals.push_back(UnresolvedExternal{relocation});
continue;
}
uint64_t gpuAddressAs64bit = src->gpuAddress;
auto relocAddress = ptrOffset(dst->hostPointer, static_cast<uintptr_t>(relocation.offset));
switch (relocType) {
default:
UNRECOVERABLE_IF(RelocationInfo::Type::Address != relocType);
patchIncrement(relocAddress, sizeof(uintptr_t), gpuAddressAs64bit);
break;
case RelocationInfo::Type::AddressLow:
patchIncrement(relocAddress, 4, static_cast<uint32_t>(gpuAddressAs64bit & 0xffffffff));
break;
}
}
return outUnresolvedExternals.size() == unresolvedExternalsPrev;
}
std::string constructLinkerErrorMessage(const Linker::UnresolvedExternals &unresolvedExternals, const std::vector<std::string> &instructionsSegmentsNames) {
@@ -191,10 +273,16 @@ std::string constructLinkerErrorMessage(const Linker::UnresolvedExternals &unres
} else {
errorStream << "error : unresolved external symbol ";
}
errorStream << unresExtern.unresolvedRelocation.symbolName << " at offset " << unresExtern.unresolvedRelocation.offset
<< " in instructions segment #" << unresExtern.instructionsSegmentId;
if (instructionsSegmentsNames.size() > unresExtern.instructionsSegmentId) {
errorStream << " (aka " << instructionsSegmentsNames[unresExtern.instructionsSegmentId] << ")";
if (unresExtern.unresolvedRelocation.relocationSegment == NEO::SegmentType::Instructions) {
errorStream << unresExtern.unresolvedRelocation.symbolName << " at offset " << unresExtern.unresolvedRelocation.offset
<< " in instructions segment #" << unresExtern.instructionsSegmentId;
if (instructionsSegmentsNames.size() > unresExtern.instructionsSegmentId) {
errorStream << " (aka " << instructionsSegmentsNames[unresExtern.instructionsSegmentId] << ")";
}
} else {
errorStream << " address of segment #" << asString(unresExtern.unresolvedRelocation.symbolSegment) << " at offset " << unresExtern.unresolvedRelocation.offset
<< " in data segment #" << asString(unresExtern.unresolvedRelocation.relocationSegment);
}
errorStream << "\n";
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017-2019 Intel Corporation
* Copyright (C) 2017-2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -16,28 +16,49 @@
namespace NEO {
enum class SegmentType : uint32_t {
Unknown,
GlobalConstants,
GlobalVariables,
Instructions,
};
inline const char *asString(SegmentType segment) {
switch (segment) {
default:
return "UNKOWN";
case SegmentType::GlobalConstants:
return "GLOBAL_CONSTANTS";
case SegmentType::GlobalVariables:
return "GLOBAL_VARIABLES";
case SegmentType::Instructions:
return "INSTRUCTIONS";
}
}
struct SymbolInfo {
enum Type : uint32_t {
Unknown,
GlobalConstant,
GlobalVariable,
Function
};
uint32_t offset = std::numeric_limits<uint32_t>::max();
uint32_t size = std::numeric_limits<uint32_t>::max();
Type type = Unknown;
SegmentType segment = SegmentType::Unknown;
};
struct LinkerInput {
union Traits {
enum PointerSize : uint8_t {
Ptr32bit = 0,
Ptr64bit = 1
};
Traits() : packed(0) {
pointerSize = (sizeof(void *) == 4) ? PointerSize::Ptr32bit : PointerSize::Ptr64bit;
}
struct {
bool exportsGlobalVariables : 1;
bool exportsGlobalConstants : 1;
bool exportsFunctions : 1;
bool requiresPatchingOfInstructionSegments : 1;
bool requiresPatchingOfGlobalVariablesBuffer : 1;
bool requiresPatchingOfGlobalConstantsBuffer : 1;
uint8_t pointerSize : 1;
};
uint32_t packed;
};
@@ -52,17 +73,22 @@ struct LinkerInput {
};
std::string symbolName;
uint32_t offset = std::numeric_limits<uint32_t>::max();
uint64_t offset = std::numeric_limits<uint64_t>::max();
Type type = Type::Unknown;
SegmentType relocationSegment = SegmentType::Unknown;
SegmentType symbolSegment = SegmentType::Unknown;
};
using Relocations = std::vector<RelocationInfo>;
using SymbolMap = std::unordered_map<std::string, SymbolInfo>;
using RelocationsPerInstSegment = std::vector<Relocations>;
bool decodeGlobalVariablesSymbolTable(const void *data, uint32_t numEntries);
bool decodeExportedFunctionsSymbolTable(const void *data, uint32_t numEntries, uint32_t instructionsSegmentId);
bool decodeRelocationTable(const void *data, uint32_t numEntries, uint32_t instructionsSegmentId);
virtual ~LinkerInput() = default;
MOCKABLE_VIRTUAL bool decodeGlobalVariablesSymbolTable(const void *data, uint32_t numEntries);
MOCKABLE_VIRTUAL bool decodeExportedFunctionsSymbolTable(const void *data, uint32_t numEntries, uint32_t instructionsSegmentId);
MOCKABLE_VIRTUAL bool decodeRelocationTable(const void *data, uint32_t numEntries, uint32_t instructionsSegmentId);
void addDataRelocationInfo(const RelocationInfo &relocationInfo);
const Traits &getTraits() const {
return traits;
@@ -76,21 +102,35 @@ struct LinkerInput {
return symbols;
}
const RelocationsPerInstSegment &getRelocations() const {
const RelocationsPerInstSegment &getRelocationsInInstructionSegments() const {
return relocations;
}
const Relocations &getDataRelocations() const {
return dataRelocations;
}
void setPointerSize(Traits::PointerSize pointerSize) {
traits.pointerSize = pointerSize;
}
bool isValid() const {
return valid;
}
protected:
Traits traits;
SymbolMap symbols;
RelocationsPerInstSegment relocations;
Relocations dataRelocations;
int32_t exportedFunctionsSegmentId = -1;
bool valid = true;
};
struct Linker {
using RelocationInfo = LinkerInput::RelocationInfo;
struct Segment {
struct SegmentInfo {
uintptr_t gpuAddress = std::numeric_limits<uintptr_t>::max();
size_t segmentSize = std::numeric_limits<size_t>::max();
};
@@ -119,10 +159,15 @@ struct Linker {
: data(data) {
}
bool link(const Segment &globalVariables, const Segment &globalConstants, const Segment &exportedFunctions,
const PatchableSegments &instructionsSegments,
bool link(const SegmentInfo &globalVariablesSegInfo, const SegmentInfo &globalConstantsSegInfo, const SegmentInfo &exportedFunctionsSegInfo,
PatchableSegment &globalVariablesSeg, PatchableSegment &globalConstantsSeg, const PatchableSegments &instructionsSegments,
UnresolvedExternals &outUnresolvedExternals) {
return processRelocations(globalVariables, globalConstants, exportedFunctions) && patchInstructionsSegments(instructionsSegments, outUnresolvedExternals);
bool success = data.isValid();
success = success && processRelocations(globalVariablesSegInfo, globalConstantsSegInfo, exportedFunctionsSegInfo);
success = success && patchInstructionsSegments(instructionsSegments, outUnresolvedExternals);
success = success && patchDataSegments(globalVariablesSegInfo, globalConstantsSegInfo, globalVariablesSeg, globalConstantsSeg, outUnresolvedExternals);
return success;
}
RelocatedSymbolsMap extractRelocatedSymbols() {
@@ -133,9 +178,13 @@ struct Linker {
const LinkerInput &data;
RelocatedSymbolsMap relocatedSymbols;
bool processRelocations(const Segment &globalVariables, const Segment &globalConstants, const Segment &exportedFunctions);
bool processRelocations(const SegmentInfo &globalVariables, const SegmentInfo &globalConstants, const SegmentInfo &exportedFunctions);
bool patchInstructionsSegments(const std::vector<PatchableSegment> &instructionsSegments, std::vector<UnresolvedExternal> &outUnresolvedExternals);
bool patchDataSegments(const SegmentInfo &globalVariablesSegInfo, const SegmentInfo &globalConstantsSegInfo,
PatchableSegment &globalVariablesSeg, PatchableSegment &globalConstantsSeg,
std::vector<UnresolvedExternal> &outUnresolvedExternals);
};
std::string constructLinkerErrorMessage(const Linker::UnresolvedExternals &unresolvedExternals, const std::vector<std::string> &instructionsSegmentsNames);

View File

@@ -1,5 +1,5 @@
#
# Copyright (C) 2019 Intel Corporation
# Copyright (C) 2019-2020 Intel Corporation
#
# SPDX-License-Identifier: MIT
#
@@ -8,6 +8,12 @@ set(NEO_CORE_PROGRAM
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
${CMAKE_CURRENT_SOURCE_DIR}/print_formatter.cpp
${CMAKE_CURRENT_SOURCE_DIR}/print_formatter.h
${CMAKE_CURRENT_SOURCE_DIR}/program_info.cpp
${CMAKE_CURRENT_SOURCE_DIR}/program_info.h
${CMAKE_CURRENT_SOURCE_DIR}/program_info_from_patchtokens.cpp
${CMAKE_CURRENT_SOURCE_DIR}/program_info_from_patchtokens.h
${CMAKE_CURRENT_SOURCE_DIR}/program_initialization.cpp
${CMAKE_CURRENT_SOURCE_DIR}/program_initialization.h
${CMAKE_CURRENT_SOURCE_DIR}/sync_buffer_handler.cpp
${CMAKE_CURRENT_SOURCE_DIR}/sync_buffer_handler.h
)

View File

@@ -0,0 +1,21 @@
/*
* Copyright (C) 2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "core/program/program_info.h"
#include "runtime/program/kernel_info.h"
namespace NEO {
ProgramInfo::~ProgramInfo() {
for (auto &kernelInfo : kernelInfos) {
delete kernelInfo;
}
kernelInfos.clear();
}
} // namespace NEO

View File

@@ -0,0 +1,43 @@
/*
* Copyright (C) 2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "core/compiler_interface/linker.h"
#include "core/utilities/stackvec.h"
#include <memory>
#include <vector>
namespace NEO {
struct KernelInfo;
struct ProgramInfo {
ProgramInfo() = default;
ProgramInfo(ProgramInfo &&) = default;
ProgramInfo &operator=(ProgramInfo &&) = default;
~ProgramInfo();
struct GlobalSurfaceInfo {
const void *initData = nullptr;
size_t size = 0U;
};
void prepareLinkerInputStorage() {
if (this->linkerInput == nullptr) {
this->linkerInput = std::make_unique<LinkerInput>();
}
}
GlobalSurfaceInfo globalConstants;
GlobalSurfaceInfo globalVariables;
std::unique_ptr<LinkerInput> linkerInput;
std::vector<KernelInfo *> kernelInfos;
};
} // namespace NEO

View File

@@ -0,0 +1,102 @@
/*
* Copyright (C) 2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "core/program/program_info_from_patchtokens.h"
#include "core/compiler_interface/linker.h"
#include "core/debug_settings/debug_settings_manager.h"
#include "core/program/program_info.h"
#include "runtime/compiler_interface/patchtokens_decoder.h"
#include "runtime/program/kernel_info.h"
#include "runtime/program/kernel_info_from_patchtokens.h"
namespace NEO {
bool requiresLocalMemoryWindowVA(const PatchTokenBinary::ProgramFromPatchtokens &src) {
for (const auto kernel : src.kernels) {
if (kernel.tokens.crossThreadPayloadArgs.localMemoryStatelessWindowStartAddress) {
return true;
}
}
return false;
}
void populateSingleKernelInfo(ProgramInfo &dst, const PatchTokenBinary::ProgramFromPatchtokens &decodedProgram, const DeviceInfoKernelPayloadConstants &constants, uint32_t kernelNum) {
auto kernelInfo = std::make_unique<KernelInfo>();
const PatchTokenBinary::KernelFromPatchtokens &decodedKernel = decodedProgram.kernels[kernelNum];
NEO::populateKernelInfo(*kernelInfo, decodedKernel, decodedProgram.header->GPUPointerSizeInBytes, constants);
if (decodedKernel.tokens.programSymbolTable) {
dst.prepareLinkerInputStorage();
dst.linkerInput->decodeExportedFunctionsSymbolTable(decodedKernel.tokens.programSymbolTable + 1, decodedKernel.tokens.programSymbolTable->NumEntries, kernelNum);
}
if (decodedKernel.tokens.programRelocationTable) {
dst.prepareLinkerInputStorage();
dst.linkerInput->decodeRelocationTable(decodedKernel.tokens.programRelocationTable + 1, decodedKernel.tokens.programRelocationTable->NumEntries, kernelNum);
}
dst.kernelInfos.push_back(kernelInfo.release());
}
void populateProgramInfo(ProgramInfo &dst, const PatchTokenBinary::ProgramFromPatchtokens &src, const DeviceInfoKernelPayloadConstants &constants) {
for (uint32_t i = 0; i < src.kernels.size(); ++i) {
populateSingleKernelInfo(dst, src, constants, i);
}
if (src.programScopeTokens.allocateConstantMemorySurface.empty() == false) {
auto surface = src.programScopeTokens.allocateConstantMemorySurface[0];
dst.globalConstants.size = surface->InlineDataSize;
dst.globalConstants.initData = NEO::PatchTokenBinary::getInlineData(surface);
}
if (src.programScopeTokens.allocateGlobalMemorySurface.empty() == false) {
auto surface = src.programScopeTokens.allocateGlobalMemorySurface[0];
dst.globalVariables.size = surface->InlineDataSize;
dst.globalVariables.initData = NEO::PatchTokenBinary::getInlineData(surface);
}
if (false == (src.programScopeTokens.constantPointer.empty() && src.programScopeTokens.globalPointer.empty() && (src.programScopeTokens.symbolTable == nullptr))) {
UNRECOVERABLE_IF((src.header->GPUPointerSizeInBytes != 4) && (src.header->GPUPointerSizeInBytes != 8));
dst.prepareLinkerInputStorage();
dst.linkerInput->setPointerSize((src.header->GPUPointerSizeInBytes == 4) ? LinkerInput::Traits::PointerSize::Ptr32bit : LinkerInput::Traits::PointerSize::Ptr64bit);
}
for (const auto &globalConstantPointerToken : src.programScopeTokens.constantPointer) {
NEO::LinkerInput::RelocationInfo relocInfo = {};
relocInfo.relocationSegment = NEO::SegmentType::GlobalConstants;
relocInfo.offset = readMisalignedUint64(&globalConstantPointerToken->ConstantPointerOffset);
relocInfo.symbolSegment = NEO::SegmentType::GlobalConstants;
if (globalConstantPointerToken->BufferType != iOpenCL::PROGRAM_SCOPE_CONSTANT_BUFFER) {
UNRECOVERABLE_IF(globalConstantPointerToken->BufferType != iOpenCL::PROGRAM_SCOPE_GLOBAL_BUFFER);
relocInfo.symbolSegment = NEO::SegmentType::GlobalVariables;
}
relocInfo.type = NEO::LinkerInput::RelocationInfo::Type::Address;
dst.linkerInput->addDataRelocationInfo(relocInfo);
}
for (const auto &globalVariablePointerToken : src.programScopeTokens.globalPointer) {
NEO::LinkerInput::RelocationInfo relocInfo = {};
relocInfo.relocationSegment = NEO::SegmentType::GlobalVariables;
relocInfo.offset = readMisalignedUint64(&globalVariablePointerToken->GlobalPointerOffset);
relocInfo.symbolSegment = NEO::SegmentType::GlobalVariables;
if (globalVariablePointerToken->BufferType != iOpenCL::PROGRAM_SCOPE_GLOBAL_BUFFER) {
UNRECOVERABLE_IF(globalVariablePointerToken->BufferType != iOpenCL::PROGRAM_SCOPE_CONSTANT_BUFFER);
relocInfo.symbolSegment = NEO::SegmentType::GlobalConstants;
}
relocInfo.type = NEO::LinkerInput::RelocationInfo::Type::Address;
dst.linkerInput->addDataRelocationInfo(relocInfo);
}
if (src.programScopeTokens.symbolTable != nullptr) {
const auto patch = src.programScopeTokens.symbolTable;
dst.linkerInput->decodeGlobalVariablesSymbolTable(patch + 1, patch->NumEntries);
}
}
} // namespace NEO

View File

@@ -0,0 +1,30 @@
/*
* Copyright (C) 2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include <cstdint>
namespace NEO {
struct ProgramInfo;
struct DeviceInfoKernelPayloadConstants;
namespace PatchTokenBinary {
struct ProgramFromPatchtokens;
}
inline uint64_t readMisalignedUint64(const uint64_t *address) {
const uint32_t *addressBits = reinterpret_cast<const uint32_t *>(address);
return static_cast<uint64_t>(static_cast<uint64_t>(addressBits[1]) << 32) | addressBits[0];
}
bool requiresLocalMemoryWindowVA(const PatchTokenBinary::ProgramFromPatchtokens &src);
void populateProgramInfo(ProgramInfo &dst, const PatchTokenBinary::ProgramFromPatchtokens &src, const DeviceInfoKernelPayloadConstants &constants);
} // namespace NEO

View File

@@ -0,0 +1,54 @@
/*
* Copyright (C) 2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "program_initialization.h"
#include "core/compiler_interface/linker.h"
#include "core/helpers/string.h"
#include "core/memory_manager/graphics_allocation.h"
#include "core/memory_manager/unified_memory_manager.h"
#include "core/program/program_info.h"
#include "runtime/device/device.h"
#include "runtime/memory_manager/memory_manager.h"
namespace NEO {
GraphicsAllocation *allocateGlobalsSurface(NEO::SVMAllocsManager *const svmAllocManager, NEO::Device &device, size_t size, bool constant, LinkerInput *const linkerInput, const void *const initData) {
bool globalsAreExported = false;
if (linkerInput != nullptr) {
globalsAreExported = constant ? linkerInput->getTraits().exportsGlobalConstants : linkerInput->getTraits().exportsGlobalVariables;
}
if (globalsAreExported && (svmAllocManager != nullptr)) {
NEO::SVMAllocsManager::SvmAllocationProperties svmProps = {};
svmProps.coherent = false;
svmProps.readOnly = constant;
svmProps.hostPtrReadOnly = constant;
auto ptr = svmAllocManager->createSVMAlloc(device.getRootDeviceIndex(), size, svmProps);
DEBUG_BREAK_IF(ptr == nullptr);
if (ptr == nullptr) {
return nullptr;
}
auto svmAlloc = svmAllocManager->getSVMAlloc(ptr);
UNRECOVERABLE_IF(svmAlloc == nullptr);
auto gpuAlloc = svmAlloc->gpuAllocation;
UNRECOVERABLE_IF(gpuAlloc == nullptr);
device.getMemoryManager()->copyMemoryToAllocation(gpuAlloc, initData, static_cast<uint32_t>(size));
return svmAllocManager->getSVMAlloc(ptr)->gpuAllocation;
} else {
auto allocationType = constant ? GraphicsAllocation::AllocationType::CONSTANT_SURFACE : GraphicsAllocation::AllocationType::GLOBAL_SURFACE;
auto gpuAlloc = device.getMemoryManager()->allocateGraphicsMemoryWithProperties({device.getRootDeviceIndex(), size, allocationType});
DEBUG_BREAK_IF(gpuAlloc == nullptr);
if (gpuAlloc == nullptr) {
return nullptr;
}
memcpy_s(gpuAlloc->getUnderlyingBuffer(), gpuAlloc->getUnderlyingBufferSize(), initData, size);
return gpuAlloc;
}
}
} // namespace NEO

View File

@@ -0,0 +1,23 @@
/*
* Copyright (C) 2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include <cstddef>
namespace NEO {
class Device;
class GraphicsAllocation;
class SVMAllocsManager;
struct LinkerInput;
GraphicsAllocation *allocateGlobalsSurface(SVMAllocsManager *const svmAllocManager, Device &device,
size_t size, bool constant,
LinkerInput *const linkerInput, const void *const initData);
} // namespace NEO

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 Intel Corporation
* Copyright (C) 2019-2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -9,15 +9,75 @@
#include "core/compiler_interface/linker.h"
#include <functional>
#include <tuple>
template <class BaseClass>
struct WhiteBox;
template <class BaseClass>
struct Mock;
template <>
struct WhiteBox<NEO::LinkerInput> : NEO::LinkerInput {
using BaseClass = NEO::LinkerInput;
using BaseClass::dataRelocations;
using BaseClass::exportedFunctionsSegmentId;
using BaseClass::relocations;
using BaseClass::symbols;
using BaseClass::traits;
using BaseClass::valid;
};
template <typename MockT, typename ReturnT, typename... ArgsT>
struct LightMockConfig {
using MockReturnT = ReturnT;
using OverrideT = std::function<ReturnT(MockT *, ArgsT...)>;
uint32_t timesCalled = 0U;
OverrideT overrideFunc;
};
template <typename ConfigT, typename ObjT, typename... ArgsT>
typename ConfigT::MockReturnT invokeMocked(ConfigT &config, ObjT obj, ArgsT &&... args) {
config.timesCalled += 1;
if (config.overrideFunc) {
return config.overrideFunc(obj, std::forward<ArgsT>(args)...);
} else {
return config.originalFunc(obj, std::forward<ArgsT>(args)...);
}
}
#define LIGHT_MOCK_OVERRIDE_2(NAME, MOCK_T, BASE_T, RETURN_T, ARG0_T, ARG1_T) \
struct : LightMockConfig<MOCK_T, RETURN_T, ARG0_T, ARG1_T> { \
OverrideT originalFunc = +[](BaseT *obj, ARG0_T arg0, ARG1_T arg1) -> RETURN_T { \
return obj->BaseT::NAME(std::forward<ARG0_T>(arg0), std::forward<ARG1_T>(arg1)); \
}; \
} NAME##MockConfig; \
\
RETURN_T NAME(ARG0_T arg0, ARG1_T arg1) override { \
return invokeMocked(NAME##MockConfig, this, std::forward<ARG0_T>(arg0), std::forward<ARG1_T>(arg1)); \
}
#define LIGHT_MOCK_OVERRIDE_3(NAME, MOCK_T, BASE_T, RETURN_T, ARG0_T, ARG1_T, ARG2_T) \
struct : LightMockConfig<MOCK_T, RETURN_T, ARG0_T, ARG1_T, ARG2_T> { \
OverrideT originalFunc = +[](BaseT *obj, ARG0_T arg0, ARG1_T arg1, ARG2_T arg2) -> RETURN_T { \
return obj->BaseT::NAME(std::forward<ARG0_T>(arg0), std::forward<ARG1_T>(arg1), std::forward<ARG2_T>(arg2)); \
}; \
} NAME##MockConfig; \
\
RETURN_T NAME(ARG0_T arg0, ARG1_T arg1, ARG2_T arg2) override { \
return invokeMocked(NAME##MockConfig, this, std::forward<ARG0_T>(arg0), std::forward<ARG1_T>(arg1), std::forward<ARG2_T>(arg2)); \
}
template <>
struct Mock<NEO::LinkerInput> : WhiteBox<NEO::LinkerInput> {
using ThisT = Mock<NEO::LinkerInput>;
using BaseT = NEO::LinkerInput;
using WhiteBoxBaseT = WhiteBox<BaseT>;
LIGHT_MOCK_OVERRIDE_2(decodeGlobalVariablesSymbolTable, ThisT, BaseT, bool, const void *, uint32_t);
LIGHT_MOCK_OVERRIDE_3(decodeExportedFunctionsSymbolTable, ThisT, BaseT, bool, const void *, uint32_t, uint32_t);
LIGHT_MOCK_OVERRIDE_3(decodeRelocationTable, ThisT, BaseT, bool, const void *, uint32_t, uint32_t);
};

View File

@@ -1,20 +1,36 @@
/*
* Copyright (C) 2019 Intel Corporation
* Copyright (C) 2019-2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "core/helpers/ptr_math.h"
#include "RelocationInfo.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "linker_mock.h"
#include <string>
#include "RelocationInfo.h"
TEST(SegmentTypeTests, givenSegmentTypeWhenAsStringIsCalledThenProperRepresentationIsReturned) {
EXPECT_STREQ("UNKOWN", NEO::asString(NEO::SegmentType::Unknown));
EXPECT_STREQ("GLOBAL_CONSTANTS", NEO::asString(NEO::SegmentType::GlobalConstants));
EXPECT_STREQ("GLOBAL_VARIABLES", NEO::asString(NEO::SegmentType::GlobalVariables));
EXPECT_STREQ("INSTRUCTIONS", NEO::asString(NEO::SegmentType::Instructions));
}
TEST(LinkerInputTraitsTests, whenPointerSizeNotSizeThenDefaultsToHostPointerSize) {
using PointerSize = NEO::LinkerInput::Traits::PointerSize;
auto expectedPointerSize = (sizeof(void *) == 4) ? PointerSize::Ptr32bit : PointerSize::Ptr64bit;
auto pointerSize = NEO::LinkerInput::Traits{}.pointerSize;
EXPECT_EQ(expectedPointerSize, pointerSize);
}
TEST(LinkerInputTests, givenGlobalsSymbolTableThenProperlyDecodesGlobalVariablesAndGlobalConstants) {
NEO::LinkerInput linkerInput;
EXPECT_TRUE(linkerInput.isValid());
vISA::GenSymEntry entry[2] = {{}, {}};
entry[0].s_name[0] = 'A';
entry[0].s_offset = 8;
@@ -33,6 +49,7 @@ TEST(LinkerInputTests, givenGlobalsSymbolTableThenProperlyDecodesGlobalVariables
auto decodeResult = linkerInput.decodeGlobalVariablesSymbolTable(entry, 2);
EXPECT_TRUE(decodeResult);
EXPECT_TRUE(linkerInput.isValid());
EXPECT_EQ(2U, linkerInput.getSymbols().size());
EXPECT_TRUE(linkerInput.getTraits().exportsGlobalVariables);
@@ -44,13 +61,13 @@ TEST(LinkerInputTests, givenGlobalsSymbolTableThenProperlyDecodesGlobalVariables
ASSERT_NE(linkerInput.getSymbols().end(), symbolA);
EXPECT_EQ(entry[0].s_offset, symbolA->second.offset);
EXPECT_EQ(entry[0].s_size, symbolA->second.size);
EXPECT_EQ(NEO::SymbolInfo::GlobalVariable, symbolA->second.type);
EXPECT_EQ(NEO::SegmentType::GlobalVariables, symbolA->second.segment);
auto symbolB = linkerInput.getSymbols().find("B");
ASSERT_NE(linkerInput.getSymbols().end(), symbolB);
EXPECT_EQ(entry[1].s_offset, symbolB->second.offset);
EXPECT_EQ(entry[1].s_size, symbolB->second.size);
EXPECT_EQ(NEO::SymbolInfo::GlobalConstant, symbolB->second.type);
EXPECT_EQ(NEO::SegmentType::GlobalConstants, symbolB->second.segment);
auto symbolC = linkerInput.getSymbols().find("C");
EXPECT_EQ(linkerInput.getSymbols().end(), symbolC);
@@ -78,6 +95,7 @@ TEST(LinkerInputTests, givenFunctionsSymbolTableThenProperlyDecodesGlobalVariabl
auto decodeResult = linkerInput.decodeExportedFunctionsSymbolTable(entry, 2, 3);
EXPECT_TRUE(decodeResult);
EXPECT_TRUE(linkerInput.isValid());
EXPECT_EQ(2U, linkerInput.getSymbols().size());
EXPECT_TRUE(linkerInput.getTraits().exportsGlobalVariables);
@@ -89,13 +107,13 @@ TEST(LinkerInputTests, givenFunctionsSymbolTableThenProperlyDecodesGlobalVariabl
ASSERT_NE(linkerInput.getSymbols().end(), symbolA);
EXPECT_EQ(entry[0].s_offset, symbolA->second.offset);
EXPECT_EQ(entry[0].s_size, symbolA->second.size);
EXPECT_EQ(NEO::SymbolInfo::GlobalVariable, symbolA->second.type);
EXPECT_EQ(NEO::SegmentType::GlobalVariables, symbolA->second.segment);
auto symbolB = linkerInput.getSymbols().find("B");
ASSERT_NE(linkerInput.getSymbols().end(), symbolB);
EXPECT_EQ(entry[1].s_offset, symbolB->second.offset);
EXPECT_EQ(entry[1].s_size, symbolB->second.size);
EXPECT_EQ(NEO::SymbolInfo::GlobalConstant, symbolB->second.type);
EXPECT_EQ(NEO::SegmentType::GlobalConstants, symbolB->second.segment);
auto symbolC = linkerInput.getSymbols().find("C");
EXPECT_EQ(linkerInput.getSymbols().end(), symbolC);
@@ -111,6 +129,7 @@ TEST(LinkerInputTests, givenGlobalsSymbolTableThenFunctionExportsAreNotAllowed)
auto decodeResult = linkerInput.decodeGlobalVariablesSymbolTable(&entry, 1);
EXPECT_FALSE(decodeResult);
EXPECT_FALSE(linkerInput.isValid());
}
TEST(LinkerInputTests, givenFunctionsSymbolTableThenProperlyDecodesExportedFunctions) {
@@ -134,6 +153,7 @@ TEST(LinkerInputTests, givenFunctionsSymbolTableThenProperlyDecodesExportedFunct
auto decodeResult = linkerInput.decodeExportedFunctionsSymbolTable(entry, 2, 3);
EXPECT_TRUE(decodeResult);
EXPECT_TRUE(linkerInput.isValid());
EXPECT_EQ(2U, linkerInput.getSymbols().size());
EXPECT_FALSE(linkerInput.getTraits().exportsGlobalVariables);
@@ -145,13 +165,13 @@ TEST(LinkerInputTests, givenFunctionsSymbolTableThenProperlyDecodesExportedFunct
ASSERT_NE(linkerInput.getSymbols().end(), symbolA);
EXPECT_EQ(entry[0].s_offset, symbolA->second.offset);
EXPECT_EQ(entry[0].s_size, symbolA->second.size);
EXPECT_EQ(NEO::SymbolInfo::Function, symbolA->second.type);
EXPECT_EQ(NEO::SegmentType::Instructions, symbolA->second.segment);
auto symbolB = linkerInput.getSymbols().find("B");
ASSERT_NE(linkerInput.getSymbols().end(), symbolB);
EXPECT_EQ(entry[1].s_offset, symbolB->second.offset);
EXPECT_EQ(entry[1].s_size, symbolB->second.size);
EXPECT_EQ(NEO::SymbolInfo::Function, symbolB->second.type);
EXPECT_EQ(NEO::SegmentType::Instructions, symbolB->second.segment);
EXPECT_EQ(3, linkerInput.getExportedFunctionsSegmentId());
}
@@ -166,6 +186,7 @@ TEST(LinkerInputTests, givenFunctionsSymbolTableThenUndefIsNotAllowed) {
auto decodeResult = linkerInput.decodeExportedFunctionsSymbolTable(&entry, 1, 3);
EXPECT_FALSE(decodeResult);
EXPECT_FALSE(linkerInput.isValid());
}
TEST(LinkerInputTests, givenRelocationTableThenRelocationEntriesAreProperlyParsed) {
@@ -186,9 +207,10 @@ TEST(LinkerInputTests, givenRelocationTableThenRelocationEntriesAreProperlyParse
decodeResult = linkerInput.decodeRelocationTable(&entry, 1, 1);
EXPECT_TRUE(decodeResult);
EXPECT_TRUE(linkerInput.isValid());
}
TEST(LinkerInputTests, givenRelocationTableThenNoneIsNotAllowed) {
TEST(LinkerInputTests, givenRelocationTableThenNoneAsRelocationTypeIsNotAllowed) {
NEO::LinkerInput linkerInput;
vISA::GenRelocEntry entry = {};
entry.r_symbol[0] = 'A';
@@ -197,22 +219,74 @@ TEST(LinkerInputTests, givenRelocationTableThenNoneIsNotAllowed) {
auto decodeResult = linkerInput.decodeRelocationTable(&entry, 1, 3);
EXPECT_FALSE(decodeResult);
EXPECT_FALSE(linkerInput.isValid());
}
TEST(LinkerInputTests, whenDataRelocationsAreAddedThenProperTraitsAreSet) {
NEO::LinkerInput linkerInput;
EXPECT_FALSE(linkerInput.getTraits().requiresPatchingOfGlobalConstantsBuffer);
EXPECT_FALSE(linkerInput.getTraits().requiresPatchingOfGlobalVariablesBuffer);
NEO::LinkerInput::RelocationInfo relocInfo;
relocInfo.offset = 7U;
relocInfo.relocationSegment = NEO::SegmentType::GlobalConstants;
relocInfo.symbolName = "aaa";
relocInfo.symbolSegment = NEO::SegmentType::GlobalVariables;
relocInfo.type = NEO::LinkerInput::RelocationInfo::Type::Address;
linkerInput.addDataRelocationInfo(relocInfo);
ASSERT_EQ(1U, linkerInput.getDataRelocations().size());
EXPECT_EQ(relocInfo.offset, linkerInput.getDataRelocations()[0].offset);
EXPECT_EQ(relocInfo.relocationSegment, linkerInput.getDataRelocations()[0].relocationSegment);
EXPECT_EQ(relocInfo.symbolName, linkerInput.getDataRelocations()[0].symbolName);
EXPECT_EQ(relocInfo.symbolSegment, linkerInput.getDataRelocations()[0].symbolSegment);
EXPECT_EQ(relocInfo.type, linkerInput.getDataRelocations()[0].type);
EXPECT_TRUE(linkerInput.getTraits().requiresPatchingOfGlobalConstantsBuffer);
EXPECT_FALSE(linkerInput.getTraits().requiresPatchingOfGlobalVariablesBuffer);
EXPECT_TRUE(linkerInput.isValid());
linkerInput = {};
EXPECT_FALSE(linkerInput.getTraits().requiresPatchingOfGlobalConstantsBuffer);
EXPECT_FALSE(linkerInput.getTraits().requiresPatchingOfGlobalVariablesBuffer);
relocInfo.relocationSegment = NEO::SegmentType::GlobalVariables;
relocInfo.symbolSegment = NEO::SegmentType::GlobalConstants;
linkerInput.addDataRelocationInfo(relocInfo);
ASSERT_EQ(1U, linkerInput.getDataRelocations().size());
EXPECT_FALSE(linkerInput.getTraits().requiresPatchingOfGlobalConstantsBuffer);
EXPECT_TRUE(linkerInput.getTraits().requiresPatchingOfGlobalVariablesBuffer);
EXPECT_TRUE(linkerInput.isValid());
}
TEST(LinkerTests, givenEmptyLinkerInputThenLinkerOutputIsEmpty) {
NEO::LinkerInput linkerInput;
NEO::Linker linker(linkerInput);
NEO::Linker::Segment globalVar, globalConst, exportedFunc;
NEO::Linker::SegmentInfo globalVar, globalConst, exportedFunc;
NEO::Linker::PatchableSegment patchableGlobalVarSeg, patchableConstVarSeg;
NEO::Linker::PatchableSegments patchableInstructionSegments;
NEO::Linker::UnresolvedExternals unresolvedExternals;
bool linkResult = linker.link(globalVar, globalConst, exportedFunc, patchableInstructionSegments, unresolvedExternals);
bool linkResult = linker.link(globalVar, globalConst, exportedFunc,
patchableGlobalVarSeg, patchableConstVarSeg, patchableInstructionSegments,
unresolvedExternals);
EXPECT_TRUE(linkResult);
EXPECT_EQ(0U, unresolvedExternals.size());
auto relocatedSymbols = linker.extractRelocatedSymbols();
EXPECT_EQ(0U, relocatedSymbols.size());
}
TEST(LinkerTests, givenUnresolvedExternalThenLinkerFails) {
TEST(LinkerTests, givenInvalidLinkerInputThenLinkerFails) {
WhiteBox<NEO::LinkerInput> mockLinkerInput;
mockLinkerInput.valid = false;
NEO::Linker linker(mockLinkerInput);
NEO::Linker::SegmentInfo globalVar, globalConst, exportedFunc;
NEO::Linker::PatchableSegment patchableGlobalVarSeg, patchableConstVarSeg;
NEO::Linker::PatchableSegments patchableInstructionSegments;
NEO::Linker::UnresolvedExternals unresolvedExternals;
bool linkResult = linker.link(globalVar, globalConst, exportedFunc,
patchableGlobalVarSeg, patchableConstVarSeg, patchableInstructionSegments,
unresolvedExternals);
EXPECT_FALSE(linkResult);
}
TEST(LinkerTests, givenUnresolvedExternalWhenPatchingInstructionsThenLinkerFails) {
NEO::LinkerInput linkerInput;
vISA::GenRelocEntry entry = {};
entry.r_symbol[0] = 'A';
@@ -222,7 +296,7 @@ TEST(LinkerTests, givenUnresolvedExternalThenLinkerFails) {
EXPECT_TRUE(decodeResult);
NEO::Linker linker(linkerInput);
NEO::Linker::Segment globalVar, globalConst, exportedFunc;
NEO::Linker::SegmentInfo globalVar, globalConst, exportedFunc;
NEO::Linker::UnresolvedExternals unresolvedExternals;
std::vector<char> instructionSegment;
@@ -230,9 +304,12 @@ TEST(LinkerTests, givenUnresolvedExternalThenLinkerFails) {
NEO::Linker::PatchableSegment seg0;
seg0.hostPointer = instructionSegment.data();
seg0.segmentSize = instructionSegment.size();
NEO::Linker::PatchableSegment patchableGlobalVarSeg, patchableConstVarSeg;
NEO::Linker::PatchableSegments patchableInstructionSegments{seg0};
bool linkResult = linker.link(globalVar, globalConst, exportedFunc, patchableInstructionSegments, unresolvedExternals);
bool linkResult = linker.link(globalVar, globalConst, exportedFunc,
patchableGlobalVarSeg, patchableConstVarSeg, patchableInstructionSegments,
unresolvedExternals);
EXPECT_FALSE(linkResult);
auto relocatedSymbols = linker.extractRelocatedSymbols();
EXPECT_EQ(0U, relocatedSymbols.size());
@@ -299,7 +376,7 @@ TEST(LinkerTests, givenValidSymbolsAndRelocationsThenInstructionSegmentsArePrope
EXPECT_TRUE(decodeRelocSuccess);
NEO::Linker linker(linkerInput);
NEO::Linker::Segment globalVarSegment, globalConstSegment, exportedFuncSegment;
NEO::Linker::SegmentInfo globalVarSegment, globalConstSegment, exportedFuncSegment;
globalVarSegment.gpuAddress = 8;
globalVarSegment.segmentSize = 64;
globalConstSegment.gpuAddress = 128;
@@ -315,9 +392,10 @@ TEST(LinkerTests, givenValidSymbolsAndRelocationsThenInstructionSegmentsArePrope
seg0.hostPointer = instructionSegment.data();
seg0.segmentSize = instructionSegment.size();
NEO::Linker::PatchableSegments patchableInstructionSegments{seg0};
NEO::Linker::PatchableSegment patchableGlobalVarSeg, patchableConstVarSeg;
bool linkResult = linker.link(globalVarSegment, globalConstSegment, exportedFuncSegment,
patchableInstructionSegments, unresolvedExternals);
patchableGlobalVarSeg, patchableConstVarSeg, patchableInstructionSegments, unresolvedExternals);
EXPECT_TRUE(linkResult);
auto relocatedSymbols = linker.extractRelocatedSymbols();
EXPECT_EQ(0U, unresolvedExternals.size());
@@ -347,7 +425,7 @@ TEST(LinkerTests, givenValidSymbolsAndRelocationsThenInstructionSegmentsArePrope
EXPECT_EQ(initData, *reinterpret_cast<const uint32_t *>(instructionSegment.data() + relocCPartHigh.r_offset + sizeof(uint32_t)));
}
TEST(LinkerTests, givenInvalidSymbolOffsetThenRelocationFails) {
TEST(LinkerTests, givenInvalidSymbolOffsetWhenPatchingInstructionsThenRelocationFails) {
NEO::LinkerInput linkerInput;
vISA::GenSymEntry symGlobalVariable = {};
@@ -359,7 +437,7 @@ TEST(LinkerTests, givenInvalidSymbolOffsetThenRelocationFails) {
EXPECT_TRUE(decodeSymSuccess);
NEO::Linker linker(linkerInput);
NEO::Linker::Segment globalVarSegment, globalConstSegment, exportedFuncSegment;
NEO::Linker::SegmentInfo globalVarSegment, globalConstSegment, exportedFuncSegment;
globalVarSegment.gpuAddress = 8;
globalVarSegment.segmentSize = symGlobalVariable.s_offset;
NEO::Linker::UnresolvedExternals unresolvedExternals;
@@ -370,9 +448,11 @@ TEST(LinkerTests, givenInvalidSymbolOffsetThenRelocationFails) {
seg0.hostPointer = instructionSegment.data();
seg0.segmentSize = instructionSegment.size();
NEO::Linker::PatchableSegments patchableInstructionSegments{seg0};
NEO::Linker::PatchableSegment patchableGlobalVarSeg, patchableConstVarSeg;
bool linkResult = linker.link(globalVarSegment, globalConstSegment, exportedFuncSegment,
patchableInstructionSegments, unresolvedExternals);
patchableGlobalVarSeg, patchableConstVarSeg, patchableInstructionSegments,
unresolvedExternals);
EXPECT_FALSE(linkResult);
auto relocatedSymbols = linker.extractRelocatedSymbols();
EXPECT_EQ(0U, unresolvedExternals.size());
@@ -380,11 +460,11 @@ TEST(LinkerTests, givenInvalidSymbolOffsetThenRelocationFails) {
globalVarSegment.segmentSize = symGlobalVariable.s_offset + symGlobalVariable.s_size;
linkResult = linker.link(globalVarSegment, globalConstSegment, exportedFuncSegment,
patchableInstructionSegments, unresolvedExternals);
patchableGlobalVarSeg, patchableConstVarSeg, patchableInstructionSegments, unresolvedExternals);
EXPECT_TRUE(linkResult);
}
TEST(LinkerTests, givenInvalidRelocationOffsetThenPatchingOfIsaFails) {
TEST(LinkerTests, givenInvalidRelocationOffsetThenPatchingOfInstructionsFails) {
NEO::LinkerInput linkerInput;
vISA::GenSymEntry symGlobalVariable = {};
@@ -403,7 +483,7 @@ TEST(LinkerTests, givenInvalidRelocationOffsetThenPatchingOfIsaFails) {
EXPECT_TRUE(decodeRelocSuccess);
NEO::Linker linker(linkerInput);
NEO::Linker::Segment globalVarSegment, globalConstSegment, exportedFuncSegment;
NEO::Linker::SegmentInfo globalVarSegment, globalConstSegment, exportedFuncSegment;
globalVarSegment.gpuAddress = 8;
globalVarSegment.segmentSize = symGlobalVariable.s_offset + symGlobalVariable.s_size;
NEO::Linker::UnresolvedExternals unresolvedExternals;
@@ -414,9 +494,11 @@ TEST(LinkerTests, givenInvalidRelocationOffsetThenPatchingOfIsaFails) {
seg0.hostPointer = instructionSegment.data();
seg0.segmentSize = relocA.r_offset;
NEO::Linker::PatchableSegments patchableInstructionSegments{seg0};
NEO::Linker::PatchableSegment patchableGlobalVarSeg, patchableConstVarSeg;
bool linkResult = linker.link(globalVarSegment, globalConstSegment, exportedFuncSegment,
patchableInstructionSegments, unresolvedExternals);
patchableGlobalVarSeg, patchableConstVarSeg, patchableInstructionSegments,
unresolvedExternals);
EXPECT_FALSE(linkResult);
auto relocatedSymbols = linker.extractRelocatedSymbols();
EXPECT_EQ(1U, relocatedSymbols.size());
@@ -425,11 +507,12 @@ TEST(LinkerTests, givenInvalidRelocationOffsetThenPatchingOfIsaFails) {
patchableInstructionSegments[0].segmentSize = relocA.r_offset + sizeof(uintptr_t);
linkResult = linker.link(globalVarSegment, globalConstSegment, exportedFuncSegment,
patchableInstructionSegments, unresolvedExternals);
patchableGlobalVarSeg, patchableConstVarSeg, patchableInstructionSegments,
unresolvedExternals);
EXPECT_TRUE(linkResult);
}
TEST(LinkerTests, givenUnknownSymbolTypeThenRelocationFails) {
TEST(LinkerTests, givenUnknownSymbolTypeWhenPatchingInstructionsThenRelocationFails) {
WhiteBox<NEO::LinkerInput> linkerInput;
vISA::GenSymEntry symGlobalVariable = {};
@@ -448,7 +531,7 @@ TEST(LinkerTests, givenUnknownSymbolTypeThenRelocationFails) {
EXPECT_TRUE(decodeRelocSuccess);
NEO::Linker linker(linkerInput);
NEO::Linker::Segment globalVarSegment, globalConstSegment, exportedFuncSegment;
NEO::Linker::SegmentInfo globalVarSegment, globalConstSegment, exportedFuncSegment;
globalVarSegment.gpuAddress = 8;
globalVarSegment.segmentSize = 64;
NEO::Linker::UnresolvedExternals unresolvedExternals;
@@ -459,30 +542,407 @@ TEST(LinkerTests, givenUnknownSymbolTypeThenRelocationFails) {
seg0.hostPointer = instructionSegment.data();
seg0.segmentSize = instructionSegment.size();
NEO::Linker::PatchableSegments patchableInstructionSegments{seg0};
NEO::Linker::PatchableSegment patchableGlobalVarSeg, patchableConstVarSeg;
ASSERT_EQ(1U, linkerInput.symbols.count("A"));
linkerInput.symbols["A"].type = NEO::SymbolInfo::Unknown;
linkerInput.symbols["A"].segment = NEO::SegmentType::Unknown;
bool linkResult = linker.link(globalVarSegment, globalConstSegment, exportedFuncSegment,
patchableInstructionSegments, unresolvedExternals);
patchableGlobalVarSeg, patchableConstVarSeg, patchableInstructionSegments,
unresolvedExternals);
EXPECT_FALSE(linkResult);
auto relocatedSymbols = linker.extractRelocatedSymbols();
EXPECT_EQ(0U, relocatedSymbols.size());
ASSERT_EQ(0U, unresolvedExternals.size());
linkerInput.symbols["A"].type = NEO::SymbolInfo::GlobalVariable;
linkerInput.symbols["A"].segment = NEO::SegmentType::GlobalVariables;
linkResult = linker.link(globalVarSegment, globalConstSegment, exportedFuncSegment,
patchableInstructionSegments, unresolvedExternals);
patchableGlobalVarSeg, patchableConstVarSeg, patchableInstructionSegments,
unresolvedExternals);
EXPECT_TRUE(linkResult);
}
TEST(LinkerErrorMessageTests, whenNoUnresolvedExternalsThenInternalError) {
TEST(LinkerTests, givenInvalidSourceSegmentWhenPatchingDataSegmentsThenLinkerFails) {
WhiteBox<NEO::LinkerInput> linkerInput;
NEO::Linker linker(linkerInput);
NEO::Linker::SegmentInfo emptySegmentInfo;
NEO::Linker::PatchableSegment emptyPatchableSegment;
NEO::Linker::UnresolvedExternals unresolvedExternals;
std::vector<char> nonEmptypatchableSegmentData;
nonEmptypatchableSegmentData.resize(64, 8U);
NEO::Linker::PatchableSegment nonEmptypatchableSegment;
nonEmptypatchableSegment.hostPointer = nonEmptypatchableSegmentData.data();
nonEmptypatchableSegment.segmentSize = nonEmptypatchableSegmentData.size();
NEO::LinkerInput::RelocationInfo relocInfo;
relocInfo.offset = 0U;
relocInfo.symbolName = "aaa";
relocInfo.type = NEO::LinkerInput::RelocationInfo::Type::Address;
linkerInput.dataRelocations.push_back(relocInfo);
{
linkerInput.traits.requiresPatchingOfGlobalVariablesBuffer = true;
linkerInput.traits.requiresPatchingOfGlobalConstantsBuffer = false;
linkerInput.dataRelocations[0].relocationSegment = NEO::SegmentType::GlobalVariables;
linkerInput.dataRelocations[0].symbolSegment = NEO::SegmentType::Unknown;
bool linkResult = linker.link(emptySegmentInfo, emptySegmentInfo, emptySegmentInfo,
nonEmptypatchableSegment, emptyPatchableSegment, {},
unresolvedExternals);
EXPECT_FALSE(linkResult);
EXPECT_EQ(1U, unresolvedExternals.size());
linkerInput.dataRelocations[0].symbolSegment = NEO::SegmentType::GlobalVariables;
unresolvedExternals.clear();
linkResult = linker.link(emptySegmentInfo, emptySegmentInfo, emptySegmentInfo,
nonEmptypatchableSegment, emptyPatchableSegment, {},
unresolvedExternals);
EXPECT_TRUE(linkResult);
EXPECT_EQ(0U, unresolvedExternals.size());
}
{
linkerInput.traits.requiresPatchingOfGlobalVariablesBuffer = false;
linkerInput.traits.requiresPatchingOfGlobalConstantsBuffer = true;
linkerInput.dataRelocations[0].relocationSegment = NEO::SegmentType::GlobalConstants;
linkerInput.dataRelocations[0].symbolSegment = NEO::SegmentType::Unknown;
unresolvedExternals.clear();
bool linkResult = linker.link(emptySegmentInfo, emptySegmentInfo, emptySegmentInfo,
emptyPatchableSegment, nonEmptypatchableSegment, {},
unresolvedExternals);
EXPECT_FALSE(linkResult);
EXPECT_EQ(1U, unresolvedExternals.size());
linkerInput.dataRelocations[0].symbolSegment = NEO::SegmentType::GlobalVariables;
unresolvedExternals.clear();
linkResult = linker.link(emptySegmentInfo, emptySegmentInfo, emptySegmentInfo,
emptyPatchableSegment, nonEmptypatchableSegment, {},
unresolvedExternals);
EXPECT_TRUE(linkResult);
EXPECT_EQ(0U, unresolvedExternals.size());
}
}
TEST(LinkerTests, givenUnknownRelocationSegmentWhenPatchingDataSegmentsThenLinkerFails) {
WhiteBox<NEO::LinkerInput> linkerInput;
NEO::Linker linker(linkerInput);
NEO::Linker::SegmentInfo emptySegmentInfo;
NEO::Linker::PatchableSegment emptyPatchableSegment;
NEO::Linker::UnresolvedExternals unresolvedExternals;
std::vector<char> nonEmptypatchableSegmentData;
nonEmptypatchableSegmentData.resize(64, 8U);
NEO::Linker::PatchableSegment nonEmptypatchableSegment;
nonEmptypatchableSegment.hostPointer = nonEmptypatchableSegmentData.data();
nonEmptypatchableSegment.segmentSize = nonEmptypatchableSegmentData.size();
NEO::LinkerInput::RelocationInfo relocInfo;
relocInfo.offset = 0U;
relocInfo.symbolName = "aaa";
relocInfo.type = NEO::LinkerInput::RelocationInfo::Type::Address;
linkerInput.dataRelocations.push_back(relocInfo);
linkerInput.dataRelocations[0].relocationSegment = NEO::SegmentType::Unknown;
linkerInput.dataRelocations[0].symbolSegment = NEO::SegmentType::GlobalVariables;
linkerInput.traits.requiresPatchingOfGlobalVariablesBuffer = true;
bool linkResult = linker.link(emptySegmentInfo, emptySegmentInfo, emptySegmentInfo,
nonEmptypatchableSegment, emptyPatchableSegment, {},
unresolvedExternals);
EXPECT_FALSE(linkResult);
EXPECT_EQ(1U, unresolvedExternals.size());
linkerInput.dataRelocations[0].relocationSegment = NEO::SegmentType::GlobalVariables;
unresolvedExternals.clear();
linkResult = linker.link(emptySegmentInfo, emptySegmentInfo, emptySegmentInfo,
nonEmptypatchableSegment, emptyPatchableSegment, {},
unresolvedExternals);
EXPECT_TRUE(linkResult);
EXPECT_EQ(0U, unresolvedExternals.size());
}
TEST(LinkerTests, givenRelocationTypeWithHighPartOfAddressWhenPatchingDataSegmentsThenLinkerFails) {
WhiteBox<NEO::LinkerInput> linkerInput;
NEO::Linker linker(linkerInput);
NEO::Linker::SegmentInfo emptySegmentInfo;
NEO::Linker::PatchableSegment emptyPatchableSegment;
NEO::Linker::UnresolvedExternals unresolvedExternals;
std::vector<char> nonEmptypatchableSegmentData;
nonEmptypatchableSegmentData.resize(64, 8U);
NEO::Linker::PatchableSegment nonEmptypatchableSegment;
nonEmptypatchableSegment.hostPointer = nonEmptypatchableSegmentData.data();
nonEmptypatchableSegment.segmentSize = nonEmptypatchableSegmentData.size();
NEO::LinkerInput::RelocationInfo relocInfo;
relocInfo.offset = 0U;
relocInfo.symbolName = "aaa";
relocInfo.type = NEO::LinkerInput::RelocationInfo::Type::AddressHigh;
linkerInput.dataRelocations.push_back(relocInfo);
linkerInput.dataRelocations[0].relocationSegment = NEO::SegmentType::GlobalVariables;
linkerInput.dataRelocations[0].symbolSegment = NEO::SegmentType::GlobalVariables;
linkerInput.traits.requiresPatchingOfGlobalVariablesBuffer = true;
bool linkResult = linker.link(emptySegmentInfo, emptySegmentInfo, emptySegmentInfo,
nonEmptypatchableSegment, emptyPatchableSegment, {},
unresolvedExternals);
EXPECT_FALSE(linkResult);
EXPECT_EQ(1U, unresolvedExternals.size());
linkerInput.dataRelocations[0].type = NEO::LinkerInput::RelocationInfo::Type::AddressLow;
unresolvedExternals.clear();
linkResult = linker.link(emptySegmentInfo, emptySegmentInfo, emptySegmentInfo,
nonEmptypatchableSegment, emptyPatchableSegment, {},
unresolvedExternals);
EXPECT_TRUE(linkResult);
EXPECT_EQ(0U, unresolvedExternals.size());
}
TEST(LinkerTests, givenValidSymbolsAndRelocationsThenDataSegmentsAreProperlyPatched) {
WhiteBox<NEO::LinkerInput> linkerInput;
NEO::Linker linker(linkerInput);
std::vector<char> globalConstantsSegmentData;
globalConstantsSegmentData.resize(128, 7U);
std::vector<char> globalVariablesSegmentData;
globalVariablesSegmentData.resize(256, 13U);
NEO::Linker::SegmentInfo globalConstantsSegmentInfo, globalVariablesSegmentInfo;
NEO::Linker::UnresolvedExternals unresolvedExternals;
NEO::Linker::PatchableSegment globalConstantsPatchableSegment, globalVariablesPatchableSegment;
globalConstantsSegmentInfo.gpuAddress = reinterpret_cast<uintptr_t>(globalConstantsSegmentData.data());
globalConstantsSegmentInfo.segmentSize = globalConstantsSegmentData.size();
globalConstantsPatchableSegment.hostPointer = globalConstantsSegmentData.data();
globalConstantsPatchableSegment.segmentSize = globalConstantsSegmentData.size();
globalVariablesSegmentInfo.gpuAddress = reinterpret_cast<uintptr_t>(globalVariablesSegmentData.data());
globalVariablesSegmentInfo.segmentSize = globalVariablesSegmentData.size();
globalVariablesPatchableSegment.hostPointer = globalVariablesSegmentData.data();
globalVariablesPatchableSegment.segmentSize = globalVariablesSegmentData.size();
NEO::LinkerInput::RelocationInfo relocationInfo[5];
// GlobalVar -> GlobalVar
relocationInfo[0].offset = 8U;
relocationInfo[0].relocationSegment = NEO::SegmentType::GlobalVariables;
relocationInfo[0].symbolSegment = NEO::SegmentType::GlobalVariables;
relocationInfo[0].type = NEO::LinkerInput::RelocationInfo::Type::Address;
// GlobalConst -> GlobalVar
relocationInfo[1].offset = 24U;
relocationInfo[1].relocationSegment = NEO::SegmentType::GlobalConstants;
relocationInfo[1].symbolSegment = NEO::SegmentType::GlobalVariables;
relocationInfo[1].type = NEO::LinkerInput::RelocationInfo::Type::Address;
// GlobalConst -> GlobalConst
relocationInfo[2].offset = 40U;
relocationInfo[2].relocationSegment = NEO::SegmentType::GlobalConstants;
relocationInfo[2].symbolSegment = NEO::SegmentType::GlobalConstants;
relocationInfo[2].type = NEO::LinkerInput::RelocationInfo::Type::Address;
// GlobalVar -> GlobalConst
relocationInfo[3].offset = 56U;
relocationInfo[3].relocationSegment = NEO::SegmentType::GlobalVariables;
relocationInfo[3].symbolSegment = NEO::SegmentType::GlobalConstants;
relocationInfo[3].type = NEO::LinkerInput::RelocationInfo::Type::Address;
// GlobalVar Low -> GlobalVar
relocationInfo[4].offset = 72;
relocationInfo[4].relocationSegment = NEO::SegmentType::GlobalVariables;
relocationInfo[4].symbolSegment = NEO::SegmentType::GlobalVariables;
relocationInfo[4].type = NEO::LinkerInput::RelocationInfo::Type::AddressLow;
uint32_t initValue = 0;
for (const auto &reloc : relocationInfo) {
linkerInput.addDataRelocationInfo(reloc);
void *dstRaw = (reloc.relocationSegment == NEO::SegmentType::GlobalVariables) ? globalVariablesPatchableSegment.hostPointer : globalConstantsPatchableSegment.hostPointer;
if (reloc.type == NEO::LinkerInput::RelocationInfo::Type::Address) {
*reinterpret_cast<uintptr_t *>(ptrOffset(dstRaw, static_cast<size_t>(reloc.offset))) = initValue * 4; // relocations to global data are currently based on patchIncrement, simulate init data
} else {
*reinterpret_cast<uint32_t *>(ptrOffset(dstRaw, static_cast<size_t>(reloc.offset))) = initValue * 4; // relocations to global data are currently based on patchIncrement, simulate init data
}
++initValue;
}
auto linkResult = linker.link(globalVariablesSegmentInfo, globalConstantsSegmentInfo, {},
globalVariablesPatchableSegment, globalConstantsPatchableSegment, {},
unresolvedExternals);
EXPECT_TRUE(linkResult);
EXPECT_EQ(0U, unresolvedExternals.size());
EXPECT_EQ(7U, *reinterpret_cast<uint8_t *>(globalConstantsPatchableSegment.hostPointer));
EXPECT_EQ(13U, *reinterpret_cast<uint8_t *>(globalVariablesPatchableSegment.hostPointer));
initValue = 0;
for (const auto &reloc : relocationInfo) {
void *srcRaw = (reloc.symbolSegment == NEO::SegmentType::GlobalVariables) ? globalVariablesPatchableSegment.hostPointer : globalConstantsPatchableSegment.hostPointer;
void *dstRaw = (reloc.relocationSegment == NEO::SegmentType::GlobalVariables) ? globalVariablesPatchableSegment.hostPointer : globalConstantsPatchableSegment.hostPointer;
uint8_t *src = reinterpret_cast<uint8_t *>(srcRaw);
uint8_t *dst = reinterpret_cast<uint8_t *>(dstRaw);
// make sure no buffer underflow occured
EXPECT_EQ(dst[0], dst[reloc.offset - 1]);
// check patch-incremented value
if (reloc.type == NEO::LinkerInput::RelocationInfo::Type::Address) {
// make sure no buffer overflow occured
EXPECT_EQ(dst[0], dst[reloc.offset + sizeof(uintptr_t)]);
EXPECT_EQ(reinterpret_cast<uintptr_t>(src) + initValue * 4, *reinterpret_cast<uintptr_t *>(dst + reloc.offset)) << initValue;
} else {
// make sure no buffer overflow occured
EXPECT_EQ(dst[0], dst[reloc.offset + sizeof(uint32_t)]);
EXPECT_EQ(static_cast<uint32_t>(reinterpret_cast<uintptr_t>(src)) + initValue * 4, *reinterpret_cast<uint32_t *>(dst + reloc.offset)) << initValue;
}
++initValue;
}
}
TEST(LinkerTests, givenValidSymbolsAndRelocationsWhenPatchin32bitBinaryThenDataSegmentsAreProperlyPatchedWithLowerPartOfTheAddress) {
WhiteBox<NEO::LinkerInput> linkerInput;
linkerInput.setPointerSize(NEO::LinkerInput::Traits::PointerSize::Ptr32bit);
NEO::Linker linker(linkerInput);
std::vector<char> globalConstantsSegmentData;
globalConstantsSegmentData.resize(128, 7U);
std::vector<char> globalVariablesSegmentData;
globalVariablesSegmentData.resize(256, 13U);
NEO::Linker::SegmentInfo globalConstantsSegmentInfo, globalVariablesSegmentInfo;
NEO::Linker::UnresolvedExternals unresolvedExternals;
NEO::Linker::PatchableSegment globalConstantsPatchableSegment, globalVariablesPatchableSegment;
globalConstantsSegmentInfo.gpuAddress = reinterpret_cast<uintptr_t>(globalConstantsSegmentData.data());
globalConstantsSegmentInfo.segmentSize = globalConstantsSegmentData.size();
globalConstantsPatchableSegment.hostPointer = globalConstantsSegmentData.data();
globalConstantsPatchableSegment.segmentSize = globalConstantsSegmentData.size();
globalVariablesSegmentInfo.gpuAddress = reinterpret_cast<uintptr_t>(globalVariablesSegmentData.data());
globalVariablesSegmentInfo.segmentSize = globalVariablesSegmentData.size();
globalVariablesPatchableSegment.hostPointer = globalVariablesSegmentData.data();
globalVariablesPatchableSegment.segmentSize = globalVariablesSegmentData.size();
NEO::LinkerInput::RelocationInfo relocationInfo[5];
// GlobalVar -> GlobalVar
relocationInfo[0].offset = 8U;
relocationInfo[0].relocationSegment = NEO::SegmentType::GlobalVariables;
relocationInfo[0].symbolSegment = NEO::SegmentType::GlobalVariables;
relocationInfo[0].type = NEO::LinkerInput::RelocationInfo::Type::Address;
// GlobalConst -> GlobalVar
relocationInfo[1].offset = 24U;
relocationInfo[1].relocationSegment = NEO::SegmentType::GlobalConstants;
relocationInfo[1].symbolSegment = NEO::SegmentType::GlobalVariables;
relocationInfo[1].type = NEO::LinkerInput::RelocationInfo::Type::Address;
// GlobalConst -> GlobalConst
relocationInfo[2].offset = 40U;
relocationInfo[2].relocationSegment = NEO::SegmentType::GlobalConstants;
relocationInfo[2].symbolSegment = NEO::SegmentType::GlobalConstants;
relocationInfo[2].type = NEO::LinkerInput::RelocationInfo::Type::Address;
// GlobalVar -> GlobalConst
relocationInfo[3].offset = 56U;
relocationInfo[3].relocationSegment = NEO::SegmentType::GlobalVariables;
relocationInfo[3].symbolSegment = NEO::SegmentType::GlobalConstants;
relocationInfo[3].type = NEO::LinkerInput::RelocationInfo::Type::Address;
// GlobalVar Low -> GlobalVar
relocationInfo[4].offset = 72;
relocationInfo[4].relocationSegment = NEO::SegmentType::GlobalVariables;
relocationInfo[4].symbolSegment = NEO::SegmentType::GlobalVariables;
relocationInfo[4].type = NEO::LinkerInput::RelocationInfo::Type::AddressLow;
uint32_t initValue = 0;
for (const auto &reloc : relocationInfo) {
linkerInput.addDataRelocationInfo(reloc);
void *dstRaw = (reloc.relocationSegment == NEO::SegmentType::GlobalVariables) ? globalVariablesPatchableSegment.hostPointer : globalConstantsPatchableSegment.hostPointer;
*reinterpret_cast<uint32_t *>(ptrOffset(dstRaw, static_cast<size_t>(reloc.offset))) = initValue * 4; // relocations to global data are currently based on patchIncrement, simulate init data
++initValue;
}
auto linkResult = linker.link(globalVariablesSegmentInfo, globalConstantsSegmentInfo, {},
globalVariablesPatchableSegment, globalConstantsPatchableSegment, {},
unresolvedExternals);
EXPECT_TRUE(linkResult);
EXPECT_EQ(0U, unresolvedExternals.size());
EXPECT_EQ(7U, *reinterpret_cast<uint8_t *>(globalConstantsPatchableSegment.hostPointer));
EXPECT_EQ(13U, *reinterpret_cast<uint8_t *>(globalVariablesPatchableSegment.hostPointer));
initValue = 0;
for (const auto &reloc : relocationInfo) {
void *srcRaw = (reloc.symbolSegment == NEO::SegmentType::GlobalVariables) ? globalVariablesPatchableSegment.hostPointer : globalConstantsPatchableSegment.hostPointer;
void *dstRaw = (reloc.relocationSegment == NEO::SegmentType::GlobalVariables) ? globalVariablesPatchableSegment.hostPointer : globalConstantsPatchableSegment.hostPointer;
uint8_t *src = reinterpret_cast<uint8_t *>(srcRaw);
uint8_t *dst = reinterpret_cast<uint8_t *>(dstRaw);
// make sure no buffer under/overflow occured
EXPECT_EQ(dst[0], dst[reloc.offset - 1]);
EXPECT_EQ(dst[0], dst[reloc.offset + sizeof(uint32_t)]);
// check patch-incremented value
EXPECT_EQ(static_cast<uint32_t>(reinterpret_cast<uintptr_t>(src)) + initValue * 4, *reinterpret_cast<uint32_t *>(dst + reloc.offset)) << initValue;
++initValue;
}
}
TEST(LinkerTests, givenInvalidRelocationOffsetThenPatchingOfDataSegmentsFails) {
WhiteBox<NEO::LinkerInput> linkerInput;
NEO::Linker linker(linkerInput);
NEO::Linker::SegmentInfo emptySegmentInfo;
NEO::Linker::PatchableSegment emptyPatchableSegment;
NEO::Linker::UnresolvedExternals unresolvedExternals;
std::vector<char> nonEmptypatchableSegmentData;
nonEmptypatchableSegmentData.resize(64, 8U);
NEO::Linker::PatchableSegment nonEmptypatchableSegment;
nonEmptypatchableSegment.hostPointer = nonEmptypatchableSegmentData.data();
nonEmptypatchableSegment.segmentSize = nonEmptypatchableSegmentData.size();
NEO::LinkerInput::RelocationInfo relocInfo;
relocInfo.offset = 64U;
relocInfo.symbolName = "aaa";
relocInfo.type = NEO::LinkerInput::RelocationInfo::Type::Address;
linkerInput.dataRelocations.push_back(relocInfo);
linkerInput.dataRelocations[0].relocationSegment = NEO::SegmentType::GlobalVariables;
linkerInput.dataRelocations[0].symbolSegment = NEO::SegmentType::GlobalVariables;
linkerInput.traits.requiresPatchingOfGlobalVariablesBuffer = true;
bool linkResult = linker.link(emptySegmentInfo, emptySegmentInfo, emptySegmentInfo,
nonEmptypatchableSegment, emptyPatchableSegment, {},
unresolvedExternals);
EXPECT_FALSE(linkResult);
EXPECT_EQ(1U, unresolvedExternals.size());
linkerInput.dataRelocations[0].offset = 32;
unresolvedExternals.clear();
linkResult = linker.link(emptySegmentInfo, emptySegmentInfo, emptySegmentInfo,
nonEmptypatchableSegment, emptyPatchableSegment, {},
unresolvedExternals);
EXPECT_TRUE(linkResult);
EXPECT_EQ(0U, unresolvedExternals.size());
}
TEST(LinkerErrorMessageTests, whenListOfUnresolvedExternalsIsEmptyThenErrorTypeDefaultsToInternalError) {
NEO::Linker::UnresolvedExternals unresolvedExternals;
std::vector<std::string> segmentsNames{"kernel1", "kernel2"};
auto err = NEO::constructLinkerErrorMessage(unresolvedExternals, segmentsNames);
EXPECT_EQ(std::string("Internal linker error"), err);
}
TEST(LinkerErrorMessageTests, whenUnresolvedExternalsThenSymbolNameInErrorMessage) {
TEST(LinkerErrorMessageTests, givenListOfUnresolvedExternalsThenSymbolNameOrSymbolSegmentTypeGetsEmbededInErrorMessage) {
NEO::Linker::UnresolvedExternals unresolvedExternals;
std::vector<std::string> segmentsNames{"kernel1", "kernel2"};
NEO::Linker::UnresolvedExternal unresolvedExternal = {};
@@ -490,6 +950,7 @@ TEST(LinkerErrorMessageTests, whenUnresolvedExternalsThenSymbolNameInErrorMessag
unresolvedExternal.internalError = false;
unresolvedExternal.unresolvedRelocation.offset = 64;
unresolvedExternal.unresolvedRelocation.symbolName = "arrayABC";
unresolvedExternal.unresolvedRelocation.relocationSegment = NEO::SegmentType::Instructions;
unresolvedExternals.push_back(unresolvedExternal);
auto err = NEO::constructLinkerErrorMessage(unresolvedExternals, segmentsNames);
EXPECT_THAT(err.c_str(), ::testing::HasSubstr(unresolvedExternal.unresolvedRelocation.symbolName.c_str()));
@@ -509,4 +970,19 @@ TEST(LinkerErrorMessageTests, whenUnresolvedExternalsThenSymbolNameInErrorMessag
EXPECT_THAT(err.c_str(), ::testing::Not(::testing::HasSubstr(segmentsNames[unresolvedExternal.instructionsSegmentId].c_str())));
EXPECT_THAT(err.c_str(), ::testing::HasSubstr(std::to_string(unresolvedExternal.unresolvedRelocation.offset).c_str()));
EXPECT_THAT(err.c_str(), ::testing::HasSubstr("internal linker error"));
unresolvedExternals[0].unresolvedRelocation.relocationSegment = NEO::SegmentType::GlobalConstants;
err = NEO::constructLinkerErrorMessage(unresolvedExternals, {});
EXPECT_THAT(err.c_str(), ::testing::HasSubstr(NEO::asString(NEO::SegmentType::GlobalConstants)));
EXPECT_THAT(err.c_str(), ::testing::HasSubstr(std::to_string(unresolvedExternal.unresolvedRelocation.offset).c_str()));
unresolvedExternals[0].unresolvedRelocation.relocationSegment = NEO::SegmentType::GlobalVariables;
err = NEO::constructLinkerErrorMessage(unresolvedExternals, {});
EXPECT_THAT(err.c_str(), ::testing::HasSubstr(NEO::asString(NEO::SegmentType::GlobalVariables)));
EXPECT_THAT(err.c_str(), ::testing::HasSubstr(std::to_string(unresolvedExternal.unresolvedRelocation.offset).c_str()));
unresolvedExternals[0].unresolvedRelocation.relocationSegment = NEO::SegmentType::Unknown;
err = NEO::constructLinkerErrorMessage(unresolvedExternals, {});
EXPECT_THAT(err.c_str(), ::testing::HasSubstr(NEO::asString(NEO::SegmentType::Unknown)));
EXPECT_THAT(err.c_str(), ::testing::HasSubstr(std::to_string(unresolvedExternal.unresolvedRelocation.offset).c_str()));
}

View File

@@ -0,0 +1,15 @@
#
# Copyright (C) 2018-2020 Intel Corporation
#
# SPDX-License-Identifier: MIT
#
set(NEO_CORE_SRCS_tests_program
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
${CMAKE_CURRENT_SOURCE_DIR}/program_info_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/program_info_from_patchtokens_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/program_initialization_tests.cpp
)
set_property(GLOBAL PROPERTY NEO_CORE_SRCS_tests_program ${NEO_CORE_SRCS_tests_program})
add_subdirectories()

View File

@@ -0,0 +1,292 @@
/*
* Copyright (C) 2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "core/compiler_interface/linker.h"
#include "core/program/program_info.h"
#include "core/program/program_info_from_patchtokens.h"
#include "core/unit_tests/compiler_interface/linker_mock.h"
#include "runtime/compiler_interface/patchtokens_decoder.h"
#include "runtime/program/kernel_info.h"
#include "unit_tests/compiler_interface/patchtokens_tests.h"
#include "RelocationInfo.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
TEST(PopulateProgramInfoFromPatchtokensTests, WhenRequiresLocalMemoryWindowVAIsCalledThenReturnsTrueOnlyIfAnyOfKernelsRequireLocalMemoryWindowVA) {
NEO::PatchTokenBinary::ProgramFromPatchtokens emptyProgram;
EXPECT_FALSE(NEO::requiresLocalMemoryWindowVA(emptyProgram));
NEO::PatchTokenBinary::KernelFromPatchtokens kernelWithoutRequirementForLocalMemoryWindowWA;
NEO::PatchTokenBinary::KernelFromPatchtokens kernelWithRequirementForLocalMemoryWindowWA;
iOpenCL::SPatchDataParameterBuffer param;
kernelWithRequirementForLocalMemoryWindowWA.tokens.crossThreadPayloadArgs.localMemoryStatelessWindowStartAddress = &param;
NEO::PatchTokenBinary::ProgramFromPatchtokens programWithOneKernelWithoutLocalMemWindow;
programWithOneKernelWithoutLocalMemWindow.kernels.push_back(kernelWithoutRequirementForLocalMemoryWindowWA);
EXPECT_FALSE(NEO::requiresLocalMemoryWindowVA(programWithOneKernelWithoutLocalMemWindow));
NEO::PatchTokenBinary::ProgramFromPatchtokens programWithOneKernelWithLocalMemWindow;
programWithOneKernelWithLocalMemWindow.kernels.push_back(kernelWithRequirementForLocalMemoryWindowWA);
EXPECT_TRUE(NEO::requiresLocalMemoryWindowVA(programWithOneKernelWithLocalMemWindow));
NEO::PatchTokenBinary::ProgramFromPatchtokens programWithTwoKernelsWithLocalMemWindow;
programWithTwoKernelsWithLocalMemWindow.kernels.push_back(kernelWithoutRequirementForLocalMemoryWindowWA);
programWithTwoKernelsWithLocalMemWindow.kernels.push_back(kernelWithRequirementForLocalMemoryWindowWA);
EXPECT_TRUE(NEO::requiresLocalMemoryWindowVA(programWithTwoKernelsWithLocalMemWindow));
std::swap(programWithTwoKernelsWithLocalMemWindow.kernels[0], programWithTwoKernelsWithLocalMemWindow.kernels[1]);
EXPECT_TRUE(NEO::requiresLocalMemoryWindowVA(programWithTwoKernelsWithLocalMemWindow));
}
TEST(PopulateProgramInfoFromPatchtokensTests, WhenProgramRequiresGlobalConstantsSurfaceThenGlobalConstantsSectionIsPopulated) {
PatchTokensTestData::ValidProgramWithConstantSurface programTokens;
NEO::ProgramInfo programInfo;
NEO::populateProgramInfo(programInfo, programTokens, {});
EXPECT_EQ(programInfo.globalConstants.size, programTokens.programScopeTokens.allocateConstantMemorySurface[0]->InlineDataSize);
EXPECT_EQ(programInfo.globalConstants.initData, NEO::PatchTokenBinary::getInlineData(programTokens.programScopeTokens.allocateConstantMemorySurface[0]));
EXPECT_TRUE(programInfo.kernelInfos.empty());
EXPECT_EQ(nullptr, programInfo.linkerInput);
}
TEST(PopulateProgramInfoFromPatchtokensTests, WhenProgramRequiresGlobalVariablesSurfaceThenGlobalConstantsSectionIsPopulated) {
PatchTokensTestData::ValidProgramWithGlobalSurface programTokens;
NEO::ProgramInfo programInfo;
NEO::populateProgramInfo(programInfo, programTokens, {});
EXPECT_EQ(programInfo.globalVariables.size, programTokens.programScopeTokens.allocateGlobalMemorySurface[0]->InlineDataSize);
EXPECT_EQ(programInfo.globalVariables.initData, NEO::PatchTokenBinary::getInlineData(programTokens.programScopeTokens.allocateGlobalMemorySurface[0]));
EXPECT_TRUE(programInfo.kernelInfos.empty());
EXPECT_EQ(nullptr, programInfo.linkerInput);
}
TEST(PopulateProgramInfoFromPatchtokensTests, WhenProgramRequiresGlobalConstantsPointersThenLinkerInputContainsProperRelocations) {
PatchTokensTestData::ValidProgramWithConstantSurfaceAndPointer programFromTokens;
NEO::ProgramInfo programInfo;
NEO::populateProgramInfo(programInfo, programFromTokens, {});
EXPECT_TRUE(programInfo.kernelInfos.empty());
ASSERT_NE(nullptr, programInfo.linkerInput);
ASSERT_EQ(1U, programInfo.linkerInput->getDataRelocations().size());
auto relocation = programInfo.linkerInput->getDataRelocations()[0];
EXPECT_EQ(programFromTokens.programScopeTokens.constantPointer[0]->ConstantPointerOffset, relocation.offset);
EXPECT_TRUE(relocation.symbolName.empty());
EXPECT_EQ(NEO::SegmentType::GlobalConstants, relocation.relocationSegment);
EXPECT_EQ(NEO::SegmentType::GlobalConstants, relocation.symbolSegment);
EXPECT_EQ(NEO::LinkerInput::RelocationInfo::Type::Address, relocation.type);
}
TEST(PopulateProgramInfoFromPatchtokensTests, WhenProgramRequiresGlobalVariablesPointersThenLinkerInputContainsProperRelocations) {
PatchTokensTestData::ValidProgramWithGlobalSurfaceAndPointer programFromTokens;
NEO::ProgramInfo programInfo;
NEO::populateProgramInfo(programInfo, programFromTokens, {});
EXPECT_TRUE(programInfo.kernelInfos.empty());
ASSERT_NE(nullptr, programInfo.linkerInput);
ASSERT_EQ(1U, programInfo.linkerInput->getDataRelocations().size());
auto relocation = programInfo.linkerInput->getDataRelocations()[0];
EXPECT_EQ(NEO::readMisalignedUint64(&programFromTokens.programScopeTokens.globalPointer[0]->GlobalPointerOffset), relocation.offset);
EXPECT_TRUE(relocation.symbolName.empty());
EXPECT_EQ(NEO::SegmentType::GlobalVariables, relocation.relocationSegment);
EXPECT_EQ(NEO::SegmentType::GlobalVariables, relocation.symbolSegment);
EXPECT_EQ(NEO::LinkerInput::RelocationInfo::Type::Address, relocation.type);
}
TEST(PopulateProgramInfoFromPatchtokensTests, WhenProgramRequiresMixedGlobalVarAndConstPointersThenLinkerInputContainsProperRelocations) {
PatchTokensTestData::ValidProgramWithMixedGlobalVarAndConstSurfacesAndPointers programFromTokens;
NEO::ProgramInfo programInfo;
NEO::populateProgramInfo(programInfo, programFromTokens, {});
EXPECT_TRUE(programInfo.kernelInfos.empty());
ASSERT_NE(nullptr, programInfo.linkerInput);
const NEO::LinkerInput::RelocationInfo *relocationGlobalConst, *relocationGlobalVar;
ASSERT_EQ(2U, programInfo.linkerInput->getDataRelocations().size());
for (const auto &reloc : programInfo.linkerInput->getDataRelocations()) {
switch (reloc.relocationSegment) {
default:
break;
case NEO::SegmentType::GlobalConstants:
relocationGlobalConst = &reloc;
break;
case NEO::SegmentType::GlobalVariables:
relocationGlobalVar = &reloc;
break;
}
}
ASSERT_NE(nullptr, relocationGlobalConst);
EXPECT_EQ(NEO::readMisalignedUint64(&programFromTokens.programScopeTokens.constantPointer[0]->ConstantPointerOffset), relocationGlobalConst->offset);
EXPECT_TRUE(relocationGlobalConst->symbolName.empty());
EXPECT_EQ(NEO::SegmentType::GlobalConstants, relocationGlobalConst->relocationSegment);
EXPECT_EQ(NEO::SegmentType::GlobalVariables, relocationGlobalConst->symbolSegment);
EXPECT_EQ(NEO::LinkerInput::RelocationInfo::Type::Address, relocationGlobalConst->type);
ASSERT_NE(nullptr, relocationGlobalVar);
EXPECT_EQ(NEO::readMisalignedUint64(&programFromTokens.programScopeTokens.globalPointer[0]->GlobalPointerOffset), relocationGlobalVar->offset);
EXPECT_TRUE(relocationGlobalVar->symbolName.empty());
EXPECT_EQ(NEO::SegmentType::GlobalVariables, relocationGlobalVar->relocationSegment);
EXPECT_EQ(NEO::SegmentType::GlobalConstants, relocationGlobalVar->symbolSegment);
EXPECT_EQ(NEO::LinkerInput::RelocationInfo::Type::Address, relocationGlobalVar->type);
}
TEST(PopulateProgramInfoFromPatchtokensTests, GivenProgramWithSpecificPointerSizeThenLinkerIsUpdatedToUseRequiredPointerSize) {
PatchTokensTestData::ValidProgramWithMixedGlobalVarAndConstSurfacesAndPointers programFromTokens;
programFromTokens.headerMutable->GPUPointerSizeInBytes = 8;
NEO::ProgramInfo programInfo;
NEO::populateProgramInfo(programInfo, programFromTokens, {});
ASSERT_NE(nullptr, programInfo.linkerInput);
EXPECT_EQ(NEO::LinkerInput::Traits::Ptr64bit, programInfo.linkerInput->getTraits().pointerSize);
programFromTokens.headerMutable->GPUPointerSizeInBytes = 4;
programInfo = {};
NEO::populateProgramInfo(programInfo, programFromTokens, {});
ASSERT_NE(nullptr, programInfo.linkerInput);
EXPECT_EQ(NEO::LinkerInput::Traits::Ptr32bit, programInfo.linkerInput->getTraits().pointerSize);
}
TEST(PopulateProgramInfoFromPatchtokensTests, GivenProgramWithProgramSymbolTableThenLinkerDecodesAllSymbolsCorrectly) {
PatchTokensTestData::ValidEmptyProgram programFromTokens;
NEO::ProgramInfo programInfo = {};
Mock<NEO::LinkerInput> *mockLinkerInput = new Mock<NEO::LinkerInput>;
programInfo.linkerInput.reset(mockLinkerInput);
vISA::GenSymEntry entry[1] = {};
iOpenCL::SPatchFunctionTableInfo symbolTable = {};
symbolTable.NumEntries = 1;
std::vector<uint8_t> symbolTableTokenStorage = {};
symbolTableTokenStorage.insert(symbolTableTokenStorage.end(),
reinterpret_cast<uint8_t *>(&symbolTable), reinterpret_cast<uint8_t *>(&symbolTable + 1));
symbolTableTokenStorage.insert(symbolTableTokenStorage.end(),
reinterpret_cast<uint8_t *>(entry), reinterpret_cast<uint8_t *>(entry + 1));
programFromTokens.programScopeTokens.symbolTable = reinterpret_cast<iOpenCL::SPatchFunctionTableInfo *>(symbolTableTokenStorage.data());
const void *receivedData = nullptr;
uint32_t receivedNumEntries = 0U;
mockLinkerInput->decodeGlobalVariablesSymbolTableMockConfig.overrideFunc = [&](Mock<NEO::LinkerInput> *, const void *data, uint32_t numEntries) -> bool {
receivedData = data;
receivedNumEntries = numEntries;
return true;
};
NEO::populateProgramInfo(programInfo, programFromTokens, {});
ASSERT_EQ(mockLinkerInput, programInfo.linkerInput.get());
EXPECT_EQ(1U, mockLinkerInput->decodeGlobalVariablesSymbolTableMockConfig.timesCalled);
EXPECT_EQ(reinterpret_cast<void *>(symbolTableTokenStorage.data() + sizeof(iOpenCL::SPatchFunctionTableInfo)), receivedData);
EXPECT_EQ(1U, receivedNumEntries);
}
TEST(PopulateProgramInfoFromPatchtokensTests, GivenProgramWithKernelsThenKernelInfosIsProperlyPopulated) {
PatchTokensTestData::ValidProgramWithKernel programFromTokens;
programFromTokens.kernels.push_back(programFromTokens.kernels[0]);
programFromTokens.kernels.push_back(programFromTokens.kernels[0]);
NEO::ProgramInfo programInfo = {};
NEO::populateProgramInfo(programInfo, programFromTokens, {});
ASSERT_EQ(3U, programInfo.kernelInfos.size());
EXPECT_EQ(programFromTokens.header->GPUPointerSizeInBytes, programInfo.kernelInfos[0]->gpuPointerSize);
EXPECT_EQ(programFromTokens.header->GPUPointerSizeInBytes, programInfo.kernelInfos[1]->gpuPointerSize);
EXPECT_EQ(programFromTokens.header->GPUPointerSizeInBytes, programInfo.kernelInfos[2]->gpuPointerSize);
}
TEST(PopulateProgramInfoFromPatchtokensTests, GivenProgramWithKernelsWhenKernelHasSymbolTableThenLinkerIsUpdatedWithAdditionalSymbolInfo) {
NEO::ProgramInfo programInfo = {};
Mock<NEO::LinkerInput> *mockLinkerInput = new Mock<NEO::LinkerInput>;
programInfo.linkerInput.reset(mockLinkerInput);
PatchTokensTestData::ValidProgramWithKernel programFromTokens;
programFromTokens.kernels.push_back(programFromTokens.kernels[0]);
vISA::GenSymEntry entryA[1] = {};
iOpenCL::SPatchFunctionTableInfo symbolTableA = {};
symbolTableA.NumEntries = 1;
std::vector<uint8_t> symbolTableATokenStorage = {};
symbolTableATokenStorage.insert(symbolTableATokenStorage.end(),
reinterpret_cast<uint8_t *>(&symbolTableA), reinterpret_cast<uint8_t *>(&symbolTableA + 1));
symbolTableATokenStorage.insert(symbolTableATokenStorage.end(),
reinterpret_cast<uint8_t *>(entryA), reinterpret_cast<uint8_t *>(entryA + 1));
programFromTokens.kernels[0].tokens.programSymbolTable = reinterpret_cast<iOpenCL::SPatchFunctionTableInfo *>(symbolTableATokenStorage.data());
vISA::GenSymEntry entryB[2] = {};
iOpenCL::SPatchFunctionTableInfo symbolTableB = {};
symbolTableB.NumEntries = 2;
std::vector<uint8_t> symbolTableBTokenStorage = {};
symbolTableBTokenStorage.insert(symbolTableBTokenStorage.end(),
reinterpret_cast<uint8_t *>(&symbolTableB), reinterpret_cast<uint8_t *>(&symbolTableB + 1));
symbolTableBTokenStorage.insert(symbolTableBTokenStorage.end(),
reinterpret_cast<uint8_t *>(entryB), reinterpret_cast<uint8_t *>(entryB + 2));
programFromTokens.kernels[1].tokens.programSymbolTable = reinterpret_cast<iOpenCL::SPatchFunctionTableInfo *>(symbolTableBTokenStorage.data());
std::vector<const void *> receivedData;
std::vector<uint32_t> receivedNumEntries;
std::vector<uint32_t> receivedSegmentIds;
mockLinkerInput->decodeExportedFunctionsSymbolTableMockConfig.overrideFunc = [&](Mock<NEO::LinkerInput> *, const void *data, uint32_t numEntries, uint32_t instructionsSegmentId) -> bool {
receivedData.push_back(data);
receivedNumEntries.push_back(numEntries);
receivedSegmentIds.push_back(instructionsSegmentId);
return true;
};
NEO::populateProgramInfo(programInfo, programFromTokens, {});
ASSERT_EQ(2U, mockLinkerInput->decodeExportedFunctionsSymbolTableMockConfig.timesCalled);
ASSERT_EQ(2U, receivedData.size());
EXPECT_EQ(1U, receivedNumEntries[0]);
EXPECT_EQ(2U, receivedNumEntries[1]);
EXPECT_EQ(reinterpret_cast<void *>(symbolTableATokenStorage.data() + sizeof(iOpenCL::SPatchFunctionTableInfo)), receivedData[0]);
EXPECT_EQ(reinterpret_cast<void *>(symbolTableBTokenStorage.data() + sizeof(iOpenCL::SPatchFunctionTableInfo)), receivedData[1]);
EXPECT_EQ(0U, receivedSegmentIds[0]);
EXPECT_EQ(1U, receivedSegmentIds[1]);
}
TEST(PopulateProgramInfoFromPatchtokensTests, GivenProgramWithKernelsWhenKernelHasRelocationTableThenLinkerIsUpdatedWithAdditionalRelocationInfo) {
NEO::ProgramInfo programInfo = {};
Mock<NEO::LinkerInput> *mockLinkerInput = new Mock<NEO::LinkerInput>;
programInfo.linkerInput.reset(mockLinkerInput);
PatchTokensTestData::ValidProgramWithKernel programFromTokens;
programFromTokens.kernels.push_back(programFromTokens.kernels[0]);
vISA::GenRelocEntry entryA[1] = {};
iOpenCL::SPatchFunctionTableInfo relocationTableA = {};
relocationTableA.NumEntries = 1;
std::vector<uint8_t> relocationTableATokenStorage = {};
relocationTableATokenStorage.insert(relocationTableATokenStorage.end(),
reinterpret_cast<uint8_t *>(&relocationTableA), reinterpret_cast<uint8_t *>(&relocationTableA + 1));
relocationTableATokenStorage.insert(relocationTableATokenStorage.end(),
reinterpret_cast<uint8_t *>(entryA), reinterpret_cast<uint8_t *>(entryA + 1));
programFromTokens.kernels[0].tokens.programRelocationTable = reinterpret_cast<iOpenCL::SPatchFunctionTableInfo *>(relocationTableATokenStorage.data());
vISA::GenRelocEntry entryB[2] = {};
iOpenCL::SPatchFunctionTableInfo relocationTableB = {};
relocationTableB.NumEntries = 2;
std::vector<uint8_t> relocationTableBTokenStorage = {};
relocationTableBTokenStorage.insert(relocationTableBTokenStorage.end(),
reinterpret_cast<uint8_t *>(&relocationTableB), reinterpret_cast<uint8_t *>(&relocationTableB + 1));
relocationTableBTokenStorage.insert(relocationTableBTokenStorage.end(),
reinterpret_cast<uint8_t *>(entryB), reinterpret_cast<uint8_t *>(entryB + 2));
programFromTokens.kernels[1].tokens.programRelocationTable = reinterpret_cast<iOpenCL::SPatchFunctionTableInfo *>(relocationTableBTokenStorage.data());
std::vector<const void *> receivedData;
std::vector<uint32_t> receivedNumEntries;
std::vector<uint32_t> receivedSegmentIds;
mockLinkerInput->decodeRelocationTableMockConfig.overrideFunc = [&](Mock<NEO::LinkerInput> *, const void *data, uint32_t numEntries, uint32_t instructionsSegmentId) -> bool {
receivedData.push_back(data);
receivedNumEntries.push_back(numEntries);
receivedSegmentIds.push_back(instructionsSegmentId);
return true;
};
NEO::populateProgramInfo(programInfo, programFromTokens, {});
ASSERT_EQ(2U, mockLinkerInput->decodeRelocationTableMockConfig.timesCalled);
ASSERT_EQ(2U, receivedData.size());
EXPECT_EQ(1U, receivedNumEntries[0]);
EXPECT_EQ(2U, receivedNumEntries[1]);
EXPECT_EQ(reinterpret_cast<void *>(relocationTableATokenStorage.data() + sizeof(iOpenCL::SPatchFunctionTableInfo)), receivedData[0]);
EXPECT_EQ(reinterpret_cast<void *>(relocationTableBTokenStorage.data() + sizeof(iOpenCL::SPatchFunctionTableInfo)), receivedData[1]);
EXPECT_EQ(0U, receivedSegmentIds[0]);
EXPECT_EQ(1U, receivedSegmentIds[1]);
}

View File

@@ -0,0 +1,21 @@
/*
* Copyright (C) 2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "core/program/program_info.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
TEST(ProgramInfoTests, whenPrepareLinkerInputStorageGetsCalledTwiceThenLinkerInputStorageIsReused) {
NEO::ProgramInfo programInfo;
EXPECT_EQ(nullptr, programInfo.linkerInput);
programInfo.prepareLinkerInputStorage();
EXPECT_NE(nullptr, programInfo.linkerInput);
auto prevLinkerInput = programInfo.linkerInput.get();
programInfo.prepareLinkerInputStorage();
EXPECT_EQ(prevLinkerInput, programInfo.linkerInput.get());
}

View File

@@ -0,0 +1,213 @@
/*
* Copyright (C) 2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "core/program/program_initialization.h"
#include "core/unit_tests/compiler_interface/linker_mock.h"
#include "unit_tests/mocks/mock_device.h"
#include "unit_tests/mocks/mock_memory_manager.h"
#include "unit_tests/mocks/mock_svm_manager.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <cstdint>
TEST(AllocateGlobalSurfaceTest, GivenSvmAllocsManagerWhenGlobalsAreNotExportedThenMemoryIsAllocatedAsNonSvmAllocation) {
MockDevice device;
if (0 == device.getDeviceInfo().svmCapabilities) {
return;
}
MockSVMAllocsManager svmAllocsManager(device.getMemoryManager());
WhiteBox<LinkerInput> emptyLinkerInput;
LinkerInput *linkerInput;
std::vector<uint8_t> initData;
initData.resize(64, 7U);
bool constant = true;
GraphicsAllocation *alloc = nullptr;
alloc = allocateGlobalsSurface(&svmAllocsManager, device, initData.size(), constant = true, linkerInput = nullptr, initData.data());
ASSERT_NE(nullptr, alloc);
ASSERT_EQ(initData.size(), alloc->getUnderlyingBufferSize());
EXPECT_EQ(0, memcmp(alloc->getUnderlyingBuffer(), initData.data(), initData.size()));
EXPECT_EQ(nullptr, svmAllocsManager.getSVMAlloc(reinterpret_cast<void *>(static_cast<uintptr_t>(alloc->getGpuAddress()))));
EXPECT_EQ(GraphicsAllocation::AllocationType::CONSTANT_SURFACE, alloc->getAllocationType());
device.getMemoryManager()->freeGraphicsMemory(alloc);
alloc = allocateGlobalsSurface(&svmAllocsManager, device, initData.size(), constant = false, linkerInput = nullptr, initData.data());
ASSERT_NE(nullptr, alloc);
ASSERT_EQ(initData.size(), alloc->getUnderlyingBufferSize());
EXPECT_EQ(0, memcmp(alloc->getUnderlyingBuffer(), initData.data(), initData.size()));
EXPECT_EQ(nullptr, svmAllocsManager.getSVMAlloc(reinterpret_cast<void *>(static_cast<uintptr_t>(alloc->getGpuAddress()))));
EXPECT_EQ(GraphicsAllocation::AllocationType::GLOBAL_SURFACE, alloc->getAllocationType());
device.getMemoryManager()->freeGraphicsMemory(alloc);
alloc = allocateGlobalsSurface(&svmAllocsManager, device, initData.size(), constant = true, linkerInput = &emptyLinkerInput, initData.data());
ASSERT_NE(nullptr, alloc);
ASSERT_EQ(initData.size(), alloc->getUnderlyingBufferSize());
EXPECT_EQ(0, memcmp(alloc->getUnderlyingBuffer(), initData.data(), initData.size()));
EXPECT_EQ(nullptr, svmAllocsManager.getSVMAlloc(reinterpret_cast<void *>(static_cast<uintptr_t>(alloc->getGpuAddress()))));
EXPECT_EQ(GraphicsAllocation::AllocationType::CONSTANT_SURFACE, alloc->getAllocationType());
device.getMemoryManager()->freeGraphicsMemory(alloc);
alloc = allocateGlobalsSurface(&svmAllocsManager, device, initData.size(), constant = false, linkerInput = &emptyLinkerInput, initData.data());
ASSERT_NE(nullptr, alloc);
ASSERT_EQ(initData.size(), alloc->getUnderlyingBufferSize());
EXPECT_EQ(0, memcmp(alloc->getUnderlyingBuffer(), initData.data(), initData.size()));
EXPECT_EQ(nullptr, svmAllocsManager.getSVMAlloc(reinterpret_cast<void *>(static_cast<uintptr_t>(alloc->getGpuAddress()))));
EXPECT_EQ(GraphicsAllocation::AllocationType::GLOBAL_SURFACE, alloc->getAllocationType());
device.getMemoryManager()->freeGraphicsMemory(alloc);
}
TEST(AllocateGlobalSurfaceTest, GivenSvmAllocsManagerWhenGlobalsAreExportedThenMemoryIsAllocatedAsSvmAllocation) {
MockDevice device;
if (0 == device.getDeviceInfo().svmCapabilities) {
return;
}
MockMemoryManager memoryManager;
MockSVMAllocsManager svmAllocsManager(&memoryManager);
WhiteBox<LinkerInput> linkerInputExportGlobalVariables;
WhiteBox<LinkerInput> linkerInputExportGlobalConstants;
linkerInputExportGlobalVariables.traits.exportsGlobalVariables = true;
linkerInputExportGlobalConstants.traits.exportsGlobalConstants = true;
LinkerInput *linkerInput;
std::vector<uint8_t> initData;
initData.resize(64, 7U);
bool constant = true;
GraphicsAllocation *alloc = nullptr;
alloc = allocateGlobalsSurface(&svmAllocsManager, device, initData.size(), constant = true, linkerInput = &linkerInputExportGlobalConstants, initData.data());
ASSERT_NE(nullptr, alloc);
ASSERT_EQ(initData.size(), alloc->getUnderlyingBufferSize());
EXPECT_EQ(0, memcmp(alloc->getUnderlyingBuffer(), initData.data(), initData.size()));
ASSERT_NE(nullptr, svmAllocsManager.getSVMAlloc(reinterpret_cast<void *>(static_cast<uintptr_t>(alloc->getGpuAddress()))));
EXPECT_FALSE(alloc->isMemObjectsAllocationWithWritableFlags());
svmAllocsManager.freeSVMAlloc(reinterpret_cast<void *>(static_cast<uintptr_t>(alloc->getGpuAddress())));
alloc = allocateGlobalsSurface(&svmAllocsManager, device, initData.size(), constant = true, linkerInput = &linkerInputExportGlobalVariables, initData.data());
ASSERT_NE(nullptr, alloc);
ASSERT_EQ(initData.size(), alloc->getUnderlyingBufferSize());
EXPECT_EQ(0, memcmp(alloc->getUnderlyingBuffer(), initData.data(), initData.size()));
EXPECT_EQ(nullptr, svmAllocsManager.getSVMAlloc(reinterpret_cast<void *>(static_cast<uintptr_t>(alloc->getGpuAddress()))));
device.getMemoryManager()->freeGraphicsMemory(alloc);
alloc = allocateGlobalsSurface(&svmAllocsManager, device, initData.size(), constant = false, linkerInput = &linkerInputExportGlobalConstants, initData.data());
ASSERT_NE(nullptr, alloc);
ASSERT_EQ(initData.size(), alloc->getUnderlyingBufferSize());
EXPECT_EQ(0, memcmp(alloc->getUnderlyingBuffer(), initData.data(), initData.size()));
EXPECT_EQ(nullptr, svmAllocsManager.getSVMAlloc(reinterpret_cast<void *>(static_cast<uintptr_t>(alloc->getGpuAddress()))));
device.getMemoryManager()->freeGraphicsMemory(alloc);
alloc = allocateGlobalsSurface(&svmAllocsManager, device, initData.size(), constant = false, linkerInput = &linkerInputExportGlobalVariables, initData.data());
ASSERT_NE(nullptr, alloc);
ASSERT_EQ(initData.size(), alloc->getUnderlyingBufferSize());
EXPECT_EQ(0, memcmp(alloc->getUnderlyingBuffer(), initData.data(), initData.size()));
EXPECT_NE(nullptr, svmAllocsManager.getSVMAlloc(reinterpret_cast<void *>(static_cast<uintptr_t>(alloc->getGpuAddress()))));
EXPECT_TRUE(alloc->isMemObjectsAllocationWithWritableFlags());
svmAllocsManager.freeSVMAlloc(reinterpret_cast<void *>(static_cast<uintptr_t>(alloc->getGpuAddress())));
}
TEST(AllocateGlobalSurfaceTest, GivenNullSvmAllocsManagerWhenGlobalsAreExportedThenMemoryIsAllocatedAsNonSvmAllocation) {
MockDevice device;
WhiteBox<LinkerInput> linkerInputExportGlobalVariables;
WhiteBox<LinkerInput> linkerInputExportGlobalConstants;
linkerInputExportGlobalVariables.traits.exportsGlobalVariables = true;
linkerInputExportGlobalConstants.traits.exportsGlobalConstants = true;
LinkerInput *linkerInput;
std::vector<uint8_t> initData;
initData.resize(64, 7U);
bool constant = true;
GraphicsAllocation *alloc = nullptr;
alloc = allocateGlobalsSurface(nullptr, device, initData.size(), constant = true, linkerInput = &linkerInputExportGlobalConstants, initData.data());
ASSERT_NE(nullptr, alloc);
ASSERT_EQ(initData.size(), alloc->getUnderlyingBufferSize());
EXPECT_EQ(0, memcmp(alloc->getUnderlyingBuffer(), initData.data(), initData.size()));
EXPECT_EQ(GraphicsAllocation::AllocationType::CONSTANT_SURFACE, alloc->getAllocationType());
device.getMemoryManager()->freeGraphicsMemory(alloc);
alloc = allocateGlobalsSurface(nullptr, device, initData.size(), constant = true, linkerInput = &linkerInputExportGlobalVariables, initData.data());
ASSERT_NE(nullptr, alloc);
ASSERT_EQ(initData.size(), alloc->getUnderlyingBufferSize());
EXPECT_EQ(0, memcmp(alloc->getUnderlyingBuffer(), initData.data(), initData.size()));
EXPECT_EQ(GraphicsAllocation::AllocationType::CONSTANT_SURFACE, alloc->getAllocationType());
device.getMemoryManager()->freeGraphicsMemory(alloc);
alloc = allocateGlobalsSurface(nullptr, device, initData.size(), constant = false, linkerInput = &linkerInputExportGlobalConstants, initData.data());
ASSERT_NE(nullptr, alloc);
ASSERT_EQ(initData.size(), alloc->getUnderlyingBufferSize());
EXPECT_EQ(0, memcmp(alloc->getUnderlyingBuffer(), initData.data(), initData.size()));
EXPECT_EQ(GraphicsAllocation::AllocationType::GLOBAL_SURFACE, alloc->getAllocationType());
device.getMemoryManager()->freeGraphicsMemory(alloc);
alloc = allocateGlobalsSurface(nullptr, device, initData.size(), constant = false, linkerInput = &linkerInputExportGlobalVariables, initData.data());
ASSERT_NE(nullptr, alloc);
ASSERT_EQ(initData.size(), alloc->getUnderlyingBufferSize());
EXPECT_EQ(0, memcmp(alloc->getUnderlyingBuffer(), initData.data(), initData.size()));
EXPECT_EQ(GraphicsAllocation::AllocationType::GLOBAL_SURFACE, alloc->getAllocationType());
device.getMemoryManager()->freeGraphicsMemory(alloc);
}
TEST(AllocateGlobalSurfaceTest, WhenGlobalsAreNotExportedAndAllocationFailsThenGracefullyReturnsNullptr) {
MockDevice device;
auto memoryManager = std::make_unique<MockMemoryManager>();
memoryManager->failInAllocateWithSizeAndAlignment = true;
device.injectMemoryManager(memoryManager.release());
MockSVMAllocsManager mockSvmAllocsManager(device.getMemoryManager());
WhiteBox<LinkerInput> emptyLinkerInput;
LinkerInput *linkerInput;
SVMAllocsManager *svmAllocsManager = &mockSvmAllocsManager;
std::vector<uint8_t> initData;
initData.resize(64, 7U);
bool constant = true;
GraphicsAllocation *alloc = nullptr;
alloc = allocateGlobalsSurface(svmAllocsManager = &mockSvmAllocsManager, device, initData.size(), constant = true, linkerInput = nullptr, initData.data());
EXPECT_EQ(nullptr, alloc);
alloc = allocateGlobalsSurface(svmAllocsManager = &mockSvmAllocsManager, device, initData.size(), constant = false, linkerInput = nullptr, initData.data());
EXPECT_EQ(nullptr, alloc);
alloc = allocateGlobalsSurface(svmAllocsManager = &mockSvmAllocsManager, device, initData.size(), constant = true, linkerInput = &emptyLinkerInput, initData.data());
EXPECT_EQ(nullptr, alloc);
alloc = allocateGlobalsSurface(svmAllocsManager = &mockSvmAllocsManager, device, initData.size(), constant = false, linkerInput = &emptyLinkerInput, initData.data());
EXPECT_EQ(nullptr, alloc);
alloc = allocateGlobalsSurface(svmAllocsManager = nullptr, device, initData.size(), constant = true, linkerInput = nullptr, initData.data());
EXPECT_EQ(nullptr, alloc);
alloc = allocateGlobalsSurface(svmAllocsManager = nullptr, device, initData.size(), constant = false, linkerInput = nullptr, initData.data());
EXPECT_EQ(nullptr, alloc);
alloc = allocateGlobalsSurface(svmAllocsManager = nullptr, device, initData.size(), constant = true, linkerInput = &emptyLinkerInput, initData.data());
EXPECT_EQ(nullptr, alloc);
alloc = allocateGlobalsSurface(svmAllocsManager = nullptr, device, initData.size(), constant = false, linkerInput = &emptyLinkerInput, initData.data());
EXPECT_EQ(nullptr, alloc);
}
TEST(AllocateGlobalSurfaceTest, WhenGlobalsAreExportedAndAllocationFailsThenGracefullyReturnsNullptr) {
MockDevice device;
MockMemoryManager memoryManager;
MockSVMAllocsManager svmAllocsManager(&memoryManager);
memoryManager.failInAllocateWithSizeAndAlignment = true;
WhiteBox<LinkerInput> linkerInputExportGlobalVariables;
WhiteBox<LinkerInput> linkerInputExportGlobalConstants;
linkerInputExportGlobalVariables.traits.exportsGlobalVariables = true;
linkerInputExportGlobalConstants.traits.exportsGlobalConstants = true;
LinkerInput *linkerInput;
std::vector<uint8_t> initData;
initData.resize(64, 7U);
bool constant = true;
GraphicsAllocation *alloc = nullptr;
alloc = allocateGlobalsSurface(&svmAllocsManager, device, initData.size(), constant = true, linkerInput = &linkerInputExportGlobalConstants, initData.data());
EXPECT_EQ(nullptr, alloc);
alloc = allocateGlobalsSurface(&svmAllocsManager, device, initData.size(), constant = false, linkerInput = &linkerInputExportGlobalVariables, initData.data());
EXPECT_EQ(nullptr, alloc);
}

View File

@@ -35,6 +35,7 @@
#include "runtime/helpers/queue_helpers.h"
#include "runtime/helpers/validators.h"
#include "runtime/kernel/kernel.h"
#include "runtime/kernel/kernel_info_cl.h"
#include "runtime/mem_obj/buffer.h"
#include "runtime/mem_obj/image.h"
#include "runtime/mem_obj/mem_obj_helper.h"
@@ -1576,11 +1577,6 @@ cl_kernel CL_API_CALL clCreateKernel(cl_program clProgram,
break;
}
if (pKernelInfo->isValid == false) {
retVal = CL_INVALID_PROGRAM_EXECUTABLE;
break;
}
kernel = Kernel::create(
pProgram,
*pKernelInfo,
@@ -1592,9 +1588,7 @@ cl_kernel CL_API_CALL clCreateKernel(cl_program clProgram,
if (errcodeRet) {
*errcodeRet = retVal;
}
if (kernel != nullptr) {
gtpinNotifyKernelCreate(kernel);
}
gtpinNotifyKernelCreate(kernel);
TRACING_EXIT(clCreateKernel, &kernel);
return kernel;
}
@@ -1621,17 +1615,14 @@ cl_int CL_API_CALL clCreateKernelsInProgram(cl_program clProgram,
return retVal;
}
for (unsigned int ordinal = 0; ordinal < numKernelsInProgram; ++ordinal) {
const auto kernelInfo = program->getKernelInfo(ordinal);
for (unsigned int i = 0; i < numKernelsInProgram; ++i) {
const auto kernelInfo = program->getKernelInfo(i);
DEBUG_BREAK_IF(kernelInfo == nullptr);
DEBUG_BREAK_IF(!kernelInfo->isValid);
kernels[ordinal] = Kernel::create(
kernels[i] = Kernel::create(
program,
*kernelInfo,
nullptr);
if (kernels[ordinal] != nullptr) {
gtpinNotifyKernelCreate(kernels[ordinal]);
}
gtpinNotifyKernelCreate(kernels[i]);
}
}
@@ -4367,7 +4358,7 @@ cl_int CL_API_CALL clSetKernelArgSVMPointer(cl_kernel kernel,
return retVal;
}
cl_int kernelArgAddressQualifier = pKernel->getKernelArgAddressQualifier(argIndex);
cl_int kernelArgAddressQualifier = asClKernelArgAddressQualifier(pKernel->getKernelInfo().kernelArgInfo[argIndex].metadata.addressQualifier);
if ((kernelArgAddressQualifier != CL_KERNEL_ARG_ADDRESS_GLOBAL) &&
(kernelArgAddressQualifier != CL_KERNEL_ARG_ADDRESS_CONSTANT)) {
retVal = CL_INVALID_ARG_VALUE;
@@ -5140,7 +5131,7 @@ cl_int CL_API_CALL clGetDeviceGlobalVariablePointerINTEL(
Program *pProgram = (Program *)(program);
const auto &symbols = pProgram->getSymbols();
auto symbolIt = symbols.find(globalVariableName);
if ((symbolIt == symbols.end()) || (symbolIt->second.symbol.type == NEO::SymbolInfo::Function)) {
if ((symbolIt == symbols.end()) || (symbolIt->second.symbol.segment == NEO::SegmentType::Instructions)) {
retVal = CL_INVALID_ARG_VALUE;
} else {
if (globalVariableSizeRet != nullptr) {
@@ -5172,7 +5163,7 @@ cl_int CL_API_CALL clGetDeviceFunctionPointerINTEL(
Program *pProgram = (Program *)(program);
const auto &symbols = pProgram->getSymbols();
auto symbolIt = symbols.find(functionName);
if ((symbolIt == symbols.end()) || (symbolIt->second.symbol.type != NEO::SymbolInfo::Function)) {
if ((symbolIt == symbols.end()) || (symbolIt->second.symbol.segment != NEO::SegmentType::Instructions)) {
retVal = CL_INVALID_ARG_VALUE;
} else {
*functionPointerRet = static_cast<cl_ulong>(symbolIt->second.gpuAddress);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2018-2019 Intel Corporation
* Copyright (C) 2018-2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -84,9 +84,7 @@ class BuiltinDispatchInfoBuilder {
template <typename KernelNameT, typename... KernelsDescArgsT>
void grabKernels(KernelNameT &&kernelName, Kernel *&kernelDst, KernelsDescArgsT &&... kernelsDesc) {
const KernelInfo *kernelInfo = prog->getKernelInfo(kernelName);
if (!kernelInfo) {
return;
}
UNRECOVERABLE_IF(nullptr == kernelInfo);
cl_int err = 0;
kernelDst = Kernel::create(prog.get(), *kernelInfo, &err);
kernelDst->isBuiltIn = true;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 Intel Corporation
* Copyright (C) 2019-2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -16,6 +16,7 @@
#include "patch_shared.h"
#include "program_debug_data.h"
#include <cstdint>
#include <limits>
#include <memory>

View File

@@ -9,6 +9,7 @@
#include "core/helpers/hw_info.h"
#include "runtime/compiler_interface/patchtokens_decoder.h"
#include "runtime/program/kernel_arg_info.h"
#include "igfxfmid.h"
@@ -90,6 +91,11 @@ inline ValidatorError validate(const ProgramFromPatchtokens &decodedProgram,
return ValidatorError::InvalidBinary;
}
if ((decodedProgram.header->GPUPointerSizeInBytes != 4U) && (decodedProgram.header->GPUPointerSizeInBytes != 8U)) {
outErrReason = "Invalid pointer size";
return ValidatorError::InvalidBinary;
}
if (false == isDeviceSupported(static_cast<GFXCORE_FAMILY>(decodedProgram.header->Device))) {
outErrReason = "Unsupported device binary, device GFXCORE_FAMILY : " + std::to_string(decodedProgram.header->Device);
return ValidatorError::InvalidBinary;
@@ -107,6 +113,25 @@ inline ValidatorError validate(const ProgramFromPatchtokens &decodedProgram,
return ValidatorError::InvalidBinary;
}
if (nullptr == decodedKernel.tokens.executionEnvironment) {
outErrReason = "Missing execution environment";
return ValidatorError::InvalidBinary;
} else {
switch (decodedKernel.tokens.executionEnvironment->LargestCompiledSIMDSize) {
case 1:
break;
case 8:
break;
case 16:
break;
case 32:
break;
default:
outErrReason = "Invalid LargestCompiledSIMDSize";
return ValidatorError::InvalidBinary;
}
}
if (decodedKernel.tokens.allocateLocalSurface) {
if (sharedLocalMemorySize < decodedKernel.tokens.allocateLocalSurface->TotalInlineLocalMemorySize) {
outErrReason = "KernelFromPatchtokens requires too much SLM";
@@ -114,6 +139,24 @@ inline ValidatorError validate(const ProgramFromPatchtokens &decodedProgram,
}
}
for (auto &kernelArg : decodedKernel.tokens.kernelArgs) {
if (kernelArg.argInfo == nullptr) {
outErrReason = "Missing kernelArgInfo";
return ValidatorError::InvalidBinary;
}
auto argInfoInlineData = getInlineData(kernelArg.argInfo);
auto accessQualifier = KernelArgMetadata::parseAccessQualifier(parseLimitedString(argInfoInlineData.accessQualifier.begin(), argInfoInlineData.accessQualifier.size()));
if (KernelArgMetadata::AccessQualifier::Unknown == accessQualifier) {
outErrReason = "Unhandled access qualifier";
return ValidatorError::InvalidBinary;
}
auto addressQualifier = KernelArgMetadata::parseAddressSpace(parseLimitedString(argInfoInlineData.addressQualifier.begin(), argInfoInlineData.addressQualifier.size()));
if (KernelArgMetadata::AddressSpaceQualifier::Unknown == addressQualifier) {
outErrReason = "Unhandled address qualifier";
return ValidatorError::InvalidBinary;
}
}
for (const auto &unhandledToken : decodedKernel.unhandledTokens) {
if (false == tokenValidator.isSafeToSkipUnhandledToken(unhandledToken->Token)) {
outErrReason = "Unhandled required kernel-scope Patch Token : " + std::to_string(unhandledToken->Token);

View File

@@ -58,6 +58,9 @@ void gtpinNotifyContextDestroy(cl_context context) {
}
void gtpinNotifyKernelCreate(cl_kernel kernel) {
if (nullptr == kernel) {
return;
}
if (isGTPinInitialized) {
auto pKernel = castToObjectOrAbort<Kernel>(kernel);
size_t gtpinBTI = pKernel->getNumberOfBindingTableStates();

View File

@@ -14,6 +14,7 @@ set(RUNTIME_SRCS_KERNEL
${CMAKE_CURRENT_SOURCE_DIR}/kernel.h
${CMAKE_CURRENT_SOURCE_DIR}/kernel.inl
${CMAKE_CURRENT_SOURCE_DIR}/kernel_execution_type.h
${CMAKE_CURRENT_SOURCE_DIR}/kernel_info_cl.h
${CMAKE_CURRENT_SOURCE_DIR}${BRANCH_DIR_SUFFIX}/kernel_extra.cpp
)
target_sources(${NEO_STATIC_LIB_NAME} PRIVATE ${RUNTIME_SRCS_KERNEL})

View File

@@ -34,6 +34,7 @@
#include "runtime/helpers/surface_formats.h"
#include "runtime/kernel/image_transformer.h"
#include "runtime/kernel/kernel.inl"
#include "runtime/kernel/kernel_info_cl.h"
#include "runtime/mem_obj/buffer.h"
#include "runtime/mem_obj/image.h"
#include "runtime/mem_obj/pipe.h"
@@ -337,22 +338,20 @@ cl_int Kernel::initialize() {
// set the argument handler
auto &argInfo = kernelInfo.kernelArgInfo[i];
if (argInfo.addressQualifier == CL_KERNEL_ARG_ADDRESS_LOCAL) {
if (argInfo.metadata.addressQualifier == KernelArgMetadata::AddressSpaceQualifier::Local) {
kernelArgHandlers[i] = &Kernel::setArgLocal;
} else if (argInfo.isAccelerator) {
kernelArgHandlers[i] = &Kernel::setArgAccelerator;
} else if (argInfo.typeQualifierStr.find("pipe") != std::string::npos) {
} else if (argInfo.metadata.typeQualifiers.pipeQual) {
kernelArgHandlers[i] = &Kernel::setArgPipe;
kernelArguments[i].type = PIPE_OBJ;
} else if (argInfo.isImage) {
kernelArgHandlers[i] = &Kernel::setArgImage;
kernelArguments[i].type = IMAGE_OBJ;
usingImages = true;
DEBUG_BREAK_IF(argInfo.typeStr.find("image") == std::string::npos);
} else if (argInfo.isSampler) {
kernelArgHandlers[i] = &Kernel::setArgSampler;
kernelArguments[i].type = SAMPLER_OBJ;
DEBUG_BREAK_IF(!(*argInfo.typeStr.c_str() == '\0' || argInfo.typeStr.find("sampler") != std::string::npos));
} else if (argInfo.isBuffer) {
kernelArgHandlers[i] = &Kernel::setArgBuffer;
kernelArguments[i].type = BUFFER_OBJ;
@@ -506,37 +505,44 @@ cl_int Kernel::getArgInfo(cl_uint argIndx, cl_kernel_arg_info paramName, size_t
const void *pSrc = nullptr;
size_t srcSize = 0;
auto numArgs = (cl_uint)kernelInfo.kernelArgInfo.size();
auto argInfoIdx = kernelInfo.kernelArgInfo[argIndx];
const auto &argInfo = kernelInfo.kernelArgInfo[argIndx];
if (argIndx >= numArgs) {
retVal = CL_INVALID_ARG_INDEX;
return retVal;
}
cl_kernel_arg_address_qualifier addressQualifier;
cl_kernel_arg_access_qualifier accessQualifier;
cl_kernel_arg_type_qualifier typeQualifier;
switch (paramName) {
case CL_KERNEL_ARG_ADDRESS_QUALIFIER:
srcSize = sizeof(cl_uint);
pSrc = &argInfoIdx.addressQualifier;
addressQualifier = asClKernelArgAddressQualifier(argInfo.metadata.addressQualifier);
srcSize = sizeof(addressQualifier);
pSrc = &addressQualifier;
break;
case CL_KERNEL_ARG_ACCESS_QUALIFIER:
srcSize = sizeof(cl_uint);
pSrc = &argInfoIdx.accessQualifier;
break;
case CL_KERNEL_ARG_TYPE_NAME:
srcSize = argInfoIdx.typeStr.length() + 1;
pSrc = argInfoIdx.typeStr.c_str();
accessQualifier = asClKernelArgAccessQualifier(argInfo.metadata.accessQualifier);
srcSize = sizeof(accessQualifier);
pSrc = &accessQualifier;
break;
case CL_KERNEL_ARG_TYPE_QUALIFIER:
srcSize = sizeof(argInfoIdx.typeQualifier);
pSrc = &argInfoIdx.typeQualifier;
typeQualifier = asClKernelArgTypeQualifier(argInfo.metadata.typeQualifiers);
srcSize = sizeof(typeQualifier);
pSrc = &typeQualifier;
break;
case CL_KERNEL_ARG_TYPE_NAME:
srcSize = argInfo.metadataExtended->type.length() + 1;
pSrc = argInfo.metadataExtended->type.c_str();
break;
case CL_KERNEL_ARG_NAME:
srcSize = argInfoIdx.name.length() + 1;
pSrc = argInfoIdx.name.c_str();
srcSize = argInfo.metadataExtended->argName.length() + 1;
pSrc = argInfo.metadataExtended->argName.c_str();
break;
default:
@@ -2290,10 +2296,10 @@ cl_int Kernel::checkCorrectImageAccessQualifier(cl_uint argIndex,
MemObj *pMemObj = nullptr;
WithCastToInternal(mem, &pMemObj);
if (pMemObj) {
cl_kernel_arg_access_qualifier accessQualifier = getKernelInfo().kernelArgInfo[argIndex].accessQualifier;
auto accessQualifier = getKernelInfo().kernelArgInfo[argIndex].metadata.accessQualifier;
cl_mem_flags flags = pMemObj->getMemoryPropertiesFlags();
if ((accessQualifier == CL_KERNEL_ARG_ACCESS_READ_ONLY && ((flags | CL_MEM_WRITE_ONLY) == flags)) ||
(accessQualifier == CL_KERNEL_ARG_ACCESS_WRITE_ONLY && ((flags | CL_MEM_READ_ONLY) == flags))) {
if ((accessQualifier == KernelArgMetadata::AccessQualifier::ReadOnly && ((flags | CL_MEM_WRITE_ONLY) == flags)) ||
(accessQualifier == KernelArgMetadata::AccessQualifier::WriteOnly && ((flags | CL_MEM_READ_ONLY) == flags))) {
return CL_INVALID_ARG_VALUE;
}
} else {
@@ -2341,7 +2347,7 @@ void Kernel::fillWithBuffersForAuxTranslation(MemObjsForAuxTranslation &memObjsF
auto &context = this->program->getContext();
if (context.isProvidingPerformanceHints()) {
context.providePerformanceHint(CL_CONTEXT_DIAGNOSTICS_LEVEL_BAD_INTEL, KERNEL_ARGUMENT_AUX_TRANSLATION,
kernelInfo.name.c_str(), i, kernelInfo.kernelArgInfo.at(i).name.c_str());
kernelInfo.name.c_str(), i, kernelInfo.kernelArgInfo.at(i).metadataExtended->argName.c_str());
}
}
}

View File

@@ -72,15 +72,12 @@ class Kernel : public BaseObject<_cl_kernel> {
const void *argVal);
template <typename kernel_t = Kernel, typename program_t = Program>
static kernel_t *create(Program *program, const KernelInfo &kernelInfo, cl_int *errcodeRet) {
static kernel_t *create(program_t *program, const KernelInfo &kernelInfo, cl_int *errcodeRet) {
cl_int retVal;
kernel_t *pKernel = nullptr;
do {
// copy the kernel data into our new allocation
pKernel = new kernel_t(program, kernelInfo, program->getDevice(0));
retVal = pKernel->initialize();
} while (false);
pKernel = new kernel_t(program, kernelInfo, program->getDevice(0));
retVal = pKernel->initialize();
if (retVal != CL_SUCCESS) {
delete pKernel;
@@ -179,10 +176,6 @@ class Kernel : public BaseObject<_cl_kernel> {
return kernelInfo.kernelArgInfo.size();
}
uint32_t getKernelArgAddressQualifier(uint32_t argIndex) const {
return kernelInfo.kernelArgInfo[argIndex].addressQualifier;
}
bool requiresSshForBuffers() const {
return kernelInfo.requiresSshForBuffers;
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright (C) 2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "runtime/program/kernel_arg_info.h"
#include "CL/cl.h"
namespace NEO {
constexpr cl_kernel_arg_access_qualifier asClKernelArgAccessQualifier(KernelArgMetadata::AccessQualifier accessQualifier) {
using namespace KernelArgMetadata;
switch (accessQualifier) {
default:
return 0U;
case AccessQualifier::None:
return CL_KERNEL_ARG_ACCESS_NONE;
case AccessQualifier::ReadOnly:
return CL_KERNEL_ARG_ACCESS_READ_ONLY;
case AccessQualifier::WriteOnly:
return CL_KERNEL_ARG_ACCESS_WRITE_ONLY;
case AccessQualifier::ReadWrite:
return CL_KERNEL_ARG_ACCESS_READ_WRITE;
}
}
constexpr cl_kernel_arg_address_qualifier asClKernelArgAddressQualifier(KernelArgMetadata::AddressSpaceQualifier addressQualifier) {
using namespace KernelArgMetadata;
switch (addressQualifier) {
default:
return 0U;
case AddressSpaceQualifier::Global:
return CL_KERNEL_ARG_ADDRESS_GLOBAL;
case AddressSpaceQualifier::Local:
return CL_KERNEL_ARG_ADDRESS_LOCAL;
case AddressSpaceQualifier::Private:
return CL_KERNEL_ARG_ADDRESS_PRIVATE;
case AddressSpaceQualifier::Constant:
return CL_KERNEL_ARG_ADDRESS_CONSTANT;
}
}
constexpr cl_kernel_arg_type_qualifier asClKernelArgTypeQualifier(KernelArgMetadata::TypeQualifiers typeQualifiers) {
using namespace KernelArgMetadata;
cl_kernel_arg_type_qualifier ret = 0U;
ret |= (typeQualifiers.constQual) ? CL_KERNEL_ARG_TYPE_CONST : 0U;
ret |= (typeQualifiers.volatileQual) ? CL_KERNEL_ARG_TYPE_VOLATILE : 0U;
ret |= (typeQualifiers.restrictQual) ? CL_KERNEL_ARG_TYPE_RESTRICT : 0U;
ret |= (typeQualifiers.pipeQual) ? CL_KERNEL_ARG_TYPE_PIPE : 0U;
return ret;
}
} // namespace NEO

View File

@@ -11,6 +11,7 @@
#include "runtime/device/device.h"
#include "runtime/helpers/base_object.h"
#include "runtime/helpers/validators.h"
#include "runtime/program/kernel_info.h"
#include "program.h"
@@ -56,7 +57,7 @@ cl_int Program::getInfo(cl_program_info paramName, size_t paramValueSize,
break;
case CL_PROGRAM_KERNEL_NAMES:
kernelNamesString = getKernelNamesString();
kernelNamesString = concatenateKernelNames(kernelInfoArray);
pSrc = kernelNamesString.c_str();
retSize = srcSize = kernelNamesString.length() + 1;

View File

@@ -1,16 +1,186 @@
/*
* Copyright (C) 2017-2019 Intel Corporation
* Copyright (C) 2017-2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "CL/cl.h"
#include "core/compiler_interface/compiler_options/compiler_options_base.h"
#include "core/utilities/const_stringref.h"
#include <cstdint>
#include <cstring>
#include <memory>
#include <string>
namespace NEO {
namespace KernelArgMetadata {
enum class AccessQualifier : uint8_t {
Unknown,
None,
ReadOnly,
WriteOnly,
ReadWrite,
};
namespace AccessQualifierStrings {
constexpr ConstStringRef none = "NONE";
constexpr ConstStringRef readOnly = "read_only";
constexpr ConstStringRef writeOnly = "write_only";
constexpr ConstStringRef readWrite = "read_write";
constexpr ConstStringRef underscoreReadOnly = "__read_only";
constexpr ConstStringRef underscoreWriteOnly = "__write_only";
constexpr ConstStringRef underscoreReadWrite = "__read_write";
} // namespace AccessQualifierStrings
enum class AddressSpaceQualifier : uint8_t {
Unknown,
Global,
Local,
Private,
Constant
};
namespace AddressSpaceQualifierStrings {
constexpr ConstStringRef addrGlobal = "__global";
constexpr ConstStringRef addrLocal = "__local";
constexpr ConstStringRef addrPrivate = "__private";
constexpr ConstStringRef addrConstant = "__constant";
constexpr ConstStringRef addrNotSpecified = "not_specified";
} // namespace AddressSpaceQualifierStrings
constexpr AccessQualifier parseAccessQualifier(ConstStringRef str) {
using namespace AccessQualifierStrings;
if (str.empty() || (none == str)) {
return AccessQualifier::None;
}
if (str.length() < 3) {
return AccessQualifier::Unknown;
}
ConstStringRef strNoUnderscore = ('_' == str[0]) ? ConstStringRef(str.data() + 2, str.length() - 2) : str;
static_assert(writeOnly[0] != readOnly[0], "");
static_assert(writeOnly[0] != readWrite[0], "");
if (strNoUnderscore[0] == writeOnly[0]) {
return (writeOnly == strNoUnderscore) ? AccessQualifier::WriteOnly : AccessQualifier::Unknown;
}
if (readOnly == strNoUnderscore) {
return AccessQualifier::ReadOnly;
}
return (readWrite == strNoUnderscore) ? AccessQualifier::ReadWrite : AccessQualifier::Unknown;
}
constexpr AddressSpaceQualifier parseAddressSpace(ConstStringRef str) {
using namespace AddressSpaceQualifierStrings;
if (str.empty()) {
return AddressSpaceQualifier::Global;
}
if (str.length() < 3) {
return AddressSpaceQualifier::Unknown;
}
switch (str[2]) {
default:
return AddressSpaceQualifier::Unknown;
case addrNotSpecified[2]:
return (str == addrNotSpecified) ? AddressSpaceQualifier::Private : AddressSpaceQualifier::Unknown;
case addrGlobal[2]:
return (str == addrGlobal) ? AddressSpaceQualifier::Global : AddressSpaceQualifier::Unknown;
case addrLocal[2]:
return (str == addrLocal) ? AddressSpaceQualifier::Local : AddressSpaceQualifier::Unknown;
case addrPrivate[2]:
return (str == addrPrivate) ? AddressSpaceQualifier::Private : AddressSpaceQualifier::Unknown;
case addrConstant[2]:
return (str == addrConstant) ? AddressSpaceQualifier::Constant : AddressSpaceQualifier::Unknown;
}
}
union TypeQualifiers {
uint8_t packed = 0U;
struct {
bool constQual : 1;
bool volatileQual : 1;
bool restrictQual : 1;
bool pipeQual : 1;
bool unknownQual : 1;
};
bool empty() const {
return 0U == packed;
}
};
namespace TypeQualifierStrings {
constexpr ConstStringRef qualConst = "const";
constexpr ConstStringRef qualVolatile = "volatile";
constexpr ConstStringRef qualRestrict = "restrict";
constexpr ConstStringRef qualPipe = "pipe";
} // namespace TypeQualifierStrings
inline TypeQualifiers parseTypeQualifiers(ConstStringRef str) {
using namespace TypeQualifierStrings;
TypeQualifiers ret = {};
auto tokenized = CompilerOptions::tokenize(str);
for (const auto &tok : tokenized) {
bool knownQualifier = true;
switch (tok[0]) {
default:
knownQualifier = false;
break;
case qualConst[0]:
knownQualifier = (qualConst == tok);
ret.constQual |= knownQualifier;
break;
case qualVolatile[0]:
knownQualifier = (qualVolatile == tok);
ret.volatileQual |= knownQualifier;
break;
case qualRestrict[0]:
knownQualifier = (qualRestrict == tok);
ret.restrictQual |= knownQualifier;
break;
case qualPipe[0]:
knownQualifier = (qualPipe == tok);
ret.pipeQual |= knownQualifier;
break;
}
ret.unknownQual |= !knownQualifier;
}
return ret;
}
} // namespace KernelArgMetadata
inline std::string parseLimitedString(const char *str, size_t maxSize) {
std::string ret{str, str + maxSize};
size_t minSize = strlen(ret.c_str());
ret.assign(str, minSize);
return ret;
}
struct ArgTypeMetadata {
uint32_t argByValSize = 0U;
KernelArgMetadata::AccessQualifier accessQualifier = {};
KernelArgMetadata::AddressSpaceQualifier addressQualifier = {};
KernelArgMetadata::TypeQualifiers typeQualifiers = {};
};
static_assert(sizeof(ArgTypeMetadata) <= 8, "");
struct ArgTypeMetadataExtended {
std::string argName;
std::string type;
std::string accessQualifier;
std::string addressQualifier;
std::string typeQualifiers;
};
struct KernelArgPatchInfo {
uint32_t crossthreadOffset = 0;
uint32_t size = 0;
@@ -18,15 +188,18 @@ struct KernelArgPatchInfo {
};
struct KernelArgInfo {
KernelArgInfo() = default;
~KernelArgInfo() = default;
KernelArgInfo(const KernelArgInfo &rhs) = delete;
KernelArgInfo &operator=(const KernelArgInfo &) = delete;
KernelArgInfo(KernelArgInfo &&) = default;
KernelArgInfo &operator=(KernelArgInfo &&) = default;
static constexpr uint32_t undefinedOffset = (uint32_t)-1;
std::string name;
std::string typeStr;
std::string accessQualifierStr;
std::string addressQualifierStr;
std::string typeQualifierStr;
uint32_t offsetHeap = 0;
std::vector<KernelArgPatchInfo> kernelArgPatchInfoVector;
ArgTypeMetadata metadata;
std::unique_ptr<ArgTypeMetadataExtended> metadataExtended;
uint32_t slmAlignment = 0;
bool isImage = false;
bool isMediaImage = false;
@@ -37,6 +210,11 @@ struct KernelArgInfo {
bool isBuffer = false;
bool pureStatefulBufferAccess = false;
bool isReadOnly = false;
bool needPatch = false;
bool isTransformable = false;
uint32_t offsetHeap = 0;
std::vector<KernelArgPatchInfo> kernelArgPatchInfoVector;
uint32_t samplerArgumentType = 0;
uint32_t offsetImgWidth = undefinedOffset;
uint32_t offsetImgHeight = undefinedOffset;
@@ -59,13 +237,6 @@ struct KernelArgInfo {
uint32_t offsetFlatWidth = undefinedOffset;
uint32_t offsetFlatHeight = undefinedOffset;
uint32_t offsetFlatPitch = undefinedOffset;
bool needPatch = false;
bool isTransformable = false;
cl_kernel_arg_access_qualifier accessQualifier = CL_KERNEL_ARG_ACCESS_NONE;
cl_kernel_arg_address_qualifier addressQualifier = CL_KERNEL_ARG_ADDRESS_GLOBAL;
cl_kernel_arg_type_qualifier typeQualifier = CL_KERNEL_ARG_TYPE_NONE;
KernelArgInfo() = default;
};
} // namespace NEO

View File

@@ -26,41 +26,11 @@
namespace NEO {
const uint32_t WorkloadInfo::undefinedOffset = (uint32_t)-1;
const uint32_t WorkloadInfo::invalidParentEvent = (uint32_t)-1;
std::unordered_map<std::string, uint32_t> accessQualifierMap = {
{"", CL_KERNEL_ARG_ACCESS_NONE},
{"NONE", CL_KERNEL_ARG_ACCESS_NONE},
{"read_only", CL_KERNEL_ARG_ACCESS_READ_ONLY},
{"__read_only", CL_KERNEL_ARG_ACCESS_READ_ONLY},
{"write_only", CL_KERNEL_ARG_ACCESS_WRITE_ONLY},
{"__write_only", CL_KERNEL_ARG_ACCESS_WRITE_ONLY},
{"read_write", CL_KERNEL_ARG_ACCESS_READ_WRITE},
{"__read_write", CL_KERNEL_ARG_ACCESS_READ_WRITE},
};
std::unordered_map<std::string, uint32_t> addressQualifierMap = {
{"", CL_KERNEL_ARG_ADDRESS_GLOBAL},
{"__global", CL_KERNEL_ARG_ADDRESS_GLOBAL},
{"__local", CL_KERNEL_ARG_ADDRESS_LOCAL},
{"__private", CL_KERNEL_ARG_ADDRESS_PRIVATE},
{"__constant", CL_KERNEL_ARG_ADDRESS_CONSTANT},
{"not_specified", CL_KERNEL_ARG_ADDRESS_PRIVATE},
};
struct KernelArgumentType {
const char *argTypeQualifier;
uint64_t argTypeQualifierValue;
};
constexpr KernelArgumentType typeQualifiers[] = {
{"const", CL_KERNEL_ARG_TYPE_CONST},
{"volatile", CL_KERNEL_ARG_TYPE_VOLATILE},
{"restrict", CL_KERNEL_ARG_TYPE_RESTRICT},
{"pipe", CL_KERNEL_ARG_TYPE_PIPE},
};
std::map<std::string, size_t> typeSizeMap = {
{"char", sizeof(cl_char)},
{"char2", sizeof(cl_char2)},
@@ -235,26 +205,12 @@ void KernelInfo::storePatchToken(const SPatchExecutionEnvironment *execEnv) {
}
}
void KernelInfo::storeArgInfo(const SPatchKernelArgumentInfo *pkernelArgInfo) {
if (pkernelArgInfo == nullptr) {
return;
}
uint32_t argNum = pkernelArgInfo->ArgumentNumber;
void KernelInfo::storeArgInfo(uint32_t argNum, ArgTypeMetadata metadata, std::unique_ptr<ArgTypeMetadataExtended> metadataExtended) {
resizeKernelArgInfoAndRegisterParameter(argNum);
auto inlineData = PatchTokenBinary::getInlineData(pkernelArgInfo);
kernelArgInfo[argNum].addressQualifierStr = std::string(inlineData.addressQualifier.begin(), inlineData.addressQualifier.end()).c_str();
kernelArgInfo[argNum].accessQualifierStr = std::string(inlineData.accessQualifier.begin(), inlineData.accessQualifier.end()).c_str();
kernelArgInfo[argNum].name = std::string(inlineData.argName.begin(), inlineData.argName.end()).c_str();
auto argTypeDelim = strchr(inlineData.typeName.begin(), ';');
DEBUG_BREAK_IF(argTypeDelim == nullptr);
kernelArgInfo[argNum].typeStr = std::string(inlineData.typeName.begin(), ptrDiff(argTypeDelim, inlineData.typeName.begin())).c_str();
kernelArgInfo[argNum].typeQualifierStr = std::string(inlineData.typeQualifiers.begin(), inlineData.typeQualifiers.end()).c_str();
patchInfo.kernelArgumentInfo.push_back(pkernelArgInfo);
auto &argInfo = kernelArgInfo[argNum];
argInfo.metadata = metadata;
argInfo.metadataExtended = std::move(metadataExtended);
argInfo.isReadOnly |= argInfo.metadata.typeQualifiers.constQual;
}
void KernelInfo::storeKernelArgument(
@@ -295,9 +251,11 @@ void KernelInfo::storeKernelArgument(
kernelArgInfo[argNum].isMediaBlockImage = true;
}
kernelArgInfo[argNum].accessQualifier = pImageMemObjKernelArg->Writeable
? CL_KERNEL_ARG_ACCESS_READ_WRITE
: CL_KERNEL_ARG_ACCESS_READ_ONLY;
kernelArgInfo[argNum].metadata.accessQualifier = pImageMemObjKernelArg->Writeable
? KernelArgMetadata::AccessQualifier::ReadWrite
: KernelArgMetadata::AccessQualifier::ReadOnly;
kernelArgInfo[argNum].metadata.argByValSize = sizeof(cl_mem);
kernelArgInfo[argNum].isTransformable = pImageMemObjKernelArg->Transformable != 0;
patchInfo.imageMemObjKernelArgs.push_back(pImageMemObjKernelArg);
@@ -311,8 +269,6 @@ void KernelInfo::storeKernelArgument(
usesSsh |= true;
storeKernelArgPatchInfo(argNum, 0, 0, 0, offsetSurfaceState);
kernelArgInfo[argNum].isBuffer = true;
patchInfo.globalMemObjKernelArgs.push_back(pGlobalMemObjKernelArg);
}
void KernelInfo::storeKernelArgument(
@@ -417,43 +373,6 @@ void KernelInfo::storePatchToken(const SPatchAllocateSyncBuffer *pAllocateSyncBu
patchInfo.pAllocateSyncBuffer = pAllocateSyncBuffer;
}
cl_int KernelInfo::resolveKernelInfo() {
cl_int retVal = CL_SUCCESS;
std::unordered_map<std::string, uint32_t>::iterator iterUint;
std::unordered_map<std::string, size_t>::iterator iterSizeT;
for (auto &argInfo : kernelArgInfo) {
iterUint = accessQualifierMap.find(argInfo.accessQualifierStr);
if (iterUint != accessQualifierMap.end()) {
argInfo.accessQualifier = iterUint->second;
} else {
retVal = CL_INVALID_BINARY;
break;
}
iterUint = addressQualifierMap.find(argInfo.addressQualifierStr);
if (iterUint != addressQualifierMap.end()) {
argInfo.addressQualifier = iterUint->second;
} else {
retVal = CL_INVALID_BINARY;
break;
}
auto qualifierCount = sizeof(typeQualifiers) / sizeof(typeQualifiers[0]);
for (auto qualifierId = 0u; qualifierId < qualifierCount; qualifierId++) {
if (strstr(argInfo.typeQualifierStr.c_str(), typeQualifiers[qualifierId].argTypeQualifier) != nullptr) {
argInfo.typeQualifier |= typeQualifiers[qualifierId].argTypeQualifierValue;
if (argInfo.typeQualifier == CL_KERNEL_ARG_TYPE_CONST) {
argInfo.isReadOnly = true;
}
}
}
}
return retVal;
}
void KernelInfo::storeKernelArgPatchInfo(uint32_t argNum, uint32_t dataSize, uint32_t dataOffset, uint32_t sourceOffset, uint32_t offsetSSH) {
resizeKernelArgInfoAndRegisterParameter(argNum);
@@ -505,4 +424,17 @@ bool KernelInfo::createKernelAllocation(uint32_t rootDeviceIndex, MemoryManager
return memoryManager->copyMemoryToAllocation(kernelAllocation, heapInfo.pKernelHeap, kernelIsaSize);
}
std::string concatenateKernelNames(ArrayRef<KernelInfo *> kernelInfos) {
std::string semiColonDelimitedKernelNameStr;
for (const auto &kernelInfo : kernelInfos) {
if (!semiColonDelimitedKernelNameStr.empty()) {
semiColonDelimitedKernelNameStr += ';';
}
semiColonDelimitedKernelNameStr += kernelInfo->name;
}
return semiColonDelimitedKernelNameStr;
}
} // namespace NEO

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017-2019 Intel Corporation
* Copyright (C) 2017-2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -7,11 +7,11 @@
#pragma once
#include "core/helpers/hw_info.h"
#include "core/utilities/arrayref.h"
#include "core/utilities/const_stringref.h"
#include "runtime/program/heap_info.h"
#include "runtime/program/kernel_arg_info.h"
#include "CL/cl.h"
#include "ocl_igc_shared/gtpin/gtpin_driver_common.h"
#include "patch_info.h"
#include <algorithm>
@@ -23,6 +23,10 @@
#include <unordered_map>
#include <vector>
namespace gtpin {
typedef struct igc_info_s igc_info_t;
}
namespace NEO {
class BuiltinDispatchInfoBuilder;
class Device;
@@ -33,13 +37,11 @@ struct KernelArgumentType;
class GraphicsAllocation;
class MemoryManager;
extern std::unordered_map<std::string, uint32_t> accessQualifierMap;
extern std::unordered_map<std::string, uint32_t> addressQualifierMap;
extern std::map<std::string, size_t> typeSizeMap;
struct WorkloadInfo {
static const uint32_t undefinedOffset;
static const uint32_t invalidParentEvent;
enum : uint32_t { undefinedOffset = std::numeric_limits<uint32_t>::max() };
enum : uint32_t { invalidParentEvent = std::numeric_limits<uint32_t>::max() };
uint32_t globalWorkOffsetOffsets[3] = {undefinedOffset, undefinedOffset, undefinedOffset};
uint32_t globalWorkSizeOffsets[3] = {undefinedOffset, undefinedOffset, undefinedOffset};
@@ -90,6 +92,13 @@ struct DebugData {
const char *genIsa = nullptr;
};
struct DeviceInfoKernelPayloadConstants {
void *slmWindow = nullptr;
uint32_t slmWindowSize = 0U;
uint32_t computeUnitsUsedForScratch = 0U;
uint32_t maxWorkGroupSize = 0U;
};
struct KernelInfo {
public:
KernelInfo() = default;
@@ -97,7 +106,7 @@ struct KernelInfo {
KernelInfo &operator=(const KernelInfo &) = delete;
~KernelInfo();
void storeArgInfo(const SPatchKernelArgumentInfo *pkernelArgInfo);
void storeArgInfo(uint32_t argNum, ArgTypeMetadata metadata, std::unique_ptr<ArgTypeMetadataExtended> metadataExtended);
void storeKernelArgument(const SPatchDataParameterBuffer *pDataParameterKernelArg);
void storeKernelArgument(const SPatchStatelessGlobalMemoryObjectKernelArgument *pStatelessGlobalKernelArg);
void storeKernelArgument(const SPatchImageMemoryObjectKernelArgument *pImageMemObjKernelArg);
@@ -117,7 +126,6 @@ struct KernelInfo {
void storePatchToken(const SPatchAllocateSystemThreadSurface *pSystemThreadSurface);
void storePatchToken(const SPatchAllocateSyncBuffer *pAllocateSyncBuffer);
GraphicsAllocation *getGraphicsAllocation() const { return this->kernelAllocation; }
cl_int resolveKernelInfo();
void resizeKernelArgInfoAndRegisterParameter(uint32_t argCount) {
if (kernelArgInfo.size() <= argCount) {
kernelArgInfo.resize(argCount + 1);
@@ -171,7 +179,7 @@ struct KernelInfo {
int32_t getArgNumByName(const char *name) const {
int32_t argNum = 0;
for (auto &arg : kernelArgInfo) {
if (arg.name == name) {
if (arg.metadataExtended && (arg.metadataExtended->argName == name)) {
return argNum;
}
++argNum;
@@ -191,7 +199,6 @@ struct KernelInfo {
std::vector<std::pair<uint32_t, uint32_t>> childrenKernelsIdOffset;
bool usesSsh = false;
bool requiresSshForBuffers = false;
bool isValid = false;
bool isVmeWorkload = false;
char *crossThreadData = nullptr;
size_t reqdWorkGroupSize[3] = {WorkloadInfo::undefinedOffset, WorkloadInfo::undefinedOffset, WorkloadInfo::undefinedOffset};
@@ -210,4 +217,7 @@ struct KernelInfo {
bool computeMode = false;
const gtpin::igc_info_t *igcInfoForGtpin = nullptr;
};
std::string concatenateKernelNames(ArrayRef<KernelInfo *> kernelInfos);
} // namespace NEO

View File

@@ -10,6 +10,8 @@
#include "runtime/compiler_interface/patchtokens_decoder.h"
#include "runtime/program/kernel_info.h"
#include <cstring>
namespace NEO {
using namespace iOpenCL;
@@ -29,14 +31,42 @@ inline uint32_t getOffset(T *token) {
return WorkloadInfo::undefinedOffset;
}
void populateKernelInfoArgMetadata(KernelInfo &dstKernelInfoArg, const SPatchKernelArgumentInfo *src) {
if (nullptr == src) {
return;
}
uint32_t argNum = src->ArgumentNumber;
auto inlineData = PatchTokenBinary::getInlineData(src);
auto metadataExtended = std::make_unique<ArgTypeMetadataExtended>();
metadataExtended->addressQualifier = parseLimitedString(inlineData.addressQualifier.begin(), inlineData.addressQualifier.size());
metadataExtended->accessQualifier = parseLimitedString(inlineData.accessQualifier.begin(), inlineData.accessQualifier.size());
metadataExtended->argName = parseLimitedString(inlineData.argName.begin(), inlineData.argName.size());
auto argTypeFull = parseLimitedString(inlineData.typeName.begin(), inlineData.typeName.size());
const char *argTypeDelim = strchr(argTypeFull.data(), ';');
if (nullptr == argTypeDelim) {
argTypeDelim = argTypeFull.data() + argTypeFull.size();
}
metadataExtended->type = std::string(argTypeFull.data(), argTypeDelim).c_str();
metadataExtended->typeQualifiers = parseLimitedString(inlineData.typeQualifiers.begin(), inlineData.typeQualifiers.size());
ArgTypeMetadata metadata = {};
metadata.accessQualifier = KernelArgMetadata::parseAccessQualifier(metadataExtended->accessQualifier);
metadata.addressQualifier = KernelArgMetadata::parseAddressSpace(metadataExtended->addressQualifier);
metadata.typeQualifiers = KernelArgMetadata::parseTypeQualifiers(metadataExtended->typeQualifiers);
dstKernelInfoArg.storeArgInfo(argNum, metadata, std::move(metadataExtended));
}
void populateKernelInfoArg(KernelInfo &dstKernelInfo, KernelArgInfo &dstKernelInfoArg, const PatchTokenBinary::KernelArgFromPatchtokens &src) {
dstKernelInfoArg.needPatch = true;
dstKernelInfo.storeArgInfo(src.argInfo);
populateKernelInfoArgMetadata(dstKernelInfo, src.argInfo);
if (src.objectArg != nullptr) {
switch (src.objectArg->Token) {
default:
UNRECOVERABLE_IF(true);
case PATCH_TOKEN_IMAGE_MEMORY_OBJECT_KERNEL_ARGUMENT:
UNRECOVERABLE_IF(PATCH_TOKEN_IMAGE_MEMORY_OBJECT_KERNEL_ARGUMENT != src.objectArg->Token);
dstKernelInfo.storeKernelArgument(reinterpret_cast<const SPatchImageMemoryObjectKernelArgument *>(src.objectArg));
break;
case PATCH_TOKEN_SAMPLER_KERNEL_ARGUMENT:
@@ -111,7 +141,9 @@ void populateKernelInfoArg(KernelInfo &dstKernelInfo, KernelArgInfo &dstKernelIn
dstKernelInfoArg.offsetObjectId = getOffset(src.objectId);
}
void populateKernelInfo(KernelInfo &dst, const PatchTokenBinary::KernelFromPatchtokens &src) {
void populateKernelInfo(KernelInfo &dst, const PatchTokenBinary::KernelFromPatchtokens &src, uint32_t gpuPointerSizeInBytes,
const DeviceInfoKernelPayloadConstants &constants) {
UNRECOVERABLE_IF(nullptr == src.header);
dst.heapInfo.pKernelHeader = src.header;
dst.name = std::string(src.name.begin(), src.name.end()).c_str();
dst.heapInfo.pKernelHeap = src.isa.begin();
@@ -132,9 +164,7 @@ void populateKernelInfo(KernelInfo &dst, const PatchTokenBinary::KernelFromPatch
dst.patchInfo.threadPayload = src.tokens.threadPayload;
dst.patchInfo.dataParameterStream = src.tokens.dataParameterStream;
dst.patchInfo.kernelArgumentInfo.reserve(src.tokens.kernelArgs.size());
dst.kernelArgInfo.resize(src.tokens.kernelArgs.size());
dst.argumentsToPatchNum = static_cast<uint32_t>(src.tokens.kernelArgs.size());
for (size_t i = 0U; i < src.tokens.kernelArgs.size(); ++i) {
auto &decodedKernelArg = src.tokens.kernelArgs[i];
@@ -184,7 +214,38 @@ void populateKernelInfo(KernelInfo &dst, const PatchTokenBinary::KernelFromPatch
dst.igcInfoForGtpin = reinterpret_cast<const gtpin::igc_info_t *>(src.tokens.gtpinInfo + 1);
}
dst.isValid = (false == NEO::PatchTokenBinary::hasInvalidChecksum(src));
dst.gpuPointerSize = gpuPointerSizeInBytes;
if (dst.patchInfo.dataParameterStream && dst.patchInfo.dataParameterStream->DataParameterStreamSize) {
uint32_t crossThreadDataSize = dst.patchInfo.dataParameterStream->DataParameterStreamSize;
dst.crossThreadData = new char[crossThreadDataSize];
memset(dst.crossThreadData, 0x00, crossThreadDataSize);
uint32_t privateMemoryStatelessSizeOffset = dst.workloadInfo.privateMemoryStatelessSizeOffset;
uint32_t localMemoryStatelessWindowSizeOffset = dst.workloadInfo.localMemoryStatelessWindowSizeOffset;
uint32_t localMemoryStatelessWindowStartAddressOffset = dst.workloadInfo.localMemoryStatelessWindowStartAddressOffset;
if (localMemoryStatelessWindowStartAddressOffset != WorkloadInfo::undefinedOffset) {
*(uintptr_t *)&(dst.crossThreadData[localMemoryStatelessWindowStartAddressOffset]) = reinterpret_cast<uintptr_t>(constants.slmWindow);
}
if (localMemoryStatelessWindowSizeOffset != WorkloadInfo::undefinedOffset) {
*(uint32_t *)&(dst.crossThreadData[localMemoryStatelessWindowSizeOffset]) = constants.slmWindowSize;
}
uint32_t privateMemorySize = 0U;
if (dst.patchInfo.pAllocateStatelessPrivateSurface) {
privateMemorySize = dst.patchInfo.pAllocateStatelessPrivateSurface->PerThreadPrivateMemorySize * constants.computeUnitsUsedForScratch * dst.getMaxSimdSize();
}
if (privateMemoryStatelessSizeOffset != WorkloadInfo::undefinedOffset) {
*(uint32_t *)&(dst.crossThreadData[privateMemoryStatelessSizeOffset]) = privateMemorySize;
}
if (dst.workloadInfo.maxWorkGroupSizeOffset != WorkloadInfo::undefinedOffset) {
*(uint32_t *)&(dst.crossThreadData[dst.workloadInfo.maxWorkGroupSizeOffset]) = constants.maxWorkGroupSize;
}
}
}
} // namespace NEO

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 Intel Corporation
* Copyright (C) 2019-2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -7,14 +7,18 @@
#pragma once
#include <cstdint>
namespace NEO {
struct DeviceInfoKernelPayloadConstants;
struct KernelInfo;
namespace PatchTokenBinary {
struct KernelFromPatchtokens;
}
void populateKernelInfo(KernelInfo &dst, const PatchTokenBinary::KernelFromPatchtokens &src);
void populateKernelInfo(KernelInfo &dst, const PatchTokenBinary::KernelFromPatchtokens &src, uint32_t gpuPointerSizeInBytes,
const DeviceInfoKernelPayloadConstants &constant);
} // namespace NEO

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017-2019 Intel Corporation
* Copyright (C) 2017-2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -60,8 +60,6 @@ struct PatchInfo {
statelessGlobalMemObjKernelArgs;
::std::vector<const SPatchImageMemoryObjectKernelArgument *>
imageMemObjKernelArgs;
::std::vector<const SPatchGlobalMemoryObjectKernelArgument *>
globalMemObjKernelArgs;
const SPatchDataParameterStream *dataParameterStream = nullptr;
const SPatchThreadPayload *threadPayload = nullptr;
const SPatchExecutionEnvironment *executionEnvironment = nullptr;
@@ -75,7 +73,6 @@ struct PatchInfo {
const SPatchAllocateStatelessDefaultDeviceQueueSurface *pAllocateStatelessDefaultDeviceQueueSurface = nullptr;
const SPatchAllocateSystemThreadSurface *pAllocateSystemThreadSurface = nullptr;
::std::unordered_map<uint32_t, std::string> stringDataMap;
::std::vector<const SPatchKernelArgumentInfo *> kernelArgumentInfo;
};
} // namespace NEO

View File

@@ -10,6 +10,9 @@
#include "core/helpers/ptr_math.h"
#include "core/helpers/string.h"
#include "core/memory_manager/unified_memory_manager.h"
#include "core/program/program_info.h"
#include "core/program/program_info_from_patchtokens.h"
#include "core/program/program_initialization.h"
#include "runtime/compiler_interface/patchtokens_decoder.h"
#include "runtime/compiler_interface/patchtokens_dumper.h"
#include "runtime/compiler_interface/patchtokens_validator.inl"
@@ -53,124 +56,6 @@ const KernelInfo *Program::getKernelInfo(size_t ordinal) const {
return kernelInfoArray[ordinal];
}
std::string Program::getKernelNamesString() const {
std::string semiColonDelimitedKernelNameStr;
for (auto kernelInfo : kernelInfoArray) {
if (!semiColonDelimitedKernelNameStr.empty()) {
semiColonDelimitedKernelNameStr += ';';
}
semiColonDelimitedKernelNameStr += kernelInfo->name;
}
return semiColonDelimitedKernelNameStr;
}
void Program::populateKernelInfo(
const PatchTokenBinary::ProgramFromPatchtokens &decodedProgram,
uint32_t kernelNum,
cl_int &retVal) {
auto kernelInfo = std::make_unique<KernelInfo>();
const PatchTokenBinary::KernelFromPatchtokens &decodedKernel = decodedProgram.kernels[kernelNum];
NEO::populateKernelInfo(*kernelInfo, decodedKernel);
retVal = kernelInfo->resolveKernelInfo();
if (retVal != CL_SUCCESS) {
return;
}
kernelInfo->gpuPointerSize = decodedProgram.header->GPUPointerSizeInBytes;
if (decodedKernel.tokens.programSymbolTable) {
prepareLinkerInputStorage();
linkerInput->decodeExportedFunctionsSymbolTable(decodedKernel.tokens.programSymbolTable + 1, decodedKernel.tokens.programSymbolTable->NumEntries, kernelNum);
}
if (decodedKernel.tokens.programRelocationTable) {
prepareLinkerInputStorage();
linkerInput->decodeRelocationTable(decodedKernel.tokens.programRelocationTable + 1, decodedKernel.tokens.programRelocationTable->NumEntries, kernelNum);
}
if (kernelInfo->patchInfo.dataParameterStream && kernelInfo->patchInfo.dataParameterStream->DataParameterStreamSize) {
uint32_t crossThreadDataSize = kernelInfo->patchInfo.dataParameterStream->DataParameterStreamSize;
kernelInfo->crossThreadData = new char[crossThreadDataSize];
memset(kernelInfo->crossThreadData, 0x00, crossThreadDataSize);
uint32_t privateMemoryStatelessSizeOffset = kernelInfo->workloadInfo.privateMemoryStatelessSizeOffset;
uint32_t localMemoryStatelessWindowSizeOffset = kernelInfo->workloadInfo.localMemoryStatelessWindowSizeOffset;
uint32_t localMemoryStatelessWindowStartAddressOffset = kernelInfo->workloadInfo.localMemoryStatelessWindowStartAddressOffset;
if (localMemoryStatelessWindowStartAddressOffset != 0xFFffFFff) {
*(uintptr_t *)&(kernelInfo->crossThreadData[localMemoryStatelessWindowStartAddressOffset]) = reinterpret_cast<uintptr_t>(this->executionEnvironment.memoryManager->getReservedMemory(MemoryConstants::slmWindowSize, MemoryConstants::slmWindowAlignment));
}
if (localMemoryStatelessWindowSizeOffset != 0xFFffFFff) {
*(uint32_t *)&(kernelInfo->crossThreadData[localMemoryStatelessWindowSizeOffset]) = (uint32_t)this->pDevice->getDeviceInfo().localMemSize;
}
if (kernelInfo->patchInfo.pAllocateStatelessPrivateSurface && (privateMemoryStatelessSizeOffset != 0xFFffFFff)) {
*(uint32_t *)&(kernelInfo->crossThreadData[privateMemoryStatelessSizeOffset]) = kernelInfo->patchInfo.pAllocateStatelessPrivateSurface->PerThreadPrivateMemorySize * this->getDevice(0).getDeviceInfo().computeUnitsUsedForScratch * kernelInfo->getMaxSimdSize();
}
if (kernelInfo->workloadInfo.maxWorkGroupSizeOffset != WorkloadInfo::undefinedOffset) {
*(uint32_t *)&(kernelInfo->crossThreadData[kernelInfo->workloadInfo.maxWorkGroupSizeOffset]) = (uint32_t)this->getDevice(0).getDeviceInfo().maxWorkGroupSize;
}
}
if (kernelInfo->heapInfo.pKernelHeader->KernelHeapSize && this->pDevice) {
retVal = kernelInfo->createKernelAllocation(this->pDevice->getRootDeviceIndex(), this->pDevice->getMemoryManager()) ? CL_SUCCESS : CL_OUT_OF_HOST_MEMORY;
}
DEBUG_BREAK_IF(kernelInfo->heapInfo.pKernelHeader->KernelHeapSize && !this->pDevice);
if (retVal != CL_SUCCESS) {
return;
}
if (kernelInfo->hasDeviceEnqueue()) {
parentKernelInfoArray.push_back(kernelInfo.get());
}
if (kernelInfo->requiresSubgroupIndependentForwardProgress()) {
subgroupKernelInfoArray.push_back(kernelInfo.get());
}
kernelInfoArray.push_back(kernelInfo.release());
}
inline uint64_t readMisalignedUint64(const uint64_t *address) {
const uint32_t *addressBits = reinterpret_cast<const uint32_t *>(address);
return static_cast<uint64_t>(static_cast<uint64_t>(addressBits[1]) << 32) | addressBits[0];
}
GraphicsAllocation *allocateGlobalsSurface(NEO::Context *ctx, NEO::ClDevice *device, size_t size, bool constant, bool globalsAreExported, const void *initData) {
UNRECOVERABLE_IF(device == nullptr);
if (globalsAreExported && (ctx != nullptr) && (ctx->getSVMAllocsManager() != nullptr)) {
NEO::SVMAllocsManager::SvmAllocationProperties svmProps = {};
svmProps.coherent = false;
svmProps.readOnly = constant;
svmProps.hostPtrReadOnly = constant;
auto ptr = ctx->getSVMAllocsManager()->createSVMAlloc(device->getRootDeviceIndex(), size, svmProps);
DEBUG_BREAK_IF(ptr == nullptr);
if (ptr == nullptr) {
return nullptr;
}
auto svmAlloc = ctx->getSVMAllocsManager()->getSVMAlloc(ptr);
UNRECOVERABLE_IF(svmAlloc == nullptr);
auto gpuAlloc = svmAlloc->gpuAllocation;
UNRECOVERABLE_IF(gpuAlloc == nullptr);
device->getMemoryManager()->copyMemoryToAllocation(gpuAlloc, initData, static_cast<uint32_t>(size));
return ctx->getSVMAllocsManager()->getSVMAlloc(ptr)->gpuAllocation;
} else {
auto allocationType = constant ? GraphicsAllocation::AllocationType::CONSTANT_SURFACE : GraphicsAllocation::AllocationType::GLOBAL_SURFACE;
auto gpuAlloc = device->getMemoryManager()->allocateGraphicsMemoryWithProperties({device->getRootDeviceIndex(), size, allocationType});
DEBUG_BREAK_IF(gpuAlloc == nullptr);
if (gpuAlloc == nullptr) {
return nullptr;
}
memcpy_s(gpuAlloc->getUnderlyingBuffer(), gpuAlloc->getUnderlyingBufferSize(), initData, size);
return gpuAlloc;
}
}
cl_int Program::isHandled(const PatchTokenBinary::ProgramFromPatchtokens &decodedProgram) const {
std::string validatorErrMessage;
std::string validatorWarnings;
@@ -191,76 +76,27 @@ cl_int Program::isHandled(const PatchTokenBinary::ProgramFromPatchtokens &decode
return CL_SUCCESS;
}
void Program::processProgramScopeMetadata(const PatchTokenBinary::ProgramFromPatchtokens &decodedProgram) {
if (decodedProgram.programScopeTokens.symbolTable != nullptr) {
const auto patch = decodedProgram.programScopeTokens.symbolTable;
this->prepareLinkerInputStorage();
this->linkerInput->decodeGlobalVariablesSymbolTable(patch + 1, patch->NumEntries);
}
if (decodedProgram.programScopeTokens.allocateConstantMemorySurface.size() != 0) {
pDevice->getMemoryManager()->freeGraphicsMemory(this->constantSurface);
auto exportsGlobals = (linkerInput && linkerInput->getTraits().exportsGlobalConstants);
size_t globalConstantsSurfaceSize = decodedProgram.programScopeTokens.allocateConstantMemorySurface[0]->InlineDataSize;
const void *globalConstantsInitData = NEO::PatchTokenBinary::getInlineData(decodedProgram.programScopeTokens.allocateConstantMemorySurface[0]);
this->constantSurface = allocateGlobalsSurface(context, pDevice, globalConstantsSurfaceSize, true, exportsGlobals, globalConstantsInitData);
}
if (decodedProgram.programScopeTokens.allocateGlobalMemorySurface.size() != 0) {
pDevice->getMemoryManager()->freeGraphicsMemory(this->globalSurface);
auto exportsGlobals = (linkerInput && linkerInput->getTraits().exportsGlobalVariables);
size_t globalVariablesSurfaceSize = decodedProgram.programScopeTokens.allocateGlobalMemorySurface[0]->InlineDataSize;
const void *globalVariablesInitData = NEO::PatchTokenBinary::getInlineData(decodedProgram.programScopeTokens.allocateGlobalMemorySurface[0]);
this->globalVarTotalSize = globalVariablesSurfaceSize;
this->globalSurface = allocateGlobalsSurface(context, pDevice, globalVariablesSurfaceSize, false, exportsGlobals, globalVariablesInitData);
}
for (const auto &globalConstantPointerToken : decodedProgram.programScopeTokens.constantPointer) {
NEO::GraphicsAllocation *srcSurface = this->constantSurface;
if (globalConstantPointerToken->BufferType != PROGRAM_SCOPE_CONSTANT_BUFFER) {
UNRECOVERABLE_IF(globalConstantPointerToken->BufferType != PROGRAM_SCOPE_GLOBAL_BUFFER);
srcSurface = this->globalSurface;
}
UNRECOVERABLE_IF(srcSurface == nullptr);
UNRECOVERABLE_IF(this->constantSurface == nullptr);
auto offset = readMisalignedUint64(&globalConstantPointerToken->ConstantPointerOffset);
UNRECOVERABLE_IF(this->constantSurface->getUnderlyingBufferSize() < ((offset + constantSurface->is32BitAllocation()) ? 4 : sizeof(uintptr_t)));
void *patchOffset = ptrOffset(this->constantSurface->getUnderlyingBuffer(), static_cast<size_t>(offset));
patchIncrement(patchOffset, constantSurface->is32BitAllocation() ? 4 : sizeof(uintptr_t), srcSurface->getGpuAddressToPatch());
}
for (const auto &globalVariablePointerToken : decodedProgram.programScopeTokens.globalPointer) {
NEO::GraphicsAllocation *srcSurface = this->globalSurface;
if (globalVariablePointerToken->BufferType != PROGRAM_SCOPE_GLOBAL_BUFFER) {
UNRECOVERABLE_IF(globalVariablePointerToken->BufferType != PROGRAM_SCOPE_CONSTANT_BUFFER);
srcSurface = this->constantSurface;
}
UNRECOVERABLE_IF(srcSurface == nullptr);
UNRECOVERABLE_IF(this->globalSurface == nullptr);
auto offset = readMisalignedUint64(&globalVariablePointerToken->GlobalPointerOffset);
UNRECOVERABLE_IF(this->globalSurface->getUnderlyingBufferSize() < ((offset + globalSurface->is32BitAllocation()) ? 4 : sizeof(uintptr_t)));
void *patchOffset = ptrOffset(this->globalSurface->getUnderlyingBuffer(), static_cast<size_t>(offset));
patchIncrement(patchOffset, globalSurface->is32BitAllocation() ? 4 : sizeof(uintptr_t), srcSurface->getGpuAddressToPatch());
}
}
cl_int Program::linkBinary() {
if (linkerInput == nullptr) {
return CL_SUCCESS;
}
Linker linker(*linkerInput);
Linker::Segment globals;
Linker::Segment constants;
Linker::Segment exportedFunctions;
Linker::SegmentInfo globals;
Linker::SegmentInfo constants;
Linker::SegmentInfo exportedFunctions;
Linker::PatchableSegment globalsForPatching;
Linker::PatchableSegment constantsForPatching;
if (this->globalSurface != nullptr) {
globals.gpuAddress = static_cast<uintptr_t>(this->globalSurface->getGpuAddress());
globals.segmentSize = this->globalSurface->getUnderlyingBufferSize();
globalsForPatching.hostPointer = this->globalSurface->getUnderlyingBuffer();
globalsForPatching.segmentSize = this->globalSurface->getUnderlyingBufferSize();
}
if (this->constantSurface != nullptr) {
constants.gpuAddress = static_cast<uintptr_t>(this->constantSurface->getGpuAddress());
constants.segmentSize = this->constantSurface->getUnderlyingBufferSize();
constantsForPatching.hostPointer = this->constantSurface->getUnderlyingBuffer();
constantsForPatching.segmentSize = this->constantSurface->getUnderlyingBufferSize();
}
if (this->linkerInput->getExportedFunctionsSegmentId() >= 0) {
// Exported functions reside in instruction heap of one of kernels
@@ -283,6 +119,7 @@ cl_int Program::linkBinary() {
Linker::UnresolvedExternals unresolvedExternalsInfo;
bool linkSuccess = linker.link(globals, constants, exportedFunctions,
globalsForPatching, constantsForPatching,
isaSegmentsForPatching, unresolvedExternalsInfo);
this->symbols = linker.extractRelocatedSymbols();
if (false == linkSuccess) {
@@ -295,6 +132,9 @@ cl_int Program::linkBinary() {
return CL_INVALID_BINARY;
} else if (linkerInput->getTraits().requiresPatchingOfInstructionSegments) {
for (const auto &kernelInfo : this->kernelInfoArray) {
if (nullptr == kernelInfo->getGraphicsAllocation()) {
continue;
}
auto &kernHeapInfo = kernelInfo->heapInfo;
auto segmentId = &kernelInfo - &this->kernelInfoArray[0];
this->pDevice->getMemoryManager()->copyMemoryToAllocation(kernelInfo->getGraphicsAllocation(),
@@ -307,30 +147,83 @@ cl_int Program::linkBinary() {
cl_int Program::processGenBinary() {
cleanCurrentKernelInfo();
if (this->constantSurface || this->globalSurface) {
pDevice->getMemoryManager()->freeGraphicsMemory(this->constantSurface);
pDevice->getMemoryManager()->freeGraphicsMemory(this->globalSurface);
this->constantSurface = nullptr;
this->globalSurface = nullptr;
}
auto blob = ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(genBinary.get()), genBinarySize);
ProgramInfo programInfo;
auto ret = this->processPatchTokensBinary(blob, programInfo);
if (CL_SUCCESS != ret) {
return ret;
}
return this->processProgramInfo(programInfo);
}
cl_int Program::processPatchTokensBinary(ArrayRef<const uint8_t> src, ProgramInfo &dst) {
NEO::PatchTokenBinary::ProgramFromPatchtokens decodedProgram = {};
NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(blob, decodedProgram);
NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(src, decodedProgram);
DBG_LOG(LogPatchTokens, NEO::PatchTokenBinary::asString(decodedProgram).c_str());
cl_int retVal = this->isHandled(decodedProgram);
if (CL_SUCCESS != retVal) {
return retVal;
}
auto numKernels = decodedProgram.header->NumberOfKernels;
for (uint32_t i = 0; i < numKernels && retVal == CL_SUCCESS; i++) {
populateKernelInfo(decodedProgram, i, retVal);
NEO::DeviceInfoKernelPayloadConstants deviceInfoConstants;
if (this->pDevice) {
deviceInfoConstants.maxWorkGroupSize = (uint32_t)this->pDevice->getDeviceInfo().maxWorkGroupSize;
deviceInfoConstants.computeUnitsUsedForScratch = this->pDevice->getDeviceInfo().computeUnitsUsedForScratch;
deviceInfoConstants.slmWindowSize = (uint32_t)this->pDevice->getDeviceInfo().localMemSize;
if (requiresLocalMemoryWindowVA(decodedProgram)) {
deviceInfoConstants.slmWindow = this->executionEnvironment.memoryManager->getReservedMemory(MemoryConstants::slmWindowSize, MemoryConstants::slmWindowAlignment);
}
}
if (retVal != CL_SUCCESS) {
return retVal;
NEO::populateProgramInfo(dst, decodedProgram, deviceInfoConstants);
return CL_SUCCESS;
}
cl_int Program::processProgramInfo(ProgramInfo &src) {
this->linkerInput = std::move(src.linkerInput);
this->kernelInfoArray = std::move(src.kernelInfos);
auto svmAllocsManager = context ? context->getSVMAllocsManager() : nullptr;
if (src.globalConstants.size != 0) {
UNRECOVERABLE_IF(nullptr == pDevice);
this->constantSurface = allocateGlobalsSurface(svmAllocsManager, pDevice->getDevice(), src.globalConstants.size, true, linkerInput.get(), src.globalConstants.initData);
}
processProgramScopeMetadata(decodedProgram);
if (src.globalVariables.size != 0) {
UNRECOVERABLE_IF(nullptr == pDevice);
this->globalSurface = allocateGlobalsSurface(svmAllocsManager, pDevice->getDevice(), src.globalVariables.size, false, linkerInput.get(), src.globalVariables.initData);
}
retVal = linkBinary();
this->globalVarTotalSize = src.globalVariables.size;
return retVal;
for (auto &kernelInfo : this->kernelInfoArray) {
cl_int retVal = CL_SUCCESS;
if (kernelInfo->heapInfo.pKernelHeader->KernelHeapSize && this->pDevice) {
retVal = kernelInfo->createKernelAllocation(this->pDevice->getRootDeviceIndex(), this->pDevice->getMemoryManager()) ? CL_SUCCESS : CL_OUT_OF_HOST_MEMORY;
}
DEBUG_BREAK_IF(kernelInfo->heapInfo.pKernelHeader->KernelHeapSize && !this->pDevice);
if (retVal != CL_SUCCESS) {
return retVal;
}
if (kernelInfo->hasDeviceEnqueue()) {
parentKernelInfoArray.push_back(kernelInfo);
}
if (kernelInfo->requiresSubgroupIndependentForwardProgress()) {
subgroupKernelInfoArray.push_back(kernelInfo);
}
}
return linkBinary();
}
bool Program::validateGenBinaryDevice(GFXCORE_FAMILY device) const {

View File

@@ -456,9 +456,4 @@ void Program::updateNonUniformFlag(const Program **inputPrograms, size_t numInpu
this->allowNonUniform = allowNonUniform;
}
void Program::prepareLinkerInputStorage() {
if (this->linkerInput == nullptr) {
this->linkerInput = std::make_unique<LinkerInput>();
}
}
} // namespace NEO

View File

@@ -9,6 +9,7 @@
#include "core/compiler_interface/compiler_interface.h"
#include "core/compiler_interface/linker.h"
#include "core/elf/writer.h"
#include "core/program/program_info.h"
#include "core/utilities/const_stringref.h"
#include "runtime/api/cl_types.h"
#include "runtime/helpers/base_object.h"
@@ -131,6 +132,8 @@ class Program : public BaseObject<_cl_program> {
std::unordered_map<std::string, BuiltinDispatchInfoBuilder *> &builtinsMap);
MOCKABLE_VIRTUAL cl_int processGenBinary();
MOCKABLE_VIRTUAL cl_int processPatchTokensBinary(ArrayRef<const uint8_t> src, ProgramInfo &dst);
MOCKABLE_VIRTUAL cl_int processProgramInfo(ProgramInfo &dst);
cl_int compile(cl_uint numDevices, const cl_device_id *deviceList, const char *buildOptions,
cl_uint numInputHeaders, const cl_program *inputHeaders, const char **headerIncludeNames,
@@ -269,16 +272,12 @@ class Program : public BaseObject<_cl_program> {
MOCKABLE_VIRTUAL cl_int linkBinary();
MOCKABLE_VIRTUAL cl_int isHandled(const PatchTokenBinary::ProgramFromPatchtokens &decodedProgram) const;
void processProgramScopeMetadata(const PatchTokenBinary::ProgramFromPatchtokens &decodedProgram);
void populateKernelInfo(const PatchTokenBinary::ProgramFromPatchtokens &decodedProgram, uint32_t kernelNum, cl_int &retVal);
MOCKABLE_VIRTUAL cl_int rebuildProgramFromIr();
bool validateGenBinaryDevice(GFXCORE_FAMILY device) const;
bool validateGenBinaryHeader(const iOpenCL::SProgramBinaryHeader *pGenBinaryHeader) const;
std::string getKernelNamesString() const;
void separateBlockKernels();
void updateNonUniformFlag();
@@ -292,8 +291,6 @@ class Program : public BaseObject<_cl_program> {
MOCKABLE_VIRTUAL bool appendKernelDebugOptions();
void notifyDebuggerWithSourceCode(std::string &filename);
void prepareLinkerInputStorage();
static const std::string clOptNameClVer;
cl_program_binary_type programBinaryType;
@@ -354,6 +351,4 @@ class Program : public BaseObject<_cl_program> {
bool kernelDebugEnabled = false;
};
GraphicsAllocation *allocateGlobalsSurface(NEO::Context *ctx, NEO::ClDevice *device, size_t size, bool constant, bool globalsAreExported, const void *initData);
} // namespace NEO

View File

@@ -178,9 +178,9 @@ void FileLogger<DebugLevel>::dumpKernelArgs(const Kernel *kernel) {
auto &argInfo = kernel->getKernelInfo().kernelArgInfo[i];
if (argInfo.addressQualifier == CL_KERNEL_ARG_ADDRESS_LOCAL) {
if (argInfo.metadata.addressQualifier == KernelArgMetadata::AddressSpaceQualifier::Local) {
type = "local";
} else if (argInfo.typeStr.find("image") != std::string::npos) {
} else if (argInfo.isImage) {
type = "image";
auto clMem = (const cl_mem)kernel->getKernelArg(i);
auto memObj = castToObject<MemObj>(clMem);
@@ -189,9 +189,9 @@ void FileLogger<DebugLevel>::dumpKernelArgs(const Kernel *kernel) {
size = memObj->getSize();
flags = memObj->getMemoryPropertiesFlags();
}
} else if (argInfo.typeStr.find("sampler") != std::string::npos) {
} else if (argInfo.isSampler) {
type = "sampler";
} else if (argInfo.typeStr.find("*") != std::string::npos) {
} else if (argInfo.isBuffer) {
type = "buffer";
auto clMem = (const cl_mem)kernel->getKernelArg(i);
auto memObj = castToObject<MemObj>(clMem);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017-2019 Intel Corporation
* Copyright (C) 2017-2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -172,7 +172,7 @@ TEST_F(clBuildProgramTests, GivenProgramCreatedFromBinaryWhenBuildProgramWithOpt
TEST_F(clBuildProgramTests, GivenSpirAsInputWhenCreatingProgramFromBinaryThenProgramBuildSucceeds) {
cl_program pProgram = nullptr;
cl_int binaryStatus = CL_SUCCESS;
unsigned char llvm[16] = "BC\xc0\xde";
unsigned char llvm[16] = "BC\xc0\xde_unique";
size_t binarySize = sizeof(llvm);
const unsigned char *binaries[1] = {llvm};
@@ -193,6 +193,7 @@ TEST_F(clBuildProgramTests, GivenSpirAsInputWhenCreatingProgramFromBinaryThenPro
progBin.Magic = iOpenCL::MAGIC_CL;
progBin.Version = iOpenCL::CURRENT_ICBE_VERSION;
progBin.Device = pContext->getDevice(0)->getHardwareInfo().platform.eRenderCoreFamily;
progBin.GPUPointerSizeInBytes = sizeof(uintptr_t);
igcDebugVars.binaryToReturn = &progBin;
igcDebugVars.binaryToReturnSize = sizeof(progBin);
auto prevDebugVars = getIgcDebugVars();

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017-2019 Intel Corporation
* Copyright (C) 2017-2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -73,24 +73,6 @@ TEST_F(clCreateKernelTests, GivenCorrectKernelInProgramWhenCreatingNewKernelThen
EXPECT_EQ(CL_SUCCESS, retVal);
}
TEST_F(clCreateKernelTests, GivenInvalidKernelWhenCreatingNewKernelThenInvalidProgramExecutableErrorIsReturned) {
cl_kernel kernel = nullptr;
KernelInfo *pKernelInfo = new KernelInfo();
pKernelInfo->isValid = false;
std::unique_ptr<MockProgram> pMockProg = std::make_unique<MockProgram>(*pPlatform->peekExecutionEnvironment(), pContext, false);
pMockProg->addKernelInfo(pKernelInfo);
pMockProg->SetBuildStatus(CL_BUILD_SUCCESS);
kernel = clCreateKernel(
pMockProg.get(),
"",
&retVal);
EXPECT_EQ(CL_INVALID_PROGRAM_EXECUTABLE, retVal);
EXPECT_EQ(nullptr, kernel);
}
TEST_F(clCreateKernelTests, GivenInvalidKernelNameWhenCreatingNewKernelThenInvalidKernelNameErrorIsReturned) {
cl_kernel kernel = nullptr;
cl_program pProgram = nullptr;
@@ -157,7 +139,6 @@ TEST_F(clCreateKernelTests, GivenNullProgramWhenCreatingNewKernelThenInvalidProg
TEST_F(clCreateKernelTests, GivenNullKernelNameWhenCreatingNewKernelThenInvalidValueErrorIsReturned) {
cl_kernel kernel = nullptr;
KernelInfo *pKernelInfo = new KernelInfo();
pKernelInfo->isValid = true;
std::unique_ptr<MockProgram> pMockProg = std::make_unique<MockProgram>(*pPlatform->peekExecutionEnvironment(), pContext, false);
pMockProg->addKernelInfo(pKernelInfo);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017-2019 Intel Corporation
* Copyright (C) 2017-2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -17,7 +17,7 @@ using clGetDeviceFunctionPointer = api_tests;
TEST_F(clGetDeviceGlobalVariablePointer, GivenNullMandatoryArgumentsThenReturnInvalidArgError) {
this->pProgram->symbols["A"].gpuAddress = 7U;
this->pProgram->symbols["A"].symbol.size = 64U;
this->pProgram->symbols["A"].symbol.type = NEO::SymbolInfo::GlobalVariable;
this->pProgram->symbols["A"].symbol.segment = NEO::SegmentType::GlobalVariables;
void *globalRet = 0;
auto ret = clGetDeviceGlobalVariablePointerINTEL(this->pContext->getDevice(0), this->pProgram, "A", nullptr, &globalRet);
@@ -37,7 +37,7 @@ TEST_F(clGetDeviceGlobalVariablePointer, GivenNullMandatoryArgumentsThenReturnIn
TEST_F(clGetDeviceGlobalVariablePointer, GivenValidSymbolNameThenReturnProperAddressAndSize) {
this->pProgram->symbols["A"].gpuAddress = 7U;
this->pProgram->symbols["A"].symbol.size = 64U;
this->pProgram->symbols["A"].symbol.type = NEO::SymbolInfo::GlobalVariable;
this->pProgram->symbols["A"].symbol.segment = NEO::SegmentType::GlobalVariables;
void *globalRet = 0;
size_t sizeRet = 0;
@@ -50,7 +50,7 @@ TEST_F(clGetDeviceGlobalVariablePointer, GivenValidSymbolNameThenReturnProperAdd
TEST_F(clGetDeviceGlobalVariablePointer, GivenFunctionSymbolNameThenReturnInvalidArgError) {
this->pProgram->symbols["A"].gpuAddress = 7U;
this->pProgram->symbols["A"].symbol.size = 64U;
this->pProgram->symbols["A"].symbol.type = NEO::SymbolInfo::Function;
this->pProgram->symbols["A"].symbol.segment = NEO::SegmentType::Instructions;
void *globalRet = 0;
auto ret = clGetDeviceGlobalVariablePointerINTEL(this->pContext->getDevice(0), this->pProgram, "A", nullptr, &globalRet);
@@ -66,7 +66,7 @@ TEST_F(clGetDeviceGlobalVariablePointer, GivenUnknownSymbolNameThenReturnInvalid
TEST_F(clGetDeviceFunctionPointer, GivenNullMandatoryArgumentsThenReturnInvalidArgError) {
this->pProgram->symbols["A"].gpuAddress = 7U;
this->pProgram->symbols["A"].symbol.size = 64U;
this->pProgram->symbols["A"].symbol.type = NEO::SymbolInfo::Function;
this->pProgram->symbols["A"].symbol.segment = NEO::SegmentType::Instructions;
cl_ulong fptrRet = 0;
auto ret = clGetDeviceFunctionPointerINTEL(this->pContext->getDevice(0), this->pProgram, "A", &fptrRet);
@@ -86,7 +86,7 @@ TEST_F(clGetDeviceFunctionPointer, GivenNullMandatoryArgumentsThenReturnInvalidA
TEST_F(clGetDeviceFunctionPointer, GivenValidSymbolNameThenReturnProperAddress) {
this->pProgram->symbols["A"].gpuAddress = 7U;
this->pProgram->symbols["A"].symbol.size = 64U;
this->pProgram->symbols["A"].symbol.type = NEO::SymbolInfo::Function;
this->pProgram->symbols["A"].symbol.segment = NEO::SegmentType::Instructions;
cl_ulong fptrRet = 0;
auto ret = clGetDeviceFunctionPointerINTEL(this->pContext->getDevice(0), this->pProgram, "A", &fptrRet);
@@ -97,10 +97,10 @@ TEST_F(clGetDeviceFunctionPointer, GivenValidSymbolNameThenReturnProperAddress)
TEST_F(clGetDeviceFunctionPointer, GivenGlobalSymbolNameThenReturnInvalidArgError) {
this->pProgram->symbols["A"].gpuAddress = 7U;
this->pProgram->symbols["A"].symbol.size = 64U;
this->pProgram->symbols["A"].symbol.type = NEO::SymbolInfo::GlobalVariable;
this->pProgram->symbols["A"].symbol.segment = NEO::SegmentType::GlobalVariables;
this->pProgram->symbols["B"].gpuAddress = 7U;
this->pProgram->symbols["B"].symbol.size = 64U;
this->pProgram->symbols["B"].symbol.type = NEO::SymbolInfo::GlobalConstant;
this->pProgram->symbols["B"].symbol.segment = NEO::SegmentType::GlobalConstants;
cl_ulong fptrRet = 0;
auto ret = clGetDeviceFunctionPointerINTEL(this->pContext->getDevice(0), this->pProgram, "A", &fptrRet);

View File

@@ -42,8 +42,7 @@ class KernelArgSvmFixture : public ApiFixture, public DeviceFixture {
pKernelInfo->kernelArgInfo[0].kernelArgPatchInfoVector[0].crossthreadOffset = 0x30;
pKernelInfo->kernelArgInfo[0].kernelArgPatchInfoVector[0].size = (uint32_t)sizeof(void *);
pKernelInfo->kernelArgInfo[0].typeStr = "char *";
pKernelInfo->kernelArgInfo[0].addressQualifier = CL_KERNEL_ARG_ADDRESS_GLOBAL;
pKernelInfo->kernelArgInfo[0].metadata.addressQualifier = KernelArgMetadata::AddressSpaceQualifier::Global;
pMockKernel = new MockKernel(pProgram, *pKernelInfo, *this->pClDevice);
ASSERT_EQ(CL_SUCCESS, pMockKernel->initialize());
@@ -88,7 +87,7 @@ TEST_F(clSetKernelArgSVMPointerTests, GivenInvalidArgIndexWhenSettingKernelArgTh
}
TEST_F(clSetKernelArgSVMPointerTests, GivenLocalAddressAndNullArgValueWhenSettingKernelArgThenInvalidArgValueErrorIsReturned) {
pKernelInfo->kernelArgInfo[0].addressQualifier = CL_KERNEL_ARG_ADDRESS_LOCAL;
pKernelInfo->kernelArgInfo[0].metadata.addressQualifier = KernelArgMetadata::AddressSpaceQualifier::Local;
auto retVal = clSetKernelArgSVMPointer(
pMockKernel, // cl_kernel kernel
@@ -148,7 +147,7 @@ TEST_F(clSetKernelArgSVMPointerTests, GivenSvmAndConstantAddressWhenSettingKerne
void *ptrSvm = clSVMAlloc(pContext, CL_MEM_READ_WRITE, 256, 4);
EXPECT_NE(nullptr, ptrSvm);
pKernelInfo->kernelArgInfo[0].addressQualifier = CL_KERNEL_ARG_ADDRESS_CONSTANT;
pKernelInfo->kernelArgInfo[0].metadata.addressQualifier = KernelArgMetadata::AddressSpaceQualifier::Constant;
auto retVal = clSetKernelArgSVMPointer(
pMockKernel, // cl_kernel kernel

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 Intel Corporation
* Copyright (C) 2019-2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -199,7 +199,8 @@ TEST(KernelDecoder, GivenValidEmptyKernelThenDecodingOfHeaderSucceeds) {
EXPECT_EQ(0U, decodedKernel.isa.size());
EXPECT_TRUE(hasEmptyHeaps(decodedKernel));
EXPECT_EQ(0U, decodedKernel.unhandledTokens.size());
EXPECT_TRUE(hasEmptyTokensInfo(decodedKernel));
EXPECT_FALSE(hasEmptyTokensInfo(decodedKernel));
EXPECT_NE(nullptr, decodedKernel.tokens.executionEnvironment);
}
TEST(KernelDecoder, GivenEmptyKernelWhenBlobSmallerThanKernelHeaderThenDecodingFails) {
@@ -220,6 +221,8 @@ TEST(KernelDecoder, GivenValidKernelWithHeapsThenDecodingSucceedsAndHeapsAreProp
ASSERT_EQ(storage.data(), kernelToEncode.blobs.kernelInfo.begin());
auto kernelHeader = reinterpret_cast<iOpenCL::SKernelBinaryHeaderCommon *>(storage.data());
auto kernelExecEnv = *reinterpret_cast<const iOpenCL::SPatchExecutionEnvironment *>(kernelToEncode.blobs.patchList.begin());
storage.resize(storage.size() - sizeof(kernelExecEnv));
size_t isaOffset = storage.size();
kernelHeader->KernelHeapSize = 16U;
@@ -237,6 +240,9 @@ TEST(KernelDecoder, GivenValidKernelWithHeapsThenDecodingSucceedsAndHeapsAreProp
kernelHeader->SurfaceStateHeapSize = 32U;
storage.resize(storage.size() + kernelHeader->SurfaceStateHeapSize);
// patchlist needs to come after heaps
storage.insert(storage.end(), reinterpret_cast<uint8_t *>(&kernelExecEnv), reinterpret_cast<uint8_t *>(&kernelExecEnv + 1));
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
EXPECT_TRUE(decodeSuccess);
@@ -244,7 +250,8 @@ TEST(KernelDecoder, GivenValidKernelWithHeapsThenDecodingSucceedsAndHeapsAreProp
EXPECT_EQ(kernelToEncode.header, decodedKernel.header);
EXPECT_EQ(0U, decodedKernel.unhandledTokens.size());
EXPECT_TRUE(hasEmptyTokensInfo(decodedKernel));
EXPECT_FALSE(hasEmptyTokensInfo(decodedKernel));
EXPECT_NE(nullptr, decodedKernel.tokens.executionEnvironment);
EXPECT_EQ(kernelToEncode.name, decodedKernel.name);
EXPECT_EQ(ArrayRef<const uint8_t>(storage.data() + isaOffset, kernelHeader->KernelHeapSize), decodedKernel.isa);
@@ -308,7 +315,7 @@ TEST(KernelDecoder, GivenKernelWithValidKernelPatchtokensThenDecodingSucceedsAnd
storage.reserve(1024);
auto kernelToEncode = PatchTokensTestData::ValidEmptyKernel::create(storage);
auto patchListOffset = static_cast<uint32_t>(storage.size());
auto patchListOffset = ptrDiff(kernelToEncode.blobs.patchList.begin(), storage.data());
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);
@@ -335,7 +342,7 @@ TEST(KernelDecoder, GivenKernelWithValidKernelPatchtokensThenDecodingSucceedsAnd
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 = static_cast<uint32_t>(storage.size() - patchListOffset);
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
@@ -379,14 +386,14 @@ TEST(KernelDecoder, GivenKernelWithValidStringPatchtokensThenDecodingSucceedsAnd
iOpenCL::SPatchString stringTok = {};
stringTok.Token = iOpenCL::PATCH_TOKEN::PATCH_TOKEN_STRING;
auto patchListOffset = static_cast<uint32_t>(storage.size());
auto patchListOffset = ptrDiff(kernelToEncode.blobs.patchList.begin(), storage.data());
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;
kernelHeader->PatchListSize = static_cast<uint32_t>(storage.size() - patchListOffset);
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
@@ -409,7 +416,7 @@ TEST(KernelDecoder, GivenKernelWithValidArgInfoPatchtokensThenDecodingSucceedsAn
iOpenCL::SPatchKernelArgumentInfo argInfoTok = {};
argInfoTok.Token = iOpenCL::PATCH_TOKEN::PATCH_TOKEN_KERNEL_ARGUMENT_INFO;
auto patchListOffset = static_cast<uint32_t>(storage.size());
auto patchListOffset = ptrDiff(kernelToEncode.blobs.patchList.begin(), storage.data());
auto arg1Off = static_cast<uint32_t>(storage.size());
argInfoTok.ArgumentNumber = 1;
@@ -434,7 +441,7 @@ TEST(KernelDecoder, GivenKernelWithValidArgInfoPatchtokensThenDecodingSucceedsAn
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 = static_cast<uint32_t>(storage.size() - patchListOffset);
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
@@ -454,7 +461,7 @@ TEST(KernelDecoder, GivenKernelWithValidObjectArgPatchtokensThenDecodingSucceeds
storage.reserve(512);
auto kernelToEncode = PatchTokensTestData::ValidEmptyKernel::create(storage);
auto patchListOffset = static_cast<uint32_t>(storage.size());
auto patchListOffset = ptrDiff(kernelToEncode.blobs.patchList.begin(), storage.data());
iOpenCL::SPatchSamplerKernelArgument samplerTok = {};
samplerTok.Token = iOpenCL::PATCH_TOKEN::PATCH_TOKEN_SAMPLER_KERNEL_ARGUMENT;
@@ -495,7 +502,7 @@ TEST(KernelDecoder, GivenKernelWithValidObjectArgPatchtokensThenDecodingSucceeds
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 = static_cast<uint32_t>(storage.size() - patchListOffset);
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
@@ -544,7 +551,7 @@ TEST(KernelDecoder, GivenKernelWithValidNonArgCrossThreadDataPatchtokensThenDeco
storage.reserve(2048);
auto kernelToEncode = PatchTokensTestData::ValidEmptyKernel::create(storage);
auto patchListOffset = static_cast<uint32_t>(storage.size());
auto patchListOffset = ptrDiff(kernelToEncode.blobs.patchList.begin(), storage.data());
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);
@@ -577,7 +584,7 @@ TEST(KernelDecoder, GivenKernelWithValidNonArgCrossThreadDataPatchtokensThenDeco
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 = static_cast<uint32_t>(storage.size() - patchListOffset);
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
@@ -623,7 +630,7 @@ TEST(KernelDecoder, GivenKernelWithArgCrossThreadDataPatchtokensWhenSourceIndexI
storage.reserve(128);
auto kernelToEncode = PatchTokensTestData::ValidEmptyKernel::create(storage);
auto patchListOffset = static_cast<uint32_t>(storage.size());
auto patchListOffset = ptrDiff(kernelToEncode.blobs.patchList.begin(), storage.data());
auto localWorkSize3Off = pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_LOCAL_WORK_SIZE, storage, 3U);
auto globalWorkOffset3Off = pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_GLOBAL_WORK_OFFSET, storage, 3U);
@@ -632,7 +639,7 @@ TEST(KernelDecoder, GivenKernelWithArgCrossThreadDataPatchtokensWhenSourceIndexI
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;
kernelHeader->PatchListSize = static_cast<uint32_t>(storage.size() - patchListOffset);
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
@@ -653,12 +660,12 @@ TEST(KernelDecoder, GivenKernelWithUnkownPatchtokensThenDecodingSucceedsButToken
storage.reserve(128);
auto kernelToEncode = PatchTokensTestData::ValidEmptyKernel::create(storage);
auto patchListOffset = static_cast<uint32_t>(storage.size());
auto patchListOffset = ptrDiff(kernelToEncode.blobs.patchList.begin(), storage.data());
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;
kernelHeader->PatchListSize = static_cast<uint32_t>(storage.size() - patchListOffset);
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
@@ -676,7 +683,7 @@ TEST(KernelDecoder, GivenKernelWithValidObjectArgMetadataPatchtokensThenDecoding
storage.reserve(1024);
auto kernelToEncode = PatchTokensTestData::ValidEmptyKernel::create(storage);
auto patchListOffset = static_cast<uint32_t>(storage.size());
auto patchListOffset = ptrDiff(kernelToEncode.blobs.patchList.begin(), storage.data());
auto arg0ObjectIdOff = pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_OBJECT_ID, storage, 0U, 0U);
auto arg0BufferOffsetOff = pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_BUFFER_OFFSET, storage, 0U, 0U);
@@ -704,7 +711,7 @@ TEST(KernelDecoder, GivenKernelWithValidObjectArgMetadataPatchtokensThenDecoding
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 = static_cast<uint32_t>(storage.size() - patchListOffset);
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
@@ -754,7 +761,7 @@ TEST(KernelDecoder, GivenKernelWithMismatchedArgMetadataPatchtokensThenDecodingF
storage.reserve(128);
auto kernelToEncode = PatchTokensTestData::ValidEmptyKernel::create(storage);
auto patchListOffset = static_cast<uint32_t>(storage.size());
auto patchListOffset = ptrDiff(kernelToEncode.blobs.patchList.begin(), storage.data());
auto arg0Metadata0Off = pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_BUFFER_STATEFUL, storage, 0U, 0U);
auto arg0Metadata1Off = pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_BUFFER_OFFSET, storage, 0U, 0U);
@@ -764,7 +771,7 @@ TEST(KernelDecoder, GivenKernelWithMismatchedArgMetadataPatchtokensThenDecodingF
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 = static_cast<uint32_t>(storage.size() - patchListOffset);
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
@@ -862,7 +869,7 @@ TEST(KernelDecoder, GivenKernelWithMismatchedArgMetadataPatchtokensThenDecodingF
storage.reserve(128);
auto kernelToEncode = PatchTokensTestData::ValidEmptyKernel::create(storage);
auto patchListOffset = static_cast<uint32_t>(storage.size());
auto patchListOffset = ptrDiff(kernelToEncode.blobs.patchList.begin(), storage.data());
pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_BUFFER_STATEFUL, storage, 0U, 0U);
pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_IMAGE_DEPTH, storage, 0U, 0U);
@@ -871,7 +878,7 @@ TEST(KernelDecoder, GivenKernelWithMismatchedArgMetadataPatchtokensThenDecodingF
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 = static_cast<uint32_t>(storage.size() - patchListOffset);
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
@@ -885,7 +892,7 @@ TEST(KernelDecoder, GivenKernelWithByValArgMetadataPatchtokensThenDecodingSuccee
storage.reserve(128);
auto kernelToEncode = PatchTokensTestData::ValidEmptyKernel::create(storage);
auto patchListOffset = static_cast<uint32_t>(storage.size());
auto patchListOffset = ptrDiff(kernelToEncode.blobs.patchList.begin(), storage.data());
auto arg0Val0Off = pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_KERNEL_ARGUMENT, storage, 0U, 0U);
auto arg0Val1Off = pushBackDataParameterToken(iOpenCL::DATA_PARAMETER_KERNEL_ARGUMENT, storage, 0U, 0U);
@@ -893,7 +900,7 @@ TEST(KernelDecoder, GivenKernelWithByValArgMetadataPatchtokensThenDecodingSuccee
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 = static_cast<uint32_t>(storage.size() - patchListOffset);
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
@@ -919,7 +926,7 @@ TEST(KernelDecoder, GivenKernelWithVmeMetadataPatchtokensThenDecodingSucceedsAnd
storage.reserve(128);
auto kernelToEncode = PatchTokensTestData::ValidEmptyKernel::create(storage);
auto patchListOffset = static_cast<uint32_t>(storage.size());
auto patchListOffset = ptrDiff(kernelToEncode.blobs.patchList.begin(), storage.data());
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);
@@ -928,7 +935,7 @@ TEST(KernelDecoder, GivenKernelWithVmeMetadataPatchtokensThenDecodingSucceedsAnd
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 = static_cast<uint32_t>(storage.size() - patchListOffset);
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
@@ -953,12 +960,12 @@ TEST(KernelDecoder, GivenKernelWithOutOfBoundsTokenThenDecodingFails) {
storage.reserve(128);
auto kernelToEncode = PatchTokensTestData::ValidEmptyKernel::create(storage);
auto patchListOffset = static_cast<uint32_t>(storage.size());
auto patchListOffset = ptrDiff(kernelToEncode.blobs.patchList.begin(), storage.data());
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 = static_cast<uint32_t>(storage.size() - patchListOffset);
kernelHeader->PatchListSize -= 1;
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 Intel Corporation
* Copyright (C) 2019-2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -128,7 +128,7 @@ TEST(ProgramDumper, GivenProgramWithPatchtokensThenProperlyCreatesDump) {
std::string generated = NEO::PatchTokenBinary::asString(progWithConst);
std::stringstream expected;
expected <<
R"===(Program of size : 200 decoded successfully
R"===(Program of size : )===" << progWithConst.blobs.programInfo.size() << R"===( decoded successfully
struct SProgramBinaryHeader {
uint32_t Magic; // = 1229870147
uint32_t Version; // = )==="
@@ -136,27 +136,32 @@ struct SProgramBinaryHeader {
uint32_t Device; // = )==="
<< renderCoreFamily << R"===(
uint32_t GPUPointerSizeInBytes; // = 0
uint32_t GPUPointerSizeInBytes; // = )==="
<< progWithConst.header->GPUPointerSizeInBytes << R"===(
uint32_t NumberOfKernels; // = 0
uint32_t SteppingId; // = 0
uint32_t PatchListSize; // = 172
uint32_t PatchListSize; // = )==="
<< progWithConst.header->PatchListSize << R"===(
};
Program-scope tokens section size : 172
Program-scope tokens section size : )==="
<< progWithConst.blobs.patchList.size() << R"===(
WARNING : Unhandled program-scope tokens detected [2] :
+ [0]:
| struct SPatchItemHeader {
| uint32_t Token;// = )==="
<< NUM_PATCH_TOKENS << R"===(
| uint32_t Size;// = 28
| uint32_t Size;// = )==="
<< progWithConst.unhandledTokens[0]->Size << R"===(
| };
+ [1]:
| struct SPatchItemHeader {
| uint32_t Token;// = )==="
<< (NUM_PATCH_TOKENS) << R"===(
| uint32_t Size;// = 28
| uint32_t Size;// = )==="
<< progWithConst.unhandledTokens[1]->Size << R"===(
| };
Inline Costant Surface(s) [2] :
+ [0]:
@@ -262,7 +267,7 @@ TEST(ProgramDumper, GivenProgramWithKernelThenProperlyCreatesDump) {
std::string generated = NEO::PatchTokenBinary::asString(program);
std::stringstream expected;
expected <<
R"===(Program of size : 96 decoded successfully
R"===(Program of size : )===" << program.blobs.programInfo.size() << R"===( decoded successfully
struct SProgramBinaryHeader {
uint32_t Magic; // = 1229870147
uint32_t Version; // = )==="
@@ -270,7 +275,8 @@ struct SProgramBinaryHeader {
uint32_t Device; // = )==="
<< renderCoreFamily << R"===(
uint32_t GPUPointerSizeInBytes; // = 0
uint32_t GPUPointerSizeInBytes; // = )==="
<< program.header->GPUPointerSizeInBytes << R"===(
uint32_t NumberOfKernels; // = 1
@@ -281,14 +287,46 @@ struct SProgramBinaryHeader {
Program-scope tokens section size : 0
Kernels section size : 0
kernel[0] test_kernel:
Kernel of size : 68 decoded successfully
Kernel of size : )==="
<< program.kernels[0].blobs.kernelInfo.size() << R"===( decoded successfully
struct SKernelBinaryHeader {
uint32_t CheckSum;// = 2446215414
uint32_t CheckSum;// = )==="
<< program.kernels[0].header->CheckSum << R"===(
uint64_t ShaderHashCode;// = 0
uint32_t KernelNameSize;// = 12
uint32_t PatchListSize;// = 16
uint32_t PatchListSize;// = )==="
<< program.kernels[0].header->PatchListSize << R"===(
};
Kernel-scope tokens section size : 16
Kernel-scope tokens section size : )==="
<< program.kernels[0].blobs.patchList.size() << R"===(
struct SPatchExecutionEnvironment :
SPatchItemHeader (Token=23(PATCH_TOKEN_EXECUTION_ENVIRONMENT), Size=)==="
<< sizeof(iOpenCL::SPatchExecutionEnvironment) << R"===()
{
uint32_t RequiredWorkGroupSizeX;// = 0
uint32_t RequiredWorkGroupSizeY;// = 0
uint32_t RequiredWorkGroupSizeZ;// = 0
uint32_t LargestCompiledSIMDSize;// = 32
uint32_t CompiledSubGroupsNumber;// = 0
uint32_t HasBarriers;// = 0
uint32_t DisableMidThreadPreemption;// = 0
uint32_t CompiledSIMD8;// = 0
uint32_t CompiledSIMD16;// = 0
uint32_t CompiledSIMD32;// = 1
uint32_t HasDeviceEnqueue;// = 0
uint32_t MayAccessUndeclaredResource;// = 0
uint32_t UsesFencesForReadWriteImages;// = 0
uint32_t UsesStatelessSpillFill;// = 0
uint32_t UsesMultiScratchSpaces;// = 0
uint32_t IsCoherent;// = 0
uint32_t IsInitializer;// = 0
uint32_t IsFinalizer;// = 0
uint32_t SubgroupIndependentForwardProgressRequired;// = 0
uint32_t CompiledForGreaterThan4GBBuffers;// = 0
uint32_t NumGRFRequired;// = 0
uint32_t WorkgroupWalkOrderDims;// = 0
uint32_t HasGlobalAtomics;// = 0
}
struct SPatchAllocateLocalSurface :
SPatchItemHeader (Token=15(PATCH_TOKEN_ALLOCATE_LOCAL_SURFACE), Size=)==="
<< sizeof(iOpenCL::SPatchAllocateLocalSurface) << R"===()
@@ -311,7 +349,7 @@ TEST(ProgramDumper, GivenProgramWithMultipleKerneslThenProperlyCreatesDump) {
std::string generated = NEO::PatchTokenBinary::asString(program);
std::stringstream expected;
expected <<
R"===(Program of size : 96 decoded successfully
R"===(Program of size : )===" << program.blobs.programInfo.size() << R"===( decoded successfully
struct SProgramBinaryHeader {
uint32_t Magic; // = 1229870147
uint32_t Version; // = )==="
@@ -319,7 +357,8 @@ struct SProgramBinaryHeader {
uint32_t Device; // = )==="
<< renderCoreFamily << R"===(
uint32_t GPUPointerSizeInBytes; // = 0
uint32_t GPUPointerSizeInBytes; // = )==="
<< program.header->GPUPointerSizeInBytes << R"===(
uint32_t NumberOfKernels; // = 1
@@ -330,14 +369,46 @@ struct SProgramBinaryHeader {
Program-scope tokens section size : 0
Kernels section size : 0
kernel[0] test_kernel:
Kernel of size : 68 decoded successfully
Kernel of size : )==="
<< program.kernels[0].blobs.kernelInfo.size() << R"===( decoded successfully
struct SKernelBinaryHeader {
uint32_t CheckSum;// = 2446215414
uint32_t CheckSum;// = )==="
<< program.kernels[0].header->CheckSum << R"===(
uint64_t ShaderHashCode;// = 0
uint32_t KernelNameSize;// = 12
uint32_t PatchListSize;// = 16
uint32_t PatchListSize;// = )==="
<< program.kernels[0].header->PatchListSize << R"===(
};
Kernel-scope tokens section size : 16
Kernel-scope tokens section size : )==="
<< program.kernels[0].blobs.patchList.size() << R"===(
struct SPatchExecutionEnvironment :
SPatchItemHeader (Token=23(PATCH_TOKEN_EXECUTION_ENVIRONMENT), Size=)==="
<< sizeof(iOpenCL::SPatchExecutionEnvironment) << R"===()
{
uint32_t RequiredWorkGroupSizeX;// = 0
uint32_t RequiredWorkGroupSizeY;// = 0
uint32_t RequiredWorkGroupSizeZ;// = 0
uint32_t LargestCompiledSIMDSize;// = 32
uint32_t CompiledSubGroupsNumber;// = 0
uint32_t HasBarriers;// = 0
uint32_t DisableMidThreadPreemption;// = 0
uint32_t CompiledSIMD8;// = 0
uint32_t CompiledSIMD16;// = 0
uint32_t CompiledSIMD32;// = 1
uint32_t HasDeviceEnqueue;// = 0
uint32_t MayAccessUndeclaredResource;// = 0
uint32_t UsesFencesForReadWriteImages;// = 0
uint32_t UsesStatelessSpillFill;// = 0
uint32_t UsesMultiScratchSpaces;// = 0
uint32_t IsCoherent;// = 0
uint32_t IsInitializer;// = 0
uint32_t IsFinalizer;// = 0
uint32_t SubgroupIndependentForwardProgressRequired;// = 0
uint32_t CompiledForGreaterThan4GBBuffers;// = 0
uint32_t NumGRFRequired;// = 0
uint32_t WorkgroupWalkOrderDims;// = 0
uint32_t HasGlobalAtomics;// = 0
}
struct SPatchAllocateLocalSurface :
SPatchItemHeader (Token=15(PATCH_TOKEN_ALLOCATE_LOCAL_SURFACE), Size=)==="
<< sizeof(iOpenCL::SPatchAllocateLocalSurface) << R"===()
@@ -346,23 +417,87 @@ Kernel-scope tokens section size : 16
uint32_t TotalInlineLocalMemorySize;// = 16
}
kernel[1] different_kernel:
Kernel of size : 68 decoded successfully
Kernel of size : )==="
<< program.kernels[1].blobs.kernelInfo.size() << R"===( decoded successfully
struct SKernelBinaryHeader {
uint32_t CheckSum;// = 2446215414
uint32_t CheckSum;// = )==="
<< program.kernels[1].header->CheckSum << R"===(
uint64_t ShaderHashCode;// = 0
uint32_t KernelNameSize;// = 12
uint32_t PatchListSize;// = 16
uint32_t PatchListSize;// = )==="
<< program.kernels[1].header->PatchListSize << R"===(
};
Kernel-scope tokens section size : 0
Kernel-scope tokens section size : )==="
<< program.kernels[1].blobs.patchList.size() << R"===(
struct SPatchExecutionEnvironment :
SPatchItemHeader (Token=23(PATCH_TOKEN_EXECUTION_ENVIRONMENT), Size=)==="
<< sizeof(iOpenCL::SPatchExecutionEnvironment) << R"===()
{
uint32_t RequiredWorkGroupSizeX;// = 0
uint32_t RequiredWorkGroupSizeY;// = 0
uint32_t RequiredWorkGroupSizeZ;// = 0
uint32_t LargestCompiledSIMDSize;// = 32
uint32_t CompiledSubGroupsNumber;// = 0
uint32_t HasBarriers;// = 0
uint32_t DisableMidThreadPreemption;// = 0
uint32_t CompiledSIMD8;// = 0
uint32_t CompiledSIMD16;// = 0
uint32_t CompiledSIMD32;// = 1
uint32_t HasDeviceEnqueue;// = 0
uint32_t MayAccessUndeclaredResource;// = 0
uint32_t UsesFencesForReadWriteImages;// = 0
uint32_t UsesStatelessSpillFill;// = 0
uint32_t UsesMultiScratchSpaces;// = 0
uint32_t IsCoherent;// = 0
uint32_t IsInitializer;// = 0
uint32_t IsFinalizer;// = 0
uint32_t SubgroupIndependentForwardProgressRequired;// = 0
uint32_t CompiledForGreaterThan4GBBuffers;// = 0
uint32_t NumGRFRequired;// = 0
uint32_t WorkgroupWalkOrderDims;// = 0
uint32_t HasGlobalAtomics;// = 0
}
kernel[2] <UNNAMED>:
Kernel of size : 68 decoded successfully
Kernel of size : )==="
<< program.kernels[2].blobs.kernelInfo.size() << R"===( decoded successfully
struct SKernelBinaryHeader {
uint32_t CheckSum;// = 2446215414
uint32_t CheckSum;// = )==="
<< program.kernels[2].header->CheckSum << R"===(
uint64_t ShaderHashCode;// = 0
uint32_t KernelNameSize;// = 12
uint32_t PatchListSize;// = 16
uint32_t PatchListSize;// = )==="
<< program.kernels[2].header->PatchListSize << R"===(
};
Kernel-scope tokens section size : 0
Kernel-scope tokens section size : )==="
<< program.kernels[2].blobs.patchList.size() << R"===(
struct SPatchExecutionEnvironment :
SPatchItemHeader (Token=23(PATCH_TOKEN_EXECUTION_ENVIRONMENT), Size=)==="
<< sizeof(iOpenCL::SPatchExecutionEnvironment) << R"===()
{
uint32_t RequiredWorkGroupSizeX;// = 0
uint32_t RequiredWorkGroupSizeY;// = 0
uint32_t RequiredWorkGroupSizeZ;// = 0
uint32_t LargestCompiledSIMDSize;// = 32
uint32_t CompiledSubGroupsNumber;// = 0
uint32_t HasBarriers;// = 0
uint32_t DisableMidThreadPreemption;// = 0
uint32_t CompiledSIMD8;// = 0
uint32_t CompiledSIMD16;// = 0
uint32_t CompiledSIMD32;// = 1
uint32_t HasDeviceEnqueue;// = 0
uint32_t MayAccessUndeclaredResource;// = 0
uint32_t UsesFencesForReadWriteImages;// = 0
uint32_t UsesStatelessSpillFill;// = 0
uint32_t UsesMultiScratchSpaces;// = 0
uint32_t IsCoherent;// = 0
uint32_t IsInitializer;// = 0
uint32_t IsFinalizer;// = 0
uint32_t SubgroupIndependentForwardProgressRequired;// = 0
uint32_t CompiledForGreaterThan4GBBuffers;// = 0
uint32_t NumGRFRequired;// = 0
uint32_t WorkgroupWalkOrderDims;// = 0
uint32_t HasGlobalAtomics;// = 0
}
)===";
EXPECT_STREQ(expected.str().c_str(), generated.c_str());
}
@@ -428,14 +563,17 @@ TEST(KernelDumper, GivenKernelWithNonCrossthreadDataPatchtokensThenProperlyCreat
std::string generated = NEO::PatchTokenBinary::asString(kernel);
std::stringstream expected;
expected <<
R"===(Kernel of size : 52 decoded successfully
R"===(Kernel of size : )===" << kernel.blobs.kernelInfo.size() << R"===( decoded successfully
struct SKernelBinaryHeader {
uint32_t CheckSum;// = 3223116527
uint32_t CheckSum;// = )==="
<< kernel.header->CheckSum << R"===(
uint64_t ShaderHashCode;// = 0
uint32_t KernelNameSize;// = 12
uint32_t PatchListSize;// = 0
uint32_t PatchListSize;// = )==="
<< kernel.header->PatchListSize << R"===(
};
Kernel-scope tokens section size : 0
Kernel-scope tokens section size : )==="
<< kernel.blobs.patchList.size() << R"===(
WARNING : Unhandled kernel-scope tokens detected [2] :
+ [0]:
| struct SPatchItemHeader {
@@ -613,7 +751,8 @@ Kernel-scope tokens section size : 0
}
struct SPatchItemHeader {
uint32_t Token;// = 50(PATCH_TOKEN_INLINE_VME_SAMPLER_INFO)
uint32_t Size;// = 8
uint32_t Size;// = )==="
<< sizeof(SPatchItemHeader) << R"===(
};
struct SPatchGtpinFreeGRFInfo :
SPatchItemHeader (Token=51(PATCH_TOKEN_GTPIN_FREE_GRF_INFO), Size=)==="
@@ -637,7 +776,8 @@ Kernel-scope tokens section size : 0
}
struct SPatchItemHeader {
uint32_t Token;// = 52(PATCH_TOKEN_GTPIN_INFO)
uint32_t Size;// = 8
uint32_t Size;// = )==="
<< sizeof(SPatchItemHeader) << R"===(
};
struct SPatchFunctionTableInfo :
SPatchItemHeader (Token=53(PATCH_TOKEN_PROGRAM_SYMBOL_TABLE), Size=)==="
@@ -679,14 +819,45 @@ TEST(KernelDumper, GivenKernelWithStringPatchTokensThenProperlyCreatesDump) {
kernel.tokens.strings.push_back(reinterpret_cast<iOpenCL::SPatchString *>(strTokStream.data() + string2Off));
std::string generated = NEO::PatchTokenBinary::asString(kernel);
std::stringstream expected;
expected << R"===(Kernel of size : 52 decoded successfully
expected << R"===(Kernel of size : )===" << kernel.blobs.kernelInfo.size() << R"===( decoded successfully
struct SKernelBinaryHeader {
uint32_t CheckSum;// = 3223116527
uint32_t CheckSum;// = )==="
<< kernel.header->CheckSum << R"===(
uint64_t ShaderHashCode;// = 0
uint32_t KernelNameSize;// = 12
uint32_t PatchListSize;// = 0
uint32_t PatchListSize;// = )==="
<< kernel.header->PatchListSize << R"===(
};
Kernel-scope tokens section size : 0
Kernel-scope tokens section size : )==="
<< kernel.blobs.patchList.size() << R"===(
struct SPatchExecutionEnvironment :
SPatchItemHeader (Token=23(PATCH_TOKEN_EXECUTION_ENVIRONMENT), Size=)==="
<< sizeof(iOpenCL::SPatchExecutionEnvironment) << R"===()
{
uint32_t RequiredWorkGroupSizeX;// = 0
uint32_t RequiredWorkGroupSizeY;// = 0
uint32_t RequiredWorkGroupSizeZ;// = 0
uint32_t LargestCompiledSIMDSize;// = 32
uint32_t CompiledSubGroupsNumber;// = 0
uint32_t HasBarriers;// = 0
uint32_t DisableMidThreadPreemption;// = 0
uint32_t CompiledSIMD8;// = 0
uint32_t CompiledSIMD16;// = 0
uint32_t CompiledSIMD32;// = 1
uint32_t HasDeviceEnqueue;// = 0
uint32_t MayAccessUndeclaredResource;// = 0
uint32_t UsesFencesForReadWriteImages;// = 0
uint32_t UsesStatelessSpillFill;// = 0
uint32_t UsesMultiScratchSpaces;// = 0
uint32_t IsCoherent;// = 0
uint32_t IsInitializer;// = 0
uint32_t IsFinalizer;// = 0
uint32_t SubgroupIndependentForwardProgressRequired;// = 0
uint32_t CompiledForGreaterThan4GBBuffers;// = 0
uint32_t NumGRFRequired;// = 0
uint32_t WorkgroupWalkOrderDims;// = 0
uint32_t HasGlobalAtomics;// = 0
}
String literals [3] :
+ [0]:
| struct SPatchString :
@@ -787,14 +958,17 @@ TEST(KernelDumper, GivenKernelWithNonArgCrossThreadDataPatchtokensThenProperlyCr
std::string generated = NEO::PatchTokenBinary::asString(kernel);
static constexpr auto tokenSize = sizeof(SPatchDataParameterBuffer);
std::stringstream expected;
expected << R"===(Kernel of size : 52 decoded successfully
expected << R"===(Kernel of size : )===" << kernel.blobs.kernelInfo.size() << R"===( decoded successfully
struct SKernelBinaryHeader {
uint32_t CheckSum;// = 3223116527
uint32_t CheckSum;// = )==="
<< kernel.header->CheckSum << R"===(
uint64_t ShaderHashCode;// = 0
uint32_t KernelNameSize;// = 12
uint32_t PatchListSize;// = 0
uint32_t PatchListSize;// = )==="
<< kernel.header->PatchListSize << R"===(
};
Kernel-scope tokens section size : 0
Kernel-scope tokens section size : )==="
<< kernel.blobs.patchList.size() << R"===(
WARNING : Unhandled kernel-scope tokens detected [2] :
+ [0]:
| struct SPatchDataParameterBuffer :
@@ -826,6 +1000,34 @@ Kernel-scope tokens section size : 0
| uint32_t LocationIndex2;// = 0
| uint32_t IsEmulationArgument;// = 0
| }
struct SPatchExecutionEnvironment :
SPatchItemHeader (Token=23(PATCH_TOKEN_EXECUTION_ENVIRONMENT), Size=)==="
<< sizeof(iOpenCL::SPatchExecutionEnvironment) << R"===()
{
uint32_t RequiredWorkGroupSizeX;// = 0
uint32_t RequiredWorkGroupSizeY;// = 0
uint32_t RequiredWorkGroupSizeZ;// = 0
uint32_t LargestCompiledSIMDSize;// = 32
uint32_t CompiledSubGroupsNumber;// = 0
uint32_t HasBarriers;// = 0
uint32_t DisableMidThreadPreemption;// = 0
uint32_t CompiledSIMD8;// = 0
uint32_t CompiledSIMD16;// = 0
uint32_t CompiledSIMD32;// = 1
uint32_t HasDeviceEnqueue;// = 0
uint32_t MayAccessUndeclaredResource;// = 0
uint32_t UsesFencesForReadWriteImages;// = 0
uint32_t UsesStatelessSpillFill;// = 0
uint32_t UsesMultiScratchSpaces;// = 0
uint32_t IsCoherent;// = 0
uint32_t IsInitializer;// = 0
uint32_t IsFinalizer;// = 0
uint32_t SubgroupIndependentForwardProgressRequired;// = 0
uint32_t CompiledForGreaterThan4GBBuffers;// = 0
uint32_t NumGRFRequired;// = 0
uint32_t WorkgroupWalkOrderDims;// = 0
uint32_t HasGlobalAtomics;// = 0
}
localWorkSize [3] :
+ [0]:
| struct SPatchDataParameterBuffer :
@@ -1188,14 +1390,45 @@ TEST(KernelDumper, GivenKernelWithArgThenProperlyCreatesDump) {
kernel.tokens.kernelArgs.push_back(kernel.tokens.kernelArgs[0]);
auto generated = NEO::PatchTokenBinary::asString(kernel);
std::stringstream expected;
expected << R"===(Kernel of size : 52 decoded successfully
expected << R"===(Kernel of size : )===" << kernel.blobs.kernelInfo.size() << R"===( decoded successfully
struct SKernelBinaryHeader {
uint32_t CheckSum;// = 3223116527
uint32_t CheckSum;// = )==="
<< kernel.header->CheckSum << R"===(
uint64_t ShaderHashCode;// = 0
uint32_t KernelNameSize;// = 12
uint32_t PatchListSize;// = 0
uint32_t PatchListSize;// = )==="
<< kernel.header->PatchListSize << R"===(
};
Kernel-scope tokens section size : 0
Kernel-scope tokens section size : )==="
<< kernel.blobs.patchList.size() << R"===(
struct SPatchExecutionEnvironment :
SPatchItemHeader (Token=23(PATCH_TOKEN_EXECUTION_ENVIRONMENT), Size=)==="
<< sizeof(iOpenCL::SPatchExecutionEnvironment) << R"===()
{
uint32_t RequiredWorkGroupSizeX;// = 0
uint32_t RequiredWorkGroupSizeY;// = 0
uint32_t RequiredWorkGroupSizeZ;// = 0
uint32_t LargestCompiledSIMDSize;// = 32
uint32_t CompiledSubGroupsNumber;// = 0
uint32_t HasBarriers;// = 0
uint32_t DisableMidThreadPreemption;// = 0
uint32_t CompiledSIMD8;// = 0
uint32_t CompiledSIMD16;// = 0
uint32_t CompiledSIMD32;// = 1
uint32_t HasDeviceEnqueue;// = 0
uint32_t MayAccessUndeclaredResource;// = 0
uint32_t UsesFencesForReadWriteImages;// = 0
uint32_t UsesStatelessSpillFill;// = 0
uint32_t UsesMultiScratchSpaces;// = 0
uint32_t IsCoherent;// = 0
uint32_t IsInitializer;// = 0
uint32_t IsFinalizer;// = 0
uint32_t SubgroupIndependentForwardProgressRequired;// = 0
uint32_t CompiledForGreaterThan4GBBuffers;// = 0
uint32_t NumGRFRequired;// = 0
uint32_t WorkgroupWalkOrderDims;// = 0
uint32_t HasGlobalAtomics;// = 0
}
Kernel arguments [2] :
+ kernelArg[0]:
| Kernel argument of type unspecified
@@ -1831,13 +2064,14 @@ TEST(PatchTokenDumper, GivenAnyTokenThenDumpingIsHandled) {
iOpenCL::SPatchItemHeader *kernelToken = nullptr;
auto kernelToDecode = PatchTokensTestData::ValidEmptyKernel::create(kernelToDecodeStorage);
{
auto kernelPatchListOffset = kernelToDecodeStorage.size();
auto kernelPatchListOffset = ptrDiff(kernelToDecode.blobs.patchList.begin(), kernelToDecodeStorage.data());
kernelToDecodeStorage.resize(kernelToDecodeStorage.size() + maxTokenSize, 0U);
kernelToDecode.blobs.kernelInfo = ArrayRef<const uint8_t>(kernelToDecodeStorage.data(), kernelToDecodeStorage.data() + kernelToDecodeStorage.size());
kernelToDecode.blobs.patchList = ArrayRef<const uint8_t>(kernelToDecodeStorage.data() + kernelPatchListOffset, kernelToDecodeStorage.data() + kernelToDecodeStorage.size());
auto kernelHeaderMutable = reinterpret_cast<iOpenCL::SKernelBinaryHeaderCommon *>(&*(kernelToDecodeStorage.begin()));
kernelHeaderMutable->PatchListSize = static_cast<uint32_t>(kernelToDecode.blobs.patchList.size());
kernelToken = reinterpret_cast<iOpenCL::SPatchItemHeader *>(kernelToDecodeStorage.data() + kernelPatchListOffset);
kernelToDecode.tokens.executionEnvironment = reinterpret_cast<iOpenCL::SPatchExecutionEnvironment *>(kernelToDecodeStorage.data() + kernelPatchListOffset);
kernelToken = reinterpret_cast<iOpenCL::SPatchItemHeader *>(kernelToDecodeStorage.data() + kernelPatchListOffset + sizeof(iOpenCL::SPatchExecutionEnvironment));
}
kernelToken->Size = maxTokenSize;

View File

@@ -8,17 +8,81 @@
#pragma once
#include "runtime/compiler_interface/patchtokens_decoder.h"
#include "test.h"
#include "igfxfmid.h"
#include <vector>
extern GFXCORE_FAMILY renderCoreFamily;
namespace PatchTokensTestData {
template <typename TokenT>
inline TokenT initToken(iOpenCL::PATCH_TOKEN tok) {
TokenT ret = {};
ret.Size = sizeof(TokenT);
ret.Token = tok;
return ret;
}
inline iOpenCL::SPatchDataParameterBuffer initDataParameterBufferToken(iOpenCL::DATA_PARAMETER_TOKEN type, uint32_t sourceIndex = 0, uint32_t argNum = 0) {
iOpenCL::SPatchDataParameterBuffer tok = {};
tok.Size = static_cast<uint32_t>(sizeof(iOpenCL::SPatchDataParameterBuffer));
tok.Token = iOpenCL::PATCH_TOKEN_DATA_PARAMETER_BUFFER;
tok.Type = type;
tok.SourceOffset = sourceIndex * sizeof(uint32_t);
tok.ArgumentNumber = argNum;
return tok;
}
inline uint32_t pushBackString(const std::string &str, std::vector<uint8_t> &storage) {
auto offset = storage.size();
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(str.c_str()), reinterpret_cast<const uint8_t *>(str.c_str()) + str.size());
return static_cast<uint32_t>(offset);
}
inline uint32_t pushBackStringToken(const std::string &str, uint32_t stringIndex, std::vector<uint8_t> &outStream) {
auto off = outStream.size();
outStream.reserve(outStream.size() + sizeof(iOpenCL::SPatchString) + str.length());
outStream.resize(outStream.size() + sizeof(iOpenCL::SPatchString));
iOpenCL::SPatchString *tok = reinterpret_cast<iOpenCL::SPatchString *>(outStream.data() + off);
*tok = initToken<iOpenCL::SPatchString>(iOpenCL::PATCH_TOKEN::PATCH_TOKEN_STRING);
tok->StringSize = static_cast<uint32_t>(str.length());
tok->Size += tok->StringSize;
tok->Index = stringIndex;
pushBackString(str, outStream);
return static_cast<uint32_t>(off);
};
inline uint32_t pushBackArgInfoToken(std::vector<uint8_t> &outStream,
uint32_t argNum = 0,
const std::string &addressQualifier = "__global", const std::string &accessQualifier = "read_write",
const std::string &argName = "custom_arg", const std::string &typeName = "int*;", std::string typeQualifier = "const") {
auto off = outStream.size();
iOpenCL::SPatchKernelArgumentInfo tok = {};
tok.Token = iOpenCL::PATCH_TOKEN_KERNEL_ARGUMENT_INFO;
tok.AddressQualifierSize = static_cast<uint32_t>(addressQualifier.size());
tok.AccessQualifierSize = static_cast<uint32_t>(accessQualifier.size());
tok.ArgumentNameSize = static_cast<uint32_t>(argName.size());
tok.TypeNameSize = static_cast<uint32_t>(typeName.size());
tok.TypeQualifierSize = static_cast<uint32_t>(typeQualifier.size());
tok.Size = sizeof(iOpenCL::SPatchKernelArgumentInfo) + tok.AddressQualifierSize + tok.AccessQualifierSize + tok.ArgumentNameSize + tok.TypeNameSize + tok.TypeQualifierSize;
outStream.insert(outStream.end(), reinterpret_cast<const uint8_t *>(&tok), reinterpret_cast<const uint8_t *>(&tok) + sizeof(tok));
pushBackString(addressQualifier, outStream);
pushBackString(accessQualifier, outStream);
pushBackString(argName, outStream);
pushBackString(typeName, outStream);
pushBackString(typeQualifier, outStream);
return static_cast<uint32_t>(off);
}
struct ValidEmptyProgram : NEO::PatchTokenBinary::ProgramFromPatchtokens {
ValidEmptyProgram() {
iOpenCL::SProgramBinaryHeader headerTok = {};
headerTok.Magic = iOpenCL::MAGIC_CL;
headerTok.Version = iOpenCL::CURRENT_ICBE_VERSION;
headerTok.Device = renderCoreFamily;
headerTok.GPUPointerSizeInBytes = sizeof(uintptr_t);
this->decodeStatus = NEO::PatchTokenBinary::DecoderError::Success;
storage.insert(storage.end(), reinterpret_cast<uint8_t *>(&headerTok), reinterpret_cast<uint8_t *>((&headerTok) + 1));
@@ -160,6 +224,10 @@ struct ValidEmptyKernel {
static NEO::PatchTokenBinary::KernelFromPatchtokens create(std::vector<uint8_t> &storage) {
NEO::PatchTokenBinary::KernelFromPatchtokens ret;
iOpenCL::SKernelBinaryHeaderCommon headerTokInl = {};
auto execEnvTokInl = initToken<iOpenCL::SPatchExecutionEnvironment>(iOpenCL::PATCH_TOKEN_EXECUTION_ENVIRONMENT);
execEnvTokInl.LargestCompiledSIMDSize = 32U;
execEnvTokInl.CompiledSIMD32 = 1U;
headerTokInl.PatchListSize = sizeof(execEnvTokInl);
ret.decodeStatus = NEO::PatchTokenBinary::DecoderError::Success;
ret.name = "test_kernel";
headerTokInl.KernelNameSize = static_cast<uint32_t>(ret.name.size());
@@ -170,8 +238,12 @@ struct ValidEmptyKernel {
auto headerTok = reinterpret_cast<iOpenCL::SKernelBinaryHeaderCommon *>(&*(storage.begin() + kernOffset));
ret.NEO::PatchTokenBinary::KernelFromPatchtokens::header = headerTok;
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(ret.name.begin()), reinterpret_cast<const uint8_t *>(ret.name.end()));
ret.blobs.kernelInfo = ArrayRef<const uint8_t>(storage.data() + kernOffset, storage.data() + storage.size());
auto execEnvOffset = storage.size();
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&execEnvTokInl), reinterpret_cast<const uint8_t *>((&execEnvTokInl) + 1));
ret.blobs.kernelInfo = ArrayRef<const uint8_t>(storage.data() + kernOffset, storage.data() + kernOffset + storage.size());
headerTok->CheckSum = NEO::PatchTokenBinary::calcKernelChecksum(ret.blobs.kernelInfo);
ret.blobs.patchList = ArrayRef<const uint8_t>(storage.data() + execEnvOffset, storage.data() + storage.size());
ret.tokens.executionEnvironment = reinterpret_cast<iOpenCL::SPatchExecutionEnvironment *>(storage.data() + execEnvOffset);
return ret;
}
};
@@ -182,6 +254,7 @@ struct ValidProgramWithKernel : ValidEmptyProgram {
kernOffset = storage.size();
this->kernels.push_back(ValidEmptyKernel::create(storage));
this->kernels[0].decodeStatus = NEO::PatchTokenBinary::DecoderError::Success;
kernExecEnvOffset = ptrDiff(this->kernels[0].blobs.patchList.begin(), storage.data());
recalcTokPtr();
}
@@ -190,16 +263,25 @@ struct ValidProgramWithKernel : ValidEmptyProgram {
this->kernels[0].blobs.kernelInfo = ArrayRef<const uint8_t>(storage.data() + kernOffset, storage.data() + storage.size());
kernelHeaderMutable = reinterpret_cast<iOpenCL::SKernelBinaryHeaderCommon *>(&*(storage.begin() + kernOffset));
this->kernels[0].header = kernelHeaderMutable;
char *name = reinterpret_cast<char *>(storage.data() + kernOffset + sizeof(iOpenCL::SKernelBinaryHeaderCommon));
this->kernels[0].name = ArrayRef<const char>(name, name + kernelHeaderMutable->KernelNameSize);
kernelExecEnvMutable = reinterpret_cast<iOpenCL::SPatchExecutionEnvironment *>(&*(storage.begin() + kernExecEnvOffset));
this->kernels[0].tokens.executionEnvironment = kernelExecEnvMutable;
this->kernels[0].blobs.patchList = ArrayRef<const uint8_t>(storage.data() + kernExecEnvOffset, storage.data() + storage.size());
this->kernelHeaderMutable->PatchListSize = static_cast<uint32_t>(this->kernels[0].blobs.patchList.size());
kernelHeaderMutable->CheckSum = NEO::PatchTokenBinary::calcKernelChecksum(this->kernels[0].blobs.kernelInfo);
}
size_t kernOffset = 0U;
size_t kernExecEnvOffset = 0U;
iOpenCL::SKernelBinaryHeaderCommon *kernelHeaderMutable = nullptr;
iOpenCL::SPatchExecutionEnvironment *kernelExecEnvMutable = nullptr;
};
struct ValidProgramWithKernelUsingSlm : ValidProgramWithKernel {
ValidProgramWithKernelUsingSlm() {
patchlistOffset = storage.size();
slmMutableOffset = storage.size();
iOpenCL::SPatchAllocateLocalSurface slmTok = {};
slmTok.Token = iOpenCL::PATCH_TOKEN_ALLOCATE_LOCAL_SURFACE;
slmTok.Size = sizeof(slmTok);
@@ -210,73 +292,42 @@ struct ValidProgramWithKernelUsingSlm : ValidProgramWithKernel {
void recalcTokPtr() {
ValidProgramWithKernel::recalcTokPtr();
this->kernels[0].blobs.patchList = ArrayRef<const uint8_t>(storage.data() + patchlistOffset, storage.data() + storage.size());
slmMutable = reinterpret_cast<iOpenCL::SPatchAllocateLocalSurface *>(storage.data() + patchlistOffset);
slmMutable = reinterpret_cast<iOpenCL::SPatchAllocateLocalSurface *>(storage.data() + slmMutableOffset);
this->kernels[0].tokens.allocateLocalSurface = slmMutable;
this->kernelHeaderMutable->PatchListSize = static_cast<uint32_t>(this->kernels[0].blobs.patchList.size());
}
iOpenCL::SPatchAllocateLocalSurface *slmMutable = nullptr;
size_t patchlistOffset = 0U;
size_t slmMutableOffset = 0U;
};
template <typename TokenT>
inline TokenT initToken(iOpenCL::PATCH_TOKEN tok) {
TokenT ret = {};
ret.Size = sizeof(TokenT);
ret.Token = tok;
return ret;
}
struct ValidProgramWithKernelAndArg : ValidProgramWithKernel {
ValidProgramWithKernelAndArg() {
kernelArgOffset = storage.size();
inline iOpenCL::SPatchDataParameterBuffer initDataParameterBufferToken(iOpenCL::DATA_PARAMETER_TOKEN type, uint32_t sourceIndex = 0, uint32_t argNum = 0) {
iOpenCL::SPatchDataParameterBuffer tok = {};
tok.Size = static_cast<uint32_t>(sizeof(iOpenCL::SPatchDataParameterBuffer));
tok.Token = iOpenCL::PATCH_TOKEN_DATA_PARAMETER_BUFFER;
tok.Type = type;
tok.SourceOffset = sourceIndex * sizeof(uint32_t);
tok.ArgumentNumber = argNum;
return tok;
}
pushBackArgInfoToken(storage);
this->kernels[0].tokens.kernelArgs.resize(1);
inline uint32_t pushBackString(const std::string &str, std::vector<uint8_t> &storage) {
auto offset = storage.size();
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(str.c_str()), reinterpret_cast<const uint8_t *>(str.c_str()) + str.size());
return static_cast<uint32_t>(offset);
}
recalcTokPtr();
}
inline uint32_t pushBackStringToken(const std::string &str, uint32_t stringIndex, std::vector<uint8_t> &outStream) {
auto off = outStream.size();
outStream.reserve(outStream.size() + sizeof(iOpenCL::SPatchString) + str.length());
outStream.resize(outStream.size() + sizeof(iOpenCL::SPatchString));
iOpenCL::SPatchString *tok = reinterpret_cast<iOpenCL::SPatchString *>(outStream.data() + off);
*tok = initToken<iOpenCL::SPatchString>(iOpenCL::PATCH_TOKEN::PATCH_TOKEN_STRING);
tok->StringSize = static_cast<uint32_t>(str.length());
tok->Size += tok->StringSize;
tok->Index = stringIndex;
pushBackString(str, outStream);
return static_cast<uint32_t>(off);
void recalcTokPtr() {
ValidProgramWithKernel::recalcTokPtr();
arg0InfoMutable = reinterpret_cast<iOpenCL::SPatchKernelArgumentInfo *>(storage.data() + kernelArgOffset);
this->kernels[0].tokens.kernelArgs[0].argInfo = arg0InfoMutable;
arg0InfoAddressQualifierMutable = reinterpret_cast<char *>(arg0InfoMutable + 1);
arg0InfoAccessQualifierMutable = arg0InfoAddressQualifierMutable + arg0InfoMutable->AddressQualifierSize;
arg0NameMutable = arg0InfoAccessQualifierMutable + arg0InfoMutable->AccessQualifierSize;
arg0TypeMutable = arg0NameMutable + arg0InfoMutable->ArgumentNameSize;
arg0TypeQualifierMutable = arg0TypeMutable + arg0InfoMutable->TypeNameSize;
}
iOpenCL::SPatchKernelArgumentInfo *arg0InfoMutable = nullptr;
char *arg0InfoAddressQualifierMutable = nullptr;
char *arg0InfoAccessQualifierMutable = nullptr;
char *arg0NameMutable = nullptr;
char *arg0TypeMutable = nullptr;
char *arg0TypeQualifierMutable = nullptr;
size_t kernelArgOffset = 0U;
};
inline uint32_t pushBackArgInfoToken(std::vector<uint8_t> &outStream,
uint32_t argNum = 0,
const std::string &addressQualifier = "__global", const std::string &accessQualifier = "read_write",
const std::string &argName = "custom_arg", const std::string &typeName = "int*;", std::string typeQualifier = "const") {
auto off = outStream.size();
iOpenCL::SPatchKernelArgumentInfo tok = {};
tok.Token = iOpenCL::PATCH_TOKEN_KERNEL_ARGUMENT_INFO;
tok.AddressQualifierSize = static_cast<uint32_t>(addressQualifier.size());
tok.AccessQualifierSize = static_cast<uint32_t>(accessQualifier.size());
tok.ArgumentNameSize = static_cast<uint32_t>(argName.size());
tok.TypeNameSize = static_cast<uint32_t>(typeName.size());
tok.TypeQualifierSize = static_cast<uint32_t>(typeQualifier.size());
tok.Size = sizeof(iOpenCL::SPatchKernelArgumentInfo) + tok.AddressQualifierSize + tok.AccessQualifierSize + tok.ArgumentNameSize + tok.TypeNameSize + tok.TypeQualifierSize;
outStream.insert(outStream.end(), reinterpret_cast<const uint8_t *>(&tok), reinterpret_cast<const uint8_t *>(&tok) + sizeof(tok));
pushBackString(addressQualifier, outStream);
pushBackString(accessQualifier, outStream);
pushBackString(argName, outStream);
pushBackString(typeName, outStream);
pushBackString(typeQualifier, outStream);
return static_cast<uint32_t>(off);
}
} // namespace PatchTokensTestData

View File

@@ -7,8 +7,9 @@
#include "runtime/compiler_interface/patchtokens_decoder.h"
#include "runtime/compiler_interface/patchtokens_validator.inl"
#include "test.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "patchtokens_tests.h"
struct UknownTokenValidator {
@@ -25,8 +26,8 @@ TEST(PatchtokensValidator, GivenValidProgramThenValidationSucceeds) {
std::string error, warning;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_EQ(0U, error.size());
EXPECT_EQ(0U, warning.size());
EXPECT_TRUE(error.empty());
EXPECT_TRUE(warning.empty());
}
TEST(PatchtokensValidator, GivenProgramWithInvalidOrUnknownStatusThenValidationFails) {
@@ -36,7 +37,7 @@ TEST(PatchtokensValidator, GivenProgramWithInvalidOrUnknownStatusThenValidationF
prog.decodeStatus = NEO::PatchTokenBinary::DecoderError::Undefined;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_STREQ("ProgramFromPatchtokens wasn't successfully decoded", error.c_str());
EXPECT_EQ(0U, warning.size());
EXPECT_TRUE(warning.empty());
error.clear();
warning.clear();
@@ -44,7 +45,7 @@ TEST(PatchtokensValidator, GivenProgramWithInvalidOrUnknownStatusThenValidationF
prog.decodeStatus = NEO::PatchTokenBinary::DecoderError::InvalidBinary;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_STREQ("ProgramFromPatchtokens wasn't successfully decoded", error.c_str());
EXPECT_EQ(0U, warning.size());
EXPECT_TRUE(warning.empty());
}
TEST(PatchtokensValidator, GivenValidProgramWithASingleConstantSurfaceThenValidationSucceeds) {
@@ -52,8 +53,8 @@ TEST(PatchtokensValidator, GivenValidProgramWithASingleConstantSurfaceThenValida
std::string error, warning;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_EQ(0U, error.size());
EXPECT_EQ(0U, warning.size());
EXPECT_TRUE(error.empty());
EXPECT_TRUE(warning.empty());
}
TEST(PatchtokensValidator, GivenProgramWithMultipleConstantSurfacesThenValidationFails) {
@@ -64,7 +65,7 @@ TEST(PatchtokensValidator, GivenProgramWithMultipleConstantSurfacesThenValidatio
prog.programScopeTokens.allocateConstantMemorySurface.push_back(&constSurface2);
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_STREQ("Unhandled number of global constants surfaces > 1", error.c_str());
EXPECT_EQ(0U, warning.size());
EXPECT_TRUE(warning.empty());
}
TEST(PatchtokensValidator, GivenValidProgramWithASingleGlobalSurfaceThenValidationSucceeds) {
@@ -72,8 +73,8 @@ TEST(PatchtokensValidator, GivenValidProgramWithASingleGlobalSurfaceThenValidati
std::string error, warning;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_EQ(0U, error.size());
EXPECT_EQ(0U, warning.size());
EXPECT_TRUE(error.empty());
EXPECT_TRUE(warning.empty());
}
TEST(PatchtokensValidator, GivenProgramWithMultipleGlobalSurfacesThenValidationFails) {
@@ -84,7 +85,7 @@ TEST(PatchtokensValidator, GivenProgramWithMultipleGlobalSurfacesThenValidationF
prog.programScopeTokens.allocateGlobalMemorySurface.push_back(&globSurface2);
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_STREQ("Unhandled number of global variables surfaces > 1", error.c_str());
EXPECT_EQ(0U, warning.size());
EXPECT_TRUE(warning.empty());
}
TEST(PatchtokensValidator, GivenValidProgramWithValidConstantPointerThenValidationSucceeds) {
@@ -92,8 +93,8 @@ TEST(PatchtokensValidator, GivenValidProgramWithValidConstantPointerThenValidati
std::string error, warning;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_EQ(0U, error.size());
EXPECT_EQ(0U, warning.size());
EXPECT_TRUE(error.empty());
EXPECT_TRUE(warning.empty());
}
TEST(PatchtokensValidator, GivenProgramWithInvalidConstantPointerBufferIndexThenValidationFails) {
@@ -103,7 +104,44 @@ TEST(PatchtokensValidator, GivenProgramWithInvalidConstantPointerBufferIndexThen
prog.constantPointerMutable->BufferIndex = 1;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_STREQ("Unhandled SPatchConstantPointerProgramBinaryInfo", error.c_str());
EXPECT_EQ(0U, warning.size());
EXPECT_TRUE(warning.empty());
}
TEST(PatchtokensValidator, GivenProgramWithInvalidGpuPointerSizeThenValidationFails) {
PatchTokensTestData::ValidEmptyProgram prog;
std::string error, warning;
prog.headerMutable->GPUPointerSizeInBytes = 0U;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_STREQ("Invalid pointer size", error.c_str());
EXPECT_TRUE(warning.empty());
prog.headerMutable->GPUPointerSizeInBytes = 1U;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
prog.headerMutable->GPUPointerSizeInBytes = 2U;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
prog.headerMutable->GPUPointerSizeInBytes = 3U;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
prog.headerMutable->GPUPointerSizeInBytes = 4U;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
prog.headerMutable->GPUPointerSizeInBytes = 5U;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
prog.headerMutable->GPUPointerSizeInBytes = 6U;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
prog.headerMutable->GPUPointerSizeInBytes = 7U;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
prog.headerMutable->GPUPointerSizeInBytes = 8U;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
prog.headerMutable->GPUPointerSizeInBytes = 9U;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
}
TEST(PatchtokensValidator, GivenProgramWithInvalidConstantPointerConstantBufferIndexThenValidationFails) {
@@ -113,7 +151,7 @@ TEST(PatchtokensValidator, GivenProgramWithInvalidConstantPointerConstantBufferI
prog.constantPointerMutable->ConstantBufferIndex = 1;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_STREQ("Unhandled SPatchConstantPointerProgramBinaryInfo", error.c_str());
EXPECT_EQ(0U, warning.size());
EXPECT_TRUE(warning.empty());
}
TEST(PatchtokensValidator, GivenProgramWithInvalidConstantPointerBufferTypeThenValidationFails) {
@@ -123,7 +161,7 @@ TEST(PatchtokensValidator, GivenProgramWithInvalidConstantPointerBufferTypeThenV
prog.constantPointerMutable->BufferType = iOpenCL::NUM_PROGRAM_SCOPE_BUFFER_TYPE;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_STREQ("Unhandled SPatchConstantPointerProgramBinaryInfo", error.c_str());
EXPECT_EQ(0U, warning.size());
EXPECT_TRUE(warning.empty());
}
TEST(PatchtokensValidator, GivenProgramWithInvalidConstantPointerOffsetThenValidationFails) {
@@ -133,7 +171,7 @@ TEST(PatchtokensValidator, GivenProgramWithInvalidConstantPointerOffsetThenValid
prog.constantPointerMutable->ConstantPointerOffset = prog.constSurfMutable->InlineDataSize;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_STREQ("Unhandled SPatchConstantPointerProgramBinaryInfo", error.c_str());
EXPECT_EQ(0U, warning.size());
EXPECT_TRUE(warning.empty());
}
TEST(PatchtokensValidator, GivenProgramWithoutConstantSurfaceButWithConstantPointerThenValidationFails) {
@@ -143,7 +181,7 @@ TEST(PatchtokensValidator, GivenProgramWithoutConstantSurfaceButWithConstantPoin
prog.programScopeTokens.allocateConstantMemorySurface.clear();
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_STREQ("Unhandled SPatchConstantPointerProgramBinaryInfo", error.c_str());
EXPECT_EQ(0U, warning.size());
EXPECT_TRUE(warning.empty());
}
TEST(PatchtokensValidator, GivenValidProgramWithValidGlobalPointerThenValidationSucceeds) {
@@ -151,8 +189,8 @@ TEST(PatchtokensValidator, GivenValidProgramWithValidGlobalPointerThenValidation
std::string error, warning;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_EQ(0U, error.size());
EXPECT_EQ(0U, warning.size());
EXPECT_TRUE(error.empty());
EXPECT_TRUE(warning.empty());
}
TEST(PatchtokensValidator, GivenValidProgramWithMixedGlobalVarAndConstSurfacesAndPointersThenValidationSucceeds) {
@@ -160,24 +198,24 @@ TEST(PatchtokensValidator, GivenValidProgramWithMixedGlobalVarAndConstSurfacesAn
std::string error, warning;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_EQ(0U, error.size());
EXPECT_EQ(0U, warning.size());
EXPECT_TRUE(error.empty());
EXPECT_TRUE(warning.empty());
}
TEST(PatchtokensValidator, GivenInvalidProgramWithMixedGlobalVarAndConstSurfacesAndPointersThenValidationSucceeds) {
TEST(PatchtokensValidator, GivenInvalidProgramWithMixedGlobalVarAndConstSurfacesAndPointersThenValidationFails) {
std::string error, warning;
PatchTokensTestData::ValidProgramWithGlobalSurfaceAndPointer progGlobalVar;
progGlobalVar.globalPointerMutable->BufferType = iOpenCL::PROGRAM_SCOPE_CONSTANT_BUFFER;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(progGlobalVar, 0U, UknownTokenValidator(), error, warning));
EXPECT_NE(0U, error.size());
EXPECT_EQ(0U, warning.size());
EXPECT_FALSE(error.empty());
EXPECT_TRUE(warning.empty());
PatchTokensTestData::ValidProgramWithConstantSurfaceAndPointer progConstVar;
progConstVar.constantPointerMutable->BufferType = iOpenCL::PROGRAM_SCOPE_GLOBAL_BUFFER;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(progGlobalVar, 0U, UknownTokenValidator(), error, warning));
EXPECT_NE(0U, error.size());
EXPECT_EQ(0U, warning.size());
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(progConstVar, 0U, UknownTokenValidator(), error, warning));
EXPECT_FALSE(error.empty());
EXPECT_TRUE(warning.empty());
}
TEST(PatchtokensValidator, GivenProgramWithInvalidGlobalPointerBufferIndexThenValidationFails) {
@@ -187,7 +225,7 @@ TEST(PatchtokensValidator, GivenProgramWithInvalidGlobalPointerBufferIndexThenVa
prog.globalPointerMutable->BufferIndex = 1;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_STREQ("Unhandled SPatchGlobalPointerProgramBinaryInfo", error.c_str());
EXPECT_EQ(0U, warning.size());
EXPECT_TRUE(warning.empty());
}
TEST(PatchtokensValidator, GivenProgramWithInvalidGlobalPointerGlobalBufferIndexThenValidationFails) {
@@ -197,7 +235,7 @@ TEST(PatchtokensValidator, GivenProgramWithInvalidGlobalPointerGlobalBufferIndex
prog.globalPointerMutable->GlobalBufferIndex = 1;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_STREQ("Unhandled SPatchGlobalPointerProgramBinaryInfo", error.c_str());
EXPECT_EQ(0U, warning.size());
EXPECT_TRUE(warning.empty());
}
TEST(PatchtokensValidator, GivenProgramWithInvalidGlobalPointerBufferTypeThenValidationFails) {
@@ -207,7 +245,7 @@ TEST(PatchtokensValidator, GivenProgramWithInvalidGlobalPointerBufferTypeThenVal
prog.globalPointerMutable->BufferType = iOpenCL::NUM_PROGRAM_SCOPE_BUFFER_TYPE;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_STREQ("Unhandled SPatchGlobalPointerProgramBinaryInfo", error.c_str());
EXPECT_EQ(0U, warning.size());
EXPECT_TRUE(warning.empty());
}
TEST(PatchtokensValidator, GivenProgramWithInvalidGlobalPointerOffsetThenValidationFails) {
@@ -217,7 +255,7 @@ TEST(PatchtokensValidator, GivenProgramWithInvalidGlobalPointerOffsetThenValidat
prog.globalPointerMutable->GlobalPointerOffset = prog.globalSurfMutable->InlineDataSize;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_STREQ("Unhandled SPatchGlobalPointerProgramBinaryInfo", error.c_str());
EXPECT_EQ(0U, warning.size());
EXPECT_TRUE(warning.empty());
}
TEST(PatchtokensValidator, GivenProgramWithoutGlobalSurfaceButWithGlobalPointerThenValidationFails) {
@@ -227,7 +265,7 @@ TEST(PatchtokensValidator, GivenProgramWithoutGlobalSurfaceButWithGlobalPointerT
prog.programScopeTokens.allocateGlobalMemorySurface.clear();
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_STREQ("Unhandled SPatchGlobalPointerProgramBinaryInfo", error.c_str());
EXPECT_EQ(0U, warning.size());
EXPECT_TRUE(warning.empty());
}
TEST(PatchtokensValidator, GivenValidProgramWithUnknownPatchTokenWhenUknownTokenCantBeSkippedThenValidationFails) {
@@ -240,7 +278,7 @@ TEST(PatchtokensValidator, GivenValidProgramWithUnknownPatchTokenWhenUknownToken
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(false), error, warning));
auto expectedError = "Unhandled required program-scope Patch Token : " + std::to_string(unknownToken.Token);
EXPECT_STREQ(expectedError.c_str(), error.c_str());
EXPECT_EQ(0U, warning.size());
EXPECT_TRUE(warning.empty());
}
TEST(PatchtokensValidator, GivenValidProgramWithUnknownPatchTokenWhenUknownTokenCanBeSkippedThenValidationSucceedsAndEmitsWarning) {
@@ -252,7 +290,7 @@ TEST(PatchtokensValidator, GivenValidProgramWithUnknownPatchTokenWhenUknownToken
prog.unhandledTokens.push_back(&unknownToken);
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
auto expectedWarning = "Unknown program-scope Patch Token : " + std::to_string(unknownToken.Token);
EXPECT_EQ(0U, error.size());
EXPECT_TRUE(error.empty());
EXPECT_STREQ(expectedWarning.c_str(), warning.c_str());
}
@@ -264,7 +302,7 @@ TEST(PatchtokensValidator, GivenProgramWithUnsupportedPatchTokenVersionThenValid
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
auto expectedError = "Unhandled Version of Patchtokens: expected: " + std::to_string(iOpenCL::CURRENT_ICBE_VERSION) + ", got: " + std::to_string(prog.header->Version);
EXPECT_STREQ(expectedError.c_str(), error.c_str());
EXPECT_EQ(0U, warning.size());
EXPECT_TRUE(warning.empty());
}
TEST(PatchtokensValidator, GivenProgramWithUnsupportedPlatformThenValidationFails) {
@@ -283,8 +321,8 @@ TEST(PatchtokensValidator, GivenValidProgramWithKernelThenValidationSucceeds) {
std::string error, warning;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_EQ(0U, error.size());
EXPECT_EQ(0U, warning.size());
EXPECT_TRUE(error.empty());
EXPECT_TRUE(warning.empty());
}
TEST(PatchtokensValidator, GivenProgramWithKernelWhenKernelHasInvalidOrUnknownStatusThenValidationFails) {
@@ -294,7 +332,7 @@ TEST(PatchtokensValidator, GivenProgramWithKernelWhenKernelHasInvalidOrUnknownSt
prog.kernels[0].decodeStatus = NEO::PatchTokenBinary::DecoderError::Undefined;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_STREQ("KernelFromPatchtokens wasn't successfully decoded", error.c_str());
EXPECT_EQ(0U, warning.size());
EXPECT_TRUE(warning.empty());
error.clear();
warning.clear();
@@ -302,7 +340,7 @@ TEST(PatchtokensValidator, GivenProgramWithKernelWhenKernelHasInvalidOrUnknownSt
prog.kernels[0].decodeStatus = NEO::PatchTokenBinary::DecoderError::InvalidBinary;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_STREQ("KernelFromPatchtokens wasn't successfully decoded", error.c_str());
EXPECT_EQ(0U, warning.size());
EXPECT_TRUE(warning.empty());
}
TEST(PatchtokensValidator, GivenProgramWithKernelWhenKernelHasInvalidChecksumThenValidationFails) {
@@ -312,7 +350,7 @@ TEST(PatchtokensValidator, GivenProgramWithKernelWhenKernelHasInvalidChecksumThe
prog.kernelHeaderMutable->CheckSum += 1;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_STREQ("KernelFromPatchtokens has invalid checksum", error.c_str());
EXPECT_EQ(0U, warning.size());
EXPECT_TRUE(warning.empty());
}
TEST(PatchtokensValidator, GivenValidProgramWithKernelUsingSlmThenValidationSucceeds) {
@@ -321,8 +359,8 @@ TEST(PatchtokensValidator, GivenValidProgramWithKernelUsingSlmThenValidationSucc
size_t slmSizeAvailable = 1 + prog.kernels[0].tokens.allocateLocalSurface->TotalInlineLocalMemorySize;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, slmSizeAvailable, UknownTokenValidator(), error, warning));
EXPECT_EQ(0U, error.size());
EXPECT_EQ(0U, warning.size());
EXPECT_TRUE(error.empty());
EXPECT_TRUE(warning.empty());
}
TEST(PatchtokensValidator, GivenProgramWithKernelUsingSlmWhenKernelRequiresTooMuchSlmThenValidationFails) {
@@ -332,7 +370,7 @@ TEST(PatchtokensValidator, GivenProgramWithKernelUsingSlmWhenKernelRequiresTooMu
size_t slmSizeAvailable = -1 + prog.kernels[0].tokens.allocateLocalSurface->TotalInlineLocalMemorySize;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::NotEnoughSlm, NEO::PatchTokenBinary::validate(prog, slmSizeAvailable, UknownTokenValidator(), error, warning));
EXPECT_STREQ("KernelFromPatchtokens requires too much SLM", error.c_str());
EXPECT_EQ(0U, warning.size());
EXPECT_TRUE(warning.empty());
}
TEST(PatchtokensValidator, GivenValidProgramWithKernelContainingUnknownPatchTokenWhenUknownTokenCantBeSkippedThenValidationFails) {
@@ -345,7 +383,7 @@ TEST(PatchtokensValidator, GivenValidProgramWithKernelContainingUnknownPatchToke
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(false), error, warning));
auto expectedError = "Unhandled required kernel-scope Patch Token : " + std::to_string(unknownToken.Token);
EXPECT_STREQ(expectedError.c_str(), error.c_str());
EXPECT_EQ(0U, warning.size());
EXPECT_TRUE(warning.empty());
}
TEST(PatchtokensValidator, GivenValidProgramWithKernelContainingUnknownPatchTokenWhenUknownTokenCanBeSkippedThenValidationSucceedsAndEmitsWarning) {
@@ -357,6 +395,145 @@ TEST(PatchtokensValidator, GivenValidProgramWithKernelContainingUnknownPatchToke
prog.kernels[0].unhandledTokens.push_back(&unknownToken);
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
auto expectedWarning = "Unknown kernel-scope Patch Token : " + std::to_string(unknownToken.Token);
EXPECT_EQ(0U, error.size());
EXPECT_TRUE(error.empty());
EXPECT_STREQ(expectedWarning.c_str(), warning.c_str());
}
TEST(PatchtokensValidator, GivenProgramWithKernelWhenKernelArgsHasProperQualifiersThenValidationSucceeds) {
PatchTokensTestData::ValidProgramWithKernelAndArg prog;
std::string error, warning;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
EXPECT_TRUE(error.empty());
EXPECT_TRUE(warning.empty());
}
TEST(PatchtokensValidator, GivenProgramWithKernelWhenKernelsArgDoesntHaveKernelArgInfoThenValidationFails) {
PatchTokensTestData::ValidProgramWithKernelAndArg prog;
std::string error, warning;
prog.kernels[0].tokens.kernelArgs[0].argInfo = nullptr;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
auto expectedError = "Missing kernelArgInfo";
EXPECT_STREQ(expectedError, error.c_str());
EXPECT_TRUE(warning.empty());
}
TEST(PatchtokensValidator, GivenProgramWithKernelWhenKernelsArgHasUnknownAddressSpaceThenValidationFails) {
PatchTokensTestData::ValidProgramWithKernelAndArg prog;
std::string error, warning;
prog.arg0InfoAddressQualifierMutable[2] = '\0';
prog.recalcTokPtr();
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
auto expectedError = "Unhandled address qualifier";
EXPECT_STREQ(expectedError, error.c_str());
EXPECT_TRUE(warning.empty());
}
TEST(PatchtokensValidator, GivenProgramWithKernelWhenKernelsArgHasUnknownAccessQualifierThenValidationFails) {
PatchTokensTestData::ValidProgramWithKernelAndArg prog;
std::string error, warning;
prog.arg0InfoAccessQualifierMutable[2] = '\0';
prog.recalcTokPtr();
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
auto expectedError = "Unhandled access qualifier";
EXPECT_STREQ(expectedError, error.c_str());
EXPECT_TRUE(warning.empty());
}
TEST(PatchtokensValidator, GivenKernelWhenExecutionEnvironmentIsMissingThenValidationFails) {
PatchTokensTestData::ValidProgramWithKernel prog;
std::string error, warning;
prog.kernels[0].tokens.executionEnvironment = nullptr;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
auto expectedError = "Missing execution environment";
EXPECT_STREQ(expectedError, error.c_str());
EXPECT_TRUE(warning.empty());
}
TEST(PatchtokensValidator, GivenKernelWhenExecutionEnvironmentHasInvalidSimdSizeThenValidationFails) {
PatchTokensTestData::ValidProgramWithKernel prog;
std::string error, warning;
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 0U;
prog.recalcTokPtr();
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
auto expectedError = "Invalid LargestCompiledSIMDSize";
EXPECT_STREQ(expectedError, error.c_str());
EXPECT_TRUE(warning.empty());
error.clear();
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 1U;
prog.recalcTokPtr();
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
EXPECT_TRUE(error.empty());
EXPECT_TRUE(warning.empty());
error.clear();
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 2U;
prog.recalcTokPtr();
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
EXPECT_STREQ(expectedError, error.c_str());
EXPECT_TRUE(warning.empty());
error.clear();
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 3U;
prog.recalcTokPtr();
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
EXPECT_STREQ(expectedError, error.c_str());
EXPECT_TRUE(warning.empty());
error.clear();
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 4U;
prog.recalcTokPtr();
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
EXPECT_STREQ(expectedError, error.c_str());
EXPECT_TRUE(warning.empty());
error.clear();
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 5U;
prog.recalcTokPtr();
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
EXPECT_STREQ(expectedError, error.c_str());
EXPECT_TRUE(warning.empty());
error.clear();
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 6U;
prog.recalcTokPtr();
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
EXPECT_STREQ(expectedError, error.c_str());
EXPECT_TRUE(warning.empty());
error.clear();
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 7U;
prog.recalcTokPtr();
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
EXPECT_STREQ(expectedError, error.c_str());
EXPECT_TRUE(warning.empty());
error.clear();
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 8U;
prog.recalcTokPtr();
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
EXPECT_TRUE(error.empty());
EXPECT_TRUE(warning.empty());
error.clear();
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 9U;
prog.recalcTokPtr();
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
EXPECT_STREQ(expectedError, error.c_str());
EXPECT_TRUE(warning.empty());
error.clear();
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 16U;
prog.recalcTokPtr();
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
EXPECT_TRUE(error.empty());
EXPECT_TRUE(warning.empty());
error.clear();
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 32U;
prog.recalcTokPtr();
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
EXPECT_TRUE(error.empty());
EXPECT_TRUE(warning.empty());
}

View File

@@ -440,8 +440,10 @@ TEST_F(PerformanceHintTest, givenPrintDriverDiagnosticsDebugModeEnabledWhenCallF
buffer.getGraphicsAllocation()->setAllocationType(GraphicsAllocation::AllocationType::BUFFER_COMPRESSED);
mockKernel.kernelInfo.kernelArgInfo.resize(1);
mockKernel.kernelInfo.kernelArgInfo.at(0).kernelArgPatchInfoVector.resize(1);
mockKernel.kernelInfo.kernelArgInfo.at(0).pureStatefulBufferAccess = false;
mockKernel.kernelInfo.kernelArgInfo[0].metadataExtended = std::make_unique<ArgTypeMetadataExtended>();
mockKernel.kernelInfo.kernelArgInfo[0].metadataExtended->argName = "arg0";
mockKernel.kernelInfo.kernelArgInfo[0].kernelArgPatchInfoVector.resize(1);
mockKernel.kernelInfo.kernelArgInfo[0].pureStatefulBufferAccess = false;
mockKernel.mockKernel->initialize();
mockKernel.mockKernel->auxTranslationRequired = true;
mockKernel.mockKernel->setArgBuffer(0, sizeof(cl_mem *), &clMem);
@@ -451,7 +453,7 @@ TEST_F(PerformanceHintTest, givenPrintDriverDiagnosticsDebugModeEnabledWhenCallF
mockKernel.mockKernel->fillWithBuffersForAuxTranslation(memObjects);
snprintf(expectedHint, DriverDiagnostics::maxHintStringSize, DriverDiagnostics::hintFormat[KERNEL_ARGUMENT_AUX_TRANSLATION],
mockKernel.mockKernel->getKernelInfo().name.c_str(), 0, mockKernel.mockKernel->getKernelInfo().kernelArgInfo.at(0).name.c_str());
mockKernel.mockKernel->getKernelInfo().name.c_str(), 0, mockKernel.mockKernel->getKernelInfo().kernelArgInfo.at(0).metadataExtended->argName.c_str());
std::string output = testing::internal::GetCapturedStdout();
EXPECT_NE(0u, output.size());

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017-2019 Intel Corporation
* Copyright (C) 2017-2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -10,6 +10,7 @@
#include "core/helpers/aligned_memory.h"
#include "core/helpers/string.h"
#include "core/memory_manager/graphics_allocation.h"
#include "core/program/program_info_from_patchtokens.h"
#include "runtime/compiler_interface/patchtokens_decoder.h"
void KernelDataTest::buildAndDecode() {
@@ -88,7 +89,9 @@ void KernelDataTest::buildAndDecode() {
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(kernelBlob, kernelFromPatchtokens);
EXPECT_TRUE(decodeSuccess);
program->populateKernelInfo(programFromPatchtokens, 0, error);
ProgramInfo programInfo;
NEO::populateProgramInfo(programInfo, programFromPatchtokens, DeviceInfoKernelPayloadConstants());
error = program->processProgramInfo(programInfo);
EXPECT_EQ(CL_SUCCESS, error);
// extract the kernel info

View File

@@ -22,7 +22,9 @@
#include "runtime/kernel/kernel.h"
#include "runtime/mem_obj/buffer.h"
#include "runtime/memory_manager/surface.h"
#include "runtime/program/create.inl"
#include "test.h"
#include "unit_tests/compiler_interface/patchtokens_tests.h"
#include "unit_tests/fixtures/context_fixture.h"
#include "unit_tests/fixtures/memory_management_fixture.h"
#include "unit_tests/fixtures/platform_fixture.h"
@@ -978,69 +980,25 @@ TEST_F(GTPinTests, givenInitializedGTPinInterfaceWhenKernelWithoutSSHIsUsedThenK
EXPECT_NE(nullptr, context);
auto pContext = castToObject<Context>(context);
// Prepare a kernel without SSH
char binary[1024] = {1, 2, 3, 4, 5, 6, 7, 8, 9, '\0'};
size_t binSize = 10;
MockProgram *pProgram = Program::createFromGenBinary<MockProgram>(*pDevice->getExecutionEnvironment(), pContext, &binary[0], binSize, false, &retVal);
ASSERT_NE(nullptr, pProgram);
EXPECT_EQ(CL_SUCCESS, retVal);
char *pBin = &binary[0];
SProgramBinaryHeader *pBHdr = (SProgramBinaryHeader *)pBin;
pBHdr->Magic = iOpenCL::MAGIC_CL;
pBHdr->Version = iOpenCL::CURRENT_ICBE_VERSION;
pBHdr->Device = pDevice->getHardwareInfo().platform.eRenderCoreFamily;
pBHdr->GPUPointerSizeInBytes = 8;
pBHdr->NumberOfKernels = 1;
pBHdr->SteppingId = 0;
pBHdr->PatchListSize = 0;
pBin += sizeof(SProgramBinaryHeader);
binSize += sizeof(SProgramBinaryHeader);
PatchTokensTestData::ValidProgramWithKernel programTokens;
SKernelBinaryHeaderCommon *pKHdr = (SKernelBinaryHeaderCommon *)pBin;
pKHdr->CheckSum = 0;
pKHdr->ShaderHashCode = 0;
pKHdr->KernelNameSize = 4;
pKHdr->PatchListSize = 0;
pKHdr->KernelHeapSize = 16;
pKHdr->GeneralStateHeapSize = 0;
pKHdr->DynamicStateHeapSize = 0;
pKHdr->SurfaceStateHeapSize = 0;
pKHdr->KernelUnpaddedSize = 0;
pBin += sizeof(SKernelBinaryHeaderCommon);
binSize += sizeof(SKernelBinaryHeaderCommon);
char *pKernelBin = pBin;
strcpy(pBin, "Tst");
pBin += pKHdr->KernelNameSize;
binSize += pKHdr->KernelNameSize;
strcpy(pBin, "fake_ISA_code__");
binSize += pKHdr->KernelHeapSize;
uint32_t kernelBinSize =
pKHdr->DynamicStateHeapSize +
pKHdr->GeneralStateHeapSize +
pKHdr->KernelHeapSize +
pKHdr->KernelNameSize +
pKHdr->PatchListSize +
pKHdr->SurfaceStateHeapSize;
uint64_t hashValue = Hash::hash(reinterpret_cast<const char *>(pKernelBin), kernelBinSize);
pKHdr->CheckSum = static_cast<uint32_t>(hashValue & 0xFFFFFFFF);
pProgram->genBinary = makeCopy(&binary[0], binSize);
pProgram->genBinarySize = binSize;
pProgram->genBinary = makeCopy(reinterpret_cast<char *>(programTokens.storage.data()), programTokens.storage.size());
pProgram->genBinarySize = programTokens.storage.size();
retVal = pProgram->processGenBinary();
EXPECT_EQ(CL_SUCCESS, retVal);
// Verify that GT-Pin Kernel Create callback is not called
int prevCount = KernelCreateCallbackCount;
cl_kernel kernel = clCreateKernel(pProgram, "Tst", &retVal);
cl_kernel kernel = clCreateKernel(pProgram, std::string(programTokens.kernels[0].name.begin(), programTokens.kernels[0].name.size()).c_str(), &retVal);
EXPECT_NE(nullptr, kernel);
EXPECT_EQ(CL_SUCCESS, retVal);
EXPECT_EQ(prevCount, KernelCreateCallbackCount);
// Cleanup
retVal = clReleaseKernel(kernel);
EXPECT_EQ(CL_SUCCESS, retVal);
@@ -2074,68 +2032,16 @@ TEST_F(GTPinTests, givenInitializedGTPinInterfaceWhenLowMemoryConditionOccursThe
EXPECT_NE(nullptr, context);
auto pContext = castToObject<Context>(context);
// Prepare a program with one kernel having Stateless Private Surface
char binary[1024] = {1, 2, 3, 4, 5, 6, 7, 8, 9, '\0'};
size_t binSize = 10;
MockProgram *pProgram = Program::createFromGenBinary<MockProgram>(*pDevice->getExecutionEnvironment(), pContext, &binary[0], binSize, false, &retVal);
ASSERT_NE(nullptr, pProgram);
EXPECT_EQ(CL_SUCCESS, retVal);
char *pBin = &binary[0];
SProgramBinaryHeader *pBHdr = (SProgramBinaryHeader *)pBin;
pBHdr->Magic = iOpenCL::MAGIC_CL;
pBHdr->Version = iOpenCL::CURRENT_ICBE_VERSION;
pBHdr->Device = pDevice->getHardwareInfo().platform.eRenderCoreFamily;
pBHdr->GPUPointerSizeInBytes = 8;
pBHdr->NumberOfKernels = 1;
pBHdr->SteppingId = 0;
pBHdr->PatchListSize = 0;
pBin += sizeof(SProgramBinaryHeader);
binSize += sizeof(SProgramBinaryHeader);
PatchTokensTestData::ValidProgramWithKernel programTokens;
SKernelBinaryHeaderCommon *pKHdr = (SKernelBinaryHeaderCommon *)pBin;
pKHdr->CheckSum = 0;
pKHdr->ShaderHashCode = 0;
pKHdr->KernelNameSize = 4;
pKHdr->PatchListSize = sizeof(SPatchAllocateStatelessPrivateSurface);
pKHdr->KernelHeapSize = 16;
pKHdr->GeneralStateHeapSize = 0;
pKHdr->DynamicStateHeapSize = 0;
pKHdr->SurfaceStateHeapSize = 0;
pKHdr->KernelUnpaddedSize = 0;
pBin += sizeof(SKernelBinaryHeaderCommon);
binSize += sizeof(SKernelBinaryHeaderCommon);
char *pKernelBin = pBin;
strcpy(pBin, "Tst");
pBin += pKHdr->KernelNameSize;
binSize += pKHdr->KernelNameSize;
strcpy(pBin, "fake_ISA_code__");
pBin += pKHdr->KernelHeapSize;
binSize += pKHdr->KernelHeapSize;
SPatchAllocateStatelessPrivateSurface *pPatch = (SPatchAllocateStatelessPrivateSurface *)pBin;
pPatch->Token = iOpenCL::PATCH_TOKEN_ALLOCATE_STATELESS_PRIVATE_MEMORY;
pPatch->Size = sizeof(iOpenCL::SPatchAllocateStatelessPrivateSurface);
pPatch->SurfaceStateHeapOffset = 0;
pPatch->DataParamOffset = 0;
pPatch->DataParamSize = 0;
pPatch->PerThreadPrivateMemorySize = 4;
binSize += sizeof(SPatchAllocateStatelessPrivateSurface);
uint32_t kernelBinSize =
pKHdr->DynamicStateHeapSize +
pKHdr->GeneralStateHeapSize +
pKHdr->KernelHeapSize +
pKHdr->KernelNameSize +
pKHdr->PatchListSize +
pKHdr->SurfaceStateHeapSize;
uint64_t hashValue = Hash::hash(reinterpret_cast<const char *>(pKernelBin), kernelBinSize);
pKHdr->CheckSum = static_cast<uint32_t>(hashValue & 0xFFFFFFFF);
pProgram->genBinary = makeCopy(&binary[0], binSize);
pProgram->genBinarySize = binSize;
pProgram->genBinary = makeCopy(programTokens.storage.data(), programTokens.storage.size());
pProgram->genBinarySize = programTokens.storage.size();
retVal = pProgram->processGenBinary();
if (retVal == CL_OUT_OF_HOST_MEMORY) {
auto nonFailingAlloc = MemoryManagement::nonfailingAllocation;
@@ -2430,64 +2336,17 @@ TEST_F(GTPinTests, givenInitializedGTPinInterfaceWhenOnContextCreateIsCalledThen
EXPECT_NE(gtpinGetIgcInit(), nullptr);
}
TEST_F(ProgramTests, givenGenBinaryWithGtpinInfoWhenProcessGenBinaryCalledThenGtpinInfoIsSet) {
cl_int retVal = CL_INVALID_BINARY;
char genBin[1024] = {1, 2, 3, 4, 5, 6, 7, 8, 9, '\0'};
size_t binSize = 10;
std::unique_ptr<MockProgram> pProgram(Program::createFromGenBinary<MockProgram>(*pDevice->getExecutionEnvironment(), nullptr, &genBin[0], binSize, false, &retVal));
EXPECT_NE(nullptr, pProgram.get());
EXPECT_EQ(CL_SUCCESS, retVal);
EXPECT_EQ((uint32_t)CL_PROGRAM_BINARY_TYPE_EXECUTABLE, (uint32_t)pProgram->getProgramBinaryType());
cl_device_id deviceId = pContext->getDevice(0);
ClDevice *pDevice = castToObject<ClDevice>(deviceId);
char *pBin = &genBin[0];
retVal = CL_INVALID_BINARY;
binSize = 0;
// Prepare simple program binary containing patch token PATCH_TOKEN_GLOBAL_MEMORY_OBJECT_KERNEL_ARGUMENT
SProgramBinaryHeader *pBHdr = (SProgramBinaryHeader *)pBin;
pBHdr->Magic = iOpenCL::MAGIC_CL;
pBHdr->Version = iOpenCL::CURRENT_ICBE_VERSION;
pBHdr->Device = pDevice->getHardwareInfo().platform.eRenderCoreFamily;
pBHdr->GPUPointerSizeInBytes = 8;
pBHdr->NumberOfKernels = 1;
pBHdr->SteppingId = 0;
pBHdr->PatchListSize = 0;
pBin += sizeof(SProgramBinaryHeader);
binSize += sizeof(SProgramBinaryHeader);
SKernelBinaryHeaderCommon *pKHdr = (SKernelBinaryHeaderCommon *)pBin;
pKHdr->CheckSum = 0;
pKHdr->ShaderHashCode = 0;
pKHdr->KernelNameSize = 8;
pKHdr->PatchListSize = 8;
pKHdr->KernelHeapSize = 0;
pKHdr->GeneralStateHeapSize = 0;
pKHdr->DynamicStateHeapSize = 0;
pKHdr->SurfaceStateHeapSize = 0;
pKHdr->KernelUnpaddedSize = 0;
pBin += sizeof(SKernelBinaryHeaderCommon);
binSize += sizeof(SKernelBinaryHeaderCommon);
strcpy(pBin, "TstCopy");
pBin += pKHdr->KernelNameSize;
binSize += pKHdr->KernelNameSize;
iOpenCL::SPatchItemHeader *pPatch = (iOpenCL::SPatchItemHeader *)pBin;
pPatch->Token = iOpenCL::PATCH_TOKEN_GTPIN_INFO;
pPatch->Size = sizeof(iOpenCL::SPatchItemHeader);
binSize += sizeof(iOpenCL::SPatchItemHeader);
pBin += sizeof(iOpenCL::SPatchItemHeader);
pKHdr->CheckSum = PatchTokenBinary::calcKernelChecksum(ArrayRef<const uint8_t>(reinterpret_cast<uint8_t *>(pKHdr), reinterpret_cast<uint8_t *>(pBin)));
// Decode prepared program binary
pProgram->genBinary = makeCopy(&genBin[0], binSize);
pProgram->genBinarySize = binSize;
retVal = pProgram->processGenBinary();
auto kernelInfo = pProgram->getKernelInfo("TstCopy");
EXPECT_NE(kernelInfo->igcInfoForGtpin, nullptr);
ASSERT_EQ(CL_SUCCESS, retVal);
TEST_F(GTPinTests, givenInitializedGTPinInterfaceWhenOnKernelCreateIsCalledWithNullptrThenCallIsIgnored) {
gtpinCallbacks.onContextCreate = OnContextCreate;
gtpinCallbacks.onContextDestroy = OnContextDestroy;
gtpinCallbacks.onKernelCreate = OnKernelCreate;
gtpinCallbacks.onKernelSubmit = OnKernelSubmit;
gtpinCallbacks.onCommandBufferCreate = OnCommandBufferCreate;
gtpinCallbacks.onCommandBufferComplete = OnCommandBufferComplete;
retFromGtPin = GTPin_Init(&gtpinCallbacks, &driverServices, nullptr);
auto prevCreateCount = KernelCreateCallbackCount;
gtpinNotifyKernelCreate(nullptr);
EXPECT_EQ(prevCreateCount, KernelCreateCallbackCount);
}
} // namespace ULT

View File

@@ -1,5 +1,5 @@
#
# Copyright (C) 2017-2019 Intel Corporation
# Copyright (C) 2017-2020 Intel Corporation
#
# SPDX-License-Identifier: MIT
#
@@ -16,6 +16,7 @@ set(IGDRCL_SRCS_tests_kernel
${CMAKE_CURRENT_SOURCE_DIR}/kernel_arg_pipe_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/kernel_arg_svm_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}${BRANCH_DIR_SUFFIX}/kernel_cache_flush_requirements_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/kernel_info_cl_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/kernel_image_arg_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/kernel_immediate_arg_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/kernel_is_patched_tests.cpp

View File

@@ -264,7 +264,7 @@ TEST_F(CloneKernelTest, cloneKernelWithArgImage) {
auto crossThreadData = reinterpret_cast<uint32_t *>(pClonedKernel->getCrossThreadData());
EXPECT_EQ(objectId, *crossThreadData);
auto argInfo = pClonedKernel->getKernelInfo().kernelArgInfo[0];
const auto &argInfo = pClonedKernel->getKernelInfo().kernelArgInfo[0];
auto pImgWidth = ptrOffset(crossThreadData, argInfo.offsetImgWidth);
EXPECT_EQ(imageWidth, *pImgWidth);
@@ -315,7 +315,7 @@ TEST_F(CloneKernelTest, cloneKernelWithArgAccelerator) {
auto crossThreadData = reinterpret_cast<uint32_t *>(pClonedKernel->getCrossThreadData());
auto argInfo = pClonedKernel->getKernelInfo().kernelArgInfo[0];
const auto &argInfo = pClonedKernel->getKernelInfo().kernelArgInfo[0];
uint32_t *pMbBlockType = ptrOffset(crossThreadData, argInfo.offsetVmeMbBlockType);
EXPECT_EQ(desc.mb_block_type, *pMbBlockType);
@@ -369,7 +369,7 @@ TEST_F(CloneKernelTest, cloneKernelWithArgSampler) {
auto crossThreadData = reinterpret_cast<uint32_t *>(pClonedKernel->getCrossThreadData());
EXPECT_EQ(objectId, *crossThreadData);
auto argInfo = pClonedKernel->getKernelInfo().kernelArgInfo[0];
const auto &argInfo = pClonedKernel->getKernelInfo().kernelArgInfo[0];
auto pSnapWa = ptrOffset(crossThreadData, argInfo.offsetSamplerSnapWa);
EXPECT_EQ(sampler->getSnapWaValue(), *pSnapWa);

View File

@@ -105,7 +105,7 @@ TEST_F(KernelArgAcceleratorTest, SetKernelArgValidAccelerator) {
char *crossThreadData = pKernel->getCrossThreadData();
auto arginfo = pKernelInfo->kernelArgInfo[0];
const auto &arginfo = pKernelInfo->kernelArgInfo[0];
uint32_t *pMbBlockType = ptrOffset(reinterpret_cast<uint32_t *>(crossThreadData),
arginfo.offsetVmeMbBlockType);

View File

@@ -191,3 +191,100 @@ INSTANTIATE_TEST_CASE_P(KernelArgInfoTests,
::testing::ValuesIn(SourceFileNames),
::testing::ValuesIn(BinaryForSourceFileNames),
::testing::ValuesIn(KernelNames)));
TEST(KernelArgMetadata, WhenParseAccessQualifierIsCalledThenQualifierIsProperlyParsed) {
using namespace NEO::KernelArgMetadata;
EXPECT_EQ(AccessQualifier::None, KernelArgMetadata::parseAccessQualifier(""));
EXPECT_EQ(AccessQualifier::None, KernelArgMetadata::parseAccessQualifier("NONE"));
EXPECT_EQ(AccessQualifier::ReadOnly, KernelArgMetadata::parseAccessQualifier("read_only"));
EXPECT_EQ(AccessQualifier::WriteOnly, KernelArgMetadata::parseAccessQualifier("write_only"));
EXPECT_EQ(AccessQualifier::ReadWrite, KernelArgMetadata::parseAccessQualifier("read_write"));
EXPECT_EQ(AccessQualifier::ReadOnly, KernelArgMetadata::parseAccessQualifier("__read_only"));
EXPECT_EQ(AccessQualifier::WriteOnly, KernelArgMetadata::parseAccessQualifier("__write_only"));
EXPECT_EQ(AccessQualifier::ReadWrite, KernelArgMetadata::parseAccessQualifier("__read_write"));
EXPECT_EQ(AccessQualifier::Unknown, KernelArgMetadata::parseAccessQualifier("re"));
EXPECT_EQ(AccessQualifier::Unknown, KernelArgMetadata::parseAccessQualifier("read"));
EXPECT_EQ(AccessQualifier::Unknown, KernelArgMetadata::parseAccessQualifier("write"));
}
TEST(KernelArgMetadata, WhenParseAddressQualifierIsCalledThenQualifierIsProperlyParsed) {
using namespace NEO::KernelArgMetadata;
EXPECT_EQ(AddressSpaceQualifier::Global, KernelArgMetadata::parseAddressSpace(""));
EXPECT_EQ(AddressSpaceQualifier::Global, KernelArgMetadata::parseAddressSpace("__global"));
EXPECT_EQ(AddressSpaceQualifier::Local, KernelArgMetadata::parseAddressSpace("__local"));
EXPECT_EQ(AddressSpaceQualifier::Private, KernelArgMetadata::parseAddressSpace("__private"));
EXPECT_EQ(AddressSpaceQualifier::Constant, KernelArgMetadata::parseAddressSpace("__constant"));
EXPECT_EQ(AddressSpaceQualifier::Private, KernelArgMetadata::parseAddressSpace("not_specified"));
EXPECT_EQ(AddressSpaceQualifier::Unknown, KernelArgMetadata::parseAddressSpace("wrong"));
EXPECT_EQ(AddressSpaceQualifier::Unknown, KernelArgMetadata::parseAddressSpace("__glob"));
EXPECT_EQ(AddressSpaceQualifier::Unknown, KernelArgMetadata::parseAddressSpace("__loc"));
EXPECT_EQ(AddressSpaceQualifier::Unknown, KernelArgMetadata::parseAddressSpace("__priv"));
EXPECT_EQ(AddressSpaceQualifier::Unknown, KernelArgMetadata::parseAddressSpace("__const"));
EXPECT_EQ(AddressSpaceQualifier::Unknown, KernelArgMetadata::parseAddressSpace("not"));
}
TEST(KernelArgMetadata, WhenParseTypeQualifiersIsCalledThenQualifierIsProperlyParsed) {
using namespace NEO::KernelArgMetadata;
TypeQualifiers qual = {};
EXPECT_EQ(qual.packed, KernelArgMetadata::parseTypeQualifiers("").packed);
qual = {};
qual.constQual = true;
EXPECT_EQ(qual.packed, KernelArgMetadata::parseTypeQualifiers("const").packed);
qual = {};
qual.volatileQual = true;
EXPECT_EQ(qual.packed, KernelArgMetadata::parseTypeQualifiers("volatile").packed);
qual = {};
qual.restrictQual = true;
EXPECT_EQ(qual.packed, KernelArgMetadata::parseTypeQualifiers("restrict").packed);
qual = {};
qual.pipeQual = true;
EXPECT_EQ(qual.packed, KernelArgMetadata::parseTypeQualifiers("pipe").packed);
qual = {};
qual.unknownQual = true;
EXPECT_EQ(qual.packed, KernelArgMetadata::parseTypeQualifiers("inval").packed);
EXPECT_EQ(qual.packed, KernelArgMetadata::parseTypeQualifiers("cons").packed);
EXPECT_EQ(qual.packed, KernelArgMetadata::parseTypeQualifiers("volat").packed);
EXPECT_EQ(qual.packed, KernelArgMetadata::parseTypeQualifiers("restr").packed);
EXPECT_EQ(qual.packed, KernelArgMetadata::parseTypeQualifiers("pip").packed);
qual = {};
qual.constQual = true;
qual.volatileQual = true;
EXPECT_EQ(qual.packed, KernelArgMetadata::parseTypeQualifiers("const volatile").packed);
qual = {};
qual.constQual = true;
qual.volatileQual = true;
qual.restrictQual = true;
qual.pipeQual = true;
EXPECT_EQ(qual.packed, KernelArgMetadata::parseTypeQualifiers("pipe const restrict volatile").packed);
qual = {};
qual.constQual = true;
qual.volatileQual = true;
qual.restrictQual = true;
qual.pipeQual = true;
qual.unknownQual = true;
EXPECT_EQ(qual.packed, KernelArgMetadata::parseTypeQualifiers("pipe const restrict volatile some").packed);
}
TEST(KernelArgMetadata, WhenParseLimitedStringIsCalledThenReturnedStringDoesntContainExcessiveTrailingZeroes) {
char str1[] = "abcd\0\0\0after\0";
EXPECT_STREQ("abcd", NEO::parseLimitedString(str1, sizeof(str1)).c_str());
EXPECT_EQ(4U, NEO::parseLimitedString(str1, sizeof(str1)).size());
EXPECT_STREQ("ab", NEO::parseLimitedString(str1, 2).c_str());
EXPECT_EQ(2U, NEO::parseLimitedString(str1, 2).size());
char str2[] = {'a', 'b', 'd', 'e', 'f'};
EXPECT_STREQ("abdef", NEO::parseLimitedString(str2, sizeof(str2)).c_str());
EXPECT_EQ(5U, NEO::parseLimitedString(str2, sizeof(str2)).size());
}

View File

@@ -118,7 +118,7 @@ TEST_F(KernelImageArgTest, givenImageWithWriteOnlyAccessAndReadOnlyArgWhenCheckC
imgDesc.image_height = 5;
auto surfaceFormat = Image::getSurfaceFormatFromTable(0, &imgFormat);
std::unique_ptr<Image> img(Image::create(context.get(), MemoryPropertiesFlagsParser::createMemoryPropertiesFlags(flags, 0, 0), flags, 0, surfaceFormat, &imgDesc, nullptr, retVal));
pKernelInfo->kernelArgInfo[0].accessQualifier = CL_KERNEL_ARG_ACCESS_READ_ONLY;
pKernelInfo->kernelArgInfo[0].metadata.accessQualifier = NEO::KernelArgMetadata::AccessQualifier::ReadOnly;
cl_mem memObj = img.get();
retVal = pKernel->checkCorrectImageAccessQualifier(0, sizeof(memObj), &memObj);
@@ -157,7 +157,7 @@ TEST_F(KernelImageArgTest, givenImageWithReadOnlyAccessAndWriteOnlyArgWhenCheckC
imgDesc.image_height = 5;
auto surfaceFormat = Image::getSurfaceFormatFromTable(0, &imgFormat);
std::unique_ptr<Image> img(Image::create(context.get(), MemoryPropertiesFlagsParser::createMemoryPropertiesFlags(flags, 0, 0), flags, 0, surfaceFormat, &imgDesc, nullptr, retVal));
pKernelInfo->kernelArgInfo[0].accessQualifier = CL_KERNEL_ARG_ACCESS_WRITE_ONLY;
pKernelInfo->kernelArgInfo[0].metadata.accessQualifier = NEO::KernelArgMetadata::AccessQualifier::WriteOnly;
cl_mem memObj = img.get();
retVal = pKernel->checkCorrectImageAccessQualifier(0, sizeof(memObj), &memObj);
@@ -177,7 +177,7 @@ TEST_F(KernelImageArgTest, givenImageWithReadOnlyAccessAndReadOnlyArgWhenCheckCo
imgDesc.image_height = 5;
auto surfaceFormat = Image::getSurfaceFormatFromTable(0, &imgFormat);
std::unique_ptr<Image> img(Image::create(context.get(), MemoryPropertiesFlagsParser::createMemoryPropertiesFlags(flags, 0, 0), flags, 0, surfaceFormat, &imgDesc, nullptr, retVal));
pKernelInfo->kernelArgInfo[0].accessQualifier = CL_KERNEL_ARG_ACCESS_READ_ONLY;
pKernelInfo->kernelArgInfo[0].metadata.accessQualifier = NEO::KernelArgMetadata::AccessQualifier::ReadOnly;
cl_mem memObj = img.get();
retVal = pKernel->checkCorrectImageAccessQualifier(0, sizeof(memObj), &memObj);
@@ -193,7 +193,7 @@ TEST_F(KernelImageArgTest, givenImageWithWriteOnlyAccessAndWriteOnlyArgWhenCheck
imgDesc.image_height = 5;
auto surfaceFormat = Image::getSurfaceFormatFromTable(0, &imgFormat);
std::unique_ptr<Image> img(Image::create(context.get(), MemoryPropertiesFlagsParser::createMemoryPropertiesFlags(flags, 0, 0), flags, 0, surfaceFormat, &imgDesc, nullptr, retVal));
pKernelInfo->kernelArgInfo[0].accessQualifier = CL_KERNEL_ARG_ACCESS_WRITE_ONLY;
pKernelInfo->kernelArgInfo[0].metadata.accessQualifier = NEO::KernelArgMetadata::AccessQualifier::WriteOnly;
cl_mem memObj = img.get();
retVal = pKernel->checkCorrectImageAccessQualifier(0, sizeof(memObj), &memObj);

View File

@@ -0,0 +1,61 @@
/*
* Copyright (C) 2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "runtime/kernel/kernel_info_cl.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
TEST(AsClConvertersTest, whenConvertingAccessQualifiersThenProperEnumValuesAreReturned) {
using namespace NEO::KernelArgMetadata;
EXPECT_EQ(static_cast<cl_kernel_arg_access_qualifier>(CL_KERNEL_ARG_ACCESS_NONE), NEO::asClKernelArgAccessQualifier(AccessQualifier::None));
EXPECT_EQ(static_cast<cl_kernel_arg_access_qualifier>(CL_KERNEL_ARG_ACCESS_READ_ONLY), NEO::asClKernelArgAccessQualifier(AccessQualifier::ReadOnly));
EXPECT_EQ(static_cast<cl_kernel_arg_access_qualifier>(CL_KERNEL_ARG_ACCESS_WRITE_ONLY), NEO::asClKernelArgAccessQualifier(AccessQualifier::WriteOnly));
EXPECT_EQ(static_cast<cl_kernel_arg_access_qualifier>(CL_KERNEL_ARG_ACCESS_READ_WRITE), NEO::asClKernelArgAccessQualifier(AccessQualifier::ReadWrite));
EXPECT_EQ(0U, NEO::asClKernelArgAccessQualifier(AccessQualifier::Unknown));
}
TEST(AsClConvertersTest, whenConvertingAddressQualifiersThenProperEnumValuesAreReturned) {
using namespace NEO::KernelArgMetadata;
EXPECT_EQ(static_cast<cl_kernel_arg_address_qualifier>(CL_KERNEL_ARG_ADDRESS_GLOBAL), NEO::asClKernelArgAddressQualifier(AddressSpaceQualifier::Global));
EXPECT_EQ(static_cast<cl_kernel_arg_address_qualifier>(CL_KERNEL_ARG_ADDRESS_LOCAL), NEO::asClKernelArgAddressQualifier(AddressSpaceQualifier::Local));
EXPECT_EQ(static_cast<cl_kernel_arg_address_qualifier>(CL_KERNEL_ARG_ADDRESS_PRIVATE), NEO::asClKernelArgAddressQualifier(AddressSpaceQualifier::Private));
EXPECT_EQ(static_cast<cl_kernel_arg_address_qualifier>(CL_KERNEL_ARG_ADDRESS_CONSTANT), NEO::asClKernelArgAddressQualifier(AddressSpaceQualifier::Constant));
EXPECT_EQ(0U, NEO::asClKernelArgAddressQualifier(AddressSpaceQualifier::Unknown));
}
TEST(AsClConvertersTest, whenConvertingTypeQualifiersThenProperBitfieldsAreSet) {
using namespace NEO::KernelArgMetadata;
TypeQualifiers typeQualifiers = {};
typeQualifiers.constQual = true;
EXPECT_EQ(static_cast<cl_kernel_arg_type_qualifier>(CL_KERNEL_ARG_TYPE_CONST), NEO::asClKernelArgTypeQualifier(typeQualifiers));
typeQualifiers = {};
typeQualifiers.volatileQual = true;
EXPECT_EQ(static_cast<cl_kernel_arg_type_qualifier>(CL_KERNEL_ARG_TYPE_VOLATILE), NEO::asClKernelArgTypeQualifier(typeQualifiers));
typeQualifiers = {};
typeQualifiers.restrictQual = true;
EXPECT_EQ(static_cast<cl_kernel_arg_type_qualifier>(CL_KERNEL_ARG_TYPE_RESTRICT), NEO::asClKernelArgTypeQualifier(typeQualifiers));
typeQualifiers = {};
typeQualifiers.pipeQual = true;
EXPECT_EQ(static_cast<cl_kernel_arg_type_qualifier>(CL_KERNEL_ARG_TYPE_PIPE), NEO::asClKernelArgTypeQualifier(typeQualifiers));
typeQualifiers = {};
typeQualifiers.constQual = true;
typeQualifiers.volatileQual = true;
EXPECT_EQ(static_cast<cl_kernel_arg_type_qualifier>(CL_KERNEL_ARG_TYPE_CONST | CL_KERNEL_ARG_TYPE_VOLATILE), NEO::asClKernelArgTypeQualifier(typeQualifiers));
typeQualifiers = {};
typeQualifiers.constQual = true;
typeQualifiers.volatileQual = true;
typeQualifiers.pipeQual = true;
typeQualifiers.restrictQual = true;
EXPECT_EQ(static_cast<cl_kernel_arg_type_qualifier>(CL_KERNEL_ARG_TYPE_CONST | CL_KERNEL_ARG_TYPE_VOLATILE | CL_KERNEL_ARG_TYPE_RESTRICT | CL_KERNEL_ARG_TYPE_PIPE),
NEO::asClKernelArgTypeQualifier(typeQualifiers));
}

View File

@@ -93,10 +93,11 @@ TEST_P(KernelReflectionSurfaceTest, GivenKernelInfoWithCorrectlyFilledImageArgum
const uint32_t offsetArraySize = 32;
info.storeKernelArgument(&imageMemObjKernelArg);
info.kernelArgInfo[0].accessQualifier = CL_KERNEL_ARG_ACCESS_READ_ONLY;
info.kernelArgInfo[0].accessQualifierStr = "read_only";
info.kernelArgInfo[0].metadataExtended = std::make_unique<NEO::ArgTypeMetadataExtended>();
info.kernelArgInfo[0].metadata.accessQualifier = NEO::KernelArgMetadata::AccessQualifier::ReadOnly;
info.kernelArgInfo[0].metadataExtended->accessQualifier = "read_only";
info.kernelArgInfo[0].isImage = true;
info.kernelArgInfo[0].name = "img";
info.kernelArgInfo[0].metadataExtended->argName = "img";
info.kernelArgInfo[0].offsetChannelDataType = offsetDataType;
info.kernelArgInfo[0].offsetChannelOrder = offsetChannelOrder;
info.kernelArgInfo[0].offsetHeap = offsetHeap;
@@ -282,8 +283,9 @@ TEST_P(KernelReflectionSurfaceTest, GivenKernelInfoWithCorrectlyFilledSamplerArg
const uint32_t offsetObjectID = 28;
info.storeKernelArgument(&samplerMemObjKernelArg);
info.kernelArgInfo[0].metadataExtended = std::make_unique<NEO::ArgTypeMetadataExtended>();
info.kernelArgInfo[0].isSampler = true;
info.kernelArgInfo[0].name = "smp";
info.kernelArgInfo[0].metadataExtended->argName = "smp";
info.kernelArgInfo[0].offsetSamplerAddressingMode = offsetSamplerAddressingMode;
info.kernelArgInfo[0].offsetSamplerNormalizedCoords = offsetSamplerNormalizedCoords;
info.kernelArgInfo[0].offsetSamplerSnapWa = offsetSamplerSnapWa;
@@ -725,7 +727,7 @@ TEST(KernelReflectionSurfaceTestSingle, ObtainKernelReflectionSurfaceWithDeviceQ
argInfo.isDeviceQueue = true;
info.kernelArgInfo.resize(1);
info.kernelArgInfo[0] = argInfo;
info.kernelArgInfo[0] = std::move(argInfo);
info.kernelArgInfo[0].kernelArgPatchInfoVector.resize(1);
info.kernelArgInfo[0].kernelArgPatchInfoVector[0].crossthreadOffset = devQueueCurbeOffset;
@@ -1654,32 +1656,35 @@ TEST_F(ReflectionSurfaceHelperFixture, setParentImageParams) {
argInfo.offsetHeap = 0;
argInfo.isBuffer = true;
info.kernelArgInfo.push_back(argInfo);
info.kernelArgInfo.push_back(std::move(argInfo));
imgInfo.type = Kernel::kernelArgType::IMAGE_OBJ;
imgInfo.object = (cl_mem)image2d.get();
kernelArguments.push_back(imgInfo);
argInfo = {};
argInfo.offsetHeap = imageID[0];
argInfo.isImage = true;
info.kernelArgInfo.push_back(argInfo);
info.kernelArgInfo.push_back(std::move(argInfo));
// Buffer Object should never be dereferenced by setParentImageParams
imgInfo.type = Kernel::kernelArgType::BUFFER_OBJ;
imgInfo.object = reinterpret_cast<void *>(0x0);
kernelArguments.push_back(imgInfo);
argInfo = {};
argInfo.offsetHeap = 0;
argInfo.isBuffer = true;
info.kernelArgInfo.push_back(argInfo);
info.kernelArgInfo.push_back(std::move(argInfo));
imgInfo.type = Kernel::kernelArgType::IMAGE_OBJ;
imgInfo.object = (cl_mem)image1d.get();
kernelArguments.push_back(imgInfo);
argInfo = {};
argInfo.offsetHeap = imageID[1];
argInfo.isImage = true;
info.kernelArgInfo.push_back(argInfo);
info.kernelArgInfo.push_back(std::move(argInfo));
std::unique_ptr<char> reflectionSurfaceMemory(new char[4096]);
@@ -1737,36 +1742,42 @@ TEST_F(ReflectionSurfaceHelperFixture, setParentSamplerParams) {
// Buffer Object should never be dereferenced by setParentImageParams
imgInfo.type = Kernel::kernelArgType::BUFFER_OBJ;
imgInfo.object = reinterpret_cast<void *>(0x0);
kernelArguments.push_back(imgInfo);
kernelArguments.push_back(std::move(imgInfo));
argInfo.offsetHeap = 0;
argInfo.isBuffer = true;
info.kernelArgInfo.push_back(argInfo);
info.kernelArgInfo.push_back(std::move(argInfo));
imgInfo = {};
imgInfo.type = Kernel::kernelArgType::SAMPLER_OBJ;
imgInfo.object = (cl_sampler)sampler1.get();
kernelArguments.push_back(imgInfo);
kernelArguments.push_back(std::move(imgInfo));
argInfo = {};
argInfo.offsetHeap = samplerID[0];
argInfo.isSampler = true;
info.kernelArgInfo.push_back(argInfo);
info.kernelArgInfo.push_back(std::move(argInfo));
// Buffer Object should never be dereferenced by setParentImageParams
imgInfo = {};
imgInfo.type = Kernel::kernelArgType::BUFFER_OBJ;
imgInfo.object = reinterpret_cast<void *>(0x0);
kernelArguments.push_back(imgInfo);
kernelArguments.push_back(std::move(imgInfo));
argInfo = {};
argInfo.offsetHeap = 0;
argInfo.isBuffer = true;
info.kernelArgInfo.push_back(argInfo);
info.kernelArgInfo.push_back(std::move(argInfo));
imgInfo = {};
imgInfo.type = Kernel::kernelArgType::SAMPLER_OBJ;
imgInfo.object = (cl_sampler)sampler2.get();
kernelArguments.push_back(imgInfo);
kernelArguments.push_back(std::move(imgInfo));
argInfo = {};
argInfo.offsetHeap = samplerID[1];
argInfo.isSampler = true;
info.kernelArgInfo.push_back(argInfo);
info.kernelArgInfo.push_back(std::move(argInfo));
std::unique_ptr<char> reflectionSurfaceMemory(new char[4096]);
@@ -2196,7 +2207,7 @@ TEST_F(KernelReflectionMultiDeviceTest, ObtainKernelReflectionSurfaceWithDeviceQ
argInfo.isDeviceQueue = true;
info.kernelArgInfo.resize(1);
info.kernelArgInfo[0] = argInfo;
info.kernelArgInfo[0] = std::move(argInfo);
info.kernelArgInfo[0].kernelArgPatchInfoVector.resize(1);
info.kernelArgInfo[0].kernelArgPatchInfoVector[0].crossthreadOffset = devQueueCurbeOffset;

View File

@@ -2075,7 +2075,7 @@ HWTEST_F(KernelResidencyTest, test_MakeArgsResidentCheckImageFromImage) {
KernelArgInfo kernelArgInfo;
kernelArgInfo.isImage = true;
pKernelInfo->kernelArgInfo.push_back(kernelArgInfo);
pKernelInfo->kernelArgInfo.push_back(std::move(kernelArgInfo));
auto program = std::make_unique<MockProgram>(*pDevice->getExecutionEnvironment());
program->setContext(&context);
@@ -2494,19 +2494,25 @@ TEST(KernelInfoTest, getArgNumByName) {
EXPECT_EQ(-1, info.getArgNumByName(""));
KernelArgInfo kai;
kai.name = "arg1";
info.kernelArgInfo.push_back(kai);
kai.metadataExtended = std::make_unique<ArgTypeMetadataExtended>();
kai.metadataExtended->argName = "arg1";
info.kernelArgInfo.push_back(std::move(kai));
EXPECT_EQ(-1, info.getArgNumByName(""));
EXPECT_EQ(-1, info.getArgNumByName("arg2"));
EXPECT_EQ(0, info.getArgNumByName("arg1"));
kai.name = "arg2";
info.kernelArgInfo.push_back(kai);
kai = {};
kai.metadataExtended = std::make_unique<ArgTypeMetadataExtended>();
kai.metadataExtended->argName = "arg2";
info.kernelArgInfo.push_back(std::move(kai));
EXPECT_EQ(0, info.getArgNumByName("arg1"));
EXPECT_EQ(1, info.getArgNumByName("arg2"));
info.kernelArgInfo[0].metadataExtended.reset();
EXPECT_EQ(-1, info.getArgNumByName("arg1"));
}
TEST(KernelTest, getInstructionHeapSizeForExecutionModelReturnsZeroForNormalKernel) {
@@ -2644,15 +2650,16 @@ TEST(KernelTest, givenFtrRenderCompressedBuffersWhenInitializingArgsWithNonState
context->contextType = ContextType::CONTEXT_TYPE_UNRESTRICTIVE;
MockKernelWithInternals kernel(*device, context.get());
kernel.kernelInfo.kernelArgInfo.resize(1);
kernel.kernelInfo.kernelArgInfo.at(0).typeStr = "char *";
kernel.kernelInfo.kernelArgInfo.at(0).isBuffer = true;
kernel.kernelInfo.kernelArgInfo[0].metadataExtended = std::make_unique<NEO::ArgTypeMetadataExtended>();
kernel.kernelInfo.kernelArgInfo[0].metadataExtended->type = "char *";
kernel.kernelInfo.kernelArgInfo[0].isBuffer = true;
capabilityTable.ftrRenderCompressedBuffers = false;
kernel.kernelInfo.kernelArgInfo.at(0).pureStatefulBufferAccess = true;
kernel.kernelInfo.kernelArgInfo[0].pureStatefulBufferAccess = true;
kernel.mockKernel->initialize();
EXPECT_FALSE(kernel.mockKernel->isAuxTranslationRequired());
kernel.kernelInfo.kernelArgInfo.at(0).pureStatefulBufferAccess = false;
kernel.kernelInfo.kernelArgInfo[0].pureStatefulBufferAccess = false;
kernel.mockKernel->initialize();
EXPECT_FALSE(kernel.mockKernel->isAuxTranslationRequired());
@@ -2680,10 +2687,11 @@ TEST(KernelTest, givenDebugVariableSetWhenKernelHasStatefulBufferAccessThenMarkK
auto context = clUniquePtr(new MockContext(device.get()));
MockKernelWithInternals kernel(*device, context.get());
kernel.kernelInfo.kernelArgInfo.resize(1);
kernel.kernelInfo.kernelArgInfo.at(0).typeStr = "char *";
kernel.kernelInfo.kernelArgInfo.at(0).isBuffer = true;
kernel.kernelInfo.kernelArgInfo[0].metadataExtended = std::make_unique<NEO::ArgTypeMetadataExtended>();
kernel.kernelInfo.kernelArgInfo[0].metadataExtended->type = "char *";
kernel.kernelInfo.kernelArgInfo[0].isBuffer = true;
kernel.kernelInfo.kernelArgInfo.at(0).pureStatefulBufferAccess = false;
kernel.kernelInfo.kernelArgInfo[0].pureStatefulBufferAccess = false;
localHwInfo.capabilityTable.ftrRenderCompressedBuffers = false;
kernel.mockKernel->initialize();
@@ -2702,7 +2710,8 @@ TEST(KernelTest, givenKernelWithPairArgumentWhenItIsInitializedThenPatchImmediat
auto context = clUniquePtr(new MockContext(device.get()));
MockKernelWithInternals kernel(*device, context.get());
kernel.kernelInfo.kernelArgInfo.resize(1);
kernel.kernelInfo.kernelArgInfo.at(0).typeStr = "pair<char*, int>";
kernel.kernelInfo.kernelArgInfo[0].metadataExtended = std::make_unique<NEO::ArgTypeMetadataExtended>();
kernel.kernelInfo.kernelArgInfo[0].metadataExtended->type = "pair<char*, int>";
kernel.mockKernel->initialize();
EXPECT_EQ(&Kernel::setArgImmediate, kernel.mockKernel->kernelArgHandlers[0]);
@@ -2800,7 +2809,7 @@ TEST(KernelTest, givenAllArgumentsAreStatefulBuffersWhenInitializingThenAllBuffe
kernelArgInfo[1].pureStatefulBufferAccess = true;
MockKernelWithInternals kernel{*device};
kernel.kernelInfo.kernelArgInfo = kernelArgInfo;
kernel.kernelInfo.kernelArgInfo.swap(kernelArgInfo);
kernel.mockKernel->initialize();
EXPECT_TRUE(kernel.mockKernel->allBufferArgsStateful);
@@ -2816,7 +2825,7 @@ TEST(KernelTest, givenAllArgumentsAreBuffersButNotAllAreStatefulWhenInitializing
kernelArgInfo[1].pureStatefulBufferAccess = false;
MockKernelWithInternals kernel{*device};
kernel.kernelInfo.kernelArgInfo = kernelArgInfo;
kernel.kernelInfo.kernelArgInfo.swap(kernelArgInfo);
kernel.mockKernel->initialize();
EXPECT_FALSE(kernel.mockKernel->allBufferArgsStateful);
@@ -2832,7 +2841,7 @@ TEST(KernelTest, givenNotAllArgumentsAreBuffersButAllBuffersAreStatefulWhenIniti
kernelArgInfo[1].pureStatefulBufferAccess = false;
MockKernelWithInternals kernel{*device};
kernel.kernelInfo.kernelArgInfo = kernelArgInfo;
kernel.kernelInfo.kernelArgInfo.swap(kernelArgInfo);
kernel.mockKernel->initialize();
EXPECT_TRUE(kernel.mockKernel->allBufferArgsStateful);
@@ -3006,3 +3015,20 @@ TEST_F(KernelMultiRootDeviceTest, privateSurfaceHasCorrectRootDeviceIndex) {
ASSERT_NE(nullptr, privateSurface);
EXPECT_EQ(expectedRootDeviceIndex, privateSurface->getRootDeviceIndex());
}
TEST(KernelCreateTest, whenInitFailedThenReturnNull) {
struct MockProgram {
int getDevice(int) { return 0; }
void getSource(std::string &) {}
} mockProgram;
struct MockKernel {
MockKernel(MockProgram *, const KernelInfo &, int) {}
int initialize() { return -1; };
};
KernelInfo info;
info.gpuPointerSize = 8;
auto ret = Kernel::create<MockKernel>(&mockProgram, info, nullptr);
EXPECT_EQ(nullptr, ret);
}

View File

@@ -14,6 +14,8 @@
#include "core/memory_manager/residency.h"
#include "core/os_interface/os_context.h"
#include "core/os_interface/os_interface.h"
#include "core/program/program_initialization.h"
#include "core/unit_tests/compiler_interface/linker_mock.h"
#include "core/unit_tests/helpers/debug_manager_state_restore.h"
#include "runtime/event/event.h"
#include "runtime/helpers/dispatch_info.h"
@@ -2118,17 +2120,15 @@ TEST(MemoryManagerTest, whenMemoryManagerReturnsNullptrThenAllocateGlobalsSurfac
MockClDevice device{new MockDevice};
std::unique_ptr<MemoryManager> memoryManager(new MemoryManagerWithFailure());
device.injectMemoryManager(memoryManager.release());
MockContext context(&device, true);
delete context.svmAllocsManager;
context.svmAllocsManager = nullptr;
GraphicsAllocation *allocation = allocateGlobalsSurface(&context, &device, 1024, false, true, nullptr);
WhiteBox<NEO::LinkerInput> linkerInput;
linkerInput.traits.exportsGlobalConstants = true;
linkerInput.traits.exportsGlobalVariables = true;
GraphicsAllocation *allocation = allocateGlobalsSurface(nullptr, device.getDevice(), 1024, false, &linkerInput, nullptr);
EXPECT_EQ(nullptr, allocation);
context.svmAllocsManager = new SVMAllocsManager(device.getMemoryManager());
allocation = allocateGlobalsSurface(&context, &device, 1024, false, true, nullptr);
auto svmAllocsManager = std::make_unique<SVMAllocsManager>(device.getMemoryManager());
allocation = allocateGlobalsSurface(svmAllocsManager.get(), device.getDevice(), 1024, false, &linkerInput, nullptr);
EXPECT_EQ(nullptr, allocation);
}
@@ -2161,7 +2161,10 @@ TEST_F(MemoryManagerMultiRootDeviceTests, globalsSurfaceHasCorrectRootDeviceInde
}
std::vector<unsigned char> initData(1024, 0x5B);
GraphicsAllocation *allocation = allocateGlobalsSurface(context.get(), device.get(), initData.size(), false, true, initData.data());
WhiteBox<NEO::LinkerInput> linkerInput;
linkerInput.traits.exportsGlobalConstants = true;
linkerInput.traits.exportsGlobalVariables = true;
GraphicsAllocation *allocation = allocateGlobalsSurface(context->svmAllocsManager, device->getDevice(), initData.size(), false, &linkerInput, initData.data());
ASSERT_NE(nullptr, allocation);
EXPECT_EQ(expectedRootDeviceIndex, allocation->getRootDeviceIndex());

View File

@@ -307,10 +307,14 @@ class MockKernelWithInternals {
kernelInfo.kernelArgInfo[0].kernelArgPatchInfoVector.resize(1);
kernelInfo.kernelArgInfo[0].kernelArgPatchInfoVector[0].crossthreadOffset = 0;
kernelInfo.kernelArgInfo[0].kernelArgPatchInfoVector[0].size = sizeof(uintptr_t);
kernelInfo.kernelArgInfo[0].metadata.addressQualifier = NEO::KernelArgMetadata::AddressSpaceQualifier::Global;
kernelInfo.kernelArgInfo[0].metadata.accessQualifier = NEO::KernelArgMetadata::AccessQualifier::ReadWrite;
kernelInfo.kernelArgInfo[1].kernelArgPatchInfoVector.resize(1);
kernelInfo.kernelArgInfo[1].kernelArgPatchInfoVector[0].crossthreadOffset = 0;
kernelInfo.kernelArgInfo[1].kernelArgPatchInfoVector[0].size = sizeof(uintptr_t);
kernelInfo.kernelArgInfo[1].metadata.addressQualifier = NEO::KernelArgMetadata::AddressSpaceQualifier::Global;
kernelInfo.kernelArgInfo[1].metadata.accessQualifier = NEO::KernelArgMetadata::AccessQualifier::ReadWrite;
mockKernel->setKernelArguments(defaultKernelArguments);
mockKernel->kernelArgRequiresCacheFlush.resize(2);

View File

@@ -9,6 +9,8 @@
#include "core/compiler_interface/compiler_cache.h"
#include "core/helpers/hash.h"
#include "core/program/program_info_from_patchtokens.h"
#include "runtime/compiler_interface/patchtokens_decoder.h"
#include "runtime/context/context.h"
#include "runtime/program/create.inl"
#include "runtime/program/kernel_info.h"
@@ -81,56 +83,30 @@ void GlobalMockSipProgram::shutDownSipProgram() {
}
Program *GlobalMockSipProgram::getSipProgramWithCustomBinary() {
char binary[1024];
char *pBinary = binary;
auto totalSize = 0u;
NEO::PatchTokenBinary::ProgramFromPatchtokens programTokens;
programTokens.kernels.resize(1);
SProgramBinaryHeader *pBHdr = (SProgramBinaryHeader *)binary;
pBHdr->Magic = iOpenCL::MAGIC_CL;
pBHdr->Version = iOpenCL::CURRENT_ICBE_VERSION;
pBHdr->Device = platformDevices[0]->platform.eRenderCoreFamily;
pBHdr->GPUPointerSizeInBytes = 8;
pBHdr->NumberOfKernels = 1;
pBHdr->SteppingId = 0;
pBHdr->PatchListSize = 0;
pBinary += sizeof(SProgramBinaryHeader);
totalSize += sizeof(SProgramBinaryHeader);
const uint8_t isa[] = "kernel morphEUs()";
const char name[] = "sip";
SKernelBinaryHeaderCommon *pKHdr = (SKernelBinaryHeaderCommon *)pBinary;
pKHdr->CheckSum = 0;
pKHdr->ShaderHashCode = 0;
pKHdr->KernelNameSize = 4;
pKHdr->PatchListSize = 0;
pKHdr->KernelHeapSize = 16;
pKHdr->GeneralStateHeapSize = 0;
pKHdr->DynamicStateHeapSize = 0;
pKHdr->SurfaceStateHeapSize = 0;
pKHdr->KernelUnpaddedSize = 0;
pBinary += sizeof(SKernelBinaryHeaderCommon);
totalSize += sizeof(SKernelBinaryHeaderCommon);
char *pKernelBin = pBinary;
strcpy_s(pBinary, 4, "sip");
pBinary += pKHdr->KernelNameSize;
totalSize += pKHdr->KernelNameSize;
SProgramBinaryHeader progHeader = {};
progHeader.NumberOfKernels = 1;
strcpy_s(pBinary, 18, "kernel morphEUs()");
totalSize += pKHdr->KernelHeapSize;
SKernelBinaryHeaderCommon kernHeader = {};
kernHeader.KernelNameSize = sizeof(name);
kernHeader.KernelHeapSize = sizeof(isa);
kernHeader.KernelUnpaddedSize = sizeof(isa);
uint32_t kernelBinSize =
pKHdr->DynamicStateHeapSize +
pKHdr->GeneralStateHeapSize +
pKHdr->KernelHeapSize +
pKHdr->KernelNameSize +
pKHdr->PatchListSize +
pKHdr->SurfaceStateHeapSize;
uint64_t hashValue = Hash::hash(reinterpret_cast<const char *>(pKernelBin), kernelBinSize);
pKHdr->CheckSum = static_cast<uint32_t>(hashValue & 0xFFFFFFFF);
programTokens.header = &progHeader;
programTokens.kernels[0].header = &kernHeader;
programTokens.kernels[0].isa = isa;
programTokens.kernels[0].name = name;
auto errCode = CL_SUCCESS;
auto program = Program::createFromGenBinary(executionEnvironment, nullptr, binary, totalSize, false, &errCode);
UNRECOVERABLE_IF(errCode != CL_SUCCESS);
errCode = program->processGenBinary();
UNRECOVERABLE_IF(errCode != CL_SUCCESS);
return program;
NEO::ProgramInfo programInfo;
NEO::populateProgramInfo(programInfo, programTokens, {});
Program *ret = new Program(executionEnvironment, nullptr, false);
ret->processProgramInfo(programInfo);
return ret;
}
} // namespace NEO

View File

@@ -26,12 +26,9 @@ class GraphicsAllocation;
class MockProgram : public Program {
public:
using Program::createProgramFromBinary;
using Program::getKernelNamesString;
using Program::internalOptionsToExtract;
using Program::isKernelDebugEnabled;
using Program::linkBinary;
using Program::populateKernelInfo;
using Program::prepareLinkerInputStorage;
using Program::rebuildProgramFromIr;
using Program::resolveProgramBinary;
using Program::separateBlockKernels;
@@ -58,7 +55,6 @@ class MockProgram : public Program {
using Program::isSpirV;
using Program::linkerInput;
using Program::pDevice;
using Program::processProgramScopeMetadata;
using Program::programBinaryType;
using Program::sourceCode;
using Program::specConstantsIds;

View File

@@ -1,5 +1,5 @@
#
# Copyright (C) 2017-2019 Intel Corporation
# Copyright (C) 2017-2020 Intel Corporation
#
# SPDX-License-Identifier: MIT
#
@@ -27,5 +27,11 @@ set(IGDRCL_SRCS_tests_program
${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()

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017-2019 Intel Corporation
* Copyright (C) 2017-2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -9,6 +9,7 @@
#include "runtime/execution_environment/execution_environment.h"
#include "runtime/program/create.inl"
#include "runtime/program/program.h"
#include "unit_tests/compiler_interface/patchtokens_tests.h"
#include "gtest/gtest.h"
@@ -61,60 +62,28 @@ inline std::vector<char> CreateBinary(bool addUnhandledProgramScopePatchToken, b
int32_t unhandledTokenId = static_cast<int32_t>(iOpenCL::NUM_PATCH_TOKENS)) {
std::vector<char> ret;
{
iOpenCL::SProgramBinaryHeader progBinHeader = {};
progBinHeader.Magic = iOpenCL::MAGIC_CL;
progBinHeader.Version = iOpenCL::CURRENT_ICBE_VERSION;
progBinHeader.Device = renderCoreFamily;
progBinHeader.GPUPointerSizeInBytes = 8;
progBinHeader.NumberOfKernels = 1;
progBinHeader.SteppingId = 0;
progBinHeader.PatchListSize = 0;
if (false == addUnhandledProgramScopePatchToken) {
PushBackToken(ret, progBinHeader);
} else {
progBinHeader.PatchListSize = static_cast<uint32_t>(sizeof(iOpenCL::SPatchItemHeader));
PushBackToken(ret, progBinHeader);
iOpenCL::SPatchItemHeader unhandledToken = {};
unhandledToken.Size = static_cast<uint32_t>(sizeof(iOpenCL::SPatchItemHeader));
unhandledToken.Token = static_cast<uint32_t>(unhandledTokenId);
PushBackToken(ret, unhandledToken);
}
if (addUnhandledProgramScopePatchToken && addUnhandledKernelScopePatchToken) {
return {};
}
{
std::string kernelName = "testKernel";
while (kernelName.size() % 4 != 0) {
// pad with \0 to get 4-byte size alignment of kernelName
kernelName.push_back('\0');
}
iOpenCL::SKernelBinaryHeaderCommon kernBinHeader = {};
kernBinHeader.CheckSum = 0U;
kernBinHeader.ShaderHashCode = 0;
kernBinHeader.KernelNameSize = static_cast<uint32_t>(kernelName.size());
kernBinHeader.PatchListSize = 0;
kernBinHeader.KernelHeapSize = 0;
kernBinHeader.GeneralStateHeapSize = 0;
kernBinHeader.DynamicStateHeapSize = 0;
kernBinHeader.SurfaceStateHeapSize = 0;
kernBinHeader.KernelUnpaddedSize = 0;
if (addUnhandledProgramScopePatchToken) {
PatchTokensTestData::ValidProgramWithConstantSurface programWithUnhandledToken;
auto headerOffset = ret.size();
PushBackToken(ret, kernBinHeader);
ret.insert(ret.end(), kernelName.begin(), kernelName.end());
uint32_t patchListSize = 0;
if (addUnhandledKernelScopePatchToken) {
iOpenCL::SPatchItemHeader unhandledToken = {};
unhandledToken.Size = static_cast<uint32_t>(sizeof(iOpenCL::SPatchItemHeader));
unhandledToken.Token = static_cast<uint32_t>(unhandledTokenId);
PushBackToken(ret, unhandledToken);
patchListSize = static_cast<uint32_t>(sizeof(iOpenCL::SPatchItemHeader));
}
iOpenCL::SKernelBinaryHeaderCommon *kernHeader = reinterpret_cast<iOpenCL::SKernelBinaryHeaderCommon *>(ret.data() + headerOffset);
kernHeader->PatchListSize = patchListSize;
auto kernelData = reinterpret_cast<const uint8_t *>(kernHeader);
kernHeader->CheckSum = NEO::PatchTokenBinary::calcKernelChecksum(ArrayRef<const uint8_t>(kernelData, reinterpret_cast<const uint8_t *>(&*ret.rbegin()) + 1));
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;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 Intel Corporation
* Copyright (C) 2019-2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -10,18 +10,177 @@
#include "runtime/program/kernel_info_from_patchtokens.h"
#include "unit_tests/compiler_interface/patchtokens_tests.h"
TEST(GetInlineData, GivenValidEmptyKernelFromPatchtokensThenReturnEmptyKernelInfo) {
#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);
NEO::populateKernelInfo(dst, src, 4, {});
NEO::KernelInfo expectedKernelInfo = {};
expectedKernelInfo.name = std::string(src.name.begin()).c_str();
expectedKernelInfo.heapInfo.pKernelHeader = src.header;
expectedKernelInfo.isValid = true;
EXPECT_STREQ(expectedKernelInfo.name.c_str(), dst.name.c_str());
EXPECT_EQ(expectedKernelInfo.heapInfo.pKernelHeader, dst.heapInfo.pKernelHeader);
EXPECT_EQ(expectedKernelInfo.isValid, dst.isValid);
}
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, 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, deviceInfoConstants);
ASSERT_NE(nullptr, dst.crossThreadData);
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, deviceInfoConstants);
ASSERT_NE(nullptr, dst.crossThreadData);
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 = &gtpinInfo;
NEO::KernelInfo kernelInfo = {};
NEO::populateKernelInfo(kernelInfo, kernelTokens, sizeof(uintptr_t), {});
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(uintptr_t), {});
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);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017-2019 Intel Corporation
* Copyright (C) 2017-2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -7,6 +7,7 @@
#include "runtime/execution_environment/execution_environment.h"
#include "runtime/memory_manager/os_agnostic_memory_manager.h"
#include "runtime/program/kernel_arg_info.h"
#include "runtime/program/kernel_info.h"
#include "unit_tests/fixtures/multi_root_device_fixture.h"
#include "unit_tests/mocks/mock_execution_environment.h"
@@ -18,20 +19,16 @@
using namespace NEO;
TEST(KernelInfo, NonCopyable) {
EXPECT_FALSE(std::is_move_constructible<KernelInfo>::value);
EXPECT_FALSE(std::is_copy_constructible<KernelInfo>::value);
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, NonAssignable) {
EXPECT_FALSE(std::is_move_assignable<KernelInfo>::value);
EXPECT_FALSE(std::is_copy_assignable<KernelInfo>::value);
}
TEST(KernelInfo, defaultBehavior) {
auto pKernelInfo = std::make_unique<KernelInfo>();
EXPECT_FALSE(pKernelInfo->usesSsh);
EXPECT_FALSE(pKernelInfo->isValid);
TEST(KernelInfo, whenDefaultConstructedThenUsesSshFlagIsNotSet) {
KernelInfo kernelInfo;
EXPECT_FALSE(kernelInfo.usesSsh);
}
TEST(KernelInfo, decodeConstantMemoryKernelArgument) {
@@ -99,13 +96,11 @@ TEST(KernelInfo, decodeImageKernelArgument) {
EXPECT_TRUE(pKernelInfo->usesSsh);
const auto &argInfo = pKernelInfo->kernelArgInfo[argumentNumber];
//EXPECT_EQ(???, argInfo.argSize);
EXPECT_EQ(sizeof(cl_mem), static_cast<size_t>(argInfo.metadata.argByValSize));
EXPECT_EQ(arg.Offset, argInfo.offsetHeap);
EXPECT_TRUE(argInfo.isImage);
EXPECT_EQ(static_cast<cl_kernel_arg_access_qualifier>(CL_KERNEL_ARG_ACCESS_READ_WRITE), argInfo.accessQualifier);
//EXPECT_EQ(CL_KERNEL_ARG_ACCESS_READ_WRITE, argInfo.accessQualifier);
//EXPECT_EQ(CL_KERNEL_ARG_ADDRESS_, argInfo.addressQualifier);
//EXPECT_EQ(CL_KERNEL_ARG_TYPE_NONE, argInfo.typeQualifier);
EXPECT_EQ(KernelArgMetadata::AccessQualifier::ReadWrite, argInfo.metadata.accessQualifier);
EXPECT_TRUE(argInfo.metadata.typeQualifiers.empty());
}
TEST(KernelInfoTest, givenKernelInfoWhenCreateKernelAllocationThenCopyWholeKernelHeapToKernelAllocation) {
@@ -190,39 +185,23 @@ TEST(KernelInfo, decodeSamplerKernelArgument) {
EXPECT_TRUE(pKernelInfo->usesSsh);
}
typedef KernelInfo KernelInfo_resolveKernelInfo;
TEST(KernelInfo_resolveKernelInfo, basicArgument) {
auto pKernelInfo = std::make_unique<KernelInfo>();
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));
pKernelInfo->kernelArgInfo.resize(1);
auto &kernelArgInfo = pKernelInfo->kernelArgInfo[0];
kernelArgInfo.accessQualifierStr = "read_only";
kernelArgInfo.addressQualifierStr = "__global";
kernelArgInfo.typeQualifierStr = "restrict";
auto retVal = pKernelInfo->resolveKernelInfo();
EXPECT_EQ(CL_SUCCESS, retVal);
EXPECT_EQ(static_cast<cl_kernel_arg_access_qualifier>(CL_KERNEL_ARG_ACCESS_READ_ONLY), kernelArgInfo.accessQualifier);
EXPECT_EQ(static_cast<cl_kernel_arg_address_qualifier>(CL_KERNEL_ARG_ADDRESS_GLOBAL), kernelArgInfo.addressQualifier);
EXPECT_EQ(static_cast<cl_kernel_arg_type_qualifier>(CL_KERNEL_ARG_TYPE_RESTRICT), kernelArgInfo.typeQualifier);
}
TEST(KernelInfo_resolveKernelInfo, complexArgumentType) {
auto pKernelInfo = std::make_unique<KernelInfo>();
pKernelInfo->kernelArgInfo.resize(1);
auto &kernelArgInfo = pKernelInfo->kernelArgInfo[0];
kernelArgInfo.accessQualifierStr = "read_only";
kernelArgInfo.addressQualifierStr = "__global";
kernelArgInfo.typeQualifierStr = "restrict const";
auto retVal = pKernelInfo->resolveKernelInfo();
EXPECT_EQ(CL_SUCCESS, retVal);
EXPECT_EQ(static_cast<cl_kernel_arg_access_qualifier>(CL_KERNEL_ARG_ACCESS_READ_ONLY), kernelArgInfo.accessQualifier);
EXPECT_EQ(static_cast<cl_kernel_arg_address_qualifier>(CL_KERNEL_ARG_ADDRESS_GLOBAL), kernelArgInfo.addressQualifier);
EXPECT_EQ(static_cast<cl_kernel_arg_type_qualifier>(CL_KERNEL_ARG_TYPE_RESTRICT | CL_KERNEL_ARG_TYPE_CONST), kernelArgInfo.typeQualifier);
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) {
@@ -267,3 +246,15 @@ TEST_F(KernelInfoMultiRootDeviceTests, kernelAllocationHasCorrectRootDeviceIndex
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());
}

View File

@@ -9,6 +9,7 @@
#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 "runtime/platform/platform.h"
#include "runtime/program/program.h"
@@ -184,12 +185,14 @@ TEST_F(ProgramDataTest, whenGlobalConstantsAreExportedThenAllocateSurfacesAsSvm)
return;
}
setupConstantAllocation();
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;
static_cast<MockProgram *>(pProgram)->linkerInput = std::move(mockLinkerInput);
buildAndDecodeProgramPatchList();
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())));
@@ -200,15 +203,14 @@ TEST_F(ProgramDataTest, whenGlobalConstantsAreNotExportedThenAllocateSurfacesAsN
return;
}
setupConstantAllocation();
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;
static_cast<MockProgram *>(pProgram)->linkerInput = std::move(mockLinkerInput);
static_cast<MockProgram *>(pProgram)->context = nullptr;
buildAndDecodeProgramPatchList();
static_cast<MockProgram *>(pProgram)->context = pContext;
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())));
@@ -219,15 +221,19 @@ TEST_F(ProgramDataTest, whenGlobalConstantsAreExportedButContextUnavailableThenA
return;
}
setupConstantAllocation();
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;
static_cast<MockProgram *>(pProgram)->linkerInput = std::move(mockLinkerInput);
static_cast<MockProgram *>(pProgram)->context = nullptr;
programInfo.linkerInput = std::move(mockLinkerInput);
buildAndDecodeProgramPatchList();
pProgram->context = nullptr;
static_cast<MockProgram *>(pProgram)->context = pContext;
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())));
@@ -237,12 +243,14 @@ TEST_F(ProgramDataTest, whenGlobalVariablesAreExportedThenAllocateSurfacesAsSvm)
if (this->pContext->getSVMAllocsManager() == nullptr) {
return;
}
setupGlobalAllocation();
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;
static_cast<MockProgram *>(pProgram)->linkerInput = std::move(mockLinkerInput);
buildAndDecodeProgramPatchList();
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())));
@@ -253,15 +261,19 @@ TEST_F(ProgramDataTest, whenGlobalVariablesAreExportedButContextUnavailableThenA
return;
}
setupGlobalAllocation();
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;
static_cast<MockProgram *>(pProgram)->linkerInput = std::move(mockLinkerInput);
static_cast<MockProgram *>(pProgram)->context = nullptr;
programInfo.linkerInput = std::move(mockLinkerInput);
buildAndDecodeProgramPatchList();
pProgram->context = nullptr;
static_cast<MockProgram *>(pProgram)->context = pContext;
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())));
@@ -272,15 +284,14 @@ TEST_F(ProgramDataTest, whenGlobalVariablesAreNotExportedThenAllocateSurfacesAsN
return;
}
setupGlobalAllocation();
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;
static_cast<MockProgram *>(pProgram)->linkerInput = std::move(mockLinkerInput);
static_cast<MockProgram *>(pProgram)->context = nullptr;
buildAndDecodeProgramPatchList();
static_cast<MockProgram *>(pProgram)->context = pContext;
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())));
@@ -342,167 +353,6 @@ TEST_F(ProgramDataTest, AllocateGlobalMemorySurfaceProgramBinaryInfo) {
EXPECT_EQ(0, memcmp(globalValue, pProgram->getGlobalSurface()->getUnderlyingBuffer(), globalSize));
}
TEST_F(ProgramDataTest, GlobalPointerProgramBinaryInfo) {
char globalValue;
char *pGlobalPointerValue = &globalValue;
size_t globalPointerSize = sizeof(pGlobalPointerValue);
char *ptr;
// simulate case when global surface was not allocated
EXPECT_EQ(nullptr, pProgram->getGlobalSurface());
SPatchGlobalPointerProgramBinaryInfo globalPointer;
globalPointer.Token = PATCH_TOKEN_GLOBAL_POINTER_PROGRAM_BINARY_INFO;
globalPointer.Size = sizeof(SPatchGlobalPointerProgramBinaryInfo);
globalPointer.GlobalBufferIndex = 0;
globalPointer.GlobalPointerOffset = 0;
globalPointer.BufferIndex = 0;
globalPointer.BufferType = PROGRAM_SCOPE_GLOBAL_BUFFER;
cl_char *pGlobalPointer = new cl_char[globalPointer.Size];
memcpy_s(pGlobalPointer,
sizeof(SPatchGlobalPointerProgramBinaryInfo),
&globalPointer,
sizeof(SPatchGlobalPointerProgramBinaryInfo));
pProgramPatchList = (void *)pGlobalPointer;
programPatchListSize = globalPointer.Size;
this->allowDecodeFailure = true;
buildAndDecodeProgramPatchList();
EXPECT_EQ(nullptr, pProgram->getGlobalSurface());
EXPECT_EQ(CL_INVALID_BINARY, this->patchlistDecodeErrorCode);
this->allowDecodeFailure = false;
delete[] pGlobalPointer;
// regular case - global surface exists
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>(globalPointerSize);
cl_char *pAllocateGlobalMemorySurface = new cl_char[allocateGlobalMemorySurface.Size + globalPointerSize];
memcpy_s(pAllocateGlobalMemorySurface,
sizeof(SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo),
&allocateGlobalMemorySurface,
sizeof(SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo));
memcpy_s((cl_char *)pAllocateGlobalMemorySurface + sizeof(allocateGlobalMemorySurface), globalPointerSize, &pGlobalPointerValue, globalPointerSize);
pProgramPatchList = pAllocateGlobalMemorySurface;
programPatchListSize = static_cast<uint32_t>(allocateGlobalMemorySurface.Size + globalPointerSize);
buildAndDecodeProgramPatchList();
EXPECT_NE(nullptr, pProgram->getGlobalSurface());
auto globalSurface = pProgram->getGlobalSurface();
globalSurface->setCpuPtrAndGpuAddress(globalSurface->getUnderlyingBuffer(), globalSurface->getGpuAddress() + 1);
EXPECT_NE(reinterpret_cast<uint64_t>(globalSurface->getUnderlyingBuffer()), globalSurface->getGpuAddress());
EXPECT_EQ(0, memcmp(&pGlobalPointerValue, globalSurface->getUnderlyingBuffer(), globalPointerSize));
delete[] pAllocateGlobalMemorySurface;
// global pointer to global surface - simulate invalid GlobalBufferIndex
globalPointer.Token = PATCH_TOKEN_GLOBAL_POINTER_PROGRAM_BINARY_INFO;
globalPointer.Size = sizeof(SPatchGlobalPointerProgramBinaryInfo);
globalPointer.GlobalBufferIndex = 10;
globalPointer.GlobalPointerOffset = 0;
globalPointer.BufferIndex = 0;
globalPointer.BufferType = PROGRAM_SCOPE_GLOBAL_BUFFER;
pGlobalPointer = new cl_char[globalPointer.Size];
memcpy_s(pGlobalPointer,
sizeof(SPatchGlobalPointerProgramBinaryInfo),
&globalPointer,
sizeof(SPatchGlobalPointerProgramBinaryInfo));
pProgramPatchList = (void *)pGlobalPointer;
programPatchListSize = globalPointer.Size;
this->allowDecodeFailure = true;
buildAndDecodeProgramPatchList();
EXPECT_EQ(0, memcmp(&pGlobalPointerValue, globalSurface->getUnderlyingBuffer(), globalPointerSize));
delete[] pGlobalPointer;
// global pointer to global surface - simulate invalid BufferIndex
globalPointer.Token = PATCH_TOKEN_GLOBAL_POINTER_PROGRAM_BINARY_INFO;
globalPointer.Size = sizeof(SPatchGlobalPointerProgramBinaryInfo);
globalPointer.GlobalBufferIndex = 0;
globalPointer.GlobalPointerOffset = 0;
globalPointer.BufferIndex = 10;
globalPointer.BufferType = PROGRAM_SCOPE_GLOBAL_BUFFER;
pGlobalPointer = new cl_char[globalPointer.Size];
memcpy_s(pGlobalPointer,
sizeof(SPatchGlobalPointerProgramBinaryInfo),
&globalPointer,
sizeof(SPatchGlobalPointerProgramBinaryInfo));
pProgramPatchList = (void *)pGlobalPointer;
programPatchListSize = globalPointer.Size;
this->allowDecodeFailure = true;
buildAndDecodeProgramPatchList();
EXPECT_EQ(0, memcmp(&pGlobalPointerValue, globalSurface->getUnderlyingBuffer(), globalPointerSize));
delete[] pGlobalPointer;
// global pointer to global surface - simulate invalid BufferType
globalPointer.Token = PATCH_TOKEN_GLOBAL_POINTER_PROGRAM_BINARY_INFO;
globalPointer.Size = sizeof(SPatchGlobalPointerProgramBinaryInfo);
globalPointer.GlobalBufferIndex = 0;
globalPointer.GlobalPointerOffset = 0;
globalPointer.BufferIndex = 0;
globalPointer.BufferType = PROGRAM_SCOPE_CONSTANT_BUFFER;
pGlobalPointer = new cl_char[globalPointer.Size];
memcpy_s(pGlobalPointer,
sizeof(SPatchGlobalPointerProgramBinaryInfo),
&globalPointer,
sizeof(SPatchGlobalPointerProgramBinaryInfo));
pProgramPatchList = (void *)pGlobalPointer;
programPatchListSize = globalPointer.Size;
buildAndDecodeProgramPatchList();
EXPECT_EQ(0, memcmp(&pGlobalPointerValue, globalSurface->getUnderlyingBuffer(), globalPointerSize));
delete[] pGlobalPointer;
// regular case - global pointer to global surface - all parameters valid
this->pProgram->skipValidationOfBinary = true;
this->allowDecodeFailure = false;
globalPointer.Token = PATCH_TOKEN_GLOBAL_POINTER_PROGRAM_BINARY_INFO;
globalPointer.Size = sizeof(SPatchGlobalPointerProgramBinaryInfo);
globalPointer.GlobalBufferIndex = 0;
globalPointer.GlobalPointerOffset = 0;
globalPointer.BufferIndex = 0;
globalPointer.BufferType = PROGRAM_SCOPE_GLOBAL_BUFFER;
pGlobalPointer = new cl_char[globalPointer.Size];
memcpy_s(pGlobalPointer,
sizeof(SPatchGlobalPointerProgramBinaryInfo),
&globalPointer,
sizeof(SPatchGlobalPointerProgramBinaryInfo));
pProgramPatchList = (void *)pGlobalPointer;
programPatchListSize = globalPointer.Size;
buildAndDecodeProgramPatchList();
if (!globalSurface->is32BitAllocation()) {
EXPECT_NE(0, memcmp(&pGlobalPointerValue, globalSurface->getUnderlyingBuffer(), globalPointerSize));
ptr = pGlobalPointerValue + (globalSurface->getGpuAddressToPatch());
EXPECT_EQ(0, memcmp(&ptr, globalSurface->getUnderlyingBuffer(), globalPointerSize));
}
delete[] pGlobalPointer;
}
TEST_F(ProgramDataTest, Given32BitDeviceWhenGlobalMemorySurfaceIsPresentThenItHas32BitStorage) {
char globalValue[] = "55667788";
size_t globalSize = strlen(globalValue) + 1;
@@ -539,188 +389,6 @@ TEST_F(ProgramDataTest, Given32BitDeviceWhenGlobalMemorySurfaceIsPresentThenItHa
delete[] pAllocateGlobalMemorySurface;
}
TEST_F(ProgramDataTest, ConstantPointerProgramBinaryInfo) {
const char *pConstantData = "01234567";
size_t constantDataLen = strlen(pConstantData);
// simulate case when constant surface was not allocated
EXPECT_EQ(nullptr, pProgram->getConstantSurface());
SPatchConstantPointerProgramBinaryInfo constantPointer;
constantPointer.Token = PATCH_TOKEN_CONSTANT_POINTER_PROGRAM_BINARY_INFO;
constantPointer.Size = sizeof(SPatchConstantPointerProgramBinaryInfo);
constantPointer.ConstantBufferIndex = 0;
constantPointer.ConstantPointerOffset = 0;
constantPointer.BufferIndex = 0;
constantPointer.BufferType = PROGRAM_SCOPE_CONSTANT_BUFFER;
cl_char *pConstantPointer = new cl_char[constantPointer.Size];
memcpy_s(pConstantPointer,
sizeof(SPatchConstantPointerProgramBinaryInfo),
&constantPointer,
sizeof(SPatchConstantPointerProgramBinaryInfo));
pProgramPatchList = (void *)pConstantPointer;
programPatchListSize = constantPointer.Size;
this->allowDecodeFailure = true;
buildAndDecodeProgramPatchList();
EXPECT_EQ(nullptr, pProgram->getConstantSurface());
EXPECT_EQ(CL_INVALID_BINARY, this->patchlistDecodeErrorCode);
this->allowDecodeFailure = false;
delete[] pConstantPointer;
// regular case - constant surface exists
SPatchAllocateConstantMemorySurfaceProgramBinaryInfo allocateConstMemorySurface;
allocateConstMemorySurface.Token = PATCH_TOKEN_ALLOCATE_CONSTANT_MEMORY_SURFACE_PROGRAM_BINARY_INFO;
// note : + sizeof(uint64_t) is to accomodate for constant buffer offset
allocateConstMemorySurface.Size = static_cast<uint32_t>(sizeof(SPatchAllocateConstantMemorySurfaceProgramBinaryInfo));
allocateConstMemorySurface.ConstantBufferIndex = 0;
allocateConstMemorySurface.InlineDataSize = static_cast<uint32_t>(constantDataLen + sizeof(uint64_t));
auto pAllocateConstMemorySurface = std::unique_ptr<char>(new char[allocateConstMemorySurface.Size + allocateConstMemorySurface.InlineDataSize]);
// copy the token header
memcpy_s(pAllocateConstMemorySurface.get(),
sizeof(SPatchAllocateConstantMemorySurfaceProgramBinaryInfo),
&allocateConstMemorySurface,
sizeof(SPatchAllocateConstantMemorySurfaceProgramBinaryInfo));
// copy the constant data
memcpy_s((char *)pAllocateConstMemorySurface.get() + sizeof(allocateConstMemorySurface), constantDataLen, pConstantData, constantDataLen);
// zero-out the constant buffer offset (will be patched during gen binary decoding)
size_t constantBufferOffsetPatchOffset = constantDataLen;
*(uint64_t *)((char *)pAllocateConstMemorySurface.get() + sizeof(allocateConstMemorySurface) + constantBufferOffsetPatchOffset) = 0U;
pProgramPatchList = (void *)pAllocateConstMemorySurface.get();
programPatchListSize = allocateConstMemorySurface.Size + allocateConstMemorySurface.InlineDataSize;
buildAndDecodeProgramPatchList();
EXPECT_NE(nullptr, pProgram->getConstantSurface());
auto constantSurface = pProgram->getConstantSurface();
constantSurface->setCpuPtrAndGpuAddress(constantSurface->getUnderlyingBuffer(), constantSurface->getGpuAddress() + 1);
EXPECT_NE(reinterpret_cast<uint64_t>(constantSurface->getUnderlyingBuffer()), constantSurface->getGpuAddress());
EXPECT_EQ(0, memcmp(pConstantData, constantSurface->getUnderlyingBuffer(), constantDataLen));
// there was no PATCH_TOKEN_CONSTANT_POINTER_PROGRAM_BINARY_INFO, so constant buffer offset should be still 0
EXPECT_EQ(0U, *reinterpret_cast<uint64_t *>(static_cast<char *>(constantSurface->getUnderlyingBuffer()) + constantBufferOffsetPatchOffset));
// once finally constant buffer offset gets patched - the patch value depends on the bitness of the compute kernel
auto patchOffsetValueStorage = std::unique_ptr<uint64_t>(new uint64_t); // 4bytes for 32-bit compute kernel, full 8byte for 64-bit compute kernel
uint64_t *patchOffsetValue = patchOffsetValueStorage.get();
if (constantSurface->is32BitAllocation() || (sizeof(void *) == 4)) {
reinterpret_cast<uint32_t *>(patchOffsetValue)[0] = static_cast<uint32_t>(constantSurface->getGpuAddressToPatch());
reinterpret_cast<uint32_t *>(patchOffsetValue)[1] = 0; // just pad with 0
} else {
// full 8 bytes
*reinterpret_cast<uint64_t *>(patchOffsetValue) = constantSurface->getGpuAddressToPatch();
}
// constant pointer to constant surface - simulate invalid GlobalBufferIndex
constantPointer.Token = PATCH_TOKEN_CONSTANT_POINTER_PROGRAM_BINARY_INFO;
constantPointer.Size = sizeof(SPatchConstantPointerProgramBinaryInfo);
constantPointer.ConstantBufferIndex = 10;
constantPointer.ConstantPointerOffset = 0;
constantPointer.BufferIndex = 0;
constantPointer.BufferType = PROGRAM_SCOPE_CONSTANT_BUFFER;
pConstantPointer = new cl_char[constantPointer.Size];
memcpy_s(pConstantPointer,
sizeof(SPatchConstantPointerProgramBinaryInfo),
&constantPointer,
sizeof(SPatchConstantPointerProgramBinaryInfo));
pProgramPatchList = (void *)pConstantPointer;
programPatchListSize = constantPointer.Size;
this->allowDecodeFailure = true;
buildAndDecodeProgramPatchList();
EXPECT_EQ(0, memcmp(pConstantData, constantSurface->getUnderlyingBuffer(), constantDataLen));
// check that constant pointer offset was not patched
EXPECT_EQ(0U, *reinterpret_cast<uint64_t *>(static_cast<char *>(constantSurface->getUnderlyingBuffer()) + constantBufferOffsetPatchOffset));
// reset the constant pointer offset
*reinterpret_cast<uint64_t *>(static_cast<char *>(constantSurface->getUnderlyingBuffer()) + constantBufferOffsetPatchOffset) = 0U;
delete[] pConstantPointer;
// constant pointer to constant surface - simulate invalid BufferIndex
constantPointer.Token = PATCH_TOKEN_CONSTANT_POINTER_PROGRAM_BINARY_INFO;
constantPointer.Size = sizeof(SPatchConstantPointerProgramBinaryInfo);
constantPointer.ConstantBufferIndex = 0;
constantPointer.ConstantPointerOffset = 0;
constantPointer.BufferIndex = 10;
constantPointer.BufferType = PROGRAM_SCOPE_CONSTANT_BUFFER;
pConstantPointer = new cl_char[constantPointer.Size];
memcpy_s(pConstantPointer,
sizeof(SPatchConstantPointerProgramBinaryInfo),
&constantPointer,
sizeof(SPatchConstantPointerProgramBinaryInfo));
pProgramPatchList = (void *)pConstantPointer;
programPatchListSize = constantPointer.Size;
buildAndDecodeProgramPatchList();
EXPECT_EQ(0, memcmp(pConstantData, constantSurface->getUnderlyingBuffer(), constantDataLen));
// check that constant pointer offset was not patched
EXPECT_EQ(0U, *reinterpret_cast<uint64_t *>(static_cast<char *>(constantSurface->getUnderlyingBuffer()) + constantBufferOffsetPatchOffset));
// reset the constant pointer offset
*(uint64_t *)((char *)constantSurface->getUnderlyingBuffer() + constantBufferOffsetPatchOffset) = 0U;
delete[] pConstantPointer;
// constant pointer to constant surface - simulate invalid BufferType
constantPointer.Token = PATCH_TOKEN_CONSTANT_POINTER_PROGRAM_BINARY_INFO;
constantPointer.Size = sizeof(SPatchConstantPointerProgramBinaryInfo);
constantPointer.ConstantBufferIndex = 0;
constantPointer.ConstantPointerOffset = 0;
constantPointer.BufferIndex = 0;
constantPointer.BufferType = PROGRAM_SCOPE_GLOBAL_BUFFER;
pConstantPointer = new cl_char[constantPointer.Size];
memcpy_s(pConstantPointer,
sizeof(SPatchConstantPointerProgramBinaryInfo),
&constantPointer,
sizeof(SPatchConstantPointerProgramBinaryInfo));
pProgramPatchList = (void *)pConstantPointer;
programPatchListSize = constantPointer.Size;
buildAndDecodeProgramPatchList();
EXPECT_EQ(0, memcmp(pConstantData, constantSurface->getUnderlyingBuffer(), constantDataLen));
// check that constant pointer offset was not patched
EXPECT_EQ(0U, *reinterpret_cast<uint64_t *>(static_cast<char *>(constantSurface->getUnderlyingBuffer()) + constantBufferOffsetPatchOffset));
// reset the constant pointer offset
*reinterpret_cast<uint64_t *>(static_cast<char *>(constantSurface->getUnderlyingBuffer()) + constantBufferOffsetPatchOffset) = 0U;
delete[] pConstantPointer;
// regular case - constant pointer to constant surface - all parameters valid
constantPointer.Token = PATCH_TOKEN_CONSTANT_POINTER_PROGRAM_BINARY_INFO;
constantPointer.Size = sizeof(SPatchConstantPointerProgramBinaryInfo);
constantPointer.ConstantBufferIndex = 0;
constantPointer.ConstantPointerOffset = constantDataLen;
constantPointer.BufferIndex = 0;
constantPointer.BufferType = PROGRAM_SCOPE_CONSTANT_BUFFER;
pConstantPointer = new cl_char[constantPointer.Size];
memcpy_s(pConstantPointer,
sizeof(SPatchConstantPointerProgramBinaryInfo),
&constantPointer,
sizeof(SPatchConstantPointerProgramBinaryInfo));
pProgramPatchList = (void *)pConstantPointer;
programPatchListSize = constantPointer.Size;
this->pProgram->skipValidationOfBinary = true;
this->allowDecodeFailure = false;
buildAndDecodeProgramPatchList();
EXPECT_EQ(0, memcmp(pConstantData, constantSurface->getUnderlyingBuffer(), constantDataLen));
// check that constant pointer offset was patched
EXPECT_EQ(*reinterpret_cast<uint64_t *>(patchOffsetValue), *reinterpret_cast<uint64_t *>(static_cast<char *>(constantSurface->getUnderlyingBuffer()) + constantBufferOffsetPatchOffset));
delete[] pConstantPointer;
}
TEST(ProgramScopeMetadataTest, WhenPatchingGlobalSurfaceThenPickProperSourceBuffer) {
MockExecutionEnvironment execEnv;
MockClDevice device{new MockDevice};
@@ -730,9 +398,11 @@ TEST(ProgramScopeMetadataTest, WhenPatchingGlobalSurfaceThenPickProperSourceBuff
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;
program.processProgramScopeMetadata(decodedProgram);
NEO::populateProgramInfo(programInfo, decodedProgram, DeviceInfoKernelPayloadConstants{});
program.processProgramInfo(programInfo);
ASSERT_NE(nullptr, program.globalSurface);
ASSERT_NE(nullptr, program.constantSurface);
ASSERT_NE(nullptr, program.globalSurface->getUnderlyingBuffer());
@@ -750,22 +420,15 @@ TEST_F(ProgramDataTest, GivenProgramWith32bitPointerOptWhenProgramScopeConstantB
// simulate case when constant surface was not allocated
EXPECT_EQ(nullptr, prog->getConstantSurface());
SPatchConstantPointerProgramBinaryInfo constantPointer;
constantPointer.Token = PATCH_TOKEN_CONSTANT_POINTER_PROGRAM_BINARY_INFO;
constantPointer.Size = sizeof(SPatchConstantPointerProgramBinaryInfo);
constantPointer.ConstantBufferIndex = 0;
constantPointer.ConstantPointerOffset = 0;
constantPointer.BufferIndex = 0;
constantPointer.BufferType = PROGRAM_SCOPE_CONSTANT_BUFFER;
auto pConstantPointer = std::unique_ptr<char[]>(new char[constantPointer.Size]);
memcpy_s(pConstantPointer.get(),
sizeof(SPatchConstantPointerProgramBinaryInfo),
&constantPointer,
sizeof(SPatchConstantPointerProgramBinaryInfo));
pProgramPatchList = (void *)pConstantPointer.get();
programPatchListSize = constantPointer.Size;
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());
@@ -775,8 +438,9 @@ TEST_F(ProgramDataTest, GivenProgramWith32bitPointerOptWhenProgramScopeConstantB
uint32_t sentinel = 0x17192329U;
constantSurfaceStorage[0] = 0U;
constantSurfaceStorage[1] = sentinel;
this->pProgram->skipValidationOfBinary = true;
buildAndDecodeProgramPatchList();
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]);
@@ -794,21 +458,15 @@ TEST_F(ProgramDataTest, GivenProgramWith32bitPointerOptWhenProgramScopeGlobalPoi
// simulate case when constant surface was not allocated
EXPECT_EQ(nullptr, prog->getConstantSurface());
SPatchGlobalPointerProgramBinaryInfo globalPointer;
globalPointer.Token = PATCH_TOKEN_GLOBAL_POINTER_PROGRAM_BINARY_INFO;
globalPointer.Size = sizeof(SPatchConstantPointerProgramBinaryInfo);
globalPointer.GlobalBufferIndex = 0;
globalPointer.GlobalPointerOffset = 0;
globalPointer.BufferIndex = 0;
globalPointer.BufferType = PROGRAM_SCOPE_GLOBAL_BUFFER;
auto pGlobalPointer = std::unique_ptr<char[]>(new char[globalPointer.Size]);
memcpy_s(pGlobalPointer.get(),
sizeof(SPatchGlobalPointerProgramBinaryInfo),
&globalPointer,
sizeof(SPatchGlobalPointerProgramBinaryInfo));
pProgramPatchList = (void *)pGlobalPointer.get();
programPatchListSize = globalPointer.Size;
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());
@@ -819,7 +477,9 @@ TEST_F(ProgramDataTest, GivenProgramWith32bitPointerOptWhenProgramScopeGlobalPoi
globalSurfaceStorage[0] = 0U;
globalSurfaceStorage[1] = sentinel;
this->pProgram->skipValidationOfBinary = true;
buildAndDecodeProgramPatchList();
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]);
@@ -882,22 +542,11 @@ TEST(ProgramLinkBinaryTest, whenLinkerUnresolvedExternalThenLinkFailedAndBuildLo
EXPECT_THAT(buildLog, ::testing::HasSubstr(expectedError));
}
TEST(ProgramLinkBinaryTest, whenPrepareLinkerInputStorageGetsCalledTwiceThenLinkerInputStorageIsReused) {
ExecutionEnvironment execEnv;
MockProgram program{execEnv};
EXPECT_EQ(nullptr, program.linkerInput);
program.prepareLinkerInputStorage();
EXPECT_NE(nullptr, program.linkerInput);
auto prevLinkerInput = program.getLinkerInput();
program.prepareLinkerInputStorage();
EXPECT_EQ(prevLinkerInput, program.linkerInput.get());
}
TEST_F(ProgramDataTest, whenLinkerInputValidThenIsaIsProperlyPatched) {
auto linkerInput = std::make_unique<WhiteBox<LinkerInput>>();
linkerInput->symbols["A"] = NEO::SymbolInfo{4U, 4U, NEO::SymbolInfo::GlobalVariable};
linkerInput->symbols["B"] = NEO::SymbolInfo{8U, 4U, NEO::SymbolInfo::GlobalConstant};
linkerInput->symbols["C"] = NEO::SymbolInfo{16U, 4U, NEO::SymbolInfo::Function};
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},
@@ -951,8 +600,8 @@ TEST_F(ProgramDataTest, whenLinkerInputValidThenIsaIsProperlyPatched) {
TEST_F(ProgramDataTest, whenRelocationsAreNotNeededThenIsaIsPreserved) {
auto linkerInput = std::make_unique<WhiteBox<LinkerInput>>();
linkerInput->symbols["A"] = NEO::SymbolInfo{4U, 4U, NEO::SymbolInfo::GlobalVariable};
linkerInput->symbols["B"] = NEO::SymbolInfo{8U, 4U, NEO::SymbolInfo::GlobalConstant};
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};

View File

@@ -26,11 +26,13 @@
#include "runtime/memory_manager/surface.h"
#include "runtime/program/create.inl"
#include "test.h"
#include "unit_tests/compiler_interface/patchtokens_tests.h"
#include "unit_tests/fixtures/device_fixture.h"
#include "unit_tests/fixtures/multi_root_device_fixture.h"
#include "unit_tests/global_environment.h"
#include "unit_tests/helpers/kernel_binary_helper.h"
#include "unit_tests/libult/ult_command_stream_receiver.h"
#include "unit_tests/mocks/mock_graphics_allocation.h"
#include "unit_tests/mocks/mock_kernel.h"
#include "unit_tests/mocks/mock_program.h"
#include "unit_tests/program/program_from_binary.h"
@@ -606,6 +608,23 @@ TEST_P(ProgramFromBinaryTest, givenProgramWhenItIsBeingBuildThenItContainsGraphi
EXPECT_EQ(GmmHelper::decanonize(graphicsAllocation->getGpuBaseAddress()), pProgram->getDevice(0).getMemoryManager()->getInternalHeapBaseAddress(rootDeviceIndex));
}
TEST_P(ProgramFromBinaryTest, whenProgramIsBeingRebuildThenOutdatedGlobalBuffersAreFreed) {
cl_device_id device = pClDevice;
pProgram->build(1, &device, nullptr, nullptr, nullptr, true);
EXPECT_EQ(nullptr, pProgram->constantSurface);
EXPECT_EQ(nullptr, pProgram->globalSurface);
pProgram->constantSurface = new MockGraphicsAllocation();
pProgram->processGenBinary();
EXPECT_EQ(nullptr, pProgram->constantSurface);
EXPECT_EQ(nullptr, pProgram->globalSurface);
pProgram->globalSurface = new MockGraphicsAllocation();
pProgram->processGenBinary();
EXPECT_EQ(nullptr, pProgram->constantSurface);
EXPECT_EQ(nullptr, pProgram->globalSurface);
}
TEST_P(ProgramFromBinaryTest, givenProgramWhenCleanKernelInfoIsCalledThenKernelAllocationIsFreed) {
cl_device_id device = pClDevice;
pProgram->build(1, &device, nullptr, nullptr, nullptr, true);
@@ -1916,203 +1935,18 @@ TEST_F(ProgramTests, ProgramFromGenBinaryWithNullcontext) {
delete pProgram;
}
TEST_F(ProgramTests, ProgramFromGenBinaryWithPATCH_TOKEN_GLOBAL_MEMORY_OBJECT_KERNEL_ARGUMENT) {
cl_int retVal = CL_INVALID_BINARY;
char genBin[1024] = {1, 2, 3, 4, 5, 6, 7, 8, 9, '\0'};
size_t binSize = 10;
MockProgram *pProgram = Program::createFromGenBinary<MockProgram>(*pDevice->getExecutionEnvironment(), nullptr, &genBin[0], binSize, false, &retVal);
EXPECT_NE(nullptr, pProgram);
EXPECT_EQ(CL_SUCCESS, retVal);
EXPECT_EQ((uint32_t)CL_PROGRAM_BINARY_TYPE_EXECUTABLE, (uint32_t)pProgram->getProgramBinaryType());
cl_device_id deviceId = pContext->getDevice(0);
ClDevice *pDevice = castToObject<ClDevice>(deviceId);
char *pBin = &genBin[0];
retVal = CL_INVALID_BINARY;
binSize = 0;
// Prepare simple program binary containing patch token PATCH_TOKEN_GLOBAL_MEMORY_OBJECT_KERNEL_ARGUMENT
SProgramBinaryHeader *pBHdr = (SProgramBinaryHeader *)pBin;
pBHdr->Magic = iOpenCL::MAGIC_CL;
pBHdr->Version = iOpenCL::CURRENT_ICBE_VERSION;
pBHdr->Device = pDevice->getHardwareInfo().platform.eRenderCoreFamily;
pBHdr->GPUPointerSizeInBytes = 8;
pBHdr->NumberOfKernels = 1;
pBHdr->SteppingId = 0;
pBHdr->PatchListSize = 0;
pBin += sizeof(SProgramBinaryHeader);
binSize += sizeof(SProgramBinaryHeader);
SKernelBinaryHeaderCommon *pKHdr = (SKernelBinaryHeaderCommon *)pBin;
pKHdr->CheckSum = 0;
pKHdr->ShaderHashCode = 0;
pKHdr->KernelNameSize = 8;
pKHdr->PatchListSize = sizeof(iOpenCL::SPatchGlobalMemoryObjectKernelArgument);
pKHdr->KernelHeapSize = 0;
pKHdr->GeneralStateHeapSize = 0;
pKHdr->DynamicStateHeapSize = 0;
pKHdr->SurfaceStateHeapSize = 0;
pKHdr->KernelUnpaddedSize = 0;
pBin += sizeof(SKernelBinaryHeaderCommon);
binSize += sizeof(SKernelBinaryHeaderCommon);
strcpy(pBin, "TstCopy");
pBin += pKHdr->KernelNameSize;
binSize += pKHdr->KernelNameSize;
SPatchGlobalMemoryObjectKernelArgument *pPatch = (SPatchGlobalMemoryObjectKernelArgument *)pBin;
pPatch->Token = iOpenCL::PATCH_TOKEN_GLOBAL_MEMORY_OBJECT_KERNEL_ARGUMENT;
pPatch->Size = sizeof(iOpenCL::SPatchGlobalMemoryObjectKernelArgument);
pPatch->ArgumentNumber = 0;
pPatch->Offset = 0x40;
pPatch->LocationIndex = iOpenCL::INVALID_INDEX;
pPatch->LocationIndex2 = iOpenCL::INVALID_INDEX;
binSize += pPatch->Size;
pBin += pPatch->Size;
ArrayRef<const uint8_t> kernelBlob(reinterpret_cast<uint8_t *>(pKHdr), reinterpret_cast<uint8_t *>(pBin));
pKHdr->CheckSum = PatchTokenBinary::calcKernelChecksum(kernelBlob);
// Decode prepared program binary
pProgram->genBinary = makeCopy(&genBin[0], binSize);
pProgram->genBinarySize = binSize;
retVal = pProgram->processGenBinary();
EXPECT_EQ(CL_SUCCESS, retVal);
delete pProgram;
}
TEST_F(ProgramTests, givenProgramFromGenBinaryWhenSLMSizeIsBiggerThenDeviceLimitThenReturnError) {
cl_int retVal = CL_INVALID_BINARY;
char genBin[1024] = {1, 2, 3, 4, 5, 6, 7, 8, 9, '\0'};
size_t binSize = 10;
auto program = std::unique_ptr<MockProgram>(Program::createFromGenBinary<MockProgram>(*pDevice->getExecutionEnvironment(), nullptr, &genBin[0], binSize, false, &retVal));
EXPECT_NE(nullptr, program.get());
EXPECT_EQ(CL_SUCCESS, retVal);
EXPECT_EQ((uint32_t)CL_PROGRAM_BINARY_TYPE_EXECUTABLE, (uint32_t)program->getProgramBinaryType());
cl_device_id deviceId = pContext->getDevice(0);
ClDevice *pDevice = castToObject<ClDevice>(deviceId);
program->setDevice(pDevice);
char *pBin = &genBin[0];
retVal = CL_INVALID_BINARY;
binSize = 0;
// Prepare simple program binary containing patch token PATCH_TOKEN_ALLOCATE_LOCAL_SURFACE
SProgramBinaryHeader *pBHdr = (SProgramBinaryHeader *)pBin;
pBHdr->Magic = iOpenCL::MAGIC_CL;
pBHdr->Version = iOpenCL::CURRENT_ICBE_VERSION;
pBHdr->Device = pDevice->getHardwareInfo().platform.eRenderCoreFamily;
pBHdr->GPUPointerSizeInBytes = 8;
pBHdr->NumberOfKernels = 1;
pBHdr->SteppingId = 0;
pBHdr->PatchListSize = 0;
pBin += sizeof(SProgramBinaryHeader);
binSize += sizeof(SProgramBinaryHeader);
SKernelBinaryHeaderCommon *pKHdr = (SKernelBinaryHeaderCommon *)pBin;
pKHdr->CheckSum = 0;
pKHdr->ShaderHashCode = 0;
pKHdr->KernelNameSize = 8;
pKHdr->PatchListSize = sizeof(iOpenCL::SPatchAllocateLocalSurface);
pKHdr->KernelHeapSize = 0;
pKHdr->GeneralStateHeapSize = 0;
pKHdr->DynamicStateHeapSize = 0;
pKHdr->SurfaceStateHeapSize = 0;
pKHdr->KernelUnpaddedSize = 0;
pBin += sizeof(SKernelBinaryHeaderCommon);
binSize += sizeof(SKernelBinaryHeaderCommon);
strcpy(pBin, "TstCopy");
pBin += pKHdr->KernelNameSize;
binSize += pKHdr->KernelNameSize;
SPatchAllocateLocalSurface *pPatch = (SPatchAllocateLocalSurface *)pBin;
pPatch->Token = iOpenCL::PATCH_TOKEN_ALLOCATE_LOCAL_SURFACE;
pPatch->Size = sizeof(iOpenCL::SPatchAllocateLocalSurface);
pPatch->TotalInlineLocalMemorySize = static_cast<uint32_t>(pDevice->getDeviceInfo().localMemSize * 2);
binSize += sizeof(SPatchAllocateLocalSurface);
pBin += sizeof(SPatchAllocateLocalSurface);
pKHdr->CheckSum = PatchTokenBinary::calcKernelChecksum(ArrayRef<const uint8_t>(reinterpret_cast<uint8_t *>(pKHdr), reinterpret_cast<uint8_t *>(pBin)));
// Decode prepared program binary
program->genBinary = makeCopy(&genBin[0], binSize);
program->genBinarySize = binSize;
retVal = program->processGenBinary();
PatchTokensTestData::ValidProgramWithKernelUsingSlm patchtokensProgram;
patchtokensProgram.slmMutable->TotalInlineLocalMemorySize = static_cast<uint32_t>(pDevice->getDeviceInfo().localMemSize * 2);
patchtokensProgram.recalcTokPtr();
auto program = std::make_unique<MockProgram>(*pDevice->getExecutionEnvironment(), nullptr, false);
program->genBinary = makeCopy(patchtokensProgram.storage.data(), patchtokensProgram.storage.size());
program->genBinarySize = patchtokensProgram.storage.size();
auto retVal = program->processGenBinary();
EXPECT_EQ(CL_OUT_OF_RESOURCES, retVal);
}
TEST_F(ProgramTests, ProgramFromGenBinaryWithPATCH_TOKEN_GTPIN_FREE_GRF_INFO) {
#define GRF_INFO_SIZE 44u
cl_int retVal = CL_INVALID_BINARY;
char genBin[1024] = {1, 2, 3, 4, 5, 6, 7, 8, 9, '\0'};
size_t binSize = 10;
MockProgram *pProgram = Program::createFromGenBinary<MockProgram>(*pDevice->getExecutionEnvironment(), nullptr, &genBin[0], binSize, false, &retVal);
EXPECT_NE(nullptr, pProgram);
EXPECT_EQ(CL_SUCCESS, retVal);
EXPECT_EQ((uint32_t)CL_PROGRAM_BINARY_TYPE_EXECUTABLE, (uint32_t)pProgram->getProgramBinaryType());
cl_device_id deviceId = pContext->getDevice(0);
ClDevice *pDevice = castToObject<ClDevice>(deviceId);
char *pBin = &genBin[0];
retVal = CL_INVALID_BINARY;
binSize = 0;
// Prepare simple program binary containing patch token PATCH_TOKEN_GTPIN_FREE_GRF_INFO
SProgramBinaryHeader *pBHdr = (SProgramBinaryHeader *)pBin;
pBHdr->Magic = iOpenCL::MAGIC_CL;
pBHdr->Version = iOpenCL::CURRENT_ICBE_VERSION;
pBHdr->Device = pDevice->getHardwareInfo().platform.eRenderCoreFamily;
pBHdr->GPUPointerSizeInBytes = 8;
pBHdr->NumberOfKernels = 1;
pBHdr->SteppingId = 0;
pBHdr->PatchListSize = 0;
pBin += sizeof(SProgramBinaryHeader);
binSize += sizeof(SProgramBinaryHeader);
uint32_t patchTokenSize = sizeof(iOpenCL::SPatchGtpinFreeGRFInfo) + GRF_INFO_SIZE;
SKernelBinaryHeaderCommon *pKHdr = (SKernelBinaryHeaderCommon *)pBin;
pKHdr->CheckSum = 0;
pKHdr->ShaderHashCode = 0;
pKHdr->KernelNameSize = 8;
pKHdr->PatchListSize = patchTokenSize;
pKHdr->KernelHeapSize = 0;
pKHdr->GeneralStateHeapSize = 0;
pKHdr->DynamicStateHeapSize = 0;
pKHdr->SurfaceStateHeapSize = 0;
pKHdr->KernelUnpaddedSize = 0;
pBin += sizeof(SKernelBinaryHeaderCommon);
binSize += sizeof(SKernelBinaryHeaderCommon);
strcpy(pBin, "TstCopy");
pBin += pKHdr->KernelNameSize;
binSize += pKHdr->KernelNameSize;
SPatchGtpinFreeGRFInfo *pPatch = (SPatchGtpinFreeGRFInfo *)pBin;
pPatch->Token = iOpenCL::PATCH_TOKEN_GTPIN_FREE_GRF_INFO;
pPatch->Size = patchTokenSize;
pPatch->BufferSize = GRF_INFO_SIZE;
binSize += pPatch->Size;
pBin += pPatch->Size;
pKHdr->CheckSum = PatchTokenBinary::calcKernelChecksum(ArrayRef<const uint8_t>(reinterpret_cast<uint8_t *>(pKHdr), reinterpret_cast<uint8_t *>(pBin)));
// Decode prepared program binary
pProgram->genBinary = makeCopy(&genBin[0], binSize);
pProgram->genBinarySize = binSize;
retVal = pProgram->processGenBinary();
EXPECT_EQ(CL_SUCCESS, retVal);
delete pProgram;
#undef GRF_INFO_SIZE
}
TEST_F(ProgramTests, ValidBinaryWithIGCVersionEqual0) {
cl_int retVal;
@@ -2989,19 +2823,6 @@ TEST(RebuildProgramFromIrTests, givenBinaryProgramWhenKernelRebulildIsNotForcedT
EXPECT_FALSE(pProgram->rebuildProgramFromIrCalled);
}
TEST(Program, whenGetKernelNamesStringIsCalledThenNamesAreProperlyConcatenated) {
ExecutionEnvironment execEnv;
MockProgram program{execEnv};
KernelInfo kernel1 = {};
kernel1.name = "kern1";
KernelInfo kernel2 = {};
kernel2.name = "kern2";
program.getKernelInfoArray().push_back(&kernel1);
program.getKernelInfoArray().push_back(&kernel2);
EXPECT_EQ("kern1;kern2", program.getKernelNamesString());
program.getKernelInfoArray().clear();
}
struct SpecializationConstantProgramMock : public MockProgram {
using MockProgram::MockProgram;
cl_int updateSpecializationConstant(cl_uint specId, size_t specSize, const void *specValue) override {

View File

@@ -367,9 +367,11 @@ HWTEST_F(SamplerSetArgTest, setKernelArgWithInvalidSampler) {
TEST_F(SamplerSetArgTest, givenSamplerTypeStrAndIsSamplerTrueWhenInitializeKernelThenKernelArgumentsTypeIsSamplerObj) {
pKernelInfo->kernelArgInfo.resize(2);
pKernelInfo->kernelArgInfo[0].typeStr = "sampler*";
pKernelInfo->kernelArgInfo[0].metadataExtended = std::make_unique<ArgTypeMetadataExtended>();
pKernelInfo->kernelArgInfo[0].metadataExtended->type = "sampler*";
pKernelInfo->kernelArgInfo[0].isSampler = true;
pKernelInfo->kernelArgInfo[1].typeStr = "sampler";
pKernelInfo->kernelArgInfo[1].metadataExtended = std::make_unique<ArgTypeMetadataExtended>();
pKernelInfo->kernelArgInfo[1].metadataExtended->type = "sampler";
pKernelInfo->kernelArgInfo[1].isSampler = true;
auto pMockKernell = std::make_unique<MockKernel>(program.get(), *pKernelInfo, *pClDevice);
@@ -380,9 +382,11 @@ TEST_F(SamplerSetArgTest, givenSamplerTypeStrAndIsSamplerTrueWhenInitializeKerne
TEST_F(SamplerSetArgTest, givenSamplerTypeStrAndAndIsSamplerFalseWhenInitializeKernelThenKernelArgumentsTypeIsNotSamplerObj) {
pKernelInfo->kernelArgInfo.resize(2);
pKernelInfo->kernelArgInfo[0].typeStr = "sampler*";
pKernelInfo->kernelArgInfo[0].metadataExtended = std::make_unique<ArgTypeMetadataExtended>();
pKernelInfo->kernelArgInfo[0].metadataExtended->type = "sampler*";
pKernelInfo->kernelArgInfo[0].isSampler = false;
pKernelInfo->kernelArgInfo[1].typeStr = "sampler";
pKernelInfo->kernelArgInfo[1].metadataExtended = std::make_unique<ArgTypeMetadataExtended>();
pKernelInfo->kernelArgInfo[1].metadataExtended->type = "sampler";
pKernelInfo->kernelArgInfo[1].isSampler = false;
auto pMockKernell = std::make_unique<MockKernel>(program.get(), *pKernelInfo, *pClDevice);

View File

@@ -50,7 +50,7 @@ class MockSchedulerKernel : public SchedulerKernel {
bufferArg.kernelArgPatchInfoVector[0].crossthreadOffset = 0;
bufferArg.kernelArgPatchInfoVector[0].size = 0;
bufferArg.kernelArgPatchInfoVector[0].sourceOffset = 0;
info->kernelArgInfo.push_back(bufferArg);
info->kernelArgInfo.push_back(std::move(bufferArg));
}
MockSchedulerKernel *mock = Kernel::create<MockSchedulerKernel>(&program, *info, nullptr);

View File

@@ -525,7 +525,7 @@ TEST(FileLogger, WithDebugFunctionalityDumpKernelArgsLocalBuffer) {
kernelInfo->kernelArgInfo.resize(1);
kernelInfo->kernelArgInfo[0].kernelArgPatchInfoVector.push_back(kernelArgPatchInfo);
kernelInfo->kernelArgInfo[0].addressQualifier = static_cast<cl_kernel_arg_address_qualifier>(CL_KERNEL_ARG_ADDRESS_LOCAL);
kernelInfo->kernelArgInfo[0].metadata.addressQualifier = KernelArgMetadata::AddressSpaceQualifier::Local;
std::string testFile = "testfile";
DebugVariables flags;
@@ -547,8 +547,9 @@ TEST(FileLogger, WithDebugFunctionalityDumpKernelArgsBufferNotSet) {
KernelArgPatchInfo kernelArgPatchInfo;
kernelInfo->kernelArgInfo.resize(1);
kernelInfo->kernelArgInfo[0].metadataExtended = std::make_unique<NEO::ArgTypeMetadataExtended>();
kernelInfo->kernelArgInfo[0].kernelArgPatchInfoVector.push_back(kernelArgPatchInfo);
kernelInfo->kernelArgInfo[0].typeStr = "uint8 *buffer";
kernelInfo->kernelArgInfo[0].metadataExtended->type = "uint8 *buffer";
kernel->initialize();
@@ -580,8 +581,9 @@ TEST(FileLogger, WithDebugFunctionalityDumpKernelArgsBuffer) {
KernelArgPatchInfo kernelArgPatchInfo;
kernelInfo->kernelArgInfo.resize(1);
kernelInfo->kernelArgInfo[0].metadataExtended = std::make_unique<NEO::ArgTypeMetadataExtended>();
kernelInfo->kernelArgInfo[0].kernelArgPatchInfoVector.push_back(kernelArgPatchInfo);
kernelInfo->kernelArgInfo[0].typeStr = "uint8 *buffer";
kernelInfo->kernelArgInfo[0].metadataExtended->type = "uint8 *buffer";
kernelInfo->kernelArgInfo.at(0).isBuffer = true;
kernel->initialize();
@@ -618,8 +620,9 @@ TEST(FileLogger, WithDebugFunctionalityDumpKernelArgsSampler) {
KernelArgPatchInfo kernelArgPatchInfo;
kernelInfo->kernelArgInfo.resize(1);
kernelInfo->kernelArgInfo[0].metadataExtended = std::make_unique<NEO::ArgTypeMetadataExtended>();
kernelInfo->kernelArgInfo[0].kernelArgPatchInfoVector.push_back(kernelArgPatchInfo);
kernelInfo->kernelArgInfo[0].typeStr = "sampler test";
kernelInfo->kernelArgInfo[0].metadataExtended->type = "sampler test";
kernel->initialize();
@@ -653,8 +656,9 @@ TEST(FileLogger, WithDebugFunctionalityDumpKernelArgsImageNotSet) {
KernelArgPatchInfo kernelArgPatchInfo;
kernelInfo->kernelArgInfo.resize(1);
kernelInfo->kernelArgInfo[0].metadataExtended = std::make_unique<NEO::ArgTypeMetadataExtended>();
kernelInfo->kernelArgInfo[0].kernelArgPatchInfoVector.push_back(kernelArgPatchInfo);
kernelInfo->kernelArgInfo[0].typeStr = "image2d buffer";
kernelInfo->kernelArgInfo[0].metadataExtended->type = "image2d buffer";
kernelInfo->kernelArgInfo[0].isImage = true;
kernelInfo->kernelArgInfo[0].offsetImgWidth = 0x4;