• 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/utilities.h"
15 #include "libANGLE/Context.h"
16 #include "libANGLE/InfoLog.h"
17 #include "libANGLE/renderer/glslang_wrapper_utils.h"
18 #include "libANGLE/renderer/vulkan/ContextVk.h"
19 #include "libANGLE/renderer/vulkan/vk_helpers.h"
20 
21 namespace rx
22 {
23 
24 class ShaderInfo final : angle::NonCopyable
25 {
26   public:
27     ShaderInfo();
28     ~ShaderInfo();
29 
30     angle::Result initShaders(ContextVk *contextVk,
31                               const gl::ShaderMap<std::string> &shaderSources,
32                               const ShaderMapInterfaceVariableInfoMap &variableInfoMap);
33     void release(ContextVk *contextVk);
34 
valid()35     ANGLE_INLINE bool valid() const { return mIsInitialized; }
36 
getSpirvBlobs()37     const gl::ShaderMap<SpirvBlob> &getSpirvBlobs() const { return mSpirvBlobs; }
getSpirvBlobs()38     gl::ShaderMap<SpirvBlob> &getSpirvBlobs() { return mSpirvBlobs; }
39 
40     // Save and load implementation for GLES Program Binary support.
41     void load(gl::BinaryInputStream *stream);
42     void save(gl::BinaryOutputStream *stream);
43 
44   private:
45     gl::ShaderMap<SpirvBlob> mSpirvBlobs;
46     bool mIsInitialized = false;
47 };
48 
49 enum class ProgramTransformOption : uint8_t
50 {
51     EnableLineRasterEmulation            = 0,
52     RemoveEarlyFragmentTestsOptimization = 1,
53     EnumCount                            = 2,
54     PermutationCount                     = 4,
55 };
56 using ProgramTransformOptionBits = angle::PackedEnumBitSet<ProgramTransformOption, uint8_t>;
57 
58 class ProgramInfo final : angle::NonCopyable
59 {
60   public:
61     ProgramInfo();
62     ~ProgramInfo();
63 
64     angle::Result initProgram(ContextVk *contextVk,
65                               const gl::ShaderType shaderType,
66                               const ShaderInfo &shaderInfo,
67                               const ShaderMapInterfaceVariableInfoMap &variableInfoMap,
68                               ProgramTransformOptionBits optionBits);
69     void release(ContextVk *contextVk);
70 
valid(const gl::ShaderType shaderType)71     ANGLE_INLINE bool valid(const gl::ShaderType shaderType) const
72     {
73         return mProgramHelper.valid(shaderType);
74     }
75 
getShaderProgram()76     vk::ShaderProgramHelper *getShaderProgram() { return &mProgramHelper; }
77 
78   private:
79     vk::ShaderProgramHelper mProgramHelper;
80     gl::ShaderMap<vk::RefCounted<vk::ShaderAndSerial>> mShaders;
81 };
82 
83 // State for the default uniform blocks.
84 struct DefaultUniformBlock final : private angle::NonCopyable
85 {
86     DefaultUniformBlock();
87     ~DefaultUniformBlock();
88 
89     vk::DynamicBuffer storage;
90 
91     // Shadow copies of the shader uniform data.
92     angle::MemoryBuffer uniformData;
93 
94     // Since the default blocks are laid out in std140, this tells us where to write on a call
95     // to a setUniform method. They are arranged in uniform location order.
96     std::vector<sh::BlockMemberInfo> uniformLayout;
97 };
98 
99 class ProgramExecutableVk
100 {
101   public:
102     ProgramExecutableVk();
103     virtual ~ProgramExecutableVk();
104 
105     void reset(ContextVk *contextVk);
106 
107     void save(gl::BinaryOutputStream *stream);
108     std::unique_ptr<rx::LinkEvent> load(gl::BinaryInputStream *stream);
109 
110     void clearVariableInfoMap();
getShaderInterfaceVariableInfoMap()111     ShaderMapInterfaceVariableInfoMap &getShaderInterfaceVariableInfoMap()
112     {
113         return mVariableInfoMap;
114     }
115 
116     ProgramVk *getShaderProgram(const gl::State &glState, gl::ShaderType shaderType) const;
117 
118     void fillProgramStateMap(const ContextVk *contextVk,
119                              gl::ShaderMap<const gl::ProgramState *> *programStatesOut);
120     const gl::ProgramExecutable &getGlExecutable();
121 
getDefaultProgramInfo()122     ProgramInfo &getDefaultProgramInfo() { return mProgramInfos[0]; }
getProgramInfo(ProgramTransformOptionBits optionBits)123     ProgramInfo &getProgramInfo(ProgramTransformOptionBits optionBits)
124     {
125         return mProgramInfos[optionBits.to_ulong()];
126     }
127 
128     angle::Result getGraphicsPipeline(ContextVk *contextVk,
129                                       gl::PrimitiveMode mode,
130                                       const vk::GraphicsPipelineDesc &desc,
131                                       const gl::AttributesMask &activeAttribLocations,
132                                       const vk::GraphicsPipelineDesc **descPtrOut,
133                                       vk::PipelineHelper **pipelineOut);
134 
135     angle::Result getComputePipeline(ContextVk *contextVk, vk::PipelineAndSerial **pipelineOut);
136 
getPipelineLayout()137     const vk::PipelineLayout &getPipelineLayout() const { return mPipelineLayout.get(); }
138     angle::Result createPipelineLayout(const gl::Context *glContext);
139 
140     angle::Result updateTexturesDescriptorSet(ContextVk *contextVk);
141     angle::Result updateShaderResourcesDescriptorSet(ContextVk *contextVk,
142                                                      vk::ResourceUseList *resourceUseList,
143                                                      CommandBufferHelper *commandBufferHelper);
144     angle::Result updateTransformFeedbackDescriptorSet(
145         const gl::ProgramState &programState,
146         gl::ShaderMap<DefaultUniformBlock> &defaultUniformBlocks,
147         ContextVk *contextVk);
148 
149     angle::Result updateDescriptorSets(ContextVk *contextVk, vk::CommandBuffer *commandBuffer);
150 
151     void updateEarlyFragmentTestsOptimization(ContextVk *contextVk);
152 
setProgram(ProgramVk * program)153     void setProgram(ProgramVk *program)
154     {
155         ASSERT(!mProgram && !mProgramPipeline);
156         mProgram = program;
157     }
setProgramPipeline(ProgramPipelineVk * pipeline)158     void setProgramPipeline(ProgramPipelineVk *pipeline)
159     {
160         ASSERT(!mProgram && !mProgramPipeline);
161         mProgramPipeline = pipeline;
162     }
163 
164   private:
165     friend class ProgramVk;
166     friend class ProgramPipelineVk;
167 
168     angle::Result allocateDescriptorSet(ContextVk *contextVk, uint32_t descriptorSetIndex);
169     angle::Result allocateDescriptorSetAndGetInfo(ContextVk *contextVk,
170                                                   uint32_t descriptorSetIndex,
171                                                   bool *newPoolAllocatedOut);
172     void addInterfaceBlockDescriptorSetDesc(const std::vector<gl::InterfaceBlock> &blocks,
173                                             const gl::ShaderType shaderType,
174                                             VkDescriptorType descType,
175                                             vk::DescriptorSetLayoutDesc *descOut);
176     void addAtomicCounterBufferDescriptorSetDesc(
177         const std::vector<gl::AtomicCounterBuffer> &atomicCounterBuffers,
178         const gl::ShaderType shaderType,
179         vk::DescriptorSetLayoutDesc *descOut);
180     void addImageDescriptorSetDesc(const gl::ProgramState &programState,
181                                    vk::DescriptorSetLayoutDesc *descOut);
182     void addTextureDescriptorSetDesc(const gl::ProgramState &programState,
183                                      bool useOldRewriteStructSamplers,
184                                      vk::DescriptorSetLayoutDesc *descOut);
185 
186     void updateDefaultUniformsDescriptorSet(
187         const gl::ShaderType shaderType,
188         gl::ShaderMap<DefaultUniformBlock> &defaultUniformBlocks,
189         ContextVk *contextVk);
190     void updateTransformFeedbackDescriptorSetImpl(const gl::ProgramState &programState,
191                                                   ContextVk *contextVk);
192     void updateBuffersDescriptorSet(ContextVk *contextVk,
193                                     const gl::ShaderType shaderType,
194                                     vk::ResourceUseList *resourceUseList,
195                                     CommandBufferHelper *commandBufferHelper,
196                                     const std::vector<gl::InterfaceBlock> &blocks,
197                                     VkDescriptorType descriptorType);
198     void updateAtomicCounterBuffersDescriptorSet(const gl::ProgramState &programState,
199                                                  const gl::ShaderType shaderType,
200                                                  ContextVk *contextVk,
201                                                  vk::ResourceUseList *resourceUseList,
202                                                  CommandBufferHelper *commandBufferHelper);
203     angle::Result updateImagesDescriptorSet(const gl::ProgramState &programState,
204                                             const gl::ShaderType shaderType,
205                                             ContextVk *contextVk);
206 
207     // This is a special "empty" placeholder buffer for when a shader has no uniforms or doesn't
208     // use all slots in the atomic counter buffer array.
209     //
210     // It is necessary because we want to keep a compatible pipeline layout in all cases,
211     // and Vulkan does not tolerate having null handles in a descriptor set.
212     vk::BufferHelper mEmptyBuffer;
213 
214     // Descriptor sets for uniform blocks and textures for this program.
215     std::vector<VkDescriptorSet> mDescriptorSets;
216     vk::DescriptorSetLayoutArray<VkDescriptorSet> mEmptyDescriptorSets;
217     std::vector<vk::BufferHelper *> mDescriptorBuffersCache;
218     size_t mNumDefaultUniformDescriptors;
219 
220     std::unordered_map<vk::TextureDescriptorDesc, VkDescriptorSet> mTextureDescriptorsCache;
221 
222     // We keep a reference to the pipeline and descriptor set layouts. This ensures they don't get
223     // deleted while this program is in use.
224     vk::BindingPointer<vk::PipelineLayout> mPipelineLayout;
225     vk::DescriptorSetLayoutPointerArray mDescriptorSetLayouts;
226     bool mPipelineLayoutCreated;
227 
228     // Keep bindings to the descriptor pools. This ensures the pools stay valid while the Program
229     // is in use.
230     vk::DescriptorSetLayoutArray<vk::RefCountedDescriptorPoolBinding> mDescriptorPoolBindings;
231 
232     // Store descriptor pools here. We store the descriptors in the Program to facilitate descriptor
233     // cache management. It can also allow fewer descriptors for shaders which use fewer
234     // textures/buffers.
235     vk::DescriptorSetLayoutArray<vk::DynamicDescriptorPool> mDynamicDescriptorPools;
236 
237     gl::ShaderVector<uint32_t> mDynamicBufferOffsets;
238 
239     // TODO: http://anglebug.com/4524: Need a different hash key than a string,
240     // since that's slow to calculate.
241     ShaderMapInterfaceVariableInfoMap mVariableInfoMap;
242 
243     ProgramInfo mProgramInfos[static_cast<int>(ProgramTransformOption::PermutationCount)];
244 
245     ProgramTransformOptionBits mTransformOptionBits;
246 
247     ProgramVk *mProgram;
248     ProgramPipelineVk *mProgramPipeline;
249 };
250 
251 }  // namespace rx
252 
253 #endif  // LIBANGLE_RENDERER_VULKAN_PROGRAMEXECUTABLEVK_H_
254