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