summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2021-12-07 13:45:49 -0800
committerGitHub <noreply@github.com>2021-12-07 13:45:49 -0800
commit90d8af888b40c83b33f9f0c037bd2ab8c19a35f4 (patch)
tree21ada472ea0d768352f46da7db64f9dc449d1209 /tools
parent646eecc6af878ea7682c814c15b4e838c3231ee3 (diff)
gfx: D3D12 and VK Fence implementation. (#2048)
* gfx: D3D12 and VK Fence implementation. * Fix. * Update project files. * Revert project file changes. * Remove project files Co-authored-by: Yong He <yhe@nvidia.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/gfx-unit-test/buffer-barrier-test.cpp2
-rw-r--r--tools/gfx-unit-test/compute-smoke.cpp2
-rw-r--r--tools/gfx-unit-test/create-buffer-from-handle.cpp2
-rw-r--r--tools/gfx-unit-test/existing-device-handle-test.cpp2
-rw-r--r--tools/gfx-unit-test/format-unit-tests.cpp2
-rw-r--r--tools/gfx-unit-test/get-shared-handle.cpp2
-rw-r--r--tools/gfx-unit-test/mutable-shader-object.cpp2
-rw-r--r--tools/gfx-unit-test/root-mutable-shader-object.cpp2
-rw-r--r--tools/gfx/cuda/render-cuda.cpp8
-rw-r--r--tools/gfx/d3d12/render-d3d12.cpp108
-rw-r--r--tools/gfx/debug-layer.cpp18
-rw-r--r--tools/gfx/debug-layer.h4
-rw-r--r--tools/gfx/immediate-renderer-base.cpp8
-rw-r--r--tools/gfx/renderer-shared.cpp7
-rw-r--r--tools/gfx/renderer-shared.h7
-rw-r--r--tools/gfx/vulkan/render-vk.cpp227
-rw-r--r--tools/gfx/vulkan/vk-api.cpp5
-rw-r--r--tools/gfx/vulkan/vk-api.h6
-rw-r--r--tools/render-test/render-test-main.cpp10
19 files changed, 371 insertions, 53 deletions
diff --git a/tools/gfx-unit-test/buffer-barrier-test.cpp b/tools/gfx-unit-test/buffer-barrier-test.cpp
index 4dd3aa9a8..f11dd1e5b 100644
--- a/tools/gfx-unit-test/buffer-barrier-test.cpp
+++ b/tools/gfx-unit-test/buffer-barrier-test.cpp
@@ -109,7 +109,7 @@ namespace gfx_test
encoder->endEncoding();
commandBuffer->close();
queue->executeCommandBuffer(commandBuffer);
- queue->wait();
+ queue->waitOnHost();
}
compareComputeResult(
diff --git a/tools/gfx-unit-test/compute-smoke.cpp b/tools/gfx-unit-test/compute-smoke.cpp
index 9a8298bf8..4dc3c685c 100644
--- a/tools/gfx-unit-test/compute-smoke.cpp
+++ b/tools/gfx-unit-test/compute-smoke.cpp
@@ -87,7 +87,7 @@ namespace gfx_test
encoder->endEncoding();
commandBuffer->close();
queue->executeCommandBuffer(commandBuffer);
- queue->wait();
+ queue->waitOnHost();
}
compareComputeResult(
diff --git a/tools/gfx-unit-test/create-buffer-from-handle.cpp b/tools/gfx-unit-test/create-buffer-from-handle.cpp
index 538dc492a..71b5f5ca2 100644
--- a/tools/gfx-unit-test/create-buffer-from-handle.cpp
+++ b/tools/gfx-unit-test/create-buffer-from-handle.cpp
@@ -78,7 +78,7 @@ namespace gfx_test
encoder->endEncoding();
commandBuffer->close();
queue->executeCommandBuffer(commandBuffer);
- queue->wait();
+ queue->waitOnHost();
}
compareComputeResult(
diff --git a/tools/gfx-unit-test/existing-device-handle-test.cpp b/tools/gfx-unit-test/existing-device-handle-test.cpp
index 652a530af..257ac1f37 100644
--- a/tools/gfx-unit-test/existing-device-handle-test.cpp
+++ b/tools/gfx-unit-test/existing-device-handle-test.cpp
@@ -72,7 +72,7 @@ namespace gfx_test
encoder->endEncoding();
commandBuffer->close();
queue->executeCommandBuffer(commandBuffer);
- queue->wait();
+ queue->waitOnHost();
}
compareComputeResult(
diff --git a/tools/gfx-unit-test/format-unit-tests.cpp b/tools/gfx-unit-test/format-unit-tests.cpp
index b499b67bd..d46a074e5 100644
--- a/tools/gfx-unit-test/format-unit-tests.cpp
+++ b/tools/gfx-unit-test/format-unit-tests.cpp
@@ -91,7 +91,7 @@ namespace gfx_test
encoder->endEncoding();
commandBuffer->close();
queue->executeCommandBuffer(commandBuffer);
- queue->wait();
+ queue->waitOnHost();
}
}
diff --git a/tools/gfx-unit-test/get-shared-handle.cpp b/tools/gfx-unit-test/get-shared-handle.cpp
index 06114f139..8b991f15c 100644
--- a/tools/gfx-unit-test/get-shared-handle.cpp
+++ b/tools/gfx-unit-test/get-shared-handle.cpp
@@ -89,7 +89,7 @@ namespace gfx_test
encoder->endEncoding();
commandBuffer->close();
queue->executeCommandBuffer(commandBuffer);
- queue->wait();
+ queue->waitOnHost();
}
compareComputeResult(
diff --git a/tools/gfx-unit-test/mutable-shader-object.cpp b/tools/gfx-unit-test/mutable-shader-object.cpp
index efaf95761..8e3838620 100644
--- a/tools/gfx-unit-test/mutable-shader-object.cpp
+++ b/tools/gfx-unit-test/mutable-shader-object.cpp
@@ -104,7 +104,7 @@ namespace gfx_test
commandBuffer->close();
queue->executeCommandBuffer(commandBuffer);
- queue->wait();
+ queue->waitOnHost();
}
compareComputeResult(
diff --git a/tools/gfx-unit-test/root-mutable-shader-object.cpp b/tools/gfx-unit-test/root-mutable-shader-object.cpp
index 8cd2abbd6..c20d3aa41 100644
--- a/tools/gfx-unit-test/root-mutable-shader-object.cpp
+++ b/tools/gfx-unit-test/root-mutable-shader-object.cpp
@@ -99,7 +99,7 @@ namespace gfx_test
commandBuffer->close();
queue->executeCommandBuffer(commandBuffer);
- queue->wait();
+ queue->waitOnHost();
}
compareComputeResult(
diff --git a/tools/gfx/cuda/render-cuda.cpp b/tools/gfx/cuda/render-cuda.cpp
index a3c288ab0..7abf51ef3 100644
--- a/tools/gfx/cuda/render-cuda.cpp
+++ b/tools/gfx/cuda/render-cuda.cpp
@@ -1212,7 +1212,7 @@ public:
}
}
- virtual SLANG_NO_THROW void SLANG_MCALL wait() override
+ virtual SLANG_NO_THROW void SLANG_MCALL waitOnHost() override
{
auto resultCode = cuStreamSynchronize(stream);
if (resultCode != cudaSuccess)
@@ -1220,6 +1220,12 @@ public:
}
virtual SLANG_NO_THROW Result SLANG_MCALL
+ waitForFences(uint32_t fenceCount, IFence** fences, uint64_t* waitValues) override
+ {
+ return SLANG_FAIL;
+ }
+
+ virtual SLANG_NO_THROW Result SLANG_MCALL
getNativeHandle(NativeHandle* outHandle) override
{
*outHandle = (uint64_t)stream;
diff --git a/tools/gfx/d3d12/render-d3d12.cpp b/tools/gfx/d3d12/render-d3d12.cpp
index e8dadfbbb..371d22002 100644
--- a/tools/gfx/d3d12/render-d3d12.cpp
+++ b/tools/gfx/d3d12/render-d3d12.cpp
@@ -144,6 +144,16 @@ public:
virtual SLANG_NO_THROW Result SLANG_MCALL createQueryPool(
const IQueryPool::Desc& desc, IQueryPool** outState) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ createFence(const IFence::Desc& desc, IFence** outFence) override;
+
+ virtual SLANG_NO_THROW Result SLANG_MCALL waitForFences(
+ uint32_t fenceCount,
+ IFence** fences,
+ uint64_t* fenceValues,
+ bool waitForAll,
+ uint64_t timeout) override;
+
virtual SLANG_NO_THROW SlangResult SLANG_MCALL readTextureResource(
ITextureResource* resource,
ResourceState state,
@@ -3780,6 +3790,65 @@ public:
}
};
+ class FenceImpl : public FenceBase
+ {
+ public:
+ ComPtr<ID3D12Fence> m_fence;
+ HANDLE m_waitEvent = 0;
+
+ ~FenceImpl()
+ {
+ if (m_waitEvent)
+ CloseHandle(m_waitEvent);
+ }
+
+ HANDLE getWaitEvent()
+ {
+ if (m_waitEvent)
+ return m_waitEvent;
+ m_waitEvent = CreateEventEx(
+ nullptr,
+ nullptr,
+ 0,
+ EVENT_ALL_ACCESS);
+ return m_waitEvent;
+ }
+
+ Result init(D3D12Device* device, const IFence::Desc& desc)
+ {
+ SLANG_RETURN_ON_FAIL(device->m_device->CreateFence(
+ desc.initialValue,
+ desc.isShared ? D3D12_FENCE_FLAG_SHARED : D3D12_FENCE_FLAG_NONE,
+ IID_PPV_ARGS(m_fence.writeRef())));
+ return SLANG_OK;
+ }
+
+ virtual SLANG_NO_THROW Result SLANG_MCALL getCurrentValue(uint64_t* outValue) override
+ {
+ *outValue = m_fence->GetCompletedValue();
+ return SLANG_OK;
+ }
+
+ virtual SLANG_NO_THROW Result SLANG_MCALL setCurrentValue(uint64_t value) override
+ {
+ SLANG_RETURN_ON_FAIL(m_fence->Signal(value));
+ return SLANG_OK;
+ }
+
+ virtual SLANG_NO_THROW Result SLANG_MCALL getSharedHandle(InteropHandle* outHandle) override
+ {
+ outHandle->handleValue = 0;
+ return SLANG_FAIL;
+ }
+
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ getNativeHandle(InteropHandle* outNativeHandle) override
+ {
+ outNativeHandle->handleValue = 0;
+ return SLANG_FAIL;
+ }
+ };
+
class CommandQueueImpl
: public ICommandQueue
, public ComObject
@@ -3823,7 +3892,7 @@ public:
}
~CommandQueueImpl()
{
- wait();
+ waitOnHost();
CloseHandle(globalWaitHandle);
m_renderer->m_queueIndexAllocator.free((int)m_queueIndex, 1);
}
@@ -3861,7 +3930,7 @@ public:
ResetEvent(globalWaitHandle);
}
- virtual SLANG_NO_THROW void SLANG_MCALL wait() override
+ virtual SLANG_NO_THROW void SLANG_MCALL waitOnHost() override
{
m_fenceValue++;
m_d3dQueue->Signal(m_fence, m_fenceValue);
@@ -3871,6 +3940,17 @@ public:
}
virtual SLANG_NO_THROW Result SLANG_MCALL
+ waitForFences(uint32_t fenceCount, IFence** fences, uint64_t* waitValues) override
+ {
+ for (uint32_t i = 0; i < fenceCount; ++i)
+ {
+ auto fenceImpl = static_cast<FenceImpl*>(fences[i]);
+ m_d3dQueue->Wait(fenceImpl->m_fence.get(), waitValues[i]);
+ }
+ return SLANG_OK;
+ }
+
+ virtual SLANG_NO_THROW Result SLANG_MCALL
getNativeHandle(NativeHandle* outHandle) override
{
*outHandle = (uint64_t)m_d3dQueue.get();
@@ -6205,6 +6285,30 @@ Result D3D12Device::createQueryPool(const IQueryPool::Desc& desc, IQueryPool** o
}
}
+Result D3D12Device::createFence(const IFence::Desc& desc, IFence** outFence)
+{
+ RefPtr<FenceImpl> fence = new FenceImpl();
+ SLANG_RETURN_ON_FAIL(fence->init(this, desc));
+ returnComPtr(outFence, fence);
+ return SLANG_OK;
+}
+
+Result D3D12Device::waitForFences(
+ uint32_t fenceCount, IFence** fences, uint64_t* fenceValues, bool waitForAll, uint64_t timeout)
+{
+ List<HANDLE> waitHandles;
+ for (uint32_t i = 0; i < fenceCount; ++i)
+ {
+ auto fenceImpl = static_cast<FenceImpl*>(fences[i]);
+ waitHandles.add(fenceImpl->getWaitEvent());
+ SLANG_RETURN_ON_FAIL(fenceImpl->m_fence->SetEventOnCompletion(fenceValues[i], fenceImpl->getWaitEvent()));
+ }
+ auto result = WaitForMultipleObjects(fenceCount, waitHandles.getBuffer(), waitForAll ? TRUE : FALSE, (DWORD)timeout);
+ if (result == WAIT_TIMEOUT)
+ return SLANG_E_TIME_OUT;
+ return result == WAIT_FAILED ? SLANG_FAIL : SLANG_OK;
+}
+
#if SLANG_GFX_HAS_DXR_SUPPORT
class D3D12AccelerationStructureImpl
diff --git a/tools/gfx/debug-layer.cpp b/tools/gfx/debug-layer.cpp
index 831566c7c..470b63599 100644
--- a/tools/gfx/debug-layer.cpp
+++ b/tools/gfx/debug-layer.cpp
@@ -1467,10 +1467,26 @@ void DebugCommandQueue::executeCommandBuffers(uint32_t count, ICommandBuffer* co
baseObject->executeCommandBuffers(count, innerCommandBuffers.getBuffer(), getInnerObj(fence), valueToSignal);
}
-void DebugCommandQueue::wait() { baseObject->wait(); }
+void DebugCommandQueue::waitOnHost()
+{
+ SLANG_GFX_API_FUNC;
+ baseObject->waitOnHost();
+}
+
+Result DebugCommandQueue::waitForFences(uint32_t fenceCount, IFence** fences, uint64_t* waitValues)
+{
+ SLANG_GFX_API_FUNC;
+ List<IFence*> innerFences;
+ for (uint32_t i = 0; i < fenceCount; ++i)
+ {
+ innerFences.add(getInnerObj(fences[i]));
+ }
+ return baseObject->waitForFences(fenceCount, innerFences.getBuffer(), waitValues);
+}
Result DebugCommandQueue::getNativeHandle(NativeHandle* outHandle)
{
+ SLANG_GFX_API_FUNC;
return baseObject->getNativeHandle(outHandle);
}
diff --git a/tools/gfx/debug-layer.h b/tools/gfx/debug-layer.h
index f61917835..e0a97ee1c 100644
--- a/tools/gfx/debug-layer.h
+++ b/tools/gfx/debug-layer.h
@@ -560,7 +560,9 @@ public:
virtual SLANG_NO_THROW const Desc& SLANG_MCALL getDesc() override;
virtual SLANG_NO_THROW void SLANG_MCALL
executeCommandBuffers(uint32_t count, ICommandBuffer* const* commandBuffers, IFence* fence, uint64_t valueToSignal) override;
- virtual SLANG_NO_THROW void SLANG_MCALL wait() override;
+ virtual SLANG_NO_THROW void SLANG_MCALL waitOnHost() override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ waitForFences(uint32_t fenceCount, IFence** fences, uint64_t* waitValues) override;
virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(NativeHandle* outHandle) override;
};
diff --git a/tools/gfx/immediate-renderer-base.cpp b/tools/gfx/immediate-renderer-base.cpp
index 360370aa0..34cc70b74 100644
--- a/tools/gfx/immediate-renderer-base.cpp
+++ b/tools/gfx/immediate-renderer-base.cpp
@@ -593,7 +593,13 @@ public:
static_cast<ImmediateRendererBase*>(m_renderer.get())->endCommandBuffer(info);
}
- virtual SLANG_NO_THROW void SLANG_MCALL wait() override { getRenderer()->waitForGpu(); }
+ virtual SLANG_NO_THROW void SLANG_MCALL waitOnHost() override { getRenderer()->waitForGpu(); }
+
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ waitForFences(uint32_t fenceCount, IFence** fences, uint64_t* waitValues) override
+ {
+ return SLANG_FAIL;
+ }
virtual SLANG_NO_THROW Result SLANG_MCALL
getNativeHandle(NativeHandle* outHandle) override
diff --git a/tools/gfx/renderer-shared.cpp b/tools/gfx/renderer-shared.cpp
index c212f21eb..101e02d47 100644
--- a/tools/gfx/renderer-shared.cpp
+++ b/tools/gfx/renderer-shared.cpp
@@ -65,6 +65,13 @@ return gfx::StageType::TO
}
}
+IFence* FenceBase::getInterface(const Slang::Guid& guid)
+{
+ if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_IFence)
+ return static_cast<IFence*>(this);
+ return nullptr;
+}
+
IResource* BufferResource::getInterface(const Slang::Guid& guid)
{
if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_IResource ||
diff --git a/tools/gfx/renderer-shared.h b/tools/gfx/renderer-shared.h
index 1d5d1860e..e7ea1b7f5 100644
--- a/tools/gfx/renderer-shared.h
+++ b/tools/gfx/renderer-shared.h
@@ -185,6 +185,13 @@ void returnRefPtrMove(TDest** outPtr, Slang::RefPtr<TImpl>& refPtr)
gfx::StageType translateStage(SlangStage slangStage);
+class FenceBase : public IFence, public Slang::ComObject
+{
+public:
+ SLANG_COM_OBJECT_IUNKNOWN_ALL
+ IFence* getInterface(const Slang::Guid& guid);
+};
+
class Resource : public Slang::ComObject
{
public:
diff --git a/tools/gfx/vulkan/render-vk.cpp b/tools/gfx/vulkan/render-vk.cpp
index 59f12cb41..25609ec6e 100644
--- a/tools/gfx/vulkan/render-vk.cpp
+++ b/tools/gfx/vulkan/render-vk.cpp
@@ -146,6 +146,16 @@ public:
virtual SLANG_NO_THROW Result SLANG_MCALL getTextureAllocationInfo(
const ITextureResource::Desc& desc, size_t* outSize, size_t* outAlignment) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ createFence(const IFence::Desc& desc, IFence** outFence) override;
+
+ virtual SLANG_NO_THROW Result SLANG_MCALL waitForFences(
+ uint32_t fenceCount,
+ IFence** fences,
+ uint64_t* fenceValues,
+ bool waitForAll,
+ uint64_t timeout) override;
+
void waitForGpu();
virtual SLANG_NO_THROW const DeviceInfo& SLANG_MCALL getDeviceInfo() const override
@@ -270,13 +280,90 @@ public:
{
return SLANG_FAIL;
}
- SLANG_RETURN_ON_FAIL(vkCreateSharedHandle(api->m_device, &info, (HANDLE*)&outHandle->handleValue) != VK_SUCCESS);
+ SLANG_VK_RETURN_ON_FAIL(
+ vkCreateSharedHandle(api->m_device, &info, (HANDLE*)&outHandle->handleValue));
#endif
outHandle->api = InteropHandleAPI::Vulkan;
return SLANG_OK;
}
};
+ class FenceImpl : public FenceBase
+ {
+ public:
+ VkSemaphore m_semaphore = VK_NULL_HANDLE;
+ RefPtr<VKDevice> m_device;
+
+ FenceImpl(VKDevice* device)
+ : m_device(device)
+ {
+
+ }
+
+ ~FenceImpl()
+ {
+ if (m_semaphore)
+ {
+ m_device->m_api.vkDestroySemaphore(m_device->m_api.m_device, m_semaphore, nullptr);
+ }
+ }
+
+ Result init(const IFence::Desc& desc)
+ {
+ if (!m_device->m_api.m_extendedFeatures.timelineFeatures.timelineSemaphore)
+ return SLANG_E_NOT_AVAILABLE;
+
+ VkSemaphoreTypeCreateInfo timelineCreateInfo;
+ timelineCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO;
+ timelineCreateInfo.pNext = nullptr;
+ timelineCreateInfo.semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE;
+ timelineCreateInfo.initialValue = desc.initialValue;
+
+ VkSemaphoreCreateInfo createInfo;
+ createInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+ createInfo.pNext = &timelineCreateInfo;
+ createInfo.flags = 0;
+
+ SLANG_VK_RETURN_ON_FAIL(m_device->m_api.vkCreateSemaphore(
+ m_device->m_api.m_device, &createInfo, nullptr, &m_semaphore));
+
+ return SLANG_OK;
+ }
+
+ virtual SLANG_NO_THROW Result SLANG_MCALL getCurrentValue(uint64_t* outValue) override
+ {
+ SLANG_VK_RETURN_ON_FAIL(m_device->m_api.vkGetSemaphoreCounterValue(
+ m_device->m_api.m_device, m_semaphore, outValue));
+ return SLANG_OK;
+ }
+
+ virtual SLANG_NO_THROW Result SLANG_MCALL setCurrentValue(uint64_t value) override
+ {
+ VkSemaphoreSignalInfo signalInfo;
+ signalInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO;
+ signalInfo.pNext = NULL;
+ signalInfo.semaphore = m_semaphore;
+ signalInfo.value = 2;
+
+ SLANG_VK_RETURN_ON_FAIL(
+ m_device->m_api.vkSignalSemaphore(m_device->m_api.m_device, &signalInfo));
+ return SLANG_OK;
+ }
+
+ virtual SLANG_NO_THROW Result SLANG_MCALL getSharedHandle(InteropHandle* outHandle) override
+ {
+ outHandle->handleValue = 0;
+ return SLANG_FAIL;
+ }
+
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ getNativeHandle(InteropHandle* outNativeHandle) override
+ {
+ outNativeHandle->handleValue = 0;
+ return SLANG_FAIL;
+ }
+ };
+
class TextureResourceImpl : public TextureResource
{
public:
@@ -4817,40 +4904,37 @@ public:
RefPtr<VKDevice> m_renderer;
VkQueue m_queue;
uint32_t m_queueFamilyIndex;
+ struct FenceWaitInfo
+ {
+ RefPtr<FenceImpl> fence;
+ uint64_t waitValue;
+ };
+ List<FenceWaitInfo> m_pendingWaitFences;
VkSemaphore m_pendingWaitSemaphores[2] = {VK_NULL_HANDLE, VK_NULL_HANDLE};
List<VkCommandBuffer> m_submitCommandBuffers;
- static const int kSemaphoreCount = 32;
- uint32_t m_currentSemaphoreIndex;
- VkSemaphore m_semaphores[kSemaphoreCount];
+ VkSemaphore m_semaphore;
~CommandQueueImpl()
{
m_renderer->m_api.vkQueueWaitIdle(m_queue);
m_renderer->m_queueAllocCount--;
- for (int i = 0; i < kSemaphoreCount; i++)
- {
- m_renderer->m_api.vkDestroySemaphore(
- m_renderer->m_api.m_device, m_semaphores[i], nullptr);
- }
+ m_renderer->m_api.vkDestroySemaphore(
+ m_renderer->m_api.m_device, m_semaphore, nullptr);
}
void init(VKDevice* renderer, VkQueue queue, uint32_t queueFamilyIndex)
{
m_renderer = renderer;
- m_currentSemaphoreIndex = 0;
m_queue = queue;
m_queueFamilyIndex = queueFamilyIndex;
- for (int i = 0; i < kSemaphoreCount; i++)
- {
- VkSemaphoreCreateInfo semaphoreCreateInfo = {};
- semaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
- semaphoreCreateInfo.flags = 0;
- m_renderer->m_api.vkCreateSemaphore(
- m_renderer->m_api.m_device, &semaphoreCreateInfo, nullptr, &m_semaphores[i]);
- }
+ VkSemaphoreCreateInfo semaphoreCreateInfo = {};
+ semaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+ semaphoreCreateInfo.flags = 0;
+ m_renderer->m_api.vkCreateSemaphore(
+ m_renderer->m_api.m_device, &semaphoreCreateInfo, nullptr, &m_semaphore);
}
- virtual SLANG_NO_THROW void SLANG_MCALL wait() override
+ virtual SLANG_NO_THROW void SLANG_MCALL waitOnHost() override
{
auto& vkAPI = m_renderer->m_api;
vkAPI.vkQueueWaitIdle(m_queue);
@@ -4868,15 +4952,25 @@ public:
return m_desc;
}
- virtual SLANG_NO_THROW void SLANG_MCALL executeCommandBuffers(
- uint32_t count, ICommandBuffer* const* commandBuffers, IFence* fence, uint64_t valueToSignal) override
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ waitForFences(uint32_t fenceCount, IFence** fences, uint64_t* waitValues) override
{
- // TODO: implement fence signaling.
- assert(fence == nullptr);
-
- if (count == 0)
- return;
+ for (uint32_t i = 0; i < fenceCount; ++i)
+ {
+ FenceWaitInfo waitInfo;
+ waitInfo.fence = static_cast<FenceImpl*>(fences[i]);
+ waitInfo.waitValue = waitValues[i];
+ m_pendingWaitFences.add(waitInfo);
+ }
+ return SLANG_OK;
+ }
+ void queueSubmitImpl(
+ uint32_t count,
+ ICommandBuffer* const* commandBuffers,
+ IFence* fence,
+ uint64_t valueToSignal)
+ {
auto& vkAPI = m_renderer->m_api;
m_submitCommandBuffers.clear();
for (uint32_t i = 0; i < count; i++)
@@ -4887,7 +4981,11 @@ public:
auto vkCmdBuf = cmdBufImpl->m_commandBuffer;
m_submitCommandBuffers.add(vkCmdBuf);
}
- VkSemaphore signalSemaphore = m_semaphores[m_currentSemaphoreIndex];
+ Array<VkSemaphore, 2> signalSemaphores;
+ Array<uint64_t, 2> signalValues;
+ signalSemaphores.add(m_semaphore);
+ signalValues.add(0);
+
VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
VkPipelineStageFlags stageFlag[] = {
@@ -4895,32 +4993,58 @@ public:
submitInfo.pWaitDstStageMask = stageFlag;
submitInfo.commandBufferCount = (uint32_t)m_submitCommandBuffers.getCount();
submitInfo.pCommandBuffers = m_submitCommandBuffers.getBuffer();
- Array<VkSemaphore, 2> waitSemaphores;
+ Array<VkSemaphore, 3> waitSemaphores;
+ Array<uint64_t, 3> waitValues;
for (auto s : m_pendingWaitSemaphores)
{
if (s != VK_NULL_HANDLE)
{
waitSemaphores.add(s);
+ waitValues.add(0);
}
}
+ for (auto& fenceWait : m_pendingWaitFences)
+ {
+ waitSemaphores.add(fenceWait.fence->m_semaphore);
+ waitValues.add(fenceWait.waitValue);
+ }
+ m_pendingWaitFences.clear();
+ VkTimelineSemaphoreSubmitInfo timelineSubmitInfo = {
+ VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO};
+ if (fence)
+ {
+ auto fenceImpl = static_cast<FenceImpl*>(fence);
+ signalSemaphores.add(fenceImpl->m_semaphore);
+ signalValues.add(valueToSignal);
+ submitInfo.pNext = &timelineSubmitInfo;
+ timelineSubmitInfo.signalSemaphoreValueCount = (uint32_t)signalValues.getCount();
+ timelineSubmitInfo.pSignalSemaphoreValues = signalValues.getBuffer();
+ timelineSubmitInfo.waitSemaphoreValueCount = (uint32_t)waitValues.getCount();
+ timelineSubmitInfo.pWaitSemaphoreValues = waitValues.getBuffer();
+ }
submitInfo.waitSemaphoreCount = (uint32_t)waitSemaphores.getCount();
if (submitInfo.waitSemaphoreCount)
{
submitInfo.pWaitSemaphores = waitSemaphores.getBuffer();
}
- submitInfo.signalSemaphoreCount = 1;
- submitInfo.pSignalSemaphores = &signalSemaphore;
+ submitInfo.signalSemaphoreCount = (uint32_t)signalSemaphores.getCount();
+ submitInfo.pSignalSemaphores = signalSemaphores.getBuffer();
auto commandBufferImpl = static_cast<CommandBufferImpl*>(commandBuffers[0]);
auto vkFence = commandBufferImpl->m_transientHeap->getCurrentFence();
vkAPI.vkResetFences(vkAPI.m_device, 1, &vkFence);
vkAPI.vkQueueSubmit(m_queue, 1, &submitInfo, vkFence);
- m_pendingWaitSemaphores[0] = signalSemaphore;
+ m_pendingWaitSemaphores[0] = m_semaphore;
m_pendingWaitSemaphores[1] = VK_NULL_HANDLE;
commandBufferImpl->m_transientHeap->advanceFence();
+ }
- m_currentSemaphoreIndex++;
- m_currentSemaphoreIndex = m_currentSemaphoreIndex % kSemaphoreCount;
+ virtual SLANG_NO_THROW void SLANG_MCALL executeCommandBuffers(
+ uint32_t count, ICommandBuffer* const* commandBuffers, IFence* fence, uint64_t valueToSignal) override
+ {
+ if (count == 0 && fence == nullptr)
+ return;
+ queueSubmitImpl(count, commandBuffers, fence, valueToSignal);
}
};
@@ -5348,6 +5472,13 @@ public:
}
virtual SLANG_NO_THROW Result SLANG_MCALL present() override
{
+ // If there are pending fence wait operations, flush them as an
+ // empty vkQueueSubmit.
+ if (m_queue->m_pendingWaitFences.getCount() != 0)
+ {
+ m_queue->queueSubmitImpl(0, nullptr, nullptr, 0);
+ }
+
uint32_t swapChainIndices[] = {uint32_t(m_currentImageIndex)};
VkPresentInfoKHR presentInfo = {};
@@ -7802,4 +7933,34 @@ Result VKDevice::createQueryPool(
return SLANG_OK;
}
+Result VKDevice::createFence(const IFence::Desc& desc, IFence** outFence)
+{
+ RefPtr<FenceImpl> fence = new FenceImpl(this);
+ SLANG_RETURN_ON_FAIL(fence->init(desc));
+ returnComPtr(outFence, fence);
+ return SLANG_OK;
+}
+
+Result VKDevice::waitForFences(
+ uint32_t fenceCount, IFence** fences, uint64_t* fenceValues, bool waitForAll, uint64_t timeout)
+{
+ ShortList<VkSemaphore> semaphores;
+ for (uint32_t i = 0; i < fenceCount; ++i)
+ {
+ auto fenceImpl = static_cast<FenceImpl*>(fences[i]);
+ semaphores.add(fenceImpl->m_semaphore);
+ }
+ VkSemaphoreWaitInfo waitInfo;
+ waitInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO;
+ waitInfo.pNext = NULL;
+ waitInfo.flags = 0;
+ waitInfo.semaphoreCount = 1;
+ waitInfo.pSemaphores = semaphores.getArrayView().getBuffer();
+ waitInfo.pValues = fenceValues;
+ auto result = m_api.vkWaitSemaphores(m_api.m_device, &waitInfo, timeout);
+ if (result == VK_TIMEOUT)
+ return SLANG_E_TIME_OUT;
+ return result == VK_SUCCESS ? SLANG_OK : SLANG_FAIL;
+}
+
} // renderer_test
diff --git a/tools/gfx/vulkan/vk-api.cpp b/tools/gfx/vulkan/vk-api.cpp
index 7e1a9bae2..8f5e4235b 100644
--- a/tools/gfx/vulkan/vk-api.cpp
+++ b/tools/gfx/vulkan/vk-api.cpp
@@ -91,7 +91,10 @@ Slang::Result VulkanApi::initDeviceProcs(VkDevice device)
vkGetBufferDeviceAddressKHR = vkGetBufferDeviceAddressEXT;
if (!vkGetBufferDeviceAddress && vkGetBufferDeviceAddressKHR)
vkGetBufferDeviceAddress = vkGetBufferDeviceAddressKHR;
-
+ if (!vkGetSemaphoreCounterValue && vkGetSemaphoreCounterValueKHR)
+ vkGetSemaphoreCounterValue = vkGetSemaphoreCounterValueKHR;
+ if (!vkSignalSemaphore && vkSignalSemaphoreKHR)
+ vkSignalSemaphore = vkSignalSemaphoreKHR;
m_device = device;
return SLANG_OK;
}
diff --git a/tools/gfx/vulkan/vk-api.h b/tools/gfx/vulkan/vk-api.h
index 543ad90d1..6e7024752 100644
--- a/tools/gfx/vulkan/vk-api.h
+++ b/tools/gfx/vulkan/vk-api.h
@@ -179,6 +179,12 @@ namespace gfx {
x(vkCreateAccelerationStructureKHR) \
x(vkDestroyAccelerationStructureKHR) \
x(vkGetAccelerationStructureBuildSizesKHR) \
+ x(vkGetSemaphoreCounterValue) \
+ x(vkGetSemaphoreCounterValueKHR) \
+ x(vkSignalSemaphore) \
+ x(vkSignalSemaphoreKHR) \
+ x(vkWaitSemaphores) \
+ x(vkWaitSemaphoresKHR) \
/* */
#define VK_API_ALL_GLOBAL_PROCS(x) \
diff --git a/tools/render-test/render-test-main.cpp b/tools/render-test/render-test-main.cpp
index 96d0e4047..78fa149e8 100644
--- a/tools/render-test/render-test-main.cpp
+++ b/tools/render-test/render-test-main.cpp
@@ -751,7 +751,7 @@ void RenderTestApp::_initializeAccelerationStructure()
encoder->endEncoding();
commandBuffer->close();
m_queue->executeCommandBuffer(commandBuffer);
- m_queue->wait();
+ m_queue->waitOnHost();
uint64_t compactedSize = 0;
compactedSizeQuery->getResult(0, 1, &compactedSize);
@@ -774,7 +774,7 @@ void RenderTestApp::_initializeAccelerationStructure()
encoder->endEncoding();
commandBuffer->close();
m_queue->executeCommandBuffer(commandBuffer);
- m_queue->wait();
+ m_queue->waitOnHost();
}
// Build top level acceleration structure.
@@ -840,7 +840,7 @@ void RenderTestApp::_initializeAccelerationStructure()
encoder->endEncoding();
commandBuffer->close();
m_queue->executeCommandBuffer(commandBuffer);
- m_queue->wait();
+ m_queue->waitOnHost();
}
}
@@ -883,7 +883,7 @@ void RenderTestApp::finalize()
Result RenderTestApp::writeBindingOutput(const String& fileName)
{
// Wait until everything is complete
- m_queue->wait();
+ m_queue->waitOnHost();
FILE * f = fopen(fileName.getBuffer(), "wb");
if (!f)
@@ -993,7 +993,7 @@ Result RenderTestApp::update()
m_startTicks = Process::getClockTick();
m_queue->executeCommandBuffer(commandBuffer);
- m_queue->wait();
+ m_queue->waitOnHost();
// If we are in a mode where output is requested, we need to snapshot the back buffer here
if (m_options.outputPath.getLength() || m_options.performanceProfile)