@@ -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+
120304HWTEST2_F (CommandQueueCommandsXeHpc, givenLinkedCopyEngineOrdinalWhenCreatingThenSetAsCopyOnly, IsXeHpcCore) {
121305 ze_result_t returnValue;
122306 auto hwInfo = *NEO::defaultHwInfo;
0 commit comments