• 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 Wrapper that can construct monolithic pipeline or use
22           VK_EXT_graphics_pipeline_library for pipeline construction
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vkRefUtil.hpp"
26 #include "vkQueryUtil.hpp"
27 #include "deSharedPtr.hpp"
28 #include "deSTLUtil.hpp"
29 #include "tcuVector.hpp"
30 #include "tcuVectorType.hpp"
31 #include "tcuMaybe.hpp"
32 #include "vkPipelineConstructionUtil.hpp"
33 
34 #include <memory>
35 #include <set>
36 
37 namespace vk
38 {
39 
40 namespace
41 {
42 
43 enum PipelineSetupState
44 {
45 	PSS_NONE						= 0x00000000,
46 	PSS_VERTEX_INPUT_INTERFACE		= 0x00000001,
47 	PSS_PRE_RASTERIZATION_SHADERS	= 0x00000002,
48 	PSS_FRAGMENT_SHADER				= 0x00000004,
49 	PSS_FRAGMENT_OUTPUT_INTERFACE	= 0x00000008,
50 };
51 
52 using TessellationDomainOriginStatePtr = std::unique_ptr<VkPipelineTessellationDomainOriginStateCreateInfo>;
53 
54 } // anonymous namespace
55 
56 static const VkVertexInputBindingDescription defaultVertexInputBindingDescription
57 {
58 	0u,																// deUint32										binding
59 	sizeof(tcu::Vec4),												// deUint32										stride
60 	VK_VERTEX_INPUT_RATE_VERTEX,									// VkVertexInputRate							inputRate
61 };
62 
63 static const VkVertexInputAttributeDescription defaultVertexInputAttributeDescription
64 {
65 	0u,																// deUint32										location
66 	0u,																// deUint32										binding
67 	VK_FORMAT_R32G32B32A32_SFLOAT,									// VkFormat										format
68 	0u																// deUint32										offset
69 };
70 
71 static const VkPipelineVertexInputStateCreateInfo defaultVertexInputState
72 {
73 	VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType								sType
74 	DE_NULL,														// const void*									pNext
75 	(VkPipelineVertexInputStateCreateFlags)0,						// VkPipelineVertexInputStateCreateFlags		flags
76 	1u,																// deUint32										vertexBindingDescriptionCount
77 	&defaultVertexInputBindingDescription,							// const VkVertexInputBindingDescription*		pVertexBindingDescriptions
78 	1u,																// deUint32										vertexAttributeDescriptionCount
79 	&defaultVertexInputAttributeDescription							// const VkVertexInputAttributeDescription*		pVertexAttributeDescriptions
80 };
81 
82 static const VkStencilOpState defaultStencilOpState
83 {
84 	VK_STENCIL_OP_KEEP,												// VkStencilOp									failOp
85 	VK_STENCIL_OP_KEEP,												// VkStencilOp									passOp
86 	VK_STENCIL_OP_KEEP,												// VkStencilOp									depthFailOp
87 	VK_COMPARE_OP_NEVER,											// VkCompareOp									compareOp
88 	0u,																// deUint32										compareMask
89 	0u,																// deUint32										writeMask
90 	0u																// deUint32										reference
91 };
92 
93 static const VkPipelineDepthStencilStateCreateInfo defaultDepthStencilState
94 {
95 	VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,		// VkStructureType								sType
96 	DE_NULL,														// const void*									pNext
97 	0u,																// VkPipelineDepthStencilStateCreateFlags		flags
98 	VK_FALSE,														// VkBool32										depthTestEnable
99 	VK_FALSE,														// VkBool32										depthWriteEnable
100 	VK_COMPARE_OP_LESS_OR_EQUAL,									// VkCompareOp									depthCompareOp
101 	VK_FALSE,														// VkBool32										depthBoundsTestEnable
102 	VK_FALSE,														// VkBool32										stencilTestEnable
103 	defaultStencilOpState,											// VkStencilOpState								front
104 	defaultStencilOpState,											// VkStencilOpState								back
105 	0.0f,															// float										minDepthBounds
106 	1.0f,															// float										maxDepthBounds
107 };
108 
109 static const VkPipelineMultisampleStateCreateInfo defaultMultisampleState
110 {
111 	VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,		// VkStructureType								sType
112 	DE_NULL,														// const void*									pNext
113 	0u,																// VkPipelineMultisampleStateCreateFlags		flags
114 	VK_SAMPLE_COUNT_1_BIT,											// VkSampleCountFlagBits						rasterizationSamples
115 	VK_FALSE,														// VkBool32										sampleShadingEnable
116 	1.0f,															// float										minSampleShading
117 	DE_NULL,														// const VkSampleMask*							pSampleMask
118 	VK_FALSE,														// VkBool32										alphaToCoverageEnable
119 	VK_FALSE														// VkBool32										alphaToOneEnable
120 };
121 
122 static const VkPipelineColorBlendAttachmentState defaultColorBlendAttachmentState
123 {
124 	VK_FALSE,														// VkBool32										blendEnable
125 	VK_BLEND_FACTOR_ZERO,											// VkBlendFactor								srcColorBlendFactor
126 	VK_BLEND_FACTOR_ZERO,											// VkBlendFactor								dstColorBlendFactor
127 	VK_BLEND_OP_ADD,												// VkBlendOp									colorBlendOp
128 	VK_BLEND_FACTOR_ZERO,											// VkBlendFactor								srcAlphaBlendFactor
129 	VK_BLEND_FACTOR_ZERO,											// VkBlendFactor								dstAlphaBlendFactor
130 	VK_BLEND_OP_ADD,												// VkBlendOp									alphaBlendOp
131 	0xf																// VkColorComponentFlags						colorWriteMask
132 };
133 
134 static const VkPipelineColorBlendStateCreateInfo defaultColorBlendState
135 {
136 	VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,		// VkStructureType								sType
137 	DE_NULL,														// const void*									pNext
138 	0u,																// VkPipelineColorBlendStateCreateFlags			flags
139 	VK_FALSE,														// VkBool32										logicOpEnable
140 	VK_LOGIC_OP_CLEAR,												// VkLogicOp									logicOp
141 	1u,																// deUint32										attachmentCount
142 	&defaultColorBlendAttachmentState,								// const VkPipelineColorBlendAttachmentState*	pAttachments
143 	{ 0.0f, 0.0f, 0.0f, 0.0f }										// float										blendConstants[4]
144 };
145 
146 namespace
147 {
148 #ifndef CTS_USES_VULKANSC
makeGraphicsPipelineLibraryCreateInfo(const VkGraphicsPipelineLibraryFlagsEXT flags)149 VkGraphicsPipelineLibraryCreateInfoEXT makeGraphicsPipelineLibraryCreateInfo(const VkGraphicsPipelineLibraryFlagsEXT flags)
150 {
151 	return
152 	{
153 		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT,	// VkStructureType						sType;
154 		DE_NULL,														// void*								pNext;
155 		flags,															// VkGraphicsPipelineLibraryFlagsEXT	flags;
156 	};
157 }
158 #endif // CTS_USES_VULKANSC
159 
makeGraphicsPipeline(const DeviceInterface & vk,VkDevice device,VkPipelineCache pipelineCache,const VkGraphicsPipelineCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator=nullptr)160 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&				vk,
161 									   VkDevice								device,
162 									   VkPipelineCache						pipelineCache,
163 									   const VkGraphicsPipelineCreateInfo*	pCreateInfo,
164 									   const VkAllocationCallbacks*			pAllocator = nullptr)
165 {
166 	VkPipeline	object					= 0;
167 	const auto	retcode					= vk.createGraphicsPipelines(device, pipelineCache, 1u, pCreateInfo, pAllocator, &object);
168 
169 #ifndef CTS_USES_VULKANSC
170 	const bool	allowCompileRequired	= ((pCreateInfo->flags & VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT) != 0u);
171 
172 	if (allowCompileRequired && retcode == VK_PIPELINE_COMPILE_REQUIRED)
173 		throw PipelineCompileRequiredError("createGraphicsPipelines returned VK_PIPELINE_COMPILE_REQUIRED");
174 #endif // CTS_USES_VULKANSC
175 
176 	VK_CHECK(retcode);
177 	return Move<VkPipeline>(check<VkPipeline>(object), Deleter<VkPipeline>(vk, device, pAllocator));
178 }
179 
180 } // anonymous
181 
checkPipelineLibraryRequirements(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,PipelineConstructionType pipelineConstructionType)182 void checkPipelineLibraryRequirements (const InstanceInterface&		vki,
183 									   VkPhysicalDevice				physicalDevice,
184 									   PipelineConstructionType		pipelineConstructionType)
185 {
186 	if (pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
187 		return;
188 
189 	const auto supportedExtensions = enumerateDeviceExtensionProperties(vki, physicalDevice, DE_NULL);
190 	if (!isExtensionStructSupported(supportedExtensions, RequiredExtension("VK_EXT_graphics_pipeline_library")))
191 		TCU_THROW(NotSupportedError, "VK_EXT_graphics_pipeline_library not supported");
192 }
193 
addToChain(void ** structThatStartsChain,void * structToAddAtTheEnd)194 void addToChain(void** structThatStartsChain, void* structToAddAtTheEnd)
195 {
196 	DE_ASSERT(structThatStartsChain);
197 
198 	if (structToAddAtTheEnd == DE_NULL)
199 		return;
200 
201 	// Cast to the base out structure which has a non-const pNext pointer.
202 	auto* structToAddAtTheEndCasted = reinterpret_cast<VkBaseOutStructure*>(structToAddAtTheEnd);
203 
204 	// make sure that pNext pointer of structure that is added to chain is empty;
205 	// we are construting chains on our own and there are cases that use same
206 	// structure for multiple instances of GraphicsPipelineWrapper
207 	structToAddAtTheEndCasted->pNext = DE_NULL;
208 
209 	deUint32	safetyCouter	= 10u;
210 	void**		structInChain	= structThatStartsChain;
211 
212 	do
213 	{
214 		// check if this is free spot
215 		if (*structInChain == DE_NULL)
216 		{
217 			// attach new structure at the end
218 			*structInChain = structToAddAtTheEndCasted;
219 			return;
220 		}
221 
222 		// Cast to the base out structure which has a non-const pNext pointer.
223 		auto* gpl = reinterpret_cast<VkBaseOutStructure*>(*structInChain);
224 
225 		// move structure pointer one position down the pNext chain
226 		structInChain = reinterpret_cast<void**>(&gpl->pNext);
227 	}
228 	while (--safetyCouter);
229 
230 	// probably safetyCouter is to small
231 	DE_ASSERT(false);
232 }
233 
234 namespace {
235 	using PipelineShaderStageModuleIdPtr = std::unique_ptr<PipelineShaderStageModuleIdentifierCreateInfoWrapper>;
236 }
237 
238 // Structure storing *CreateInfo structures that do not need to exist in memory after pipeline was constructed.
239 struct GraphicsPipelineWrapper::InternalData
240 {
241 	const DeviceInterface&								vk;
242 	VkDevice											device;
243 	const PipelineConstructionType						pipelineConstructionType;
244 	const VkPipelineCreateFlags							pipelineFlags;
245 
246 	// attribute used for making sure pipeline is configured in correct order
247 	int													setupState;
248 
249 	std::vector<PipelineShaderStageModuleIdPtr>			pipelineShaderIdentifiers;
250 	std::vector<VkPipelineShaderStageCreateInfo>		pipelineShaderStages;
251 	VkPipelineInputAssemblyStateCreateInfo				inputAssemblyState;
252 	VkPipelineRasterizationStateCreateInfo				defaultRasterizationState;
253 	VkPipelineViewportStateCreateInfo					viewportState;
254 	VkPipelineTessellationStateCreateInfo				tessellationState;
255 	VkPipelineFragmentShadingRateStateCreateInfoKHR*	pFragmentShadingRateState;
256 	PipelineRenderingCreateInfoWrapper					pRenderingState;
257 	const VkPipelineDynamicStateCreateInfo*				pDynamicState;
258 	PipelineRepresentativeFragmentTestCreateInfoWrapper	pRepresentativeFragmentTestState;
259 
260 	TessellationDomainOriginStatePtr					pTessellationDomainOrigin;
261 	deBool												useViewportState;
262 	deBool												useDefaultRasterizationState;
263 	deBool												useDefaultDepthStencilState;
264 	deBool												useDefaultColorBlendState;
265 	deBool												useDefaultMultisampleState;
266 	bool												failOnCompileWhenLinking;
267 
268 	VkGraphicsPipelineCreateInfo						monolithicPipelineCreateInfo;
269 
270 	// initialize with most common values
InternalDatavk::GraphicsPipelineWrapper::InternalData271 	InternalData(const DeviceInterface& vkd, VkDevice vkDevice, const PipelineConstructionType constructionType, const VkPipelineCreateFlags pipelineCreateFlags)
272 		: vk						(vkd)
273 		, device					(vkDevice)
274 		, pipelineConstructionType	(constructionType)
275 		, pipelineFlags				(pipelineCreateFlags)
276 		, setupState				(PSS_NONE)
277 		, inputAssemblyState
278 		{
279 			VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType								sType
280 			DE_NULL,														// const void*									pNext
281 			0u,																// VkPipelineInputAssemblyStateCreateFlags		flags
282 			VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,							// VkPrimitiveTopology							topology
283 			VK_FALSE														// VkBool32										primitiveRestartEnable
284 		}
285 		, defaultRasterizationState
286 		{
287 			VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType								sType
288 			DE_NULL,														// const void*									pNext
289 			0u,																// VkPipelineRasterizationStateCreateFlags		flags
290 			VK_FALSE,														// VkBool32										depthClampEnable
291 			VK_FALSE,														// VkBool32										rasterizerDiscardEnable
292 			VK_POLYGON_MODE_FILL,											// VkPolygonMode								polygonMode
293 			VK_CULL_MODE_NONE,												// VkCullModeFlags								cullMode
294 			VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace									frontFace
295 			VK_FALSE,														// VkBool32										depthBiasEnable
296 			0.0f,															// float										depthBiasConstantFactor
297 			0.0f,															// float										depthBiasClamp
298 			0.0f,															// float										depthBiasSlopeFactor
299 			1.0f															// float										lineWidth
300 		}
301 		, viewportState
302 		{
303 			VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,			// VkStructureType								sType
304 			DE_NULL,														// const void*									pNext
305 			(VkPipelineViewportStateCreateFlags)0,							// VkPipelineViewportStateCreateFlags			flags
306 			1u,																// deUint32										viewportCount
307 			DE_NULL,														// const VkViewport*							pViewports
308 			1u,																// deUint32										scissorCount
309 			DE_NULL															// const VkRect2D*								pScissors
310 		}
311 		, tessellationState
312 		{
313 			VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,		// VkStructureType								sType
314 			DE_NULL,														// const void*									pNext
315 			0u,																// VkPipelineTessellationStateCreateFlags		flags
316 			3u																// deUint32										patchControlPoints
317 		}
318 		, pFragmentShadingRateState		(nullptr)
319 		, pDynamicState					(DE_NULL)
320 		, pRepresentativeFragmentTestState(nullptr)
321 		, pTessellationDomainOrigin		()
322 		, useViewportState				(DE_TRUE)
323 		, useDefaultRasterizationState	(DE_FALSE)
324 		, useDefaultDepthStencilState	(DE_FALSE)
325 		, useDefaultColorBlendState		(DE_FALSE)
326 		, useDefaultMultisampleState	(DE_FALSE)
327 		, failOnCompileWhenLinking		(false)
328 	{
329 		monolithicPipelineCreateInfo = initVulkanStructure();
330 	}
331 };
332 
GraphicsPipelineWrapper(const DeviceInterface & vk,VkDevice device,const PipelineConstructionType pipelineConstructionType,const VkPipelineCreateFlags flags)333 GraphicsPipelineWrapper::GraphicsPipelineWrapper(const DeviceInterface&				vk,
334 												 VkDevice							device,
335 												 const PipelineConstructionType		pipelineConstructionType,
336 												 const VkPipelineCreateFlags		flags)
337 	: m_internalData	(new InternalData(vk, device, pipelineConstructionType, flags))
338 {
339 }
340 
GraphicsPipelineWrapper(GraphicsPipelineWrapper && pw)341 GraphicsPipelineWrapper::GraphicsPipelineWrapper(GraphicsPipelineWrapper&& pw) noexcept
342 	: m_pipelineFinal	(pw.m_pipelineFinal)
343 	, m_internalData	(pw.m_internalData)
344 {
345 	std::move(pw.m_pipelineParts, pw.m_pipelineParts + de::arrayLength(pw.m_pipelineParts), m_pipelineParts);
346 }
347 
setMonolithicPipelineLayout(const VkPipelineLayout layout)348 GraphicsPipelineWrapper& GraphicsPipelineWrapper::setMonolithicPipelineLayout(const VkPipelineLayout layout)
349 {
350 	// make sure pipeline was not already built
351 	DE_ASSERT(m_pipelineFinal.get() == DE_NULL);
352 
353 	m_internalData->monolithicPipelineCreateInfo.layout = layout;
354 
355 	return *this;
356 }
357 
setDynamicState(const VkPipelineDynamicStateCreateInfo * dynamicState)358 GraphicsPipelineWrapper& GraphicsPipelineWrapper::setDynamicState(const VkPipelineDynamicStateCreateInfo* dynamicState)
359 {
360 	// make sure states are not yet setup - all pipeline states must know about dynamic state
361 	DE_ASSERT(m_internalData && m_internalData->setupState == PSS_NONE);
362 
363 	m_internalData->pDynamicState								= dynamicState;
364 	m_internalData->monolithicPipelineCreateInfo.pDynamicState	= dynamicState;
365 
366 	return *this;
367 }
368 
setRepresentativeFragmentTestState(PipelineRepresentativeFragmentTestCreateInfoWrapper representativeFragmentTestState)369 GraphicsPipelineWrapper& GraphicsPipelineWrapper::setRepresentativeFragmentTestState(PipelineRepresentativeFragmentTestCreateInfoWrapper representativeFragmentTestState)
370 {
371 	// Representative fragment test state is needed by the fragment shader state.
372 	DE_ASSERT(m_internalData && (m_internalData->setupState < PSS_FRAGMENT_SHADER));
373 
374 	m_internalData->pRepresentativeFragmentTestState = representativeFragmentTestState;
375 	return *this;
376 }
377 
getDynamicStates(const VkPipelineDynamicStateCreateInfo * dynamicStateInfo,uint32_t setupState)378 std::vector<VkDynamicState> getDynamicStates(const VkPipelineDynamicStateCreateInfo* dynamicStateInfo, uint32_t setupState)
379 {
380 	static const std::set<VkDynamicState> vertexInputStates {
381 		VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT,
382 		VK_DYNAMIC_STATE_VERTEX_INPUT_EXT,
383 		VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT,
384 		VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE_EXT,
385 	};
386 
387 	static const std::set<VkDynamicState> preRastStates {
388 		VK_DYNAMIC_STATE_VIEWPORT,
389 		VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT_EXT,
390 		VK_DYNAMIC_STATE_SCISSOR,
391 		VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT_EXT,
392 		VK_DYNAMIC_STATE_LINE_WIDTH,
393 		VK_DYNAMIC_STATE_LINE_STIPPLE_EXT,
394 		VK_DYNAMIC_STATE_CULL_MODE_EXT,
395 		VK_DYNAMIC_STATE_FRONT_FACE_EXT,
396 		VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT,
397 		VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE_EXT,
398 		VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT,
399 		VK_DYNAMIC_STATE_DEPTH_BIAS,
400 		VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE_EXT,
401 		VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR,
402 #ifndef CTS_USES_VULKANSC
403 		VK_DYNAMIC_STATE_TESSELLATION_DOMAIN_ORIGIN_EXT,
404 		VK_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT,
405 		VK_DYNAMIC_STATE_POLYGON_MODE_EXT,
406 		VK_DYNAMIC_STATE_RASTERIZATION_STREAM_EXT,
407 		VK_DYNAMIC_STATE_PROVOKING_VERTEX_MODE_EXT,
408 		VK_DYNAMIC_STATE_DEPTH_CLIP_NEGATIVE_ONE_TO_ONE_EXT,
409 		VK_DYNAMIC_STATE_DEPTH_CLIP_ENABLE_EXT,
410 		VK_DYNAMIC_STATE_LINE_STIPPLE_ENABLE_EXT,
411 		VK_DYNAMIC_STATE_LINE_STIPPLE_EXT,
412 		VK_DYNAMIC_STATE_CONSERVATIVE_RASTERIZATION_MODE_EXT,
413 		VK_DYNAMIC_STATE_EXTRA_PRIMITIVE_OVERESTIMATION_SIZE_EXT,
414 		VK_DYNAMIC_STATE_LINE_RASTERIZATION_MODE_EXT,
415 		VK_DYNAMIC_STATE_VIEWPORT_SWIZZLE_NV,
416 		VK_DYNAMIC_STATE_SHADING_RATE_IMAGE_ENABLE_NV,
417 		VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_ENABLE_NV,
418 		VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV,
419 		VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV,
420 		VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV,
421 		VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV,
422 #endif
423 	};
424 
425 	static const std::set<VkDynamicState> fragShaderStates {
426 		VK_DYNAMIC_STATE_DEPTH_BOUNDS,
427 		VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT,
428 		VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT,
429 		VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT,
430 		VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT,
431 		VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK,
432 		VK_DYNAMIC_STATE_STENCIL_WRITE_MASK,
433 		VK_DYNAMIC_STATE_STENCIL_REFERENCE,
434 		VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT,
435 		VK_DYNAMIC_STATE_STENCIL_OP_EXT,
436 		VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR,
437 		// Needs MSAA info here as well as fragment output state
438 		VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT,
439 #ifndef CTS_USES_VULKANSC
440 		VK_DYNAMIC_STATE_SAMPLE_MASK_EXT,
441 		VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT,
442 		VK_DYNAMIC_STATE_ALPHA_TO_ONE_ENABLE_EXT,
443 		VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_ENABLE_EXT,
444 		VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT,
445 		VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_ENABLE_NV,
446 		VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_LOCATION_NV,
447 		VK_DYNAMIC_STATE_COVERAGE_MODULATION_MODE_NV,
448 		VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_ENABLE_NV,
449 		VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_NV,
450 		VK_DYNAMIC_STATE_COVERAGE_REDUCTION_MODE_NV,
451 		VK_DYNAMIC_STATE_REPRESENTATIVE_FRAGMENT_TEST_ENABLE_NV,
452 
453 #endif
454 	};
455 
456 	static const std::set<VkDynamicState> fragOutputStates {
457 		VK_DYNAMIC_STATE_LOGIC_OP_EXT,
458 		VK_DYNAMIC_STATE_BLEND_CONSTANTS,
459 		VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT,
460 		VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR,
461 		VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT,
462 #ifndef CTS_USES_VULKANSC
463 		VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT,
464 		VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT,
465 		VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT,
466 		VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT,
467 		VK_DYNAMIC_STATE_LOGIC_OP_ENABLE_EXT,
468 		VK_DYNAMIC_STATE_SAMPLE_MASK_EXT,
469 		VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT,
470 		VK_DYNAMIC_STATE_ALPHA_TO_ONE_ENABLE_EXT,
471 		VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_ENABLE_EXT,
472 		VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT,
473 		VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_ENABLE_NV,
474 		VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_LOCATION_NV,
475 		VK_DYNAMIC_STATE_COVERAGE_MODULATION_MODE_NV,
476 		VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_ENABLE_NV,
477 		VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_NV,
478 		VK_DYNAMIC_STATE_COVERAGE_REDUCTION_MODE_NV,
479 		VK_DYNAMIC_STATE_REPRESENTATIVE_FRAGMENT_TEST_ENABLE_NV,
480 #endif
481 	};
482 
483 	const std::set<VkDynamicState> dynamicStates (dynamicStateInfo->pDynamicStates,
484 												  dynamicStateInfo->pDynamicStates + dynamicStateInfo->dynamicStateCount);
485 
486 	std::set<VkDynamicState> intersectedStates;
487 
488 	if (setupState & PSS_VERTEX_INPUT_INTERFACE)
489 		std::set_intersection(vertexInputStates.begin(), vertexInputStates.end(), dynamicStates.begin(), dynamicStates.end(), std::inserter(intersectedStates, intersectedStates.end()));
490 
491 	if (setupState & PSS_PRE_RASTERIZATION_SHADERS)
492 		std::set_intersection(preRastStates.begin(),	 preRastStates.end(),	  dynamicStates.begin(), dynamicStates.end(), std::inserter(intersectedStates, intersectedStates.end()));
493 
494 	if (setupState & PSS_FRAGMENT_SHADER)
495 		std::set_intersection(fragShaderStates.begin(),  fragShaderStates.end(),  dynamicStates.begin(), dynamicStates.end(), std::inserter(intersectedStates, intersectedStates.end()));
496 
497 	if (setupState & PSS_FRAGMENT_OUTPUT_INTERFACE)
498 		std::set_intersection(fragOutputStates.begin(),  fragOutputStates.end(),  dynamicStates.begin(), dynamicStates.end(), std::inserter(intersectedStates, intersectedStates.end()));
499 
500 	const std::vector<VkDynamicState> returnedStates (begin(intersectedStates), end(intersectedStates));
501 
502 	return returnedStates;
503 }
504 
setDefaultTopology(const VkPrimitiveTopology topology)505 GraphicsPipelineWrapper& GraphicsPipelineWrapper::setDefaultTopology(const VkPrimitiveTopology topology)
506 {
507 	// topology is needed by vertex input state, make sure vertex input state was not setup yet
508 	DE_ASSERT(m_internalData && (m_internalData->setupState == PSS_NONE));
509 
510 	m_internalData->inputAssemblyState.topology = topology;
511 
512 	return *this;
513 }
514 
setDefaultPatchControlPoints(const deUint32 patchControlPoints)515 GraphicsPipelineWrapper& GraphicsPipelineWrapper::setDefaultPatchControlPoints(const deUint32 patchControlPoints)
516 {
517 	// patchControlPoints are needed by pre-rasterization shader state, make sure pre-rasterization state was not setup yet
518 	DE_ASSERT(m_internalData && (m_internalData->setupState < PSS_PRE_RASTERIZATION_SHADERS));
519 
520 	m_internalData->tessellationState.patchControlPoints = patchControlPoints;
521 
522 	return *this;
523 }
524 
setDefaultTessellationDomainOrigin(const VkTessellationDomainOrigin domainOrigin,bool forceExtStruct)525 GraphicsPipelineWrapper& GraphicsPipelineWrapper::setDefaultTessellationDomainOrigin (const VkTessellationDomainOrigin domainOrigin, bool forceExtStruct)
526 {
527 	// Tessellation domain origin is needed by pre-rasterization shader state, make sure pre-rasterization state was not setup yet
528 	DE_ASSERT(m_internalData && (m_internalData->setupState < PSS_PRE_RASTERIZATION_SHADERS));
529 
530 	// We need the extension structure when:
531 	// - We want to force it.
532 	// - The domain origin is not the default value.
533 	// - We have already hooked the extension structure.
534 	if (forceExtStruct || domainOrigin != VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT || m_internalData->pTessellationDomainOrigin)
535 	{
536 		if (!m_internalData->pTessellationDomainOrigin)
537 		{
538 			m_internalData->pTessellationDomainOrigin.reset(new VkPipelineTessellationDomainOriginStateCreateInfo(initVulkanStructure()));
539 			m_internalData->tessellationState.pNext = m_internalData->pTessellationDomainOrigin.get();
540 		}
541 		m_internalData->pTessellationDomainOrigin->domainOrigin = domainOrigin;
542 	}
543 
544 	return *this;
545 }
546 
setDefaultRasterizerDiscardEnable(const deBool rasterizerDiscardEnable)547 GraphicsPipelineWrapper& GraphicsPipelineWrapper::setDefaultRasterizerDiscardEnable(const deBool rasterizerDiscardEnable)
548 {
549 	// rasterizerDiscardEnable is used in pre-rasterization shader state, make sure pre-rasterization state was not setup yet
550 	DE_ASSERT(m_internalData && (m_internalData->setupState < PSS_PRE_RASTERIZATION_SHADERS));
551 
552 	m_internalData->defaultRasterizationState.rasterizerDiscardEnable = rasterizerDiscardEnable;
553 
554 	return *this;
555 }
556 
557 
setDefaultRasterizationState()558 GraphicsPipelineWrapper& GraphicsPipelineWrapper::setDefaultRasterizationState()
559 {
560 	// RasterizationState is used in pre-rasterization shader state, make sure this state was not setup yet
561 	DE_ASSERT(m_internalData && (m_internalData->setupState < PSS_PRE_RASTERIZATION_SHADERS));
562 
563 	m_internalData->useDefaultRasterizationState = DE_TRUE;
564 
565 	return *this;
566 }
567 
setDefaultDepthStencilState()568 GraphicsPipelineWrapper& GraphicsPipelineWrapper::setDefaultDepthStencilState()
569 {
570 	// DepthStencilState is used in fragment shader state, make sure fragment shader state was not setup yet
571 	DE_ASSERT(m_internalData && (m_internalData->setupState < PSS_FRAGMENT_SHADER));
572 
573 	m_internalData->useDefaultDepthStencilState = DE_TRUE;
574 
575 	return *this;
576 }
577 
setDefaultColorBlendState()578 GraphicsPipelineWrapper& GraphicsPipelineWrapper::setDefaultColorBlendState()
579 {
580 	// ColorBlendState is used in fragment shader state, make sure fragment shader state was not setup yet
581 	DE_ASSERT(m_internalData && (m_internalData->setupState < PSS_FRAGMENT_SHADER));
582 
583 	m_internalData->useDefaultColorBlendState = DE_TRUE;
584 
585 	return *this;
586 }
587 
setDefaultMultisampleState()588 GraphicsPipelineWrapper& GraphicsPipelineWrapper::setDefaultMultisampleState()
589 {
590 	// MultisampleState is used in fragment shader state, make sure fragment shader state was not setup yet
591 	DE_ASSERT(m_internalData && (m_internalData->setupState < PSS_FRAGMENT_SHADER));
592 
593 	m_internalData->useDefaultMultisampleState = DE_TRUE;
594 
595 	return *this;
596 }
597 
setDefaultViewportsCount(deUint32 viewportCount)598 GraphicsPipelineWrapper& GraphicsPipelineWrapper::setDefaultViewportsCount(deUint32 viewportCount)
599 {
600 	// ViewportState is used in pre-rasterization shader state, make sure pre-rasterization state was not setup yet
601 	DE_ASSERT(m_internalData && (m_internalData->setupState < PSS_PRE_RASTERIZATION_SHADERS));
602 
603 	m_internalData->viewportState.viewportCount = viewportCount;
604 
605 	return *this;
606 }
607 
setDefaultScissorsCount(deUint32 scissorCount)608 GraphicsPipelineWrapper& GraphicsPipelineWrapper::setDefaultScissorsCount(deUint32 scissorCount)
609 {
610 	// ViewportState is used in pre-rasterization shader state, make sure pre-rasterization state was not setup yet
611 	DE_ASSERT(m_internalData && (m_internalData->setupState < PSS_PRE_RASTERIZATION_SHADERS));
612 
613 	m_internalData->viewportState.scissorCount = scissorCount;
614 
615 	return *this;
616 }
617 
setViewportStatePnext(const void * pNext)618 GraphicsPipelineWrapper& GraphicsPipelineWrapper::setViewportStatePnext(const void* pNext)
619 {
620 	// ViewportState is used in pre-rasterization shader state, make sure pre-rasterization state was not setup yet
621 	DE_ASSERT(m_internalData && (m_internalData->setupState < PSS_PRE_RASTERIZATION_SHADERS));
622 
623 	m_internalData->viewportState.pNext = pNext;
624 
625 	return *this;
626 }
627 
628 #ifndef CTS_USES_VULKANSC
setRenderingColorAttachmentsInfo(PipelineRenderingCreateInfoWrapper pipelineRenderingCreateInfo)629 GraphicsPipelineWrapper& GraphicsPipelineWrapper::setRenderingColorAttachmentsInfo(PipelineRenderingCreateInfoWrapper pipelineRenderingCreateInfo)
630 {
631 	/* When both graphics pipeline library and dynamic rendering enabled, we just need only viewMask of VkPipelineRenderingCreateInfo
632 	 * on non-fragment stages. But we need the rest info for setting up fragment output states.
633 	 * This method provides a way to verify this condition.
634 	 */
635 	if (!m_internalData->pRenderingState.ptr || m_internalData->pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
636 		return *this;
637 
638 	DE_ASSERT(m_internalData && (m_internalData->setupState > PSS_VERTEX_INPUT_INTERFACE) &&
639 								(m_internalData->setupState < PSS_FRAGMENT_OUTPUT_INTERFACE) &&
640 								(m_internalData->pRenderingState.ptr->viewMask == pipelineRenderingCreateInfo.ptr->viewMask));
641 
642 	m_internalData->pRenderingState.ptr = pipelineRenderingCreateInfo.ptr;
643 
644 	return *this;
645 }
646 #endif
647 
disableViewportState()648 GraphicsPipelineWrapper& GraphicsPipelineWrapper::disableViewportState()
649 {
650 	// ViewportState is used in pre-rasterization shader state, make sure pre-rasterization state was not setup yet
651 	DE_ASSERT(m_internalData && (m_internalData->setupState < PSS_PRE_RASTERIZATION_SHADERS));
652 
653 	m_internalData->useViewportState = DE_FALSE;
654 
655 	return *this;
656 }
657 
setupVertexInputState(const VkPipelineVertexInputStateCreateInfo * vertexInputState,const VkPipelineInputAssemblyStateCreateInfo * inputAssemblyState,const VkPipelineCache partPipelineCache,PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback)658 GraphicsPipelineWrapper& GraphicsPipelineWrapper::setupVertexInputState(const VkPipelineVertexInputStateCreateInfo*		vertexInputState,
659 																		const VkPipelineInputAssemblyStateCreateInfo*	inputAssemblyState,
660 																		const VkPipelineCache							partPipelineCache,
661 																		PipelineCreationFeedbackCreateInfoWrapper		partCreationFeedback)
662 {
663 	// make sure pipeline was not already build
664 	DE_ASSERT(m_pipelineFinal.get() == DE_NULL);
665 
666 	// make sure states are set in order - no need to complicate logic to support out of order specification - this state needs to be set first
667 	DE_ASSERT(m_internalData && (m_internalData->setupState == PSS_NONE));
668 
669 	// Unreference variables that are not used in Vulkan SC. No need to put this in ifdef.
670 	DE_UNREF(partPipelineCache);
671 	DE_UNREF(partCreationFeedback);
672 
673 	m_internalData->setupState = PSS_VERTEX_INPUT_INTERFACE;
674 
675 	const auto pVertexInputState = vertexInputState ? vertexInputState : &defaultVertexInputState;
676 	const auto pInputAssemblyState = inputAssemblyState ? inputAssemblyState : &m_internalData->inputAssemblyState;
677 
678 	if (m_internalData->pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
679 	{
680 		m_internalData->monolithicPipelineCreateInfo.pVertexInputState = pVertexInputState;
681 		m_internalData->monolithicPipelineCreateInfo.pInputAssemblyState = pInputAssemblyState;
682 	}
683 
684 #ifndef CTS_USES_VULKANSC
685 	// note we could just use else to if statement above but sinc
686 	// this section is cut out for Vulkan SC its cleaner with separate if
687 	if (m_internalData->pipelineConstructionType != PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
688 	{
689 		auto	libraryCreateInfo = makeGraphicsPipelineLibraryCreateInfo(VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT);
690 		void*	firstStructInChain = reinterpret_cast<void*>(&libraryCreateInfo);
691 		addToChain(&firstStructInChain, partCreationFeedback.ptr);
692 
693 		VkPipelineDynamicStateCreateInfo pickedDynamicStateInfo = initVulkanStructure();
694 		std::vector<VkDynamicState> states;
695 
696 		if(m_internalData->pDynamicState)
697 		{
698 			states = getDynamicStates(m_internalData->pDynamicState, m_internalData->setupState);
699 
700 			pickedDynamicStateInfo.pDynamicStates = states.data();
701 			pickedDynamicStateInfo.dynamicStateCount = static_cast<uint32_t>(states.size());
702 		}
703 
704 		VkGraphicsPipelineCreateInfo pipelinePartCreateInfo = initVulkanStructure();
705 		pipelinePartCreateInfo.pNext						= firstStructInChain;
706 		pipelinePartCreateInfo.flags						= (m_internalData->pipelineFlags | VK_PIPELINE_CREATE_LIBRARY_BIT_KHR) & ~VK_PIPELINE_CREATE_DERIVATIVE_BIT;
707 		pipelinePartCreateInfo.pVertexInputState			= pVertexInputState;
708 		pipelinePartCreateInfo.pInputAssemblyState			= pInputAssemblyState;
709 		pipelinePartCreateInfo.pDynamicState				= &pickedDynamicStateInfo;
710 
711 		if (m_internalData->pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_LINK_TIME_OPTIMIZED_LIBRARY)
712 			pipelinePartCreateInfo.flags |= VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT;
713 
714 		m_pipelineParts[0] = makeGraphicsPipeline(m_internalData->vk, m_internalData->device, partPipelineCache, &pipelinePartCreateInfo);
715 	}
716 #endif // CTS_USES_VULKANSC
717 
718 	return *this;
719 }
720 
setupPreRasterizationShaderState(const std::vector<VkViewport> & viewports,const std::vector<VkRect2D> & scissors,const VkPipelineLayout layout,const VkRenderPass renderPass,const deUint32 subpass,const VkShaderModule vertexShaderModule,const VkPipelineRasterizationStateCreateInfo * rasterizationState,const VkShaderModule tessellationControlShaderModule,const VkShaderModule tessellationEvalShaderModule,const VkShaderModule geometryShaderModule,const VkSpecializationInfo * specializationInfo,VkPipelineFragmentShadingRateStateCreateInfoKHR * fragmentShadingRateState,PipelineRenderingCreateInfoWrapper rendering,const VkPipelineCache partPipelineCache,PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback)721 GraphicsPipelineWrapper& GraphicsPipelineWrapper::setupPreRasterizationShaderState(const std::vector<VkViewport>&					viewports,
722 																				   const std::vector<VkRect2D>&						scissors,
723 																				   const VkPipelineLayout							layout,
724 																				   const VkRenderPass								renderPass,
725 																				   const deUint32									subpass,
726 																				   const VkShaderModule								vertexShaderModule,
727 																				   const VkPipelineRasterizationStateCreateInfo*	rasterizationState,
728 																				   const VkShaderModule								tessellationControlShaderModule,
729 																				   const VkShaderModule								tessellationEvalShaderModule,
730 																				   const VkShaderModule								geometryShaderModule,
731 																				   const VkSpecializationInfo						*specializationInfo,
732 																				   VkPipelineFragmentShadingRateStateCreateInfoKHR*	fragmentShadingRateState,
733 																				   PipelineRenderingCreateInfoWrapper				rendering,
734 																				   const VkPipelineCache							partPipelineCache,
735 																				   PipelineCreationFeedbackCreateInfoWrapper		partCreationFeedback)
736 {
737 	return setupPreRasterizationShaderState2(viewports,
738 											 scissors,
739 											 layout,
740 											 renderPass,
741 											 subpass,
742 											 vertexShaderModule,
743 											 rasterizationState,
744 											 tessellationControlShaderModule,
745 											 tessellationEvalShaderModule,
746 											 geometryShaderModule,
747 											 // Reuse the same specialization info for all stages.
748 											 specializationInfo,
749 											 specializationInfo,
750 											 specializationInfo,
751 											 specializationInfo,
752 											 fragmentShadingRateState,
753 											 rendering,
754 											 partPipelineCache,
755 											 partCreationFeedback);
756 }
757 
setupPreRasterizationShaderState2(const std::vector<VkViewport> & viewports,const std::vector<VkRect2D> & scissors,const VkPipelineLayout layout,const VkRenderPass renderPass,const deUint32 subpass,const VkShaderModule vertexShaderModule,const VkPipelineRasterizationStateCreateInfo * rasterizationState,const VkShaderModule tessellationControlShaderModule,const VkShaderModule tessellationEvalShaderModule,const VkShaderModule geometryShaderModule,const VkSpecializationInfo * vertSpecializationInfo,const VkSpecializationInfo * tescSpecializationInfo,const VkSpecializationInfo * teseSpecializationInfo,const VkSpecializationInfo * geomSpecializationInfo,VkPipelineFragmentShadingRateStateCreateInfoKHR * fragmentShadingRateState,PipelineRenderingCreateInfoWrapper rendering,const VkPipelineCache partPipelineCache,PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback)758 GraphicsPipelineWrapper& GraphicsPipelineWrapper::setupPreRasterizationShaderState2(const std::vector<VkViewport>&					viewports,
759 																					const std::vector<VkRect2D>&					scissors,
760 																					const VkPipelineLayout							layout,
761 																					const VkRenderPass								renderPass,
762 																					const deUint32									subpass,
763 																					const VkShaderModule							vertexShaderModule,
764 																					const VkPipelineRasterizationStateCreateInfo*	rasterizationState,
765 																					const VkShaderModule							tessellationControlShaderModule,
766 																					const VkShaderModule							tessellationEvalShaderModule,
767 																					const VkShaderModule							geometryShaderModule,
768 																					const VkSpecializationInfo*						vertSpecializationInfo,
769 																					const VkSpecializationInfo*						tescSpecializationInfo,
770 																					const VkSpecializationInfo*						teseSpecializationInfo,
771 																					const VkSpecializationInfo*						geomSpecializationInfo,
772 																					VkPipelineFragmentShadingRateStateCreateInfoKHR*fragmentShadingRateState,
773 																					PipelineRenderingCreateInfoWrapper				rendering,
774 																					const VkPipelineCache							partPipelineCache,
775 																					PipelineCreationFeedbackCreateInfoWrapper		partCreationFeedback)
776 {
777 	return setupPreRasterizationShaderState3(viewports,
778 											 scissors,
779 											 layout,
780 											 renderPass,
781 											 subpass,
782 											 vertexShaderModule,
783 											 PipelineShaderStageModuleIdentifierCreateInfoWrapper(),
784 											 rasterizationState,
785 											 tessellationControlShaderModule,
786 											 PipelineShaderStageModuleIdentifierCreateInfoWrapper(),
787 											 tessellationEvalShaderModule,
788 											 PipelineShaderStageModuleIdentifierCreateInfoWrapper(),
789 											 geometryShaderModule,
790 											 PipelineShaderStageModuleIdentifierCreateInfoWrapper(),
791 											 vertSpecializationInfo,
792 											 tescSpecializationInfo,
793 											 teseSpecializationInfo,
794 											 geomSpecializationInfo,
795 											 fragmentShadingRateState,
796 											 rendering,
797 											 partPipelineCache,
798 											 partCreationFeedback);
799 }
800 
setupPreRasterizationShaderState3(const std::vector<VkViewport> & viewports,const std::vector<VkRect2D> & scissors,const VkPipelineLayout layout,const VkRenderPass renderPass,const deUint32 subpass,const VkShaderModule vertexShaderModule,PipelineShaderStageModuleIdentifierCreateInfoWrapper vertShaderModuleId,const VkPipelineRasterizationStateCreateInfo * rasterizationState,const VkShaderModule tessellationControlShaderModule,PipelineShaderStageModuleIdentifierCreateInfoWrapper tescShaderModuleId,const VkShaderModule tessellationEvalShaderModule,PipelineShaderStageModuleIdentifierCreateInfoWrapper teseShaderModuleId,const VkShaderModule geometryShaderModule,PipelineShaderStageModuleIdentifierCreateInfoWrapper geomShaderModuleId,const VkSpecializationInfo * vertSpecializationInfo,const VkSpecializationInfo * tescSpecializationInfo,const VkSpecializationInfo * teseSpecializationInfo,const VkSpecializationInfo * geomSpecializationInfo,VkPipelineFragmentShadingRateStateCreateInfoKHR * fragmentShadingRateState,PipelineRenderingCreateInfoWrapper rendering,const VkPipelineCache partPipelineCache,PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback)801 GraphicsPipelineWrapper& GraphicsPipelineWrapper::setupPreRasterizationShaderState3(const std::vector<VkViewport>&								viewports,
802 																					const std::vector<VkRect2D>&								scissors,
803 																					const VkPipelineLayout										layout,
804 																					const VkRenderPass											renderPass,
805 																					const deUint32												subpass,
806 																					const VkShaderModule										vertexShaderModule,
807 																					PipelineShaderStageModuleIdentifierCreateInfoWrapper		vertShaderModuleId,
808 																					const VkPipelineRasterizationStateCreateInfo*				rasterizationState,
809 																					const VkShaderModule										tessellationControlShaderModule,
810 																					PipelineShaderStageModuleIdentifierCreateInfoWrapper		tescShaderModuleId,
811 																					const VkShaderModule										tessellationEvalShaderModule,
812 																					PipelineShaderStageModuleIdentifierCreateInfoWrapper		teseShaderModuleId,
813 																					const VkShaderModule										geometryShaderModule,
814 																					PipelineShaderStageModuleIdentifierCreateInfoWrapper		geomShaderModuleId,
815 																					const VkSpecializationInfo*									vertSpecializationInfo,
816 																					const VkSpecializationInfo*									tescSpecializationInfo,
817 																					const VkSpecializationInfo*									teseSpecializationInfo,
818 																					const VkSpecializationInfo*									geomSpecializationInfo,
819 																					VkPipelineFragmentShadingRateStateCreateInfoKHR*			fragmentShadingRateState,
820 																					PipelineRenderingCreateInfoWrapper							rendering,
821 																					const VkPipelineCache										partPipelineCache,
822 																					PipelineCreationFeedbackCreateInfoWrapper					partCreationFeedback)
823 {
824 	// make sure pipeline was not already build
825 	DE_ASSERT(m_pipelineFinal.get() == DE_NULL);
826 
827 	// make sure states are set in order - no need to complicate logic to support out of order specification - this state needs to be set second
828 	DE_ASSERT(m_internalData && (m_internalData->setupState == PSS_VERTEX_INPUT_INTERFACE));
829 
830 	// Unreference variables that are not used in Vulkan SC. No need to put this in ifdef.
831 	DE_UNREF(partPipelineCache);
832 	DE_UNREF(partCreationFeedback);
833 	DE_UNREF(vertShaderModuleId);
834 	DE_UNREF(tescShaderModuleId);
835 	DE_UNREF(teseShaderModuleId);
836 	DE_UNREF(geomShaderModuleId);
837 
838 	m_internalData->setupState |= PSS_PRE_RASTERIZATION_SHADERS;
839 	m_internalData->pFragmentShadingRateState = fragmentShadingRateState;
840 	m_internalData->pRenderingState.ptr = rendering.ptr;
841 
842 	const bool hasTesc = (tessellationControlShaderModule != DE_NULL || tescShaderModuleId.ptr);
843 	const bool hasTese = (tessellationEvalShaderModule != DE_NULL || teseShaderModuleId.ptr);
844 	const bool hasGeom = (geometryShaderModule != DE_NULL || geomShaderModuleId.ptr);
845 
846 	const auto pRasterizationState = rasterizationState ? rasterizationState
847 														: (m_internalData->useDefaultRasterizationState ? &m_internalData->defaultRasterizationState : DE_NULL);
848 	const auto pTessellationState	= (hasTesc || hasTese) ? &m_internalData->tessellationState : DE_NULL;
849 	const auto pViewportState		= m_internalData->useViewportState ? &m_internalData->viewportState : DE_NULL;
850 
851 	VkPipelineCreateFlags shaderModuleIdFlags = 0u;
852 
853 	// reserve space for all stages including fragment - this is needed when we create monolithic pipeline
854 	m_internalData->pipelineShaderStages = std::vector<VkPipelineShaderStageCreateInfo>(2u + hasTesc + hasTese + hasGeom,
855 	{
856 		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType
857 		DE_NULL,												// const void*							pNext
858 		0u,														// VkPipelineShaderStageCreateFlags		flags
859 		VK_SHADER_STAGE_VERTEX_BIT,								// VkShaderStageFlagBits				stage
860 		vertexShaderModule,										// VkShaderModule						module
861 		"main",													// const char*							pName
862 		vertSpecializationInfo									// const VkSpecializationInfo*			pSpecializationInfo
863 	});
864 
865 #ifndef CTS_USES_VULKANSC
866 	if (vertShaderModuleId.ptr)
867 	{
868 		m_internalData->pipelineShaderIdentifiers.emplace_back(new PipelineShaderStageModuleIdentifierCreateInfoWrapper(vertShaderModuleId.ptr));
869 		m_internalData->pipelineShaderStages[0].pNext = m_internalData->pipelineShaderIdentifiers.back().get()->ptr;
870 
871 		if (vertexShaderModule == DE_NULL)
872 			shaderModuleIdFlags |= VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT;
873 	}
874 #endif // CTS_USES_VULKANSC
875 
876 	std::vector<VkPipelineShaderStageCreateInfo>::iterator currStage = m_internalData->pipelineShaderStages.begin() + 1;
877 
878 	if (hasTesc)
879 	{
880 		currStage->stage				= VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
881 		currStage->module				= tessellationControlShaderModule;
882 		currStage->pSpecializationInfo	= tescSpecializationInfo;
883 
884 #ifndef CTS_USES_VULKANSC
885 		if (tescShaderModuleId.ptr)
886 		{
887 			m_internalData->pipelineShaderIdentifiers.emplace_back(new PipelineShaderStageModuleIdentifierCreateInfoWrapper(tescShaderModuleId.ptr));
888 			currStage->pNext = m_internalData->pipelineShaderIdentifiers.back().get()->ptr;
889 
890 			if (tessellationControlShaderModule == DE_NULL)
891 				shaderModuleIdFlags |= VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT;
892 		}
893 #endif // CTS_USES_VULKANSC
894 
895 		++currStage;
896 	}
897 
898 	if (hasTese)
899 	{
900 		currStage->stage				= VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
901 		currStage->module				= tessellationEvalShaderModule;
902 		currStage->pSpecializationInfo	= teseSpecializationInfo;
903 
904 #ifndef CTS_USES_VULKANSC
905 		if (teseShaderModuleId.ptr)
906 		{
907 			m_internalData->pipelineShaderIdentifiers.emplace_back(new PipelineShaderStageModuleIdentifierCreateInfoWrapper(teseShaderModuleId.ptr));
908 			currStage->pNext = m_internalData->pipelineShaderIdentifiers.back().get()->ptr;
909 
910 			if (tessellationEvalShaderModule == DE_NULL)
911 				shaderModuleIdFlags |= VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT;
912 		}
913 #endif // CTS_USES_VULKANSC
914 
915 		++currStage;
916 	}
917 
918 	if (hasGeom)
919 	{
920 		currStage->stage				= VK_SHADER_STAGE_GEOMETRY_BIT;
921 		currStage->module				= geometryShaderModule;
922 		currStage->pSpecializationInfo	= geomSpecializationInfo;
923 
924 #ifndef CTS_USES_VULKANSC
925 		if (geomShaderModuleId.ptr)
926 		{
927 			m_internalData->pipelineShaderIdentifiers.emplace_back(new PipelineShaderStageModuleIdentifierCreateInfoWrapper(geomShaderModuleId.ptr));
928 			currStage->pNext = m_internalData->pipelineShaderIdentifiers.back().get()->ptr;
929 
930 			if (geometryShaderModule == DE_NULL)
931 				shaderModuleIdFlags |= VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT;
932 		}
933 #endif // CTS_USES_VULKANSC
934 	}
935 
936 	if (pViewportState)
937 	{
938 		if (!viewports.empty())
939 		{
940 			pViewportState->viewportCount	= (deUint32)viewports.size();
941 			pViewportState->pViewports		= &viewports[0];
942 		}
943 		if (!scissors.empty())
944 		{
945 			pViewportState->scissorCount	= (deUint32)scissors.size();
946 			pViewportState->pScissors		= &scissors[0];
947 		}
948 	}
949 
950 	if (m_internalData->pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
951 	{
952 		// make sure we dont overwrite layout specified with setupMonolithicPipelineLayout
953 		if (m_internalData->monolithicPipelineCreateInfo.layout == 0)
954 			m_internalData->monolithicPipelineCreateInfo.layout = layout;
955 
956 		m_internalData->monolithicPipelineCreateInfo.renderPass				= renderPass;
957 		m_internalData->monolithicPipelineCreateInfo.subpass				= subpass;
958 		m_internalData->monolithicPipelineCreateInfo.pRasterizationState	= pRasterizationState;
959 		m_internalData->monolithicPipelineCreateInfo.pViewportState			= pViewportState;
960 		m_internalData->monolithicPipelineCreateInfo.stageCount				= 1u + hasTesc + hasTese + hasGeom;
961 		m_internalData->monolithicPipelineCreateInfo.pStages				= m_internalData->pipelineShaderStages.data();
962 		m_internalData->monolithicPipelineCreateInfo.pTessellationState		= pTessellationState;
963 		m_internalData->monolithicPipelineCreateInfo.flags					|= shaderModuleIdFlags;
964 	}
965 
966 #ifndef CTS_USES_VULKANSC
967 	// note we could just use else to if statement above but sinc
968 	// this section is cut out for Vulkan SC its cleaner with separate if
969 	if (m_internalData->pipelineConstructionType != PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
970 	{
971 		auto	libraryCreateInfo	= makeGraphicsPipelineLibraryCreateInfo(VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT);
972 		void*	firstStructInChain	= reinterpret_cast<void*>(&libraryCreateInfo);
973 		addToChain(&firstStructInChain, m_internalData->pFragmentShadingRateState);
974 		addToChain(&firstStructInChain, m_internalData->pRenderingState.ptr);
975 		addToChain(&firstStructInChain, partCreationFeedback.ptr);
976 
977 		VkPipelineDynamicStateCreateInfo pickedDynamicStateInfo = initVulkanStructure();
978 		std::vector<VkDynamicState> states;
979 
980 		if(m_internalData->pDynamicState)
981 		{
982 			states = getDynamicStates(m_internalData->pDynamicState, m_internalData->setupState);
983 
984 			pickedDynamicStateInfo.pDynamicStates = states.data();
985 			pickedDynamicStateInfo.dynamicStateCount = static_cast<uint32_t>(states.size());
986 		}
987 
988 		VkGraphicsPipelineCreateInfo pipelinePartCreateInfo = initVulkanStructure();
989 		pipelinePartCreateInfo.pNext				= firstStructInChain;
990 		pipelinePartCreateInfo.flags				= (m_internalData->pipelineFlags | VK_PIPELINE_CREATE_LIBRARY_BIT_KHR | shaderModuleIdFlags) & ~VK_PIPELINE_CREATE_DERIVATIVE_BIT;
991 		pipelinePartCreateInfo.layout				= layout;
992 		pipelinePartCreateInfo.renderPass			= renderPass;
993 		pipelinePartCreateInfo.subpass				= subpass;
994 		pipelinePartCreateInfo.pRasterizationState	= pRasterizationState;
995 		pipelinePartCreateInfo.pViewportState		= pViewportState;
996 		pipelinePartCreateInfo.stageCount			= 1u + hasTesc + hasTese + hasGeom;
997 		pipelinePartCreateInfo.pStages				= m_internalData->pipelineShaderStages.data();
998 		pipelinePartCreateInfo.pTessellationState	= pTessellationState;
999 		pipelinePartCreateInfo.pDynamicState		= &pickedDynamicStateInfo;
1000 
1001 		if (m_internalData->pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_LINK_TIME_OPTIMIZED_LIBRARY)
1002 			pipelinePartCreateInfo.flags |= VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT;
1003 
1004 		if ((shaderModuleIdFlags & VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT) != 0)
1005 			m_internalData->failOnCompileWhenLinking = true;
1006 
1007 		m_pipelineParts[1] = makeGraphicsPipeline(m_internalData->vk, m_internalData->device, partPipelineCache, &pipelinePartCreateInfo);
1008 	}
1009 #endif // CTS_USES_VULKANSC
1010 
1011 	return *this;
1012 }
1013 
1014 #ifndef CTS_USES_VULKANSC
setupPreRasterizationMeshShaderState(const std::vector<VkViewport> & viewports,const std::vector<VkRect2D> & scissors,const VkPipelineLayout layout,const VkRenderPass renderPass,const deUint32 subpass,const VkShaderModule taskShaderModule,const VkShaderModule meshShaderModule,const VkPipelineRasterizationStateCreateInfo * rasterizationState,const VkSpecializationInfo * taskSpecializationInfo,const VkSpecializationInfo * meshSpecializationInfo,VkPipelineFragmentShadingRateStateCreateInfoKHR * fragmentShadingRateState,PipelineRenderingCreateInfoWrapper rendering,const VkPipelineCache partPipelineCache,VkPipelineCreationFeedbackCreateInfoEXT * partCreationFeedback)1015 GraphicsPipelineWrapper& GraphicsPipelineWrapper::setupPreRasterizationMeshShaderState(const std::vector<VkViewport>&					viewports,
1016 																					   const std::vector<VkRect2D>&						scissors,
1017 																					   const VkPipelineLayout							layout,
1018 																					   const VkRenderPass								renderPass,
1019 																					   const deUint32									subpass,
1020 																					   const VkShaderModule								taskShaderModule,
1021 																					   const VkShaderModule								meshShaderModule,
1022 																					   const VkPipelineRasterizationStateCreateInfo*	rasterizationState,
1023 																					   const VkSpecializationInfo						*taskSpecializationInfo,
1024 																					   const VkSpecializationInfo						*meshSpecializationInfo,
1025 																					   VkPipelineFragmentShadingRateStateCreateInfoKHR*	fragmentShadingRateState,
1026 																					   PipelineRenderingCreateInfoWrapper				rendering,
1027 																					   const VkPipelineCache							partPipelineCache,
1028 																					   VkPipelineCreationFeedbackCreateInfoEXT			*partCreationFeedback)
1029 {
1030 	// Make sure pipeline was not already built.
1031 	DE_ASSERT(m_pipelineFinal.get() == DE_NULL);
1032 
1033 	// Make sure states are set in order - this state needs to be set first or second.
1034 	DE_ASSERT(m_internalData && (m_internalData->setupState < PSS_PRE_RASTERIZATION_SHADERS));
1035 
1036 	// The vertex input interface is not needed for mesh shading pipelines, so we're going to mark it as ready here.
1037 	m_internalData->setupState					|= (PSS_VERTEX_INPUT_INTERFACE | PSS_PRE_RASTERIZATION_SHADERS);
1038 	m_internalData->pFragmentShadingRateState	= fragmentShadingRateState;
1039 	m_internalData->pRenderingState				= rendering;
1040 
1041 	const bool hasTask				= (taskShaderModule != DE_NULL);
1042 	const auto taskShaderCount		= static_cast<uint32_t>(hasTask);
1043 	const auto pRasterizationState	= rasterizationState
1044 									? rasterizationState
1045 									: (m_internalData->useDefaultRasterizationState
1046 										? &m_internalData->defaultRasterizationState
1047 										: nullptr);
1048 	const auto pTessellationState	= nullptr;
1049 	const auto pViewportState		= m_internalData->useViewportState ? &m_internalData->viewportState : DE_NULL;
1050 
1051 	// Reserve space for all stages including fragment. This is needed when we create monolithic pipeline.
1052 	m_internalData->pipelineShaderStages = std::vector<VkPipelineShaderStageCreateInfo>(2u + taskShaderCount,
1053 	{
1054 		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType
1055 		nullptr,												// const void*							pNext
1056 		0u,														// VkPipelineShaderStageCreateFlags		flags
1057 		VK_SHADER_STAGE_VERTEX_BIT,								// VkShaderStageFlagBits				stage
1058 		DE_NULL,												// VkShaderModule						module
1059 		"main",													// const char*							pName
1060 		nullptr,												// const VkSpecializationInfo*			pSpecializationInfo
1061 	});
1062 
1063 	// Mesh shader.
1064 	auto currStage = m_internalData->pipelineShaderStages.begin();
1065 	{
1066 		auto& stageInfo = *currStage;
1067 
1068 		stageInfo.stage					= VK_SHADER_STAGE_MESH_BIT_EXT;
1069 		stageInfo.module				= meshShaderModule;
1070 		stageInfo.pSpecializationInfo	= meshSpecializationInfo;
1071 
1072 		++currStage;
1073 	}
1074 
1075 	if (hasTask)
1076 	{
1077 		auto& stageInfo = *currStage;
1078 
1079 		stageInfo.stage					= VK_SHADER_STAGE_TASK_BIT_EXT;
1080 		stageInfo.module				= taskShaderModule;
1081 		stageInfo.pSpecializationInfo	= taskSpecializationInfo;
1082 
1083 		++currStage;
1084 	}
1085 
1086 	if (pViewportState)
1087 	{
1088 		if (!viewports.empty())
1089 		{
1090 			pViewportState->viewportCount	= (deUint32)viewports.size();
1091 			pViewportState->pViewports		= &viewports[0];
1092 		}
1093 		if (!scissors.empty())
1094 		{
1095 			pViewportState->scissorCount	= (deUint32)scissors.size();
1096 			pViewportState->pScissors		= &scissors[0];
1097 		}
1098 	}
1099 
1100 	if (m_internalData->pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
1101 	{
1102 		// make sure we dont overwrite layout specified with setupMonolithicPipelineLayout
1103 		if (m_internalData->monolithicPipelineCreateInfo.layout == 0)
1104 			m_internalData->monolithicPipelineCreateInfo.layout = layout;
1105 
1106 		m_internalData->monolithicPipelineCreateInfo.renderPass				= renderPass;
1107 		m_internalData->monolithicPipelineCreateInfo.subpass				= subpass;
1108 		m_internalData->monolithicPipelineCreateInfo.pRasterizationState	= pRasterizationState;
1109 		m_internalData->monolithicPipelineCreateInfo.pViewportState			= pViewportState;
1110 		m_internalData->monolithicPipelineCreateInfo.stageCount				= 1u + taskShaderCount;
1111 		m_internalData->monolithicPipelineCreateInfo.pStages				= m_internalData->pipelineShaderStages.data();
1112 		m_internalData->monolithicPipelineCreateInfo.pTessellationState		= pTessellationState;
1113 	}
1114 	else
1115 	{
1116 		auto	libraryCreateInfo	= makeGraphicsPipelineLibraryCreateInfo(VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT);
1117 		void*	firstStructInChain	= reinterpret_cast<void*>(&libraryCreateInfo);
1118 		addToChain(&firstStructInChain, m_internalData->pFragmentShadingRateState);
1119 		addToChain(&firstStructInChain, m_internalData->pRenderingState.ptr);
1120 		addToChain(&firstStructInChain, partCreationFeedback);
1121 
1122 		VkPipelineDynamicStateCreateInfo pickedDynamicStateInfo = initVulkanStructure();
1123 		std::vector<VkDynamicState> states;
1124 
1125 		if(m_internalData->pDynamicState)
1126 		{
1127 			states = getDynamicStates(m_internalData->pDynamicState, m_internalData->setupState);
1128 
1129 			pickedDynamicStateInfo.pDynamicStates = states.data();
1130 			pickedDynamicStateInfo.dynamicStateCount = static_cast<uint32_t>(states.size());
1131 		}
1132 
1133 
1134 		VkGraphicsPipelineCreateInfo pipelinePartCreateInfo = initVulkanStructure();
1135 		pipelinePartCreateInfo.pNext			= firstStructInChain;
1136 		pipelinePartCreateInfo.flags			= m_internalData->pipelineFlags | VK_PIPELINE_CREATE_LIBRARY_BIT_KHR;
1137 		pipelinePartCreateInfo.layout				= layout;
1138 		pipelinePartCreateInfo.renderPass			= renderPass;
1139 		pipelinePartCreateInfo.subpass				= subpass;
1140 		pipelinePartCreateInfo.pRasterizationState	= pRasterizationState;
1141 		pipelinePartCreateInfo.pViewportState		= pViewportState;
1142 		pipelinePartCreateInfo.stageCount			= 1u + taskShaderCount;
1143 		pipelinePartCreateInfo.pStages				= m_internalData->pipelineShaderStages.data();
1144 		pipelinePartCreateInfo.pTessellationState	= pTessellationState;
1145 		pipelinePartCreateInfo.pDynamicState		= &pickedDynamicStateInfo;
1146 
1147 		if (m_internalData->pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_LINK_TIME_OPTIMIZED_LIBRARY)
1148 			pipelinePartCreateInfo.flags |= VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT;
1149 
1150 		m_pipelineParts[1] = createGraphicsPipeline(m_internalData->vk, m_internalData->device, partPipelineCache, &pipelinePartCreateInfo);
1151 	}
1152 
1153 	return *this;
1154 }
1155 #endif // CTS_USES_VULKANSC
1156 
setupFragmentShaderState(const VkPipelineLayout layout,const VkRenderPass renderPass,const deUint32 subpass,const VkShaderModule fragmentShaderModule,const VkPipelineDepthStencilStateCreateInfo * depthStencilState,const VkPipelineMultisampleStateCreateInfo * multisampleState,const VkSpecializationInfo * specializationInfo,const VkPipelineCache partPipelineCache,PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback)1157 GraphicsPipelineWrapper& GraphicsPipelineWrapper::setupFragmentShaderState(const VkPipelineLayout							layout,
1158 																		   const VkRenderPass								renderPass,
1159 																		   const deUint32									subpass,
1160 																		   const VkShaderModule								fragmentShaderModule,
1161 																		   const VkPipelineDepthStencilStateCreateInfo*		depthStencilState,
1162 																		   const VkPipelineMultisampleStateCreateInfo*		multisampleState,
1163 																		   const VkSpecializationInfo*						specializationInfo,
1164 																		   const VkPipelineCache							partPipelineCache,
1165 																		   PipelineCreationFeedbackCreateInfoWrapper		partCreationFeedback)
1166 {
1167 	return setupFragmentShaderState2(layout,
1168 									 renderPass,
1169 									 subpass,
1170 									 fragmentShaderModule,
1171 									 PipelineShaderStageModuleIdentifierCreateInfoWrapper(),
1172 									 depthStencilState,
1173 									 multisampleState,
1174 									 specializationInfo,
1175 									 partPipelineCache,
1176 									 partCreationFeedback);
1177 }
1178 
setupFragmentShaderState2(const VkPipelineLayout layout,const VkRenderPass renderPass,const deUint32 subpass,const VkShaderModule fragmentShaderModule,PipelineShaderStageModuleIdentifierCreateInfoWrapper fragmentShaderModuleId,const VkPipelineDepthStencilStateCreateInfo * depthStencilState,const VkPipelineMultisampleStateCreateInfo * multisampleState,const VkSpecializationInfo * specializationInfo,const VkPipelineCache partPipelineCache,PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback)1179 GraphicsPipelineWrapper& GraphicsPipelineWrapper::setupFragmentShaderState2(const VkPipelineLayout										layout,
1180 																			const VkRenderPass											renderPass,
1181 																			const deUint32												subpass,
1182 																			const VkShaderModule										fragmentShaderModule,
1183 																			PipelineShaderStageModuleIdentifierCreateInfoWrapper		fragmentShaderModuleId,
1184 																			const VkPipelineDepthStencilStateCreateInfo*				depthStencilState,
1185 																			const VkPipelineMultisampleStateCreateInfo*					multisampleState,
1186 																			const VkSpecializationInfo*									specializationInfo,
1187 																			const VkPipelineCache										partPipelineCache,
1188 																			PipelineCreationFeedbackCreateInfoWrapper					partCreationFeedback)
1189 {
1190 	// make sure pipeline was not already build
1191 	DE_ASSERT(m_pipelineFinal.get() == DE_NULL);
1192 
1193 	// make sure states are set in order - no need to complicate logic to support out of order specification - this state needs to be set third
1194 	DE_ASSERT(m_internalData && (m_internalData->setupState == (PSS_VERTEX_INPUT_INTERFACE | PSS_PRE_RASTERIZATION_SHADERS)));
1195 
1196 	// Unreference variables that are not used in Vulkan SC. No need to put this in ifdef.
1197 	DE_UNREF(layout);
1198 	DE_UNREF(renderPass);
1199 	DE_UNREF(subpass);
1200 	DE_UNREF(partPipelineCache);
1201 	DE_UNREF(partCreationFeedback);
1202 	DE_UNREF(fragmentShaderModuleId);
1203 
1204 	m_internalData->setupState |= PSS_FRAGMENT_SHADER;
1205 
1206 	const auto pDepthStencilState	= depthStencilState ? depthStencilState
1207 														: (m_internalData->useDefaultDepthStencilState ? &defaultDepthStencilState : DE_NULL);
1208 	const auto pMultisampleState	= multisampleState ? multisampleState
1209 														: (m_internalData->useDefaultMultisampleState ? &defaultMultisampleState : DE_NULL);
1210 	const bool hasFrag				= (fragmentShaderModule != DE_NULL || fragmentShaderModuleId.ptr);
1211 
1212 	VkPipelineCreateFlags shaderModuleIdFlags = 0u;
1213 
1214 	deUint32 stageIndex = 1;
1215 	if (hasFrag)
1216 	{
1217 		// find free space for fragment shader
1218 		for (; stageIndex < 5; ++stageIndex)
1219 		{
1220 			if (m_internalData->pipelineShaderStages[stageIndex].stage == VK_SHADER_STAGE_VERTEX_BIT)
1221 			{
1222 				m_internalData->pipelineShaderStages[stageIndex].stage					= VK_SHADER_STAGE_FRAGMENT_BIT;
1223 				m_internalData->pipelineShaderStages[stageIndex].module					= fragmentShaderModule;
1224 				m_internalData->pipelineShaderStages[stageIndex].pSpecializationInfo	= specializationInfo;
1225 #ifndef CTS_USES_VULKANSC
1226 				if (fragmentShaderModuleId.ptr)
1227 				{
1228 					m_internalData->pipelineShaderIdentifiers.emplace_back(new PipelineShaderStageModuleIdentifierCreateInfoWrapper(fragmentShaderModuleId.ptr));
1229 					m_internalData->pipelineShaderStages[stageIndex].pNext = m_internalData->pipelineShaderIdentifiers.back().get()->ptr;
1230 
1231 					if (fragmentShaderModule == DE_NULL)
1232 						shaderModuleIdFlags |= VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT;
1233 				}
1234 #endif // CTS_USES_VULKANSC
1235 				break;
1236 			}
1237 		}
1238 	}
1239 
1240 	if (m_internalData->pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
1241 	{
1242 		m_internalData->monolithicPipelineCreateInfo.pDepthStencilState	= pDepthStencilState;
1243 		m_internalData->monolithicPipelineCreateInfo.pMultisampleState	= pMultisampleState;
1244 		m_internalData->monolithicPipelineCreateInfo.stageCount			+= (hasFrag ? 1u : 0u);
1245 		m_internalData->monolithicPipelineCreateInfo.flags				|= shaderModuleIdFlags;
1246 	}
1247 
1248 #ifndef CTS_USES_VULKANSC
1249 	// note we could just use else to if statement above but sinc
1250 	// this section is cut out for Vulkan SC its cleaner with separate if
1251 	if (m_internalData->pipelineConstructionType != PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
1252 	{
1253 		auto	libraryCreateInfo	= makeGraphicsPipelineLibraryCreateInfo(VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT);
1254 		void*	firstStructInChain	= reinterpret_cast<void*>(&libraryCreateInfo);
1255 		addToChain(&firstStructInChain, m_internalData->pFragmentShadingRateState);
1256 		addToChain(&firstStructInChain, m_internalData->pRenderingState.ptr);
1257 		addToChain(&firstStructInChain, partCreationFeedback.ptr);
1258 		addToChain(&firstStructInChain, m_internalData->pRepresentativeFragmentTestState.ptr);
1259 
1260 		VkPipelineDynamicStateCreateInfo pickedDynamicStateInfo = initVulkanStructure();
1261 		std::vector<VkDynamicState> states;
1262 
1263 		if(m_internalData->pDynamicState)
1264 		{
1265 			states = getDynamicStates(m_internalData->pDynamicState, m_internalData->setupState);
1266 
1267 			pickedDynamicStateInfo.pDynamicStates = states.data();
1268 			pickedDynamicStateInfo.dynamicStateCount = static_cast<uint32_t>(states.size());
1269 		}
1270 
1271 
1272 		VkGraphicsPipelineCreateInfo pipelinePartCreateInfo = initVulkanStructure();
1273 		pipelinePartCreateInfo.pNext				= firstStructInChain;
1274 		pipelinePartCreateInfo.flags				= (m_internalData->pipelineFlags | VK_PIPELINE_CREATE_LIBRARY_BIT_KHR | shaderModuleIdFlags) & ~VK_PIPELINE_CREATE_DERIVATIVE_BIT;
1275 		pipelinePartCreateInfo.layout				= layout;
1276 		pipelinePartCreateInfo.renderPass			= renderPass;
1277 		pipelinePartCreateInfo.subpass				= subpass;
1278 		pipelinePartCreateInfo.pDepthStencilState	= pDepthStencilState;
1279 		pipelinePartCreateInfo.pMultisampleState	= pMultisampleState;
1280 		pipelinePartCreateInfo.stageCount			= hasFrag;
1281 		pipelinePartCreateInfo.pStages				= hasFrag ? &m_internalData->pipelineShaderStages[stageIndex] : DE_NULL;
1282 		pipelinePartCreateInfo.pDynamicState		= &pickedDynamicStateInfo;
1283 
1284 		if (m_internalData->pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_LINK_TIME_OPTIMIZED_LIBRARY)
1285 			pipelinePartCreateInfo.flags |= VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT;
1286 
1287 		if ((shaderModuleIdFlags & VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT) != 0)
1288 			m_internalData->failOnCompileWhenLinking = true;
1289 
1290 		m_pipelineParts[2] = makeGraphicsPipeline(m_internalData->vk, m_internalData->device, partPipelineCache, &pipelinePartCreateInfo);
1291 	}
1292 #endif // CTS_USES_VULKANSC
1293 
1294 	return *this;
1295 }
1296 
setupFragmentOutputState(const VkRenderPass renderPass,const deUint32 subpass,const VkPipelineColorBlendStateCreateInfo * colorBlendState,const VkPipelineMultisampleStateCreateInfo * multisampleState,const VkPipelineCache partPipelineCache,PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback)1297 GraphicsPipelineWrapper& GraphicsPipelineWrapper::setupFragmentOutputState(const VkRenderPass								renderPass,
1298 																		   const deUint32									subpass,
1299 																		   const VkPipelineColorBlendStateCreateInfo*		colorBlendState,
1300 																		   const VkPipelineMultisampleStateCreateInfo*		multisampleState,
1301 																		   const VkPipelineCache							partPipelineCache,
1302 																		   PipelineCreationFeedbackCreateInfoWrapper		partCreationFeedback)
1303 {
1304 	// make sure pipeline was not already build
1305 	DE_ASSERT(m_pipelineFinal.get() == DE_NULL);
1306 
1307 	// make sure states are set in order - no need to complicate logic to support out of order specification - this state needs to be set last
1308 	DE_ASSERT(m_internalData && (m_internalData->setupState == (PSS_VERTEX_INPUT_INTERFACE | PSS_PRE_RASTERIZATION_SHADERS | PSS_FRAGMENT_SHADER)));
1309 	m_internalData->setupState |= PSS_FRAGMENT_OUTPUT_INTERFACE;
1310 
1311 	// Unreference variables that are not used in Vulkan SC. No need to put this in ifdef.
1312 	DE_UNREF(renderPass);
1313 	DE_UNREF(subpass);
1314 	DE_UNREF(partPipelineCache);
1315 	DE_UNREF(partCreationFeedback);
1316 
1317 	void* firstStructInChain = DE_NULL;
1318 	addToChain(&firstStructInChain, m_internalData->pFragmentShadingRateState);
1319 
1320 #ifndef CTS_USES_VULKANSC
1321 	addToChain(&firstStructInChain, m_internalData->pRenderingState.ptr);
1322 #endif // CTS_USES_VULKANSC
1323 
1324 	const auto pColorBlendState		= colorBlendState ? colorBlendState
1325 														: (m_internalData->useDefaultColorBlendState ? &defaultColorBlendState : DE_NULL);
1326 	const auto pMultisampleState	= multisampleState ? multisampleState
1327 														: (m_internalData->useDefaultMultisampleState ? &defaultMultisampleState : DE_NULL);
1328 
1329 	if (m_internalData->pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
1330 	{
1331 		m_internalData->monolithicPipelineCreateInfo.pNext				= firstStructInChain;
1332 		m_internalData->monolithicPipelineCreateInfo.flags				|= m_internalData->pipelineFlags;
1333 		m_internalData->monolithicPipelineCreateInfo.pColorBlendState	= pColorBlendState;
1334 		m_internalData->monolithicPipelineCreateInfo.pMultisampleState	= pMultisampleState;
1335 	}
1336 
1337 #ifndef CTS_USES_VULKANSC
1338 	// note we could just use else to if statement above but sinc
1339 	// this section is cut out for Vulkan SC its cleaner with separate if
1340 	if (m_internalData->pipelineConstructionType != PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
1341 	{
1342 		auto libraryCreateInfo = makeGraphicsPipelineLibraryCreateInfo(VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT);
1343 		addToChain(&firstStructInChain, &libraryCreateInfo);
1344 		addToChain(&firstStructInChain, partCreationFeedback.ptr);
1345 
1346 
1347 		VkPipelineDynamicStateCreateInfo pickedDynamicStateInfo = initVulkanStructure();
1348 		std::vector<VkDynamicState> states;
1349 
1350 		if(m_internalData->pDynamicState)
1351 		{
1352 			states = getDynamicStates(m_internalData->pDynamicState, m_internalData->setupState);
1353 
1354 			pickedDynamicStateInfo.pDynamicStates = states.data();
1355 			pickedDynamicStateInfo.dynamicStateCount = static_cast<uint32_t>(states.size());
1356 		}
1357 
1358 
1359 		VkGraphicsPipelineCreateInfo pipelinePartCreateInfo = initVulkanStructure();
1360 		pipelinePartCreateInfo.pNext				= firstStructInChain;
1361 		pipelinePartCreateInfo.flags				= (m_internalData->pipelineFlags | VK_PIPELINE_CREATE_LIBRARY_BIT_KHR) & ~VK_PIPELINE_CREATE_DERIVATIVE_BIT;
1362 		pipelinePartCreateInfo.renderPass			= renderPass;
1363 		pipelinePartCreateInfo.subpass				= subpass;
1364 		pipelinePartCreateInfo.pColorBlendState		= pColorBlendState;
1365 		pipelinePartCreateInfo.pMultisampleState	= pMultisampleState;
1366 		pipelinePartCreateInfo.pDynamicState		= &pickedDynamicStateInfo;
1367 
1368 		if (m_internalData->pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_LINK_TIME_OPTIMIZED_LIBRARY)
1369 			pipelinePartCreateInfo.flags |= VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT;
1370 
1371 		m_pipelineParts[3] = makeGraphicsPipeline(m_internalData->vk, m_internalData->device, partPipelineCache, &pipelinePartCreateInfo);
1372 	}
1373 #endif // CTS_USES_VULKANSC
1374 
1375 	return *this;
1376 }
1377 
buildPipeline(const VkPipelineCache pipelineCache,const VkPipeline basePipelineHandle,const deInt32 basePipelineIndex,PipelineCreationFeedbackCreateInfoWrapper creationFeedback)1378 void GraphicsPipelineWrapper::buildPipeline(const VkPipelineCache						pipelineCache,
1379 											const VkPipeline							basePipelineHandle,
1380 											const deInt32								basePipelineIndex,
1381 											PipelineCreationFeedbackCreateInfoWrapper	creationFeedback)
1382 {
1383 	// make sure we are not trying to build pipeline second time
1384 	DE_ASSERT(m_pipelineFinal.get() == DE_NULL);
1385 
1386 	// make sure all states were set
1387 	DE_ASSERT(m_internalData && (m_internalData->setupState == (PSS_VERTEX_INPUT_INTERFACE | PSS_PRE_RASTERIZATION_SHADERS |
1388 																PSS_FRAGMENT_SHADER | PSS_FRAGMENT_OUTPUT_INTERFACE)));
1389 
1390 	// Unreference variables that are not used in Vulkan SC. No need to put this in ifdef.
1391 	DE_UNREF(creationFeedback);
1392 
1393 	VkGraphicsPipelineCreateInfo*	pointerToCreateInfo	= &m_internalData->monolithicPipelineCreateInfo;
1394 
1395 #ifndef CTS_USES_VULKANSC
1396 	VkGraphicsPipelineCreateInfo	linkedCreateInfo	= initVulkanStructure();
1397 	std::vector<VkPipeline>			rawPipelines;
1398 	VkPipelineLibraryCreateInfoKHR	linkingInfo
1399 	{
1400 		VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR,		// VkStructureType		sType;
1401 		creationFeedback.ptr,									// const void*			pNext;
1402 		0u,														// deUint32				libraryCount;
1403 		nullptr,												// const VkPipeline*	pLibraries;
1404 	};
1405 
1406 	if (m_internalData->pipelineConstructionType != PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
1407 	{
1408 		for (const auto& pipelinePtr : m_pipelineParts)
1409 		{
1410 			const auto& pipeline = pipelinePtr.get();
1411 			if (pipeline != DE_NULL)
1412 				rawPipelines.push_back(pipeline);
1413 		}
1414 
1415 		linkingInfo.libraryCount	= static_cast<uint32_t>(rawPipelines.size());
1416 		linkingInfo.pLibraries		= de::dataOrNull(rawPipelines);
1417 
1418 		linkedCreateInfo.flags		= m_internalData->pipelineFlags;
1419 		linkedCreateInfo.layout		= m_internalData->monolithicPipelineCreateInfo.layout;
1420 		linkedCreateInfo.pNext		= &linkingInfo;
1421 
1422 		pointerToCreateInfo			= &linkedCreateInfo;
1423 
1424 		if (m_internalData->pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_LINK_TIME_OPTIMIZED_LIBRARY)
1425 			linkedCreateInfo.flags |= VK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXT;
1426 
1427 		if (m_internalData->failOnCompileWhenLinking)
1428 			linkedCreateInfo.flags |= VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT;
1429 	}
1430 	else
1431 	{
1432 		// note: there might be other structures in the chain already
1433 		void* firstStructInChain = static_cast<void*>(pointerToCreateInfo);
1434 		addToChain(&firstStructInChain, creationFeedback.ptr);
1435 		addToChain(&firstStructInChain, m_internalData->pRepresentativeFragmentTestState.ptr);
1436 	}
1437 #endif // CTS_USES_VULKANSC
1438 
1439 	pointerToCreateInfo->basePipelineHandle	= basePipelineHandle;
1440 	pointerToCreateInfo->basePipelineIndex	= basePipelineIndex;
1441 
1442 	m_pipelineFinal = makeGraphicsPipeline(m_internalData->vk, m_internalData->device, pipelineCache, pointerToCreateInfo);
1443 
1444 	// pipeline was created - we can free CreateInfo structures
1445 	m_internalData.clear();
1446 }
1447 
wasBuild() const1448 deBool GraphicsPipelineWrapper::wasBuild() const
1449 {
1450 	return !!m_pipelineFinal.get();
1451 }
1452 
getPipeline() const1453 VkPipeline GraphicsPipelineWrapper::getPipeline() const
1454 {
1455 	DE_ASSERT(m_pipelineFinal.get() != DE_NULL);
1456 	return m_pipelineFinal.get();
1457 }
1458 
destroyPipeline(void)1459 void GraphicsPipelineWrapper::destroyPipeline(void)
1460 {
1461 	DE_ASSERT(m_pipelineFinal.get() != DE_NULL);
1462 
1463 	m_pipelineFinal = Move<VkPipeline>();
1464 }
1465 
1466 } // vk
1467