Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions sycl/include/sycl/ext/oneapi/bindless_images_interop.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@ struct resource_win32_handle {
// Windows external name type
struct resource_win32_name {
const void *name;
void *device; // ID3D12Device* (ID3D12Device1 or higher) for opening the
// named handle via OpenSharedHandleByName
};

/// Opaque external memory descriptor type
Expand Down
213 changes: 5 additions & 208 deletions sycl/source/detail/bindless_images.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,6 @@

#include <memory>

#if defined(_WIN32) || defined(_WIN64)
#include <mutex>
#include <unordered_map>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

namespace {
// Track handles opened via resource_win32_name so we can close them on release.
// Declared here so release_external_memory/semaphore can access them. Separate
// maps per UR handle type (memory vs. semaphore) — the two handle types are
// unrelated and must not be confused via reinterpret_cast.
std::mutex g_win32NameHandlesMutex;
std::unordered_map<ur_exp_external_mem_handle_t, HANDLE> g_win32NameMemHandles;
std::unordered_map<ur_exp_external_semaphore_handle_t, HANDLE>
g_win32NameSemHandles;
} // namespace
#endif

namespace sycl {
inline namespace _V1 {
namespace ext::oneapi::experimental {
Expand Down Expand Up @@ -514,9 +496,11 @@ __SYCL_EXPORT external_mem import_external_memory<resource_win32_handle>(
externalMemDesc, syclQueue.get_device(), syclQueue.get_context());
}

__SYCL_EXPORT image_mem_handle map_external_image_memory(
external_mem extMem, const image_descriptor &desc,
const sycl::device &syclDevice, const sycl::context &syclContext) {
__SYCL_EXPORT
image_mem_handle map_external_image_memory(external_mem extMem,
const image_descriptor &desc,
const sycl::device &syclDevice,
const sycl::context &syclContext) {
desc.verify();

auto [urDevice, urCtx, Adapter] = get_ur_handles(syclDevice, syclContext);
Expand Down Expand Up @@ -571,18 +555,6 @@ void *map_external_linear_memory(external_mem extMem, uint64_t offset,
__SYCL_EXPORT void release_external_memory(external_mem extMem,
const sycl::device &syclDevice,
const sycl::context &syclContext) {
#if defined(_WIN32) || defined(_WIN64)
// Close handle if it was opened via resource_win32_name
{
std::lock_guard<std::mutex> lock(g_win32NameHandlesMutex);
auto it = g_win32NameMemHandles.find(extMem.raw_handle);
if (it != g_win32NameMemHandles.end()) {
CloseHandle(it->second);
g_win32NameMemHandles.erase(it);
}
}
#endif

auto [urDevice, urCtx, Adapter] = get_ur_handles(syclDevice, syclContext);

Adapter
Expand Down Expand Up @@ -732,18 +704,6 @@ __SYCL_EXPORT void
release_external_semaphore(external_semaphore externalSemaphore,
const sycl::device &syclDevice,
const sycl::context &syclContext) {
#if defined(_WIN32) || defined(_WIN64)
// Close handle if it was opened via resource_win32_name
{
std::lock_guard<std::mutex> lock(g_win32NameHandlesMutex);
auto it = g_win32NameSemHandles.find(externalSemaphore.raw_handle);
if (it != g_win32NameSemHandles.end()) {
CloseHandle(it->second);
g_win32NameSemHandles.erase(it);
}
}
#endif

auto [urDevice, urCtx, Adapter] = get_ur_handles(syclDevice, syclContext);

Adapter->call<
Expand Down Expand Up @@ -1008,169 +968,6 @@ __SYCL_EXPORT bool is_image_handle_supported<sampled_image_handle>(
syclQueue.get_context());
}

// ============================================================================
// resource_win32_name support - Windows-specific code at end of file
// ============================================================================
#if defined(_WIN32) || defined(_WIN64)

// Include D3D12 for OpenSharedHandleByName
#ifdef __has_include
#if __has_include(<d3d12.h>)
#include <d3d12.h>
#define SYCL_HAS_D3D12_INTEROP 1
#endif
#endif

namespace {

// Closes a HANDLE on scope exit unless released. Used so that if the UR import
// call throws after we've opened a named handle, we don't leak it.
struct NamedHandleGuard {
HANDLE h;
explicit NamedHandleGuard(HANDLE handle) : h(handle) {}
~NamedHandleGuard() {
if (h)
CloseHandle(h);
}
HANDLE release() {
HANDLE out = h;
h = nullptr;
return out;
}
NamedHandleGuard(const NamedHandleGuard &) = delete;
NamedHandleGuard &operator=(const NamedHandleGuard &) = delete;
};

HANDLE openNamedHandleImpl(void *device, const void *name) {
#ifdef SYCL_HAS_D3D12_INTEROP
// OpenSharedHandleByName requires ID3D12Device1 or higher
auto d3dDeviceBase = static_cast<ID3D12Device *>(device);
ID3D12Device1 *d3dDevice1 = nullptr;

HRESULT hr = d3dDeviceBase->QueryInterface(IID_PPV_ARGS(&d3dDevice1));
if (FAILED(hr)) {
return nullptr;
}

HANDLE openedHandle = nullptr;
const wchar_t *wname = static_cast<const wchar_t *>(name);

hr = d3dDevice1->OpenSharedHandleByName(wname, GENERIC_ALL, &openedHandle);
d3dDevice1->Release();

return SUCCEEDED(hr) ? openedHandle : nullptr;
#else
(void)device;
(void)name;
throw sycl::exception(
sycl::make_error_code(sycl::errc::feature_not_supported),
"resource_win32_name requires D3D12 headers. "
"Use resource_win32_handle instead.");
#endif
}
} // anonymous namespace

template <>
__SYCL_EXPORT external_mem import_external_memory<resource_win32_name>(
external_mem_descriptor<resource_win32_name> externalMemDesc,
const sycl::device &syclDevice, const sycl::context &syclContext) {

if (!externalMemDesc.external_resource.device) {
throw sycl::exception(sycl::make_error_code(sycl::errc::invalid),
"D3D12 device required in resource_win32_name");
}

HANDLE openedHandle =
openNamedHandleImpl(externalMemDesc.external_resource.device,
externalMemDesc.external_resource.name);

if (!openedHandle) {
throw sycl::exception(sycl::make_error_code(sycl::errc::invalid),
"Failed to open named Win32 handle");
}

// Close openedHandle if the delegated UR import throws before we've
// handed ownership to the tracking map.
NamedHandleGuard guard(openedHandle);

// Use existing resource_win32_handle implementation
external_mem_descriptor<resource_win32_handle> handleDesc{
{openedHandle},
externalMemDesc.handle_type,
externalMemDesc.size_in_bytes};

// Delegate to existing resource_win32_handle implementation
external_mem result = import_external_memory<resource_win32_handle>(
handleDesc, syclDevice, syclContext);

// Track the opened handle so we can close it on release
{
std::lock_guard<std::mutex> lock(g_win32NameHandlesMutex);
g_win32NameMemHandles[result.raw_handle] = openedHandle;
}
guard.release();

return result;
}

template <>
__SYCL_EXPORT external_mem import_external_memory<resource_win32_name>(
external_mem_descriptor<resource_win32_name> externalMemDesc,
const sycl::queue &syclQueue) {
return import_external_memory<resource_win32_name>(
externalMemDesc, syclQueue.get_device(), syclQueue.get_context());
}

template <>
__SYCL_EXPORT external_semaphore import_external_semaphore(
external_semaphore_descriptor<resource_win32_name> externalSemaphoreDesc,
const sycl::device &syclDevice, const sycl::context &syclContext) {

if (!externalSemaphoreDesc.external_resource.device) {
throw sycl::exception(sycl::make_error_code(sycl::errc::invalid),
"D3D12 device required in resource_win32_name");
}

HANDLE openedHandle =
openNamedHandleImpl(externalSemaphoreDesc.external_resource.device,
externalSemaphoreDesc.external_resource.name);

if (!openedHandle) {
throw sycl::exception(sycl::make_error_code(sycl::errc::invalid),
"Failed to open named Win32 semaphore");
}

// Close openedHandle if the delegated UR import throws before we've
// handed ownership to the tracking map.
NamedHandleGuard guard(openedHandle);

// Delegate to existing resource_win32_handle implementation
external_semaphore_descriptor<resource_win32_handle> handleDesc{
{openedHandle}, externalSemaphoreDesc.handle_type};

external_semaphore result =
import_external_semaphore(handleDesc, syclDevice, syclContext);

// Track the opened handle so we can close it on release
{
std::lock_guard<std::mutex> lock(g_win32NameHandlesMutex);
g_win32NameSemHandles[result.raw_handle] = openedHandle;
}
guard.release();

return result;
}

template <>
__SYCL_EXPORT external_semaphore import_external_semaphore(
external_semaphore_descriptor<resource_win32_name> externalSemaphoreDesc,
const sycl::queue &syclQueue) {
return import_external_semaphore(
externalSemaphoreDesc, syclQueue.get_device(), syclQueue.get_context());
}

#endif // _WIN32 || _WIN64

} // namespace ext::oneapi::experimental
} // namespace _V1
} // namespace sycl
Loading
Loading