1 // 2 // Copyright 2020 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 // ProgramExecutableVk.h: Collects the information and interfaces common to both ProgramVks and 8 // ProgramPipelineVks in order to execute/draw with either. 9 10 #ifndef LIBANGLE_RENDERER_VULKAN_PROGRAMEXECUTABLEVK_H_ 11 #define LIBANGLE_RENDERER_VULKAN_PROGRAMEXECUTABLEVK_H_ 12 13 #include "common/bitset_utils.h" 14 #include "common/mathutil.h" 15 #include "common/utilities.h" 16 #include "libANGLE/Context.h" 17 #include "libANGLE/InfoLog.h" 18 #include "libANGLE/ProgramExecutable.h" 19 #include "libANGLE/renderer/ProgramExecutableImpl.h" 20 #include "libANGLE/renderer/vulkan/ContextVk.h" 21 #include "libANGLE/renderer/vulkan/ShaderInterfaceVariableInfoMap.h" 22 #include "libANGLE/renderer/vulkan/spv_utils.h" 23 #include "libANGLE/renderer/vulkan/vk_cache_utils.h" 24 #include "libANGLE/renderer/vulkan/vk_helpers.h" 25 26 namespace rx 27 { 28 29 class ShaderInfo final : angle::NonCopyable 30 { 31 public: 32 ShaderInfo(); 33 ~ShaderInfo(); 34 35 angle::Result initShaders(vk::Context *context, 36 const gl::ShaderBitSet &linkedShaderStages, 37 const gl::ShaderMap<const angle::spirv::Blob *> &spirvBlobs, 38 const ShaderInterfaceVariableInfoMap &variableInfoMap, 39 bool isGLES1); 40 void initShaderFromProgram(gl::ShaderType shaderType, const ShaderInfo &programShaderInfo); 41 void clear(); 42 valid()43 ANGLE_INLINE bool valid() const { return mIsInitialized; } 44 getSpirvBlobs()45 const gl::ShaderMap<angle::spirv::Blob> &getSpirvBlobs() const { return mSpirvBlobs; } 46 47 // Save and load implementation for GLES Program Binary support. 48 void load(gl::BinaryInputStream *stream); 49 void save(gl::BinaryOutputStream *stream); 50 51 private: 52 gl::ShaderMap<angle::spirv::Blob> mSpirvBlobs; 53 bool mIsInitialized = false; 54 }; 55 56 union ProgramTransformOptions final 57 { 58 struct 59 { 60 uint8_t surfaceRotation : 1; 61 uint8_t removeTransformFeedbackEmulation : 1; 62 uint8_t multiSampleFramebufferFetch : 1; 63 uint8_t enableSampleShading : 1; 64 uint8_t reserved : 4; // must initialize to zero 65 }; 66 uint8_t permutationIndex; 67 static constexpr uint32_t kPermutationCount = 0x1 << 4; 68 }; 69 static_assert(sizeof(ProgramTransformOptions) == 1, "Size check failed"); 70 static_assert(static_cast<int>(SurfaceRotation::EnumCount) <= 8, "Size check failed"); 71 72 class ProgramInfo final : angle::NonCopyable 73 { 74 public: 75 ProgramInfo(); 76 ~ProgramInfo(); 77 78 angle::Result initProgram(vk::Context *context, 79 gl::ShaderType shaderType, 80 bool isLastPreFragmentStage, 81 bool isTransformFeedbackProgram, 82 const ShaderInfo &shaderInfo, 83 ProgramTransformOptions optionBits, 84 const ShaderInterfaceVariableInfoMap &variableInfoMap); 85 void release(ContextVk *contextVk); 86 valid(gl::ShaderType shaderType)87 ANGLE_INLINE bool valid(gl::ShaderType shaderType) const 88 { 89 return mProgramHelper.valid(shaderType); 90 } 91 getShaderProgram()92 vk::ShaderProgramHelper &getShaderProgram() { return mProgramHelper; } 93 94 private: 95 vk::ShaderProgramHelper mProgramHelper; 96 gl::ShaderMap<vk::RefCounted<vk::ShaderModule>> mShaders; 97 }; 98 99 // State for the default uniform blocks. 100 struct DefaultUniformBlockVk final : private angle::NonCopyable 101 { 102 DefaultUniformBlockVk(); 103 ~DefaultUniformBlockVk(); 104 105 // Shadow copies of the shader uniform data. 106 angle::MemoryBuffer uniformData; 107 108 // Since the default blocks are laid out in std140, this tells us where to write on a call 109 // to a setUniform method. They are arranged in uniform location order. 110 std::vector<sh::BlockMemberInfo> uniformLayout; 111 }; 112 113 // Performance and resource counters. 114 using DescriptorSetCountList = angle::PackedEnumMap<DescriptorSetIndex, uint32_t>; 115 using ImmutableSamplerIndexMap = angle::HashMap<vk::YcbcrConversionDesc, uint32_t>; 116 117 using DefaultUniformBlockMap = gl::ShaderMap<std::shared_ptr<DefaultUniformBlockVk>>; 118 119 class ProgramExecutableVk : public ProgramExecutableImpl 120 { 121 public: 122 ProgramExecutableVk(const gl::ProgramExecutable *executable); 123 ~ProgramExecutableVk() override; 124 125 void destroy(const gl::Context *context) override; 126 127 void save(ContextVk *contextVk, bool isSeparable, gl::BinaryOutputStream *stream); 128 angle::Result load(ContextVk *contextVk, 129 bool isSeparable, 130 gl::BinaryInputStream *stream, 131 egl::CacheGetResult *resultOut); 132 133 void setUniform1fv(GLint location, GLsizei count, const GLfloat *v) override; 134 void setUniform2fv(GLint location, GLsizei count, const GLfloat *v) override; 135 void setUniform3fv(GLint location, GLsizei count, const GLfloat *v) override; 136 void setUniform4fv(GLint location, GLsizei count, const GLfloat *v) override; 137 void setUniform1iv(GLint location, GLsizei count, const GLint *v) override; 138 void setUniform2iv(GLint location, GLsizei count, const GLint *v) override; 139 void setUniform3iv(GLint location, GLsizei count, const GLint *v) override; 140 void setUniform4iv(GLint location, GLsizei count, const GLint *v) override; 141 void setUniform1uiv(GLint location, GLsizei count, const GLuint *v) override; 142 void setUniform2uiv(GLint location, GLsizei count, const GLuint *v) override; 143 void setUniform3uiv(GLint location, GLsizei count, const GLuint *v) override; 144 void setUniform4uiv(GLint location, GLsizei count, const GLuint *v) override; 145 void setUniformMatrix2fv(GLint location, 146 GLsizei count, 147 GLboolean transpose, 148 const GLfloat *value) override; 149 void setUniformMatrix3fv(GLint location, 150 GLsizei count, 151 GLboolean transpose, 152 const GLfloat *value) override; 153 void setUniformMatrix4fv(GLint location, 154 GLsizei count, 155 GLboolean transpose, 156 const GLfloat *value) override; 157 void setUniformMatrix2x3fv(GLint location, 158 GLsizei count, 159 GLboolean transpose, 160 const GLfloat *value) override; 161 void setUniformMatrix3x2fv(GLint location, 162 GLsizei count, 163 GLboolean transpose, 164 const GLfloat *value) override; 165 void setUniformMatrix2x4fv(GLint location, 166 GLsizei count, 167 GLboolean transpose, 168 const GLfloat *value) override; 169 void setUniformMatrix4x2fv(GLint location, 170 GLsizei count, 171 GLboolean transpose, 172 const GLfloat *value) override; 173 void setUniformMatrix3x4fv(GLint location, 174 GLsizei count, 175 GLboolean transpose, 176 const GLfloat *value) override; 177 void setUniformMatrix4x3fv(GLint location, 178 GLsizei count, 179 GLboolean transpose, 180 const GLfloat *value) override; 181 182 void getUniformfv(const gl::Context *context, GLint location, GLfloat *params) const override; 183 void getUniformiv(const gl::Context *context, GLint location, GLint *params) const override; 184 void getUniformuiv(const gl::Context *context, GLint location, GLuint *params) const override; 185 186 void clearVariableInfoMap(); 187 getCurrentDefaultUniformBufferSerial()188 vk::BufferSerial getCurrentDefaultUniformBufferSerial() const 189 { 190 return mCurrentDefaultUniformBufferSerial; 191 } 192 193 // Get the graphics pipeline if already created. 194 angle::Result getGraphicsPipeline(ContextVk *contextVk, 195 vk::GraphicsPipelineSubset pipelineSubset, 196 const vk::GraphicsPipelineDesc &desc, 197 const vk::GraphicsPipelineDesc **descPtrOut, 198 vk::PipelineHelper **pipelineOut); 199 200 angle::Result createGraphicsPipeline(ContextVk *contextVk, 201 vk::GraphicsPipelineSubset pipelineSubset, 202 vk::PipelineCacheAccess *pipelineCache, 203 PipelineSource source, 204 const vk::GraphicsPipelineDesc &desc, 205 const vk::GraphicsPipelineDesc **descPtrOut, 206 vk::PipelineHelper **pipelineOut); 207 208 angle::Result linkGraphicsPipelineLibraries(ContextVk *contextVk, 209 vk::PipelineCacheAccess *pipelineCache, 210 const vk::GraphicsPipelineDesc &desc, 211 vk::PipelineHelper *vertexInputPipeline, 212 vk::PipelineHelper *shadersPipeline, 213 vk::PipelineHelper *fragmentOutputPipeline, 214 const vk::GraphicsPipelineDesc **descPtrOut, 215 vk::PipelineHelper **pipelineOut); 216 217 angle::Result getOrCreateComputePipeline(vk::Context *context, 218 vk::PipelineCacheAccess *pipelineCache, 219 PipelineSource source, 220 vk::PipelineRobustness pipelineRobustness, 221 vk::PipelineProtectedAccess pipelineProtectedAccess, 222 vk::PipelineHelper **pipelineOut); 223 getPipelineLayout()224 const vk::PipelineLayout &getPipelineLayout() const { return mPipelineLayout.get(); } 225 void resetLayout(ContextVk *contextVk); 226 angle::Result createPipelineLayout(vk::Context *context, 227 PipelineLayoutCache *pipelineLayoutCache, 228 DescriptorSetLayoutCache *descriptorSetLayoutCache, 229 gl::ActiveTextureArray<TextureVk *> *activeTextures); 230 angle::Result initializeDescriptorPools( 231 vk::Context *context, 232 DescriptorSetLayoutCache *descriptorSetLayoutCache, 233 vk::DescriptorSetArray<vk::MetaDescriptorPool> *metaDescriptorPools); 234 235 angle::Result updateTexturesDescriptorSet(vk::Context *context, 236 const gl::ActiveTextureArray<TextureVk *> &textures, 237 const gl::SamplerBindingVector &samplers, 238 bool emulateSeamfulCubeMapSampling, 239 PipelineType pipelineType, 240 UpdateDescriptorSetsBuilder *updateBuilder, 241 vk::CommandBufferHelperCommon *commandBufferHelper, 242 const vk::DescriptorSetDesc &texturesDesc); 243 244 angle::Result updateShaderResourcesDescriptorSet( 245 vk::Context *context, 246 UpdateDescriptorSetsBuilder *updateBuilder, 247 const vk::WriteDescriptorDescs &writeDescriptorDescs, 248 vk::CommandBufferHelperCommon *commandBufferHelper, 249 const vk::DescriptorSetDescBuilder &shaderResourcesDesc, 250 vk::SharedDescriptorSetCacheKey *newSharedCacheKeyOut); 251 252 angle::Result updateUniformsAndXfbDescriptorSet( 253 vk::Context *context, 254 UpdateDescriptorSetsBuilder *updateBuilder, 255 const vk::WriteDescriptorDescs &writeDescriptorDescs, 256 vk::CommandBufferHelperCommon *commandBufferHelper, 257 vk::BufferHelper *defaultUniformBuffer, 258 vk::DescriptorSetDescBuilder *uniformsAndXfbDesc, 259 vk::SharedDescriptorSetCacheKey *sharedCacheKeyOut); 260 261 template <typename CommandBufferT> 262 angle::Result bindDescriptorSets(vk::Context *context, 263 vk::CommandBufferHelperCommon *commandBufferHelper, 264 CommandBufferT *commandBuffer, 265 PipelineType pipelineType); 266 usesDynamicUniformBufferDescriptors()267 bool usesDynamicUniformBufferDescriptors() const 268 { 269 return mUniformBufferDescriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; 270 } getUniformBufferDescriptorType()271 VkDescriptorType getUniformBufferDescriptorType() const { return mUniformBufferDescriptorType; } usesDynamicShaderStorageBufferDescriptors()272 bool usesDynamicShaderStorageBufferDescriptors() const { return false; } getStorageBufferDescriptorType()273 VkDescriptorType getStorageBufferDescriptorType() const 274 { 275 return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; 276 } getAtomicCounterBufferDescriptorType()277 VkDescriptorType getAtomicCounterBufferDescriptorType() const 278 { 279 return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; 280 } usesDynamicAtomicCounterBufferDescriptors()281 bool usesDynamicAtomicCounterBufferDescriptors() const { return false; } 282 areImmutableSamplersCompatible(const ImmutableSamplerIndexMap & immutableSamplerIndexMap)283 bool areImmutableSamplersCompatible( 284 const ImmutableSamplerIndexMap &immutableSamplerIndexMap) const 285 { 286 return (mImmutableSamplerIndexMap == immutableSamplerIndexMap); 287 } 288 getDefaultUniformAlignedSize(vk::Context * context,gl::ShaderType shaderType)289 size_t getDefaultUniformAlignedSize(vk::Context *context, gl::ShaderType shaderType) const 290 { 291 vk::Renderer *renderer = context->getRenderer(); 292 size_t alignment = static_cast<size_t>( 293 renderer->getPhysicalDeviceProperties().limits.minUniformBufferOffsetAlignment); 294 return roundUp(mDefaultUniformBlocks[shaderType]->uniformData.size(), alignment); 295 } 296 getSharedDefaultUniformBlock(gl::ShaderType shaderType)297 std::shared_ptr<DefaultUniformBlockVk> &getSharedDefaultUniformBlock(gl::ShaderType shaderType) 298 { 299 return mDefaultUniformBlocks[shaderType]; 300 } 301 updateAndCheckDirtyUniforms()302 bool updateAndCheckDirtyUniforms() 303 { 304 if (ANGLE_LIKELY(!mExecutable->IsPPO())) 305 { 306 return mDefaultUniformBlocksDirty.any(); 307 } 308 309 const auto &ppoExecutables = mExecutable->getPPOProgramExecutables(); 310 for (gl::ShaderType shaderType : mExecutable->getLinkedShaderStages()) 311 { 312 ProgramExecutableVk *executableVk = vk::GetImpl(ppoExecutables[shaderType].get()); 313 if (executableVk->mDefaultUniformBlocksDirty.test(shaderType)) 314 { 315 mDefaultUniformBlocksDirty.set(shaderType); 316 // Note: this relies on onProgramBind marking everything as dirty 317 executableVk->mDefaultUniformBlocksDirty.reset(shaderType); 318 } 319 } 320 321 return mDefaultUniformBlocksDirty.any(); 322 } 323 324 void setAllDefaultUniformsDirty(); 325 angle::Result updateUniforms(vk::Context *context, 326 UpdateDescriptorSetsBuilder *updateBuilder, 327 vk::CommandBufferHelperCommon *commandBufferHelper, 328 vk::BufferHelper *emptyBuffer, 329 vk::DynamicBuffer *defaultUniformStorage, 330 bool isTransformFeedbackActiveUnpaused, 331 TransformFeedbackVk *transformFeedbackVk); 332 void onProgramBind(); 333 getVariableInfoMap()334 const ShaderInterfaceVariableInfoMap &getVariableInfoMap() const { return mVariableInfoMap; } 335 warmUpPipelineCache(vk::Renderer * renderer,vk::PipelineRobustness pipelineRobustness,vk::PipelineProtectedAccess pipelineProtectedAccess,vk::GraphicsPipelineSubset subset)336 angle::Result warmUpPipelineCache(vk::Renderer *renderer, 337 vk::PipelineRobustness pipelineRobustness, 338 vk::PipelineProtectedAccess pipelineProtectedAccess, 339 vk::GraphicsPipelineSubset subset) 340 { 341 return getPipelineCacheWarmUpTasks(renderer, pipelineRobustness, pipelineProtectedAccess, 342 subset, nullptr); 343 } 344 angle::Result getPipelineCacheWarmUpTasks( 345 vk::Renderer *renderer, 346 vk::PipelineRobustness pipelineRobustness, 347 vk::PipelineProtectedAccess pipelineProtectedAccess, 348 vk::GraphicsPipelineSubset subset, 349 std::vector<std::shared_ptr<LinkSubTask>> *postLinkSubTasksOut); 350 waitForPostLinkTasks(const gl::Context * context)351 void waitForPostLinkTasks(const gl::Context *context) override 352 { 353 ContextVk *contextVk = vk::GetImpl(context); 354 waitForPostLinkTasksImpl(contextVk); 355 } waitForComputePostLinkTasks(ContextVk * contextVk)356 void waitForComputePostLinkTasks(ContextVk *contextVk) 357 { 358 ASSERT(mExecutable->hasLinkedShaderStage(gl::ShaderType::Compute)); 359 waitForPostLinkTasksImpl(contextVk); 360 } 361 void waitForGraphicsPostLinkTasks(ContextVk *contextVk, 362 const vk::GraphicsPipelineDesc ¤tGraphicsPipelineDesc); 363 364 angle::Result mergePipelineCacheToRenderer(vk::Context *context) const; 365 getShaderResourceWriteDescriptorDescs()366 const vk::WriteDescriptorDescs &getShaderResourceWriteDescriptorDescs() const 367 { 368 return mShaderResourceWriteDescriptorDescs; 369 } getDefaultUniformWriteDescriptorDescs(TransformFeedbackVk * transformFeedbackVk)370 const vk::WriteDescriptorDescs &getDefaultUniformWriteDescriptorDescs( 371 TransformFeedbackVk *transformFeedbackVk) const 372 { 373 return transformFeedbackVk == nullptr ? mDefaultUniformWriteDescriptorDescs 374 : mDefaultUniformAndXfbWriteDescriptorDescs; 375 } 376 getTextureWriteDescriptorDescs()377 const vk::WriteDescriptorDescs &getTextureWriteDescriptorDescs() const 378 { 379 return mTextureWriteDescriptorDescs; 380 } 381 // The following functions are for internal use of programs, including from a threaded link job: 382 angle::Result resizeUniformBlockMemory(vk::Context *context, 383 const gl::ShaderMap<size_t> &requiredBufferSize); 384 void resolvePrecisionMismatch(const gl::ProgramMergedVaryings &mergedVaryings); initShaders(vk::Context * context,const gl::ShaderBitSet & linkedShaderStages,const gl::ShaderMap<const angle::spirv::Blob * > & spirvBlobs,bool isGLES1)385 angle::Result initShaders(vk::Context *context, 386 const gl::ShaderBitSet &linkedShaderStages, 387 const gl::ShaderMap<const angle::spirv::Blob *> &spirvBlobs, 388 bool isGLES1) 389 { 390 return mOriginalShaderInfo.initShaders(context, linkedShaderStages, spirvBlobs, 391 mVariableInfoMap, isGLES1); 392 } assignAllSpvLocations(vk::Context * context,const gl::ProgramState & programState,const gl::ProgramLinkedResources & resources)393 void assignAllSpvLocations(vk::Context *context, 394 const gl::ProgramState &programState, 395 const gl::ProgramLinkedResources &resources) 396 { 397 SpvSourceOptions options = SpvCreateSourceOptions(context->getFeatures()); 398 SpvAssignAllLocations(options, programState, resources, &mVariableInfoMap); 399 } 400 401 private: 402 class WarmUpTaskCommon; 403 class WarmUpComputeTask; 404 class WarmUpGraphicsTask; 405 406 friend class ProgramVk; 407 friend class ProgramPipelineVk; 408 409 void reset(ContextVk *contextVk); 410 411 template <class T> 412 void getUniformImpl(GLint location, T *v, GLenum entryPointType) const; 413 414 void addInterfaceBlockDescriptorSetDesc(const std::vector<gl::InterfaceBlock> &blocks, 415 gl::ShaderBitSet shaderTypes, 416 VkDescriptorType descType, 417 vk::DescriptorSetLayoutDesc *descOut); 418 void addAtomicCounterBufferDescriptorSetDesc( 419 const std::vector<gl::AtomicCounterBuffer> &atomicCounterBuffers, 420 vk::DescriptorSetLayoutDesc *descOut); 421 void addImageDescriptorSetDesc(vk::DescriptorSetLayoutDesc *descOut); 422 void addInputAttachmentDescriptorSetDesc(vk::DescriptorSetLayoutDesc *descOut); 423 angle::Result addTextureDescriptorSetDesc( 424 vk::Context *context, 425 const gl::ActiveTextureArray<TextureVk *> *activeTextures, 426 vk::DescriptorSetLayoutDesc *descOut); 427 428 size_t calcUniformUpdateRequiredSpace(vk::Context *context, 429 gl::ShaderMap<VkDeviceSize> *uniformOffsets) const; 430 initProgram(vk::Context * context,gl::ShaderType shaderType,bool isLastPreFragmentStage,bool isTransformFeedbackProgram,ProgramTransformOptions optionBits,ProgramInfo * programInfo,const ShaderInterfaceVariableInfoMap & variableInfoMap)431 ANGLE_INLINE angle::Result initProgram(vk::Context *context, 432 gl::ShaderType shaderType, 433 bool isLastPreFragmentStage, 434 bool isTransformFeedbackProgram, 435 ProgramTransformOptions optionBits, 436 ProgramInfo *programInfo, 437 const ShaderInterfaceVariableInfoMap &variableInfoMap) 438 { 439 ASSERT(mOriginalShaderInfo.valid()); 440 441 // Create the program pipeline. This is done lazily and once per combination of 442 // specialization constants. 443 if (!programInfo->valid(shaderType)) 444 { 445 ANGLE_TRY(programInfo->initProgram(context, shaderType, isLastPreFragmentStage, 446 isTransformFeedbackProgram, mOriginalShaderInfo, 447 optionBits, variableInfoMap)); 448 mValidPermutations.set(optionBits.permutationIndex); 449 } 450 ASSERT(programInfo->valid(shaderType)); 451 452 return angle::Result::Continue; 453 } 454 initGraphicsShaderProgram(vk::Context * context,gl::ShaderType shaderType,bool isLastPreFragmentStage,bool isTransformFeedbackProgram,ProgramTransformOptions optionBits,ProgramInfo * programInfo,const ShaderInterfaceVariableInfoMap & variableInfoMap)455 ANGLE_INLINE angle::Result initGraphicsShaderProgram( 456 vk::Context *context, 457 gl::ShaderType shaderType, 458 bool isLastPreFragmentStage, 459 bool isTransformFeedbackProgram, 460 ProgramTransformOptions optionBits, 461 ProgramInfo *programInfo, 462 const ShaderInterfaceVariableInfoMap &variableInfoMap) 463 { 464 return initProgram(context, shaderType, isLastPreFragmentStage, isTransformFeedbackProgram, 465 optionBits, programInfo, variableInfoMap); 466 } 467 initComputeProgram(vk::Context * context,ProgramInfo * programInfo,const ShaderInterfaceVariableInfoMap & variableInfoMap)468 ANGLE_INLINE angle::Result initComputeProgram( 469 vk::Context *context, 470 ProgramInfo *programInfo, 471 const ShaderInterfaceVariableInfoMap &variableInfoMap) 472 { 473 ProgramTransformOptions optionBits = {}; 474 return initProgram(context, gl::ShaderType::Compute, false, false, optionBits, programInfo, 475 variableInfoMap); 476 } 477 478 ProgramTransformOptions getTransformOptions(ContextVk *contextVk, 479 const vk::GraphicsPipelineDesc &desc); 480 angle::Result initGraphicsShaderPrograms(vk::Context *context, 481 ProgramTransformOptions transformOptions); 482 angle::Result initProgramThenCreateGraphicsPipeline(vk::Context *context, 483 ProgramTransformOptions transformOptions, 484 vk::GraphicsPipelineSubset pipelineSubset, 485 vk::PipelineCacheAccess *pipelineCache, 486 PipelineSource source, 487 const vk::GraphicsPipelineDesc &desc, 488 const vk::RenderPass &compatibleRenderPass, 489 const vk::GraphicsPipelineDesc **descPtrOut, 490 vk::PipelineHelper **pipelineOut); 491 angle::Result createGraphicsPipelineImpl(vk::Context *context, 492 ProgramTransformOptions transformOptions, 493 vk::GraphicsPipelineSubset pipelineSubset, 494 vk::PipelineCacheAccess *pipelineCache, 495 PipelineSource source, 496 const vk::GraphicsPipelineDesc &desc, 497 const vk::RenderPass &compatibleRenderPass, 498 const vk::GraphicsPipelineDesc **descPtrOut, 499 vk::PipelineHelper **pipelineOut); 500 angle::Result prepareForWarmUpPipelineCache( 501 vk::Context *context, 502 vk::PipelineRobustness pipelineRobustness, 503 vk::PipelineProtectedAccess pipelineProtectedAccess, 504 vk::GraphicsPipelineSubset subset, 505 bool *isComputeOut, 506 angle::FixedVector<bool, 2> *surfaceRotationVariationsOut, 507 vk::GraphicsPipelineDesc **graphicsPipelineDescOut, 508 vk::RenderPass *renderPassOut); 509 angle::Result warmUpComputePipelineCache(vk::Context *context, 510 vk::PipelineRobustness pipelineRobustness, 511 vk::PipelineProtectedAccess pipelineProtectedAccess); 512 angle::Result warmUpGraphicsPipelineCache(vk::Context *context, 513 vk::PipelineRobustness pipelineRobustness, 514 vk::PipelineProtectedAccess pipelineProtectedAccess, 515 vk::GraphicsPipelineSubset subset, 516 const bool isSurfaceRotated, 517 const vk::GraphicsPipelineDesc &graphicsPipelineDesc, 518 const vk::RenderPass &renderPass, 519 vk::PipelineHelper *placeholderPipelineHelper); 520 void waitForPostLinkTasksImpl(ContextVk *contextVk); 521 522 angle::Result getOrAllocateDescriptorSet(vk::Context *context, 523 UpdateDescriptorSetsBuilder *updateBuilder, 524 vk::CommandBufferHelperCommon *commandBufferHelper, 525 const vk::DescriptorSetDescBuilder &descriptorSetDesc, 526 const vk::WriteDescriptorDescs &writeDescriptorDescs, 527 DescriptorSetIndex setIndex, 528 vk::SharedDescriptorSetCacheKey *newSharedCacheKeyOut); 529 530 // When loading from cache / binary, initialize the pipeline cache with given data. Otherwise 531 // the cache is lazily created as needed. 532 angle::Result initializePipelineCache(vk::Context *context, 533 bool compressed, 534 const std::vector<uint8_t> &pipelineData); 535 angle::Result ensurePipelineCacheInitialized(vk::Context *context); 536 537 void initializeWriteDescriptorDesc(vk::Context *context); 538 539 // Descriptor sets and pools for shader resources for this program. 540 vk::DescriptorSetArray<VkDescriptorSet> mDescriptorSets; 541 vk::DescriptorSetArray<vk::DescriptorPoolPointer> mDescriptorPools; 542 vk::DescriptorSetArray<vk::RefCountedDescriptorPoolBinding> mDescriptorPoolBindings; 543 vk::BufferSerial mCurrentDefaultUniformBufferSerial; 544 545 // We keep a reference to the pipeline and descriptor set layouts. This ensures they don't get 546 // deleted while this program is in use. 547 uint32_t mImmutableSamplersMaxDescriptorCount; 548 ImmutableSamplerIndexMap mImmutableSamplerIndexMap; 549 vk::AtomicBindingPointer<vk::PipelineLayout> mPipelineLayout; 550 vk::DescriptorSetLayoutPointerArray mDescriptorSetLayouts; 551 552 // A set of dynamic offsets used with vkCmdBindDescriptorSets for the default uniform buffers. 553 VkDescriptorType mUniformBufferDescriptorType; 554 gl::ShaderVector<uint32_t> mDynamicUniformDescriptorOffsets; 555 std::vector<uint32_t> mDynamicShaderResourceDescriptorOffsets; 556 557 ShaderInterfaceVariableInfoMap mVariableInfoMap; 558 559 static_assert((ProgramTransformOptions::kPermutationCount == 16), 560 "ProgramTransformOptions::kPermutationCount must be 16."); 561 angle::BitSet16<ProgramTransformOptions::kPermutationCount> mValidPermutations; 562 563 // We store all permutations of surface rotation and transformed SPIR-V programs here. We may 564 // need some LRU algorithm to free least used programs to reduce the number of programs. 565 ProgramInfo mGraphicsProgramInfos[ProgramTransformOptions::kPermutationCount]; 566 ProgramInfo mComputeProgramInfo; 567 568 // Pipeline caches. The pipelines are tightly coupled with the shaders they are created for, so 569 // they live in the program executable. With VK_EXT_graphics_pipeline_library, the pipeline is 570 // divided in subsets; the "shaders" subset is created based on the shaders, so its cache lives 571 // in the program executable. The "vertex input" and "fragment output" pipelines are 572 // independent, and live in the context. 573 CompleteGraphicsPipelineCache 574 mCompleteGraphicsPipelines[ProgramTransformOptions::kPermutationCount]; 575 ShadersGraphicsPipelineCache 576 mShadersGraphicsPipelines[ProgramTransformOptions::kPermutationCount]; 577 vk::ComputePipelineCache mComputePipelines; 578 579 DefaultUniformBlockMap mDefaultUniformBlocks; 580 gl::ShaderBitSet mDefaultUniformBlocksDirty; 581 582 ShaderInfo mOriginalShaderInfo; 583 584 // The pipeline cache specific to this program executable. Currently: 585 // 586 // - This is used during warm up (at link time) 587 // - The contents are merged to Renderer's pipeline cache immediately after warm up 588 // - The contents are returned as part of program binary 589 // - Draw-time pipeline creation uses Renderer's cache 590 // 591 // Without VK_EXT_graphics_pipeline_library, this cache is not used for draw-time pipeline 592 // creations to allow reuse of other blobs that are independent of the actual shaders; vertex 593 // input fetch, fragment output and blend. 594 // 595 // With VK_EXT_graphics_pipeline_library, this cache is used for the "shaders" subset of the 596 // pipeline. 597 vk::PipelineCache mPipelineCache; 598 599 vk::GraphicsPipelineDesc mWarmUpGraphicsPipelineDesc; 600 601 // The "layout" information for descriptorSets 602 vk::WriteDescriptorDescs mShaderResourceWriteDescriptorDescs; 603 vk::WriteDescriptorDescs mTextureWriteDescriptorDescs; 604 vk::WriteDescriptorDescs mDefaultUniformWriteDescriptorDescs; 605 vk::WriteDescriptorDescs mDefaultUniformAndXfbWriteDescriptorDescs; 606 607 vk::DescriptorSetLayoutDesc mShaderResourceSetDesc; 608 vk::DescriptorSetLayoutDesc mTextureSetDesc; 609 vk::DescriptorSetLayoutDesc mDefaultUniformAndXfbSetDesc; 610 }; 611 612 } // namespace rx 613 614 #endif // LIBANGLE_RENDERER_VULKAN_PROGRAMEXECUTABLEVK_H_ 615