Skip to content

Commit dec8c40

Browse files
authored
[SYCL][E2E][Bindless] Add Vulkan interop test sampled_images_semaphore.cpp (#16300)
The test extends sampled_images.cpp test with semaphore import/wait. Only sycl waiting for vulkan semaphore is tested. Vulkan waiting for sycl semaphore isn't added, because the test's output is buffer and interop between vulkan and sycl buffers isn't supported.
1 parent a37bba8 commit dec8c40

File tree

2 files changed

+107
-15
lines changed

2 files changed

+107
-15
lines changed

sycl/test-e2e/bindless_images/vulkan_interop/sampled_images.cpp

+98-15
Original file line numberDiff line numberDiff line change
@@ -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

2829
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> {
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*/, &copyRegion);
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
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// REQUIRES: cuda || (windows && level_zero && aspect-ext_oneapi_bindless_images)
2+
// REQUIRES: vulkan
3+
// REQUIRES: build-and-run-mode
4+
5+
// RUN: %{build} %link-vulkan -o %t.out
6+
// RUN: %{run} %t.out
7+
8+
#define TEST_SEMAPHORE_IMPORT
9+
#include "sampled_images.cpp"

0 commit comments

Comments
 (0)