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 &¤tGarbage,
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