1/*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2021 The Khronos Group Inc.
6 * Copyright (c) 2023 LunarG, Inc.
7 * Copyright (c) 2023 Nintendo
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 *	  http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 *//*!
22 * \file
23 * \brief Tests Verifying Graphics Pipeline Libraries
24 *//*--------------------------------------------------------------------*/
25
26#include "vktPipelineLibraryTests.hpp"
27
28#include "vkDefs.hpp"
29#include "vkCmdUtil.hpp"
30#include "vkObjUtil.hpp"
31#include "vkTypeUtil.hpp"
32#include "vkQueryUtil.hpp"
33#include "vkImageUtil.hpp"
34#include "vkBarrierUtil.hpp"
35#include "vkBufferWithMemory.hpp"
36#include "vkImageWithMemory.hpp"
37#include "vkBuilderUtil.hpp"
38#include "vkRayTracingUtil.hpp"
39#include "vktTestCase.hpp"
40#include "vktTestGroupUtil.hpp"
41#include "tcuCommandLine.hpp"
42#include "tcuImageCompare.hpp"
43#include "tcuTestLog.hpp"
44#include "tcuRGBA.hpp"
45
46#include "../draw/vktDrawCreateInfoUtil.hpp"
47#include "deMath.h"
48#include "deRandom.hpp"
49#include "deClock.h"
50
51#include <vector>
52#include <chrono>
53#include <set>
54#include <limits>
55
56namespace vkt
57{
58namespace pipeline
59{
60namespace
61{
62using namespace vk;
63using namespace vkt;
64using namespace tcu;
65
66
67static const deUint32								RENDER_SIZE_WIDTH							= 16u;
68static const deUint32								RENDER_SIZE_HEIGHT							= 16u;
69static const VkColorComponentFlags					COLOR_COMPONENTS_NO_RED						= VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
70static const VkGraphicsPipelineLibraryFlagBitsEXT	GRAPHICS_PIPELINE_LIBRARY_FLAGS[]			=
71{
72	VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT,
73	VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT,
74	VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT,
75	VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT,
76};
77static const VkGraphicsPipelineLibraryFlagsEXT		ALL_GRAPHICS_PIPELINE_LIBRARY_FLAGS			= static_cast<VkGraphicsPipelineLibraryFlagsEXT>(VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT)
78																								| static_cast<VkGraphicsPipelineLibraryFlagsEXT>(VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT)
79																								| static_cast<VkGraphicsPipelineLibraryFlagsEXT>(VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT)
80																								| static_cast<VkGraphicsPipelineLibraryFlagsEXT>(VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT);
81
82struct PipelineTreeNode
83{
84	deInt32		parentIndex;
85	deUint32	shaderCount;
86};
87
88typedef std::vector<PipelineTreeNode>	PipelineTreeConfiguration;
89
90struct TestParams
91{
92	PipelineTreeConfiguration	pipelineTreeConfiguration;
93	bool						optimize;
94	bool						delayedShaderCreate;
95	bool						useMaintenance5;
96};
97
98struct RuntimePipelineTreeNode
99{
100	deInt32												parentIndex;
101	VkGraphicsPipelineLibraryFlagsEXT					graphicsPipelineLibraryFlags;
102	VkGraphicsPipelineLibraryFlagsEXT					subtreeGraphicsPipelineLibraryFlags;
103	Move<VkPipeline>									pipeline;
104	std::vector<VkPipeline>								pipelineLibraries;
105	// We need to track the linked libraries too, included in VkPipelineLibraryCreateInfoKHR->pLibraries
106	std::vector<VkGraphicsPipelineLibraryFlagsEXT>		linkedLibraryFlags;
107};
108
109typedef std::vector<RuntimePipelineTreeNode>	RuntimePipelineTreeConfiguration;
110
111inline UVec4 ivec2uvec (const IVec4& ivec)
112{
113	return UVec4
114	{
115		static_cast<deUint32>(ivec[0]),
116		static_cast<deUint32>(ivec[1]),
117		static_cast<deUint32>(ivec[2]),
118		static_cast<deUint32>(ivec[3]),
119	};
120}
121
122inline std::string getTestName (const PipelineTreeConfiguration& pipelineTreeConfiguration)
123{
124	std::string	result;
125	int			level	= pipelineTreeConfiguration[0].parentIndex;
126
127	for (const auto& node: pipelineTreeConfiguration)
128	{
129		if (level != node.parentIndex)
130		{
131			DE_ASSERT(level < node.parentIndex);
132
133			result += '_';
134
135			level = node.parentIndex;
136		}
137
138		result += de::toString(node.shaderCount);
139	}
140
141	return result;
142}
143
144inline VkPipelineCreateFlags calcPipelineCreateFlags (bool optimize, bool buildLibrary)
145{
146	VkPipelineCreateFlags	result = 0;
147
148	if (buildLibrary)
149		result |= static_cast<VkPipelineCreateFlags>(VK_PIPELINE_CREATE_LIBRARY_BIT_KHR);
150
151	if (optimize)
152	{
153		if (buildLibrary)
154			result |= static_cast<VkPipelineCreateFlags>(VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT);
155		else
156			result |= static_cast<VkPipelineCreateFlags>(VK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXT);
157	}
158
159	return result;
160}
161
162inline VkRenderPass getRenderPass (VkGraphicsPipelineLibraryFlagsEXT subset, VkRenderPass renderPass)
163{
164	static const VkGraphicsPipelineLibraryFlagsEXT	subsetRequiresRenderPass	= static_cast<VkGraphicsPipelineLibraryFlagsEXT>(VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT)
165																				| static_cast<VkGraphicsPipelineLibraryFlagsEXT>(VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT)
166																				| static_cast<VkGraphicsPipelineLibraryFlagsEXT>(VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT);
167	if ((subsetRequiresRenderPass & subset) != 0)
168		return renderPass;
169
170	return DE_NULL;
171}
172
173inline VkGraphicsPipelineLibraryCreateInfoEXT makeGraphicsPipelineLibraryCreateInfo (const VkGraphicsPipelineLibraryFlagsEXT flags)
174{
175	const VkGraphicsPipelineLibraryCreateInfoEXT	graphicsPipelineLibraryCreateInfo =
176	{
177		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT,	//  VkStructureType						sType;
178		DE_NULL,														//  void*								pNext;
179		flags,															//  VkGraphicsPipelineLibraryFlagsEXT	flags;
180	};
181
182	return graphicsPipelineLibraryCreateInfo;
183}
184
185inline VkPipelineLibraryCreateInfoKHR makePipelineLibraryCreateInfo (const std::vector<VkPipeline>& pipelineLibraries)
186{
187	const deUint32							libraryCount				= static_cast<deUint32>(pipelineLibraries.size());
188	const VkPipeline*						libraries					= de::dataOrNull(pipelineLibraries);
189	const VkPipelineLibraryCreateInfoKHR	pipelineLibraryCreateInfo	=
190	{
191		VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR,		//  VkStructureType		sType;
192		DE_NULL,												//  const void*			pNext;
193		libraryCount,											//  deUint32			libraryCount;
194		libraries,												//  const VkPipeline*	pLibraries;
195	};
196
197	return pipelineLibraryCreateInfo;
198}
199
200inline std::string getGraphicsPipelineLibraryFlagsString (const VkGraphicsPipelineLibraryFlagsEXT flags)
201{
202	std::string result;
203
204	if ((flags & VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT) != 0)		result += "VERTEX_INPUT_INTERFACE ";
205	if ((flags & VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT) != 0)	result += "PRE_RASTERIZATION_SHADERS ";
206	if ((flags & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT) != 0)			result += "FRAGMENT_SHADER ";
207	if ((flags & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT) != 0)	result += "FRAGMENT_OUTPUT_INTERFACE ";
208
209	if (!result.empty())
210		result.resize(result.size() - 1);
211
212	return result;
213};
214
215VkImageCreateInfo makeColorImageCreateInfo (const VkFormat format, const deUint32 width, const deUint32 height)
216{
217	const VkImageUsageFlags	usage		= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
218	const VkImageCreateInfo	imageInfo	=
219	{
220		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//  VkStructureType			sType;
221		DE_NULL,								//  const void*				pNext;
222		(VkImageCreateFlags)0,					//  VkImageCreateFlags		flags;
223		VK_IMAGE_TYPE_2D,						//  VkImageType				imageType;
224		format,									//  VkFormat				format;
225		makeExtent3D(width, height, 1),			//  VkExtent3D				extent;
226		1u,										//  deUint32				mipLevels;
227		1u,										//  deUint32				arrayLayers;
228		VK_SAMPLE_COUNT_1_BIT,					//  VkSampleCountFlagBits	samples;
229		VK_IMAGE_TILING_OPTIMAL,				//  VkImageTiling			tiling;
230		usage,									//  VkImageUsageFlags		usage;
231		VK_SHARING_MODE_EXCLUSIVE,				//  VkSharingMode			sharingMode;
232		0u,										//  deUint32				queueFamilyIndexCount;
233		DE_NULL,								//  const deUint32*			pQueueFamilyIndices;
234		VK_IMAGE_LAYOUT_UNDEFINED,				//  VkImageLayout			initialLayout;
235	};
236
237	return imageInfo;
238}
239
240VkImageViewCreateInfo makeImageViewCreateInfo (VkImage image, VkFormat format, VkImageAspectFlags aspectMask)
241{
242	const VkComponentMapping		components			=
243	{
244		VK_COMPONENT_SWIZZLE_R,
245		VK_COMPONENT_SWIZZLE_G,
246		VK_COMPONENT_SWIZZLE_B,
247		VK_COMPONENT_SWIZZLE_A,
248	};
249	const VkImageSubresourceRange	subresourceRange	=
250	{
251		aspectMask,	//  VkImageAspectFlags	aspectMask;
252		0,			//  deUint32			baseMipLevel;
253		1,			//  deUint32			levelCount;
254		0,			//  deUint32			baseArrayLayer;
255		1,			//  deUint32			layerCount;
256	};
257	const VkImageViewCreateInfo		result				=
258	{
259		VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	//  VkStructureType			sType;
260		DE_NULL,									//  const void*				pNext;
261		0u,											//  VkImageViewCreateFlags	flags;
262		image,										//  VkImage					image;
263		VK_IMAGE_VIEW_TYPE_2D,						//  VkImageViewType			viewType;
264		format,										//  VkFormat				format;
265		components,									//  VkComponentMapping		components;
266		subresourceRange,							//  VkImageSubresourceRange	subresourceRange;
267	};
268
269	return result;
270}
271
272VkImageCreateInfo makeDepthImageCreateInfo (const VkFormat format, const deUint32 width, const deUint32 height)
273{
274	const VkImageUsageFlags	usage		= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
275	const VkImageCreateInfo	imageInfo	=
276	{
277		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//  VkStructureType			sType;
278		DE_NULL,								//  const void*				pNext;
279		(VkImageCreateFlags)0,					//  VkImageCreateFlags		flags;
280		VK_IMAGE_TYPE_2D,						//  VkImageType				imageType;
281		format,									//  VkFormat				format;
282		makeExtent3D(width, height, 1),			//  VkExtent3D				extent;
283		1u,										//  deUint32				mipLevels;
284		1u,										//  deUint32				arrayLayers;
285		VK_SAMPLE_COUNT_1_BIT,					//  VkSampleCountFlagBits	samples;
286		VK_IMAGE_TILING_OPTIMAL,				//  VkImageTiling			tiling;
287		usage,									//  VkImageUsageFlags		usage;
288		VK_SHARING_MODE_EXCLUSIVE,				//  VkSharingMode			sharingMode;
289		0u,										//  deUint32				queueFamilyIndexCount;
290		DE_NULL,								//  const deUint32*			pQueueFamilyIndices;
291		VK_IMAGE_LAYOUT_UNDEFINED,				//  VkImageLayout			initialLayout;
292	};
293
294	return imageInfo;
295}
296
297const VkFramebufferCreateInfo makeFramebufferCreateInfo (const VkRenderPass	renderPass,
298														 const deUint32		attachmentCount,
299														 const VkImageView*	attachments,
300														 const deUint32		width,
301														 const deUint32		height)
302{
303	const VkFramebufferCreateInfo	result			=
304	{
305		VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,	//  VkStructureType				sType;
306		DE_NULL,									//  const void*					pNext;
307		0,											//  VkFramebufferCreateFlags	flags;
308		renderPass,									//  VkRenderPass				renderPass;
309		attachmentCount,							//  deUint32					attachmentCount;
310		attachments,								//  const VkImageView*			pAttachments;
311		width,										//  deUint32					width;
312		height,										//  deUint32					height;
313		1,											//  deUint32					layers;
314	};
315
316	return result;
317}
318
319const VkPipelineMultisampleStateCreateInfo makePipelineMultisampleStateCreateInfo (void)
320{
321	const VkPipelineMultisampleStateCreateInfo		pipelineMultisampleStateCreateInfo	=
322	{
323		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	//  VkStructureType							sType;
324		DE_NULL,													//  const void*								pNext;
325		0u,															//  VkPipelineMultisampleStateCreateFlags	flags;
326		VK_SAMPLE_COUNT_1_BIT,										//  VkSampleCountFlagBits					rasterizationSamples;
327		DE_FALSE,													//  VkBool32								sampleShadingEnable;
328		0.0f,														//  float									minSampleShading;
329		DE_NULL,													//  const VkSampleMask*						pSampleMask;
330		DE_FALSE,													//  VkBool32								alphaToCoverageEnable;
331		DE_FALSE,													//  VkBool32								alphaToOneEnable;
332	};
333
334	return pipelineMultisampleStateCreateInfo;
335}
336
337class GraphicsPipelineCreateInfo : public ::vkt::Draw::PipelineCreateInfo
338{
339public:
340	GraphicsPipelineCreateInfo (vk::VkPipelineLayout		_layout,
341								vk::VkRenderPass			_renderPass,
342								int							_subpass,
343								vk::VkPipelineCreateFlags	_flags)
344		: ::vkt::Draw::PipelineCreateInfo	(_layout, _renderPass, _subpass, _flags)
345		, m_vertexInputBindingDescription	()
346		, m_vertexInputAttributeDescription	()
347		, m_shaderModuleCreateInfoCount		(0)
348		, m_shaderModuleCreateInfo			{ initVulkanStructure(), initVulkanStructure() }
349		, m_pipelineShaderStageCreateInfo	()
350		, m_vertModule						()
351		, m_fragModule						()
352	{
353	}
354
355	VkVertexInputBindingDescription					m_vertexInputBindingDescription;
356	VkVertexInputAttributeDescription				m_vertexInputAttributeDescription;
357	deUint32										m_shaderModuleCreateInfoCount;
358	VkShaderModuleCreateInfo						m_shaderModuleCreateInfo[2];
359	std::vector<VkPipelineShaderStageCreateInfo>	m_pipelineShaderStageCreateInfo;
360	Move<VkShaderModule>							m_vertModule;
361	Move<VkShaderModule>							m_fragModule;
362};
363
364void updateVertexInputInterface (Context&						context,
365								 GraphicsPipelineCreateInfo&	graphicsPipelineCreateInfo,
366								 VkPrimitiveTopology			topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
367								 deUint32						vertexDescriptionCount = 1u)
368{
369	DE_UNREF(context);
370
371	graphicsPipelineCreateInfo.m_vertexInputBindingDescription =
372	{
373		0u,									//  deUint32			binding;
374		sizeof(tcu::Vec4),					//  deUint32			strideInBytes;
375		VK_VERTEX_INPUT_RATE_VERTEX,		//  VkVertexInputRate	inputRate;
376	};
377	graphicsPipelineCreateInfo.m_vertexInputAttributeDescription =
378	{
379		0u,									//  deUint32	location;
380		0u,									//  deUint32	binding;
381		VK_FORMAT_R32G32B32A32_SFLOAT,		//  VkFormat	format;
382		0u									//  deUint32	offsetInBytes;
383	};
384
385	const VkPipelineVertexInputStateCreateInfo		vertexInputStateCreateInfo
386	{
387		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
388		DE_NULL,														// const void*								pNext;
389		0u,																// VkPipelineVertexInputStateCreateFlags	flags;
390		vertexDescriptionCount,											// deUint32									vertexBindingDescriptionCount;
391		&graphicsPipelineCreateInfo.m_vertexInputBindingDescription,	// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
392		vertexDescriptionCount,											// deUint32									vertexAttributeDescriptionCount;
393		&graphicsPipelineCreateInfo.m_vertexInputAttributeDescription,	// const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
394	};
395	const VkPipelineInputAssemblyStateCreateInfo	inputAssemblyStateCreateInfo
396	{
397		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType							sType;
398		DE_NULL,														// const void*								pNext;
399		0u,																// VkPipelineInputAssemblyStateCreateFlags	flags;
400		topology,														// VkPrimitiveTopology						topology;
401		VK_FALSE,														// VkBool32									primitiveRestartEnable;
402	};
403
404	graphicsPipelineCreateInfo.addState(vertexInputStateCreateInfo);
405	graphicsPipelineCreateInfo.addState(inputAssemblyStateCreateInfo);
406}
407
408void updatePreRasterization (Context&						context,
409							 GraphicsPipelineCreateInfo&	graphicsPipelineCreateInfo,
410							 bool							delayedShaderCreate,
411							 VkPolygonMode					polygonMode = VK_POLYGON_MODE_FILL,
412							 const VkSpecializationInfo*	specializationInfo = DE_NULL)
413{
414	const ProgramBinary&		shaderBinary			= context.getBinaryCollection().get("vert");
415	VkShaderModuleCreateInfo&	shaderModuleCreateInfo	= graphicsPipelineCreateInfo.m_shaderModuleCreateInfo[graphicsPipelineCreateInfo.m_shaderModuleCreateInfoCount];
416
417	DE_ASSERT(graphicsPipelineCreateInfo.m_shaderModuleCreateInfoCount < DE_LENGTH_OF_ARRAY(graphicsPipelineCreateInfo.m_shaderModuleCreateInfo));
418
419	shaderModuleCreateInfo	=
420	{
421		VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,	//  VkStructureType				sType;
422		DE_NULL,										//  const void*					pNext;
423		0u,												//  VkShaderModuleCreateFlags	flags;
424		(deUintptr)shaderBinary.getSize(),				//  deUintptr					codeSize;
425		(deUint32*)shaderBinary.getBinary(),			//  const deUint32*				pCode;
426	};
427
428	if (!delayedShaderCreate)
429	{
430		const DeviceInterface&	vk		= context.getDeviceInterface();
431		const VkDevice			device	= context.getDevice();
432
433		graphicsPipelineCreateInfo.m_vertModule = createShaderModule(vk, device, &shaderModuleCreateInfo);
434	}
435
436	const void*										pNext								= delayedShaderCreate
437																						? &shaderModuleCreateInfo
438																						: DE_NULL;
439	const VkShaderModule							shaderModule						= delayedShaderCreate
440																						? DE_NULL
441																						: *graphicsPipelineCreateInfo.m_vertModule;
442	const VkPipelineShaderStageCreateInfo			pipelineShaderStageCreateInfo				=
443	{
444		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType					sType;
445		pNext,													// const void*						pNext;
446		0u,														// VkPipelineShaderStageCreateFlags	flags;
447		VK_SHADER_STAGE_VERTEX_BIT,								// VkShaderStageFlagBits			stage;
448		shaderModule,											// VkShaderModule					module;
449		"main",													// const char*						pName;
450		specializationInfo										// const VkSpecializationInfo*		pSpecializationInfo;
451	};
452
453	shaderBinary.setUsed();
454
455	// Within the VkPipelineLayout, all	bindings that affect the specified shader stages
456	const VkViewport								viewport							= makeViewport(RENDER_SIZE_WIDTH, RENDER_SIZE_HEIGHT);
457	const VkRect2D									scissor								= makeRect2D(3 * RENDER_SIZE_WIDTH / 4, RENDER_SIZE_HEIGHT);
458	const VkPipelineViewportStateCreateInfo			pipelineViewportStateCreateInfo		=
459	{
460		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,	// VkStructureType						sType;
461		DE_NULL,												// const void*							pNext;
462		0u,														// VkPipelineViewportStateCreateFlags	flags;
463		1u,														// deUint32								viewportCount;
464		&viewport,												// const VkViewport*					pViewports;
465		1u,														// deUint32								scissorCount;
466		&scissor												// const VkRect2D*						pScissors;
467	};
468	const VkPipelineRasterizationStateCreateInfo	pipelineRasterizationStateCreateInfo =
469	{
470		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType							sType;
471		DE_NULL,														// const void*								pNext;
472		0u,																// VkPipelineRasterizationStateCreateFlags	flags;
473		VK_FALSE,														// VkBool32									depthClampEnable;
474		VK_FALSE,														// VkBool32									rasterizerDiscardEnable;
475		polygonMode,													// VkPolygonMode							polygonMode;
476		VK_CULL_MODE_NONE,												// VkCullModeFlags							cullMode;
477		VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace								frontFace;
478		VK_FALSE,														// VkBool32									depthBiasEnable;
479		0.0f,															// float									depthBiasConstantFactor;
480		0.0f,															// float									depthBiasClamp;
481		0.0f,															// float									depthBiasSlopeFactor;
482		1.0f,															// float									lineWidth;
483	};
484
485	graphicsPipelineCreateInfo.m_shaderModuleCreateInfoCount++;
486
487	graphicsPipelineCreateInfo.addShader(pipelineShaderStageCreateInfo);
488	graphicsPipelineCreateInfo.addState(pipelineViewportStateCreateInfo);
489	graphicsPipelineCreateInfo.addState(pipelineRasterizationStateCreateInfo);
490}
491
492void updatePostRasterization (Context&						context,
493							  GraphicsPipelineCreateInfo&	graphicsPipelineCreateInfo,
494							  bool							delayedShaderCreate,
495							  bool							enableDepth = true,
496							  const VkSpecializationInfo*	specializationInfo = DE_NULL)
497{
498	const ProgramBinary&		shaderBinary			= context.getBinaryCollection().get("frag");
499	VkShaderModuleCreateInfo&	shaderModuleCreateInfo	= graphicsPipelineCreateInfo.m_shaderModuleCreateInfo[graphicsPipelineCreateInfo.m_shaderModuleCreateInfoCount];
500
501	DE_ASSERT(graphicsPipelineCreateInfo.m_shaderModuleCreateInfoCount < DE_LENGTH_OF_ARRAY(graphicsPipelineCreateInfo.m_shaderModuleCreateInfo));
502
503	shaderModuleCreateInfo	=
504	{
505		VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,	//  VkStructureType				sType;
506		DE_NULL,										//  const void*					pNext;
507		0u,												//  VkShaderModuleCreateFlags	flags;
508		(deUintptr)shaderBinary.getSize(),				//  deUintptr					codeSize;
509		(deUint32*)shaderBinary.getBinary(),			//  const deUint32*				pCode;
510	};
511
512	if (!delayedShaderCreate)
513	{
514		const DeviceInterface&	vk		= context.getDeviceInterface();
515		const VkDevice			device	= context.getDevice();
516
517		graphicsPipelineCreateInfo.m_fragModule = createShaderModule(vk, device, &shaderModuleCreateInfo);
518	}
519
520	const void*										pNext								= delayedShaderCreate
521																						? &shaderModuleCreateInfo
522																						: DE_NULL;
523	const VkShaderModule							shaderModule						= delayedShaderCreate
524																						? DE_NULL
525																						: *graphicsPipelineCreateInfo.m_fragModule;
526	const VkPipelineShaderStageCreateInfo			pipelineShaderStageCreateInfo		=
527	{
528		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType					sType;
529		pNext,													// const void*						pNext;
530		0u,														// VkPipelineShaderStageCreateFlags	flags;
531		VK_SHADER_STAGE_FRAGMENT_BIT,							// VkShaderStageFlagBits			stage;
532		shaderModule,											// VkShaderModule					module;
533		"main",													// const char*						pName;
534		specializationInfo										// const VkSpecializationInfo*		pSpecializationInfo;
535	};
536
537	shaderBinary.setUsed();
538
539	// Within the VkPipelineLayout, all bindings that affect the fragment shader stage
540
541	const VkPipelineDepthStencilStateCreateInfo		pipelineDepthStencilStateCreateInfo	=
542	{
543		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, //  VkStructureType							sType;
544		DE_NULL,													//  const void*								pNext;
545		0u,															//  VkPipelineDepthStencilStateCreateFlags	flags;
546		enableDepth,												//  VkBool32								depthTestEnable;
547		enableDepth,												//  VkBool32								depthWriteEnable;
548		VK_COMPARE_OP_LESS_OR_EQUAL,								//  VkCompareOp								depthCompareOp;
549		VK_FALSE,													//  VkBool32								depthBoundsTestEnable;
550		VK_FALSE,													//  VkBool32								stencilTestEnable;
551		{															//  VkStencilOpState						front;
552			VK_STENCIL_OP_KEEP,		// VkStencilOp	failOp;
553			VK_STENCIL_OP_KEEP,		// VkStencilOp	passOp;
554			VK_STENCIL_OP_KEEP,		// VkStencilOp	depthFailOp;
555			VK_COMPARE_OP_NEVER,	// VkCompareOp	compareOp;
556			0u,						// deUint32		compareMask;
557			0u,						// deUint32		writeMask;
558			0u,						// deUint32		reference;
559		},
560		{															//  VkStencilOpState						back;
561			VK_STENCIL_OP_KEEP,		// VkStencilOp	failOp;
562			VK_STENCIL_OP_KEEP,		// VkStencilOp	passOp;
563			VK_STENCIL_OP_KEEP,		// VkStencilOp	depthFailOp;
564			VK_COMPARE_OP_NEVER,	// VkCompareOp	compareOp;
565			0u,						// deUint32		compareMask;
566			0u,						// deUint32		writeMask;
567			0u,						// deUint32		reference;
568		},
569		0.0f,														//  float									minDepthBounds;
570		1.0f,														//  float									maxDepthBounds;
571	};
572
573	graphicsPipelineCreateInfo.m_shaderModuleCreateInfoCount++;
574	graphicsPipelineCreateInfo.addShader(pipelineShaderStageCreateInfo);
575
576	DE_ASSERT(graphicsPipelineCreateInfo.pDepthStencilState == DE_NULL);
577	graphicsPipelineCreateInfo.addState(pipelineDepthStencilStateCreateInfo);
578
579	if (graphicsPipelineCreateInfo.pMultisampleState == DE_NULL)
580	{
581		const VkPipelineMultisampleStateCreateInfo	pipelineMultisampleStateCreateInfo = makePipelineMultisampleStateCreateInfo();
582
583		graphicsPipelineCreateInfo.addState(pipelineMultisampleStateCreateInfo);
584	}
585}
586
587void updateFragmentOutputInterface (Context&					context,
588									GraphicsPipelineCreateInfo& graphicsPipelineCreateInfo,
589									VkColorComponentFlags		colorWriteMask = COLOR_COMPONENTS_NO_RED)
590{
591	DE_UNREF(context);
592
593	// Number of blend attachments must equal the number of color attachments during any subpass.
594	const VkPipelineColorBlendAttachmentState	pipelineColorBlendAttachmentState =
595	{
596		VK_FALSE,						// VkBool32					blendEnable;
597		VK_BLEND_FACTOR_ONE,			// VkBlendFactor			srcColorBlendFactor;
598		VK_BLEND_FACTOR_ZERO,			// VkBlendFactor			dstColorBlendFactor;
599		VK_BLEND_OP_ADD,				// VkBlendOp				colorBlendOp;
600		VK_BLEND_FACTOR_ONE,			// VkBlendFactor			srcAlphaBlendFactor;
601		VK_BLEND_FACTOR_ZERO,			// VkBlendFactor			dstAlphaBlendFactor;
602		VK_BLEND_OP_ADD,				// VkBlendOp				alphaBlendOp;
603		colorWriteMask,					// VkColorComponentFlags	colorWriteMask;
604	};
605	const VkPipelineColorBlendStateCreateInfo	pipelineColorBlendStateCreateInfo	=
606	{
607		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,		// VkStructureType								sType;
608		DE_NULL,														// const void*									pNext;
609		(VkPipelineColorBlendStateCreateFlags)0,						// VkPipelineColorBlendStateCreateFlags			flags;
610		VK_FALSE,														// VkBool32										logicOpEnable;
611		VK_LOGIC_OP_COPY,												// VkLogicOp									logicOp;
612		1u,																// deUint32										attachmentCount;
613		&pipelineColorBlendAttachmentState,								// const VkPipelineColorBlendAttachmentState*	pAttachments;
614		{ 0.0f, 0.0f, 0.0f, 0.0f },										// float										blendConstants[4];
615	};
616
617	graphicsPipelineCreateInfo.addState(pipelineColorBlendStateCreateInfo);
618
619	if (graphicsPipelineCreateInfo.pMultisampleState == DE_NULL)
620	{
621		const VkPipelineMultisampleStateCreateInfo	pipelineMultisampleStateCreateInfo = makePipelineMultisampleStateCreateInfo();
622
623		graphicsPipelineCreateInfo.addState(pipelineMultisampleStateCreateInfo);
624	}
625}
626
627/*
628	To test that each of graphics pipeline libraries have influence on final pipeline
629	the functions have following features:
630
631	updateVertexInputInterface
632		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST
633		VK_VERTEX_INPUT_RATE_VERTEX
634		Z is read from uniform and written in shader
635
636	updatePreRasterization
637		VkRect2D scissor = makeRect2D(3 * RENDER_SIZE_WIDTH / 4, RENDER_SIZE_HEIGHT);
638
639	updatePostRasterization
640		Fragment shader top and bottom colors read from uniform buffer
641
642	updateFragmentOutputInterface
643		Cut off red component
644*/
645
646class PipelineLibraryTestInstance : public TestInstance
647{
648public:
649									PipelineLibraryTestInstance		(Context&							context,
650																	 const TestParams&					data);
651									~PipelineLibraryTestInstance	(void);
652	tcu::TestStatus					iterate							(void);
653
654protected:
655	de::MovePtr<BufferWithMemory>	makeVertexBuffer				(void);
656	de::MovePtr<BufferWithMemory>	makeZCoordBuffer				(void);
657	de::MovePtr<BufferWithMemory>	makePaletteBuffer				(void);
658	Move<VkDescriptorPool>			createDescriptorPool			(void);
659	Move<VkDescriptorSetLayout>		createDescriptorSetLayout		(const VkBuffer						vertShaderBuffer,
660																	 const VkBuffer						fragShaderBuffer);
661	Move<VkDescriptorSet>			createDescriptorSet				(const VkDescriptorPool				pool,
662																	 const VkDescriptorSetLayout		layout,
663																	 const VkBuffer						vertShaderBuffer,
664																	 const VkBuffer						fragShaderBuffer);
665	bool							verifyColorImage				(const tcu::ConstPixelBufferAccess&	pba);
666	bool							verifyDepthImage				(const tcu::ConstPixelBufferAccess&	pba);
667	bool							runTest							(RuntimePipelineTreeConfiguration&	runtimePipelineTreeConfiguration,
668																	 const bool							optimize,
669																	 const bool							delayedShaderCreate);
670private:
671	TestParams						m_data;
672	std::vector<tcu::Vec4>			m_vertexData;
673	std::vector<tcu::Vec4>			m_paletteData;
674	std::vector<tcu::Vec4>			m_zCoordData;
675};
676
677PipelineLibraryTestInstance::PipelineLibraryTestInstance (Context& context, const TestParams& data)
678	: vkt::TestInstance		(context)
679	, m_data				(data)
680	, m_vertexData			()
681	, m_paletteData			()
682{
683	m_vertexData =
684	{
685		{ -1.0f, -1.0f, 0.0f, 1.0f },
686		{ +1.0f, -1.0f, 0.5f, 1.0f },
687		{ -1.0f, +1.0f, 0.5f, 1.0f },
688		{ -1.0f, +1.0f, 0.5f, 1.0f },
689		{ +1.0f, -1.0f, 0.5f, 1.0f },
690		{ +1.0f, +1.0f, 1.0f, 1.0f },
691	};
692	m_paletteData =
693	{
694		{ 0.25f, 1.0f, 0.0f, 1.0f },
695		{ 0.75f, 0.0f, 1.0f, 1.0f },
696	};
697	m_zCoordData =
698	{
699		{ 0.25f, 0.75f, 0.0f, 1.0f },
700	};
701}
702
703PipelineLibraryTestInstance::~PipelineLibraryTestInstance (void)
704{
705}
706
707de::MovePtr<BufferWithMemory> PipelineLibraryTestInstance::makeVertexBuffer (void)
708{
709	const DeviceInterface&			vk					= m_context.getDeviceInterface();
710	const VkDevice					device				= m_context.getDevice();
711	Allocator&						allocator			= m_context.getDefaultAllocator();
712	const size_t					bufferDataSize		= de::dataSize(m_vertexData);
713	const VkBufferCreateInfo		bufferCreateInfo	= makeBufferCreateInfo(bufferDataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
714	de::MovePtr<BufferWithMemory>	buffer				= de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
715
716	deMemcpy(buffer->getAllocation().getHostPtr(), m_vertexData.data(), bufferDataSize);
717	flushAlloc(vk, device, buffer->getAllocation());
718
719	return buffer;
720}
721
722de::MovePtr<BufferWithMemory> PipelineLibraryTestInstance::makeZCoordBuffer (void)
723{
724	const DeviceInterface&			vk					= m_context.getDeviceInterface();
725	const VkDevice					device				= m_context.getDevice();
726	Allocator&						allocator			= m_context.getDefaultAllocator();
727	const size_t					bufferDataSize		= de::dataSize(m_zCoordData);
728	const VkBufferCreateInfo		bufferCreateInfo	= makeBufferCreateInfo(bufferDataSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
729	de::MovePtr<BufferWithMemory>	buffer				= de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
730
731	deMemcpy(buffer->getAllocation().getHostPtr(), m_zCoordData.data(), bufferDataSize);
732	flushAlloc(vk, device, buffer->getAllocation());
733
734	return buffer;
735}
736
737de::MovePtr<BufferWithMemory> PipelineLibraryTestInstance::makePaletteBuffer (void)
738{
739	const DeviceInterface&			vk					= m_context.getDeviceInterface();
740	const VkDevice					device				= m_context.getDevice();
741	Allocator&						allocator			= m_context.getDefaultAllocator();
742	const size_t					bufferDataSize		= de::dataSize(m_paletteData);
743	const VkBufferCreateInfo		bufferCreateInfo	= makeBufferCreateInfo(bufferDataSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
744	de::MovePtr<BufferWithMemory>	buffer				= de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
745
746	deMemcpy(buffer->getAllocation().getHostPtr(), m_paletteData.data(), bufferDataSize);
747	flushAlloc(vk, device, buffer->getAllocation());
748
749	return buffer;
750}
751
752Move<VkDescriptorPool> PipelineLibraryTestInstance::createDescriptorPool (void)
753{
754	const DeviceInterface&	vk		= m_context.getDeviceInterface();
755	const VkDevice			device	= m_context.getDevice();
756
757	return DescriptorPoolBuilder()
758		.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 4)
759		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 3);
760}
761
762Move<VkDescriptorSetLayout> PipelineLibraryTestInstance::createDescriptorSetLayout (const VkBuffer			vertShaderBuffer,
763																					const VkBuffer			fragShaderBuffer)
764{
765	const DeviceInterface&		vk		= m_context.getDeviceInterface();
766	const VkDevice				device	= m_context.getDevice();
767	DescriptorSetLayoutBuilder	builder;
768
769	if (vertShaderBuffer != DE_NULL)
770		builder.addIndexedBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u, VK_SHADER_STAGE_VERTEX_BIT, 0u, DE_NULL);
771
772	if (fragShaderBuffer != DE_NULL)
773		builder.addIndexedBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u, VK_SHADER_STAGE_FRAGMENT_BIT, 1u, DE_NULL);
774
775	return builder.build(vk, device);
776}
777
778Move<VkDescriptorSet> PipelineLibraryTestInstance::createDescriptorSet (const VkDescriptorPool		pool,
779																		const VkDescriptorSetLayout	layout,
780																		const VkBuffer				vertShaderBuffer,
781																		const VkBuffer				fragShaderBuffer)
782{
783	const DeviceInterface&				vk					= m_context.getDeviceInterface();
784	const VkDevice						device				= m_context.getDevice();
785	const VkDescriptorSetAllocateInfo	allocInfo			=
786	{
787		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,	//  VkStructureType					sType;
788		DE_NULL,										//  const void*						pNext;
789		pool,											//  VkDescriptorPool				descriptorPool;
790		1u,												//  deUint32						descriptorSetCount;
791		&layout											//  const VkDescriptorSetLayout*	pSetLayouts;
792	};
793	Move<VkDescriptorSet>				descriptorSet		= allocateDescriptorSet(vk, device, &allocInfo);
794	DescriptorSetUpdateBuilder			builder;
795
796	if (vertShaderBuffer != DE_NULL)
797	{
798		const VkDeviceSize				vertShaderBufferSize	= de::dataSize(m_zCoordData);
799		const VkDescriptorBufferInfo	vertShaderBufferInfo	= makeDescriptorBufferInfo(vertShaderBuffer, 0u, vertShaderBufferSize);
800
801		builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &vertShaderBufferInfo);
802	}
803
804	if (fragShaderBuffer != DE_NULL)
805	{
806		const VkDeviceSize				fragShaderBufferSize	= de::dataSize(m_paletteData);
807		const VkDescriptorBufferInfo	fragShaderBufferInfo	= makeDescriptorBufferInfo(fragShaderBuffer, 0u, fragShaderBufferSize);
808
809		builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &fragShaderBufferInfo);
810	}
811
812	builder.update(vk, device);
813
814	return descriptorSet;
815}
816
817VkFormat getSupportedDepthFormat(const InstanceInterface &vk, const VkPhysicalDevice physicalDevice)
818{
819	VkFormatProperties properties;
820
821	const VkFormat DepthFormats[] =
822	{
823		VK_FORMAT_D32_SFLOAT,
824		VK_FORMAT_X8_D24_UNORM_PACK32,
825		VK_FORMAT_D24_UNORM_S8_UINT,
826		VK_FORMAT_D32_SFLOAT_S8_UINT
827	};
828
829	for (const auto format: DepthFormats)
830	{
831		vk.getPhysicalDeviceFormatProperties(physicalDevice, format, &properties);
832
833		if (properties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)
834			return format;
835	}
836
837	TCU_THROW(NotSupportedError, "Depth format is not supported");
838}
839
840bool PipelineLibraryTestInstance::runTest (RuntimePipelineTreeConfiguration&	runtimePipelineTreeConfiguration,
841										   const bool							optimize,
842										   const bool							delayedShaderCreate)
843{
844	const DeviceInterface&					vk						= m_context.getDeviceInterface();
845	const VkDevice							device					= m_context.getDevice();
846	const deUint32							queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
847	Allocator&								allocator				= m_context.getDefaultAllocator();
848	tcu::TestLog&							log						= m_context.getTestContext().getLog();
849	const VkFormat							colorFormat				= VK_FORMAT_R8G8B8A8_UNORM;
850	const VkFormat							depthFormat				= getSupportedDepthFormat(m_context.getInstanceInterface(), m_context.getPhysicalDevice());
851	const VkGraphicsPipelineLibraryFlagsEXT	vertPipelineFlags		= static_cast<VkGraphicsPipelineLibraryFlagsEXT>(VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT);
852	const VkGraphicsPipelineLibraryFlagsEXT	fragPipelineFlags		= static_cast<VkGraphicsPipelineLibraryFlagsEXT>(VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT);
853	const VkGraphicsPipelineLibraryFlagsEXT	samePipelineFlags		= vertPipelineFlags | fragPipelineFlags;
854	const deInt32							nodeNdxLast				= static_cast<deInt32>(runtimePipelineTreeConfiguration.size()) - 1;
855	const Move<VkRenderPass>				renderPass				= makeRenderPass(vk, device, colorFormat, depthFormat);
856	const de::MovePtr<BufferWithMemory>		zCoordBuffer			= makeZCoordBuffer();
857	const de::MovePtr<BufferWithMemory>		paletteBuffer			= makePaletteBuffer();
858	const Move<VkDescriptorPool>			descriptorPool			= createDescriptorPool();
859
860	const Move<VkDescriptorSetLayout>		descriptorSetLayoutVert	= createDescriptorSetLayout(**zCoordBuffer, DE_NULL);
861	const Move<VkDescriptorSetLayout>		descriptorSetLayoutFrag	= createDescriptorSetLayout(DE_NULL, **paletteBuffer);
862	const Move<VkDescriptorSetLayout>		descriptorSetLayoutBoth	= createDescriptorSetLayout(**zCoordBuffer, **paletteBuffer);
863	const Move<VkDescriptorSet>				descriptorSetVert		= createDescriptorSet(*descriptorPool, *descriptorSetLayoutVert, **zCoordBuffer, DE_NULL);
864	const Move<VkDescriptorSet>				descriptorSetFrag		= createDescriptorSet(*descriptorPool, *descriptorSetLayoutFrag, DE_NULL , **paletteBuffer);
865
866	VkDescriptorSet vecDescriptorSetBoth[2] = { *descriptorSetVert, *descriptorSetFrag };
867
868	VkDescriptorSetLayout vecLayoutVert[2] = { *descriptorSetLayoutVert, DE_NULL };
869	VkDescriptorSetLayout vecLayoutFrag[2] = { DE_NULL, *descriptorSetLayoutFrag };
870	VkDescriptorSetLayout vecLayoutBoth[2] = { *descriptorSetLayoutVert, *descriptorSetLayoutFrag };
871
872	VkPipelineLayoutCreateFlags pipelineLayoutCreateFlag = 0u;
873	if (!m_data.useMaintenance5 && (m_data.delayedShaderCreate || (m_data.pipelineTreeConfiguration.size() > 1)))
874		pipelineLayoutCreateFlag = VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT;
875
876	const Move<VkCommandPool>				cmdPool					= createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
877	const Move<VkCommandBuffer>				cmdBuffer				= allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
878	const Move<VkPipelineLayout>			pipelineLayoutSame		= makePipelineLayout(vk, device, 2, vecLayoutBoth, pipelineLayoutCreateFlag);
879	Move<VkPipelineLayout>					pipelineLayoutVert;
880	Move<VkPipelineLayout>					pipelineLayoutFrag;
881	Move<VkPipeline>						rootPipeline;
882
883	// Go through tree nodes and create library for each up to root
884	for (deInt32 nodeNdx = nodeNdxLast; nodeNdx >= 0 ; --nodeNdx)	// We expect only backward node reference, thus build pipielines from end is safe
885	{
886		RuntimePipelineTreeNode&				node								= runtimePipelineTreeConfiguration[nodeNdx];
887		const bool								buildLibrary						= (nodeNdx != 0);
888		const VkPipelineCreateFlags				pipelineCreateFlags					= calcPipelineCreateFlags(optimize, buildLibrary);
889		const VkGraphicsPipelineLibraryFlagsEXT	subtreeGraphicsPipelineLibraryFlags	= node.subtreeGraphicsPipelineLibraryFlags | node.graphicsPipelineLibraryFlags;
890		const bool								samePipelineLayout					= samePipelineFlags == (samePipelineFlags & subtreeGraphicsPipelineLibraryFlags);
891		const bool								vertPipelineLayout					= vertPipelineFlags == (vertPipelineFlags & subtreeGraphicsPipelineLibraryFlags);
892		const bool								fragPipelineLayout					= fragPipelineFlags == (fragPipelineFlags & subtreeGraphicsPipelineLibraryFlags);
893
894		if (samePipelineLayout)
895			; // pipelineLayoutSame is always built before.
896		else if (vertPipelineLayout)
897		{
898			if (!pipelineLayoutVert)
899				pipelineLayoutVert = makePipelineLayout(vk, device, 2, vecLayoutVert, pipelineLayoutCreateFlag);
900		}
901		else if (fragPipelineLayout)
902		{
903			if (!pipelineLayoutFrag)
904				pipelineLayoutFrag = makePipelineLayout(vk, device, 2, vecLayoutFrag, pipelineLayoutCreateFlag);
905		}
906
907		const VkPipelineLayout					pipelineLayout						= samePipelineLayout ? *pipelineLayoutSame
908																					: vertPipelineLayout ? *pipelineLayoutVert
909																					: fragPipelineLayout ? *pipelineLayoutFrag
910																					: DE_NULL;
911		const VkRenderPass						renderPassHandle					= getRenderPass(node.graphicsPipelineLibraryFlags, *renderPass);
912		VkGraphicsPipelineLibraryCreateInfoEXT	graphicsPipelineLibraryCreateInfo	= makeGraphicsPipelineLibraryCreateInfo(node.graphicsPipelineLibraryFlags);
913		VkPipelineLibraryCreateInfoKHR			linkingInfo							= makePipelineLibraryCreateInfo(node.pipelineLibraries);
914		GraphicsPipelineCreateInfo				graphicsPipelineCreateInfo			(pipelineLayout, renderPassHandle, 0, pipelineCreateFlags);
915
916		for (const auto subsetFlag: GRAPHICS_PIPELINE_LIBRARY_FLAGS)
917		{
918			if ((node.graphicsPipelineLibraryFlags & subsetFlag) != 0)
919			{
920				switch (subsetFlag)
921				{
922					case VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT:		updateVertexInputInterface(m_context, graphicsPipelineCreateInfo);					break;
923					case VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT:	updatePreRasterization(m_context, graphicsPipelineCreateInfo, delayedShaderCreate);	break;
924					case VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT:				updatePostRasterization(m_context, graphicsPipelineCreateInfo, delayedShaderCreate);break;
925					case VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT:	updateFragmentOutputInterface(m_context, graphicsPipelineCreateInfo);				break;
926					default:																TCU_THROW(InternalError, "Unknown pipeline subset");
927				}
928			}
929		}
930
931		VkGraphicsPipelineLibraryFlagsEXT linkedLibrariesFlags = 0;
932
933		for (auto flag : node.linkedLibraryFlags)
934			linkedLibrariesFlags |= flag;
935
936		// When pLibraries have any pipeline library with fragment shader state and current pipeline we try to create doesn't,
937		// we need to set a MS info.
938		if ((linkedLibrariesFlags & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT) &&
939				!(node.graphicsPipelineLibraryFlags & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT) &&
940				(graphicsPipelineCreateInfo.pMultisampleState == DE_NULL))
941		{
942			const VkPipelineMultisampleStateCreateInfo	pipelineMultisampleStateCreateInfo = makePipelineMultisampleStateCreateInfo();
943
944			graphicsPipelineCreateInfo.addState(pipelineMultisampleStateCreateInfo);
945		}
946
947
948		if (!m_data.useMaintenance5 && linkedLibrariesFlags != ALL_GRAPHICS_PIPELINE_LIBRARY_FLAGS && graphicsPipelineLibraryCreateInfo.flags != 0)
949			appendStructurePtrToVulkanChain(&graphicsPipelineCreateInfo.pNext, &graphicsPipelineLibraryCreateInfo);
950
951		if (linkingInfo.libraryCount != 0)
952		{
953			appendStructurePtrToVulkanChain(&graphicsPipelineCreateInfo.pNext, &linkingInfo);
954			graphicsPipelineCreateInfo.layout = *pipelineLayoutSame;
955		}
956
957		linkedLibrariesFlags |= node.graphicsPipelineLibraryFlags;
958
959		// if current pipeline that we try to create and pLibraries have all states of pipelines, we are not allowed to create a pipeline library.
960		if (linkedLibrariesFlags == ALL_GRAPHICS_PIPELINE_LIBRARY_FLAGS)
961		{
962			DE_ASSERT(!buildLibrary);
963			graphicsPipelineCreateInfo.flags &= ~VK_PIPELINE_CREATE_LIBRARY_BIT_KHR;
964		}
965
966		node.pipeline = createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineCreateInfo);
967
968		if (buildLibrary)
969		{
970			DE_ASSERT(de::inBounds(node.parentIndex, 0, static_cast<deInt32>(runtimePipelineTreeConfiguration.size())));
971
972			runtimePipelineTreeConfiguration[node.parentIndex].pipelineLibraries.push_back(*node.pipeline);
973			runtimePipelineTreeConfiguration[node.parentIndex].linkedLibraryFlags.push_back(linkedLibrariesFlags);
974		}
975		else
976		{
977			DE_ASSERT(node.parentIndex == -1);
978
979			rootPipeline = node.pipeline;
980		}
981	}
982
983	// Queue commands and read results.
984	{
985		const tcu::UVec2					renderSize					= { RENDER_SIZE_WIDTH, RENDER_SIZE_HEIGHT };
986		const VkRect2D						renderArea					= makeRect2D(renderSize.x(), renderSize.y());
987		const de::MovePtr<BufferWithMemory>	vertexBuffer				= makeVertexBuffer();
988		const deUint32						vertexCount					= static_cast<deUint32>(m_vertexData.size());
989		const VkDeviceSize					vertexBufferOffset			= 0;
990		const Vec4							colorClearColor				(0.0f, 0.0f, 0.0f, 1.0f);
991		const VkImageCreateInfo				colorImageCreateInfo		= makeColorImageCreateInfo(colorFormat, renderSize.x(), renderSize.y());
992		const ImageWithMemory				colorImage					(vk, device, allocator, colorImageCreateInfo, MemoryRequirement::Any);
993		const VkImageViewCreateInfo			colorImageViewCreateInfo	= makeImageViewCreateInfo(*colorImage, colorFormat, static_cast<VkImageAspectFlags>(VK_IMAGE_ASPECT_COLOR_BIT));
994		const Move<VkImageView>				colorImageView				= createImageView(vk, device, &colorImageViewCreateInfo);
995		const VkImageCreateInfo				depthImageCreateInfo		= makeDepthImageCreateInfo(depthFormat, renderSize.x(), renderSize.y());
996		const ImageWithMemory				depthImage					(vk, device, allocator, depthImageCreateInfo, MemoryRequirement::Any);
997		const VkImageViewCreateInfo			depthImageViewCreateInfo	= makeImageViewCreateInfo(*depthImage, depthFormat, static_cast<VkImageAspectFlags>(VK_IMAGE_ASPECT_DEPTH_BIT));
998		const Move<VkImageView>				depthImageView				= createImageView(vk, device, &depthImageViewCreateInfo);
999		const float							depthClearDepth				= 1.0f;
1000		const deUint32						depthClearStencil			= 0u;
1001		const VkDeviceSize					colorBufferDataSize			= static_cast<VkDeviceSize>(renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat)));
1002		const VkBufferCreateInfo			colorBufferCreateInfo		= makeBufferCreateInfo(colorBufferDataSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1003		const BufferWithMemory				colorBuffer					(vk, device, allocator, colorBufferCreateInfo, MemoryRequirement::HostVisible);
1004		const VkDeviceSize					depthBufferDataSize			= static_cast<VkDeviceSize>(renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(depthFormat)));
1005		const VkBufferCreateInfo			depthBufferCreateInfo		= makeBufferCreateInfo(depthBufferDataSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1006		const BufferWithMemory				depthBuffer					(vk, device, allocator, depthBufferCreateInfo, MemoryRequirement::HostVisible);
1007		const VkImageView					attachments[]				= { *colorImageView, *depthImageView };
1008		const VkFramebufferCreateInfo		framebufferCreateInfo		= makeFramebufferCreateInfo(*renderPass, DE_LENGTH_OF_ARRAY(attachments), attachments, renderSize.x(), renderSize.y());
1009		const Move<VkFramebuffer>			framebuffer					= createFramebuffer(vk, device, &framebufferCreateInfo);
1010
1011		vk::beginCommandBuffer(vk, *cmdBuffer, 0u);
1012		{
1013			beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, colorClearColor, depthClearDepth, depthClearStencil);
1014			{
1015				vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &vertexBuffer->get(), &vertexBufferOffset);
1016				vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *rootPipeline);
1017				vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayoutSame, 0u, 2u, vecDescriptorSetBoth, 0u, DE_NULL);
1018				vk.cmdDraw(*cmdBuffer, vertexCount, 1u, 0u, 0u);
1019			}
1020			endRenderPass(vk, *cmdBuffer);
1021
1022			const tcu::IVec2 size = { (deInt32)renderSize.x(), (deInt32)renderSize.y() };
1023			copyImageToBuffer(vk, *cmdBuffer, *colorImage, *colorBuffer, size);
1024			copyImageToBuffer(vk, *cmdBuffer, *depthImage, *depthBuffer, size, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 1u, VK_IMAGE_ASPECT_DEPTH_BIT, VK_IMAGE_ASPECT_DEPTH_BIT);
1025		}
1026		vk::endCommandBuffer(vk, *cmdBuffer);
1027		vk::submitCommandsAndWait(vk, device, m_context.getUniversalQueue(), cmdBuffer.get());
1028
1029		vk::invalidateAlloc(vk, device, colorBuffer.getAllocation());
1030		vk::invalidateAlloc(vk, device, depthBuffer.getAllocation());
1031
1032		const tcu::ConstPixelBufferAccess colorPixelAccess(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, colorBuffer.getAllocation().getHostPtr());
1033		const tcu::ConstPixelBufferAccess depthPixelAccess(mapVkFormat(depthFormat), renderSize.x(), renderSize.y(), 1, depthBuffer.getAllocation().getHostPtr());
1034
1035		if (!verifyColorImage(colorPixelAccess))
1036		{
1037			log << tcu::TestLog::Image("color", "Rendered image", colorPixelAccess);
1038
1039			return false;
1040		}
1041
1042		if (!verifyDepthImage(depthPixelAccess))
1043		{
1044			log << tcu::TestLog::Image("depth", "Rendered image", depthPixelAccess);
1045
1046			return false;
1047		}
1048	}
1049
1050	return true;
1051}
1052
1053bool PipelineLibraryTestInstance::verifyColorImage (const ConstPixelBufferAccess& pba)
1054{
1055	tcu::TestLog&		log				= m_context.getTestContext().getLog();
1056	TextureLevel		referenceImage	(pba.getFormat(), pba.getWidth(), pba.getHeight());
1057	PixelBufferAccess	reference		(referenceImage);
1058	const int			horzEdge		= 3 * reference.getWidth() / 4;
1059	const int			vertEdge		= reference.getHeight() / 2;
1060	const UVec4			green			= ivec2uvec(RGBA::green().toIVec());
1061	const UVec4			blue			= ivec2uvec(RGBA::blue().toIVec());
1062	const UVec4			black			= ivec2uvec(RGBA::black().toIVec());
1063
1064	for (int y = 0; y < reference.getHeight(); ++y)
1065	{
1066		for (int x = 0; x < reference.getWidth(); ++x)
1067		{
1068			if (x < horzEdge)
1069			{
1070				if (y < vertEdge)
1071					reference.setPixel(green, x, y);
1072				else
1073					reference.setPixel(blue, x, y);
1074			}
1075			else
1076				reference.setPixel(black, x, y);
1077		}
1078	}
1079
1080	return intThresholdCompare(log, "colorImage", "colorImage", reference, pba, UVec4(), COMPARE_LOG_RESULT);
1081}
1082
1083bool PipelineLibraryTestInstance::verifyDepthImage (const ConstPixelBufferAccess& pba)
1084{
1085	tcu::TestLog&		log				= m_context.getTestContext().getLog();
1086	const VkFormat		compareFormat	= VK_FORMAT_R8_UNORM;
1087	TextureLevel		referenceImage	(mapVkFormat(compareFormat), pba.getWidth(), pba.getHeight());
1088	PixelBufferAccess	reference		(referenceImage);
1089	TextureLevel		resultImage		(mapVkFormat(compareFormat), pba.getWidth(), pba.getHeight());
1090	PixelBufferAccess	result			(resultImage);
1091	const int			horzEdge		= 3 * reference.getWidth() / 4;
1092	const int			diagonalEdge	= (reference.getWidth() + reference.getHeight()) / 2 - 1;
1093	const UVec4			red100			= ivec2uvec(RGBA::red().toIVec());
1094	const UVec4			red025			= UVec4(red100[0] / 4, red100[1] / 4, red100[2] / 4, red100[3]);
1095	const UVec4			red075			= UVec4(3 * red100[0] / 4, 3 * red100[1] / 4, 3 * red100[2] / 4, red100[3]);
1096
1097	for (int y = 0; y < result.getHeight(); ++y)
1098		for (int x = 0; x < result.getWidth(); ++x)
1099		{
1100			const UVec4 pix(static_cast<deUint32>(static_cast<float>(red100[0]) * pba.getPixDepth(x, y)), 0, 0, 0);
1101
1102			result.setPixel(pix, x, y);
1103		}
1104
1105	for (int y = 0; y < reference.getHeight(); ++y)
1106	{
1107		for (int x = 0; x < reference.getWidth(); ++x)
1108		{
1109			if (x < horzEdge)
1110			{
1111				if (x + y < diagonalEdge)
1112					reference.setPixel(red025, x, y);
1113				else
1114					reference.setPixel(red075, x, y);
1115			}
1116			else
1117				reference.setPixel(red100, x, y);
1118		}
1119	}
1120
1121	return intThresholdCompare(log, "depthImage", "depthImage", reference, result, UVec4(), COMPARE_LOG_RESULT);
1122}
1123
1124tcu::TestStatus PipelineLibraryTestInstance::iterate (void)
1125{
1126	VkGraphicsPipelineLibraryFlagBitsEXT	graphicsPipelineLibraryFlags[]		=
1127	{
1128		VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT,
1129		VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT,
1130		VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT,
1131		VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT,
1132	};
1133	const auto								graphicsPipelineLibraryFlagsBegin	= graphicsPipelineLibraryFlags;
1134	const auto								graphicsPipelineLibraryFlagsEnd		= graphicsPipelineLibraryFlags + DE_LENGTH_OF_ARRAY(graphicsPipelineLibraryFlags);
1135	deUint32								permutationId						= 0;
1136	std::set<deUint32>						was;
1137	bool									result								= true;
1138
1139	do
1140	{
1141		RuntimePipelineTreeConfiguration	runtimePipelineTreeConfiguration	(m_data.pipelineTreeConfiguration.size());
1142		size_t								subsetNdxStart						= 0;
1143		deUint32							uniqueTreeSubsetCode				= 0;
1144
1145		for (size_t nodeNdx = 0; nodeNdx < runtimePipelineTreeConfiguration.size(); ++nodeNdx)
1146		{
1147			const deUint32				shaderCount	= m_data.pipelineTreeConfiguration[nodeNdx].shaderCount;
1148			RuntimePipelineTreeNode&	node		= runtimePipelineTreeConfiguration[nodeNdx];
1149
1150			node.parentIndex					= m_data.pipelineTreeConfiguration[nodeNdx].parentIndex;
1151			node.graphicsPipelineLibraryFlags	= 0u;
1152
1153			for (size_t subsetNdx = 0; subsetNdx < shaderCount; ++subsetNdx)
1154				node.graphicsPipelineLibraryFlags |= static_cast<VkGraphicsPipelineLibraryFlagsEXT>(graphicsPipelineLibraryFlags[subsetNdxStart + subsetNdx]);
1155
1156			if (node.parentIndex > 0)
1157				runtimePipelineTreeConfiguration[node.parentIndex].subtreeGraphicsPipelineLibraryFlags |= node.graphicsPipelineLibraryFlags;
1158
1159			// Each shader subset should be tested in each node of tree
1160			subsetNdxStart += shaderCount;
1161
1162			uniqueTreeSubsetCode = (uniqueTreeSubsetCode << 4) | node.graphicsPipelineLibraryFlags;
1163		}
1164
1165		// Check whether this configuration has been tried
1166		if (was.find(uniqueTreeSubsetCode) == was.end())
1167			was.insert(uniqueTreeSubsetCode);
1168		else
1169			continue;
1170
1171		result = result && runTest(runtimePipelineTreeConfiguration, m_data.optimize, m_data.delayedShaderCreate);
1172
1173		if (!result)
1174		{
1175			tcu::TestLog&		log = m_context.getTestContext().getLog();
1176			std::ostringstream	ess;
1177
1178			for (size_t nodeNdx = 0; nodeNdx < runtimePipelineTreeConfiguration.size(); ++nodeNdx)
1179			{
1180				const RuntimePipelineTreeNode&	node	= runtimePipelineTreeConfiguration[nodeNdx];
1181
1182				ess << node.parentIndex << " {";
1183
1184				for (size_t subsetNdx = 0; subsetNdx < DE_LENGTH_OF_ARRAY(graphicsPipelineLibraryFlags); ++subsetNdx)
1185				{
1186					if ((node.graphicsPipelineLibraryFlags & graphicsPipelineLibraryFlags[subsetNdx]) == 0)
1187						continue;
1188
1189					ess << getGraphicsPipelineLibraryFlagsString(graphicsPipelineLibraryFlags[subsetNdx]) << " ";
1190				}
1191
1192				ess  << "}" << std::endl;
1193			}
1194
1195			log << tcu::TestLog::Message << ess.str() << tcu::TestLog::EndMessage;
1196
1197			return tcu::TestStatus::fail("At permutation " + de::toString(permutationId));
1198		}
1199
1200		++permutationId;
1201	} while (std::next_permutation(graphicsPipelineLibraryFlagsBegin, graphicsPipelineLibraryFlagsEnd));
1202
1203	return tcu::TestStatus::pass("OK");
1204}
1205
1206
1207class PipelineLibraryTestCase : public TestCase
1208{
1209	public:
1210							PipelineLibraryTestCase		(tcu::TestContext& context, const char* name, const TestParams data);
1211							~PipelineLibraryTestCase	(void);
1212
1213	virtual void			checkSupport				(Context& context) const;
1214	virtual	void			initPrograms				(SourceCollections& programCollection) const;
1215	virtual TestInstance*	createInstance				(Context& context) const;
1216private:
1217	TestParams				m_data;
1218};
1219
1220PipelineLibraryTestCase::PipelineLibraryTestCase (tcu::TestContext& context, const char* name, const TestParams data)
1221	: vkt::TestCase	(context, name)
1222	, m_data		(data)
1223{
1224}
1225
1226PipelineLibraryTestCase::~PipelineLibraryTestCase (void)
1227{
1228}
1229
1230void PipelineLibraryTestCase::checkSupport (Context& context) const
1231{
1232	if (m_data.useMaintenance5)
1233	{
1234		context.requireDeviceFunctionality("VK_KHR_maintenance5");
1235		return;
1236	}
1237
1238	context.requireDeviceFunctionality("VK_KHR_pipeline_library");
1239
1240	if (m_data.delayedShaderCreate || (m_data.pipelineTreeConfiguration.size() > 1))
1241	{
1242		context.requireDeviceFunctionality("VK_EXT_graphics_pipeline_library");
1243
1244		const VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT& graphicsPipelineLibraryFeaturesEXT = context.getGraphicsPipelineLibraryFeaturesEXT();
1245
1246		if (!graphicsPipelineLibraryFeaturesEXT.graphicsPipelineLibrary)
1247			TCU_THROW(NotSupportedError, "graphicsPipelineLibraryFeaturesEXT.graphicsPipelineLibrary required");
1248	}
1249}
1250
1251void PipelineLibraryTestCase::initPrograms (SourceCollections& programCollection) const
1252{
1253	std::string	vert	=
1254		"#version 450\n"
1255		"layout(location = 0) in vec4 in_position;\n"
1256		"layout(set = 0, binding = 0) uniform buf\n"
1257		"{\n"
1258		"  vec4 z_coord;\n"
1259		"};\n"
1260		"\n"
1261		"out gl_PerVertex\n"
1262		"{\n"
1263		"  vec4 gl_Position;\n"
1264		"};\n"
1265		"\n"
1266		"void main()\n"
1267		"{\n"
1268		"  const float z = gl_VertexIndex < 3 ? z_coord.x : z_coord.y;\n"
1269		"  gl_Position = vec4(in_position.x, in_position.y, z, 1.0f);\n"
1270		"}\n";
1271
1272	programCollection.glslSources.add("vert") << glu::VertexSource(vert);
1273
1274	std::string	frag	=
1275		"#version 450\n"
1276		"layout(location = 0) out highp vec4 o_color;\n"
1277		"layout(set = 1, binding = 1) uniform buf\n"
1278		"{\n"
1279		"  vec4 colorTop;\n"
1280		"  vec4 colorBot;\n"
1281		"};\n"
1282		"\n"
1283		"void main()\n"
1284		"{\n"
1285		"  const int middle = " + de::toString(RENDER_SIZE_HEIGHT / 2) + ";\n"
1286		"  o_color          = int(gl_FragCoord.y - 0.5f) < middle ? colorTop : colorBot;\n"
1287		"}\n";
1288
1289	programCollection.glslSources.add("frag") << glu::FragmentSource(frag);
1290}
1291
1292TestInstance* PipelineLibraryTestCase::createInstance (Context& context) const
1293{
1294	return new PipelineLibraryTestInstance(context, m_data);
1295}
1296
1297enum class MiscTestMode
1298{
1299	INDEPENDENT_PIPELINE_LAYOUT_SETS_FAST_LINKED = 0,
1300	INDEPENDENT_PIPELINE_LAYOUT_SETS_WITH_LINK_TIME_OPTIMIZATION_UNION_HANDLE,
1301	BIND_NULL_DESCRIPTOR_SET,
1302	BIND_NULL_DESCRIPTOR_SET_IN_MONOLITHIC_PIPELINE,
1303	COMPARE_LINK_TIMES,
1304	SHADER_MODULE_CREATE_INFO_COMP,
1305	SHADER_MODULE_CREATE_INFO_RT,
1306	SHADER_MODULE_CREATE_INFO_RT_LIB,
1307	NULL_RENDERING_CREATE_INFO,
1308};
1309
1310struct MiscTestParams
1311{
1312	MiscTestMode	mode;
1313
1314	// attributes used in BIND_NULL_DESCRIPTOR_SET mode
1315	deUint32		layoutsCount;
1316	deUint32		layoutsBits;
1317};
1318
1319class PipelineLibraryMiscTestInstance : public TestInstance
1320{
1321public:
1322						PipelineLibraryMiscTestInstance		(Context&					context,
1323															 const MiscTestParams&		params);
1324						~PipelineLibraryMiscTestInstance	(void) = default;
1325	tcu::TestStatus		iterate								(void);
1326
1327protected:
1328
1329	tcu::TestStatus		runNullDescriptorSet					(void);
1330	tcu::TestStatus		runNullDescriptorSetInMonolithicPipeline(void);
1331	tcu::TestStatus		runIndependentPipelineLayoutSets		(bool useLinkTimeOptimization = false);
1332	tcu::TestStatus		runCompareLinkTimes						(void);
1333
1334	struct VerificationData
1335	{
1336		const tcu::IVec2	point;
1337		const tcu::IVec4	color;
1338	};
1339	tcu::TestStatus		verifyResult						(const std::vector<VerificationData>&	verificationData,
1340															 const tcu::ConstPixelBufferAccess&		colorPixelAccess) const;
1341
1342private:
1343	MiscTestParams					m_testParams;
1344	const VkFormat					m_colorFormat;
1345	const Vec4						m_colorClearColor;
1346	const VkRect2D					m_renderArea;
1347
1348	de::MovePtr<ImageWithMemory>	m_colorImage;
1349	Move<VkImageView>				m_colorImageView;
1350
1351	Move<VkRenderPass>				m_renderPass;
1352	Move<VkFramebuffer>				m_framebuffer;
1353
1354	Move<VkCommandPool>				m_cmdPool;
1355	Move<VkCommandBuffer>			m_cmdBuffer;
1356};
1357
1358PipelineLibraryMiscTestInstance::PipelineLibraryMiscTestInstance(Context& context, const MiscTestParams& params)
1359	: vkt::TestInstance		(context)
1360	, m_testParams			(params)
1361	, m_colorFormat			(VK_FORMAT_R8G8B8A8_UNORM)
1362	, m_colorClearColor		(0.0f, 0.0f, 0.0f, 1.0f)
1363	, m_renderArea			(makeRect2D(RENDER_SIZE_WIDTH, RENDER_SIZE_HEIGHT))
1364{
1365}
1366
1367tcu::TestStatus PipelineLibraryMiscTestInstance::iterate (void)
1368{
1369	const DeviceInterface&	vk			= m_context.getDeviceInterface();
1370	const VkDevice			device		= m_context.getDevice();
1371	Allocator&				allocator	= m_context.getDefaultAllocator();
1372
1373	// create image and image view that will hold rendered frame
1374	const VkImageCreateInfo colorImageCreateInfo = makeColorImageCreateInfo(m_colorFormat, m_renderArea.extent.width, m_renderArea.extent.height);
1375	m_colorImage = de::MovePtr<ImageWithMemory>(new ImageWithMemory(vk, device, allocator, colorImageCreateInfo, MemoryRequirement::Any));
1376	const VkImageViewCreateInfo		colorImageViewCreateInfo	= makeImageViewCreateInfo(**m_colorImage, m_colorFormat, static_cast<VkImageAspectFlags>(VK_IMAGE_ASPECT_COLOR_BIT));
1377	const Move<VkImageView>			colorImageView				= createImageView(vk, device, &colorImageViewCreateInfo);
1378
1379	// create renderpass and framebuffer
1380	m_renderPass = makeRenderPass(vk, device, m_colorFormat);
1381	const VkFramebufferCreateInfo framebufferCreateInfo = makeFramebufferCreateInfo(*m_renderPass, 1u, &*colorImageView, m_renderArea.extent.width, m_renderArea.extent.height);
1382	m_framebuffer = createFramebuffer(vk, device, &framebufferCreateInfo);
1383
1384	// create command pool and command buffer
1385	const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1386	m_cmdPool	= createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
1387	m_cmdBuffer	= allocateCommandBuffer(vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1388
1389	// run selected test
1390	if (m_testParams.mode == MiscTestMode::BIND_NULL_DESCRIPTOR_SET)
1391		return runNullDescriptorSet();
1392	else if (m_testParams.mode == MiscTestMode::BIND_NULL_DESCRIPTOR_SET_IN_MONOLITHIC_PIPELINE)
1393		return runNullDescriptorSetInMonolithicPipeline();
1394	else if (m_testParams.mode == MiscTestMode::INDEPENDENT_PIPELINE_LAYOUT_SETS_FAST_LINKED)
1395		return runIndependentPipelineLayoutSets();
1396	else if (m_testParams.mode == MiscTestMode::INDEPENDENT_PIPELINE_LAYOUT_SETS_WITH_LINK_TIME_OPTIMIZATION_UNION_HANDLE)
1397		return runIndependentPipelineLayoutSets(true);
1398	else if (m_testParams.mode == MiscTestMode::COMPARE_LINK_TIMES)
1399		return runCompareLinkTimes();
1400
1401	DE_ASSERT(DE_FALSE);
1402	return tcu::TestStatus::fail("Fail");
1403}
1404
1405tcu::TestStatus PipelineLibraryMiscTestInstance::runNullDescriptorSet(void)
1406{
1407	const DeviceInterface&			vk						= m_context.getDeviceInterface();
1408	const VkDevice					device					= m_context.getDevice();
1409	Allocator&						allocator				= m_context.getDefaultAllocator();
1410
1411	const VkDeviceSize				colorBufferDataSize		= static_cast<VkDeviceSize>(m_renderArea.extent.width * m_renderArea.extent.height * tcu::getPixelSize(mapVkFormat(m_colorFormat)));
1412	const VkBufferCreateInfo		colorBufferCreateInfo	= makeBufferCreateInfo(colorBufferDataSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1413	const BufferWithMemory			colorBuffer				(vk, device, allocator, colorBufferCreateInfo, MemoryRequirement::HostVisible);
1414
1415	VkDeviceSize					uniformBufferDataSize	= sizeof(tcu::Vec4);
1416	const VkBufferCreateInfo		uniformBufferCreateInfo	= makeBufferCreateInfo(uniformBufferDataSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
1417	de::MovePtr<BufferWithMemory>	uniformBuffer[2];
1418
1419	// setup data in uniform buffers that will give us expected result for validation
1420	const tcu::Vec4 uniformBuffData[]
1421	{
1422		{ -1.00f,  1.00f,  2.0f, -2.00f },
1423		{  0.00f,  0.20f,  0.6f,  0.75f },
1424	};
1425
1426	for (deUint32 i = 0; i < 2; ++i)
1427	{
1428		uniformBuffer[i] = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, uniformBufferCreateInfo, MemoryRequirement::HostVisible));
1429		deMemcpy(uniformBuffer[i]->getAllocation().getHostPtr(), uniformBuffData[i].getPtr(), (size_t)uniformBufferDataSize);
1430		flushAlloc(vk, device, uniformBuffer[i]->getAllocation());
1431	}
1432
1433	const deUint32 maxBitsCount = 8 * sizeof(m_testParams.layoutsBits);
1434	VkDescriptorSetLayout vertDescriptorSetLayouts[maxBitsCount];
1435	VkDescriptorSetLayout fragDescriptorSetLayouts[maxBitsCount];
1436	VkDescriptorSetLayout allDescriptorSetLayouts[maxBitsCount];
1437
1438	// set all layouts to NULL
1439	deMemset(&vertDescriptorSetLayouts, DE_NULL, maxBitsCount * sizeof(VkDescriptorSetLayout));
1440	deMemset(&fragDescriptorSetLayouts, DE_NULL, maxBitsCount * sizeof(VkDescriptorSetLayout));
1441
1442	// create used descriptor set layouts
1443	Move<VkDescriptorSetLayout> usedDescriptorSetLayouts[]
1444	{
1445		DescriptorSetLayoutBuilder()
1446			.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT)
1447			.build(vk, device),
1448		DescriptorSetLayoutBuilder()
1449			.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
1450			.build(vk, device)
1451	};
1452
1453	// create descriptor set layouts that are not used by shaders in test - finalPipelineLayout,
1454	// needs to always be the complete pipeline layout with no holes; we can put NULLs in
1455	// DescriptorSetLayouts used by partial pipelines (vertDescriptorSetLayouts and fragDescriptorSetLayouts)
1456	Move<VkDescriptorSetLayout> unusedDescriptorSetLayouts[maxBitsCount];
1457	for (deUint32 i = 0u; i < m_testParams.layoutsCount; ++i)
1458	{
1459		unusedDescriptorSetLayouts[i] = DescriptorSetLayoutBuilder().build(vk, device);
1460
1461		// by default allDescriptorSetLayouts is filled with unused layouts but later
1462		// if test requires this proper indexes are replaced with used layouts
1463		allDescriptorSetLayouts[i] = *unusedDescriptorSetLayouts[i];
1464	}
1465
1466	VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = initVulkanStructure();
1467	pipelineLayoutCreateInfo.flags = VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT;
1468
1469	// find set bits
1470	std::vector<deUint32> bitsThatAreSet;
1471	for (deUint32 i = 0u; i < m_testParams.layoutsCount; ++i)
1472	{
1473		if (m_testParams.layoutsBits & (1 << (maxBitsCount - 1 - i)))
1474			bitsThatAreSet.push_back(i);
1475	}
1476
1477	deUint32 usedDescriptorSets = static_cast<deUint32>(bitsThatAreSet.size());
1478	DE_ASSERT(usedDescriptorSets && (usedDescriptorSets < 3u));
1479
1480	deUint32 vertSetIndex						= bitsThatAreSet[0];
1481	deUint32 fragSetIndex						= 0u;
1482	vertDescriptorSetLayouts[vertSetIndex]		= *usedDescriptorSetLayouts[0];
1483	allDescriptorSetLayouts[vertSetIndex]		= *usedDescriptorSetLayouts[0];
1484	pipelineLayoutCreateInfo.setLayoutCount		= vertSetIndex + 1u;
1485	pipelineLayoutCreateInfo.pSetLayouts		= vertDescriptorSetLayouts;
1486
1487	Move<VkPipelineLayout>	vertPipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
1488	Move<VkPipelineLayout>	fragPipelineLayout;
1489
1490	if (usedDescriptorSets == 2u)
1491	{
1492		fragSetIndex							= bitsThatAreSet[1];
1493		fragDescriptorSetLayouts[fragSetIndex]	= *usedDescriptorSetLayouts[1];
1494		allDescriptorSetLayouts[fragSetIndex]	= *usedDescriptorSetLayouts[1];
1495		pipelineLayoutCreateInfo.setLayoutCount	= fragSetIndex + 1u;
1496		pipelineLayoutCreateInfo.pSetLayouts	= fragDescriptorSetLayouts;
1497
1498		fragPipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
1499	}
1500	else
1501	{
1502		pipelineLayoutCreateInfo.setLayoutCount = 0u;
1503		pipelineLayoutCreateInfo.pSetLayouts	= DE_NULL;
1504		fragPipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
1505	}
1506
1507	// create descriptor pool
1508	Move<VkDescriptorPool> descriptorPool = DescriptorPoolBuilder()
1509		.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, usedDescriptorSets)
1510		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, usedDescriptorSets);
1511
1512	const VkDescriptorBufferInfo	vertShaderBufferInfo	= makeDescriptorBufferInfo(**uniformBuffer[0], 0u, uniformBufferDataSize);
1513	Move<VkDescriptorSet>			vertDescriptorSet		= makeDescriptorSet(vk, device, *descriptorPool, *usedDescriptorSetLayouts[0]);
1514	Move<VkDescriptorSet>			fragDescriptorSet;
1515
1516	if (usedDescriptorSets == 1u)
1517	{
1518		// update single descriptors with actual buffer
1519		DescriptorSetUpdateBuilder()
1520			.writeSingle(*vertDescriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &vertShaderBufferInfo)
1521			.update(vk, device);
1522	}
1523	else
1524	{
1525		const VkDescriptorBufferInfo fragShaderBufferInfo = makeDescriptorBufferInfo(**uniformBuffer[1], 0u, uniformBufferDataSize);
1526		fragDescriptorSet = makeDescriptorSet(vk, device, *descriptorPool, *usedDescriptorSetLayouts[1]);
1527
1528		// update both descriptors with actual buffers
1529		DescriptorSetUpdateBuilder()
1530			.writeSingle(*vertDescriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &vertShaderBufferInfo)
1531			.writeSingle(*fragDescriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &fragShaderBufferInfo)
1532			.update(vk, device);
1533	}
1534
1535	pipelineLayoutCreateInfo.setLayoutCount		= m_testParams.layoutsCount;
1536	pipelineLayoutCreateInfo.pSetLayouts		= allDescriptorSetLayouts;
1537	Move<VkPipelineLayout> finalPipelineLayout	= createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
1538
1539	const deUint32 commonPipelinePartFlags = deUint32(VK_PIPELINE_CREATE_LIBRARY_BIT_KHR);
1540	GraphicsPipelineCreateInfo partialPipelineCreateInfo[]
1541	{
1542		{ *vertPipelineLayout,	*m_renderPass, 0, commonPipelinePartFlags },
1543		{ *fragPipelineLayout,	*m_renderPass, 0, commonPipelinePartFlags },
1544	};
1545
1546	// fill proper portion of pipeline state
1547	updateVertexInputInterface(m_context, partialPipelineCreateInfo[0], VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 0u);
1548	updatePreRasterization(m_context, partialPipelineCreateInfo[0], false);
1549	updatePostRasterization(m_context, partialPipelineCreateInfo[1], false);
1550	updateFragmentOutputInterface(m_context, partialPipelineCreateInfo[1]);
1551
1552	Move<VkPipeline> vertPipelinePart;
1553	Move<VkPipeline> fragPipelinePart;
1554
1555	// extend pNext chain and create partial pipelines
1556	{
1557		VkGraphicsPipelineLibraryCreateInfoEXT libraryCreateInfo = makeGraphicsPipelineLibraryCreateInfo(VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT | VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT);
1558		appendStructurePtrToVulkanChain(&partialPipelineCreateInfo[0].pNext, &libraryCreateInfo);
1559		vertPipelinePart = createGraphicsPipeline(vk, device, DE_NULL, &partialPipelineCreateInfo[0]);
1560
1561		libraryCreateInfo.flags = VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT | VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT,
1562		appendStructurePtrToVulkanChain(&partialPipelineCreateInfo[1].pNext, &libraryCreateInfo);
1563		fragPipelinePart = createGraphicsPipeline(vk, device, DE_NULL, &partialPipelineCreateInfo[1]);
1564	}
1565
1566	// create final pipeline out of two parts
1567	std::vector<VkPipeline>			rawParts			= { *vertPipelinePart, *fragPipelinePart };
1568	VkPipelineLibraryCreateInfoKHR	linkingInfo			= makePipelineLibraryCreateInfo(rawParts);
1569	VkGraphicsPipelineCreateInfo	finalPipelineInfo	= initVulkanStructure();
1570
1571	finalPipelineInfo.layout = *finalPipelineLayout;
1572	appendStructurePtrToVulkanChain(&finalPipelineInfo.pNext, &linkingInfo);
1573	Move<VkPipeline> pipeline = createGraphicsPipeline(vk, device, DE_NULL, &finalPipelineInfo);
1574
1575	vk::beginCommandBuffer(vk, *m_cmdBuffer, 0u);
1576	{
1577		// change color image layout
1578		const VkImageMemoryBarrier initialImageBarrier = makeImageMemoryBarrier(
1579			0,													// VkAccessFlags					srcAccessMask;
1580			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,				// VkAccessFlags					dstAccessMask;
1581			VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout					oldLayout;
1582			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					newLayout;
1583			**m_colorImage,										// VkImage							image;
1584			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }		// VkImageSubresourceRange			subresourceRange;
1585		);
1586		vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (VkDependencyFlags)0, 0, DE_NULL, 0, DE_NULL, 1, &initialImageBarrier);
1587
1588		// wait for uniform buffers
1589		std::vector<VkBufferMemoryBarrier> initialBufferBarriers(2u, makeBufferMemoryBarrier(
1590			VK_ACCESS_HOST_WRITE_BIT,							// VkAccessFlags2KHR				srcAccessMask
1591			VK_ACCESS_TRANSFER_READ_BIT,						// VkAccessFlags2KHR				dstAccessMask
1592			uniformBuffer[0]->get(),							// VkBuffer							buffer
1593			0u,													// VkDeviceSize						offset
1594			uniformBufferDataSize								// VkDeviceSize						size
1595		));
1596		initialBufferBarriers[1].buffer = uniformBuffer[1]->get();
1597		vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, DE_NULL, 2, initialBufferBarriers.data(), 0, DE_NULL);
1598
1599		beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, m_renderArea, m_colorClearColor);
1600
1601		vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1602
1603		vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *finalPipelineLayout, vertSetIndex, 1u, &*vertDescriptorSet, 0u, DE_NULL);
1604		if (usedDescriptorSets == 2u)
1605			vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *finalPipelineLayout, fragSetIndex, 1u, &*fragDescriptorSet, 0u, DE_NULL);
1606
1607		vk.cmdDraw(*m_cmdBuffer, 4, 1u, 0u, 0u);
1608
1609		endRenderPass(vk, *m_cmdBuffer);
1610
1611		const tcu::IVec2 size { (deInt32)m_renderArea.extent.width, (deInt32)m_renderArea.extent.height };
1612		copyImageToBuffer(vk, *m_cmdBuffer, **m_colorImage, *colorBuffer, size);
1613	}
1614	vk::endCommandBuffer(vk, *m_cmdBuffer);
1615	vk::submitCommandsAndWait(vk, device, m_context.getUniversalQueue(), *m_cmdBuffer);
1616
1617	vk::invalidateAlloc(vk, device, colorBuffer.getAllocation());
1618	const tcu::ConstPixelBufferAccess colorPixelAccess(mapVkFormat(m_colorFormat), m_renderArea.extent.width, m_renderArea.extent.height, 1, colorBuffer.getAllocation().getHostPtr());
1619
1620	// verify result
1621	deInt32 width	= (deInt32)m_renderArea.extent.width;
1622	deInt32 height	= (deInt32)m_renderArea.extent.height;
1623	const std::vector<VerificationData> verificationData
1624	{
1625		{ { 1, 1 },						{ 0, 51, 153, 191 } },		// note COLOR_COMPONENTS_NO_RED is used
1626		{ { width / 2, height / 2 },	{ 0, 51, 153, 191 } },
1627		{ { width - 2, height - 2 },	{ 0, 0, 0, 255 } }			// clear color
1628	};
1629	return verifyResult(verificationData, colorPixelAccess);
1630}
1631
1632tcu::TestStatus PipelineLibraryMiscTestInstance::runNullDescriptorSetInMonolithicPipeline()
1633{
1634	// VK_NULL_HANDLE can be used for descriptor set layouts when creating a pipeline layout whether independent sets are used or not,
1635	// as long as graphics pipeline libraries are enabled; VK_NULL_HANDLE is also alowed for a descriptor set under the same conditions
1636	// when using vkCmdBindDescriptorSets
1637
1638	const DeviceInterface&	vk			= m_context.getDeviceInterface();
1639	const VkDevice			device		= m_context.getDevice();
1640	Allocator&				allocator	= m_context.getDefaultAllocator();
1641
1642	const VkDeviceSize				colorBufferDataSize		= static_cast<VkDeviceSize>(m_renderArea.extent.width * m_renderArea.extent.height * tcu::getPixelSize(mapVkFormat(m_colorFormat)));
1643	const VkBufferCreateInfo		colorBufferCreateInfo	= makeBufferCreateInfo(colorBufferDataSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1644	const BufferWithMemory			colorBuffer(vk, device, allocator, colorBufferCreateInfo, MemoryRequirement::HostVisible);
1645
1646	const tcu::Vec4 uniformBuffData	{ 0.0f, 0.20f, 0.6f, 0.75f };
1647	VkDeviceSize					uniformBufferDataSize = sizeof(tcu::Vec4);
1648	const VkBufferCreateInfo		uniformBufferCreateInfo = makeBufferCreateInfo(uniformBufferDataSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
1649
1650	de::MovePtr<BufferWithMemory> uniformBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, uniformBufferCreateInfo, MemoryRequirement::HostVisible));
1651	deMemcpy(uniformBuffer->getAllocation().getHostPtr(), uniformBuffData.getPtr(), (size_t)uniformBufferDataSize);
1652	flushAlloc(vk, device, uniformBuffer->getAllocation());
1653
1654	// create descriptor set layouts - first unused, second used
1655	Move<VkDescriptorSetLayout> descriptorSetLayout
1656	{
1657		DescriptorSetLayoutBuilder()
1658			.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
1659			.build(vk, device)
1660	};
1661
1662	Move<VkDescriptorPool> allDescriptorPool = DescriptorPoolBuilder()
1663		.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1)
1664		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
1665
1666	// create descriptor set
1667	Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vk, device, *allDescriptorPool, *descriptorSetLayout);
1668
1669	// update descriptor with actual buffer
1670	const VkDescriptorBufferInfo shaderBufferInfo = makeDescriptorBufferInfo(**uniformBuffer, 0u, uniformBufferDataSize);
1671	DescriptorSetUpdateBuilder()
1672		.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &shaderBufferInfo)
1673		.update(vk, device);
1674
1675	// create a pipeline layout with its first descriptor set layout as VK_NULL_HANDLE
1676	// and a second with a valid descriptor set layout containing a buffer
1677	VkDescriptorSet			rawDescriptorSets[]			= { DE_NULL, *descriptorSet };
1678	VkDescriptorSetLayout	rawDescriptorSetLayouts[]	= { DE_NULL, *descriptorSetLayout };
1679
1680	VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = initVulkanStructure();
1681	pipelineLayoutCreateInfo.setLayoutCount = 2u;
1682	pipelineLayoutCreateInfo.pSetLayouts = rawDescriptorSetLayouts;
1683	Move<VkPipelineLayout> pipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
1684
1685	// create monolithic graphics pipeline
1686	GraphicsPipelineCreateInfo pipelineCreateInfo(*pipelineLayout, *m_renderPass, 0, 0u);
1687	updateVertexInputInterface(m_context, pipelineCreateInfo, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 0u);
1688	updatePreRasterization(m_context, pipelineCreateInfo, false);
1689	updatePostRasterization(m_context, pipelineCreateInfo, false);
1690	updateFragmentOutputInterface(m_context, pipelineCreateInfo);
1691	Move<VkPipeline> pipeline = createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
1692
1693	vk::beginCommandBuffer(vk, *m_cmdBuffer, 0u);
1694	{
1695		// change color image layout
1696		const VkImageMemoryBarrier initialImageBarrier = makeImageMemoryBarrier(
1697			0,													// VkAccessFlags					srcAccessMask;
1698			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,				// VkAccessFlags					dstAccessMask;
1699			VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout					oldLayout;
1700			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					newLayout;
1701			**m_colorImage,										// VkImage							image;
1702			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }		// VkImageSubresourceRange			subresourceRange;
1703		);
1704		vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (VkDependencyFlags)0, 0, DE_NULL, 0, DE_NULL, 1, &initialImageBarrier);
1705
1706		// wait for uniform buffer
1707		const VkBufferMemoryBarrier initialBufferBarrier = makeBufferMemoryBarrier(
1708			VK_ACCESS_HOST_WRITE_BIT,							// VkAccessFlags2KHR				srcAccessMask
1709			VK_ACCESS_UNIFORM_READ_BIT,							// VkAccessFlags2KHR				dstAccessMask
1710			uniformBuffer->get(),								// VkBuffer							buffer
1711			0u,													// VkDeviceSize						offset
1712			uniformBufferDataSize								// VkDeviceSize						size
1713		);
1714		vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, (VkDependencyFlags)0, 0, DE_NULL, 1, &initialBufferBarrier, 0, DE_NULL);
1715
1716		beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, m_renderArea, m_colorClearColor);
1717
1718		vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1719		vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 2u, rawDescriptorSets, 0u, DE_NULL);
1720		vk.cmdDraw(*m_cmdBuffer, 4, 1u, 0u, 0u);
1721
1722		endRenderPass(vk, *m_cmdBuffer);
1723
1724		const tcu::IVec2 size{ (deInt32)m_renderArea.extent.width, (deInt32)m_renderArea.extent.height };
1725		copyImageToBuffer(vk, *m_cmdBuffer, **m_colorImage, *colorBuffer, size);
1726	}
1727	vk::endCommandBuffer(vk, *m_cmdBuffer);
1728	vk::submitCommandsAndWait(vk, device, m_context.getUniversalQueue(), *m_cmdBuffer);
1729
1730	vk::invalidateAlloc(vk, device, colorBuffer.getAllocation());
1731	const tcu::ConstPixelBufferAccess colorPixelAccess(mapVkFormat(m_colorFormat), m_renderArea.extent.width, m_renderArea.extent.height, 1, colorBuffer.getAllocation().getHostPtr());
1732
1733	// verify result
1734	deInt32		width		= (deInt32)m_renderArea.extent.width;
1735	deInt32		height		= (deInt32)m_renderArea.extent.height;
1736	tcu::IVec4	outColor
1737	{
1738		0,										// r is 0 because COLOR_COMPONENTS_NO_RED is used
1739		static_cast<int>(uniformBuffData[1] * 255),
1740		static_cast<int>(uniformBuffData[2] * 255),
1741		static_cast<int>(uniformBuffData[3] * 255)
1742	};
1743	const std::vector<VerificationData> verificationData
1744	{
1745		{ { 1, 1 },						outColor },
1746		{ { width / 2, height / 2 },	outColor },
1747		{ { width - 2, height - 2 },	{ 0, 0, 0, 255 } }			// clear color
1748	};
1749
1750	return verifyResult(verificationData, colorPixelAccess);
1751}
1752
1753tcu::TestStatus PipelineLibraryMiscTestInstance::runIndependentPipelineLayoutSets (bool useLinkTimeOptimization)
1754{
1755	const DeviceInterface&			vk							= m_context.getDeviceInterface();
1756	const VkDevice					device						= m_context.getDevice();
1757	Allocator&						allocator					= m_context.getDefaultAllocator();
1758
1759	const VkDeviceSize				colorBufferDataSize			= static_cast<VkDeviceSize>(m_renderArea.extent.width * m_renderArea.extent.height * tcu::getPixelSize(mapVkFormat(m_colorFormat)));
1760	const VkBufferCreateInfo		colorBufferCreateInfo		= makeBufferCreateInfo(colorBufferDataSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1761	const BufferWithMemory			colorBuffer					(vk, device, allocator, colorBufferCreateInfo, MemoryRequirement::HostVisible);
1762
1763	VkDeviceSize					uniformBufferDataSize		= sizeof(tcu::Vec4);
1764	const VkBufferCreateInfo		uniformBufferCreateInfo		= makeBufferCreateInfo(uniformBufferDataSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
1765
1766	de::MovePtr<BufferWithMemory>	uniformBuffer[3];
1767
1768	// setup data in uniform buffers that will give us expected result for validation
1769	const tcu::Vec4 uniformBuffData[3]
1770	{
1771		{  4.00f,  3.00f, -1.0f,  4.00f },
1772		{  0.10f,  0.25f, -0.5f,  0.05f },
1773		{ -5.00f, -2.00f,  3.0f, -6.00f },
1774	};
1775
1776	for (deUint32 i = 0; i < 3; ++i)
1777	{
1778		uniformBuffer[i] = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, uniformBufferCreateInfo, MemoryRequirement::HostVisible));
1779		deMemcpy(uniformBuffer[i]->getAllocation().getHostPtr(), uniformBuffData[i].getPtr(), (size_t)uniformBufferDataSize);
1780		flushAlloc(vk, device, uniformBuffer[i]->getAllocation());
1781	}
1782
1783	// create three descriptor set layouts
1784	Move<VkDescriptorSetLayout>	descriptorSetLayouts[3];
1785	descriptorSetLayouts[0] = DescriptorSetLayoutBuilder()
1786		.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT)
1787		.build(vk, device);
1788	descriptorSetLayouts[1] = DescriptorSetLayoutBuilder()
1789		.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
1790		.build(vk, device);
1791	descriptorSetLayouts[2] = DescriptorSetLayoutBuilder()
1792		.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT)
1793		.build(vk, device);
1794
1795	// for the link time opt (and when null handle is used) use total pipeline layout recreated without the INDEPENDENT SETS bit
1796	deUint32 allLayoutsFlag = deUint32(VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT);
1797	if (useLinkTimeOptimization)
1798		allLayoutsFlag = 0u;
1799
1800	// Pre-rasterization stage library has sets 0, 1, 2
1801	// * set 0 has descriptors
1802	// * set 1 has no descriptors
1803	// * set 2 has descriptors
1804	// Fragment stage library has sets 0, 1
1805	// * set 0 has descriptors
1806	// * set 1 has descriptors
1807	VkDescriptorSetLayout vertDescriptorSetLayouts[]	= { *descriptorSetLayouts[0], DE_NULL, *descriptorSetLayouts[2] };
1808	VkDescriptorSetLayout fragDescriptorSetLayouts[]	= { *descriptorSetLayouts[0], *descriptorSetLayouts[1] };
1809	VkDescriptorSetLayout allDescriptorSetLayouts[]		= { *descriptorSetLayouts[0], *descriptorSetLayouts[1], *descriptorSetLayouts[2] };
1810
1811	VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo	= initVulkanStructure();
1812	pipelineLayoutCreateInfo.flags						= allLayoutsFlag;
1813	pipelineLayoutCreateInfo.setLayoutCount				= 3u;
1814	pipelineLayoutCreateInfo.pSetLayouts				= allDescriptorSetLayouts;
1815	Move<VkPipelineLayout> allLayouts					= createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
1816	pipelineLayoutCreateInfo.flags						= deUint32(VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT);
1817	pipelineLayoutCreateInfo.pSetLayouts				= vertDescriptorSetLayouts;
1818	Move<VkPipelineLayout> vertLayouts					= createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
1819	pipelineLayoutCreateInfo.setLayoutCount				= 2u;
1820	pipelineLayoutCreateInfo.pSetLayouts				= fragDescriptorSetLayouts;
1821	Move<VkPipelineLayout> fragLayouts					= createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
1822
1823	Move<VkDescriptorPool> allDescriptorPool = DescriptorPoolBuilder()
1824		.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3)
1825		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 3);
1826
1827	// create three descriptor sets
1828	Move<VkDescriptorSet>	descriptorSetA			= makeDescriptorSet(vk, device, *allDescriptorPool, *descriptorSetLayouts[0]);
1829	Move<VkDescriptorSet>	descriptorSetB			= makeDescriptorSet(vk, device, *allDescriptorPool, *descriptorSetLayouts[1]);
1830	Move<VkDescriptorSet>	descriptorSetC			= makeDescriptorSet(vk, device, *allDescriptorPool, *descriptorSetLayouts[2]);
1831	VkDescriptorSet			allDescriptorSets[]		= { *descriptorSetA , *descriptorSetB , *descriptorSetC };
1832
1833	// update descriptors with actual buffers
1834	const VkDescriptorBufferInfo shaderBufferAInfo = makeDescriptorBufferInfo(**uniformBuffer[0], 0u, uniformBufferDataSize);
1835	const VkDescriptorBufferInfo shaderBufferBInfo = makeDescriptorBufferInfo(**uniformBuffer[1], 0u, uniformBufferDataSize);
1836	const VkDescriptorBufferInfo shaderBufferCInfo = makeDescriptorBufferInfo(**uniformBuffer[2], 0u, uniformBufferDataSize);
1837	DescriptorSetUpdateBuilder()
1838		.writeSingle(*descriptorSetA, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &shaderBufferAInfo)
1839		.writeSingle(*descriptorSetB, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &shaderBufferBInfo)
1840		.writeSingle(*descriptorSetC, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &shaderBufferCInfo)
1841		.update(vk, device);
1842
1843	deUint32 commonPipelinePartFlags	= deUint32(VK_PIPELINE_CREATE_LIBRARY_BIT_KHR);
1844	deUint32 finalPipelineFlag			= 0u;
1845	if (useLinkTimeOptimization)
1846	{
1847		commonPipelinePartFlags |= deUint32(VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT);
1848		finalPipelineFlag		 = deUint32(VK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXT);
1849	}
1850
1851	GraphicsPipelineCreateInfo partialPipelineCreateInfo[]
1852	{
1853		{ DE_NULL,		*m_renderPass, 0, commonPipelinePartFlags },
1854		{ *vertLayouts,	*m_renderPass, 0, commonPipelinePartFlags },
1855		{ *fragLayouts,	*m_renderPass, 0, commonPipelinePartFlags },
1856		{ DE_NULL,		*m_renderPass, 0, commonPipelinePartFlags }
1857	};
1858
1859	// fill proper portion of pipeline state
1860	updateVertexInputInterface		(m_context, partialPipelineCreateInfo[0], VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 0u);
1861	updatePreRasterization			(m_context, partialPipelineCreateInfo[1], false);
1862	updatePostRasterization			(m_context, partialPipelineCreateInfo[2], false);
1863	updateFragmentOutputInterface	(m_context, partialPipelineCreateInfo[3]);
1864
1865	// extend pNext chain and create all partial pipelines
1866	std::vector<VkPipeline>			rawParts(4u, DE_NULL);
1867	std::vector<Move<VkPipeline> >	pipelineParts;
1868	pipelineParts.reserve(4u);
1869	VkGraphicsPipelineLibraryCreateInfoEXT libraryCreateInfo = makeGraphicsPipelineLibraryCreateInfo(VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT);
1870	for (deUint32 i = 0 ; i < 4u ; ++i)
1871	{
1872		libraryCreateInfo.flags = GRAPHICS_PIPELINE_LIBRARY_FLAGS[i];
1873		appendStructurePtrToVulkanChain(&partialPipelineCreateInfo[i].pNext, &libraryCreateInfo);
1874		pipelineParts.emplace_back(createGraphicsPipeline(vk, device, DE_NULL, &partialPipelineCreateInfo[i]));
1875		rawParts[i] = *pipelineParts[i];
1876	}
1877
1878	// create final pipeline out of four parts
1879	VkPipelineLibraryCreateInfoKHR	linkingInfo			= makePipelineLibraryCreateInfo(rawParts);
1880	VkGraphicsPipelineCreateInfo	finalPipelineInfo	= initVulkanStructure();
1881
1882	finalPipelineInfo.flags		= finalPipelineFlag;
1883	finalPipelineInfo.layout	= *allLayouts;
1884
1885	appendStructurePtrToVulkanChain(&finalPipelineInfo.pNext, &linkingInfo);
1886	Move<VkPipeline> pipeline = createGraphicsPipeline(vk, device, DE_NULL, &finalPipelineInfo);
1887
1888	vk::beginCommandBuffer(vk, *m_cmdBuffer, 0u);
1889	{
1890		// change color image layout
1891		const VkImageMemoryBarrier initialImageBarrier = makeImageMemoryBarrier(
1892			0,													// VkAccessFlags					srcAccessMask;
1893			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,				// VkAccessFlags					dstAccessMask;
1894			VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout					oldLayout;
1895			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					newLayout;
1896			**m_colorImage,										// VkImage							image;
1897			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }		// VkImageSubresourceRange			subresourceRange;
1898		);
1899		vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (VkDependencyFlags)0, 0, DE_NULL, 0, DE_NULL, 1, &initialImageBarrier);
1900
1901		// wait for uniform buffers
1902		std::vector<VkBufferMemoryBarrier> initialBufferBarriers(3u, makeBufferMemoryBarrier(
1903			VK_ACCESS_HOST_WRITE_BIT,							// VkAccessFlags2KHR				srcAccessMask
1904			VK_ACCESS_UNIFORM_READ_BIT,							// VkAccessFlags2KHR				dstAccessMask
1905			uniformBuffer[0]->get(),							// VkBuffer							buffer
1906			0u,													// VkDeviceSize						offset
1907			uniformBufferDataSize								// VkDeviceSize						size
1908		));
1909		initialBufferBarriers[1].buffer = uniformBuffer[1]->get();
1910		initialBufferBarriers[2].buffer = uniformBuffer[2]->get();
1911		vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, (VkDependencyFlags)0, 0, DE_NULL, 3, initialBufferBarriers.data(), 0, DE_NULL);
1912
1913		beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, m_renderArea, m_colorClearColor);
1914
1915		vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1916		vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *allLayouts, 0u, 3u, allDescriptorSets, 0u, DE_NULL);
1917		vk.cmdDraw(*m_cmdBuffer, 4, 1u, 0u, 0u);
1918
1919		endRenderPass(vk, *m_cmdBuffer);
1920
1921		const tcu::IVec2 size{ (deInt32)m_renderArea.extent.width, (deInt32)m_renderArea.extent.height };
1922		copyImageToBuffer(vk, *m_cmdBuffer, **m_colorImage, *colorBuffer, size);
1923	}
1924	vk::endCommandBuffer(vk, *m_cmdBuffer);
1925	vk::submitCommandsAndWait(vk, device, m_context.getUniversalQueue(), *m_cmdBuffer);
1926
1927	vk::invalidateAlloc(vk, device, colorBuffer.getAllocation());
1928	const tcu::ConstPixelBufferAccess colorPixelAccess(mapVkFormat(m_colorFormat), m_renderArea.extent.width, m_renderArea.extent.height, 1, colorBuffer.getAllocation().getHostPtr());
1929
1930	// verify result
1931	deInt32 width	= (deInt32)m_renderArea.extent.width;
1932	deInt32 height	= (deInt32)m_renderArea.extent.height;
1933	const std::vector<VerificationData> verificationData
1934	{
1935		{ { 1, 1 },						{ 0, 191, 127, 51 } },		// note COLOR_COMPONENTS_NO_RED is used
1936		{ { width / 2, height / 2 },	{ 0, 191, 127, 51 } },
1937		{ { width - 2, height - 2 },	{ 0, 0, 0, 255 } }			// clear color
1938	};
1939	return verifyResult(verificationData, colorPixelAccess);
1940}
1941
1942tcu::TestStatus PipelineLibraryMiscTestInstance::runCompareLinkTimes (void)
1943{
1944	const deUint32				uniqueLibrariesCount	= 2u;
1945	const deUint32				pipelinesCount			= 4u * uniqueLibrariesCount;
1946
1947	const DeviceInterface&		vk						= m_context.getDeviceInterface();
1948	const VkDevice				device					= m_context.getDevice();
1949	tcu::TestLog&				log						= m_context.getTestContext().getLog();
1950	bool						allChecksPassed			= true;
1951	VkPipelineLayoutCreateInfo	pipelineLayoutParams	= initVulkanStructure();
1952	Move<VkPipelineLayout>		layout					= createPipelineLayout(vk, device, &pipelineLayoutParams);
1953
1954	GraphicsPipelineCreateInfo partialPipelineCreateInfo[]
1955	{
1956		{ *layout, *m_renderPass, 0, VK_PIPELINE_CREATE_LIBRARY_BIT_KHR },
1957		{ *layout, *m_renderPass, 0, VK_PIPELINE_CREATE_LIBRARY_BIT_KHR },
1958		{ *layout, *m_renderPass, 0, VK_PIPELINE_CREATE_LIBRARY_BIT_KHR },
1959		{ *layout, *m_renderPass, 0, VK_PIPELINE_CREATE_LIBRARY_BIT_KHR },
1960		{ *layout, *m_renderPass, 0, VK_PIPELINE_CREATE_LIBRARY_BIT_KHR },
1961		{ *layout, *m_renderPass, 0, VK_PIPELINE_CREATE_LIBRARY_BIT_KHR },
1962		{ *layout, *m_renderPass, 0, VK_PIPELINE_CREATE_LIBRARY_BIT_KHR },
1963		{ *layout, *m_renderPass, 0, VK_PIPELINE_CREATE_LIBRARY_BIT_KHR },
1964	};
1965
1966	de::Random rnd(static_cast<deUint32>(deGetMicroseconds()));
1967
1968	const uint32_t vertexRandSpecConsts[]	= { rnd.getUint32() * 2, rnd.getUint32() * 2 };
1969	const uint32_t fragmentRandSpecConsts[] = { rnd.getUint32() * 2, rnd.getUint32() * 2 };
1970
1971	const VkSpecializationMapEntry entry =
1972	{
1973		0,					// uint32_t	constantID;
1974		0,					// uint32_t	offset;
1975		sizeof(int32_t)		// size_t	size;
1976	};
1977
1978	const VkSpecializationInfo vertexSpecializationInfos[] =
1979	{
1980		{
1981			1u,							// uint32_t							mapEntryCount;
1982			&entry,						// const VkSpecializationMapEntry*	pMapEntries;
1983			sizeof(int32_t),			// size_t							dataSize;
1984			&vertexRandSpecConsts[0]	// const void*						pData;
1985		},
1986		{
1987			1u,							// uint32_t							mapEntryCount;
1988			&entry,						// const VkSpecializationMapEntry*	pMapEntries;
1989			sizeof(int32_t),			// size_t							dataSize;
1990			&vertexRandSpecConsts[1]	// const void*						pData;
1991		}
1992	};
1993
1994	const VkSpecializationInfo fragmentSpecializationInfos[] =
1995	{
1996		{
1997			1u,							// uint32_t							mapEntryCount;
1998			&entry,						// const VkSpecializationMapEntry*	pMapEntries;
1999			sizeof(int32_t),			// size_t							dataSize;
2000			&fragmentRandSpecConsts[0]	// const void*						pData;
2001		},
2002		{
2003			1u,							// uint32_t							mapEntryCount;
2004			&entry,						// const VkSpecializationMapEntry*	pMapEntries;
2005			sizeof(int32_t),			// size_t							dataSize;
2006			&fragmentRandSpecConsts[1]	// const void*						pData;
2007		}
2008	};
2009
2010	// fill proper portion of pipeline state - this cant be easily done in a scalable loop
2011	updateVertexInputInterface		(m_context, partialPipelineCreateInfo[0], VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
2012	updateVertexInputInterface		(m_context, partialPipelineCreateInfo[1], VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
2013	updatePreRasterization			(m_context, partialPipelineCreateInfo[2], false, VK_POLYGON_MODE_FILL, &vertexSpecializationInfos[0]);
2014	updatePreRasterization			(m_context, partialPipelineCreateInfo[3], false, VK_POLYGON_MODE_LINE, &vertexSpecializationInfos[1]);
2015	updatePostRasterization			(m_context, partialPipelineCreateInfo[4], false, true,	&fragmentSpecializationInfos[0]);
2016	updatePostRasterization			(m_context, partialPipelineCreateInfo[5], false, false, &fragmentSpecializationInfos[1]);
2017	updateFragmentOutputInterface	(m_context, partialPipelineCreateInfo[6], 0xf);
2018	updateFragmentOutputInterface	(m_context, partialPipelineCreateInfo[7]);
2019
2020	// construct all pipeline parts and mesure time it took
2021	struct PipelinePartData
2022	{
2023		Move<VkPipeline>							pipelineHandle;
2024		std::chrono::duration<deInt64, std::nano>	creationDuration;
2025	};
2026	std::vector<PipelinePartData> pipelinePartData(pipelinesCount);
2027	VkGraphicsPipelineLibraryCreateInfoEXT libraryCreateInfo = makeGraphicsPipelineLibraryCreateInfo(VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT);
2028	for (deUint32 i = 0; i < pipelinesCount; ++i)
2029	{
2030		appendStructurePtrToVulkanChain(&partialPipelineCreateInfo[i].pNext, &libraryCreateInfo);
2031		libraryCreateInfo.flags = GRAPHICS_PIPELINE_LIBRARY_FLAGS[i / 2];
2032
2033		auto&	partData	= pipelinePartData[i];
2034		auto	timeStart	= std::chrono::high_resolution_clock::now();
2035		partData.pipelineHandle		= createGraphicsPipeline(vk, device, DE_NULL, partialPipelineCreateInfo + i);
2036		partData.creationDuration	= std::chrono::high_resolution_clock::now() - timeStart;
2037	}
2038
2039	// iterate over all combinations of parts
2040	for (deUint32 i = 0u ; i < (deUint32)dePow(4, uniqueLibrariesCount) ; ++i)
2041	{
2042		// select new unique combination of parts
2043		deUint32 vertexInputIndex		= (i    ) % 2;
2044		deUint32 preRasterizationIndex	= (i / 2) % 2;
2045		deUint32 fragmentStateIndex		= (i / 4) % 2;
2046		deUint32 fragmentOutputIndex	= (i / 8) % 2;
2047
2048		const auto& vertexInputData			= pipelinePartData[                           vertexInputIndex];
2049		const auto& preRasterizationData	= pipelinePartData[    uniqueLibrariesCount + preRasterizationIndex];
2050		const auto& fragmentStateData		= pipelinePartData[2 * uniqueLibrariesCount + fragmentStateIndex];
2051		const auto& fragmentOutputData		= pipelinePartData[3 * uniqueLibrariesCount + fragmentOutputIndex];
2052
2053		std::vector<VkPipeline> pipelinesToLink
2054		{
2055			*vertexInputData.pipelineHandle,
2056			*preRasterizationData.pipelineHandle,
2057			*fragmentStateData.pipelineHandle,
2058			*fragmentOutputData.pipelineHandle,
2059		};
2060
2061		VkPipelineLibraryCreateInfoKHR	linkingInfo			= makePipelineLibraryCreateInfo(pipelinesToLink);
2062		VkGraphicsPipelineCreateInfo	finalPipelineInfo	= initVulkanStructure();
2063		finalPipelineInfo.layout = *layout;
2064
2065		appendStructurePtrToVulkanChain(&finalPipelineInfo.pNext, &linkingInfo);
2066
2067		// link pipeline without the optimised bit, and record the time taken to link it
2068		auto				timeStart		= std::chrono::high_resolution_clock::now();
2069		Move<VkPipeline>	pipeline		= createGraphicsPipeline(vk, device, DE_NULL, &finalPipelineInfo);
2070		const auto			linkingTime		= std::chrono::high_resolution_clock::now() - timeStart;
2071		const auto			creationTime	= preRasterizationData.creationDuration + fragmentStateData.creationDuration;
2072
2073		if (linkingTime > (10 * creationTime))
2074		{
2075			allChecksPassed = false;
2076			log << tcu::TestLog::Message
2077				<< "Liking time (" << linkingTime.count() << ") of combination " << i
2078				<< " is more then ten times greater than creation of both pre-rasterization and fragment states (" << creationTime.count() << ")"
2079				<< tcu::TestLog::EndMessage;
2080		}
2081	}
2082
2083	if (allChecksPassed)
2084		return tcu::TestStatus::pass("Pass");
2085
2086	return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Liking of one or more combinations took to long");
2087}
2088
2089tcu::TestStatus PipelineLibraryMiscTestInstance::verifyResult(const std::vector<VerificationData>& verificationData, const tcu::ConstPixelBufferAccess& colorPixelAccess) const
2090{
2091	const deInt32 epsilon = 1;
2092	for (const auto& v : verificationData)
2093	{
2094		const IVec4	pixel = colorPixelAccess.getPixelInt(v.point.x(), v.point.y());
2095		const IVec4	diff = pixel - v.color;
2096		for (deUint32 compNdx = 0; compNdx < 4u; ++compNdx)
2097		{
2098			if (de::abs(diff[compNdx]) > epsilon)
2099			{
2100				const Vec4 pixelBias(0.0f);
2101				const Vec4 pixelScale(1.0f);
2102
2103				m_context.getTestContext().getLog()
2104					<< TestLog::Image("Result", "Result", colorPixelAccess, pixelScale, pixelBias)
2105					<< tcu::TestLog::Message
2106					<< "For texel " << v.point << " expected color "
2107					<< v.color << " got: " << pixel
2108					<< tcu::TestLog::EndMessage;
2109
2110				return tcu::TestStatus::fail("Fail");
2111			}
2112		}
2113	}
2114
2115	return tcu::TestStatus::pass("Pass");
2116}
2117
2118class PipelineLibraryShaderModuleInfoInstance : public TestInstance
2119{
2120public:
2121					PipelineLibraryShaderModuleInfoInstance		(Context& context)
2122						: TestInstance	(context)
2123						, m_vkd			(m_context.getDeviceInterface())
2124						, m_device		(m_context.getDevice())
2125						, m_alloc		(m_context.getDefaultAllocator())
2126						, m_queueIndex	(m_context.getUniversalQueueFamilyIndex())
2127						, m_queue		(m_context.getUniversalQueue())
2128						, m_outVector	(kOutputBufferElements, std::numeric_limits<uint32_t>::max())
2129						, m_cmdBuffer	(DE_NULL)
2130						{}
2131	virtual			~PipelineLibraryShaderModuleInfoInstance	(void) {}
2132
2133	static constexpr size_t kOutputBufferElements = 64u;
2134
2135protected:
2136	void			prepareOutputBuffer							(VkShaderStageFlags stages);
2137	void			allocateCmdBuffers							(void);
2138	void			addModule									(const std::string& moduleName, VkShaderStageFlagBits stage);
2139	void			recordShaderToHostBarrier					(VkPipelineStageFlagBits pipelineStage) const;
2140	void			verifyOutputBuffer							(void);
2141
2142	using BufferWithMemoryPtr = de::MovePtr<BufferWithMemory>;
2143
2144	// From the context.
2145	const DeviceInterface&		m_vkd;
2146	const VkDevice				m_device;
2147	Allocator&					m_alloc;
2148	const uint32_t				m_queueIndex;
2149	const VkQueue				m_queue;
2150
2151	Move<VkDescriptorSetLayout>	m_setLayout;
2152	Move<VkDescriptorPool>		m_descriptorPool;
2153	Move<VkDescriptorSet>		m_descriptorSet;
2154	std::vector<uint32_t>		m_outVector;
2155	BufferWithMemoryPtr			m_outputBuffer;
2156
2157	Move<VkCommandPool>			m_cmdPool;
2158	Move<VkCommandBuffer>		m_cmdBufferPtr;
2159	VkCommandBuffer				m_cmdBuffer;
2160
2161	std::vector<VkPipelineShaderStageCreateInfo>	m_pipelineStageInfos;
2162	std::vector<VkShaderModuleCreateInfo>			m_shaderModuleInfos;
2163};
2164
2165void PipelineLibraryShaderModuleInfoInstance::prepareOutputBuffer (VkShaderStageFlags stages)
2166{
2167	const auto	descriptorType	= VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
2168	const auto	poolFlags		= VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
2169
2170	// Create set layout.
2171	DescriptorSetLayoutBuilder layoutBuilder;
2172	layoutBuilder.addSingleBinding(descriptorType, stages);
2173	m_setLayout = layoutBuilder.build(m_vkd, m_device);
2174
2175	// Create pool and set.
2176	DescriptorPoolBuilder poolBuilder;
2177	poolBuilder.addType(descriptorType);
2178	m_descriptorPool	= poolBuilder.build(m_vkd, m_device, poolFlags, 1u);
2179	m_descriptorSet		= makeDescriptorSet(m_vkd, m_device, m_descriptorPool.get(), m_setLayout.get());
2180
2181	// Create buffer.
2182	const auto outputBufferSize			= static_cast<VkDeviceSize>(de::dataSize(m_outVector));
2183	const auto outputBufferCreateInfo	= makeBufferCreateInfo(outputBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
2184	m_outputBuffer = BufferWithMemoryPtr(new BufferWithMemory(m_vkd, m_device, m_alloc, outputBufferCreateInfo, MemoryRequirement::HostVisible));
2185
2186	// Update set.
2187	const auto outputBufferDescInfo = makeDescriptorBufferInfo(m_outputBuffer->get(), 0ull, outputBufferSize);
2188	DescriptorSetUpdateBuilder updateBuilder;
2189	updateBuilder.writeSingle(m_descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, &outputBufferDescInfo);
2190	updateBuilder.update(m_vkd, m_device);
2191}
2192
2193void PipelineLibraryShaderModuleInfoInstance::addModule (const std::string& moduleName, VkShaderStageFlagBits stage)
2194{
2195	const auto& binary = m_context.getBinaryCollection().get(moduleName);
2196
2197	const VkShaderModuleCreateInfo modInfo =
2198	{
2199		VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,			//	VkStructureType				sType;
2200		nullptr,												//	const void*					pNext;
2201		0u,														//	VkShaderModuleCreateFlags	flags;
2202		binary.getSize(),										//	size_t						codeSize;
2203		reinterpret_cast<const uint32_t*>(binary.getBinary()),	//	const uint32_t*				pCode;
2204	};
2205	m_shaderModuleInfos.push_back(modInfo);
2206
2207	// Note: the pNext pointer will be updated below.
2208	const VkPipelineShaderStageCreateInfo stageInfo =
2209	{
2210		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	//	VkStructureType						sType;
2211		nullptr,												//	const void*							pNext;
2212		0u,														//	VkPipelineShaderStageCreateFlags	flags;
2213		stage,													//	VkShaderStageFlagBits				stage;
2214		DE_NULL,												//	VkShaderModule						module;
2215		"main",													//	const char*							pName;
2216		nullptr,												//	const VkSpecializationInfo*			pSpecializationInfo;
2217	};
2218	m_pipelineStageInfos.push_back(stageInfo);
2219
2220	DE_ASSERT(m_shaderModuleInfos.size() == m_pipelineStageInfos.size());
2221
2222	// Update pNext pointers after possible reallocation.
2223	for (size_t i = 0u; i < m_shaderModuleInfos.size(); ++i)
2224		m_pipelineStageInfos[i].pNext = &(m_shaderModuleInfos[i]);
2225}
2226
2227void PipelineLibraryShaderModuleInfoInstance::recordShaderToHostBarrier (VkPipelineStageFlagBits pipelineStage) const
2228{
2229	const auto postWriteBarrier = makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
2230	cmdPipelineMemoryBarrier(m_vkd, m_cmdBuffer, pipelineStage, VK_PIPELINE_STAGE_HOST_BIT, &postWriteBarrier);
2231}
2232
2233void PipelineLibraryShaderModuleInfoInstance::verifyOutputBuffer (void)
2234{
2235	auto& allocation	= m_outputBuffer->getAllocation();
2236
2237	invalidateAlloc(m_vkd, m_device, allocation);
2238	deMemcpy(m_outVector.data(), allocation.getHostPtr(), de::dataSize(m_outVector));
2239
2240	for (uint32_t i = 0; i < static_cast<uint32_t>(m_outVector.size()); ++i)
2241	{
2242		if (m_outVector[i] != i)
2243		{
2244			std::ostringstream msg;
2245			msg << "Unexpected value found at position " << i << ": " << m_outVector[i];
2246			TCU_FAIL(msg.str());
2247		}
2248	}
2249}
2250
2251void PipelineLibraryShaderModuleInfoInstance::allocateCmdBuffers (void)
2252{
2253	m_cmdPool		= makeCommandPool(m_vkd, m_device, m_queueIndex);
2254	m_cmdBufferPtr	= allocateCommandBuffer(m_vkd, m_device, m_cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2255	m_cmdBuffer		= m_cmdBufferPtr.get();
2256}
2257
2258class PipelineLibraryShaderModuleInfoCompInstance : public PipelineLibraryShaderModuleInfoInstance
2259{
2260public:
2261					PipelineLibraryShaderModuleInfoCompInstance		(Context& context)
2262						: PipelineLibraryShaderModuleInfoInstance(context)
2263						{}
2264	virtual			~PipelineLibraryShaderModuleInfoCompInstance	(void) {}
2265
2266	tcu::TestStatus	iterate											(void) override;
2267};
2268
2269tcu::TestStatus	PipelineLibraryShaderModuleInfoCompInstance::iterate (void)
2270{
2271	const auto stage		= VK_SHADER_STAGE_COMPUTE_BIT;
2272	const auto bindPoint	= VK_PIPELINE_BIND_POINT_COMPUTE;
2273
2274	prepareOutputBuffer(stage);
2275	addModule("comp", stage);
2276	allocateCmdBuffers();
2277
2278	const auto pipelineLayout = makePipelineLayout(m_vkd, m_device, m_setLayout.get());
2279
2280	const VkComputePipelineCreateInfo pipelineCreateInfo =
2281	{
2282		VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,	//	VkStructureType					sType;
2283		nullptr,										//	const void*						pNext;
2284		0u,												//	VkPipelineCreateFlags			flags;
2285		m_pipelineStageInfos.at(0u),					//	VkPipelineShaderStageCreateInfo	stage;
2286		pipelineLayout.get(),							//	VkPipelineLayout				layout;
2287		DE_NULL,										//	VkPipeline						basePipelineHandle;
2288		0,												//	int32_t							basePipelineIndex;
2289	};
2290
2291	const auto pipeline = createComputePipeline(m_vkd, m_device, DE_NULL, &pipelineCreateInfo);
2292
2293	beginCommandBuffer(m_vkd, m_cmdBuffer);
2294	m_vkd.cmdBindDescriptorSets(m_cmdBuffer, bindPoint, pipelineLayout.get(), 0u, 1u, &m_descriptorSet.get(), 0u, nullptr);
2295	m_vkd.cmdBindPipeline(m_cmdBuffer, bindPoint, pipeline.get());
2296	m_vkd.cmdDispatch(m_cmdBuffer, 1u, 1u, 1u);
2297	recordShaderToHostBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
2298	endCommandBuffer(m_vkd, m_cmdBuffer);
2299	submitCommandsAndWait(m_vkd, m_device, m_queue, m_cmdBuffer);
2300	verifyOutputBuffer();
2301
2302	return tcu::TestStatus::pass("Pass");
2303}
2304
2305class PipelineLibraryShaderModuleInfoRTInstance : public PipelineLibraryShaderModuleInfoInstance
2306{
2307public:
2308					PipelineLibraryShaderModuleInfoRTInstance		(Context& context, bool withLibrary)
2309						: PipelineLibraryShaderModuleInfoInstance	(context)
2310						, m_withLibrary								(withLibrary)
2311						{}
2312	virtual			~PipelineLibraryShaderModuleInfoRTInstance		(void) {}
2313
2314	tcu::TestStatus	iterate											(void) override;
2315
2316protected:
2317	bool m_withLibrary;
2318};
2319
2320tcu::TestStatus	PipelineLibraryShaderModuleInfoRTInstance::iterate (void)
2321{
2322	const auto stage		= VK_SHADER_STAGE_RAYGEN_BIT_KHR;
2323	const auto bindPoint	= VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR;
2324
2325	prepareOutputBuffer(stage);
2326	addModule("rgen", stage);
2327	allocateCmdBuffers();
2328
2329	const auto pipelineLayout = makePipelineLayout(m_vkd, m_device, m_setLayout.get());
2330
2331	const VkRayTracingShaderGroupCreateInfoKHR shaderGroupInfo =
2332	{
2333		VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR,	//	VkStructureType					sType;
2334		nullptr,													//	const void*						pNext;
2335		VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR,				//	VkRayTracingShaderGroupTypeKHR	type;
2336		0u,															//	uint32_t						generalShader;
2337		VK_SHADER_UNUSED_KHR,										//	uint32_t						closestHitShader;
2338		VK_SHADER_UNUSED_KHR,										//	uint32_t						anyHitShader;
2339		VK_SHADER_UNUSED_KHR,										//	uint32_t						intersectionShader;
2340		nullptr,													//	const void*						pShaderGroupCaptureReplayHandle;
2341	};
2342
2343	const VkPipelineCreateFlags							createFlags		= (m_withLibrary ? static_cast<VkPipelineCreateFlags>(VK_PIPELINE_CREATE_LIBRARY_BIT_KHR) : 0u);
2344	const VkRayTracingPipelineInterfaceCreateInfoKHR	libIfaceInfo	= initVulkanStructure();
2345	const VkRayTracingPipelineInterfaceCreateInfoKHR*	pLibraryIface	= (m_withLibrary ? &libIfaceInfo : nullptr);
2346
2347	const VkRayTracingPipelineCreateInfoKHR pipelineCreateInfo =
2348	{
2349		VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR,	//	VkStructureType										sType;
2350		nullptr,												//	const void*											pNext;
2351		createFlags,											//	VkPipelineCreateFlags								flags;
2352		de::sizeU32(m_pipelineStageInfos),						//	uint32_t											stageCount;
2353		de::dataOrNull(m_pipelineStageInfos),					//	const VkPipelineShaderStageCreateInfo*				pStages;
2354		1u,														//	uint32_t											groupCount;
2355		&shaderGroupInfo,										//	const VkRayTracingShaderGroupCreateInfoKHR*			pGroups;
2356		1u,														//	uint32_t											maxPipelineRayRecursionDepth;
2357		nullptr,												//	const VkPipelineLibraryCreateInfoKHR*				pLibraryInfo;
2358		pLibraryIface,											//	const VkRayTracingPipelineInterfaceCreateInfoKHR*	pLibraryInterface;
2359		nullptr,												//	const VkPipelineDynamicStateCreateInfo*				pDynamicState;
2360		pipelineLayout.get(),									//	VkPipelineLayout									layout;
2361		DE_NULL,												//	VkPipeline											basePipelineHandle;
2362		0,														//	int32_t												basePipelineIndex;
2363	};
2364
2365	Move<VkPipeline> pipelineLib;
2366	Move<VkPipeline> pipeline;
2367
2368	if (m_withLibrary)
2369	{
2370		pipelineLib = createRayTracingPipelineKHR(m_vkd, m_device, DE_NULL, DE_NULL, &pipelineCreateInfo);
2371
2372		const VkPipelineLibraryCreateInfoKHR libraryInfo =
2373		{
2374			VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR,	//	VkStructureType		sType;
2375			nullptr,											//	const void*			pNext;
2376			1u,													//	uint32_t			libraryCount;
2377			&pipelineLib.get(),									//	const VkPipeline*	pLibraries;
2378		};
2379
2380		const VkRayTracingPipelineCreateInfoKHR nonLibCreateInfo =
2381		{
2382			VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR,	//	VkStructureType										sType;
2383			nullptr,												//	const void*											pNext;
2384			0u,														//	VkPipelineCreateFlags								flags;
2385			0u,														//	uint32_t											stageCount;
2386			nullptr,												//	const VkPipelineShaderStageCreateInfo*				pStages;
2387			0u,														//	uint32_t											groupCount;
2388			nullptr,												//	const VkRayTracingShaderGroupCreateInfoKHR*			pGroups;
2389			1u,														//	uint32_t											maxPipelineRayRecursionDepth;
2390			&libraryInfo,											//	const VkPipelineLibraryCreateInfoKHR*				pLibraryInfo;
2391			pLibraryIface,											//	const VkRayTracingPipelineInterfaceCreateInfoKHR*	pLibraryInterface;
2392			nullptr,												//	const VkPipelineDynamicStateCreateInfo*				pDynamicState;
2393			pipelineLayout.get(),									//	VkPipelineLayout									layout;
2394			DE_NULL,												//	VkPipeline											basePipelineHandle;
2395			0,														//	int32_t												basePipelineIndex;
2396		};
2397		pipeline = createRayTracingPipelineKHR(m_vkd, m_device, DE_NULL, DE_NULL, &nonLibCreateInfo);
2398	}
2399	else
2400	{
2401		pipeline = createRayTracingPipelineKHR(m_vkd, m_device, DE_NULL, DE_NULL, &pipelineCreateInfo);
2402	}
2403
2404	// Make shader binding table.
2405	const auto			rtProperties	= makeRayTracingProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice());
2406	const auto			rtHandleSize	= rtProperties->getShaderGroupHandleSize();
2407	const auto			sbtSize			= static_cast<VkDeviceSize>(rtHandleSize);
2408	const auto			sbtMemReqs		= (MemoryRequirement::HostVisible | MemoryRequirement::DeviceAddress);
2409	const auto			sbtCreateInfo	= makeBufferCreateInfo(sbtSize, VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
2410	BufferWithMemoryPtr	sbt				= BufferWithMemoryPtr(new BufferWithMemory(m_vkd, m_device, m_alloc, sbtCreateInfo, sbtMemReqs));
2411	auto&				sbtAlloc		= sbt->getAllocation();
2412	void*				sbtData			= sbtAlloc.getHostPtr();
2413
2414	// Copy ray gen shader group handle to the start of  the buffer.
2415	VK_CHECK(m_vkd.getRayTracingShaderGroupHandlesKHR(m_device, pipeline.get(), 0u, 1u, static_cast<size_t>(sbtSize), sbtData));
2416	flushAlloc(m_vkd, m_device, sbtAlloc);
2417
2418	// Strided device address regions.
2419	VkStridedDeviceAddressRegionKHR rgenSBTRegion	= makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(m_vkd, m_device, sbt->get(), 0), rtHandleSize, rtHandleSize);
2420	VkStridedDeviceAddressRegionKHR	missSBTRegion	= makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
2421	VkStridedDeviceAddressRegionKHR	hitsSBTRegion	= makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
2422	VkStridedDeviceAddressRegionKHR	callSBTRegion	= makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
2423
2424	beginCommandBuffer(m_vkd, m_cmdBuffer);
2425	m_vkd.cmdBindDescriptorSets(m_cmdBuffer, bindPoint, pipelineLayout.get(), 0u, 1u, &m_descriptorSet.get(), 0u, nullptr);
2426	m_vkd.cmdBindPipeline(m_cmdBuffer, bindPoint, pipeline.get());
2427	m_vkd.cmdTraceRaysKHR(m_cmdBuffer, &rgenSBTRegion, &missSBTRegion, &hitsSBTRegion, &callSBTRegion, kOutputBufferElements, 1u, 1u);
2428	recordShaderToHostBarrier(VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR);
2429	endCommandBuffer(m_vkd, m_cmdBuffer);
2430	submitCommandsAndWait(m_vkd, m_device, m_queue, m_cmdBuffer);
2431	verifyOutputBuffer();
2432
2433	return tcu::TestStatus::pass("Pass");
2434}
2435
2436class NullRenderingCreateInfoInstance : public vkt::TestInstance
2437{
2438public:
2439						NullRenderingCreateInfoInstance		(Context& context)
2440							: vkt::TestInstance(context)
2441							{}
2442	virtual				~NullRenderingCreateInfoInstance	(void) {}
2443
2444	tcu::TestStatus		iterate			(void) override;
2445};
2446
2447tcu::TestStatus NullRenderingCreateInfoInstance::iterate (void)
2448{
2449	const auto			ctx				= m_context.getContextCommonData();
2450	const tcu::IVec3	colorExtent		(1, 1, 1);
2451	const auto			imageExtent		= makeExtent3D(colorExtent);
2452	const auto			colorFormat		= VK_FORMAT_R8G8B8A8_UNORM;
2453	const auto			tcuFormat		= mapVkFormat(colorFormat);
2454	const auto			colorUsage		= (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
2455	const auto			colorSRR		= makeDefaultImageSubresourceRange();
2456	const auto			colorSRL		= makeDefaultImageSubresourceLayers();
2457
2458	// Color buffer and view.
2459	ImageWithBuffer	colorBuffer	(ctx.vkd, ctx.device, ctx.allocator, imageExtent, colorFormat, colorUsage, VK_IMAGE_TYPE_2D);
2460	const auto		colorView	= makeImageView(ctx.vkd, ctx.device, colorBuffer.getImage(), VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSRR);
2461
2462	// Verification buffer.
2463	const auto			verificationBufferSize	= static_cast<VkDeviceSize>(colorExtent.x() * colorExtent.y() * colorExtent.z() * tcu::getPixelSize(tcuFormat));
2464	const auto			verificationBufferInfo	= makeBufferCreateInfo(verificationBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
2465	BufferWithMemory	verificationBuffer		(ctx.vkd, ctx.device, ctx.allocator, verificationBufferInfo, MemoryRequirement::HostVisible);
2466	auto&				verificationBufferAlloc = verificationBuffer.getAllocation();
2467	void*				verificationBufferPtr	= verificationBufferAlloc.getHostPtr();
2468
2469	const auto pipelineLayout = makePipelineLayout(ctx.vkd, ctx.device);
2470
2471	const VkPipelineVertexInputStateCreateInfo	vertexInputStateInfo	= initVulkanStructure();
2472	VkPipelineInputAssemblyStateCreateInfo		inputAssemblyStateInfo	= initVulkanStructure();
2473	inputAssemblyStateInfo.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
2474
2475	const std::vector<VkViewport>	viewports	(1u, makeViewport(imageExtent));
2476	const std::vector<VkRect2D>		scissors	(1u, makeRect2D(imageExtent));
2477
2478	const auto&	binaries	= m_context.getBinaryCollection();
2479	const auto	vertModule	= createShaderModule(ctx.vkd, ctx.device, binaries.get("vert"));
2480	const auto	fragModule	= createShaderModule(ctx.vkd, ctx.device, binaries.get("frag"));
2481
2482	// We will use a null-filled pipeline rendering info structure for all substates except the fragment output state.
2483	VkPipelineRenderingCreateInfo nullRenderingInfo = initVulkanStructure();
2484	nullRenderingInfo.colorAttachmentCount = std::numeric_limits<uint32_t>::max();
2485
2486	VkPipelineRenderingCreateInfo finalRenderingInfo = initVulkanStructure();
2487	finalRenderingInfo.colorAttachmentCount		= 1u;
2488	finalRenderingInfo.pColorAttachmentFormats	= &colorFormat;
2489
2490	const VkPipelineViewportStateCreateInfo viewportStateInfo =
2491	{
2492		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,	//	VkStructureType						sType;
2493		nullptr,												//	const void*							pNext;
2494		0u,														//	VkPipelineViewportStateCreateFlags	flags;
2495		de::sizeU32(viewports),									//	uint32_t							viewportCount;
2496		de::dataOrNull(viewports),								//	const VkViewport*					pViewports;
2497		de::sizeU32(scissors),									//	uint32_t							scissorCount;
2498		de::dataOrNull(scissors),								//	const VkRect2D*						pScissors;
2499	};
2500
2501	const VkPipelineRasterizationStateCreateInfo rasterizationStateInfo =
2502	{
2503		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		//	VkStructureType							sType;
2504		nullptr,														//	const void*								pNext;
2505		0u,																//	VkPipelineRasterizationStateCreateFlags	flags;
2506		VK_FALSE,														//	VkBool32								depthClampEnable;
2507		VK_FALSE,														//	VkBool32								rasterizerDiscardEnable;
2508		VK_POLYGON_MODE_FILL,											//	VkPolygonMode							polygonMode;
2509		VK_CULL_MODE_BACK_BIT,											//	VkCullModeFlags							cullMode;
2510		VK_FRONT_FACE_COUNTER_CLOCKWISE,								//	VkFrontFace								frontFace;
2511		VK_FALSE,														//	VkBool32								depthBiasEnable;
2512		0.0f,															//	float									depthBiasConstantFactor;
2513		0.0f,															//	float									depthBiasClamp;
2514		0.0f,															//	float									depthBiasSlopeFactor;
2515		1.0f,															//	float									lineWidth;
2516	};
2517
2518	const VkPipelineMultisampleStateCreateInfo multisampleStateInfo =
2519	{
2520		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	//	VkStructureType							sType;
2521		nullptr,													//	const void*								pNext;
2522		0u,															//	VkPipelineMultisampleStateCreateFlags	flags;
2523		VK_SAMPLE_COUNT_1_BIT,										//	VkSampleCountFlagBits					rasterizationSamples;
2524		VK_FALSE,													//	VkBool32								sampleShadingEnable;
2525		1.0f,														//	float									minSampleShading;
2526		nullptr,													//	const VkSampleMask*						pSampleMask;
2527		VK_FALSE,													//	VkBool32								alphaToCoverageEnable;
2528		VK_FALSE,													//	VkBool32								alphaToOneEnable;
2529	};
2530
2531	const VkPipelineDepthStencilStateCreateInfo depthStencilStateInfo = initVulkanStructure();
2532
2533	const VkColorComponentFlags colorComponentFlags = (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT);
2534
2535	const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
2536	{
2537		VK_FALSE,				//	VkBool32				blendEnable;
2538		VK_BLEND_FACTOR_ZERO,	//	VkBlendFactor			srcColorBlendFactor;
2539		VK_BLEND_FACTOR_ZERO,	//	VkBlendFactor			dstColorBlendFactor;
2540		VK_BLEND_OP_ADD,		//	VkBlendOp				colorBlendOp;
2541		VK_BLEND_FACTOR_ZERO,	//	VkBlendFactor			srcAlphaBlendFactor;
2542		VK_BLEND_FACTOR_ZERO,	//	VkBlendFactor			dstAlphaBlendFactor;
2543		VK_BLEND_OP_ADD,		//	VkBlendOp				alphaBlendOp;
2544		colorComponentFlags,	//	VkColorComponentFlags	colorWriteMask;
2545	};
2546
2547	const VkPipelineColorBlendStateCreateInfo colorBlendStateInfo =
2548	{
2549		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	//	VkStructureType								sType;
2550		nullptr,													//	const void*									pNext;
2551		0u,															//	VkPipelineColorBlendStateCreateFlags		flags;
2552		VK_FALSE,													//	VkBool32									logicOpEnable;
2553		VK_LOGIC_OP_CLEAR,											//	VkLogicOp									logicOp;
2554		1u,															//	uint32_t									attachmentCount;
2555		&colorBlendAttachmentState,									//	const VkPipelineColorBlendAttachmentState*	pAttachments;
2556		{ 0.0f, 0.0f, 0.0f, 0.0f },									//	float										blendConstants[4];
2557	};
2558
2559	// Build the different pipeline pieces.
2560	Move<VkPipeline> vertexInputLib;
2561	Move<VkPipeline> preRasterShaderLib;
2562	Move<VkPipeline> fragShaderLib;
2563	Move<VkPipeline> fragOutputLib;
2564
2565	const VkPipelineCreateFlags libCreationFlags	= VK_PIPELINE_CREATE_LIBRARY_BIT_KHR;
2566	const VkPipelineCreateFlags linkFlags			= 0u;
2567
2568	// Vertex input state library.
2569	{
2570		VkGraphicsPipelineLibraryCreateInfoEXT vertexInputLibInfo	= initVulkanStructure();
2571		vertexInputLibInfo.flags									|= VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT;
2572
2573		VkGraphicsPipelineCreateInfo vertexInputPipelineInfo	= initVulkanStructure(&vertexInputLibInfo);
2574		vertexInputPipelineInfo.flags							= libCreationFlags;
2575		vertexInputPipelineInfo.pVertexInputState				= &vertexInputStateInfo;
2576		vertexInputPipelineInfo.pInputAssemblyState				= &inputAssemblyStateInfo;
2577
2578		vertexInputLib = createGraphicsPipeline(ctx.vkd, ctx.device, VK_NULL_HANDLE, &vertexInputPipelineInfo);
2579	}
2580
2581	// Pre-rasterization shader state library.
2582	{
2583		VkGraphicsPipelineLibraryCreateInfoEXT preRasterShaderLibInfo	= initVulkanStructure(&nullRenderingInfo); // What we're testing.
2584		preRasterShaderLibInfo.flags									|= VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT;
2585
2586		VkGraphicsPipelineCreateInfo preRasterShaderPipelineInfo	= initVulkanStructure(&preRasterShaderLibInfo);
2587		preRasterShaderPipelineInfo.flags							= libCreationFlags;
2588		preRasterShaderPipelineInfo.layout							= pipelineLayout.get();
2589		preRasterShaderPipelineInfo.pViewportState					= &viewportStateInfo;
2590		preRasterShaderPipelineInfo.pRasterizationState				= &rasterizationStateInfo;
2591
2592		const auto vertShaderInfo = makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_VERTEX_BIT, vertModule.get());
2593		preRasterShaderPipelineInfo.stageCount	= 1u;
2594		preRasterShaderPipelineInfo.pStages		= &vertShaderInfo;
2595
2596		preRasterShaderLib = createGraphicsPipeline(ctx.vkd, ctx.device, DE_NULL, &preRasterShaderPipelineInfo);
2597	}
2598
2599	// Fragment shader stage library.
2600	{
2601		VkGraphicsPipelineLibraryCreateInfoEXT fragShaderLibInfo	= initVulkanStructure(&nullRenderingInfo); // What we're testing.
2602		fragShaderLibInfo.flags										|= VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT;
2603
2604		VkGraphicsPipelineCreateInfo fragShaderPipelineInfo	= initVulkanStructure(&fragShaderLibInfo);
2605		fragShaderPipelineInfo.flags						= libCreationFlags;
2606		fragShaderPipelineInfo.layout						= pipelineLayout.get();
2607		fragShaderPipelineInfo.pMultisampleState			= &multisampleStateInfo;
2608		fragShaderPipelineInfo.pDepthStencilState			= &depthStencilStateInfo;
2609
2610		const auto fragShaderInfo = makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_FRAGMENT_BIT, fragModule.get());
2611		fragShaderPipelineInfo.stageCount	= 1u;
2612		fragShaderPipelineInfo.pStages		= &fragShaderInfo;
2613
2614		fragShaderLib = createGraphicsPipeline(ctx.vkd, ctx.device, DE_NULL, &fragShaderPipelineInfo);
2615	}
2616
2617	// Fragment output library.
2618	{
2619		VkGraphicsPipelineLibraryCreateInfoEXT fragOutputLibInfo	= initVulkanStructure(&finalRenderingInfo); // Good info only in the fragment output substate.
2620		fragOutputLibInfo.flags										|= VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT;
2621
2622		VkGraphicsPipelineCreateInfo fragOutputPipelineInfo	= initVulkanStructure(&fragOutputLibInfo);
2623		fragOutputPipelineInfo.flags						= libCreationFlags;
2624		fragOutputPipelineInfo.pColorBlendState				= &colorBlendStateInfo;
2625		fragOutputPipelineInfo.pMultisampleState			= &multisampleStateInfo;
2626
2627		fragOutputLib = createGraphicsPipeline(ctx.vkd, ctx.device, DE_NULL, &fragOutputPipelineInfo);
2628	}
2629
2630	// Linked pipeline.
2631	const std::vector<VkPipeline> libraryHandles
2632	{
2633		vertexInputLib.get(),
2634		preRasterShaderLib.get(),
2635		fragShaderLib.get(),
2636		fragOutputLib.get(),
2637	};
2638
2639	VkPipelineLibraryCreateInfoKHR linkedPipelineLibraryInfo	= initVulkanStructure();
2640	linkedPipelineLibraryInfo.libraryCount						= de::sizeU32(libraryHandles);
2641	linkedPipelineLibraryInfo.pLibraries						= de::dataOrNull(libraryHandles);
2642
2643	VkGraphicsPipelineCreateInfo linkedPipelineInfo	= initVulkanStructure(&linkedPipelineLibraryInfo);
2644	linkedPipelineInfo.flags						= linkFlags;
2645	linkedPipelineInfo.layout						= pipelineLayout.get();
2646
2647	const auto pipeline = createGraphicsPipeline(ctx.vkd, ctx.device, DE_NULL, &linkedPipelineInfo);
2648
2649	CommandPoolWithBuffer cmd (ctx.vkd, ctx.device, ctx.qfIndex);
2650	const auto cmdBuffer = cmd.cmdBuffer.get();
2651
2652	const auto clearValue = makeClearValueColorF32(0.0f, 0.0f, 0.0f, 1.0f);
2653
2654	beginCommandBuffer(ctx.vkd, cmdBuffer);
2655
2656	const auto preRenderBarrier = makeImageMemoryBarrier(0u, (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
2657														 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
2658														 colorBuffer.getImage(), colorSRR);
2659	cmdPipelineImageMemoryBarrier(ctx.vkd, cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, &preRenderBarrier);
2660
2661	beginRendering(ctx.vkd, cmdBuffer, colorView.get(), scissors.at(0u), clearValue, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
2662	ctx.vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
2663	ctx.vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u);
2664	endRendering(ctx.vkd, cmdBuffer);
2665
2666	const auto color2Transfer = makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
2667													   VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
2668													   colorBuffer.getImage(), colorSRR);
2669	cmdPipelineImageMemoryBarrier(ctx.vkd, cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &color2Transfer);
2670	const auto copyRegion = makeBufferImageCopy(imageExtent, colorSRL);
2671	ctx.vkd.cmdCopyImageToBuffer(cmdBuffer, colorBuffer.getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verificationBuffer.get(), 1u, &copyRegion);
2672
2673	const auto transfer2Host = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
2674	cmdPipelineMemoryBarrier(ctx.vkd, cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, &transfer2Host);
2675
2676	endCommandBuffer(ctx.vkd, cmdBuffer);
2677
2678	submitCommandsAndWait(ctx.vkd, ctx.device, ctx.queue, cmdBuffer);
2679	invalidateAlloc(ctx.vkd, ctx.device, verificationBufferAlloc);
2680
2681	auto&						testLog			= m_context.getTestContext().getLog();
2682	const tcu::Vec4				expectedColor	(0.0f, 0.0f, 1.0f, 1.0f); // Must match frag shader.
2683	const tcu::Vec4				threshold		(0.0f, 0.0f, 0.0f, 0.0f);
2684	tcu::ConstPixelBufferAccess	resultAccess	(tcuFormat, colorExtent, verificationBufferPtr);
2685
2686	if (!tcu::floatThresholdCompare(testLog, "Result", "", expectedColor, resultAccess, threshold, tcu::COMPARE_LOG_ON_ERROR))
2687		return tcu::TestStatus::fail("Unexpected color buffer contents -- check log for details");
2688
2689	return tcu::TestStatus::pass("Pass");
2690}
2691
2692class PipelineLibraryMiscTestCase : public TestCase
2693{
2694public:
2695	PipelineLibraryMiscTestCase			(tcu::TestContext& context, const char* name, const MiscTestParams data);
2696	~PipelineLibraryMiscTestCase		(void) = default;
2697
2698	void			checkSupport		(Context& context) const;
2699	void			initPrograms		(SourceCollections& programCollection) const;
2700	TestInstance*	createInstance		(Context& context) const;
2701
2702private:
2703	MiscTestParams		m_testParams;
2704};
2705
2706PipelineLibraryMiscTestCase::PipelineLibraryMiscTestCase(tcu::TestContext& context, const char* name, const MiscTestParams params)
2707	: TestCase			(context, name)
2708	, m_testParams		(params)
2709{
2710}
2711
2712void PipelineLibraryMiscTestCase::checkSupport(Context& context) const
2713{
2714	context.requireDeviceFunctionality("VK_EXT_graphics_pipeline_library");
2715
2716	if ((m_testParams.mode == MiscTestMode::INDEPENDENT_PIPELINE_LAYOUT_SETS_FAST_LINKED) &&
2717		!context.getGraphicsPipelineLibraryPropertiesEXT().graphicsPipelineLibraryFastLinking)
2718		TCU_THROW(NotSupportedError, "graphicsPipelineLibraryFastLinking is not supported");
2719
2720	if (m_testParams.mode == MiscTestMode::SHADER_MODULE_CREATE_INFO_RT || m_testParams.mode == MiscTestMode::SHADER_MODULE_CREATE_INFO_RT_LIB)
2721		context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
2722
2723	if (m_testParams.mode == MiscTestMode::SHADER_MODULE_CREATE_INFO_RT_LIB)
2724		context.requireDeviceFunctionality("VK_KHR_pipeline_library");
2725
2726	if (m_testParams.mode == MiscTestMode::NULL_RENDERING_CREATE_INFO)
2727		context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
2728}
2729
2730void PipelineLibraryMiscTestCase::initPrograms(SourceCollections& programCollection) const
2731{
2732	if ((m_testParams.mode == MiscTestMode::BIND_NULL_DESCRIPTOR_SET) ||
2733		(m_testParams.mode == MiscTestMode::BIND_NULL_DESCRIPTOR_SET_IN_MONOLITHIC_PIPELINE))
2734	{
2735		std::string vertDefinition	= "";
2736		std::string fragDefinition	= "";
2737		std::string vertValue		= "  vec4 v = vec4(-1.0, 1.0, 2.0, -2.0);\n";
2738		std::string fragValue		= "  vec4 v = vec4(0.0, 0.2, 0.6, 0.75);\n";
2739
2740		// define lambda that creates proper uniform buffer definition
2741		auto constructBufferDefinition = [](deUint32 setIndex)
2742		{
2743			return std::string("layout(set = ") + std::to_string(setIndex) + ", binding = 0) uniform buf\n"
2744				"{\n"
2745				"  vec4 v;\n"
2746				"};\n\n";
2747		};
2748
2749		if (m_testParams.mode == MiscTestMode::BIND_NULL_DESCRIPTOR_SET_IN_MONOLITHIC_PIPELINE)
2750		{
2751			// descriptor set 0 will be DE_NULL, descriptor set 1 will be valid buffer with color
2752			fragDefinition	= constructBufferDefinition(1);
2753			fragValue		= "";
2754		}
2755		else if (m_testParams.layoutsBits > 0u)
2756		{
2757			std::vector<deUint32>	bitsThatAreSet;
2758			const deUint32			maxBitsCount	= 8 * sizeof(m_testParams.layoutsBits);
2759
2760			// find set bits
2761			for (deUint32 i = 0u; i < m_testParams.layoutsCount; ++i)
2762			{
2763				if (m_testParams.layoutsBits & (1 << (maxBitsCount - 1 - i)))
2764					bitsThatAreSet.push_back(i);
2765			}
2766
2767			// there should be 1 or 2 bits set
2768			DE_ASSERT((bitsThatAreSet.size() > 0) && (bitsThatAreSet.size() < 3));
2769
2770			vertDefinition	= constructBufferDefinition(bitsThatAreSet[0]);
2771			vertValue		= "";
2772
2773			if (bitsThatAreSet.size() == 2u)
2774			{
2775				fragDefinition	= constructBufferDefinition(bitsThatAreSet[1]);
2776				fragValue		= "";
2777			}
2778		}
2779
2780		programCollection.glslSources.add("vert") << glu::VertexSource(
2781			std::string("#version 450\n"
2782			"precision mediump int;\nprecision highp float;\n") +
2783			vertDefinition +
2784			"out gl_PerVertex\n"
2785			"{\n"
2786			"  vec4 gl_Position;\n"
2787			"};\n\n"
2788			"void main()\n"
2789			"{\n" +
2790			vertValue +
2791			"  const float x = (v.x+v.z*((gl_VertexIndex & 2)>>1));\n"
2792			"  const float y = (v.y+v.w* (gl_VertexIndex % 2));\n"
2793
2794			// note: there won't be full screen quad because of used scissors
2795			"  gl_Position = vec4(x, y, 0.0, 1.0);\n"
2796			"}\n");
2797
2798		programCollection.glslSources.add("frag") << glu::FragmentSource(
2799			std::string("#version 450\n"
2800			"precision mediump int; precision highp float;"
2801			"layout(location = 0) out highp vec4 o_color;\n") +
2802			fragDefinition +
2803			"void main()\n"
2804			"{\n" +
2805			fragValue +
2806			"  o_color = v;\n"
2807			"}\n");
2808	}
2809	else if ((m_testParams.mode == MiscTestMode::INDEPENDENT_PIPELINE_LAYOUT_SETS_FAST_LINKED) ||
2810			 (m_testParams.mode == MiscTestMode::INDEPENDENT_PIPELINE_LAYOUT_SETS_WITH_LINK_TIME_OPTIMIZATION_UNION_HANDLE))
2811	{
2812		programCollection.glslSources.add("vert") << glu::VertexSource(
2813			"#version 450\n"
2814			"precision mediump int; precision highp float;\n"
2815			"layout(set = 0, binding = 0) uniform bufA\n"
2816			"{\n"
2817			"  vec4 valueA;\n"
2818			"};\n"
2819			"layout(set = 2, binding = 0) uniform bufC\n"
2820			"{\n"
2821			"  vec4 valueC;\n"
2822			"};\n"
2823			"out gl_PerVertex\n"
2824			"{\n"
2825			"  vec4 gl_Position;\n"
2826			"};\n\n"
2827			"void main()\n"
2828			"{\n"
2829			// note: values in buffers were set to get vec4(-1, 1, 2, -2)
2830			"  const vec4  v = valueA + valueC;\n"
2831			"  const float x = (v.x+v.z*((gl_VertexIndex & 2)>>1));\n"
2832			"  const float y = (v.y+v.w* (gl_VertexIndex % 2));\n"
2833
2834			// note: there won't be full screen quad because of used scissors
2835			"  gl_Position = vec4(x, y, 0.0, 1.0);\n"
2836			"}\n");
2837
2838		programCollection.glslSources.add("frag") << glu::FragmentSource(
2839			"#version 450\n"
2840			"precision mediump int; precision highp float;"
2841			"layout(location = 0) out highp vec4 o_color;\n"
2842			"layout(set = 0, binding = 0) uniform bufA\n"
2843			"{\n"
2844			"  vec4 valueA;\n"
2845			"};\n"
2846			"layout(set = 1, binding = 0) uniform bufB\n"
2847			"{\n"
2848			"  vec4 valueB;\n"
2849			"};\n"
2850			"void main()\n"
2851			"{\n"
2852			// note: values in buffers were set to get vec4(0.0, 0.75, 0.5, 0.2)
2853			"  o_color = valueA * valueB;\n"
2854			"}\n");
2855	}
2856	else if (m_testParams.mode == MiscTestMode::COMPARE_LINK_TIMES)
2857	{
2858		programCollection.glslSources.add("vert") << glu::VertexSource(
2859			"#version 450\n"
2860			"precision mediump int; precision highp float;"
2861			"layout(location = 0) in vec4 in_position;\n"
2862			"out gl_PerVertex\n"
2863			"{\n"
2864			"  vec4 gl_Position;\n"
2865			"};\n"
2866			"layout(constant_id = 0) const int random = 0;\n\n"
2867			"void main()\n"
2868			"{\n"
2869			"   gl_Position = vec4(float(1 - 2 * int(gl_VertexIndex != 1)),\n"
2870			"                      float(1 - 2 * int(gl_VertexIndex > 0)), 0.0, 1.0) + float(random & 1);\n"
2871			"}\n");
2872
2873		programCollection.glslSources.add("frag") << glu::FragmentSource(
2874			"#version 450\n"
2875			"precision mediump int; precision highp float;"
2876			"layout(location = 0) out highp vec4 o_color;\n"
2877			"layout(constant_id = 0) const int random = 0;\n\n"
2878			"void main()\n"
2879			"{\n"
2880			"  o_color = vec4(0.0, 1.0, 0.5, 1.0) + float(random & 1);\n"
2881			"}\n");
2882	}
2883	else if (m_testParams.mode == MiscTestMode::SHADER_MODULE_CREATE_INFO_COMP)
2884	{
2885		std::ostringstream comp;
2886		comp
2887			<< "#version 450\n"
2888			<< "layout (set=0, binding=0, std430) buffer BufferBlock {\n"
2889			<< "    uint values[" << PipelineLibraryShaderModuleInfoInstance::kOutputBufferElements << "];\n"
2890			<< "} outBuffer;\n"
2891			<< "layout (local_size_x=" << PipelineLibraryShaderModuleInfoInstance::kOutputBufferElements << ", local_size_y=1, local_size_z=1) in;\n"
2892			<< "void main (void)\n"
2893			<< "{\n"
2894			<< "    outBuffer.values[gl_LocalInvocationIndex] = gl_LocalInvocationIndex;\n"
2895			<< "}\n"
2896			;
2897		programCollection.glslSources.add("comp") << glu::ComputeSource(comp.str());
2898	}
2899	else if (m_testParams.mode == MiscTestMode::SHADER_MODULE_CREATE_INFO_RT || m_testParams.mode == MiscTestMode::SHADER_MODULE_CREATE_INFO_RT_LIB)
2900	{
2901		const vk::ShaderBuildOptions	buildOptions (programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
2902		std::ostringstream				rgen;
2903		rgen
2904			<< "#version 460 core\n"
2905			<< "#extension GL_EXT_ray_tracing : require\n"
2906			<< "layout (set=0, binding=0, std430) buffer BufferBlock {\n"
2907			<< "    uint values[" << PipelineLibraryShaderModuleInfoInstance::kOutputBufferElements << "];\n"
2908			<< "} outBuffer;\n"
2909			<< "void main (void)\n"
2910			<< "{\n"
2911			<< "    outBuffer.values[gl_LaunchIDEXT.x] = gl_LaunchIDEXT.x;\n"
2912			<< "}\n"
2913			;
2914		programCollection.glslSources.add("rgen") << glu::RaygenSource(rgen.str()) << buildOptions;
2915	}
2916	else if (m_testParams.mode == MiscTestMode::NULL_RENDERING_CREATE_INFO)
2917	{
2918		std::ostringstream vert;
2919		vert
2920			<< "#version 460\n"
2921			<< "vec2 positions[3] = vec2[](\n"
2922			<< "    vec2(-1.0, -1.0),\n"
2923			<< "    vec2(-1.0,  3.0),\n"
2924			<< "    vec2( 3.0, -1.0)\n"
2925			<< ");\n"
2926			<< "void main() {\n"
2927			<< "    gl_Position = vec4(positions[gl_VertexIndex % 3], 0.0, 1.0);\n"
2928			<< "}\n"
2929			;
2930		programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
2931
2932		std::ostringstream frag;
2933		frag
2934			<< "#version 460\n"
2935			<< "layout (location=0) out vec4 color;\n"
2936			<< "void main () {\n"
2937			<< "    color = vec4(0.0, 0.0, 1.0, 1.0);\n"
2938			<< "}\n"
2939			;
2940		programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
2941	}
2942	else
2943	{
2944		DE_ASSERT(false);
2945	}
2946}
2947
2948TestInstance* PipelineLibraryMiscTestCase::createInstance(Context& context) const
2949{
2950	if (m_testParams.mode == MiscTestMode::SHADER_MODULE_CREATE_INFO_COMP)
2951		return new PipelineLibraryShaderModuleInfoCompInstance(context);
2952
2953	if (m_testParams.mode == MiscTestMode::SHADER_MODULE_CREATE_INFO_RT)
2954		return new PipelineLibraryShaderModuleInfoRTInstance(context, false/*withLibrary*/);
2955
2956	if (m_testParams.mode == MiscTestMode::SHADER_MODULE_CREATE_INFO_RT_LIB)
2957		return new PipelineLibraryShaderModuleInfoRTInstance(context, true/*withLibrary*/);
2958
2959	if (m_testParams.mode == MiscTestMode::NULL_RENDERING_CREATE_INFO)
2960		return new NullRenderingCreateInfoInstance(context);
2961
2962	return new PipelineLibraryMiscTestInstance(context, m_testParams);
2963}
2964
2965void addPipelineLibraryConfigurationsTests (tcu::TestCaseGroup* group, bool optimize)
2966{
2967	const int						R							= -1;
2968	const PipelineTreeConfiguration	pipelineTreeConfiguration[]	=
2969	{
2970		{ {
2971			{ R, 4 },									/*     4     */
2972		} },
2973
2974		{ {
2975			{ R, 0 },									/*     0     */
2976														/*  / / \ \  */
2977			{ 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 1 }		/*  1 1 1 1  */
2978		} },
2979
2980		{ {
2981			{ R, 0 },									/*     0     */
2982														/*  / / \    */
2983			{ 0, 1 }, { 0, 1 }, { 0, 2 }				/*  1 1  2   */
2984		} },
2985
2986		{ {
2987			{ R, 0 },									/*     0     */
2988														/*  / / \    */
2989			{ 0, 1 }, { 0, 2 }, { 0, 1 }				/* 1 2   1   */
2990		} },
2991
2992		{ {
2993			{ R, 0 },									/*     0     */
2994														/*    / \    */
2995			{ 0, 2 }, { 0, 2 },							/*   2   2   */
2996		} },
2997
2998		{ {
2999			{ R, 1 },									/*     1     */
3000														/*    / \    */
3001			{ 0, 2 }, { 0, 1 },							/*   2   1   */
3002		} },
3003
3004		{ {
3005			{ R, 2 },									/*     2     */
3006														/*    / \    */
3007			{ 0, 1 }, { 0, 1 },							/*   1   1   */
3008		} },
3009
3010		{ {
3011			{ R, 3 },									/*     3     */
3012														/*    /      */
3013			{ 0, 1 },									/*   1       */
3014		} },
3015
3016		{ {
3017			{ R, 1 },									/*     1     */
3018														/*    /      */
3019			{ 0, 3 },									/*   3       */
3020		} },
3021
3022		{ {
3023			{ R, 0 },									/*     0     */
3024														/*    / \    */
3025			{ 0, 0 },           { 0, 0 },				/*   0   0   */
3026														/*  / \ / \  */
3027			{ 1, 1 }, { 1, 1 }, { 2, 1 }, { 2, 1 },		/* 1  1 1  1 */
3028		} },
3029
3030		{ {
3031			{ R, 0 },									/*     0     */
3032														/*    / \    */
3033			{ 0, 0 },           { 0, 1 },				/*   0   1   */
3034														/*  / \   \  */
3035			{ 1, 1 }, { 1, 1 }, { 2, 1 },				/* 1   1   1 */
3036		} },
3037
3038		{ {
3039			{ R, 1 },									/*     1     */
3040														/*    / \    */
3041			{ 0, 0 },           { 0, 1 },				/*   0   1   */
3042														/*  / \      */
3043			{ 1, 1 }, { 1, 1 },							/* 1   1     */
3044		} },
3045
3046		{ {
3047			{ R, 1 },									/*     1     */
3048														/*    /      */
3049			{ 0, 1 },									/*   1       */
3050														/*  / \      */
3051			{ 1, 1 }, { 1, 1 },							/* 1   1     */
3052		} },
3053
3054		{ {
3055			{ R, 1 },									/*        1  */
3056														/*       /   */
3057			{ 0, 1 },									/*      1    */
3058														/*     /     */
3059			{ 1, 1 },									/*    1      */
3060														/*   /       */
3061			{ 2, 1 },									/*  1        */
3062		} },
3063	};
3064
3065	for (size_t libConfigNdx = 0; libConfigNdx < DE_LENGTH_OF_ARRAY(pipelineTreeConfiguration); ++libConfigNdx)
3066	{
3067		const bool			delayedShaderCreate	= (libConfigNdx != 0);
3068		const TestParams	testParams			=
3069		{
3070			pipelineTreeConfiguration[libConfigNdx],	//  PipelineTreeConfiguration	pipelineTreeConfiguration;
3071			optimize,									//  bool						optimize;
3072			delayedShaderCreate,						//  bool						delayedShaderCreate;
3073			false										//  bool						useMaintenance5;
3074		};
3075		const std::string	testName			= getTestName(pipelineTreeConfiguration[libConfigNdx]);
3076
3077		if (optimize && testParams.pipelineTreeConfiguration.size() == 1)
3078			continue;
3079
3080		group->addChild(new PipelineLibraryTestCase(group->getTestContext(), testName.c_str(), testParams));
3081	}
3082
3083	// repeat first case (one that creates montolithic pipeline) to test VK_KHR_maintenance5;
3084	// VkShaderModule deprecation (tested with delayedShaderCreate) was added to VK_KHR_maintenance5
3085	if (optimize == false)
3086	{
3087		const TestParams testParams
3088		{
3089			pipelineTreeConfiguration[0],				//  PipelineTreeConfiguration	pipelineTreeConfiguration;
3090			false,										//  bool						optimize;
3091			true,										//  bool						delayedShaderCreate;
3092			true										//  bool						useMaintenance5;
3093		};
3094
3095		group->addChild(new PipelineLibraryTestCase(group->getTestContext(), "maintenance5", testParams));
3096	}
3097}
3098
3099}	// anonymous
3100
3101tcu::TestCaseGroup*	createPipelineLibraryTests (tcu::TestContext& testCtx)
3102{
3103	de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "graphics_library"));
3104
3105	// Tests graphics pipeline libraries linkage without optimization
3106	addTestGroup(group.get(), "fast", addPipelineLibraryConfigurationsTests, false);
3107	// Tests graphics pipeline libraries linkage with optimization
3108	addTestGroup(group.get(), "optimize", addPipelineLibraryConfigurationsTests, true);
3109
3110	de::MovePtr<tcu::TestCaseGroup> miscTests(new tcu::TestCaseGroup(testCtx, "misc"));
3111
3112	de::MovePtr<tcu::TestCaseGroup> independentLayoutSetsTests(new tcu::TestCaseGroup(testCtx, "independent_pipeline_layout_sets"));
3113	independentLayoutSetsTests->addChild(new PipelineLibraryMiscTestCase(testCtx, "fast_linked", { MiscTestMode::INDEPENDENT_PIPELINE_LAYOUT_SETS_FAST_LINKED, 0u, 0u }));
3114	independentLayoutSetsTests->addChild(new PipelineLibraryMiscTestCase(testCtx, "link_opt_union_handle", { MiscTestMode::INDEPENDENT_PIPELINE_LAYOUT_SETS_WITH_LINK_TIME_OPTIMIZATION_UNION_HANDLE, 0u, 0u }));
3115	miscTests->addChild(independentLayoutSetsTests.release());
3116
3117	de::MovePtr<tcu::TestCaseGroup> bindNullDescriptorCombinationsTests(new tcu::TestCaseGroup(testCtx, "bind_null_descriptor_set"));
3118	const std::vector<const char*> bindNullDescriptorCombinations
3119	{
3120		// note: there will be as many descriptor sets layouts in pipeline layout as there are chcaracters in the case name;
3121		// '0' represents unused descriptor set layout, '1' represents used one;
3122		// location of first '1' represents index of layout used in vertex shader;
3123		// if present second '1' represents index of layout used in fragment shader
3124		"1",
3125		"11",
3126		"01",
3127		"10",
3128		"101",
3129		"1010",
3130		"1001"		// descriptor sets layouts for first pipeline part will be (&layoutA, NULL, NULL, NULL),
3131					//									 for second pipeline part (NULL, NULL, NULL, &layoutB)
3132	};
3133	for (const char* name : bindNullDescriptorCombinations)
3134	{
3135		deUint32 layoutsCount	= static_cast<deUint32>(strlen(name));
3136		deUint32 layoutsBits	= 0u;
3137
3138		// construct deUint32 with bits sets based on case name
3139		for (deUint32 i = 0; i < layoutsCount; ++i)
3140			layoutsBits |= (name[i] == '1') * (1 << (8 * sizeof(layoutsBits) - i - 1));
3141
3142		bindNullDescriptorCombinationsTests->addChild(new PipelineLibraryMiscTestCase(testCtx, name, { MiscTestMode::BIND_NULL_DESCRIPTOR_SET, layoutsCount, layoutsBits }));
3143	}
3144	miscTests->addChild(bindNullDescriptorCombinationsTests.release());
3145
3146	{
3147		de::MovePtr<tcu::TestCaseGroup> otherTests(new tcu::TestCaseGroup(testCtx, "other"));
3148		otherTests->addChild(new PipelineLibraryMiscTestCase(testCtx, "compare_link_times", { MiscTestMode::COMPARE_LINK_TIMES, 0u, 0u }));
3149		otherTests->addChild(new PipelineLibraryMiscTestCase(testCtx, "null_descriptor_set_in_monolithic_pipeline", { MiscTestMode::BIND_NULL_DESCRIPTOR_SET_IN_MONOLITHIC_PIPELINE, 0u, 0u }));
3150		otherTests->addChild(new PipelineLibraryMiscTestCase(testCtx, "null_rendering_create_info", { MiscTestMode::NULL_RENDERING_CREATE_INFO, 0u, 0u }));
3151		miscTests->addChild(otherTests.release());
3152	}
3153
3154	{
3155		de::MovePtr<tcu::TestCaseGroup> nonGraphicsTests(new tcu::TestCaseGroup(testCtx, "non_graphics"));
3156		nonGraphicsTests->addChild(new PipelineLibraryMiscTestCase(testCtx, "shader_module_info_comp",		{ MiscTestMode::SHADER_MODULE_CREATE_INFO_COMP, 0u, 0u }));
3157		nonGraphicsTests->addChild(new PipelineLibraryMiscTestCase(testCtx, "shader_module_info_rt",		{ MiscTestMode::SHADER_MODULE_CREATE_INFO_RT, 0u, 0u }));
3158		nonGraphicsTests->addChild(new PipelineLibraryMiscTestCase(testCtx, "shader_module_info_rt_lib",	{ MiscTestMode::SHADER_MODULE_CREATE_INFO_RT_LIB, 0u, 0u }));
3159		miscTests->addChild(nonGraphicsTests.release());
3160	}
3161
3162	group->addChild(miscTests.release());
3163
3164	return group.release();
3165}
3166
3167}	// pipeline
3168
3169}	// vkt
3170