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/renderer/glslang_wrapper_utils.h" 19 #include "libANGLE/renderer/vulkan/ContextVk.h" 20 #include "libANGLE/renderer/vulkan/vk_cache_utils.h" 21 #include "libANGLE/renderer/vulkan/vk_helpers.h" 22 23 namespace rx 24 { 25 26 class ShaderInfo final : angle::NonCopyable 27 { 28 public: 29 ShaderInfo(); 30 ~ShaderInfo(); 31 32 angle::Result initShaders(const gl::ShaderBitSet &linkedShaderStages, 33 const gl::ShaderMap<const angle::spirv::Blob *> &spirvBlobs, 34 const ShaderInterfaceVariableInfoMap &variableInfoMap); 35 void release(ContextVk *contextVk); 36 valid()37 ANGLE_INLINE bool valid() const { return mIsInitialized; } 38 getSpirvBlobs()39 const gl::ShaderMap<angle::spirv::Blob> &getSpirvBlobs() const { 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<angle::spirv::Blob> mSpirvBlobs; 47 bool mIsInitialized = false; 48 }; 49 50 struct ProgramTransformOptions final 51 { 52 uint8_t enableLineRasterEmulation : 1; 53 uint8_t removeEarlyFragmentTestsOptimization : 1; 54 uint8_t surfaceRotation : 3; 55 uint8_t enableDepthCorrection : 1; 56 uint8_t reserved : 2; // must initialize to zero 57 static constexpr uint32_t kPermutationCount = 0x1 << 6; 58 }; 59 static_assert(sizeof(ProgramTransformOptions) == 1, "Size check failed"); 60 static_assert(static_cast<int>(SurfaceRotation::EnumCount) <= 8, "Size check failed"); 61 62 class ProgramInfo final : angle::NonCopyable 63 { 64 public: 65 ProgramInfo(); 66 ~ProgramInfo(); 67 68 angle::Result initProgram(ContextVk *contextVk, 69 const gl::ShaderType shaderType, 70 bool isLastPreFragmentStage, 71 bool isTransformFeedbackProgram, 72 const ShaderInfo &shaderInfo, 73 ProgramTransformOptions optionBits, 74 const ShaderInterfaceVariableInfoMap &variableInfoMap); 75 void release(ContextVk *contextVk); 76 valid(const gl::ShaderType shaderType)77 ANGLE_INLINE bool valid(const gl::ShaderType shaderType) const 78 { 79 return mProgramHelper.valid(shaderType); 80 } 81 getShaderProgram()82 vk::ShaderProgramHelper *getShaderProgram() { return &mProgramHelper; } 83 84 private: 85 vk::ShaderProgramHelper mProgramHelper; 86 gl::ShaderMap<vk::RefCounted<vk::ShaderAndSerial>> mShaders; 87 }; 88 89 // State for the default uniform blocks. 90 struct DefaultUniformBlock final : private angle::NonCopyable 91 { 92 DefaultUniformBlock(); 93 ~DefaultUniformBlock(); 94 95 // Shadow copies of the shader uniform data. 96 angle::MemoryBuffer uniformData; 97 98 // Since the default blocks are laid out in std140, this tells us where to write on a call 99 // to a setUniform method. They are arranged in uniform location order. 100 std::vector<sh::BlockMemberInfo> uniformLayout; 101 }; 102 103 // Performance and resource counters. 104 using DescriptorSetCountList = angle::PackedEnumMap<DescriptorSetIndex, uint32_t>; 105 template <typename T> 106 using FormatIndexMap = angle::HashMap<T, uint32_t>; 107 108 struct ProgramExecutablePerfCounters 109 { 110 DescriptorSetCountList descriptorSetAllocations; 111 DescriptorSetCountList descriptorSetCacheHits; 112 DescriptorSetCountList descriptorSetCacheMisses; 113 }; 114 115 class ProgramExecutableVk 116 { 117 public: 118 ProgramExecutableVk(); 119 virtual ~ProgramExecutableVk(); 120 121 void reset(ContextVk *contextVk); 122 123 void save(gl::BinaryOutputStream *stream); 124 std::unique_ptr<rx::LinkEvent> load(gl::BinaryInputStream *stream); 125 126 void clearVariableInfoMap(); 127 128 ProgramVk *getShaderProgram(const gl::State &glState, gl::ShaderType shaderType) const; 129 130 void fillProgramStateMap(const ContextVk *contextVk, 131 gl::ShaderMap<const gl::ProgramState *> *programStatesOut); 132 const gl::ProgramExecutable &getGlExecutable(); 133 getGraphicsDefaultProgramInfo()134 ProgramInfo &getGraphicsDefaultProgramInfo() { return mGraphicsProgramInfos[0]; } getGraphicsProgramInfo(ProgramTransformOptions option)135 ProgramInfo &getGraphicsProgramInfo(ProgramTransformOptions option) 136 { 137 uint8_t index = gl::bitCast<uint8_t, ProgramTransformOptions>(option); 138 return mGraphicsProgramInfos[index]; 139 } getComputeProgramInfo()140 ProgramInfo &getComputeProgramInfo() { return mComputeProgramInfo; } getCurrentDefaultUniformBufferSerial()141 vk::BufferSerial getCurrentDefaultUniformBufferSerial() const 142 { 143 return mCurrentDefaultUniformBufferSerial; 144 } 145 146 angle::Result getGraphicsPipeline(ContextVk *contextVk, 147 gl::PrimitiveMode mode, 148 const vk::GraphicsPipelineDesc &desc, 149 const gl::AttributesMask &activeAttribLocations, 150 const vk::GraphicsPipelineDesc **descPtrOut, 151 vk::PipelineHelper **pipelineOut); 152 153 angle::Result getComputePipeline(ContextVk *contextVk, vk::PipelineAndSerial **pipelineOut); 154 getPipelineLayout()155 const vk::PipelineLayout &getPipelineLayout() const { return mPipelineLayout.get(); } 156 angle::Result createPipelineLayout(const gl::Context *glContext, 157 gl::ActiveTextureArray<vk::TextureUnit> *activeTextures); 158 159 angle::Result updateTexturesDescriptorSet(ContextVk *contextVk, 160 const vk::TextureDescriptorDesc &texturesDesc); 161 angle::Result updateShaderResourcesDescriptorSet( 162 ContextVk *contextVk, 163 FramebufferVk *framebufferVk, 164 const vk::ShaderBuffersDescriptorDesc &shaderBuffersDesc, 165 vk::CommandBufferHelper *commandBufferHelper); 166 angle::Result updateTransformFeedbackDescriptorSet( 167 const gl::ProgramState &programState, 168 gl::ShaderMap<DefaultUniformBlock> &defaultUniformBlocks, 169 vk::BufferHelper *defaultUniformBuffer, 170 ContextVk *contextVk, 171 const vk::UniformsAndXfbDescriptorDesc &xfbBufferDesc); 172 angle::Result updateInputAttachmentDescriptorSet(const gl::ProgramExecutable &executable, 173 const gl::ShaderType shaderType, 174 ContextVk *contextVk, 175 FramebufferVk *framebufferVk); 176 177 angle::Result updateDescriptorSets(ContextVk *contextVk, vk::CommandBuffer *commandBuffer); 178 179 void updateEarlyFragmentTestsOptimization(ContextVk *contextVk); 180 setProgram(ProgramVk * program)181 void setProgram(ProgramVk *program) 182 { 183 ASSERT(!mProgram && !mProgramPipeline); 184 mProgram = program; 185 } setProgramPipeline(ProgramPipelineVk * pipeline)186 void setProgramPipeline(ProgramPipelineVk *pipeline) 187 { 188 ASSERT(!mProgram && !mProgramPipeline); 189 mProgramPipeline = pipeline; 190 } 191 usesDynamicUniformBufferDescriptors()192 bool usesDynamicUniformBufferDescriptors() const 193 { 194 return mUniformBufferDescriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; 195 } 196 isImmutableSamplerFormatCompatible(const FormatIndexMap<uint64_t> & externalFormatIndexMap,const FormatIndexMap<VkFormat> & vkFormatIndexMap)197 bool isImmutableSamplerFormatCompatible(const FormatIndexMap<uint64_t> &externalFormatIndexMap, 198 const FormatIndexMap<VkFormat> &vkFormatIndexMap) const 199 { 200 return (mExternalFormatIndexMap == externalFormatIndexMap && 201 mVkFormatIndexMap == vkFormatIndexMap); 202 } 203 204 void accumulateCacheStats(VulkanCacheType cacheType, const CacheStats &cacheStats); 205 ProgramExecutablePerfCounters getAndResetObjectPerfCounters(); 206 207 private: 208 friend class ProgramVk; 209 friend class ProgramPipelineVk; 210 211 angle::Result allocUniformAndXfbDescriptorSet( 212 ContextVk *contextVk, 213 const vk::UniformsAndXfbDescriptorDesc &xfbBufferDesc, 214 bool *newDescriptorSetAllocated); 215 216 angle::Result allocateDescriptorSet(ContextVk *contextVk, 217 DescriptorSetIndex descriptorSetIndex); 218 angle::Result allocateDescriptorSetAndGetInfo(ContextVk *contextVk, 219 DescriptorSetIndex descriptorSetIndex, 220 bool *newPoolAllocatedOut); 221 void addInterfaceBlockDescriptorSetDesc(const std::vector<gl::InterfaceBlock> &blocks, 222 const gl::ShaderType shaderType, 223 VkDescriptorType descType, 224 vk::DescriptorSetLayoutDesc *descOut); 225 void addAtomicCounterBufferDescriptorSetDesc( 226 const std::vector<gl::AtomicCounterBuffer> &atomicCounterBuffers, 227 const gl::ShaderType shaderType, 228 vk::DescriptorSetLayoutDesc *descOut); 229 void addImageDescriptorSetDesc(const gl::ProgramExecutable &executable, 230 vk::DescriptorSetLayoutDesc *descOut); 231 void addInputAttachmentDescriptorSetDesc(const gl::ProgramExecutable &executable, 232 const gl::ShaderType shaderType, 233 vk::DescriptorSetLayoutDesc *descOut); 234 void addTextureDescriptorSetDesc(ContextVk *contextVk, 235 const gl::ProgramState &programState, 236 const gl::ActiveTextureArray<vk::TextureUnit> *activeTextures, 237 vk::DescriptorSetLayoutDesc *descOut); 238 239 void resolvePrecisionMismatch(const gl::ProgramMergedVaryings &mergedVaryings); 240 void updateDefaultUniformsDescriptorSet(const gl::ShaderType shaderType, 241 const DefaultUniformBlock &defaultUniformBlock, 242 vk::BufferHelper *defaultUniformBuffer, 243 ContextVk *contextVk); 244 void updateTransformFeedbackDescriptorSetImpl(const gl::ProgramState &programState, 245 ContextVk *contextVk); 246 angle::Result getOrAllocateShaderResourcesDescriptorSet( 247 ContextVk *contextVk, 248 const vk::ShaderBuffersDescriptorDesc *shaderBuffersDesc, 249 VkDescriptorSet *descriptorSetOut); 250 angle::Result updateBuffersDescriptorSet( 251 ContextVk *contextVk, 252 const gl::ShaderType shaderType, 253 const vk::ShaderBuffersDescriptorDesc &shaderBuffersDesc, 254 const std::vector<gl::InterfaceBlock> &blocks, 255 VkDescriptorType descriptorType, 256 bool cacheHit); 257 angle::Result updateAtomicCounterBuffersDescriptorSet( 258 ContextVk *contextVk, 259 const gl::ProgramState &programState, 260 const gl::ShaderType shaderType, 261 const vk::ShaderBuffersDescriptorDesc &shaderBuffersDesc, 262 bool cacheHit); 263 angle::Result updateImagesDescriptorSet(ContextVk *contextVk, 264 const gl::ProgramExecutable &executable, 265 const gl::ShaderType shaderType); 266 angle::Result initDynamicDescriptorPools(ContextVk *contextVk, 267 vk::DescriptorSetLayoutDesc &descriptorSetLayoutDesc, 268 DescriptorSetIndex descriptorSetIndex, 269 VkDescriptorSetLayout descriptorSetLayout); 270 271 void outputCumulativePerfCounters(); 272 273 // Descriptor sets for uniform blocks and textures for this program. 274 vk::DescriptorSetArray<VkDescriptorSet> mDescriptorSets; 275 vk::DescriptorSetArray<VkDescriptorSet> mEmptyDescriptorSets; 276 uint32_t mNumDefaultUniformDescriptors; 277 vk::BufferSerial mCurrentDefaultUniformBufferSerial; 278 279 DescriptorSetCache<vk::UniformsAndXfbDescriptorDesc, VulkanCacheType::UniformsAndXfbDescriptors> 280 mUniformsAndXfbDescriptorsCache; 281 DescriptorSetCache<vk::TextureDescriptorDesc, VulkanCacheType::TextureDescriptors> 282 mTextureDescriptorsCache; 283 DescriptorSetCache<vk::ShaderBuffersDescriptorDesc, VulkanCacheType::ShaderBuffersDescriptors> 284 mShaderBufferDescriptorsCache; 285 286 // We keep a reference to the pipeline and descriptor set layouts. This ensures they don't get 287 // deleted while this program is in use. 288 uint32_t mImmutableSamplersMaxDescriptorCount; 289 FormatIndexMap<uint64_t> mExternalFormatIndexMap; 290 FormatIndexMap<VkFormat> mVkFormatIndexMap; 291 vk::BindingPointer<vk::PipelineLayout> mPipelineLayout; 292 vk::DescriptorSetLayoutPointerArray mDescriptorSetLayouts; 293 294 // Keep bindings to the descriptor pools. This ensures the pools stay valid while the Program 295 // is in use. 296 vk::DescriptorSetArray<vk::RefCountedDescriptorPoolBinding> mDescriptorPoolBindings; 297 298 // Store descriptor pools here. We store the descriptors in the Program to facilitate descriptor 299 // cache management. It can also allow fewer descriptors for shaders which use fewer 300 // textures/buffers. 301 vk::DescriptorSetArray<vk::DynamicDescriptorPool> mDynamicDescriptorPools; 302 303 // A set of dynamic offsets used with vkCmdBindDescriptorSets for the default uniform buffers. 304 VkDescriptorType mUniformBufferDescriptorType; 305 gl::ShaderVector<uint32_t> mDynamicUniformDescriptorOffsets; 306 std::vector<uint32_t> mDynamicShaderBufferDescriptorOffsets; 307 308 // TODO: http://anglebug.com/4524: Need a different hash key than a string, 309 // since that's slow to calculate. 310 ShaderInterfaceVariableInfoMap mVariableInfoMap; 311 312 // We store all permutations of surface rotation and transformed SPIR-V programs here. We may 313 // need some LRU algorithm to free least used programs to reduce the number of programs. 314 ProgramInfo mGraphicsProgramInfos[ProgramTransformOptions::kPermutationCount]; 315 ProgramInfo mComputeProgramInfo; 316 317 ProgramTransformOptions mTransformOptions; 318 319 ProgramVk *mProgram; 320 ProgramPipelineVk *mProgramPipeline; 321 322 ProgramExecutablePerfCounters mPerfCounters; 323 ProgramExecutablePerfCounters mCumulativePerfCounters; 324 }; 325 326 } // namespace rx 327 328 #endif // LIBANGLE_RENDERER_VULKAN_PROGRAMEXECUTABLEVK_H_ 329