Vulkan SDK for Android 1.1.1 Mali Developer Center
context.cpp
1 /* Copyright (c) 2016-2017, ARM Limited and Contributors
2  *
3  * SPDX-License-Identifier: MIT
4  *
5  * Permission is hereby granted, free of charge,
6  * to any person obtaining a copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation the rights to
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
9  * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
14  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
16  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
17  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19  */
20 
21 #include "context.hpp"
22 #include "platform/platform.hpp"
23 
24 namespace MaliSDK
25 {
26 Context::PerFrame::PerFrame(VkDevice device, unsigned graphicsQueueIndex)
27  : device(device)
28  , fenceManager(device)
29  , commandManager(device, VK_COMMAND_BUFFER_LEVEL_PRIMARY, graphicsQueueIndex)
30  , queueIndex(graphicsQueueIndex)
31 {
32 }
33 
34 void Context::PerFrame::setSecondaryCommandManagersCount(unsigned count)
35 {
36  secondaryCommandManagers.clear();
37  for (unsigned i = 0; i < count; i++)
38  {
39  secondaryCommandManagers.emplace_back(
40  new CommandBufferManager(device, VK_COMMAND_BUFFER_LEVEL_SECONDARY, queueIndex));
41  }
42 }
43 
44 VkPhysicalDevice Context::getPhysicalDevice() const
45 {
46  return pPlatform->getPhysicalDevice();
47 }
48 
49 VkSemaphore Context::PerFrame::setSwapchainAcquireSemaphore(VkSemaphore acquireSemaphore)
50 {
51  VkSemaphore ret = swapchainAcquireSemaphore;
52  swapchainAcquireSemaphore = acquireSemaphore;
53  return ret;
54 }
55 
56 void Context::PerFrame::setSwapchainReleaseSemaphore(VkSemaphore releaseSemaphore)
57 {
58  if (swapchainReleaseSemaphore != VK_NULL_HANDLE)
59  vkDestroySemaphore(device, swapchainReleaseSemaphore, nullptr);
60  swapchainReleaseSemaphore = releaseSemaphore;
61 }
62 
63 void Context::PerFrame::beginFrame()
64 {
65  fenceManager.beginFrame();
66  commandManager.beginFrame();
67  for (auto &pManager : secondaryCommandManagers)
68  pManager->beginFrame();
69 }
70 
71 Context::PerFrame::~PerFrame()
72 {
73  if (swapchainAcquireSemaphore != VK_NULL_HANDLE)
74  vkDestroySemaphore(device, swapchainAcquireSemaphore, nullptr);
75  if (swapchainReleaseSemaphore != VK_NULL_HANDLE)
76  vkDestroySemaphore(device, swapchainReleaseSemaphore, nullptr);
77 }
78 
79 void Context::waitIdle()
80 {
81  vkDeviceWaitIdle(device);
82 }
83 
85 {
86  device = pPlatform->getDevice();
87  queue = pPlatform->getGraphicsQueue();
88  this->pPlatform = pPlatform;
89 
90  waitIdle();
91 
92  // Initialize per-frame resources.
93  // Every swapchain image has its own command pool and fence manager.
94  // This makes it very easy to keep track of when we can reset command buffers
95  // and such.
96  perFrame.clear();
97  for (unsigned i = 0; i < pPlatform->getNumSwapchainImages(); i++)
98  perFrame.emplace_back(new PerFrame(device, pPlatform->getGraphicsQueueIndex()));
99 
100  setRenderingThreadCount(renderingThreadCount);
101 
102  return RESULT_SUCCESS;
103 }
104 
105 void Context::submit(VkCommandBuffer cmd)
106 {
107  submitCommandBuffer(cmd, VK_NULL_HANDLE, VK_NULL_HANDLE);
108 }
109 
110 void Context::submitSwapchain(VkCommandBuffer cmd)
111 {
112  // For the first frames, we will create a release semaphore.
113  // This can be reused every frame. Semaphores are reset when they have been
114  // successfully been waited on.
115  // If we aren't using acquire semaphores, we aren't using release semaphores
116  // either.
117  if (getSwapchainReleaseSemaphore() == VK_NULL_HANDLE && getSwapchainAcquireSemaphore() != VK_NULL_HANDLE)
118  {
119  VkSemaphore releaseSemaphore;
120  VkSemaphoreCreateInfo semaphoreInfo = { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO };
121  VK_CHECK(vkCreateSemaphore(device, &semaphoreInfo, nullptr, &releaseSemaphore));
122  perFrame[swapchainIndex]->setSwapchainReleaseSemaphore(releaseSemaphore);
123  }
124 
125  submitCommandBuffer(cmd, getSwapchainAcquireSemaphore(), getSwapchainReleaseSemaphore());
126 }
127 
128 void Context::submitCommandBuffer(VkCommandBuffer cmd, VkSemaphore acquireSemaphore, VkSemaphore releaseSemaphore)
129 {
130  // All queue submissions get a fence that CPU will wait
131  // on for synchronization purposes.
132  VkFence fence = getFenceManager().requestClearedFence();
133 
134  VkSubmitInfo info = { VK_STRUCTURE_TYPE_SUBMIT_INFO };
135  info.commandBufferCount = 1;
136  info.pCommandBuffers = &cmd;
137 
138  const VkPipelineStageFlags waitStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
139  info.waitSemaphoreCount = acquireSemaphore != VK_NULL_HANDLE ? 1 : 0;
140  info.pWaitSemaphores = &acquireSemaphore;
141  info.pWaitDstStageMask = &waitStage;
142  info.signalSemaphoreCount = releaseSemaphore != VK_NULL_HANDLE ? 1 : 0;
143  info.pSignalSemaphores = &releaseSemaphore;
144 
145  VK_CHECK(vkQueueSubmit(queue, 1, &info, fence));
146 }
147 }
unsigned getGraphicsQueueIndex() const
Gets the current Vulkan graphics queue family index.
Definition: platform.hpp:188
VkDevice getDevice() const
Gets the current Vulkan device.
Definition: platform.hpp:160
void submit(VkCommandBuffer cmdBuffer)
Submit a command buffer to the queue.
Definition: context.cpp:105
The platform class is to abstract the Vulkan implementation of a particular platform. It is not used directly by applications, but by the mainloop implementation which is OS specific.
Definition: platform.hpp:38
Result onPlatformUpdate(Platform *pPlatform)
Called by the platform internally when platform either initializes itself or the swapchain has been r...
Definition: context.cpp:84
void submitSwapchain(VkCommandBuffer cmdBuffer)
Submit a command buffer to the queue which renders to the swapchain image.
Definition: context.cpp:110
CommandBufferManager(VkDevice device, VkCommandBufferLevel bufferLevel, unsigned graphicsQueueIndex)
Constructor.
virtual unsigned getNumSwapchainImages() const =0
Gets number of swapchain images used.
VkQueue getGraphicsQueue() const
Gets the current Vulkan graphics queue.
Definition: platform.hpp:181
VkPhysicalDevice getPhysicalDevice() const
Gets the Vulkan physical device assigned to the context.
Definition: context.cpp:44