xref: /aosp_15_r20/external/swiftshader/src/WSI/VkSwapchainKHR.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
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 			surface->releaseImageMemory(&currentImage);
46 		}
47 	}
48 
49 	if(!retired)
50 	{
51 		surface->disassociateSwapchain();
52 	}
53 
54 	vk::freeHostMemory(images, pAllocator);
55 }
56 
ComputeRequiredAllocationSize(const VkSwapchainCreateInfoKHR * pCreateInfo)57 size_t SwapchainKHR::ComputeRequiredAllocationSize(const VkSwapchainCreateInfoKHR *pCreateInfo)
58 {
59 	return pCreateInfo->minImageCount * sizeof(PresentImage);
60 }
61 
retire()62 void SwapchainKHR::retire()
63 {
64 	if(!retired)
65 	{
66 		retired = true;
67 		surface->disassociateSwapchain();
68 
69 		for(uint32_t i = 0; i < imageCount; i++)
70 		{
71 			PresentImage &currentImage = images[i];
72 			if(currentImage.isAvailable())
73 			{
74 				surface->detachImage(&currentImage);
75 				currentImage.release();
76 			}
77 		}
78 	}
79 }
80 
resetImages()81 void SwapchainKHR::resetImages()
82 {
83 	for(uint32_t i = 0; i < imageCount; i++)
84 	{
85 		images[i].release();
86 	}
87 }
88 
createImages(VkDevice device,const VkSwapchainCreateInfoKHR * pCreateInfo)89 VkResult SwapchainKHR::createImages(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo)
90 {
91 	resetImages();
92 
93 	VkImageCreateInfo imageInfo = {};
94 	imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
95 
96 	if(pCreateInfo->flags & VK_SWAPCHAIN_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR)
97 	{
98 		imageInfo.flags |= VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT;
99 	}
100 
101 	if(pCreateInfo->flags & VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR)
102 	{
103 		imageInfo.flags |= VK_IMAGE_CREATE_PROTECTED_BIT;
104 	}
105 
106 	if(pCreateInfo->flags & VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR)
107 	{
108 		imageInfo.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
109 	}
110 
111 	imageInfo.imageType = VK_IMAGE_TYPE_2D;
112 	imageInfo.format = pCreateInfo->imageFormat;
113 	imageInfo.extent.height = pCreateInfo->imageExtent.height;
114 	imageInfo.extent.width = pCreateInfo->imageExtent.width;
115 	imageInfo.extent.depth = 1;
116 	imageInfo.mipLevels = 1;
117 	imageInfo.arrayLayers = pCreateInfo->imageArrayLayers;
118 	imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
119 	imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
120 	imageInfo.usage = pCreateInfo->imageUsage;
121 	imageInfo.sharingMode = pCreateInfo->imageSharingMode;
122 	imageInfo.pQueueFamilyIndices = pCreateInfo->pQueueFamilyIndices;
123 	imageInfo.queueFamilyIndexCount = pCreateInfo->queueFamilyIndexCount;
124 	imageInfo.initialLayout = VK_IMAGE_LAYOUT_GENERAL;
125 
126 	VkMemoryAllocateInfo allocInfo = {};
127 	allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
128 	allocInfo.allocationSize = 0;
129 	allocInfo.memoryTypeIndex = 0;
130 
131 	VkResult status;
132 	for(uint32_t i = 0; i < imageCount; i++)
133 	{
134 		PresentImage &currentImage = images[i];
135 
136 		status = currentImage.createImage(device, imageInfo);
137 		if(status != VK_SUCCESS)
138 		{
139 			return status;
140 		}
141 
142 		allocInfo.allocationSize = currentImage.getImage()->getMemoryRequirements().size;
143 		void* memory = vk::Cast(pCreateInfo->surface)->allocateImageMemory(&currentImage, allocInfo);
144 
145 		VkImportMemoryHostPointerInfoEXT importMemoryHostPointerInfo = {};
146 		if (memory)
147 		{
148 			importMemoryHostPointerInfo.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT;
149 			importMemoryHostPointerInfo.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT;
150 			importMemoryHostPointerInfo.pHostPointer = memory;
151 			allocInfo.pNext = &importMemoryHostPointerInfo;
152 		}
153 
154 		status = currentImage.allocateAndBindImageMemory(device, allocInfo);
155 		if(status != VK_SUCCESS)
156 		{
157 			vk::Cast(pCreateInfo->surface)->releaseImageMemory(&currentImage);
158 			return status;
159 		}
160 
161 		surface->attachImage(&currentImage);
162 	}
163 
164 	return VK_SUCCESS;
165 }
166 
getImageCount() const167 uint32_t SwapchainKHR::getImageCount() const
168 {
169 	return imageCount;
170 }
171 
getImages(uint32_t * pSwapchainImageCount,VkImage * pSwapchainImages) const172 VkResult SwapchainKHR::getImages(uint32_t *pSwapchainImageCount, VkImage *pSwapchainImages) const
173 {
174 	uint32_t i;
175 	for(i = 0; i < std::min(*pSwapchainImageCount, imageCount); i++)
176 	{
177 		pSwapchainImages[i] = images[i].asVkImage();
178 	}
179 
180 	*pSwapchainImageCount = i;
181 
182 	if(*pSwapchainImageCount < imageCount)
183 	{
184 		return VK_INCOMPLETE;
185 	}
186 
187 	return VK_SUCCESS;
188 }
189 
getNextImage(uint64_t timeout,BinarySemaphore * semaphore,Fence * fence,uint32_t * pImageIndex)190 VkResult SwapchainKHR::getNextImage(uint64_t timeout, BinarySemaphore *semaphore, Fence *fence, uint32_t *pImageIndex)
191 {
192 	for(uint32_t i = 0; i < imageCount; i++)
193 	{
194 		PresentImage &currentImage = images[i];
195 		if(currentImage.isAvailable())
196 		{
197 			currentImage.setStatus(DRAWING);
198 			*pImageIndex = i;
199 
200 			if(semaphore)
201 			{
202 				semaphore->signal();
203 			}
204 
205 			if(fence)
206 			{
207 				fence->complete();
208 			}
209 
210 			return VK_SUCCESS;
211 		}
212 	}
213 
214 	return (timeout > 0) ? VK_TIMEOUT : VK_NOT_READY;
215 }
216 
present(uint32_t index)217 VkResult SwapchainKHR::present(uint32_t index)
218 {
219 	auto &image = images[index];
220 	image.setStatus(PRESENTING);
221 	VkResult result = surface->present(&image);
222 
223 	releaseImage(index);
224 	return result;
225 }
226 
releaseImages(uint32_t imageIndexCount,const uint32_t * pImageIndices)227 VkResult SwapchainKHR::releaseImages(uint32_t imageIndexCount, const uint32_t *pImageIndices)
228 {
229 	for(uint32_t i = 0; i < imageIndexCount; ++i)
230 	{
231 		releaseImage(pImageIndices[i]);
232 	}
233 	return VK_SUCCESS;
234 }
235 
releaseImage(uint32_t index)236 void SwapchainKHR::releaseImage(uint32_t index)
237 {
238 	auto &image = images[index];
239 	image.setStatus(AVAILABLE);
240 
241 	if(retired)
242 	{
243 		surface->detachImage(&image);
244 		image.release();
245 		surface->releaseImageMemory(&image);
246 	}
247 }
248 }  // namespace vk
249