• 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.release();
45 		}
46 	}
47 
48 	if(!retired)
49 	{
50 		surface->disassociateSwapchain();
51 	}
52 
53 	vk::freeHostMemory(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.release();
75 			}
76 		}
77 	}
78 }
79 
resetImages()80 void SwapchainKHR::resetImages()
81 {
82 	for(uint32_t i = 0; i < imageCount; i++)
83 	{
84 		images[i].release();
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 	if(pCreateInfo->flags & VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR)
106 	{
107 		imageInfo.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
108 	}
109 
110 	imageInfo.imageType = VK_IMAGE_TYPE_2D;
111 	imageInfo.format = pCreateInfo->imageFormat;
112 	imageInfo.extent.height = pCreateInfo->imageExtent.height;
113 	imageInfo.extent.width = pCreateInfo->imageExtent.width;
114 	imageInfo.extent.depth = 1;
115 	imageInfo.mipLevels = 1;
116 	imageInfo.arrayLayers = pCreateInfo->imageArrayLayers;
117 	imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
118 	imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
119 	imageInfo.usage = pCreateInfo->imageUsage;
120 	imageInfo.sharingMode = pCreateInfo->imageSharingMode;
121 	imageInfo.pQueueFamilyIndices = pCreateInfo->pQueueFamilyIndices;
122 	imageInfo.queueFamilyIndexCount = pCreateInfo->queueFamilyIndexCount;
123 	imageInfo.initialLayout = VK_IMAGE_LAYOUT_GENERAL;
124 
125 	VkMemoryAllocateInfo allocInfo = {};
126 	allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
127 	allocInfo.allocationSize = 0;
128 	allocInfo.memoryTypeIndex = 0;
129 
130 	VkResult status;
131 	for(uint32_t i = 0; i < imageCount; i++)
132 	{
133 		PresentImage &currentImage = images[i];
134 
135 		status = currentImage.createImage(device, imageInfo);
136 		if(status != VK_SUCCESS)
137 		{
138 			return status;
139 		}
140 
141 		allocInfo.allocationSize = currentImage.getImage()->getMemoryRequirements().size;
142 
143 		status = currentImage.allocateAndBindImageMemory(device, allocInfo);
144 		if(status != VK_SUCCESS)
145 		{
146 			return status;
147 		}
148 
149 		surface->attachImage(&currentImage);
150 	}
151 
152 	return VK_SUCCESS;
153 }
154 
getImageCount() const155 uint32_t SwapchainKHR::getImageCount() const
156 {
157 	return imageCount;
158 }
159 
getImages(uint32_t * pSwapchainImageCount,VkImage * pSwapchainImages) const160 VkResult SwapchainKHR::getImages(uint32_t *pSwapchainImageCount, VkImage *pSwapchainImages) const
161 {
162 	uint32_t i;
163 	for(i = 0; i < std::min(*pSwapchainImageCount, imageCount); i++)
164 	{
165 		pSwapchainImages[i] = images[i].asVkImage();
166 	}
167 
168 	*pSwapchainImageCount = i;
169 
170 	if(*pSwapchainImageCount < imageCount)
171 	{
172 		return VK_INCOMPLETE;
173 	}
174 
175 	return VK_SUCCESS;
176 }
177 
getNextImage(uint64_t timeout,BinarySemaphore * semaphore,Fence * fence,uint32_t * pImageIndex)178 VkResult SwapchainKHR::getNextImage(uint64_t timeout, BinarySemaphore *semaphore, Fence *fence, uint32_t *pImageIndex)
179 {
180 	for(uint32_t i = 0; i < imageCount; i++)
181 	{
182 		PresentImage &currentImage = images[i];
183 		if(currentImage.isAvailable())
184 		{
185 			currentImage.setStatus(DRAWING);
186 			*pImageIndex = i;
187 
188 			if(semaphore)
189 			{
190 				semaphore->signal();
191 			}
192 
193 			if(fence)
194 			{
195 				fence->complete();
196 			}
197 
198 			return VK_SUCCESS;
199 		}
200 	}
201 
202 	return (timeout > 0) ? VK_TIMEOUT : VK_NOT_READY;
203 }
204 
present(uint32_t index)205 VkResult SwapchainKHR::present(uint32_t index)
206 {
207 	auto &image = images[index];
208 	image.setStatus(PRESENTING);
209 	VkResult result = surface->present(&image);
210 	image.setStatus(AVAILABLE);
211 
212 	if(retired)
213 	{
214 		surface->detachImage(&image);
215 		image.release();
216 	}
217 
218 	return result;
219 }
220 
221 }  // namespace vk