diff options
| author | lucy96chen <47800040+lucy96chen@users.noreply.github.com> | 2021-10-01 13:08:25 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-10-01 13:08:25 -0700 |
| commit | 35bca4cc432613af3926da3bed217a6baa9cbd26 (patch) | |
| tree | e07b9f779ea950666c2960c44eefdab7258ad312 | |
| parent | 6c6200f547c7387598743b23bb3c8f0d375d9494 (diff) | |
Add getNativeHandle() to ICommandQueue and ICommandBuffer (#1952)
* Added support for getting command buffer and command queue handles to ICommandBuffer and ICommandQueue; D3D12Device, VkDevice, and DebugDevice modifieid to implement this new functionality; immediate-renderer-base.cpp also modified to implement the new functions
* Removed excess boilerplate
* Changed readRef() to get() in D3D12 getNativeHandle() implementation for ICommandBuffer and ICommandQueue
* Added unit tests for new getNativeHandle() implementations, unfinished
* Queue test added; Minor cleanup changes
* getBufferHandleTestImpl() now closes the command buffer before returning
* Added getNativeHandle() implementations to CUDADevice
* Added comment clarifying that the Vulkan check is checking for a null handle, which is defined to be 0
| -rw-r--r-- | build/visual-studio/gfx-unit-test-tool/gfx-unit-test-tool.vcxproj | 2 | ||||
| -rw-r--r-- | build/visual-studio/gfx-unit-test-tool/gfx-unit-test-tool.vcxproj.filters | 6 | ||||
| -rw-r--r-- | slang-gfx.h | 13 | ||||
| -rw-r--r-- | tools/gfx-unit-test/get-buffer-handle-test.cpp | 98 | ||||
| -rw-r--r-- | tools/gfx-unit-test/get-queue-handle-test.cpp | 82 | ||||
| -rw-r--r-- | tools/gfx/cuda/render-cuda.cpp | 14 | ||||
| -rw-r--r-- | tools/gfx/d3d12/render-d3d12.cpp | 14 | ||||
| -rw-r--r-- | tools/gfx/debug-layer.cpp | 10 | ||||
| -rw-r--r-- | tools/gfx/debug-layer.h | 2 | ||||
| -rw-r--r-- | tools/gfx/immediate-renderer-base.cpp | 13 | ||||
| -rw-r--r-- | tools/gfx/vulkan/render-vk.cpp | 14 |
11 files changed, 267 insertions, 1 deletions
diff --git a/build/visual-studio/gfx-unit-test-tool/gfx-unit-test-tool.vcxproj b/build/visual-studio/gfx-unit-test-tool/gfx-unit-test-tool.vcxproj index 3dfb78cfb..ec0c7f3c5 100644 --- a/build/visual-studio/gfx-unit-test-tool/gfx-unit-test-tool.vcxproj +++ b/build/visual-studio/gfx-unit-test-tool/gfx-unit-test-tool.vcxproj @@ -274,6 +274,8 @@ <ItemGroup>
<ClCompile Include="..\..\..\tools\gfx-unit-test\compute-smoke.cpp" />
<ClCompile Include="..\..\..\tools\gfx-unit-test\existing-device-handle-test.cpp" />
+ <ClCompile Include="..\..\..\tools\gfx-unit-test\get-buffer-handle-test.cpp" />
+ <ClCompile Include="..\..\..\tools\gfx-unit-test\get-queue-handle-test.cpp" />
<ClCompile Include="..\..\..\tools\gfx-unit-test\gfx-test-util.cpp" />
<ClCompile Include="..\..\..\tools\unit-test\slang-unit-test.cpp" />
</ItemGroup>
diff --git a/build/visual-studio/gfx-unit-test-tool/gfx-unit-test-tool.vcxproj.filters b/build/visual-studio/gfx-unit-test-tool/gfx-unit-test-tool.vcxproj.filters index 3a86541bf..73763e62b 100644 --- a/build/visual-studio/gfx-unit-test-tool/gfx-unit-test-tool.vcxproj.filters +++ b/build/visual-studio/gfx-unit-test-tool/gfx-unit-test-tool.vcxproj.filters @@ -23,6 +23,12 @@ <ClCompile Include="..\..\..\tools\gfx-unit-test\existing-device-handle-test.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="..\..\..\tools\gfx-unit-test\get-buffer-handle-test.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\tools\gfx-unit-test\get-queue-handle-test.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
<ClCompile Include="..\..\..\tools\gfx-unit-test\gfx-test-util.cpp">
<Filter>Source Files</Filter>
</ClCompile>
diff --git a/slang-gfx.h b/slang-gfx.h index 82c3c3fa3..ac2b7b774 100644 --- a/slang-gfx.h +++ b/slang-gfx.h @@ -1225,6 +1225,9 @@ public: class ICommandBuffer : public ISlangUnknown { public: + // For D3D12, this is the pointer to the buffer. For Vulkan, this is the buffer itself. + typedef uint64_t NativeHandle; + // Only one encoder may be open at a time. User must call `ICommandEncoder::endEncoding` // before calling other `encode*Commands` methods. // Once `endEncoding` is called, the `ICommandEncoder` object becomes obsolete and is @@ -1270,6 +1273,8 @@ public: } virtual SLANG_NO_THROW void SLANG_MCALL close() = 0; + + virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(NativeHandle* outHandle) = 0; }; #define SLANG_UUID_ICommandBuffer \ { \ @@ -1287,6 +1292,10 @@ public: { QueueType type; }; + + // For D3D12, this is the pointer to the queue. For Vulkan, this is the queue itself. + typedef uint64_t NativeHandle; + virtual SLANG_NO_THROW const Desc& SLANG_MCALL getDesc() = 0; virtual SLANG_NO_THROW void SLANG_MCALL @@ -1296,6 +1305,8 @@ public: executeCommandBuffers(1, &commandBuffer); } virtual SLANG_NO_THROW void SLANG_MCALL wait() = 0; + + virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(NativeHandle* outHandle) = 0; }; #define SLANG_UUID_ICommandQueue \ { \ @@ -1425,7 +1436,7 @@ public: struct NativeHandle { public: - // The following functions create an ExistingDeviceHandles object containing the provided handles. + // The following functions return a NativeHandle object containing the provided handles. static NativeHandle fromVulkanHandles(uint64_t instance, uint64_t physicalDevice, uint64_t device) { NativeHandle handles = {}; diff --git a/tools/gfx-unit-test/get-buffer-handle-test.cpp b/tools/gfx-unit-test/get-buffer-handle-test.cpp new file mode 100644 index 000000000..c8bd9bca5 --- /dev/null +++ b/tools/gfx-unit-test/get-buffer-handle-test.cpp @@ -0,0 +1,98 @@ +#include "tools/unit-test/slang-unit-test.h" + +#include "slang-gfx.h" +#include "gfx-test-util.h" +#include "tools/gfx-util/shader-cursor.h" +#include "source/core/slang-basic.h" + +#if SLANG_WINDOWS_FAMILY +#include <d3d12.h> +#endif + +using namespace gfx; + +namespace gfx_test +{ + void getBufferHandleTestImpl(IDevice* device, UnitTestContext* context) + { + // We need to create a transient heap in order to create a command buffer. + Slang::ComPtr<ITransientResourceHeap> transientHeap; + ITransientResourceHeap::Desc transientHeapDesc = {}; + transientHeapDesc.constantBufferSize = 4096; + GFX_CHECK_CALL_ABORT( + device->createTransientResourceHeap(transientHeapDesc, transientHeap.writeRef())); + + auto commandBuffer = transientHeap->createCommandBuffer(); + struct CloseComandBufferRAII + { + ICommandBuffer* m_commandBuffer; + ~CloseComandBufferRAII() + { + m_commandBuffer->close(); + } + } closeCommandBufferRAII{ commandBuffer }; + ICommandBuffer::NativeHandle handle = 0; + GFX_CHECK_CALL_ABORT(commandBuffer->getNativeHandle(&handle)); + if (device->getDeviceInfo().deviceType == gfx::DeviceType::Vulkan) + { + // Check that the handle is not null, which is defined as 0. + SLANG_CHECK(handle != 0); + } +#if SLANG_WINDOWS_FAMILY + else + { + auto d3d12Handle = (ID3D12GraphicsCommandList*)handle; + Slang::ComPtr<ID3D12CommandList> testHandle; + GFX_CHECK_CALL_ABORT(d3d12Handle->QueryInterface<ID3D12CommandList>(testHandle.writeRef())); + } +#endif + } + + void getBufferHandleTestAPI(UnitTestContext* context, Slang::RenderApiFlag::Enum api) + { + if ((api & context->enabledApis) == 0) + { + SLANG_IGNORE_TEST; + } + Slang::ComPtr<IDevice> device; + IDevice::Desc deviceDesc = {}; + switch (api) + { + case Slang::RenderApiFlag::D3D11: + deviceDesc.deviceType = gfx::DeviceType::DirectX11; + break; + case Slang::RenderApiFlag::D3D12: + deviceDesc.deviceType = gfx::DeviceType::DirectX12; + break; + case Slang::RenderApiFlag::Vulkan: + deviceDesc.deviceType = gfx::DeviceType::Vulkan; + break; + default: + SLANG_IGNORE_TEST; + } + deviceDesc.slang.slangGlobalSession = context->slangGlobalSession; + const char* searchPaths[] = { "", "../../tools/gfx-unit-test", "tools/gfx-unit-test" }; + deviceDesc.slang.searchPathCount = (SlangInt)SLANG_COUNT_OF(searchPaths); + deviceDesc.slang.searchPaths = searchPaths; + auto createDeviceResult = gfxCreateDevice(&deviceDesc, device.writeRef()); + if (SLANG_FAILED(createDeviceResult)) + { + SLANG_IGNORE_TEST; + } + + getBufferHandleTestImpl(device, context); + } + +#if SLANG_WINDOWS_FAMILY + SLANG_UNIT_TEST(getBufferHandleD3D12) + { + return getBufferHandleTestAPI(unitTestContext, Slang::RenderApiFlag::D3D12); + } +#endif + + SLANG_UNIT_TEST(getBufferHandleVulkan) + { + return getBufferHandleTestAPI(unitTestContext, Slang::RenderApiFlag::Vulkan); + } + +} diff --git a/tools/gfx-unit-test/get-queue-handle-test.cpp b/tools/gfx-unit-test/get-queue-handle-test.cpp new file mode 100644 index 000000000..f16e740bf --- /dev/null +++ b/tools/gfx-unit-test/get-queue-handle-test.cpp @@ -0,0 +1,82 @@ +#include "tools/unit-test/slang-unit-test.h" + +#include "slang-gfx.h" +#include "gfx-test-util.h" +#include "tools/gfx-util/shader-cursor.h" +#include "source/core/slang-basic.h" + +#if SLANG_WINDOWS_FAMILY +#include <d3d12.h> +#endif + +using namespace gfx; + +namespace gfx_test +{ + void getQueueHandleTestImpl(IDevice* device, UnitTestContext* context) + { + ICommandQueue::Desc queueDesc = { ICommandQueue::QueueType::Graphics }; + auto queue = device->createCommandQueue(queueDesc); + ICommandQueue::NativeHandle handle; + GFX_CHECK_CALL_ABORT(queue->getNativeHandle(&handle)); + if (device->getDeviceInfo().deviceType == gfx::DeviceType::Vulkan) + { + // Check that the handle is not null, which is defined as 0. + SLANG_CHECK(handle != 0); + } +#if SLANG_WINDOWS_FAMILY + else + { + auto d3d12Queue = (ID3D12CommandQueue*)handle; + Slang::ComPtr<IUnknown> testHandle; + GFX_CHECK_CALL_ABORT(d3d12Queue->QueryInterface<IUnknown>(testHandle.writeRef())); + } +#endif + } + + void getQueueHandleTestAPI(UnitTestContext* context, Slang::RenderApiFlag::Enum api) + { + if ((api & context->enabledApis) == 0) + { + SLANG_IGNORE_TEST; + } + Slang::ComPtr<IDevice> device; + IDevice::Desc deviceDesc = {}; + switch (api) + { + case Slang::RenderApiFlag::D3D11: + deviceDesc.deviceType = gfx::DeviceType::DirectX11; + break; + case Slang::RenderApiFlag::D3D12: + deviceDesc.deviceType = gfx::DeviceType::DirectX12; + break; + case Slang::RenderApiFlag::Vulkan: + deviceDesc.deviceType = gfx::DeviceType::Vulkan; + break; + default: + SLANG_IGNORE_TEST; + } + deviceDesc.slang.slangGlobalSession = context->slangGlobalSession; + const char* searchPaths[] = { "", "../../tools/gfx-unit-test", "tools/gfx-unit-test" }; + deviceDesc.slang.searchPathCount = (SlangInt)SLANG_COUNT_OF(searchPaths); + deviceDesc.slang.searchPaths = searchPaths; + auto createDeviceResult = gfxCreateDevice(&deviceDesc, device.writeRef()); + if (SLANG_FAILED(createDeviceResult)) + { + SLANG_IGNORE_TEST; + } + + getQueueHandleTestImpl(device, context); + } + + SLANG_UNIT_TEST(getQueueHandleD3D12) + { + return getQueueHandleTestAPI(unitTestContext, Slang::RenderApiFlag::D3D12); + } + + SLANG_UNIT_TEST(getQueueHandleVulkan) + { + return getQueueHandleTestAPI(unitTestContext, Slang::RenderApiFlag::Vulkan); + } + +} diff --git a/tools/gfx/cuda/render-cuda.cpp b/tools/gfx/cuda/render-cuda.cpp index 9b99e5f26..ec6f1212a 100644 --- a/tools/gfx/cuda/render-cuda.cpp +++ b/tools/gfx/cuda/render-cuda.cpp @@ -1021,6 +1021,13 @@ public: } virtual SLANG_NO_THROW void SLANG_MCALL close() override {} + + virtual SLANG_NO_THROW Result SLANG_MCALL + getNativeHandle(NativeHandle* outHandle) override + { + *outHandle = 0; + return SLANG_OK; + } }; class CommandQueueImpl @@ -1079,6 +1086,13 @@ public: SLANG_CUDA_HANDLE_ERROR(resultCode); } + virtual SLANG_NO_THROW Result SLANG_MCALL + getNativeHandle(NativeHandle* outHandle) override + { + *outHandle = (uint64_t)stream; + return SLANG_OK; + } + public: void setPipelineState(IPipelineState* state) { diff --git a/tools/gfx/d3d12/render-d3d12.cpp b/tools/gfx/d3d12/render-d3d12.cpp index c867e156b..2d8c5fa10 100644 --- a/tools/gfx/d3d12/render-d3d12.cpp +++ b/tools/gfx/d3d12/render-d3d12.cpp @@ -3520,6 +3520,13 @@ public: #endif virtual SLANG_NO_THROW void SLANG_MCALL close() override { m_cmdList->Close(); } + + virtual SLANG_NO_THROW Result SLANG_MCALL + getNativeHandle(NativeHandle* outHandle) override + { + *outHandle = (uint64_t)m_cmdList.get(); + return SLANG_OK; + } }; class CommandQueueImpl @@ -3609,6 +3616,13 @@ public: m_fence->SetEventOnCompletion(m_fenceValue, globalWaitHandle); WaitForSingleObject(globalWaitHandle, INFINITE); } + + virtual SLANG_NO_THROW Result SLANG_MCALL + getNativeHandle(NativeHandle* outHandle) override + { + *outHandle = (uint64_t)m_d3dQueue.get(); + return SLANG_OK; + } }; class SwapchainImpl : public D3DSwapchainBase diff --git a/tools/gfx/debug-layer.cpp b/tools/gfx/debug-layer.cpp index 3e22bd510..74b319a08 100644 --- a/tools/gfx/debug-layer.cpp +++ b/tools/gfx/debug-layer.cpp @@ -814,6 +814,11 @@ void DebugCommandBuffer::close() baseObject->close(); } +Result DebugCommandBuffer::getNativeHandle(NativeHandle* outHandle) +{ + return baseObject->getNativeHandle(outHandle); +} + void DebugCommandBuffer::checkEncodersClosedBeforeNewEncoder() { if (m_renderCommandEncoder.isOpen || m_resourceCommandEncoder.isOpen || @@ -1160,6 +1165,11 @@ void DebugCommandQueue::executeCommandBuffers(uint32_t count, ICommandBuffer* co void DebugCommandQueue::wait() { baseObject->wait(); } +Result DebugCommandQueue::getNativeHandle(NativeHandle* outHandle) +{ + return baseObject->getNativeHandle(outHandle); +} + Result DebugTransientResourceHeap::synchronizeAndReset() { SLANG_GFX_API_FUNC; diff --git a/tools/gfx/debug-layer.h b/tools/gfx/debug-layer.h index 69ef5ffe2..88e0e5ecd 100644 --- a/tools/gfx/debug-layer.h +++ b/tools/gfx/debug-layer.h @@ -396,6 +396,7 @@ public: virtual SLANG_NO_THROW void SLANG_MCALL encodeRayTracingCommands(IRayTracingCommandEncoder** outEncoder) override; virtual SLANG_NO_THROW void SLANG_MCALL close() override; + virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(NativeHandle* outHandle) override; private: void checkEncodersClosedBeforeNewEncoder(); @@ -416,6 +417,7 @@ public: virtual SLANG_NO_THROW void SLANG_MCALL executeCommandBuffers(uint32_t count, ICommandBuffer* const* commandBuffers) override; virtual SLANG_NO_THROW void SLANG_MCALL wait() override; + virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(NativeHandle* outHandle) override; }; class DebugFramebuffer diff --git a/tools/gfx/immediate-renderer-base.cpp b/tools/gfx/immediate-renderer-base.cpp index fbe5ad423..e87c1e558 100644 --- a/tools/gfx/immediate-renderer-base.cpp +++ b/tools/gfx/immediate-renderer-base.cpp @@ -277,6 +277,13 @@ public: virtual SLANG_NO_THROW void SLANG_MCALL close() override { } + virtual SLANG_NO_THROW Result SLANG_MCALL + getNativeHandle(NativeHandle* outHandle) + { + *outHandle = 0; + return SLANG_OK; + } + void execute() { for (auto& cmd : m_writer.m_commands) @@ -412,6 +419,12 @@ public: } virtual SLANG_NO_THROW void SLANG_MCALL wait() override { getRenderer()->waitForGpu(); } + + virtual SLANG_NO_THROW Result SLANG_MCALL + getNativeHandle(NativeHandle* outHandle) override + { + return getRenderer()->m_queue->getNativeHandle(outHandle); + } }; using TransientResourceHeapImpl = diff --git a/tools/gfx/vulkan/render-vk.cpp b/tools/gfx/vulkan/render-vk.cpp index 186c7eb40..7af7d086f 100644 --- a/tools/gfx/vulkan/render-vk.cpp +++ b/tools/gfx/vulkan/render-vk.cpp @@ -4492,6 +4492,13 @@ public: } vkAPI.vkEndCommandBuffer(m_commandBuffer); } + + virtual SLANG_NO_THROW Result SLANG_MCALL + getNativeHandle(NativeHandle* outHandle) override + { + *outHandle = (uint64_t)m_commandBuffer; + return SLANG_OK; + } }; class CommandQueueImpl @@ -4551,6 +4558,13 @@ public: vkAPI.vkQueueWaitIdle(m_queue); } + virtual SLANG_NO_THROW Result SLANG_MCALL + getNativeHandle(NativeHandle* outHandle) override + { + *outHandle = (uint64_t)m_queue; + return SLANG_OK; + } + virtual SLANG_NO_THROW const Desc& SLANG_MCALL getDesc() override { return m_desc; |
