diff --git a/level_zero/core/source/module/module_imp.cpp b/level_zero/core/source/module/module_imp.cpp index e6626b313f..38d184133d 100644 --- a/level_zero/core/source/module/module_imp.cpp +++ b/level_zero/core/source/module/module_imp.cpp @@ -300,7 +300,7 @@ ze_result_t ModuleTranslationUnit::createFromNativeBinary(const char *input, siz } bool rebuild = NEO::DebugManager.flags.RebuildPrecompiledKernels.get() && irBinarySize != 0; - rebuild |= NEO::isRebuiltToPatchtokensRequired(device->getNEODevice(), archive, this->options, this->isBuiltIn); + rebuild |= NEO::isRebuiltToPatchtokensRequired(device->getNEODevice(), archive, this->options, this->isBuiltIn, false); if (rebuild && irBinarySize == 0) { return ZE_RESULT_ERROR_INVALID_NATIVE_BINARY; } diff --git a/opencl/source/program/program.cpp b/opencl/source/program/program.cpp index 1535968eb5..11a9a9d88b 100644 --- a/opencl/source/program/program.cpp +++ b/opencl/source/program/program.cpp @@ -181,8 +181,10 @@ cl_int Program::createProgramFromBinary( this->buildInfos[rootDeviceIndex].debugData = makeCopy(reinterpret_cast(singleDeviceBinary.debugData.begin()), singleDeviceBinary.debugData.size()); this->buildInfos[rootDeviceIndex].debugDataSize = singleDeviceBinary.debugData.size(); - bool rebuild = isRebuiltToPatchtokensRequired(&clDevice.getDevice(), archive, this->options, this->isBuiltIn); + auto isVmeUsed = containsVmeUsage(this->buildInfos[rootDeviceIndex].kernelInfoArray); + bool rebuild = isRebuiltToPatchtokensRequired(&clDevice.getDevice(), archive, this->options, this->isBuiltIn, isVmeUsed); rebuild |= DebugManager.flags.RebuildPrecompiledKernels.get(); + if (rebuild && 0u == this->irBinarySize) { return CL_INVALID_BINARY; } @@ -435,6 +437,15 @@ void Program::setBuildStatusSuccess(const ClDeviceVector &deviceVector, cl_progr } } +bool Program::containsVmeUsage(const std::vector &kernelInfos) const { + for (auto kernelInfo : kernelInfos) { + if (kernelInfo->isVmeUsed()) { + return true; + } + } + return false; +} + bool Program::isValidCallback(void(CL_CALLBACK *funcNotify)(cl_program program, void *userData), void *userData) { return funcNotify != nullptr || userData == nullptr; } diff --git a/opencl/source/program/program.h b/opencl/source/program/program.h index 46f3ae72ad..56f2f19099 100644 --- a/opencl/source/program/program.h +++ b/opencl/source/program/program.h @@ -306,6 +306,8 @@ class Program : public BaseObject<_cl_program> { void setBuildStatus(cl_build_status status); void setBuildStatusSuccess(const ClDeviceVector &deviceVector, cl_program_binary_type binaryType); + bool containsVmeUsage(const std::vector &kernelInfos) const; + bool isSpirV = false; std::unique_ptr irBinary; diff --git a/opencl/test/unit_test/mocks/mock_program.h b/opencl/test/unit_test/mocks/mock_program.h index bb0a19f037..4087c468b5 100644 --- a/opencl/test/unit_test/mocks/mock_program.h +++ b/opencl/test/unit_test/mocks/mock_program.h @@ -47,6 +47,7 @@ class MockProgram : public Program { using Program::allowNonUniform; using Program::areSpecializationConstantsInitialized; using Program::buildInfos; + using Program::containsVmeUsage; using Program::context; using Program::createdFrom; using Program::createProgramFromBinary; diff --git a/opencl/test/unit_test/program/program_tests.cpp b/opencl/test/unit_test/program/program_tests.cpp index c6ddb66ab2..517f62f237 100644 --- a/opencl/test/unit_test/program/program_tests.cpp +++ b/opencl/test/unit_test/program/program_tests.cpp @@ -3361,6 +3361,24 @@ TEST(ProgramPopulateZebinExtendedArgsMetadataTests, givenNonZebinaryFormatWhenCa buildInfo.kernelInfoArray.clear(); } +TEST(ProgramVmeUsage, givenVmeUsageWhenContainsVmeUsageIsCalledThenReturnTrue) { + MockClDevice device{new MockDevice()}; + MockProgram program(toClDeviceVector(device)); + + { + KernelInfo kernelInfo; + kernelInfo.kernelDescriptor.kernelAttributes.flags.usesVme = false; + std::vector kernelInfos{&kernelInfo}; + EXPECT_FALSE(program.containsVmeUsage(kernelInfos)); + } + { + KernelInfo kernelInfo; + kernelInfo.kernelDescriptor.kernelAttributes.flags.usesVme = true; + std::vector kernelInfos{&kernelInfo}; + EXPECT_TRUE(program.containsVmeUsage(kernelInfos)); + } +} + TEST(ProgramPopulateZebinExtendedArgsMetadataTests, givenZebinaryFormatAndDecodeErrorOnDecodingArgsMetadataWhenCallingPopulateZebinExtendedArgsMetadataThenMetadataIsNotPopulated) { MockClDevice device{new MockDevice()}; MockProgram program(toClDeviceVector(device)); diff --git a/shared/source/program/kernel_info.h b/shared/source/program/kernel_info.h index 3b7cf30c62..f4cb8d21e1 100644 --- a/shared/source/program/kernel_info.h +++ b/shared/source/program/kernel_info.h @@ -100,6 +100,10 @@ struct KernelInfo { return maxRequiredWorkGroupSize; } + bool isVmeUsed() const { + return kernelDescriptor.kernelAttributes.flags.usesVme; + } + uint32_t getConstantBufferSize() const; int32_t getArgNumByName(const char *name) const; diff --git a/shared/source/program/program_info.cpp b/shared/source/program/program_info.cpp index 13f5bc7fb8..4ccb0cb99a 100644 --- a/shared/source/program/program_info.cpp +++ b/shared/source/program/program_info.cpp @@ -36,13 +36,13 @@ bool requiresLocalMemoryWindowVA(const ProgramInfo &programInfo) { return false; } -bool isRebuiltToPatchtokensRequired(Device *neoDevice, ArrayRef archive, std::string &optionsString, bool isBuiltin) { +bool isRebuiltToPatchtokensRequired(Device *neoDevice, ArrayRef archive, std::string &optionsString, bool isBuiltin, bool isVmeUsed) { if (isBuiltin) { return false; } auto isSourceLevelDebuggerActive = (nullptr != neoDevice->getSourceLevelDebugger()); auto isZebinFormat = NEO::isDeviceBinaryFormat(archive); - if (isSourceLevelDebuggerActive && isZebinFormat) { + if ((isSourceLevelDebuggerActive || isVmeUsed) && isZebinFormat) { auto pos = optionsString.find(NEO::CompilerOptions::allowZebin.str()); optionsString.erase(pos, pos + NEO::CompilerOptions::allowZebin.length()); optionsString += " " + NEO::CompilerOptions::disableZebin.str(); diff --git a/shared/source/program/program_info.h b/shared/source/program/program_info.h index a2ca522c3b..6f00f7afe6 100644 --- a/shared/source/program/program_info.h +++ b/shared/source/program/program_info.h @@ -52,6 +52,6 @@ struct ProgramInfo { size_t getMaxInlineSlmNeeded(const ProgramInfo &programInfo); bool requiresLocalMemoryWindowVA(const ProgramInfo &programInfo); -bool isRebuiltToPatchtokensRequired(Device *neoDevice, ArrayRef archive, std::string &optionsString, bool isBuiltin); +bool isRebuiltToPatchtokensRequired(Device *neoDevice, ArrayRef archive, std::string &optionsString, bool isBuiltin, bool isVmeUsed); } // namespace NEO diff --git a/shared/test/unit_test/program/program_info_tests.cpp b/shared/test/unit_test/program/program_info_tests.cpp index a2e1058a28..4f7e363ab7 100644 --- a/shared/test/unit_test/program/program_info_tests.cpp +++ b/shared/test/unit_test/program/program_info_tests.cpp @@ -69,7 +69,7 @@ TEST(RequiresRebuildWithPatchtokens, givenLegacyDebuggerAttachedAndZebinaryForma std::string options{NEO::CompilerOptions::allowZebin}; bool isBuiltIn{false}; - bool rebuildRequired = isRebuiltToPatchtokensRequired(device.get(), ArrayRef::fromAny(zebin.storage.data(), zebin.storage.size()), options, isBuiltIn); + bool rebuildRequired = isRebuiltToPatchtokensRequired(device.get(), ArrayRef::fromAny(zebin.storage.data(), zebin.storage.size()), options, isBuiltIn, false); EXPECT_TRUE(rebuildRequired); EXPECT_FALSE(NEO::CompilerOptions::contains(options, NEO::CompilerOptions::allowZebin)); EXPECT_TRUE(NEO::CompilerOptions::contains(options, NEO::CompilerOptions::disableZebin)); @@ -83,21 +83,42 @@ TEST(RequiresRebuildWithPatchtokens, givenNoLegacyDebuggerAttachedOrNonZebinaryF std::string options{NEO::CompilerOptions::allowZebin}; bool isBuiltIn{true}; - bool rebuildRequired = isRebuiltToPatchtokensRequired(device.get(), ArrayRef::fromAny(zebin.storage.data(), zebin.storage.size()), options, isBuiltIn); + bool rebuildRequired = isRebuiltToPatchtokensRequired(device.get(), ArrayRef::fromAny(zebin.storage.data(), zebin.storage.size()), options, isBuiltIn, false); EXPECT_FALSE(rebuildRequired); EXPECT_TRUE(NEO::CompilerOptions::contains(options, NEO::CompilerOptions::allowZebin)); isBuiltIn = false; device->getRootDeviceEnvironmentRef().debugger.reset(nullptr); - rebuildRequired = isRebuiltToPatchtokensRequired(device.get(), ArrayRef::fromAny(zebin.storage.data(), zebin.storage.size()), options, isBuiltIn); + rebuildRequired = isRebuiltToPatchtokensRequired(device.get(), ArrayRef::fromAny(zebin.storage.data(), zebin.storage.size()), options, isBuiltIn, false); EXPECT_FALSE(rebuildRequired); EXPECT_TRUE(NEO::CompilerOptions::contains(options, NEO::CompilerOptions::allowZebin)); device->getRootDeviceEnvironmentRef().debugger.reset(new MockActiveSourceLevelDebugger); for (auto idx = 0; idx < 4; idx++) { zebin.elfHeader->identity.magic[idx] = 0; - } //broken header - zebinary format will not be detected - rebuildRequired = isRebuiltToPatchtokensRequired(device.get(), ArrayRef::fromAny(zebin.storage.data(), zebin.storage.size()), options, isBuiltIn); + } // broken header - zebinary format will not be detected + rebuildRequired = isRebuiltToPatchtokensRequired(device.get(), ArrayRef::fromAny(zebin.storage.data(), zebin.storage.size()), options, isBuiltIn, false); EXPECT_FALSE(rebuildRequired); EXPECT_TRUE(NEO::CompilerOptions::contains(options, NEO::CompilerOptions::allowZebin)); +} + +TEST(RequiresRebuildWithPatchtokens, givenVmeUsedWhenIsRebuiltToPatchtokensRequiredThenReturnFalse) { + ZebinTestData::ValidEmptyProgram<> zebin; + auto device = std::unique_ptr(MockDevice::createWithNewExecutionEnvironment(nullptr)); + device->getRootDeviceEnvironmentRef().debugger.reset(nullptr); + std::string options{NEO::CompilerOptions::allowZebin}; + bool isBuiltIn = false; + + { + bool isVmeUsed = false; + bool rebuildRequired = isRebuiltToPatchtokensRequired(device.get(), ArrayRef::fromAny(zebin.storage.data(), zebin.storage.size()), options, isBuiltIn, isVmeUsed); + EXPECT_FALSE(rebuildRequired); + EXPECT_TRUE(NEO::CompilerOptions::contains(options, NEO::CompilerOptions::allowZebin)); + } + { + bool isVmeUsed = true; + bool rebuildRequired = isRebuiltToPatchtokensRequired(device.get(), ArrayRef::fromAny(zebin.storage.data(), zebin.storage.size()), options, isBuiltIn, isVmeUsed); + EXPECT_TRUE(rebuildRequired); + EXPECT_FALSE(NEO::CompilerOptions::contains(options, NEO::CompilerOptions::allowZebin)); + } } \ No newline at end of file