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/vk_cache_utils.h" 15 #include "libANGLE/renderer/vulkan/vk_helpers.h" 16 #include "libANGLE/renderer/vulkan/vk_resource.h" 17 #include "libANGLE/renderer/vulkan/vk_utils.h" 18 19 namespace rx 20 { 21 constexpr VkDeviceSize kMaxTotalEmptyBufferBytes = 16 * 1024 * 1024; 22 23 class TextureUpload 24 { 25 public: TextureUpload()26 TextureUpload() { mPrevUploadedMutableTexture = nullptr; } ~TextureUpload()27 ~TextureUpload() { resetPrevTexture(); } 28 angle::Result onMutableTextureUpload(ContextVk *contextVk, TextureVk *newTexture); 29 void onTextureRelease(TextureVk *textureVk); resetPrevTexture()30 void resetPrevTexture() { mPrevUploadedMutableTexture = nullptr; } 31 32 private: 33 // Keep track of the previously stored texture. Used to flush mutable textures. 34 TextureVk *mPrevUploadedMutableTexture; 35 }; 36 37 class ShareGroupVk : public ShareGroupImpl 38 { 39 public: 40 ShareGroupVk(const egl::ShareGroupState &state, vk::Renderer *renderer); 41 void onDestroy(const egl::Display *display) override; 42 43 void onContextAdd() override; 44 getFramebufferCache()45 FramebufferCache &getFramebufferCache() { return mFramebufferCache; } 46 hasAnyContextWithRobustness()47 bool hasAnyContextWithRobustness() const { return mState.hasAnyContextWithRobustness(); } 48 49 // PipelineLayoutCache and DescriptorSetLayoutCache can be shared between multiple threads 50 // accessing them via shared contexts. The ShareGroup locks around gl entrypoints ensuring 51 // synchronous update to the caches. getPipelineLayoutCache()52 PipelineLayoutCache &getPipelineLayoutCache() { return mPipelineLayoutCache; } getDescriptorSetLayoutCache()53 DescriptorSetLayoutCache &getDescriptorSetLayoutCache() { return mDescriptorSetLayoutCache; } getContexts()54 const egl::ContextMap &getContexts() const { return mState.getContexts(); } getMetaDescriptorPools()55 vk::DescriptorSetArray<vk::MetaDescriptorPool> &getMetaDescriptorPools() 56 { 57 return mMetaDescriptorPools; 58 } 59 60 // Used to flush the mutable textures more often. 61 angle::Result onMutableTextureUpload(ContextVk *contextVk, TextureVk *newTexture); 62 63 vk::BufferPool *getDefaultBufferPool(VkDeviceSize size, 64 uint32_t memoryTypeIndex, 65 BufferUsageType usageType); 66 67 void pruneDefaultBufferPools(); 68 69 void calculateTotalBufferCount(size_t *bufferCount, VkDeviceSize *totalSize) const; 70 void logBufferPools() const; 71 72 // Temporary workaround until VkSemaphore(s) will be used between different priorities. 73 angle::Result unifyContextsPriority(ContextVk *newContextVk); 74 // Temporary workaround until VkSemaphore(s) will be used between different priorities. 75 angle::Result lockDefaultContextsPriority(ContextVk *contextVk); 76 getUpdateDescriptorSetsBuilder()77 UpdateDescriptorSetsBuilder *getUpdateDescriptorSetsBuilder() 78 { 79 return &mUpdateDescriptorSetsBuilder; 80 } 81 82 void onTextureRelease(TextureVk *textureVk); 83 getVertexInputGraphicsPipelineCache()84 VertexInputGraphicsPipelineCache *getVertexInputGraphicsPipelineCache() 85 { 86 return &mVertexInputGraphicsPipelineCache; 87 } getFragmentOutputGraphicsPipelineCache()88 FragmentOutputGraphicsPipelineCache *getFragmentOutputGraphicsPipelineCache() 89 { 90 return &mFragmentOutputGraphicsPipelineCache; 91 } 92 93 angle::Result scheduleMonolithicPipelineCreationTask( 94 ContextVk *contextVk, 95 vk::WaitableMonolithicPipelineCreationTask *taskOut); 96 void waitForCurrentMonolithicPipelineCreationTask(); 97 getRefCountedEventsGarbageRecycler()98 vk::RefCountedEventsGarbageRecycler *getRefCountedEventsGarbageRecycler() 99 { 100 return &mRefCountedEventsGarbageRecycler; 101 } cleanupRefCountedEventGarbage()102 void cleanupRefCountedEventGarbage() { mRefCountedEventsGarbageRecycler.cleanup(mRenderer); } cleanupExcessiveRefCountedEventGarbage()103 void cleanupExcessiveRefCountedEventGarbage() 104 { 105 // TODO: b/336844257 needs tune. 106 constexpr size_t kExcessiveGarbageCountThreshold = 256; 107 if (mRefCountedEventsGarbageRecycler.getGarbageCount() > kExcessiveGarbageCountThreshold) 108 { 109 mRefCountedEventsGarbageRecycler.cleanup(mRenderer); 110 } 111 } 112 113 void onFramebufferBoundary(); getCurrentFrameCount()114 uint32_t getCurrentFrameCount() const { return mCurrentFrameCount; } 115 116 private: 117 angle::Result updateContextsPriority(ContextVk *contextVk, egl::ContextPriority newPriority); 118 119 bool isDueForBufferPoolPrune(); 120 121 vk::Renderer *mRenderer; 122 123 // Tracks the total number of frames rendered. 124 uint32_t mCurrentFrameCount; 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 vk::BufferPoolPointerArray mDefaultBufferPools; 149 150 // The system time when last pruneEmptyBuffer gets called. 151 double mLastPruneTime; 152 153 // Used when VK_EXT_graphics_pipeline_library is available, the vertex input and fragment output 154 // partial pipelines are created in the following caches. These caches are in the share group 155 // because linked pipelines using these pipeline libraries are referenced from 156 // ProgramExecutableVk, and as such must stay alive as long as the program may be alive. 157 VertexInputGraphicsPipelineCache mVertexInputGraphicsPipelineCache; 158 FragmentOutputGraphicsPipelineCache mFragmentOutputGraphicsPipelineCache; 159 160 // The system time when the last monolithic pipeline creation job was launched. This is 161 // rate-limited to avoid hogging all cores and interfering with the application threads. A 162 // single pipeline creation job is currently supported. 163 double mLastMonolithicPipelineJobTime; 164 std::shared_ptr<angle::WaitableEvent> mMonolithicPipelineCreationEvent; 165 166 // Texture update manager used to flush uploaded mutable textures. 167 TextureUpload mTextureUpload; 168 169 // Holds RefCountedEvent that are free and ready to reuse 170 vk::RefCountedEventsGarbageRecycler mRefCountedEventsGarbageRecycler; 171 }; 172 } // namespace rx 173 174 #endif // LIBANGLE_RENDERER_VULKAN_SHAREGROUPVK_H_ 175