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(nullptr) 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(nullptr) 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 PointerWrapper<VkPipelineBinaryInfoKHR> PipelineBinaryInfoWrapper; 106 typedef VkPipelineCreateFlags2KHR PipelineCreateFlags2; 107 typedef VkShaderCreateFlagsEXT ShaderCreateFlags; 108 typedef PointerWrapper<VkPipelineRobustnessCreateInfoEXT> PipelineRobustnessCreateInfoWrapper; 109 #else 110 typedef PointerWrapper<void> PipelineViewportDepthClipControlCreateInfoWrapper; 111 typedef PointerWrapper<void> PipelineRenderingCreateInfoWrapper; 112 typedef PointerWrapper<void> RenderingAttachmentLocationInfoWrapper; 113 typedef PointerWrapper<void> RenderingInputAttachmentIndexInfoWrapper; 114 typedef PointerWrapper<void> PipelineCreationFeedbackCreateInfoWrapper; 115 typedef ConstPointerWrapper<void> PipelineShaderStageModuleIdentifierCreateInfoWrapper; 116 typedef PointerWrapper<void> PipelineRepresentativeFragmentTestCreateInfoWrapper; 117 typedef PointerWrapper<void> PipelineBinaryInfoWrapper; 118 typedef uint64_t PipelineCreateFlags2; 119 typedef uint32_t ShaderCreateFlags; 120 typedef PointerWrapper<void> PipelineRobustnessCreateInfoWrapper; 121 #endif 122 123 PipelineCreateFlags2 translateCreateFlag(VkPipelineCreateFlags flagToTranslate); 124 125 class PipelineLayoutWrapper 126 { 127 public: 128 PipelineLayoutWrapper() = default; 129 PipelineLayoutWrapper(PipelineConstructionType pipelineConstructionType, const DeviceInterface &vk, VkDevice device, 130 const VkDescriptorSetLayout descriptorSetLayout = VK_NULL_HANDLE, 131 const VkPushConstantRange *pushConstantRange = nullptr); 132 PipelineLayoutWrapper(PipelineConstructionType pipelineConstructionType, const DeviceInterface &vk, VkDevice device, 133 const std::vector<vk::Move<VkDescriptorSetLayout>> &descriptorSetLayout); 134 PipelineLayoutWrapper(PipelineConstructionType pipelineConstructionType, const DeviceInterface &vk, VkDevice device, 135 uint32_t setLayoutCount, const VkDescriptorSetLayout *descriptorSetLayout); 136 PipelineLayoutWrapper(PipelineConstructionType pipelineConstructionType, const DeviceInterface &vk, VkDevice device, 137 const VkPipelineLayoutCreateInfo *pCreateInfo, const VkAllocationCallbacks * = nullptr); 138 PipelineLayoutWrapper(PipelineConstructionType pipelineConstructionType, const DeviceInterface &vk, 139 const VkDevice device, const uint32_t setLayoutCount, 140 const VkDescriptorSetLayout *descriptorSetLayout, const uint32_t pushConstantRangeCount, 141 const VkPushConstantRange *pPushConstantRanges, 142 const VkPipelineLayoutCreateFlags flags = (VkPipelineLayoutCreateFlags)0u); 143 PipelineLayoutWrapper(const PipelineLayoutWrapper &rhs) = delete; 144 PipelineLayoutWrapper(PipelineLayoutWrapper &&rhs) noexcept; 145 ~PipelineLayoutWrapper() = default; 146 operator *(void) const147 const VkPipelineLayout operator*(void) const 148 { 149 return *m_pipelineLayout; 150 } get(void) const151 const VkPipelineLayout get(void) const 152 { 153 return *m_pipelineLayout; 154 } 155 PipelineLayoutWrapper &operator=(const PipelineLayoutWrapper &rhs) = delete; 156 PipelineLayoutWrapper &operator=(PipelineLayoutWrapper &&rhs); destroy(void)157 void destroy(void) 158 { 159 m_pipelineLayout = vk::Move<VkPipelineLayout>{}; 160 } 161 getSetLayoutCount(void) const162 uint32_t getSetLayoutCount(void) const 163 { 164 return m_setLayoutCount; 165 } getSetLayouts(void) const166 const VkDescriptorSetLayout *getSetLayouts(void) const 167 { 168 return m_setLayouts.data(); 169 } getSetLayout(uint32_t i)170 VkDescriptorSetLayout *getSetLayout(uint32_t i) 171 { 172 return &m_setLayouts[i]; 173 } getPushConstantRangeCount(void) const174 uint32_t getPushConstantRangeCount(void) const 175 { 176 return m_pushConstantRangeCount; 177 } getPushConstantRanges(void) const178 const VkPushConstantRange *getPushConstantRanges(void) const 179 { 180 return m_pushConstantRanges.data(); 181 } 182 183 void bindDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, uint32_t firstSet, 184 uint32_t descriptorSetCount, const VkDescriptorSet *pDescriptorSets, 185 uint32_t dynamicOffsetCount, const uint32_t *pDynamicOffsets) const; 186 187 private: 188 PipelineConstructionType m_pipelineConstructionType; 189 const DeviceInterface *m_vk; 190 VkDevice m_device; 191 VkPipelineLayoutCreateFlags m_flags; 192 uint32_t m_setLayoutCount; 193 std::vector<VkDescriptorSetLayout> m_setLayouts; 194 uint32_t m_pushConstantRangeCount; 195 std::vector<VkPushConstantRange> m_pushConstantRanges; 196 vk::Move<VkPipelineLayout> m_pipelineLayout; 197 }; 198 199 class RenderPassWrapper 200 { 201 public: 202 RenderPassWrapper() = default; 203 RenderPassWrapper(const DeviceInterface &vk, VkDevice device, const VkRenderPassCreateInfo2 *pCreateInfo, 204 bool dynamicRendering); 205 RenderPassWrapper(PipelineConstructionType pipelineConstructionType, const DeviceInterface &vk, VkDevice device, 206 const VkRenderPassCreateInfo *pCreateInfo); 207 RenderPassWrapper(PipelineConstructionType pipelineConstructionType, const DeviceInterface &vk, VkDevice device, 208 const VkRenderPassCreateInfo2 *pCreateInfo); 209 RenderPassWrapper(PipelineConstructionType pipelineConstructionType, const DeviceInterface &vk, 210 const VkDevice device, const VkFormat colorFormat = VK_FORMAT_UNDEFINED, 211 const VkFormat depthStencilFormat = VK_FORMAT_UNDEFINED, 212 const VkAttachmentLoadOp loadOperation = VK_ATTACHMENT_LOAD_OP_CLEAR, 213 const VkImageLayout finalLayoutColor = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 214 const VkImageLayout finalLayoutDepthStencil = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 215 const VkImageLayout subpassLayoutColor = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 216 const VkImageLayout subpassLayoutDepthStencil = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 217 const VkAllocationCallbacks *const allocationCallbacks = nullptr); 218 219 RenderPassWrapper(RenderPassWrapper &&rhs) noexcept; 220 RenderPassWrapper &operator=(RenderPassWrapper &&rhs) noexcept; 221 222 ~RenderPassWrapper() = default; 223 operator *(void) const224 const VkRenderPass operator*(void) const 225 { 226 return *m_renderPass; 227 } get(void) const228 const VkRenderPass get(void) const 229 { 230 return *m_renderPass; 231 } getFramebuffer(void) const232 const VkFramebuffer getFramebuffer(void) const 233 { 234 return m_framebuffer ? *m_framebuffer : VK_NULL_HANDLE; 235 } 236 void resetLayouts(void); 237 238 void begin(const DeviceInterface &vk, const VkCommandBuffer commandBuffer, const VkRect2D &renderArea, 239 const uint32_t clearValueCount, const VkClearValue *clearValues, 240 const VkSubpassContents contents = VK_SUBPASS_CONTENTS_INLINE, const void *pNext = nullptr) const; 241 void begin(const DeviceInterface &vk, const VkCommandBuffer commandBuffer, const VkRect2D &renderArea, 242 const VkClearValue &clearValue, const VkSubpassContents contents = VK_SUBPASS_CONTENTS_INLINE) const; 243 void begin(const DeviceInterface &vk, const VkCommandBuffer commandBuffer, const VkRect2D &renderArea, 244 const tcu::Vec4 &clearColor, const VkSubpassContents contents = VK_SUBPASS_CONTENTS_INLINE) const; 245 void begin(const DeviceInterface &vk, const VkCommandBuffer commandBuffer, const VkRect2D &renderArea, 246 const tcu::Vec4 &clearColor, const float clearDepth, const uint32_t clearStencil, 247 const VkSubpassContents contents = VK_SUBPASS_CONTENTS_INLINE) const; 248 void begin(const DeviceInterface &vk, const VkCommandBuffer commandBuffer, const VkRect2D &renderArea, 249 const VkSubpassContents contents = VK_SUBPASS_CONTENTS_INLINE) const; 250 void begin(const DeviceInterface &vk, const VkCommandBuffer commandBuffer, const VkRect2D &renderArea, 251 const tcu::UVec4 &clearColor, const VkSubpassContents contents = VK_SUBPASS_CONTENTS_INLINE) const; 252 253 void end(const DeviceInterface &vk, const VkCommandBuffer commandBuffer) const; 254 void nextSubpass(const DeviceInterface &vk, const VkCommandBuffer commandBuffer, 255 const VkSubpassContents contents) const; 256 257 void createFramebuffer(const DeviceInterface &vk, const VkDevice device, const VkFramebufferCreateInfo *pCreateInfo, 258 const std::vector<vk::VkImage> &images); 259 void createFramebuffer(const DeviceInterface &vk, const VkDevice device, const VkFramebufferCreateInfo *pCreateInfo, 260 vk::VkImage colorImage, vk::VkImage depthStencilImage = VK_NULL_HANDLE); 261 void createFramebuffer(const DeviceInterface &vk, const VkDevice device, const VkImage colorImage, 262 const VkImageView colorAttachment, const uint32_t width, const uint32_t height, 263 const uint32_t layers = 1u); 264 void createFramebuffer(const DeviceInterface &vk, const VkDevice device, const uint32_t attachmentCount, 265 const VkImage *imagesArray, const VkImageView *attachmentsArray, const uint32_t width, 266 const uint32_t height, const uint32_t layers = 1u); 267 268 private: 269 void beginRendering(const DeviceInterface &vk, const VkCommandBuffer commandBuffer) const; 270 271 bool m_isDynamicRendering; 272 vk::Move<vk::VkRenderPass> m_renderPass; 273 vk::Move<vk::VkFramebuffer> m_framebuffer; 274 275 #ifndef CTS_USES_VULKANSC 276 struct Subpass 277 { 278 struct Attachment 279 { 280 uint32_t index = VK_ATTACHMENT_UNUSED; 281 vk::VkRenderingAttachmentInfo attachmentInfo = {}; 282 vk::VkFormat format; 283 vk::VkAttachmentLoadOp stencilLoadOp = vk::VK_ATTACHMENT_LOAD_OP_LOAD; 284 vk::VkAttachmentStoreOp stencilStoreOp = vk::VK_ATTACHMENT_STORE_OP_STORE; 285 }; 286 mutable std::vector<Attachment> m_colorAttachments; 287 mutable Attachment m_depthStencilAttachment; 288 mutable std::vector<Attachment> m_resolveAttachments; 289 mutable VkMultisampledRenderToSingleSampledInfoEXT m_msrtss = {}; 290 mutable VkSubpassDescriptionDepthStencilResolve m_dsr = {}; 291 mutable VkAttachmentReference2 m_depthStencilResolveAttachment = {}; 292 }; 293 struct SubpassDependency 294 { 295 SubpassDependency(const VkSubpassDependency &dependency); 296 SubpassDependency(const VkSubpassDependency2 &dependency); 297 298 uint32_t srcSubpass; 299 uint32_t dstSubpass; 300 VkPipelineStageFlags2 srcStageMask; 301 VkPipelineStageFlags2 dstStageMask; 302 VkAccessFlags2 srcAccessMask; 303 VkAccessFlags2 dstAccessMask; 304 VkDependencyFlags dependencyFlags; 305 bool sync2; 306 }; 307 std::vector<Subpass> m_subpasses; 308 std::vector<SubpassDependency> m_dependencies; 309 std::vector<vk::VkAttachmentDescription2> m_attachments; 310 std::vector<vk::VkImage> m_images; 311 std::vector<vk::VkImageView> m_imageViews; 312 mutable std::vector<vk::VkClearValue> m_clearValues; 313 mutable std::vector<vk::VkImageLayout> m_layouts; 314 mutable uint32_t m_activeSubpass = 0; 315 mutable vk::VkRenderingInfo m_renderingInfo; 316 uint32_t m_layers = 1; 317 std::vector<uint32_t> m_viewMasks; 318 mutable bool m_secondaryCommandBuffers; 319 320 void clearAttachments(const DeviceInterface &vk, const VkCommandBuffer commandBuffer) const; 321 void updateLayout(VkImage updatedImage, VkImageLayout newLayout) const; 322 void transitionLayouts(const DeviceInterface &vk, const VkCommandBuffer commandBuffer, const Subpass &subpass, 323 bool renderPassBegin) const; 324 void insertDependencies(const DeviceInterface &vk, const VkCommandBuffer commandBuffer, uint32_t subpassIdx) const; 325 326 public: 327 void fillInheritanceRenderingInfo(uint32_t subpassIndex, std::vector<vk::VkFormat> *colorFormats, 328 vk::VkCommandBufferInheritanceRenderingInfo *inheritanceRenderingInfo) const; 329 330 private: 331 #endif 332 }; 333 334 class ShaderWrapper 335 { 336 public: 337 ShaderWrapper(); 338 339 ShaderWrapper(const DeviceInterface &vk, VkDevice device, const vk::ProgramBinary &binary, 340 const vk::VkShaderModuleCreateFlags createFlags = 0u); 341 342 ShaderWrapper(const ShaderWrapper &rhs) noexcept; 343 344 ~ShaderWrapper() = default; 345 346 ShaderWrapper &operator=(const ShaderWrapper &rhs) noexcept; 347 isSet(void) const348 bool isSet(void) const 349 { 350 return m_binary != nullptr; 351 } 352 353 vk::VkShaderModule getModule(void) const; 354 355 size_t getCodeSize(void) const; 356 void *getBinary(void) const; 357 358 void createModule(void); 359 void setLayoutAndSpecialization(const PipelineLayoutWrapper *layout, 360 const VkSpecializationInfo *specializationInfo); 361 getPipelineLayout(void) const362 const PipelineLayoutWrapper *getPipelineLayout(void) const 363 { 364 return m_layout; 365 } getSpecializationInfo(void) const366 const VkSpecializationInfo *getSpecializationInfo(void) const 367 { 368 return m_specializationInfo; 369 } 370 371 #ifndef CTS_USES_VULKANSC getShader(void) const372 vk::VkShaderEXT getShader(void) const 373 { 374 return m_shader ? *m_shader : VK_NULL_HANDLE; 375 } setShader(Move<VkShaderEXT> shader)376 void setShader(Move<VkShaderEXT> shader) 377 { 378 m_shader = shader; 379 } 380 addFlags(const VkShaderCreateFlagsEXT flags)381 void addFlags(const VkShaderCreateFlagsEXT flags) 382 { 383 m_shaderCreateFlags |= flags; 384 } 385 void getShaderBinary(void); getShaderBinaryDataSize(void)386 size_t getShaderBinaryDataSize(void) 387 { 388 return m_binaryDataSize; 389 } getShaderBinaryData(void)390 void *getShaderBinaryData(void) 391 { 392 return m_binaryData.data(); 393 } 394 #endif 395 396 private: 397 const DeviceInterface *m_vk; 398 VkDevice m_device; 399 const vk::ProgramBinary *m_binary; 400 vk::VkShaderModuleCreateFlags m_moduleCreateFlags; 401 mutable vk::Move<vk::VkShaderModule> m_module; 402 const PipelineLayoutWrapper *m_layout; 403 const VkSpecializationInfo *m_specializationInfo; 404 #ifndef CTS_USES_VULKANSC 405 vk::Move<vk::VkShaderEXT> m_shader; 406 VkShaderCreateFlagsEXT m_shaderCreateFlags; 407 size_t m_binaryDataSize; 408 std::vector<uint8_t> m_binaryData; 409 #endif 410 }; 411 412 // Class that can build monolithic pipeline or fully separated pipeline libraries 413 // depending on PipelineType specified in the constructor. 414 // Rarely needed configuration was extracted to setDefault*/disable* functions while common 415 // state setup is provided as arguments of four setup* functions - one for each state group. 416 class GraphicsPipelineWrapper 417 { 418 public: 419 GraphicsPipelineWrapper(const InstanceInterface &vki, const DeviceInterface &vk, VkPhysicalDevice physicalDevice, 420 VkDevice device, const std::vector<std::string> &deviceExtensions, 421 const PipelineConstructionType pipelineConstructionType, 422 const VkPipelineCreateFlags flags = 0u); 423 424 GraphicsPipelineWrapper(GraphicsPipelineWrapper &&) noexcept; 425 426 ~GraphicsPipelineWrapper(void) = default; 427 428 // By default pipelineLayout used for monotlithic pipeline is taken from layout specified 429 // in setupPreRasterizationShaderState but when there are also descriptor sets needed for fragment 430 // shader bindings then separate pipeline layout for monolithic pipeline must be provided 431 GraphicsPipelineWrapper &setMonolithicPipelineLayout(const PipelineLayoutWrapper &layout); 432 433 // By default dynamic state has to be specified before specifying other CreateInfo structures 434 GraphicsPipelineWrapper &setDynamicState(const VkPipelineDynamicStateCreateInfo *dynamicState); 435 436 // When this wrapper is used with functionality provided by VK_KHR_pipeline_binary 437 // then we need to be able to set binaries for individual pipeline parts as well as for monolithic pipeline. 438 GraphicsPipelineWrapper &setMonolithicPipelineBinaries(PipelineBinaryInfoWrapper binaries); 439 440 // Specify the representative fragment test state. 441 GraphicsPipelineWrapper &setRepresentativeFragmentTestState( 442 PipelineRepresentativeFragmentTestCreateInfoWrapper representativeFragmentTestState); 443 444 // Specify pipeline robustness state 445 GraphicsPipelineWrapper &setPipelineRobustnessState(PipelineRobustnessCreateInfoWrapper pipelineRobustnessState); 446 447 // Specifying how a pipeline is created using VkPipelineCreateFlags2CreateInfoKHR. 448 GraphicsPipelineWrapper &setPipelineCreateFlags2(PipelineCreateFlags2 pipelineFlags2); 449 450 // Specify how shaders should be created with explicit flags. Note we could try to unify this with 451 // setPipelineCreateFlags2 but the equivalence is not direct and some flags do not map. 452 GraphicsPipelineWrapper &setShaderCreateFlags(ShaderCreateFlags shaderFlags); 453 454 // Specify topology that is used by default InputAssemblyState in vertex input state. This needs to be 455 // specified only when there is no custom InputAssemblyState provided in setupVertexInputState and when 456 // topology is diferent then VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST which is used by default. 457 GraphicsPipelineWrapper &setDefaultTopology(const VkPrimitiveTopology topology); 458 459 // Specify patch control points that is used by default TessellationState in pre-rasterization shader state. 460 // This can to be specified only when there is no custom TessellationState provided in 461 // setupPreRasterizationShaderState and when patchControlPoints is diferent then 3 which is used by default. 462 // A value of std::numeric_limits<uint32_t>::max() forces the tessellation state to be null. 463 GraphicsPipelineWrapper &setDefaultPatchControlPoints(const uint32_t patchControlPoints); 464 465 // Specify tesellation domain origin, used by the tessellation state in pre-rasterization shader state. 466 GraphicsPipelineWrapper &setDefaultTessellationDomainOrigin(const VkTessellationDomainOrigin domainOrigin, 467 bool forceExtStruct = false); 468 469 // Enable discarding of primitives that is used by default RasterizationState in pre-rasterization shader state. 470 // This can be specified only when there is no custom RasterizationState provided in setupPreRasterizationShaderState. 471 GraphicsPipelineWrapper &setDefaultRasterizerDiscardEnable(const bool rasterizerDiscardEnable = true); 472 473 // When some states are not provided then default structures can be used. This behaviour can be turned on by one of below methods. 474 // Some tests require those states to be NULL so we can't assume using default versions. 475 GraphicsPipelineWrapper &setDefaultRasterizationState(void); 476 GraphicsPipelineWrapper &setDefaultDepthStencilState(void); 477 GraphicsPipelineWrapper &setDefaultColorBlendState(void); 478 GraphicsPipelineWrapper &setDefaultMultisampleState(void); 479 GraphicsPipelineWrapper &setDefaultVertexInputState(const bool useDefaultVertexInputState); 480 481 // Pre-rasterization shader state uses provieded viewports and scissors to create ViewportState. By default 482 // number of viewports and scissors is same as number of items in vector but when vectors are empty then by 483 // default count of viewports/scissors is set to 1. This can be changed by below functions. 484 GraphicsPipelineWrapper &setDefaultViewportsCount(uint32_t viewportCount = 0u); 485 GraphicsPipelineWrapper &setDefaultScissorsCount(uint32_t scissorCount = 0u); 486 487 // Pre-rasterization shader state uses default ViewportState, this method extends the internal structure. 488 GraphicsPipelineWrapper &setViewportStatePnext(const void *pNext); 489 490 #ifndef CTS_USES_VULKANSC 491 GraphicsPipelineWrapper &setRenderingColorAttachmentsInfo( 492 PipelineRenderingCreateInfoWrapper pipelineRenderingCreateInfo); 493 #endif 494 495 // Pre-rasterization shader state uses provieded viewports and scissors to create ViewportState. When disableViewportState 496 // is used then ViewportState won't be constructed and NULL will be used. 497 GraphicsPipelineWrapper &disableViewportState(const bool disable = true); 498 499 // Setup vertex input state. When VertexInputState or InputAssemblyState are not provided then default structures will be used. 500 GraphicsPipelineWrapper &setupVertexInputState( 501 const VkPipelineVertexInputStateCreateInfo *vertexInputState = nullptr, 502 const VkPipelineInputAssemblyStateCreateInfo *inputAssemblyState = nullptr, 503 const VkPipelineCache partPipelineCache = VK_NULL_HANDLE, 504 PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback = PipelineCreationFeedbackCreateInfoWrapper(), 505 PipelineBinaryInfoWrapper partBinaries = PipelineBinaryInfoWrapper(), const bool useNullPtrs = false); 506 507 // When disableShaderModules is used module attributes in VkPipelineShaderStageCreateInfo will be set to NULL. 508 // This is needed for VK_KHR_pipeline_binary tests where we need to construct a pipeline from pipeline binaries without using modules. 509 GraphicsPipelineWrapper &disableShaderModules(const bool disable = true); 510 511 // Setup pre-rasterization shader state. 512 GraphicsPipelineWrapper &setupPreRasterizationShaderState( 513 const std::vector<VkViewport> &viewports, const std::vector<VkRect2D> &scissors, 514 const PipelineLayoutWrapper &layout, const VkRenderPass renderPass, const uint32_t subpass, 515 const ShaderWrapper vertexShaderModule, 516 const VkPipelineRasterizationStateCreateInfo *rasterizationState = nullptr, 517 const ShaderWrapper tessellationControlShader = ShaderWrapper(), 518 const ShaderWrapper tessellationEvalShader = ShaderWrapper(), 519 const ShaderWrapper geometryShader = ShaderWrapper(), const VkSpecializationInfo *specializationInfo = nullptr, 520 VkPipelineFragmentShadingRateStateCreateInfoKHR *fragmentShadingRateState = nullptr, 521 PipelineRenderingCreateInfoWrapper rendering = PipelineRenderingCreateInfoWrapper(), 522 const VkPipelineCache partPipelineCache = VK_NULL_HANDLE, 523 PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback = PipelineCreationFeedbackCreateInfoWrapper()); 524 525 GraphicsPipelineWrapper &setupPreRasterizationShaderState2( 526 const std::vector<VkViewport> &viewports, const std::vector<VkRect2D> &scissors, 527 const PipelineLayoutWrapper &layout, const VkRenderPass renderPass, const uint32_t subpass, 528 const ShaderWrapper vertexShaderModule, 529 const VkPipelineRasterizationStateCreateInfo *rasterizationState = nullptr, 530 const ShaderWrapper tessellationControlShader = ShaderWrapper(), 531 const ShaderWrapper tessellationEvalShader = ShaderWrapper(), 532 const ShaderWrapper geometryShader = ShaderWrapper(), 533 const VkSpecializationInfo *vertSpecializationInfo = nullptr, 534 const VkSpecializationInfo *tescSpecializationInfo = nullptr, 535 const VkSpecializationInfo *teseSpecializationInfo = nullptr, 536 const VkSpecializationInfo *geomSpecializationInfo = nullptr, 537 VkPipelineFragmentShadingRateStateCreateInfoKHR *fragmentShadingRateState = nullptr, 538 PipelineRenderingCreateInfoWrapper rendering = PipelineRenderingCreateInfoWrapper(), 539 const VkPipelineCache partPipelineCache = VK_NULL_HANDLE, 540 PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback = PipelineCreationFeedbackCreateInfoWrapper()); 541 542 // Note: VkPipelineShaderStageModuleIdentifierCreateInfoEXT::pIdentifier will not be copied. They need to continue to exist outside this wrapper. 543 GraphicsPipelineWrapper &setupPreRasterizationShaderState3( 544 const std::vector<VkViewport> &viewports, const std::vector<VkRect2D> &scissors, 545 const PipelineLayoutWrapper &layout, const VkRenderPass renderPass, const uint32_t subpass, 546 const ShaderWrapper vertexShaderModule, 547 PipelineShaderStageModuleIdentifierCreateInfoWrapper vertShaderModuleId = 548 PipelineShaderStageModuleIdentifierCreateInfoWrapper(), 549 const VkPipelineRasterizationStateCreateInfo *rasterizationState = nullptr, 550 const ShaderWrapper tessellationControlShader = ShaderWrapper(), 551 PipelineShaderStageModuleIdentifierCreateInfoWrapper tescShaderModuleId = 552 PipelineShaderStageModuleIdentifierCreateInfoWrapper(), 553 const ShaderWrapper tessellationEvalShader = ShaderWrapper(), 554 PipelineShaderStageModuleIdentifierCreateInfoWrapper teseShaderModuleId = 555 PipelineShaderStageModuleIdentifierCreateInfoWrapper(), 556 const ShaderWrapper geometryShader = ShaderWrapper(), 557 PipelineShaderStageModuleIdentifierCreateInfoWrapper geomShaderModuleId = 558 PipelineShaderStageModuleIdentifierCreateInfoWrapper(), 559 const VkSpecializationInfo *vertSpecializationInfo = nullptr, 560 const VkSpecializationInfo *tescSpecializationInfo = nullptr, 561 const VkSpecializationInfo *teseSpecializationInfo = nullptr, 562 const VkSpecializationInfo *geomSpecializationInfo = nullptr, 563 VkPipelineFragmentShadingRateStateCreateInfoKHR *fragmentShadingRateState = nullptr, 564 PipelineRenderingCreateInfoWrapper rendering = PipelineRenderingCreateInfoWrapper(), 565 const VkPipelineCache partPipelineCache = VK_NULL_HANDLE, 566 PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback = PipelineCreationFeedbackCreateInfoWrapper(), 567 PipelineBinaryInfoWrapper partBinaries = PipelineBinaryInfoWrapper()); 568 569 #ifndef CTS_USES_VULKANSC 570 // Setup pre-rasterization shader state, mesh shading version. 571 GraphicsPipelineWrapper &setupPreRasterizationMeshShaderState( 572 const std::vector<VkViewport> &viewports, const std::vector<VkRect2D> &scissors, 573 const PipelineLayoutWrapper &layout, const VkRenderPass renderPass, const uint32_t subpass, 574 const ShaderWrapper taskShader, const ShaderWrapper meshShader, 575 const VkPipelineRasterizationStateCreateInfo *rasterizationState = nullptr, 576 const VkSpecializationInfo *taskSpecializationInfo = nullptr, 577 const VkSpecializationInfo *meshSpecializationInfo = nullptr, 578 VkPipelineFragmentShadingRateStateCreateInfoKHR *fragmentShadingRateState = nullptr, 579 PipelineRenderingCreateInfoWrapper rendering = PipelineRenderingCreateInfoWrapper(), 580 const VkPipelineCache partPipelineCache = VK_NULL_HANDLE, 581 VkPipelineCreationFeedbackCreateInfoEXT *partCreationFeedback = nullptr); 582 583 GraphicsPipelineWrapper &setupPreRasterizationMeshShaderState2( 584 const std::vector<VkViewport> &viewports, const std::vector<VkRect2D> &scissors, 585 const PipelineLayoutWrapper &layout, const VkRenderPass renderPass, const uint32_t subpass, 586 const ShaderWrapper taskShader, PipelineShaderStageModuleIdentifierCreateInfoWrapper taskShaderModuleId, 587 const ShaderWrapper meshShader, PipelineShaderStageModuleIdentifierCreateInfoWrapper meshShaderModuleId, 588 const VkPipelineRasterizationStateCreateInfo *rasterizationState = nullptr, 589 const VkSpecializationInfo *taskSpecializationInfo = nullptr, 590 const VkSpecializationInfo *meshSpecializationInfo = nullptr, 591 VkPipelineFragmentShadingRateStateCreateInfoKHR *fragmentShadingRateState = nullptr, 592 PipelineRenderingCreateInfoWrapper rendering = PipelineRenderingCreateInfoWrapper(), 593 const VkPipelineCache partPipelineCache = VK_NULL_HANDLE, 594 VkPipelineCreationFeedbackCreateInfoEXT *partCreationFeedback = nullptr); 595 #endif // CTS_USES_VULKANSC 596 597 // Setup fragment shader state. 598 GraphicsPipelineWrapper &setupFragmentShaderState( 599 const PipelineLayoutWrapper &layout, const VkRenderPass renderPass, const uint32_t subpass, 600 const ShaderWrapper fragmentShaderModule, 601 const VkPipelineDepthStencilStateCreateInfo *depthStencilState = nullptr, 602 const VkPipelineMultisampleStateCreateInfo *multisampleState = nullptr, 603 const VkSpecializationInfo *specializationInfo = nullptr, 604 const VkPipelineCache partPipelineCache = VK_NULL_HANDLE, 605 PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback = PipelineCreationFeedbackCreateInfoWrapper(), 606 RenderingInputAttachmentIndexInfoWrapper renderingInputAttachmentIndexInfo = 607 RenderingInputAttachmentIndexInfoWrapper()); 608 609 // Note: VkPipelineShaderStageModuleIdentifierCreateInfoEXT::pIdentifier will not be copied. They need to continue to exist outside this wrapper. 610 GraphicsPipelineWrapper &setupFragmentShaderState2( 611 const PipelineLayoutWrapper &layout, const VkRenderPass renderPass, const uint32_t subpass, 612 const ShaderWrapper fragmentShaderModule, 613 PipelineShaderStageModuleIdentifierCreateInfoWrapper fragmentShaderModuleId = 614 PipelineShaderStageModuleIdentifierCreateInfoWrapper(), 615 const VkPipelineDepthStencilStateCreateInfo *depthStencilState = nullptr, 616 const VkPipelineMultisampleStateCreateInfo *multisampleState = nullptr, 617 const VkSpecializationInfo *specializationInfo = nullptr, 618 const VkPipelineCache partPipelineCache = VK_NULL_HANDLE, 619 PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback = PipelineCreationFeedbackCreateInfoWrapper(), 620 RenderingInputAttachmentIndexInfoWrapper renderingInputAttachmentIndexInfo = 621 RenderingInputAttachmentIndexInfoWrapper(), 622 PipelineBinaryInfoWrapper partBinaries = PipelineBinaryInfoWrapper()); 623 624 // Setup fragment output state. 625 GraphicsPipelineWrapper &setupFragmentOutputState( 626 const VkRenderPass renderPass, const uint32_t subpass = 0u, 627 const VkPipelineColorBlendStateCreateInfo *colorBlendState = nullptr, 628 const VkPipelineMultisampleStateCreateInfo *multisampleState = nullptr, 629 const VkPipelineCache partPipelineCache = VK_NULL_HANDLE, 630 PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback = PipelineCreationFeedbackCreateInfoWrapper(), 631 RenderingAttachmentLocationInfoWrapper renderingAttachmentLocationInfo = 632 RenderingAttachmentLocationInfoWrapper(), 633 PipelineBinaryInfoWrapper partBinaries = PipelineBinaryInfoWrapper()); 634 635 // Build pipeline object out of provided state. 636 void buildPipeline( 637 const VkPipelineCache pipelineCache = VK_NULL_HANDLE, const VkPipeline basePipelineHandle = VK_NULL_HANDLE, 638 const int32_t basePipelineIndex = 0, 639 PipelineCreationFeedbackCreateInfoWrapper creationFeedback = PipelineCreationFeedbackCreateInfoWrapper(), 640 void *pNext = nullptr); 641 // Create shader objects if used 642 #ifndef CTS_USES_VULKANSC 643 vk::VkShaderStageFlags getNextStages(vk::VkShaderStageFlagBits shaderStage, bool tessellationShaders, 644 bool geometryShaders, bool link); 645 vk::VkShaderCreateInfoEXT makeShaderCreateInfo(VkShaderStageFlagBits stage, ShaderWrapper &shader, bool link, 646 bool binary, ShaderWrapper &other); 647 void createShaders(bool linked, bool binary); 648 #endif 649 650 // Bind pipeline or shader objects 651 void bind(vk::VkCommandBuffer cmdBuffer) const; 652 653 // Returns true when pipeline was build using buildPipeline method. 654 bool wasBuild(void) const; 655 // Returns true when pipeline or shader objects was built. 656 bool wasPipelineOrShaderObjectBuild(void) const; 657 658 // Get compleate pipeline. GraphicsPipelineWrapper preserves ovnership and will destroy pipeline in its destructor. 659 vk::VkPipeline getPipeline(void) const; 660 661 // Get partial pipeline. GraphicsPipelineWrapper preserves ovnership and will desroy pipeline in its destructor. 662 vk::VkPipeline getPartialPipeline(uint32_t part) const; 663 664 // Get compleate pipeline create info. 665 const VkGraphicsPipelineCreateInfo &getPipelineCreateInfo(void) const; 666 667 // Get partial pipeline create info. 668 const VkGraphicsPipelineCreateInfo &getPartialPipelineCreateInfo(uint32_t part) const; 669 670 #ifndef CTS_USES_VULKANSC 671 // Get particular shader. GraphicsPipelineWrapper preserves ovnership and will destroy shaders in its destructor. 672 vk::VkShaderEXT getShader(VkShaderStageFlagBits stage) const; 673 #endif 674 675 // Destroy compleate pipeline - pipeline parts are not destroyed. 676 void destroyPipeline(void); 677 678 protected: 679 // No default constructor - use parametrized constructor or emplace_back in case of vectors. 680 GraphicsPipelineWrapper() = default; 681 682 // Dynamic states that are only dynamic in shader objects 683 bool isShaderObjectDynamic(vk::VkDynamicState dynamicState) const; 684 void setShaderObjectDynamicStates(vk::VkCommandBuffer cmdBuffer) const; 685 686 struct InternalData; 687 688 protected: 689 static constexpr size_t kMaxPipelineParts = 4u; 690 691 // Store partial pipelines when non monolithic construction was used. 692 Move<VkPipeline> m_pipelineParts[kMaxPipelineParts]; 693 694 // Store monolithic pipeline or linked pipeline libraries. 695 Move<VkPipeline> m_pipelineFinal; 696 697 // Store internal data that is needed only for pipeline construction. 698 de::SharedPtr<InternalData> m_internalData; 699 }; 700 701 std::vector<VkDynamicState> getShaderObjectDynamicStatesFromExtensions(const std::vector<std::string> &extensions); 702 703 } // namespace vk 704 705 #endif // _VKPIPELINECONSTRUCTIONUTIL_HPP 706