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