From 1aca16a7ac382d8b864d5c481872c88438d5c08f Mon Sep 17 00:00:00 2001 From: Jaime Arteaga Date: Wed, 13 Jan 2021 17:19:44 -0800 Subject: [PATCH] Add experimental_properties for indirect access Read zebin experimental properties indicating whether a kernel has indirect access and if so, ignore calls to zeKernelSetIndirectAccess. Signed-off-by: Jaime Arteaga --- level_zero/core/source/kernel/kernel_imp.cpp | 10 +- level_zero/core/source/kernel/kernel_imp.h | 6 + .../test/unit_tests/fixtures/module_fixture.h | 2 + .../unit_tests/sources/kernel/test_kernel.cpp | 270 +++++++++++++--- .../debug_settings/debug_variables_base.inl | 2 +- .../device_binary_format_ar.cpp | 2 +- .../device_binary_format_ocl_elf.cpp | 2 +- .../device_binary_format/elf/zebin_elf.h | 18 ++ .../device_binary_format/zebin_decoder.cpp | 43 +++ .../device_binary_format/zebin_decoder.h | 7 +- shared/source/kernel/kernel_descriptor.h | 5 +- .../zebin_decoder_tests.cpp | 291 ++++++++++++++++++ 12 files changed, 605 insertions(+), 53 deletions(-) diff --git a/level_zero/core/source/kernel/kernel_imp.cpp b/level_zero/core/source/kernel/kernel_imp.cpp index 5dae827991..41ed6a3a24 100644 --- a/level_zero/core/source/kernel/kernel_imp.cpp +++ b/level_zero/core/source/kernel/kernel_imp.cpp @@ -362,7 +362,7 @@ ze_result_t KernelImp::suggestMaxCooperativeGroupCount(uint32_t *totalGroupCount } ze_result_t KernelImp::setIndirectAccess(ze_kernel_indirect_access_flags_t flags) { - if (NEO::DebugManager.flags.DisableIndirectAccess.get() == 1) { + if (NEO::DebugManager.flags.DisableIndirectAccess.get() == 1 && this->kernelHasIndirectAccess == false) { return ZE_RESULT_SUCCESS; } @@ -385,10 +385,10 @@ ze_result_t KernelImp::getIndirectAccess(ze_kernel_indirect_access_flags_t *flag *flags |= ZE_KERNEL_INDIRECT_ACCESS_FLAG_DEVICE; } if (this->unifiedMemoryControls.indirectHostAllocationsAllowed) { - *flags |= ZE_KERNEL_INDIRECT_ACCESS_FLAG_DEVICE; + *flags |= ZE_KERNEL_INDIRECT_ACCESS_FLAG_HOST; } if (this->unifiedMemoryControls.indirectSharedAllocationsAllowed) { - *flags |= ZE_KERNEL_INDIRECT_ACCESS_FLAG_DEVICE; + *flags |= ZE_KERNEL_INDIRECT_ACCESS_FLAG_SHARED; } return ZE_RESULT_SUCCESS; @@ -714,6 +714,10 @@ ze_result_t KernelImp::initialize(const ze_kernel_desc_t *desc) { residencyContainer.insert(residencyContainer.end(), kernelImmData->getResidencyContainer().begin(), kernelImmData->getResidencyContainer().end()); + kernelHasIndirectAccess = kernelImmData->getDescriptor().kernelAttributes.hasNonKernelArgLoad || + kernelImmData->getDescriptor().kernelAttributes.hasNonKernelArgStore || + kernelImmData->getDescriptor().kernelAttributes.hasNonKernelArgAtomic; + return ZE_RESULT_SUCCESS; } diff --git a/level_zero/core/source/kernel/kernel_imp.h b/level_zero/core/source/kernel/kernel_imp.h index bb17168f39..fa6649a513 100644 --- a/level_zero/core/source/kernel/kernel_imp.h +++ b/level_zero/core/source/kernel/kernel_imp.h @@ -124,6 +124,10 @@ struct KernelImp : Kernel { ze_result_t setCacheConfig(ze_cache_config_flags_t flags) override; + bool hasIndirectAccess() { + return kernelHasIndirectAccess; + } + protected: KernelImp() = default; @@ -174,6 +178,8 @@ struct KernelImp : Kernel { uint32_t globalOffsets[3] = {}; ze_cache_config_flags_t cacheConfigFlags = 0u; + + bool kernelHasIndirectAccess = true; }; } // namespace L0 diff --git a/level_zero/core/test/unit_tests/fixtures/module_fixture.h b/level_zero/core/test/unit_tests/fixtures/module_fixture.h index d4374c9561..5f52399083 100644 --- a/level_zero/core/test/unit_tests/fixtures/module_fixture.h +++ b/level_zero/core/test/unit_tests/fixtures/module_fixture.h @@ -101,7 +101,9 @@ struct ModuleImmutableDataFixture : public DeviceFixture { class MockKernel : public WhiteBox { public: + using KernelImp::kernelHasIndirectAccess; using L0::KernelImp::privateMemoryGraphicsAllocation; + MockKernel(MockModule *mockModule) : WhiteBox(mockModule) { } void setBufferSurfaceState(uint32_t argIndex, void *address, NEO::GraphicsAllocation *alloc) override { diff --git a/level_zero/core/test/unit_tests/sources/kernel/test_kernel.cpp b/level_zero/core/test/unit_tests/sources/kernel/test_kernel.cpp index 56313fe7e7..08d238ef8a 100644 --- a/level_zero/core/test/unit_tests/sources/kernel/test_kernel.cpp +++ b/level_zero/core/test/unit_tests/sources/kernel/test_kernel.cpp @@ -212,49 +212,6 @@ HWTEST2_F(SetKernelArg, givenBufferArgumentWhichHasNotBeenAllocatedByRuntimeThen EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, res); } -class KernelPropertiesTests : public ModuleFixture, public ::testing::Test { - public: - void SetUp() override { - ModuleFixture::SetUp(); - - ze_kernel_desc_t kernelDesc = {}; - kernelDesc.pKernelName = kernelName.c_str(); - - ze_result_t res = module->createKernel(&kernelDesc, &kernelHandle); - EXPECT_EQ(ZE_RESULT_SUCCESS, res); - - kernel = L0::Kernel::fromHandle(kernelHandle); - } - - void TearDown() override { - Kernel::fromHandle(kernelHandle)->destroy(); - ModuleFixture::TearDown(); - } - - ze_kernel_handle_t kernelHandle; - L0::Kernel *kernel = nullptr; -}; - -HWTEST_F(KernelPropertiesTests, givenKernelThenCorrectNameIsRetrieved) { - size_t kernelSize = 0; - ze_result_t res = kernel->getKernelName(&kernelSize, nullptr); - EXPECT_EQ(ZE_RESULT_SUCCESS, res); - EXPECT_EQ(kernelSize, kernelName.length() + 1); - - size_t alteredKernelSize = kernelSize * 2; - res = kernel->getKernelName(&alteredKernelSize, nullptr); - EXPECT_EQ(ZE_RESULT_SUCCESS, res); - EXPECT_EQ(alteredKernelSize, kernelSize); - - char *kernelNameRetrieved = new char[kernelSize]; - res = kernel->getKernelName(&kernelSize, kernelNameRetrieved); - EXPECT_EQ(ZE_RESULT_SUCCESS, res); - - EXPECT_EQ(0, strncmp(kernelName.c_str(), kernelNameRetrieved, kernelSize)); - - delete[] kernelNameRetrieved; -} - class KernelImmutableDataTests : public ModuleImmutableDataFixture, public ::testing::Test { public: void SetUp() override { @@ -561,6 +518,144 @@ HWTEST_F(KernelImmutableDataTests, givenKernelInitializedWithPrivateMemoryThenCo EXPECT_EQ(sizeContainerWithoutPrivateMemory + 1u, sizeContainerWithPrivateMemory); } +using KernelIndirectPropertiesFromIGCTests = KernelImmutableDataTests; + +HWTEST_F(KernelIndirectPropertiesFromIGCTests, whenInitializingKernelWithNoKernelLoadAndNoStoreAndNoAtomicThenHasIndirectAccessIsSetToFalse) { + DebugManagerStateRestore restorer; + NEO::DebugManager.flags.DisableIndirectAccess.set(0); + + uint32_t perHwThreadPrivateMemorySizeRequested = 32u; + bool isInternal = false; + + std::unique_ptr mockKernelImmData = + std::make_unique(perHwThreadPrivateMemorySizeRequested); + + createModuleFromBinary(perHwThreadPrivateMemorySizeRequested, isInternal, mockKernelImmData.get()); + + std::unique_ptr kernel; + kernel = std::make_unique(module.get()); + + ze_kernel_desc_t desc = {}; + desc.pKernelName = kernelName.c_str(); + + module->mockKernelImmData->mockKernelDescriptor->kernelAttributes.hasNonKernelArgLoad = false; + module->mockKernelImmData->mockKernelDescriptor->kernelAttributes.hasNonKernelArgStore = false; + module->mockKernelImmData->mockKernelDescriptor->kernelAttributes.hasNonKernelArgAtomic = false; + + kernel->initialize(&desc); + + EXPECT_FALSE(kernel->hasIndirectAccess()); +} + +HWTEST_F(KernelIndirectPropertiesFromIGCTests, whenInitializingKernelWithKernelLoadStoreAtomicThenHasIndirectAccessIsSetToTrue) { + DebugManagerStateRestore restorer; + NEO::DebugManager.flags.DisableIndirectAccess.set(0); + + uint32_t perHwThreadPrivateMemorySizeRequested = 32u; + bool isInternal = false; + + std::unique_ptr mockKernelImmData = + std::make_unique(perHwThreadPrivateMemorySizeRequested); + + createModuleFromBinary(perHwThreadPrivateMemorySizeRequested, isInternal, mockKernelImmData.get()); + + { + std::unique_ptr kernel; + kernel = std::make_unique(module.get()); + + ze_kernel_desc_t desc = {}; + desc.pKernelName = kernelName.c_str(); + + module->mockKernelImmData->mockKernelDescriptor->kernelAttributes.hasNonKernelArgLoad = true; + module->mockKernelImmData->mockKernelDescriptor->kernelAttributes.hasNonKernelArgStore = false; + module->mockKernelImmData->mockKernelDescriptor->kernelAttributes.hasNonKernelArgAtomic = false; + + kernel->initialize(&desc); + + EXPECT_TRUE(kernel->hasIndirectAccess()); + } + + { + std::unique_ptr kernel; + kernel = std::make_unique(module.get()); + + ze_kernel_desc_t desc = {}; + desc.pKernelName = kernelName.c_str(); + + module->mockKernelImmData->mockKernelDescriptor->kernelAttributes.hasNonKernelArgLoad = false; + module->mockKernelImmData->mockKernelDescriptor->kernelAttributes.hasNonKernelArgStore = true; + module->mockKernelImmData->mockKernelDescriptor->kernelAttributes.hasNonKernelArgAtomic = false; + + kernel->initialize(&desc); + + EXPECT_TRUE(kernel->hasIndirectAccess()); + } + + { + std::unique_ptr kernel; + kernel = std::make_unique(module.get()); + + ze_kernel_desc_t desc = {}; + desc.pKernelName = kernelName.c_str(); + + module->mockKernelImmData->mockKernelDescriptor->kernelAttributes.hasNonKernelArgLoad = false; + module->mockKernelImmData->mockKernelDescriptor->kernelAttributes.hasNonKernelArgStore = false; + module->mockKernelImmData->mockKernelDescriptor->kernelAttributes.hasNonKernelArgAtomic = true; + + kernel->initialize(&desc); + + EXPECT_TRUE(kernel->hasIndirectAccess()); + } +} + +class KernelPropertiesTests : public ModuleFixture, public ::testing::Test { + public: + class MockKernel : public KernelImp { + public: + using KernelImp::kernelHasIndirectAccess; + }; + void SetUp() override { + ModuleFixture::SetUp(); + + ze_kernel_desc_t kernelDesc = {}; + kernelDesc.pKernelName = kernelName.c_str(); + + ze_result_t res = module->createKernel(&kernelDesc, &kernelHandle); + EXPECT_EQ(ZE_RESULT_SUCCESS, res); + + kernel = static_cast(L0::Kernel::fromHandle(kernelHandle)); + kernel->kernelHasIndirectAccess = true; + } + + void TearDown() override { + Kernel::fromHandle(kernelHandle)->destroy(); + ModuleFixture::TearDown(); + } + + ze_kernel_handle_t kernelHandle; + MockKernel *kernel = nullptr; +}; + +HWTEST_F(KernelPropertiesTests, givenKernelThenCorrectNameIsRetrieved) { + size_t kernelSize = 0; + ze_result_t res = kernel->getKernelName(&kernelSize, nullptr); + EXPECT_EQ(ZE_RESULT_SUCCESS, res); + EXPECT_EQ(kernelSize, kernelName.length() + 1); + + size_t alteredKernelSize = kernelSize * 2; + res = kernel->getKernelName(&alteredKernelSize, nullptr); + EXPECT_EQ(ZE_RESULT_SUCCESS, res); + EXPECT_EQ(alteredKernelSize, kernelSize); + + char *kernelNameRetrieved = new char[kernelSize]; + res = kernel->getKernelName(&kernelSize, kernelNameRetrieved); + EXPECT_EQ(ZE_RESULT_SUCCESS, res); + + EXPECT_EQ(0, strncmp(kernelName.c_str(), kernelNameRetrieved, kernelSize)); + + delete[] kernelNameRetrieved; +} + HWTEST_F(KernelPropertiesTests, givenValidKernelThenPropertiesAreRetrieved) { ze_kernel_properties_t kernelProperties = {}; @@ -610,7 +705,7 @@ HWTEST_F(KernelPropertiesTests, givenValidKernelThenPropertiesAreRetrieved) { sizeof(kernelProperties.uuid.mid))); } -HWTEST_F(KernelPropertiesTests, givenValidKernelIndirectAccessFlagsThenFlagsSetCorrectly) { +HWTEST_F(KernelPropertiesTests, whenSettingValidKernelIndirectAccessFlagsThenFlagsAreSetCorrectly) { UnifiedMemoryControls unifiedMemoryControls = kernel->getUnifiedMemoryControls(); EXPECT_EQ(false, unifiedMemoryControls.indirectDeviceAllocationsAllowed); EXPECT_EQ(false, unifiedMemoryControls.indirectHostAllocationsAllowed); @@ -628,6 +723,44 @@ HWTEST_F(KernelPropertiesTests, givenValidKernelIndirectAccessFlagsThenFlagsSetC EXPECT_EQ(true, unifiedMemoryControls.indirectSharedAllocationsAllowed); } +HWTEST_F(KernelPropertiesTests, whenCallingGetIndirectAccessAfterSetIndirectAccessWithDeviceFlagThenCorrectFlagIsReturned) { + ze_kernel_indirect_access_flags_t flags = ZE_KERNEL_INDIRECT_ACCESS_FLAG_DEVICE; + auto res = kernel->setIndirectAccess(flags); + EXPECT_EQ(ZE_RESULT_SUCCESS, res); + + ze_kernel_indirect_access_flags_t returnedFlags; + res = kernel->getIndirectAccess(&returnedFlags); + EXPECT_EQ(ZE_RESULT_SUCCESS, res); + EXPECT_TRUE(returnedFlags & ZE_KERNEL_INDIRECT_ACCESS_FLAG_DEVICE); + EXPECT_FALSE(returnedFlags & ZE_KERNEL_INDIRECT_ACCESS_FLAG_HOST); + EXPECT_FALSE(returnedFlags & ZE_KERNEL_INDIRECT_ACCESS_FLAG_SHARED); +} + +HWTEST_F(KernelPropertiesTests, whenCallingGetIndirectAccessAfterSetIndirectAccessWithHostFlagThenCorrectFlagIsReturned) { + ze_kernel_indirect_access_flags_t flags = ZE_KERNEL_INDIRECT_ACCESS_FLAG_HOST; + auto res = kernel->setIndirectAccess(flags); + EXPECT_EQ(ZE_RESULT_SUCCESS, res); + + ze_kernel_indirect_access_flags_t returnedFlags; + res = kernel->getIndirectAccess(&returnedFlags); + EXPECT_EQ(ZE_RESULT_SUCCESS, res); + EXPECT_FALSE(returnedFlags & ZE_KERNEL_INDIRECT_ACCESS_FLAG_DEVICE); + EXPECT_TRUE(returnedFlags & ZE_KERNEL_INDIRECT_ACCESS_FLAG_HOST); + EXPECT_FALSE(returnedFlags & ZE_KERNEL_INDIRECT_ACCESS_FLAG_SHARED); +} + +HWTEST_F(KernelPropertiesTests, whenCallingGetIndirectAccessAfterSetIndirectAccessWithSharedFlagThenCorrectFlagIsReturned) { + ze_kernel_indirect_access_flags_t flags = ZE_KERNEL_INDIRECT_ACCESS_FLAG_SHARED; + auto res = kernel->setIndirectAccess(flags); + EXPECT_EQ(ZE_RESULT_SUCCESS, res); + + ze_kernel_indirect_access_flags_t returnedFlags; + res = kernel->getIndirectAccess(&returnedFlags); + EXPECT_EQ(ZE_RESULT_SUCCESS, res); + EXPECT_FALSE(returnedFlags & ZE_KERNEL_INDIRECT_ACCESS_FLAG_DEVICE); + EXPECT_FALSE(returnedFlags & ZE_KERNEL_INDIRECT_ACCESS_FLAG_HOST); + EXPECT_TRUE(returnedFlags & ZE_KERNEL_INDIRECT_ACCESS_FLAG_SHARED); +} HWTEST_F(KernelPropertiesTests, givenValidKernelWithIndirectAccessFlagsAndDisableIndirectAccessSetToZeroThenFlagsAreSet) { DebugManagerStateRestore restorer; NEO::DebugManager.flags.DisableIndirectAccess.set(0); @@ -649,9 +782,34 @@ HWTEST_F(KernelPropertiesTests, givenValidKernelWithIndirectAccessFlagsAndDisabl EXPECT_TRUE(unifiedMemoryControls.indirectSharedAllocationsAllowed); } -HWTEST_F(KernelPropertiesTests, givenValidKernelWithIndirectAccessFlagsAndDisableIndirectAccessSetToOneThenFlagsAreNotSet) { +using KernelIndirectPropertiesTests = KernelPropertiesTests; + +HWTEST_F(KernelIndirectPropertiesTests, whenCallingSetIndirectAccessWithKernelThatHasIndirectAccessThenIndirectAccessIsSet) { DebugManagerStateRestore restorer; NEO::DebugManager.flags.DisableIndirectAccess.set(1); + kernel->kernelHasIndirectAccess = true; + + UnifiedMemoryControls unifiedMemoryControls = kernel->getUnifiedMemoryControls(); + EXPECT_EQ(false, unifiedMemoryControls.indirectDeviceAllocationsAllowed); + EXPECT_EQ(false, unifiedMemoryControls.indirectHostAllocationsAllowed); + EXPECT_EQ(false, unifiedMemoryControls.indirectSharedAllocationsAllowed); + + ze_kernel_indirect_access_flags_t flags = ZE_KERNEL_INDIRECT_ACCESS_FLAG_DEVICE | + ZE_KERNEL_INDIRECT_ACCESS_FLAG_HOST | + ZE_KERNEL_INDIRECT_ACCESS_FLAG_SHARED; + auto res = kernel->setIndirectAccess(flags); + EXPECT_EQ(ZE_RESULT_SUCCESS, res); + + unifiedMemoryControls = kernel->getUnifiedMemoryControls(); + EXPECT_TRUE(unifiedMemoryControls.indirectDeviceAllocationsAllowed); + EXPECT_TRUE(unifiedMemoryControls.indirectHostAllocationsAllowed); + EXPECT_TRUE(unifiedMemoryControls.indirectSharedAllocationsAllowed); +} + +HWTEST_F(KernelIndirectPropertiesTests, whenCallingSetIndirectAccessWithKernelThatDoesNotHaveIndirectAccessThenIndirectAccessIsNotSet) { + DebugManagerStateRestore restorer; + NEO::DebugManager.flags.DisableIndirectAccess.set(1); + kernel->kernelHasIndirectAccess = false; UnifiedMemoryControls unifiedMemoryControls = kernel->getUnifiedMemoryControls(); EXPECT_EQ(false, unifiedMemoryControls.indirectDeviceAllocationsAllowed); @@ -670,6 +828,28 @@ HWTEST_F(KernelPropertiesTests, givenValidKernelWithIndirectAccessFlagsAndDisabl EXPECT_FALSE(unifiedMemoryControls.indirectSharedAllocationsAllowed); } +HWTEST_F(KernelIndirectPropertiesTests, whenCallingSetIndirectAccessWithKernelThatDoesNotHaveIndirectAccessButWithoutSettingDisableIndirectAccessThenIndirectAccessIsSet) { + DebugManagerStateRestore restorer; + NEO::DebugManager.flags.DisableIndirectAccess.set(0); + kernel->kernelHasIndirectAccess = false; + + UnifiedMemoryControls unifiedMemoryControls = kernel->getUnifiedMemoryControls(); + EXPECT_EQ(false, unifiedMemoryControls.indirectDeviceAllocationsAllowed); + EXPECT_EQ(false, unifiedMemoryControls.indirectHostAllocationsAllowed); + EXPECT_EQ(false, unifiedMemoryControls.indirectSharedAllocationsAllowed); + + ze_kernel_indirect_access_flags_t flags = ZE_KERNEL_INDIRECT_ACCESS_FLAG_DEVICE | + ZE_KERNEL_INDIRECT_ACCESS_FLAG_HOST | + ZE_KERNEL_INDIRECT_ACCESS_FLAG_SHARED; + auto res = kernel->setIndirectAccess(flags); + EXPECT_EQ(ZE_RESULT_SUCCESS, res); + + unifiedMemoryControls = kernel->getUnifiedMemoryControls(); + EXPECT_TRUE(unifiedMemoryControls.indirectDeviceAllocationsAllowed); + EXPECT_TRUE(unifiedMemoryControls.indirectHostAllocationsAllowed); + EXPECT_TRUE(unifiedMemoryControls.indirectSharedAllocationsAllowed); +} + HWTEST_F(KernelPropertiesTests, givenValidKernelIndirectAccessFlagsSetThenExpectKernelIndirectAllocationsAllowedTrue) { EXPECT_EQ(false, kernel->hasIndirectAllocationsAllowed()); diff --git a/shared/source/debug_settings/debug_variables_base.inl b/shared/source/debug_settings/debug_variables_base.inl index 5f797e7011..5ac008391f 100644 --- a/shared/source/debug_settings/debug_variables_base.inl +++ b/shared/source/debug_settings/debug_variables_base.inl @@ -220,7 +220,7 @@ DECLARE_DEBUG_VARIABLE(int32_t, ForceLocalMemoryAccessMode, -1, "-1: don't overr DECLARE_DEBUG_VARIABLE(int32_t, ForceUserptrAlignment, -1, "-1: no force (4kb), >0: n kb alignment") DECLARE_DEBUG_VARIABLE(int64_t, ForceSystemMemoryPlacement, 0, "0: default, >0: (bitmask) for given Graphics Allocation Type, force system memory placement") DECLARE_DEBUG_VARIABLE(int64_t, ForceNonSystemMemoryPlacement, 0, "0: default, >0: (bitmask) for given Graphics Allocation Type, force non-system memory placement") -DECLARE_DEBUG_VARIABLE(int64_t, DisableIndirectAccess, -1, "0: default, 0: Indirect access for L0 kernels is enabled, 1: Indirect is disabled") +DECLARE_DEBUG_VARIABLE(int64_t, DisableIndirectAccess, -1, "0: default, 0: Indirect access for L0 kernels is enabled, 1: Read IGC experimental properties to determine whether indirect access is required") DECLARE_DEBUG_VARIABLE(int32_t, UseVmBind, -1, "Use new residency model on Linux (requires kernel support), -1: default, 0: disabled, 1: enabled") DECLARE_DEBUG_VARIABLE(bool, UseMaxSimdSizeToDeduceMaxWorkgroupSize, false, "With this flag on, max workgroup size is deduced using SIMD32 instead of SIMD8, this causes the max wkg size to be 4 times bigger") DECLARE_DEBUG_VARIABLE(bool, ReturnRawGpuTimestamps, false, "Driver returns raw GPU tiemstamps instead of calculated ones.") diff --git a/shared/source/device_binary_format/device_binary_format_ar.cpp b/shared/source/device_binary_format/device_binary_format_ar.cpp index 5dadac7346..b67b80c343 100644 --- a/shared/source/device_binary_format/device_binary_format_ar.cpp +++ b/shared/source/device_binary_format/device_binary_format_ar.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2020-2021 Intel Corporation * * SPDX-License-Identifier: MIT * diff --git a/shared/source/device_binary_format/device_binary_format_ocl_elf.cpp b/shared/source/device_binary_format/device_binary_format_ocl_elf.cpp index 22a0486451..1697e5a5f9 100644 --- a/shared/source/device_binary_format/device_binary_format_ocl_elf.cpp +++ b/shared/source/device_binary_format/device_binary_format_ocl_elf.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2020-2021 Intel Corporation * * SPDX-License-Identifier: MIT * diff --git a/shared/source/device_binary_format/elf/zebin_elf.h b/shared/source/device_binary_format/elf/zebin_elf.h index 1b8d823281..8ef31f2645 100644 --- a/shared/source/device_binary_format/elf/zebin_elf.h +++ b/shared/source/device_binary_format/elf/zebin_elf.h @@ -93,6 +93,7 @@ static constexpr ConstStringRef payloadArguments("payload_arguments"); static constexpr ConstStringRef bindingTableIndices("binding_table_indices"); static constexpr ConstStringRef perThreadPayloadArguments("per_thread_payload_arguments"); static constexpr ConstStringRef perThreadMemoryBuffers("per_thread_memory_buffers"); +static constexpr ConstStringRef experimentalProperties("experimental_properties"); namespace ExecutionEnv { static constexpr ConstStringRef actualKernelStartOffset("actual_kernel_start_offset"); @@ -186,6 +187,11 @@ static constexpr ConstStringRef spillFillSpace("spill_fill_space"); static constexpr ConstStringRef singleSpace("single_space"); } // namespace MemoryUsage } // namespace PerThreadMemoryBuffer +namespace ExperimentalProperties { +static constexpr ConstStringRef hasNonKernelArgLoad("has_non_kernel_arg_load"); +static constexpr ConstStringRef hasNonKernelArgStore("has_non_kernel_arg_store"); +static constexpr ConstStringRef hasNonKernelArgAtomic("has_non_kernel_arg_atomic"); +} // namespace ExperimentalProperties } // namespace Kernel } // namespace Tags @@ -217,6 +223,9 @@ using SimdSizeT = int32_t; using SlmSizeT = int32_t; using SubgroupIndependentForwardProgressT = bool; using WorkgroupWalkOrderDimensionsT = int32_t[3]; +using HasNonKernelArgLoad = int32_t; +using HasNonKernelArgStore = int32_t; +using HasNonKernelArgAtomic = int32_t; namespace Defaults { static constexpr BarrierCountT barrierCount = 0; @@ -235,6 +244,9 @@ static constexpr RequiredWorkGroupSizeT requiredWorkGroupSize = {0, 0, 0}; static constexpr SlmSizeT slmSize = 0; static constexpr SubgroupIndependentForwardProgressT subgroupIndependentForwardProgress = false; static constexpr WorkgroupWalkOrderDimensionsT workgroupWalkOrderDimensions = {0, 1, 2}; +static constexpr HasNonKernelArgLoad hasNonKernelArgLoad = false; +static constexpr HasNonKernelArgStore hasNonKernelArgStore = false; +static constexpr HasNonKernelArgAtomic hasNonKernelArgAtomic = false; } // namespace Defaults static constexpr ConstStringRef required[] = { @@ -264,6 +276,12 @@ struct ExecutionEnvBaseT { WorkgroupWalkOrderDimensionsT workgroupWalkOrderDimensions{Defaults::workgroupWalkOrderDimensions[0], Defaults::workgroupWalkOrderDimensions[1], Defaults::workgroupWalkOrderDimensions[2]}; }; +struct ExperimentalPropertiesBaseT { + HasNonKernelArgLoad hasNonKernelArgLoad = Defaults::hasNonKernelArgLoad; + HasNonKernelArgStore hasNonKernelArgStore = Defaults::hasNonKernelArgStore; + HasNonKernelArgAtomic hasNonKernelArgAtomic = Defaults::hasNonKernelArgAtomic; +}; + } // namespace ExecutionEnv enum ArgType : uint8_t { diff --git a/shared/source/device_binary_format/zebin_decoder.cpp b/shared/source/device_binary_format/zebin_decoder.cpp index b3ec90e750..f91c3c90df 100644 --- a/shared/source/device_binary_format/zebin_decoder.cpp +++ b/shared/source/device_binary_format/zebin_decoder.cpp @@ -126,6 +126,8 @@ void extractZeInfoKernelSections(const NEO::Yaml::YamlParser &parser, const NEO: outZeInfoKernelSections.bindingTableIndicesNd.push_back(&kernelMetadataNd); } else if (NEO::Elf::ZebinKernelMetadata::Tags::Kernel::perThreadMemoryBuffers == key) { outZeInfoKernelSections.perThreadMemoryBuffersNd.push_back(&kernelMetadataNd); + } else if (NEO::Elf::ZebinKernelMetadata::Tags::Kernel::experimentalProperties == key) { + outZeInfoKernelSections.experimentalPropertiesNd.push_back(&kernelMetadataNd); } else { outWarning.append("DeviceBinaryFormat::Zebin::" + NEO::Elf::SectionsNamesZebin::zeInfo.str() + " : Unknown entry \"" + parser.readKey(kernelMetadataNd).str() + "\" in context of : " + context.str() + "\n"); } @@ -139,6 +141,7 @@ DecodeError validateZeInfoKernelSectionsCount(const ZeInfoKernelSections &outZeI valid &= validateZebinSectionsCountAtMost(outZeInfoKernelSections.perThreadPayloadArgumentsNd, NEO::Elf::ZebinKernelMetadata::Tags::Kernel::perThreadPayloadArguments, 1U, outErrReason, outWarning); valid &= validateZebinSectionsCountAtMost(outZeInfoKernelSections.bindingTableIndicesNd, NEO::Elf::ZebinKernelMetadata::Tags::Kernel::bindingTableIndices, 1U, outErrReason, outWarning); valid &= validateZebinSectionsCountAtMost(outZeInfoKernelSections.perThreadMemoryBuffersNd, NEO::Elf::ZebinKernelMetadata::Tags::Kernel::perThreadMemoryBuffers, 1U, outErrReason, outWarning); + valid &= validateZebinSectionsCountAtMost(outZeInfoKernelSections.experimentalPropertiesNd, NEO::Elf::ZebinKernelMetadata::Tags::Kernel::experimentalProperties, 1U, outErrReason, outWarning); return valid ? DecodeError::Success : DecodeError::InvalidBinary; } @@ -200,6 +203,33 @@ DecodeError readZeInfoExecutionEnvironment(const NEO::Yaml::YamlParser &parser, return validExecEnv ? DecodeError::Success : DecodeError::InvalidBinary; } +DecodeError readZeInfoExperimentalProperties(const NEO::Yaml::YamlParser &parser, const NEO::Yaml::Node &node, + NEO::Elf::ZebinKernelMetadata::Types::Kernel::ExecutionEnv::ExperimentalPropertiesBaseT &outExperimentalProperties, + ConstStringRef context, + std::string &outErrReason, std::string &outWarning) { + bool validExperimentalProperty = true; + for (const auto &experimentalPropertyNd : parser.createChildrenRange(node)) { + for (const auto &experimentalPropertyMemberNd : parser.createChildrenRange(experimentalPropertyNd)) { + auto key = parser.readKey(experimentalPropertyMemberNd); + if (NEO::Elf::ZebinKernelMetadata::Tags::Kernel::ExperimentalProperties::hasNonKernelArgLoad == key) { + validExperimentalProperty = validExperimentalProperty & readZeInfoValueChecked(parser, experimentalPropertyMemberNd, + outExperimentalProperties.hasNonKernelArgLoad, context, outErrReason); + } else if (NEO::Elf::ZebinKernelMetadata::Tags::Kernel::ExperimentalProperties::hasNonKernelArgStore == key) { + validExperimentalProperty = validExperimentalProperty & readZeInfoValueChecked(parser, experimentalPropertyMemberNd, + outExperimentalProperties.hasNonKernelArgStore, context, outErrReason); + } else if (NEO::Elf::ZebinKernelMetadata::Tags::Kernel::ExperimentalProperties::hasNonKernelArgAtomic == key) { + validExperimentalProperty = validExperimentalProperty & readZeInfoValueChecked(parser, experimentalPropertyMemberNd, + outExperimentalProperties.hasNonKernelArgAtomic, context, outErrReason); + } else { + outWarning.append("DeviceBinaryFormat::Zebin::" + NEO::Elf::SectionsNamesZebin::zeInfo.str() + " : Unknown entry \"" + key.str() + "\" in context of " + context.str() + "\n"); + validExperimentalProperty = false; + } + } + } + + return validExperimentalProperty ? DecodeError::Success : DecodeError::InvalidBinary; +} + bool readEnumChecked(const Yaml::Token *token, NEO::Elf::ZebinKernelMetadata::Types::Kernel::ArgType &out, ConstStringRef context, std::string &outErrReason) { if (nullptr == token) { return false; @@ -803,6 +833,19 @@ NEO::DecodeError populateKernelDescriptor(NEO::ProgramInfo &dst, NEO::Elf::ElfkernelDescriptor.kernelMetadata.kernelName, outErrReason, outWarning); + if (DecodeError::Success != experimentalPropertiesErr) { + return experimentalPropertiesErr; + } + + kernelDescriptor.kernelAttributes.hasNonKernelArgLoad = outExperimentalProperties.hasNonKernelArgLoad; + kernelDescriptor.kernelAttributes.hasNonKernelArgStore = outExperimentalProperties.hasNonKernelArgStore; + kernelDescriptor.kernelAttributes.hasNonKernelArgAtomic = outExperimentalProperties.hasNonKernelArgAtomic; + } + kernelDescriptor.kernelAttributes.barrierCount = execEnv.barrierCount; kernelDescriptor.kernelAttributes.flags.requiresDisabledMidThreadPreemption = execEnv.disableMidThreadPreemption; kernelDescriptor.kernelAttributes.numGrfRequired = execEnv.grfCount; diff --git a/shared/source/device_binary_format/zebin_decoder.h b/shared/source/device_binary_format/zebin_decoder.h index c6838089a1..ed547590be 100644 --- a/shared/source/device_binary_format/zebin_decoder.h +++ b/shared/source/device_binary_format/zebin_decoder.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2020-2021 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -38,6 +38,7 @@ struct ZeInfoKernelSections { UniqueNode bindingTableIndicesNd; UniqueNode perThreadPayloadArgumentsNd; UniqueNode perThreadMemoryBuffersNd; + UniqueNode experimentalPropertiesNd; }; DecodeError extractZebinSections(NEO::Elf::Elf &elf, ZebinSections &out, std::string &outErrReason, std::string &outWarning); @@ -47,6 +48,10 @@ DecodeError validateZeInfoKernelSectionsCount(const ZeInfoKernelSections &outZeI DecodeError readZeInfoExecutionEnvironment(const NEO::Yaml::YamlParser &parser, const NEO::Yaml::Node &node, NEO::Elf::ZebinKernelMetadata::Types::Kernel::ExecutionEnv::ExecutionEnvBaseT &outExecEnv, ConstStringRef context, std::string &outErrReason, std::string &outWarning); +DecodeError readZeInfoExperimentalProperties(const NEO::Yaml::YamlParser &parser, const NEO::Yaml::Node &node, + NEO::Elf::ZebinKernelMetadata::Types::Kernel::ExecutionEnv::ExperimentalPropertiesBaseT &outExperimentalProperties, + ConstStringRef context, + std::string &outErrReason, std::string &outWarning); bool readEnumChecked(const Yaml::Token *token, NEO::Elf::ZebinKernelMetadata::Types::Kernel::ArgType &out, ConstStringRef context, std::string &outErrReason); bool readEnumChecked(const Yaml::Token *token, NEO::Elf::ZebinKernelMetadata::Types::Kernel::PayloadArgument::MemoryAddressingMode &out, diff --git a/shared/source/kernel/kernel_descriptor.h b/shared/source/kernel/kernel_descriptor.h index 929b178d86..847b80697e 100644 --- a/shared/source/kernel/kernel_descriptor.h +++ b/shared/source/kernel/kernel_descriptor.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2020-2021 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -56,6 +56,9 @@ struct KernelDescriptor final { uint16_t numArgsToPatch = 0U; uint16_t numGrfRequired = 0U; uint8_t barrierCount = 0u; + bool hasNonKernelArgLoad = true; + bool hasNonKernelArgStore = true; + bool hasNonKernelArgAtomic = true; AddressingMode bufferAddressingMode = BindfulAndStateless; AddressingMode imageAddressingMode = Bindful; 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 5c78b60387..e378315b84 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 @@ -454,6 +454,7 @@ kernels: ASSERT_FALSE(kernelSections.bindingTableIndicesNd.empty()); ASSERT_FALSE(kernelSections.perThreadPayloadArgumentsNd.empty()); ASSERT_FALSE(kernelSections.perThreadMemoryBuffersNd.empty()); + ASSERT_TRUE(kernelSections.experimentalPropertiesNd.empty()); EXPECT_EQ("name", parser.readKey(*kernelSections.nameNd[0])) << parser.readKey(*kernelSections.nameNd[0]).str(); EXPECT_EQ("execution_env", parser.readKey(*kernelSections.executionEnvNd[0])) << parser.readKey(*kernelSections.executionEnvNd[0]).str(); @@ -463,6 +464,64 @@ kernels: EXPECT_EQ("per_thread_memory_buffers", parser.readKey(*kernelSections.perThreadMemoryBuffersNd[0])) << parser.readKey(*kernelSections.perThreadMemoryBuffersNd[0]).str(); } +TEST(ExtractZeInfoKernelSections, GivenExperimentalPropertyInKnownSectionsThenSectionIsCapturedProperly) { + NEO::ConstStringRef yaml = R"===(--- +kernels: + - name: some_kernel + execution_env: + actual_kernel_start_offset: 0 + payload_arguments: + - arg_type: global_id_offset + offset: 0 + size: 12 + per_thread_payload_arguments: + - arg_type: local_id + offset: 0 + size: 192 + binding_table_indices: + - bti_value: 0 + arg_index: 0 + per_thread_memory_buffers: + - type: scratch + usage: single_space + size: 64 + experimental_properties: + - has_non_kernel_arg_load: 1 + has_non_kernel_arg_store: 1 + has_non_kernel_arg_atomic: 0 +... +)==="; + + NEO::ZeInfoKernelSections kernelSections; + std::string parserErrors; + std::string parserWarnings; + NEO::Yaml::YamlParser parser; + bool success = parser.parse(yaml, parserErrors, parserWarnings); + EXPECT_TRUE(parserErrors.empty()) << parserErrors; + EXPECT_TRUE(parserWarnings.empty()) << parserWarnings; + ASSERT_TRUE(success); + + auto &kernelNode = *parser.createChildrenRange(*parser.findNodeWithKeyDfs("kernels")).begin(); + std::string warnings; + NEO::extractZeInfoKernelSections(parser, kernelNode, kernelSections, "some_kernel", warnings); + EXPECT_TRUE(warnings.empty()) << warnings; + ASSERT_FALSE(kernelSections.nameNd.empty()); + ASSERT_FALSE(kernelSections.executionEnvNd.empty()); + ASSERT_FALSE(kernelSections.payloadArgumentsNd.empty()); + ASSERT_FALSE(kernelSections.bindingTableIndicesNd.empty()); + ASSERT_FALSE(kernelSections.perThreadPayloadArgumentsNd.empty()); + ASSERT_FALSE(kernelSections.perThreadMemoryBuffersNd.empty()); + ASSERT_FALSE(kernelSections.experimentalPropertiesNd.empty()); + + EXPECT_EQ("name", parser.readKey(*kernelSections.nameNd[0])) << parser.readKey(*kernelSections.nameNd[0]).str(); + EXPECT_EQ("execution_env", parser.readKey(*kernelSections.executionEnvNd[0])) << parser.readKey(*kernelSections.executionEnvNd[0]).str(); + EXPECT_EQ("payload_arguments", parser.readKey(*kernelSections.payloadArgumentsNd[0])) << parser.readKey(*kernelSections.payloadArgumentsNd[0]).str(); + EXPECT_EQ("per_thread_payload_arguments", parser.readKey(*kernelSections.perThreadPayloadArgumentsNd[0])) << parser.readKey(*kernelSections.perThreadPayloadArgumentsNd[0]).str(); + EXPECT_EQ("binding_table_indices", parser.readKey(*kernelSections.bindingTableIndicesNd[0])) << parser.readKey(*kernelSections.bindingTableIndicesNd[0]).str(); + EXPECT_EQ("per_thread_memory_buffers", parser.readKey(*kernelSections.perThreadMemoryBuffersNd[0])) << parser.readKey(*kernelSections.perThreadMemoryBuffersNd[0]).str(); + EXPECT_EQ("experimental_properties", parser.readKey(*kernelSections.experimentalPropertiesNd[0])) << parser.readKey(*kernelSections.experimentalPropertiesNd[0]).str(); +} + TEST(ExtractZeInfoKernelSections, GivenUnknownSectionThenEmitsAWarning) { NEO::ConstStringRef yaml = R"===(--- kernels: @@ -613,6 +672,238 @@ TEST(ValidateZeInfoKernelSectionsCount, GivenTwoPerThreadMemoryBuffersSectionsTh EXPECT_TRUE(warnings.empty()) << warnings; } +TEST(ReadZeExperimentalProperties, GivenYamlWithLoadExperimentalPropertyEntryThenExperimentalPropertiesAreCorrectlyRead) { + NEO::ConstStringRef yaml = R"===(--- +kernels: + - name: some_kernel + experimental_properties: + - has_non_kernel_arg_load: 1 + has_non_kernel_arg_store: 0 + has_non_kernel_arg_atomic: 0 +... +)==="; + + std::string parserErrors; + std::string parserWarnings; + NEO::Yaml::YamlParser parser; + bool success = parser.parse(yaml, parserErrors, parserWarnings); + ASSERT_TRUE(success); + auto &experimentalPropertiesNode = *parser.findNodeWithKeyDfs("experimental_properties"); + std::string errors; + std::string warnings; + NEO::Elf::ZebinKernelMetadata::Types::Kernel::ExecutionEnv::ExperimentalPropertiesBaseT experimentalProperties; + auto err = NEO::readZeInfoExperimentalProperties(parser, + experimentalPropertiesNode, + experimentalProperties, + "some_kernel", + errors, + warnings); + EXPECT_EQ(NEO::DecodeError::Success, err); + EXPECT_TRUE(errors.empty()) << errors; + EXPECT_TRUE(warnings.empty()) << warnings; + EXPECT_EQ(experimentalProperties.hasNonKernelArgLoad, 1); + EXPECT_EQ(experimentalProperties.hasNonKernelArgStore, 0); + EXPECT_EQ(experimentalProperties.hasNonKernelArgAtomic, 0); +} + +TEST(ReadZeExperimentalProperties, GivenYamlWithStoreExperimentalPropertyEntryThenExperimentalPropertiesAreCorrectlyRead) { + NEO::ConstStringRef yaml = R"===(--- +kernels: + - name: some_kernel + experimental_properties: + - has_non_kernel_arg_load: 0 + has_non_kernel_arg_store: 1 + has_non_kernel_arg_atomic: 0 +... +)==="; + + std::string parserErrors; + std::string parserWarnings; + NEO::Yaml::YamlParser parser; + bool success = parser.parse(yaml, parserErrors, parserWarnings); + ASSERT_TRUE(success); + auto &experimentalPropertiesNode = *parser.findNodeWithKeyDfs("experimental_properties"); + std::string errors; + std::string warnings; + NEO::Elf::ZebinKernelMetadata::Types::Kernel::ExecutionEnv::ExperimentalPropertiesBaseT experimentalProperties; + auto err = NEO::readZeInfoExperimentalProperties(parser, + experimentalPropertiesNode, + experimentalProperties, + "some_kernel", + errors, + warnings); + EXPECT_EQ(NEO::DecodeError::Success, err); + EXPECT_TRUE(errors.empty()) << errors; + EXPECT_TRUE(warnings.empty()) << warnings; + EXPECT_EQ(experimentalProperties.hasNonKernelArgLoad, 0); + EXPECT_EQ(experimentalProperties.hasNonKernelArgStore, 1); + EXPECT_EQ(experimentalProperties.hasNonKernelArgAtomic, 0); +} + +TEST(ReadZeExperimentalProperties, GivenYamlWithAtomicExperimentalPropertyEntryThenExperimentalPropertiesAreCorrectlyRead) { + NEO::ConstStringRef yaml = R"===(--- +kernels: + - name: some_kernel + experimental_properties: + - has_non_kernel_arg_load: 0 + has_non_kernel_arg_store: 0 + has_non_kernel_arg_atomic: 1 +... +)==="; + + std::string parserErrors; + std::string parserWarnings; + NEO::Yaml::YamlParser parser; + bool success = parser.parse(yaml, parserErrors, parserWarnings); + ASSERT_TRUE(success); + auto &experimentalPropertiesNode = *parser.findNodeWithKeyDfs("experimental_properties"); + std::string errors; + std::string warnings; + NEO::Elf::ZebinKernelMetadata::Types::Kernel::ExecutionEnv::ExperimentalPropertiesBaseT experimentalProperties; + auto err = NEO::readZeInfoExperimentalProperties(parser, + experimentalPropertiesNode, + experimentalProperties, + "some_kernel", + errors, + warnings); + EXPECT_EQ(NEO::DecodeError::Success, err); + EXPECT_TRUE(errors.empty()) << errors; + EXPECT_TRUE(warnings.empty()) << warnings; + EXPECT_EQ(experimentalProperties.hasNonKernelArgLoad, 0); + EXPECT_EQ(experimentalProperties.hasNonKernelArgStore, 0); + EXPECT_EQ(experimentalProperties.hasNonKernelArgAtomic, 1); +} + +TEST(ReadZeExperimentalProperties, GivenYamlWithInvalidExperimentalPropertyEntryValueThenErrorIsReturned) { + NEO::ConstStringRef yaml = R"===(--- +kernels: + - name: some_kernel + experimental_properties: + - has_non_kernel_arg_load: true + has_non_kernel_arg_store: 0 + has_non_kernel_arg_atomic: 0 +... +)==="; + + std::string parserErrors; + std::string parserWarnings; + NEO::Yaml::YamlParser parser; + bool success = parser.parse(yaml, parserErrors, parserWarnings); + ASSERT_TRUE(success); + auto &experimentalPropertiesNode = *parser.findNodeWithKeyDfs("experimental_properties"); + std::string errors; + std::string warnings; + NEO::Elf::ZebinKernelMetadata::Types::Kernel::ExecutionEnv::ExperimentalPropertiesBaseT experimentalProperties; + auto err = NEO::readZeInfoExperimentalProperties(parser, + experimentalPropertiesNode, + experimentalProperties, + "some_kernel", + errors, + warnings); + EXPECT_EQ(NEO::DecodeError::InvalidBinary, err); +} + +TEST(ReadZeExperimentalProperties, GivenYamlWithInvalidExperimentalPropertyEntryThenErrorIsReturned) { + NEO::ConstStringRef yaml = R"===(--- +kernels: + - name: some_kernel + experimental_properties: + - has_non_kernel_arg_load: 1 + has_non_kernel_arg_store: 0 + has_non_kernel_arg_invalid: 0 +... +)==="; + + std::string parserErrors; + std::string parserWarnings; + NEO::Yaml::YamlParser parser; + bool success = parser.parse(yaml, parserErrors, parserWarnings); + ASSERT_TRUE(success); + auto &experimentalPropertiesNode = *parser.findNodeWithKeyDfs("experimental_properties"); + std::string errors; + std::string warnings; + NEO::Elf::ZebinKernelMetadata::Types::Kernel::ExecutionEnv::ExperimentalPropertiesBaseT experimentalProperties; + auto err = NEO::readZeInfoExperimentalProperties(parser, + experimentalPropertiesNode, + experimentalProperties, + "some_kernel", + errors, + warnings); + EXPECT_EQ(NEO::DecodeError::InvalidBinary, err); +} + +TEST(PopulateKernelDescriptor, GivenValidExperimentalPropertiesThenPopulateKernelDescriptorSucceeds) { + NEO::ConstStringRef zeinfo = R"===( +kernels: + - name : some_kernel + execution_env: + simd_size: 8 + payload_arguments: + - arg_type: local_size + offset: 16 + size: 12 + experimental_properties: + - has_non_kernel_arg_load: 0 + has_non_kernel_arg_store: 0 + has_non_kernel_arg_atomic: 0 +... +)==="; + NEO::ProgramInfo programInfo; + ZebinTestData::ValidEmptyProgram zebin; + zebin.appendSection(NEO::Elf::SHT_PROGBITS, NEO::Elf::SectionsNamesZebin::textPrefix.str() + "some_kernel", {}); + std::string errors, warnings; + auto elf = NEO::Elf::decodeElf(zebin.storage, errors, warnings); + ASSERT_NE(nullptr, elf.elfFileHeader) << errors << " " << warnings; + + NEO::Yaml::YamlParser parser; + bool parseSuccess = parser.parse(zeinfo, errors, warnings); + ASSERT_TRUE(parseSuccess) << errors << " " << warnings; + + NEO::ZebinSections zebinSections; + auto extractErr = NEO::extractZebinSections(elf, zebinSections, errors, warnings); + ASSERT_EQ(NEO::DecodeError::Success, extractErr) << errors << " " << warnings; + + auto &kernelNode = *parser.createChildrenRange(*parser.findNodeWithKeyDfs("kernels")).begin(); + auto err = NEO::populateKernelDescriptor(programInfo, elf, zebinSections, parser, kernelNode, errors, warnings); + EXPECT_EQ(NEO::DecodeError::Success, err); +} + +TEST(PopulateKernelDescriptor, GivenErrorWhileReadingExperimentalPropertiesThenPopulateKernelDescriptorFails) { + NEO::ConstStringRef zeinfo = R"===( +kernels: + - name : some_kernel + execution_env: + simd_size: 8 + payload_arguments: + - arg_type: local_size + offset: 16 + size: 12 + experimental_properties: + - has_non_kernel_arg_load: true + has_non_kernel_arg_store: 0 + has_non_kernel_arg_atomic: 0 +... +)==="; + NEO::ProgramInfo programInfo; + ZebinTestData::ValidEmptyProgram zebin; + zebin.appendSection(NEO::Elf::SHT_PROGBITS, NEO::Elf::SectionsNamesZebin::textPrefix.str() + "some_kernel", {}); + std::string errors, warnings; + auto elf = NEO::Elf::decodeElf(zebin.storage, errors, warnings); + ASSERT_NE(nullptr, elf.elfFileHeader) << errors << " " << warnings; + + NEO::Yaml::YamlParser parser; + bool parseSuccess = parser.parse(zeinfo, errors, warnings); + ASSERT_TRUE(parseSuccess) << errors << " " << warnings; + + NEO::ZebinSections zebinSections; + auto extractErr = NEO::extractZebinSections(elf, zebinSections, errors, warnings); + ASSERT_EQ(NEO::DecodeError::Success, extractErr) << errors << " " << warnings; + + auto &kernelNode = *parser.createChildrenRange(*parser.findNodeWithKeyDfs("kernels")).begin(); + auto err = NEO::populateKernelDescriptor(programInfo, elf, zebinSections, parser, kernelNode, errors, warnings); + EXPECT_EQ(NEO::DecodeError::InvalidBinary, err); +} + TEST(ReadZeInfoExecutionEnvironment, GivenValidYamlEntriesThenSetProperMembers) { NEO::ConstStringRef yaml = R"===(--- kernels: