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