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 
56 namespace vkt
57 {
58 namespace pipeline
59 {
60 namespace
61 {
62 using namespace vk;
63 using namespace vkt;
64 using namespace tcu;
65 
66 
67 static const deUint32								RENDER_SIZE_WIDTH							= 16u;
68 static const deUint32								RENDER_SIZE_HEIGHT							= 16u;
69 static const VkColorComponentFlags					COLOR_COMPONENTS_NO_RED						= VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
70 static 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 };
77 static 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 
82 struct PipelineTreeNode
83 {
84 	deInt32		parentIndex;
85 	deUint32	shaderCount;
86 };
87 
88 typedef std::vector<PipelineTreeNode>	PipelineTreeConfiguration;
89 
90 struct TestParams
91 {
92 	PipelineTreeConfiguration	pipelineTreeConfiguration;
93 	bool						optimize;
94 	bool						delayedShaderCreate;
95 	bool						useMaintenance5;
96 };
97 
98 struct 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 
109 typedef std::vector<RuntimePipelineTreeNode>	RuntimePipelineTreeConfiguration;
110 
ivec2uvec(const IVec4& ivec)111 inline 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 
getTestName(const PipelineTreeConfiguration& pipelineTreeConfiguration)122 inline 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 
144 inline 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 
162 inline 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 
173 inline 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 
185 inline 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 
200 inline 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 
215 VkImageCreateInfo 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 
240 VkImageViewCreateInfo 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 
272 VkImageCreateInfo 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 
297 const 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 
319 const 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 
337 class GraphicsPipelineCreateInfo : public ::vkt::Draw::PipelineCreateInfo
338 {
339 public:
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 
364 void 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 
408 void 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 
492 void 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 
587 void 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 
646 class PipelineLibraryTestInstance : public TestInstance
647 {
648 public:
649 									PipelineLibraryTestInstance		(Context&							context,
650 																	 const TestParams&					data);
651 									~PipelineLibraryTestInstance	(void);
652 	tcu::TestStatus					iterate							(void);
653 
654 protected:
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);
670 private:
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 
677 PipelineLibraryTestInstance::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 
703 PipelineLibraryTestInstance::~PipelineLibraryTestInstance (void)
704 {
705 }
706 
707 de::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 
722 de::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 
makePaletteBuffer(void)737 de::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 
createDescriptorPool(void)752 Move<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 
createDescriptorSetLayout(const VkBuffer vertShaderBuffer, const VkBuffer fragShaderBuffer)762 Move<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 
createDescriptorSet(const VkDescriptorPool pool, const VkDescriptorSetLayout layout, const VkBuffer vertShaderBuffer, const VkBuffer fragShaderBuffer)778 Move<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 
getSupportedDepthFormat(const InstanceInterface &vk, const VkPhysicalDevice physicalDevice)817 VkFormat 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 
runTest(RuntimePipelineTreeConfiguration& runtimePipelineTreeConfiguration, const bool optimize, const bool delayedShaderCreate)840 bool 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 
verifyColorImage(const ConstPixelBufferAccess& pba)1053 bool 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 
verifyDepthImage(const ConstPixelBufferAccess& pba)1083 bool 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 
iterate(void)1124 tcu::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 
1207 class 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;
1216 private:
1217 	TestParams				m_data;
1218 };
1219 
PipelineLibraryTestCase(tcu::TestContext& context, const char* name, const TestParams data)1220 PipelineLibraryTestCase::PipelineLibraryTestCase (tcu::TestContext& context, const char* name, const TestParams data)
1221 	: vkt::TestCase	(context, name)
1222 	, m_data		(data)
1223 {
1224 }
1225 
~PipelineLibraryTestCase(void)1226 PipelineLibraryTestCase::~PipelineLibraryTestCase (void)
1227 {
1228 }
1229 
checkSupport(Context& context) const1230 void 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 
initPrograms(SourceCollections& programCollection) const1251 void 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 
createInstance(Context& context) const1292 TestInstance* PipelineLibraryTestCase::createInstance (Context& context) const
1293 {
1294 	return new PipelineLibraryTestInstance(context, m_data);
1295 }
1296 
1297 enum 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 
1310 struct MiscTestParams
1311 {
1312 	MiscTestMode	mode;
1313 
1314 	// attributes used in BIND_NULL_DESCRIPTOR_SET mode
1315 	deUint32		layoutsCount;
1316 	deUint32		layoutsBits;
1317 };
1318 
1319 class PipelineLibraryMiscTestInstance : public TestInstance
1320 {
1321 public:
1322 						PipelineLibraryMiscTestInstance		(Context&					context,
1323 															 const MiscTestParams&		params);
1324 						~PipelineLibraryMiscTestInstance	(void) = default;
1325 	tcu::TestStatus		iterate								(void);
1326 
1327 protected:
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 
1342 private:
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 
PipelineLibraryMiscTestInstance(Context& context, const MiscTestParams& params)1358 PipelineLibraryMiscTestInstance::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 
iterate(void)1367 tcu::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 
runNullDescriptorSet(void)1405 tcu::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 
runNullDescriptorSetInMonolithicPipeline()1632 tcu::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 
runIndependentPipelineLayoutSets(bool useLinkTimeOptimization)1753 tcu::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 
runCompareLinkTimes(void)1942 tcu::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 
verifyResult(const std::vector<VerificationData>& verificationData, const tcu::ConstPixelBufferAccess& colorPixelAccess) const2089 tcu::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 
2118 class PipelineLibraryShaderModuleInfoInstance : public TestInstance
2119 {
2120 public:
PipelineLibraryShaderModuleInfoInstance(Context& context)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 						{}
~PipelineLibraryShaderModuleInfoInstance(void)2131 	virtual			~PipelineLibraryShaderModuleInfoInstance	(void) {}
2132 
2133 	static constexpr size_t kOutputBufferElements = 64u;
2134 
2135 protected:
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 
prepareOutputBuffer(VkShaderStageFlags stages)2165 void 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 
addModule(const std::string& moduleName, VkShaderStageFlagBits stage)2193 void 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 
recordShaderToHostBarrier(VkPipelineStageFlagBits pipelineStage) const2227 void 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 
verifyOutputBuffer(void)2233 void 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 
allocateCmdBuffers(void)2251 void 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 
2258 class PipelineLibraryShaderModuleInfoCompInstance : public PipelineLibraryShaderModuleInfoInstance
2259 {
2260 public:
PipelineLibraryShaderModuleInfoCompInstance(Context& context)2261 					PipelineLibraryShaderModuleInfoCompInstance		(Context& context)
2262 						: PipelineLibraryShaderModuleInfoInstance(context)
2263 						{}
~PipelineLibraryShaderModuleInfoCompInstance(void)2264 	virtual			~PipelineLibraryShaderModuleInfoCompInstance	(void) {}
2265 
2266 	tcu::TestStatus	iterate											(void) override;
2267 };
2268 
iterate(void)2269 tcu::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 
2305 class PipelineLibraryShaderModuleInfoRTInstance : public PipelineLibraryShaderModuleInfoInstance
2306 {
2307 public:
PipelineLibraryShaderModuleInfoRTInstance(Context& context, bool withLibrary)2308 					PipelineLibraryShaderModuleInfoRTInstance		(Context& context, bool withLibrary)
2309 						: PipelineLibraryShaderModuleInfoInstance	(context)
2310 						, m_withLibrary								(withLibrary)
2311 						{}
~PipelineLibraryShaderModuleInfoRTInstance(void)2312 	virtual			~PipelineLibraryShaderModuleInfoRTInstance		(void) {}
2313 
2314 	tcu::TestStatus	iterate											(void) override;
2315 
2316 protected:
2317 	bool m_withLibrary;
2318 };
2319 
iterate(void)2320 tcu::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 
2436 class NullRenderingCreateInfoInstance : public vkt::TestInstance
2437 {
2438 public:
NullRenderingCreateInfoInstance(Context& context)2439 						NullRenderingCreateInfoInstance		(Context& context)
2440 							: vkt::TestInstance(context)
2441 							{}
~NullRenderingCreateInfoInstance(void)2442 	virtual				~NullRenderingCreateInfoInstance	(void) {}
2443 
2444 	tcu::TestStatus		iterate			(void) override;
2445 };
2446 
iterate(void)2447 tcu::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 
2692 class PipelineLibraryMiscTestCase : public TestCase
2693 {
2694 public:
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 
2702 private:
2703 	MiscTestParams		m_testParams;
2704 };
2705 
PipelineLibraryMiscTestCase(tcu::TestContext& context, const char* name, const MiscTestParams params)2706 PipelineLibraryMiscTestCase::PipelineLibraryMiscTestCase(tcu::TestContext& context, const char* name, const MiscTestParams params)
2707 	: TestCase			(context, name)
2708 	, m_testParams		(params)
2709 {
2710 }
2711 
checkSupport(Context& context) const2712 void 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 
initPrograms(SourceCollections& programCollection) const2730 void 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 
createInstance(Context& context) const2948 TestInstance* 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 
addPipelineLibraryConfigurationsTests(tcu::TestCaseGroup* group, bool optimize)2965 void 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 
createPipelineLibraryTests(tcu::TestContext& testCtx)3101 tcu::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