Skip to content

Commit f6b9454

Browse files
fix: state cache invalidation WA for xe3
Related-To: NEO-16281, NEO-16405 Signed-off-by: Jaroslaw Warchulski <[email protected]>
1 parent 1ef4c2f commit f6b9454

27 files changed

+321
-41
lines changed

level_zero/core/source/cmdlist/cmdlist_hw_xehp_and_later.inl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,9 @@ ze_result_t CommandListCoreFamily<gfxCoreFamily>::appendLaunchKernelWithParams(K
573573
kernelWithAssertAppended = true;
574574
}
575575

576-
if (kernelImp->usesRayTracing()) {
576+
bool stateCacheInvalidationWaRequired = neoDevice->getReleaseHelper()->isStateCacheInvalidationWaRequired() && kernelImp->checkKernelContainsStatefulAccess();
577+
578+
if (stateCacheInvalidationWaRequired || kernelImp->usesRayTracing()) {
577579
NEO::PipeControlArgs args{};
578580
args.stateCacheInvalidationEnable = true;
579581
NEO::MemorySynchronizationCommands<GfxFamily>::addSingleBarrier(*commandContainer.getCommandStream(), args);

level_zero/core/test/unit_tests/sources/cmdlist/test_cmdlist_append_launch_kernel_1.cpp

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include "shared/source/command_container/command_encoder.h"
99
#include "shared/source/command_stream/scratch_space_controller.h"
10+
#include "shared/source/helpers/addressing_mode_helper.h"
1011
#include "shared/source/helpers/aligned_memory.h"
1112
#include "shared/source/helpers/api_specific_config.h"
1213
#include "shared/source/helpers/bindless_heaps_helper.h"
@@ -1780,5 +1781,99 @@ HWTEST2_F(CommandListAppendLaunchKernelMockModule,
17801781
EXPECT_NE(eventAllocationIt, cmdlistResidency.end());
17811782
}
17821783

1784+
HWTEST2_F(CommandListAppendLaunchKernelMockModule,
1785+
givenStateCacheInvalidationWaIsRequiredWhenTwoKernelsWithStatefulAccessAreAppendedThenPipeControlWithStateCacheInvalidationIsInsertedBetweenWalkers, IsAtLeastXeCore) {
1786+
using PIPE_CONTROL = typename FamilyType::PIPE_CONTROL;
1787+
using COMPUTE_WALKER = typename FamilyType::DefaultWalkerType;
1788+
1789+
static_cast<ModuleImp *>(module.get())->getTranslationUnit()->isGeneratedByIgc = true;
1790+
NEO::ArgDescriptor ptrArg(NEO::ArgDescriptor::argTPointer);
1791+
mockKernelImmData->kernelDescriptor->payloadMappings.explicitArgs.push_back(ptrArg);
1792+
commandList->cmdListHeapAddressModel = NEO::HeapAddressModel::privateHeaps;
1793+
1794+
ze_group_count_t groupCount{1, 1, 1};
1795+
ze_result_t returnValue;
1796+
CmdListKernelLaunchParams launchParams = {};
1797+
1798+
auto usedSpaceBefore = commandList->getCmdContainer().getCommandStream()->getUsed();
1799+
returnValue = commandList->appendLaunchKernel(kernel->toHandle(), groupCount, nullptr, 0, nullptr, launchParams);
1800+
ASSERT_EQ(ZE_RESULT_SUCCESS, returnValue);
1801+
1802+
returnValue = commandList->appendLaunchKernel(kernel->toHandle(), groupCount, nullptr, 0, nullptr, launchParams);
1803+
ASSERT_EQ(ZE_RESULT_SUCCESS, returnValue);
1804+
1805+
auto usedSpaceAfter = commandList->getCmdContainer().getCommandStream()->getUsed();
1806+
EXPECT_GT(usedSpaceAfter, usedSpaceBefore);
1807+
1808+
GenCmdList cmdList;
1809+
ASSERT_TRUE(FamilyType::Parse::parseCommandBuffer(
1810+
cmdList,
1811+
ptrOffset(commandList->getCmdContainer().getCommandStream()->getCpuBase(), usedSpaceBefore),
1812+
usedSpaceAfter - usedSpaceBefore));
1813+
1814+
auto walkers = findAll<COMPUTE_WALKER *>(cmdList.begin(), cmdList.end());
1815+
ASSERT_EQ(2u, walkers.size());
1816+
1817+
auto itorPC = findAll<PIPE_CONTROL *>(walkers[0], walkers[1]);
1818+
1819+
bool foundStateCacheInvalidation = false;
1820+
for (auto it : itorPC) {
1821+
auto pcCmd = genCmdCast<PIPE_CONTROL *>(*it);
1822+
if (pcCmd->getStateCacheInvalidationEnable()) {
1823+
foundStateCacheInvalidation = true;
1824+
break;
1825+
}
1826+
}
1827+
1828+
if (device->getNEODevice()->getReleaseHelper()->isStateCacheInvalidationWaRequired()) {
1829+
EXPECT_TRUE(foundStateCacheInvalidation);
1830+
} else {
1831+
EXPECT_FALSE(foundStateCacheInvalidation);
1832+
}
1833+
}
1834+
1835+
HWTEST2_F(CommandListAppendLaunchKernelMockModule,
1836+
givenStateCacheInvalidationWaIsRequiredWhenTwoKernelsWithoutStatefulAccessAreAppendedThenPipeControlWithStateCacheInvalidationIsNotInsertedBetweenWalkers, IsAtLeastXeCore) {
1837+
using PIPE_CONTROL = typename FamilyType::PIPE_CONTROL;
1838+
using COMPUTE_WALKER = typename FamilyType::DefaultWalkerType;
1839+
1840+
ze_group_count_t groupCount{1, 1, 1};
1841+
ze_result_t returnValue;
1842+
CmdListKernelLaunchParams launchParams = {};
1843+
1844+
auto usedSpaceBefore = commandList->getCmdContainer().getCommandStream()->getUsed();
1845+
1846+
returnValue = commandList->appendLaunchKernel(kernel->toHandle(), groupCount, nullptr, 0, nullptr, launchParams);
1847+
ASSERT_EQ(ZE_RESULT_SUCCESS, returnValue);
1848+
1849+
returnValue = commandList->appendLaunchKernel(kernel->toHandle(), groupCount, nullptr, 0, nullptr, launchParams);
1850+
ASSERT_EQ(ZE_RESULT_SUCCESS, returnValue);
1851+
1852+
auto usedSpaceAfter = commandList->getCmdContainer().getCommandStream()->getUsed();
1853+
EXPECT_GT(usedSpaceAfter, usedSpaceBefore);
1854+
1855+
GenCmdList cmdList;
1856+
ASSERT_TRUE(FamilyType::Parse::parseCommandBuffer(
1857+
cmdList,
1858+
ptrOffset(commandList->getCmdContainer().getCommandStream()->getCpuBase(), usedSpaceBefore),
1859+
usedSpaceAfter - usedSpaceBefore));
1860+
1861+
auto walkers = findAll<COMPUTE_WALKER *>(cmdList.begin(), cmdList.end());
1862+
ASSERT_EQ(2u, walkers.size());
1863+
1864+
auto itorPC = findAll<PIPE_CONTROL *>(walkers[0], walkers[1]);
1865+
1866+
bool foundStateCacheInvalidation = false;
1867+
for (auto it : itorPC) {
1868+
auto pcCmd = genCmdCast<PIPE_CONTROL *>(*it);
1869+
if (pcCmd->getStateCacheInvalidationEnable()) {
1870+
foundStateCacheInvalidation = true;
1871+
break;
1872+
}
1873+
}
1874+
1875+
EXPECT_FALSE(foundStateCacheInvalidation);
1876+
}
1877+
17831878
} // namespace ult
1784-
} // namespace L0
1879+
} // namespace L0

level_zero/core/test/unit_tests/sources/cmdlist/test_in_order_cmdlist_1.cpp

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4264,16 +4264,25 @@ HWCMDTEST_F(IGFX_XE_HP_CORE, InOrderCmdListTests, givenInOrderModeWhenProgrammin
42644264

42654265
ASSERT_NE(cmdList.end(), walkerItor);
42664266

4267-
auto pcItor = find<PIPE_CONTROL *>(walkerItor, cmdList.end());
4268-
ASSERT_NE(cmdList.end(), pcItor);
4267+
auto pcItors = findAll<PIPE_CONTROL *>(walkerItor, cmdList.end());
4268+
EXPECT_FALSE(pcItors.empty());
4269+
4270+
bool foundMatchingPipeControl = false;
4271+
for (auto pcItor : pcItors) {
4272+
auto pcCmd = genCmdCast<PIPE_CONTROL *>(*pcItor);
4273+
ASSERT_NE(nullptr, pcCmd);
4274+
4275+
if (pcCmd->getDcFlushEnable() == immCmdList->getDcFlushRequired(true) &&
4276+
UnitTestHelper<FamilyType>::getPipeControlHdcPipelineFlush(*pcCmd) &&
4277+
pcCmd->getUnTypedDataPortCacheFlush()) {
4278+
foundMatchingPipeControl = true;
4279+
break;
4280+
}
4281+
}
42694282

4270-
auto pcCmd = genCmdCast<PIPE_CONTROL *>(*pcItor);
4271-
ASSERT_NE(nullptr, pcCmd);
4272-
EXPECT_EQ(immCmdList->getDcFlushRequired(true), pcCmd->getDcFlushEnable());
4273-
EXPECT_TRUE(UnitTestHelper<FamilyType>::getPipeControlHdcPipelineFlush(*pcCmd));
4274-
EXPECT_TRUE(pcCmd->getUnTypedDataPortCacheFlush());
4283+
EXPECT_TRUE(foundMatchingPipeControl);
42754284

4276-
auto sdiItor = find<MI_STORE_DATA_IMM *>(pcItor, cmdList.end());
4285+
auto sdiItor = find<MI_STORE_DATA_IMM *>(walkerItor, cmdList.end());
42774286
ASSERT_NE(cmdList.end(), sdiItor);
42784287

42794288
auto sdiCmd = genCmdCast<MI_STORE_DATA_IMM *>(*sdiItor);
@@ -6609,15 +6618,25 @@ HWCMDTEST_F(IGFX_XE_HP_CORE, InOrderCmdListTests, givenInOrderModeWhenProgrammin
66096618
GenCmdList cmdList;
66106619
ASSERT_TRUE(FamilyType::Parse::parseCommandBuffer(cmdList, cmdStream->getCpuBase(), cmdStream->getUsed()));
66116620

6612-
auto cmdItor = find<PIPE_CONTROL *>(cmdList.begin(), cmdList.end());
6613-
ASSERT_NE(cmdList.end(), cmdItor);
6621+
auto pcItors = findAll<PIPE_CONTROL *>(cmdList.begin(), cmdList.end());
6622+
ASSERT_FALSE(pcItors.empty());
6623+
auto cmdItor = pcItors[0];
66146624

6615-
auto pcCmd = genCmdCast<PIPE_CONTROL *>(*cmdItor);
6616-
ASSERT_NE(nullptr, pcCmd);
6625+
bool foundMatchingPipeControl = false;
6626+
for (auto pcItor : pcItors) {
6627+
auto pcCmd = genCmdCast<PIPE_CONTROL *>(*pcItor);
6628+
ASSERT_NE(nullptr, pcCmd);
66176629

6618-
EXPECT_EQ(immCmdList->getDcFlushRequired(true), pcCmd->getDcFlushEnable());
6619-
EXPECT_TRUE(UnitTestHelper<FamilyType>::getPipeControlHdcPipelineFlush(*pcCmd));
6620-
EXPECT_TRUE(pcCmd->getUnTypedDataPortCacheFlush());
6630+
if (pcCmd->getDcFlushEnable() == immCmdList->getDcFlushRequired(true) &&
6631+
UnitTestHelper<FamilyType>::getPipeControlHdcPipelineFlush(*pcCmd) &&
6632+
pcCmd->getUnTypedDataPortCacheFlush()) {
6633+
foundMatchingPipeControl = true;
6634+
cmdItor = pcItor;
6635+
break;
6636+
}
6637+
}
6638+
6639+
EXPECT_TRUE(foundMatchingPipeControl);
66216640

66226641
auto sdiCmd = genCmdCast<MI_STORE_DATA_IMM *>(*(++cmdItor));
66236642

level_zero/core/test/unit_tests/sources/cmdlist/test_in_order_cmdlist_2.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "shared/source/gmm_helper/gmm_helper.h"
1010
#include "shared/source/helpers/compiler_product_helper.h"
1111
#include "shared/source/memory_manager/internal_allocation_storage.h"
12+
#include "shared/source/release_helper/release_helper.h"
1213
#include "shared/test/common/cmd_parse/hw_parse.h"
1314
#include "shared/test/common/helpers/relaxed_ordering_commands_helper.h"
1415
#include "shared/test/common/libult/ult_command_stream_receiver.h"
@@ -4073,6 +4074,9 @@ HWTEST2_F(MultiTileInOrderCmdListTests, givenMultiTileInOrderModeWhenProgramming
40734074
auto pcItors = findAll<PIPE_CONTROL *>(cmdList.begin(), cmdList.end());
40744075
ASSERT_NE(pcItors.size(), 0u);
40754076
auto pcCmd = genCmdCast<PIPE_CONTROL *>(*pcItors.back());
4077+
if (device->getNEODevice()->getReleaseHelper()->isStateCacheInvalidationWaRequired()) {
4078+
pcCmd = genCmdCast<PIPE_CONTROL *>(*pcItors.front());
4079+
}
40764080

40774081
uint64_t address = pcCmd->getAddressHigh();
40784082
address <<= 32;

opencl/source/command_queue/hardware_interface_xehp_and_later.inl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@
1111
#include "shared/source/command_stream/scratch_space_controller.h"
1212
#include "shared/source/debug_settings/debug_settings_manager.h"
1313
#include "shared/source/device/device.h"
14+
#include "shared/source/helpers/addressing_mode_helper.h"
1415
#include "shared/source/helpers/definitions/command_encoder_args.h"
1516
#include "shared/source/helpers/engine_node_helper.h"
1617
#include "shared/source/os_interface/os_context.h"
1718
#include "shared/source/os_interface/os_interface.h"
19+
#include "shared/source/release_helper/release_helper.h"
1820
#include "shared/source/utilities/tag_allocator.h"
1921

2022
#include "opencl/source/command_queue/hardware_interface_base.inl"
@@ -39,6 +41,13 @@ inline void HardwareInterface<GfxFamily>::dispatchWorkarounds(
3941
CommandQueue &commandQueue,
4042
Kernel &kernel,
4143
const bool &enable) {
44+
bool containsStatefulAccess = AddressingModeHelper::containsStatefulAccess(kernel.getDescriptor(), false);
45+
bool stateCacheInvalidationWaRequired = commandQueue.getDevice().getReleaseHelper()->isStateCacheInvalidationWaRequired() && containsStatefulAccess;
46+
if (!enable && stateCacheInvalidationWaRequired) {
47+
PipeControlArgs args{};
48+
args.stateCacheInvalidationEnable = true;
49+
MemorySynchronizationCommands<GfxFamily>::addSingleBarrier(*commandStream, args);
50+
}
4251
}
4352

4453
template <typename GfxFamily>

opencl/test/unit_test/command_queue/enqueue_kernel_two_walker_ioq_tests.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77

88
#include "shared/source/helpers/gfx_core_helper.h"
9+
#include "shared/source/release_helper/release_helper.h"
910
#include "shared/test/common/helpers/unit_test_helper.h"
1011
#include "shared/test/common/libult/ult_command_stream_receiver.h"
1112
#include "shared/test/common/test_macros/test.h"
@@ -69,3 +70,58 @@ HWTEST_F(IOQWithTwoWalkers, GivenTwoCommandQueuesWhenEnqueuingKernelThenOnePipeC
6970
EXPECT_EQ(commandStreamReceiver.getTagAllocation()->getGpuAddress(), NEO::UnitTestHelper<FamilyType>::getPipeControlPostSyncAddress(*pipeControl));
7071
EXPECT_EQ(commandStreamReceiver.heaplessStateInitialized ? 2u : 1u, pipeControl->getImmediateData());
7172
}
73+
74+
HWTEST_F(IOQWithTwoWalkers, GivenStateCacheInvalidationWaIsRequiredWhenTwoKernelsWithStatefulAccessAreEnqueuedThenPipeControlWithStateCacheInvalidationIsInsertedBetweenWalkers) {
75+
NEO::ArgDescriptor ptrArg(NEO::ArgDescriptor::argTPointer);
76+
auto &explicitArgs = const_cast<KernelDescriptor &>(pKernel->getDescriptor()).payloadMappings.explicitArgs;
77+
explicitArgs.clear();
78+
explicitArgs.push_back(ptrArg);
79+
enqueueTwoKernels<FamilyType>();
80+
81+
typedef typename FamilyType::PIPE_CONTROL PIPE_CONTROL;
82+
using COMPUTE_WALKER = typename FamilyType::DefaultWalkerType;
83+
84+
auto walkers = findAll<COMPUTE_WALKER *>(cmdList.begin(), cmdList.end());
85+
ASSERT_EQ(2u, walkers.size());
86+
87+
auto itorPC = findAll<PIPE_CONTROL *>(walkers[0], walkers[1]);
88+
89+
bool foundStateCacheInvalidation = false;
90+
for (auto it : itorPC) {
91+
auto pcCmd = genCmdCast<PIPE_CONTROL *>(*it);
92+
if (pcCmd->getStateCacheInvalidationEnable()) {
93+
foundStateCacheInvalidation = true;
94+
break;
95+
}
96+
}
97+
98+
auto releaseHelper = pClDevice->getDevice().getReleaseHelper();
99+
if (releaseHelper && releaseHelper->isStateCacheInvalidationWaRequired()) {
100+
EXPECT_TRUE(foundStateCacheInvalidation);
101+
} else {
102+
EXPECT_FALSE(foundStateCacheInvalidation);
103+
}
104+
}
105+
106+
HWTEST_F(IOQWithTwoWalkers, GivenStateCacheInvalidationWaIsRequiredWhenTwoKernelsWithoutStatefulAccessAreEnqueuedThenPipeControlWithStateCacheInvalidationIsNotInsertedBetweenWalkers) {
107+
enqueueTwoKernels<FamilyType>();
108+
109+
typedef typename FamilyType::PIPE_CONTROL PIPE_CONTROL;
110+
using COMPUTE_WALKER = typename FamilyType::DefaultWalkerType;
111+
112+
auto walkers = findAll<COMPUTE_WALKER *>(cmdList.begin(), cmdList.end());
113+
ASSERT_EQ(2u, walkers.size());
114+
115+
auto itorPC = findAll<PIPE_CONTROL *>(walkers[0], walkers[1]);
116+
117+
bool foundStateCacheInvalidation = false;
118+
for (auto it : itorPC) {
119+
auto pcCmd = genCmdCast<PIPE_CONTROL *>(*it);
120+
if (pcCmd->getStateCacheInvalidationEnable()) {
121+
foundStateCacheInvalidation = true;
122+
break;
123+
}
124+
}
125+
126+
EXPECT_FALSE(foundStateCacheInvalidation);
127+
}

opencl/test/unit_test/command_stream/command_stream_receiver_flush_task_1_tests.cpp

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "shared/source/helpers/preamble.h"
1313
#include "shared/source/os_interface/os_context.h"
1414
#include "shared/source/os_interface/product_helper.h"
15+
#include "shared/source/release_helper/release_helper.h"
1516
#include "shared/test/common/helpers/debug_manager_state_restore.h"
1617
#include "shared/test/common/helpers/dispatch_flags_helper.h"
1718
#include "shared/test/common/helpers/ult_gfx_core_helper.h"
@@ -1251,17 +1252,22 @@ HWTEST_F(CommandStreamReceiverFlushTaskTests, GivenBlockedKernelRequiringDCFlush
12511252
// Parse command list
12521253
parseCommands<FamilyType>(commandStreamTask, 0);
12531254

1254-
auto itorPC = find<PIPE_CONTROL *>(cmdList.begin(), cmdList.end());
1255-
EXPECT_NE(cmdList.end(), itorPC);
1256-
if (UnitTestHelper<FamilyType>::isPipeControlWArequired(pDevice->getHardwareInfo())) {
1257-
itorPC++;
1258-
itorPC = find<PIPE_CONTROL *>(itorPC, cmdList.end());
1259-
EXPECT_NE(cmdList.end(), itorPC);
1255+
auto pcItors = findAll<PIPE_CONTROL *>(cmdList.begin(), cmdList.end());
1256+
EXPECT_FALSE(pcItors.empty());
1257+
1258+
bool foundMatchingPipeControl = false;
1259+
for (auto pcItor : pcItors) {
1260+
auto pcCmd = genCmdCast<PIPE_CONTROL *>(*pcItor);
1261+
ASSERT_NE(nullptr, pcCmd);
1262+
1263+
// Verify that the dcFlushEnabled bit is set in PC
1264+
if (MemorySynchronizationCommands<FamilyType>::getDcFlushEnable(true, pDevice->getRootDeviceEnvironment()) == pcCmd->getDcFlushEnable()) {
1265+
foundMatchingPipeControl = true;
1266+
break;
1267+
}
12601268
}
12611269

1262-
// Verify that the dcFlushEnabled bit is set in PC
1263-
auto pCmdWA = reinterpret_cast<PIPE_CONTROL *>(*itorPC);
1264-
EXPECT_EQ(MemorySynchronizationCommands<FamilyType>::getDcFlushEnable(true, pDevice->getRootDeviceEnvironment()), pCmdWA->getDcFlushEnable());
1270+
EXPECT_TRUE(foundMatchingPipeControl);
12651271

12661272
buffer->release();
12671273
}

shared/source/release_helper/release_helper.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ class ReleaseHelper {
6969
virtual uint32_t adjustMaxThreadsPerEuCount(uint32_t maxThreadsPerEuCount, uint32_t grfCount) const = 0;
7070
virtual bool shouldQueryPeerAccess() const = 0;
7171
virtual bool isSingleDispatchRequiredForMultiCCS() const = 0;
72+
virtual bool isStateCacheInvalidationWaRequired() const = 0;
7273

7374
protected:
7475
ReleaseHelper(HardwareIpVersion hardwareIpVersion) : hardwareIpVersion(hardwareIpVersion) {}
@@ -117,6 +118,7 @@ class ReleaseHelperHw : public ReleaseHelper {
117118
uint32_t adjustMaxThreadsPerEuCount(uint32_t maxThreadsPerEuCount, uint32_t grfCount) const override;
118119
bool shouldQueryPeerAccess() const override;
119120
bool isSingleDispatchRequiredForMultiCCS() const override;
121+
bool isStateCacheInvalidationWaRequired() const override;
120122

121123
protected:
122124
ReleaseHelperHw(HardwareIpVersion hardwareIpVersion) : ReleaseHelper(hardwareIpVersion) {}

shared/source/release_helper/release_helper_base.inl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,4 +191,9 @@ bool ReleaseHelperHw<releaseType>::isSingleDispatchRequiredForMultiCCS() const {
191191
return false;
192192
}
193193

194+
template <ReleaseType releaseType>
195+
bool ReleaseHelperHw<releaseType>::isStateCacheInvalidationWaRequired() const {
196+
return false;
197+
}
198+
194199
} // namespace NEO

shared/source/release_helper/release_helper_common_xe3_lpg.inl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,9 @@ const SizeToPreferredSlmValueArray &ReleaseHelperHw<release>::getSizeToPreferred
3333
return sizeToPreferredSlmValue;
3434
}
3535

36+
template <>
37+
bool ReleaseHelperHw<release>::isStateCacheInvalidationWaRequired() const {
38+
return true;
39+
}
40+
3641
} // namespace NEO

0 commit comments

Comments
 (0)