@@ -23,6 +23,7 @@ struct handles_t {
23
23
syclexp::sampled_image_handle imgInput;
24
24
syclexp::image_mem_handle imgMem;
25
25
syclexp::external_mem inputExternalMem;
26
+ syclexp::external_semaphore sycl_wait_external_semaphore;
26
27
};
27
28
28
29
template <typename DType, sycl::image_channel_type CType> struct OutputType {
@@ -33,12 +34,12 @@ template <> struct OutputType<uint8_t, sycl::image_channel_type::unorm_int8> {
33
34
using type = float ;
34
35
};
35
36
36
- template <typename InteropHandleT>
37
- handles_t create_test_handles (sycl::context &ctxt, sycl::device &dev,
38
- const syclexp::bindless_image_sampler &samp ,
39
- InteropHandleT interopHandle,
40
- syclexp::image_descriptor desc ,
41
- const size_t imgSize) {
37
+ template <typename InteropHandleT, typename InteropSemHandleT >
38
+ handles_t create_test_handles (
39
+ sycl::context &ctxt, sycl::device &dev ,
40
+ const syclexp::bindless_image_sampler &samp, InteropHandleT interopHandle,
41
+ [[maybe_unused]] InteropSemHandleT sycl_wait_semaphore_handle ,
42
+ syclexp::image_descriptor desc, const size_t imgSize) {
42
43
// Extension: external memory descriptor
43
44
#ifdef _WIN32
44
45
syclexp::external_mem_descriptor<syclexp::resource_win32_handle>
@@ -62,13 +63,37 @@ handles_t create_test_handles(sycl::context &ctxt, sycl::device &dev,
62
63
syclexp::sampled_image_handle imgInput =
63
64
syclexp::create_image (inputMappedMemHandle, samp, desc, dev, ctxt);
64
65
65
- return {imgInput, inputMappedMemHandle, inputExternalMem};
66
+ #ifdef TEST_SEMAPHORE_IMPORT
67
+ // Extension: import semaphores
68
+ #ifdef _WIN32
69
+ syclexp::external_semaphore_descriptor<syclexp::resource_win32_handle>
70
+ sycl_wait_external_semaphore_desc{
71
+ sycl_wait_semaphore_handle,
72
+ syclexp::external_semaphore_handle_type::win32_nt_handle};
73
+ #else
74
+ syclexp::external_semaphore_descriptor<syclexp::resource_fd>
75
+ sycl_wait_external_semaphore_desc{
76
+ sycl_wait_semaphore_handle,
77
+ syclexp::external_semaphore_handle_type::opaque_fd};
78
+ #endif
79
+
80
+ syclexp::external_semaphore sycl_wait_external_semaphore =
81
+ syclexp::import_external_semaphore (sycl_wait_external_semaphore_desc, dev,
82
+ ctxt);
83
+ #else // #ifdef TEST_SEMAPHORE_IMPORT
84
+ syclexp::external_semaphore sycl_wait_external_semaphore{};
85
+ #endif // #ifdef TEST_SEMAPHORE_IMPORT
86
+
87
+ return {imgInput, inputMappedMemHandle, inputExternalMem,
88
+ sycl_wait_external_semaphore};
66
89
}
67
90
68
- template <typename InteropHandleT, int NDims, typename DType, int NChannels,
69
- sycl::image_channel_type CType, typename KernelName>
70
- bool run_sycl (InteropHandleT inputInteropMemHandle,
71
- sycl::range<NDims> globalSize, sycl::range<NDims> localSize) {
91
+ template <typename InteropHandleT, typename InteropSemHandleT, int NDims,
92
+ typename DType, int NChannels, sycl::image_channel_type CType,
93
+ typename KernelName>
94
+ bool run_sycl (sycl::range<NDims> globalSize, sycl::range<NDims> localSize,
95
+ InteropHandleT inputInteropMemHandle,
96
+ InteropSemHandleT sycl_wait_semaphore_handle) {
72
97
sycl::device dev;
73
98
sycl::queue q (dev);
74
99
auto ctxt = q.get_context ();
@@ -104,8 +129,14 @@ bool run_sycl(InteropHandleT inputInteropMemHandle,
104
129
using OutType = typename OutputType<DType, CType>::type;
105
130
using VecType = sycl::vec<OutType, NChannels>;
106
131
107
- auto handles = create_test_handles (ctxt, dev, samp, inputInteropMemHandle,
108
- desc, img_size);
132
+ auto handles =
133
+ create_test_handles (ctxt, dev, samp, inputInteropMemHandle,
134
+ sycl_wait_semaphore_handle, desc, img_size);
135
+
136
+ #ifdef TEST_SEMAPHORE_IMPORT
137
+ // Extension: wait for imported semaphore
138
+ q.ext_oneapi_wait_external_semaphore (handles.sycl_wait_external_semaphore );
139
+ #endif
109
140
110
141
std::vector<VecType> out (numElems);
111
142
try {
@@ -167,6 +198,10 @@ bool run_sycl(InteropHandleT inputInteropMemHandle,
167
198
});
168
199
q.wait_and_throw ();
169
200
201
+ #ifdef TEST_SEMAPHORE_IMPORT
202
+ syclexp::release_external_semaphore (handles.sycl_wait_external_semaphore ,
203
+ dev, ctxt);
204
+ #endif
170
205
syclexp::destroy_image_handle (handles.imgInput , dev, ctxt);
171
206
syclexp::free_image_mem (handles.imgMem , syclexp::image_type::standard, dev,
172
207
ctxt);
@@ -326,6 +361,27 @@ bool run_test(sycl::range<NDims> dims, sycl::range<NDims> localSize,
326
361
VK_CHECK_CALL (vkQueueWaitIdle (vk_compute_queue));
327
362
}
328
363
364
+ #ifdef TEST_SEMAPHORE_IMPORT
365
+ // Create semaphore to later import in SYCL
366
+ printString (" Creating semaphores\n " );
367
+ VkSemaphore syclWaitSemaphore;
368
+ {
369
+ VkExportSemaphoreCreateInfo esci = {};
370
+ esci.sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO;
371
+ #ifdef _WIN32
372
+ esci.handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT;
373
+ #else
374
+ esci.handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT;
375
+ #endif
376
+
377
+ VkSemaphoreCreateInfo sci = {};
378
+ sci.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
379
+ sci.pNext = &esci;
380
+ VK_CHECK_CALL (
381
+ vkCreateSemaphore (vk_device, &sci, nullptr , &syclWaitSemaphore));
382
+ }
383
+ #endif // #ifdef TEST_SEMAPHORE_IMPORT
384
+
329
385
printString (" Copying staging memory to images\n " );
330
386
// Copy staging to main image memory
331
387
{
@@ -344,11 +400,19 @@ bool run_test(sycl::range<NDims> dims, sycl::range<NDims> localSize,
344
400
1 /* regionCount*/ , ©Region);
345
401
VK_CHECK_CALL (vkEndCommandBuffer (vk_transferCmdBuffers[0 ]));
346
402
403
+ std::vector<VkPipelineStageFlags> stages{VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT};
404
+
347
405
VkSubmitInfo submission = {};
348
406
submission.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
349
407
submission.commandBufferCount = 1 ;
350
408
submission.pCommandBuffers = &vk_transferCmdBuffers[0 ];
351
409
410
+ #ifdef TEST_SEMAPHORE_IMPORT
411
+ submission.signalSemaphoreCount = 1 ;
412
+ submission.pSignalSemaphores = &syclWaitSemaphore;
413
+ #endif
414
+ submission.pWaitDstStageMask = stages.data ();
415
+
352
416
VK_CHECK_CALL (vkQueueSubmit (vk_transfer_queue, 1 /* submitCount*/ ,
353
417
&submission, VK_NULL_HANDLE /* fence*/ ));
354
418
VK_CHECK_CALL (vkQueueWaitIdle (vk_transfer_queue));
@@ -363,17 +427,36 @@ bool run_test(sycl::range<NDims> dims, sycl::range<NDims> localSize,
363
427
auto input_mem_handle = vkutil::getMemoryOpaqueFD (inputMemory);
364
428
#endif
365
429
430
+ printString (" Getting semaphore interop handles\n " );
431
+
432
+ #ifdef TEST_SEMAPHORE_IMPORT
433
+ // Pass semaphores to SYCL for synchronization
434
+ #ifdef _WIN32
435
+ auto sycl_wait_semaphore_handle =
436
+ vkutil::getSemaphoreWin32Handle (syclWaitSemaphore);
437
+ #else
438
+ auto sycl_wait_semaphore_handle =
439
+ vkutil::getSemaphoreOpaqueFD (syclWaitSemaphore);
440
+ #endif
441
+ #else // #ifdef TEST_SEMAPHORE_IMPORT
442
+ void *sycl_wait_semaphore_handle = nullptr ;
443
+ #endif // #ifdef TEST_SEMAPHORE_IMPORT
444
+
366
445
printString (" Calling into SYCL with interop memory handle\n " );
367
446
368
447
bool validated =
369
- run_sycl<decltype (input_mem_handle), NDims, DType, NChannels, CType,
370
- KernelName>(input_mem_handle, dims, localSize);
448
+ run_sycl<decltype (input_mem_handle), decltype (sycl_wait_semaphore_handle),
449
+ NDims, DType, NChannels, CType, KernelName>(
450
+ dims, localSize, input_mem_handle, sycl_wait_semaphore_handle);
371
451
372
452
// Cleanup
373
453
vkDestroyBuffer (vk_device, inputStagingBuffer, nullptr );
374
454
vkDestroyImage (vk_device, inputImage, nullptr );
375
455
vkFreeMemory (vk_device, inputStagingMemory, nullptr );
376
456
vkFreeMemory (vk_device, inputMemory, nullptr );
457
+ #ifdef TEST_SEMAPHORE_IMPORT
458
+ vkDestroySemaphore (vk_device, syclWaitSemaphore, nullptr );
459
+ #endif
377
460
378
461
return validated;
379
462
}
0 commit comments