1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2017 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 VkSwapchain Tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktWsiSwapchainTests.hpp"
25 
26 #include "vktTestCaseUtil.hpp"
27 #include "vktTestGroupUtil.hpp"
28 
29 #include "vkDefs.hpp"
30 #include "vkPlatform.hpp"
31 #include "vkStrUtil.hpp"
32 #include "vkRef.hpp"
33 #include "vkRefUtil.hpp"
34 #include "vkQueryUtil.hpp"
35 #include "vkMemUtil.hpp"
36 #include "vkDeviceUtil.hpp"
37 #include "vkPrograms.hpp"
38 #include "vkTypeUtil.hpp"
39 #include "vkCmdUtil.hpp"
40 #include "vkWsiPlatform.hpp"
41 #include "vkWsiUtil.hpp"
42 #include "vkAllocationCallbackUtil.hpp"
43 #include "vkCmdUtil.hpp"
44 #include "vkObjUtil.hpp"
45 
46 #include "tcuTestLog.hpp"
47 #include "tcuFormatUtil.hpp"
48 #include "tcuPlatform.hpp"
49 #include "tcuResultCollector.hpp"
50 
51 #include "deUniquePtr.hpp"
52 #include "deStringUtil.hpp"
53 #include "deArrayUtil.hpp"
54 #include "deSharedPtr.hpp"
55 
56 #include <limits>
57 
58 namespace vkt
59 {
60 namespace wsi
61 {
62 
63 namespace
64 {
65 
66 using namespace vk;
67 using namespace vk::wsi;
68 
69 using tcu::TestLog;
70 using tcu::Maybe;
71 using tcu::UVec2;
72 
73 using de::MovePtr;
74 using de::UniquePtr;
75 
76 using std::string;
77 using std::vector;
78 
79 typedef vector<VkExtensionProperties> Extensions;
80 
checkAllSupported(const Extensions & supportedExtensions,const vector<string> & requiredExtensions)81 void checkAllSupported (const Extensions& supportedExtensions, const vector<string>& requiredExtensions)
82 {
83 	for (vector<string>::const_iterator requiredExtName = requiredExtensions.begin();
84 		 requiredExtName != requiredExtensions.end();
85 		 ++requiredExtName)
86 	{
87 		if (!isExtensionSupported(supportedExtensions, RequiredExtension(*requiredExtName)))
88 			TCU_THROW(NotSupportedError, (*requiredExtName + " is not supported").c_str());
89 	}
90 }
91 
createInstanceWithWsi(const PlatformInterface & vkp,deUint32 version,const Extensions & supportedExtensions,Type wsiType,const VkAllocationCallbacks * pAllocator=DE_NULL)92 Move<VkInstance> createInstanceWithWsi (const PlatformInterface&		vkp,
93 										deUint32						version,
94 										const Extensions&				supportedExtensions,
95 										Type							wsiType,
96 										const VkAllocationCallbacks*	pAllocator	= DE_NULL)
97 {
98 	vector<string>	extensions;
99 
100 	extensions.push_back("VK_KHR_surface");
101 	extensions.push_back(getExtensionName(wsiType));
102 
103 	// VK_EXT_swapchain_colorspace adds new surface formats. Driver can enumerate
104 	// the formats regardless of whether VK_EXT_swapchain_colorspace was enabled,
105 	// but using them without enabling the extension is not allowed. Thus we have
106 	// two options:
107 	//
108 	// 1) Filter out non-core formats to stay within valid usage.
109 	//
110 	// 2) Enable VK_EXT_swapchain colorspace if advertised by the driver.
111 	//
112 	// We opt for (2) as it provides basic coverage for the extension as a bonus.
113 	if (isExtensionSupported(supportedExtensions, RequiredExtension("VK_EXT_swapchain_colorspace")))
114 		extensions.push_back("VK_EXT_swapchain_colorspace");
115 
116 	checkAllSupported(supportedExtensions, extensions);
117 
118 	return createDefaultInstance(vkp, version, vector<string>(), extensions, pAllocator);
119 }
120 
getDeviceFeaturesForWsi(void)121 VkPhysicalDeviceFeatures getDeviceFeaturesForWsi (void)
122 {
123 	VkPhysicalDeviceFeatures features;
124 	deMemset(&features, 0, sizeof(features));
125 	return features;
126 }
127 
createDeviceWithWsi(const vk::PlatformInterface & vkp,vk::VkInstance instance,const InstanceInterface & vki,VkPhysicalDevice physicalDevice,const Extensions & supportedExtensions,const deUint32 queueFamilyIndex,const VkAllocationCallbacks * pAllocator=DE_NULL)128 Move<VkDevice> createDeviceWithWsi (const vk::PlatformInterface&	vkp,
129 									vk::VkInstance					instance,
130 									const InstanceInterface&		vki,
131 									VkPhysicalDevice				physicalDevice,
132 									const Extensions&				supportedExtensions,
133 									const deUint32					queueFamilyIndex,
134 									const VkAllocationCallbacks*	pAllocator = DE_NULL)
135 {
136 	const float						queuePriorities[]	= { 1.0f };
137 	const VkDeviceQueueCreateInfo	queueInfos[]		=
138 	{
139 		{
140 			VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
141 			DE_NULL,
142 			(VkDeviceQueueCreateFlags)0,
143 			queueFamilyIndex,
144 			DE_LENGTH_OF_ARRAY(queuePriorities),
145 			&queuePriorities[0]
146 		}
147 	};
148 	const VkPhysicalDeviceFeatures	features		= getDeviceFeaturesForWsi();
149 	vector<const char*>		extensions;
150 
151 	if (!isExtensionSupported(supportedExtensions, RequiredExtension("VK_KHR_swapchain")))
152 		TCU_THROW(NotSupportedError, (string(extensions[0]) + " is not supported").c_str());
153 	extensions.push_back("VK_KHR_swapchain");
154 
155 	if (isExtensionSupported(supportedExtensions, RequiredExtension("VK_EXT_hdr_metadata")))
156 		extensions.push_back("VK_EXT_hdr_metadata");
157 
158 	const VkDeviceCreateInfo		deviceParams	=
159 	{
160 		VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
161 		DE_NULL,
162 		(VkDeviceCreateFlags)0,
163 		DE_LENGTH_OF_ARRAY(queueInfos),
164 		&queueInfos[0],
165 		0u,									// enabledLayerCount
166 		DE_NULL,							// ppEnabledLayerNames
167 		(deUint32)extensions.size(),
168 		extensions.empty() ? DE_NULL : &extensions[0],
169 		&features
170 	};
171 
172 	return createDevice(vkp, instance, vki, physicalDevice, &deviceParams, pAllocator);
173 }
174 
getNumQueueFamilyIndices(const InstanceInterface & vki,VkPhysicalDevice physicalDevice)175 deUint32 getNumQueueFamilyIndices (const InstanceInterface& vki, VkPhysicalDevice physicalDevice)
176 {
177 	deUint32	numFamilies		= 0;
178 
179 	vki.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numFamilies, DE_NULL);
180 
181 	return numFamilies;
182 }
183 
getSupportedQueueFamilyIndices(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,VkSurfaceKHR surface)184 vector<deUint32> getSupportedQueueFamilyIndices (const InstanceInterface& vki, VkPhysicalDevice physicalDevice, VkSurfaceKHR surface)
185 {
186 	const deUint32		numTotalFamilyIndices	= getNumQueueFamilyIndices(vki, physicalDevice);
187 	vector<deUint32>	supportedFamilyIndices;
188 
189 	for (deUint32 queueFamilyNdx = 0; queueFamilyNdx < numTotalFamilyIndices; ++queueFamilyNdx)
190 	{
191 		if (getPhysicalDeviceSurfaceSupport(vki, physicalDevice, queueFamilyNdx, surface) != VK_FALSE)
192 			supportedFamilyIndices.push_back(queueFamilyNdx);
193 	}
194 
195 	return supportedFamilyIndices;
196 }
197 
chooseQueueFamilyIndex(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,VkSurfaceKHR surface)198 deUint32 chooseQueueFamilyIndex (const InstanceInterface& vki, VkPhysicalDevice physicalDevice, VkSurfaceKHR surface)
199 {
200 	const vector<deUint32>	supportedFamilyIndices	= getSupportedQueueFamilyIndices(vki, physicalDevice, surface);
201 
202 	if (supportedFamilyIndices.empty())
203 		TCU_THROW(NotSupportedError, "Device doesn't support presentation");
204 
205 	return supportedFamilyIndices[0];
206 }
207 
208 struct InstanceHelper
209 {
210 	const vector<VkExtensionProperties>	supportedExtensions;
211 	const Unique<VkInstance>			instance;
212 	const InstanceDriver				vki;
213 
InstanceHelpervkt::wsi::__anon345ad5070111::InstanceHelper214 	InstanceHelper (Context& context, Type wsiType, const VkAllocationCallbacks* pAllocator = DE_NULL)
215 		: supportedExtensions	(enumerateInstanceExtensionProperties(context.getPlatformInterface(),
216 																	  DE_NULL))
217 		, instance				(createInstanceWithWsi(context.getPlatformInterface(),
218 													   context.getUsedApiVersion(),
219 													   supportedExtensions,
220 													   wsiType,
221 													   pAllocator))
222 		, vki					(context.getPlatformInterface(), *instance)
223 	{}
224 };
225 
226 struct DeviceHelper
227 {
228 	const VkPhysicalDevice	physicalDevice;
229 	const deUint32			queueFamilyIndex;
230 	const Unique<VkDevice>	device;
231 	const DeviceDriver		vkd;
232 	const VkQueue			queue;
233 
DeviceHelpervkt::wsi::__anon345ad5070111::DeviceHelper234 	DeviceHelper (Context&						context,
235 				  const InstanceInterface&		vki,
236 				  VkInstance					instance,
237 				  VkSurfaceKHR					surface,
238 				  const VkAllocationCallbacks*	pAllocator = DE_NULL)
239 		: physicalDevice	(chooseDevice(vki, instance, context.getTestContext().getCommandLine()))
240 		, queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, surface))
241 		, device			(createDeviceWithWsi(context.getPlatformInterface(),
242 												 instance,
243 												 vki,
244 												 physicalDevice,
245 												 enumerateDeviceExtensionProperties(vki, physicalDevice, DE_NULL),
246 												 queueFamilyIndex,
247 												 pAllocator))
248 		, vkd				(context.getPlatformInterface(), instance, *device)
249 		, queue				(getDeviceQueue(vkd, *device, queueFamilyIndex, 0))
250 	{
251 	}
252 };
253 
createDisplay(const vk::Platform & platform,const Extensions & supportedExtensions,Type wsiType)254 MovePtr<Display> createDisplay (const vk::Platform&	platform,
255 								const Extensions&	supportedExtensions,
256 								Type				wsiType)
257 {
258 	try
259 	{
260 		return MovePtr<Display>(platform.createWsiDisplay(wsiType));
261 	}
262 	catch (const tcu::NotSupportedError& e)
263 	{
264 		if (isExtensionSupported(supportedExtensions, RequiredExtension(getExtensionName(wsiType))) &&
265 		    platform.hasDisplay(wsiType))
266 		{
267 			// If VK_KHR_{platform}_surface was supported, vk::Platform implementation
268 			// must support creating native display & window for that WSI type.
269 			throw tcu::TestError(e.getMessage());
270 		}
271 		else
272 			throw;
273 	}
274 }
275 
createWindow(const Display & display,const Maybe<UVec2> & initialSize)276 MovePtr<Window> createWindow (const Display& display, const Maybe<UVec2>& initialSize)
277 {
278 	try
279 	{
280 		return MovePtr<Window>(display.createWindow(initialSize));
281 	}
282 	catch (const tcu::NotSupportedError& e)
283 	{
284 		// See createDisplay - assuming that wsi::Display was supported platform port
285 		// should also support creating a window.
286 		throw tcu::TestError(e.getMessage());
287 	}
288 }
289 
290 struct NativeObjects
291 {
292 	const UniquePtr<Display>	display;
293 	const UniquePtr<Window>		window;
294 
NativeObjectsvkt::wsi::__anon345ad5070111::NativeObjects295 	NativeObjects (Context&				context,
296 				   const Extensions&	supportedExtensions,
297 				   Type					wsiType,
298 				   const Maybe<UVec2>&	initialWindowSize = tcu::nothing<UVec2>())
299 		: display	(createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(), supportedExtensions, wsiType))
300 		, window	(createWindow(*display, initialWindowSize))
301 	{}
302 };
303 
304 enum TestDimension
305 {
306 	TEST_DIMENSION_MIN_IMAGE_COUNT = 0,	//!< Test all supported image counts
307 	TEST_DIMENSION_IMAGE_FORMAT,		//!< Test all supported formats
308 	TEST_DIMENSION_IMAGE_EXTENT,		//!< Test various (supported) extents
309 	TEST_DIMENSION_IMAGE_ARRAY_LAYERS,
310 	TEST_DIMENSION_IMAGE_USAGE,
311 	TEST_DIMENSION_IMAGE_SHARING_MODE,
312 	TEST_DIMENSION_PRE_TRANSFORM,
313 	TEST_DIMENSION_COMPOSITE_ALPHA,
314 	TEST_DIMENSION_PRESENT_MODE,
315 	TEST_DIMENSION_CLIPPED,
316 
317 	TEST_DIMENSION_LAST
318 };
319 
320 struct TestParameters
321 {
322 	Type			wsiType;
323 	TestDimension	dimension;
324 
TestParametersvkt::wsi::__anon345ad5070111::TestParameters325 	TestParameters (Type wsiType_, TestDimension dimension_)
326 		: wsiType	(wsiType_)
327 		, dimension	(dimension_)
328 	{}
329 
TestParametersvkt::wsi::__anon345ad5070111::TestParameters330 	TestParameters (void)
331 		: wsiType	(TYPE_LAST)
332 		, dimension	(TEST_DIMENSION_LAST)
333 	{}
334 };
335 
336 struct GroupParameters
337 {
338 	typedef FunctionInstance1<TestParameters>::Function	Function;
339 
340 	Type		wsiType;
341 	Function	function;
342 
GroupParametersvkt::wsi::__anon345ad5070111::GroupParameters343 	GroupParameters (Type wsiType_, Function function_)
344 		: wsiType	(wsiType_)
345 		, function	(function_)
346 	{}
347 
GroupParametersvkt::wsi::__anon345ad5070111::GroupParameters348 	GroupParameters (void)
349 		: wsiType	(TYPE_LAST)
350 		, function	((Function)DE_NULL)
351 	{}
352 };
353 
getBasicSwapchainParameters(Type wsiType,const InstanceInterface & vki,VkPhysicalDevice physicalDevice,VkSurfaceKHR surface,VkSurfaceFormatKHR surfaceFormat,const tcu::UVec2 & desiredSize,deUint32 desiredImageCount)354 VkSwapchainCreateInfoKHR getBasicSwapchainParameters (Type						wsiType,
355 													  const InstanceInterface&	vki,
356 													  VkPhysicalDevice			physicalDevice,
357 													  VkSurfaceKHR				surface,
358 													  VkSurfaceFormatKHR		surfaceFormat,
359 													  const tcu::UVec2&			desiredSize,
360 													  deUint32					desiredImageCount)
361 {
362 	const VkSurfaceCapabilitiesKHR		capabilities		= getPhysicalDeviceSurfaceCapabilities(vki,
363 																								   physicalDevice,
364 																								   surface);
365 	const PlatformProperties&			platformProperties	= getPlatformProperties(wsiType);
366 	const VkSurfaceTransformFlagBitsKHR transform			= (capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : capabilities.currentTransform;
367 	const VkSwapchainCreateInfoKHR		parameters			=
368 	{
369 		VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
370 		DE_NULL,
371 		(VkSwapchainCreateFlagsKHR)0,
372 		surface,
373 		de::clamp(desiredImageCount, capabilities.minImageCount, capabilities.maxImageCount > 0 ? capabilities.maxImageCount : capabilities.minImageCount + desiredImageCount),
374 		surfaceFormat.format,
375 		surfaceFormat.colorSpace,
376 		(platformProperties.swapchainExtent == PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE
377 			? capabilities.currentExtent : vk::makeExtent2D(desiredSize.x(), desiredSize.y())),
378 		1u,									// imageArrayLayers
379 		VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
380 		VK_SHARING_MODE_EXCLUSIVE,
381 		0u,
382 		(const deUint32*)DE_NULL,
383 		transform,
384 		VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
385 		VK_PRESENT_MODE_FIFO_KHR,
386 		VK_FALSE,							// clipped
387 		(VkSwapchainKHR)0					// oldSwapchain
388 	};
389 
390 	return parameters;
391 }
392 
393 typedef de::SharedPtr<Unique<VkImageView> >		ImageViewSp;
394 typedef de::SharedPtr<Unique<VkFramebuffer> >	FramebufferSp;
395 
396 class TriangleRenderer
397 {
398 public:
399 									TriangleRenderer	(const DeviceInterface&		vkd,
400 														 const VkDevice				device,
401 														 Allocator&					allocator,
402 														 const BinaryCollection&	binaryRegistry,
403 														 const vector<VkImage>		swapchainImages,
404 														 const VkFormat				framebufferFormat,
405 														 const UVec2&				renderSize);
406 									~TriangleRenderer	(void);
407 
408 	void							recordFrame			(VkCommandBuffer			cmdBuffer,
409 														 deUint32					imageNdx,
410 														 deUint32					frameNdx) const;
411 
412 	static void						getPrograms			(SourceCollections& dst);
413 
414 private:
415 	static Move<VkRenderPass>		createRenderPass	(const DeviceInterface&		vkd,
416 														 const VkDevice				device,
417 														 const VkFormat				colorAttachmentFormat);
418 	static Move<VkPipelineLayout>	createPipelineLayout(const DeviceInterface&		vkd,
419 														 VkDevice					device);
420 	static Move<VkPipeline>			createPipeline		(const DeviceInterface&		vkd,
421 														 const VkDevice				device,
422 														 const VkRenderPass			renderPass,
423 														 const VkPipelineLayout		pipelineLayout,
424 														 const BinaryCollection&	binaryCollection,
425 														 const UVec2&				renderSize);
426 
427 	static Move<VkImageView>		createAttachmentView(const DeviceInterface&		vkd,
428 														 const VkDevice				device,
429 														 const VkImage				image,
430 														 const VkFormat				format);
431 	static Move<VkFramebuffer>		createFramebuffer	(const DeviceInterface&		vkd,
432 														 const VkDevice				device,
433 														 const VkRenderPass			renderPass,
434 														 const VkImageView			colorAttachment,
435 														 const UVec2&				renderSize);
436 
437 	static Move<VkBuffer>			createBuffer		(const DeviceInterface&		vkd,
438 														 VkDevice					device,
439 														 VkDeviceSize				size,
440 														 VkBufferUsageFlags			usage);
441 
442 	const DeviceInterface&			m_vkd;
443 
444 	const vector<VkImage>			m_swapchainImages;
445 	const tcu::UVec2				m_renderSize;
446 
447 	const Unique<VkRenderPass>		m_renderPass;
448 	const Unique<VkPipelineLayout>	m_pipelineLayout;
449 	const Unique<VkPipeline>		m_pipeline;
450 
451 	const Unique<VkBuffer>			m_vertexBuffer;
452 	const UniquePtr<Allocation>		m_vertexBufferMemory;
453 
454 	vector<ImageViewSp>				m_attachmentViews;
455 	vector<FramebufferSp>			m_framebuffers;
456 };
457 
createRenderPass(const DeviceInterface & vkd,const VkDevice device,const VkFormat colorAttachmentFormat)458 Move<VkRenderPass> TriangleRenderer::createRenderPass (const DeviceInterface&	vkd,
459 													   const VkDevice			device,
460 													   const VkFormat			colorAttachmentFormat)
461 {
462 	const VkAttachmentDescription	colorAttDesc		=
463 	{
464 		(VkAttachmentDescriptionFlags)0,
465 		colorAttachmentFormat,
466 		VK_SAMPLE_COUNT_1_BIT,
467 		VK_ATTACHMENT_LOAD_OP_CLEAR,
468 		VK_ATTACHMENT_STORE_OP_STORE,
469 		VK_ATTACHMENT_LOAD_OP_DONT_CARE,
470 		VK_ATTACHMENT_STORE_OP_DONT_CARE,
471 		VK_IMAGE_LAYOUT_UNDEFINED,
472 		VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
473 	};
474 	const VkAttachmentReference		colorAttRef			=
475 	{
476 		0u,
477 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
478 	};
479 	const VkSubpassDescription		subpassDesc			=
480 	{
481 		(VkSubpassDescriptionFlags)0u,
482 		VK_PIPELINE_BIND_POINT_GRAPHICS,
483 		0u,							// inputAttachmentCount
484 		DE_NULL,					// pInputAttachments
485 		1u,							// colorAttachmentCount
486 		&colorAttRef,				// pColorAttachments
487 		DE_NULL,					// pResolveAttachments
488 		DE_NULL,					// depthStencilAttachment
489 		0u,							// preserveAttachmentCount
490 		DE_NULL,					// pPreserveAttachments
491 	};
492 	const VkSubpassDependency		dependencies[]		=
493 	{
494 		{
495 			VK_SUBPASS_EXTERNAL,	// srcSubpass
496 			0u,						// dstSubpass
497 			VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
498 			VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
499 			VK_ACCESS_MEMORY_READ_BIT,
500 			(VK_ACCESS_COLOR_ATTACHMENT_READ_BIT|
501 			 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
502 			VK_DEPENDENCY_BY_REGION_BIT
503 		},
504 		{
505 			0u,						// srcSubpass
506 			VK_SUBPASS_EXTERNAL,	// dstSubpass
507 			VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
508 			VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
509 			(VK_ACCESS_COLOR_ATTACHMENT_READ_BIT|
510 			 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
511 			VK_ACCESS_MEMORY_READ_BIT,
512 			VK_DEPENDENCY_BY_REGION_BIT
513 		},
514 	};
515 	const VkRenderPassCreateInfo	renderPassParams	=
516 	{
517 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
518 		DE_NULL,
519 		(VkRenderPassCreateFlags)0,
520 		1u,
521 		&colorAttDesc,
522 		1u,
523 		&subpassDesc,
524 		DE_LENGTH_OF_ARRAY(dependencies),
525 		dependencies,
526 	};
527 
528 	return vk::createRenderPass(vkd, device, &renderPassParams);
529 }
530 
createPipelineLayout(const DeviceInterface & vkd,const VkDevice device)531 Move<VkPipelineLayout> TriangleRenderer::createPipelineLayout (const DeviceInterface&	vkd,
532 															   const VkDevice			device)
533 {
534 	const VkPushConstantRange						pushConstantRange		=
535 	{
536 		VK_SHADER_STAGE_VERTEX_BIT,
537 		0u,											// offset
538 		(deUint32)sizeof(deUint32),					// size
539 	};
540 	const VkPipelineLayoutCreateInfo				pipelineLayoutParams	=
541 	{
542 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
543 		DE_NULL,
544 		(vk::VkPipelineLayoutCreateFlags)0,
545 		0u,											// setLayoutCount
546 		DE_NULL,									// pSetLayouts
547 		1u,
548 		&pushConstantRange,
549 	};
550 
551 	return vk::createPipelineLayout(vkd, device, &pipelineLayoutParams);
552 }
553 
createPipeline(const DeviceInterface & vkd,const VkDevice device,const VkRenderPass renderPass,const VkPipelineLayout pipelineLayout,const BinaryCollection & binaryCollection,const UVec2 & renderSize)554 Move<VkPipeline> TriangleRenderer::createPipeline (const DeviceInterface&	vkd,
555 												   const VkDevice			device,
556 												   const VkRenderPass		renderPass,
557 												   const VkPipelineLayout	pipelineLayout,
558 												   const BinaryCollection&	binaryCollection,
559 												   const UVec2&				renderSize)
560 {
561 	// \note VkShaderModules are fully consumed by vkCreateGraphicsPipelines()
562 	//		 and can be deleted immediately following that call.
563 	const Unique<VkShaderModule>					vertShaderModule		(createShaderModule(vkd, device, binaryCollection.get("tri-vert"), 0));
564 	const Unique<VkShaderModule>					fragShaderModule		(createShaderModule(vkd, device, binaryCollection.get("tri-frag"), 0));
565 	const std::vector<VkViewport>					viewports				(1, makeViewport(renderSize));
566 	const std::vector<VkRect2D>						scissors				(1, makeRect2D(renderSize));
567 
568 	return vk::makeGraphicsPipeline(vkd,				// const DeviceInterface&            vk
569 									device,				// const VkDevice                    device
570 									pipelineLayout,		// const VkPipelineLayout            pipelineLayout
571 									*vertShaderModule,	// const VkShaderModule              vertexShaderModule
572 									DE_NULL,			// const VkShaderModule              tessellationControlShaderModule
573 									DE_NULL,			// const VkShaderModule              tessellationEvalShaderModule
574 									DE_NULL,			// const VkShaderModule              geometryShaderModule
575 									*fragShaderModule,	// const VkShaderModule              fragmentShaderModule
576 									renderPass,			// const VkRenderPass                renderPass
577 									viewports,			// const std::vector<VkViewport>&    viewports
578 									scissors);			// const std::vector<VkRect2D>&      scissors
579 }
580 
createAttachmentView(const DeviceInterface & vkd,const VkDevice device,const VkImage image,const VkFormat format)581 Move<VkImageView> TriangleRenderer::createAttachmentView (const DeviceInterface&	vkd,
582 														  const VkDevice			device,
583 														  const VkImage				image,
584 														  const VkFormat			format)
585 {
586 	const VkImageViewCreateInfo		viewParams	=
587 	{
588 		VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
589 		DE_NULL,
590 		(VkImageViewCreateFlags)0,
591 		image,
592 		VK_IMAGE_VIEW_TYPE_2D,
593 		format,
594 		vk::makeComponentMappingRGBA(),
595 		{
596 			VK_IMAGE_ASPECT_COLOR_BIT,
597 			0u,						// baseMipLevel
598 			1u,						// levelCount
599 			0u,						// baseArrayLayer
600 			1u,						// layerCount
601 		},
602 	};
603 
604 	return vk::createImageView(vkd, device, &viewParams);
605 }
606 
createFramebuffer(const DeviceInterface & vkd,const VkDevice device,const VkRenderPass renderPass,const VkImageView colorAttachment,const UVec2 & renderSize)607 Move<VkFramebuffer> TriangleRenderer::createFramebuffer	(const DeviceInterface&		vkd,
608 														 const VkDevice				device,
609 														 const VkRenderPass			renderPass,
610 														 const VkImageView			colorAttachment,
611 														 const UVec2&				renderSize)
612 {
613 	const VkFramebufferCreateInfo	framebufferParams	=
614 	{
615 		VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
616 		DE_NULL,
617 		(VkFramebufferCreateFlags)0,
618 		renderPass,
619 		1u,
620 		&colorAttachment,
621 		renderSize.x(),
622 		renderSize.y(),
623 		1u,							// layers
624 	};
625 
626 	return vk::createFramebuffer(vkd, device, &framebufferParams);
627 }
628 
createBuffer(const DeviceInterface & vkd,VkDevice device,VkDeviceSize size,VkBufferUsageFlags usage)629 Move<VkBuffer> TriangleRenderer::createBuffer (const DeviceInterface&	vkd,
630 											   VkDevice					device,
631 											   VkDeviceSize				size,
632 											   VkBufferUsageFlags		usage)
633 {
634 	const VkBufferCreateInfo	bufferParams	=
635 	{
636 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
637 		DE_NULL,
638 		(VkBufferCreateFlags)0,
639 		size,
640 		usage,
641 		VK_SHARING_MODE_EXCLUSIVE,
642 		0,
643 		DE_NULL
644 	};
645 
646 	return vk::createBuffer(vkd, device, &bufferParams);
647 }
648 
TriangleRenderer(const DeviceInterface & vkd,const VkDevice device,Allocator & allocator,const BinaryCollection & binaryRegistry,const vector<VkImage> swapchainImages,const VkFormat framebufferFormat,const UVec2 & renderSize)649 TriangleRenderer::TriangleRenderer (const DeviceInterface&	vkd,
650 									const VkDevice			device,
651 									Allocator&				allocator,
652 									const BinaryCollection&	binaryRegistry,
653 									const vector<VkImage>	swapchainImages,
654 									const VkFormat			framebufferFormat,
655 									const UVec2&			renderSize)
656 	: m_vkd					(vkd)
657 	, m_swapchainImages		(swapchainImages)
658 	, m_renderSize			(renderSize)
659 	, m_renderPass			(createRenderPass(vkd, device, framebufferFormat))
660 	, m_pipelineLayout		(createPipelineLayout(vkd, device))
661 	, m_pipeline			(createPipeline(vkd, device, *m_renderPass, *m_pipelineLayout, binaryRegistry, renderSize))
662 	, m_vertexBuffer		(createBuffer(vkd, device, (VkDeviceSize)(sizeof(float)*4*3), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT))
663 	, m_vertexBufferMemory	(allocator.allocate(getBufferMemoryRequirements(vkd, device, *m_vertexBuffer),
664 							 MemoryRequirement::HostVisible))
665 {
666 	m_attachmentViews.resize(swapchainImages.size());
667 	m_framebuffers.resize(swapchainImages.size());
668 
669 	for (size_t imageNdx = 0; imageNdx < swapchainImages.size(); ++imageNdx)
670 	{
671 		m_attachmentViews[imageNdx]	= ImageViewSp(new Unique<VkImageView>(createAttachmentView(vkd, device, swapchainImages[imageNdx], framebufferFormat)));
672 		m_framebuffers[imageNdx]	= FramebufferSp(new Unique<VkFramebuffer>(createFramebuffer(vkd, device, *m_renderPass, **m_attachmentViews[imageNdx], renderSize)));
673 	}
674 
675 	VK_CHECK(vkd.bindBufferMemory(device, *m_vertexBuffer, m_vertexBufferMemory->getMemory(), m_vertexBufferMemory->getOffset()));
676 
677 	{
678 		const VkMappedMemoryRange	memRange	=
679 		{
680 			VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
681 			DE_NULL,
682 			m_vertexBufferMemory->getMemory(),
683 			m_vertexBufferMemory->getOffset(),
684 			VK_WHOLE_SIZE
685 		};
686 		const tcu::Vec4				vertices[]	=
687 		{
688 			tcu::Vec4(-0.5f, -0.5f, 0.0f, 1.0f),
689 			tcu::Vec4(+0.5f, -0.5f, 0.0f, 1.0f),
690 			tcu::Vec4( 0.0f, +0.5f, 0.0f, 1.0f)
691 		};
692 		DE_STATIC_ASSERT(sizeof(vertices) == sizeof(float)*4*3);
693 
694 		deMemcpy(m_vertexBufferMemory->getHostPtr(), &vertices[0], sizeof(vertices));
695 		VK_CHECK(vkd.flushMappedMemoryRanges(device, 1u, &memRange));
696 	}
697 }
698 
~TriangleRenderer(void)699 TriangleRenderer::~TriangleRenderer (void)
700 {
701 }
702 
recordFrame(VkCommandBuffer cmdBuffer,deUint32 imageNdx,deUint32 frameNdx) const703 void TriangleRenderer::recordFrame (VkCommandBuffer	cmdBuffer,
704 									deUint32		imageNdx,
705 									deUint32		frameNdx) const
706 {
707 	const VkFramebuffer	curFramebuffer	= **m_framebuffers[imageNdx];
708 
709 	beginCommandBuffer(m_vkd, cmdBuffer, 0u);
710 
711 	beginRenderPass(m_vkd, cmdBuffer, *m_renderPass, curFramebuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), tcu::Vec4(0.125f, 0.25f, 0.75f, 1.0f));
712 
713 	m_vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
714 
715 	{
716 		const VkDeviceSize bindingOffset = 0;
717 		m_vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &m_vertexBuffer.get(), &bindingOffset);
718 	}
719 
720 	m_vkd.cmdPushConstants(cmdBuffer, *m_pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, (deUint32)sizeof(deUint32), &frameNdx);
721 	m_vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u);
722 	endRenderPass(m_vkd, cmdBuffer);
723 
724 	endCommandBuffer(m_vkd, cmdBuffer);
725 }
726 
getPrograms(SourceCollections & dst)727 void TriangleRenderer::getPrograms (SourceCollections& dst)
728 {
729 	dst.glslSources.add("tri-vert") << glu::VertexSource(
730 		"#version 310 es\n"
731 		"layout(location = 0) in highp vec4 a_position;\n"
732 		"layout(push_constant) uniform FrameData\n"
733 		"{\n"
734 		"    highp uint frameNdx;\n"
735 		"} frameData;\n"
736 		"void main (void)\n"
737 		"{\n"
738 		"    highp float angle = float(frameData.frameNdx) / 100.0;\n"
739 		"    highp float c     = cos(angle);\n"
740 		"    highp float s     = sin(angle);\n"
741 		"    highp mat4  t     = mat4( c, -s,  0,  0,\n"
742 		"                              s,  c,  0,  0,\n"
743 		"                              0,  0,  1,  0,\n"
744 		"                              0,  0,  0,  1);\n"
745 		"    gl_Position = t * a_position;\n"
746 		"}\n");
747 	dst.glslSources.add("tri-frag") << glu::FragmentSource(
748 		"#version 310 es\n"
749 		"layout(location = 0) out lowp vec4 o_color;\n"
750 		"void main (void) { o_color = vec4(1.0, 0.0, 1.0, 1.0); }\n");
751 }
752 
753 typedef de::SharedPtr<Unique<VkCommandBuffer> >	CommandBufferSp;
754 typedef de::SharedPtr<Unique<VkFence> >			FenceSp;
755 typedef de::SharedPtr<Unique<VkSemaphore> >		SemaphoreSp;
756 
createFences(const DeviceInterface & vkd,const VkDevice device,size_t numFences)757 vector<FenceSp> createFences (const DeviceInterface&	vkd,
758 							  const VkDevice			device,
759 							  size_t					numFences)
760 {
761 	vector<FenceSp> fences(numFences);
762 
763 	for (size_t ndx = 0; ndx < numFences; ++ndx)
764 		fences[ndx] = FenceSp(new Unique<VkFence>(createFence(vkd, device)));
765 
766 	return fences;
767 }
768 
createSemaphores(const DeviceInterface & vkd,const VkDevice device,size_t numSemaphores)769 vector<SemaphoreSp> createSemaphores (const DeviceInterface&	vkd,
770 									  const VkDevice			device,
771 									  size_t					numSemaphores)
772 {
773 	vector<SemaphoreSp> semaphores(numSemaphores);
774 
775 	for (size_t ndx = 0; ndx < numSemaphores; ++ndx)
776 		semaphores[ndx] = SemaphoreSp(new Unique<VkSemaphore>(createSemaphore(vkd, device)));
777 
778 	return semaphores;
779 }
780 
allocateCommandBuffers(const DeviceInterface & vkd,const VkDevice device,const VkCommandPool commandPool,const VkCommandBufferLevel level,const size_t numCommandBuffers)781 vector<CommandBufferSp> allocateCommandBuffers (const DeviceInterface&		vkd,
782 												const VkDevice				device,
783 												const VkCommandPool			commandPool,
784 												const VkCommandBufferLevel	level,
785 												const size_t				numCommandBuffers)
786 {
787 	vector<CommandBufferSp>				buffers		(numCommandBuffers);
788 
789 	for (size_t ndx = 0; ndx < numCommandBuffers; ++ndx)
790 		buffers[ndx] = CommandBufferSp(new Unique<VkCommandBuffer>(allocateCommandBuffer(vkd, device, commandPool, level)));
791 
792 	return buffers;
793 }
794 
basicExtensionTest(Context & context,Type wsiType)795 tcu::TestStatus basicExtensionTest (Context& context, Type wsiType)
796 {
797 	const tcu::UVec2				desiredSize		(256, 256);
798 	const InstanceHelper			instHelper		(context, wsiType);
799 	const NativeObjects				native			(context, instHelper.supportedExtensions, wsiType, tcu::just(desiredSize));
800 	const Unique<VkSurfaceKHR>		surface			(createSurface(instHelper.vki, *instHelper.instance, wsiType, *native.display, *native.window));
801 	const DeviceHelper				devHelper		(context, instHelper.vki, *instHelper.instance, *surface);
802 
803 	if (!de::contains(context.getInstanceExtensions().begin(), context.getInstanceExtensions().end(), "VK_EXT_swapchain_colorspace"))
804 		TCU_THROW(NotSupportedError, "Extension VK_EXT_swapchain_colorspace not supported");
805 
806 	const vector<VkSurfaceFormatKHR>	formats			= getPhysicalDeviceSurfaceFormats(instHelper.vki,
807 																						  devHelper.physicalDevice,
808 																						  *surface);
809 
810 	bool found = false;
811 	for (vector<VkSurfaceFormatKHR>::const_iterator curFmt = formats.begin(); curFmt != formats.end(); ++curFmt)
812 	{
813 		if (curFmt->colorSpace != VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
814 		{
815 			found = true;
816 			break;
817 		}
818 	}
819 	if (!found)
820 	{
821 		TCU_THROW(NotSupportedError, "VK_EXT_swapchain_colorspace supported, but no non-SRGB_NONLINEAR_KHR surface formats found.");
822 	}
823 	return tcu::TestStatus::pass("Extension tests succeeded");
824 }
825 
surfaceFormatRenderTest(Context & context,Type wsiType,VkSurfaceKHR surface,VkSurfaceFormatKHR curFmt,deBool checkHdr=false)826 tcu::TestStatus surfaceFormatRenderTest (Context& context,
827 										 Type wsiType,
828 										 VkSurfaceKHR surface,
829 										 VkSurfaceFormatKHR curFmt,
830 										 deBool checkHdr = false)
831 {
832 	const tcu::UVec2					desiredSize		(256, 256);
833 	const InstanceHelper				instHelper		(context, wsiType);
834 	const DeviceHelper					devHelper		(context, instHelper.vki, *instHelper.instance, surface);
835 	const DeviceInterface&				vkd				= devHelper.vkd;
836 	const VkDevice						device			= *devHelper.device;
837 	SimpleAllocator						allocator		(vkd, device, getPhysicalDeviceMemoryProperties(instHelper.vki, devHelper.physicalDevice));
838 
839 	const VkSwapchainCreateInfoKHR		swapchainInfo			= getBasicSwapchainParameters(wsiType, instHelper.vki, devHelper.physicalDevice, surface, curFmt, desiredSize, 2);
840 	const Unique<VkSwapchainKHR>		swapchain				(createSwapchainKHR(vkd, device, &swapchainInfo));
841 	const vector<VkImage>				swapchainImages			= getSwapchainImages(vkd, device, *swapchain);
842 	const vector<VkExtensionProperties>	deviceExtensions		(enumerateDeviceExtensionProperties(instHelper.vki, devHelper.physicalDevice, DE_NULL));
843 
844 	if (checkHdr && !isExtensionSupported(deviceExtensions, RequiredExtension("VK_EXT_hdr_metadata")))
845 		TCU_THROW(NotSupportedError, "Extension VK_EXT_hdr_metadata not supported");
846 
847 	const TriangleRenderer			renderer					(vkd,
848 																 device,
849 																 allocator,
850 																 context.getBinaryCollection(),
851 																 swapchainImages,
852 																 swapchainInfo.imageFormat,
853 																 tcu::UVec2(swapchainInfo.imageExtent.width, swapchainInfo.imageExtent.height));
854 
855 	const Unique<VkCommandPool>		commandPool					(createCommandPool(vkd, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, devHelper.queueFamilyIndex));
856 
857 	const size_t					maxQueuedFrames				= swapchainImages.size()*2;
858 
859 	// We need to keep hold of fences from vkAcquireNextImageKHR to actually
860 	// limit number of frames we allow to be queued.
861 	const vector<FenceSp>			imageReadyFences			(createFences(vkd, device, maxQueuedFrames));
862 
863 	// We need maxQueuedFrames+1 for imageReadySemaphores pool as we need to pass
864 	// the semaphore in same time as the fence we use to meter rendering.
865 	const vector<SemaphoreSp>		imageReadySemaphores		(createSemaphores(vkd, device, maxQueuedFrames+1));
866 
867 	// For rest we simply need maxQueuedFrames as we will wait for image
868 	// from frameNdx-maxQueuedFrames to become available to us, guaranteeing that
869 	// previous uses must have completed.
870 	const vector<SemaphoreSp>		renderingCompleteSemaphores	(createSemaphores(vkd, device, maxQueuedFrames));
871 	const vector<CommandBufferSp>	commandBuffers				(allocateCommandBuffers(vkd, device, *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, maxQueuedFrames));
872 
873 	try
874 	{
875 		const deUint32	numFramesToRender	= 60;
876 
877 		for (deUint32 frameNdx = 0; frameNdx < numFramesToRender; ++frameNdx)
878 		{
879 			const VkFence		imageReadyFence		= **imageReadyFences[frameNdx%imageReadyFences.size()];
880 			const VkSemaphore	imageReadySemaphore	= **imageReadySemaphores[frameNdx%imageReadySemaphores.size()];
881 			deUint32			imageNdx			= ~0u;
882 
883 			if (frameNdx >= maxQueuedFrames)
884 				VK_CHECK(vkd.waitForFences(device, 1u, &imageReadyFence, VK_TRUE, std::numeric_limits<deUint64>::max()));
885 
886 			VK_CHECK(vkd.resetFences(device, 1, &imageReadyFence));
887 
888 			{
889 				const VkResult	acquireResult	= vkd.acquireNextImageKHR(device,
890 																		  *swapchain,
891 																		  std::numeric_limits<deUint64>::max(),
892 																		  imageReadySemaphore,
893 																		  (vk::VkFence)0,
894 																		  &imageNdx);
895 
896 				if (acquireResult == VK_SUBOPTIMAL_KHR)
897 					context.getTestContext().getLog() << TestLog::Message << "Got " << acquireResult << " at frame " << frameNdx << TestLog::EndMessage;
898 				else
899 					VK_CHECK(acquireResult);
900 			}
901 
902 			TCU_CHECK((size_t)imageNdx < swapchainImages.size());
903 
904 			{
905 				const VkSemaphore			renderingCompleteSemaphore	= **renderingCompleteSemaphores[frameNdx%renderingCompleteSemaphores.size()];
906 				const VkCommandBuffer		commandBuffer				= **commandBuffers[frameNdx%commandBuffers.size()];
907 				const VkPipelineStageFlags	waitDstStage				= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
908 				const VkSubmitInfo			submitInfo					=
909 				{
910 					VK_STRUCTURE_TYPE_SUBMIT_INFO,
911 					DE_NULL,
912 					1u,
913 					&imageReadySemaphore,
914 					&waitDstStage,
915 					1u,
916 					&commandBuffer,
917 					1u,
918 					&renderingCompleteSemaphore
919 				};
920 				const VkPresentInfoKHR		presentInfo					=
921 				{
922 					VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
923 					DE_NULL,
924 					1u,
925 					&renderingCompleteSemaphore,
926 					1u,
927 					&*swapchain,
928 					&imageNdx,
929 					(VkResult*)DE_NULL
930 				};
931 
932 				if (checkHdr) {
933 					const VkHdrMetadataEXT hdrData = {
934 							VK_STRUCTURE_TYPE_HDR_METADATA_EXT,
935 							DE_NULL,
936 							makeXYColorEXT(0.680f, 0.320f),
937 							makeXYColorEXT(0.265f, 0.690f),
938 							makeXYColorEXT(0.150f, 0.060f),
939 							makeXYColorEXT(0.3127f, 0.3290f),
940 							1000.0,
941 							0.0,
942 							1000.0,
943 							70.0
944 					};
945 					vector<VkSwapchainKHR> swapchainArray;
946 
947 					swapchainArray.push_back(*swapchain);
948 					vkd.setHdrMetadataEXT(device, (deUint32)swapchainArray.size(), swapchainArray.data(), &hdrData);
949 				}
950 
951 				renderer.recordFrame(commandBuffer, imageNdx, frameNdx);
952 				VK_CHECK(vkd.queueSubmit(devHelper.queue, 1u, &submitInfo, imageReadyFence));
953 				VK_CHECK_WSI(vkd.queuePresentKHR(devHelper.queue, &presentInfo));
954 			}
955 		}
956 
957 		VK_CHECK(vkd.deviceWaitIdle(device));
958 	}
959 	catch (...)
960 	{
961 		// Make sure device is idle before destroying resources
962 		vkd.deviceWaitIdle(device);
963 		throw;
964 	}
965 
966 	return tcu::TestStatus::pass("Rendering test succeeded");
967 }
968 
surfaceFormatRenderTests(Context & context,Type wsiType)969 tcu::TestStatus surfaceFormatRenderTests (Context& context, Type wsiType)
970 {
971 	const tcu::UVec2					desiredSize		(256, 256);
972 	const InstanceHelper				instHelper		(context, wsiType);
973 	const NativeObjects					native			(context, instHelper.supportedExtensions, wsiType, tcu::just(desiredSize));
974 	const Unique<VkSurfaceKHR>			surface			(createSurface(instHelper.vki, *instHelper.instance, wsiType, *native.display, *native.window));
975 	const DeviceHelper					devHelper		(context, instHelper.vki, *instHelper.instance, *surface);
976 
977 	if (!de::contains(context.getInstanceExtensions().begin(), context.getInstanceExtensions().end(), "VK_EXT_swapchain_colorspace"))
978 		TCU_THROW(NotSupportedError, "Extension VK_EXT_swapchain_colorspace not supported");
979 
980 	const vector<VkSurfaceFormatKHR>	formats			= getPhysicalDeviceSurfaceFormats(instHelper.vki,
981 																							 devHelper.physicalDevice,
982 																							 *surface);
983 	for (vector<VkSurfaceFormatKHR>::const_iterator curFmt = formats.begin(); curFmt != formats.end(); ++curFmt)
984 	{
985 		surfaceFormatRenderTest(context, wsiType, *surface, *curFmt);
986 	}
987 	return tcu::TestStatus::pass("Rendering tests succeeded");
988 }
989 
surfaceFormatRenderWithHdrTests(Context & context,Type wsiType)990 tcu::TestStatus surfaceFormatRenderWithHdrTests (Context& context, Type wsiType)
991 {
992 	const tcu::UVec2					desiredSize		(256, 256);
993 	const InstanceHelper				instHelper		(context, wsiType);
994 	const NativeObjects					native			(context, instHelper.supportedExtensions, wsiType, tcu::just(desiredSize));
995 	const Unique<VkSurfaceKHR>			surface			(createSurface(instHelper.vki, *instHelper.instance, wsiType, *native.display, *native.window));
996 	const DeviceHelper					devHelper		(context, instHelper.vki, *instHelper.instance, *surface);
997 
998 	if (!de::contains(context.getInstanceExtensions().begin(), context.getInstanceExtensions().end(), "VK_EXT_swapchain_colorspace"))
999 		TCU_THROW(NotSupportedError, "Extension VK_EXT_swapchain_colorspace not supported");
1000 
1001 	const vector<VkSurfaceFormatKHR>	formats			= getPhysicalDeviceSurfaceFormats(instHelper.vki,
1002 																						  devHelper.physicalDevice,
1003 																						  *surface);
1004 	for (vector<VkSurfaceFormatKHR>::const_iterator curFmt = formats.begin(); curFmt != formats.end(); ++curFmt)
1005 	{
1006 		surfaceFormatRenderTest(context, wsiType, *surface, *curFmt, true);
1007 	}
1008 	return tcu::TestStatus::pass("Rendering tests succeeded");
1009 }
1010 
getBasicRenderPrograms(SourceCollections & dst,Type)1011 void getBasicRenderPrograms (SourceCollections& dst, Type)
1012 {
1013 	TriangleRenderer::getPrograms(dst);
1014 }
1015 
1016 } // anonymous
1017 
createColorSpaceTests(tcu::TestCaseGroup * testGroup,vk::wsi::Type wsiType)1018 void createColorSpaceTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType)
1019 {
1020 	addFunctionCase(testGroup, "extensions", "Verify Colorspace Extensions", basicExtensionTest, wsiType);
1021 	addFunctionCaseWithPrograms(testGroup, "basic", "Basic Rendering Tests", getBasicRenderPrograms, surfaceFormatRenderTests, wsiType);
1022 	addFunctionCaseWithPrograms(testGroup, "hdr", "Basic Rendering Tests with HDR", getBasicRenderPrograms, surfaceFormatRenderWithHdrTests, wsiType);
1023 }
1024 
1025 } // wsi
1026 } // vkt
1027