1 #ifndef _VKPIPELINECONSTRUCTIONUTIL_HPP 2 #define _VKPIPELINECONSTRUCTIONUTIL_HPP 3 /*------------------------------------------------------------------------ 4 * Vulkan Conformance Tests 5 * ------------------------ 6 * 7 * Copyright (c) 2021 The Khronos Group Inc. 8 * Copyright (c) 2023 LunarG, Inc. 9 * Copyright (c) 2023 Nintendo 10 * 11 * Licensed under the Apache License, Version 2.0 (the "License"); 12 * you may not use this file except in compliance with the License. 13 * You may obtain a copy of the License at 14 * 15 * http://www.apache.org/licenses/LICENSE-2.0 16 * 17 * Unless required by applicable law or agreed to in writing, software 18 * distributed under the License is distributed on an "AS IS" BASIS, 19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 * See the License for the specific language governing permissions and 21 * limitations under the License. 22 * 23 *//*! 24 * \file 25 * \brief Wrapper that can construct monolithic pipeline or use 26 VK_EXT_graphics_pipeline_library for pipeline construction or use 27 VK_EXT_shader_object for shader objects. 28 *//*--------------------------------------------------------------------*/ 29 30 #include "vkRef.hpp" 31 #include "vkDefs.hpp" 32 #include "tcuDefs.hpp" 33 #include "deSharedPtr.hpp" 34 #include "vkPrograms.hpp" 35 #include "vkShaderObjectUtil.hpp" 36 #include <vector> 37 #include <stdexcept> 38 39 namespace vk 40 { 41 42 enum PipelineConstructionType 43 { 44 PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC = 0, // Construct legacy - monolithic pipeline 45 PIPELINE_CONSTRUCTION_TYPE_LINK_TIME_OPTIMIZED_LIBRARY, // Use VK_EXT_graphics_pipeline_library and construct pipeline out of several pipeline parts. 46 PIPELINE_CONSTRUCTION_TYPE_FAST_LINKED_LIBRARY, // Same as PIPELINE_CONSTRUCTION_TYPE_OPTIMISED_LIBRARY but with fast linking 47 PIPELINE_CONSTRUCTION_TYPE_SHADER_OBJECT_UNLINKED_SPIRV, // Use VK_EXT_shader_object unlinked shader objects from spirv 48 PIPELINE_CONSTRUCTION_TYPE_SHADER_OBJECT_UNLINKED_BINARY, // Use VK_EXT_shader_object unlinked shader objects from binary 49 PIPELINE_CONSTRUCTION_TYPE_SHADER_OBJECT_LINKED_SPIRV, // Use VK_EXT_shader_object linked shader objects from spirv 50 PIPELINE_CONSTRUCTION_TYPE_SHADER_OBJECT_LINKED_BINARY, // Use VK_EXT_shader_object linked shader objects from binary 51 }; 52 53 bool isConstructionTypeLibrary(PipelineConstructionType pipelineConstructionType); 54 bool isConstructionTypeShaderObject(PipelineConstructionType pipelineConstructionType); 55 void checkPipelineConstructionRequirements(const InstanceInterface &vki, VkPhysicalDevice physicalDevice, 56 PipelineConstructionType pipelineConstructionType); 57 58 // This exception may be raised in one of the intermediate steps when using shader module IDs instead of normal module objects. 59 class PipelineCompileRequiredError : public std::runtime_error 60 { 61 public: PipelineCompileRequiredError(const std::string & msg)62 PipelineCompileRequiredError(const std::string &msg) : std::runtime_error(msg) 63 { 64 } 65 }; 66 67 // PointerWrapper template is used to hide structures that should not be visible for Vulkan SC 68 template <typename T> 69 class PointerWrapper 70 { 71 public: PointerWrapper()72 PointerWrapper() : ptr(DE_NULL) 73 { 74 } PointerWrapper(T * p0)75 PointerWrapper(T *p0) : ptr(p0) 76 { 77 } 78 T *ptr; 79 }; 80 81 template <typename T> 82 class ConstPointerWrapper 83 { 84 public: ConstPointerWrapper()85 ConstPointerWrapper() : ptr(DE_NULL) 86 { 87 } ConstPointerWrapper(const T * p0)88 ConstPointerWrapper(const T *p0) : ptr(p0) 89 { 90 } 91 const T *ptr; 92 }; 93 94 #ifndef CTS_USES_VULKANSC 95 typedef PointerWrapper<VkPipelineViewportDepthClipControlCreateInfoEXT> 96 PipelineViewportDepthClipControlCreateInfoWrapper; 97 typedef PointerWrapper<VkPipelineRenderingCreateInfoKHR> PipelineRenderingCreateInfoWrapper; 98 typedef PointerWrapper<VkRenderingAttachmentLocationInfoKHR> RenderingAttachmentLocationInfoWrapper; 99 typedef PointerWrapper<VkRenderingInputAttachmentIndexInfoKHR> RenderingInputAttachmentIndexInfoWrapper; 100 typedef PointerWrapper<VkPipelineCreationFeedbackCreateInfoEXT> PipelineCreationFeedbackCreateInfoWrapper; 101 typedef ConstPointerWrapper<VkPipelineShaderStageModuleIdentifierCreateInfoEXT> 102 PipelineShaderStageModuleIdentifierCreateInfoWrapper; 103 typedef PointerWrapper<VkPipelineRepresentativeFragmentTestStateCreateInfoNV> 104 PipelineRepresentativeFragmentTestCreateInfoWrapper; 105 typedef VkPipelineCreateFlags2KHR PipelineCreateFlags2; 106 typedef PointerWrapper<VkPipelineRobustnessCreateInfoEXT> PipelineRobustnessCreateInfoWrapper; 107 #else 108 typedef PointerWrapper<void> PipelineViewportDepthClipControlCreateInfoWrapper; 109 typedef PointerWrapper<void> PipelineRenderingCreateInfoWrapper; 110 typedef PointerWrapper<void> RenderingAttachmentLocationInfoWrapper; 111 typedef PointerWrapper<void> RenderingInputAttachmentIndexInfoWrapper; 112 typedef PointerWrapper<void> PipelineCreationFeedbackCreateInfoWrapper; 113 typedef ConstPointerWrapper<void> PipelineShaderStageModuleIdentifierCreateInfoWrapper; 114 typedef PointerWrapper<void> PipelineRepresentativeFragmentTestCreateInfoWrapper; 115 typedef uint64_t PipelineCreateFlags2; 116 typedef PointerWrapper<void> PipelineRobustnessCreateInfoWrapper; 117 #endif 118 119 PipelineCreateFlags2 translateCreateFlag(VkPipelineCreateFlags flagToTranslate); 120 121 class PipelineLayoutWrapper 122 { 123 public: 124 PipelineLayoutWrapper() = default; 125 PipelineLayoutWrapper(PipelineConstructionType pipelineConstructionType, const DeviceInterface &vk, VkDevice device, 126 const VkDescriptorSetLayout descriptorSetLayout = DE_NULL, 127 const VkPushConstantRange *pushConstantRange = DE_NULL); 128 PipelineLayoutWrapper(PipelineConstructionType pipelineConstructionType, const DeviceInterface &vk, VkDevice device, 129 const std::vector<vk::Move<VkDescriptorSetLayout>> &descriptorSetLayout); 130 PipelineLayoutWrapper(PipelineConstructionType pipelineConstructionType, const DeviceInterface &vk, VkDevice device, 131 uint32_t setLayoutCount, const VkDescriptorSetLayout *descriptorSetLayout); 132 PipelineLayoutWrapper(PipelineConstructionType pipelineConstructionType, const DeviceInterface &vk, VkDevice device, 133 const VkPipelineLayoutCreateInfo *pCreateInfo, const VkAllocationCallbacks * = DE_NULL); 134 PipelineLayoutWrapper(PipelineConstructionType pipelineConstructionType, const DeviceInterface &vk, 135 const VkDevice device, const uint32_t setLayoutCount, 136 const VkDescriptorSetLayout *descriptorSetLayout, const uint32_t pushConstantRangeCount, 137 const VkPushConstantRange *pPushConstantRanges, 138 const VkPipelineLayoutCreateFlags flags = (VkPipelineLayoutCreateFlags)0u); 139 PipelineLayoutWrapper(const PipelineLayoutWrapper &rhs) = delete; 140 PipelineLayoutWrapper(PipelineLayoutWrapper &&rhs) noexcept; 141 ~PipelineLayoutWrapper() = default; 142 operator *(void) const143 const VkPipelineLayout operator*(void) const 144 { 145 return *m_pipelineLayout; 146 } get(void) const147 const VkPipelineLayout get(void) const 148 { 149 return *m_pipelineLayout; 150 } 151 PipelineLayoutWrapper &operator=(const PipelineLayoutWrapper &rhs) = delete; 152 PipelineLayoutWrapper &operator=(PipelineLayoutWrapper &&rhs); destroy(void)153 void destroy(void) 154 { 155 m_pipelineLayout = vk::Move<VkPipelineLayout>{}; 156 } 157 getSetLayoutCount(void) const158 uint32_t getSetLayoutCount(void) const 159 { 160 return m_setLayoutCount; 161 } getSetLayouts(void) const162 const VkDescriptorSetLayout *getSetLayouts(void) const 163 { 164 return m_setLayouts.data(); 165 } getSetLayout(uint32_t i)166 VkDescriptorSetLayout *getSetLayout(uint32_t i) 167 { 168 return &m_setLayouts[i]; 169 } getPushConstantRangeCount(void) const170 uint32_t getPushConstantRangeCount(void) const 171 { 172 return m_pushConstantRangeCount; 173 } getPushConstantRanges(void) const174 const VkPushConstantRange *getPushConstantRanges(void) const 175 { 176 return m_pushConstantRanges.data(); 177 } 178 179 void bindDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, uint32_t firstSet, 180 uint32_t descriptorSetCount, const VkDescriptorSet *pDescriptorSets, 181 uint32_t dynamicOffsetCount, const uint32_t *pDynamicOffsets) const; 182 183 private: 184 PipelineConstructionType m_pipelineConstructionType; 185 const DeviceInterface *m_vk; 186 VkDevice m_device; 187 VkPipelineLayoutCreateFlags m_flags; 188 uint32_t m_setLayoutCount; 189 std::vector<VkDescriptorSetLayout> m_setLayouts; 190 uint32_t m_pushConstantRangeCount; 191 std::vector<VkPushConstantRange> m_pushConstantRanges; 192 vk::Move<VkPipelineLayout> m_pipelineLayout; 193 }; 194 195 class RenderPassWrapper 196 { 197 public: 198 RenderPassWrapper() = default; 199 RenderPassWrapper(const DeviceInterface &vk, VkDevice device, const VkRenderPassCreateInfo2 *pCreateInfo, 200 bool dynamicRendering); 201 RenderPassWrapper(PipelineConstructionType pipelineConstructionType, const DeviceInterface &vk, VkDevice device, 202 const VkRenderPassCreateInfo *pCreateInfo); 203 RenderPassWrapper(PipelineConstructionType pipelineConstructionType, const DeviceInterface &vk, VkDevice device, 204 const VkRenderPassCreateInfo2 *pCreateInfo); 205 RenderPassWrapper(PipelineConstructionType pipelineConstructionType, const DeviceInterface &vk, 206 const VkDevice device, const VkFormat colorFormat = VK_FORMAT_UNDEFINED, 207 const VkFormat depthStencilFormat = VK_FORMAT_UNDEFINED, 208 const VkAttachmentLoadOp loadOperation = VK_ATTACHMENT_LOAD_OP_CLEAR, 209 const VkImageLayout finalLayoutColor = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 210 const VkImageLayout finalLayoutDepthStencil = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 211 const VkImageLayout subpassLayoutColor = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 212 const VkImageLayout subpassLayoutDepthStencil = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 213 const VkAllocationCallbacks *const allocationCallbacks = DE_NULL); 214 215 RenderPassWrapper(RenderPassWrapper &&rhs) noexcept; 216 RenderPassWrapper &operator=(RenderPassWrapper &&rhs) noexcept; 217 218 ~RenderPassWrapper() = default; 219 operator *(void) const220 const VkRenderPass operator*(void) const 221 { 222 return *m_renderPass; 223 } get(void) const224 const VkRenderPass get(void) const 225 { 226 return *m_renderPass; 227 } getFramebuffer(void) const228 const VkFramebuffer getFramebuffer(void) const 229 { 230 return m_framebuffer ? *m_framebuffer : VK_NULL_HANDLE; 231 } 232 233 void begin(const DeviceInterface &vk, const VkCommandBuffer commandBuffer, const VkRect2D &renderArea, 234 const uint32_t clearValueCount, const VkClearValue *clearValues, 235 const VkSubpassContents contents = VK_SUBPASS_CONTENTS_INLINE, const void *pNext = DE_NULL) const; 236 void begin(const DeviceInterface &vk, const VkCommandBuffer commandBuffer, const VkRect2D &renderArea, 237 const VkClearValue &clearValue, const VkSubpassContents contents = VK_SUBPASS_CONTENTS_INLINE) const; 238 void begin(const DeviceInterface &vk, const VkCommandBuffer commandBuffer, const VkRect2D &renderArea, 239 const tcu::Vec4 &clearColor, const VkSubpassContents contents = VK_SUBPASS_CONTENTS_INLINE) const; 240 void begin(const DeviceInterface &vk, const VkCommandBuffer commandBuffer, const VkRect2D &renderArea, 241 const tcu::Vec4 &clearColor, const float clearDepth, const uint32_t clearStencil, 242 const VkSubpassContents contents = VK_SUBPASS_CONTENTS_INLINE) const; 243 void begin(const DeviceInterface &vk, const VkCommandBuffer commandBuffer, const VkRect2D &renderArea, 244 const VkSubpassContents contents = VK_SUBPASS_CONTENTS_INLINE) const; 245 void begin(const DeviceInterface &vk, const VkCommandBuffer commandBuffer, const VkRect2D &renderArea, 246 const tcu::UVec4 &clearColor, const VkSubpassContents contents = VK_SUBPASS_CONTENTS_INLINE) const; 247 248 void end(const DeviceInterface &vk, const VkCommandBuffer commandBuffer) const; 249 void nextSubpass(const DeviceInterface &vk, const VkCommandBuffer commandBuffer, 250 const VkSubpassContents contents) const; 251 252 void createFramebuffer(const DeviceInterface &vk, const VkDevice device, const VkFramebufferCreateInfo *pCreateInfo, 253 const std::vector<vk::VkImage> &images); 254 void createFramebuffer(const DeviceInterface &vk, const VkDevice device, const VkFramebufferCreateInfo *pCreateInfo, 255 vk::VkImage colorImage, vk::VkImage depthStencilImage = VK_NULL_HANDLE); 256 void createFramebuffer(const DeviceInterface &vk, const VkDevice device, const VkImage colorImage, 257 const VkImageView colorAttachment, const uint32_t width, const uint32_t height, 258 const uint32_t layers = 1u); 259 void createFramebuffer(const DeviceInterface &vk, const VkDevice device, const uint32_t attachmentCount, 260 const VkImage *imagesArray, const VkImageView *attachmentsArray, const uint32_t width, 261 const uint32_t height, const uint32_t layers = 1u); 262 263 private: 264 void beginRendering(const DeviceInterface &vk, const VkCommandBuffer commandBuffer) const; 265 266 bool m_isDynamicRendering; 267 vk::Move<vk::VkRenderPass> m_renderPass; 268 vk::Move<vk::VkFramebuffer> m_framebuffer; 269 270 #ifndef CTS_USES_VULKANSC 271 struct Subpass 272 { 273 struct Attachment 274 { 275 uint32_t index = VK_ATTACHMENT_UNUSED; 276 vk::VkRenderingAttachmentInfo attachmentInfo = {}; 277 vk::VkFormat format; 278 vk::VkAttachmentLoadOp stencilLoadOp = vk::VK_ATTACHMENT_LOAD_OP_LOAD; 279 vk::VkAttachmentStoreOp stencilStoreOp = vk::VK_ATTACHMENT_STORE_OP_STORE; 280 }; 281 mutable std::vector<Attachment> m_colorAttachments; 282 mutable Attachment m_depthStencilAttachment; 283 mutable std::vector<Attachment> m_resolveAttachments; 284 mutable VkMultisampledRenderToSingleSampledInfoEXT m_msrtss = {}; 285 mutable VkSubpassDescriptionDepthStencilResolve m_dsr = {}; 286 mutable VkAttachmentReference2 m_depthStencilResolveAttachment = {}; 287 }; 288 struct SubpassDependency 289 { 290 SubpassDependency(const VkSubpassDependency &dependency); 291 SubpassDependency(const VkSubpassDependency2 &dependency); 292 293 uint32_t srcSubpass; 294 uint32_t dstSubpass; 295 VkPipelineStageFlags2 srcStageMask; 296 VkPipelineStageFlags2 dstStageMask; 297 VkAccessFlags2 srcAccessMask; 298 VkAccessFlags2 dstAccessMask; 299 VkDependencyFlags dependencyFlags; 300 bool sync2; 301 }; 302 std::vector<Subpass> m_subpasses; 303 std::vector<SubpassDependency> m_dependencies; 304 std::vector<vk::VkAttachmentDescription2> m_attachments; 305 std::vector<vk::VkImage> m_images; 306 std::vector<vk::VkImageView> m_imageViews; 307 mutable std::vector<vk::VkClearValue> m_clearValues; 308 mutable std::vector<vk::VkImageLayout> m_layouts; 309 mutable uint32_t m_activeSubpass = 0; 310 mutable vk::VkRenderingInfo m_renderingInfo; 311 uint32_t m_layers = 1; 312 std::vector<uint32_t> m_viewMasks; 313 mutable bool m_secondaryCommandBuffers; 314 315 void clearAttachments(const DeviceInterface &vk, const VkCommandBuffer commandBuffer) const; 316 void updateLayout(VkImage updatedImage, VkImageLayout newLayout) const; 317 void transitionLayouts(const DeviceInterface &vk, const VkCommandBuffer commandBuffer, const Subpass &subpass, 318 bool renderPassBegin) const; 319 void insertDependencies(const DeviceInterface &vk, const VkCommandBuffer commandBuffer, uint32_t subpassIdx) const; 320 321 public: 322 void fillInheritanceRenderingInfo(uint32_t subpassIndex, std::vector<vk::VkFormat> *colorFormats, 323 vk::VkCommandBufferInheritanceRenderingInfo *inheritanceRenderingInfo) const; 324 325 private: 326 #endif 327 }; 328 329 class ShaderWrapper 330 { 331 public: 332 ShaderWrapper(); 333 334 ShaderWrapper(const DeviceInterface &vk, VkDevice device, const vk::ProgramBinary &binary, 335 const vk::VkShaderModuleCreateFlags createFlags = 0u); 336 337 ShaderWrapper(const ShaderWrapper &rhs) noexcept; 338 339 ~ShaderWrapper() = default; 340 341 ShaderWrapper &operator=(const ShaderWrapper &rhs) noexcept; 342 isSet(void) const343 bool isSet(void) const 344 { 345 return m_binary != DE_NULL; 346 } 347 348 vk::VkShaderModule getModule(void) const; 349 350 size_t getCodeSize(void) const; 351 void *getBinary(void) const; 352 353 void createModule(void); 354 void setLayoutAndSpecialization(const PipelineLayoutWrapper *layout, 355 const VkSpecializationInfo *specializationInfo); 356 getPipelineLayout(void) const357 const PipelineLayoutWrapper *getPipelineLayout(void) const 358 { 359 return m_layout; 360 } getSpecializationInfo(void) const361 const VkSpecializationInfo *getSpecializationInfo(void) const 362 { 363 return m_specializationInfo; 364 } 365 366 #ifndef CTS_USES_VULKANSC getShader(void) const367 vk::VkShaderEXT getShader(void) const 368 { 369 return m_shader ? *m_shader : VK_NULL_HANDLE; 370 } setShader(Move<VkShaderEXT> shader)371 void setShader(Move<VkShaderEXT> shader) 372 { 373 m_shader = shader; 374 } 375 addFlags(const VkShaderCreateFlagsEXT flags)376 void addFlags(const VkShaderCreateFlagsEXT flags) 377 { 378 m_shaderCreateFlags |= flags; 379 } 380 void getShaderBinary(void); getShaderBinaryDataSize(void)381 size_t getShaderBinaryDataSize(void) 382 { 383 return m_binaryDataSize; 384 } getShaderBinaryData(void)385 void *getShaderBinaryData(void) 386 { 387 return m_binaryData.data(); 388 } 389 #endif 390 391 private: 392 const DeviceInterface *m_vk; 393 VkDevice m_device; 394 const vk::ProgramBinary *m_binary; 395 vk::VkShaderModuleCreateFlags m_moduleCreateFlags; 396 mutable vk::Move<vk::VkShaderModule> m_module; 397 const PipelineLayoutWrapper *m_layout; 398 const VkSpecializationInfo *m_specializationInfo; 399 #ifndef CTS_USES_VULKANSC 400 vk::Move<vk::VkShaderEXT> m_shader; 401 VkShaderCreateFlagsEXT m_shaderCreateFlags; 402 size_t m_binaryDataSize; 403 std::vector<uint8_t> m_binaryData; 404 #endif 405 }; 406 407 // Class that can build monolithic pipeline or fully separated pipeline libraries 408 // depending on PipelineType specified in the constructor. 409 // Rarely needed configuration was extracted to setDefault*/disable* functions while common 410 // state setup is provided as arguments of four setup* functions - one for each state group. 411 class GraphicsPipelineWrapper 412 { 413 public: 414 GraphicsPipelineWrapper(const InstanceInterface &vki, const DeviceInterface &vk, VkPhysicalDevice physicalDevice, 415 VkDevice device, const std::vector<std::string> &deviceExtensions, 416 const PipelineConstructionType pipelineConstructionType, 417 const VkPipelineCreateFlags flags = 0u); 418 419 GraphicsPipelineWrapper(GraphicsPipelineWrapper &&) noexcept; 420 421 ~GraphicsPipelineWrapper(void) = default; 422 423 // By default pipelineLayout used for monotlithic pipeline is taken from layout specified 424 // in setupPreRasterizationShaderState but when there are also descriptor sets needed for fragment 425 // shader bindings then separate pipeline layout for monolithic pipeline must be provided 426 GraphicsPipelineWrapper &setMonolithicPipelineLayout(const PipelineLayoutWrapper &layout); 427 428 // By default dynamic state has to be specified before specifying other CreateInfo structures 429 GraphicsPipelineWrapper &setDynamicState(const VkPipelineDynamicStateCreateInfo *dynamicState); 430 431 // Specify the representative fragment test state. 432 GraphicsPipelineWrapper &setRepresentativeFragmentTestState( 433 PipelineRepresentativeFragmentTestCreateInfoWrapper representativeFragmentTestState); 434 435 // Specify pipeline robustness state 436 GraphicsPipelineWrapper &setPipelineRobustnessState(PipelineRobustnessCreateInfoWrapper pipelineRobustnessState); 437 438 // Specifying how a pipeline is created using VkPipelineCreateFlags2CreateInfoKHR. 439 GraphicsPipelineWrapper &setPipelineCreateFlags2(PipelineCreateFlags2 pipelineFlags2); 440 441 // Specify topology that is used by default InputAssemblyState in vertex input state. This needs to be 442 // specified only when there is no custom InputAssemblyState provided in setupVertexInputState and when 443 // topology is diferent then VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST which is used by default. 444 GraphicsPipelineWrapper &setDefaultTopology(const VkPrimitiveTopology topology); 445 446 // Specify patch control points that is used by default TessellationState in pre-rasterization shader state. 447 // This can to be specified only when there is no custom TessellationState provided in 448 // setupPreRasterizationShaderState and when patchControlPoints is diferent then 3 which is used by default. 449 // A value of std::numeric_limits<uint32_t>::max() forces the tessellation state to be null. 450 GraphicsPipelineWrapper &setDefaultPatchControlPoints(const uint32_t patchControlPoints); 451 452 // Specify tesellation domain origin, used by the tessellation state in pre-rasterization shader state. 453 GraphicsPipelineWrapper &setDefaultTessellationDomainOrigin(const VkTessellationDomainOrigin domainOrigin, 454 bool forceExtStruct = false); 455 456 // Enable discarding of primitives that is used by default RasterizationState in pre-rasterization shader state. 457 // This can be specified only when there is no custom RasterizationState provided in setupPreRasterizationShaderState. 458 GraphicsPipelineWrapper &setDefaultRasterizerDiscardEnable(const bool rasterizerDiscardEnable = true); 459 460 // When some states are not provided then default structures can be used. This behaviour can be turned on by one of below methods. 461 // Some tests require those states to be NULL so we can't assume using default versions. 462 GraphicsPipelineWrapper &setDefaultRasterizationState(void); 463 GraphicsPipelineWrapper &setDefaultDepthStencilState(void); 464 GraphicsPipelineWrapper &setDefaultColorBlendState(void); 465 GraphicsPipelineWrapper &setDefaultMultisampleState(void); 466 GraphicsPipelineWrapper &setDefaultVertexInputState(const bool useDefaultVertexInputState); 467 468 // Pre-rasterization shader state uses provieded viewports and scissors to create ViewportState. By default 469 // number of viewports and scissors is same as number of items in vector but when vectors are empty then by 470 // default count of viewports/scissors is set to 1. This can be changed by below functions. 471 GraphicsPipelineWrapper &setDefaultViewportsCount(uint32_t viewportCount = 0u); 472 GraphicsPipelineWrapper &setDefaultScissorsCount(uint32_t scissorCount = 0u); 473 474 // Pre-rasterization shader state uses default ViewportState, this method extends the internal structure. 475 GraphicsPipelineWrapper &setViewportStatePnext(const void *pNext); 476 477 #ifndef CTS_USES_VULKANSC 478 GraphicsPipelineWrapper &setRenderingColorAttachmentsInfo( 479 PipelineRenderingCreateInfoWrapper pipelineRenderingCreateInfo); 480 #endif 481 482 // Pre-rasterization shader state uses provieded viewports and scissors to create ViewportState. When disableViewportState 483 // is used then ViewportState won't be constructed and NULL will be used. 484 GraphicsPipelineWrapper &disableViewportState(const bool disable = true); 485 486 // Setup vertex input state. When VertexInputState or InputAssemblyState are not provided then default structures will be used. 487 GraphicsPipelineWrapper &setupVertexInputState( 488 const VkPipelineVertexInputStateCreateInfo *vertexInputState = nullptr, 489 const VkPipelineInputAssemblyStateCreateInfo *inputAssemblyState = nullptr, 490 const VkPipelineCache partPipelineCache = DE_NULL, 491 PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback = PipelineCreationFeedbackCreateInfoWrapper(), 492 const bool useNullPtrs = false); 493 494 // Setup pre-rasterization shader state. 495 GraphicsPipelineWrapper &setupPreRasterizationShaderState( 496 const std::vector<VkViewport> &viewports, const std::vector<VkRect2D> &scissors, 497 const PipelineLayoutWrapper &layout, const VkRenderPass renderPass, const uint32_t subpass, 498 const ShaderWrapper vertexShaderModule, 499 const VkPipelineRasterizationStateCreateInfo *rasterizationState = DE_NULL, 500 const ShaderWrapper tessellationControlShader = ShaderWrapper(), 501 const ShaderWrapper tessellationEvalShader = ShaderWrapper(), 502 const ShaderWrapper geometryShader = ShaderWrapper(), const VkSpecializationInfo *specializationInfo = DE_NULL, 503 VkPipelineFragmentShadingRateStateCreateInfoKHR *fragmentShadingRateState = nullptr, 504 PipelineRenderingCreateInfoWrapper rendering = PipelineRenderingCreateInfoWrapper(), 505 const VkPipelineCache partPipelineCache = DE_NULL, 506 PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback = PipelineCreationFeedbackCreateInfoWrapper()); 507 508 GraphicsPipelineWrapper &setupPreRasterizationShaderState2( 509 const std::vector<VkViewport> &viewports, const std::vector<VkRect2D> &scissors, 510 const PipelineLayoutWrapper &layout, const VkRenderPass renderPass, const uint32_t subpass, 511 const ShaderWrapper vertexShaderModule, 512 const VkPipelineRasterizationStateCreateInfo *rasterizationState = nullptr, 513 const ShaderWrapper tessellationControlShader = ShaderWrapper(), 514 const ShaderWrapper tessellationEvalShader = ShaderWrapper(), 515 const ShaderWrapper geometryShader = ShaderWrapper(), 516 const VkSpecializationInfo *vertSpecializationInfo = nullptr, 517 const VkSpecializationInfo *tescSpecializationInfo = nullptr, 518 const VkSpecializationInfo *teseSpecializationInfo = nullptr, 519 const VkSpecializationInfo *geomSpecializationInfo = nullptr, 520 VkPipelineFragmentShadingRateStateCreateInfoKHR *fragmentShadingRateState = nullptr, 521 PipelineRenderingCreateInfoWrapper rendering = PipelineRenderingCreateInfoWrapper(), 522 const VkPipelineCache partPipelineCache = DE_NULL, 523 PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback = PipelineCreationFeedbackCreateInfoWrapper()); 524 525 // Note: VkPipelineShaderStageModuleIdentifierCreateInfoEXT::pIdentifier will not be copied. They need to continue to exist outside this wrapper. 526 GraphicsPipelineWrapper &setupPreRasterizationShaderState3( 527 const std::vector<VkViewport> &viewports, const std::vector<VkRect2D> &scissors, 528 const PipelineLayoutWrapper &layout, const VkRenderPass renderPass, const uint32_t subpass, 529 const ShaderWrapper vertexShaderModule, 530 PipelineShaderStageModuleIdentifierCreateInfoWrapper vertShaderModuleId = 531 PipelineShaderStageModuleIdentifierCreateInfoWrapper(), 532 const VkPipelineRasterizationStateCreateInfo *rasterizationState = nullptr, 533 const ShaderWrapper tessellationControlShader = ShaderWrapper(), 534 PipelineShaderStageModuleIdentifierCreateInfoWrapper tescShaderModuleId = 535 PipelineShaderStageModuleIdentifierCreateInfoWrapper(), 536 const ShaderWrapper tessellationEvalShader = ShaderWrapper(), 537 PipelineShaderStageModuleIdentifierCreateInfoWrapper teseShaderModuleId = 538 PipelineShaderStageModuleIdentifierCreateInfoWrapper(), 539 const ShaderWrapper geometryShader = ShaderWrapper(), 540 PipelineShaderStageModuleIdentifierCreateInfoWrapper geomShaderModuleId = 541 PipelineShaderStageModuleIdentifierCreateInfoWrapper(), 542 const VkSpecializationInfo *vertSpecializationInfo = nullptr, 543 const VkSpecializationInfo *tescSpecializationInfo = nullptr, 544 const VkSpecializationInfo *teseSpecializationInfo = nullptr, 545 const VkSpecializationInfo *geomSpecializationInfo = nullptr, 546 VkPipelineFragmentShadingRateStateCreateInfoKHR *fragmentShadingRateState = nullptr, 547 PipelineRenderingCreateInfoWrapper rendering = PipelineRenderingCreateInfoWrapper(), 548 const VkPipelineCache partPipelineCache = DE_NULL, 549 PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback = PipelineCreationFeedbackCreateInfoWrapper()); 550 551 #ifndef CTS_USES_VULKANSC 552 // Setup pre-rasterization shader state, mesh shading version. 553 GraphicsPipelineWrapper &setupPreRasterizationMeshShaderState( 554 const std::vector<VkViewport> &viewports, const std::vector<VkRect2D> &scissors, 555 const PipelineLayoutWrapper &layout, const VkRenderPass renderPass, const uint32_t subpass, 556 const ShaderWrapper taskShader, const ShaderWrapper meshShader, 557 const VkPipelineRasterizationStateCreateInfo *rasterizationState = nullptr, 558 const VkSpecializationInfo *taskSpecializationInfo = nullptr, 559 const VkSpecializationInfo *meshSpecializationInfo = nullptr, 560 VkPipelineFragmentShadingRateStateCreateInfoKHR *fragmentShadingRateState = nullptr, 561 PipelineRenderingCreateInfoWrapper rendering = PipelineRenderingCreateInfoWrapper(), 562 const VkPipelineCache partPipelineCache = DE_NULL, 563 VkPipelineCreationFeedbackCreateInfoEXT *partCreationFeedback = nullptr); 564 #endif // CTS_USES_VULKANSC 565 566 // Setup fragment shader state. 567 GraphicsPipelineWrapper &setupFragmentShaderState( 568 const PipelineLayoutWrapper &layout, const VkRenderPass renderPass, const uint32_t subpass, 569 const ShaderWrapper fragmentShaderModule, 570 const VkPipelineDepthStencilStateCreateInfo *depthStencilState = DE_NULL, 571 const VkPipelineMultisampleStateCreateInfo *multisampleState = DE_NULL, 572 const VkSpecializationInfo *specializationInfo = DE_NULL, const VkPipelineCache partPipelineCache = DE_NULL, 573 PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback = PipelineCreationFeedbackCreateInfoWrapper(), 574 RenderingInputAttachmentIndexInfoWrapper renderingInputAttachmentIndexInfo = 575 RenderingInputAttachmentIndexInfoWrapper()); 576 577 // Note: VkPipelineShaderStageModuleIdentifierCreateInfoEXT::pIdentifier will not be copied. They need to continue to exist outside this wrapper. 578 GraphicsPipelineWrapper &setupFragmentShaderState2( 579 const PipelineLayoutWrapper &layout, const VkRenderPass renderPass, const uint32_t subpass, 580 const ShaderWrapper fragmentShaderModule, 581 PipelineShaderStageModuleIdentifierCreateInfoWrapper fragmentShaderModuleId = 582 PipelineShaderStageModuleIdentifierCreateInfoWrapper(), 583 const VkPipelineDepthStencilStateCreateInfo *depthStencilState = nullptr, 584 const VkPipelineMultisampleStateCreateInfo *multisampleState = nullptr, 585 const VkSpecializationInfo *specializationInfo = nullptr, const VkPipelineCache partPipelineCache = DE_NULL, 586 PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback = PipelineCreationFeedbackCreateInfoWrapper(), 587 RenderingInputAttachmentIndexInfoWrapper renderingInputAttachmentIndexInfo = 588 RenderingInputAttachmentIndexInfoWrapper()); 589 590 // Setup fragment output state. 591 GraphicsPipelineWrapper &setupFragmentOutputState( 592 const VkRenderPass renderPass, const uint32_t subpass = 0u, 593 const VkPipelineColorBlendStateCreateInfo *colorBlendState = DE_NULL, 594 const VkPipelineMultisampleStateCreateInfo *multisampleState = DE_NULL, 595 const VkPipelineCache partPipelineCache = DE_NULL, 596 PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback = PipelineCreationFeedbackCreateInfoWrapper(), 597 RenderingAttachmentLocationInfoWrapper renderingAttachmentLocationInfo = 598 RenderingAttachmentLocationInfoWrapper()); 599 600 // Build pipeline object out of provided state. 601 void buildPipeline( 602 const VkPipelineCache pipelineCache = DE_NULL, const VkPipeline basePipelineHandle = DE_NULL, 603 const int32_t basePipelineIndex = 0, 604 PipelineCreationFeedbackCreateInfoWrapper creationFeedback = PipelineCreationFeedbackCreateInfoWrapper()); 605 // Create shader objects if used 606 #ifndef CTS_USES_VULKANSC 607 vk::VkShaderStageFlags getNextStages(vk::VkShaderStageFlagBits shaderStage, bool tessellationShaders, 608 bool geometryShaders, bool link); 609 vk::VkShaderCreateInfoEXT makeShaderCreateInfo(VkShaderStageFlagBits stage, ShaderWrapper &shader, bool link, 610 bool binary, ShaderWrapper &other); 611 void createShaders(bool linked, bool binary); 612 #endif 613 614 // Bind pipeline or shader objects 615 void bind(vk::VkCommandBuffer cmdBuffer) const; 616 617 // Returns true when pipeline was build using buildPipeline method. 618 bool wasBuild(void) const; 619 // Returns true when pipeline or shader objects was built. 620 bool wasPipelineOrShaderObjectBuild(void) const; 621 622 // Get compleate pipeline. GraphicsPipelineWrapper preserves ovnership and will destroy pipeline in its destructor. 623 vk::VkPipeline getPipeline(void) const; 624 625 // Destroy compleate pipeline - pipeline parts are not destroyed. 626 void destroyPipeline(void); 627 628 protected: 629 // No default constructor - use parametrized constructor or emplace_back in case of vectors. 630 GraphicsPipelineWrapper() = default; 631 632 // Dynamic states that are only dynamic in shader objects 633 bool isShaderObjectDynamic(vk::VkDynamicState dynamicState) const; 634 void setShaderObjectDynamicStates(vk::VkCommandBuffer cmdBuffer) const; 635 636 struct InternalData; 637 638 protected: 639 static constexpr size_t kMaxPipelineParts = 4u; 640 641 // Store partial pipelines when non monolithic construction was used. 642 Move<VkPipeline> m_pipelineParts[kMaxPipelineParts]; 643 644 // Store monolithic pipeline or linked pipeline libraries. 645 Move<VkPipeline> m_pipelineFinal; 646 647 // Store internal data that is needed only for pipeline construction. 648 de::SharedPtr<InternalData> m_internalData; 649 }; 650 651 } // namespace vk 652 653 #endif // _VKPIPELINECONSTRUCTIONUTIL_HPP 654