1 //
2 // Copyright 2016 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 // RendererVk.h:
7 //    Defines the class interface for RendererVk.
8 //
9 
10 #ifndef LIBANGLE_RENDERER_VULKAN_RENDERERVK_H_
11 #define LIBANGLE_RENDERER_VULKAN_RENDERERVK_H_
12 
13 #include <condition_variable>
14 #include <deque>
15 #include <memory>
16 #include <mutex>
17 #include <queue>
18 #include <thread>
19 
20 #include "common/PackedEnums.h"
21 #include "common/PoolAlloc.h"
22 #include "common/angleutils.h"
23 #include "common/vulkan/vk_headers.h"
24 #include "common/vulkan/vulkan_icd.h"
25 #include "libANGLE/BlobCache.h"
26 #include "libANGLE/Caps.h"
27 #include "libANGLE/WorkerThread.h"
28 #include "libANGLE/renderer/vulkan/CommandProcessor.h"
29 #include "libANGLE/renderer/vulkan/DebugAnnotatorVk.h"
30 #include "libANGLE/renderer/vulkan/QueryVk.h"
31 #include "libANGLE/renderer/vulkan/ResourceVk.h"
32 #include "libANGLE/renderer/vulkan/UtilsVk.h"
33 #include "libANGLE/renderer/vulkan/vk_format_utils.h"
34 #include "libANGLE/renderer/vulkan/vk_helpers.h"
35 #include "libANGLE/renderer/vulkan/vk_internal_shaders_autogen.h"
36 #include "libANGLE/renderer/vulkan/vk_mem_alloc_wrapper.h"
37 
38 namespace angle
39 {
40 class Library;
41 }  // namespace angle
42 
43 namespace egl
44 {
45 class Display;
46 class BlobCache;
47 }  // namespace egl
48 
49 namespace rx
50 {
51 class DisplayVk;
52 class FramebufferVk;
53 
54 namespace vk
55 {
56 struct Format;
57 
58 static constexpr size_t kMaxExtensionNames = 400;
59 using ExtensionNameList                    = angle::FixedVector<const char *, kMaxExtensionNames>;
60 
61 // Process GPU memory reports
62 class MemoryReport final : angle::NonCopyable
63 {
64   public:
65     MemoryReport();
66     void processCallback(const VkDeviceMemoryReportCallbackDataEXT &callbackData, bool logCallback);
67     void logMemoryReportStats() const;
68 
69   private:
70     struct MemorySizes
71     {
72         VkDeviceSize allocatedMemory;
73         VkDeviceSize allocatedMemoryMax;
74         VkDeviceSize importedMemory;
75         VkDeviceSize importedMemoryMax;
76     };
77     mutable std::mutex mMemoryReportMutex;
78     VkDeviceSize mCurrentTotalAllocatedMemory;
79     VkDeviceSize mMaxTotalAllocatedMemory;
80     angle::HashMap<VkObjectType, MemorySizes> mSizesPerType;
81     VkDeviceSize mCurrentTotalImportedMemory;
82     VkDeviceSize mMaxTotalImportedMemory;
83     angle::HashMap<uint64_t, int> mUniqueIDCounts;
84 };
85 }  // namespace vk
86 
87 // Supports one semaphore from current surface, and one semaphore passed to
88 // glSignalSemaphoreEXT.
89 using SignalSemaphoreVector = angle::FixedVector<VkSemaphore, 2>;
90 
CollectGarbage(std::vector<vk::GarbageObject> * garbageOut)91 inline void CollectGarbage(std::vector<vk::GarbageObject> *garbageOut) {}
92 
93 template <typename ArgT, typename... ArgsT>
CollectGarbage(std::vector<vk::GarbageObject> * garbageOut,ArgT object,ArgsT...objectsIn)94 void CollectGarbage(std::vector<vk::GarbageObject> *garbageOut, ArgT object, ArgsT... objectsIn)
95 {
96     if (object->valid())
97     {
98         garbageOut->emplace_back(vk::GarbageObject::Get(object));
99     }
100     CollectGarbage(garbageOut, objectsIn...);
101 }
102 
103 class WaitableCompressEvent
104 {
105   public:
WaitableCompressEvent(std::shared_ptr<angle::WaitableEvent> waitableEvent)106     WaitableCompressEvent(std::shared_ptr<angle::WaitableEvent> waitableEvent)
107         : mWaitableEvent(waitableEvent)
108     {}
109 
~WaitableCompressEvent()110     virtual ~WaitableCompressEvent() {}
111 
wait()112     void wait() { return mWaitableEvent->wait(); }
113 
isReady()114     bool isReady() { return mWaitableEvent->isReady(); }
115 
116     virtual bool getResult() = 0;
117 
118   private:
119     std::shared_ptr<angle::WaitableEvent> mWaitableEvent;
120 };
121 
122 class RendererVk : angle::NonCopyable
123 {
124   public:
125     RendererVk();
126     ~RendererVk();
127 
128     angle::Result initialize(DisplayVk *displayVk,
129                              egl::Display *display,
130                              const char *wsiExtension,
131                              const char *wsiLayer);
132     // Reload volk vk* function ptrs if needed for an already initialized RendererVk
133     void reloadVolkIfNeeded() const;
134     void onDestroy(vk::Context *context);
135 
136     void notifyDeviceLost();
137     bool isDeviceLost() const;
138     bool hasSharedGarbage();
139     void releaseSharedResources(vk::ResourceUseList *resourceList);
140 
141     std::string getVendorString() const;
142     std::string getRendererDescription() const;
143     std::string getVersionString() const;
144 
145     gl::Version getMaxSupportedESVersion() const;
146     gl::Version getMaxConformantESVersion() const;
147 
getInstance()148     VkInstance getInstance() const { return mInstance; }
getPhysicalDevice()149     VkPhysicalDevice getPhysicalDevice() const { return mPhysicalDevice; }
getPhysicalDeviceProperties()150     const VkPhysicalDeviceProperties &getPhysicalDeviceProperties() const
151     {
152         return mPhysicalDeviceProperties;
153     }
getPhysicalDeviceSubgroupProperties()154     const VkPhysicalDeviceSubgroupProperties &getPhysicalDeviceSubgroupProperties() const
155     {
156         return mSubgroupProperties;
157     }
getPhysicalDeviceFeatures()158     const VkPhysicalDeviceFeatures &getPhysicalDeviceFeatures() const
159     {
160         return mPhysicalDeviceFeatures;
161     }
getDevice()162     VkDevice getDevice() const { return mDevice; }
163 
getAllocator()164     const vk::Allocator &getAllocator() const { return mAllocator; }
165 
166     angle::Result selectPresentQueueForSurface(DisplayVk *displayVk,
167                                                VkSurfaceKHR surface,
168                                                uint32_t *presentQueueOut);
169 
170     const gl::Caps &getNativeCaps() const;
171     const gl::TextureCapsMap &getNativeTextureCaps() const;
172     const gl::Extensions &getNativeExtensions() const;
173     const gl::Limitations &getNativeLimitations() const;
174 
getQueueFamilyIndex()175     uint32_t getQueueFamilyIndex() const { return mCurrentQueueFamilyIndex; }
getQueueFamilyProperties()176     const VkQueueFamilyProperties &getQueueFamilyProperties() const
177     {
178         return mQueueFamilyProperties[mCurrentQueueFamilyIndex];
179     }
180 
getMemoryProperties()181     const vk::MemoryProperties &getMemoryProperties() const { return mMemoryProperties; }
182 
getFormat(GLenum internalFormat)183     const vk::Format &getFormat(GLenum internalFormat) const
184     {
185         return mFormatTable[internalFormat];
186     }
187 
getFormat(angle::FormatID formatID)188     const vk::Format &getFormat(angle::FormatID formatID) const { return mFormatTable[formatID]; }
189 
190     angle::Result getPipelineCacheSize(DisplayVk *displayVk, size_t *pipelineCacheSizeOut);
191     angle::Result syncPipelineCacheVk(DisplayVk *displayVk, const gl::Context *context);
192 
193     // Issues a new serial for linked shader modules. Used in the pipeline cache.
194     Serial issueShaderSerial();
195 
getFeatures()196     const angle::FeaturesVk &getFeatures() const { return mFeatures; }
getMaxVertexAttribDivisor()197     uint32_t getMaxVertexAttribDivisor() const { return mMaxVertexAttribDivisor; }
getMaxVertexAttribStride()198     VkDeviceSize getMaxVertexAttribStride() const { return mMaxVertexAttribStride; }
199 
getMinImportedHostPointerAlignment()200     VkDeviceSize getMinImportedHostPointerAlignment() const
201     {
202         return mMinImportedHostPointerAlignment;
203     }
getDefaultUniformBufferSize()204     uint32_t getDefaultUniformBufferSize() const { return mDefaultUniformBufferSize; }
205 
isMockICDEnabled()206     bool isMockICDEnabled() const { return mEnabledICD == angle::vk::ICD::Mock; }
207 
208     // Query the format properties for select bits (linearTilingFeatures, optimalTilingFeatures and
209     // bufferFeatures).  Looks through mandatory features first, and falls back to querying the
210     // device (first time only).
211     bool hasLinearImageFormatFeatureBits(angle::FormatID format,
212                                          const VkFormatFeatureFlags featureBits) const;
213     VkFormatFeatureFlags getLinearImageFormatFeatureBits(
214         angle::FormatID format,
215         const VkFormatFeatureFlags featureBits) const;
216     VkFormatFeatureFlags getImageFormatFeatureBits(angle::FormatID format,
217                                                    const VkFormatFeatureFlags featureBits) const;
218     bool hasImageFormatFeatureBits(angle::FormatID format,
219                                    const VkFormatFeatureFlags featureBits) const;
220     bool hasBufferFormatFeatureBits(angle::FormatID format,
221                                     const VkFormatFeatureFlags featureBits) const;
222 
getDriverPriority(egl::ContextPriority priority)223     ANGLE_INLINE egl::ContextPriority getDriverPriority(egl::ContextPriority priority)
224     {
225         return mCommandQueue.getDriverPriority(priority);
226     }
227 
228     // This command buffer should be submitted immediately via queueSubmitOneOff.
229     angle::Result getCommandBufferOneOff(vk::Context *context,
230                                          bool hasProtectedContent,
231                                          vk::PrimaryCommandBuffer *commandBufferOut);
232 
233     // Fire off a single command buffer immediately with default priority.
234     // Command buffer must be allocated with getCommandBufferOneOff and is reclaimed.
235     angle::Result queueSubmitOneOff(vk::Context *context,
236                                     vk::PrimaryCommandBuffer &&primary,
237                                     bool hasProtectedContent,
238                                     egl::ContextPriority priority,
239                                     const vk::Fence *fence,
240                                     vk::SubmitPolicy submitPolicy,
241                                     Serial *serialOut);
242 
243     template <typename... ArgsT>
collectGarbageAndReinit(vk::SharedResourceUse * use,ArgsT...garbageIn)244     void collectGarbageAndReinit(vk::SharedResourceUse *use, ArgsT... garbageIn)
245     {
246         std::vector<vk::GarbageObject> sharedGarbage;
247         CollectGarbage(&sharedGarbage, garbageIn...);
248         if (!sharedGarbage.empty())
249         {
250             collectGarbage(std::move(*use), std::move(sharedGarbage));
251         }
252         else
253         {
254             // Force releasing "use" even if no garbage was created.
255             use->release();
256         }
257         // Keep "use" valid.
258         use->init();
259     }
260 
collectGarbage(vk::SharedResourceUse && use,std::vector<vk::GarbageObject> && sharedGarbage)261     void collectGarbage(vk::SharedResourceUse &&use, std::vector<vk::GarbageObject> &&sharedGarbage)
262     {
263         if (!sharedGarbage.empty())
264         {
265             std::lock_guard<std::mutex> lock(mGarbageMutex);
266             mSharedGarbage.emplace_back(std::move(use), std::move(sharedGarbage));
267         }
268     }
269 
270     angle::Result getPipelineCache(vk::PipelineCache **pipelineCache);
onNewGraphicsPipeline()271     void onNewGraphicsPipeline()
272     {
273         std::lock_guard<std::mutex> lock(mPipelineCacheMutex);
274         mPipelineCacheDirty = true;
275     }
276 
277     void onNewValidationMessage(const std::string &message);
278     std::string getAndClearLastValidationMessage(uint32_t *countSinceLastClear);
279 
280     uint64_t getMaxFenceWaitTimeNs() const;
281 
getCurrentQueueSerial()282     ANGLE_INLINE Serial getCurrentQueueSerial()
283     {
284         if (mFeatures.asyncCommandQueue.enabled)
285         {
286             return mCommandProcessor.getCurrentQueueSerial();
287         }
288         else
289         {
290             std::lock_guard<std::mutex> lock(mCommandQueueMutex);
291             return mCommandQueue.getCurrentQueueSerial();
292         }
293     }
294 
getLastSubmittedQueueSerial()295     ANGLE_INLINE Serial getLastSubmittedQueueSerial()
296     {
297         if (mFeatures.asyncCommandQueue.enabled)
298         {
299             return mCommandProcessor.getLastSubmittedQueueSerial();
300         }
301         else
302         {
303             std::lock_guard<std::mutex> lock(mCommandQueueMutex);
304             return mCommandQueue.getLastSubmittedQueueSerial();
305         }
306     }
307 
getLastCompletedQueueSerial()308     ANGLE_INLINE Serial getLastCompletedQueueSerial()
309     {
310         if (mFeatures.asyncCommandQueue.enabled)
311         {
312             return mCommandProcessor.getLastCompletedQueueSerial();
313         }
314         else
315         {
316             std::lock_guard<std::mutex> lock(mCommandQueueMutex);
317             return mCommandQueue.getLastCompletedQueueSerial();
318         }
319     }
320 
getDisplay()321     egl::Display *getDisplay() const { return mDisplay; }
322 
getLastPresentResult(VkSwapchainKHR swapchain)323     VkResult getLastPresentResult(VkSwapchainKHR swapchain)
324     {
325         return mCommandProcessor.getLastPresentResult(swapchain);
326     }
327 
enableDebugUtils()328     bool enableDebugUtils() const { return mEnableDebugUtils; }
angleDebuggerMode()329     bool angleDebuggerMode() const { return mAngleDebuggerMode; }
330 
getSamplerCache()331     SamplerCache &getSamplerCache() { return mSamplerCache; }
getYuvConversionCache()332     SamplerYcbcrConversionCache &getYuvConversionCache() { return mYuvConversionCache; }
getActiveHandleCounts()333     vk::ActiveHandleCounter &getActiveHandleCounts() { return mActiveHandleCounts; }
334 
getEnableValidationLayers()335     bool getEnableValidationLayers() const { return mEnableValidationLayers; }
336 
getResourceSerialFactory()337     vk::ResourceSerialFactory &getResourceSerialFactory() { return mResourceSerialFactory; }
338 
339     void setGlobalDebugAnnotator();
340 
341     void outputVmaStatString();
342 
343     bool haveSameFormatFeatureBits(angle::FormatID formatID1, angle::FormatID formatID2) const;
344 
345     angle::Result cleanupGarbage(Serial lastCompletedQueueSerial);
346     void cleanupCompletedCommandsGarbage();
347 
348     angle::Result submitFrame(vk::Context *context,
349                               bool hasProtectedContent,
350                               egl::ContextPriority contextPriority,
351                               std::vector<VkSemaphore> &&waitSemaphores,
352                               std::vector<VkPipelineStageFlags> &&waitSemaphoreStageMasks,
353                               const vk::Semaphore *signalSemaphore,
354                               std::vector<vk::ResourceUseList> &&resourceUseLists,
355                               vk::GarbageList &&currentGarbage,
356                               vk::CommandPool *commandPool);
357 
358     void handleDeviceLost();
359     angle::Result finishToSerial(vk::Context *context, Serial serial);
360     angle::Result waitForSerialWithUserTimeout(vk::Context *context,
361                                                Serial serial,
362                                                uint64_t timeout,
363                                                VkResult *result);
364     angle::Result finish(vk::Context *context, bool hasProtectedContent);
365     angle::Result checkCompletedCommands(vk::Context *context);
366 
367     angle::Result flushRenderPassCommands(vk::Context *context,
368                                           bool hasProtectedContent,
369                                           const vk::RenderPass &renderPass,
370                                           vk::CommandBufferHelper **renderPassCommands);
371     angle::Result flushOutsideRPCommands(vk::Context *context,
372                                          bool hasProtectedContent,
373                                          vk::CommandBufferHelper **outsideRPCommands);
374 
375     VkResult queuePresent(vk::Context *context,
376                           egl::ContextPriority priority,
377                           const VkPresentInfoKHR &presentInfo);
378 
379     vk::CommandBufferHelper *getCommandBufferHelper(bool hasRenderPass);
380     void recycleCommandBufferHelper(vk::CommandBufferHelper *commandBuffer);
381 
382     // Process GPU memory reports
processMemoryReportCallback(const VkDeviceMemoryReportCallbackDataEXT & callbackData)383     void processMemoryReportCallback(const VkDeviceMemoryReportCallbackDataEXT &callbackData)
384     {
385         bool logCallback = getFeatures().logMemoryReportCallbacks.enabled;
386         mMemoryReport.processCallback(callbackData, logCallback);
387     }
388 
389     // Accumulate cache stats for a specific cache
accumulateCacheStats(VulkanCacheType cache,const CacheStats & stats)390     void accumulateCacheStats(VulkanCacheType cache, const CacheStats &stats)
391     {
392         mVulkanCacheStats[cache].accumulate(stats);
393     }
394     // Log cache stats for all caches
395     void logCacheStats() const;
396 
getSupportedVulkanPipelineStageMask()397     VkPipelineStageFlags getSupportedVulkanPipelineStageMask() const
398     {
399         return mSupportedVulkanPipelineStageMask;
400     }
401 
402     angle::Result getFormatDescriptorCountForVkFormat(ContextVk *contextVk,
403                                                       VkFormat format,
404                                                       uint32_t *descriptorCountOut);
405 
406     angle::Result getFormatDescriptorCountForExternalFormat(ContextVk *contextVk,
407                                                             uint64_t format,
408                                                             uint32_t *descriptorCountOut);
409 
410   private:
411     angle::Result initializeDevice(DisplayVk *displayVk, uint32_t queueFamilyIndex);
412     void ensureCapsInitialized() const;
413 
414     void queryDeviceExtensionFeatures(const vk::ExtensionNameList &deviceExtensionNames);
415 
416     void initFeatures(DisplayVk *display, const vk::ExtensionNameList &extensions);
417     angle::Result initPipelineCache(DisplayVk *display,
418                                     vk::PipelineCache *pipelineCache,
419                                     bool *success);
420 
421     template <VkFormatFeatureFlags VkFormatProperties::*features>
422     VkFormatFeatureFlags getFormatFeatureBits(angle::FormatID formatID,
423                                               const VkFormatFeatureFlags featureBits) const;
424 
425     template <VkFormatFeatureFlags VkFormatProperties::*features>
426     bool hasFormatFeatureBits(angle::FormatID formatID,
427                               const VkFormatFeatureFlags featureBits) const;
428 
429     egl::Display *mDisplay;
430 
431     std::unique_ptr<angle::Library> mLibVulkanLibrary;
432 
433     mutable bool mCapsInitialized;
434     mutable gl::Caps mNativeCaps;
435     mutable gl::TextureCapsMap mNativeTextureCaps;
436     mutable gl::Extensions mNativeExtensions;
437     mutable gl::Limitations mNativeLimitations;
438     mutable angle::FeaturesVk mFeatures;
439 
440     VkInstance mInstance;
441     bool mEnableValidationLayers;
442     // True if ANGLE is enabling the VK_EXT_debug_utils extension.
443     bool mEnableDebugUtils;
444     // True if ANGLE should call the vkCmd*DebugUtilsLabelEXT functions in order to communicate to
445     // debuggers (e.g. AGI) the OpenGL ES commands that the application uses.  This is independent
446     // of mEnableDebugUtils, as an external graphics debugger can enable the VK_EXT_debug_utils
447     // extension and cause this to be set true.
448     bool mAngleDebuggerMode;
449     angle::vk::ICD mEnabledICD;
450     VkDebugUtilsMessengerEXT mDebugUtilsMessenger;
451     VkDebugReportCallbackEXT mDebugReportCallback;
452     VkPhysicalDevice mPhysicalDevice;
453     VkPhysicalDeviceProperties mPhysicalDeviceProperties;
454     VkPhysicalDeviceFeatures mPhysicalDeviceFeatures;
455     VkPhysicalDeviceLineRasterizationFeaturesEXT mLineRasterizationFeatures;
456     VkPhysicalDeviceProvokingVertexFeaturesEXT mProvokingVertexFeatures;
457     VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT mVertexAttributeDivisorFeatures;
458     VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT mVertexAttributeDivisorProperties;
459     VkPhysicalDeviceTransformFeedbackFeaturesEXT mTransformFeedbackFeatures;
460     VkPhysicalDeviceIndexTypeUint8FeaturesEXT mIndexTypeUint8Features;
461     VkPhysicalDeviceSubgroupProperties mSubgroupProperties;
462     VkPhysicalDeviceDeviceMemoryReportFeaturesEXT mMemoryReportFeatures;
463     VkDeviceDeviceMemoryReportCreateInfoEXT mMemoryReportCallback;
464     VkPhysicalDeviceExternalMemoryHostPropertiesEXT mExternalMemoryHostProperties;
465     VkPhysicalDeviceShaderFloat16Int8FeaturesKHR mShaderFloat16Int8Features;
466     VkPhysicalDeviceDepthStencilResolvePropertiesKHR mDepthStencilResolveProperties;
467     VkPhysicalDeviceMultisampledRenderToSingleSampledFeaturesEXT
468         mMultisampledRenderToSingleSampledFeatures;
469     VkPhysicalDeviceMultiviewFeatures mMultiviewFeatures;
470     VkPhysicalDeviceMultiviewProperties mMultiviewProperties;
471     VkPhysicalDeviceDriverPropertiesKHR mDriverProperties;
472     VkPhysicalDeviceCustomBorderColorFeaturesEXT mCustomBorderColorFeatures;
473     VkPhysicalDeviceProtectedMemoryFeatures mProtectedMemoryFeatures;
474     VkPhysicalDeviceProtectedMemoryProperties mProtectedMemoryProperties;
475     VkExternalFenceProperties mExternalFenceProperties;
476     VkExternalSemaphoreProperties mExternalSemaphoreProperties;
477     VkPhysicalDeviceSamplerYcbcrConversionFeatures mSamplerYcbcrConversionFeatures;
478     std::vector<VkQueueFamilyProperties> mQueueFamilyProperties;
479     uint32_t mMaxVertexAttribDivisor;
480     uint32_t mCurrentQueueFamilyIndex;
481     VkDeviceSize mMaxVertexAttribStride;
482     VkDeviceSize mMinImportedHostPointerAlignment;
483     uint32_t mDefaultUniformBufferSize;
484     VkDevice mDevice;
485     AtomicSerialFactory mShaderSerialFactory;
486 
487     bool mDeviceLost;
488 
489     std::mutex mGarbageMutex;
490     vk::SharedGarbageList mSharedGarbage;
491 
492     vk::MemoryProperties mMemoryProperties;
493     vk::FormatTable mFormatTable;
494 
495     // All access to the pipeline cache is done through EGL objects so it is thread safe to not use
496     // a lock.
497     std::mutex mPipelineCacheMutex;
498     vk::PipelineCache mPipelineCache;
499     uint32_t mPipelineCacheVkUpdateTimeout;
500     bool mPipelineCacheDirty;
501     bool mPipelineCacheInitialized;
502 
503     // A cache of VkFormatProperties as queried from the device over time.
504     mutable angle::FormatMap<VkFormatProperties> mFormatProperties;
505 
506     // Latest validation data for debug overlay.
507     std::string mLastValidationMessage;
508     uint32_t mValidationMessageCount;
509 
510     DebugAnnotatorVk mAnnotator;
511 
512     // How close to VkPhysicalDeviceLimits::maxMemoryAllocationCount we allow ourselves to get
513     static constexpr double kPercentMaxMemoryAllocationCount = 0.3;
514     // How many objects to garbage collect before issuing a flush()
515     uint32_t mGarbageCollectionFlushThreshold;
516 
517     // Only used for "one off" command buffers.
518     vk::CommandPool mOneOffCommandPool;
519 
520     struct PendingOneOffCommands
521     {
522         Serial serial;
523         vk::PrimaryCommandBuffer commandBuffer;
524     };
525     std::deque<PendingOneOffCommands> mPendingOneOffCommands;
526 
527     std::mutex mCommandQueueMutex;
528     vk::CommandQueue mCommandQueue;
529 
530     // Command buffer pool management.
531     std::mutex mCommandBufferHelperFreeListMutex;
532     std::vector<vk::CommandBufferHelper *> mCommandBufferHelperFreeList;
533 
534     // Async Command Queue
535     vk::CommandProcessor mCommandProcessor;
536 
537     vk::Allocator mAllocator;
538     SamplerCache mSamplerCache;
539     SamplerYcbcrConversionCache mYuvConversionCache;
540     angle::HashMap<VkFormat, uint32_t> mVkFormatDescriptorCountMap;
541     vk::ActiveHandleCounter mActiveHandleCounts;
542 
543     // Tracks resource serials.
544     vk::ResourceSerialFactory mResourceSerialFactory;
545 
546     // Process GPU memory reports
547     vk::MemoryReport mMemoryReport;
548 
549     // Stats about all Vulkan object caches
550     using VulkanCacheStats = angle::PackedEnumMap<VulkanCacheType, CacheStats>;
551     VulkanCacheStats mVulkanCacheStats;
552 
553     // A mask to filter out Vulkan pipeline stages that are not supported, applied in situations
554     // where multiple stages are prespecified (for example with image layout transitions):
555     //
556     // - Excludes GEOMETRY if geometry shaders are not supported.
557     // - Excludes TESSELLATION_CONTROL and TESSELLATION_EVALUATION if tessellation shaders are not
558     //   supported.
559     //
560     // Note that this mask can have bits set that don't correspond to valid stages, so it's strictly
561     // only useful for masking out unsupported stages in an otherwise valid set of stages.
562     VkPipelineStageFlags mSupportedVulkanPipelineStageMask;
563 
564     // Use thread pool to compress cache data.
565     std::shared_ptr<rx::WaitableCompressEvent> mCompressEvent;
566 };
567 
568 }  // namespace rx
569 
570 #endif  // LIBANGLE_RENDERER_VULKAN_RENDERERVK_H_
571