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