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 removeTransformFeedbackEmulation : 1; 57 uint8_t reserved : 1; // must initialize to zero 58 static constexpr uint32_t kPermutationCount = 0x1 << 7; 59 }; 60 static_assert(sizeof(ProgramTransformOptions) == 1, "Size check failed"); 61 static_assert(static_cast<int>(SurfaceRotation::EnumCount) <= 8, "Size check failed"); 62 63 class ProgramInfo final : angle::NonCopyable 64 { 65 public: 66 ProgramInfo(); 67 ~ProgramInfo(); 68 69 angle::Result initProgram(ContextVk *contextVk, 70 const gl::ShaderType shaderType, 71 bool isLastPreFragmentStage, 72 bool isTransformFeedbackProgram, 73 const ShaderInfo &shaderInfo, 74 ProgramTransformOptions optionBits, 75 const ShaderInterfaceVariableInfoMap &variableInfoMap); 76 void release(ContextVk *contextVk); 77 valid(const gl::ShaderType shaderType)78 ANGLE_INLINE bool valid(const gl::ShaderType shaderType) const 79 { 80 return mProgramHelper.valid(shaderType); 81 } 82 getShaderProgram()83 vk::ShaderProgramHelper *getShaderProgram() { return &mProgramHelper; } 84 85 private: 86 vk::ShaderProgramHelper mProgramHelper; 87 gl::ShaderMap<vk::RefCounted<vk::ShaderAndSerial>> mShaders; 88 }; 89 90 // State for the default uniform blocks. 91 struct DefaultUniformBlock final : private angle::NonCopyable 92 { 93 DefaultUniformBlock(); 94 ~DefaultUniformBlock(); 95 96 // Shadow copies of the shader uniform data. 97 angle::MemoryBuffer uniformData; 98 99 // Since the default blocks are laid out in std140, this tells us where to write on a call 100 // to a setUniform method. They are arranged in uniform location order. 101 std::vector<sh::BlockMemberInfo> uniformLayout; 102 }; 103 104 // Performance and resource counters. 105 using DescriptorSetCountList = angle::PackedEnumMap<DescriptorSetIndex, uint32_t>; 106 using ImmutableSamplerIndexMap = angle::HashMap<vk::YcbcrConversionDesc, 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 vk::GraphicsPipelineDesc **descPtrOut, 150 vk::PipelineHelper **pipelineOut); 151 152 angle::Result getComputePipeline(ContextVk *contextVk, vk::PipelineHelper **pipelineOut); 153 getPipelineLayout()154 const vk::PipelineLayout &getPipelineLayout() const { return mPipelineLayout.get(); } 155 angle::Result createPipelineLayout(ContextVk *contextVk, 156 const gl::ProgramExecutable &glExecutable, 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, 178 vk::CommandBuffer *commandBuffer, 179 PipelineType pipelineType); 180 181 void updateEarlyFragmentTestsOptimization(ContextVk *contextVk); 182 setProgram(ProgramVk * program)183 void setProgram(ProgramVk *program) 184 { 185 ASSERT(!mProgram && !mProgramPipeline); 186 mProgram = program; 187 } setProgramPipeline(ProgramPipelineVk * pipeline)188 void setProgramPipeline(ProgramPipelineVk *pipeline) 189 { 190 ASSERT(!mProgram && !mProgramPipeline); 191 mProgramPipeline = pipeline; 192 } 193 usesDynamicUniformBufferDescriptors()194 bool usesDynamicUniformBufferDescriptors() const 195 { 196 return mUniformBufferDescriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; 197 } 198 areImmutableSamplersCompatible(const ImmutableSamplerIndexMap & immutableSamplerIndexMap)199 bool areImmutableSamplersCompatible( 200 const ImmutableSamplerIndexMap &immutableSamplerIndexMap) const 201 { 202 return (mImmutableSamplerIndexMap == immutableSamplerIndexMap); 203 } 204 205 void accumulateCacheStats(VulkanCacheType cacheType, const CacheStats &cacheStats); 206 ProgramExecutablePerfCounters getAndResetObjectPerfCounters(); 207 208 private: 209 friend class ProgramVk; 210 friend class ProgramPipelineVk; 211 212 angle::Result allocUniformAndXfbDescriptorSet( 213 ContextVk *contextVk, 214 const vk::UniformsAndXfbDescriptorDesc &xfbBufferDesc, 215 bool *newDescriptorSetAllocated); 216 217 angle::Result allocateDescriptorSet(ContextVk *contextVk, 218 DescriptorSetIndex descriptorSetIndex); 219 angle::Result allocateDescriptorSetAndGetInfo(ContextVk *contextVk, 220 DescriptorSetIndex descriptorSetIndex, 221 bool *newPoolAllocatedOut); 222 void addInterfaceBlockDescriptorSetDesc(const std::vector<gl::InterfaceBlock> &blocks, 223 const gl::ShaderType shaderType, 224 VkDescriptorType descType, 225 vk::DescriptorSetLayoutDesc *descOut); 226 void addAtomicCounterBufferDescriptorSetDesc( 227 const std::vector<gl::AtomicCounterBuffer> &atomicCounterBuffers, 228 const gl::ShaderType shaderType, 229 vk::DescriptorSetLayoutDesc *descOut); 230 void addImageDescriptorSetDesc(const gl::ProgramExecutable &executable, 231 vk::DescriptorSetLayoutDesc *descOut); 232 void addInputAttachmentDescriptorSetDesc(const gl::ProgramExecutable &executable, 233 const gl::ShaderType shaderType, 234 vk::DescriptorSetLayoutDesc *descOut); 235 void addTextureDescriptorSetDesc(ContextVk *contextVk, 236 const gl::ProgramState &programState, 237 const gl::ActiveTextureArray<vk::TextureUnit> *activeTextures, 238 vk::DescriptorSetLayoutDesc *descOut); 239 240 void resolvePrecisionMismatch(const gl::ProgramMergedVaryings &mergedVaryings); 241 void updateDefaultUniformsDescriptorSet(const gl::ShaderType shaderType, 242 const DefaultUniformBlock &defaultUniformBlock, 243 vk::BufferHelper *defaultUniformBuffer, 244 ContextVk *contextVk); 245 void updateTransformFeedbackDescriptorSetImpl(const gl::ProgramState &programState, 246 ContextVk *contextVk); 247 angle::Result getOrAllocateShaderResourcesDescriptorSet( 248 ContextVk *contextVk, 249 const vk::ShaderBuffersDescriptorDesc *shaderBuffersDesc, 250 VkDescriptorSet *descriptorSetOut); 251 angle::Result updateBuffersDescriptorSet( 252 ContextVk *contextVk, 253 const gl::ShaderType shaderType, 254 const vk::ShaderBuffersDescriptorDesc &shaderBuffersDesc, 255 const std::vector<gl::InterfaceBlock> &blocks, 256 VkDescriptorType descriptorType, 257 bool cacheHit); 258 angle::Result updateAtomicCounterBuffersDescriptorSet( 259 ContextVk *contextVk, 260 const gl::ProgramState &programState, 261 const gl::ShaderType shaderType, 262 const vk::ShaderBuffersDescriptorDesc &shaderBuffersDesc, 263 bool cacheHit); 264 angle::Result updateImagesDescriptorSet(ContextVk *contextVk, 265 const gl::ProgramExecutable &executable, 266 const gl::ShaderType shaderType); 267 angle::Result initDynamicDescriptorPools(ContextVk *contextVk, 268 vk::DescriptorSetLayoutDesc &descriptorSetLayoutDesc, 269 DescriptorSetIndex descriptorSetIndex, 270 VkDescriptorSetLayout descriptorSetLayout); 271 272 void outputCumulativePerfCounters(); 273 274 // Descriptor sets for uniform blocks and textures for this program. 275 vk::DescriptorSetArray<VkDescriptorSet> mDescriptorSets; 276 vk::DescriptorSetArray<VkDescriptorSet> mEmptyDescriptorSets; 277 uint32_t mNumDefaultUniformDescriptors; 278 vk::BufferSerial mCurrentDefaultUniformBufferSerial; 279 280 DescriptorSetCache<vk::UniformsAndXfbDescriptorDesc, VulkanCacheType::UniformsAndXfbDescriptors> 281 mUniformsAndXfbDescriptorsCache; 282 DescriptorSetCache<vk::TextureDescriptorDesc, VulkanCacheType::TextureDescriptors> 283 mTextureDescriptorsCache; 284 DescriptorSetCache<vk::ShaderBuffersDescriptorDesc, VulkanCacheType::ShaderBuffersDescriptors> 285 mShaderBufferDescriptorsCache; 286 287 // We keep a reference to the pipeline and descriptor set layouts. This ensures they don't get 288 // deleted while this program is in use. 289 uint32_t mImmutableSamplersMaxDescriptorCount; 290 ImmutableSamplerIndexMap mImmutableSamplerIndexMap; 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