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