Skip to content

Commit f86b606

Browse files
authored
[SYCL][Bindless] Add DX11 memory interop (#19217)
In DX11 Texture1D and Texture3D cannot be shared between process or devices, so only Texture2D is used but its layout is adapted (height = 1 for 1D and ArraySlices = depth for 3D) for the interop purposes and testing 1D and 3D image operations on it in the SYCL kernel. The new DXGI adapter selection fixes issues with non-matching devices between DX and SYCL which also failed the DX12 tests when more than 1 potential adapter is visible to DirectX. Ideally the introduction of LUIDs to SYCL will resolve that completely when they are properly matched. The future flow should change to - 1) create SYCL device (so the device selection itself can be manipulated via `ONEAPI_DEVICE_SELECTOR`) , 2) get DXGI adapter for creating a DX logical device (D3D11 or D3D12) by matching adapter LUIDs (this is going to depend on a LUID device info query extension for SYCL). Some notes on synchronisation: - IKeyedMutex is required for synchronising the access to the shared resource (texture) between devices or processes. - Currently the SYCL queue calls wait after submission to execute immediately and block until completion, but we can use ID3D11Fence imported in SYCL to signal the completion of the work to D3D11 via SYCL in the future when this kind of interop is considered.
1 parent ebe9758 commit f86b606

File tree

20 files changed

+928
-231
lines changed

20 files changed

+928
-231
lines changed

sycl/doc/extensions/experimental/sycl_ext_oneapi_bindless_images.asciidoc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2075,6 +2075,7 @@ enum class external_mem_handle_type {
20752075
win32_nt_handle = 1,
20762076
win32_nt_dx12_resource = 2,
20772077
dma_buf = 3,
2078+
win32_nt_dx11_resource = 4,
20782079
};
20792080
20802081
// Descriptor templated on specific resource type
@@ -2739,3 +2740,6 @@ This query should be added in a later revision of the proposal.
27392740
- Clarify how and when external memory should be unmapped.
27402741
|6.11|2025-06-16| - Add `external_mem_handle_type::dma_buf`
27412742
- Add `supports_importing_handle_type`
2743+
|6.12|2025-07-03| - Add `win32_nt_dx11_resource` enum entry to
2744+
`external_mem_handle_type` for Direct3D 11 memory interop.
2745+
|======================

sycl/include/sycl/ext/oneapi/bindless_images_interop.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ enum class external_mem_handle_type {
2222
win32_nt_handle = 1,
2323
win32_nt_dx12_resource = 2,
2424
dma_buf = 3,
25+
win32_nt_dx11_resource = 4,
2526
};
2627

2728
// Types of external semaphore handles

sycl/source/detail/bindless_images.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,8 @@ to_ur_type(external_mem_handle_type externalMemHandleType) {
406406
return UR_EXP_EXTERNAL_MEM_TYPE_DMA_BUF;
407407
case external_mem_handle_type::win32_nt_handle:
408408
return UR_EXP_EXTERNAL_MEM_TYPE_WIN32_NT;
409+
case external_mem_handle_type::win32_nt_dx11_resource:
410+
return UR_EXP_EXTERNAL_MEM_TYPE_WIN32_NT_DX11_RESOURCE;
409411
case external_mem_handle_type::win32_nt_dx12_resource:
410412
return UR_EXP_EXTERNAL_MEM_TYPE_WIN32_NT_DX12_RESOURCE;
411413
default:
@@ -471,6 +473,7 @@ __SYCL_EXPORT external_mem import_external_memory<resource_win32_handle>(
471473

472474
const auto urHandleType = detail::to_ur_type(externalMemDesc.handle_type);
473475
if ((urHandleType != UR_EXP_EXTERNAL_MEM_TYPE_WIN32_NT) &&
476+
(urHandleType != UR_EXP_EXTERNAL_MEM_TYPE_WIN32_NT_DX11_RESOURCE) &&
474477
(urHandleType != UR_EXP_EXTERNAL_MEM_TYPE_WIN32_NT_DX12_RESOURCE)) {
475478
throw sycl::exception(sycl::make_error_code(sycl::errc::invalid),
476479
"Invalid memory handle type");
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#ifndef DX11_INTEROP_H
2+
#define DX11_INTEROP_H
3+
4+
#pragma clang diagnostic ignored "-Waddress-of-temporary"
5+
6+
#include "../helpers/common.hpp"
7+
#include "../helpers/dx_interop_common.hpp"
8+
9+
#include <sycl/detail/core.hpp>
10+
#include <sycl/device.hpp>
11+
12+
#include <atomic>
13+
#include <string_view>
14+
15+
using namespace dx_helpers;
16+
17+
namespace dx11_interop {
18+
19+
/// @brief
20+
struct D3D11ProgramState {
21+
// device management
22+
ID3D11Device *device{nullptr};
23+
ID3D11DeviceContext *deviceContext{nullptr};
24+
25+
// Temporary, this is to be replaced by LUID.
26+
// Can also store a DXGI_ADAPTER_DESC if more state is needed.
27+
std::string deviceName;
28+
29+
// Keyed mutex ID for synchronizing access to the shared resource.
30+
std::atomic<UINT64> key;
31+
32+
D3D11ProgramState(const sycl::device &syclDevice);
33+
~D3D11ProgramState();
34+
};
35+
36+
D3D11ProgramState::D3D11ProgramState(const sycl::device &syclDevice) {
37+
UINT dxgiFactoryFlags = 0;
38+
#if WITH_DX_DEBUG
39+
dxgiFactoryFlags |= DXGI_CREATE_FACTORY_DEBUG;
40+
#endif
41+
ComPtr<IDXGIFactory3> factory;
42+
ThrowIfFailed(CreateDXGIFactory2(dxgiFactoryFlags, IID_PPV_ARGS(&factory)));
43+
44+
auto hardwareAdapter = getDXGIHardwareAdapter<dx_version::DX11>(
45+
factory.Get(), syclDevice.get_info<sycl::info::device::name>());
46+
assert(hardwareAdapter && "Invalid DirectX hardware adapter.");
47+
48+
// Creating the D3D11 device.
49+
UINT deviceFlags = 0;
50+
#if defined(D3D_DEVICE_DEBUG)
51+
deviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
52+
#endif
53+
constexpr D3D_FEATURE_LEVEL requestedFeatureLevel = D3D_FEATURE_LEVEL_11_0;
54+
D3D_FEATURE_LEVEL featureLevel;
55+
ThrowIfFailed(D3D11CreateDevice(hardwareAdapter.Get(),
56+
D3D_DRIVER_TYPE_UNKNOWN, nullptr, deviceFlags,
57+
&requestedFeatureLevel, 1, D3D11_SDK_VERSION,
58+
&device, &featureLevel, &deviceContext));
59+
60+
// Get the description of the adapter which contains the LUID, etc.
61+
DXGI_ADAPTER_DESC1 adapterDesc;
62+
ThrowIfFailed(hardwareAdapter->GetDesc1(&adapterDesc));
63+
64+
deviceName = getD3DDeviceName(adapterDesc);
65+
}
66+
67+
D3D11ProgramState::~D3D11ProgramState() {
68+
if (device)
69+
device->Release();
70+
if (deviceContext)
71+
deviceContext->Release();
72+
}
73+
74+
} // namespace dx11_interop
75+
76+
#endif // DX11_INTEROP_H

0 commit comments

Comments
 (0)