• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 struct FrontendFeatures;
42 }  // namespace angle
43 
44 namespace egl
45 {
46 class Display;
47 class BlobCache;
48 }  // namespace egl
49 
50 namespace rx
51 {
52 class DisplayVk;
53 class FramebufferVk;
54 
55 namespace vk
56 {
57 class Format;
58 
59 static constexpr size_t kMaxExtensionNames = 400;
60 using ExtensionNameList                    = angle::FixedVector<const char *, kMaxExtensionNames>;
61 
62 // Process GPU memory reports
63 class MemoryReport final : angle::NonCopyable
64 {
65   public:
66     MemoryReport();
67     void processCallback(const VkDeviceMemoryReportCallbackDataEXT &callbackData, bool logCallback);
68     void logMemoryReportStats() const;
69 
70   private:
71     struct MemorySizes
72     {
73         VkDeviceSize allocatedMemory;
74         VkDeviceSize allocatedMemoryMax;
75         VkDeviceSize importedMemory;
76         VkDeviceSize importedMemoryMax;
77     };
78     mutable std::mutex mMemoryReportMutex;
79     VkDeviceSize mCurrentTotalAllocatedMemory;
80     VkDeviceSize mMaxTotalAllocatedMemory;
81     angle::HashMap<VkObjectType, MemorySizes> mSizesPerType;
82     VkDeviceSize mCurrentTotalImportedMemory;
83     VkDeviceSize mMaxTotalImportedMemory;
84     angle::HashMap<uint64_t, int> mUniqueIDCounts;
85 };
86 }  // namespace vk
87 
88 // Supports one semaphore from current surface, and one semaphore passed to
89 // glSignalSemaphoreEXT.
90 using SignalSemaphoreVector = angle::FixedVector<VkSemaphore, 2>;
91 
CollectGarbage(std::vector<vk::GarbageObject> * garbageOut)92 inline void CollectGarbage(std::vector<vk::GarbageObject> *garbageOut) {}
93 
94 template <typename ArgT, typename... ArgsT>
CollectGarbage(std::vector<vk::GarbageObject> * garbageOut,ArgT object,ArgsT...objectsIn)95 void CollectGarbage(std::vector<vk::GarbageObject> *garbageOut, ArgT object, ArgsT... objectsIn)
96 {
97     if (object->valid())
98     {
99         garbageOut->emplace_back(vk::GarbageObject::Get(object));
100     }
101     CollectGarbage(garbageOut, objectsIn...);
102 }
103 
104 class WaitableCompressEvent
105 {
106   public:
WaitableCompressEvent(std::shared_ptr<angle::WaitableEvent> waitableEvent)107     WaitableCompressEvent(std::shared_ptr<angle::WaitableEvent> waitableEvent)
108         : mWaitableEvent(waitableEvent)
109     {}
110 
~WaitableCompressEvent()111     virtual ~WaitableCompressEvent() {}
112 
wait()113     void wait() { return mWaitableEvent->wait(); }
114 
isReady()115     bool isReady() { return mWaitableEvent->isReady(); }
116 
117     virtual bool getResult() = 0;
118 
119   private:
120     std::shared_ptr<angle::WaitableEvent> mWaitableEvent;
121 };
122 
123 class RendererVk : angle::NonCopyable
124 {
125   public:
126     RendererVk();
127     ~RendererVk();
128 
129     angle::Result initialize(DisplayVk *displayVk,
130                              egl::Display *display,
131                              const char *wsiExtension,
132                              const char *wsiLayer);
133     // Reload volk vk* function ptrs if needed for an already initialized RendererVk
134     void reloadVolkIfNeeded() const;
135     void onDestroy(vk::Context *context);
136 
137     void notifyDeviceLost();
138     bool isDeviceLost() const;
139     bool hasSharedGarbage();
140     void releaseSharedResources(vk::ResourceUseList *resourceList);
141 
142     std::string getVendorString() const;
143     std::string getRendererDescription() const;
144     std::string getVersionString(bool includeFullVersion) const;
145 
146     gl::Version getMaxSupportedESVersion() const;
147     gl::Version getMaxConformantESVersion() const;
148 
getApiVersion()149     uint32_t getApiVersion() const { return mApiVersion; }
getInstance()150     VkInstance getInstance() const { return mInstance; }
getPhysicalDevice()151     VkPhysicalDevice getPhysicalDevice() const { return mPhysicalDevice; }
getPhysicalDeviceProperties()152     const VkPhysicalDeviceProperties &getPhysicalDeviceProperties() const
153     {
154         return mPhysicalDeviceProperties;
155     }
getPhysicalDeviceSubgroupProperties()156     const VkPhysicalDeviceSubgroupProperties &getPhysicalDeviceSubgroupProperties() const
157     {
158         return mSubgroupProperties;
159     }
getPhysicalDeviceFeatures()160     const VkPhysicalDeviceFeatures &getPhysicalDeviceFeatures() const
161     {
162         return mPhysicalDeviceFeatures;
163     }
getEnabledFeatures()164     const VkPhysicalDeviceFeatures2KHR &getEnabledFeatures() const { return mEnabledFeatures; }
getDevice()165     VkDevice getDevice() const { return mDevice; }
166 
getAllocator()167     const vk::Allocator &getAllocator() const { return mAllocator; }
168 
169     angle::Result selectPresentQueueForSurface(DisplayVk *displayVk,
170                                                VkSurfaceKHR surface,
171                                                uint32_t *presentQueueOut);
172 
173     const gl::Caps &getNativeCaps() const;
174     const gl::TextureCapsMap &getNativeTextureCaps() const;
175     const gl::Extensions &getNativeExtensions() const;
176     const gl::Limitations &getNativeLimitations() const;
177     void initializeFrontendFeatures(angle::FrontendFeatures *features) const;
178 
getQueueFamilyIndex()179     uint32_t getQueueFamilyIndex() const { return mCurrentQueueFamilyIndex; }
getQueueFamilyProperties()180     const VkQueueFamilyProperties &getQueueFamilyProperties() const
181     {
182         return mQueueFamilyProperties[mCurrentQueueFamilyIndex];
183     }
184 
getMemoryProperties()185     const vk::MemoryProperties &getMemoryProperties() const { return mMemoryProperties; }
186 
getFormat(GLenum internalFormat)187     const vk::Format &getFormat(GLenum internalFormat) const
188     {
189         return mFormatTable[internalFormat];
190     }
191 
getFormat(angle::FormatID formatID)192     const vk::Format &getFormat(angle::FormatID formatID) const { return mFormatTable[formatID]; }
193 
194     angle::Result getPipelineCacheSize(DisplayVk *displayVk, size_t *pipelineCacheSizeOut);
195     angle::Result syncPipelineCacheVk(DisplayVk *displayVk, const gl::Context *context);
196 
197     // Issues a new serial for linked shader modules. Used in the pipeline cache.
198     Serial issueShaderSerial();
199 
getFeatures()200     const angle::FeaturesVk &getFeatures() const { return mFeatures; }
getMaxVertexAttribDivisor()201     uint32_t getMaxVertexAttribDivisor() const { return mMaxVertexAttribDivisor; }
getMaxVertexAttribStride()202     VkDeviceSize getMaxVertexAttribStride() const { return mMaxVertexAttribStride; }
203 
getMinImportedHostPointerAlignment()204     VkDeviceSize getMinImportedHostPointerAlignment() const
205     {
206         return mMinImportedHostPointerAlignment;
207     }
getDefaultUniformBufferSize()208     uint32_t getDefaultUniformBufferSize() const { return mDefaultUniformBufferSize; }
209 
getEnabledICD()210     angle::vk::ICD getEnabledICD() const { return mEnabledICD; }
isMockICDEnabled()211     bool isMockICDEnabled() const { return mEnabledICD == angle::vk::ICD::Mock; }
212 
213     // Query the format properties for select bits (linearTilingFeatures, optimalTilingFeatures and
214     // bufferFeatures).  Looks through mandatory features first, and falls back to querying the
215     // device (first time only).
216     bool hasLinearImageFormatFeatureBits(angle::FormatID format,
217                                          const VkFormatFeatureFlags featureBits) const;
218     VkFormatFeatureFlags getLinearImageFormatFeatureBits(
219         angle::FormatID format,
220         const VkFormatFeatureFlags featureBits) const;
221     VkFormatFeatureFlags getImageFormatFeatureBits(angle::FormatID format,
222                                                    const VkFormatFeatureFlags featureBits) const;
223     bool hasImageFormatFeatureBits(angle::FormatID format,
224                                    const VkFormatFeatureFlags featureBits) const;
225     bool hasBufferFormatFeatureBits(angle::FormatID format,
226                                     const VkFormatFeatureFlags featureBits) const;
227 
isAsyncCommandQueueEnabled()228     bool isAsyncCommandQueueEnabled() const { return mFeatures.asyncCommandQueue.enabled; }
229 
getDriverPriority(egl::ContextPriority priority)230     ANGLE_INLINE egl::ContextPriority getDriverPriority(egl::ContextPriority priority)
231     {
232         if (isAsyncCommandQueueEnabled())
233         {
234             return mCommandProcessor.getDriverPriority(priority);
235         }
236         else
237         {
238             return mCommandQueue.getDriverPriority(priority);
239         }
240     }
getDeviceQueueIndex()241     ANGLE_INLINE uint32_t getDeviceQueueIndex()
242     {
243         if (isAsyncCommandQueueEnabled())
244         {
245             return mCommandProcessor.getDeviceQueueIndex();
246         }
247         else
248         {
249             return mCommandQueue.getDeviceQueueIndex();
250         }
251     }
252 
getQueue(egl::ContextPriority priority)253     VkQueue getQueue(egl::ContextPriority priority)
254     {
255         if (isAsyncCommandQueueEnabled())
256         {
257             return mCommandProcessor.getQueue(priority);
258         }
259         else
260         {
261             return mCommandQueue.getQueue(priority);
262         }
263     }
264 
265     // This command buffer should be submitted immediately via queueSubmitOneOff.
266     angle::Result getCommandBufferOneOff(vk::Context *context,
267                                          bool hasProtectedContent,
268                                          vk::PrimaryCommandBuffer *commandBufferOut);
269 
resetOutsideRenderPassCommandBuffer(vk::OutsideRenderPassCommandBuffer && commandBuffer)270     void resetOutsideRenderPassCommandBuffer(vk::OutsideRenderPassCommandBuffer &&commandBuffer)
271     {
272         mOutsideRenderPassCommandBufferRecycler.resetCommandBuffer(std::move(commandBuffer));
273     }
274 
resetRenderPassCommandBuffer(vk::RenderPassCommandBuffer && commandBuffer)275     void resetRenderPassCommandBuffer(vk::RenderPassCommandBuffer &&commandBuffer)
276     {
277         mRenderPassCommandBufferRecycler.resetCommandBuffer(std::move(commandBuffer));
278     }
279 
280     // Fire off a single command buffer immediately with default priority.
281     // Command buffer must be allocated with getCommandBufferOneOff and is reclaimed.
282     angle::Result queueSubmitOneOff(vk::Context *context,
283                                     vk::PrimaryCommandBuffer &&primary,
284                                     bool hasProtectedContent,
285                                     egl::ContextPriority priority,
286                                     const vk::Semaphore *waitSemaphore,
287                                     VkPipelineStageFlags waitSemaphoreStageMasks,
288                                     const vk::Fence *fence,
289                                     vk::SubmitPolicy submitPolicy,
290                                     Serial *serialOut);
291 
292     template <typename... ArgsT>
collectGarbageAndReinit(vk::SharedResourceUse * use,ArgsT...garbageIn)293     void collectGarbageAndReinit(vk::SharedResourceUse *use, ArgsT... garbageIn)
294     {
295         std::vector<vk::GarbageObject> sharedGarbage;
296         CollectGarbage(&sharedGarbage, garbageIn...);
297         if (!sharedGarbage.empty())
298         {
299             collectGarbage(std::move(*use), std::move(sharedGarbage));
300         }
301         else
302         {
303             // Force releasing "use" even if no garbage was created.
304             use->release();
305         }
306         // Keep "use" valid.
307         use->init();
308     }
309 
collectGarbage(vk::SharedResourceUse && use,std::vector<vk::GarbageObject> && sharedGarbage)310     void collectGarbage(vk::SharedResourceUse &&use, std::vector<vk::GarbageObject> &&sharedGarbage)
311     {
312         if (!sharedGarbage.empty())
313         {
314             vk::SharedGarbage garbage(std::move(use), std::move(sharedGarbage));
315             if (garbage.usedInRecordedCommands())
316             {
317                 std::lock_guard<std::mutex> lock(mGarbageMutex);
318                 mPendingSubmissionGarbage.push(std::move(garbage));
319             }
320             else if (!garbage.destroyIfComplete(this, getLastCompletedQueueSerial()))
321             {
322                 std::lock_guard<std::mutex> lock(mGarbageMutex);
323                 mSharedGarbage.push(std::move(garbage));
324             }
325         }
326     }
327 
collectSuballocationGarbage(vk::SharedResourceUse && use,vk::BufferSuballocation && suballocation,vk::Buffer && buffer)328     void collectSuballocationGarbage(vk::SharedResourceUse &&use,
329                                      vk::BufferSuballocation &&suballocation,
330                                      vk::Buffer &&buffer)
331     {
332         std::lock_guard<std::mutex> lock(mGarbageMutex);
333         if (use.usedInRecordedCommands())
334         {
335             mPendingSubmissionSuballocationGarbage.emplace(std::move(use), std::move(suballocation),
336                                                            std::move(buffer));
337         }
338         else
339         {
340             mSuballocationGarbage.emplace(std::move(use), std::move(suballocation),
341                                           std::move(buffer));
342         }
343     }
344 
345     angle::Result getPipelineCache(vk::PipelineCache **pipelineCache);
onNewGraphicsPipeline()346     void onNewGraphicsPipeline()
347     {
348         std::lock_guard<std::mutex> lock(mPipelineCacheMutex);
349         mPipelineCacheDirty = true;
350     }
351 
352     void onNewValidationMessage(const std::string &message);
353     std::string getAndClearLastValidationMessage(uint32_t *countSinceLastClear);
354 
355     void onFramebufferFetchUsed();
isFramebufferFetchUsed()356     bool isFramebufferFetchUsed() const { return mIsFramebufferFetchUsed; }
357 
358     uint64_t getMaxFenceWaitTimeNs() const;
359 
getLastCompletedQueueSerial()360     ANGLE_INLINE Serial getLastCompletedQueueSerial()
361     {
362         if (isAsyncCommandQueueEnabled())
363         {
364             return mCommandProcessor.getLastCompletedQueueSerial();
365         }
366         else
367         {
368             vk::ScopedCommandQueueLock lock(this, mCommandQueueMutex);
369             return mCommandQueue.getLastCompletedQueueSerial();
370         }
371     }
372 
isCommandQueueBusy()373     ANGLE_INLINE bool isCommandQueueBusy()
374     {
375         vk::ScopedCommandQueueLock lock(this, mCommandQueueMutex);
376         if (isAsyncCommandQueueEnabled())
377         {
378             return mCommandProcessor.isBusy();
379         }
380         else
381         {
382             return mCommandQueue.isBusy();
383         }
384     }
385 
ensureNoPendingWork(vk::Context * context)386     angle::Result ensureNoPendingWork(vk::Context *context)
387     {
388         if (isAsyncCommandQueueEnabled())
389         {
390             return mCommandProcessor.ensureNoPendingWork(context);
391         }
392         else
393         {
394             return mCommandQueue.ensureNoPendingWork(context);
395         }
396     }
397 
getDisplay()398     egl::Display *getDisplay() const { return mDisplay; }
399 
getLastPresentResult(VkSwapchainKHR swapchain)400     VkResult getLastPresentResult(VkSwapchainKHR swapchain)
401     {
402         return mCommandProcessor.getLastPresentResult(swapchain);
403     }
404 
enableDebugUtils()405     bool enableDebugUtils() const { return mEnableDebugUtils; }
angleDebuggerMode()406     bool angleDebuggerMode() const { return mAngleDebuggerMode; }
407 
getSamplerCache()408     SamplerCache &getSamplerCache() { return mSamplerCache; }
getYuvConversionCache()409     SamplerYcbcrConversionCache &getYuvConversionCache() { return mYuvConversionCache; }
410 
411     void onAllocateHandle(vk::HandleType handleType);
412     void onDeallocateHandle(vk::HandleType handleType);
413 
getEnableValidationLayers()414     bool getEnableValidationLayers() const { return mEnableValidationLayers; }
415 
getResourceSerialFactory()416     vk::ResourceSerialFactory &getResourceSerialFactory() { return mResourceSerialFactory; }
417 
418     void setGlobalDebugAnnotator();
419 
420     void outputVmaStatString();
421 
422     bool haveSameFormatFeatureBits(angle::FormatID formatID1, angle::FormatID formatID2) const;
423 
424     angle::Result cleanupGarbage(Serial lastCompletedQueueSerial);
425     void cleanupCompletedCommandsGarbage();
426     void cleanupPendingSubmissionGarbage();
427 
428     angle::Result submitFrame(vk::Context *context,
429                               bool hasProtectedContent,
430                               egl::ContextPriority contextPriority,
431                               std::vector<VkSemaphore> &&waitSemaphores,
432                               std::vector<VkPipelineStageFlags> &&waitSemaphoreStageMasks,
433                               const vk::Semaphore *signalSemaphore,
434                               vk::GarbageList &&currentGarbage,
435                               vk::SecondaryCommandPools *commandPools,
436                               Serial *submitSerialOut);
437 
438     // When the device is lost, the commands queue is cleaned up.  This shouldn't be done
439     // immediately if the device loss is generated from the command queue itself (due to mutual
440     // exclusion requirements).
441     //
442     // - handleDeviceLost() defers device loss handling if the mutex is already taken
443     // - ScopedCommandQueueLock handles device loss at the end of the scope (i.e. when the command
444     //   queue operation is finished) by calling handleDeviceLostNoLock() before releasing the lock.
445     void handleDeviceLost();
446     void handleDeviceLostNoLock();
447     angle::Result finishToSerial(vk::Context *context, Serial serial);
448     angle::Result waitForSerialWithUserTimeout(vk::Context *context,
449                                                Serial serial,
450                                                uint64_t timeout,
451                                                VkResult *result);
452     angle::Result finish(vk::Context *context, bool hasProtectedContent);
453     angle::Result checkCompletedCommands(vk::Context *context);
454 
455     angle::Result flushRenderPassCommands(vk::Context *context,
456                                           bool hasProtectedContent,
457                                           const vk::RenderPass &renderPass,
458                                           vk::RenderPassCommandBufferHelper **renderPassCommands);
459     angle::Result flushOutsideRPCommands(
460         vk::Context *context,
461         bool hasProtectedContent,
462         vk::OutsideRenderPassCommandBufferHelper **outsideRPCommands);
463 
464     VkResult queuePresent(vk::Context *context,
465                           egl::ContextPriority priority,
466                           const VkPresentInfoKHR &presentInfo);
467 
468     angle::Result getOutsideRenderPassCommandBufferHelper(
469         vk::Context *context,
470         vk::CommandPool *commandPool,
471         vk::OutsideRenderPassCommandBufferHelper **commandBufferHelperOut);
472     angle::Result getRenderPassCommandBufferHelper(
473         vk::Context *context,
474         vk::CommandPool *commandPool,
475         vk::RenderPassCommandBufferHelper **commandBufferHelperOut);
476 
477     void recycleOutsideRenderPassCommandBufferHelper(
478         VkDevice device,
479         vk::OutsideRenderPassCommandBufferHelper **commandBuffer);
480     void recycleRenderPassCommandBufferHelper(VkDevice device,
481                                               vk::RenderPassCommandBufferHelper **commandBuffer);
482 
483     // Process GPU memory reports
processMemoryReportCallback(const VkDeviceMemoryReportCallbackDataEXT & callbackData)484     void processMemoryReportCallback(const VkDeviceMemoryReportCallbackDataEXT &callbackData)
485     {
486         bool logCallback = getFeatures().logMemoryReportCallbacks.enabled;
487         mMemoryReport.processCallback(callbackData, logCallback);
488     }
489 
490     // Accumulate cache stats for a specific cache
accumulateCacheStats(VulkanCacheType cache,const CacheStats & stats)491     void accumulateCacheStats(VulkanCacheType cache, const CacheStats &stats)
492     {
493         std::lock_guard<std::mutex> localLock(mCacheStatsMutex);
494         mVulkanCacheStats[cache].accumulate(stats);
495     }
496     // Log cache stats for all caches
497     void logCacheStats() const;
498 
getSupportedVulkanPipelineStageMask()499     VkPipelineStageFlags getSupportedVulkanPipelineStageMask() const
500     {
501         return mSupportedVulkanPipelineStageMask;
502     }
503 
504     angle::Result getFormatDescriptorCountForVkFormat(ContextVk *contextVk,
505                                                       VkFormat format,
506                                                       uint32_t *descriptorCountOut);
507 
508     angle::Result getFormatDescriptorCountForExternalFormat(ContextVk *contextVk,
509                                                             uint64_t format,
510                                                             uint32_t *descriptorCountOut);
511 
getMaxCopyBytesUsingCPUWhenPreservingBufferData()512     VkDeviceSize getMaxCopyBytesUsingCPUWhenPreservingBufferData() const
513     {
514         return mMaxCopyBytesUsingCPUWhenPreservingBufferData;
515     }
516 
getEnabledInstanceExtensions()517     const vk::ExtensionNameList &getEnabledInstanceExtensions() const
518     {
519         return mEnabledInstanceExtensions;
520     }
521 
getEnabledDeviceExtensions()522     const vk::ExtensionNameList &getEnabledDeviceExtensions() const
523     {
524         return mEnabledDeviceExtensions;
525     }
526 
527     VkDeviceSize getPreferedBufferBlockSize(uint32_t memoryTypeIndex) const;
528 
getDefaultBufferAlignment()529     size_t getDefaultBufferAlignment() const { return mDefaultBufferAlignment; }
530 
getStagingBufferMemoryTypeIndex(vk::MemoryCoherency coherency)531     uint32_t getStagingBufferMemoryTypeIndex(vk::MemoryCoherency coherency) const
532     {
533         return coherency == vk::MemoryCoherency::Coherent
534                    ? mCoherentStagingBufferMemoryTypeIndex
535                    : mNonCoherentStagingBufferMemoryTypeIndex;
536     }
getStagingBufferAlignment()537     size_t getStagingBufferAlignment() const { return mStagingBufferAlignment; }
538 
getVertexConversionBufferMemoryTypeIndex(vk::MemoryHostVisibility hostVisibility)539     uint32_t getVertexConversionBufferMemoryTypeIndex(vk::MemoryHostVisibility hostVisibility) const
540     {
541         return hostVisibility == vk::MemoryHostVisibility::Visible
542                    ? mHostVisibleVertexConversionBufferMemoryTypeIndex
543                    : mDeviceLocalVertexConversionBufferMemoryTypeIndex;
544     }
getVertexConversionBufferAlignment()545     size_t getVertexConversionBufferAlignment() const { return mVertexConversionBufferAlignment; }
546 
getDeviceLocalMemoryTypeIndex()547     uint32_t getDeviceLocalMemoryTypeIndex() const
548     {
549         return mDeviceLocalVertexConversionBufferMemoryTypeIndex;
550     }
551 
552     void addBufferBlockToOrphanList(vk::BufferBlock *block);
553     void pruneOrphanedBufferBlocks();
554 
555   private:
556     angle::Result initializeDevice(DisplayVk *displayVk, uint32_t queueFamilyIndex);
557     void ensureCapsInitialized() const;
558 
559     void queryDeviceExtensionFeatures(const vk::ExtensionNameList &deviceExtensionNames);
560 
561     void initFeatures(DisplayVk *display, const vk::ExtensionNameList &extensions);
562     void appBasedFeatureOverrides(DisplayVk *display, const vk::ExtensionNameList &extensions);
563     angle::Result initPipelineCache(DisplayVk *display,
564                                     vk::PipelineCache *pipelineCache,
565                                     bool *success);
566 
567     template <VkFormatFeatureFlags VkFormatProperties::*features>
568     VkFormatFeatureFlags getFormatFeatureBits(angle::FormatID formatID,
569                                               const VkFormatFeatureFlags featureBits) const;
570 
571     template <VkFormatFeatureFlags VkFormatProperties::*features>
572     bool hasFormatFeatureBits(angle::FormatID formatID,
573                               const VkFormatFeatureFlags featureBits) const;
574 
575     // Initialize VMA allocator and buffer suballocator related data.
576     angle::Result initializeMemoryAllocator(DisplayVk *displayVk);
577 
578     egl::Display *mDisplay;
579 
580     void *mLibVulkanLibrary;
581 
582     mutable bool mCapsInitialized;
583     mutable gl::Caps mNativeCaps;
584     mutable gl::TextureCapsMap mNativeTextureCaps;
585     mutable gl::Extensions mNativeExtensions;
586     mutable gl::Limitations mNativeLimitations;
587     mutable angle::FeaturesVk mFeatures;
588 
589     uint32_t mApiVersion;
590     VkInstance mInstance;
591     bool mEnableValidationLayers;
592     // True if ANGLE is enabling the VK_EXT_debug_utils extension.
593     bool mEnableDebugUtils;
594     // True if ANGLE should call the vkCmd*DebugUtilsLabelEXT functions in order to communicate to
595     // debuggers (e.g. AGI) the OpenGL ES commands that the application uses.  This is independent
596     // of mEnableDebugUtils, as an external graphics debugger can enable the VK_EXT_debug_utils
597     // extension and cause this to be set true.
598     bool mAngleDebuggerMode;
599     angle::vk::ICD mEnabledICD;
600     VkDebugUtilsMessengerEXT mDebugUtilsMessenger;
601     VkDebugReportCallbackEXT mDebugReportCallback;
602     VkPhysicalDevice mPhysicalDevice;
603     VkPhysicalDeviceProperties mPhysicalDeviceProperties;
604     VkPhysicalDeviceFeatures mPhysicalDeviceFeatures;
605     VkPhysicalDeviceLineRasterizationFeaturesEXT mLineRasterizationFeatures;
606     VkPhysicalDeviceProvokingVertexFeaturesEXT mProvokingVertexFeatures;
607     VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT mVertexAttributeDivisorFeatures;
608     VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT mVertexAttributeDivisorProperties;
609     VkPhysicalDeviceTransformFeedbackFeaturesEXT mTransformFeedbackFeatures;
610     VkPhysicalDeviceIndexTypeUint8FeaturesEXT mIndexTypeUint8Features;
611     VkPhysicalDeviceSubgroupProperties mSubgroupProperties;
612     VkPhysicalDeviceShaderSubgroupExtendedTypesFeaturesKHR mSubgroupExtendedTypesFeatures;
613     VkPhysicalDeviceDeviceMemoryReportFeaturesEXT mMemoryReportFeatures;
614     VkDeviceDeviceMemoryReportCreateInfoEXT mMemoryReportCallback;
615     VkPhysicalDeviceExternalMemoryHostPropertiesEXT mExternalMemoryHostProperties;
616     VkPhysicalDeviceShaderFloat16Int8FeaturesKHR mShaderFloat16Int8Features;
617     VkPhysicalDeviceDepthStencilResolvePropertiesKHR mDepthStencilResolveProperties;
618     VkPhysicalDeviceMultisampledRenderToSingleSampledFeaturesEXT
619         mMultisampledRenderToSingleSampledFeatures;
620     VkPhysicalDeviceMultiviewFeatures mMultiviewFeatures;
621     VkPhysicalDeviceFeatures2KHR mEnabledFeatures;
622     VkPhysicalDeviceMultiviewProperties mMultiviewProperties;
623     VkPhysicalDeviceDriverPropertiesKHR mDriverProperties;
624     VkPhysicalDeviceCustomBorderColorFeaturesEXT mCustomBorderColorFeatures;
625     VkPhysicalDeviceProtectedMemoryFeatures mProtectedMemoryFeatures;
626     VkPhysicalDeviceProtectedMemoryProperties mProtectedMemoryProperties;
627     VkPhysicalDeviceHostQueryResetFeaturesEXT mHostQueryResetFeatures;
628     VkPhysicalDeviceDepthClipControlFeaturesEXT mDepthClipControlFeatures;
629     VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT mBlendOperationAdvancedFeatures;
630     VkPhysicalDeviceSamplerYcbcrConversionFeatures mSamplerYcbcrConversionFeatures;
631     std::vector<VkQueueFamilyProperties> mQueueFamilyProperties;
632     uint32_t mMaxVertexAttribDivisor;
633     uint32_t mCurrentQueueFamilyIndex;
634     VkDeviceSize mMaxVertexAttribStride;
635     VkDeviceSize mMinImportedHostPointerAlignment;
636     uint32_t mDefaultUniformBufferSize;
637     VkDevice mDevice;
638     AtomicSerialFactory mShaderSerialFactory;
639     VkDeviceSize mMaxCopyBytesUsingCPUWhenPreservingBufferData;
640 
641     bool mDeviceLost;
642 
643     // We group garbage into four categories: mSharedGarbage is the garbage that has already
644     // submitted to vulkan, we expect them to finish in finite time. mPendingSubmissionGarbage is
645     // the garbage that is still referenced in the recorded commands. suballocations have its own
646     // dedicated garbage list for performance optimization since they tend to be the most common
647     // garbage objects. All these four groups of garbage share the same mutex lock.
648     std::mutex mGarbageMutex;
649     vk::SharedGarbageList mSharedGarbage;
650     vk::SharedGarbageList mPendingSubmissionGarbage;
651     vk::SharedBufferSuballocationGarbageList mSuballocationGarbage;
652     vk::SharedBufferSuballocationGarbageList mPendingSubmissionSuballocationGarbage;
653 
654     vk::FormatTable mFormatTable;
655     // A cache of VkFormatProperties as queried from the device over time.
656     mutable angle::FormatMap<VkFormatProperties> mFormatProperties;
657 
658     vk::Allocator mAllocator;
659     vk::MemoryProperties mMemoryProperties;
660     VkDeviceSize mPreferredLargeHeapBlockSize;
661 
662     // The default alignment for BufferVk object
663     size_t mDefaultBufferAlignment;
664     // The cached memory type index for staging buffer that is host visible.
665     uint32_t mCoherentStagingBufferMemoryTypeIndex;
666     uint32_t mNonCoherentStagingBufferMemoryTypeIndex;
667     size_t mStagingBufferAlignment;
668     // For vertex conversion buffers
669     uint32_t mHostVisibleVertexConversionBufferMemoryTypeIndex;
670     uint32_t mDeviceLocalVertexConversionBufferMemoryTypeIndex;
671     size_t mVertexConversionBufferAlignment;
672 
673     // Holds orphaned BufferBlocks when ShareGroup gets destroyed
674     vk::BufferBlockPointerVector mOrphanedBufferBlocks;
675 
676     // All access to the pipeline cache is done through EGL objects so it is thread safe to not use
677     // a lock.
678     std::mutex mPipelineCacheMutex;
679     vk::PipelineCache mPipelineCache;
680     uint32_t mPipelineCacheVkUpdateTimeout;
681     bool mPipelineCacheDirty;
682     bool mPipelineCacheInitialized;
683 
684     // Latest validation data for debug overlay.
685     std::string mLastValidationMessage;
686     uint32_t mValidationMessageCount;
687 
688     // Whether framebuffer fetch has been used, for the purposes of more accurate syncval error
689     // filtering.
690     bool mIsFramebufferFetchUsed;
691 
692     // How close to VkPhysicalDeviceLimits::maxMemoryAllocationCount we allow ourselves to get
693     static constexpr double kPercentMaxMemoryAllocationCount = 0.3;
694     // How many objects to garbage collect before issuing a flush()
695     uint32_t mGarbageCollectionFlushThreshold;
696 
697     // Only used for "one off" command buffers.
698     vk::CommandPool mOneOffCommandPool;
699 
700     struct PendingOneOffCommands
701     {
702         Serial serial;
703         vk::PrimaryCommandBuffer commandBuffer;
704     };
705     std::deque<PendingOneOffCommands> mPendingOneOffCommands;
706 
707     // Synchronous Command Queue
708     std::mutex mCommandQueueMutex;
709     vk::CommandQueue mCommandQueue;
710 
711     // Async Command Queue
712     vk::CommandProcessor mCommandProcessor;
713 
714     // Command buffer pool management.
715     std::mutex mCommandBufferRecyclerMutex;
716     vk::CommandBufferRecycler<vk::OutsideRenderPassCommandBuffer,
717                               vk::OutsideRenderPassCommandBufferHelper>
718         mOutsideRenderPassCommandBufferRecycler;
719     vk::CommandBufferRecycler<vk::RenderPassCommandBuffer, vk::RenderPassCommandBufferHelper>
720         mRenderPassCommandBufferRecycler;
721 
722     SamplerCache mSamplerCache;
723     SamplerYcbcrConversionCache mYuvConversionCache;
724     angle::HashMap<VkFormat, uint32_t> mVkFormatDescriptorCountMap;
725     vk::ActiveHandleCounter mActiveHandleCounts;
726     std::mutex mActiveHandleCountsMutex;
727 
728     // Tracks resource serials.
729     vk::ResourceSerialFactory mResourceSerialFactory;
730 
731     // Application executable information
732     VkApplicationInfo mApplicationInfo;
733     // Process GPU memory reports
734     vk::MemoryReport mMemoryReport;
735     // Helpers for adding trace annotations
736     DebugAnnotatorVk mAnnotator;
737 
738     // Stats about all Vulkan object caches
739     using VulkanCacheStats = angle::PackedEnumMap<VulkanCacheType, CacheStats>;
740     VulkanCacheStats mVulkanCacheStats;
741     mutable std::mutex mCacheStatsMutex;
742 
743     // A mask to filter out Vulkan pipeline stages that are not supported, applied in situations
744     // where multiple stages are prespecified (for example with image layout transitions):
745     //
746     // - Excludes GEOMETRY if geometry shaders are not supported.
747     // - Excludes TESSELLATION_CONTROL and TESSELLATION_EVALUATION if tessellation shaders are not
748     //   supported.
749     //
750     // Note that this mask can have bits set that don't correspond to valid stages, so it's strictly
751     // only useful for masking out unsupported stages in an otherwise valid set of stages.
752     VkPipelineStageFlags mSupportedVulkanPipelineStageMask;
753 
754     // Use thread pool to compress cache data.
755     std::shared_ptr<rx::WaitableCompressEvent> mCompressEvent;
756 
757     vk::ExtensionNameList mEnabledInstanceExtensions;
758     vk::ExtensionNameList mEnabledDeviceExtensions;
759 };
760 
761 }  // namespace rx
762 
763 #endif  // LIBANGLE_RENDERER_VULKAN_RENDERERVK_H_
764