// // 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 &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 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 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_