81c7a3cded00eac45adcb44db89fa7c66b172f3a
[platform/core/uifw/dali-core.git] / dali / graphics / vulkan / vulkan-queue.cpp
1 /*
2  * Copyright (c) 2017 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // INTERNAL INCLUDES
19 #include <dali/graphics/vulkan/vulkan-command-buffer.h>
20 #include <dali/graphics/vulkan/vulkan-fence.h>
21 #include <dali/graphics/vulkan/vulkan-graphics.h>
22 #include <dali/graphics/vulkan/vulkan-queue.h>
23
24 namespace Dali
25 {
26 namespace Graphics
27 {
28 namespace Vulkan
29 {
30
31 namespace
32 {
33 // this class is non-copyable, just movable
34 struct PrepareSemaphoresData
35 {
36   PrepareSemaphoresData()                             = default;
37   PrepareSemaphoresData(const PrepareSemaphoresData&) = delete;
38   PrepareSemaphoresData& operator=(const PrepareSemaphoresData&) = delete;
39   PrepareSemaphoresData(PrepareSemaphoresData&&)                 = default;
40   PrepareSemaphoresData& operator=(PrepareSemaphoresData&&) = default;
41
42   std::vector< vk::Semaphore >          signalSemaphores;
43   std::vector< vk::Semaphore >          waitSemaphores;
44   std::vector< vk::PipelineStageFlags > waitDstStageMasks;
45 };
46
47 // helper function converting size_t to required uint32_t
48 template< typename T >
49 inline uint32_t u32(T val)
50 {
51   return static_cast< uint32_t >(val);
52 }
53
54 inline PrepareSemaphoresData PrepareSemaphores(const std::vector< CommandBufferRef >& commandBuffers)
55 {
56   PrepareSemaphoresData retval{};
57   for(auto& cmdbufref : commandBuffers)
58   {
59     auto& cmdbuf = cmdbufref.get();
60     if(!retval.signalSemaphores.empty())
61     {
62       retval.signalSemaphores.insert(retval.signalSemaphores.end(),
63                                      cmdbuf.GetSignalSemaphores().begin(),
64                                      cmdbuf.GetSignalSemaphores().end());
65     }
66     if(!retval.waitSemaphores.empty())
67     {
68       retval.waitSemaphores.insert(retval.waitSemaphores.end(), cmdbuf.GetSWaitSemaphores().begin(),
69                                    cmdbuf.GetSWaitSemaphores().end());
70       retval.waitDstStageMasks.insert(retval.waitDstStageMasks.end(),
71                                       cmdbuf.GetWaitSemaphoreStages().begin(),
72                                       cmdbuf.GetWaitSemaphoreStages().end());
73     }
74   }
75   return std::move(retval);
76 }
77 }
78
79 // submission
80 Submission::Submission(Fence& fence) : mFences(fence)
81 {
82 }
83
84 bool Submission::WaitForFence(uint32_t timeout)
85 {
86   return mFences.get().Wait(timeout);
87 }
88
89 // queue
90 Queue::Queue(Graphics& graphics, vk::Queue queue, uint32_t queueFamilyIndex, uint32_t queueIndex,
91              vk::QueueFlags queueFlags)
92 : mGraphics(graphics), mQueue(queue), mFlags(queueFlags), mQueueFamilyIndex(queueFamilyIndex), mQueueIndex(queueIndex)
93 {
94 }
95
96 Queue::~Queue() // queues are non-destructible
97 {
98 }
99
100 std::unique_ptr< Submission > Queue::Submit(CommandBuffer& commandBuffer, Fence& fence)
101 {
102   auto buffers = std::vector< CommandBufferRef >({commandBuffer});
103   return Submit(buffers, fence);
104 }
105
106 #pragma GCC diagnostic push
107 #pragma GCC diagnostic ignored "-Wframe-larger-than="
108 std::unique_ptr< Submission > Queue::Submit(const std::vector< CommandBufferRef >& commandBuffers, Fence& fence)
109 {
110   // Prepare command buffers for submission
111   auto buffers = PrepareBuffers(commandBuffers);
112
113   auto semaphores = PrepareSemaphores(commandBuffers);
114
115   auto info = vk::SubmitInfo{};
116
117   /* semaphores per command buffer */
118   info.setCommandBufferCount(u32(commandBuffers.size()));
119   info.setPCommandBuffers(buffers.data());
120   info.setSignalSemaphoreCount(u32(semaphores.signalSemaphores.size()));
121   info.setPSignalSemaphores(semaphores.signalSemaphores.data());
122   info.setWaitSemaphoreCount(u32(semaphores.waitSemaphores.size()));
123   info.setPWaitSemaphores(semaphores.waitSemaphores.data());
124   info.setPWaitDstStageMask(semaphores.waitDstStageMasks.data());
125
126   VkAssert(mQueue.submit(1, &info, fence.GetFence()));
127
128   return MakeUnique< Submission >(fence);
129 }
130 #pragma GCC diagnostic pop
131
132 std::vector< vk::CommandBuffer > Queue::PrepareBuffers(const std::vector< CommandBufferRef >& commandBuffers) const
133 {
134   std::vector< vk::CommandBuffer > retval(commandBuffers.size());
135   for(uint32_t i = 0; i < commandBuffers.size(); ++i)
136   {
137     retval[i] = commandBuffers[i].get().Get();
138   }
139   return retval;
140 }
141
142 void Queue::WaitIdle() const
143 {
144   assert(mQueue && "Queue isn't initialised!");
145   mQueue.waitIdle();
146 }
147
148 vk::Result Queue::Present(const vk::PresentInfoKHR& presentInfo)
149 {
150   return VkTest(mQueue.presentKHR(presentInfo));
151 }
152
153 vk::Result Queue::Present(vk::SwapchainKHR swapchain, uint32_t imageIndex)
154 {
155   auto info = vk::PresentInfoKHR{}
156                   .setWaitSemaphoreCount(0)
157                   .setPWaitSemaphores(nullptr)
158                   .setPResults(nullptr)
159                   .setPImageIndices(&imageIndex)
160                   .setPSwapchains(&swapchain)
161                   .setSwapchainCount(1);
162
163   return Present(info);
164 }
165
166 } // namespace Vulkan
167 } // namespace Graphics
168 } // namespace Dali