diff options
| author | lucy96chen <47800040+lucy96chen@users.noreply.github.com> | 2021-11-09 11:59:43 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-11-09 11:59:43 -0800 |
| commit | 4d4cd569ad7fcc88693c18f848603f18894e24be (patch) | |
| tree | 4c7fb036eea9e259d1610a933b448a5d0edcd918 /tools/gfx/d3d12/render-d3d12.cpp | |
| parent | 8fe3f9cd7d664fc98e33cf276427390b42b9b468 (diff) | |
Allow buffers to be shared between D3D12 and CUDA (#2005)
* Added both the SharedHandle struct containing a handle and the API the handle originated from and the getSharedHandle() method to IResource, which returns a Windows system handle for the resource that can then be shared between multiple APIs (currently only fully implemented for D3D12); Added createTextureFromNativeHandle() and createBufferFromNativeHandle() to IDevice, which creates a buffer or texture resource using the provided handle (currently only fully implemented for D3D12); Added createBufferFromSharedHandle() to IDevice, which creates a BufferResource using the provided system handle (currently only fully implemented for the D3D12 to CUDA interface); Provided a proper implementation for CUDADevice::getNativeHandle(); Added several new tests testing the aforementioned implementations; Moved NativeHandle and getNativeHandle() for IBufferResource and ITextureResource up a layer into IResource and renamed to NativeResourceHandle; Modified NativeResourceHandle to be a struct containing the handle and the API it originated from and propagated these changes where appropriate
* Combined all native and shared handle representations into a unified InteropHandle struct which tracks the handle's value and source API; Modified all getNativeHandle() and getSharedHandle() variants to operate on InteropHandle and modified all affected files
* D3D12 buffers and textures are now responsible for closing their shared handles if they exist; Renamed IDevice::getNativeHandle() to getNativeDeviceHandles()
* Fixed getNativeDeviceHandles() in render-cuda to match updated method elsewhere
* Temporarily disabling existingDeviceHandleCUDA and sharedHandleD3D12ToCUDA due to currently unreproducable test failures on TC
Diffstat (limited to 'tools/gfx/d3d12/render-d3d12.cpp')
| -rw-r--r-- | tools/gfx/d3d12/render-d3d12.cpp | 121 |
1 files changed, 108 insertions, 13 deletions
diff --git a/tools/gfx/d3d12/render-d3d12.cpp b/tools/gfx/d3d12/render-d3d12.cpp index 4384cc243..d14d72b84 100644 --- a/tools/gfx/d3d12/render-d3d12.cpp +++ b/tools/gfx/d3d12/render-d3d12.cpp @@ -84,10 +84,19 @@ public: const ITextureResource::Desc& desc, const ITextureResource::SubresourceData* initData, ITextureResource** outResource) override; + virtual SLANG_NO_THROW Result SLANG_MCALL createTextureFromNativeHandle( + InteropHandle handle, + const ITextureResource::Desc& srcDesc, + ITextureResource** outResource) override; virtual SLANG_NO_THROW Result SLANG_MCALL createBufferResource( const IBufferResource::Desc& desc, const void* initData, IBufferResource** outResource) override; + virtual SLANG_NO_THROW Result SLANG_MCALL createBufferFromNativeHandle( + InteropHandle handle, + const IBufferResource::Desc& srcDesc, + IBufferResource** outResource) override; + virtual SLANG_NO_THROW Result SLANG_MCALL createSamplerState(ISamplerState::Desc const& desc, ISamplerState** outSampler) override; @@ -149,7 +158,7 @@ public: return m_info; } - virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(NativeHandle* outHandle) override; + virtual SLANG_NO_THROW Result SLANG_MCALL getNativeDeviceHandles(InteropHandles* outHandles) override; ~D3D12Device(); @@ -215,6 +224,14 @@ public: { } + ~BufferResourceImpl() + { + if (sharedHandle.handleValue != 0) + { + CloseHandle((HANDLE)sharedHandle.handleValue); + } + } + D3D12Resource m_resource; ///< The resource typically in gpu memory D3D12Resource m_uploadResource; ///< If the resource can be written to, and is in gpu memory (ie not Memory backed), will have upload resource @@ -225,9 +242,29 @@ public: return (DeviceAddress)m_resource.getResource()->GetGPUVirtualAddress(); } - virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(NativeHandle* outHandle) override + virtual SLANG_NO_THROW Result SLANG_MCALL getNativeResourceHandle(InteropHandle* outHandle) override + { + outHandle->handleValue = (uint64_t)m_resource.getResource(); + outHandle->api = InteropHandleAPI::D3D12; + return SLANG_OK; + } + + virtual SLANG_NO_THROW Result SLANG_MCALL getSharedHandle(InteropHandle* outHandle) override { - *outHandle = (uint64_t)m_resource.getResource(); + // Check if a shared handle already exists for this resource. + if (sharedHandle.handleValue != 0) + { + *outHandle = sharedHandle; + return SLANG_OK; + } + + // If a shared handle doesn't exist, create one and store it. + ComPtr<ID3D12Device> pDevice; + auto pResource = m_resource.getResource(); + pResource->GetDevice(IID_PPV_ARGS(pDevice.writeRef())); + SLANG_RETURN_ON_FAIL(pDevice->CreateSharedHandle(pResource, NULL, GENERIC_ALL, nullptr, (HANDLE*)&outHandle->handleValue)); + outHandle->api = InteropHandleAPI::Win32; + sharedHandle = *outHandle; return SLANG_OK; } }; @@ -243,12 +280,31 @@ public: { } + ~TextureResourceImpl() + { + if (sharedHandle.handleValue != 0) + { + CloseHandle((HANDLE)sharedHandle.handleValue); + } + } + D3D12Resource m_resource; D3D12_RESOURCE_STATES m_defaultState; - virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(NativeHandle* outHandle) override + virtual SLANG_NO_THROW Result SLANG_MCALL getNativeResourceHandle(InteropHandle* outHandle) override { - *outHandle = (uint64_t)m_resource.getResource(); + outHandle->handleValue = (uint64_t)m_resource.getResource(); + outHandle->api = InteropHandleAPI::D3D12; + return SLANG_OK; + } + + virtual SLANG_NO_THROW Result SLANG_MCALL getSharedHandle(InteropHandle* outHandle) override + { + ComPtr<ID3D12Device> pDevice; + auto pResource = m_resource.getResource(); + pResource->GetDevice(IID_PPV_ARGS(pDevice.writeRef())); + SLANG_RETURN_ON_FAIL(pDevice->CreateSharedHandle(pResource, NULL, GENERIC_ALL, nullptr, (HANDLE*)&outHandle->handleValue)); + outHandle->api = InteropHandleAPI::Win32; return SLANG_OK; } }; @@ -3810,7 +3866,8 @@ public: size_t srcDataSize, D3D12Resource& uploadResource, D3D12_RESOURCE_STATES finalState, - D3D12Resource& resourceOut); + D3D12Resource& resourceOut, + bool isShared = false); Result captureTextureToSurface( D3D12Resource& resource, @@ -4080,7 +4137,7 @@ static void _initSrvDesc(IResource::Type resourceType, const ITextureResource::D } } -Result D3D12Device::createBuffer(const D3D12_RESOURCE_DESC& resourceDesc, const void* srcData, size_t srcDataSize, D3D12Resource& uploadResource, D3D12_RESOURCE_STATES finalState, D3D12Resource& resourceOut) +Result D3D12Device::createBuffer(const D3D12_RESOURCE_DESC& resourceDesc, const void* srcData, size_t srcDataSize, D3D12Resource& uploadResource, D3D12_RESOURCE_STATES finalState, D3D12Resource& resourceOut, bool isShared) { const size_t bufferSize = size_t(resourceDesc.Width); @@ -4092,9 +4149,12 @@ Result D3D12Device::createBuffer(const D3D12_RESOURCE_DESC& resourceDesc, const heapProps.CreationNodeMask = 1; heapProps.VisibleNodeMask = 1; + D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE; + if (isShared) flags |= D3D12_HEAP_FLAG_SHARED; + const D3D12_RESOURCE_STATES initialState = srcData ? D3D12_RESOURCE_STATE_COPY_DEST : finalState; - SLANG_RETURN_ON_FAIL(resourceOut.initCommitted(m_device, heapProps, D3D12_HEAP_FLAG_NONE, resourceDesc, initialState, nullptr)); + SLANG_RETURN_ON_FAIL(resourceOut.initCommitted(m_device, heapProps, flags, resourceDesc, initialState, nullptr)); } { @@ -4228,9 +4288,10 @@ Result D3D12Device::captureTextureToSurface( // !!!!!!!!!!!!!!!!!!!!!!!!!!!! Renderer interface !!!!!!!!!!!!!!!!!!!!!!!!!! -Result D3D12Device::getNativeHandle(NativeHandle* outHandle) +Result D3D12Device::getNativeDeviceHandles(InteropHandles* outHandles) { - *outHandle = NativeHandle::fromD3D12Handle(m_device); + outHandles->handles[0].handleValue = (uint64_t)m_device; + outHandles->handles[0].api = InteropHandleAPI::D3D12; return SLANG_OK; } @@ -4409,7 +4470,7 @@ Result D3D12Device::initialize(const Desc& desc) return SLANG_FAIL; } - if (desc.existingDeviceHandles.getD3D12Device() == 0) + if (desc.existingDeviceHandles.handles[0].handleValue == 0) { FlagCombiner combiner; // TODO: we should probably provide a command-line option @@ -4442,7 +4503,7 @@ Result D3D12Device::initialize(const Desc& desc) else { // Store the existing device handle in desc in m_deviceInfo - m_deviceInfo.m_device = (ID3D12Device*)desc.existingDeviceHandles.getD3D12Device(); + m_deviceInfo.m_device = (ID3D12Device*)desc.existingDeviceHandles.handles[0].handleValue; } // Set the device @@ -4942,6 +5003,23 @@ Result D3D12Device::createTextureResource(const ITextureResource::Desc& descIn, return SLANG_OK; } +Result D3D12Device::createTextureFromNativeHandle(InteropHandle handle, const ITextureResource::Desc& srcDesc, ITextureResource** outResource) +{ + RefPtr<TextureResourceImpl> texture(new TextureResourceImpl(srcDesc)); + + if (handle.api == InteropHandleAPI::D3D12) + { + texture->m_resource.setResource((ID3D12Resource*)handle.handleValue); + } + else + { + return SLANG_FAIL; + } + + returnComPtr(outResource, texture); + return SLANG_OK; +} + Result D3D12Device::createBufferResource(const IBufferResource::Desc& descIn, const void* initData, IBufferResource** outResource) { BufferResource::Desc srcDesc = fixupBufferDesc(descIn); @@ -4960,7 +5038,24 @@ Result D3D12Device::createBufferResource(const IBufferResource::Desc& descIn, co bufferDesc.Flags |= _calcResourceFlags(srcDesc.allowedStates); const D3D12_RESOURCE_STATES initialState = buffer->m_defaultState; - SLANG_RETURN_ON_FAIL(createBuffer(bufferDesc, initData, srcDesc.sizeInBytes, buffer->m_uploadResource, initialState, buffer->m_resource)); + SLANG_RETURN_ON_FAIL(createBuffer(bufferDesc, initData, srcDesc.sizeInBytes, buffer->m_uploadResource, initialState, buffer->m_resource, descIn.isShared)); + + returnComPtr(outResource, buffer); + return SLANG_OK; +} + +Result D3D12Device::createBufferFromNativeHandle(InteropHandle handle, const IBufferResource::Desc& srcDesc, IBufferResource** outResource) +{ + RefPtr<BufferResourceImpl> buffer(new BufferResourceImpl(srcDesc)); + + if (handle.api == InteropHandleAPI::D3D12) + { + buffer->m_resource.setResource((ID3D12Resource*)handle.handleValue); + } + else + { + return SLANG_FAIL; + } returnComPtr(outResource, buffer); return SLANG_OK; |
