yum-mirror/slang

Making it easier to work with shaders

git clone https://git.yummers.dev/yum-mirror/slang

Ellie Hermaszewskaformatf65d756bf

master
5.2 KiB167 linesraw
1// vk-command-queue.cpp
2#include "vk-command-queue.h"
3
4#include "vk-command-buffer.h"
5#include "vk-fence.h"
6#include "vk-transient-heap.h"
7
8namespace gfx
9{
10
11using namespace Slang;
12
13namespace vk
14{
15
16ICommandQueue* CommandQueueImpl::getInterface(const Guid& guid)
17{
18    if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_ICommandQueue)
19        return static_cast<ICommandQueue*>(this);
20    return nullptr;
21}
22
23CommandQueueImpl::~CommandQueueImpl()
24{
25    m_renderer->m_api.vkQueueWaitIdle(m_queue);
26
27    m_renderer->m_queueAllocCount--;
28    m_renderer->m_api.vkDestroySemaphore(m_renderer->m_api.m_device, m_semaphore, nullptr);
29}
30
31void CommandQueueImpl::init(DeviceImpl* renderer, VkQueue queue, uint32_t queueFamilyIndex)
32{
33    m_renderer = renderer;
34    m_queue = queue;
35    m_queueFamilyIndex = queueFamilyIndex;
36    VkSemaphoreCreateInfo semaphoreCreateInfo = {};
37    semaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
38    semaphoreCreateInfo.flags = 0;
39    m_renderer->m_api
40        .vkCreateSemaphore(m_renderer->m_api.m_device, &semaphoreCreateInfo, nullptr, &m_semaphore);
41}
42
43void CommandQueueImpl::waitOnHost()
44{
45    auto& vkAPI = m_renderer->m_api;
46    vkAPI.vkQueueWaitIdle(m_queue);
47}
48
49Result CommandQueueImpl::getNativeHandle(InteropHandle* outHandle)
50{
51    outHandle->api = InteropHandleAPI::D3D12;
52    outHandle->handleValue = (uint64_t)m_queue;
53    return SLANG_OK;
54}
55
56const CommandQueueImpl::Desc& CommandQueueImpl::getDesc()
57{
58    return m_desc;
59}
60
61Result CommandQueueImpl::waitForFenceValuesOnDevice(
62    GfxCount fenceCount,
63    IFence** fences,
64    uint64_t* waitValues)
65{
66    for (GfxIndex i = 0; i < fenceCount; ++i)
67    {
68        FenceWaitInfo waitInfo;
69        waitInfo.fence = static_cast<FenceImpl*>(fences[i]);
70        waitInfo.waitValue = waitValues[i];
71        m_pendingWaitFences.add(waitInfo);
72    }
73    return SLANG_OK;
74}
75
76void CommandQueueImpl::queueSubmitImpl(
77    uint32_t count,
78    ICommandBuffer* const* commandBuffers,
79    IFence* fence,
80    uint64_t valueToSignal)
81{
82    auto& vkAPI = m_renderer->m_api;
83    m_submitCommandBuffers.clear();
84    for (uint32_t i = 0; i < count; i++)
85    {
86        auto cmdBufImpl = static_cast<CommandBufferImpl*>(commandBuffers[i]);
87        if (!cmdBufImpl->m_isPreCommandBufferEmpty)
88            m_submitCommandBuffers.add(cmdBufImpl->m_preCommandBuffer);
89        auto vkCmdBuf = cmdBufImpl->m_commandBuffer;
90        m_submitCommandBuffers.add(vkCmdBuf);
91    }
92    Array<VkSemaphore, 2> signalSemaphores;
93    Array<uint64_t, 2> signalValues;
94    signalSemaphores.add(m_semaphore);
95    signalValues.add(0);
96
97    VkSubmitInfo submitInfo = {};
98    submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
99    VkPipelineStageFlags stageFlag[] = {
100        VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
101        VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT};
102    submitInfo.pWaitDstStageMask = stageFlag;
103    submitInfo.commandBufferCount = (uint32_t)m_submitCommandBuffers.getCount();
104    submitInfo.pCommandBuffers = m_submitCommandBuffers.getBuffer();
105    Array<VkSemaphore, 3> waitSemaphores;
106    Array<uint64_t, 3> waitValues;
107    for (auto s : m_pendingWaitSemaphores)
108    {
109        if (s != VK_NULL_HANDLE)
110        {
111            waitSemaphores.add(s);
112            waitValues.add(0);
113        }
114    }
115    for (auto& fenceWait : m_pendingWaitFences)
116    {
117        waitSemaphores.add(fenceWait.fence->m_semaphore);
118        waitValues.add(fenceWait.waitValue);
119    }
120    m_pendingWaitFences.clear();
121    VkTimelineSemaphoreSubmitInfo timelineSubmitInfo = {
122        VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO};
123    if (fence)
124    {
125        auto fenceImpl = static_cast<FenceImpl*>(fence);
126        signalSemaphores.add(fenceImpl->m_semaphore);
127        signalValues.add(valueToSignal);
128        submitInfo.pNext = &timelineSubmitInfo;
129        timelineSubmitInfo.signalSemaphoreValueCount = (uint32_t)signalValues.getCount();
130        timelineSubmitInfo.pSignalSemaphoreValues = signalValues.getBuffer();
131        timelineSubmitInfo.waitSemaphoreValueCount = (uint32_t)waitValues.getCount();
132        timelineSubmitInfo.pWaitSemaphoreValues = waitValues.getBuffer();
133    }
134    submitInfo.waitSemaphoreCount = (uint32_t)waitSemaphores.getCount();
135    if (submitInfo.waitSemaphoreCount)
136    {
137        submitInfo.pWaitSemaphores = waitSemaphores.getBuffer();
138    }
139    submitInfo.signalSemaphoreCount = (uint32_t)signalSemaphores.getCount();
140    submitInfo.pSignalSemaphores = signalSemaphores.getBuffer();
141
142    VkFence vkFence = VK_NULL_HANDLE;
143    if (count)
144    {
145        auto commandBufferImpl = static_cast<CommandBufferImpl*>(commandBuffers[0]);
146        vkFence = commandBufferImpl->m_transientHeap->getCurrentFence();
147        vkAPI.vkResetFences(vkAPI.m_device, 1, &vkFence);
148        commandBufferImpl->m_transientHeap->advanceFence();
149    }
150    vkAPI.vkQueueSubmit(m_queue, 1, &submitInfo, vkFence);
151    m_pendingWaitSemaphores[0] = m_semaphore;
152    m_pendingWaitSemaphores[1] = VK_NULL_HANDLE;
153}
154
155void CommandQueueImpl::executeCommandBuffers(
156    GfxCount count,
157    ICommandBuffer* const* commandBuffers,
158    IFence* fence,
159    uint64_t valueToSignal)
160{
161    if (count == 0 && fence == nullptr)
162        return;
163    queueSubmitImpl(count, commandBuffers, fence, valueToSignal);
164}
165
166} // namespace vk
167} // namespace gfx