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