@@ -23,6 +23,7 @@ struct handles_t {
2323 syclexp::sampled_image_handle imgInput;
2424 syclexp::image_mem_handle imgMem;
2525 syclexp::external_mem inputExternalMem;
26+ syclexp::external_semaphore sycl_wait_external_semaphore;
2627};
2728
2829template <typename DType, sycl::image_channel_type CType> struct OutputType {
@@ -33,12 +34,12 @@ template <> struct OutputType<uint8_t, sycl::image_channel_type::unorm_int8> {
3334 using type = float ;
3435};
3536
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) {
4243 // Extension: external memory descriptor
4344#ifdef _WIN32
4445 syclexp::external_mem_descriptor<syclexp::resource_win32_handle>
@@ -62,13 +63,37 @@ handles_t create_test_handles(sycl::context &ctxt, sycl::device &dev,
6263 syclexp::sampled_image_handle imgInput =
6364 syclexp::create_image (inputMappedMemHandle, samp, desc, dev, ctxt);
6465
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};
6689}
6790
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) {
7297 sycl::device dev;
7398 sycl::queue q (dev);
7499 auto ctxt = q.get_context ();
@@ -104,8 +129,14 @@ bool run_sycl(InteropHandleT inputInteropMemHandle,
104129 using OutType = typename OutputType<DType, CType>::type;
105130 using VecType = sycl::vec<OutType, NChannels>;
106131
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
109140
110141 std::vector<VecType> out (numElems);
111142 try {
@@ -167,6 +198,10 @@ bool run_sycl(InteropHandleT inputInteropMemHandle,
167198 });
168199 q.wait_and_throw ();
169200
201+ #ifdef TEST_SEMAPHORE_IMPORT
202+ syclexp::release_external_semaphore (handles.sycl_wait_external_semaphore ,
203+ dev, ctxt);
204+ #endif
170205 syclexp::destroy_image_handle (handles.imgInput , dev, ctxt);
171206 syclexp::free_image_mem (handles.imgMem , syclexp::image_type::standard, dev,
172207 ctxt);
@@ -326,6 +361,27 @@ bool run_test(sycl::range<NDims> dims, sycl::range<NDims> localSize,
326361 VK_CHECK_CALL (vkQueueWaitIdle (vk_compute_queue));
327362 }
328363
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+
329385 printString (" Copying staging memory to images\n " );
330386 // Copy staging to main image memory
331387 {
@@ -344,11 +400,19 @@ bool run_test(sycl::range<NDims> dims, sycl::range<NDims> localSize,
344400 1 /* regionCount*/ , ©Region);
345401 VK_CHECK_CALL (vkEndCommandBuffer (vk_transferCmdBuffers[0 ]));
346402
403+ std::vector<VkPipelineStageFlags> stages{VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT};
404+
347405 VkSubmitInfo submission = {};
348406 submission.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
349407 submission.commandBufferCount = 1 ;
350408 submission.pCommandBuffers = &vk_transferCmdBuffers[0 ];
351409
410+ #ifdef TEST_SEMAPHORE_IMPORT
411+ submission.signalSemaphoreCount = 1 ;
412+ submission.pSignalSemaphores = &syclWaitSemaphore;
413+ #endif
414+ submission.pWaitDstStageMask = stages.data ();
415+
352416 VK_CHECK_CALL (vkQueueSubmit (vk_transfer_queue, 1 /* submitCount*/ ,
353417 &submission, VK_NULL_HANDLE /* fence*/ ));
354418 VK_CHECK_CALL (vkQueueWaitIdle (vk_transfer_queue));
@@ -363,17 +427,36 @@ bool run_test(sycl::range<NDims> dims, sycl::range<NDims> localSize,
363427 auto input_mem_handle = vkutil::getMemoryOpaqueFD (inputMemory);
364428#endif
365429
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+
366445 printString (" Calling into SYCL with interop memory handle\n " );
367446
368447 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);
371451
372452 // Cleanup
373453 vkDestroyBuffer (vk_device, inputStagingBuffer, nullptr );
374454 vkDestroyImage (vk_device, inputImage, nullptr );
375455 vkFreeMemory (vk_device, inputStagingMemory, nullptr );
376456 vkFreeMemory (vk_device, inputMemory, nullptr );
457+ #ifdef TEST_SEMAPHORE_IMPORT
458+ vkDestroySemaphore (vk_device, syclWaitSemaphore, nullptr );
459+ #endif
377460
378461 return validated;
379462}
0 commit comments