fix(ocl): Force rebuild if binary contains bindless kernel

Related-To: NEO-7063
Signed-off-by: Fabian Zwoliński <fabian.zwolinski@intel.com>
This commit is contained in:
Fabian Zwoliński
2024-05-17 13:28:41 +00:00
committed by Compute-Runtime-Automation
parent 90927135f9
commit 59829aeb11
7 changed files with 133 additions and 22 deletions

View File

@@ -216,29 +216,30 @@ cl_int Program::processGenBinary(const ClDevice &clDevice) {
buildInfo.globalSurface = nullptr;
}
ProgramInfo programInfo;
auto blob = ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(buildInfo.unpackedDeviceBinary.get()), buildInfo.unpackedDeviceBinarySize);
SingleDeviceBinary binary = {};
binary.deviceBinary = blob;
binary.targetDevice = NEO::getTargetDevice(clDevice.getRootDeviceEnvironment());
std::string decodeErrors;
std::string decodeWarnings;
if (!decodedSingleDeviceBinary.isSet) {
decodedSingleDeviceBinary.programInfo = {};
DecodeError decodeError;
DeviceBinaryFormat singleDeviceBinaryFormat;
auto &gfxCoreHelper = clDevice.getGfxCoreHelper();
std::tie(decodeError, singleDeviceBinaryFormat) = NEO::decodeSingleDeviceBinary(programInfo, binary, decodeErrors, decodeWarnings, gfxCoreHelper);
auto blob = ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(buildInfo.unpackedDeviceBinary.get()), buildInfo.unpackedDeviceBinarySize);
SingleDeviceBinary binary = {};
binary.deviceBinary = blob;
binary.targetDevice = NEO::getTargetDevice(clDevice.getRootDeviceEnvironment());
if (decodeWarnings.empty() == false) {
PRINT_DEBUG_STRING(debugManager.flags.PrintDebugMessages.get(), stderr, "%s\n", decodeWarnings.c_str());
auto &gfxCoreHelper = clDevice.getGfxCoreHelper();
std::tie(decodedSingleDeviceBinary.decodeError, std::ignore) = NEO::decodeSingleDeviceBinary(decodedSingleDeviceBinary.programInfo, binary, decodedSingleDeviceBinary.decodeErrors, decodedSingleDeviceBinary.decodeWarnings, gfxCoreHelper);
} else {
decodedSingleDeviceBinary.isSet = false;
}
if (DecodeError::success != decodeError) {
PRINT_DEBUG_STRING(debugManager.flags.PrintDebugMessages.get(), stderr, "%s\n", decodeErrors.c_str());
if (decodedSingleDeviceBinary.decodeWarnings.empty() == false) {
PRINT_DEBUG_STRING(debugManager.flags.PrintDebugMessages.get(), stderr, "%s\n", decodedSingleDeviceBinary.decodeWarnings.c_str());
}
if (DecodeError::success != decodedSingleDeviceBinary.decodeError) {
PRINT_DEBUG_STRING(debugManager.flags.PrintDebugMessages.get(), stderr, "%s\n", decodedSingleDeviceBinary.decodeErrors.c_str());
return CL_INVALID_BINARY;
}
return this->processProgramInfo(programInfo, clDevice);
return this->processProgramInfo(decodedSingleDeviceBinary.programInfo, clDevice);
}
cl_int Program::processProgramInfo(ProgramInfo &src, const ClDevice &clDevice) {

View File

@@ -18,6 +18,7 @@
#include "shared/source/device_binary_format/elf/ocl_elf.h"
#include "shared/source/execution_environment/execution_environment.h"
#include "shared/source/execution_environment/root_device_environment.h"
#include "shared/source/helpers/addressing_mode_helper.h"
#include "shared/source/helpers/api_specific_config.h"
#include "shared/source/helpers/compiler_options_parser.h"
#include "shared/source/helpers/compiler_product_helper.h"
@@ -196,6 +197,19 @@ cl_int Program::createProgramFromBinary(
this->options += " " + NEO::CompilerOptions::enableZebin.str();
}
auto deviceBinary = makeCopy<char>(reinterpret_cast<const char *>(singleDeviceBinary.deviceBinary.begin()), singleDeviceBinary.deviceBinary.size());
auto blob = ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(deviceBinary.get()), singleDeviceBinary.deviceBinary.size());
SingleDeviceBinary binary = {};
binary.deviceBinary = blob;
binary.targetDevice = NEO::getTargetDevice(clDevice.getRootDeviceEnvironment());
auto &gfxCoreHelper = clDevice.getGfxCoreHelper();
std::tie(decodedSingleDeviceBinary.decodeError, std::ignore) = NEO::decodeSingleDeviceBinary(decodedSingleDeviceBinary.programInfo,
binary,
decodedSingleDeviceBinary.decodeErrors,
decodedSingleDeviceBinary.decodeWarnings,
gfxCoreHelper);
this->buildInfos[rootDeviceIndex].debugData = makeCopy(reinterpret_cast<const char *>(singleDeviceBinary.debugData.begin()), singleDeviceBinary.debugData.size());
this->buildInfos[rootDeviceIndex].debugDataSize = singleDeviceBinary.debugData.size();
@@ -203,7 +217,9 @@ cl_int Program::createProgramFromBinary(
this->indirectDetectionVersion = singleDeviceBinary.generatorFeatureVersions.indirectMemoryAccessDetection;
auto isVmeUsed = containsVmeUsage(this->buildInfos[rootDeviceIndex].kernelInfoArray);
bool rebuild = isRebuiltToPatchtokensRequired(&clDevice.getDevice(), archive, this->options, this->isBuiltIn, isVmeUsed);
bool rebuild = isRebuiltToPatchtokensRequired(&clDevice.getDevice(), archive, this->options, this->isBuiltIn, isVmeUsed) ||
AddressingModeHelper::containsBindlessKernel(decodedSingleDeviceBinary.programInfo.kernelInfos);
bool flagRebuild = debugManager.flags.RebuildPrecompiledKernels.get();
if (0u == this->irBinarySize) {
@@ -219,12 +235,13 @@ cl_int Program::createProgramFromBinary(
}
if ((false == singleDeviceBinary.deviceBinary.empty()) && (false == rebuild)) {
this->buildInfos[rootDeviceIndex].unpackedDeviceBinary = makeCopy<char>(reinterpret_cast<const char *>(singleDeviceBinary.deviceBinary.begin()), singleDeviceBinary.deviceBinary.size());
this->buildInfos[rootDeviceIndex].unpackedDeviceBinary = std::move(deviceBinary);
this->buildInfos[rootDeviceIndex].unpackedDeviceBinarySize = singleDeviceBinary.deviceBinary.size();
this->buildInfos[rootDeviceIndex].packedDeviceBinary = makeCopy<char>(reinterpret_cast<const char *>(archive.begin()), archive.size());
this->buildInfos[rootDeviceIndex].packedDeviceBinarySize = archive.size();
this->decodedSingleDeviceBinary.isSet = true;
} else {
this->decodedSingleDeviceBinary.isSet = false;
this->isCreatedFromBinary = false;
this->requiresRebuild = true;
}

View File

@@ -8,6 +8,7 @@
#pragma once
#include "shared/source/compiler_interface/compiler_interface.h"
#include "shared/source/compiler_interface/linker.h"
#include "shared/source/device_binary_format/device_binary_formats.h"
#include "shared/source/helpers/non_copyable_or_moveable.h"
#include "shared/source/program/program_info.h"
@@ -388,6 +389,14 @@ class Program : public BaseObject<_cl_program> {
std::once_flag generateDefaultMetadataOnce;
};
std::unique_ptr<MetadataGenerationFlags> metadataGenerationFlags;
struct DecodedSingleDeviceBinary {
bool isSet = false;
ProgramInfo programInfo;
DecodeError decodeError;
std::string decodeErrors;
std::string decodeWarnings;
} decodedSingleDeviceBinary;
};
} // namespace NEO

View File

@@ -2904,6 +2904,50 @@ TEST(CreateProgramFromBinaryTests, givenBinaryProgramNotBuiltInWhenBuiltInKernel
EXPECT_EQ(0U, pProgram->buildInfos[rootDeviceIndex].packedDeviceBinarySize);
}
TEST(CreateProgramFromBinaryTests, givenBinaryWithBindlessKernelWhenCreateProgramFromBinaryThenDeviceBinaryIsNotUsedAndRebuildIsRequired) {
std::string validZeInfo = std::string("version :\'") + versionToString(NEO::Zebin::ZeInfo::zeInfoDecoderVersion) + R"===('
kernels:
- name : kernel_bindless
execution_env:
simd_size: 8
payload_arguments:
- arg_type: arg_bypointer
offset: 0
size: 4
arg_index: 0
addrmode: bindless
addrspace: global
access_type: readwrite
...
)===";
uint8_t kernelIsa[8]{0U};
ZebinTestData::ValidEmptyProgram zebin;
zebin.removeSection(NEO::Zebin::Elf::SectionHeaderTypeZebin::SHT_ZEBIN_ZEINFO, NEO::Zebin::Elf::SectionNames::zeInfo);
zebin.appendSection(NEO::Zebin::Elf::SectionHeaderTypeZebin::SHT_ZEBIN_ZEINFO, NEO::Zebin::Elf::SectionNames::zeInfo, ArrayRef<const uint8_t>::fromAny(validZeInfo.data(), validZeInfo.size()));
zebin.appendSection(NEO::Elf::SHT_PROGBITS, NEO::Zebin::Elf::SectionNames::textPrefix.str() + "kernel_bindless", {kernelIsa, sizeof(kernelIsa)});
constexpr auto mockSpirvDataSize = 0x10;
uint8_t mockSpirvData[mockSpirvDataSize]{0};
zebin.appendSection(Elf::SHT_OPENCL_SPIRV, Elf::SectionNamesOpenCl::spirvObject, ArrayRef<const uint8_t>::fromAny(mockSpirvData, mockSpirvDataSize));
zebin.elfHeader->machine = NEO::defaultHwInfo->platform.eProductFamily;
cl_int retVal = CL_INVALID_BINARY;
auto clDevice = std::make_unique<MockClDevice>(MockDevice::createWithNewExecutionEnvironment<MockDevice>(nullptr));
std::unique_ptr<MockProgram> pProgram(Program::createBuiltInFromGenBinary<MockProgram>(nullptr, toClDeviceVector(*clDevice), zebin.storage.data(), zebin.storage.size(), &retVal));
ASSERT_NE(nullptr, pProgram.get());
EXPECT_EQ(CL_SUCCESS, retVal);
auto rootDeviceIndex = clDevice->getRootDeviceIndex();
retVal = pProgram->createProgramFromBinary(zebin.storage.data(), zebin.storage.size(), *clDevice);
EXPECT_EQ(CL_SUCCESS, retVal);
EXPECT_EQ(nullptr, pProgram->buildInfos[rootDeviceIndex].unpackedDeviceBinary.get());
EXPECT_EQ(0U, pProgram->buildInfos[rootDeviceIndex].unpackedDeviceBinarySize);
EXPECT_EQ(nullptr, pProgram->buildInfos[rootDeviceIndex].packedDeviceBinary);
EXPECT_EQ(0U, pProgram->buildInfos[rootDeviceIndex].packedDeviceBinarySize);
ASSERT_TRUE(pProgram->requiresRebuild);
}
TEST(CreateProgramFromBinaryTests, givenBinaryProgramWhenKernelRebulildIsNotForcedThenDeviceBinaryIsUsed) {
cl_int retVal = CL_INVALID_BINARY;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2022-2023 Intel Corporation
* Copyright (C) 2022-2024 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -55,4 +55,13 @@ bool containsStatefulAccess(const std::vector<KernelInfo *> &kernelInfos, bool s
return false;
}
bool containsBindlessKernel(const std::vector<KernelInfo *> &kernelInfos) {
for (const auto &kernelInfo : kernelInfos) {
if (NEO::KernelDescriptor::isBindlessAddressingKernel(kernelInfo->kernelDescriptor)) {
return true;
}
}
return false;
}
} // namespace NEO::AddressingModeHelper

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2022-2023 Intel Corporation
* Copyright (C) 2022-2024 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -17,6 +17,7 @@ namespace AddressingModeHelper {
bool failBuildProgramWithStatefulAccess(const RootDeviceEnvironment &rootDeviceEnvironment);
bool containsStatefulAccess(const KernelDescriptor &kernelDescriptor, bool skipLastExplicitArg);
bool containsStatefulAccess(const std::vector<KernelInfo *> &kernelInfos, bool skipLastExplicitArg);
bool containsBindlessKernel(const std::vector<KernelInfo *> &kernelInfos);
} // namespace AddressingModeHelper
} // namespace NEO

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2023 Intel Corporation
* Copyright (C) 2023-2024 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -64,3 +64,33 @@ TEST(AddressingModeHelperTest, GivenLastArgIsPointerWithValidBindlessOffsetWhenI
EXPECT_FALSE(AddressingModeHelper::containsStatefulAccess(kernelDescriptor, true));
}
TEST(AddressingModeHelperTest, GivenKernelInfosWhenCheckingForBindlessKernelThenReturnCorrectValue) {
KernelInfo kernelInfo1{};
KernelInfo kernelInfo2{};
{
kernelInfo1.kernelDescriptor.kernelAttributes.bufferAddressingMode = KernelDescriptor::Bindless;
std::vector<KernelInfo *> kernelInfos{&kernelInfo1};
EXPECT_TRUE(AddressingModeHelper::containsBindlessKernel(kernelInfos));
}
{
kernelInfo1.kernelDescriptor.kernelAttributes.bufferAddressingMode = KernelDescriptor::Bindful;
std::vector<KernelInfo *> kernelInfos{&kernelInfo1};
EXPECT_FALSE(AddressingModeHelper::containsBindlessKernel(kernelInfos));
}
{
kernelInfo1.kernelDescriptor.kernelAttributes.bufferAddressingMode = KernelDescriptor::Bindful;
std::vector<KernelInfo *> kernelInfos{&kernelInfo1};
EXPECT_FALSE(AddressingModeHelper::containsBindlessKernel(kernelInfos));
}
{
kernelInfo1.kernelDescriptor.kernelAttributes.bufferAddressingMode = KernelDescriptor::Bindful;
kernelInfo2.kernelDescriptor.kernelAttributes.bufferAddressingMode = KernelDescriptor::Bindless;
std::vector<KernelInfo *> kernelInfos{&kernelInfo1, &kernelInfo2};
EXPECT_TRUE(AddressingModeHelper::containsBindlessKernel(kernelInfos));
}
}