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