From 6a0f7afd642926e01a67b28c67f9d2f4b56b18b5 Mon Sep 17 00:00:00 2001 From: Kamil Kopryk Date: Fri, 9 Jun 2023 15:23:03 +0000 Subject: [PATCH] feature: verify stateful information only when binary is generated by IGC Signed-off-by: Kamil Kopryk Related-To: NEO-6075 Ngen binaries contain stateful information, however they are not used in isa on Pvc. Therefore, we can just ignore them. --- level_zero/core/source/module/module_imp.cpp | 7 +- level_zero/core/source/module/module_imp.h | 1 + .../unit_tests/sources/module/test_module.cpp | 16 +++-- opencl/source/program/build.cpp | 7 +- .../source/program/process_device_binary.cpp | 3 + opencl/source/program/program.cpp | 3 + opencl/source/program/program.h | 2 + .../unit_test/api/cl_build_program_tests.inl | 46 +++++++++++++ .../test/unit_test/program/program_tests.cpp | 11 +-- .../command_encoder_xehp_and_later.inl | 9 ++- .../device_binary_format_zebin.cpp | 10 ++- .../device_binary_formats.h | 6 ++ .../zebin/zebin_decoder.cpp | 7 +- .../zebin/zebin_decoder.h | 2 +- shared/source/kernel/kernel_descriptor.h | 1 + shared/source/os_interface/product_helper.h | 1 + shared/source/os_interface/product_helper.inl | 6 ++ .../source/os_interface/product_helper_hw.h | 1 + .../pvc/os_agnostic_product_helper_pvc.inl | 7 ++ .../test/common/mocks/mock_modules_zebin.cpp | 2 + .../zebin_decoder_tests.cpp | 68 ++++++++++++++++--- .../encoders/test_encode_dispatch_kernel.cpp | 44 ++++++++++++ .../fixtures/command_container_fixture.h | 1 + .../os_interface/product_helper_tests.cpp | 10 +++ .../pvc/test_product_helper_pvc.cpp | 10 +++ 25 files changed, 249 insertions(+), 32 deletions(-) diff --git a/level_zero/core/source/module/module_imp.cpp b/level_zero/core/source/module/module_imp.cpp index 38e096c68a..860360a6ac 100644 --- a/level_zero/core/source/module/module_imp.cpp +++ b/level_zero/core/source/module/module_imp.cpp @@ -310,6 +310,8 @@ ze_result_t ModuleTranslationUnit::createFromNativeBinary(const char *input, siz this->debugDataSize = singleDeviceBinary.debugData.size(); } + this->isGeneratedByIgc = singleDeviceBinary.generator == NEO::GeneratorType::Igc; + bool rebuild = NEO::DebugManager.flags.RebuildPrecompiledKernels.get() && irBinarySize != 0; rebuild |= NEO::isRebuiltToPatchtokensRequired(device->getNEODevice(), archive, this->options, this->isBuiltIn, false); if (rebuild && irBinarySize == 0) { @@ -598,9 +600,12 @@ ze_result_t ModuleImp::initialize(const ze_module_desc_t *desc, NEO::Device *neo auto containsStatefulAccess = NEO::AddressingModeHelper::containsStatefulAccess(translationUnit->programInfo.kernelInfos, false); auto isUserKernel = (type == ModuleType::User); + auto isGeneratedByIgc = translationUnit->isGeneratedByIgc; + auto failBuildProgram = containsStatefulAccess && isUserKernel && - NEO::AddressingModeHelper::failBuildProgramWithStatefulAccess(rootDeviceEnvironment); + NEO::AddressingModeHelper::failBuildProgramWithStatefulAccess(rootDeviceEnvironment) && + isGeneratedByIgc; if (failBuildProgram) { result = ZE_RESULT_ERROR_MODULE_BUILD_FAILURE; diff --git a/level_zero/core/source/module/module_imp.h b/level_zero/core/source/module/module_imp.h index c48c5084bd..552df89e71 100644 --- a/level_zero/core/source/module/module_imp.h +++ b/level_zero/core/source/module/module_imp.h @@ -85,6 +85,7 @@ struct ModuleTranslationUnit { NEO::specConstValuesMap specConstantsValues; bool isBuiltIn{false}; + bool isGeneratedByIgc = true; }; struct ModuleImp : public Module { diff --git a/level_zero/core/test/unit_tests/sources/module/test_module.cpp b/level_zero/core/test/unit_tests/sources/module/test_module.cpp index 86ed400f26..612168f3c7 100644 --- a/level_zero/core/test/unit_tests/sources/module/test_module.cpp +++ b/level_zero/core/test/unit_tests/sources/module/test_module.cpp @@ -3258,17 +3258,19 @@ TEST_F(ModuleInitializeTest, whenModuleInitializeIsCalledThenCorrectResultIsRetu moduleDesc.pInputModule = reinterpret_cast(src.data()); moduleDesc.inputSize = src.size(); - std::array, 5> testParams = {{ - {ZE_RESULT_SUCCESS, false, ModuleType::Builtin, -1}, - {ZE_RESULT_SUCCESS, true, ModuleType::Builtin, 0}, - {ZE_RESULT_SUCCESS, true, ModuleType::User, 0}, - {ZE_RESULT_SUCCESS, true, ModuleType::Builtin, 1}, - {ZE_RESULT_ERROR_MODULE_BUILD_FAILURE, true, ModuleType::User, 1}, + std::array, 6> testParams = {{ + {ZE_RESULT_SUCCESS, false, true, ModuleType::Builtin, -1}, + {ZE_RESULT_SUCCESS, true, true, ModuleType::Builtin, 0}, + {ZE_RESULT_SUCCESS, true, true, ModuleType::User, 0}, + {ZE_RESULT_SUCCESS, true, true, ModuleType::Builtin, 1}, + {ZE_RESULT_ERROR_MODULE_BUILD_FAILURE, true, true, ModuleType::User, 1}, + {ZE_RESULT_SUCCESS, true, false, ModuleType::User, 1}, }}; - for (auto &[expectedResult, isStateful, moduleType, debugKey] : testParams) { + for (auto &[expectedResult, isStateful, isIgcGenerated, moduleType, debugKey] : testParams) { MockModuleImp module(device, nullptr, moduleType); module.translationUnit = std::make_unique(device); + module.translationUnit->isGeneratedByIgc = isIgcGenerated; DebugManager.flags.FailBuildProgramWithStatefulAccess.set(debugKey); module.setAddressingMode(isStateful); EXPECT_EQ(expectedResult, module.initialize(&moduleDesc, device->getNEODevice())); diff --git a/opencl/source/program/build.cpp b/opencl/source/program/build.cpp index 6b7cf1ce28..e514eb0ea3 100644 --- a/opencl/source/program/build.cpp +++ b/opencl/source/program/build.cpp @@ -168,9 +168,10 @@ cl_int Program::build( auto containsStatefulAccess = AddressingModeHelper::containsStatefulAccess(buildInfos[clDevices[0]->getRootDeviceIndex()].kernelInfoArray, skipLastExplicitArg); auto isUserKernel = !isBuiltIn; - auto failBuildProgram = (containsStatefulAccess && - isUserKernel && - AddressingModeHelper::failBuildProgramWithStatefulAccess(clDevices[0]->getRootDeviceEnvironment())); + auto failBuildProgram = containsStatefulAccess && + isUserKernel && + AddressingModeHelper::failBuildProgramWithStatefulAccess(clDevices[0]->getRootDeviceEnvironment()) && + isGeneratedByIgc; if (failBuildProgram) { retVal = CL_BUILD_PROGRAM_FAILURE; diff --git a/opencl/source/program/process_device_binary.cpp b/opencl/source/program/process_device_binary.cpp index de3296698d..1fe34e5e35 100644 --- a/opencl/source/program/process_device_binary.cpp +++ b/opencl/source/program/process_device_binary.cpp @@ -192,6 +192,9 @@ cl_int Program::processGenBinary(const ClDevice &clDevice) { this->buildInfos[rootDeviceIndex].unpackedDeviceBinary = makeCopy(reinterpret_cast(singleDeviceBinary.deviceBinary.begin()), singleDeviceBinarySize); this->buildInfos[rootDeviceIndex].unpackedDeviceBinarySize = singleDeviceBinarySize; + + this->isGeneratedByIgc = singleDeviceBinary.generator == GeneratorType::Igc; + } else { return CL_INVALID_BINARY; } diff --git a/opencl/source/program/program.cpp b/opencl/source/program/program.cpp index e3c50347a5..f223e7765c 100644 --- a/opencl/source/program/program.cpp +++ b/opencl/source/program/program.cpp @@ -195,6 +195,8 @@ cl_int Program::createProgramFromBinary( this->buildInfos[rootDeviceIndex].debugData = makeCopy(reinterpret_cast(singleDeviceBinary.debugData.begin()), singleDeviceBinary.debugData.size()); this->buildInfos[rootDeviceIndex].debugDataSize = singleDeviceBinary.debugData.size(); + this->isGeneratedByIgc = singleDeviceBinary.generator == GeneratorType::Igc; + auto isVmeUsed = containsVmeUsage(this->buildInfos[rootDeviceIndex].kernelInfoArray); bool rebuild = isRebuiltToPatchtokensRequired(&clDevice.getDevice(), archive, this->options, this->isBuiltIn, isVmeUsed); rebuild |= DebugManager.flags.RebuildPrecompiledKernels.get(); @@ -207,6 +209,7 @@ cl_int Program::createProgramFromBinary( this->buildInfos[rootDeviceIndex].unpackedDeviceBinarySize = singleDeviceBinary.deviceBinary.size(); this->buildInfos[rootDeviceIndex].packedDeviceBinary = makeCopy(reinterpret_cast(archive.begin()), archive.size()); this->buildInfos[rootDeviceIndex].packedDeviceBinarySize = archive.size(); + } else { this->isCreatedFromBinary = false; this->requiresRebuild = true; diff --git a/opencl/source/program/program.h b/opencl/source/program/program.h index 5a61bad6a1..e29a312f14 100644 --- a/opencl/source/program/program.h +++ b/opencl/source/program/program.h @@ -379,6 +379,8 @@ class Program : public BaseObject<_cl_program> { bool isBuiltIn = false; bool kernelDebugEnabled = false; + bool isGeneratedByIgc = true; + uint32_t maxRootDeviceIndex = std::numeric_limits::max(); std::mutex lockMutex; uint32_t exposedKernels = 0; diff --git a/opencl/test/unit_test/api/cl_build_program_tests.inl b/opencl/test/unit_test/api/cl_build_program_tests.inl index e32fe10548..b9af316e60 100644 --- a/opencl/test/unit_test/api/cl_build_program_tests.inl +++ b/opencl/test/unit_test/api/cl_build_program_tests.inl @@ -168,6 +168,52 @@ HWTEST2_F(ClBuildProgramTests, GivenFailBuildProgramAndBinaryAsInputWhenCreating EXPECT_EQ(CL_SUCCESS, retVal); } +HWTEST2_F(ClBuildProgramTests, GivenFailBuildProgramAndBinaryGeneratedByNgenAsInputWhenCreatingProgramWithSourceThenProgramBuildReturnsSuccess, IsAtLeastXeHpcCore) { + + DebugManager.flags.FailBuildProgramWithStatefulAccess.set(1); + + cl_program pProgram = nullptr; + cl_int binaryStatus = CL_SUCCESS; + + constexpr auto numBits = is32bit ? Elf::EI_CLASS_32 : Elf::EI_CLASS_64; + auto zebinData = std::make_unique>(pDevice->getHardwareInfo(), 16); + const auto &src = zebinData->storage; + + auto &flags = reinterpret_cast(zebinData->elfHeader->flags); + flags.generatorId = 0u; // ngen generated + + ASSERT_NE(nullptr, src.data()); + ASSERT_NE(0u, src.size()); + + const unsigned char *binaries[1] = {reinterpret_cast(src.data())}; + const size_t binarySize = src.size(); + + pProgram = clCreateProgramWithBinary( + pContext, + 1, + &testedClDevice, + &binarySize, + binaries, + &binaryStatus, + &retVal); + + EXPECT_NE(nullptr, pProgram); + ASSERT_EQ(CL_SUCCESS, retVal); + + retVal = clBuildProgram( + pProgram, + 1, + &testedClDevice, + nullptr, + nullptr, + nullptr); + + EXPECT_EQ(CL_SUCCESS, retVal); + + retVal = clReleaseProgram(pProgram); + EXPECT_EQ(CL_SUCCESS, retVal); +} + TEST_F(ClBuildProgramTests, GivenBinaryAsInputWhenCreatingProgramWithBinaryForMultipleDevicesThenProgramBuildSucceeds) { MockUnrestrictiveContextMultiGPU context; cl_program pProgram = nullptr; diff --git a/opencl/test/unit_test/program/program_tests.cpp b/opencl/test/unit_test/program/program_tests.cpp index e7ed7537d2..6c0f137fe9 100644 --- a/opencl/test/unit_test/program/program_tests.cpp +++ b/opencl/test/unit_test/program/program_tests.cpp @@ -1872,6 +1872,7 @@ TEST_F(ProgramTests, givenStatefulAndStatelessAccessesWhenProgramBuildIsCalledTh using Program::irBinary; using Program::irBinarySize; using Program::isBuiltIn; + using Program::isGeneratedByIgc; using Program::options; using Program::Program; using Program::sourceCode; @@ -1898,11 +1899,12 @@ TEST_F(ProgramTests, givenStatefulAndStatelessAccessesWhenProgramBuildIsCalledTh } }; - std::array, 3> testParams = {{{CL_SUCCESS, false, -1}, - {CL_SUCCESS, true, 0}, - {CL_BUILD_PROGRAM_FAILURE, true, 1}}}; + std::array, 4> testParams = {{{CL_SUCCESS, false, true, -1}, + {CL_SUCCESS, true, true, 0}, + {CL_BUILD_PROGRAM_FAILURE, true, true, 1}, + {CL_SUCCESS, true, false, 1}}}; - for (auto &[result, isStatefulAccess, debuyKey] : testParams) { + for (auto &[result, isStatefulAccess, isIgcGenerated, debuyKey] : testParams) { if (!compilerProductHelper.isForceToStatelessRequired()) { result = CL_SUCCESS; @@ -1911,6 +1913,7 @@ TEST_F(ProgramTests, givenStatefulAndStatelessAccessesWhenProgramBuildIsCalledTh program.isBuiltIn = false; program.sourceCode = "test_kernel"; program.createdFrom = Program::CreatedFrom::SOURCE; + program.isGeneratedByIgc = isIgcGenerated; program.setAddressingMode(isStatefulAccess); DebugManager.flags.FailBuildProgramWithStatefulAccess.set(debuyKey); EXPECT_EQ(result, program.build(toClDeviceVector(*pClDevice), nullptr)); diff --git a/shared/source/command_container/command_encoder_xehp_and_later.inl b/shared/source/command_container/command_encoder_xehp_and_later.inl index 2a7b173944..b2bb1e9f72 100644 --- a/shared/source/command_container/command_encoder_xehp_and_later.inl +++ b/shared/source/command_container/command_encoder_xehp_and_later.inl @@ -114,8 +114,15 @@ void EncodeDispatchKernel::encode(CommandContainer &container, EncodeDis idd.setSharedLocalMemorySize(slmSize); auto bindingTableStateCount = kernelDescriptor.payloadMappings.bindingTable.numEntries; + auto bufferAddressingMode = kernelDescriptor.kernelAttributes.bufferAddressingMode; + + if (productHelper.isSkippingStatefulInformationRequired(kernelDescriptor)) { + bindingTableStateCount = 0u; + bufferAddressingMode = KernelDescriptor::Stateless; + } + uint32_t bindingTablePointer = 0u; - if ((kernelDescriptor.kernelAttributes.bufferAddressingMode == KernelDescriptor::BindfulAndStateless) || + if ((bufferAddressingMode == KernelDescriptor::BindfulAndStateless) || kernelDescriptor.kernelAttributes.flags.usesImages) { container.prepareBindfulSsh(); if (bindingTableStateCount > 0u) { diff --git a/shared/source/device_binary_format/device_binary_format_zebin.cpp b/shared/source/device_binary_format/device_binary_format_zebin.cpp index d621ed96d1..9208844c75 100644 --- a/shared/source/device_binary_format/device_binary_format_zebin.cpp +++ b/shared/source/device_binary_format/device_binary_format_zebin.cpp @@ -59,7 +59,7 @@ SingleDeviceBinary unpackSingleZebin(const ArrayRef archive, cons bool validForTarget = true; if (elf.elfFileHeader->machine == Elf::ELF_MACHINE::EM_INTELGT) { - validForTarget &= Zebin::validateTargetDevice(elf, requestedTargetDevice, outErrReason, outWarning); + validForTarget &= Zebin::validateTargetDevice(elf, requestedTargetDevice, outErrReason, outWarning, ret.generator); } else { const auto &flags = reinterpret_cast(elf.elfFileHeader->flags); validForTarget &= flags.machineEntryUsesGfxCoreInsteadOfProductFamily @@ -67,6 +67,8 @@ SingleDeviceBinary unpackSingleZebin(const ArrayRef archive, cons : (requestedTargetDevice.productFamily == static_cast(elf.elfFileHeader->machine)); validForTarget &= (0 == flags.validateRevisionId) | ((requestedTargetDevice.stepping >= flags.minHwRevisionId) & (requestedTargetDevice.stepping <= flags.maxHwRevisionId)); validForTarget &= (requestedTargetDevice.maxPointerSizeInBytes >= static_cast(numBits == Elf::EI_CLASS_32 ? 4 : 8)); + + ret.generator = static_cast(flags.generatorId); } if (false == validForTarget) { @@ -119,6 +121,12 @@ DecodeError decodeSingleZebin(ProgramInfo &dst, const SingleDeviceBinary &src, s return decodeError; } + bool isGeneratedByIgc = src.generator == GeneratorType::Igc; + + for (auto &kernelInfo : dst.kernelInfos) { + kernelInfo->kernelDescriptor.kernelMetadata.isGeneratedByIgc = isGeneratedByIgc; + } + prepareLinkerInputForZebin(dst, elf); return decodeError; } diff --git a/shared/source/device_binary_format/device_binary_formats.h b/shared/source/device_binary_format/device_binary_formats.h index 57e725adca..768de62a9c 100644 --- a/shared/source/device_binary_format/device_binary_formats.h +++ b/shared/source/device_binary_format/device_binary_formats.h @@ -37,6 +37,11 @@ enum class DecodeError : uint8_t { UnhandledBinary }; +enum class GeneratorType : uint8_t { + Unknown, + Igc +}; + inline const char *asString(DecodeError err) { switch (err) { default: @@ -73,6 +78,7 @@ struct SingleDeviceBinary { ArrayRef packedTargetDeviceBinary; ConstStringRef buildOptions; TargetDevice targetDevice; + GeneratorType generator = GeneratorType::Igc; }; template diff --git a/shared/source/device_binary_format/zebin/zebin_decoder.cpp b/shared/source/device_binary_format/zebin/zebin_decoder.cpp index a521a4091c..e2f30fc7db 100644 --- a/shared/source/device_binary_format/zebin/zebin_decoder.cpp +++ b/shared/source/device_binary_format/zebin/zebin_decoder.cpp @@ -75,10 +75,10 @@ bool validateTargetDevice(const TargetDevice &targetDevice, Elf::ELF_IDENTIFIER_ return true; } -template bool validateTargetDevice(const Elf::Elf &elf, const TargetDevice &targetDevice, std::string &outErrReason, std::string &outWarning); -template bool validateTargetDevice(const Elf::Elf &elf, const TargetDevice &targetDevice, std::string &outErrReason, std::string &outWarning); +template bool validateTargetDevice(const Elf::Elf &elf, const TargetDevice &targetDevice, std::string &outErrReason, std::string &outWarning, GeneratorType &generatorType); +template bool validateTargetDevice(const Elf::Elf &elf, const TargetDevice &targetDevice, std::string &outErrReason, std::string &outWarning, GeneratorType &generatorType); template -bool validateTargetDevice(const Elf::Elf &elf, const TargetDevice &targetDevice, std::string &outErrReason, std::string &outWarning) { +bool validateTargetDevice(const Elf::Elf &elf, const TargetDevice &targetDevice, std::string &outErrReason, std::string &outWarning, GeneratorType &generatorType) { GFXCORE_FAMILY gfxCore = IGFX_UNKNOWN_CORE; PRODUCT_FAMILY productFamily = IGFX_UNKNOWN; AOT::PRODUCT_CONFIG productConfig = AOT::UNKNOWN_ISA; @@ -106,6 +106,7 @@ bool validateTargetDevice(const Elf::Elf &elf, const TargetDevice &targ DEBUG_BREAK_IF(sizeof(uint32_t) != intelGTNote.data.size()); auto targetMetadataPacked = reinterpret_cast(intelGTNote.data.begin()); targetMetadata.packed = static_cast(*targetMetadataPacked); + generatorType = static_cast(targetMetadata.generatorId); break; } case Elf::IntelGTSectionType::ZebinVersion: { diff --git a/shared/source/device_binary_format/zebin/zebin_decoder.h b/shared/source/device_binary_format/zebin/zebin_decoder.h index 771ae23991..0fef76f57b 100644 --- a/shared/source/device_binary_format/zebin/zebin_decoder.h +++ b/shared/source/device_binary_format/zebin/zebin_decoder.h @@ -50,7 +50,7 @@ bool isZebin(ArrayRef binary); bool validateTargetDevice(const TargetDevice &targetDevice, Elf::ELF_IDENTIFIER_CLASS numBits, PRODUCT_FAMILY productFamily, GFXCORE_FAMILY gfxCore, AOT::PRODUCT_CONFIG productConfig, Zebin::Elf::ZebinTargetFlags targetMetadata); template -bool validateTargetDevice(const Elf::Elf &elf, const TargetDevice &targetDevice, std::string &outErrReason, std::string &outWarning); +bool validateTargetDevice(const Elf::Elf &elf, const TargetDevice &targetDevice, std::string &outErrReason, std::string &outWarning, GeneratorType &generatorType); template DecodeError decodeIntelGTNoteSection(ArrayRef intelGTNotesSection, std::vector &intelGTNotes, std::string &outErrReason, std::string &outWarning); diff --git a/shared/source/kernel/kernel_descriptor.h b/shared/source/kernel/kernel_descriptor.h index 8253ccfbc7..b6ae34f5b3 100644 --- a/shared/source/kernel/kernel_descriptor.h +++ b/shared/source/kernel/kernel_descriptor.h @@ -215,6 +215,7 @@ struct KernelDescriptor { uint16_t compiledSubGroupsNumber = 0U; uint8_t requiredSubGroupSize = 0U; + bool isGeneratedByIgc = true; } kernelMetadata; struct { diff --git a/shared/source/os_interface/product_helper.h b/shared/source/os_interface/product_helper.h index 810432faf6..6a969f2542 100644 --- a/shared/source/os_interface/product_helper.h +++ b/shared/source/os_interface/product_helper.h @@ -206,6 +206,7 @@ class ProductHelper { virtual bool is48bResourceNeededForRayTracing() const = 0; virtual bool disableL3CacheForDebug(const HardwareInfo &hwInfo) const = 0; virtual bool isCachingOnCpuAvailable() const = 0; + virtual bool isSkippingStatefulInformationRequired(const KernelDescriptor &kernelDescriptor) const = 0; virtual ~ProductHelper() = default; diff --git a/shared/source/os_interface/product_helper.inl b/shared/source/os_interface/product_helper.inl index 848327b260..96bd84312f 100644 --- a/shared/source/os_interface/product_helper.inl +++ b/shared/source/os_interface/product_helper.inl @@ -784,4 +784,10 @@ template bool ProductHelperHw::isCachingOnCpuAvailable() const { return true; } + +template +bool ProductHelperHw::isSkippingStatefulInformationRequired(const KernelDescriptor &kernelDescriptor) const { + return false; +} + } // namespace NEO diff --git a/shared/source/os_interface/product_helper_hw.h b/shared/source/os_interface/product_helper_hw.h index 2cd69f6b46..9c707bb5ca 100644 --- a/shared/source/os_interface/product_helper_hw.h +++ b/shared/source/os_interface/product_helper_hw.h @@ -159,6 +159,7 @@ class ProductHelperHw : public ProductHelper { bool is48bResourceNeededForRayTracing() const override; bool disableL3CacheForDebug(const HardwareInfo &hwInfo) const override; bool isCachingOnCpuAvailable() const override; + bool isSkippingStatefulInformationRequired(const KernelDescriptor &kernelDescriptor) const override; ~ProductHelperHw() override = default; diff --git a/shared/source/xe_hpc_core/pvc/os_agnostic_product_helper_pvc.inl b/shared/source/xe_hpc_core/pvc/os_agnostic_product_helper_pvc.inl index 2ce2c650dc..9ab075b177 100644 --- a/shared/source/xe_hpc_core/pvc/os_agnostic_product_helper_pvc.inl +++ b/shared/source/xe_hpc_core/pvc/os_agnostic_product_helper_pvc.inl @@ -212,4 +212,11 @@ template <> uint32_t ProductHelperHw::getNumberOfPartsInTileForConcurrentKernel() const { return PVC::numberOfpartsInTileForConcurrentKernels; } + +template <> +bool ProductHelperHw::isSkippingStatefulInformationRequired(const KernelDescriptor &kernelDescriptor) const { + bool isGeneratedByNgen = !kernelDescriptor.kernelMetadata.isGeneratedByIgc; + return isGeneratedByNgen; +} + } // namespace NEO diff --git a/shared/test/common/mocks/mock_modules_zebin.cpp b/shared/test/common/mocks/mock_modules_zebin.cpp index 4af5956d3f..e272cc835b 100644 --- a/shared/test/common/mocks/mock_modules_zebin.cpp +++ b/shared/test/common/mocks/mock_modules_zebin.cpp @@ -239,6 +239,8 @@ ZebinCopyBufferSimdModule::ZebinCopyBufferSimdModule(const NEO::Hardwar elfHeader.type = NEO::Zebin::Elf::ET_ZEBIN_EXE; elfHeader.machine = hwInfo.platform.eProductFamily; + auto &flags = reinterpret_cast(elfHeader.flags); + flags.generatorId = 1u; const uint8_t testKernelData[0x2c0] = {0u}; diff --git a/shared/test/unit_test/device_binary_format/zebin_decoder_tests.cpp b/shared/test/unit_test/device_binary_format/zebin_decoder_tests.cpp index 936bfedcf9..0a027c3f25 100644 --- a/shared/test/unit_test/device_binary_format/zebin_decoder_tests.cpp +++ b/shared/test/unit_test/device_binary_format/zebin_decoder_tests.cpp @@ -5459,7 +5459,8 @@ TEST_F(IntelGTNotesFixture, GivenValidTargetDeviceAndNoteWithUnrecognizedTypeWhe EXPECT_TRUE(outWarning.empty()); EXPECT_TRUE(outErrReason.empty()); - auto validationRes = validateTargetDevice(elf, targetDevice, outErrReason, outWarning); + GeneratorType generator{}; + auto validationRes = validateTargetDevice(elf, targetDevice, outErrReason, outWarning, generator); EXPECT_TRUE(validationRes); EXPECT_TRUE(outErrReason.empty()); @@ -5516,7 +5517,8 @@ TEST_F(IntelGTNotesFixture, WhenValidatingTargetDeviceGivenValidTargetDeviceAndV EXPECT_TRUE(outWarning.empty()); EXPECT_TRUE(outErrReason.empty()); - EXPECT_TRUE(validateTargetDevice(elf, targetDevice, outErrReason, outWarning)); + GeneratorType generator{}; + EXPECT_TRUE(validateTargetDevice(elf, targetDevice, outErrReason, outWarning, generator)); } TEST_F(IntelGTNotesFixture, givenAotConfigInIntelGTNotesSectionWhenValidatingTargetDeviceThenUseOnlyItForValidation) { @@ -5546,8 +5548,9 @@ TEST_F(IntelGTNotesFixture, givenAotConfigInIntelGTNotesSectionWhenValidatingTar auto elf = NEO::Elf::decodeElf(zebin.storage, outErrReason, outWarning); EXPECT_TRUE(outWarning.empty()); EXPECT_TRUE(outErrReason.empty()); + GeneratorType generator{}; - EXPECT_TRUE(validateTargetDevice(elf, targetDevice, outErrReason, outWarning)); + EXPECT_TRUE(validateTargetDevice(elf, targetDevice, outErrReason, outWarning, generator)); } TEST(ValidateTargetDevice32BitZebin, Given32BitZebinAndValidIntelGTNotesWhenValidatingTargetDeviceThenReturnTrue) { @@ -5572,8 +5575,44 @@ TEST(ValidateTargetDevice32BitZebin, Given32BitZebinAndValidIntelGTNotesWhenVali auto elf = NEO::Elf::decodeElf(zebin.storage, outErrReason, outWarning); EXPECT_TRUE(outWarning.empty()); EXPECT_TRUE(outErrReason.empty()); + GeneratorType generator{}; - EXPECT_TRUE(validateTargetDevice(elf, targetDevice, outErrReason, outWarning)); + EXPECT_TRUE(validateTargetDevice(elf, targetDevice, outErrReason, outWarning, generator)); +} + +TEST(ValidateTargetDeviceGeneratorZebin, GivenZebinAndValidIntelGTNotesWithGeneratorIdWhenValidatingTargetDeviceThenGeneratorIsSetCorrectly) { + + for (auto generatorId : {0u, 1u}) { + TargetDevice targetDevice; + targetDevice.productFamily = productFamily; + targetDevice.coreFamily = renderCoreFamily; + targetDevice.maxPointerSizeInBytes = 4; + targetDevice.stepping = hardwareInfoTable[productFamily]->platform.usRevId; + + ZebinTestData::ValidEmptyProgram zebin; + zebin.elfHeader->type = NEO::Elf::ET_REL; + zebin.elfHeader->machine = NEO::Elf::ELF_MACHINE::EM_INTELGT; + + Zebin::Elf::ZebinTargetFlags targetMetadata; + targetMetadata.validateRevisionId = true; + targetMetadata.minHwRevisionId = targetDevice.stepping; + targetMetadata.maxHwRevisionId = targetDevice.stepping; + targetMetadata.generatorId = generatorId; + auto currentVersion = versionToString(NEO::Zebin::ZeInfo::zeInfoDecoderVersion); + auto intelGTNotesSection = ZebinTestData::createIntelGTNoteSection(productFamily, renderCoreFamily, targetMetadata, currentVersion); + zebin.appendSection(NEO::Elf::SHT_NOTE, Zebin::Elf::SectionNames::noteIntelGT, intelGTNotesSection); + std::string outErrReason, outWarning; + auto elf = NEO::Elf::decodeElf(zebin.storage, outErrReason, outWarning); + EXPECT_TRUE(outWarning.empty()); + EXPECT_TRUE(outErrReason.empty()); + + GeneratorType generator{}; + EXPECT_TRUE(validateTargetDevice(elf, targetDevice, outErrReason, outWarning, generator)); + + bool isIgcGeneratedExpectation = static_cast(generatorId); + bool isIgcGenerated = static_cast(generator); + EXPECT_EQ(isIgcGeneratedExpectation, isIgcGenerated); + } } TEST_F(IntelGTNotesFixture, WhenValidatingTargetDeviceGivenValidTargetDeviceAndNoNotesThenReturnFalse) { @@ -5587,8 +5626,9 @@ TEST_F(IntelGTNotesFixture, WhenValidatingTargetDeviceGivenValidTargetDeviceAndN auto elf = Zebin::Elf::decodeElf(zebin.storage, outErrReason, outWarning); EXPECT_TRUE(outWarning.empty()); EXPECT_TRUE(outErrReason.empty()); + GeneratorType generator{}; - EXPECT_FALSE(validateTargetDevice(elf, targetDevice, outErrReason, outWarning)); + EXPECT_FALSE(validateTargetDevice(elf, targetDevice, outErrReason, outWarning, generator)); } TEST_F(IntelGTNotesFixture, WhenValidatingTargetDeviceGivenInvalidTargetDeviceAndValidNotesThenReturnFalse) { @@ -5639,8 +5679,9 @@ TEST_F(IntelGTNotesFixture, WhenValidatingTargetDeviceGivenInvalidTargetDeviceAn auto elf = Zebin::Elf::decodeElf(zebin.storage, outErrReason, outWarning); EXPECT_TRUE(outWarning.empty()); EXPECT_TRUE(outErrReason.empty()); + GeneratorType generator{}; - EXPECT_FALSE(validateTargetDevice(elf, targetDevice, outErrReason, outWarning)); + EXPECT_FALSE(validateTargetDevice(elf, targetDevice, outErrReason, outWarning, generator)); } TEST_F(IntelGTNotesFixture, WhenValidatingTargetDeviceGivenValidTargetDeviceAndInvalidNoteTypeThenReturnFalse) { @@ -5664,8 +5705,9 @@ TEST_F(IntelGTNotesFixture, WhenValidatingTargetDeviceGivenValidTargetDeviceAndI auto elf = Zebin::Elf::decodeElf(zebin.storage, outErrReason, outWarning); EXPECT_TRUE(outWarning.empty()); EXPECT_TRUE(outErrReason.empty()); + GeneratorType generator{}; - EXPECT_FALSE(validateTargetDevice(elf, targetDevice, outErrReason, outWarning)); + EXPECT_FALSE(validateTargetDevice(elf, targetDevice, outErrReason, outWarning, generator)); } TEST_F(IntelGTNotesFixture, WhenValidatingTargetDeviceGivenInvalidIntelGTNotesSecionSizeWhichWilLCauseOOBAccessThenReturnFalse) { @@ -5688,9 +5730,10 @@ TEST_F(IntelGTNotesFixture, WhenValidatingTargetDeviceGivenInvalidIntelGTNotesSe auto elf = Zebin::Elf::decodeElf(zebin.storage, outErrReason, outWarning); EXPECT_TRUE(outWarning.empty()); EXPECT_TRUE(outErrReason.empty()); + GeneratorType generator{}; TargetDevice targetDevice; - auto result = validateTargetDevice(elf, targetDevice, outErrReason, outWarning); + auto result = validateTargetDevice(elf, targetDevice, outErrReason, outWarning, generator); EXPECT_FALSE(result); EXPECT_TRUE(outWarning.empty()); auto errStr{"DeviceBinaryFormat::Zebin : Offseting will cause out-of-bound memory read! Section size: " + std::to_string(incorrectSectionDataSize) + @@ -5716,9 +5759,10 @@ TEST_F(IntelGTNotesFixture, WhenValidatingTargetDeviceGivenValidZeInfoVersionInI auto elf = Zebin::Elf::decodeElf(zebin.storage, outErrReason, outWarning); EXPECT_TRUE(outWarning.empty()); EXPECT_TRUE(outErrReason.empty()); + GeneratorType generator{}; TargetDevice targetDevice; - validateTargetDevice(elf, targetDevice, outErrReason, outWarning); + validateTargetDevice(elf, targetDevice, outErrReason, outWarning, generator); EXPECT_TRUE(outErrReason.empty()); } @@ -5763,9 +5807,10 @@ TEST_F(IntelGTNotesFixture, GivenInvalidVersioningWhenValidatingTargetDeviceThen auto elf = Zebin::Elf::decodeElf(zebin.storage, outErrReason, outWarning); EXPECT_TRUE(outWarning.empty()); EXPECT_TRUE(outErrReason.empty()); + GeneratorType generator{}; TargetDevice targetDevice; - validateTargetDevice(elf, targetDevice, outErrReason, outWarning); + validateTargetDevice(elf, targetDevice, outErrReason, outWarning, generator); EXPECT_TRUE(outWarning.empty()); EXPECT_STREQ("DeviceBinaryFormat::Zebin::.ze_info : Invalid version format - expected 'MAJOR.MINOR' string, got : .11\n", outErrReason.c_str()); } @@ -5786,9 +5831,10 @@ TEST_F(IntelGTNotesFixture, GivenIncompatibleVersioningWhenValidatingTargetDevic auto elf = Zebin::Elf::decodeElf(zebin.storage, outErrReason, outWarning); EXPECT_TRUE(outWarning.empty()); EXPECT_TRUE(outErrReason.empty()); + GeneratorType generator{}; TargetDevice targetDevice; - validateTargetDevice(elf, targetDevice, outErrReason, outWarning); + validateTargetDevice(elf, targetDevice, outErrReason, outWarning, generator); EXPECT_TRUE(outWarning.empty()); EXPECT_STREQ("DeviceBinaryFormat::Zebin::.ze_info : Unhandled major version : 2, decoder is at : 1\n", outErrReason.c_str()); } diff --git a/shared/test/unit_test/encoders/test_encode_dispatch_kernel.cpp b/shared/test/unit_test/encoders/test_encode_dispatch_kernel.cpp index d6f0e1af14..590af5da21 100644 --- a/shared/test/unit_test/encoders/test_encode_dispatch_kernel.cpp +++ b/shared/test/unit_test/encoders/test_encode_dispatch_kernel.cpp @@ -1354,6 +1354,50 @@ HWTEST_F(BindlessCommandEncodeStatesContainerTest, givenBindfulKernelWhenBindles EXPECT_NE(commandContainer->getIndirectHeap(HeapType::SURFACE_STATE), nullptr); } +using NgenGeneratorDispatchKernelEncodeTest = Test; + +HWTEST2_F(NgenGeneratorDispatchKernelEncodeTest, givenBindfulKernelAndIsNotGeneratedByIgcWhenEncodeDispatchKernelThenCmdContainerDoesNotHaveSsh, IsPVC) { + using BINDING_TABLE_STATE = typename FamilyType::BINDING_TABLE_STATE; + + for (auto isGeneratedByIgc : {false, true}) { + auto commandContainer = std::make_unique(); + commandContainer->initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false); + commandContainer->setDirtyStateForAllHeaps(false); + commandContainer->l1CachePolicyDataRef() = &l1CachePolicyData; + + if (isGeneratedByIgc == false) { + commandContainer->indirectHeaps[HeapType::SURFACE_STATE].reset(nullptr); + } + + uint32_t numBindingTable = 1; + BINDING_TABLE_STATE bindingTableState = FamilyType::cmdInitBindingTableState; + + uint32_t dims[] = {1, 1, 1}; + std::unique_ptr dispatchInterface(new MockDispatchKernelEncoder()); + + dispatchInterface->kernelDescriptor.payloadMappings.bindingTable.numEntries = numBindingTable; + dispatchInterface->kernelDescriptor.payloadMappings.bindingTable.tableOffset = 0U; + dispatchInterface->kernelDescriptor.kernelAttributes.bufferAddressingMode = KernelDescriptor::BindfulAndStateless; + dispatchInterface->kernelDescriptor.kernelMetadata.isGeneratedByIgc = isGeneratedByIgc; + + const uint8_t *sshData = reinterpret_cast(&bindingTableState); + dispatchInterface->getSurfaceStateHeapDataResult = const_cast(sshData); + dispatchInterface->getSurfaceStateHeapDataSizeResult = static_cast(sizeof(BINDING_TABLE_STATE)); + + bool requiresUncachedMocs = false; + + EncodeDispatchKernelArgs dispatchArgs = createDefaultDispatchKernelArgs(pDevice, dispatchInterface.get(), dims, requiresUncachedMocs); + + EncodeDispatchKernel::encode(*commandContainer.get(), dispatchArgs, nullptr); + + if (isGeneratedByIgc) { + EXPECT_NE(commandContainer->getIndirectHeap(HeapType::SURFACE_STATE), nullptr); + } else { + EXPECT_EQ(commandContainer->getIndirectHeap(HeapType::SURFACE_STATE), nullptr); + } + } +} + HWTEST_F(CommandEncodeStatesTest, givenKernelInfoWhenGettingRequiredDshSpaceThenReturnCorrectValues) { using INTERFACE_DESCRIPTOR_DATA = typename FamilyType::INTERFACE_DESCRIPTOR_DATA; using SAMPLER_STATE = typename FamilyType::SAMPLER_STATE; diff --git a/shared/test/unit_test/fixtures/command_container_fixture.h b/shared/test/unit_test/fixtures/command_container_fixture.h index 057141430d..a0b07a582b 100644 --- a/shared/test/unit_test/fixtures/command_container_fixture.h +++ b/shared/test/unit_test/fixtures/command_container_fixture.h @@ -20,6 +20,7 @@ class CommandEncodeStatesFixture : public DeviceFixture { class MyMockCommandContainer : public CommandContainer { public: using CommandContainer::dirtyHeaps; + using CommandContainer::indirectHeaps; IndirectHeap *getHeapWithRequiredSizeAndAlignment(HeapType heapType, size_t sizeRequired, size_t alignment) override { getHeapWithRequiredSizeAndAlignmentCalled++; diff --git a/shared/test/unit_test/os_interface/product_helper_tests.cpp b/shared/test/unit_test/os_interface/product_helper_tests.cpp index 9384678c13..a6909bc627 100644 --- a/shared/test/unit_test/os_interface/product_helper_tests.cpp +++ b/shared/test/unit_test/os_interface/product_helper_tests.cpp @@ -342,6 +342,16 @@ HWTEST2_F(ProductHelperTest, givenProductHelperWhenAskedIfHeapInLocalMemThenFals EXPECT_FALSE(productHelper->heapInLocalMem(pInHwInfo)); } +HWTEST2_F(ProductHelperTest, givenProductHelperWhenIsSkippingStatefulInformationRequiredThenFalseIsReturned, IsNotPVC) { + + KernelDescriptor kernelDescriptor{}; + kernelDescriptor.kernelMetadata.isGeneratedByIgc = true; + EXPECT_FALSE(productHelper->isSkippingStatefulInformationRequired(kernelDescriptor)); + + kernelDescriptor.kernelMetadata.isGeneratedByIgc = false; + EXPECT_FALSE(productHelper->isSkippingStatefulInformationRequired(kernelDescriptor)); +} + HWTEST2_F(ProductHelperTest, givenProductHelperWhenSettingCapabilityCoherencyFlagThenFlagIsSet, IsAtMostGen11) { bool coherency = false; diff --git a/shared/test/unit_test/xe_hpc_core/pvc/test_product_helper_pvc.cpp b/shared/test/unit_test/xe_hpc_core/pvc/test_product_helper_pvc.cpp index c4b795ef30..29bccb017f 100644 --- a/shared/test/unit_test/xe_hpc_core/pvc/test_product_helper_pvc.cpp +++ b/shared/test/unit_test/xe_hpc_core/pvc/test_product_helper_pvc.cpp @@ -178,6 +178,16 @@ PVCTEST_F(PvcProductHelper, givenPvcProductHelperWhenCheckCopyEngineSelectorEnab EXPECT_FALSE(productHelper->isCopyEngineSelectorEnabled(hwInfo)); } +PVCTEST_F(PvcProductHelper, givenPvcProductHelperWhenIsSkippingStatefulInformationRequiredThenCorrectResultIsReturned) { + + KernelDescriptor kernelDescriptor{}; + kernelDescriptor.kernelMetadata.isGeneratedByIgc = true; + EXPECT_FALSE(productHelper->isSkippingStatefulInformationRequired(kernelDescriptor)); + + kernelDescriptor.kernelMetadata.isGeneratedByIgc = false; + EXPECT_TRUE(productHelper->isSkippingStatefulInformationRequired(kernelDescriptor)); +} + PVCTEST_F(PvcProductHelper, givenProductHelperAndProgramExtendedPipeControlPriorToNonPipelinedStateCommandDisabledWhenAskedIfPipeControlPriorToNonPipelinedStateCommandsWARequiredThenFalseIsReturned) { DebugManagerStateRestore restore; DebugManager.flags.ProgramExtendedPipeControlPriorToNonPipelinedStateCommand.set(0);