501cd2624db4d3f9791205173eefa18cc8831257
[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   break;
114   case vk::ImageLayout::eColorAttachmentOptimal:
115   {
116     srcStageMask = vk::PipelineStageFlagBits::eFragmentShader | vk::PipelineStageFlagBits::eColorAttachmentOutput;
117     srcAccessMask = vk::AccessFlagBits::eColorAttachmentWrite | vk::AccessFlagBits::eColorAttachmentRead;
118   }
119   break;
120   case vk::ImageLayout::eGeneral:
121   case vk::ImageLayout::eDepthStencilAttachmentOptimal:
122   case vk::ImageLayout::eDepthStencilReadOnlyOptimal:
123   case vk::ImageLayout::eShaderReadOnlyOptimal:
124   case vk::ImageLayout::eTransferSrcOptimal:
125   case vk::ImageLayout::eTransferDstOptimal:
126   case vk::ImageLayout::ePreinitialized:
127   case vk::ImageLayout::eSharedPresentKHR:
128   {
129   }
130   }
131
132   switch(newLayout)
133   {
134   case vk::ImageLayout::eColorAttachmentOptimal:
135   {
136     dstStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput | vk::PipelineStageFlagBits::eFragmentShader;
137     dstAccessMask = vk::AccessFlagBits::eColorAttachmentWrite | vk::AccessFlagBits::eHostWrite;
138     break;
139   }
140   case vk::ImageLayout::eDepthStencilAttachmentOptimal:
141   {
142     dstStageMask = vk::PipelineStageFlagBits::eFragmentShader | vk::PipelineStageFlagBits::eEarlyFragmentTests;
143     dstAccessMask = vk::AccessFlagBits::eDepthStencilAttachmentRead | vk::AccessFlagBits::eDepthStencilAttachmentWrite;
144     break;
145   }
146   case vk::ImageLayout::ePresentSrcKHR:
147   {
148     dstStageMask  = vk::PipelineStageFlagBits::eBottomOfPipe;
149     dstAccessMask = vk::AccessFlagBits::eColorAttachmentRead | vk::AccessFlagBits::eMemoryRead;
150   }
151   case vk::ImageLayout::eGeneral:
152   case vk::ImageLayout::eDepthStencilReadOnlyOptimal:
153   case vk::ImageLayout::eShaderReadOnlyOptimal:
154   case vk::ImageLayout::eTransferSrcOptimal:
155   case vk::ImageLayout::eTransferDstOptimal:
156   case vk::ImageLayout::ePreinitialized:
157   case vk::ImageLayout::eUndefined:
158   case vk::ImageLayout::eSharedPresentKHR:
159   default:
160   {
161   }
162   }
163
164   RecordImageLayoutTransition(image, srcAccessMask, dstAccessMask, srcStageMask, dstStageMask,
165                               oldLayout, newLayout, aspectMask);
166 }
167
168 #pragma GCC diagnostic push
169 #pragma GCC diagnostic ignored "-Wframe-larger-than="
170 void CommandBuffer::RecordImageLayoutTransition(vk::Image image, vk::AccessFlags srcAccessMask,
171                                                 vk::AccessFlags dstAccessMask, vk::PipelineStageFlags srcStageMask,
172                                                 vk::PipelineStageFlags dstStageMask, vk::ImageLayout oldLayout,
173                                                 vk::ImageLayout newLayout, vk::ImageAspectFlags aspectMask)
174 {
175   vk::ImageSubresourceRange subres;
176   subres.setLayerCount(1).setBaseMipLevel(0).setBaseArrayLayer(0).setLevelCount(1).setAspectMask(aspectMask);
177
178
179   auto barrier = vk::ImageMemoryBarrier{};
180   barrier
181                      .setImage(image)
182                      .setSubresourceRange(subres)
183                      .setSrcAccessMask(srcAccessMask)
184                      .setDstAccessMask(dstAccessMask)
185                      .setOldLayout(oldLayout)
186                      .setNewLayout(newLayout);
187   ;
188   // todo: implement barriers batching
189   mCommandBuffer.pipelineBarrier(srcStageMask, dstStageMask, vk::DependencyFlags{}, nullptr, nullptr, barrier);
190 }
191 #pragma GCC diagnostic pop
192
193 /** Push wait semaphores */
194 void CommandBuffer::PushWaitSemaphores(const std::vector< vk::Semaphore >&          semaphores,
195                                        const std::vector< vk::PipelineStageFlags >& stages)
196 {
197   mWaitSemaphores = semaphores;
198   mWaitStages     = stages;
199 }
200
201 /** Push signal semaphores */
202 void CommandBuffer::PushSignalSemaphores(const std::vector< vk::Semaphore >& semaphores)
203 {
204   mSignalSemaphores = semaphores;
205 }
206
207 } // namespace Vulkan
208 } // namespace Graphics
209 } // namespace Dali