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