• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &currentGraphicsPipelineDesc);
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