@@ -312,74 +312,95 @@ TEST_F(CommandGraphTest, InOrderQueueWithPreviousHostTask) {
312
312
}
313
313
314
314
TEST_F (CommandGraphTest, InOrderQueueHostTaskAndGraph) {
315
- sycl::property_list Properties{sycl::property::queue::in_order ()};
316
- sycl::queue InOrderQueue{Dev, Properties};
317
- experimental::command_graph<experimental::graph_state::modifiable>
318
- InOrderGraph{InOrderQueue.get_context (), InOrderQueue.get_device ()};
319
-
320
- auto EventInitial =
321
- InOrderQueue.submit ([&](handler &CGH) { CGH.host_task ([=]() {}); });
322
- auto EventInitialImpl = sycl::detail::getSyclObjImpl (EventInitial);
323
-
324
- // Record in-order queue with three nodes.
325
- InOrderGraph.begin_recording (InOrderQueue);
326
- auto Node1Graph = InOrderQueue.submit (
327
- [&](sycl::handler &cgh) { cgh.single_task <TestKernel<>>([]() {}); });
328
-
329
- auto PtrNode1 =
330
- sycl::detail::getSyclObjImpl (InOrderGraph)
331
- ->getLastInorderNode (sycl::detail::getSyclObjImpl (InOrderQueue));
332
- ASSERT_NE (PtrNode1, nullptr );
333
- ASSERT_TRUE (PtrNode1->MPredecessors .empty ());
334
-
335
- auto Node2Graph = InOrderQueue.submit (
336
- [&](sycl::handler &cgh) { cgh.single_task <TestKernel<>>([]() {}); });
337
-
338
- auto PtrNode2 =
339
- sycl::detail::getSyclObjImpl (InOrderGraph)
340
- ->getLastInorderNode (sycl::detail::getSyclObjImpl (InOrderQueue));
341
- ASSERT_NE (PtrNode2, nullptr );
342
- ASSERT_NE (PtrNode2, PtrNode1);
343
- ASSERT_EQ (PtrNode1->MSuccessors .size (), 1lu);
344
- ASSERT_EQ (PtrNode1->MSuccessors .front ().lock (), PtrNode2);
345
- ASSERT_EQ (PtrNode2->MPredecessors .size (), 1lu);
346
- ASSERT_EQ (PtrNode2->MPredecessors .front ().lock (), PtrNode1);
347
-
348
- auto Node3Graph = InOrderQueue.submit (
349
- [&](sycl::handler &cgh) { cgh.single_task <TestKernel<>>([]() {}); });
350
-
351
- auto PtrNode3 =
352
- sycl::detail::getSyclObjImpl (InOrderGraph)
353
- ->getLastInorderNode (sycl::detail::getSyclObjImpl (InOrderQueue));
354
- ASSERT_NE (PtrNode3, nullptr );
355
- ASSERT_NE (PtrNode3, PtrNode2);
356
- ASSERT_EQ (PtrNode2->MSuccessors .size (), 1lu);
357
- ASSERT_EQ (PtrNode2->MSuccessors .front ().lock (), PtrNode3);
358
- ASSERT_EQ (PtrNode3->MPredecessors .size (), 1lu);
359
- ASSERT_EQ (PtrNode3->MPredecessors .front ().lock (), PtrNode2);
360
-
361
- InOrderGraph.end_recording (InOrderQueue);
362
-
363
- auto InOrderGraphExec = InOrderGraph.finalize ();
364
- auto EventGraph = InOrderQueue.submit (
365
- [&](sycl::handler &CGH) { CGH.ext_oneapi_graph (InOrderGraphExec); });
366
-
367
- auto EventGraphImpl = sycl::detail::getSyclObjImpl (EventGraph);
368
- auto EventGraphWaitList = EventGraphImpl->getWaitList ();
369
- // Previous task is a host task. Explicit dependency is needed to enforce the
370
- // execution order.
371
- ASSERT_EQ (EventGraphWaitList.size (), 1lu);
372
- ASSERT_EQ (EventGraphWaitList[0 ], EventInitialImpl);
373
-
374
- auto EventLast = InOrderQueue.submit (
375
- [&](sycl::handler &cgh) { cgh.single_task <TestKernel<>>([]() {}); });
376
- auto EventLastImpl = sycl::detail::getSyclObjImpl (EventLast);
377
- auto EventLastWaitList = EventLastImpl->getWaitList ();
378
- // Previous task is not a host task. Explicit dependency is still needed
379
- // to properly handle blocked tasks (the event will be filtered out before
380
- // submission to the backend).
381
- ASSERT_EQ (EventLastWaitList.size (), 1lu);
382
- ASSERT_EQ (EventLastWaitList[0 ], EventGraphImpl);
315
+ auto TestBody = [&](bool BlockHostTask) {
316
+ sycl::property_list Properties{sycl::property::queue::in_order ()};
317
+ sycl::queue InOrderQueue{Dev, Properties};
318
+ experimental::command_graph<experimental::graph_state::modifiable>
319
+ InOrderGraph{InOrderQueue.get_context (), InOrderQueue.get_device ()};
320
+ // Event dependency build depends on host task completion. Making it
321
+ // predictable with mutex in host task.
322
+ std::mutex HostTaskMutex;
323
+ std::unique_lock<std::mutex> Lock (HostTaskMutex, std::defer_lock);
324
+ if (BlockHostTask)
325
+ Lock.lock ();
326
+ auto EventInitial = InOrderQueue.submit ([&](handler &CGH) {
327
+ CGH.host_task ([&HostTaskMutex]() {
328
+ std::lock_guard<std::mutex> HostTaskLock (HostTaskMutex);
329
+ });
330
+ });
331
+ auto EventInitialImpl = sycl::detail::getSyclObjImpl (EventInitial);
332
+
333
+ // Record in-order queue with three nodes.
334
+ InOrderGraph.begin_recording (InOrderQueue);
335
+ auto Node1Graph = InOrderQueue.submit (
336
+ [&](sycl::handler &cgh) { cgh.single_task <TestKernel<>>([]() {}); });
337
+
338
+ auto PtrNode1 =
339
+ sycl::detail::getSyclObjImpl (InOrderGraph)
340
+ ->getLastInorderNode (sycl::detail::getSyclObjImpl (InOrderQueue));
341
+ ASSERT_NE (PtrNode1, nullptr );
342
+ ASSERT_TRUE (PtrNode1->MPredecessors .empty ());
343
+
344
+ auto Node2Graph = InOrderQueue.submit (
345
+ [&](sycl::handler &cgh) { cgh.single_task <TestKernel<>>([]() {}); });
346
+
347
+ auto PtrNode2 =
348
+ sycl::detail::getSyclObjImpl (InOrderGraph)
349
+ ->getLastInorderNode (sycl::detail::getSyclObjImpl (InOrderQueue));
350
+ ASSERT_NE (PtrNode2, nullptr );
351
+ ASSERT_NE (PtrNode2, PtrNode1);
352
+ ASSERT_EQ (PtrNode1->MSuccessors .size (), 1lu);
353
+ ASSERT_EQ (PtrNode1->MSuccessors .front ().lock (), PtrNode2);
354
+ ASSERT_EQ (PtrNode2->MPredecessors .size (), 1lu);
355
+ ASSERT_EQ (PtrNode2->MPredecessors .front ().lock (), PtrNode1);
356
+
357
+ auto Node3Graph = InOrderQueue.submit (
358
+ [&](sycl::handler &cgh) { cgh.single_task <TestKernel<>>([]() {}); });
359
+
360
+ auto PtrNode3 =
361
+ sycl::detail::getSyclObjImpl (InOrderGraph)
362
+ ->getLastInorderNode (sycl::detail::getSyclObjImpl (InOrderQueue));
363
+ ASSERT_NE (PtrNode3, nullptr );
364
+ ASSERT_NE (PtrNode3, PtrNode2);
365
+ ASSERT_EQ (PtrNode2->MSuccessors .size (), 1lu);
366
+ ASSERT_EQ (PtrNode2->MSuccessors .front ().lock (), PtrNode3);
367
+ ASSERT_EQ (PtrNode3->MPredecessors .size (), 1lu);
368
+ ASSERT_EQ (PtrNode3->MPredecessors .front ().lock (), PtrNode2);
369
+
370
+ InOrderGraph.end_recording (InOrderQueue);
371
+
372
+ auto InOrderGraphExec = InOrderGraph.finalize ();
373
+
374
+ if (!BlockHostTask)
375
+ EventInitial.wait ();
376
+ auto EventGraph = InOrderQueue.submit (
377
+ [&](sycl::handler &CGH) { CGH.ext_oneapi_graph (InOrderGraphExec); });
378
+
379
+ auto EventGraphImpl = sycl::detail::getSyclObjImpl (EventGraph);
380
+ auto EventGraphWaitList = EventGraphImpl->getWaitList ();
381
+ // Previous task is a host task. Explicit dependency is needed to enforce
382
+ // the execution order.
383
+ ASSERT_EQ (EventGraphWaitList.size (), 1lu);
384
+ ASSERT_EQ (EventGraphWaitList[0 ], EventInitialImpl);
385
+
386
+ auto EventLast = InOrderQueue.submit (
387
+ [&](sycl::handler &cgh) { cgh.single_task <TestKernel<>>([]() {}); });
388
+ auto EventLastImpl = sycl::detail::getSyclObjImpl (EventLast);
389
+ auto EventLastWaitList = EventLastImpl->getWaitList ();
390
+ // Previous task is not a host task. Explicit dependency is still needed
391
+ // to properly handle blocked tasks (the event will be filtered out before
392
+ // submission to the backend).
393
+ if (BlockHostTask)
394
+ Lock.unlock ();
395
+ ASSERT_EQ (EventLastWaitList.size (), size_t (BlockHostTask));
396
+ if (EventLastWaitList.size ()) {
397
+ ASSERT_EQ (EventLastWaitList[0 ], EventGraphImpl);
398
+ }
399
+ EventLast.wait ();
400
+ };
401
+
402
+ TestBody (false );
403
+ TestBody (true );
383
404
}
384
405
385
406
TEST_F (CommandGraphTest, InOrderQueueMemsetAndGraph) {
0 commit comments