• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // 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/VkDeviceMemory.hpp"
18 #include "Vulkan/VkFence.hpp"
19 #include "Vulkan/VkImage.hpp"
20 #include "Vulkan/VkSemaphore.hpp"
21 
22 #include <algorithm>
23 #include <cstring>
24 
25 namespace vk {
26 
SwapchainKHR(const VkSwapchainCreateInfoKHR * pCreateInfo,void * mem)27 SwapchainKHR::SwapchainKHR(const VkSwapchainCreateInfoKHR *pCreateInfo, void *mem)
28     : surface(vk::Cast(pCreateInfo->surface))
29     , images(reinterpret_cast<PresentImage *>(mem))
30     , imageCount(pCreateInfo->minImageCount)
31     , retired(false)
32 {
33 	memset(reinterpret_cast<void *>(images), 0, imageCount * sizeof(PresentImage));
34 }
35 
destroy(const VkAllocationCallbacks * pAllocator)36 void SwapchainKHR::destroy(const VkAllocationCallbacks *pAllocator)
37 {
38 	for(uint32_t i = 0; i < imageCount; i++)
39 	{
40 		PresentImage &currentImage = images[i];
41 		if(currentImage.exists())
42 		{
43 			surface->detachImage(&currentImage);
44 			currentImage.clear();
45 		}
46 	}
47 
48 	if(!retired)
49 	{
50 		surface->disassociateSwapchain();
51 	}
52 
53 	vk::deallocate(images, pAllocator);
54 }
55 
ComputeRequiredAllocationSize(const VkSwapchainCreateInfoKHR * pCreateInfo)56 size_t SwapchainKHR::ComputeRequiredAllocationSize(const VkSwapchainCreateInfoKHR *pCreateInfo)
57 {
58 	return pCreateInfo->minImageCount * sizeof(PresentImage);
59 }
60 
retire()61 void SwapchainKHR::retire()
62 {
63 	if(!retired)
64 	{
65 		retired = true;
66 		surface->disassociateSwapchain();
67 
68 		for(uint32_t i = 0; i < imageCount; i++)
69 		{
70 			PresentImage &currentImage = images[i];
71 			if(currentImage.isAvailable())
72 			{
73 				surface->detachImage(&currentImage);
74 				currentImage.clear();
75 			}
76 		}
77 	}
78 }
79 
resetImages()80 void SwapchainKHR::resetImages()
81 {
82 	for(uint32_t i = 0; i < imageCount; i++)
83 	{
84 		images[i].clear();
85 	}
86 }
87 
createImages(VkDevice device,const VkSwapchainCreateInfoKHR * pCreateInfo)88 VkResult SwapchainKHR::createImages(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo)
89 {
90 	resetImages();
91 
92 	VkImageCreateInfo imageInfo = {};
93 	imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
94 
95 	if(pCreateInfo->flags & VK_SWAPCHAIN_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR)
96 	{
97 		imageInfo.flags |= VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT;
98 	}
99 
100 	if(pCreateInfo->flags & VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR)
101 	{
102 		imageInfo.flags |= VK_IMAGE_CREATE_PROTECTED_BIT;
103 	}
104 
105 	imageInfo.imageType = VK_IMAGE_TYPE_2D;
106 	imageInfo.format = pCreateInfo->imageFormat;
107 	imageInfo.extent.height = pCreateInfo->imageExtent.height;
108 	imageInfo.extent.width = pCreateInfo->imageExtent.width;
109 	imageInfo.extent.depth = 1;
110 	imageInfo.mipLevels = 1;
111 	imageInfo.arrayLayers = pCreateInfo->imageArrayLayers;
112 	imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
113 	imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
114 	imageInfo.usage = pCreateInfo->imageUsage;
115 	imageInfo.sharingMode = pCreateInfo->imageSharingMode;
116 	imageInfo.pQueueFamilyIndices = pCreateInfo->pQueueFamilyIndices;
117 	imageInfo.queueFamilyIndexCount = pCreateInfo->queueFamilyIndexCount;
118 	imageInfo.initialLayout = VK_IMAGE_LAYOUT_GENERAL;
119 
120 	VkMemoryAllocateInfo allocInfo = {};
121 	allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
122 	allocInfo.allocationSize = 0;
123 	allocInfo.memoryTypeIndex = 0;
124 
125 	VkResult status;
126 	for(uint32_t i = 0; i < imageCount; i++)
127 	{
128 		PresentImage &currentImage = images[i];
129 
130 		status = currentImage.allocateImage(device, imageInfo);
131 		if(status != VK_SUCCESS)
132 		{
133 			return status;
134 		}
135 
136 		allocInfo.allocationSize = currentImage.getImage()->getMemoryRequirements().size;
137 
138 		status = currentImage.allocateAndBindImageMemory(device, allocInfo);
139 		if(status != VK_SUCCESS)
140 		{
141 			return status;
142 		}
143 
144 		surface->attachImage(&currentImage);
145 	}
146 
147 	return VK_SUCCESS;
148 }
149 
getImageCount() const150 uint32_t SwapchainKHR::getImageCount() const
151 {
152 	return imageCount;
153 }
154 
getImages(uint32_t * pSwapchainImageCount,VkImage * pSwapchainImages) const155 VkResult SwapchainKHR::getImages(uint32_t *pSwapchainImageCount, VkImage *pSwapchainImages) const
156 {
157 	uint32_t i;
158 	for(i = 0; i < std::min(*pSwapchainImageCount, imageCount); i++)
159 	{
160 		pSwapchainImages[i] = images[i].asVkImage();
161 	}
162 
163 	*pSwapchainImageCount = i;
164 
165 	if(*pSwapchainImageCount < imageCount)
166 	{
167 		return VK_INCOMPLETE;
168 	}
169 
170 	return VK_SUCCESS;
171 }
172 
getNextImage(uint64_t timeout,Semaphore * semaphore,Fence * fence,uint32_t * pImageIndex)173 VkResult SwapchainKHR::getNextImage(uint64_t timeout, Semaphore *semaphore, Fence *fence, uint32_t *pImageIndex)
174 {
175 	for(uint32_t i = 0; i < imageCount; i++)
176 	{
177 		PresentImage &currentImage = images[i];
178 		if(currentImage.isAvailable())
179 		{
180 			currentImage.setStatus(DRAWING);
181 			*pImageIndex = i;
182 
183 			if(semaphore)
184 			{
185 				semaphore->signal();
186 			}
187 
188 			if(fence)
189 			{
190 				fence->complete();
191 			}
192 
193 			return VK_SUCCESS;
194 		}
195 	}
196 
197 	return VK_NOT_READY;
198 }
199 
present(uint32_t index)200 VkResult SwapchainKHR::present(uint32_t index)
201 {
202 	auto &image = images[index];
203 	image.setStatus(PRESENTING);
204 	VkResult result = surface->present(&image);
205 	image.setStatus(AVAILABLE);
206 
207 	if(retired)
208 	{
209 		surface->detachImage(&image);
210 		image.clear();
211 	}
212 
213 	return result;
214 }
215 
216 }  // namespace vk