From 7a4f08ee0411220c728bf42832d98e72d72167e2 Mon Sep 17 00:00:00 2001 From: lucy96chen <47800040+lucy96chen@users.noreply.github.com> Date: Fri, 12 Nov 2021 15:43:23 -0800 Subject: Add support for buffer sharing from Vulkan to CUDA (#2008) * Added getSharedHandle() and additional code to handle shareable buffer creation to Buffer::init() and initVulkanInstanceAndDevice() for Vulkan; Modified createBufferFromSharedHandle() in CUDA to assign externalMemoryHandleDesc.type based on the type of handle being provided; Added an additional test case to get-shared-handle.cpp testing Vulkan to CUDA * Added createBufferFromNativeHandle() to Vulkan and enabled corresponding test * disable cuda * Fixed getSharedHandle() for D3D12 buffers assigning Win32 as the handle's source * Removed a dangling comment inside Buffer::init() * Added a missing override; Added code to check that a physical device supports the necessary external memory extensions before adding them to the deviceExtensions list; Added #if SLANG_WINDOWS_FAMILY guards around all Windows-specific code and sharedHandleVulkanToCUDA test (which uses said platform-specific code) * Added Windows check around vkGetMemoryWin32HandleKHR in vk-api.h * Added missing Windows check around BufferResourceImpl destructor * Added a temporary hack to ensure synchronization between devices, which solves an issue with buffer sharing resulting in incorrect values being read back; Added #if SLANG_WIN64 around all CUDA tests as the backend currently only supports running CUDA on 64-bit (despite devices being created successfully in a 32-bit config) --- tools/gfx-unit-test/get-shared-handle.cpp | 63 ++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 2 deletions(-) (limited to 'tools/gfx-unit-test/get-shared-handle.cpp') diff --git a/tools/gfx-unit-test/get-shared-handle.cpp b/tools/gfx-unit-test/get-shared-handle.cpp index 7c091abc8..06114f139 100644 --- a/tools/gfx-unit-test/get-shared-handle.cpp +++ b/tools/gfx-unit-test/get-shared-handle.cpp @@ -11,6 +11,8 @@ namespace gfx_test { void sharedHandleTestImpl(IDevice* srcDevice, IDevice* dstDevice, UnitTestContext* context) { + // Create a shareable buffer using srcDevice, get its handle, then create a buffer using the handle using + // dstDevice. Read back the buffer and check that its contents are correct. const int numberCount = 4; float initialData[] = { 0.0f, 1.0f, 2.0f, 3.0f }; IBufferResource::Desc bufferDesc = {}; @@ -36,6 +38,9 @@ namespace gfx_test GFX_CHECK_CALL_ABORT(srcBuffer->getSharedHandle(&sharedHandle)); ComPtr dstBuffer; GFX_CHECK_CALL_ABORT(dstDevice->createBufferFromSharedHandle(sharedHandle, bufferDesc, dstBuffer.writeRef())); + // Reading back the buffer from srcDevice to make sure it's been filled in before reading anything back from dstDevice + // TODO: Implement actual synchronization (and not this hacky solution) + compareComputeResult(srcDevice, srcBuffer, Slang::makeArray(0.0f, 1.0f, 2.0f, 3.0f)); InteropHandle testHandle; GFX_CHECK_CALL_ABORT(dstBuffer->getNativeResourceHandle(&testHandle)); @@ -43,6 +48,54 @@ namespace gfx_test SLANG_CHECK(testDesc->elementSize == sizeof(float)); SLANG_CHECK(testDesc->sizeInBytes == numberCount * sizeof(float)); compareComputeResult(dstDevice, dstBuffer, Slang::makeArray(0.0f, 1.0f, 2.0f, 3.0f)); + + // Check that dstBuffer can be successfully used in a compute dispatch using dstDevice. + Slang::ComPtr transientHeap; + ITransientResourceHeap::Desc transientHeapDesc = {}; + transientHeapDesc.constantBufferSize = 4096; + GFX_CHECK_CALL_ABORT( + dstDevice->createTransientResourceHeap(transientHeapDesc, transientHeap.writeRef())); + + ComPtr shaderProgram; + slang::ProgramLayout* slangReflection; + GFX_CHECK_CALL_ABORT(loadComputeProgram(dstDevice, shaderProgram, "compute-trivial", "computeMain", slangReflection)); + + ComputePipelineStateDesc pipelineDesc = {}; + pipelineDesc.program = shaderProgram.get(); + ComPtr pipelineState; + GFX_CHECK_CALL_ABORT( + dstDevice->createComputePipelineState(pipelineDesc, pipelineState.writeRef())); + + ComPtr bufferView; + IResourceView::Desc viewDesc = {}; + viewDesc.type = IResourceView::Type::UnorderedAccess; + viewDesc.format = Format::Unknown; + GFX_CHECK_CALL_ABORT(dstDevice->createBufferView(dstBuffer, viewDesc, bufferView.writeRef())); + + { + ICommandQueue::Desc queueDesc = { ICommandQueue::QueueType::Graphics }; + auto queue = dstDevice->createCommandQueue(queueDesc); + + auto commandBuffer = transientHeap->createCommandBuffer(); + auto encoder = commandBuffer->encodeComputeCommands(); + + auto rootObject = encoder->bindPipeline(pipelineState); + + ShaderCursor rootCursor(rootObject); + // Bind buffer view to the entry point. + rootCursor.getPath("buffer").setResource(bufferView); + + encoder->dispatchCompute(1, 1, 1); + encoder->endEncoding(); + commandBuffer->close(); + queue->executeCommandBuffer(commandBuffer); + queue->wait(); + } + + compareComputeResult( + dstDevice, + dstBuffer, + Slang::makeArray(1.0f, 2.0f, 3.0f, 4.0f)); } void sharedHandleTestAPI(UnitTestContext* context, Slang::RenderApiFlag::Enum srcApi, Slang::RenderApiFlag::Enum dstApi) @@ -56,11 +109,17 @@ namespace gfx_test sharedHandleTestImpl(srcDevice, dstDevice, context); } -#if 0 - // Temporarily disabled due to inconsistent test results on TC +#if SLANG_WIN64 SLANG_UNIT_TEST(sharedHandleD3D12ToCUDA) { sharedHandleTestAPI(unitTestContext, Slang::RenderApiFlag::D3D12, Slang::RenderApiFlag::CUDA); } + +#if SLANG_WINDOWS_FAMILY // TODO: Remove when Linux support is added + SLANG_UNIT_TEST(sharedHandleVulkanToCUDA) + { + sharedHandleTestAPI(unitTestContext, Slang::RenderApiFlag::Vulkan, Slang::RenderApiFlag::CUDA); + } +#endif #endif } -- cgit v1.2.3