Simplified Vulkan backend [WIP]
[platform/core/uifw/dali-core.git] / dali / graphics / vulkan / vulkan-command-buffer.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-command-pool.h>
21 #include <dali/graphics/vulkan/vulkan-graphics.h>
22
23 namespace Dali
24 {
25 namespace Graphics
26 {
27 namespace Vulkan
28 {
29
30 CommandBuffer::CommandBuffer(Graphics& graphics, CommandPool& ownerPool)
31 : CommandBuffer(graphics, ownerPool,
32                 vk::CommandBufferAllocateInfo().setCommandBufferCount(1).setLevel(vk::CommandBufferLevel::ePrimary))
33 {
34 }
35
36 CommandBuffer::CommandBuffer(Graphics& graphics, CommandPool& ownerPool,
37                              const vk::CommandBufferAllocateInfo& allocateInfo)
38 : mGraphics(graphics), mCommandPool(ownerPool), mRecording(false)
39 {
40   assert(allocateInfo.commandBufferCount == 1 && "Number of buffers to allocate must be equal 1!");
41   mCommandBuffer = VkAssert(mGraphics.GetDevice().allocateCommandBuffers(allocateInfo))[0];
42 }
43
44 CommandBuffer::~CommandBuffer()
45 {
46   if(mCommandBuffer)
47   {
48     mGraphics.GetDevice().freeCommandBuffers(mCommandPool.GetPool(), mCommandBuffer);
49   }
50 }
51
52 /** Begin recording */
53 void CommandBuffer::Begin(vk::CommandBufferUsageFlags usageFlags, vk::CommandBufferInheritanceInfo* inheritanceInfo)
54 {
55   assert(!mRecording && "CommandBuffer already is in the recording state");
56   auto info = vk::CommandBufferBeginInfo{};
57   info.setPInheritanceInfo(inheritanceInfo);
58   info.setFlags(usageFlags);
59   VkAssert(mCommandBuffer.begin(info));
60   mRecording = true;
61 }
62
63 /** Finish recording */
64 void CommandBuffer::End()
65 {
66   assert(mRecording && "CommandBuffer is not in the recording state!");
67   VkAssert(mCommandBuffer.end());
68   mRecording = false;
69 }
70
71 /** Reset command buffer */
72 void CommandBuffer::Reset()
73 {
74   assert(!mRecording && "Can't reset command buffer during recording!");
75   assert(mCommandBuffer && "Invalid command buffer!");
76   mCommandBuffer.reset(vk::CommandBufferResetFlagBits::eReleaseResources);
77 }
78
79 /** Free command buffer */
80 void CommandBuffer::Free()
81 {
82   assert(mCommandBuffer && "Invalid command buffer!");
83   mGraphics.GetDevice().freeCommandBuffers(mCommandPool.GetPool(), mCommandBuffer);
84 }
85
86 /** Records image layout transition barrier for one image */
87 void CommandBuffer::ImageLayoutTransition(vk::Image            image,
88                                           vk::ImageLayout      oldLayout,
89                                           vk::ImageLayout      newLayout,
90                                           vk::ImageAspectFlags aspectMask)
91 {
92   // must be in recording state
93
94   // just push new image barrier until any command is being called or buffer recording ends.
95   // it will make sure we batch barriers together rather than calling cmdPipelineBarrier
96   // for each separately
97   vk::AccessFlags        srcAccessMask, dstAccessMask;
98   vk::PipelineStageFlags srcStageMask, dstStageMask;
99
100   // TODO: add other transitions
101   switch(oldLayout)
102   {
103   case vk::ImageLayout::eUndefined:
104   {
105     srcStageMask = vk::PipelineStageFlagBits::eTopOfPipe;
106   }
107   break;
108   case vk::ImageLayout::ePresentSrcKHR:
109   {
110     srcStageMask = vk::PipelineStageFlagBits::eBottomOfPipe;
111     srcAccessMask = vk::AccessFlagBits::eColorAttachmentWrite | vk::AccessFlagBits::eColorAttachmentRead;
112   }
113   case vk::ImageLayout::eColorAttachmentOptimal:
114   {
115     srcStageMask = vk::PipelineStageFlagBits::eFragmentShader | vk::PipelineStageFlagBits::eColorAttachmentOutput;
116     srcAccessMask = vk::AccessFlagBits::eColorAttachmentWrite | vk::AccessFlagBits::eColorAttachmentRead;
117   }
118   break;
119   case vk::ImageLayout::eGeneral:
120   case vk::ImageLayout::eDepthStencilAttachmentOptimal:
121   case vk::ImageLayout::eDepthStencilReadOnlyOptimal:
122   case vk::ImageLayout::eShaderReadOnlyOptimal:
123   case vk::ImageLayout::eTransferSrcOptimal:
124   case vk::ImageLayout::eTransferDstOptimal:
125   case vk::ImageLayout::ePreinitialized:
126   default:
127   {
128   }
129   }
130
131   switch(newLayout)
132   {
133   case vk::ImageLayout::eColorAttachmentOptimal:
134   {
135     dstStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput | vk::PipelineStageFlagBits::eFragmentShader;
136     dstAccessMask = vk::AccessFlagBits::eColorAttachmentWrite | vk::AccessFlagBits::eHostWrite;
137     break;
138   }
139   case vk::ImageLayout::eDepthStencilAttachmentOptimal:
140   {
141     dstStageMask = vk::PipelineStageFlagBits::eFragmentShader | vk::PipelineStageFlagBits::eEarlyFragmentTests;
142     dstAccessMask = vk::AccessFlagBits::eDepthStencilAttachmentRead | vk::AccessFlagBits::eDepthStencilAttachmentWrite;
143     break;
144   }
145   case vk::ImageLayout::ePresentSrcKHR:
146   {
147     dstStageMask  = vk::PipelineStageFlagBits::eBottomOfPipe;
148     dstAccessMask = vk::AccessFlagBits::eColorAttachmentRead | vk::AccessFlagBits::eMemoryRead;
149   }
150   case vk::ImageLayout::eGeneral:
151   case vk::ImageLayout::eDepthStencilReadOnlyOptimal:
152   case vk::ImageLayout::eShaderReadOnlyOptimal:
153   case vk::ImageLayout::eTransferSrcOptimal:
154   case vk::ImageLayout::eTransferDstOptimal:
155   case vk::ImageLayout::ePreinitialized:
156   case vk::ImageLayout::eUndefined:
157   default:
158   {
159   }
160   }
161
162   RecordImageLayoutTransition(image, srcAccessMask, dstAccessMask, srcStageMask, dstStageMask,
163                               oldLayout, newLayout, aspectMask);
164 }
165
166 #pragma GCC diagnostic push
167 #pragma GCC diagnostic ignored "-Wframe-larger-than="
168 void CommandBuffer::RecordImageLayoutTransition(vk::Image image, vk::AccessFlags srcAccessMask,
169                                                 vk::AccessFlags dstAccessMask, vk::PipelineStageFlags srcStageMask,
170                                                 vk::PipelineStageFlags dstStageMask, vk::ImageLayout oldLayout,
171                                                 vk::ImageLayout newLayout, vk::ImageAspectFlags aspectMask)
172 {
173   vk::ImageSubresourceRange subres;
174   subres.setLayerCount(1).setBaseMipLevel(0).setBaseArrayLayer(0).setLevelCount(1).setAspectMask(aspectMask);
175
176
177   auto barrier = vk::ImageMemoryBarrier{};
178   barrier
179                      .setImage(image)
180                      .setSubresourceRange(subres)
181                      .setSrcAccessMask(srcAccessMask)
182                      .setDstAccessMask(dstAccessMask)
183                      .setOldLayout(oldLayout)
184                      .setNewLayout(newLayout);
185   ;
186   // todo: implement barriers batching
187   mCommandBuffer.pipelineBarrier(srcStageMask, dstStageMask, vk::DependencyFlags{}, nullptr, nullptr, barrier);
188 }
189 #pragma GCC diagnostic pop
190
191 /** Push wait semaphores */
192 void CommandBuffer::PushWaitSemaphores(const std::vector< vk::Semaphore >&          semaphores,
193                                        const std::vector< vk::PipelineStageFlags >& stages)
194 {
195   mWaitSemaphores = semaphores;
196   mWaitStages     = stages;
197 }
198
199 /** Push signal semaphores */
200 void CommandBuffer::PushSignalSemaphores(const std::vector< vk::Semaphore >& semaphores)
201 {
202   mSignalSemaphores = semaphores;
203 }
204
205 } // namespace Vulkan
206 } // namespace Graphics
207 } // namespace Dali