diff --git a/level_zero/core/source/cmdlist/cmdlist_imp.cpp b/level_zero/core/source/cmdlist/cmdlist_imp.cpp index bcb3fa674d..7978aca41d 100644 --- a/level_zero/core/source/cmdlist/cmdlist_imp.cpp +++ b/level_zero/core/source/cmdlist/cmdlist_imp.cpp @@ -53,16 +53,21 @@ ze_result_t CommandListImp::destroy() { this->stateBaseAddressTracking && this->cmdListHeapAddressModel == NEO::HeapAddressModel::PrivateHeaps) { - auto memoryManager = device->getNEODevice()->getMemoryManager(); + auto surfaceStateHeap = this->commandContainer.getIndirectHeap(NEO::HeapType::SURFACE_STATE); + if (surfaceStateHeap) { + auto heapAllocation = surfaceStateHeap->getGraphicsAllocation(); + NEO::WaitParams defaultWaitParams{false, false, NEO::TimeoutControls::maxTimeout}; - auto heapAllocation = this->commandContainer.getIndirectHeap(NEO::HeapType::SURFACE_STATE)->getGraphicsAllocation(); - for (auto &engine : memoryManager->getRegisteredEngines()) { - if (NEO::EngineHelpers::isComputeEngine(engine.getEngineType())) { - auto contextId = engine.osContext->getContextId(); - - if (heapAllocation->isUsedByOsContext(contextId)) { - engine.commandStreamReceiver->sendRenderStateCacheFlush(); - engine.commandStreamReceiver->waitForCompletionWithTimeout(NEO::WaitParams{false, false, NEO::TimeoutControls::maxTimeout}, engine.commandStreamReceiver->peekTaskCount()); + auto &deviceEngines = device->getNEODevice()->getMemoryManager()->getRegisteredEngines(); + for (auto &engine : deviceEngines) { + if (NEO::EngineHelpers::isComputeEngine(engine.getEngineType())) { + auto contextId = engine.osContext->getContextId(); + if (heapAllocation->isUsedByOsContext(contextId) && engine.osContext->isInitialized() && heapAllocation->getTaskCount(contextId) > 0) { + auto submissionStatus = engine.commandStreamReceiver->sendRenderStateCacheFlush(); + if (submissionStatus == NEO::SubmissionStatus::SUCCESS) { + engine.commandStreamReceiver->waitForCompletionWithTimeout(defaultWaitParams, engine.commandStreamReceiver->peekTaskCount()); + } + } } } } diff --git a/level_zero/core/test/unit_tests/sources/cmdlist/test_cmdlist_3.cpp b/level_zero/core/test/unit_tests/sources/cmdlist/test_cmdlist_3.cpp index fcd1c8b5b1..99e825ccb7 100644 --- a/level_zero/core/test/unit_tests/sources/cmdlist/test_cmdlist_3.cpp +++ b/level_zero/core/test/unit_tests/sources/cmdlist/test_cmdlist_3.cpp @@ -38,8 +38,11 @@ struct MemoryManagerCommandListCreateNegativeTest : public NEO::MockMemoryManage bool forceFailureInPrimaryAllocation = false; }; -struct CommandListCreateNegativeTest : public ::testing::Test { - void SetUp() override { +template +struct CommandListCreateNegativeFixture { + void setUp() { + DebugManager.flags.EnableStateBaseAddressTracking.set(stateBaseAddressTracking); + executionEnvironment = new NEO::ExecutionEnvironment(); executionEnvironment->prepareRootDeviceEnvironments(numRootDevices); for (uint32_t i = 0; i < numRootDevices; i++) { @@ -61,9 +64,11 @@ struct CommandListCreateNegativeTest : public ::testing::Test { device = driverHandle->devices[0]; } - void TearDown() override { + void tearDown() { } + DebugManagerStateRestore restorer; + NEO::ExecutionEnvironment *executionEnvironment = nullptr; std::unique_ptr> driverHandle; NEO::MockDevice *neoDevice = nullptr; @@ -72,6 +77,8 @@ struct CommandListCreateNegativeTest : public ::testing::Test { const uint32_t numRootDevices = 1u; }; +using CommandListCreateNegativeTest = Test>; + TEST_F(CommandListCreateNegativeTest, whenDeviceAllocationFailsDuringCommandListCreateThenAppropriateValueIsReturned) { ze_result_t returnValue; memoryManager->forceFailureInPrimaryAllocation = true; @@ -80,6 +87,23 @@ TEST_F(CommandListCreateNegativeTest, whenDeviceAllocationFailsDuringCommandList ASSERT_EQ(nullptr, commandList); } +using CommandListCreateNegativeStateBaseAddressTest = Test>; + +HWTEST2_F(CommandListCreateNegativeStateBaseAddressTest, + GivenStateBaseAddressTrackingWhenDeviceAllocationFailsDuringCommandListCreateThenCacheIsNotInvalidatedAndAppropriateValueIsReturned, + IsAtLeastSkl) { + auto &csr = neoDevice->getUltCommandStreamReceiver(); + auto &csrStream = csr.commandStream; + + ze_result_t returnValue; + memoryManager->forceFailureInPrimaryAllocation = true; + std::unique_ptr commandList(CommandList::create(productFamily, device, NEO::EngineGroupType::RenderCompute, 0u, returnValue)); + EXPECT_EQ(ZE_RESULT_ERROR_OUT_OF_DEVICE_MEMORY, returnValue); + ASSERT_EQ(nullptr, commandList); + + EXPECT_EQ(0u, csrStream.getUsed()); +} + TEST_F(CommandListCreateNegativeTest, whenDeviceAllocationFailsDuringCommandListImmediateCreateThenAppropriateValueIsReturned) { ze_result_t returnValue; const ze_command_queue_desc_t desc = {}; diff --git a/level_zero/core/test/unit_tests/sources/cmdlist/test_cmdlist_5.cpp b/level_zero/core/test/unit_tests/sources/cmdlist/test_cmdlist_5.cpp index f891c36b4e..ef4c0209a4 100644 --- a/level_zero/core/test/unit_tests/sources/cmdlist/test_cmdlist_5.cpp +++ b/level_zero/core/test/unit_tests/sources/cmdlist/test_cmdlist_5.cpp @@ -12,6 +12,7 @@ #include "shared/test/common/cmd_parse/gen_cmd_parse.h" #include "shared/test/common/helpers/unit_test_helper.h" #include "shared/test/common/libult/ult_command_stream_receiver.h" +#include "shared/test/common/mocks/mock_os_context.h" #include "shared/test/common/test_macros/hw_test.h" #include "level_zero/core/source/kernel/kernel_imp.h" @@ -2584,5 +2585,80 @@ HWTEST2_F(CommandListStateBaseAddressPrivateHeapTest, EXPECT_TRUE(NEO::UnitTestHelper::findStateCacheFlushPipeControl(csrStream)); } +HWTEST2_F(CommandListStateBaseAddressPrivateHeapTest, + givenCommandListUsingPrivateSurfaceHeapWhenOsContextNotInitializedAndCommandListDestroyedThenCsrDoNotDispatchesStateCacheFlush, + IsAtLeastSkl) { + auto &csr = neoDevice->getUltCommandStreamReceiver(); + EngineControl &engine = neoDevice->getDefaultEngine(); + static_cast(engine.osContext)->contextInitialized = false; + auto &csrStream = csr.commandStream; + + ze_result_t returnValue; + L0::ult::CommandList *cmdListObject = whiteboxCast(CommandList::create(productFamily, device, engineGroupType, 0u, returnValue)); + + ze_group_count_t groupCount{1, 1, 1}; + CmdListKernelLaunchParams launchParams = {}; + cmdListObject->appendLaunchKernel(kernel->toHandle(), &groupCount, nullptr, 0, nullptr, launchParams, false); + + returnValue = cmdListObject->close(); + EXPECT_EQ(ZE_RESULT_SUCCESS, returnValue); + + returnValue = cmdListObject->destroy(); + EXPECT_EQ(ZE_RESULT_SUCCESS, returnValue); + + EXPECT_EQ(0u, csrStream.getUsed()); +} + +HWTEST2_F(CommandListStateBaseAddressPrivateHeapTest, + givenCommandListUsingPrivateSurfaceHeapWhenTaskCountZeroAndCommandListDestroyedThenCsrDoNotDispatchesStateCacheFlush, + IsAtLeastSkl) { + auto &csr = neoDevice->getUltCommandStreamReceiver(); + auto &csrStream = csr.commandStream; + + ze_result_t returnValue; + L0::ult::CommandList *cmdListObject = whiteboxCast(CommandList::create(productFamily, device, engineGroupType, 0u, returnValue)); + + returnValue = cmdListObject->destroy(); + EXPECT_EQ(ZE_RESULT_SUCCESS, returnValue); + + cmdListObject = whiteboxCast(CommandList::create(productFamily, device, engineGroupType, 0u, returnValue)); + + returnValue = cmdListObject->destroy(); + EXPECT_EQ(ZE_RESULT_SUCCESS, returnValue); + + EXPECT_EQ(0u, csrStream.getUsed()); +} + +HWTEST2_F(CommandListStateBaseAddressPrivateHeapTest, + givenCommandListUsingPrivateSurfaceHeapWhenCommandListDestroyedAndCsrStateCacheFlushDispatchFailsThenWaitNotCalled, + IsAtLeastSkl) { + auto &csr = neoDevice->getUltCommandStreamReceiver(); + + ze_result_t returnValue; + L0::ult::CommandList *cmdListObject = whiteboxCast(CommandList::create(productFamily, device, engineGroupType, 0u, returnValue)); + + ze_group_count_t groupCount{1, 1, 1}; + CmdListKernelLaunchParams launchParams = {}; + cmdListObject->appendLaunchKernel(kernel->toHandle(), &groupCount, nullptr, 0, nullptr, launchParams, false); + + returnValue = cmdListObject->close(); + EXPECT_EQ(ZE_RESULT_SUCCESS, returnValue); + + auto cmdListHandle = cmdListObject->toHandle(); + returnValue = commandQueue->executeCommandLists(1, &cmdListHandle, nullptr, true); + EXPECT_EQ(ZE_RESULT_SUCCESS, returnValue); + + csr.callBaseSendRenderStateCacheFlush = false; + csr.flushReturnValue = SubmissionStatus::DEVICE_UNINITIALIZED; + csr.waitForCompletionWithTimeoutTaskCountCalled = 0; + + returnValue = cmdListObject->destroy(); + EXPECT_EQ(ZE_RESULT_SUCCESS, returnValue); + + EXPECT_EQ(0u, csr.waitForCompletionWithTimeoutTaskCountCalled); + + csr.callBaseSendRenderStateCacheFlush = true; +} + } // namespace ult } // namespace L0 diff --git a/level_zero/core/test/unit_tests/sources/cmdqueue/test_cmdqueue_enqueue_cmdlist.cpp b/level_zero/core/test/unit_tests/sources/cmdqueue/test_cmdqueue_enqueue_cmdlist.cpp index a999bbf56e..5c97eea738 100644 --- a/level_zero/core/test/unit_tests/sources/cmdqueue/test_cmdqueue_enqueue_cmdlist.cpp +++ b/level_zero/core/test/unit_tests/sources/cmdqueue/test_cmdqueue_enqueue_cmdlist.cpp @@ -44,6 +44,9 @@ struct CommandQueueExecuteCommandLists : public Test { } void TearDown() override { + auto tagAddress = device->getNEODevice()->getDefaultEngine().commandStreamReceiver->getTagAddress(); + *tagAddress = std::numeric_limits::max(); + for (auto i = 0u; i < numCommandLists; i++) { auto commandList = CommandList::fromHandle(commandLists[i]); commandList->destroy(); diff --git a/shared/test/common/libult/ult_command_stream_receiver.h b/shared/test/common/libult/ult_command_stream_receiver.h index 83cff63bab..05991bbfff 100644 --- a/shared/test/common/libult/ult_command_stream_receiver.h +++ b/shared/test/common/libult/ult_command_stream_receiver.h @@ -382,6 +382,13 @@ class UltCommandStreamReceiver : public CommandStreamReceiverHw, publ pollForCompletionCalled++; } + SubmissionStatus sendRenderStateCacheFlush() override { + if (callBaseSendRenderStateCacheFlush) { + return BaseClass::sendRenderStateCacheFlush(); + } + return *flushReturnValue; + } + std::vector aubCommentMessages; BatchBuffer latestFlushedBatchBuffer = {}; @@ -430,6 +437,7 @@ class UltCommandStreamReceiver : public CommandStreamReceiverHw, publ bool shouldFlushBatchedSubmissionsReturnSuccess = false; bool callBaseFillReusableAllocationsList = false; bool callBaseFlushBcsTask{true}; + bool callBaseSendRenderStateCacheFlush = true; }; } // namespace NEO diff --git a/shared/test/common/mocks/mock_os_context.h b/shared/test/common/mocks/mock_os_context.h index 1abf1282bb..8d4e2fa393 100644 --- a/shared/test/common/mocks/mock_os_context.h +++ b/shared/test/common/mocks/mock_os_context.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019-2022 Intel Corporation + * Copyright (C) 2019-2023 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -12,6 +12,7 @@ namespace NEO { class MockOsContext : public OsContext { public: using OsContext::checkDirectSubmissionSupportsEngine; + using OsContext::contextInitialized; using OsContext::debuggableContext; using OsContext::engineType; using OsContext::engineUsage;