yum-mirror/slang

Making it easier to work with shaders

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

Ellie Hermaszewskaformatf65d756bf

master
5.9 KiB217 linesraw
1// vk-device-queue.cpp
2#include "vk-device-queue.h"
3
4#include <assert.h>
5#include <stdio.h>
6#include <stdlib.h>
7
8namespace gfx
9{
10using namespace Slang;
11
12VulkanDeviceQueue::~VulkanDeviceQueue()
13{
14    destroy();
15}
16
17void VulkanDeviceQueue::destroy()
18{
19    if (m_api)
20    {
21        for (int i = 0; i < int(EventType::CountOf); ++i)
22        {
23            m_api->vkDestroySemaphore(m_api->m_device, m_semaphores[i], nullptr);
24        }
25
26        for (int i = 0; i < m_numCommandBuffers; i++)
27        {
28            m_api
29                ->vkFreeCommandBuffers(m_api->m_device, m_commandPools[i], 1, &m_commandBuffers[i]);
30            m_api->vkDestroyFence(m_api->m_device, m_fences[i].fence, nullptr);
31            m_api->vkDestroyCommandPool(m_api->m_device, m_commandPools[i], nullptr);
32        }
33        m_api = nullptr;
34    }
35}
36
37SlangResult VulkanDeviceQueue::init(const VulkanApi& api, VkQueue queue, int queueIndex)
38{
39    assert(m_api == nullptr);
40
41    for (int i = 0; i < int(EventType::CountOf); ++i)
42    {
43        m_semaphores[i] = VK_NULL_HANDLE;
44        m_currentSemaphores[i] = VK_NULL_HANDLE;
45    }
46
47    m_numCommandBuffers = kMaxCommandBuffers;
48    m_queueIndex = queueIndex;
49
50    m_queue = queue;
51
52    for (int i = 0; i < m_numCommandBuffers; i++)
53    {
54        VkCommandPoolCreateInfo poolCreateInfo = {};
55        poolCreateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
56        poolCreateInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
57
58        poolCreateInfo.queueFamilyIndex = queueIndex;
59
60        api.vkCreateCommandPool(api.m_device, &poolCreateInfo, nullptr, &m_commandPools[i]);
61
62        VkCommandBufferAllocateInfo commandInfo = {};
63        commandInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
64        commandInfo.commandPool = m_commandPools[i];
65        commandInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
66        commandInfo.commandBufferCount = 1;
67
68        VkFenceCreateInfo fenceCreateInfo = {};
69        fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
70        fenceCreateInfo.flags = 0; // VK_FENCE_CREATE_SIGNALED_BIT;
71        Fence& fence = m_fences[i];
72
73        api.vkAllocateCommandBuffers(api.m_device, &commandInfo, &m_commandBuffers[i]);
74
75        api.vkCreateFence(api.m_device, &fenceCreateInfo, nullptr, &fence.fence);
76        fence.active = false;
77        fence.value = 0;
78    }
79
80    VkSemaphoreCreateInfo semaphoreCreateInfo = {};
81    semaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
82
83    for (int i = 0; i < int(EventType::CountOf); ++i)
84    {
85        api.vkCreateSemaphore(api.m_device, &semaphoreCreateInfo, nullptr, &m_semaphores[i]);
86    }
87
88    // Set the api - also marks that the queue appears to be valid
89    m_api = &api;
90
91    // Second step of flush to prime command buffer
92    flushStepB();
93
94    return SLANG_OK;
95}
96
97void VulkanDeviceQueue::flushStepA()
98{
99    m_api->vkEndCommandBuffer(m_commandBuffer);
100
101    VkPipelineStageFlags stageFlags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
102
103    VkSubmitInfo submitInfo = {};
104    submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
105
106    // Wait semaphores
107    if (isCurrent(EventType::BeginFrame))
108    {
109        submitInfo.waitSemaphoreCount = 1;
110        submitInfo.pWaitSemaphores = &m_currentSemaphores[int(EventType::BeginFrame)];
111    }
112
113    submitInfo.pWaitDstStageMask = &stageFlags;
114    submitInfo.commandBufferCount = 1;
115    submitInfo.pCommandBuffers = &m_commandBuffer;
116
117    // Signal semaphores
118    if (isCurrent(EventType::EndFrame))
119    {
120        submitInfo.signalSemaphoreCount = 1;
121        submitInfo.pSignalSemaphores = &m_currentSemaphores[int(EventType::EndFrame)];
122    }
123
124    Fence& fence = m_fences[m_commandBufferIndex];
125
126    m_api->vkQueueSubmit(m_queue, 1, &submitInfo, fence.fence);
127
128    // mark signaled fence value
129    fence.value = m_nextFenceValue;
130    fence.active = true;
131
132    // increment fence value
133    m_nextFenceValue++;
134
135    // No longer waiting on this semaphore
136    makeCompleted(EventType::BeginFrame);
137    makeCompleted(EventType::EndFrame);
138}
139
140void VulkanDeviceQueue::_updateFenceAtIndex(int fenceIndex, bool blocking)
141{
142    Fence& fence = m_fences[fenceIndex];
143
144    if (fence.active)
145    {
146        uint64_t timeout = blocking ? ~uint64_t(0) : 0;
147
148        if (VK_SUCCESS ==
149            m_api->vkWaitForFences(m_api->m_device, 1, &fence.fence, VK_TRUE, timeout))
150        {
151            m_api->vkResetFences(m_api->m_device, 1, &fence.fence);
152
153            fence.active = false;
154
155            if (fence.value > m_lastFenceCompleted)
156            {
157                m_lastFenceCompleted = fence.value;
158            }
159        }
160    }
161}
162
163void VulkanDeviceQueue::flushStepB()
164{
165    m_commandBufferIndex = (m_commandBufferIndex + 1) % m_numCommandBuffers;
166    m_commandBuffer = m_commandBuffers[m_commandBufferIndex];
167    m_commandPool = m_commandPools[m_commandBufferIndex];
168
169    // non-blocking update of fence values
170    for (int i = 0; i < m_numCommandBuffers; ++i)
171    {
172        _updateFenceAtIndex(i, false);
173    }
174
175    // blocking update of fence values
176    _updateFenceAtIndex(m_commandBufferIndex, true);
177
178    m_api->vkResetCommandPool(m_api->m_device, m_commandPool, 0);
179
180    VkCommandBufferBeginInfo beginInfo = {};
181    beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
182    beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
183
184    m_api->vkBeginCommandBuffer(m_commandBuffer, &beginInfo);
185}
186
187void VulkanDeviceQueue::flush()
188{
189    flushStepA();
190    flushStepB();
191}
192
193void VulkanDeviceQueue::flushAndWait()
194{
195    flush();
196    waitForIdle();
197}
198
199VkSemaphore VulkanDeviceQueue::getSemaphore(EventType eventType)
200{
201    return m_semaphores[int(eventType)];
202}
203
204VkSemaphore VulkanDeviceQueue::makeCurrent(EventType eventType)
205{
206    assert(!isCurrent(eventType));
207    VkSemaphore semaphore = m_semaphores[int(eventType)];
208    m_currentSemaphores[int(eventType)] = semaphore;
209    return semaphore;
210}
211
212void VulkanDeviceQueue::makeCompleted(EventType eventType)
213{
214    m_currentSemaphores[int(eventType)] = VK_NULL_HANDLE;
215}
216
217} // namespace gfx