diff options
Diffstat (limited to 'tools/gfx/vulkan/render-vk.cpp')
| -rw-r--r-- | tools/gfx/vulkan/render-vk.cpp | 227 |
1 files changed, 194 insertions, 33 deletions
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 |
