blob: 59639356b92d82704ce07ca0baef95a4fea86835 [file] [log] [blame]
Hernan Liatisc7943e92019-02-25 19:29:54 -08001// Copyright 2019 The SwiftShader Authors. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "VkSwapchainKHR.hpp"
16
17#include "Vulkan/VkImage.hpp"
18#include "Vulkan/VkDeviceMemory.hpp"
19#include "Vulkan/VkDestroy.h"
20
Hernan Liatisd00375a2019-02-26 11:19:27 -080021#include <algorithm>
22
Hernan Liatisc7943e92019-02-25 19:29:54 -080023namespace vk
24{
25
26SwapchainKHR::SwapchainKHR(const VkSwapchainCreateInfoKHR *pCreateInfo, void *mem) :
Hernan Liatis43be7162019-03-08 17:57:41 -080027 createInfo(*pCreateInfo),
28 retired(false)
Hernan Liatisc7943e92019-02-25 19:29:54 -080029{
30 images.resize(pCreateInfo->minImageCount);
31 resetImages();
32}
33
34void SwapchainKHR::destroy(const VkAllocationCallbacks *pAllocator)
35{
36 for(auto& currentImage : images)
37 {
38 if (currentImage.imageStatus != NONEXISTENT)
39 {
Hernan Liatisf945a5e2019-03-06 15:31:04 -080040 vk::Cast(createInfo.surface)->detachImage(&currentImage);
Hernan Liatisc7943e92019-02-25 19:29:54 -080041 vk::destroy(currentImage.imageMemory, pAllocator);
42 vk::destroy(currentImage.image, pAllocator);
43
44 currentImage.imageStatus = NONEXISTENT;
45 }
46 }
Hernan Liatis43be7162019-03-08 17:57:41 -080047
48 if(!retired)
49 {
50 vk::Cast(createInfo.surface)->disassociateSwapchain();
51 }
Hernan Liatisc7943e92019-02-25 19:29:54 -080052}
53
54size_t SwapchainKHR::ComputeRequiredAllocationSize(const VkSwapchainCreateInfoKHR *pCreateInfo)
55{
56 return 0;
57}
58
Hernan Liatis43be7162019-03-08 17:57:41 -080059void SwapchainKHR::retire()
60{
61 if(!retired)
62 {
63 retired = true;
64 vk::Cast(createInfo.surface)->disassociateSwapchain();
65
66 for(auto& currentImage : images)
67 {
68 if(currentImage.imageStatus == AVAILABLE)
69 {
70 vk::Cast(createInfo.surface)->detachImage(&currentImage);
71 vk::destroy(currentImage.imageMemory, nullptr);
72 vk::destroy(currentImage.image, nullptr);
73
74 currentImage.imageStatus = NONEXISTENT;
75 }
76 }
77 }
78}
79
Hernan Liatisc7943e92019-02-25 19:29:54 -080080void SwapchainKHR::resetImages()
81{
82 for(auto& currentImage : images)
83 {
84 currentImage.image = VK_NULL_HANDLE;
85 currentImage.imageMemory = VK_NULL_HANDLE;
86 currentImage.imageStatus = NONEXISTENT;
87 }
88}
89
90VkResult SwapchainKHR::createImages(VkDevice device)
91{
92 resetImages();
93
94 VkImageCreateInfo imageInfo = {};
95 imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
96
97 if(createInfo.flags & VK_SWAPCHAIN_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR)
98 {
99 imageInfo.flags |= VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT;
100 }
101
102 if(createInfo.flags & VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR)
103 {
104 imageInfo.flags |= VK_IMAGE_CREATE_PROTECTED_BIT;
105 }
106
107 imageInfo.imageType = VK_IMAGE_TYPE_2D;
108 imageInfo.format = createInfo.imageFormat;
109 imageInfo.extent.height = createInfo.imageExtent.height;
110 imageInfo.extent.width = createInfo.imageExtent.width;
111 imageInfo.extent.depth = 1;
112 imageInfo.mipLevels = 1;
113 imageInfo.arrayLayers = createInfo.imageArrayLayers;
114 imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
115 imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
116 imageInfo.usage = createInfo.imageUsage;
117 imageInfo.sharingMode = createInfo.imageSharingMode;
118 imageInfo.pQueueFamilyIndices = createInfo.pQueueFamilyIndices;
119 imageInfo.queueFamilyIndexCount = createInfo.queueFamilyIndexCount;
120 imageInfo.initialLayout = VK_IMAGE_LAYOUT_GENERAL;
121
122 VkResult status;
123 for(auto& currentImage : images)
124 {
125 status = vkCreateImage(device, &imageInfo, nullptr, &currentImage.image);
126 if(status != VK_SUCCESS)
127 {
128 return status;
129 }
130
131 VkMemoryRequirements memRequirements = vk::Cast(currentImage.image)->getMemoryRequirements();
132
133 VkMemoryAllocateInfo allocInfo = {};
134 allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
135 allocInfo.allocationSize = memRequirements.size;
136 allocInfo.memoryTypeIndex = 0;
137
138 status = vkAllocateMemory(device, &allocInfo, nullptr, &currentImage.imageMemory);
139 if(status != VK_SUCCESS)
140 {
141 return status;
142 }
143
144 vkBindImageMemory(device, currentImage.image, currentImage.imageMemory, 0);
145
146 currentImage.imageStatus = AVAILABLE;
Hernan Liatisf945a5e2019-03-06 15:31:04 -0800147
148 vk::Cast(createInfo.surface)->attachImage(&currentImage);
Hernan Liatisc7943e92019-02-25 19:29:54 -0800149 }
150
151 return VK_SUCCESS;
152}
153
Hernan Liatisd00375a2019-02-26 11:19:27 -0800154uint32_t SwapchainKHR::getImageCount() const
155{
156 return static_cast<uint32_t >(images.size());
157}
158
159VkResult SwapchainKHR::getImages(uint32_t *pSwapchainImageCount, VkImage *pSwapchainImages) const
160{
161 uint32_t count = getImageCount();
162
163 uint32_t i;
164 for (i = 0; i < std::min(*pSwapchainImageCount, count); i++)
165 {
166 pSwapchainImages[i] = images[i].image;
167 }
168
169 *pSwapchainImageCount = i;
170
171 if (*pSwapchainImageCount < count)
172 {
173 return VK_INCOMPLETE;
174 }
175
176 return VK_SUCCESS;
177}
178
Hernan Liatis6b12a502019-03-01 15:06:13 -0800179VkResult SwapchainKHR::getNextImage(uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t *pImageIndex)
180{
181 for(uint32_t i = 0; i < getImageCount(); i++)
182 {
183 PresentImage& currentImage = images[i];
184 if(currentImage.imageStatus == AVAILABLE)
185 {
186 currentImage.imageStatus = DRAWING;
187 *pImageIndex = i;
188
189 if(semaphore)
190 {
191 vk::Cast(semaphore)->signal();
192 }
193
194 if(fence)
195 {
196 vk::Cast(fence)->signal();
197 }
198
199 return VK_SUCCESS;
200 }
201 }
202
203 return VK_NOT_READY;
204}
205
206void SwapchainKHR::present(uint32_t index)
207{
208 auto & image = images[index];
209 image.imageStatus = PRESENTING;
Hernan Liatisf945a5e2019-03-06 15:31:04 -0800210 vk::Cast(createInfo.surface)->present(&image);
Hernan Liatis6b12a502019-03-01 15:06:13 -0800211 image.imageStatus = AVAILABLE;
Hernan Liatis43be7162019-03-08 17:57:41 -0800212
213 if(retired)
214 {
215 vk::Cast(createInfo.surface)->detachImage(&image);
216 vk::destroy(image.imageMemory, nullptr);
217 vk::destroy(image.image, nullptr);
218
219 image.imageStatus = NONEXISTENT;
220 }
Hernan Liatis6b12a502019-03-01 15:06:13 -0800221}
222
Hernan Liatisc7943e92019-02-25 19:29:54 -0800223}