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