1 #ifndef _VKPIPELINECONSTRUCTIONUTIL_HPP 2 #define _VKPIPELINECONSTRUCTIONUTIL_HPP 3 /*------------------------------------------------------------------------ 4 * Vulkan Conformance Tests 5 * ------------------------ 6 * 7 * Copyright (c) 2021 The Khronos Group Inc. 8 * 9 * Licensed under the Apache License, Version 2.0 (the "License"); 10 * you may not use this file except in compliance with the License. 11 * You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 * 21 *//*! 22 * \file 23 * \brief Wrapper that can construct monolithic pipeline or use 24 VK_EXT_graphics_pipeline_library for pipeline construction. 25 *//*--------------------------------------------------------------------*/ 26 27 #include "vkRef.hpp" 28 #include "vkDefs.hpp" 29 #include "tcuDefs.hpp" 30 #include "deSharedPtr.hpp" 31 #include <vector> 32 #include <stdexcept> 33 34 namespace vk 35 { 36 37 enum PipelineConstructionType 38 { 39 PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC = 0, // Construct legacy - monolithic pipeline 40 PIPELINE_CONSTRUCTION_TYPE_LINK_TIME_OPTIMIZED_LIBRARY, // Use VK_EXT_graphics_pipeline_library and construct pipeline out of several pipeline parts. 41 PIPELINE_CONSTRUCTION_TYPE_FAST_LINKED_LIBRARY // Same as PIPELINE_CONSTRUCTION_TYPE_OPTIMISED_LIBRARY but with fast linking 42 }; 43 44 void checkPipelineLibraryRequirements (const InstanceInterface& vki, 45 VkPhysicalDevice physicalDevice, 46 PipelineConstructionType pipelineConstructionType); 47 48 // This exception may be raised in one of the intermediate steps when using shader module IDs instead of normal module objects. 49 class PipelineCompileRequiredError : public std::runtime_error 50 { 51 public: PipelineCompileRequiredError(const std::string & msg)52 PipelineCompileRequiredError (const std::string& msg) 53 : std::runtime_error(msg) 54 {} 55 }; 56 57 // PointerWrapper template is used to hide structures that should not be visible for Vulkan SC 58 template <typename T> 59 class PointerWrapper 60 { 61 public: PointerWrapper()62 PointerWrapper(): ptr(DE_NULL) {} PointerWrapper(T * p0)63 PointerWrapper(T* p0) : ptr(p0) {} 64 T* ptr; 65 }; 66 67 template <typename T> 68 class ConstPointerWrapper 69 { 70 public: ConstPointerWrapper()71 ConstPointerWrapper(): ptr(DE_NULL) {} ConstPointerWrapper(const T * p0)72 ConstPointerWrapper(const T* p0) : ptr(p0) {} 73 const T* ptr; 74 }; 75 76 #ifndef CTS_USES_VULKANSC 77 typedef PointerWrapper<VkPipelineViewportDepthClipControlCreateInfoEXT> PipelineViewportDepthClipControlCreateInfoWrapper; 78 typedef PointerWrapper<VkPipelineRenderingCreateInfoKHR> PipelineRenderingCreateInfoWrapper; 79 typedef PointerWrapper<VkPipelineCreationFeedbackCreateInfoEXT> PipelineCreationFeedbackCreateInfoWrapper; 80 typedef ConstPointerWrapper<VkPipelineShaderStageModuleIdentifierCreateInfoEXT> PipelineShaderStageModuleIdentifierCreateInfoWrapper; 81 typedef PointerWrapper<VkPipelineRepresentativeFragmentTestStateCreateInfoNV> PipelineRepresentativeFragmentTestCreateInfoWrapper; 82 #else 83 typedef PointerWrapper<void> PipelineViewportDepthClipControlCreateInfoWrapper; 84 typedef PointerWrapper<void> PipelineRenderingCreateInfoWrapper; 85 typedef PointerWrapper<void> PipelineCreationFeedbackCreateInfoWrapper; 86 typedef ConstPointerWrapper<void> PipelineShaderStageModuleIdentifierCreateInfoWrapper; 87 typedef PointerWrapper<void> PipelineRepresentativeFragmentTestCreateInfoWrapper; 88 #endif 89 90 // Class that can build monolithic pipeline or fully separated pipeline libraries 91 // depending on PipelineType specified in the constructor. 92 // Rarely needed configuration was extracted to setDefault*/disable* functions while common 93 // state setup is provided as arguments of four setup* functions - one for each state group. 94 class GraphicsPipelineWrapper 95 { 96 public: 97 GraphicsPipelineWrapper (const DeviceInterface& vk, 98 VkDevice device, 99 const PipelineConstructionType pipelineConstructionType, 100 const VkPipelineCreateFlags flags = 0u); 101 102 GraphicsPipelineWrapper (GraphicsPipelineWrapper&&) noexcept; 103 104 ~GraphicsPipelineWrapper (void) = default; 105 106 107 // By default pipelineLayout used for monotlithic pipeline is taken from layout specified 108 // in setupPreRasterizationShaderState but when there are also descriptor sets needed for fragment 109 // shader bindings then separate pipeline layout for monolithic pipeline must be provided 110 GraphicsPipelineWrapper& setMonolithicPipelineLayout (const VkPipelineLayout layout); 111 112 113 // By default dynamic state has to be specified before specifying other CreateInfo structures 114 GraphicsPipelineWrapper& setDynamicState (const VkPipelineDynamicStateCreateInfo* dynamicState); 115 116 // Specify the representative fragment test state. 117 GraphicsPipelineWrapper& setRepresentativeFragmentTestState (PipelineRepresentativeFragmentTestCreateInfoWrapper representativeFragmentTestState); 118 119 // Specify topology that is used by default InputAssemblyState in vertex input state. This needs to be 120 // specified only when there is no custom InputAssemblyState provided in setupVertexInputState and when 121 // topology is diferent then VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST which is used by default. 122 GraphicsPipelineWrapper& setDefaultTopology (const VkPrimitiveTopology topology); 123 124 // Specify patch control points that is used by default TessellationState in pre-rasterization shader state. 125 // This can to be specified only when there is no custom TessellationState provided in 126 // setupPreRasterizationShaderState and when patchControlPoints is diferent then 3 which is used by default. 127 GraphicsPipelineWrapper& setDefaultPatchControlPoints (const deUint32 patchControlPoints); 128 129 // Specify tesellation domain origin, used by the tessellation state in pre-rasterization shader state. 130 GraphicsPipelineWrapper& setDefaultTessellationDomainOrigin (const VkTessellationDomainOrigin domainOrigin, bool forceExtStruct = false); 131 132 // Enable discarding of primitives that is used by default RasterizationState in pre-rasterization shader state. 133 // This can be specified only when there is no custom RasterizationState provided in setupPreRasterizationShaderState. 134 GraphicsPipelineWrapper& setDefaultRasterizerDiscardEnable (const deBool rasterizerDiscardEnable = DE_TRUE); 135 136 // When some states are not provided then default structures can be used. This behaviour can be turned on by one of below methods. 137 // Some tests require those states to be NULL so we can't assume using default versions. 138 GraphicsPipelineWrapper& setDefaultRasterizationState (void); 139 GraphicsPipelineWrapper& setDefaultDepthStencilState (void); 140 GraphicsPipelineWrapper& setDefaultColorBlendState (void); 141 GraphicsPipelineWrapper& setDefaultMultisampleState (void); 142 143 // Pre-rasterization shader state uses provieded viewports and scissors to create ViewportState. By default 144 // number of viewports and scissors is same as number of items in vector but when vectors are empty then by 145 // default count of viewports/scissors is set to 1. This can be changed by below functions. 146 GraphicsPipelineWrapper& setDefaultViewportsCount (deUint32 viewportCount = 0u); 147 GraphicsPipelineWrapper& setDefaultScissorsCount (deUint32 scissorCount = 0u); 148 149 // Pre-rasterization shader state uses default ViewportState, this method extends the internal structure. 150 GraphicsPipelineWrapper& setViewportStatePnext (const void* pNext); 151 152 #ifndef CTS_USES_VULKANSC 153 GraphicsPipelineWrapper& setRenderingColorAttachmentsInfo (PipelineRenderingCreateInfoWrapper pipelineRenderingCreateInfo); 154 #endif 155 156 // Pre-rasterization shader state uses provieded viewports and scissors to create ViewportState. When disableViewportState 157 // is used then ViewportState won't be constructed and NULL will be used. 158 GraphicsPipelineWrapper& disableViewportState (void); 159 160 161 // Setup vertex input state. When VertexInputState or InputAssemblyState are not provided then default structures will be used. 162 GraphicsPipelineWrapper& setupVertexInputState (const VkPipelineVertexInputStateCreateInfo* vertexInputState = DE_NULL, 163 const VkPipelineInputAssemblyStateCreateInfo* inputAssemblyState = DE_NULL, 164 const VkPipelineCache partPipelineCache = DE_NULL, 165 PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback = PipelineCreationFeedbackCreateInfoWrapper()); 166 167 // Setup pre-rasterization shader state. 168 GraphicsPipelineWrapper& setupPreRasterizationShaderState (const std::vector<VkViewport>& viewports, 169 const std::vector<VkRect2D>& scissors, 170 const VkPipelineLayout layout, 171 const VkRenderPass renderPass, 172 const deUint32 subpass, 173 const VkShaderModule vertexShaderModule, 174 const VkPipelineRasterizationStateCreateInfo* rasterizationState = DE_NULL, 175 const VkShaderModule tessellationControlShaderModule = DE_NULL, 176 const VkShaderModule tessellationEvalShaderModule = DE_NULL, 177 const VkShaderModule geometryShaderModule = DE_NULL, 178 const VkSpecializationInfo* specializationInfo = DE_NULL, 179 VkPipelineFragmentShadingRateStateCreateInfoKHR* fragmentShadingRateState = nullptr, 180 PipelineRenderingCreateInfoWrapper rendering = PipelineRenderingCreateInfoWrapper(), 181 const VkPipelineCache partPipelineCache = DE_NULL, 182 PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback = PipelineCreationFeedbackCreateInfoWrapper()); 183 184 GraphicsPipelineWrapper& setupPreRasterizationShaderState2 (const std::vector<VkViewport>& viewports, 185 const std::vector<VkRect2D>& scissors, 186 const VkPipelineLayout layout, 187 const VkRenderPass renderPass, 188 const deUint32 subpass, 189 const VkShaderModule vertexShaderModule, 190 const VkPipelineRasterizationStateCreateInfo* rasterizationState = nullptr, 191 const VkShaderModule tessellationControlShaderModulnullptre = DE_NULL, 192 const VkShaderModule tessellationEvalShaderModule = DE_NULL, 193 const VkShaderModule geometryShaderModule = DE_NULL, 194 const VkSpecializationInfo* vertSpecializationInfo = nullptr, 195 const VkSpecializationInfo* tescSpecializationInfo = nullptr, 196 const VkSpecializationInfo* teseSpecializationInfo = nullptr, 197 const VkSpecializationInfo* geomSpecializationInfo = nullptr, 198 VkPipelineFragmentShadingRateStateCreateInfoKHR* fragmentShadingRateState = nullptr, 199 PipelineRenderingCreateInfoWrapper rendering = PipelineRenderingCreateInfoWrapper(), 200 const VkPipelineCache partPipelineCache = DE_NULL, 201 PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback = PipelineCreationFeedbackCreateInfoWrapper()); 202 203 // Note: VkPipelineShaderStageModuleIdentifierCreateInfoEXT::pIdentifier will not be copied. They need to continue to exist outside this wrapper. 204 GraphicsPipelineWrapper& setupPreRasterizationShaderState3 (const std::vector<VkViewport>& viewports, 205 const std::vector<VkRect2D>& scissors, 206 const VkPipelineLayout layout, 207 const VkRenderPass renderPass, 208 const deUint32 subpass, 209 const VkShaderModule vertexShaderModule, 210 PipelineShaderStageModuleIdentifierCreateInfoWrapper vertShaderModuleId = PipelineShaderStageModuleIdentifierCreateInfoWrapper(), 211 const VkPipelineRasterizationStateCreateInfo* rasterizationState = nullptr, 212 const VkShaderModule tessellationControlShaderModule = DE_NULL, 213 PipelineShaderStageModuleIdentifierCreateInfoWrapper tescShaderModuleId = PipelineShaderStageModuleIdentifierCreateInfoWrapper(), 214 const VkShaderModule tessellationEvalShaderModule = DE_NULL, 215 PipelineShaderStageModuleIdentifierCreateInfoWrapper teseShaderModuleId = PipelineShaderStageModuleIdentifierCreateInfoWrapper(), 216 const VkShaderModule geometryShaderModule = DE_NULL, 217 PipelineShaderStageModuleIdentifierCreateInfoWrapper geomShaderModuleId = PipelineShaderStageModuleIdentifierCreateInfoWrapper(), 218 const VkSpecializationInfo* vertSpecializationInfo = nullptr, 219 const VkSpecializationInfo* tescSpecializationInfo = nullptr, 220 const VkSpecializationInfo* teseSpecializationInfo = nullptr, 221 const VkSpecializationInfo* geomSpecializationInfo = nullptr, 222 VkPipelineFragmentShadingRateStateCreateInfoKHR* fragmentShadingRateState = nullptr, 223 PipelineRenderingCreateInfoWrapper rendering = PipelineRenderingCreateInfoWrapper(), 224 const VkPipelineCache partPipelineCache = DE_NULL, 225 PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback = PipelineCreationFeedbackCreateInfoWrapper()); 226 227 #ifndef CTS_USES_VULKANSC 228 // Setup pre-rasterization shader state, mesh shading version. 229 GraphicsPipelineWrapper& setupPreRasterizationMeshShaderState(const std::vector<VkViewport>& viewports, 230 const std::vector<VkRect2D>& scissors, 231 const VkPipelineLayout layout, 232 const VkRenderPass renderPass, 233 const deUint32 subpass, 234 const VkShaderModule taskShaderModule, 235 const VkShaderModule meshShaderModule, 236 const VkPipelineRasterizationStateCreateInfo* rasterizationState = nullptr, 237 const VkSpecializationInfo* taskSpecializationInfo = nullptr, 238 const VkSpecializationInfo* meshSpecializationInfo = nullptr, 239 VkPipelineFragmentShadingRateStateCreateInfoKHR* fragmentShadingRateState = nullptr, 240 PipelineRenderingCreateInfoWrapper rendering = PipelineRenderingCreateInfoWrapper(), 241 const VkPipelineCache partPipelineCache = DE_NULL, 242 VkPipelineCreationFeedbackCreateInfoEXT* partCreationFeedback = nullptr); 243 #endif // CTS_USES_VULKANSC 244 245 // Setup fragment shader state. 246 GraphicsPipelineWrapper& setupFragmentShaderState (const VkPipelineLayout layout, 247 const VkRenderPass renderPass, 248 const deUint32 subpass, 249 const VkShaderModule fragmentShaderModule, 250 const VkPipelineDepthStencilStateCreateInfo* depthStencilState = DE_NULL, 251 const VkPipelineMultisampleStateCreateInfo* multisampleState = DE_NULL, 252 const VkSpecializationInfo* specializationInfo = DE_NULL, 253 const VkPipelineCache partPipelineCache = DE_NULL, 254 PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback = PipelineCreationFeedbackCreateInfoWrapper()); 255 256 // Note: VkPipelineShaderStageModuleIdentifierCreateInfoEXT::pIdentifier will not be copied. They need to continue to exist outside this wrapper. 257 GraphicsPipelineWrapper& setupFragmentShaderState2 (const VkPipelineLayout layout, 258 const VkRenderPass renderPass, 259 const deUint32 subpass, 260 const VkShaderModule fragmentShaderModule, 261 PipelineShaderStageModuleIdentifierCreateInfoWrapper fragmentShaderModuleId = PipelineShaderStageModuleIdentifierCreateInfoWrapper(), 262 const VkPipelineDepthStencilStateCreateInfo* depthStencilState = nullptr, 263 const VkPipelineMultisampleStateCreateInfo* multisampleState = nullptr, 264 const VkSpecializationInfo* specializationInfo = nullptr, 265 const VkPipelineCache partPipelineCache = DE_NULL, 266 PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback = PipelineCreationFeedbackCreateInfoWrapper()); 267 268 // Setup fragment output state. 269 GraphicsPipelineWrapper& setupFragmentOutputState (const VkRenderPass renderPass, 270 const deUint32 subpass = 0u, 271 const VkPipelineColorBlendStateCreateInfo* colorBlendState = DE_NULL, 272 const VkPipelineMultisampleStateCreateInfo* multisampleState = DE_NULL, 273 const VkPipelineCache partPipelineCache = DE_NULL, 274 PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback = PipelineCreationFeedbackCreateInfoWrapper()); 275 276 // Build pipeline object out of provided state. 277 void buildPipeline (const VkPipelineCache pipelineCache = DE_NULL, 278 const VkPipeline basePipelineHandle = DE_NULL, 279 const deInt32 basePipelineIndex = 0, 280 PipelineCreationFeedbackCreateInfoWrapper creationFeedback = PipelineCreationFeedbackCreateInfoWrapper()); 281 282 // Returns true when pipeline was build using buildPipeline method. 283 deBool wasBuild (void) const; 284 285 // Get compleate pipeline. GraphicsPipelineWrapper preserves ovnership and will desroy pipeline in its destructor. 286 vk::VkPipeline getPipeline (void) const; 287 288 // Destroy compleate pipeline - pipeline parts are not destroyed. 289 void destroyPipeline (void); 290 291 protected: 292 293 // No default constructor - use parametrized constructor or emplace_back in case of vectors. 294 GraphicsPipelineWrapper() = default; 295 296 struct InternalData; 297 298 protected: 299 300 static constexpr size_t kMaxPipelineParts = 4u; 301 302 // Store partial pipelines when non monolithic construction was used. 303 Move<VkPipeline> m_pipelineParts[kMaxPipelineParts]; 304 305 // Store monolithic pipeline or linked pipeline libraries. 306 Move<VkPipeline> m_pipelineFinal; 307 308 // Store internal data that is needed only for pipeline construction. 309 de::SharedPtr<InternalData> m_internalData; 310 }; 311 312 } // vk 313 314 #endif // _VKPIPELINECONSTRUCTIONUTIL_HPP 315