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 | |
| 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')
| -rw-r--r-- | tools/gfx/cuda/render-cuda.cpp | 75 | ||||
| -rw-r--r-- | tools/gfx/d3d12/render-d3d12.cpp | 121 | ||||
| -rw-r--r-- | tools/gfx/debug-layer.cpp | 73 | ||||
| -rw-r--r-- | tools/gfx/debug-layer.h | 22 | ||||
| -rw-r--r-- | tools/gfx/renderer-shared.cpp | 61 | ||||
| -rw-r--r-- | tools/gfx/renderer-shared.h | 26 | ||||
| -rw-r--r-- | tools/gfx/vulkan/render-vk.cpp | 57 |
7 files changed, 378 insertions, 57 deletions
diff --git a/tools/gfx/cuda/render-cuda.cpp b/tools/gfx/cuda/render-cuda.cpp index c7b16fc66..2dc1bc1e1 100644 --- a/tools/gfx/cuda/render-cuda.cpp +++ b/tools/gfx/cuda/render-cuda.cpp @@ -186,6 +186,7 @@ public: uint64_t getBindlessHandle() { return (uint64_t)m_cudaMemory; } + void* m_cudaExternalMemory = nullptr; void* m_cudaMemory = nullptr; RefPtr<CUDAContext> m_cudaContext; @@ -195,9 +196,10 @@ public: return (DeviceAddress)m_cudaMemory; } - virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(NativeHandle* outHandle) override + virtual SLANG_NO_THROW Result SLANG_MCALL getNativeResourceHandle(InteropHandle* outHandle) override { - *outHandle = getBindlessHandle(); + outHandle->handleValue = getBindlessHandle(); + outHandle->api = InteropHandleAPI::CUDA; return SLANG_OK; } }; @@ -242,9 +244,10 @@ public: RefPtr<CUDAContext> m_cudaContext; - virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(NativeHandle* outHandle) override + virtual SLANG_NO_THROW Result SLANG_MCALL getNativeResourceHandle(InteropHandle* outHandle) override { - *outHandle = getBindlessHandle(); + outHandle->handleValue = getBindlessHandle(); + outHandle->api = InteropHandleAPI::CUDA; return SLANG_OK; } }; @@ -892,6 +895,13 @@ private: String m_adapterName; public: + virtual SLANG_NO_THROW Result SLANG_MCALL getNativeDeviceHandles(InteropHandles* outHandles) override + { + outHandles->handles[0].handleValue = (uint64_t)m_device; + outHandles->handles[0].api = InteropHandleAPI::CUDA; + return SLANG_OK; + } + class CommandQueueImpl; class CommandBufferImpl @@ -1332,6 +1342,8 @@ public: m_context = new CUDAContext(); + int count = -1; + cuDeviceGetCount(&count); SLANG_CUDA_RETURN_ON_FAIL(cuDeviceGet(&m_device, m_deviceIndex)); SLANG_CUDA_RETURN_WITH_REPORT_ON_FAIL( @@ -1810,6 +1822,59 @@ public: return SLANG_OK; } + virtual SLANG_NO_THROW Result SLANG_MCALL createBufferFromSharedHandle( + InteropHandle handle, + const IBufferResource::Desc& desc, + IBufferResource** outResource) override + { + if (handle.handleValue == 0) + { + *outResource = nullptr; + return SLANG_OK; + } + + RefPtr<MemoryCUDAResource> resource = new MemoryCUDAResource(desc); + resource->m_cudaContext = m_context; + + // CUDA manages sharing of buffers through the idea of an + // "external memory" object, which represents the relationship + // with another API's objects. In order to create this external + // memory association, we first need to fill in a descriptor struct. + cudaExternalMemoryHandleDesc externalMemoryHandleDesc; + memset(&externalMemoryHandleDesc, 0, sizeof(externalMemoryHandleDesc)); + // TODO: Change according to the type of handle being passed in + externalMemoryHandleDesc.type = cudaExternalMemoryHandleTypeD3D12Resource; + externalMemoryHandleDesc.handle.win32.handle = (void*)handle.handleValue; + externalMemoryHandleDesc.size = desc.sizeInBytes; + externalMemoryHandleDesc.flags = cudaExternalMemoryDedicated; + + // Once we have filled in the descriptor, we can request + // that CUDA create the required association between the + // external buffer and its own memory. + cudaExternalMemory_t externalMemory; + SLANG_CUDA_RETURN_ON_FAIL(cudaImportExternalMemory(&externalMemory, &externalMemoryHandleDesc)); + resource->m_cudaExternalMemory = externalMemory; + + // The CUDA "external memory" handle is not itself a device + // pointer, so we need to query for a suitable device address + // for the buffer with another call. + // + // Just as for the external memory, we fill in a descriptor + // structure (although in this case we only need to specify + // the size). + cudaExternalMemoryBufferDesc bufferDesc; + memset(&bufferDesc, 0, sizeof(bufferDesc)); + bufferDesc.size = desc.sizeInBytes; + + // Finally, we can "map" the buffer to get a device address. + void* deviceAddress; + SLANG_CUDA_RETURN_ON_FAIL(cudaExternalMemoryGetMappedBuffer(&deviceAddress, externalMemory, &bufferDesc)); + resource->m_cudaMemory = deviceAddress; + + returnComPtr(outResource, resource); + return SLANG_OK; + } + virtual SLANG_NO_THROW Result SLANG_MCALL createTextureView( ITextureResource* texture, IResourceView::Desc const& desc, IResourceView** outView) override { @@ -2157,7 +2222,7 @@ SlangResult SLANG_MCALL createCUDADevice(const IDevice::Desc* desc, IDevice** ou { SLANG_UNUSED(desc); *outDevice = nullptr; - return SLANG_OK; + return SLANG_FAIL; } #endif 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; diff --git a/tools/gfx/debug-layer.cpp b/tools/gfx/debug-layer.cpp index 19504aaa4..e01773c30 100644 --- a/tools/gfx/debug-layer.cpp +++ b/tools/gfx/debug-layer.cpp @@ -287,9 +287,9 @@ void validateAccelerationStructureBuildInputs( } } -Result DebugDevice::getNativeHandle(NativeHandle* outHandle) +Result DebugDevice::getNativeDeviceHandles(InteropHandles* outHandles) { - return baseObject->getNativeHandle(outHandle); + return baseObject->getNativeDeviceHandles(outHandles); } Result DebugDevice::getFeatures(const char** outFeatures, UInt bufferSize, UInt* outFeatureCount) @@ -355,6 +355,21 @@ Result DebugDevice::createTextureResource( return result; } +Result DebugDevice::createTextureFromNativeHandle( + InteropHandle handle, + const ITextureResource::Desc& srcDesc, + ITextureResource** outResource) +{ + SLANG_GFX_API_FUNC; + + RefPtr<DebugTextureResource> outObject = new DebugTextureResource(); + auto result = baseObject->createTextureFromNativeHandle(handle, srcDesc, outObject->baseObject.writeRef()); + if (SLANG_FAILED(result)) + return result; + returnComPtr(outResource, outObject); + return result; +} + Result DebugDevice::createBufferResource( const IBufferResource::Desc& desc, const void* initData, @@ -363,8 +378,37 @@ Result DebugDevice::createBufferResource( SLANG_GFX_API_FUNC; RefPtr<DebugBufferResource> outObject = new DebugBufferResource(); - auto result = - baseObject->createBufferResource(desc, initData, outObject->baseObject.writeRef()); + auto result = baseObject->createBufferResource(desc, initData, outObject->baseObject.writeRef()); + if (SLANG_FAILED(result)) + return result; + returnComPtr(outResource, outObject); + return result; +} + +Result DebugDevice::createBufferFromNativeHandle( + InteropHandle handle, + const IBufferResource::Desc& srcDesc, + IBufferResource** outResource) +{ + SLANG_GFX_API_FUNC; + + RefPtr<DebugBufferResource> outObject = new DebugBufferResource(); + auto result = baseObject->createBufferFromNativeHandle(handle, srcDesc, outObject->baseObject.writeRef()); + if (SLANG_FAILED(result)) + return result; + returnComPtr(outResource, outObject); + return result; +} + +Result DebugDevice::createBufferFromSharedHandle( + InteropHandle handle, + const IBufferResource::Desc& srcDesc, + IBufferResource** outResource) +{ + SLANG_GFX_API_FUNC; + + RefPtr<DebugBufferResource> outObject = new DebugBufferResource(); + auto result = baseObject->createBufferFromSharedHandle(handle, srcDesc, outObject->baseObject.writeRef()); if (SLANG_FAILED(result)) return result; returnComPtr(outResource, outObject); @@ -744,10 +788,16 @@ DeviceAddress DebugBufferResource::getDeviceAddress() return baseObject->getDeviceAddress(); } -Result DebugBufferResource::getNativeHandle(NativeHandle* outHandle) +Result DebugBufferResource::getNativeResourceHandle(InteropHandle* outHandle) { SLANG_GFX_API_FUNC; - return baseObject->getNativeHandle(outHandle); + return baseObject->getNativeResourceHandle(outHandle); +} + +Result DebugBufferResource::getSharedHandle(InteropHandle* outHandle) +{ + SLANG_GFX_API_FUNC; + return baseObject->getSharedHandle(outHandle); } Result DebugBufferResource::setDebugName(const char* name) @@ -774,9 +824,16 @@ ITextureResource::Desc* DebugTextureResource::getDesc() return baseObject->getDesc(); } -Result DebugTextureResource::getNativeHandle(NativeHandle* outHandle) +Result DebugTextureResource::getNativeResourceHandle(InteropHandle* outHandle) { - return baseObject->getNativeHandle(outHandle); + SLANG_GFX_API_FUNC; + return baseObject->getNativeResourceHandle(outHandle); +} + +Result DebugTextureResource::getSharedHandle(InteropHandle* outHandle) +{ + SLANG_GFX_API_FUNC; + return baseObject->getSharedHandle(outHandle); } Result DebugTextureResource::setDebugName(const char* name) diff --git a/tools/gfx/debug-layer.h b/tools/gfx/debug-layer.h index 9be3aca20..f1167fe63 100644 --- a/tools/gfx/debug-layer.h +++ b/tools/gfx/debug-layer.h @@ -40,7 +40,7 @@ public: public: DebugDevice(); IDevice* getInterface(const Slang::Guid& guid); - virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(NativeHandle* outHandle) override; + virtual SLANG_NO_THROW Result SLANG_MCALL getNativeDeviceHandles(InteropHandles* outHandles) override; virtual SLANG_NO_THROW bool SLANG_MCALL hasFeature(const char* feature) override; virtual SLANG_NO_THROW Result SLANG_MCALL getFeatures(const char** outFeatures, UInt bufferSize, UInt* outFeatureCount) override; @@ -56,10 +56,22 @@ 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 createBufferFromSharedHandle( + InteropHandle handle, + const IBufferResource::Desc& srcDesc, + IBufferResource** outResource) override; virtual SLANG_NO_THROW Result SLANG_MCALL createSamplerState(ISamplerState::Desc const& desc, ISamplerState** outSampler) override; virtual SLANG_NO_THROW Result SLANG_MCALL createTextureView( @@ -157,7 +169,9 @@ public: virtual SLANG_NO_THROW Type SLANG_MCALL getType() override; virtual SLANG_NO_THROW Desc* SLANG_MCALL getDesc() override; virtual SLANG_NO_THROW DeviceAddress SLANG_MCALL getDeviceAddress() override; - virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(NativeHandle* outHandle) override; + virtual SLANG_NO_THROW Result SLANG_MCALL getNativeResourceHandle(InteropHandle* outHandle) override; + virtual SLANG_NO_THROW Result SLANG_MCALL getSharedHandle(InteropHandle* outHandle) override; + virtual SLANG_NO_THROW Result SLANG_MCALL setDebugName(const char* name) override; virtual SLANG_NO_THROW const char* SLANG_MCALL getDebugName() override; }; @@ -171,7 +185,9 @@ public: ITextureResource* getInterface(const Slang::Guid& guid); virtual SLANG_NO_THROW Type SLANG_MCALL getType() override; virtual SLANG_NO_THROW Desc* SLANG_MCALL getDesc() override; - virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(NativeHandle* outHandle) override; + virtual SLANG_NO_THROW Result SLANG_MCALL getNativeResourceHandle(InteropHandle* outHandle) override; + virtual SLANG_NO_THROW Result SLANG_MCALL getSharedHandle(InteropHandle* outHandle) override; + virtual SLANG_NO_THROW Result SLANG_MCALL setDebugName(const char* name) override; virtual SLANG_NO_THROW const char* SLANG_MCALL getDebugName() override; }; diff --git a/tools/gfx/renderer-shared.cpp b/tools/gfx/renderer-shared.cpp index 64f3f318c..7dbee8ed5 100644 --- a/tools/gfx/renderer-shared.cpp +++ b/tools/gfx/renderer-shared.cpp @@ -76,10 +76,18 @@ IResource* BufferResource::getInterface(const Slang::Guid& guid) SLANG_NO_THROW IResource::Type SLANG_MCALL BufferResource::getType() { return m_type; } SLANG_NO_THROW IBufferResource::Desc* SLANG_MCALL BufferResource::getDesc() { return &m_desc; } -Result BufferResource::getNativeHandle(NativeHandle* outHandle) +Result BufferResource::getNativeResourceHandle(InteropHandle* outHandle) { - *outHandle = NULL; - return SLANG_OK; + outHandle->handleValue = 0; + outHandle->api = InteropHandleAPI::Unknown; + return SLANG_FAIL; +} + +Result BufferResource::getSharedHandle(InteropHandle* outHandle) +{ + outHandle->api = InteropHandleAPI::Unknown; + outHandle->handleValue = 0; + return SLANG_FAIL; } IResource* TextureResource::getInterface(const Slang::Guid& guid) @@ -93,9 +101,17 @@ IResource* TextureResource::getInterface(const Slang::Guid& guid) SLANG_NO_THROW IResource::Type SLANG_MCALL TextureResource::getType() { return m_type; } SLANG_NO_THROW ITextureResource::Desc* SLANG_MCALL TextureResource::getDesc() { return &m_desc; } -Result TextureResource::getNativeHandle(NativeHandle* outHandle) +Result TextureResource::getNativeResourceHandle(InteropHandle* outHandle) +{ + outHandle->handleValue = 0; + outHandle->api = InteropHandleAPI::Unknown; + return SLANG_FAIL; +} + +Result TextureResource::getSharedHandle(InteropHandle* outHandle) { - *outHandle = NULL; + outHandle->api = InteropHandleAPI::Unknown; + outHandle->handleValue = 0; return SLANG_OK; } @@ -275,9 +291,8 @@ SLANG_NO_THROW Result SLANG_MCALL RendererBase::initialize(const Desc& desc) return SLANG_OK; } -SLANG_NO_THROW Result SLANG_MCALL RendererBase::getNativeHandle(NativeHandle* outHandle) +SLANG_NO_THROW Result SLANG_MCALL RendererBase::getNativeDeviceHandles(InteropHandles* outHandles) { - *outHandle = {}; return SLANG_OK; } @@ -332,6 +347,38 @@ SLANG_NO_THROW Result SLANG_MCALL RendererBase::getSlangSession(slang::ISession* return SLANG_OK; } +SLANG_NO_THROW Result SLANG_MCALL RendererBase::createTextureFromNativeHandle( + InteropHandle handle, + const ITextureResource::Desc& srcDesc, + ITextureResource** outResource) +{ + SLANG_UNUSED(handle); + SLANG_UNUSED(srcDesc); + SLANG_UNUSED(outResource); + return SLANG_E_NOT_AVAILABLE; +} + +SLANG_NO_THROW Result SLANG_MCALL RendererBase::createBufferFromNativeHandle( + InteropHandle handle, + const IBufferResource::Desc& srcDesc, + IBufferResource** outResource) +{ + SLANG_UNUSED(handle); + SLANG_UNUSED(srcDesc); + SLANG_UNUSED(outResource); + return SLANG_E_NOT_AVAILABLE; +} + +SLANG_NO_THROW Result SLANG_MCALL RendererBase::createBufferFromSharedHandle( + InteropHandle handle, + const IBufferResource::Desc& srcDesc, + IBufferResource** outResource) +{ + SLANG_UNUSED(srcDesc); + SLANG_UNUSED(outResource); + return SLANG_E_NOT_AVAILABLE; +} + SLANG_NO_THROW Result SLANG_MCALL RendererBase::createShaderObject( slang::TypeReflection* type, ShaderObjectContainerType container, diff --git a/tools/gfx/renderer-shared.h b/tools/gfx/renderer-shared.h index 11e80dbaa..504f49bd7 100644 --- a/tools/gfx/renderer-shared.h +++ b/tools/gfx/renderer-shared.h @@ -200,6 +200,7 @@ protected: {} IResource::Type m_type; + InteropHandle sharedHandle = {}; Slang::String m_debugName; }; @@ -220,7 +221,9 @@ public: virtual SLANG_NO_THROW IResource::Type SLANG_MCALL getType() SLANG_OVERRIDE; virtual SLANG_NO_THROW IBufferResource::Desc* SLANG_MCALL getDesc() SLANG_OVERRIDE; - virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(NativeHandle* outHandle) SLANG_OVERRIDE; + virtual SLANG_NO_THROW Result SLANG_MCALL getNativeResourceHandle(InteropHandle* outHandle) SLANG_OVERRIDE; + virtual SLANG_NO_THROW Result SLANG_MCALL getSharedHandle(InteropHandle* outHandle) SLANG_OVERRIDE; + virtual SLANG_NO_THROW Result SLANG_MCALL setDebugName(const char* name) override { m_debugName = name; @@ -252,7 +255,9 @@ public: virtual SLANG_NO_THROW IResource::Type SLANG_MCALL getType() SLANG_OVERRIDE; virtual SLANG_NO_THROW ITextureResource::Desc* SLANG_MCALL getDesc() SLANG_OVERRIDE; - virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(NativeHandle* outHandle) SLANG_OVERRIDE; + virtual SLANG_NO_THROW Result SLANG_MCALL getNativeResourceHandle(InteropHandle* outHandle) SLANG_OVERRIDE; + virtual SLANG_NO_THROW Result SLANG_MCALL getSharedHandle(InteropHandle* outHandle) SLANG_OVERRIDE; + virtual SLANG_NO_THROW Result SLANG_MCALL setDebugName(const char* name) override { m_debugName = name; @@ -1167,7 +1172,7 @@ class RendererBase : public IDevice, public Slang::ComObject public: SLANG_COM_OBJECT_IUNKNOWN_ALL - virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(NativeHandle* outHandle) SLANG_OVERRIDE; + virtual SLANG_NO_THROW Result SLANG_MCALL getNativeDeviceHandles(InteropHandles* outHandles) SLANG_OVERRIDE; virtual SLANG_NO_THROW Result SLANG_MCALL getFeatures( const char** outFeatures, UInt bufferSize, UInt* outFeatureCount) SLANG_OVERRIDE; virtual SLANG_NO_THROW bool SLANG_MCALL hasFeature(const char* featureName) SLANG_OVERRIDE; @@ -1176,6 +1181,21 @@ public: virtual SLANG_NO_THROW Result SLANG_MCALL getSlangSession(slang::ISession** outSlangSession) SLANG_OVERRIDE; IDevice* getInterface(const Slang::Guid& guid); + virtual SLANG_NO_THROW Result SLANG_MCALL createTextureFromNativeHandle( + InteropHandle handle, + const ITextureResource::Desc& srcDesc, + ITextureResource** outResource) SLANG_OVERRIDE; + + virtual SLANG_NO_THROW Result SLANG_MCALL createBufferFromNativeHandle( + InteropHandle handle, + const IBufferResource::Desc& srcDesc, + IBufferResource** outResource) SLANG_OVERRIDE; + + virtual SLANG_NO_THROW Result SLANG_MCALL createBufferFromSharedHandle( + InteropHandle handle, + const IBufferResource::Desc& srcDesc, + IBufferResource** outResource) SLANG_OVERRIDE; + virtual SLANG_NO_THROW Result SLANG_MCALL createShaderObject( slang::TypeReflection* type, ShaderObjectContainerType containerType, diff --git a/tools/gfx/vulkan/render-vk.cpp b/tools/gfx/vulkan/render-vk.cpp index 1b538f992..b68812af6 100644 --- a/tools/gfx/vulkan/render-vk.cpp +++ b/tools/gfx/vulkan/render-vk.cpp @@ -54,7 +54,7 @@ public: kMaxDescriptorSets = 8, }; // Renderer implementation - Result initVulkanInstanceAndDevice(NativeHandle handles, bool useValidationLayer); + Result initVulkanInstanceAndDevice(const InteropHandle* handles, bool useValidationLayer); virtual SLANG_NO_THROW Result SLANG_MCALL initialize(const Desc& desc) override; virtual SLANG_NO_THROW Result SLANG_MCALL createTransientResourceHeap( const ITransientResourceHeap::Desc& desc, @@ -138,7 +138,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; /// Dtor ~VKDevice(); @@ -208,9 +208,17 @@ public: m_buffer.m_api->m_device, &info); } - 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_buffer.m_buffer; + outHandle->handleValue = (uint64_t)m_buffer.m_buffer; + outHandle->api = InteropHandleAPI::Vulkan; + return SLANG_OK; + } + + virtual SLANG_NO_THROW Result SLANG_MCALL getSharedHandle(InteropHandle* outHandle) override + { + outHandle->api = InteropHandleAPI::Vulkan; + outHandle->handleValue = 0; return SLANG_OK; } }; @@ -240,9 +248,17 @@ public: bool m_isWeakImageReference = false; RefPtr<VKDevice> m_device; - 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_image; + outHandle->api = InteropHandleAPI::Vulkan; + return SLANG_OK; + } + + virtual SLANG_NO_THROW Result SLANG_MCALL getSharedHandle(InteropHandle* outHandle) override { - *outHandle = (uint64_t)m_image; + outHandle->api = InteropHandleAPI::Vulkan; + outHandle->handleValue = 0; return SLANG_OK; } }; @@ -5419,12 +5435,12 @@ VKDevice::~VKDevice() if (m_device != VK_NULL_HANDLE) { - if (m_desc.existingDeviceHandles.getVkDevice() == 0) + if (m_desc.existingDeviceHandles.handles[2].handleValue == 0) m_api.vkDestroyDevice(m_device, nullptr); m_device = VK_NULL_HANDLE; if (m_debugReportCallback != VK_NULL_HANDLE) m_api.vkDestroyDebugReportCallbackEXT(m_api.m_instance, m_debugReportCallback, nullptr); - if (m_api.m_instance != VK_NULL_HANDLE && m_desc.existingDeviceHandles.getVkInstance() == 0) + if (m_api.m_instance != VK_NULL_HANDLE && m_desc.existingDeviceHandles.handles[0].handleValue == 0) m_api.vkDestroyInstance(m_api.m_instance, nullptr); } } @@ -5503,20 +5519,25 @@ VkPipelineShaderStageCreateInfo VKDevice::compileEntryPoint( // !!!!!!!!!!!!!!!!!!!!!!!!!!!! Renderer interface !!!!!!!!!!!!!!!!!!!!!!!!!! -Result VKDevice::getNativeHandle(NativeHandle* outHandle) +Result VKDevice::getNativeDeviceHandles(InteropHandles* outHandles) { - *outHandle = NativeHandle::fromVulkanHandles((uint64_t)m_api.m_instance, (uint64_t)m_api.m_physicalDevice, (uint64_t)m_api.m_device); + outHandles->handles[0].handleValue = (uint64_t)m_api.m_instance; + outHandles->handles[0].api = InteropHandleAPI::Vulkan; + outHandles->handles[1].handleValue = (uint64_t)m_api.m_physicalDevice; + outHandles->handles[1].api = InteropHandleAPI::Vulkan; + outHandles->handles[2].handleValue = (uint64_t)m_api.m_device; + outHandles->handles[2].api = InteropHandleAPI::Vulkan; return SLANG_OK; } -Result VKDevice::initVulkanInstanceAndDevice(const NativeHandle handles, bool useValidationLayer) +Result VKDevice::initVulkanInstanceAndDevice(const InteropHandle* handles, bool useValidationLayer) { m_features.clear(); m_queueAllocCount = 0; VkInstance instance = VK_NULL_HANDLE; - if (handles.getVkInstance() == 0) + if (handles[0].handleValue == 0) { VkApplicationInfo applicationInfo = { VK_STRUCTURE_TYPE_APPLICATION_INFO }; applicationInfo.pApplicationName = "slang-gfx"; @@ -5610,7 +5631,7 @@ Result VKDevice::initVulkanInstanceAndDevice(const NativeHandle handles, bool us } else { - instance = (VkInstance)handles.getVkInstance(); + instance = (VkInstance)handles[0].handleValue; } if (!instance) return SLANG_FAIL; @@ -5629,7 +5650,7 @@ Result VKDevice::initVulkanInstanceAndDevice(const NativeHandle handles, bool us VkPhysicalDevice physicalDevice = VK_NULL_HANDLE; Index selectedDeviceIndex = 0; - if (handles.getVkPhysicalDevice() == 0) + if (handles[1].handleValue == 0) { uint32_t numPhysicalDevices = 0; SLANG_VK_RETURN_ON_FAIL(m_api.vkEnumeratePhysicalDevices(instance, &numPhysicalDevices, nullptr)); @@ -5671,7 +5692,7 @@ Result VKDevice::initVulkanInstanceAndDevice(const NativeHandle handles, bool us } else { - physicalDevice = (VkPhysicalDevice)handles.getVkPhysicalDevice(); + physicalDevice = (VkPhysicalDevice)handles[1].handleValue; } SLANG_RETURN_ON_FAIL(m_api.initPhysicalDevice(physicalDevice)); @@ -5904,7 +5925,7 @@ Result VKDevice::initVulkanInstanceAndDevice(const NativeHandle handles, bool us m_queueFamilyIndex = m_api.findQueue(VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT); assert(m_queueFamilyIndex >= 0); - if (handles.getVkDevice() == 0) + if (handles[2].handleValue == 0) { float queuePriority = 0.0f; VkDeviceQueueCreateInfo queueCreateInfo = { VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO }; @@ -5922,7 +5943,7 @@ Result VKDevice::initVulkanInstanceAndDevice(const NativeHandle handles, bool us } else { - m_device = (VkDevice)handles.getVkDevice(); + m_device = (VkDevice)handles[2].handleValue; } SLANG_RETURN_ON_FAIL(m_api.initDeviceProcs(m_device)); @@ -5956,7 +5977,7 @@ SlangResult VKDevice::initialize(const Desc& desc) if (initDeviceResult != SLANG_OK) continue; descriptorSetAllocator.m_api = &m_api; - initDeviceResult = initVulkanInstanceAndDevice(desc.existingDeviceHandles, ENABLE_VALIDATION_LAYER != 0); + initDeviceResult = initVulkanInstanceAndDevice(desc.existingDeviceHandles.handles, ENABLE_VALIDATION_LAYER != 0); if (initDeviceResult == SLANG_OK) break; } |
