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