From e6e6ae2d2b5d7fab2980abe165a5c677e56ab3ef Mon Sep 17 00:00:00 2001 From: Lisanna Dettwyler Date: Mon, 28 Feb 2022 12:01:34 -0800 Subject: [PATCH] Don't use low-priority CSR for copy-only cmdq getCsrForLowPriority will always return a CSR with a compute engine regardless of the ordinal used. When a copy-only ordinal is used to create a command queue or command list, batch buffers are written using BCS style commands rather than CCS style. This caused BCS commands to be submitted to a low-priority compute engine which was invalid. This patch ensures a copy engine is selected when a copy-only ordinal is used even if ZE_COMMAND_QUEUE_PRIORITY_PRIORITY_LOW is specified. Related-To: LOCI-2980 Signed-off-by: Lisanna Dettwyler --- level_zero/core/source/device/device_imp.cpp | 9 +-- .../sources/cmdqueue/test_cmdqueue_1.cpp | 69 +++++++++++++++++++ 2 files changed, 74 insertions(+), 4 deletions(-) diff --git a/level_zero/core/source/device/device_imp.cpp b/level_zero/core/source/device/device_imp.cpp index cd2e9961a3..c968ee5c68 100644 --- a/level_zero/core/source/device/device_imp.cpp +++ b/level_zero/core/source/device/device_imp.cpp @@ -179,7 +179,11 @@ ze_result_t DeviceImp::createCommandQueue(const ze_command_queue_desc_t *desc, if (desc->ordinal >= engineGroups.size()) { return ZE_RESULT_ERROR_INVALID_ARGUMENT; } - if (desc->priority == ZE_COMMAND_QUEUE_PRIORITY_PRIORITY_LOW) { + + auto &hwHelper = NEO::HwHelper::get(platform.eRenderCoreFamily); + bool isCopyOnly = hwHelper.isCopyOnlyEngineType(engineGroups[desc->ordinal].engineGroupType); + + if (desc->priority == ZE_COMMAND_QUEUE_PRIORITY_PRIORITY_LOW && !isCopyOnly) { getCsrForLowPriority(&csr); } else { auto ret = getCsrForOrdinalAndIndex(&csr, desc->ordinal, desc->index); @@ -190,9 +194,6 @@ ze_result_t DeviceImp::createCommandQueue(const ze_command_queue_desc_t *desc, UNRECOVERABLE_IF(csr == nullptr); - auto &hwHelper = NEO::HwHelper::get(platform.eRenderCoreFamily); - bool isCopyOnly = hwHelper.isCopyOnlyEngineType(engineGroups[desc->ordinal].engineGroupType); - ze_result_t returnValue = ZE_RESULT_SUCCESS; *commandQueue = CommandQueue::create(platform.eProductFamily, this, csr, desc, isCopyOnly, false, returnValue); diff --git a/level_zero/core/test/unit_tests/sources/cmdqueue/test_cmdqueue_1.cpp b/level_zero/core/test/unit_tests/sources/cmdqueue/test_cmdqueue_1.cpp index ca3531348a..a3451beb8b 100644 --- a/level_zero/core/test/unit_tests/sources/cmdqueue/test_cmdqueue_1.cpp +++ b/level_zero/core/test/unit_tests/sources/cmdqueue/test_cmdqueue_1.cpp @@ -1050,6 +1050,75 @@ TEST_F(DeviceCreateCommandQueueTest, givenLowPriorityDescWhenCreateCommandQueueI commandQueue->destroy(); } +TEST_F(DeviceCreateCommandQueueTest, givenCopyOrdinalWhenCreateCommandQueueWithLowPriorityDescIsCalledThenCopyCsrIsAssigned) { + auto copyCsr = std::unique_ptr(neoDevice->createCommandStreamReceiver()); + EngineDescriptor copyEngineDescriptor({aub_stream::ENGINE_BCS, EngineUsage::Regular}, neoDevice->getDeviceBitfield(), neoDevice->getPreemptionMode(), false, false); + auto copyOsContext = neoDevice->getExecutionEnvironment()->memoryManager->createAndRegisterOsContext(copyCsr.get(), copyEngineDescriptor); + copyCsr->setupContext(*copyOsContext); + + auto computeCsr = std::unique_ptr(neoDevice->createCommandStreamReceiver()); + EngineDescriptor computeEngineDescriptor({aub_stream::ENGINE_CCS, EngineUsage::LowPriority}, neoDevice->getDeviceBitfield(), neoDevice->getPreemptionMode(), false, false); + auto computeOsContext = neoDevice->getExecutionEnvironment()->memoryManager->createAndRegisterOsContext(computeCsr.get(), computeEngineDescriptor); + computeCsr->setupContext(*computeOsContext); + + auto &engineGroups = neoDevice->getRegularEngineGroups(); + engineGroups.clear(); + + auto &allEngines = const_cast &>(neoDevice->getAllEngines()); + allEngines.clear(); + + engineGroups.push_back(NEO::Device::EngineGroupT{}); + engineGroups.back().engineGroupType = EngineGroupType::Copy; + engineGroups.back().engines.resize(1); + engineGroups.back().engines[0].commandStreamReceiver = copyCsr.get(); + EngineControl copyEngine{copyCsr.get(), copyOsContext}; + allEngines.push_back(copyEngine); + + engineGroups.push_back(NEO::Device::EngineGroupT{}); + engineGroups.back().engineGroupType = EngineGroupType::Compute; + engineGroups.back().engines.resize(1); + engineGroups.back().engines[0].commandStreamReceiver = computeCsr.get(); + EngineControl computeEngine{computeCsr.get(), computeOsContext}; + allEngines.push_back(computeEngine); + + uint32_t count = 0u; + ze_result_t res = device->getCommandQueueGroupProperties(&count, nullptr); + EXPECT_EQ(ZE_RESULT_SUCCESS, res); + EXPECT_GT(count, 0u); + + std::vector properties(count); + res = device->getCommandQueueGroupProperties(&count, properties.data()); + EXPECT_EQ(ZE_RESULT_SUCCESS, res); + + uint32_t ordinal = 0u; + for (ordinal = 0u; ordinal < count; ordinal++) { + if ((properties[ordinal].flags & ZE_COMMAND_QUEUE_GROUP_PROPERTY_FLAG_COPY) && + !(properties[ordinal].flags & ZE_COMMAND_QUEUE_GROUP_PROPERTY_FLAG_COMPUTE)) { + if (properties[ordinal].numQueues == 0) + continue; + break; + } + } + EXPECT_LT(ordinal, count); + + ze_command_queue_desc_t desc{}; + desc.ordinal = ordinal; + desc.index = 0u; + desc.priority = ZE_COMMAND_QUEUE_PRIORITY_PRIORITY_LOW; + + ze_command_queue_handle_t commandQueueHandle = {}; + + res = device->createCommandQueue(&desc, &commandQueueHandle); + EXPECT_EQ(ZE_RESULT_SUCCESS, res); + auto commandQueue = static_cast(L0::CommandQueue::fromHandle(commandQueueHandle)); + EXPECT_NE(commandQueue, nullptr); + EXPECT_EQ(copyCsr.get(), commandQueue->getCsr()); + commandQueue->destroy(); + + engineGroups.clear(); + allEngines.clear(); +} + struct DeferredContextCreationDeviceCreateCommandQueueTest : DeviceCreateCommandQueueTest { void SetUp() override { DebugManager.flags.DeferOsContextInitialization.set(1);