mirror of
https://github.com/intel/compute-runtime.git
synced 2026-01-03 14:55:24 +08:00
Program refactor
* Decouple binary program handling from Program object * Add binary formats multiplexer * Improve Elf format support Change-Id: Ic22aff40173532e14825d70b82ec53fcc5fa9fdf
This commit is contained in:
@@ -48,7 +48,6 @@ if(WIN32)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
target_link_libraries(${NEO_STATIC_LIB_NAME} elflib)
|
||||
if(DEFINED AUB_STREAM_DIR)
|
||||
target_link_libraries(${NEO_STATIC_LIB_NAME} ${AUB_STREAM_PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
@@ -30,7 +30,6 @@ set(RUNTIME_SRCS_DLL_BASE
|
||||
${NEO_SOURCE_DIR}/runtime/api/api.cpp
|
||||
${NEO_SOURCE_DIR}/runtime/compiler_interface/default_cache_config.cpp
|
||||
${NEO_SOURCE_DIR}/runtime/helpers/built_ins_helper.cpp
|
||||
${NEO_SOURCE_DIR}/runtime/program/evaluate_unhandled_token.cpp
|
||||
|
||||
${GTPIN_INIT_FILE}
|
||||
${HW_SRC_LINK}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (C) 2018-2019 Intel Corporation
|
||||
# Copyright (C) 2018-2020 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
@@ -25,9 +25,8 @@ set(RUNTIME_SRCS_PROGRAM
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/patch_info.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/printf_handler.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/printf_handler.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/process_elf_binary.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/process_gen_binary.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/process_spir_binary.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/process_device_binary.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/process_intermediate_binary.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/program.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/program.h
|
||||
)
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "core/compiler_interface/compiler_interface.h"
|
||||
#include "core/device/device.h"
|
||||
#include "core/device_binary_format/device_binary_formats.h"
|
||||
#include "core/execution_environment/execution_environment.h"
|
||||
#include "core/utilities/time_measure_wrapper.h"
|
||||
#include "runtime/device/cl_device.h"
|
||||
@@ -125,8 +126,7 @@ cl_int Program::build(
|
||||
this->irBinarySize = compilerOuput.intermediateRepresentation.size;
|
||||
this->isSpirV = compilerOuput.intermediateCodeType == IGC::CodeType::spirV;
|
||||
}
|
||||
this->genBinary = std::move(compilerOuput.deviceBinary.mem);
|
||||
this->genBinarySize = compilerOuput.deviceBinary.size;
|
||||
this->replaceDeviceBinary(std::move(compilerOuput.deviceBinary.mem), compilerOuput.deviceBinary.size);
|
||||
this->debugData = std::move(compilerOuput.debugData.mem);
|
||||
this->debugDataSize = compilerOuput.debugData.size;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,10 @@
|
||||
*/
|
||||
|
||||
#include "core/compiler_interface/compiler_interface.h"
|
||||
#include "core/elf/writer.h"
|
||||
#include "core/device/device.h"
|
||||
#include "core/device_binary_format/elf/elf.h"
|
||||
#include "core/device_binary_format/elf/elf_encoder.h"
|
||||
#include "core/device_binary_format/elf/ocl_elf.h"
|
||||
#include "core/execution_environment/execution_environment.h"
|
||||
#include "runtime/device/cl_device.h"
|
||||
#include "runtime/helpers/validators.h"
|
||||
@@ -30,9 +33,6 @@ cl_int Program::compile(
|
||||
void(CL_CALLBACK *funcNotify)(cl_program program, void *userData),
|
||||
void *userData) {
|
||||
cl_int retVal = CL_SUCCESS;
|
||||
cl_program program;
|
||||
Program *pHeaderProgObj;
|
||||
size_t compileDataSize;
|
||||
|
||||
do {
|
||||
if (((deviceList == nullptr) && (numDevices != 0)) ||
|
||||
@@ -89,43 +89,35 @@ cl_int Program::compile(
|
||||
}
|
||||
|
||||
// create ELF writer to process all sources to be compiled
|
||||
CLElfLib::CElfWriter elfWriter(CLElfLib::E_EH_TYPE::EH_TYPE_OPENCL_SOURCE, CLElfLib::E_EH_MACHINE::EH_MACHINE_NONE, 0);
|
||||
|
||||
CLElfLib::SSectionNode sectionNode(CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_SOURCE, CLElfLib::E_SH_FLAG::SH_FLAG_NONE, "CLMain", sourceCode, static_cast<uint32_t>(sourceCode.size() + 1u));
|
||||
|
||||
// add main program's source
|
||||
elfWriter.addSection(sectionNode);
|
||||
NEO::Elf::ElfEncoder<> elfEncoder(true, true, 1U);
|
||||
elfEncoder.getElfFileHeader().type = NEO::Elf::ET_OPENCL_SOURCE;
|
||||
elfEncoder.appendSection(NEO::Elf::SHT_OPENCL_SOURCE, "CLMain", sourceCode);
|
||||
|
||||
for (cl_uint i = 0; i < numInputHeaders; i++) {
|
||||
program = inputHeaders[i];
|
||||
auto program = inputHeaders[i];
|
||||
if (program == nullptr) {
|
||||
retVal = CL_INVALID_PROGRAM;
|
||||
break;
|
||||
}
|
||||
pHeaderProgObj = castToObject<Program>(program);
|
||||
auto pHeaderProgObj = castToObject<Program>(program);
|
||||
if (pHeaderProgObj == nullptr) {
|
||||
retVal = CL_INVALID_PROGRAM;
|
||||
break;
|
||||
}
|
||||
sectionNode.name = headerIncludeNames[i];
|
||||
sectionNode.type = CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_HEADER;
|
||||
sectionNode.flag = CLElfLib::E_SH_FLAG::SH_FLAG_NONE;
|
||||
// collect required data from the header
|
||||
retVal = pHeaderProgObj->getSource(sectionNode.data);
|
||||
|
||||
std::string includeHeaderSource;
|
||||
retVal = pHeaderProgObj->getSource(includeHeaderSource);
|
||||
if (retVal != CL_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
|
||||
sectionNode.dataSize = static_cast<uint32_t>(sectionNode.data.size());
|
||||
elfWriter.addSection(sectionNode);
|
||||
elfEncoder.appendSection(NEO::Elf::SHT_OPENCL_HEADER, ConstStringRef(headerIncludeNames[i], strlen(headerIncludeNames[i])), includeHeaderSource);
|
||||
}
|
||||
if (retVal != CL_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
|
||||
compileDataSize = elfWriter.getTotalBinarySize();
|
||||
CLElfLib::ElfBinaryStorage compileData(compileDataSize);
|
||||
elfWriter.resolveBinary(compileData);
|
||||
std::vector<uint8_t> compileData = elfEncoder.encode();
|
||||
|
||||
CompilerInterface *pCompilerInterface = this->executionEnvironment.getCompilerInterface();
|
||||
if (!pCompilerInterface) {
|
||||
@@ -148,7 +140,7 @@ cl_int Program::compile(
|
||||
}
|
||||
}
|
||||
|
||||
inputArgs.src = ArrayRef<const char>(compileData.data(), compileDataSize);
|
||||
inputArgs.src = ArrayRef<const char>(reinterpret_cast<const char *>(compileData.data()), compileData.size());
|
||||
inputArgs.apiOptions = ArrayRef<const char>(options.c_str(), options.length());
|
||||
inputArgs.internalOptions = ArrayRef<const char>(internalOptions.c_str(), internalOptions.length());
|
||||
|
||||
|
||||
@@ -144,11 +144,9 @@ T *Program::createFromGenBinary(
|
||||
if (CL_SUCCESS == retVal) {
|
||||
program = new T(executionEnvironment, context, isBuiltIn);
|
||||
program->numDevices = 1;
|
||||
program->genBinary = makeCopy(binary, size);
|
||||
program->genBinarySize = size;
|
||||
program->replaceDeviceBinary(makeCopy(binary, size), size);
|
||||
program->isCreatedFromBinary = true;
|
||||
program->programBinaryType = CL_PROGRAM_BINARY_TYPE_EXECUTABLE;
|
||||
program->isProgramBinaryResolved = true;
|
||||
program->buildStatus = CL_BUILD_SUCCESS;
|
||||
program->createdFrom = CreatedFrom::BINARY;
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2019 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "runtime/program/program.h"
|
||||
|
||||
namespace NEO {
|
||||
|
||||
bool Program::isSafeToSkipUnhandledToken(unsigned int token) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace NEO
|
||||
@@ -36,10 +36,10 @@ cl_int Program::getInfo(cl_program_info paramName, size_t paramValueSize,
|
||||
break;
|
||||
|
||||
case CL_PROGRAM_BINARIES:
|
||||
resolveProgramBinary();
|
||||
pSrc = elfBinary.data();
|
||||
packDeviceBinary();
|
||||
pSrc = packedDeviceBinary.get();
|
||||
retSize = sizeof(void **);
|
||||
srcSize = elfBinarySize;
|
||||
srcSize = packedDeviceBinarySize;
|
||||
if (paramValue != nullptr) {
|
||||
if (paramValueSize < retSize) {
|
||||
retVal = CL_INVALID_VALUE;
|
||||
@@ -51,8 +51,8 @@ cl_int Program::getInfo(cl_program_info paramName, size_t paramValueSize,
|
||||
break;
|
||||
|
||||
case CL_PROGRAM_BINARY_SIZES:
|
||||
resolveProgramBinary();
|
||||
pSrc = &elfBinarySize;
|
||||
packDeviceBinary();
|
||||
pSrc = &packedDeviceBinarySize;
|
||||
retSize = srcSize = sizeof(size_t *);
|
||||
break;
|
||||
|
||||
@@ -116,13 +116,11 @@ cl_int Program::getInfo(cl_program_info paramName, size_t paramValueSize,
|
||||
break;
|
||||
|
||||
case CL_PROGRAM_DEBUG_INFO_SIZES_INTEL:
|
||||
resolveProgramBinary();
|
||||
retSize = srcSize = sizeof(debugDataSize);
|
||||
pSrc = &debugDataSize;
|
||||
break;
|
||||
|
||||
case CL_PROGRAM_DEBUG_INFO_INTEL:
|
||||
resolveProgramBinary();
|
||||
pSrc = debugData.get();
|
||||
retSize = numDevices * sizeof(void **);
|
||||
srcSize = debugDataSize;
|
||||
|
||||
@@ -425,6 +425,37 @@ bool KernelInfo::createKernelAllocation(uint32_t rootDeviceIndex, MemoryManager
|
||||
return memoryManager->copyMemoryToAllocation(kernelAllocation, heapInfo.pKernelHeap, kernelIsaSize);
|
||||
}
|
||||
|
||||
void KernelInfo::apply(const DeviceInfoKernelPayloadConstants &constants) {
|
||||
if (nullptr == this->crossThreadData) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t privateMemoryStatelessSizeOffset = this->workloadInfo.privateMemoryStatelessSizeOffset;
|
||||
uint32_t localMemoryStatelessWindowSizeOffset = this->workloadInfo.localMemoryStatelessWindowSizeOffset;
|
||||
uint32_t localMemoryStatelessWindowStartAddressOffset = this->workloadInfo.localMemoryStatelessWindowStartAddressOffset;
|
||||
|
||||
if (localMemoryStatelessWindowStartAddressOffset != WorkloadInfo::undefinedOffset) {
|
||||
*(uintptr_t *)&(this->crossThreadData[localMemoryStatelessWindowStartAddressOffset]) = reinterpret_cast<uintptr_t>(constants.slmWindow);
|
||||
}
|
||||
|
||||
if (localMemoryStatelessWindowSizeOffset != WorkloadInfo::undefinedOffset) {
|
||||
*(uint32_t *)&(this->crossThreadData[localMemoryStatelessWindowSizeOffset]) = constants.slmWindowSize;
|
||||
}
|
||||
|
||||
uint32_t privateMemorySize = 0U;
|
||||
if (this->patchInfo.pAllocateStatelessPrivateSurface) {
|
||||
privateMemorySize = this->patchInfo.pAllocateStatelessPrivateSurface->PerThreadPrivateMemorySize * constants.computeUnitsUsedForScratch * this->getMaxSimdSize();
|
||||
}
|
||||
|
||||
if (privateMemoryStatelessSizeOffset != WorkloadInfo::undefinedOffset) {
|
||||
*(uint32_t *)&(this->crossThreadData[privateMemoryStatelessSizeOffset]) = privateMemorySize;
|
||||
}
|
||||
|
||||
if (this->workloadInfo.maxWorkGroupSizeOffset != WorkloadInfo::undefinedOffset) {
|
||||
*(uint32_t *)&(this->crossThreadData[this->workloadInfo.maxWorkGroupSizeOffset]) = constants.maxWorkGroupSize;
|
||||
}
|
||||
}
|
||||
|
||||
std::string concatenateKernelNames(ArrayRef<KernelInfo *> kernelInfos) {
|
||||
std::string semiColonDelimitedKernelNameStr;
|
||||
|
||||
|
||||
@@ -188,6 +188,7 @@ struct KernelInfo {
|
||||
}
|
||||
|
||||
bool createKernelAllocation(uint32_t rootDeviceIndex, MemoryManager *memoryManager);
|
||||
void apply(const DeviceInfoKernelPayloadConstants &constants);
|
||||
|
||||
std::string name;
|
||||
std::string attributes;
|
||||
|
||||
@@ -141,8 +141,7 @@ void populateKernelInfoArg(KernelInfo &dstKernelInfo, KernelArgInfo &dstKernelIn
|
||||
dstKernelInfoArg.offsetObjectId = getOffset(src.objectId);
|
||||
}
|
||||
|
||||
void populateKernelInfo(KernelInfo &dst, const PatchTokenBinary::KernelFromPatchtokens &src, uint32_t gpuPointerSizeInBytes,
|
||||
const DeviceInfoKernelPayloadConstants &constants) {
|
||||
void populateKernelInfo(KernelInfo &dst, const PatchTokenBinary::KernelFromPatchtokens &src, uint32_t gpuPointerSizeInBytes) {
|
||||
UNRECOVERABLE_IF(nullptr == src.header);
|
||||
dst.heapInfo.pKernelHeader = src.header;
|
||||
dst.name = std::string(src.name.begin(), src.name.end()).c_str();
|
||||
@@ -220,31 +219,6 @@ void populateKernelInfo(KernelInfo &dst, const PatchTokenBinary::KernelFromPatch
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,14 +11,12 @@
|
||||
|
||||
namespace NEO {
|
||||
|
||||
struct DeviceInfoKernelPayloadConstants;
|
||||
struct KernelInfo;
|
||||
|
||||
namespace PatchTokenBinary {
|
||||
struct KernelFromPatchtokens;
|
||||
}
|
||||
|
||||
void populateKernelInfo(KernelInfo &dst, const PatchTokenBinary::KernelFromPatchtokens &src, uint32_t gpuPointerSizeInBytes,
|
||||
const DeviceInfoKernelPayloadConstants &constant);
|
||||
void populateKernelInfo(KernelInfo &dst, const PatchTokenBinary::KernelFromPatchtokens &src, uint32_t gpuPointerSizeInBytes);
|
||||
|
||||
} // namespace NEO
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
*/
|
||||
|
||||
#include "core/compiler_interface/compiler_interface.h"
|
||||
#include "core/elf/writer.h"
|
||||
#include "core/device_binary_format/elf/elf.h"
|
||||
#include "core/device_binary_format/elf/elf_encoder.h"
|
||||
#include "core/device_binary_format/elf/ocl_elf.h"
|
||||
#include "core/execution_environment/execution_environment.h"
|
||||
#include "core/utilities/stackvec.h"
|
||||
#include "runtime/device/cl_device.h"
|
||||
@@ -30,9 +32,6 @@ cl_int Program::link(
|
||||
void(CL_CALLBACK *funcNotify)(cl_program program, void *userData),
|
||||
void *userData) {
|
||||
cl_int retVal = CL_SUCCESS;
|
||||
cl_program program;
|
||||
Program *pInputProgObj;
|
||||
size_t dataSize;
|
||||
bool isCreateLibrary;
|
||||
|
||||
do {
|
||||
@@ -73,16 +72,17 @@ cl_int Program::link(
|
||||
|
||||
buildStatus = CL_BUILD_IN_PROGRESS;
|
||||
|
||||
CLElfLib::CElfWriter elfWriter(CLElfLib::E_EH_TYPE::EH_TYPE_OPENCL_OBJECTS, CLElfLib::E_EH_MACHINE::EH_MACHINE_NONE, 0);
|
||||
NEO::Elf::ElfEncoder<> elfEncoder(true, false, 1U);
|
||||
elfEncoder.getElfFileHeader().type = NEO::Elf::ET_OPENCL_OBJECTS;
|
||||
|
||||
StackVec<const Program *, 16> inputProgramsInternal;
|
||||
for (cl_uint i = 0; i < numInputPrograms; i++) {
|
||||
program = inputPrograms[i];
|
||||
auto program = inputPrograms[i];
|
||||
if (program == nullptr) {
|
||||
retVal = CL_INVALID_PROGRAM;
|
||||
break;
|
||||
}
|
||||
pInputProgObj = castToObject<Program>(program);
|
||||
auto pInputProgObj = castToObject<Program>(program);
|
||||
if (pInputProgObj == nullptr) {
|
||||
retVal = CL_INVALID_PROGRAM;
|
||||
break;
|
||||
@@ -93,16 +93,15 @@ cl_int Program::link(
|
||||
break;
|
||||
}
|
||||
|
||||
elfWriter.addSection(CLElfLib::SSectionNode(pInputProgObj->getIsSpirV() ? CLElfLib::E_SH_TYPE::SH_TYPE_SPIRV : CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_LLVM_BINARY,
|
||||
CLElfLib::E_SH_FLAG::SH_FLAG_NONE, "", std::string(pInputProgObj->irBinary.get(), pInputProgObj->irBinarySize), static_cast<uint32_t>(pInputProgObj->irBinarySize)));
|
||||
auto sectionType = pInputProgObj->getIsSpirV() ? NEO::Elf::SHT_OPENCL_SPIRV : NEO::Elf::SHT_OPENCL_LLVM_BINARY;
|
||||
ConstStringRef sectionName = pInputProgObj->getIsSpirV() ? NEO::Elf::SectionNamesOpenCl::spirvObject : NEO::Elf::SectionNamesOpenCl::llvmObject;
|
||||
elfEncoder.appendSection(sectionType, sectionName, ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(pInputProgObj->irBinary.get()), pInputProgObj->irBinarySize));
|
||||
}
|
||||
if (retVal != CL_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
|
||||
dataSize = elfWriter.getTotalBinarySize();
|
||||
CLElfLib::ElfBinaryStorage data(dataSize);
|
||||
elfWriter.resolveBinary(data);
|
||||
auto clLinkInput = elfEncoder.encode();
|
||||
|
||||
CompilerInterface *pCompilerInterface = this->executionEnvironment.getCompilerInterface();
|
||||
if (!pCompilerInterface) {
|
||||
@@ -112,7 +111,7 @@ cl_int Program::link(
|
||||
|
||||
TranslationInput inputArgs = {IGC::CodeType::elf, IGC::CodeType::undefined};
|
||||
|
||||
inputArgs.src = ArrayRef<const char>(data.data(), dataSize);
|
||||
inputArgs.src = ArrayRef<const char>(reinterpret_cast<const char *>(clLinkInput.data()), clLinkInput.size());
|
||||
inputArgs.apiOptions = ArrayRef<const char>(options.c_str(), options.length());
|
||||
inputArgs.internalOptions = ArrayRef<const char>(internalOptions.c_str(), internalOptions.length());
|
||||
|
||||
@@ -127,8 +126,7 @@ cl_int Program::link(
|
||||
break;
|
||||
}
|
||||
|
||||
this->genBinary = std::move(compilerOuput.deviceBinary.mem);
|
||||
this->genBinarySize = compilerOuput.deviceBinary.size;
|
||||
this->replaceDeviceBinary(std::move(compilerOuput.deviceBinary.mem), compilerOuput.deviceBinary.size);
|
||||
this->debugData = std::move(compilerOuput.debugData.mem);
|
||||
this->debugDataSize = compilerOuput.debugData.size;
|
||||
|
||||
|
||||
@@ -5,27 +5,21 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "core/device_binary_format/patchtokens_decoder.h"
|
||||
#include "core/device_binary_format/patchtokens_dumper.h"
|
||||
#include "core/device_binary_format/patchtokens_validator.inl"
|
||||
#include "core/device_binary_format/device_binary_formats.h"
|
||||
#include "core/helpers/aligned_memory.h"
|
||||
#include "core/helpers/debug_helpers.h"
|
||||
#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/context/context.h"
|
||||
#include "runtime/device/cl_device.h"
|
||||
#include "runtime/gtpin/gtpin_notify.h"
|
||||
#include "runtime/memory_manager/memory_manager.h"
|
||||
#include "runtime/program/kernel_info.h"
|
||||
#include "runtime/program/kernel_info_from_patchtokens.h"
|
||||
#include "runtime/program/program.h"
|
||||
|
||||
#include "patch_list.h"
|
||||
#include "patch_shared.h"
|
||||
#include "program_debug_data.h"
|
||||
|
||||
#include <algorithm>
|
||||
@@ -56,26 +50,6 @@ const KernelInfo *Program::getKernelInfo(size_t ordinal) const {
|
||||
return kernelInfoArray[ordinal];
|
||||
}
|
||||
|
||||
cl_int Program::isHandled(const PatchTokenBinary::ProgramFromPatchtokens &decodedProgram) const {
|
||||
std::string validatorErrMessage;
|
||||
std::string validatorWarnings;
|
||||
auto availableSlm = this->pDevice ? static_cast<size_t>(this->pDevice->getDeviceInfo().localMemSize) : 0U;
|
||||
auto validatorErr = PatchTokenBinary::validate(decodedProgram, availableSlm, *this, validatorErrMessage, validatorWarnings);
|
||||
if (validatorWarnings.empty() == false) {
|
||||
printDebugString(DebugManager.flags.PrintDebugMessages.get(), stderr, "%s\n", validatorWarnings.c_str());
|
||||
}
|
||||
if (validatorErr != PatchTokenBinary::ValidatorError::Success) {
|
||||
printDebugString(DebugManager.flags.PrintDebugMessages.get(), stderr, "%s\n", validatorErrMessage.c_str());
|
||||
switch (validatorErr) {
|
||||
default:
|
||||
return CL_INVALID_BINARY;
|
||||
case PatchTokenBinary::ValidatorError::NotEnoughSlm:
|
||||
return CL_OUT_OF_RESOURCES;
|
||||
}
|
||||
}
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
cl_int Program::linkBinary() {
|
||||
if (linkerInput == nullptr) {
|
||||
return CL_SUCCESS;
|
||||
@@ -146,6 +120,10 @@ cl_int Program::linkBinary() {
|
||||
}
|
||||
|
||||
cl_int Program::processGenBinary() {
|
||||
if (nullptr == this->unpackedDeviceBinary) {
|
||||
return CL_INVALID_BINARY;
|
||||
}
|
||||
|
||||
cleanCurrentKernelInfo();
|
||||
if (this->constantSurface || this->globalSurface) {
|
||||
pDevice->getMemoryManager()->freeGraphicsMemory(this->constantSurface);
|
||||
@@ -154,41 +132,45 @@ cl_int Program::processGenBinary() {
|
||||
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;
|
||||
auto blob = ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(this->unpackedDeviceBinary.get()), this->unpackedDeviceBinarySize);
|
||||
SingleDeviceBinary binary = {};
|
||||
binary.deviceBinary = blob;
|
||||
std::string decodeErrors;
|
||||
std::string decodeWarnings;
|
||||
|
||||
DecodeError decodeError;
|
||||
DeviceBinaryFormat singleDeviceBinaryFormat;
|
||||
std::tie(decodeError, singleDeviceBinaryFormat) = NEO::decodeSingleDeviceBinary(programInfo, binary, decodeErrors, decodeWarnings);
|
||||
if (decodeWarnings.empty() == false) {
|
||||
printDebugString(DebugManager.flags.PrintDebugMessages.get(), stderr, "%s\n", decodeWarnings.c_str());
|
||||
}
|
||||
|
||||
if (DecodeError::Success != decodeError) {
|
||||
printDebugString(DebugManager.flags.PrintDebugMessages.get(), stderr, "%s\n", decodeErrors.c_str());
|
||||
return CL_INVALID_BINARY;
|
||||
}
|
||||
|
||||
return this->processProgramInfo(programInfo);
|
||||
}
|
||||
|
||||
cl_int Program::processPatchTokensBinary(ArrayRef<const uint8_t> src, ProgramInfo &dst) {
|
||||
NEO::PatchTokenBinary::ProgramFromPatchtokens 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;
|
||||
}
|
||||
|
||||
cl_int Program::processProgramInfo(ProgramInfo &src) {
|
||||
size_t slmNeeded = getMaxInlineSlmNeeded(src);
|
||||
size_t slmAvailable = 0U;
|
||||
NEO::DeviceInfoKernelPayloadConstants deviceInfoConstants;
|
||||
if (this->pDevice) {
|
||||
slmAvailable = static_cast<size_t>(this->pDevice->getDeviceInfo().localMemSize);
|
||||
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)) {
|
||||
if (requiresLocalMemoryWindowVA(src)) {
|
||||
deviceInfoConstants.slmWindow = this->executionEnvironment.memoryManager->getReservedMemory(MemoryConstants::slmWindowSize, MemoryConstants::slmWindowAlignment);
|
||||
}
|
||||
}
|
||||
if (slmNeeded > slmAvailable) {
|
||||
return CL_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -221,23 +203,13 @@ cl_int Program::processProgramInfo(ProgramInfo &src) {
|
||||
if (kernelInfo->requiresSubgroupIndependentForwardProgress()) {
|
||||
subgroupKernelInfoArray.push_back(kernelInfo);
|
||||
}
|
||||
|
||||
kernelInfo->apply(deviceInfoConstants);
|
||||
}
|
||||
|
||||
return linkBinary();
|
||||
}
|
||||
|
||||
bool Program::validateGenBinaryDevice(GFXCORE_FAMILY device) const {
|
||||
bool isValid = familyEnabled[device];
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
bool Program::validateGenBinaryHeader(const iOpenCL::SProgramBinaryHeader *pGenBinaryHeader) const {
|
||||
return pGenBinaryHeader->Magic == MAGIC_CL &&
|
||||
pGenBinaryHeader->Version == CURRENT_ICBE_VERSION &&
|
||||
validateGenBinaryDevice(static_cast<GFXCORE_FAMILY>(pGenBinaryHeader->Device));
|
||||
}
|
||||
|
||||
void Program::processDebugData() {
|
||||
if (debugData != nullptr) {
|
||||
SProgramDebugDataHeaderIGC *programDebugHeader = reinterpret_cast<SProgramDebugDataHeaderIGC *>(debugData.get());
|
||||
@@ -1,165 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/compiler_support.h"
|
||||
#include "core/device_binary_format/patchtokens_decoder.h"
|
||||
#include "core/elf/reader.h"
|
||||
#include "core/elf/writer.h"
|
||||
#include "core/helpers/string.h"
|
||||
|
||||
#include "program.h"
|
||||
|
||||
namespace NEO {
|
||||
|
||||
cl_int Program::processElfBinary(
|
||||
const void *pBinary,
|
||||
size_t binarySize,
|
||||
uint32_t &binaryVersion) {
|
||||
const CLElfLib::SElf64Header *pElfHeader = nullptr;
|
||||
|
||||
binaryVersion = iOpenCL::CURRENT_ICBE_VERSION;
|
||||
|
||||
elfBinarySize = binarySize;
|
||||
elfBinary = CLElfLib::ElfBinaryStorage(reinterpret_cast<const char *>(pBinary), reinterpret_cast<const char *>(reinterpret_cast<const char *>(pBinary) + binarySize));
|
||||
|
||||
try {
|
||||
CLElfLib::CElfReader elfReader(elfBinary);
|
||||
|
||||
pElfHeader = elfReader.getElfHeader();
|
||||
|
||||
switch (pElfHeader->Type) {
|
||||
case CLElfLib::E_EH_TYPE::EH_TYPE_OPENCL_EXECUTABLE:
|
||||
programBinaryType = CL_PROGRAM_BINARY_TYPE_EXECUTABLE;
|
||||
break;
|
||||
|
||||
case CLElfLib::E_EH_TYPE::EH_TYPE_OPENCL_LIBRARY:
|
||||
programBinaryType = CL_PROGRAM_BINARY_TYPE_LIBRARY;
|
||||
break;
|
||||
|
||||
case CLElfLib::E_EH_TYPE::EH_TYPE_OPENCL_OBJECTS:
|
||||
programBinaryType = CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT;
|
||||
break;
|
||||
|
||||
default:
|
||||
return CL_INVALID_BINARY;
|
||||
}
|
||||
// section 0 is always null
|
||||
for (size_t i = 1u; i < elfReader.getSectionHeaders().size(); ++i) {
|
||||
const auto §ionHeader = elfReader.getSectionHeaders()[i];
|
||||
switch (sectionHeader.Type) {
|
||||
case CLElfLib::E_SH_TYPE::SH_TYPE_SPIRV:
|
||||
this->isSpirV = true;
|
||||
CPP_ATTRIBUTE_FALLTHROUGH;
|
||||
case CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_LLVM_BINARY:
|
||||
if (sectionHeader.DataSize > 0) {
|
||||
this->irBinary = makeCopy(elfReader.getSectionData(sectionHeader.DataOffset), static_cast<size_t>(sectionHeader.DataSize));
|
||||
this->irBinarySize = static_cast<size_t>(sectionHeader.DataSize);
|
||||
}
|
||||
break;
|
||||
|
||||
case CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_DEV_BINARY:
|
||||
if (sectionHeader.DataSize > 0 && validateGenBinaryHeader(reinterpret_cast<iOpenCL::SProgramBinaryHeader *>(elfReader.getSectionData(sectionHeader.DataOffset)))) {
|
||||
this->genBinary = makeCopy(elfReader.getSectionData(sectionHeader.DataOffset), static_cast<size_t>(sectionHeader.DataSize));
|
||||
this->genBinarySize = static_cast<size_t>(sectionHeader.DataSize);
|
||||
isCreatedFromBinary = true;
|
||||
} else {
|
||||
binaryVersion = reinterpret_cast<iOpenCL::SProgramBinaryHeader *>(elfReader.getSectionData(sectionHeader.DataOffset))->Version;
|
||||
return CL_INVALID_BINARY;
|
||||
}
|
||||
break;
|
||||
|
||||
case CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_OPTIONS:
|
||||
if (sectionHeader.DataSize > 0) {
|
||||
options = std::string(elfReader.getSectionData(sectionHeader.DataOffset), static_cast<size_t>(sectionHeader.DataSize));
|
||||
}
|
||||
break;
|
||||
|
||||
case CLElfLib::E_SH_TYPE::SH_TYPE_STR_TBL:
|
||||
// We can skip the string table
|
||||
break;
|
||||
|
||||
default:
|
||||
return CL_INVALID_BINARY;
|
||||
}
|
||||
}
|
||||
|
||||
isProgramBinaryResolved = true;
|
||||
|
||||
// Create an empty build log since program is effectively built
|
||||
updateBuildLog(pDevice, "", 1);
|
||||
} catch (const CLElfLib::ElfException &) {
|
||||
return CL_INVALID_BINARY;
|
||||
}
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
cl_int Program::resolveProgramBinary() {
|
||||
CLElfLib::E_EH_TYPE headerType;
|
||||
|
||||
if (isProgramBinaryResolved == false) {
|
||||
elfBinary.clear();
|
||||
elfBinarySize = 0;
|
||||
|
||||
switch (programBinaryType) {
|
||||
case CL_PROGRAM_BINARY_TYPE_EXECUTABLE:
|
||||
headerType = CLElfLib::E_EH_TYPE::EH_TYPE_OPENCL_EXECUTABLE;
|
||||
|
||||
if (!genBinary || !genBinarySize) {
|
||||
return CL_INVALID_BINARY;
|
||||
}
|
||||
break;
|
||||
|
||||
case CL_PROGRAM_BINARY_TYPE_LIBRARY:
|
||||
headerType = CLElfLib::E_EH_TYPE::EH_TYPE_OPENCL_LIBRARY;
|
||||
|
||||
if (!irBinary || !irBinarySize) {
|
||||
return CL_INVALID_BINARY;
|
||||
}
|
||||
break;
|
||||
|
||||
case CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT:
|
||||
headerType = CLElfLib::E_EH_TYPE::EH_TYPE_OPENCL_OBJECTS;
|
||||
|
||||
if (!irBinary || !irBinarySize) {
|
||||
return CL_INVALID_BINARY;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return CL_INVALID_BINARY;
|
||||
}
|
||||
|
||||
CLElfLib::CElfWriter elfWriter(headerType, CLElfLib::E_EH_MACHINE::EH_MACHINE_NONE, 0);
|
||||
|
||||
elfWriter.addSection(CLElfLib::SSectionNode(CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_OPTIONS, CLElfLib::E_SH_FLAG::SH_FLAG_NONE, "BuildOptions", options, static_cast<uint32_t>(strlen(options.c_str()) + 1u)));
|
||||
std::string irBinaryTemp = irBinary ? std::string(irBinary.get(), irBinarySize) : "";
|
||||
// Add the LLVM component if available
|
||||
elfWriter.addSection(CLElfLib::SSectionNode(getIsSpirV() ? CLElfLib::E_SH_TYPE::SH_TYPE_SPIRV : CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_LLVM_BINARY, CLElfLib::E_SH_FLAG::SH_FLAG_NONE,
|
||||
headerType == CLElfLib::E_EH_TYPE::EH_TYPE_OPENCL_LIBRARY ? "Intel(R) OpenCL LLVM Archive" : "Intel(R) OpenCL LLVM Object", std::move(irBinaryTemp), static_cast<uint32_t>(irBinarySize)));
|
||||
// Add the device binary if it exists
|
||||
if (genBinary) {
|
||||
std::string genBinaryTemp = genBinary ? std::string(genBinary.get(), genBinarySize) : "";
|
||||
elfWriter.addSection(CLElfLib::SSectionNode(CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_DEV_BINARY, CLElfLib::E_SH_FLAG::SH_FLAG_NONE, "Intel(R) OpenCL Device Binary", std::move(genBinaryTemp), static_cast<uint32_t>(genBinarySize)));
|
||||
}
|
||||
|
||||
// Add the device debug data if it exists
|
||||
if (debugData != nullptr) {
|
||||
std::string debugDataTemp = debugData ? std::string(debugData.get(), debugDataSize) : "";
|
||||
elfWriter.addSection(CLElfLib::SSectionNode(CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_DEV_DEBUG, CLElfLib::E_SH_FLAG::SH_FLAG_NONE, "Intel(R) OpenCL Device Debug", std::move(debugDataTemp), static_cast<uint32_t>(debugDataSize)));
|
||||
}
|
||||
|
||||
elfBinarySize = elfWriter.getTotalBinarySize();
|
||||
elfBinary = CLElfLib::ElfBinaryStorage(elfBinarySize);
|
||||
elfWriter.resolveBinary(elfBinary);
|
||||
isProgramBinaryResolved = true;
|
||||
} else {
|
||||
return CL_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
} // namespace NEO
|
||||
25
runtime/program/process_intermediate_binary.cpp
Normal file
25
runtime/program/process_intermediate_binary.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "program.h"
|
||||
|
||||
namespace NEO {
|
||||
cl_int Program::processSpirBinary(
|
||||
const void *pBinary,
|
||||
size_t binarySize,
|
||||
bool isSpirV) {
|
||||
programBinaryType = CL_PROGRAM_BINARY_TYPE_INTERMEDIATE;
|
||||
|
||||
this->irBinary = makeCopy(pBinary, binarySize);
|
||||
this->irBinarySize = binarySize;
|
||||
|
||||
buildStatus = CL_BUILD_NONE;
|
||||
this->isSpirV = isSpirV;
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
} // namespace NEO
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2019 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "program.h"
|
||||
|
||||
namespace NEO {
|
||||
|
||||
bool Program::isValidSpirvBinary(
|
||||
const void *pBinary,
|
||||
size_t binarySize) {
|
||||
|
||||
const uint32_t magicWord[2] = {0x03022307, 0x07230203};
|
||||
bool retVal = false;
|
||||
|
||||
if (pBinary && (binarySize > sizeof(uint32_t))) {
|
||||
if ((memcmp(pBinary, &magicWord[0], sizeof(uint32_t)) == 0) ||
|
||||
(memcmp(pBinary, &magicWord[1], sizeof(uint32_t)) == 0)) {
|
||||
retVal = true;
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
cl_int Program::processSpirBinary(
|
||||
const void *pBinary,
|
||||
size_t binarySize,
|
||||
bool isSpirV) {
|
||||
programBinaryType = CL_PROGRAM_BINARY_TYPE_INTERMEDIATE;
|
||||
|
||||
this->irBinary = makeCopy(pBinary, binarySize);
|
||||
this->irBinarySize = binarySize;
|
||||
|
||||
buildStatus = CL_BUILD_NONE;
|
||||
this->isSpirV = isSpirV;
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
} // namespace NEO
|
||||
@@ -8,7 +8,10 @@
|
||||
#include "program.h"
|
||||
|
||||
#include "core/compiler_interface/compiler_interface.h"
|
||||
#include "core/elf/writer.h"
|
||||
#include "core/compiler_interface/intermediate_representations.h"
|
||||
#include "core/device_binary_format/device_binary_formats.h"
|
||||
#include "core/device_binary_format/elf/elf_encoder.h"
|
||||
#include "core/device_binary_format/elf/ocl_elf.h"
|
||||
#include "core/helpers/debug_helpers.h"
|
||||
#include "core/helpers/hw_helper.h"
|
||||
#include "core/helpers/string.h"
|
||||
@@ -43,22 +46,6 @@ Program::Program(ExecutionEnvironment &executionEnvironment, Context *context, b
|
||||
blockKernelManager = new BlockKernelManager();
|
||||
pDevice = context ? context->getDevice(0) : nullptr;
|
||||
numDevices = 1;
|
||||
elfBinarySize = 0;
|
||||
genBinary = nullptr;
|
||||
genBinarySize = 0;
|
||||
irBinary = nullptr;
|
||||
irBinarySize = 0;
|
||||
debugData = nullptr;
|
||||
debugDataSize = 0;
|
||||
buildStatus = CL_BUILD_NONE;
|
||||
programBinaryType = CL_PROGRAM_BINARY_TYPE_NONE;
|
||||
isCreatedFromBinary = false;
|
||||
isProgramBinaryResolved = false;
|
||||
constantSurface = nullptr;
|
||||
globalSurface = nullptr;
|
||||
globalVarTotalSize = 0;
|
||||
programOptionVersion = 12u;
|
||||
allowNonUniform = false;
|
||||
char paramValue[32] = {};
|
||||
bool force32BitAddressess = false;
|
||||
|
||||
@@ -111,8 +98,6 @@ Program::Program(ExecutionEnvironment &executionEnvironment, Context *context, b
|
||||
}
|
||||
|
||||
Program::~Program() {
|
||||
elfBinarySize = 0;
|
||||
|
||||
cleanCurrentKernelInfo();
|
||||
|
||||
freeBlockResources();
|
||||
@@ -146,28 +131,68 @@ cl_int Program::createProgramFromBinary(
|
||||
const void *pBinary,
|
||||
size_t binarySize) {
|
||||
|
||||
cl_int retVal = CL_INVALID_PROGRAM;
|
||||
uint32_t binaryVersion = iOpenCL::CURRENT_ICBE_VERSION;
|
||||
cl_int retVal = CL_INVALID_BINARY;
|
||||
|
||||
if (Program::isValidLlvmBinary(pBinary, binarySize)) {
|
||||
retVal = processSpirBinary(pBinary, binarySize, false);
|
||||
} else if (Program::isValidSpirvBinary(pBinary, binarySize)) {
|
||||
retVal = processSpirBinary(pBinary, binarySize, true);
|
||||
} else {
|
||||
bool rebuildRequired = DebugManager.flags.RebuildPrecompiledKernels.get();
|
||||
retVal = processElfBinary(pBinary, binarySize, binaryVersion);
|
||||
if (retVal == CL_SUCCESS) {
|
||||
isCreatedFromBinary = true;
|
||||
} else if (binaryVersion != iOpenCL::CURRENT_ICBE_VERSION) {
|
||||
// Version of compiler used to create program binary is invalid,
|
||||
// needs to recompile program binary from its IR (if available).
|
||||
// if recompile fails propagate error retVal from previous function
|
||||
rebuildRequired = true;
|
||||
this->irBinary.reset();
|
||||
this->irBinarySize = 0U;
|
||||
this->isSpirV = false;
|
||||
this->unpackedDeviceBinary.reset();
|
||||
this->unpackedDeviceBinarySize = 0U;
|
||||
this->packedDeviceBinary.reset();
|
||||
this->packedDeviceBinarySize = 0U;
|
||||
|
||||
ArrayRef<const uint8_t> archive(reinterpret_cast<const uint8_t *>(pBinary), binarySize);
|
||||
bool isSpirV = NEO::isSpirVBitcode(archive);
|
||||
|
||||
if (isSpirV || NEO::isLlvmBitcode(archive)) {
|
||||
this->programBinaryType = CL_PROGRAM_BINARY_TYPE_INTERMEDIATE;
|
||||
retVal = processSpirBinary(archive.begin(), archive.size(), isSpirV);
|
||||
} else if (isAnyDeviceBinaryFormat(archive)) {
|
||||
this->programBinaryType = CL_PROGRAM_BINARY_TYPE_EXECUTABLE;
|
||||
this->isCreatedFromBinary = true;
|
||||
|
||||
auto productAbbreviation = hardwarePrefix[pDevice->getHardwareInfo().platform.eProductFamily];
|
||||
|
||||
TargetDevice targetDevice = {};
|
||||
targetDevice.coreFamily = pDevice->getHardwareInfo().platform.eRenderCoreFamily;
|
||||
targetDevice.stepping = pDevice->getHardwareInfo().platform.usRevId;
|
||||
targetDevice.maxPointerSizeInBytes = sizeof(uintptr_t);
|
||||
std::string decodeErrors;
|
||||
std::string decodeWarnings;
|
||||
auto singleDeviceBinary = unpackSingleDeviceBinary(archive, ConstStringRef(productAbbreviation, strlen(productAbbreviation)), targetDevice,
|
||||
decodeErrors, decodeWarnings);
|
||||
if (decodeWarnings.empty() == false) {
|
||||
printDebugString(DebugManager.flags.PrintDebugMessages.get(), stderr, "%s\n", decodeWarnings.c_str());
|
||||
}
|
||||
|
||||
if (rebuildRequired) {
|
||||
if (rebuildProgramFromIr() == CL_SUCCESS) {
|
||||
retVal = CL_SUCCESS;
|
||||
if (singleDeviceBinary.intermediateRepresentation.empty() && singleDeviceBinary.deviceBinary.empty()) {
|
||||
retVal = CL_INVALID_BINARY;
|
||||
printDebugString(DebugManager.flags.PrintDebugMessages.get(), stderr, "%s\n", decodeErrors.c_str());
|
||||
} else {
|
||||
retVal = CL_SUCCESS;
|
||||
this->irBinary = makeCopy(reinterpret_cast<const char *>(singleDeviceBinary.intermediateRepresentation.begin()), singleDeviceBinary.intermediateRepresentation.size());
|
||||
this->irBinarySize = singleDeviceBinary.intermediateRepresentation.size();
|
||||
this->isSpirV = NEO::isSpirVBitcode(ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(this->irBinary.get()), this->irBinarySize));
|
||||
this->options = singleDeviceBinary.buildOptions.str();
|
||||
|
||||
if ((false == singleDeviceBinary.deviceBinary.empty()) && (false == DebugManager.flags.RebuildPrecompiledKernels.get())) {
|
||||
this->unpackedDeviceBinary = makeCopy<char>(reinterpret_cast<const char *>(singleDeviceBinary.deviceBinary.begin()), singleDeviceBinary.deviceBinary.size());
|
||||
this->unpackedDeviceBinarySize = singleDeviceBinary.deviceBinary.size();
|
||||
this->packedDeviceBinary = makeCopy<char>(reinterpret_cast<const char *>(archive.begin()), archive.size());
|
||||
this->packedDeviceBinarySize = archive.size();
|
||||
} else {
|
||||
this->isCreatedFromBinary = false;
|
||||
}
|
||||
|
||||
switch (singleDeviceBinary.format) {
|
||||
default:
|
||||
break;
|
||||
case DeviceBinaryFormat::OclLibrary:
|
||||
this->programBinaryType = CL_PROGRAM_BINARY_TYPE_LIBRARY;
|
||||
break;
|
||||
case DeviceBinaryFormat::OclCompiledObject:
|
||||
this->programBinaryType = CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -175,60 +200,6 @@ cl_int Program::createProgramFromBinary(
|
||||
return retVal;
|
||||
}
|
||||
|
||||
cl_int Program::rebuildProgramFromIr() {
|
||||
size_t dataSize;
|
||||
|
||||
isSpirV = false;
|
||||
if (Program::isValidSpirvBinary(irBinary.get(), irBinarySize)) {
|
||||
isSpirV = true;
|
||||
} else if (false == Program::isValidLlvmBinary(irBinary.get(), irBinarySize)) {
|
||||
return CL_INVALID_PROGRAM;
|
||||
}
|
||||
|
||||
CLElfLib::CElfWriter elfWriter(CLElfLib::E_EH_TYPE::EH_TYPE_OPENCL_OBJECTS, CLElfLib::E_EH_MACHINE::EH_MACHINE_NONE, 0);
|
||||
|
||||
elfWriter.addSection(CLElfLib::SSectionNode(isSpirV ? CLElfLib::E_SH_TYPE::SH_TYPE_SPIRV : CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_LLVM_BINARY,
|
||||
CLElfLib::E_SH_FLAG::SH_FLAG_NONE, "", std::string(irBinary.get(), irBinarySize), static_cast<uint32_t>(irBinarySize)));
|
||||
|
||||
dataSize = elfWriter.getTotalBinarySize();
|
||||
CLElfLib::ElfBinaryStorage data(dataSize);
|
||||
elfWriter.resolveBinary(data);
|
||||
|
||||
CompilerInterface *pCompilerInterface = this->executionEnvironment.getCompilerInterface();
|
||||
if (nullptr == pCompilerInterface) {
|
||||
return CL_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
|
||||
TranslationInput inputArgs = {IGC::CodeType::elf, IGC::CodeType::oclGenBin};
|
||||
inputArgs.src = ArrayRef<const char>(data);
|
||||
inputArgs.apiOptions = ArrayRef<const char>(options);
|
||||
inputArgs.internalOptions = ArrayRef<const char>(internalOptions);
|
||||
|
||||
TranslationOutput compilerOuput = {};
|
||||
auto err = pCompilerInterface->link(this->pDevice->getDevice(), inputArgs, compilerOuput);
|
||||
this->updateBuildLog(this->pDevice, compilerOuput.frontendCompilerLog.c_str(), compilerOuput.frontendCompilerLog.size());
|
||||
this->updateBuildLog(this->pDevice, compilerOuput.backendCompilerLog.c_str(), compilerOuput.backendCompilerLog.size());
|
||||
if (TranslationOutput::ErrorCode::Success != err) {
|
||||
return asClError(err);
|
||||
}
|
||||
|
||||
this->genBinary = std::move(compilerOuput.deviceBinary.mem);
|
||||
this->genBinarySize = compilerOuput.deviceBinary.size;
|
||||
this->debugData = std::move(compilerOuput.debugData.mem);
|
||||
this->debugDataSize = compilerOuput.debugData.size;
|
||||
|
||||
auto retVal = processGenBinary();
|
||||
if (retVal != CL_SUCCESS) {
|
||||
return retVal;
|
||||
}
|
||||
|
||||
programBinaryType = CL_PROGRAM_BINARY_TYPE_EXECUTABLE;
|
||||
isCreatedFromBinary = true;
|
||||
isProgramBinaryResolved = true;
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
cl_int Program::setProgramSpecializationConstant(cl_uint specId, size_t specSize, const void *specValue) {
|
||||
if (!isSpirV) {
|
||||
return CL_INVALID_PROGRAM;
|
||||
@@ -270,22 +241,6 @@ cl_int Program::updateSpecializationConstant(cl_uint specId, size_t specSize, co
|
||||
return CL_INVALID_SPEC_ID;
|
||||
}
|
||||
|
||||
bool Program::isValidLlvmBinary(
|
||||
const void *pBinary,
|
||||
size_t binarySize) {
|
||||
|
||||
const char *pLlvmMagic = "BC\xc0\xde";
|
||||
bool retVal = false;
|
||||
|
||||
if (pBinary && (binarySize > (strlen(pLlvmMagic) + 1))) {
|
||||
if (strstr((char *)pBinary, pLlvmMagic) != nullptr) {
|
||||
retVal = true;
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
void Program::setDevice(Device *device) {
|
||||
this->pDevice = device->getSpecializedDevice<ClDevice>();
|
||||
}
|
||||
@@ -456,4 +411,61 @@ void Program::updateNonUniformFlag(const Program **inputPrograms, size_t numInpu
|
||||
this->allowNonUniform = allowNonUniform;
|
||||
}
|
||||
|
||||
void Program::replaceDeviceBinary(std::unique_ptr<char[]> newBinary, size_t newBinarySize) {
|
||||
if (isAnyPackedDeviceBinaryFormat(ArrayRef<const uint8_t>(reinterpret_cast<uint8_t *>(newBinary.get()), newBinarySize))) {
|
||||
this->packedDeviceBinary = std::move(newBinary);
|
||||
this->packedDeviceBinarySize = newBinarySize;
|
||||
this->unpackedDeviceBinary.reset();
|
||||
this->unpackedDeviceBinarySize = 0U;
|
||||
} else {
|
||||
this->packedDeviceBinary.reset();
|
||||
this->packedDeviceBinarySize = 0U;
|
||||
this->unpackedDeviceBinary = std::move(newBinary);
|
||||
this->unpackedDeviceBinarySize = newBinarySize;
|
||||
}
|
||||
}
|
||||
|
||||
cl_int Program::packDeviceBinary() {
|
||||
if (nullptr != packedDeviceBinary) {
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
auto gfxCore = pDevice->getHardwareInfo().platform.eRenderCoreFamily;
|
||||
auto stepping = pDevice->getHardwareInfo().platform.usRevId;
|
||||
|
||||
if (nullptr != this->unpackedDeviceBinary.get()) {
|
||||
SingleDeviceBinary singleDeviceBinary;
|
||||
singleDeviceBinary.buildOptions = this->options;
|
||||
singleDeviceBinary.targetDevice.coreFamily = gfxCore;
|
||||
singleDeviceBinary.targetDevice.stepping = stepping;
|
||||
singleDeviceBinary.deviceBinary = ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(this->unpackedDeviceBinary.get()), this->unpackedDeviceBinarySize);
|
||||
singleDeviceBinary.intermediateRepresentation = ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(this->irBinary.get()), this->irBinarySize);
|
||||
std::string packWarnings;
|
||||
std::string packErrors;
|
||||
auto packedDeviceBinary = NEO::packDeviceBinary(singleDeviceBinary, packErrors, packWarnings);
|
||||
if (packedDeviceBinary.empty()) {
|
||||
DEBUG_BREAK_IF(true);
|
||||
return CL_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
this->packedDeviceBinary = makeCopy(packedDeviceBinary.data(), packedDeviceBinary.size());
|
||||
this->packedDeviceBinarySize = packedDeviceBinary.size();
|
||||
} else if (nullptr != this->irBinary.get()) {
|
||||
NEO::Elf::ElfEncoder<> elfEncoder(true, true, 1U);
|
||||
if (this->programBinaryType == CL_PROGRAM_BINARY_TYPE_LIBRARY) {
|
||||
elfEncoder.getElfFileHeader().type = NEO::Elf::ET_OPENCL_LIBRARY;
|
||||
} else {
|
||||
elfEncoder.getElfFileHeader().type = NEO::Elf::ET_OPENCL_OBJECTS;
|
||||
}
|
||||
elfEncoder.appendSection(NEO::Elf::SHT_OPENCL_SPIRV, NEO::Elf::SectionNamesOpenCl::spirvObject, ArrayRef<const uint8_t>::fromAny(this->irBinary.get(), this->irBinarySize));
|
||||
elfEncoder.appendSection(NEO::Elf::SHT_OPENCL_OPTIONS, NEO::Elf::SectionNamesOpenCl::buildOptions, this->options);
|
||||
auto elfData = elfEncoder.encode();
|
||||
this->packedDeviceBinary = makeCopy(elfData.data(), elfData.size());
|
||||
this->packedDeviceBinarySize = elfData.size();
|
||||
} else {
|
||||
return CL_INVALID_PROGRAM;
|
||||
}
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace NEO
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#pragma once
|
||||
#include "core/compiler_interface/compiler_interface.h"
|
||||
#include "core/compiler_interface/linker.h"
|
||||
#include "core/elf/writer.h"
|
||||
#include "core/device_binary_format/elf/elf_encoder.h"
|
||||
#include "core/program/program_info.h"
|
||||
#include "core/utilities/const_stringref.h"
|
||||
#include "runtime/api/cl_types.h"
|
||||
@@ -132,7 +132,6 @@ 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,
|
||||
@@ -181,7 +180,6 @@ class Program : public BaseObject<_cl_program> {
|
||||
|
||||
void setDevice(Device *device);
|
||||
|
||||
MOCKABLE_VIRTUAL cl_int processElfBinary(const void *pBinary, size_t binarySize, uint32_t &binaryVersion);
|
||||
cl_int processSpirBinary(const void *pBinary, size_t binarySize, bool isSpirV);
|
||||
|
||||
cl_int getSource(std::string &binary) const;
|
||||
@@ -238,8 +236,6 @@ class Program : public BaseObject<_cl_program> {
|
||||
kernelDebugEnabled = true;
|
||||
}
|
||||
|
||||
static bool isValidLlvmBinary(const void *pBinary, size_t binarySize);
|
||||
static bool isValidSpirvBinary(const void *pBinary, size_t binarySize);
|
||||
bool isKernelDebugEnabled() {
|
||||
return kernelDebugEnabled;
|
||||
}
|
||||
@@ -260,24 +256,17 @@ class Program : public BaseObject<_cl_program> {
|
||||
return this->linkerInput.get();
|
||||
}
|
||||
|
||||
MOCKABLE_VIRTUAL bool isSafeToSkipUnhandledToken(unsigned int token) const;
|
||||
MOCKABLE_VIRTUAL void replaceDeviceBinary(std::unique_ptr<char[]> newBinary, size_t newBinarySize);
|
||||
|
||||
protected:
|
||||
Program(ExecutionEnvironment &executionEnvironment);
|
||||
|
||||
MOCKABLE_VIRTUAL cl_int createProgramFromBinary(const void *pBinary, size_t binarySize);
|
||||
|
||||
cl_int resolveProgramBinary();
|
||||
cl_int packDeviceBinary();
|
||||
|
||||
MOCKABLE_VIRTUAL cl_int linkBinary();
|
||||
|
||||
MOCKABLE_VIRTUAL cl_int isHandled(const PatchTokenBinary::ProgramFromPatchtokens &decodedProgram) const;
|
||||
|
||||
MOCKABLE_VIRTUAL cl_int rebuildProgramFromIr();
|
||||
|
||||
bool validateGenBinaryDevice(GFXCORE_FAMILY device) const;
|
||||
bool validateGenBinaryHeader(const iOpenCL::SProgramBinaryHeader *pGenBinaryHeader) const;
|
||||
|
||||
void separateBlockKernels();
|
||||
|
||||
void updateNonUniformFlag();
|
||||
@@ -293,19 +282,20 @@ class Program : public BaseObject<_cl_program> {
|
||||
|
||||
static const std::string clOptNameClVer;
|
||||
|
||||
cl_program_binary_type programBinaryType;
|
||||
cl_program_binary_type programBinaryType = CL_PROGRAM_BINARY_TYPE_NONE;
|
||||
bool isSpirV = false;
|
||||
CLElfLib::ElfBinaryStorage elfBinary;
|
||||
size_t elfBinarySize;
|
||||
|
||||
std::unique_ptr<char[]> genBinary;
|
||||
size_t genBinarySize;
|
||||
|
||||
std::unique_ptr<char[]> irBinary;
|
||||
size_t irBinarySize;
|
||||
size_t irBinarySize = 0U;
|
||||
|
||||
std::unique_ptr<char[]> unpackedDeviceBinary;
|
||||
size_t unpackedDeviceBinarySize = 0U;
|
||||
|
||||
std::unique_ptr<char[]> packedDeviceBinary;
|
||||
size_t packedDeviceBinarySize = 0U;
|
||||
|
||||
std::unique_ptr<char[]> debugData;
|
||||
size_t debugDataSize;
|
||||
size_t debugDataSize = 0U;
|
||||
|
||||
CreatedFrom createdFrom = CreatedFrom::UNKNOWN;
|
||||
|
||||
@@ -313,23 +303,22 @@ class Program : public BaseObject<_cl_program> {
|
||||
std::vector<KernelInfo *> parentKernelInfoArray;
|
||||
std::vector<KernelInfo *> subgroupKernelInfoArray;
|
||||
|
||||
GraphicsAllocation *constantSurface;
|
||||
GraphicsAllocation *globalSurface;
|
||||
GraphicsAllocation *constantSurface = nullptr;
|
||||
GraphicsAllocation *globalSurface = nullptr;
|
||||
GraphicsAllocation *exportedFunctionsSurface = nullptr;
|
||||
|
||||
size_t globalVarTotalSize;
|
||||
size_t globalVarTotalSize = 0U;
|
||||
|
||||
cl_build_status buildStatus;
|
||||
bool isCreatedFromBinary;
|
||||
bool isProgramBinaryResolved;
|
||||
cl_build_status buildStatus = CL_BUILD_NONE;
|
||||
bool isCreatedFromBinary = false;
|
||||
|
||||
std::string sourceCode;
|
||||
std::string options;
|
||||
std::string internalOptions;
|
||||
static const std::vector<ConstStringRef> internalOptionsToExtract;
|
||||
|
||||
uint32_t programOptionVersion;
|
||||
bool allowNonUniform;
|
||||
uint32_t programOptionVersion = 12U;
|
||||
bool allowNonUniform = false;
|
||||
|
||||
std::unique_ptr<LinkerInput> linkerInput;
|
||||
Linker::RelocatedSymbolsMap symbols;
|
||||
@@ -341,13 +330,13 @@ class Program : public BaseObject<_cl_program> {
|
||||
CIF::RAII::UPtr_t<CIF::Builtins::BufferSimple> specConstantsSizes;
|
||||
CIF::RAII::UPtr_t<CIF::Builtins::BufferSimple> specConstantsValues;
|
||||
|
||||
BlockKernelManager *blockKernelManager;
|
||||
BlockKernelManager *blockKernelManager = nullptr;
|
||||
ExecutionEnvironment &executionEnvironment;
|
||||
Context *context;
|
||||
ClDevice *pDevice;
|
||||
cl_uint numDevices;
|
||||
Context *context = nullptr;
|
||||
ClDevice *pDevice = nullptr;
|
||||
cl_uint numDevices = 0U;
|
||||
|
||||
bool isBuiltIn;
|
||||
bool isBuiltIn = false;
|
||||
bool kernelDebugEnabled = false;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation
|
||||
* Copyright (C) 2019-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
@@ -8,7 +8,18 @@
|
||||
#pragma once
|
||||
#include "core/debug_settings/debug_settings_manager.h"
|
||||
|
||||
#include <cinttypes>
|
||||
#include <cstddef>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
namespace NEO {
|
||||
class Kernel;
|
||||
struct MultiDispatchInfo;
|
||||
|
||||
template <DebugFunctionalityLevel DebugLevel>
|
||||
class FileLogger {
|
||||
public:
|
||||
|
||||
Reference in New Issue
Block a user