Skip to content

Commit 88cccaf

Browse files
feature: add support for ForceBcsEngineIndex flag 2
Related-To: NEO-8356 Signed-off-by: Dunajski, Bartosz <[email protected]>
1 parent 829e5ba commit 88cccaf

File tree

4 files changed

+319
-0
lines changed

4 files changed

+319
-0
lines changed

level_zero/core/source/device/device_imp.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1526,6 +1526,41 @@ ze_result_t DeviceImp::getCsrForOrdinalAndIndex(NEO::CommandStreamReceiver **csr
15261526
return ZE_RESULT_ERROR_INVALID_ARGUMENT;
15271527
}
15281528

1529+
if ((NEO::DebugManager.flags.ForceBcsEngineIndex.get() != -1) && NEO::EngineHelper::isCopyOnlyEngineType(getEngineGroupTypeForOrdinal(ordinal))) {
1530+
index = static_cast<uint32_t>(NEO::DebugManager.flags.ForceBcsEngineIndex.get());
1531+
1532+
constexpr uint32_t invalidOrdinal = std::numeric_limits<uint32_t>::max();
1533+
1534+
auto findOrdinal = [&](NEO::EngineGroupType type) -> uint32_t {
1535+
bool subDeviceCopyEngines = (ordinal >= numEngineGroups);
1536+
auto &lookupGroup = subDeviceCopyEngines ? this->subDeviceCopyEngineGroups : engineGroups;
1537+
1538+
uint32_t ordinal = invalidOrdinal;
1539+
1540+
for (uint32_t i = 0; i < lookupGroup.size(); i++) {
1541+
if (lookupGroup[i].engineGroupType == type) {
1542+
ordinal = (i + (subDeviceCopyEngines ? numEngineGroups : 0));
1543+
break;
1544+
}
1545+
}
1546+
1547+
return ordinal;
1548+
};
1549+
1550+
if (index == 0 && getEngineGroupTypeForOrdinal(ordinal) != NEO::EngineGroupType::Copy) {
1551+
ordinal = findOrdinal(NEO::EngineGroupType::Copy);
1552+
} else if (index > 0) {
1553+
if (getEngineGroupTypeForOrdinal(ordinal) != NEO::EngineGroupType::LinkedCopy) {
1554+
ordinal = findOrdinal(NEO::EngineGroupType::LinkedCopy);
1555+
}
1556+
index--;
1557+
}
1558+
1559+
if (ordinal == invalidOrdinal) {
1560+
return ZE_RESULT_ERROR_INVALID_ARGUMENT;
1561+
}
1562+
}
1563+
15291564
if (ordinal < numEngineGroups) {
15301565
auto &engines = engineGroups[ordinal].engines;
15311566
if (index >= engines.size()) {

level_zero/core/test/unit_tests/mocks/mock_device.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ struct MockDeviceImp : public L0::DeviceImp {
105105
using Base::getNEODevice;
106106
using Base::implicitScalingCapable;
107107
using Base::neoDevice;
108+
using Base::subDeviceCopyEngineGroups;
108109

109110
MockDeviceImp(NEO::Device *device, NEO::ExecutionEnvironment *execEnv) {
110111
device->incRefInternal();

level_zero/core/test/unit_tests/xe_hpc_core/test_cmdqueue_xe_hpc_core.cpp

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,190 @@ HWTEST2_F(CommandQueueCommandsXeHpc, givenCommandQueueWhenExecutingCommandListsF
117117
commandQueue->destroy();
118118
}
119119

120+
HWTEST2_F(CommandQueueCommandsXeHpc, givenDebugFlagWithLinkedEngineSetWhenCreatingCommandQueueThenOverrideEngineIndex, IsXeHpcCore) {
121+
DebugManagerStateRestore restore;
122+
const uint32_t newIndex = 2;
123+
DebugManager.flags.ForceBcsEngineIndex.set(newIndex);
124+
ze_result_t returnValue;
125+
auto hwInfo = *NEO::defaultHwInfo;
126+
hwInfo.featureTable.ftrBcsInfo = 0b111111111;
127+
hwInfo.capabilityTable.blitterOperationsSupported = true;
128+
129+
auto testNeoDevice = NEO::MockDevice::createWithNewExecutionEnvironment<NEO::MockDevice>(&hwInfo);
130+
131+
auto testL0Device = std::unique_ptr<L0::Device>(L0::Device::create(driverHandle.get(), testNeoDevice, false, &returnValue));
132+
133+
auto &engineGroups = testNeoDevice->getRegularEngineGroups();
134+
135+
uint32_t expectedCopyOrdinal = 0;
136+
for (uint32_t i = 0; i < engineGroups.size(); i++) {
137+
if (engineGroups[i].engineGroupType == EngineGroupType::LinkedCopy) {
138+
expectedCopyOrdinal = i;
139+
break;
140+
}
141+
}
142+
143+
bool queueCreated = false;
144+
bool hasMultiInstancedEngine = false;
145+
for (uint32_t ordinal = 0; ordinal < engineGroups.size(); ordinal++) {
146+
for (uint32_t index = 0; index < engineGroups[ordinal].engines.size(); index++) {
147+
bool copyOrdinal = NEO::EngineHelper::isCopyOnlyEngineType(engineGroups[ordinal].engineGroupType);
148+
if (engineGroups[ordinal].engines.size() > 1 && copyOrdinal) {
149+
hasMultiInstancedEngine = true;
150+
}
151+
152+
ze_command_queue_handle_t commandQueue = {};
153+
154+
ze_command_queue_desc_t desc = {};
155+
desc.ordinal = ordinal;
156+
desc.index = index;
157+
ze_result_t res = context->createCommandQueue(testL0Device.get(), &desc, &commandQueue);
158+
159+
EXPECT_EQ(ZE_RESULT_SUCCESS, res);
160+
EXPECT_NE(nullptr, commandQueue);
161+
162+
auto queue = whiteboxCast(L0::CommandQueue::fromHandle(commandQueue));
163+
164+
if (copyOrdinal) {
165+
EXPECT_EQ(engineGroups[expectedCopyOrdinal].engines[newIndex - 1].commandStreamReceiver, queue->csr);
166+
queueCreated = true;
167+
} else {
168+
EXPECT_EQ(engineGroups[ordinal].engines[index].commandStreamReceiver, queue->csr);
169+
}
170+
171+
queue->destroy();
172+
}
173+
}
174+
175+
EXPECT_EQ(hasMultiInstancedEngine, queueCreated);
176+
}
177+
178+
HWTEST2_F(CommandQueueCommandsXeHpc, givenDebugFlagWithInvalidIndexSetWhenCreatingCommandQueueThenReturnError, IsXeHpcCore) {
179+
DebugManagerStateRestore restore;
180+
const uint32_t newIndex = 999;
181+
DebugManager.flags.ForceBcsEngineIndex.set(newIndex);
182+
ze_result_t returnValue;
183+
auto hwInfo = *NEO::defaultHwInfo;
184+
hwInfo.featureTable.ftrBcsInfo = 0b111111111;
185+
hwInfo.capabilityTable.blitterOperationsSupported = true;
186+
187+
auto testNeoDevice = NEO::MockDevice::createWithNewExecutionEnvironment<NEO::MockDevice>(&hwInfo);
188+
189+
auto testL0Device = std::unique_ptr<L0::Device>(L0::Device::create(driverHandle.get(), testNeoDevice, false, &returnValue));
190+
191+
auto &engineGroups = testNeoDevice->getRegularEngineGroups();
192+
193+
uint32_t expectedCopyOrdinal = 0;
194+
for (uint32_t i = 0; i < engineGroups.size(); i++) {
195+
if (engineGroups[i].engineGroupType == EngineGroupType::LinkedCopy) {
196+
expectedCopyOrdinal = i;
197+
break;
198+
}
199+
}
200+
201+
ze_command_queue_handle_t commandQueue = {};
202+
203+
ze_command_queue_desc_t desc = {};
204+
desc.ordinal = expectedCopyOrdinal;
205+
desc.index = 0;
206+
ze_result_t res = context->createCommandQueue(testL0Device.get(), &desc, &commandQueue);
207+
208+
EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, res);
209+
EXPECT_EQ(nullptr, commandQueue);
210+
}
211+
212+
HWTEST2_F(CommandQueueCommandsXeHpc, givenDebugFlagWithNonExistingIndexSetWhenCreatingCommandQueueThenReturnError, IsXeHpcCore) {
213+
DebugManagerStateRestore restore;
214+
const uint32_t newIndex = 1;
215+
DebugManager.flags.ForceBcsEngineIndex.set(newIndex);
216+
ze_result_t returnValue;
217+
auto hwInfo = *NEO::defaultHwInfo;
218+
hwInfo.featureTable.ftrBcsInfo = 1;
219+
hwInfo.capabilityTable.blitterOperationsSupported = true;
220+
221+
auto testNeoDevice = NEO::MockDevice::createWithNewExecutionEnvironment<NEO::MockDevice>(&hwInfo);
222+
223+
auto testL0Device = std::unique_ptr<L0::Device>(L0::Device::create(driverHandle.get(), testNeoDevice, false, &returnValue));
224+
225+
auto &engineGroups = testNeoDevice->getRegularEngineGroups();
226+
227+
uint32_t expectedCopyOrdinal = 0;
228+
for (uint32_t i = 0; i < engineGroups.size(); i++) {
229+
if (engineGroups[i].engineGroupType == EngineGroupType::Copy) {
230+
expectedCopyOrdinal = i;
231+
break;
232+
}
233+
}
234+
235+
ze_command_queue_handle_t commandQueue = {};
236+
237+
ze_command_queue_desc_t desc = {};
238+
desc.ordinal = expectedCopyOrdinal;
239+
desc.index = 0;
240+
ze_result_t res = context->createCommandQueue(testL0Device.get(), &desc, &commandQueue);
241+
242+
EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, res);
243+
EXPECT_EQ(nullptr, commandQueue);
244+
}
245+
246+
HWTEST2_F(CommandQueueCommandsXeHpc, givenDebugFlagWithMainEngineSetWhenCreatingCommandQueueThenOverrideEngineIndex, IsXeHpcCore) {
247+
DebugManagerStateRestore restore;
248+
const uint32_t newIndex = 0;
249+
DebugManager.flags.ForceBcsEngineIndex.set(newIndex);
250+
ze_result_t returnValue;
251+
auto hwInfo = *NEO::defaultHwInfo;
252+
hwInfo.featureTable.ftrBcsInfo = 0b111111111;
253+
hwInfo.capabilityTable.blitterOperationsSupported = true;
254+
255+
auto testNeoDevice = NEO::MockDevice::createWithNewExecutionEnvironment<NEO::MockDevice>(&hwInfo);
256+
257+
auto testL0Device = std::unique_ptr<L0::Device>(L0::Device::create(driverHandle.get(), testNeoDevice, false, &returnValue));
258+
259+
auto &engineGroups = testNeoDevice->getRegularEngineGroups();
260+
261+
uint32_t expectedCopyOrdinal = 0;
262+
for (uint32_t i = 0; i < engineGroups.size(); i++) {
263+
if (engineGroups[i].engineGroupType == EngineGroupType::Copy) {
264+
expectedCopyOrdinal = i;
265+
break;
266+
}
267+
}
268+
269+
bool queueCreated = false;
270+
bool hasMultiInstancedEngine = false;
271+
for (uint32_t ordinal = 0; ordinal < engineGroups.size(); ordinal++) {
272+
for (uint32_t index = 0; index < engineGroups[ordinal].engines.size(); index++) {
273+
bool copyOrdinal = NEO::EngineHelper::isCopyOnlyEngineType(engineGroups[ordinal].engineGroupType);
274+
if (engineGroups[ordinal].engines.size() > 1 && copyOrdinal) {
275+
hasMultiInstancedEngine = true;
276+
}
277+
278+
ze_command_queue_handle_t commandQueue = {};
279+
280+
ze_command_queue_desc_t desc = {};
281+
desc.ordinal = ordinal;
282+
desc.index = index;
283+
ze_result_t res = context->createCommandQueue(testL0Device.get(), &desc, &commandQueue);
284+
285+
EXPECT_EQ(ZE_RESULT_SUCCESS, res);
286+
EXPECT_NE(nullptr, commandQueue);
287+
288+
auto queue = whiteboxCast(L0::CommandQueue::fromHandle(commandQueue));
289+
290+
if (copyOrdinal) {
291+
EXPECT_EQ(engineGroups[expectedCopyOrdinal].engines[newIndex].commandStreamReceiver, queue->csr);
292+
queueCreated = true;
293+
} else {
294+
EXPECT_EQ(engineGroups[ordinal].engines[index].commandStreamReceiver, queue->csr);
295+
}
296+
297+
queue->destroy();
298+
}
299+
}
300+
301+
EXPECT_EQ(hasMultiInstancedEngine, queueCreated);
302+
}
303+
120304
HWTEST2_F(CommandQueueCommandsXeHpc, givenLinkedCopyEngineOrdinalWhenCreatingThenSetAsCopyOnly, IsXeHpcCore) {
121305
ze_result_t returnValue;
122306
auto hwInfo = *NEO::defaultHwInfo;

level_zero/core/test/unit_tests/xe_hpc_core/test_device_xe_hpc_core.cpp

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "level_zero/core/source/cmdqueue/cmdqueue.h"
1818
#include "level_zero/core/source/gfx_core_helpers/l0_gfx_core_helper.h"
1919
#include "level_zero/core/test/unit_tests/fixtures/device_fixture.h"
20+
#include "level_zero/core/test/unit_tests/mocks/mock_cmdqueue.h"
2021
#include "level_zero/core/test/unit_tests/mocks/mock_device.h"
2122
#include "level_zero/include/ze_intel_gpu.h"
2223

@@ -216,6 +217,104 @@ HWTEST2_F(MultiDeviceCommandQueueGroupWithNineCopyEnginesTest,
216217
EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, res);
217218
}
218219

220+
HWTEST2_F(MultiDeviceCommandQueueGroupWithNineCopyEnginesTest, givenDebugFlagWithLinkedEngineSetWhenCreatingCommandQueueThenOverrideEngineIndex, IsXeHpcCore) {
221+
DebugManagerStateRestore restore;
222+
const uint32_t newIndex = 2;
223+
DebugManager.flags.ForceBcsEngineIndex.set(newIndex);
224+
225+
auto &engineGroups = static_cast<MockDeviceImp *>(deviceImp)->subDeviceCopyEngineGroups;
226+
227+
uint32_t expectedCopyOrdinal = 0;
228+
for (uint32_t i = 0; i < engineGroups.size(); i++) {
229+
if (engineGroups[i].engineGroupType == EngineGroupType::LinkedCopy) {
230+
expectedCopyOrdinal = i;
231+
break;
232+
}
233+
}
234+
235+
for (uint32_t ordinal = 0; ordinal < engineGroups.size(); ordinal++) {
236+
for (uint32_t index = 0; index < engineGroups[ordinal].engines.size(); index++) {
237+
ze_command_queue_handle_t commandQueue = {};
238+
239+
ze_command_queue_desc_t desc = {};
240+
desc.ordinal = ordinal + 1;
241+
desc.index = index;
242+
ze_result_t res = context->createCommandQueue(deviceImp, &desc, &commandQueue);
243+
244+
EXPECT_EQ(ZE_RESULT_SUCCESS, res);
245+
EXPECT_NE(nullptr, commandQueue);
246+
247+
auto queue = whiteboxCast(L0::CommandQueue::fromHandle(commandQueue));
248+
249+
EXPECT_EQ(engineGroups[expectedCopyOrdinal].engines[newIndex - 1].commandStreamReceiver, queue->csr);
250+
251+
queue->destroy();
252+
}
253+
}
254+
}
255+
256+
HWTEST2_F(MultiDeviceCommandQueueGroupWithNineCopyEnginesTest, givenDebugFlagWithInvalidIndexSetWhenCreatingCommandQueueThenReturnError, IsXeHpcCore) {
257+
DebugManagerStateRestore restore;
258+
const uint32_t newIndex = 999;
259+
DebugManager.flags.ForceBcsEngineIndex.set(newIndex);
260+
261+
auto &engineGroups = static_cast<MockDeviceImp *>(deviceImp)->subDeviceCopyEngineGroups;
262+
263+
uint32_t expectedCopyOrdinal = 0;
264+
for (uint32_t i = 0; i < engineGroups.size(); i++) {
265+
if (engineGroups[i].engineGroupType == EngineGroupType::LinkedCopy) {
266+
expectedCopyOrdinal = i;
267+
break;
268+
}
269+
}
270+
271+
ze_command_queue_handle_t commandQueue = {};
272+
273+
ze_command_queue_desc_t desc = {};
274+
desc.ordinal = expectedCopyOrdinal + 1;
275+
desc.index = 0;
276+
ze_result_t res = context->createCommandQueue(deviceImp, &desc, &commandQueue);
277+
278+
EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, res);
279+
EXPECT_EQ(nullptr, commandQueue);
280+
}
281+
282+
HWTEST2_F(MultiDeviceCommandQueueGroupWithNineCopyEnginesTest, givenDebugFlagWithMainEngineSetWhenCreatingCommandQueueThenOverrideEngineIndex, IsXeHpcCore) {
283+
DebugManagerStateRestore restore;
284+
const uint32_t newIndex = 0;
285+
DebugManager.flags.ForceBcsEngineIndex.set(newIndex);
286+
287+
auto &engineGroups = static_cast<MockDeviceImp *>(deviceImp)->subDeviceCopyEngineGroups;
288+
289+
uint32_t expectedCopyOrdinal = 0;
290+
for (uint32_t i = 0; i < engineGroups.size(); i++) {
291+
if (engineGroups[i].engineGroupType == EngineGroupType::Copy) {
292+
expectedCopyOrdinal = i;
293+
break;
294+
}
295+
}
296+
297+
for (uint32_t ordinal = 0; ordinal < engineGroups.size(); ordinal++) {
298+
for (uint32_t index = 0; index < engineGroups[ordinal].engines.size(); index++) {
299+
ze_command_queue_handle_t commandQueue = {};
300+
301+
ze_command_queue_desc_t desc = {};
302+
desc.ordinal = ordinal + 1;
303+
desc.index = index;
304+
ze_result_t res = context->createCommandQueue(deviceImp, &desc, &commandQueue);
305+
306+
EXPECT_EQ(ZE_RESULT_SUCCESS, res);
307+
EXPECT_NE(nullptr, commandQueue);
308+
309+
auto queue = whiteboxCast(L0::CommandQueue::fromHandle(commandQueue));
310+
311+
EXPECT_EQ(engineGroups[expectedCopyOrdinal].engines[newIndex].commandStreamReceiver, queue->csr);
312+
313+
queue->destroy();
314+
}
315+
}
316+
}
317+
219318
HWTEST2_F(MultiDeviceCommandQueueGroupWithNineCopyEnginesTest,
220319
givenMainAndLinkCopyEngineSupportAndCCSAndImplicitScalingThenImmediateCommandListCreatedWithCorrectDevice, IsXeHpcCore) {
221320
uint32_t count = 0;

0 commit comments

Comments
 (0)