| // |
| // Copyright 2023 The ANGLE Project Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| // |
| // ShareGroupVk.h: |
| // Defines the class interface for ShareGroupVk, implementing ShareGroupImpl. |
| // |
| |
| #ifndef LIBANGLE_RENDERER_VULKAN_SHAREGROUPVK_H_ |
| #define LIBANGLE_RENDERER_VULKAN_SHAREGROUPVK_H_ |
| |
| #include "libANGLE/renderer/ShareGroupImpl.h" |
| #include "libANGLE/renderer/vulkan/vk_cache_utils.h" |
| #include "libANGLE/renderer/vulkan/vk_helpers.h" |
| #include "libANGLE/renderer/vulkan/vk_resource.h" |
| #include "libANGLE/renderer/vulkan/vk_utils.h" |
| |
| namespace rx |
| { |
| constexpr VkDeviceSize kMaxTotalEmptyBufferBytes = 16 * 1024 * 1024; |
| |
| class TextureUpload |
| { |
| public: |
| TextureUpload() { mPrevUploadedMutableTexture = nullptr; } |
| ~TextureUpload() { resetPrevTexture(); } |
| angle::Result onMutableTextureUpload(ContextVk *contextVk, TextureVk *newTexture); |
| void onTextureRelease(TextureVk *textureVk); |
| void resetPrevTexture() { mPrevUploadedMutableTexture = nullptr; } |
| |
| private: |
| // Keep track of the previously stored texture. Used to flush mutable textures. |
| TextureVk *mPrevUploadedMutableTexture; |
| }; |
| |
| class ShareGroupVk : public ShareGroupImpl |
| { |
| public: |
| ShareGroupVk(const egl::ShareGroupState &state, vk::Renderer *renderer); |
| void onDestroy(const egl::Display *display) override; |
| |
| void onContextAdd() override; |
| |
| FramebufferCache &getFramebufferCache() { return mFramebufferCache; } |
| |
| bool hasAnyContextWithRobustness() const { return mState.hasAnyContextWithRobustness(); } |
| |
| // PipelineLayoutCache and DescriptorSetLayoutCache can be shared between multiple threads |
| // accessing them via shared contexts. The ShareGroup locks around gl entrypoints ensuring |
| // synchronous update to the caches. |
| PipelineLayoutCache &getPipelineLayoutCache() { return mPipelineLayoutCache; } |
| DescriptorSetLayoutCache &getDescriptorSetLayoutCache() { return mDescriptorSetLayoutCache; } |
| const egl::ContextMap &getContexts() const { return mState.getContexts(); } |
| vk::DescriptorSetArray<vk::MetaDescriptorPool> &getMetaDescriptorPools() |
| { |
| return mMetaDescriptorPools; |
| } |
| |
| // Used to flush the mutable textures more often. |
| angle::Result onMutableTextureUpload(ContextVk *contextVk, TextureVk *newTexture); |
| |
| vk::BufferPool *getDefaultBufferPool(VkDeviceSize size, |
| uint32_t memoryTypeIndex, |
| BufferUsageType usageType); |
| |
| void pruneDefaultBufferPools(); |
| |
| void calculateTotalBufferCount(size_t *bufferCount, VkDeviceSize *totalSize) const; |
| void logBufferPools() const; |
| |
| // Temporary workaround until VkSemaphore(s) will be used between different priorities. |
| angle::Result unifyContextsPriority(ContextVk *newContextVk); |
| // Temporary workaround until VkSemaphore(s) will be used between different priorities. |
| angle::Result lockDefaultContextsPriority(ContextVk *contextVk); |
| |
| UpdateDescriptorSetsBuilder *getUpdateDescriptorSetsBuilder() |
| { |
| return &mUpdateDescriptorSetsBuilder; |
| } |
| |
| void onTextureRelease(TextureVk *textureVk); |
| |
| angle::Result scheduleMonolithicPipelineCreationTask( |
| ContextVk *contextVk, |
| vk::WaitableMonolithicPipelineCreationTask *taskOut); |
| void waitForCurrentMonolithicPipelineCreationTask(); |
| |
| vk::RefCountedEventsGarbageRecycler *getRefCountedEventsGarbageRecycler() |
| { |
| return &mRefCountedEventsGarbageRecycler; |
| } |
| void cleanupRefCountedEventGarbage() { mRefCountedEventsGarbageRecycler.cleanup(mRenderer); } |
| void cleanupExcessiveRefCountedEventGarbage() |
| { |
| // TODO: b/336844257 needs tune. |
| constexpr size_t kExcessiveGarbageCountThreshold = 256; |
| if (mRefCountedEventsGarbageRecycler.getGarbageCount() > kExcessiveGarbageCountThreshold) |
| { |
| mRefCountedEventsGarbageRecycler.cleanup(mRenderer); |
| } |
| } |
| |
| void onFramebufferBoundary(); |
| uint32_t getCurrentFrameCount() const { return mCurrentFrameCount; } |
| |
| private: |
| angle::Result updateContextsPriority(ContextVk *contextVk, egl::ContextPriority newPriority); |
| |
| bool isDueForBufferPoolPrune(); |
| |
| vk::Renderer *mRenderer; |
| |
| // Tracks the total number of frames rendered. |
| uint32_t mCurrentFrameCount; |
| |
| // VkFramebuffer caches |
| FramebufferCache mFramebufferCache; |
| |
| void resetPrevTexture() { mTextureUpload.resetPrevTexture(); } |
| |
| // ANGLE uses a PipelineLayout cache to store compatible pipeline layouts. |
| PipelineLayoutCache mPipelineLayoutCache; |
| |
| // DescriptorSetLayouts are also managed in a cache. |
| DescriptorSetLayoutCache mDescriptorSetLayoutCache; |
| |
| // Descriptor set caches |
| vk::DescriptorSetArray<vk::MetaDescriptorPool> mMetaDescriptorPools; |
| |
| // Priority of all Contexts in the context set |
| egl::ContextPriority mContextsPriority; |
| bool mIsContextsPriorityLocked; |
| |
| // Storage for vkUpdateDescriptorSets |
| UpdateDescriptorSetsBuilder mUpdateDescriptorSetsBuilder; |
| |
| // The per shared group buffer pools that all buffers should sub-allocate from. |
| vk::BufferPoolPointerArray mDefaultBufferPools; |
| |
| // The system time when last pruneEmptyBuffer gets called. |
| double mLastPruneTime; |
| |
| // The system time when the last monolithic pipeline creation job was launched. This is |
| // rate-limited to avoid hogging all cores and interfering with the application threads. A |
| // single pipeline creation job is currently supported. |
| double mLastMonolithicPipelineJobTime; |
| std::shared_ptr<angle::WaitableEvent> mMonolithicPipelineCreationEvent; |
| |
| // Texture update manager used to flush uploaded mutable textures. |
| TextureUpload mTextureUpload; |
| |
| // Holds RefCountedEvent that are free and ready to reuse |
| vk::RefCountedEventsGarbageRecycler mRefCountedEventsGarbageRecycler; |
| }; |
| } // namespace rx |
| |
| #endif // LIBANGLE_RENDERER_VULKAN_SHAREGROUPVK_H_ |