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 <lisanna.dettwyler@intel.com>
This commit is contained in:
Lisanna Dettwyler
2022-02-28 12:01:34 -08:00
committed by Compute-Runtime-Automation
parent 8f5dd3cff5
commit e6e6ae2d2b
2 changed files with 74 additions and 4 deletions

View File

@ -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);

View File

@ -1050,6 +1050,75 @@ TEST_F(DeviceCreateCommandQueueTest, givenLowPriorityDescWhenCreateCommandQueueI
commandQueue->destroy();
}
TEST_F(DeviceCreateCommandQueueTest, givenCopyOrdinalWhenCreateCommandQueueWithLowPriorityDescIsCalledThenCopyCsrIsAssigned) {
auto copyCsr = std::unique_ptr<NEO::CommandStreamReceiver>(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<NEO::CommandStreamReceiver>(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<std::vector<NEO::EngineControl> &>(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<ze_command_queue_group_properties_t> 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<CommandQueueImp *>(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);