1 // 2 // Copyright 2023 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 // ShareGroupVk.h: 7 // Defines the class interface for ShareGroupVk, implementing ShareGroupImpl. 8 // 9 10 #ifndef LIBANGLE_RENDERER_VULKAN_SHAREGROUPVK_H_ 11 #define LIBANGLE_RENDERER_VULKAN_SHAREGROUPVK_H_ 12 13 #include "libANGLE/renderer/ShareGroupImpl.h" 14 #include "libANGLE/renderer/vulkan/ResourceVk.h" 15 #include "libANGLE/renderer/vulkan/vk_cache_utils.h" 16 #include "libANGLE/renderer/vulkan/vk_helpers.h" 17 #include "libANGLE/renderer/vulkan/vk_utils.h" 18 19 namespace rx 20 { 21 constexpr VkDeviceSize kMaxTotalEmptyBufferBytes = 16 * 1024 * 1024; 22 23 class RendererVk; 24 25 class TextureUpload 26 { 27 public: TextureUpload()28 TextureUpload() { mPrevUploadedMutableTexture = nullptr; } ~TextureUpload()29 ~TextureUpload() { resetPrevTexture(); } 30 angle::Result onMutableTextureUpload(ContextVk *contextVk, TextureVk *newTexture); 31 void onTextureRelease(TextureVk *textureVk); resetPrevTexture()32 void resetPrevTexture() { mPrevUploadedMutableTexture = nullptr; } 33 34 private: 35 // Keep track of the previously stored texture. Used to flush mutable textures. 36 TextureVk *mPrevUploadedMutableTexture; 37 }; 38 39 class UpdateDescriptorSetsBuilder final : angle::NonCopyable 40 { 41 public: 42 UpdateDescriptorSetsBuilder(); 43 ~UpdateDescriptorSetsBuilder(); 44 45 VkDescriptorBufferInfo *allocDescriptorBufferInfos(size_t count); 46 VkDescriptorImageInfo *allocDescriptorImageInfos(size_t count); 47 VkWriteDescriptorSet *allocWriteDescriptorSets(size_t count); 48 VkBufferView *allocBufferViews(size_t count); 49 allocDescriptorBufferInfo()50 VkDescriptorBufferInfo &allocDescriptorBufferInfo() { return *allocDescriptorBufferInfos(1); } allocDescriptorImageInfo()51 VkDescriptorImageInfo &allocDescriptorImageInfo() { return *allocDescriptorImageInfos(1); } allocWriteDescriptorSet()52 VkWriteDescriptorSet &allocWriteDescriptorSet() { return *allocWriteDescriptorSets(1); } allocBufferView()53 VkBufferView &allocBufferView() { return *allocBufferViews(1); } 54 55 // Returns the number of written descriptor sets. 56 uint32_t flushDescriptorSetUpdates(VkDevice device); 57 58 private: 59 template <typename T, const T *VkWriteDescriptorSet::*pInfo> 60 T *allocDescriptorInfos(std::vector<T> *descriptorVector, size_t count); 61 template <typename T, const T *VkWriteDescriptorSet::*pInfo> 62 void growDescriptorCapacity(std::vector<T> *descriptorVector, size_t newSize); 63 64 std::vector<VkDescriptorBufferInfo> mDescriptorBufferInfos; 65 std::vector<VkDescriptorImageInfo> mDescriptorImageInfos; 66 std::vector<VkWriteDescriptorSet> mWriteDescriptorSets; 67 std::vector<VkBufferView> mBufferViews; 68 }; 69 70 class ShareGroupVk : public ShareGroupImpl 71 { 72 public: 73 ShareGroupVk(const egl::ShareGroupState &state); 74 void onDestroy(const egl::Display *display) override; 75 76 void onContextAdd() override; 77 getFramebufferCache()78 FramebufferCache &getFramebufferCache() { return mFramebufferCache; } 79 hasAnyContextWithRobustness()80 bool hasAnyContextWithRobustness() const { return mState.hasAnyContextWithRobustness(); } 81 82 // PipelineLayoutCache and DescriptorSetLayoutCache can be shared between multiple threads 83 // accessing them via shared contexts. The ShareGroup locks around gl entrypoints ensuring 84 // synchronous update to the caches. getPipelineLayoutCache()85 PipelineLayoutCache &getPipelineLayoutCache() { return mPipelineLayoutCache; } getDescriptorSetLayoutCache()86 DescriptorSetLayoutCache &getDescriptorSetLayoutCache() { return mDescriptorSetLayoutCache; } getContexts()87 const egl::ContextMap &getContexts() const { return mState.getContexts(); } getMetaDescriptorPool(DescriptorSetIndex descriptorSetIndex)88 vk::MetaDescriptorPool &getMetaDescriptorPool(DescriptorSetIndex descriptorSetIndex) 89 { 90 return mMetaDescriptorPools[descriptorSetIndex]; 91 } 92 93 // Used to flush the mutable textures more often. 94 angle::Result onMutableTextureUpload(ContextVk *contextVk, TextureVk *newTexture); 95 96 vk::BufferPool *getDefaultBufferPool(RendererVk *renderer, 97 VkDeviceSize size, 98 uint32_t memoryTypeIndex, 99 BufferUsageType usageType); 100 void pruneDefaultBufferPools(RendererVk *renderer); 101 bool isDueForBufferPoolPrune(RendererVk *renderer); 102 103 void calculateTotalBufferCount(size_t *bufferCount, VkDeviceSize *totalSize) const; 104 void logBufferPools() const; 105 106 // Temporary workaround until VkSemaphore(s) will be used between different priorities. 107 angle::Result unifyContextsPriority(ContextVk *newContextVk); 108 // Temporary workaround until VkSemaphore(s) will be used between different priorities. 109 angle::Result lockDefaultContextsPriority(ContextVk *contextVk); 110 getUpdateDescriptorSetsBuilder()111 UpdateDescriptorSetsBuilder *getUpdateDescriptorSetsBuilder() 112 { 113 return &mUpdateDescriptorSetsBuilder; 114 } 115 116 void onTextureRelease(TextureVk *textureVk); 117 118 angle::Result scheduleMonolithicPipelineCreationTask( 119 ContextVk *contextVk, 120 vk::WaitableMonolithicPipelineCreationTask *taskOut); 121 void waitForCurrentMonolithicPipelineCreationTask(); 122 123 private: 124 angle::Result updateContextsPriority(ContextVk *contextVk, egl::ContextPriority newPriority); 125 126 // VkFramebuffer caches 127 FramebufferCache mFramebufferCache; 128 resetPrevTexture()129 void resetPrevTexture() { mTextureUpload.resetPrevTexture(); } 130 131 // ANGLE uses a PipelineLayout cache to store compatible pipeline layouts. 132 PipelineLayoutCache mPipelineLayoutCache; 133 134 // DescriptorSetLayouts are also managed in a cache. 135 DescriptorSetLayoutCache mDescriptorSetLayoutCache; 136 137 // Descriptor set caches 138 vk::DescriptorSetArray<vk::MetaDescriptorPool> mMetaDescriptorPools; 139 140 // Priority of all Contexts in the context set 141 egl::ContextPriority mContextsPriority; 142 bool mIsContextsPriorityLocked; 143 144 // Storage for vkUpdateDescriptorSets 145 UpdateDescriptorSetsBuilder mUpdateDescriptorSetsBuilder; 146 147 // The per shared group buffer pools that all buffers should sub-allocate from. 148 enum class SuballocationAlgorithm : uint8_t 149 { 150 Buddy = 0, 151 General = 1, 152 InvalidEnum = 2, 153 EnumCount = InvalidEnum, 154 }; 155 angle::PackedEnumMap<SuballocationAlgorithm, vk::BufferPoolPointerArray> mDefaultBufferPools; 156 angle::PackedEnumMap<BufferUsageType, size_t> mSizeLimitForBuddyAlgorithm; 157 158 // The system time when last pruneEmptyBuffer gets called. 159 double mLastPruneTime; 160 161 // The system time when the last monolithic pipeline creation job was launched. This is 162 // rate-limited to avoid hogging all cores and interfering with the application threads. A 163 // single pipeline creation job is currently supported. 164 double mLastMonolithicPipelineJobTime; 165 std::shared_ptr<angle::WaitableEvent> mMonolithicPipelineCreationEvent; 166 167 // Texture update manager used to flush uploaded mutable textures. 168 TextureUpload mTextureUpload; 169 }; 170 } // namespace rx 171 172 #endif // LIBANGLE_RENDERER_VULKAN_SHAREGROUPVK_H_ 173