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