fix: use internal options when native binary is rebuilt from spirv

Resolves: NEO-12838

Signed-off-by: Mateusz Hoppe <mateusz.hoppe@intel.com>
This commit is contained in:
Mateusz Hoppe 2024-09-30 15:13:31 +00:00 committed by Compute-Runtime-Automation
parent c7ae732a2a
commit 46b78812cc
3 changed files with 69 additions and 13 deletions

View File

@ -291,7 +291,7 @@ ze_result_t ModuleTranslationUnit::buildFromSpirV(const char *input, uint32_t in
return this->compileGenBinary(inputArgs, false); return this->compileGenBinary(inputArgs, false);
} }
ze_result_t ModuleTranslationUnit::createFromNativeBinary(const char *input, size_t inputSize) { ze_result_t ModuleTranslationUnit::createFromNativeBinary(const char *input, size_t inputSize, const char *internalBuildOptions) {
UNRECOVERABLE_IF((nullptr == device) || (nullptr == device->getNEODevice())); UNRECOVERABLE_IF((nullptr == device) || (nullptr == device->getNEODevice()));
auto productAbbreviation = NEO::hardwarePrefix[device->getNEODevice()->getHardwareInfo().platform.eProductFamily]; auto productAbbreviation = NEO::hardwarePrefix[device->getNEODevice()->getHardwareInfo().platform.eProductFamily];
@ -348,7 +348,7 @@ ze_result_t ModuleTranslationUnit::createFromNativeBinary(const char *input, siz
updateBuildLog(NEO::CompilerWarnings::recompiledFromIr.str()); updateBuildLog(NEO::CompilerWarnings::recompiledFromIr.str());
} }
return buildFromSpirV(this->irBinary.get(), static_cast<uint32_t>(this->irBinarySize), this->options.c_str(), "", nullptr); return buildFromSpirV(this->irBinary.get(), static_cast<uint32_t>(this->irBinarySize), this->options.c_str(), internalBuildOptions, nullptr);
} else { } else {
if (processUnpackedBinary() != ZE_RESULT_SUCCESS) { if (processUnpackedBinary() != ZE_RESULT_SUCCESS) {
driverHandle->clearErrorDescription(); driverHandle->clearErrorDescription();
@ -741,7 +741,7 @@ inline ze_result_t ModuleImp::initializeTranslationUnit(const ze_module_desc_t *
this->isFunctionSymbolExportEnabled = true; this->isFunctionSymbolExportEnabled = true;
this->isGlobalSymbolExportEnabled = true; this->isGlobalSymbolExportEnabled = true;
this->precompiled = true; this->precompiled = true;
return this->translationUnit->createFromNativeBinary(reinterpret_cast<const char *>(desc->pInputModule), desc->inputSize); return this->translationUnit->createFromNativeBinary(reinterpret_cast<const char *>(desc->pInputModule), desc->inputSize, internalBuildOptions.c_str());
} else if (desc->format == ZE_MODULE_FORMAT_IL_SPIRV) { } else if (desc->format == ZE_MODULE_FORMAT_IL_SPIRV) {
this->builtFromSpirv = true; this->builtFromSpirv = true;
this->precompiled = false; this->precompiled = false;

View File

@ -53,7 +53,7 @@ struct ModuleTranslationUnit {
const ze_module_constants_t *pConstants); const ze_module_constants_t *pConstants);
MOCKABLE_VIRTUAL ze_result_t staticLinkSpirV(std::vector<const char *> inputSpirVs, std::vector<uint32_t> inputModuleSizes, const char *buildOptions, const char *internalBuildOptions, MOCKABLE_VIRTUAL ze_result_t staticLinkSpirV(std::vector<const char *> inputSpirVs, std::vector<uint32_t> inputModuleSizes, const char *buildOptions, const char *internalBuildOptions,
std::vector<const ze_module_constants_t *> specConstants); std::vector<const ze_module_constants_t *> specConstants);
MOCKABLE_VIRTUAL ze_result_t createFromNativeBinary(const char *input, size_t inputSize); MOCKABLE_VIRTUAL ze_result_t createFromNativeBinary(const char *input, size_t inputSize, const char *internalBuildOptions);
MOCKABLE_VIRTUAL ze_result_t processUnpackedBinary(); MOCKABLE_VIRTUAL ze_result_t processUnpackedBinary();
std::vector<uint8_t> generateElfFromSpirV(std::vector<const char *> inputSpirVs, std::vector<uint32_t> inputModuleSizes); std::vector<uint8_t> generateElfFromSpirV(std::vector<const char *> inputSpirVs, std::vector<uint32_t> inputModuleSizes);
bool processSpecConstantInfo(NEO::CompilerInterface *compilerInterface, const ze_module_constants_t *pConstants, const char *input, uint32_t inputSize); bool processSpecConstantInfo(NEO::CompilerInterface *compilerInterface, const ze_module_constants_t *pConstants, const char *input, uint32_t inputSize);

View File

@ -3012,10 +3012,10 @@ struct MockModuleTU : public L0::ModuleTranslationUnit {
} }
} }
ze_result_t createFromNativeBinary(const char *input, size_t inputSize) override { ze_result_t createFromNativeBinary(const char *input, size_t inputSize, const char *internalBuildOptions) override {
debugManager.flags.FailBuildProgramWithStatefulAccess.set(0); debugManager.flags.FailBuildProgramWithStatefulAccess.set(0);
wasCreateFromNativeBinaryCalled = true; wasCreateFromNativeBinaryCalled = true;
return L0::ModuleTranslationUnit::createFromNativeBinary(input, inputSize); return L0::ModuleTranslationUnit::createFromNativeBinary(input, inputSize, internalBuildOptions);
} }
bool callRealBuildFromSpirv = false; bool callRealBuildFromSpirv = false;
@ -3145,6 +3145,62 @@ HWTEST_F(ModuleTranslationUnitTest, GivenRebuildFlagWhenCreatingModuleFromNative
EXPECT_TRUE(containsWarning); EXPECT_TRUE(containsWarning);
} }
HWTEST_F(ModuleTranslationUnitTest, GivenNativeBinaryWhenRebuildingFromIntermediateThenCorrectInternalOptionsAreUsed) {
DebugManagerStateRestore dgbRestorer;
NEO::debugManager.flags.RebuildPrecompiledKernels.set(true);
auto *pMockCompilerInterface = new MockCompilerInterface;
auto &rootDeviceEnvironment = this->neoDevice->executionEnvironment->rootDeviceEnvironments[this->neoDevice->getRootDeviceIndex()];
rootDeviceEnvironment->compilerInterface.reset(pMockCompilerInterface);
auto additionalSections = {ZebinTestData::AppendElfAdditionalSection::spirv};
bool forceRecompilation = true;
auto zebinData = std::make_unique<ZebinTestData::ZebinWithL0TestCommonModule>(device->getHwInfo(), additionalSections, forceRecompilation);
const auto &src = zebinData->storage;
ze_module_desc_t moduleDesc = {};
moduleDesc.format = ZE_MODULE_FORMAT_NATIVE;
moduleDesc.pInputModule = reinterpret_cast<const uint8_t *>(src.data());
moduleDesc.inputSize = src.size();
std::unique_ptr<ModuleBuildLog> moduleBuildLog{ModuleBuildLog::create()};
Module module(device, moduleBuildLog.get(), ModuleType::user);
auto mockTranslationUnit = new MockModuleTranslationUnit(device);
mockTranslationUnit->processUnpackedBinaryCallBase = false;
module.translationUnit.reset(mockTranslationUnit);
ze_result_t result = ZE_RESULT_ERROR_MODULE_BUILD_FAILURE;
result = module.initialize(&moduleDesc, neoDevice);
ASSERT_EQ(result, ZE_RESULT_SUCCESS);
char *buildFlags = nullptr;
std::string options;
std::string internalOptions;
module.createBuildOptions(buildFlags, options, internalOptions);
internalOptions = module.translationUnit->generateCompilerOptions(options.c_str(), internalOptions.c_str());
EXPECT_EQ(internalOptions, pMockCompilerInterface->inputInternalOptions);
pMockCompilerInterface->inputInternalOptions = "";
uint8_t binary[10];
moduleDesc.format = ZE_MODULE_FORMAT_IL_SPIRV;
moduleDesc.pInputModule = binary;
moduleDesc.inputSize = 10;
Module module2(device, nullptr, ModuleType::user);
auto mockTranslationUnit2 = new MockModuleTranslationUnit(device);
mockTranslationUnit2->processUnpackedBinaryCallBase = false;
module2.translationUnit.reset(mockTranslationUnit2);
result = module2.initialize(&moduleDesc, neoDevice);
ASSERT_EQ(result, ZE_RESULT_SUCCESS);
// make sure internal options are matching those from buildFromSpirv
EXPECT_EQ(internalOptions, pMockCompilerInterface->inputInternalOptions);
}
HWTEST_F(ModuleTranslationUnitTest, GivenRebuildFlagWhenCreatingModuleFromNativeBinaryAndWarningSuppressionIsPresentThenModuleRecompilationWarningIsNotIssued) { HWTEST_F(ModuleTranslationUnitTest, GivenRebuildFlagWhenCreatingModuleFromNativeBinaryAndWarningSuppressionIsPresentThenModuleRecompilationWarningIsNotIssued) {
DebugManagerStateRestore dgbRestorer; DebugManagerStateRestore dgbRestorer;
NEO::debugManager.flags.RebuildPrecompiledKernels.set(true); NEO::debugManager.flags.RebuildPrecompiledKernels.set(true);
@ -3189,7 +3245,7 @@ HWTEST_F(ModuleTranslationUnitTest, WhenCreatingFromNativeBinaryThenSetsUpRequir
emptyProgram.elfHeader->machine = hwInfo.platform.eProductFamily; emptyProgram.elfHeader->machine = hwInfo.platform.eProductFamily;
L0::ModuleTranslationUnit moduleTuValid(this->device); L0::ModuleTranslationUnit moduleTuValid(this->device);
ze_result_t result = ZE_RESULT_ERROR_MODULE_BUILD_FAILURE; ze_result_t result = ZE_RESULT_ERROR_MODULE_BUILD_FAILURE;
result = moduleTuValid.createFromNativeBinary(reinterpret_cast<const char *>(emptyProgram.storage.data()), emptyProgram.storage.size()); result = moduleTuValid.createFromNativeBinary(reinterpret_cast<const char *>(emptyProgram.storage.data()), emptyProgram.storage.size(), "");
const char *pStr = nullptr; const char *pStr = nullptr;
std::string emptyString = ""; std::string emptyString = "";
zeDriverGetLastErrorDescription(this->device->getDriverHandle(), &pStr); zeDriverGetLastErrorDescription(this->device->getDriverHandle(), &pStr);
@ -3198,7 +3254,7 @@ HWTEST_F(ModuleTranslationUnitTest, WhenCreatingFromNativeBinaryThenSetsUpRequir
++emptyProgram.elfHeader->machine; ++emptyProgram.elfHeader->machine;
L0::ModuleTranslationUnit moduleTuInvalid(this->device); L0::ModuleTranslationUnit moduleTuInvalid(this->device);
result = moduleTuInvalid.createFromNativeBinary(reinterpret_cast<const char *>(emptyProgram.storage.data()), emptyProgram.storage.size()); result = moduleTuInvalid.createFromNativeBinary(reinterpret_cast<const char *>(emptyProgram.storage.data()), emptyProgram.storage.size(), "");
zeDriverGetLastErrorDescription(this->device->getDriverHandle(), &pStr); zeDriverGetLastErrorDescription(this->device->getDriverHandle(), &pStr);
EXPECT_NE(0, strcmp(pStr, emptyString.c_str())); EXPECT_NE(0, strcmp(pStr, emptyString.c_str()));
EXPECT_EQ(ZE_RESULT_ERROR_MODULE_BUILD_FAILURE, result); EXPECT_EQ(ZE_RESULT_ERROR_MODULE_BUILD_FAILURE, result);
@ -3234,7 +3290,7 @@ HWTEST_F(ModuleTranslationUnitTest, WhenCreatingFromNativeBinaryThenSetsUpPacked
moduleTuValid.setDummyKernelInfo(); moduleTuValid.setDummyKernelInfo();
ze_result_t result = ZE_RESULT_ERROR_MODULE_BUILD_FAILURE; ze_result_t result = ZE_RESULT_ERROR_MODULE_BUILD_FAILURE;
result = moduleTuValid.createFromNativeBinary(reinterpret_cast<const char *>(arData.data()), arData.size()); result = moduleTuValid.createFromNativeBinary(reinterpret_cast<const char *>(arData.data()), arData.size(), "");
EXPECT_EQ(result, ZE_RESULT_SUCCESS); EXPECT_EQ(result, ZE_RESULT_SUCCESS);
EXPECT_EQ(moduleTuValid.processUnpackedBinaryCalled, 1u); EXPECT_EQ(moduleTuValid.processUnpackedBinaryCalled, 1u);
EXPECT_NE(moduleTuValid.packedDeviceBinarySize, arData.size()); EXPECT_NE(moduleTuValid.packedDeviceBinarySize, arData.size());
@ -3248,7 +3304,7 @@ HWTEST_F(ModuleTranslationUnitTest, WhenCreatingFromZebinThenDontAppendAllowZebi
zebin.elfHeader->machine = hwInfo.platform.eProductFamily; zebin.elfHeader->machine = hwInfo.platform.eProductFamily;
L0::ModuleTranslationUnit moduleTu(this->device); L0::ModuleTranslationUnit moduleTu(this->device);
ze_result_t result = ZE_RESULT_ERROR_MODULE_BUILD_FAILURE; ze_result_t result = ZE_RESULT_ERROR_MODULE_BUILD_FAILURE;
result = moduleTu.createFromNativeBinary(reinterpret_cast<const char *>(zebin.storage.data()), zebin.storage.size()); result = moduleTu.createFromNativeBinary(reinterpret_cast<const char *>(zebin.storage.data()), zebin.storage.size(), "");
EXPECT_EQ(result, ZE_RESULT_SUCCESS); EXPECT_EQ(result, ZE_RESULT_SUCCESS);
auto expectedOptions = ""; auto expectedOptions = "";
@ -3280,7 +3336,7 @@ kernels:
MockModule mockModule{this->device, nullptr, ModuleType::user}; MockModule mockModule{this->device, nullptr, ModuleType::user};
auto maxWorkGroupSize = static_cast<uint32_t>(this->neoDevice->deviceInfo.maxWorkGroupSize); auto maxWorkGroupSize = static_cast<uint32_t>(this->neoDevice->deviceInfo.maxWorkGroupSize);
auto mockTU = mockModule.translationUnit.get(); auto mockTU = mockModule.translationUnit.get();
auto result = mockTU->createFromNativeBinary(reinterpret_cast<const char *>(zebin.storage.data()), zebin.storage.size()); auto result = mockTU->createFromNativeBinary(reinterpret_cast<const char *>(zebin.storage.data()), zebin.storage.size(), "");
EXPECT_EQ(result, ZE_RESULT_SUCCESS); EXPECT_EQ(result, ZE_RESULT_SUCCESS);
auto &defaultKernelDescriptor = mockTU->programInfo.kernelInfos[0]->kernelDescriptor; auto &defaultKernelDescriptor = mockTU->programInfo.kernelInfos[0]->kernelDescriptor;
@ -3327,7 +3383,7 @@ kernels:
MockModule mockModule{this->device, nullptr, ModuleType::user}; MockModule mockModule{this->device, nullptr, ModuleType::user};
auto maxWorkGroupSize = static_cast<uint32_t>(this->neoDevice->deviceInfo.maxWorkGroupSize); auto maxWorkGroupSize = static_cast<uint32_t>(this->neoDevice->deviceInfo.maxWorkGroupSize);
auto mockTU = mockModule.translationUnit.get(); auto mockTU = mockModule.translationUnit.get();
auto result = mockTU->createFromNativeBinary(reinterpret_cast<const char *>(zebin.storage.data()), zebin.storage.size()); auto result = mockTU->createFromNativeBinary(reinterpret_cast<const char *>(zebin.storage.data()), zebin.storage.size(), "");
EXPECT_EQ(result, ZE_RESULT_SUCCESS); EXPECT_EQ(result, ZE_RESULT_SUCCESS);
auto &defaultKernelDescriptor = mockTU->programInfo.kernelInfos[0]->kernelDescriptor; auto &defaultKernelDescriptor = mockTU->programInfo.kernelInfos[0]->kernelDescriptor;
@ -4220,7 +4276,7 @@ TEST_F(ModuleInitializeTest, whenModuleInitializeIsCalledThenCorrectResultIsRetu
class MyMockModuleTU : public MockModuleTU { class MyMockModuleTU : public MockModuleTU {
public: public:
using MockModuleTU::MockModuleTU; using MockModuleTU::MockModuleTU;
ze_result_t createFromNativeBinary(const char *input, size_t inputSize) override { ze_result_t createFromNativeBinary(const char *input, size_t inputSize, const char *internalBuildOptions) override {
programInfo.kernelInfos[0]->heapInfo.pKernelHeap = &mockKernelHeap; programInfo.kernelInfos[0]->heapInfo.pKernelHeap = &mockKernelHeap;
programInfo.kernelInfos[0]->heapInfo.kernelHeapSize = 4; programInfo.kernelInfos[0]->heapInfo.kernelHeapSize = 4;
return ZE_RESULT_SUCCESS; return ZE_RESULT_SUCCESS;