xref: /aosp_15_r20/external/swiftshader/src/WSI/VkSwapchainKHR.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1*03ce13f7SAndroid Build Coastguard Worker // Copyright 2019 The SwiftShader Authors. All Rights Reserved.
2*03ce13f7SAndroid Build Coastguard Worker //
3*03ce13f7SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*03ce13f7SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*03ce13f7SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*03ce13f7SAndroid Build Coastguard Worker //
7*03ce13f7SAndroid Build Coastguard Worker //    http://www.apache.org/licenses/LICENSE-2.0
8*03ce13f7SAndroid Build Coastguard Worker //
9*03ce13f7SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*03ce13f7SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*03ce13f7SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*03ce13f7SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*03ce13f7SAndroid Build Coastguard Worker // limitations under the License.
14*03ce13f7SAndroid Build Coastguard Worker 
15*03ce13f7SAndroid Build Coastguard Worker #include "VkSwapchainKHR.hpp"
16*03ce13f7SAndroid Build Coastguard Worker 
17*03ce13f7SAndroid Build Coastguard Worker #include "Vulkan/VkDeviceMemory.hpp"
18*03ce13f7SAndroid Build Coastguard Worker #include "Vulkan/VkFence.hpp"
19*03ce13f7SAndroid Build Coastguard Worker #include "Vulkan/VkImage.hpp"
20*03ce13f7SAndroid Build Coastguard Worker #include "Vulkan/VkSemaphore.hpp"
21*03ce13f7SAndroid Build Coastguard Worker 
22*03ce13f7SAndroid Build Coastguard Worker #include <algorithm>
23*03ce13f7SAndroid Build Coastguard Worker #include <cstring>
24*03ce13f7SAndroid Build Coastguard Worker 
25*03ce13f7SAndroid Build Coastguard Worker namespace vk {
26*03ce13f7SAndroid Build Coastguard Worker 
SwapchainKHR(const VkSwapchainCreateInfoKHR * pCreateInfo,void * mem)27*03ce13f7SAndroid Build Coastguard Worker SwapchainKHR::SwapchainKHR(const VkSwapchainCreateInfoKHR *pCreateInfo, void *mem)
28*03ce13f7SAndroid Build Coastguard Worker     : surface(vk::Cast(pCreateInfo->surface))
29*03ce13f7SAndroid Build Coastguard Worker     , images(reinterpret_cast<PresentImage *>(mem))
30*03ce13f7SAndroid Build Coastguard Worker     , imageCount(pCreateInfo->minImageCount)
31*03ce13f7SAndroid Build Coastguard Worker     , retired(false)
32*03ce13f7SAndroid Build Coastguard Worker {
33*03ce13f7SAndroid Build Coastguard Worker 	memset(reinterpret_cast<void *>(images), 0, imageCount * sizeof(PresentImage));
34*03ce13f7SAndroid Build Coastguard Worker }
35*03ce13f7SAndroid Build Coastguard Worker 
destroy(const VkAllocationCallbacks * pAllocator)36*03ce13f7SAndroid Build Coastguard Worker void SwapchainKHR::destroy(const VkAllocationCallbacks *pAllocator)
37*03ce13f7SAndroid Build Coastguard Worker {
38*03ce13f7SAndroid Build Coastguard Worker 	for(uint32_t i = 0; i < imageCount; i++)
39*03ce13f7SAndroid Build Coastguard Worker 	{
40*03ce13f7SAndroid Build Coastguard Worker 		PresentImage &currentImage = images[i];
41*03ce13f7SAndroid Build Coastguard Worker 		if(currentImage.exists())
42*03ce13f7SAndroid Build Coastguard Worker 		{
43*03ce13f7SAndroid Build Coastguard Worker 			surface->detachImage(&currentImage);
44*03ce13f7SAndroid Build Coastguard Worker 			currentImage.release();
45*03ce13f7SAndroid Build Coastguard Worker 			surface->releaseImageMemory(&currentImage);
46*03ce13f7SAndroid Build Coastguard Worker 		}
47*03ce13f7SAndroid Build Coastguard Worker 	}
48*03ce13f7SAndroid Build Coastguard Worker 
49*03ce13f7SAndroid Build Coastguard Worker 	if(!retired)
50*03ce13f7SAndroid Build Coastguard Worker 	{
51*03ce13f7SAndroid Build Coastguard Worker 		surface->disassociateSwapchain();
52*03ce13f7SAndroid Build Coastguard Worker 	}
53*03ce13f7SAndroid Build Coastguard Worker 
54*03ce13f7SAndroid Build Coastguard Worker 	vk::freeHostMemory(images, pAllocator);
55*03ce13f7SAndroid Build Coastguard Worker }
56*03ce13f7SAndroid Build Coastguard Worker 
ComputeRequiredAllocationSize(const VkSwapchainCreateInfoKHR * pCreateInfo)57*03ce13f7SAndroid Build Coastguard Worker size_t SwapchainKHR::ComputeRequiredAllocationSize(const VkSwapchainCreateInfoKHR *pCreateInfo)
58*03ce13f7SAndroid Build Coastguard Worker {
59*03ce13f7SAndroid Build Coastguard Worker 	return pCreateInfo->minImageCount * sizeof(PresentImage);
60*03ce13f7SAndroid Build Coastguard Worker }
61*03ce13f7SAndroid Build Coastguard Worker 
retire()62*03ce13f7SAndroid Build Coastguard Worker void SwapchainKHR::retire()
63*03ce13f7SAndroid Build Coastguard Worker {
64*03ce13f7SAndroid Build Coastguard Worker 	if(!retired)
65*03ce13f7SAndroid Build Coastguard Worker 	{
66*03ce13f7SAndroid Build Coastguard Worker 		retired = true;
67*03ce13f7SAndroid Build Coastguard Worker 		surface->disassociateSwapchain();
68*03ce13f7SAndroid Build Coastguard Worker 
69*03ce13f7SAndroid Build Coastguard Worker 		for(uint32_t i = 0; i < imageCount; i++)
70*03ce13f7SAndroid Build Coastguard Worker 		{
71*03ce13f7SAndroid Build Coastguard Worker 			PresentImage &currentImage = images[i];
72*03ce13f7SAndroid Build Coastguard Worker 			if(currentImage.isAvailable())
73*03ce13f7SAndroid Build Coastguard Worker 			{
74*03ce13f7SAndroid Build Coastguard Worker 				surface->detachImage(&currentImage);
75*03ce13f7SAndroid Build Coastguard Worker 				currentImage.release();
76*03ce13f7SAndroid Build Coastguard Worker 			}
77*03ce13f7SAndroid Build Coastguard Worker 		}
78*03ce13f7SAndroid Build Coastguard Worker 	}
79*03ce13f7SAndroid Build Coastguard Worker }
80*03ce13f7SAndroid Build Coastguard Worker 
resetImages()81*03ce13f7SAndroid Build Coastguard Worker void SwapchainKHR::resetImages()
82*03ce13f7SAndroid Build Coastguard Worker {
83*03ce13f7SAndroid Build Coastguard Worker 	for(uint32_t i = 0; i < imageCount; i++)
84*03ce13f7SAndroid Build Coastguard Worker 	{
85*03ce13f7SAndroid Build Coastguard Worker 		images[i].release();
86*03ce13f7SAndroid Build Coastguard Worker 	}
87*03ce13f7SAndroid Build Coastguard Worker }
88*03ce13f7SAndroid Build Coastguard Worker 
createImages(VkDevice device,const VkSwapchainCreateInfoKHR * pCreateInfo)89*03ce13f7SAndroid Build Coastguard Worker VkResult SwapchainKHR::createImages(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo)
90*03ce13f7SAndroid Build Coastguard Worker {
91*03ce13f7SAndroid Build Coastguard Worker 	resetImages();
92*03ce13f7SAndroid Build Coastguard Worker 
93*03ce13f7SAndroid Build Coastguard Worker 	VkImageCreateInfo imageInfo = {};
94*03ce13f7SAndroid Build Coastguard Worker 	imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
95*03ce13f7SAndroid Build Coastguard Worker 
96*03ce13f7SAndroid Build Coastguard Worker 	if(pCreateInfo->flags & VK_SWAPCHAIN_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR)
97*03ce13f7SAndroid Build Coastguard Worker 	{
98*03ce13f7SAndroid Build Coastguard Worker 		imageInfo.flags |= VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT;
99*03ce13f7SAndroid Build Coastguard Worker 	}
100*03ce13f7SAndroid Build Coastguard Worker 
101*03ce13f7SAndroid Build Coastguard Worker 	if(pCreateInfo->flags & VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR)
102*03ce13f7SAndroid Build Coastguard Worker 	{
103*03ce13f7SAndroid Build Coastguard Worker 		imageInfo.flags |= VK_IMAGE_CREATE_PROTECTED_BIT;
104*03ce13f7SAndroid Build Coastguard Worker 	}
105*03ce13f7SAndroid Build Coastguard Worker 
106*03ce13f7SAndroid Build Coastguard Worker 	if(pCreateInfo->flags & VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR)
107*03ce13f7SAndroid Build Coastguard Worker 	{
108*03ce13f7SAndroid Build Coastguard Worker 		imageInfo.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
109*03ce13f7SAndroid Build Coastguard Worker 	}
110*03ce13f7SAndroid Build Coastguard Worker 
111*03ce13f7SAndroid Build Coastguard Worker 	imageInfo.imageType = VK_IMAGE_TYPE_2D;
112*03ce13f7SAndroid Build Coastguard Worker 	imageInfo.format = pCreateInfo->imageFormat;
113*03ce13f7SAndroid Build Coastguard Worker 	imageInfo.extent.height = pCreateInfo->imageExtent.height;
114*03ce13f7SAndroid Build Coastguard Worker 	imageInfo.extent.width = pCreateInfo->imageExtent.width;
115*03ce13f7SAndroid Build Coastguard Worker 	imageInfo.extent.depth = 1;
116*03ce13f7SAndroid Build Coastguard Worker 	imageInfo.mipLevels = 1;
117*03ce13f7SAndroid Build Coastguard Worker 	imageInfo.arrayLayers = pCreateInfo->imageArrayLayers;
118*03ce13f7SAndroid Build Coastguard Worker 	imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
119*03ce13f7SAndroid Build Coastguard Worker 	imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
120*03ce13f7SAndroid Build Coastguard Worker 	imageInfo.usage = pCreateInfo->imageUsage;
121*03ce13f7SAndroid Build Coastguard Worker 	imageInfo.sharingMode = pCreateInfo->imageSharingMode;
122*03ce13f7SAndroid Build Coastguard Worker 	imageInfo.pQueueFamilyIndices = pCreateInfo->pQueueFamilyIndices;
123*03ce13f7SAndroid Build Coastguard Worker 	imageInfo.queueFamilyIndexCount = pCreateInfo->queueFamilyIndexCount;
124*03ce13f7SAndroid Build Coastguard Worker 	imageInfo.initialLayout = VK_IMAGE_LAYOUT_GENERAL;
125*03ce13f7SAndroid Build Coastguard Worker 
126*03ce13f7SAndroid Build Coastguard Worker 	VkMemoryAllocateInfo allocInfo = {};
127*03ce13f7SAndroid Build Coastguard Worker 	allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
128*03ce13f7SAndroid Build Coastguard Worker 	allocInfo.allocationSize = 0;
129*03ce13f7SAndroid Build Coastguard Worker 	allocInfo.memoryTypeIndex = 0;
130*03ce13f7SAndroid Build Coastguard Worker 
131*03ce13f7SAndroid Build Coastguard Worker 	VkResult status;
132*03ce13f7SAndroid Build Coastguard Worker 	for(uint32_t i = 0; i < imageCount; i++)
133*03ce13f7SAndroid Build Coastguard Worker 	{
134*03ce13f7SAndroid Build Coastguard Worker 		PresentImage &currentImage = images[i];
135*03ce13f7SAndroid Build Coastguard Worker 
136*03ce13f7SAndroid Build Coastguard Worker 		status = currentImage.createImage(device, imageInfo);
137*03ce13f7SAndroid Build Coastguard Worker 		if(status != VK_SUCCESS)
138*03ce13f7SAndroid Build Coastguard Worker 		{
139*03ce13f7SAndroid Build Coastguard Worker 			return status;
140*03ce13f7SAndroid Build Coastguard Worker 		}
141*03ce13f7SAndroid Build Coastguard Worker 
142*03ce13f7SAndroid Build Coastguard Worker 		allocInfo.allocationSize = currentImage.getImage()->getMemoryRequirements().size;
143*03ce13f7SAndroid Build Coastguard Worker 		void* memory = vk::Cast(pCreateInfo->surface)->allocateImageMemory(&currentImage, allocInfo);
144*03ce13f7SAndroid Build Coastguard Worker 
145*03ce13f7SAndroid Build Coastguard Worker 		VkImportMemoryHostPointerInfoEXT importMemoryHostPointerInfo = {};
146*03ce13f7SAndroid Build Coastguard Worker 		if (memory)
147*03ce13f7SAndroid Build Coastguard Worker 		{
148*03ce13f7SAndroid Build Coastguard Worker 			importMemoryHostPointerInfo.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT;
149*03ce13f7SAndroid Build Coastguard Worker 			importMemoryHostPointerInfo.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT;
150*03ce13f7SAndroid Build Coastguard Worker 			importMemoryHostPointerInfo.pHostPointer = memory;
151*03ce13f7SAndroid Build Coastguard Worker 			allocInfo.pNext = &importMemoryHostPointerInfo;
152*03ce13f7SAndroid Build Coastguard Worker 		}
153*03ce13f7SAndroid Build Coastguard Worker 
154*03ce13f7SAndroid Build Coastguard Worker 		status = currentImage.allocateAndBindImageMemory(device, allocInfo);
155*03ce13f7SAndroid Build Coastguard Worker 		if(status != VK_SUCCESS)
156*03ce13f7SAndroid Build Coastguard Worker 		{
157*03ce13f7SAndroid Build Coastguard Worker 			vk::Cast(pCreateInfo->surface)->releaseImageMemory(&currentImage);
158*03ce13f7SAndroid Build Coastguard Worker 			return status;
159*03ce13f7SAndroid Build Coastguard Worker 		}
160*03ce13f7SAndroid Build Coastguard Worker 
161*03ce13f7SAndroid Build Coastguard Worker 		surface->attachImage(&currentImage);
162*03ce13f7SAndroid Build Coastguard Worker 	}
163*03ce13f7SAndroid Build Coastguard Worker 
164*03ce13f7SAndroid Build Coastguard Worker 	return VK_SUCCESS;
165*03ce13f7SAndroid Build Coastguard Worker }
166*03ce13f7SAndroid Build Coastguard Worker 
getImageCount() const167*03ce13f7SAndroid Build Coastguard Worker uint32_t SwapchainKHR::getImageCount() const
168*03ce13f7SAndroid Build Coastguard Worker {
169*03ce13f7SAndroid Build Coastguard Worker 	return imageCount;
170*03ce13f7SAndroid Build Coastguard Worker }
171*03ce13f7SAndroid Build Coastguard Worker 
getImages(uint32_t * pSwapchainImageCount,VkImage * pSwapchainImages) const172*03ce13f7SAndroid Build Coastguard Worker VkResult SwapchainKHR::getImages(uint32_t *pSwapchainImageCount, VkImage *pSwapchainImages) const
173*03ce13f7SAndroid Build Coastguard Worker {
174*03ce13f7SAndroid Build Coastguard Worker 	uint32_t i;
175*03ce13f7SAndroid Build Coastguard Worker 	for(i = 0; i < std::min(*pSwapchainImageCount, imageCount); i++)
176*03ce13f7SAndroid Build Coastguard Worker 	{
177*03ce13f7SAndroid Build Coastguard Worker 		pSwapchainImages[i] = images[i].asVkImage();
178*03ce13f7SAndroid Build Coastguard Worker 	}
179*03ce13f7SAndroid Build Coastguard Worker 
180*03ce13f7SAndroid Build Coastguard Worker 	*pSwapchainImageCount = i;
181*03ce13f7SAndroid Build Coastguard Worker 
182*03ce13f7SAndroid Build Coastguard Worker 	if(*pSwapchainImageCount < imageCount)
183*03ce13f7SAndroid Build Coastguard Worker 	{
184*03ce13f7SAndroid Build Coastguard Worker 		return VK_INCOMPLETE;
185*03ce13f7SAndroid Build Coastguard Worker 	}
186*03ce13f7SAndroid Build Coastguard Worker 
187*03ce13f7SAndroid Build Coastguard Worker 	return VK_SUCCESS;
188*03ce13f7SAndroid Build Coastguard Worker }
189*03ce13f7SAndroid Build Coastguard Worker 
getNextImage(uint64_t timeout,BinarySemaphore * semaphore,Fence * fence,uint32_t * pImageIndex)190*03ce13f7SAndroid Build Coastguard Worker VkResult SwapchainKHR::getNextImage(uint64_t timeout, BinarySemaphore *semaphore, Fence *fence, uint32_t *pImageIndex)
191*03ce13f7SAndroid Build Coastguard Worker {
192*03ce13f7SAndroid Build Coastguard Worker 	for(uint32_t i = 0; i < imageCount; i++)
193*03ce13f7SAndroid Build Coastguard Worker 	{
194*03ce13f7SAndroid Build Coastguard Worker 		PresentImage &currentImage = images[i];
195*03ce13f7SAndroid Build Coastguard Worker 		if(currentImage.isAvailable())
196*03ce13f7SAndroid Build Coastguard Worker 		{
197*03ce13f7SAndroid Build Coastguard Worker 			currentImage.setStatus(DRAWING);
198*03ce13f7SAndroid Build Coastguard Worker 			*pImageIndex = i;
199*03ce13f7SAndroid Build Coastguard Worker 
200*03ce13f7SAndroid Build Coastguard Worker 			if(semaphore)
201*03ce13f7SAndroid Build Coastguard Worker 			{
202*03ce13f7SAndroid Build Coastguard Worker 				semaphore->signal();
203*03ce13f7SAndroid Build Coastguard Worker 			}
204*03ce13f7SAndroid Build Coastguard Worker 
205*03ce13f7SAndroid Build Coastguard Worker 			if(fence)
206*03ce13f7SAndroid Build Coastguard Worker 			{
207*03ce13f7SAndroid Build Coastguard Worker 				fence->complete();
208*03ce13f7SAndroid Build Coastguard Worker 			}
209*03ce13f7SAndroid Build Coastguard Worker 
210*03ce13f7SAndroid Build Coastguard Worker 			return VK_SUCCESS;
211*03ce13f7SAndroid Build Coastguard Worker 		}
212*03ce13f7SAndroid Build Coastguard Worker 	}
213*03ce13f7SAndroid Build Coastguard Worker 
214*03ce13f7SAndroid Build Coastguard Worker 	return (timeout > 0) ? VK_TIMEOUT : VK_NOT_READY;
215*03ce13f7SAndroid Build Coastguard Worker }
216*03ce13f7SAndroid Build Coastguard Worker 
present(uint32_t index)217*03ce13f7SAndroid Build Coastguard Worker VkResult SwapchainKHR::present(uint32_t index)
218*03ce13f7SAndroid Build Coastguard Worker {
219*03ce13f7SAndroid Build Coastguard Worker 	auto &image = images[index];
220*03ce13f7SAndroid Build Coastguard Worker 	image.setStatus(PRESENTING);
221*03ce13f7SAndroid Build Coastguard Worker 	VkResult result = surface->present(&image);
222*03ce13f7SAndroid Build Coastguard Worker 
223*03ce13f7SAndroid Build Coastguard Worker 	releaseImage(index);
224*03ce13f7SAndroid Build Coastguard Worker 	return result;
225*03ce13f7SAndroid Build Coastguard Worker }
226*03ce13f7SAndroid Build Coastguard Worker 
releaseImages(uint32_t imageIndexCount,const uint32_t * pImageIndices)227*03ce13f7SAndroid Build Coastguard Worker VkResult SwapchainKHR::releaseImages(uint32_t imageIndexCount, const uint32_t *pImageIndices)
228*03ce13f7SAndroid Build Coastguard Worker {
229*03ce13f7SAndroid Build Coastguard Worker 	for(uint32_t i = 0; i < imageIndexCount; ++i)
230*03ce13f7SAndroid Build Coastguard Worker 	{
231*03ce13f7SAndroid Build Coastguard Worker 		releaseImage(pImageIndices[i]);
232*03ce13f7SAndroid Build Coastguard Worker 	}
233*03ce13f7SAndroid Build Coastguard Worker 	return VK_SUCCESS;
234*03ce13f7SAndroid Build Coastguard Worker }
235*03ce13f7SAndroid Build Coastguard Worker 
releaseImage(uint32_t index)236*03ce13f7SAndroid Build Coastguard Worker void SwapchainKHR::releaseImage(uint32_t index)
237*03ce13f7SAndroid Build Coastguard Worker {
238*03ce13f7SAndroid Build Coastguard Worker 	auto &image = images[index];
239*03ce13f7SAndroid Build Coastguard Worker 	image.setStatus(AVAILABLE);
240*03ce13f7SAndroid Build Coastguard Worker 
241*03ce13f7SAndroid Build Coastguard Worker 	if(retired)
242*03ce13f7SAndroid Build Coastguard Worker 	{
243*03ce13f7SAndroid Build Coastguard Worker 		surface->detachImage(&image);
244*03ce13f7SAndroid Build Coastguard Worker 		image.release();
245*03ce13f7SAndroid Build Coastguard Worker 		surface->releaseImageMemory(&image);
246*03ce13f7SAndroid Build Coastguard Worker 	}
247*03ce13f7SAndroid Build Coastguard Worker }
248*03ce13f7SAndroid Build Coastguard Worker }  // namespace vk
249