1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 Google Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Tests for incremental present extension
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktWsiIncrementalPresentTests.hpp"
25 
26 #include "vktTestCaseUtil.hpp"
27 #include "vktTestGroupUtil.hpp"
28 #include "vkRefUtil.hpp"
29 #include "vkWsiPlatform.hpp"
30 #include "vkWsiUtil.hpp"
31 #include "vkQueryUtil.hpp"
32 #include "vkDeviceUtil.hpp"
33 #include "vkPlatform.hpp"
34 #include "vkTypeUtil.hpp"
35 #include "vkPrograms.hpp"
36 #include "vkCmdUtil.hpp"
37 #include "vkObjUtil.hpp"
38 
39 #include "vkWsiUtil.hpp"
40 
41 #include "tcuPlatform.hpp"
42 #include "tcuResultCollector.hpp"
43 #include "tcuTestLog.hpp"
44 
45 #include <vector>
46 #include <string>
47 
48 using std::vector;
49 using std::string;
50 
51 using tcu::Maybe;
52 using tcu::UVec2;
53 using tcu::TestLog;
54 
55 namespace vkt
56 {
57 namespace wsi
58 {
59 namespace
60 {
61 enum Scaling
62 {
63 	SCALING_NONE,
64 	SCALING_UP,
65 	SCALING_DOWN
66 };
67 
68 typedef vector<vk::VkExtensionProperties> Extensions;
69 
checkAllSupported(const Extensions & supportedExtensions,const vector<string> & requiredExtensions)70 void checkAllSupported (const Extensions& supportedExtensions, const vector<string>& requiredExtensions)
71 {
72 	for (vector<string>::const_iterator requiredExtName = requiredExtensions.begin();
73 		 requiredExtName != requiredExtensions.end();
74 		 ++requiredExtName)
75 	{
76 		if (!isExtensionSupported(supportedExtensions, vk::RequiredExtension(*requiredExtName)))
77 			TCU_THROW(NotSupportedError, (*requiredExtName + " is not supported").c_str());
78 	}
79 }
80 
createInstanceWithWsi(const vk::PlatformInterface & vkp,deUint32 version,const Extensions & supportedExtensions,vk::wsi::Type wsiType)81 vk::Move<vk::VkInstance> createInstanceWithWsi (const vk::PlatformInterface&		vkp,
82 												deUint32							version,
83 												const Extensions&					supportedExtensions,
84 												vk::wsi::Type						wsiType)
85 {
86 	vector<string>	extensions;
87 
88 	extensions.push_back("VK_KHR_surface");
89 	extensions.push_back(getExtensionName(wsiType));
90 
91 	checkAllSupported(supportedExtensions, extensions);
92 
93 	return vk::createDefaultInstance(vkp, version, vector<string>(), extensions);
94 }
95 
getDeviceNullFeatures(void)96 vk::VkPhysicalDeviceFeatures getDeviceNullFeatures (void)
97 {
98 	vk::VkPhysicalDeviceFeatures features;
99 	deMemset(&features, 0, sizeof(features));
100 	return features;
101 }
102 
getNumQueueFamilyIndices(const vk::InstanceInterface & vki,vk::VkPhysicalDevice physicalDevice)103 deUint32 getNumQueueFamilyIndices (const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice)
104 {
105 	deUint32	numFamilies		= 0;
106 
107 	vki.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numFamilies, DE_NULL);
108 
109 	return numFamilies;
110 }
111 
getSupportedQueueFamilyIndices(const vk::InstanceInterface & vki,vk::VkPhysicalDevice physicalDevice,vk::VkSurfaceKHR surface)112 vector<deUint32> getSupportedQueueFamilyIndices (const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice, vk::VkSurfaceKHR surface)
113 {
114 	const deUint32		numTotalFamilyIndices	= getNumQueueFamilyIndices(vki, physicalDevice);
115 	vector<deUint32>	supportedFamilyIndices;
116 
117 	for (deUint32 queueFamilyNdx = 0; queueFamilyNdx < numTotalFamilyIndices; ++queueFamilyNdx)
118 	{
119 		if (vk::wsi::getPhysicalDeviceSurfaceSupport(vki, physicalDevice, queueFamilyNdx, surface) != VK_FALSE)
120 			supportedFamilyIndices.push_back(queueFamilyNdx);
121 	}
122 
123 	return supportedFamilyIndices;
124 }
125 
chooseQueueFamilyIndex(const vk::InstanceInterface & vki,vk::VkPhysicalDevice physicalDevice,vk::VkSurfaceKHR surface)126 deUint32 chooseQueueFamilyIndex (const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice, vk::VkSurfaceKHR surface)
127 {
128 	const vector<deUint32>	supportedFamilyIndices	= getSupportedQueueFamilyIndices(vki, physicalDevice, surface);
129 
130 	if (supportedFamilyIndices.empty())
131 		TCU_THROW(NotSupportedError, "Device doesn't support presentation");
132 
133 	return supportedFamilyIndices[0];
134 }
135 
createDeviceWithWsi(const vk::PlatformInterface & vkp,vk::VkInstance instance,const vk::InstanceInterface & vki,vk::VkPhysicalDevice physicalDevice,const Extensions & supportedExtensions,const deUint32 queueFamilyIndex,bool requiresIncrementalPresent,const vk::VkAllocationCallbacks * pAllocator=DE_NULL)136 vk::Move<vk::VkDevice> createDeviceWithWsi (const vk::PlatformInterface&		vkp,
137 											vk::VkInstance						instance,
138 											const vk::InstanceInterface&		vki,
139 											vk::VkPhysicalDevice				physicalDevice,
140 											const Extensions&					supportedExtensions,
141 											const deUint32						queueFamilyIndex,
142 											bool								requiresIncrementalPresent,
143 											const vk::VkAllocationCallbacks*	pAllocator = DE_NULL)
144 {
145 	const float							queuePriorities[]	= { 1.0f };
146 	const vk::VkDeviceQueueCreateInfo	queueInfos[]		=
147 	{
148 		{
149 			vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
150 			DE_NULL,
151 			(vk::VkDeviceQueueCreateFlags)0,
152 			queueFamilyIndex,
153 			DE_LENGTH_OF_ARRAY(queuePriorities),
154 			&queuePriorities[0]
155 		}
156 	};
157 	const vk::VkPhysicalDeviceFeatures	features		= getDeviceNullFeatures();
158 	const char* const					extensions[]	=
159 	{
160 		"VK_KHR_swapchain",
161 		"VK_KHR_incremental_present"
162 	};
163 
164 	const vk::VkDeviceCreateInfo		deviceParams	=
165 	{
166 		vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
167 		DE_NULL,
168 		(vk::VkDeviceCreateFlags)0,
169 		DE_LENGTH_OF_ARRAY(queueInfos),
170 		&queueInfos[0],
171 		0u,
172 		DE_NULL,
173 		requiresIncrementalPresent ? 2u : 1u,
174 		DE_ARRAY_BEGIN(extensions),
175 		&features
176 	};
177 
178 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(extensions); ++ndx)
179 	{
180 		if (!isExtensionSupported(supportedExtensions, vk::RequiredExtension(extensions[ndx])))
181 			TCU_THROW(NotSupportedError, (string(extensions[ndx]) + " is not supported").c_str());
182 	}
183 
184 	return createDevice(vkp, instance, vki, physicalDevice, &deviceParams, pAllocator);
185 }
186 
createDisplay(const vk::Platform & platform,const Extensions & supportedExtensions,vk::wsi::Type wsiType)187 de::MovePtr<vk::wsi::Display> createDisplay (const vk::Platform&	platform,
188 											 const Extensions&		supportedExtensions,
189 											 vk::wsi::Type			wsiType)
190 {
191 	try
192 	{
193 		return de::MovePtr<vk::wsi::Display>(platform.createWsiDisplay(wsiType));
194 	}
195 	catch (const tcu::NotSupportedError& e)
196 	{
197 		if (isExtensionSupported(supportedExtensions, vk::RequiredExtension(getExtensionName(wsiType))) &&
198 		    platform.hasDisplay(wsiType))
199 		{
200 			// If VK_KHR_{platform}_surface was supported, vk::Platform implementation
201 			// must support creating native display & window for that WSI type.
202 			throw tcu::TestError(e.getMessage());
203 		}
204 		else
205 			throw;
206 	}
207 }
208 
createWindow(const vk::wsi::Display & display,const Maybe<UVec2> & initialSize)209 de::MovePtr<vk::wsi::Window> createWindow (const vk::wsi::Display& display, const Maybe<UVec2>& initialSize)
210 {
211 	try
212 	{
213 		return de::MovePtr<vk::wsi::Window>(display.createWindow(initialSize));
214 	}
215 	catch (const tcu::NotSupportedError& e)
216 	{
217 		// See createDisplay - assuming that wsi::Display was supported platform port
218 		// should also support creating a window.
219 		throw tcu::TestError(e.getMessage());
220 	}
221 }
222 
initSemaphores(const vk::DeviceInterface & vkd,vk::VkDevice device,std::vector<vk::VkSemaphore> & semaphores)223 void initSemaphores (const vk::DeviceInterface&		vkd,
224 					 vk::VkDevice					device,
225 					 std::vector<vk::VkSemaphore>&	semaphores)
226 {
227 	for (size_t ndx = 0; ndx < semaphores.size(); ndx++)
228 		semaphores[ndx] = createSemaphore(vkd, device).disown();
229 }
230 
deinitSemaphores(const vk::DeviceInterface & vkd,vk::VkDevice device,std::vector<vk::VkSemaphore> & semaphores)231 void deinitSemaphores (const vk::DeviceInterface&	vkd,
232 					 vk::VkDevice					device,
233 					 std::vector<vk::VkSemaphore>&	semaphores)
234 {
235 	for (size_t ndx = 0; ndx < semaphores.size(); ndx++)
236 	{
237 		if (semaphores[ndx] != (vk::VkSemaphore)0)
238 			vkd.destroySemaphore(device, semaphores[ndx], DE_NULL);
239 
240 		semaphores[ndx] = (vk::VkSemaphore)0;
241 	}
242 
243 	semaphores.clear();
244 }
245 
initFences(const vk::DeviceInterface & vkd,vk::VkDevice device,std::vector<vk::VkFence> & fences)246 void initFences (const vk::DeviceInterface&	vkd,
247 				 vk::VkDevice				device,
248 				 std::vector<vk::VkFence>&	fences)
249 {
250 	for (size_t ndx = 0; ndx < fences.size(); ndx++)
251 		fences[ndx] = createFence(vkd, device).disown();
252 }
253 
deinitFences(const vk::DeviceInterface & vkd,vk::VkDevice device,std::vector<vk::VkFence> & fences)254 void deinitFences (const vk::DeviceInterface&	vkd,
255 				   vk::VkDevice					device,
256 				   std::vector<vk::VkFence>&	fences)
257 {
258 	for (size_t ndx = 0; ndx < fences.size(); ndx++)
259 	{
260 		if (fences[ndx] != (vk::VkFence)0)
261 			vkd.destroyFence(device, fences[ndx], DE_NULL);
262 
263 		fences[ndx] = (vk::VkFence)0;
264 	}
265 
266 	fences.clear();
267 }
268 
getRenderFrameRect(size_t frameNdx,deUint32 imageWidth,deUint32 imageHeight)269 vk::VkRect2D getRenderFrameRect (size_t		frameNdx,
270 								 deUint32	imageWidth,
271 								 deUint32	imageHeight)
272 {
273 	const deUint32		x		= frameNdx == 0
274 								? 0
275 								: de::min(((deUint32)frameNdx) % imageWidth, imageWidth - 1u);
276 	const deUint32		y		= frameNdx == 0
277 								? 0
278 								: de::min(((deUint32)frameNdx) % imageHeight, imageHeight - 1u);
279 	const deUint32		width	= frameNdx == 0
280 								? imageWidth
281 								: 1 + de::min((deUint32)(frameNdx) % de::min<deUint32>(100, imageWidth / 3), imageWidth - x);
282 	const deUint32		height	= frameNdx == 0
283 								? imageHeight
284 								: 1 + de::min((deUint32)(frameNdx) % de::min<deUint32>(100, imageHeight / 3), imageHeight - y);
285 	const vk::VkRect2D	rect	=
286 	{
287 		{ (deInt32)x, (deInt32)y },
288 		{ width, height }
289 	};
290 
291 	DE_ASSERT(width > 0);
292 	DE_ASSERT(height > 0);
293 
294 	return rect;
295 }
296 
getUpdatedRects(size_t firstFrameNdx,size_t lastFrameNdx,deUint32 width,deUint32 height)297 vector<vk::VkRectLayerKHR> getUpdatedRects (size_t		firstFrameNdx,
298 											size_t		lastFrameNdx,
299 											deUint32	width,
300 											deUint32	height)
301 {
302 	vector<vk::VkRectLayerKHR> rects;
303 
304 	for (size_t frameNdx =  firstFrameNdx; frameNdx <= lastFrameNdx; frameNdx++)
305 	{
306 		const vk::VkRect2D			rect		= getRenderFrameRect(frameNdx, width, height);
307 		const vk::VkRectLayerKHR	rectLayer	=
308 		{
309 			rect.offset,
310 			rect.extent,
311 			0
312 		};
313 
314 		rects.push_back(rectLayer);
315 	}
316 
317 	return rects;
318 }
319 
cmdRenderFrame(const vk::DeviceInterface & vkd,vk::VkCommandBuffer commandBuffer,vk::VkPipelineLayout pipelineLayout,vk::VkPipeline pipeline,size_t frameNdx,deUint32 imageWidth,deUint32 imageHeight)320 void cmdRenderFrame (const vk::DeviceInterface&	vkd,
321 					 vk::VkCommandBuffer		commandBuffer,
322 					 vk::VkPipelineLayout		pipelineLayout,
323 					 vk::VkPipeline				pipeline,
324 					 size_t						frameNdx,
325 					 deUint32					imageWidth,
326 					 deUint32					imageHeight)
327 {
328 	const deUint32 mask = (deUint32)frameNdx;
329 
330 	if (frameNdx == 0)
331 	{
332 		const vk::VkRect2D	scissor	= vk::makeRect2D(imageWidth, imageHeight);
333 		vkd.cmdSetScissor(commandBuffer, 0u, 1u, &scissor);
334 		const vk::VkClearAttachment	attachment	=
335 		{
336 			vk::VK_IMAGE_ASPECT_COLOR_BIT,
337 			0u,
338 			vk::makeClearValueColorF32(0.25f, 0.50, 0.75f, 1.00f)
339 		};
340 		const vk::VkClearRect		rect		=
341 		{
342 			scissor,
343 			0u,
344 			1u
345 		};
346 
347 		vkd.cmdClearAttachments(commandBuffer, 1u, &attachment, 1u, &rect);
348 	}
349 
350 	{
351 		const vk::VkRect2D	scissor	= getRenderFrameRect(frameNdx, imageWidth, imageHeight);
352 		vkd.cmdSetScissor(commandBuffer, 0u, 1u, &scissor);
353 
354 		vkd.cmdPushConstants(commandBuffer, pipelineLayout, vk::VK_SHADER_STAGE_FRAGMENT_BIT, 0u, 4u, &mask);
355 		vkd.cmdBindPipeline(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
356 		vkd.cmdDraw(commandBuffer, 6u, 1u, 0u, 0u);
357 	}
358 }
359 
createCommandBuffer(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkCommandPool commandPool,vk::VkPipelineLayout pipelineLayout,vk::VkRenderPass renderPass,vk::VkFramebuffer framebuffer,vk::VkPipeline pipeline,vk::VkImage image,bool isFirst,size_t imageNextFrame,size_t currentFrame,deUint32 imageWidth,deUint32 imageHeight)360 vk::Move<vk::VkCommandBuffer> createCommandBuffer (const vk::DeviceInterface&	vkd,
361 												   vk::VkDevice					device,
362 												   vk::VkCommandPool			commandPool,
363 												   vk::VkPipelineLayout			pipelineLayout,
364 												   vk::VkRenderPass				renderPass,
365 												   vk::VkFramebuffer			framebuffer,
366 												   vk::VkPipeline				pipeline,
367 												   vk::VkImage					image,
368 												   bool							isFirst,
369 												   size_t						imageNextFrame,
370 												   size_t						currentFrame,
371 												   deUint32						imageWidth,
372 												   deUint32						imageHeight)
373 {
374 	const vk::VkCommandBufferAllocateInfo allocateInfo =
375 	{
376 		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
377 		DE_NULL,
378 
379 		commandPool,
380 		vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY,
381 		1
382 	};
383 
384 	vk::Move<vk::VkCommandBuffer>	commandBuffer	(vk::allocateCommandBuffer(vkd, device, &allocateInfo));
385 	beginCommandBuffer(vkd, *commandBuffer, 0u);
386 
387 	{
388 		const vk::VkImageSubresourceRange subRange =
389 		{
390 			vk::VK_IMAGE_ASPECT_COLOR_BIT,
391 			0,
392 			1,
393 			0,
394 			1
395 		};
396 		const vk::VkImageMemoryBarrier barrier =
397 		{
398 			vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
399 			DE_NULL,
400 			vk::VK_ACCESS_TRANSFER_WRITE_BIT,
401 			vk::VK_ACCESS_TRANSFER_READ_BIT | vk::VK_ACCESS_TRANSFER_WRITE_BIT,
402 			isFirst ? vk::VK_IMAGE_LAYOUT_UNDEFINED : vk::VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
403 			vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
404 			VK_QUEUE_FAMILY_IGNORED,
405 			VK_QUEUE_FAMILY_IGNORED,
406 			image,
407 			subRange
408 		};
409 		vkd.cmdPipelineBarrier(*commandBuffer, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, DE_NULL, 0, DE_NULL, 1, &barrier);
410 	}
411 
412 	beginRenderPass(vkd, *commandBuffer, renderPass, framebuffer, vk::makeRect2D(imageWidth, imageHeight), tcu::Vec4(0.25f, 0.5f, 0.75f, 1.0f));
413 
414 	for (size_t frameNdx = imageNextFrame; frameNdx <= currentFrame; frameNdx++)
415 		cmdRenderFrame(vkd, *commandBuffer, pipelineLayout, pipeline, frameNdx, imageWidth, imageHeight);
416 
417 	endRenderPass(vkd, *commandBuffer);
418 
419 	endCommandBuffer(vkd, *commandBuffer);
420 	return commandBuffer;
421 }
422 
deinitCommandBuffers(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkCommandPool commandPool,std::vector<vk::VkCommandBuffer> & commandBuffers)423 void deinitCommandBuffers (const vk::DeviceInterface&			vkd,
424 						   vk::VkDevice							device,
425 						   vk::VkCommandPool					commandPool,
426 						   std::vector<vk::VkCommandBuffer>&	commandBuffers)
427 {
428 	for (size_t ndx = 0; ndx < commandBuffers.size(); ndx++)
429 	{
430 		if (commandBuffers[ndx] != (vk::VkCommandBuffer)0)
431 			vkd.freeCommandBuffers(device, commandPool, 1u,  &commandBuffers[ndx]);
432 
433 		commandBuffers[ndx] = (vk::VkCommandBuffer)0;
434 	}
435 
436 	commandBuffers.clear();
437 }
438 
createCommandPool(const vk::DeviceInterface & vkd,vk::VkDevice device,deUint32 queueFamilyIndex)439 vk::Move<vk::VkCommandPool> createCommandPool (const vk::DeviceInterface&	vkd,
440 											   vk::VkDevice					device,
441 											   deUint32						queueFamilyIndex)
442 {
443 	const vk::VkCommandPoolCreateInfo createInfo =
444 	{
445 		vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
446 		DE_NULL,
447 		0u,
448 		queueFamilyIndex
449 	};
450 
451 	return vk::createCommandPool(vkd, device, &createInfo);
452 }
453 
createFramebuffer(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkRenderPass renderPass,vk::VkImageView imageView,deUint32 width,deUint32 height)454 vk::Move<vk::VkFramebuffer>	createFramebuffer (const vk::DeviceInterface&	vkd,
455 											   vk::VkDevice					device,
456 											   vk::VkRenderPass				renderPass,
457 											   vk::VkImageView				imageView,
458 											   deUint32						width,
459 											   deUint32						height)
460 {
461 	const vk::VkFramebufferCreateInfo createInfo =
462 	{
463 		vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
464 		DE_NULL,
465 
466 		0u,
467 		renderPass,
468 		1u,
469 		&imageView,
470 		width,
471 		height,
472 		1u
473 	};
474 
475 	return vk::createFramebuffer(vkd, device, &createInfo);
476 }
477 
initFramebuffers(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkRenderPass renderPass,std::vector<vk::VkImageView> imageViews,deUint32 width,deUint32 height,std::vector<vk::VkFramebuffer> & framebuffers)478 void initFramebuffers (const vk::DeviceInterface&		vkd,
479 					   vk::VkDevice						device,
480 					   vk::VkRenderPass					renderPass,
481 					   std::vector<vk::VkImageView>		imageViews,
482 					   deUint32							width,
483 					   deUint32							height,
484 					   std::vector<vk::VkFramebuffer>&	framebuffers)
485 {
486 	DE_ASSERT(framebuffers.size() == imageViews.size());
487 
488 	for (size_t ndx = 0; ndx < framebuffers.size(); ndx++)
489 		framebuffers[ndx] = createFramebuffer(vkd, device, renderPass, imageViews[ndx], width, height).disown();
490 }
491 
deinitFramebuffers(const vk::DeviceInterface & vkd,vk::VkDevice device,std::vector<vk::VkFramebuffer> & framebuffers)492 void deinitFramebuffers (const vk::DeviceInterface&			vkd,
493 						 vk::VkDevice						device,
494 						 std::vector<vk::VkFramebuffer>&	framebuffers)
495 {
496 	for (size_t ndx = 0; ndx < framebuffers.size(); ndx++)
497 	{
498 		if (framebuffers[ndx] != (vk::VkFramebuffer)0)
499 			vkd.destroyFramebuffer(device, framebuffers[ndx], DE_NULL);
500 
501 		framebuffers[ndx] = (vk::VkFramebuffer)0;
502 	}
503 
504 	framebuffers.clear();
505 }
506 
createImageView(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkImage image,vk::VkFormat format)507 vk::Move<vk::VkImageView> createImageView (const vk::DeviceInterface&	vkd,
508 										   vk::VkDevice					device,
509 										   vk::VkImage					image,
510 										   vk::VkFormat					format)
511 {
512 	const vk::VkImageViewCreateInfo	createInfo =
513 	{
514 		vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
515 		DE_NULL,
516 
517 		0u,
518 		image,
519 		vk::VK_IMAGE_VIEW_TYPE_2D,
520 		format,
521 		vk::makeComponentMappingRGBA(),
522 		{
523 			vk::VK_IMAGE_ASPECT_COLOR_BIT,
524 			0u,
525 			1u,
526 			0u,
527 			1u
528 		}
529 	};
530 
531 	return vk::createImageView(vkd, device, &createInfo, DE_NULL);
532 }
533 
initImageViews(const vk::DeviceInterface & vkd,vk::VkDevice device,const std::vector<vk::VkImage> & images,vk::VkFormat format,std::vector<vk::VkImageView> & imageViews)534 void initImageViews (const vk::DeviceInterface&			vkd,
535 					 vk::VkDevice						device,
536 					 const std::vector<vk::VkImage>&	images,
537 					 vk::VkFormat						format,
538 					 std::vector<vk::VkImageView>&		imageViews)
539 {
540 	DE_ASSERT(images.size() == imageViews.size());
541 
542 	for (size_t ndx = 0; ndx < imageViews.size(); ndx++)
543 		imageViews[ndx] = createImageView(vkd, device, images[ndx], format).disown();
544 }
545 
deinitImageViews(const vk::DeviceInterface & vkd,vk::VkDevice device,std::vector<vk::VkImageView> & imageViews)546 void deinitImageViews (const vk::DeviceInterface&		vkd,
547 					   vk::VkDevice						device,
548 					   std::vector<vk::VkImageView>&	imageViews)
549 {
550 	for (size_t ndx = 0; ndx < imageViews.size(); ndx++)
551 	{
552 		if (imageViews[ndx] != (vk::VkImageView)0)
553 			vkd.destroyImageView(device, imageViews[ndx], DE_NULL);
554 
555 		imageViews[ndx] = (vk::VkImageView)0;
556 	}
557 
558 	imageViews.clear();
559 }
560 
createRenderPass(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkFormat format)561 vk::Move<vk::VkRenderPass> createRenderPass (const vk::DeviceInterface&	vkd,
562 											 vk::VkDevice				device,
563 											 vk::VkFormat				format)
564 {
565 	return vk::makeRenderPass(vkd, device, format, vk::VK_FORMAT_UNDEFINED, vk::VK_ATTACHMENT_LOAD_OP_LOAD, vk::VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
566 }
567 
createPipeline(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkRenderPass renderPass,vk::VkPipelineLayout layout,vk::VkShaderModule vertexShaderModule,vk::VkShaderModule fragmentShaderModule,deUint32 width,deUint32 height)568 vk::Move<vk::VkPipeline> createPipeline (const vk::DeviceInterface&	vkd,
569 										 vk::VkDevice				device,
570 										 vk::VkRenderPass			renderPass,
571 										 vk::VkPipelineLayout		layout,
572 										 vk::VkShaderModule			vertexShaderModule,
573 										 vk::VkShaderModule			fragmentShaderModule,
574 										 deUint32					width,
575 										 deUint32					height)
576 {
577 	const vk::VkPipelineVertexInputStateCreateInfo		vertexInputState	=
578 	{
579 		vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
580 		DE_NULL,
581 		0u,
582 		0u,
583 		DE_NULL,
584 		0u,
585 		DE_NULL
586 	};
587 	const std::vector<vk::VkViewport>					viewports			(1, vk::makeViewport(tcu::UVec2(width, height)));
588 	const std::vector<vk::VkRect2D>						noScissors;
589 
590 	return vk::makeGraphicsPipeline(vkd,										// const DeviceInterface&                        vk
591 									device,										// const VkDevice                                device
592 									layout,										// const VkPipelineLayout                        pipelineLayout
593 									vertexShaderModule,							// const VkShaderModule                          vertexShaderModule
594 									DE_NULL,									// const VkShaderModule                          tessellationControlShaderModule
595 									DE_NULL,									// const VkShaderModule                          tessellationEvalShaderModule
596 									DE_NULL,									// const VkShaderModule                          geometryShaderModule
597 									fragmentShaderModule,						// const VkShaderModule                          fragmentShaderModule
598 									renderPass,									// const VkRenderPass                            renderPass
599 									viewports,									// const std::vector<VkViewport>&                viewports
600 									noScissors,									// const std::vector<VkRect2D>&                  scissors
601 									vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	// const VkPrimitiveTopology                     topology
602 									0u,											// const deUint32                                subpass
603 									0u,											// const deUint32                                patchControlPoints
604 									&vertexInputState);							// const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
605 }
606 
createPipelineLayout(const vk::DeviceInterface & vkd,vk::VkDevice device)607 vk::Move<vk::VkPipelineLayout> createPipelineLayout (const vk::DeviceInterface&	vkd,
608 													 vk::VkDevice				device)
609 {
610 	const vk::VkPushConstantRange			pushConstants[] =
611 	{
612 		{
613 			vk::VK_SHADER_STAGE_FRAGMENT_BIT,
614 			0u,
615 			4u
616 		}
617 	};
618 	const vk::VkPipelineLayoutCreateInfo	createInfo	=
619 	{
620 		vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
621 		DE_NULL,
622 		0u,
623 
624 		0u,
625 		DE_NULL,
626 
627 		DE_LENGTH_OF_ARRAY(pushConstants),
628 		pushConstants
629 	};
630 
631 	return vk::createPipelineLayout(vkd, device, &createInfo);
632 }
633 
634 struct TestConfig
635 {
636 	vk::wsi::Type					wsiType;
637 	Scaling							scaling;
638 	bool							useIncrementalPresent;
639 	vk::VkPresentModeKHR			presentMode;
640 	vk::VkSurfaceTransformFlagsKHR	transform;
641 	vk::VkCompositeAlphaFlagsKHR	alpha;
642 };
643 
644 class IncrementalPresentTestInstance : public TestInstance
645 {
646 public:
647 													IncrementalPresentTestInstance	(Context& context, const TestConfig& testConfig);
648 													~IncrementalPresentTestInstance	(void);
649 
650 	tcu::TestStatus									iterate							(void);
651 
652 private:
653 	const TestConfig								m_testConfig;
654 	const bool										m_useIncrementalPresent;
655 	const vk::PlatformInterface&					m_vkp;
656 	const Extensions								m_instanceExtensions;
657 	const vk::Unique<vk::VkInstance>				m_instance;
658 	const vk::InstanceDriver						m_vki;
659 	const vk::VkPhysicalDevice						m_physicalDevice;
660 	const de::UniquePtr<vk::wsi::Display>			m_nativeDisplay;
661 	const de::UniquePtr<vk::wsi::Window>			m_nativeWindow;
662 	const vk::Unique<vk::VkSurfaceKHR>				m_surface;
663 
664 	const deUint32									m_queueFamilyIndex;
665 	const Extensions								m_deviceExtensions;
666 	const vk::Unique<vk::VkDevice>					m_device;
667 	const vk::DeviceDriver							m_vkd;
668 	const vk::VkQueue								m_queue;
669 
670 	const vk::Unique<vk::VkCommandPool>				m_commandPool;
671 	const vk::Unique<vk::VkShaderModule>			m_vertexShaderModule;
672 	const vk::Unique<vk::VkShaderModule>			m_fragmentShaderModule;
673 	const vk::Unique<vk::VkPipelineLayout>			m_pipelineLayout;
674 
675 	const vk::VkSurfaceCapabilitiesKHR				m_surfaceProperties;
676 	const vector<vk::VkSurfaceFormatKHR>			m_surfaceFormats;
677 	const vector<vk::VkPresentModeKHR>				m_presentModes;
678 
679 	tcu::ResultCollector							m_resultCollector;
680 
681 	vk::Move<vk::VkSwapchainKHR>					m_swapchain;
682 	std::vector<vk::VkImage>						m_swapchainImages;
683 	std::vector<size_t>								m_imageNextFrames;
684 	std::vector<bool>								m_isFirst;
685 
686 	vk::Move<vk::VkRenderPass>						m_renderPass;
687 	vk::Move<vk::VkPipeline>						m_pipeline;
688 
689 	std::vector<vk::VkImageView>					m_swapchainImageViews;
690 	std::vector<vk::VkFramebuffer>					m_framebuffers;
691 	std::vector<vk::VkCommandBuffer>				m_commandBuffers;
692 	std::vector<vk::VkSemaphore>					m_acquireSemaphores;
693 	std::vector<vk::VkSemaphore>					m_renderSemaphores;
694 	std::vector<vk::VkFence>						m_fences;
695 
696 	vk::VkSemaphore									m_freeAcquireSemaphore;
697 	vk::VkSemaphore									m_freeRenderSemaphore;
698 
699 	std::vector<vk::VkSwapchainCreateInfoKHR>		m_swapchainConfigs;
700 	size_t											m_swapchainConfigNdx;
701 
702 	const size_t									m_frameCount;
703 	size_t											m_frameNdx;
704 
705 	const size_t									m_maxOutOfDateCount;
706 	size_t											m_outOfDateCount;
707 
708 	void											initSwapchainResources		(void);
709 	void											deinitSwapchainResources	(void);
710 	void											render						(void);
711 };
712 
generateSwapchainConfigs(vk::VkSurfaceKHR surface,const deUint32 * queueFamilyIndex,Scaling scaling,const vk::VkSurfaceCapabilitiesKHR & properties,const vector<vk::VkSurfaceFormatKHR> & formats,const vector<vk::VkPresentModeKHR> & presentModes,vk::VkPresentModeKHR presentMode,const vk::VkSurfaceTransformFlagsKHR transform,const vk::VkCompositeAlphaFlagsKHR alpha)713 std::vector<vk::VkSwapchainCreateInfoKHR> generateSwapchainConfigs (vk::VkSurfaceKHR						surface,
714 																	const deUint32							*queueFamilyIndex,
715 																	Scaling									scaling,
716 																	const vk::VkSurfaceCapabilitiesKHR&		properties,
717 																	const vector<vk::VkSurfaceFormatKHR>&	formats,
718 																	const vector<vk::VkPresentModeKHR>&		presentModes,
719 																	vk::VkPresentModeKHR					presentMode,
720 																	const vk::VkSurfaceTransformFlagsKHR	transform,
721 																	const vk::VkCompositeAlphaFlagsKHR		alpha)
722 {
723 	const deUint32							imageLayers			= 1u;
724 	const vk::VkImageUsageFlags				imageUsage			= vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
725 	const vk::VkBool32						clipped				= VK_FALSE;
726 	vector<vk::VkSwapchainCreateInfoKHR>	createInfos;
727 
728 	const deUint32				currentWidth		= properties.currentExtent.width != 0xFFFFFFFFu
729 												? properties.currentExtent.width
730 												: de::min(1024u, properties.minImageExtent.width + ((properties.maxImageExtent.width - properties.minImageExtent.width) / 2));
731 	const deUint32				currentHeight		= properties.currentExtent.height != 0xFFFFFFFFu
732 												? properties.currentExtent.height
733 												: de::min(1024u, properties.minImageExtent.height + ((properties.maxImageExtent.height - properties.minImageExtent.height) / 2));
734 
735 	const deUint32				imageWidth		= scaling == SCALING_NONE
736 												? currentWidth
737 												: (scaling == SCALING_UP
738 													? de::max(31u, properties.minImageExtent.width)
739 													: de::min(deSmallestGreaterOrEquallPowerOfTwoU32(currentWidth+1), properties.maxImageExtent.width));
740 	const deUint32				imageHeight		= scaling == SCALING_NONE
741 												? currentHeight
742 												: (scaling == SCALING_UP
743 													? de::max(31u, properties.minImageExtent.height)
744 													: de::min(deSmallestGreaterOrEquallPowerOfTwoU32(currentHeight+1), properties.maxImageExtent.height));
745 	const vk::VkExtent2D		imageSize		= { imageWidth, imageHeight };
746 	const vk::VkExtent2D		dummySize		= { de::max(31u, properties.minImageExtent.width), de::max(31u, properties.minImageExtent.height) };
747 
748 	{
749 		size_t presentModeNdx;
750 
751 		for (presentModeNdx = 0; presentModeNdx < presentModes.size(); presentModeNdx++)
752 		{
753 			if (presentModes[presentModeNdx] == presentMode)
754 				break;
755 		}
756 
757 		if (presentModeNdx == presentModes.size())
758 			TCU_THROW(NotSupportedError, "Present mode not supported");
759 
760 		if ((properties.supportedTransforms & transform) == 0)
761 			TCU_THROW(NotSupportedError, "Transform not supported");
762 
763 		if ((properties.supportedCompositeAlpha & alpha) == 0)
764 			TCU_THROW(NotSupportedError, "Composite alpha not supported");
765 	}
766 
767 	for (size_t formatNdx = 0; formatNdx < formats.size(); formatNdx++)
768 	{
769 
770 		const vk::VkSurfaceTransformFlagBitsKHR	preTransform	= (vk::VkSurfaceTransformFlagBitsKHR)transform;
771 		const vk::VkCompositeAlphaFlagBitsKHR	compositeAlpha	= (vk::VkCompositeAlphaFlagBitsKHR)alpha;
772 		const vk::VkFormat						imageFormat		= formats[formatNdx].format;
773 		const vk::VkColorSpaceKHR				imageColorSpace	= formats[formatNdx].colorSpace;
774 		const vk::VkSwapchainCreateInfoKHR		createInfo		=
775 		{
776 			vk::VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
777 			DE_NULL,
778 			0u,
779 			surface,
780 			properties.minImageCount,
781 			imageFormat,
782 			imageColorSpace,
783 			imageSize,
784 			imageLayers,
785 			imageUsage,
786 			vk::VK_SHARING_MODE_EXCLUSIVE,
787 			1u,
788 			queueFamilyIndex,
789 			preTransform,
790 			compositeAlpha,
791 			presentMode,
792 			clipped,
793 			(vk::VkSwapchainKHR)0
794 		};
795 
796 		createInfos.push_back(createInfo);
797 
798 		// add an extra dummy swapchain
799 		const vk::VkSwapchainCreateInfoKHR		dummyInfo		=
800 		{
801 			vk::VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
802 			DE_NULL,
803 			0u,
804 			surface,
805 			properties.minImageCount,
806 			imageFormat,
807 			imageColorSpace,
808 			dummySize,
809 			imageLayers,
810 			imageUsage,
811 			vk::VK_SHARING_MODE_EXCLUSIVE,
812 			1u,
813 			queueFamilyIndex,
814 			preTransform,
815 			compositeAlpha,
816 			presentMode,
817 			clipped,
818 			(vk::VkSwapchainKHR)0
819 		};
820 
821 		createInfos.push_back(dummyInfo);
822 	}
823 
824 	return createInfos;
825 }
826 
IncrementalPresentTestInstance(Context & context,const TestConfig & testConfig)827 IncrementalPresentTestInstance::IncrementalPresentTestInstance (Context& context, const TestConfig& testConfig)
828 	: TestInstance				(context)
829 	, m_testConfig				(testConfig)
830 	, m_useIncrementalPresent	(testConfig.useIncrementalPresent)
831 	, m_vkp						(context.getPlatformInterface())
832 	, m_instanceExtensions		(vk::enumerateInstanceExtensionProperties(m_vkp, DE_NULL))
833 	, m_instance				(createInstanceWithWsi(m_vkp, context.getUsedApiVersion(), m_instanceExtensions, testConfig.wsiType))
834 	, m_vki						(m_vkp, *m_instance)
835 	, m_physicalDevice			(vk::chooseDevice(m_vki, *m_instance, context.getTestContext().getCommandLine()))
836 	, m_nativeDisplay			(createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(), m_instanceExtensions, testConfig.wsiType))
837 	, m_nativeWindow			(createWindow(*m_nativeDisplay, tcu::nothing<UVec2>()))
838 	, m_surface					(vk::wsi::createSurface(m_vki, *m_instance, testConfig.wsiType, *m_nativeDisplay, *m_nativeWindow))
839 
840 	, m_queueFamilyIndex		(chooseQueueFamilyIndex(m_vki, m_physicalDevice, *m_surface))
841 	, m_deviceExtensions		(vk::enumerateDeviceExtensionProperties(m_vki, m_physicalDevice, DE_NULL))
842 	, m_device					(createDeviceWithWsi(m_vkp, *m_instance, m_vki, m_physicalDevice, m_deviceExtensions, m_queueFamilyIndex, testConfig.useIncrementalPresent))
843 	, m_vkd						(m_vkp, *m_instance, *m_device)
844 	, m_queue					(getDeviceQueue(m_vkd, *m_device, m_queueFamilyIndex, 0u))
845 
846 	, m_commandPool				(createCommandPool(m_vkd, *m_device, m_queueFamilyIndex))
847 	, m_vertexShaderModule		(vk::createShaderModule(m_vkd, *m_device, context.getBinaryCollection().get("quad-vert"), 0u))
848 	, m_fragmentShaderModule	(vk::createShaderModule(m_vkd, *m_device, context.getBinaryCollection().get("quad-frag"), 0u))
849 	, m_pipelineLayout			(createPipelineLayout(m_vkd, *m_device))
850 
851 	, m_surfaceProperties		(vk::wsi::getPhysicalDeviceSurfaceCapabilities(m_vki, m_physicalDevice, *m_surface))
852 	, m_surfaceFormats			(vk::wsi::getPhysicalDeviceSurfaceFormats(m_vki, m_physicalDevice, *m_surface))
853 	, m_presentModes			(vk::wsi::getPhysicalDeviceSurfacePresentModes(m_vki, m_physicalDevice, *m_surface))
854 
855 	, m_freeAcquireSemaphore	((vk::VkSemaphore)0)
856 	, m_freeRenderSemaphore		((vk::VkSemaphore)0)
857 
858 	, m_swapchainConfigs		(generateSwapchainConfigs(*m_surface, &m_queueFamilyIndex, testConfig.scaling, m_surfaceProperties, m_surfaceFormats, m_presentModes, testConfig.presentMode, testConfig.transform, testConfig.alpha))
859 	, m_swapchainConfigNdx		(0u)
860 
861 	, m_frameCount				(60u * 5u)
862 	, m_frameNdx				(0u)
863 
864 	, m_maxOutOfDateCount		(20u)
865 	, m_outOfDateCount			(0u)
866 {
867 	{
868 		const tcu::ScopedLogSection surfaceInfo (m_context.getTestContext().getLog(), "SurfaceCapabilities", "SurfaceCapabilities");
869 		m_context.getTestContext().getLog() << TestLog::Message << m_surfaceProperties << TestLog::EndMessage;
870 	}
871 }
872 
~IncrementalPresentTestInstance(void)873 IncrementalPresentTestInstance::~IncrementalPresentTestInstance (void)
874 {
875 	deinitSwapchainResources();
876 }
877 
initSwapchainResources(void)878 void IncrementalPresentTestInstance::initSwapchainResources (void)
879 {
880 	const size_t		fenceCount	= 6;
881 	const deUint32		imageWidth	= m_swapchainConfigs[m_swapchainConfigNdx].imageExtent.width;
882 	const deUint32		imageHeight	= m_swapchainConfigs[m_swapchainConfigNdx].imageExtent.height;
883 	const vk::VkFormat	imageFormat	= m_swapchainConfigs[m_swapchainConfigNdx].imageFormat;
884 
885 	m_swapchain				= vk::createSwapchainKHR(m_vkd, *m_device, &m_swapchainConfigs[m_swapchainConfigNdx]);
886 	m_swapchainImages		= vk::wsi::getSwapchainImages(m_vkd, *m_device, *m_swapchain);
887 
888 	m_imageNextFrames.resize(m_swapchainImages.size(), 0);
889 	m_isFirst.resize(m_swapchainImages.size(), true);
890 
891 	m_renderPass			= createRenderPass(m_vkd, *m_device, imageFormat);
892 	m_pipeline				= createPipeline(m_vkd, *m_device, *m_renderPass, *m_pipelineLayout, *m_vertexShaderModule, *m_fragmentShaderModule, imageWidth, imageHeight);
893 
894 	m_swapchainImageViews	= std::vector<vk::VkImageView>(m_swapchainImages.size(), (vk::VkImageView)0);
895 	m_framebuffers			= std::vector<vk::VkFramebuffer>(m_swapchainImages.size(), (vk::VkFramebuffer)0);
896 	m_acquireSemaphores		= std::vector<vk::VkSemaphore>(m_swapchainImages.size(), (vk::VkSemaphore)0);
897 	m_renderSemaphores		= std::vector<vk::VkSemaphore>(m_swapchainImages.size(), (vk::VkSemaphore)0);
898 
899 	m_fences				= std::vector<vk::VkFence>(fenceCount, (vk::VkFence)0);
900 	m_commandBuffers		= std::vector<vk::VkCommandBuffer>(m_fences.size(), (vk::VkCommandBuffer)0);
901 
902 	m_freeAcquireSemaphore	= (vk::VkSemaphore)0;
903 	m_freeRenderSemaphore	= (vk::VkSemaphore)0;
904 
905 	m_freeAcquireSemaphore	= createSemaphore(m_vkd, *m_device).disown();
906 	m_freeRenderSemaphore	= createSemaphore(m_vkd, *m_device).disown();
907 
908 	initImageViews(m_vkd, *m_device, m_swapchainImages, imageFormat, m_swapchainImageViews);
909 	initFramebuffers(m_vkd, *m_device, *m_renderPass, m_swapchainImageViews, imageWidth, imageHeight, m_framebuffers);
910 	initSemaphores(m_vkd, *m_device, m_acquireSemaphores);
911 	initSemaphores(m_vkd, *m_device, m_renderSemaphores);
912 
913 	initFences(m_vkd, *m_device, m_fences);
914 }
915 
deinitSwapchainResources(void)916 void IncrementalPresentTestInstance::deinitSwapchainResources (void)
917 {
918 	VK_CHECK(m_vkd.queueWaitIdle(m_queue));
919 
920 	if (m_freeAcquireSemaphore != (vk::VkSemaphore)0)
921 	{
922 		m_vkd.destroySemaphore(*m_device, m_freeAcquireSemaphore, DE_NULL);
923 		m_freeAcquireSemaphore = (vk::VkSemaphore)0;
924 	}
925 
926 	if (m_freeRenderSemaphore != (vk::VkSemaphore)0)
927 	{
928 		m_vkd.destroySemaphore(*m_device, m_freeRenderSemaphore, DE_NULL);
929 		m_freeRenderSemaphore = (vk::VkSemaphore)0;
930 	}
931 
932 	deinitSemaphores(m_vkd, *m_device, m_acquireSemaphores);
933 	deinitSemaphores(m_vkd, *m_device, m_renderSemaphores);
934 	deinitFences(m_vkd, *m_device, m_fences);
935 	deinitCommandBuffers(m_vkd, *m_device, *m_commandPool, m_commandBuffers);
936 	deinitFramebuffers(m_vkd, *m_device, m_framebuffers);
937 	deinitImageViews(m_vkd, *m_device, m_swapchainImageViews);
938 
939 	m_swapchainImages.clear();
940 	m_imageNextFrames.clear();
941 	m_isFirst.clear();
942 
943 	m_swapchain		= vk::Move<vk::VkSwapchainKHR>();
944 	m_renderPass	= vk::Move<vk::VkRenderPass>();
945 	m_pipeline		= vk::Move<vk::VkPipeline>();
946 
947 }
948 
render(void)949 void IncrementalPresentTestInstance::render (void)
950 {
951 	const deUint64		foreverNs		= 0xFFFFFFFFFFFFFFFFul;
952 	const vk::VkFence	fence			= m_fences[m_frameNdx % m_fences.size()];
953 	const deUint32		width			= m_swapchainConfigs[m_swapchainConfigNdx].imageExtent.width;
954 	const deUint32		height			= m_swapchainConfigs[m_swapchainConfigNdx].imageExtent.height;
955 	size_t				imageNextFrame;
956 
957 	// Throttle execution
958 	if (m_frameNdx >= m_fences.size())
959 	{
960 		VK_CHECK(m_vkd.waitForFences(*m_device, 1u, &fence, VK_TRUE, foreverNs));
961 		VK_CHECK(m_vkd.resetFences(*m_device, 1u, &fence));
962 
963 		m_vkd.freeCommandBuffers(*m_device, *m_commandPool, 1u, &m_commandBuffers[m_frameNdx % m_commandBuffers.size()]);
964 		m_commandBuffers[m_frameNdx % m_commandBuffers.size()] = (vk::VkCommandBuffer)0;
965 	}
966 
967 	vk::VkSemaphore		currentAcquireSemaphore	= m_freeAcquireSemaphore;
968 	vk::VkSemaphore		currentRenderSemaphore	= m_freeRenderSemaphore;
969 	deUint32			imageIndex;
970 
971 	// Acquire next image
972 	VK_CHECK(m_vkd.acquireNextImageKHR(*m_device, *m_swapchain, foreverNs, currentAcquireSemaphore, (vk::VkFence)0, &imageIndex));
973 
974 	// Create command buffer
975 	{
976 		imageNextFrame = m_imageNextFrames[imageIndex];
977 		m_commandBuffers[m_frameNdx % m_commandBuffers.size()] = createCommandBuffer(m_vkd, *m_device, *m_commandPool, *m_pipelineLayout, *m_renderPass, m_framebuffers[imageIndex], *m_pipeline, m_swapchainImages[imageIndex], m_isFirst[imageIndex], imageNextFrame, m_frameNdx, width, height).disown();
978 		m_imageNextFrames[imageIndex] = m_frameNdx + 1;
979 		m_isFirst[imageIndex] = false;
980 	}
981 
982 	// Submit command buffer
983 	{
984 		const vk::VkPipelineStageFlags	dstStageMask	= vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
985 		const vk::VkSubmitInfo			submitInfo		=
986 		{
987 			vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
988 			DE_NULL,
989 			1u,
990 			&currentAcquireSemaphore,
991 			&dstStageMask,
992 			1u,
993 			&m_commandBuffers[m_frameNdx % m_commandBuffers.size()],
994 			1u,
995 			&currentRenderSemaphore
996 		};
997 
998 		VK_CHECK(m_vkd.queueSubmit(m_queue, 1u, &submitInfo, fence));
999 	}
1000 
1001 	// Present frame
1002 	if (m_useIncrementalPresent)
1003 	{
1004 		vk::VkResult result;
1005 		const vector<vk::VkRectLayerKHR>	rects		= getUpdatedRects(imageNextFrame, m_frameNdx, width, height);
1006 		const vk::VkPresentRegionKHR		region		=
1007 		{
1008 			(deUint32)rects.size(),
1009 			rects.empty() ? DE_NULL : &rects[0]
1010 		};
1011 		const vk::VkPresentRegionsKHR	regionInfo	=
1012 		{
1013 			vk::VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR,
1014 			DE_NULL,
1015 			1u,
1016 			&region
1017 		};
1018 		const vk::VkPresentInfoKHR presentInfo =
1019 		{
1020 			vk::VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
1021 			&regionInfo,
1022 			1u,
1023 			&currentRenderSemaphore,
1024 			1u,
1025 			&*m_swapchain,
1026 			&imageIndex,
1027 			&result
1028 		};
1029 
1030 		VK_CHECK_WSI(m_vkd.queuePresentKHR(m_queue, &presentInfo));
1031 		VK_CHECK_WSI(result);
1032 	}
1033 	else
1034 	{
1035 		vk::VkResult result;
1036 		const vk::VkPresentInfoKHR presentInfo =
1037 		{
1038 			vk::VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
1039 			DE_NULL,
1040 			1u,
1041 			&currentRenderSemaphore,
1042 			1u,
1043 			&*m_swapchain,
1044 			&imageIndex,
1045 			&result
1046 		};
1047 
1048 		VK_CHECK_WSI(m_vkd.queuePresentKHR(m_queue, &presentInfo));
1049 		VK_CHECK_WSI(result);
1050 	}
1051 
1052 	{
1053 		m_freeAcquireSemaphore = m_acquireSemaphores[imageIndex];
1054 		m_acquireSemaphores[imageIndex] = currentAcquireSemaphore;
1055 
1056 		m_freeRenderSemaphore = m_renderSemaphores[imageIndex];
1057 		m_renderSemaphores[imageIndex] = currentRenderSemaphore;
1058 	}
1059 }
1060 
iterate(void)1061 tcu::TestStatus IncrementalPresentTestInstance::iterate (void)
1062 {
1063 	// Initialize swapchain specific resources
1064 	// Render test
1065 	try
1066 	{
1067 		if (m_frameNdx == 0)
1068 		{
1069 			if (m_outOfDateCount == 0)
1070 				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Swapchain: " << m_swapchainConfigs[m_swapchainConfigNdx] << tcu::TestLog::EndMessage;
1071 
1072 			initSwapchainResources();
1073 		}
1074 
1075 		render();
1076 	}
1077 	catch (const vk::Error& error)
1078 	{
1079 		if (error.getError() == vk::VK_ERROR_OUT_OF_DATE_KHR)
1080 		{
1081 			m_swapchainConfigs = generateSwapchainConfigs(*m_surface, &m_queueFamilyIndex, m_testConfig.scaling, m_surfaceProperties, m_surfaceFormats, m_presentModes, m_testConfig.presentMode, m_testConfig.transform, m_testConfig.alpha);
1082 
1083 			if (m_outOfDateCount < m_maxOutOfDateCount)
1084 			{
1085 				m_context.getTestContext().getLog() << TestLog::Message << "Frame " << m_frameNdx << ": Swapchain out of date. Recreating resources." << TestLog::EndMessage;
1086 				deinitSwapchainResources();
1087 				m_frameNdx = 0;
1088 				m_outOfDateCount++;
1089 
1090 				return tcu::TestStatus::incomplete();
1091 			}
1092 			else
1093 			{
1094 				m_context.getTestContext().getLog() << TestLog::Message << "Frame " << m_frameNdx << ": Swapchain out of date." << TestLog::EndMessage;
1095 				m_resultCollector.fail("Received too many VK_ERROR_OUT_OF_DATE_KHR errors. Received " + de::toString(m_outOfDateCount) + ", max " + de::toString(m_maxOutOfDateCount));
1096 			}
1097 		}
1098 		else
1099 		{
1100 			m_resultCollector.fail(error.what());
1101 		}
1102 
1103 		deinitSwapchainResources();
1104 
1105 		m_swapchainConfigNdx++;
1106 		m_frameNdx = 0;
1107 		m_outOfDateCount = 0;
1108 
1109 		if (m_swapchainConfigNdx >= m_swapchainConfigs.size())
1110 			return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
1111 		else
1112 			return tcu::TestStatus::incomplete();
1113 	}
1114 
1115 	m_frameNdx++;
1116 
1117 	if (m_frameNdx >= m_frameCount)
1118 	{
1119 		m_frameNdx = 0;
1120 		m_outOfDateCount = 0;
1121 		m_swapchainConfigNdx++;
1122 
1123 		deinitSwapchainResources();
1124 
1125 		if (m_swapchainConfigNdx >= m_swapchainConfigs.size())
1126 			return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
1127 		else
1128 			return tcu::TestStatus::incomplete();
1129 	}
1130 	else
1131 		return tcu::TestStatus::incomplete();
1132 }
1133 
1134 struct Programs
1135 {
initvkt::wsi::__anoncbc7440f0111::Programs1136 	static void init (vk::SourceCollections& dst, TestConfig)
1137 	{
1138 		dst.glslSources.add("quad-vert") << glu::VertexSource(
1139 			"#version 450\n"
1140 			"out gl_PerVertex {\n"
1141 			"\tvec4 gl_Position;\n"
1142 			"};\n"
1143 			"highp float;\n"
1144 			"void main (void) {\n"
1145 			"\tgl_Position = vec4(((gl_VertexIndex + 2) / 3) % 2 == 0 ? -1.0 : 1.0,\n"
1146 			"\t                   ((gl_VertexIndex + 1) / 3) % 2 == 0 ? -1.0 : 1.0, 0.0, 1.0);\n"
1147 			"}\n");
1148 		dst.glslSources.add("quad-frag") << glu::FragmentSource(
1149 			"#version 310 es\n"
1150 			"layout(location = 0) out highp vec4 o_color;\n"
1151 			"layout(push_constant) uniform PushConstant {\n"
1152 			"\thighp uint mask;\n"
1153 			"} pushConstants;\n"
1154 			"void main (void)\n"
1155 			"{\n"
1156 			"\thighp uint mask = pushConstants.mask;\n"
1157 			"\thighp uint x = mask ^ uint(gl_FragCoord.x);\n"
1158 			"\thighp uint y = mask ^ uint(gl_FragCoord.y);\n"
1159 			"\thighp uint r = 128u * bitfieldExtract(x, 0, 1)\n"
1160 			"\t             +  64u * bitfieldExtract(y, 1, 1)\n"
1161 			"\t             +  32u * bitfieldExtract(x, 3, 1);\n"
1162 			"\thighp uint g = 128u * bitfieldExtract(y, 0, 1)\n"
1163 			"\t             +  64u * bitfieldExtract(x, 2, 1)\n"
1164 			"\t             +  32u * bitfieldExtract(y, 3, 1);\n"
1165 			"\thighp uint b = 128u * bitfieldExtract(x, 1, 1)\n"
1166 			"\t             +  64u * bitfieldExtract(y, 2, 1)\n"
1167 			"\t             +  32u * bitfieldExtract(x, 4, 1);\n"
1168 			"\to_color = vec4(float(r) / 255.0, float(g) / 255.0, float(b) / 255.0, 1.0);\n"
1169 			"}\n");
1170 	}
1171 };
1172 
1173 } // anonymous
1174 
createIncrementalPresentTests(tcu::TestCaseGroup * testGroup,vk::wsi::Type wsiType)1175 void createIncrementalPresentTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType)
1176 {
1177 	const struct
1178 	{
1179 		Scaling		scaling;
1180 		const char*	name;
1181 	} scaling [] =
1182 	{
1183 		{ SCALING_NONE,	"scale_none"	},
1184 		{ SCALING_UP,	"scale_up"		},
1185 		{ SCALING_DOWN, "scale_down"	}
1186 	};
1187 	const struct
1188 	{
1189 		vk::VkPresentModeKHR	mode;
1190 		const char*				name;
1191 	} presentModes[] =
1192 	{
1193 		{ vk::VK_PRESENT_MODE_IMMEDIATE_KHR,	"immediate"		},
1194 		{ vk::VK_PRESENT_MODE_MAILBOX_KHR,		"mailbox"		},
1195 		{ vk::VK_PRESENT_MODE_FIFO_KHR,			"fifo"			},
1196 		{ vk::VK_PRESENT_MODE_FIFO_RELAXED_KHR,	"fifo_relaxed"	}
1197 	};
1198 	const struct
1199 	{
1200 		vk::VkSurfaceTransformFlagsKHR	transform;
1201 		const char*						name;
1202 	} transforms[] =
1203 	{
1204 		{ vk::VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR,						"identity"						},
1205 		{ vk::VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR,						"rotate_90"						},
1206 		{ vk::VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR,						"rotate_180"					},
1207 		{ vk::VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR,						"rotate_270"					},
1208 		{ vk::VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR,				"horizontal_mirror"				},
1209 		{ vk::VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR,		"horizontal_mirror_rotate_90"	},
1210 		{ vk::VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR,	"horizontal_mirror_rotate_180"	},
1211 		{ vk::VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR,	"horizontal_mirror_rotate_270"	},
1212 		{ vk::VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR,							"inherit"						}
1213 	};
1214 	const struct
1215 	{
1216 		vk::VkCompositeAlphaFlagsKHR	alpha;
1217 		const char*						name;
1218 	} alphas[] =
1219 	{
1220 		{ vk::VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,			"opaque"			},
1221 		{ vk::VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR,	"pre_multiplied"	},
1222 		{ vk::VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR,	"post_multiplied"	},
1223 		{ vk::VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR,			"inherit"			}
1224 	};
1225 
1226 	for (size_t scalingNdx = 0; scalingNdx < DE_LENGTH_OF_ARRAY(scaling); scalingNdx++)
1227 	{
1228 		if (scaling[scalingNdx].scaling != SCALING_NONE && wsiType == vk::wsi::TYPE_WAYLAND)
1229 			continue;
1230 
1231 		if (scaling[scalingNdx].scaling != SCALING_NONE && vk::wsi::getPlatformProperties(wsiType).swapchainExtent != vk::wsi::PlatformProperties::SWAPCHAIN_EXTENT_SCALED_TO_WINDOW_SIZE)
1232 			continue;
1233 
1234 		{
1235 
1236 			de::MovePtr<tcu::TestCaseGroup>	scaleGroup	(new tcu::TestCaseGroup(testGroup->getTestContext(), scaling[scalingNdx].name, scaling[scalingNdx].name));
1237 
1238 			for (size_t presentModeNdx = 0; presentModeNdx < DE_LENGTH_OF_ARRAY(presentModes); presentModeNdx++)
1239 			{
1240 				de::MovePtr<tcu::TestCaseGroup>	presentModeGroup	(new tcu::TestCaseGroup(testGroup->getTestContext(), presentModes[presentModeNdx].name, presentModes[presentModeNdx].name));
1241 
1242 				for (size_t transformNdx = 0; transformNdx < DE_LENGTH_OF_ARRAY(transforms); transformNdx++)
1243 				{
1244 					de::MovePtr<tcu::TestCaseGroup>	transformGroup	(new tcu::TestCaseGroup(testGroup->getTestContext(), transforms[transformNdx].name, transforms[transformNdx].name));
1245 
1246 					for (size_t alphaNdx = 0; alphaNdx < DE_LENGTH_OF_ARRAY(alphas); alphaNdx++)
1247 					{
1248 						de::MovePtr<tcu::TestCaseGroup>	alphaGroup	(new tcu::TestCaseGroup(testGroup->getTestContext(), alphas[alphaNdx].name, alphas[alphaNdx].name));
1249 
1250 						for (size_t ref = 0; ref < 2; ref++)
1251 						{
1252 							const bool						isReference	= (ref == 0);
1253 							const char* const				name		= isReference ? "reference" : "incremental_present";
1254 							TestConfig						config;
1255 
1256 							config.wsiType					= wsiType;
1257 							config.scaling					= scaling[scalingNdx].scaling;
1258 							config.useIncrementalPresent	= !isReference;
1259 							config.presentMode				= presentModes[presentModeNdx].mode;
1260 							config.transform				= transforms[transformNdx].transform;
1261 							config.alpha					= alphas[alphaNdx].alpha;
1262 
1263 							alphaGroup->addChild(new vkt::InstanceFactory1<IncrementalPresentTestInstance, TestConfig, Programs>(testGroup->getTestContext(), tcu::NODETYPE_SELF_VALIDATE, name, name, Programs(), config));
1264 						}
1265 
1266 						transformGroup->addChild(alphaGroup.release());
1267 					}
1268 
1269 					presentModeGroup->addChild(transformGroup.release());
1270 				}
1271 
1272 				scaleGroup->addChild(presentModeGroup.release());
1273 			}
1274 
1275 			testGroup->addChild(scaleGroup.release());
1276 		}
1277 	}
1278 }
1279 
1280 } // wsi
1281 } // vkt
1282