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