• 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.cpp:
7 //    Implements the class methods for RendererVk.
8 //
9 
10 #include "libANGLE/renderer/vulkan/RendererVk.h"
11 
12 // Placing this first seems to solve an intellisense bug.
13 #include "libANGLE/renderer/vulkan/vk_utils.h"
14 
15 #include <EGL/eglext.h>
16 
17 #include "common/debug.h"
18 #include "common/platform.h"
19 #include "common/system_utils.h"
20 #include "common/vulkan/libvulkan_loader.h"
21 #include "common/vulkan/vk_google_filtering_precision.h"
22 #include "common/vulkan/vulkan_icd.h"
23 #include "gpu_info_util/SystemInfo.h"
24 #include "libANGLE/Context.h"
25 #include "libANGLE/Display.h"
26 #include "libANGLE/renderer/driver_utils.h"
27 #include "libANGLE/renderer/glslang_wrapper_utils.h"
28 #include "libANGLE/renderer/vulkan/CompilerVk.h"
29 #include "libANGLE/renderer/vulkan/ContextVk.h"
30 #include "libANGLE/renderer/vulkan/DisplayVk.h"
31 #include "libANGLE/renderer/vulkan/FramebufferVk.h"
32 #include "libANGLE/renderer/vulkan/ProgramVk.h"
33 #include "libANGLE/renderer/vulkan/ResourceVk.h"
34 #include "libANGLE/renderer/vulkan/VertexArrayVk.h"
35 #include "libANGLE/renderer/vulkan/vk_caps_utils.h"
36 #include "libANGLE/renderer/vulkan/vk_format_utils.h"
37 #include "libANGLE/trace.h"
38 #include "platform/PlatformMethods.h"
39 
40 // Consts
41 namespace
42 {
43 constexpr VkFormatFeatureFlags kInvalidFormatFeatureFlags = static_cast<VkFormatFeatureFlags>(-1);
44 
45 #if defined(ANGLE_EXPOSE_NON_CONFORMANT_EXTENSIONS_AND_VERSIONS)
46 constexpr bool kExposeNonConformantExtensionsAndVersions = true;
47 #else
48 constexpr bool kExposeNonConformantExtensionsAndVersions = false;
49 #endif
50 
51 }  // anonymous namespace
52 
53 namespace rx
54 {
55 
56 namespace
57 {
58 constexpr uint32_t kMinDefaultUniformBufferSize = 16 * 1024u;
59 // This size is picked based on experience. Majority of devices support 64K
60 // maxUniformBufferSize. Since this is per context buffer, a bigger buffer size reduces the
61 // number of descriptor set allocations, so we picked the maxUniformBufferSize that most
62 // devices supports. It may needs further tuning based on specific device needs and balance
63 // between performance and memory usage.
64 constexpr uint32_t kPreferredDefaultUniformBufferSize = 64 * 1024u;
65 
66 // Update the pipeline cache every this many swaps.
67 constexpr uint32_t kPipelineCacheVkUpdatePeriod = 60;
68 // Per the Vulkan specification, as long as Vulkan 1.1+ is returned by vkEnumerateInstanceVersion,
69 // ANGLE must indicate the highest version of Vulkan functionality that it uses.  The Vulkan
70 // validation layers will issue messages for any core functionality that requires a higher version.
71 // This value must be increased whenever ANGLE starts using functionality from a newer core
72 // version of Vulkan.
73 constexpr uint32_t kPreferredVulkanAPIVersion = VK_API_VERSION_1_1;
74 
ChooseICDFromAttribs(const egl::AttributeMap & attribs)75 angle::vk::ICD ChooseICDFromAttribs(const egl::AttributeMap &attribs)
76 {
77 #if !defined(ANGLE_PLATFORM_ANDROID)
78     // Mock ICD does not currently run on Android
79     EGLAttrib deviceType = attribs.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE,
80                                        EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE);
81 
82     switch (deviceType)
83     {
84         case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE:
85             break;
86         case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE:
87             return angle::vk::ICD::Mock;
88         case EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE:
89             return angle::vk::ICD::SwiftShader;
90         default:
91             UNREACHABLE();
92             break;
93     }
94 #endif  // !defined(ANGLE_PLATFORM_ANDROID)
95 
96     return angle::vk::ICD::Default;
97 }
98 
StrLess(const char * a,const char * b)99 bool StrLess(const char *a, const char *b)
100 {
101     return strcmp(a, b) < 0;
102 }
103 
ExtensionFound(const char * needle,const vk::ExtensionNameList & haystack)104 bool ExtensionFound(const char *needle, const vk::ExtensionNameList &haystack)
105 {
106     // NOTE: The list must be sorted.
107     return std::binary_search(haystack.begin(), haystack.end(), needle, StrLess);
108 }
109 
VerifyExtensionsPresent(const vk::ExtensionNameList & haystack,const vk::ExtensionNameList & needles)110 VkResult VerifyExtensionsPresent(const vk::ExtensionNameList &haystack,
111                                  const vk::ExtensionNameList &needles)
112 {
113     // NOTE: The lists must be sorted.
114     if (std::includes(haystack.begin(), haystack.end(), needles.begin(), needles.end(), StrLess))
115     {
116         return VK_SUCCESS;
117     }
118     for (const char *needle : needles)
119     {
120         if (!ExtensionFound(needle, haystack))
121         {
122             ERR() << "Extension not supported: " << needle;
123         }
124     }
125     return VK_ERROR_EXTENSION_NOT_PRESENT;
126 }
127 
128 // Array of Validation error/warning messages that will be ignored, should include bugID
129 constexpr const char *kSkippedMessages[] = {
130     // http://anglebug.com/2866
131     "UNASSIGNED-CoreValidation-Shader-OutputNotConsumed",
132     // http://anglebug.com/4883
133     "UNASSIGNED-CoreValidation-Shader-InputNotProduced",
134     // http://anglebug.com/2796
135     "UNASSIGNED-CoreValidation-Shader-PointSizeMissing",
136     // http://anglebug.com/3832
137     "VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00428",
138     // http://anglebug.com/4063
139     "VUID-VkDeviceCreateInfo-pNext-pNext",
140     "VUID-VkPipelineRasterizationStateCreateInfo-pNext-pNext",
141     "VUID_Undefined",
142     // https://issuetracker.google.com/issues/159493191
143     "VUID-vkCmdDraw-None-02690",
144     "VUID-vkCmdDrawIndexed-None-02690",
145     // http://anglebug.com/4975
146     "VUID-vkCmdDraw-None-02687",
147     "VUID-vkCmdDrawIndexed-None-02687",
148     // Best Practices Skips https://issuetracker.google.com/issues/166641492
149     // https://issuetracker.google.com/issues/166793850
150     "UNASSIGNED-BestPractices-vkCreateCommandPool-command-buffer-reset",
151     "UNASSIGNED-BestPractices-pipeline-stage-flags",
152     "UNASSIGNED-BestPractices-Error-Result",
153     "UNASSIGNED-BestPractices-vkAllocateMemory-small-allocation",
154     "UNASSIGNED-BestPractices-vkBindMemory-small-dedicated-allocation",
155     "UNASSIGNED-BestPractices-vkAllocateMemory-too-many-objects",
156     "UNASSIGNED-BestPractices-vkCreateDevice-deprecated-extension",
157     "UNASSIGNED-BestPractices-vkCreateRenderPass-image-requires-memory",
158     "UNASSIGNED-BestPractices-vkCreateGraphicsPipelines-too-many-instanced-vertex-buffers",
159     "UNASSIGNED-BestPractices-DrawState-ClearCmdBeforeDraw",
160     "UNASSIGNED-BestPractices-vkCmdClearAttachments-clear-after-load",
161     // http://anglebug.com/4928
162     "VUID-vkMapMemory-memory-00683",
163     // http://anglebug.com/5027
164     "UNASSIGNED-CoreValidation-Shader-PushConstantOutOfRange",
165     // http://anglebug.com/5304
166     "VUID-vkCmdDraw-magFilter-04553",
167     "VUID-vkCmdDrawIndexed-magFilter-04553",
168     // http://anglebug.com/5309
169     "VUID-VkImageViewCreateInfo-usage-02652",
170     // http://anglebug.com/5336
171     "UNASSIGNED-BestPractices-vkCreateDevice-specialuse-extension",
172     // http://anglebug.com/5331
173     "VUID-VkSubpassDescriptionDepthStencilResolve-depthResolveMode-parameter",
174     "VUID-VkSubpassDescriptionDepthStencilResolve-stencilResolveMode-parameter",
175     // https://issuetracker.google.com/175584609
176     "VUID-vkCmdDraw-None-04584",
177     "VUID-vkCmdDrawIndexed-None-04584",
178     "VUID-vkCmdDrawIndirect-None-04584",
179     "VUID-vkCmdDrawIndirectCount-None-04584",
180     "VUID-vkCmdDrawIndexedIndirect-None-04584",
181     "VUID-vkCmdDrawIndexedIndirectCount-None-04584",
182     // https://anglebug.com/5912
183     "VUID-VkImageViewCreateInfo-pNext-01585",
184     // http://anglebug.com/6155
185     "VUID-vkCmdDraw-None-02699",
186     // http://anglebug.com/6168
187     "VUID-VkImageViewCreateInfo-None-02273",
188 };
189 
190 // Suppress validation errors that are known
191 //  return "true" if given code/prefix/message is known, else return "false"
IsIgnoredDebugMessage(const char * message)192 bool IsIgnoredDebugMessage(const char *message)
193 {
194     if (!message)
195     {
196         return false;
197     }
198     for (const char *msg : kSkippedMessages)
199     {
200         if (strstr(message, msg) != nullptr)
201         {
202             return true;
203         }
204     }
205     return false;
206 }
207 
GetVkObjectTypeName(VkObjectType type)208 const char *GetVkObjectTypeName(VkObjectType type)
209 {
210     switch (type)
211     {
212         case VK_OBJECT_TYPE_UNKNOWN:
213             return "Unknown";
214         case VK_OBJECT_TYPE_INSTANCE:
215             return "Instance";
216         case VK_OBJECT_TYPE_PHYSICAL_DEVICE:
217             return "Physical Device";
218         case VK_OBJECT_TYPE_DEVICE:
219             return "Device";
220         case VK_OBJECT_TYPE_QUEUE:
221             return "Queue";
222         case VK_OBJECT_TYPE_SEMAPHORE:
223             return "Semaphore";
224         case VK_OBJECT_TYPE_COMMAND_BUFFER:
225             return "Command Buffer";
226         case VK_OBJECT_TYPE_FENCE:
227             return "Fence";
228         case VK_OBJECT_TYPE_DEVICE_MEMORY:
229             return "Device Memory";
230         case VK_OBJECT_TYPE_BUFFER:
231             return "Buffer";
232         case VK_OBJECT_TYPE_IMAGE:
233             return "Image";
234         case VK_OBJECT_TYPE_EVENT:
235             return "Event";
236         case VK_OBJECT_TYPE_QUERY_POOL:
237             return "Query Pool";
238         case VK_OBJECT_TYPE_BUFFER_VIEW:
239             return "Buffer View";
240         case VK_OBJECT_TYPE_IMAGE_VIEW:
241             return "Image View";
242         case VK_OBJECT_TYPE_SHADER_MODULE:
243             return "Shader Module";
244         case VK_OBJECT_TYPE_PIPELINE_CACHE:
245             return "Pipeline Cache";
246         case VK_OBJECT_TYPE_PIPELINE_LAYOUT:
247             return "Pipeline Layout";
248         case VK_OBJECT_TYPE_RENDER_PASS:
249             return "Render Pass";
250         case VK_OBJECT_TYPE_PIPELINE:
251             return "Pipeline";
252         case VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT:
253             return "Descriptor Set Layout";
254         case VK_OBJECT_TYPE_SAMPLER:
255             return "Sampler";
256         case VK_OBJECT_TYPE_DESCRIPTOR_POOL:
257             return "Descriptor Pool";
258         case VK_OBJECT_TYPE_DESCRIPTOR_SET:
259             return "Descriptor Set";
260         case VK_OBJECT_TYPE_FRAMEBUFFER:
261             return "Framebuffer";
262         case VK_OBJECT_TYPE_COMMAND_POOL:
263             return "Command Pool";
264         case VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION:
265             return "Sampler YCbCr Conversion";
266         case VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE:
267             return "Descriptor Update Template";
268         case VK_OBJECT_TYPE_SURFACE_KHR:
269             return "Surface";
270         case VK_OBJECT_TYPE_SWAPCHAIN_KHR:
271             return "Swapchain";
272         case VK_OBJECT_TYPE_DISPLAY_KHR:
273             return "Display";
274         case VK_OBJECT_TYPE_DISPLAY_MODE_KHR:
275             return "Display Mode";
276         case VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT:
277             return "Debug Report Callback";
278         case VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NV:
279             return "Indirect Commands Layout";
280         case VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT:
281             return "Debug Utils Messenger";
282         case VK_OBJECT_TYPE_VALIDATION_CACHE_EXT:
283             return "Validation Cache";
284         case VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV:
285             return "Acceleration Structure";
286         default:
287             return "<Unrecognized>";
288     }
289 }
290 
291 VKAPI_ATTR VkBool32 VKAPI_CALL
DebugUtilsMessenger(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,VkDebugUtilsMessageTypeFlagsEXT messageTypes,const VkDebugUtilsMessengerCallbackDataEXT * callbackData,void * userData)292 DebugUtilsMessenger(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
293                     VkDebugUtilsMessageTypeFlagsEXT messageTypes,
294                     const VkDebugUtilsMessengerCallbackDataEXT *callbackData,
295                     void *userData)
296 {
297     // See if it's an issue we are aware of and don't want to be spammed about.
298     if (IsIgnoredDebugMessage(callbackData->pMessageIdName))
299     {
300         return VK_FALSE;
301     }
302 
303     std::ostringstream log;
304     if (callbackData->pMessageIdName)
305     {
306         log << "[ " << callbackData->pMessageIdName << " ] ";
307     }
308     log << callbackData->pMessage << std::endl;
309 
310     // Aesthetic value based on length of the function name, line number, etc.
311     constexpr size_t kStartIndent = 28;
312 
313     // Output the debug marker hierarchy under which this error has occured.
314     size_t indent = kStartIndent;
315     if (callbackData->queueLabelCount > 0)
316     {
317         log << std::string(indent++, ' ') << "<Queue Label Hierarchy:>" << std::endl;
318         for (uint32_t i = 0; i < callbackData->queueLabelCount; ++i)
319         {
320             log << std::string(indent++, ' ') << callbackData->pQueueLabels[i].pLabelName
321                 << std::endl;
322         }
323     }
324     if (callbackData->cmdBufLabelCount > 0)
325     {
326         log << std::string(indent++, ' ') << "<Command Buffer Label Hierarchy:>" << std::endl;
327         for (uint32_t i = 0; i < callbackData->cmdBufLabelCount; ++i)
328         {
329             log << std::string(indent++, ' ') << callbackData->pCmdBufLabels[i].pLabelName
330                 << std::endl;
331         }
332     }
333     // Output the objects involved in this error message.
334     if (callbackData->objectCount > 0)
335     {
336         for (uint32_t i = 0; i < callbackData->objectCount; ++i)
337         {
338             const char *objectName = callbackData->pObjects[i].pObjectName;
339             const char *objectType = GetVkObjectTypeName(callbackData->pObjects[i].objectType);
340             uint64_t objectHandle  = callbackData->pObjects[i].objectHandle;
341             log << std::string(indent, ' ') << "Object: ";
342             if (objectHandle == 0)
343             {
344                 log << "VK_NULL_HANDLE";
345             }
346             else
347             {
348                 log << "0x" << std::hex << objectHandle << std::dec;
349             }
350             log << " (type = " << objectType << "(" << callbackData->pObjects[i].objectType << "))";
351             if (objectName)
352             {
353                 log << " [" << objectName << "]";
354             }
355             log << std::endl;
356         }
357     }
358 
359     bool isError    = (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) != 0;
360     std::string msg = log.str();
361 
362     RendererVk *rendererVk = static_cast<RendererVk *>(userData);
363     rendererVk->onNewValidationMessage(msg);
364 
365     if (isError)
366     {
367         ERR() << msg;
368     }
369     else
370     {
371         WARN() << msg;
372     }
373 
374     return VK_FALSE;
375 }
376 
DebugReportCallback(VkDebugReportFlagsEXT flags,VkDebugReportObjectTypeEXT objectType,uint64_t object,size_t location,int32_t messageCode,const char * layerPrefix,const char * message,void * userData)377 VKAPI_ATTR VkBool32 VKAPI_CALL DebugReportCallback(VkDebugReportFlagsEXT flags,
378                                                    VkDebugReportObjectTypeEXT objectType,
379                                                    uint64_t object,
380                                                    size_t location,
381                                                    int32_t messageCode,
382                                                    const char *layerPrefix,
383                                                    const char *message,
384                                                    void *userData)
385 {
386     if (IsIgnoredDebugMessage(message))
387     {
388         return VK_FALSE;
389     }
390     if ((flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) != 0)
391     {
392         ERR() << message;
393 #if !defined(NDEBUG)
394         // Abort the call in Debug builds.
395         return VK_TRUE;
396 #endif
397     }
398     else if ((flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) != 0)
399     {
400         WARN() << message;
401     }
402     else
403     {
404         // Uncomment this if you want Vulkan spam.
405         // WARN() << message;
406     }
407 
408     return VK_FALSE;
409 }
410 
411 VKAPI_ATTR void VKAPI_CALL
MemoryReportCallback(const VkDeviceMemoryReportCallbackDataEXT * callbackData,void * userData)412 MemoryReportCallback(const VkDeviceMemoryReportCallbackDataEXT *callbackData, void *userData)
413 {
414     RendererVk *rendererVk = static_cast<RendererVk *>(userData);
415     rendererVk->processMemoryReportCallback(*callbackData);
416 }
417 
ShouldUseValidationLayers(const egl::AttributeMap & attribs)418 bool ShouldUseValidationLayers(const egl::AttributeMap &attribs)
419 {
420 #if defined(ANGLE_ENABLE_VULKAN_VALIDATION_LAYERS_BY_DEFAULT)
421     return ShouldUseDebugLayers(attribs);
422 #else
423     EGLAttrib debugSetting =
424         attribs.get(EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE, EGL_DONT_CARE);
425     return debugSetting == EGL_TRUE;
426 #endif  // defined(ANGLE_ENABLE_VULKAN_VALIDATION_LAYERS_BY_DEFAULT)
427 }
428 
LimitVersionTo(const gl::Version & current,const gl::Version & lower)429 gl::Version LimitVersionTo(const gl::Version &current, const gl::Version &lower)
430 {
431     return std::min(current, lower);
432 }
433 
FencePropertiesCompatibleWithAndroid(const VkExternalFenceProperties & externalFenceProperties)434 ANGLE_MAYBE_UNUSED bool FencePropertiesCompatibleWithAndroid(
435     const VkExternalFenceProperties &externalFenceProperties)
436 {
437     // handleType here is the external fence type -
438     // we want type compatible with creating and export/dup() Android FD
439 
440     // Imported handleType that can be exported - need for vkGetFenceFdKHR()
441     if ((externalFenceProperties.exportFromImportedHandleTypes &
442          VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR) == 0)
443     {
444         return false;
445     }
446 
447     // HandleTypes which can be specified at creating a fence
448     if ((externalFenceProperties.compatibleHandleTypes &
449          VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR) == 0)
450     {
451         return false;
452     }
453 
454     constexpr VkExternalFenceFeatureFlags kFeatureFlags =
455         (VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT_KHR |
456          VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT_KHR);
457     if ((externalFenceProperties.externalFenceFeatures & kFeatureFlags) != kFeatureFlags)
458     {
459         return false;
460     }
461 
462     return true;
463 }
464 
SemaphorePropertiesCompatibleWithAndroid(const VkExternalSemaphoreProperties & externalSemaphoreProperties)465 ANGLE_MAYBE_UNUSED bool SemaphorePropertiesCompatibleWithAndroid(
466     const VkExternalSemaphoreProperties &externalSemaphoreProperties)
467 {
468     // handleType here is the external semaphore type -
469     // we want type compatible with importing an Android FD
470 
471     constexpr VkExternalSemaphoreFeatureFlags kFeatureFlags =
472         (VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHR);
473     if ((externalSemaphoreProperties.externalSemaphoreFeatures & kFeatureFlags) != kFeatureFlags)
474     {
475         return false;
476     }
477 
478     return true;
479 }
480 
ComputePipelineCacheVkChunkKey(VkPhysicalDeviceProperties physicalDeviceProperties,const uint8_t chunkIndex,egl::BlobCache::Key * hashOut)481 void ComputePipelineCacheVkChunkKey(VkPhysicalDeviceProperties physicalDeviceProperties,
482                                     const uint8_t chunkIndex,
483                                     egl::BlobCache::Key *hashOut)
484 {
485     std::ostringstream hashStream("ANGLE Pipeline Cache: ", std::ios_base::ate);
486     // Add the pipeline cache UUID to make sure the blob cache always gives a compatible pipeline
487     // cache.  It's not particularly necessary to write it as a hex number as done here, so long as
488     // there is no '\0' in the result.
489     for (const uint32_t c : physicalDeviceProperties.pipelineCacheUUID)
490     {
491         hashStream << std::hex << c;
492     }
493     // Add the vendor and device id too for good measure.
494     hashStream << std::hex << physicalDeviceProperties.vendorID;
495     hashStream << std::hex << physicalDeviceProperties.deviceID;
496 
497     // Add chunkIndex to generate unique key for chunks.
498     hashStream << std::hex << chunkIndex;
499 
500     const std::string &hashString = hashStream.str();
501     angle::base::SHA1HashBytes(reinterpret_cast<const unsigned char *>(hashString.c_str()),
502                                hashString.length(), hashOut->data());
503 }
504 
CompressAndStorePipelineCacheVk(VkPhysicalDeviceProperties physicalDeviceProperties,DisplayVk * displayVk,ContextVk * contextVk,const std::vector<uint8_t> & cacheData,const size_t maxTotalSize)505 bool CompressAndStorePipelineCacheVk(VkPhysicalDeviceProperties physicalDeviceProperties,
506                                      DisplayVk *displayVk,
507                                      ContextVk *contextVk,
508                                      const std::vector<uint8_t> &cacheData,
509                                      const size_t maxTotalSize)
510 {
511     // Though the pipeline cache will be compressed and divided into several chunks to store in blob
512     // cache, the largest total size of blob cache is only 2M in android now, so there is no use to
513     // handle big pipeline cache when android will reject it finally.
514     if (cacheData.size() >= maxTotalSize)
515     {
516         // TODO: handle the big pipeline cache. http://anglebug.com/4722
517         ANGLE_PERF_WARNING(contextVk->getDebug(), GL_DEBUG_SEVERITY_LOW,
518                            "Skip syncing pipeline cache data when it's larger than maxTotalSize.");
519         return false;
520     }
521 
522     // To make it possible to store more pipeline cache data, compress the whole pipelineCache.
523     angle::MemoryBuffer compressedData;
524 
525     if (!egl::CompressBlobCacheData(cacheData.size(), cacheData.data(), &compressedData))
526     {
527         return false;
528     }
529 
530     // If the size of compressedData is larger than (kMaxBlobCacheSize - sizeof(numChunks)),
531     // the pipelineCache still can't be stored in blob cache. Divide the large compressed
532     // pipelineCache into several parts to store seperately. There is no function to
533     // query the limit size in android.
534     constexpr size_t kMaxBlobCacheSize = 64 * 1024;
535 
536     // Store {numChunks, chunkCompressedData} in keyData, numChunks is used to validate the data.
537     // For example, if the compressed size is 68841 bytes(67k), divide into {2,34421 bytes} and
538     // {2,34420 bytes}.
539     constexpr size_t kBlobHeaderSize = sizeof(uint8_t);
540     size_t compressedOffset          = 0;
541 
542     const size_t numChunks = UnsignedCeilDivide(static_cast<unsigned int>(compressedData.size()),
543                                                 kMaxBlobCacheSize - kBlobHeaderSize);
544     size_t chunkSize       = UnsignedCeilDivide(static_cast<unsigned int>(compressedData.size()),
545                                           static_cast<unsigned int>(numChunks));
546 
547     for (size_t chunkIndex = 0; chunkIndex < numChunks; ++chunkIndex)
548     {
549         if (chunkIndex == numChunks - 1)
550         {
551             chunkSize = compressedData.size() - compressedOffset;
552         }
553 
554         angle::MemoryBuffer keyData;
555         if (!keyData.resize(kBlobHeaderSize + chunkSize))
556         {
557             return false;
558         }
559 
560         ASSERT(numChunks <= UINT8_MAX);
561         keyData.data()[0] = static_cast<uint8_t>(numChunks);
562         memcpy(keyData.data() + kBlobHeaderSize, compressedData.data() + compressedOffset,
563                chunkSize);
564         compressedOffset += chunkSize;
565 
566         // Create unique hash key.
567         egl::BlobCache::Key chunkCacheHash;
568         ComputePipelineCacheVkChunkKey(physicalDeviceProperties, chunkIndex, &chunkCacheHash);
569 
570         displayVk->getBlobCache()->putApplication(chunkCacheHash, keyData);
571     }
572 
573     return true;
574 }
575 
576 class CompressAndStorePipelineCacheTask : public angle::Closure
577 {
578   public:
CompressAndStorePipelineCacheTask(DisplayVk * displayVk,ContextVk * contextVk,std::vector<uint8_t> && cacheData,size_t kMaxTotalSize)579     CompressAndStorePipelineCacheTask(DisplayVk *displayVk,
580                                       ContextVk *contextVk,
581                                       std::vector<uint8_t> &&cacheData,
582                                       size_t kMaxTotalSize)
583         : mDisplayVk(displayVk),
584           mContextVk(contextVk),
585           mCacheData(std::move(cacheData)),
586           mMaxTotalSize(kMaxTotalSize),
587           mResult(true)
588     {}
589 
operator ()()590     void operator()() override
591     {
592         ANGLE_TRACE_EVENT0("gpu.angle", "CompressAndStorePipelineCacheVk");
593         mResult = CompressAndStorePipelineCacheVk(
594             mContextVk->getRenderer()->getPhysicalDeviceProperties(), mDisplayVk, mContextVk,
595             mCacheData, mMaxTotalSize);
596     }
597 
getResult()598     bool getResult() { return mResult; }
599 
600   private:
601     DisplayVk *mDisplayVk;
602     ContextVk *mContextVk;
603     std::vector<uint8_t> mCacheData;
604     size_t mMaxTotalSize;
605     bool mResult;
606 };
607 
608 class WaitableCompressEventImpl : public WaitableCompressEvent
609 {
610   public:
WaitableCompressEventImpl(std::shared_ptr<angle::WaitableEvent> waitableEvent,std::shared_ptr<CompressAndStorePipelineCacheTask> compressTask)611     WaitableCompressEventImpl(std::shared_ptr<angle::WaitableEvent> waitableEvent,
612                               std::shared_ptr<CompressAndStorePipelineCacheTask> compressTask)
613         : WaitableCompressEvent(waitableEvent), mCompressTask(compressTask)
614     {}
615 
getResult()616     bool getResult() override { return mCompressTask->getResult(); }
617 
618   private:
619     std::shared_ptr<CompressAndStorePipelineCacheTask> mCompressTask;
620 };
621 
GetAndDecompressPipelineCacheVk(VkPhysicalDeviceProperties physicalDeviceProperties,DisplayVk * displayVk,angle::MemoryBuffer * uncompressedData,bool * success)622 angle::Result GetAndDecompressPipelineCacheVk(VkPhysicalDeviceProperties physicalDeviceProperties,
623                                               DisplayVk *displayVk,
624                                               angle::MemoryBuffer *uncompressedData,
625                                               bool *success)
626 {
627     // Compute the hash key of chunkIndex 0 and find the first cache data in blob cache.
628     egl::BlobCache::Key chunkCacheHash;
629     ComputePipelineCacheVkChunkKey(physicalDeviceProperties, 0, &chunkCacheHash);
630     egl::BlobCache::Value keyData;
631     size_t keySize                   = 0;
632     constexpr size_t kBlobHeaderSize = sizeof(uint8_t);
633 
634     if (!displayVk->getBlobCache()->get(displayVk->getScratchBuffer(), chunkCacheHash, &keyData,
635                                         &keySize) ||
636         keyData.size() < kBlobHeaderSize)
637     {
638         // Nothing in the cache.
639         return angle::Result::Continue;
640     }
641 
642     // Get the number of chunks.
643     size_t numChunks      = keyData.data()[0];
644     size_t chunkSize      = keySize - kBlobHeaderSize;
645     size_t compressedSize = 0;
646 
647     // Allocate enough memory.
648     angle::MemoryBuffer compressedData;
649     ANGLE_VK_CHECK(displayVk, compressedData.resize(chunkSize * numChunks),
650                    VK_ERROR_INITIALIZATION_FAILED);
651 
652     // To combine the parts of the pipelineCache data.
653     for (size_t chunkIndex = 0; chunkIndex < numChunks; ++chunkIndex)
654     {
655         // Get the unique key by chunkIndex.
656         ComputePipelineCacheVkChunkKey(physicalDeviceProperties, chunkIndex, &chunkCacheHash);
657 
658         if (!displayVk->getBlobCache()->get(displayVk->getScratchBuffer(), chunkCacheHash, &keyData,
659                                             &keySize) ||
660             keyData.size() < kBlobHeaderSize)
661         {
662             // Can't find every part of the cache data.
663             WARN() << "Failed to get pipeline cache chunk " << chunkIndex << " of " << numChunks;
664             return angle::Result::Continue;
665         }
666 
667         size_t checkNumber = keyData.data()[0];
668         chunkSize          = keySize - kBlobHeaderSize;
669 
670         if (checkNumber != numChunks || compressedData.size() < (compressedSize + chunkSize))
671         {
672             // Validate the number value and enough space to store.
673             WARN() << "Pipeline cache chunk header corrupted: checkNumber = " << checkNumber
674                    << ", numChunks = " << numChunks
675                    << ", compressedData.size() = " << compressedData.size()
676                    << ", (compressedSize + chunkSize) = " << (compressedSize + chunkSize);
677             return angle::Result::Continue;
678         }
679         memcpy(compressedData.data() + compressedSize, keyData.data() + kBlobHeaderSize, chunkSize);
680         compressedSize += chunkSize;
681     }
682 
683     ANGLE_VK_CHECK(
684         displayVk,
685         egl::DecompressBlobCacheData(compressedData.data(), compressedSize, uncompressedData),
686         VK_ERROR_INITIALIZATION_FAILED);
687 
688     *success = true;
689     return angle::Result::Continue;
690 }
691 
692 // Environment variable (and associated Android property) to enable Vulkan debug-utils markers
693 constexpr char kEnableDebugMarkersVarName[]      = "ANGLE_ENABLE_DEBUG_MARKERS";
694 constexpr char kEnableDebugMarkersPropertyName[] = "debug.angle.markers";
695 }  // namespace
696 
697 // RendererVk implementation.
RendererVk()698 RendererVk::RendererVk()
699     : mDisplay(nullptr),
700       mCapsInitialized(false),
701       mInstance(VK_NULL_HANDLE),
702       mEnableValidationLayers(false),
703       mEnableDebugUtils(false),
704       mAngleDebuggerMode(false),
705       mEnabledICD(angle::vk::ICD::Default),
706       mDebugUtilsMessenger(VK_NULL_HANDLE),
707       mDebugReportCallback(VK_NULL_HANDLE),
708       mPhysicalDevice(VK_NULL_HANDLE),
709       mMaxVertexAttribDivisor(1),
710       mCurrentQueueFamilyIndex(std::numeric_limits<uint32_t>::max()),
711       mMaxVertexAttribStride(0),
712       mMinImportedHostPointerAlignment(1),
713       mDefaultUniformBufferSize(kPreferredDefaultUniformBufferSize),
714       mDevice(VK_NULL_HANDLE),
715       mDeviceLost(false),
716       mPipelineCacheVkUpdateTimeout(kPipelineCacheVkUpdatePeriod),
717       mPipelineCacheDirty(false),
718       mPipelineCacheInitialized(false),
719       mValidationMessageCount(0),
720       mCommandProcessor(this),
721       mSupportedVulkanPipelineStageMask(0)
722 {
723     VkFormatProperties invalid = {0, 0, kInvalidFormatFeatureFlags};
724     mFormatProperties.fill(invalid);
725 
726     // We currently don't have any big-endian devices in the list of supported platforms.  There are
727     // a number of places in the Vulkan backend that make this assumption.  This assertion is made
728     // early to fail immediately on big-endian platforms.
729     ASSERT(IsLittleEndian());
730 }
731 
~RendererVk()732 RendererVk::~RendererVk()
733 {
734     mAllocator.release();
735     mPipelineCache.release();
736     ASSERT(!hasSharedGarbage());
737 }
738 
hasSharedGarbage()739 bool RendererVk::hasSharedGarbage()
740 {
741     std::lock_guard<std::mutex> lock(mGarbageMutex);
742     return !mSharedGarbage.empty();
743 }
744 
releaseSharedResources(vk::ResourceUseList * resourceList)745 void RendererVk::releaseSharedResources(vk::ResourceUseList *resourceList)
746 {
747     // resource list may access same resources referenced by garbage collection so need to protect
748     // that access with a lock.
749     std::lock_guard<std::mutex> lock(mGarbageMutex);
750     resourceList->releaseResourceUses();
751 }
752 
onDestroy(vk::Context * context)753 void RendererVk::onDestroy(vk::Context *context)
754 {
755     {
756         std::lock_guard<std::mutex> lock(mCommandQueueMutex);
757         if (mFeatures.asyncCommandQueue.enabled)
758         {
759             mCommandProcessor.destroy(context);
760         }
761         else
762         {
763             mCommandQueue.destroy(context);
764         }
765     }
766 
767     // Assigns an infinite "last completed" serial to force garbage to delete.
768     (void)cleanupGarbage(Serial::Infinite());
769     ASSERT(!hasSharedGarbage());
770 
771     for (PendingOneOffCommands &pending : mPendingOneOffCommands)
772     {
773         pending.commandBuffer.releaseHandle();
774     }
775 
776     mOneOffCommandPool.destroy(mDevice);
777 
778     mPipelineCache.destroy(mDevice);
779     mSamplerCache.destroy(this);
780     mYuvConversionCache.destroy(this);
781     mVkFormatDescriptorCountMap.clear();
782 
783     for (vk::CommandBufferHelper *commandBufferHelper : mCommandBufferHelperFreeList)
784     {
785         SafeDelete(commandBufferHelper);
786     }
787     mCommandBufferHelperFreeList.clear();
788 
789     mAllocator.destroy();
790 
791     sh::FinalizeGlslang();
792 
793     if (mDevice)
794     {
795         vkDestroyDevice(mDevice, nullptr);
796         mDevice = VK_NULL_HANDLE;
797     }
798 
799     if (mDebugUtilsMessenger)
800     {
801         vkDestroyDebugUtilsMessengerEXT(mInstance, mDebugUtilsMessenger, nullptr);
802 
803         ASSERT(mDebugReportCallback == VK_NULL_HANDLE);
804     }
805     else if (mDebugReportCallback)
806     {
807         vkDestroyDebugReportCallbackEXT(mInstance, mDebugReportCallback, nullptr);
808     }
809 
810     logCacheStats();
811 
812     if (mInstance)
813     {
814         vkDestroyInstance(mInstance, nullptr);
815         mInstance = VK_NULL_HANDLE;
816     }
817 
818     if (mCompressEvent)
819     {
820         mCompressEvent->wait();
821         mCompressEvent.reset();
822     }
823 
824     mMemoryProperties.destroy();
825     mPhysicalDevice = VK_NULL_HANDLE;
826 }
827 
notifyDeviceLost()828 void RendererVk::notifyDeviceLost()
829 {
830     mDeviceLost = true;
831     mDisplay->notifyDeviceLost();
832 }
833 
isDeviceLost() const834 bool RendererVk::isDeviceLost() const
835 {
836     return mDeviceLost;
837 }
838 
initialize(DisplayVk * displayVk,egl::Display * display,const char * wsiExtension,const char * wsiLayer)839 angle::Result RendererVk::initialize(DisplayVk *displayVk,
840                                      egl::Display *display,
841                                      const char *wsiExtension,
842                                      const char *wsiLayer)
843 {
844     bool canLoadDebugUtils = true;
845 #if defined(ANGLE_SHARED_LIBVULKAN)
846     mLibVulkanLibrary = angle::vk::OpenLibVulkan();
847     ANGLE_VK_CHECK(displayVk, mLibVulkanLibrary, VK_ERROR_INITIALIZATION_FAILED);
848 
849     PFN_vkGetInstanceProcAddr vulkanLoaderGetInstanceProcAddr = nullptr;
850     mLibVulkanLibrary->getAs("vkGetInstanceProcAddr", &vulkanLoaderGetInstanceProcAddr);
851 
852     // Set all vk* function ptrs
853     ANGLE_VK_TRY(displayVk, volkInitialize());
854 
855     uint32_t ver = volkGetInstanceVersion();
856     if (!IsAndroid() && VK_API_VERSION_MAJOR(ver) == 1 &&
857         (VK_API_VERSION_MINOR(ver) < 1 ||
858          (VK_API_VERSION_MINOR(ver) == 1 && VK_API_VERSION_PATCH(ver) < 91)))
859     {
860         // http://crbug.com/1205999 - non-Android Vulkan Loader versions before 1.1.91 have a bug
861         // which prevents loading VK_EXT_debug_utils function pointers.
862         canLoadDebugUtils = false;
863     }
864 #endif  // defined(ANGLE_SHARED_LIBVULKAN)
865 
866     mDisplay                         = display;
867     const egl::AttributeMap &attribs = mDisplay->getAttributeMap();
868     angle::vk::ScopedVkLoaderEnvironment scopedEnvironment(ShouldUseValidationLayers(attribs),
869                                                            ChooseICDFromAttribs(attribs));
870     mEnableValidationLayers = scopedEnvironment.canEnableValidationLayers();
871     mEnabledICD             = scopedEnvironment.getEnabledICD();
872 
873     // Gather global layer properties.
874     uint32_t instanceLayerCount = 0;
875     {
876         ANGLE_SCOPED_DISABLE_LSAN();
877         ANGLE_VK_TRY(displayVk, vkEnumerateInstanceLayerProperties(&instanceLayerCount, nullptr));
878     }
879 
880     std::vector<VkLayerProperties> instanceLayerProps(instanceLayerCount);
881     if (instanceLayerCount > 0)
882     {
883         ANGLE_SCOPED_DISABLE_LSAN();
884         ANGLE_VK_TRY(displayVk, vkEnumerateInstanceLayerProperties(&instanceLayerCount,
885                                                                    instanceLayerProps.data()));
886     }
887 
888     VulkanLayerVector enabledInstanceLayerNames;
889     if (mEnableValidationLayers)
890     {
891         bool layersRequested =
892             (attribs.get(EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE, EGL_DONT_CARE) == EGL_TRUE);
893         mEnableValidationLayers = GetAvailableValidationLayers(instanceLayerProps, layersRequested,
894                                                                &enabledInstanceLayerNames);
895     }
896 
897     if (wsiLayer)
898     {
899         enabledInstanceLayerNames.push_back(wsiLayer);
900     }
901 
902     // Enumerate instance extensions that are provided by the vulkan
903     // implementation and implicit layers.
904     uint32_t instanceExtensionCount = 0;
905     {
906         ANGLE_SCOPED_DISABLE_LSAN();
907         ANGLE_VK_TRY(displayVk, vkEnumerateInstanceExtensionProperties(
908                                     nullptr, &instanceExtensionCount, nullptr));
909     }
910 
911     std::vector<VkExtensionProperties> instanceExtensionProps(instanceExtensionCount);
912     if (instanceExtensionCount > 0)
913     {
914         ANGLE_SCOPED_DISABLE_LSAN();
915         ANGLE_VK_TRY(displayVk,
916                      vkEnumerateInstanceExtensionProperties(nullptr, &instanceExtensionCount,
917                                                             instanceExtensionProps.data()));
918     }
919 
920     // Enumerate instance extensions that are provided by explicit layers.
921     for (const char *layerName : enabledInstanceLayerNames)
922     {
923         uint32_t previousExtensionCount      = static_cast<uint32_t>(instanceExtensionProps.size());
924         uint32_t instanceLayerExtensionCount = 0;
925         {
926             ANGLE_SCOPED_DISABLE_LSAN();
927             ANGLE_VK_TRY(displayVk, vkEnumerateInstanceExtensionProperties(
928                                         layerName, &instanceLayerExtensionCount, nullptr));
929         }
930         instanceExtensionProps.resize(previousExtensionCount + instanceLayerExtensionCount);
931         {
932             ANGLE_SCOPED_DISABLE_LSAN();
933             ANGLE_VK_TRY(displayVk, vkEnumerateInstanceExtensionProperties(
934                                         layerName, &instanceLayerExtensionCount,
935                                         instanceExtensionProps.data() + previousExtensionCount));
936         }
937     }
938 
939     vk::ExtensionNameList instanceExtensionNames;
940     if (!instanceExtensionProps.empty())
941     {
942         for (const VkExtensionProperties &i : instanceExtensionProps)
943         {
944             instanceExtensionNames.push_back(i.extensionName);
945         }
946         std::sort(instanceExtensionNames.begin(), instanceExtensionNames.end(), StrLess);
947     }
948 
949     vk::ExtensionNameList enabledInstanceExtensions;
950     if (displayVk->isUsingSwapchain())
951     {
952         enabledInstanceExtensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
953     }
954     if (wsiExtension)
955     {
956         enabledInstanceExtensions.push_back(wsiExtension);
957     }
958 
959     mEnableDebugUtils = canLoadDebugUtils && mEnableValidationLayers &&
960                         ExtensionFound(VK_EXT_DEBUG_UTILS_EXTENSION_NAME, instanceExtensionNames);
961 
962     bool enableDebugReport =
963         mEnableValidationLayers && !mEnableDebugUtils &&
964         ExtensionFound(VK_EXT_DEBUG_REPORT_EXTENSION_NAME, instanceExtensionNames);
965 
966     if (mEnableDebugUtils)
967     {
968         enabledInstanceExtensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
969     }
970     else if (enableDebugReport)
971     {
972         enabledInstanceExtensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
973     }
974 
975     if (ExtensionFound(VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME, instanceExtensionNames))
976     {
977         enabledInstanceExtensions.push_back(VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME);
978         ANGLE_FEATURE_CONDITION(&mFeatures, supportsSwapchainColorspace, true);
979     }
980 
981     if (ExtensionFound(VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME, instanceExtensionNames))
982     {
983         enabledInstanceExtensions.push_back(VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME);
984         ANGLE_FEATURE_CONDITION(&mFeatures, supportsSurfaceCapabilities2Extension, true);
985     }
986 
987     if (ExtensionFound(VK_KHR_SURFACE_PROTECTED_CAPABILITIES_EXTENSION_NAME,
988                        instanceExtensionNames))
989     {
990         enabledInstanceExtensions.push_back(VK_KHR_SURFACE_PROTECTED_CAPABILITIES_EXTENSION_NAME);
991         ANGLE_FEATURE_CONDITION(&mFeatures, supportsSurfaceProtectedCapabilitiesExtension, true);
992     }
993 
994     // Verify the required extensions are in the extension names set. Fail if not.
995     std::sort(enabledInstanceExtensions.begin(), enabledInstanceExtensions.end(), StrLess);
996     ANGLE_VK_TRY(displayVk,
997                  VerifyExtensionsPresent(instanceExtensionNames, enabledInstanceExtensions));
998 
999     // Enable VK_KHR_get_physical_device_properties_2 if available.
1000     if (ExtensionFound(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
1001                        instanceExtensionNames))
1002     {
1003         enabledInstanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
1004     }
1005 
1006     VkApplicationInfo applicationInfo  = {};
1007     applicationInfo.sType              = VK_STRUCTURE_TYPE_APPLICATION_INFO;
1008     std::string appName                = angle::GetExecutableName();
1009     applicationInfo.pApplicationName   = appName.c_str();
1010     applicationInfo.applicationVersion = 1;
1011     applicationInfo.pEngineName        = "ANGLE";
1012     applicationInfo.engineVersion      = 1;
1013 
1014     auto enumerateInstanceVersion = reinterpret_cast<PFN_vkEnumerateInstanceVersion>(
1015         vkGetInstanceProcAddr(mInstance, "vkEnumerateInstanceVersion"));
1016     if (!enumerateInstanceVersion)
1017     {
1018         applicationInfo.apiVersion = VK_API_VERSION_1_0;
1019     }
1020     else
1021     {
1022         uint32_t apiVersion = VK_API_VERSION_1_0;
1023         {
1024             ANGLE_SCOPED_DISABLE_LSAN();
1025             ANGLE_VK_TRY(displayVk, enumerateInstanceVersion(&apiVersion));
1026         }
1027         if ((VK_VERSION_MAJOR(apiVersion) > 1) || (VK_VERSION_MINOR(apiVersion) >= 1))
1028         {
1029             // This is the highest version of core Vulkan functionality that ANGLE uses.
1030             applicationInfo.apiVersion = kPreferredVulkanAPIVersion;
1031         }
1032         else
1033         {
1034             // Since only 1.0 instance-level functionality is available, this must set to 1.0.
1035             applicationInfo.apiVersion = VK_API_VERSION_1_0;
1036         }
1037     }
1038 
1039     VkInstanceCreateInfo instanceInfo = {};
1040     instanceInfo.sType                = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
1041     instanceInfo.flags                = 0;
1042     instanceInfo.pApplicationInfo     = &applicationInfo;
1043 
1044     // Enable requested layers and extensions.
1045     instanceInfo.enabledExtensionCount = static_cast<uint32_t>(enabledInstanceExtensions.size());
1046     instanceInfo.ppEnabledExtensionNames =
1047         enabledInstanceExtensions.empty() ? nullptr : enabledInstanceExtensions.data();
1048     instanceInfo.enabledLayerCount   = static_cast<uint32_t>(enabledInstanceLayerNames.size());
1049     instanceInfo.ppEnabledLayerNames = enabledInstanceLayerNames.data();
1050 
1051     VkValidationFeatureEnableEXT enabledFeatures[] = {
1052         VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT};
1053     VkValidationFeaturesEXT validationFeatures       = {};
1054     validationFeatures.sType                         = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT;
1055     validationFeatures.enabledValidationFeatureCount = 1;
1056     validationFeatures.pEnabledValidationFeatures    = enabledFeatures;
1057 
1058     if (mEnableValidationLayers)
1059     {
1060         // Enable best practices output which includes perfdoc layer
1061         vk::AddToPNextChain(&instanceInfo, &validationFeatures);
1062     }
1063 
1064     ANGLE_VK_TRY(displayVk, vkCreateInstance(&instanceInfo, nullptr, &mInstance));
1065 #if defined(ANGLE_SHARED_LIBVULKAN)
1066     // Load volk if we are linking dynamically
1067     volkLoadInstance(mInstance);
1068 #endif  // defined(ANGLE_SHARED_LIBVULKAN)
1069 
1070     if (mEnableDebugUtils)
1071     {
1072         // Use the newer EXT_debug_utils if it exists.
1073 #if !defined(ANGLE_SHARED_LIBVULKAN)
1074         InitDebugUtilsEXTFunctions(mInstance);
1075 #endif  // !defined(ANGLE_SHARED_LIBVULKAN)
1076 
1077         // Create the messenger callback.
1078         VkDebugUtilsMessengerCreateInfoEXT messengerInfo = {};
1079 
1080         constexpr VkDebugUtilsMessageSeverityFlagsEXT kSeveritiesToLog =
1081             VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT |
1082             VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
1083 
1084         constexpr VkDebugUtilsMessageTypeFlagsEXT kMessagesToLog =
1085             VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
1086             VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
1087             VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
1088 
1089         messengerInfo.sType           = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
1090         messengerInfo.messageSeverity = kSeveritiesToLog;
1091         messengerInfo.messageType     = kMessagesToLog;
1092         messengerInfo.pfnUserCallback = &DebugUtilsMessenger;
1093         messengerInfo.pUserData       = this;
1094 
1095         ANGLE_VK_TRY(displayVk, vkCreateDebugUtilsMessengerEXT(mInstance, &messengerInfo, nullptr,
1096                                                                &mDebugUtilsMessenger));
1097     }
1098     else if (enableDebugReport)
1099     {
1100         // Fallback to EXT_debug_report.
1101 #if !defined(ANGLE_SHARED_LIBVULKAN)
1102         InitDebugReportEXTFunctions(mInstance);
1103 #endif  // !defined(ANGLE_SHARED_LIBVULKAN)
1104 
1105         VkDebugReportCallbackCreateInfoEXT debugReportInfo = {};
1106 
1107         debugReportInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
1108         debugReportInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT;
1109         debugReportInfo.pfnCallback = &DebugReportCallback;
1110         debugReportInfo.pUserData   = this;
1111 
1112         ANGLE_VK_TRY(displayVk, vkCreateDebugReportCallbackEXT(mInstance, &debugReportInfo, nullptr,
1113                                                                &mDebugReportCallback));
1114     }
1115 
1116     if (std::find(enabledInstanceExtensions.begin(), enabledInstanceExtensions.end(),
1117                   VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME) !=
1118         enabledInstanceExtensions.end())
1119     {
1120 #if !defined(ANGLE_SHARED_LIBVULKAN)
1121         InitGetPhysicalDeviceProperties2KHRFunctions(mInstance);
1122 #endif  // !defined(ANGLE_SHARED_LIBVULKAN)
1123         ASSERT(vkGetPhysicalDeviceProperties2KHR);
1124     }
1125 
1126     uint32_t physicalDeviceCount = 0;
1127     ANGLE_VK_TRY(displayVk, vkEnumeratePhysicalDevices(mInstance, &physicalDeviceCount, nullptr));
1128     ANGLE_VK_CHECK(displayVk, physicalDeviceCount > 0, VK_ERROR_INITIALIZATION_FAILED);
1129 
1130     // TODO(jmadill): Handle multiple physical devices. For now, use the first device.
1131     std::vector<VkPhysicalDevice> physicalDevices(physicalDeviceCount);
1132     ANGLE_VK_TRY(displayVk, vkEnumeratePhysicalDevices(mInstance, &physicalDeviceCount,
1133                                                        physicalDevices.data()));
1134     ChoosePhysicalDevice(physicalDevices, mEnabledICD, &mPhysicalDevice,
1135                          &mPhysicalDeviceProperties);
1136 
1137     mGarbageCollectionFlushThreshold =
1138         static_cast<uint32_t>(mPhysicalDeviceProperties.limits.maxMemoryAllocationCount *
1139                               kPercentMaxMemoryAllocationCount);
1140 
1141     vkGetPhysicalDeviceFeatures(mPhysicalDevice, &mPhysicalDeviceFeatures);
1142 
1143     // Ensure we can find a graphics queue family.
1144     uint32_t queueFamilyCount = 0;
1145     vkGetPhysicalDeviceQueueFamilyProperties(mPhysicalDevice, &queueFamilyCount, nullptr);
1146 
1147     ANGLE_VK_CHECK(displayVk, queueFamilyCount > 0, VK_ERROR_INITIALIZATION_FAILED);
1148 
1149     mQueueFamilyProperties.resize(queueFamilyCount);
1150     vkGetPhysicalDeviceQueueFamilyProperties(mPhysicalDevice, &queueFamilyCount,
1151                                              mQueueFamilyProperties.data());
1152 
1153     uint32_t queueFamilyMatchCount = 0;
1154     // Try first for a protected graphics queue family
1155     uint32_t firstGraphicsQueueFamily = vk::QueueFamily::FindIndex(
1156         mQueueFamilyProperties,
1157         (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_PROTECTED_BIT), 0,
1158         &queueFamilyMatchCount);
1159     // else just a graphics queue family
1160     if (queueFamilyMatchCount == 0)
1161     {
1162         firstGraphicsQueueFamily = vk::QueueFamily::FindIndex(
1163             mQueueFamilyProperties, (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT), 0,
1164             &queueFamilyMatchCount);
1165     }
1166     ANGLE_VK_CHECK(displayVk, queueFamilyMatchCount > 0, VK_ERROR_INITIALIZATION_FAILED);
1167 
1168     // If only one queue family, go ahead and initialize the device. If there is more than one
1169     // queue, we'll have to wait until we see a WindowSurface to know which supports present.
1170     if (queueFamilyMatchCount == 1)
1171     {
1172         ANGLE_TRY(initializeDevice(displayVk, firstGraphicsQueueFamily));
1173     }
1174 
1175     VkDeviceSize preferredLargeHeapBlockSize = 0;
1176     if (mFeatures.preferredLargeHeapBlockSize4MB.enabled)
1177     {
1178         // This number matches Chromium and was picked by looking at memory usage of
1179         // Android apps. The allocator will start making blocks at 1/8 the max size
1180         // and builds up block size as needed before capping at the max set here.
1181         preferredLargeHeapBlockSize = 4 * 1024 * 1024;
1182     }
1183 
1184     // Create VMA allocator
1185     ANGLE_VK_TRY(displayVk,
1186                  mAllocator.init(mPhysicalDevice, mDevice, mInstance, applicationInfo.apiVersion,
1187                                  preferredLargeHeapBlockSize));
1188 
1189     // Store the physical device memory properties so we can find the right memory pools.
1190     mMemoryProperties.init(mPhysicalDevice);
1191 
1192     {
1193         ANGLE_TRACE_EVENT0("gpu.angle,startup", "GlslangWarmup");
1194         sh::InitializeGlslang();
1195     }
1196 
1197     // Initialize the format table.
1198     mFormatTable.initialize(this, &mNativeTextureCaps, &mNativeCaps.compressedTextureFormats);
1199 
1200     setGlobalDebugAnnotator();
1201 
1202     return angle::Result::Continue;
1203 }
1204 
queryDeviceExtensionFeatures(const vk::ExtensionNameList & deviceExtensionNames)1205 void RendererVk::queryDeviceExtensionFeatures(const vk::ExtensionNameList &deviceExtensionNames)
1206 {
1207     // Default initialize all extension features to false.
1208     mLineRasterizationFeatures = {};
1209     mLineRasterizationFeatures.sType =
1210         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT;
1211 
1212     mProvokingVertexFeatures = {};
1213     mProvokingVertexFeatures.sType =
1214         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT;
1215 
1216     mVertexAttributeDivisorFeatures = {};
1217     mVertexAttributeDivisorFeatures.sType =
1218         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT;
1219 
1220     mVertexAttributeDivisorProperties = {};
1221     mVertexAttributeDivisorProperties.sType =
1222         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT;
1223 
1224     mTransformFeedbackFeatures = {};
1225     mTransformFeedbackFeatures.sType =
1226         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT;
1227 
1228     mIndexTypeUint8Features       = {};
1229     mIndexTypeUint8Features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT;
1230 
1231     mSubgroupProperties       = {};
1232     mSubgroupProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES;
1233 
1234     mMemoryReportFeatures = {};
1235     mMemoryReportFeatures.sType =
1236         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_MEMORY_REPORT_FEATURES_EXT;
1237 
1238     mExternalMemoryHostProperties = {};
1239     mExternalMemoryHostProperties.sType =
1240         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT;
1241 
1242     mShaderFloat16Int8Features = {};
1243     mShaderFloat16Int8Features.sType =
1244         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES;
1245 
1246     mDepthStencilResolveProperties = {};
1247     mDepthStencilResolveProperties.sType =
1248         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES;
1249 
1250     mCustomBorderColorFeatures = {};
1251     mCustomBorderColorFeatures.sType =
1252         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT;
1253 
1254     mMultisampledRenderToSingleSampledFeatures = {};
1255     mMultisampledRenderToSingleSampledFeatures.sType =
1256         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_FEATURES_EXT;
1257 
1258     mMultiviewFeatures       = {};
1259     mMultiviewFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES;
1260 
1261     mMultiviewProperties       = {};
1262     mMultiviewProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES;
1263 
1264     mDriverProperties       = {};
1265     mDriverProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES;
1266 
1267     mExternalFenceProperties       = {};
1268     mExternalFenceProperties.sType = VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES;
1269 
1270     mExternalSemaphoreProperties       = {};
1271     mExternalSemaphoreProperties.sType = VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES;
1272 
1273     mSamplerYcbcrConversionFeatures = {};
1274     mSamplerYcbcrConversionFeatures.sType =
1275         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES;
1276 
1277     mProtectedMemoryFeatures       = {};
1278     mProtectedMemoryFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES;
1279 
1280     mProtectedMemoryProperties = {};
1281     mProtectedMemoryProperties.sType =
1282         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES;
1283 
1284     if (!vkGetPhysicalDeviceProperties2KHR || !vkGetPhysicalDeviceFeatures2KHR)
1285     {
1286         return;
1287     }
1288 
1289     // Query features and properties.
1290     VkPhysicalDeviceFeatures2KHR deviceFeatures = {};
1291     deviceFeatures.sType                        = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
1292 
1293     VkPhysicalDeviceProperties2 deviceProperties = {};
1294     deviceProperties.sType                       = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
1295 
1296     // Query line rasterization features
1297     if (ExtensionFound(VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME, deviceExtensionNames))
1298     {
1299         vk::AddToPNextChain(&deviceFeatures, &mLineRasterizationFeatures);
1300     }
1301 
1302     // Query provoking vertex features
1303     if (ExtensionFound(VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME, deviceExtensionNames))
1304     {
1305         vk::AddToPNextChain(&deviceFeatures, &mProvokingVertexFeatures);
1306     }
1307 
1308     // Query attribute divisor features and properties
1309     if (ExtensionFound(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME, deviceExtensionNames))
1310     {
1311         vk::AddToPNextChain(&deviceFeatures, &mVertexAttributeDivisorFeatures);
1312         vk::AddToPNextChain(&deviceProperties, &mVertexAttributeDivisorProperties);
1313     }
1314 
1315     // Query transform feedback features
1316     if (ExtensionFound(VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME, deviceExtensionNames))
1317     {
1318         vk::AddToPNextChain(&deviceFeatures, &mTransformFeedbackFeatures);
1319     }
1320 
1321     // Query uint8 index type features
1322     if (ExtensionFound(VK_EXT_INDEX_TYPE_UINT8_EXTENSION_NAME, deviceExtensionNames))
1323     {
1324         vk::AddToPNextChain(&deviceFeatures, &mIndexTypeUint8Features);
1325     }
1326 
1327     // Query memory report features
1328     if (ExtensionFound(VK_EXT_DEVICE_MEMORY_REPORT_EXTENSION_NAME, deviceExtensionNames))
1329     {
1330         vk::AddToPNextChain(&deviceFeatures, &mMemoryReportFeatures);
1331     }
1332 
1333     // Query external memory host properties
1334     if (ExtensionFound(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME, deviceExtensionNames))
1335     {
1336         vk::AddToPNextChain(&deviceProperties, &mExternalMemoryHostProperties);
1337     }
1338 
1339     // Query Ycbcr conversion properties
1340     if (ExtensionFound(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME, deviceExtensionNames))
1341     {
1342         vk::AddToPNextChain(&deviceFeatures, &mSamplerYcbcrConversionFeatures);
1343     }
1344 
1345     // Query float16/int8 features
1346     if (ExtensionFound(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME, deviceExtensionNames))
1347     {
1348         vk::AddToPNextChain(&deviceFeatures, &mShaderFloat16Int8Features);
1349     }
1350 
1351     // Query depth/stencil resolve properties
1352     if (ExtensionFound(VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME, deviceExtensionNames))
1353     {
1354         vk::AddToPNextChain(&deviceProperties, &mDepthStencilResolveProperties);
1355     }
1356 
1357     // Query multisampled render to single-sampled features
1358     if (ExtensionFound(VK_EXT_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_EXTENSION_NAME,
1359                        deviceExtensionNames))
1360     {
1361         vk::AddToPNextChain(&deviceFeatures, &mMultisampledRenderToSingleSampledFeatures);
1362     }
1363 
1364     // Query multiview features and properties
1365     if (ExtensionFound(VK_KHR_MULTIVIEW_EXTENSION_NAME, deviceExtensionNames))
1366     {
1367         vk::AddToPNextChain(&deviceFeatures, &mMultiviewFeatures);
1368         vk::AddToPNextChain(&deviceProperties, &mMultiviewProperties);
1369     }
1370 
1371     // Query driver properties
1372     if (ExtensionFound(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME, deviceExtensionNames))
1373     {
1374         vk::AddToPNextChain(&deviceProperties, &mDriverProperties);
1375     }
1376 
1377     // Query custom border color features
1378     if (ExtensionFound(VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME, deviceExtensionNames))
1379     {
1380         vk::AddToPNextChain(&deviceFeatures, &mCustomBorderColorFeatures);
1381     }
1382 
1383     // Query subgroup properties
1384     vk::AddToPNextChain(&deviceProperties, &mSubgroupProperties);
1385 
1386     // Query protected memory features and properties
1387     if (mPhysicalDeviceProperties.apiVersion >= VK_MAKE_VERSION(1, 1, 0))
1388     {
1389         vk::AddToPNextChain(&deviceFeatures, &mProtectedMemoryFeatures);
1390         vk::AddToPNextChain(&deviceProperties, &mProtectedMemoryProperties);
1391     }
1392 
1393     vkGetPhysicalDeviceFeatures2KHR(mPhysicalDevice, &deviceFeatures);
1394     vkGetPhysicalDeviceProperties2KHR(mPhysicalDevice, &deviceProperties);
1395 
1396     // Fence properties
1397     if (mFeatures.supportsExternalFenceCapabilities.enabled)
1398     {
1399         VkPhysicalDeviceExternalFenceInfo externalFenceInfo = {};
1400         externalFenceInfo.sType      = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO;
1401         externalFenceInfo.handleType = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR;
1402 
1403         vkGetPhysicalDeviceExternalFencePropertiesKHR(mPhysicalDevice, &externalFenceInfo,
1404                                                       &mExternalFenceProperties);
1405     }
1406 
1407     // Semaphore properties
1408     if (mFeatures.supportsExternalSemaphoreCapabilities.enabled)
1409     {
1410         VkPhysicalDeviceExternalSemaphoreInfo externalSemaphoreInfo = {};
1411         externalSemaphoreInfo.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO;
1412         externalSemaphoreInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR;
1413 
1414         vkGetPhysicalDeviceExternalSemaphorePropertiesKHR(mPhysicalDevice, &externalSemaphoreInfo,
1415                                                           &mExternalSemaphoreProperties);
1416     }
1417 
1418     // Clean up pNext chains
1419     mLineRasterizationFeatures.pNext                 = nullptr;
1420     mMemoryReportFeatures.pNext                      = nullptr;
1421     mProvokingVertexFeatures.pNext                   = nullptr;
1422     mVertexAttributeDivisorFeatures.pNext            = nullptr;
1423     mVertexAttributeDivisorProperties.pNext          = nullptr;
1424     mTransformFeedbackFeatures.pNext                 = nullptr;
1425     mIndexTypeUint8Features.pNext                    = nullptr;
1426     mSubgroupProperties.pNext                        = nullptr;
1427     mExternalMemoryHostProperties.pNext              = nullptr;
1428     mCustomBorderColorFeatures.pNext                 = nullptr;
1429     mShaderFloat16Int8Features.pNext                 = nullptr;
1430     mDepthStencilResolveProperties.pNext             = nullptr;
1431     mMultisampledRenderToSingleSampledFeatures.pNext = nullptr;
1432     mMultiviewFeatures.pNext                         = nullptr;
1433     mMultiviewProperties.pNext                       = nullptr;
1434     mDriverProperties.pNext                          = nullptr;
1435     mSamplerYcbcrConversionFeatures.pNext            = nullptr;
1436     mProtectedMemoryFeatures.pNext                   = nullptr;
1437     mProtectedMemoryProperties.pNext                 = nullptr;
1438 }
1439 
initializeDevice(DisplayVk * displayVk,uint32_t queueFamilyIndex)1440 angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueFamilyIndex)
1441 {
1442     uint32_t deviceLayerCount = 0;
1443     ANGLE_VK_TRY(displayVk,
1444                  vkEnumerateDeviceLayerProperties(mPhysicalDevice, &deviceLayerCount, nullptr));
1445 
1446     std::vector<VkLayerProperties> deviceLayerProps(deviceLayerCount);
1447     if (deviceLayerCount > 0)
1448     {
1449         ANGLE_VK_TRY(displayVk, vkEnumerateDeviceLayerProperties(mPhysicalDevice, &deviceLayerCount,
1450                                                                  deviceLayerProps.data()));
1451     }
1452 
1453     VulkanLayerVector enabledDeviceLayerNames;
1454     if (mEnableValidationLayers)
1455     {
1456         mEnableValidationLayers =
1457             GetAvailableValidationLayers(deviceLayerProps, false, &enabledDeviceLayerNames);
1458     }
1459 
1460     const char *wsiLayer = displayVk->getWSILayer();
1461     if (wsiLayer)
1462     {
1463         enabledDeviceLayerNames.push_back(wsiLayer);
1464     }
1465 
1466     // Enumerate device extensions that are provided by the vulkan
1467     // implementation and implicit layers.
1468     uint32_t deviceExtensionCount = 0;
1469     ANGLE_VK_TRY(displayVk, vkEnumerateDeviceExtensionProperties(mPhysicalDevice, nullptr,
1470                                                                  &deviceExtensionCount, nullptr));
1471 
1472     std::vector<VkExtensionProperties> deviceExtensionProps(deviceExtensionCount);
1473     if (deviceExtensionCount > 0)
1474     {
1475         ANGLE_VK_TRY(displayVk, vkEnumerateDeviceExtensionProperties(mPhysicalDevice, nullptr,
1476                                                                      &deviceExtensionCount,
1477                                                                      deviceExtensionProps.data()));
1478     }
1479 
1480     // Enumerate device extensions that are provided by explicit layers.
1481     for (const char *layerName : enabledDeviceLayerNames)
1482     {
1483         uint32_t previousExtensionCount    = static_cast<uint32_t>(deviceExtensionProps.size());
1484         uint32_t deviceLayerExtensionCount = 0;
1485         ANGLE_VK_TRY(displayVk,
1486                      vkEnumerateDeviceExtensionProperties(mPhysicalDevice, layerName,
1487                                                           &deviceLayerExtensionCount, nullptr));
1488         deviceExtensionProps.resize(previousExtensionCount + deviceLayerExtensionCount);
1489         ANGLE_VK_TRY(displayVk, vkEnumerateDeviceExtensionProperties(
1490                                     mPhysicalDevice, layerName, &deviceLayerExtensionCount,
1491                                     deviceExtensionProps.data() + previousExtensionCount));
1492     }
1493 
1494     vk::ExtensionNameList deviceExtensionNames;
1495     if (!deviceExtensionProps.empty())
1496     {
1497         ASSERT(deviceExtensionNames.size() <= deviceExtensionProps.size());
1498         for (const VkExtensionProperties &prop : deviceExtensionProps)
1499         {
1500             deviceExtensionNames.push_back(prop.extensionName);
1501         }
1502         std::sort(deviceExtensionNames.begin(), deviceExtensionNames.end(), StrLess);
1503     }
1504 
1505     vk::ExtensionNameList enabledDeviceExtensions;
1506     if (displayVk->isUsingSwapchain())
1507     {
1508         enabledDeviceExtensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
1509     }
1510 
1511     // Query extensions and their features.
1512     queryDeviceExtensionFeatures(deviceExtensionNames);
1513 
1514     // Initialize features and workarounds.
1515     initFeatures(displayVk, deviceExtensionNames);
1516 
1517     // Enable VK_EXT_depth_clip_enable, if supported
1518     if (ExtensionFound(VK_EXT_DEPTH_CLIP_ENABLE_EXTENSION_NAME, deviceExtensionNames))
1519     {
1520         enabledDeviceExtensions.push_back(VK_EXT_DEPTH_CLIP_ENABLE_EXTENSION_NAME);
1521     }
1522 
1523     // Enable VK_KHR_get_memory_requirements2, if supported
1524     bool hasGetMemoryRequirements2KHR = false;
1525     if (ExtensionFound(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME, deviceExtensionNames))
1526     {
1527         enabledDeviceExtensions.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME);
1528         hasGetMemoryRequirements2KHR = true;
1529     }
1530 
1531     // Enable VK_KHR_bind_memory2, if supported
1532     bool hasBindMemory2KHR = false;
1533     if (ExtensionFound(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME, deviceExtensionNames))
1534     {
1535         hasBindMemory2KHR = true;
1536         enabledDeviceExtensions.push_back(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME);
1537     }
1538 
1539     // Enable KHR_MAINTENANCE1 to support viewport flipping.
1540     if (mPhysicalDeviceProperties.apiVersion < VK_MAKE_VERSION(1, 1, 0))
1541     {
1542         enabledDeviceExtensions.push_back(VK_KHR_MAINTENANCE1_EXTENSION_NAME);
1543     }
1544 
1545     if (getFeatures().supportsRenderpass2.enabled)
1546     {
1547         enabledDeviceExtensions.push_back(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
1548     }
1549 
1550     if (getFeatures().supportsIncrementalPresent.enabled)
1551     {
1552         enabledDeviceExtensions.push_back(VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME);
1553     }
1554 
1555 #if defined(ANGLE_PLATFORM_ANDROID)
1556     if (getFeatures().supportsAndroidHardwareBuffer.enabled)
1557     {
1558         enabledDeviceExtensions.push_back(VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME);
1559         enabledDeviceExtensions.push_back(
1560             VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME);
1561 #    if !defined(ANGLE_SHARED_LIBVULKAN)
1562         InitExternalMemoryHardwareBufferANDROIDFunctions(mInstance);
1563 #    endif  // !defined(ANGLE_SHARED_LIBVULKAN)
1564     }
1565 #else
1566     ASSERT(!getFeatures().supportsAndroidHardwareBuffer.enabled);
1567 #endif
1568 
1569 #if defined(ANGLE_PLATFORM_GGP)
1570     if (getFeatures().supportsGGPFrameToken.enabled)
1571     {
1572         enabledDeviceExtensions.push_back(VK_GGP_FRAME_TOKEN_EXTENSION_NAME);
1573     }
1574     ANGLE_VK_CHECK(displayVk, getFeatures().supportsGGPFrameToken.enabled,
1575                    VK_ERROR_EXTENSION_NOT_PRESENT);
1576 #else
1577     ASSERT(!getFeatures().supportsGGPFrameToken.enabled);
1578 #endif
1579 
1580     if (getFeatures().supportsAndroidHardwareBuffer.enabled ||
1581         getFeatures().supportsExternalMemoryFd.enabled ||
1582         getFeatures().supportsExternalMemoryFuchsia.enabled)
1583     {
1584         enabledDeviceExtensions.push_back(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME);
1585     }
1586 
1587     if (getFeatures().supportsExternalMemoryFd.enabled)
1588     {
1589         enabledDeviceExtensions.push_back(VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME);
1590     }
1591 
1592     if (getFeatures().supportsExternalMemoryFuchsia.enabled)
1593     {
1594         enabledDeviceExtensions.push_back(VK_FUCHSIA_EXTERNAL_MEMORY_EXTENSION_NAME);
1595     }
1596 
1597     if (getFeatures().supportsExternalSemaphoreFd.enabled ||
1598         getFeatures().supportsExternalSemaphoreFuchsia.enabled)
1599     {
1600         enabledDeviceExtensions.push_back(VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME);
1601 #if !defined(ANGLE_SHARED_LIBVULKAN)
1602         InitExternalSemaphoreFdFunctions(mInstance);
1603 #endif  // !defined(ANGLE_SHARED_LIBVULKAN)
1604     }
1605 
1606     if (getFeatures().supportsExternalSemaphoreCapabilities.enabled)
1607     {
1608         enabledDeviceExtensions.push_back(VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME);
1609     }
1610 
1611     if (getFeatures().supportsExternalFenceCapabilities.enabled)
1612     {
1613         enabledDeviceExtensions.push_back(VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME);
1614     }
1615 
1616     if (getFeatures().supportsExternalSemaphoreFd.enabled)
1617     {
1618         enabledDeviceExtensions.push_back(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME);
1619     }
1620 
1621     if (getFeatures().supportsExternalSemaphoreCapabilities.enabled)
1622     {
1623         enabledDeviceExtensions.push_back(VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME);
1624 #if !defined(ANGLE_SHARED_LIBVULKAN)
1625         InitExternalSemaphoreCapabilitiesFunctions(mInstance);
1626 #endif  // !defined(ANGLE_SHARED_LIBVULKAN)
1627     }
1628 
1629     if (getFeatures().supportsExternalFenceFd.enabled)
1630     {
1631         enabledDeviceExtensions.push_back(VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME);
1632 #if !defined(ANGLE_SHARED_LIBVULKAN)
1633         InitExternalFenceFdFunctions(mInstance);
1634 #endif  // !defined(ANGLE_SHARED_LIBVULKAN)
1635     }
1636 
1637     if (getFeatures().supportsExternalFenceCapabilities.enabled)
1638     {
1639         enabledDeviceExtensions.push_back(VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME);
1640 #if !defined(ANGLE_SHARED_LIBVULKAN)
1641         InitExternalFenceCapabilitiesFunctions(mInstance);
1642 #endif  // !defined(ANGLE_SHARED_LIBVULKAN)
1643     }
1644 
1645     if (getFeatures().supportsExternalSemaphoreFuchsia.enabled)
1646     {
1647         enabledDeviceExtensions.push_back(VK_FUCHSIA_EXTERNAL_SEMAPHORE_EXTENSION_NAME);
1648     }
1649 
1650     if (getFeatures().supportsShaderStencilExport.enabled)
1651     {
1652         enabledDeviceExtensions.push_back(VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME);
1653     }
1654 
1655     if (getFeatures().supportsRenderPassStoreOpNoneQCOM.enabled)
1656     {
1657         enabledDeviceExtensions.push_back(VK_QCOM_RENDER_PASS_STORE_OPS_EXTENSION_NAME);
1658     }
1659 
1660     if (getFeatures().supportsImageFormatList.enabled)
1661     {
1662         enabledDeviceExtensions.push_back(VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME);
1663     }
1664 
1665     std::sort(enabledDeviceExtensions.begin(), enabledDeviceExtensions.end(), StrLess);
1666     ANGLE_VK_TRY(displayVk, VerifyExtensionsPresent(deviceExtensionNames, enabledDeviceExtensions));
1667 
1668     // Select additional features to be enabled.
1669     VkPhysicalDeviceFeatures2KHR enabledFeatures = {};
1670     enabledFeatures.sType                        = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
1671     // Used to support cubemap array:
1672     enabledFeatures.features.imageCubeArray = getFeatures().supportsImageCubeArray.enabled;
1673     // Used to support framebuffers with multiple attachments:
1674     enabledFeatures.features.independentBlend = mPhysicalDeviceFeatures.independentBlend;
1675     // Used to support robust buffer access:
1676     enabledFeatures.features.robustBufferAccess = mPhysicalDeviceFeatures.robustBufferAccess;
1677     // Used to support Anisotropic filtering:
1678     enabledFeatures.features.samplerAnisotropy = mPhysicalDeviceFeatures.samplerAnisotropy;
1679     // Used to support wide lines:
1680     enabledFeatures.features.wideLines = mPhysicalDeviceFeatures.wideLines;
1681     // Used to emulate transform feedback:
1682     enabledFeatures.features.vertexPipelineStoresAndAtomics =
1683         mPhysicalDeviceFeatures.vertexPipelineStoresAndAtomics;
1684     // Used to implement storage buffers and images in the fragment shader:
1685     enabledFeatures.features.fragmentStoresAndAtomics =
1686         mPhysicalDeviceFeatures.fragmentStoresAndAtomics;
1687     // Used to emulate the primitives generated query:
1688     enabledFeatures.features.pipelineStatisticsQuery =
1689         getFeatures().supportsPipelineStatisticsQuery.enabled;
1690     // Used to support geometry shaders:
1691     enabledFeatures.features.geometryShader = mPhysicalDeviceFeatures.geometryShader;
1692     // Used to support EXT_gpu_shader5:
1693     enabledFeatures.features.shaderImageGatherExtended =
1694         mPhysicalDeviceFeatures.shaderImageGatherExtended;
1695     // Used to support EXT_gpu_shader5:
1696     enabledFeatures.features.shaderUniformBufferArrayDynamicIndexing =
1697         mPhysicalDeviceFeatures.shaderUniformBufferArrayDynamicIndexing;
1698     enabledFeatures.features.shaderSampledImageArrayDynamicIndexing =
1699         mPhysicalDeviceFeatures.shaderSampledImageArrayDynamicIndexing;
1700     // Used to support APPLE_clip_distance
1701     enabledFeatures.features.shaderClipDistance = mPhysicalDeviceFeatures.shaderClipDistance;
1702     // Used to support OES_sample_shading
1703     enabledFeatures.features.sampleRateShading = mPhysicalDeviceFeatures.sampleRateShading;
1704     // Used to support depth clears through draw calls.
1705     enabledFeatures.features.depthClamp = mPhysicalDeviceFeatures.depthClamp;
1706     // Used to support EXT_clip_cull_distance
1707     enabledFeatures.features.shaderCullDistance = mPhysicalDeviceFeatures.shaderCullDistance;
1708     // Used to support tessellation Shader:
1709     enabledFeatures.features.tessellationShader = mPhysicalDeviceFeatures.tessellationShader;
1710     // Used to support EXT_blend_func_extended
1711     enabledFeatures.features.dualSrcBlend = mPhysicalDeviceFeatures.dualSrcBlend;
1712 
1713     if (!vk::CommandBuffer::ExecutesInline())
1714     {
1715         enabledFeatures.features.inheritedQueries = mPhysicalDeviceFeatures.inheritedQueries;
1716     }
1717 
1718     // Setup device initialization struct
1719     VkDeviceCreateInfo createInfo = {};
1720 
1721     // Based on available extension features, decide on which extensions and features to enable.
1722 
1723     if (mLineRasterizationFeatures.bresenhamLines)
1724     {
1725         enabledDeviceExtensions.push_back(VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME);
1726         vk::AddToPNextChain(&createInfo, &mLineRasterizationFeatures);
1727     }
1728 
1729     if (mProvokingVertexFeatures.provokingVertexLast)
1730     {
1731         enabledDeviceExtensions.push_back(VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME);
1732         vk::AddToPNextChain(&createInfo, &mProvokingVertexFeatures);
1733     }
1734 
1735     if (mVertexAttributeDivisorFeatures.vertexAttributeInstanceRateDivisor)
1736     {
1737         enabledDeviceExtensions.push_back(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME);
1738         vk::AddToPNextChain(&createInfo, &mVertexAttributeDivisorFeatures);
1739 
1740         // We only store 8 bit divisor in GraphicsPipelineDesc so capping value & we emulate if
1741         // exceeded
1742         mMaxVertexAttribDivisor =
1743             std::min(mVertexAttributeDivisorProperties.maxVertexAttribDivisor,
1744                      static_cast<uint32_t>(std::numeric_limits<uint8_t>::max()));
1745     }
1746 
1747     if (getFeatures().supportsTransformFeedbackExtension.enabled)
1748     {
1749         enabledDeviceExtensions.push_back(VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME);
1750         vk::AddToPNextChain(&createInfo, &mTransformFeedbackFeatures);
1751     }
1752 
1753     if (getFeatures().supportsCustomBorderColorEXT.enabled)
1754     {
1755         enabledDeviceExtensions.push_back(VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME);
1756         vk::AddToPNextChain(&createInfo, &mCustomBorderColorFeatures);
1757     }
1758 
1759     if (getFeatures().supportsIndexTypeUint8.enabled)
1760     {
1761         enabledDeviceExtensions.push_back(VK_EXT_INDEX_TYPE_UINT8_EXTENSION_NAME);
1762         vk::AddToPNextChain(&createInfo, &mIndexTypeUint8Features);
1763     }
1764 
1765     if (getFeatures().supportsDepthStencilResolve.enabled)
1766     {
1767         enabledDeviceExtensions.push_back(VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME);
1768     }
1769 
1770     if (getFeatures().supportsMultisampledRenderToSingleSampled.enabled)
1771     {
1772         enabledDeviceExtensions.push_back(
1773             VK_EXT_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_EXTENSION_NAME);
1774         vk::AddToPNextChain(&createInfo, &mMultisampledRenderToSingleSampledFeatures);
1775     }
1776 
1777     if (getFeatures().supportsMultiview.enabled)
1778     {
1779         // OVR_multiview disallows multiview with geometry and tessellation, so don't request these
1780         // features.
1781         mMultiviewFeatures.multiviewGeometryShader     = VK_FALSE;
1782         mMultiviewFeatures.multiviewTessellationShader = VK_FALSE;
1783         enabledDeviceExtensions.push_back(VK_KHR_MULTIVIEW_EXTENSION_NAME);
1784         vk::AddToPNextChain(&createInfo, &mMultiviewFeatures);
1785     }
1786 
1787     if (getFeatures().logMemoryReportCallbacks.enabled ||
1788         getFeatures().logMemoryReportStats.enabled)
1789     {
1790         if (mMemoryReportFeatures.deviceMemoryReport)
1791         {
1792             enabledDeviceExtensions.push_back(VK_EXT_DEVICE_MEMORY_REPORT_EXTENSION_NAME);
1793 
1794             mMemoryReportCallback = {};
1795             mMemoryReportCallback.sType =
1796                 VK_STRUCTURE_TYPE_DEVICE_DEVICE_MEMORY_REPORT_CREATE_INFO_EXT;
1797             mMemoryReportCallback.pfnUserCallback = &MemoryReportCallback;
1798             mMemoryReportCallback.pUserData       = this;
1799             vk::AddToPNextChain(&createInfo, &mMemoryReportCallback);
1800         }
1801         else
1802         {
1803             WARN() << "Disabling the following feature(s) because driver does not support "
1804                       "VK_EXT_device_memory_report extension:";
1805             if (getFeatures().logMemoryReportStats.enabled)
1806             {
1807                 WARN() << "\tlogMemoryReportStats";
1808                 ANGLE_FEATURE_CONDITION(&mFeatures, logMemoryReportStats, false);
1809             }
1810             if (getFeatures().logMemoryReportCallbacks.enabled)
1811             {
1812                 WARN() << "\tlogMemoryReportCallbacks";
1813                 ANGLE_FEATURE_CONDITION(&mFeatures, logMemoryReportCallbacks, false);
1814             }
1815         }
1816     }
1817 
1818     if (getFeatures().supportsExternalMemoryHost.enabled)
1819     {
1820         enabledDeviceExtensions.push_back(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME);
1821         mMinImportedHostPointerAlignment =
1822             mExternalMemoryHostProperties.minImportedHostPointerAlignment;
1823 #if !defined(ANGLE_SHARED_LIBVULKAN)
1824         InitExternalMemoryHostFunctions(mInstance);
1825 #endif  // !defined(ANGLE_SHARED_LIBVULKAN)
1826     }
1827 
1828     if (getFeatures().supportsYUVSamplerConversion.enabled)
1829     {
1830         enabledDeviceExtensions.push_back(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME);
1831         vk::AddToPNextChain(&createInfo, &mSamplerYcbcrConversionFeatures);
1832     }
1833 
1834     if (getFeatures().supportsShaderFloat16.enabled)
1835     {
1836         enabledDeviceExtensions.push_back(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME);
1837         vk::AddToPNextChain(&createInfo, &mShaderFloat16Int8Features);
1838     }
1839 
1840     if (getFeatures().supportsProtectedMemory.enabled)
1841     {
1842         vk::AddToPNextChain(&createInfo, &mProtectedMemoryFeatures);
1843     }
1844 
1845     mCurrentQueueFamilyIndex = queueFamilyIndex;
1846 
1847     vk::QueueFamily queueFamily;
1848     queueFamily.initialize(mQueueFamilyProperties[queueFamilyIndex], queueFamilyIndex);
1849     ANGLE_VK_CHECK(displayVk, queueFamily.getDeviceQueueCount() > 0,
1850                    VK_ERROR_INITIALIZATION_FAILED);
1851 
1852     uint32_t queueCount = std::min(queueFamily.getDeviceQueueCount(),
1853                                    static_cast<uint32_t>(egl::ContextPriority::EnumCount));
1854 
1855     uint32_t queueCreateInfoCount              = 1;
1856     VkDeviceQueueCreateInfo queueCreateInfo[1] = {};
1857     queueCreateInfo[0].sType                   = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
1858     queueCreateInfo[0].flags =
1859         queueFamily.supportsProtected() ? VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT : 0;
1860     queueCreateInfo[0].queueFamilyIndex = queueFamilyIndex;
1861     queueCreateInfo[0].queueCount       = queueCount;
1862     queueCreateInfo[0].pQueuePriorities = vk::QueueFamily::kQueuePriorities;
1863 
1864     // Create Device
1865     createInfo.sType                 = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
1866     createInfo.flags                 = 0;
1867     createInfo.queueCreateInfoCount  = queueCreateInfoCount;
1868     createInfo.pQueueCreateInfos     = queueCreateInfo;
1869     createInfo.enabledLayerCount     = static_cast<uint32_t>(enabledDeviceLayerNames.size());
1870     createInfo.ppEnabledLayerNames   = enabledDeviceLayerNames.data();
1871     createInfo.enabledExtensionCount = static_cast<uint32_t>(enabledDeviceExtensions.size());
1872     createInfo.ppEnabledExtensionNames =
1873         enabledDeviceExtensions.empty() ? nullptr : enabledDeviceExtensions.data();
1874 
1875     // Enable core features without assuming VkPhysicalDeviceFeatures2KHR is accepted in the
1876     // pNext chain of VkDeviceCreateInfo.
1877     createInfo.pEnabledFeatures = &enabledFeatures.features;
1878 
1879     ANGLE_VK_TRY(displayVk, vkCreateDevice(mPhysicalDevice, &createInfo, nullptr, &mDevice));
1880 #if defined(ANGLE_SHARED_LIBVULKAN)
1881     // Load volk if we are loading dynamically
1882     volkLoadDevice(mDevice);
1883 #endif  // defined(ANGLE_SHARED_LIBVULKAN)
1884 
1885     vk::DeviceQueueMap graphicsQueueMap =
1886         queueFamily.initializeQueueMap(mDevice, queueFamily.supportsProtected(), 0, queueCount);
1887 
1888     if (mFeatures.asyncCommandQueue.enabled)
1889     {
1890         ANGLE_TRY(mCommandProcessor.init(displayVk, graphicsQueueMap));
1891     }
1892     else
1893     {
1894         ANGLE_TRY(mCommandQueue.init(displayVk, graphicsQueueMap));
1895     }
1896 
1897 #if !defined(ANGLE_SHARED_LIBVULKAN)
1898     if (hasGetMemoryRequirements2KHR)
1899     {
1900         InitGetMemoryRequirements2KHRFunctions(mDevice);
1901     }
1902     if (hasBindMemory2KHR)
1903     {
1904         InitBindMemory2KHRFunctions(mDevice);
1905     }
1906     if (getFeatures().supportsTransformFeedbackExtension.enabled)
1907     {
1908         InitTransformFeedbackEXTFunctions(mDevice);
1909     }
1910     if (getFeatures().supportsYUVSamplerConversion.enabled)
1911     {
1912         InitSamplerYcbcrKHRFunctions(mDevice);
1913     }
1914     if (getFeatures().supportsRenderpass2.enabled)
1915     {
1916         InitRenderPass2KHRFunctions(mDevice);
1917     }
1918 #endif  // !defined(ANGLE_SHARED_LIBVULKAN)
1919 
1920     if (getFeatures().forceMaxUniformBufferSize16KB.enabled)
1921     {
1922         mDefaultUniformBufferSize = kMinDefaultUniformBufferSize;
1923     }
1924     // Cap it with the driver limit
1925     mDefaultUniformBufferSize = std::min(
1926         mDefaultUniformBufferSize, getPhysicalDeviceProperties().limits.maxUniformBufferRange);
1927 
1928     // Initialize the vulkan pipeline cache.
1929     bool success = false;
1930     {
1931         std::lock_guard<std::mutex> lock(mPipelineCacheMutex);
1932         ANGLE_TRY(initPipelineCache(displayVk, &mPipelineCache, &success));
1933     }
1934 
1935     // Track the set of supported pipeline stages.  This is used when issuing image layout
1936     // transitions that cover many stages (such as AllGraphicsReadOnly) to mask out unsupported
1937     // stages, which avoids enumerating every possible combination of stages in the layouts.
1938     VkPipelineStageFlags unsupportedStages = 0;
1939     if (!mPhysicalDeviceFeatures.tessellationShader)
1940     {
1941         unsupportedStages |= VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT |
1942                              VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT;
1943     }
1944     if (!mPhysicalDeviceFeatures.geometryShader)
1945     {
1946         unsupportedStages |= VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
1947     }
1948     mSupportedVulkanPipelineStageMask = ~unsupportedStages;
1949 
1950     return angle::Result::Continue;
1951 }
1952 
selectPresentQueueForSurface(DisplayVk * displayVk,VkSurfaceKHR surface,uint32_t * presentQueueOut)1953 angle::Result RendererVk::selectPresentQueueForSurface(DisplayVk *displayVk,
1954                                                        VkSurfaceKHR surface,
1955                                                        uint32_t *presentQueueOut)
1956 {
1957     // We've already initialized a device, and can't re-create it unless it's never been used.
1958     // TODO(jmadill): Handle the re-creation case if necessary.
1959     if (mDevice != VK_NULL_HANDLE)
1960     {
1961         ASSERT(mCurrentQueueFamilyIndex != std::numeric_limits<uint32_t>::max());
1962 
1963         // Check if the current device supports present on this surface.
1964         VkBool32 supportsPresent = VK_FALSE;
1965         ANGLE_VK_TRY(displayVk,
1966                      vkGetPhysicalDeviceSurfaceSupportKHR(mPhysicalDevice, mCurrentQueueFamilyIndex,
1967                                                           surface, &supportsPresent));
1968 
1969         if (supportsPresent == VK_TRUE)
1970         {
1971             *presentQueueOut = mCurrentQueueFamilyIndex;
1972             return angle::Result::Continue;
1973         }
1974     }
1975 
1976     // Find a graphics and present queue.
1977     Optional<uint32_t> newPresentQueue;
1978     uint32_t queueCount = static_cast<uint32_t>(mQueueFamilyProperties.size());
1979     constexpr VkQueueFlags kGraphicsAndCompute = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT;
1980     for (uint32_t queueIndex = 0; queueIndex < queueCount; ++queueIndex)
1981     {
1982         const auto &queueInfo = mQueueFamilyProperties[queueIndex];
1983         if ((queueInfo.queueFlags & kGraphicsAndCompute) == kGraphicsAndCompute)
1984         {
1985             VkBool32 supportsPresent = VK_FALSE;
1986             ANGLE_VK_TRY(displayVk, vkGetPhysicalDeviceSurfaceSupportKHR(
1987                                         mPhysicalDevice, queueIndex, surface, &supportsPresent));
1988 
1989             if (supportsPresent == VK_TRUE)
1990             {
1991                 newPresentQueue = queueIndex;
1992                 break;
1993             }
1994         }
1995     }
1996 
1997     ANGLE_VK_CHECK(displayVk, newPresentQueue.valid(), VK_ERROR_INITIALIZATION_FAILED);
1998     ANGLE_TRY(initializeDevice(displayVk, newPresentQueue.value()));
1999 
2000     *presentQueueOut = newPresentQueue.value();
2001     return angle::Result::Continue;
2002 }
2003 
getVendorString() const2004 std::string RendererVk::getVendorString() const
2005 {
2006     return GetVendorString(mPhysicalDeviceProperties.vendorID);
2007 }
2008 
getRendererDescription() const2009 std::string RendererVk::getRendererDescription() const
2010 {
2011     std::stringstream strstr;
2012 
2013     uint32_t apiVersion = mPhysicalDeviceProperties.apiVersion;
2014 
2015     strstr << "Vulkan ";
2016     strstr << VK_VERSION_MAJOR(apiVersion) << ".";
2017     strstr << VK_VERSION_MINOR(apiVersion) << ".";
2018     strstr << VK_VERSION_PATCH(apiVersion);
2019 
2020     strstr << " (";
2021 
2022     // In the case of NVIDIA, deviceName does not necessarily contain "NVIDIA". Add "NVIDIA" so that
2023     // Vulkan end2end tests can be selectively disabled on NVIDIA. TODO(jmadill): should not be
2024     // needed after http://anglebug.com/1874 is fixed and end2end_tests use more sophisticated
2025     // driver detection.
2026     if (mPhysicalDeviceProperties.vendorID == VENDOR_ID_NVIDIA)
2027     {
2028         strstr << GetVendorString(mPhysicalDeviceProperties.vendorID) << " ";
2029     }
2030 
2031     strstr << mPhysicalDeviceProperties.deviceName;
2032     strstr << " (" << gl::FmtHex(mPhysicalDeviceProperties.deviceID) << ")";
2033 
2034     strstr << ")";
2035 
2036     return strstr.str();
2037 }
2038 
getVersionString() const2039 std::string RendererVk::getVersionString() const
2040 {
2041     std::stringstream strstr;
2042 
2043     uint32_t driverVersion = mPhysicalDeviceProperties.driverVersion;
2044     std::string driverName = std::string(mDriverProperties.driverName);
2045 
2046     if (!driverName.empty())
2047     {
2048         strstr << driverName;
2049     }
2050     else
2051     {
2052         strstr << GetVendorString(mPhysicalDeviceProperties.vendorID);
2053     }
2054 
2055     strstr << "-";
2056 
2057     if (mPhysicalDeviceProperties.vendorID == VENDOR_ID_NVIDIA)
2058     {
2059         strstr << ANGLE_VK_VERSION_MAJOR_NVIDIA(driverVersion) << ".";
2060         strstr << ANGLE_VK_VERSION_MINOR_NVIDIA(driverVersion) << ".";
2061         strstr << ANGLE_VK_VERSION_SUB_MINOR_NVIDIA(driverVersion) << ".";
2062         strstr << ANGLE_VK_VERSION_PATCH_NVIDIA(driverVersion);
2063     }
2064     else if (mPhysicalDeviceProperties.vendorID == VENDOR_ID_INTEL && IsWindows())
2065     {
2066         strstr << ANGLE_VK_VERSION_MAJOR_WIN_INTEL(driverVersion) << ".";
2067         strstr << ANGLE_VK_VERSION_MAJOR_WIN_INTEL(driverVersion) << ".";
2068     }
2069     // All other drivers use the Vulkan standard
2070     else
2071     {
2072         strstr << VK_VERSION_MAJOR(driverVersion) << ".";
2073         strstr << VK_VERSION_MINOR(driverVersion) << ".";
2074         strstr << VK_VERSION_PATCH(driverVersion);
2075     }
2076 
2077     return strstr.str();
2078 }
2079 
getMaxSupportedESVersion() const2080 gl::Version RendererVk::getMaxSupportedESVersion() const
2081 {
2082     // Current highest supported version
2083     gl::Version maxVersion = gl::Version(3, 2);
2084 
2085     // Early out without downgrading ES version if mock ICD enabled.
2086     // Mock ICD doesn't expose sufficient capabilities yet.
2087     // https://github.com/KhronosGroup/Vulkan-Tools/issues/84
2088     if (isMockICDEnabled())
2089     {
2090         return maxVersion;
2091     }
2092 
2093     // Limit to ES3.1 if there are any blockers for 3.2.
2094     if (!vk::CanSupportGPUShader5EXT(mPhysicalDeviceFeatures))
2095     {
2096         maxVersion = LimitVersionTo(maxVersion, {3, 1});
2097     }
2098 
2099     // TODO: more extension checks for 3.2.  http://anglebug.com/5366
2100     if (!mFeatures.exposeNonConformantExtensionsAndVersions.enabled)
2101     {
2102         maxVersion = LimitVersionTo(maxVersion, {3, 1});
2103     }
2104 
2105     // Limit to ES3.0 if there are any blockers for 3.1.
2106 
2107     // ES3.1 requires at least one atomic counter buffer and four storage buffers in compute.
2108     // Atomic counter buffers are emulated with storage buffers.  For simplicity, we always support
2109     // either none or IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS atomic counter buffers.  So if
2110     // Vulkan doesn't support at least that many storage buffers in compute, we don't support 3.1.
2111     const uint32_t kMinimumStorageBuffersForES31 =
2112         gl::limits::kMinimumComputeStorageBuffers +
2113         gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS;
2114     if (mPhysicalDeviceProperties.limits.maxPerStageDescriptorStorageBuffers <
2115         kMinimumStorageBuffersForES31)
2116     {
2117         maxVersion = LimitVersionTo(maxVersion, {3, 0});
2118     }
2119 
2120     // ES3.1 requires at least a maximum offset of at least 2047.
2121     // If the Vulkan implementation can't support that, we cannot support 3.1.
2122     if (mPhysicalDeviceProperties.limits.maxVertexInputAttributeOffset < 2047)
2123     {
2124         maxVersion = LimitVersionTo(maxVersion, {3, 0});
2125     }
2126 
2127     // Limit to ES2.0 if there are any blockers for 3.0.
2128     // TODO: http://anglebug.com/3972 Limit to GLES 2.0 if flat shading can't be emulated
2129 
2130     // Multisample textures (ES3.1) and multisample renderbuffers (ES3.0) require the Vulkan driver
2131     // to support the standard sample locations (in order to pass dEQP tests that check these
2132     // locations).  If the Vulkan implementation can't support that, we cannot support 3.0/3.1.
2133     if (mPhysicalDeviceProperties.limits.standardSampleLocations != VK_TRUE)
2134     {
2135         maxVersion = LimitVersionTo(maxVersion, {2, 0});
2136     }
2137 
2138     // If the command buffer doesn't support queries, we can't support ES3.
2139     if (!vk::CommandBuffer::SupportsQueries(mPhysicalDeviceFeatures))
2140     {
2141         maxVersion = LimitVersionTo(maxVersion, {2, 0});
2142     }
2143 
2144     // If independentBlend is not supported, we can't have a mix of has-alpha and emulated-alpha
2145     // render targets in a framebuffer.  We also cannot perform masked clears of multiple render
2146     // targets.
2147     if (!mPhysicalDeviceFeatures.independentBlend)
2148     {
2149         maxVersion = LimitVersionTo(maxVersion, {2, 0});
2150     }
2151 
2152     // If the Vulkan transform feedback extension is not present, we use an emulation path that
2153     // requires the vertexPipelineStoresAndAtomics feature. Without the extension or this feature,
2154     // we can't currently support transform feedback.
2155     if (!mFeatures.supportsTransformFeedbackExtension.enabled &&
2156         !mFeatures.emulateTransformFeedback.enabled)
2157     {
2158         maxVersion = LimitVersionTo(maxVersion, {2, 0});
2159     }
2160 
2161     // Limit to GLES 2.0 if maxPerStageDescriptorUniformBuffers is too low.
2162     // Table 6.31 MAX_VERTEX_UNIFORM_BLOCKS minimum value = 12
2163     // Table 6.32 MAX_FRAGMENT_UNIFORM_BLOCKS minimum value = 12
2164     // NOTE: We reserve some uniform buffers for emulation, so use the NativeCaps which takes this
2165     // into account, rather than the physical device maxPerStageDescriptorUniformBuffers limits.
2166     for (gl::ShaderType shaderType : gl::AllShaderTypes())
2167     {
2168         if (static_cast<GLuint>(getNativeCaps().maxShaderUniformBlocks[shaderType]) <
2169             gl::limits::kMinimumShaderUniformBlocks)
2170         {
2171             maxVersion = LimitVersionTo(maxVersion, {2, 0});
2172         }
2173     }
2174 
2175     // Limit to GLES 2.0 if maxVertexOutputComponents is too low.
2176     // Table 6.31 MAX VERTEX OUTPUT COMPONENTS minimum value = 64
2177     // NOTE: We reserve some vertex output components for emulation, so use the NativeCaps which
2178     // takes this into account, rather than the physical device maxVertexOutputComponents limits.
2179     if (static_cast<GLuint>(getNativeCaps().maxVertexOutputComponents) <
2180         gl::limits::kMinimumVertexOutputComponents)
2181     {
2182         maxVersion = LimitVersionTo(maxVersion, {2, 0});
2183     }
2184 
2185     return maxVersion;
2186 }
2187 
getMaxConformantESVersion() const2188 gl::Version RendererVk::getMaxConformantESVersion() const
2189 {
2190     return LimitVersionTo(getMaxSupportedESVersion(), {3, 1});
2191 }
2192 
initFeatures(DisplayVk * displayVk,const vk::ExtensionNameList & deviceExtensionNames)2193 void RendererVk::initFeatures(DisplayVk *displayVk,
2194                               const vk::ExtensionNameList &deviceExtensionNames)
2195 {
2196     if (displayVk->getState().featuresAllDisabled)
2197     {
2198         ApplyFeatureOverrides(&mFeatures, displayVk->getState());
2199         return;
2200     }
2201 
2202     constexpr uint32_t kPixel2DriverWithRelaxedPrecision        = 0x801EA000;
2203     constexpr uint32_t kPixel4DriverWithWorkingSpecConstSupport = 0x80201000;
2204 
2205     bool isAMD      = IsAMD(mPhysicalDeviceProperties.vendorID);
2206     bool isIntel    = IsIntel(mPhysicalDeviceProperties.vendorID);
2207     bool isNvidia   = IsNvidia(mPhysicalDeviceProperties.vendorID);
2208     bool isQualcomm = IsQualcomm(mPhysicalDeviceProperties.vendorID);
2209     bool isARM      = IsARM(mPhysicalDeviceProperties.vendorID);
2210     bool isPowerVR  = IsPowerVR(mPhysicalDeviceProperties.vendorID);
2211     bool isSwiftShader =
2212         IsSwiftshader(mPhysicalDeviceProperties.vendorID, mPhysicalDeviceProperties.deviceID);
2213 
2214     bool supportsNegativeViewport =
2215         ExtensionFound(VK_KHR_MAINTENANCE1_EXTENSION_NAME, deviceExtensionNames) ||
2216         mPhysicalDeviceProperties.apiVersion >= VK_API_VERSION_1_1;
2217 
2218     if (mLineRasterizationFeatures.bresenhamLines == VK_TRUE)
2219     {
2220         ASSERT(mLineRasterizationFeatures.sType ==
2221                VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT);
2222         ANGLE_FEATURE_CONDITION(&mFeatures, bresenhamLineRasterization, true);
2223     }
2224     else
2225     {
2226         // Use OpenGL line rasterization rules if extension not available by default.
2227         // TODO(jmadill): Fix Android support. http://anglebug.com/2830
2228         ANGLE_FEATURE_CONDITION(&mFeatures, basicGLLineRasterization, !IsAndroid() && !isPowerVR);
2229     }
2230 
2231     if (mProvokingVertexFeatures.provokingVertexLast == VK_TRUE)
2232     {
2233         ASSERT(mProvokingVertexFeatures.sType ==
2234                VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT);
2235         ANGLE_FEATURE_CONDITION(&mFeatures, provokingVertex, true);
2236     }
2237 
2238     // http://anglebug.com/3965
2239     ANGLE_FEATURE_CONDITION(&mFeatures, supportsProtectedMemory,
2240                             (mProtectedMemoryFeatures.protectedMemory == VK_TRUE));
2241 
2242     // Note: Protected Swapchains is not determined until we have a VkSurface to query.
2243     // So here vendors should indicate support so that protected_content extension
2244     // is enabled.
2245     ANGLE_FEATURE_CONDITION(&mFeatures, supportsSurfaceProtectedSwapchains, IsAndroid());
2246 
2247     // http://anglebug.com/2838
2248     ANGLE_FEATURE_CONDITION(&mFeatures, extraCopyBufferRegion, IsWindows() && isIntel);
2249 
2250     ANGLE_FEATURE_CONDITION(&mFeatures, forceCPUPathForCubeMapCopy, false);
2251 
2252     // Work around incorrect NVIDIA point size range clamping.
2253     // http://anglebug.com/2970#c10
2254     // Clamp if driver version is:
2255     //   < 430 on Windows
2256     //   < 421 otherwise
2257     angle::VersionInfo nvidiaVersion;
2258     if (isNvidia)
2259     {
2260         nvidiaVersion =
2261             angle::ParseNvidiaDriverVersion(this->mPhysicalDeviceProperties.driverVersion);
2262     }
2263     ANGLE_FEATURE_CONDITION(&mFeatures, clampPointSize,
2264                             isNvidia && nvidiaVersion.major < uint32_t(IsWindows() ? 430 : 421));
2265     // http://anglebug.com/3970#c25.
2266     // The workaround requires the VK_EXT_depth_clip_enable extension and the 'depthClamp' physical
2267     // device feature. This workaround caused test failures on Quadro P400/driver 418.56/Linux.
2268     // Therefore, on Linux we require a major version > 418.
2269     ANGLE_FEATURE_CONDITION(
2270         &mFeatures, depthClamping,
2271         isNvidia && mPhysicalDeviceFeatures.depthClamp &&
2272             ExtensionFound(VK_EXT_DEPTH_CLIP_ENABLE_EXTENSION_NAME, deviceExtensionNames) &&
2273             (!IsLinux() || nvidiaVersion.major > 418u));
2274 
2275     // Work around ineffective compute-graphics barriers on Nexus 5X.
2276     // TODO(syoussefi): Figure out which other vendors and driver versions are affected.
2277     // http://anglebug.com/3019
2278     ANGLE_FEATURE_CONDITION(&mFeatures, flushAfterVertexConversion,
2279                             IsAndroid() && IsNexus5X(mPhysicalDeviceProperties.vendorID,
2280                                                      mPhysicalDeviceProperties.deviceID));
2281 
2282     ANGLE_FEATURE_CONDITION(
2283         &mFeatures, supportsRenderpass2,
2284         ExtensionFound(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME, deviceExtensionNames));
2285 
2286     ANGLE_FEATURE_CONDITION(
2287         &mFeatures, supportsIncrementalPresent,
2288         ExtensionFound(VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME, deviceExtensionNames));
2289 
2290 #if defined(ANGLE_PLATFORM_ANDROID)
2291     ANGLE_FEATURE_CONDITION(
2292         &mFeatures, supportsAndroidHardwareBuffer,
2293         IsAndroid() &&
2294             ExtensionFound(VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME,
2295                            deviceExtensionNames) &&
2296             ExtensionFound(VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME, deviceExtensionNames));
2297 #endif
2298 
2299 #if defined(ANGLE_PLATFORM_GGP)
2300     ANGLE_FEATURE_CONDITION(
2301         &mFeatures, supportsGGPFrameToken,
2302         ExtensionFound(VK_GGP_FRAME_TOKEN_EXTENSION_NAME, deviceExtensionNames));
2303 #endif
2304 
2305     ANGLE_FEATURE_CONDITION(
2306         &mFeatures, supportsExternalMemoryFd,
2307         ExtensionFound(VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, deviceExtensionNames));
2308 
2309     ANGLE_FEATURE_CONDITION(
2310         &mFeatures, supportsExternalMemoryFuchsia,
2311         ExtensionFound(VK_FUCHSIA_EXTERNAL_MEMORY_EXTENSION_NAME, deviceExtensionNames));
2312 
2313     ANGLE_FEATURE_CONDITION(
2314         &mFeatures, supportsFilteringPrecision,
2315         ExtensionFound(VK_GOOGLE_SAMPLER_FILTERING_PRECISION_EXTENSION_NAME, deviceExtensionNames));
2316 
2317     ANGLE_FEATURE_CONDITION(
2318         &mFeatures, supportsExternalFenceCapabilities,
2319         ExtensionFound(VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME, deviceExtensionNames));
2320 
2321     ANGLE_FEATURE_CONDITION(&mFeatures, supportsExternalSemaphoreCapabilities,
2322                             ExtensionFound(VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME,
2323                                            deviceExtensionNames));
2324 
2325     ANGLE_FEATURE_CONDITION(
2326         &mFeatures, supportsExternalSemaphoreFd,
2327         ExtensionFound(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, deviceExtensionNames));
2328 
2329     ANGLE_FEATURE_CONDITION(
2330         &mFeatures, supportsExternalSemaphoreFuchsia,
2331         ExtensionFound(VK_FUCHSIA_EXTERNAL_SEMAPHORE_EXTENSION_NAME, deviceExtensionNames));
2332 
2333     ANGLE_FEATURE_CONDITION(
2334         &mFeatures, supportsExternalFenceFd,
2335         ExtensionFound(VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME, deviceExtensionNames));
2336 
2337 #if defined(ANGLE_PLATFORM_ANDROID)
2338     if (mFeatures.supportsExternalFenceCapabilities.enabled &&
2339         mFeatures.supportsExternalSemaphoreCapabilities.enabled)
2340     {
2341         ANGLE_FEATURE_CONDITION(
2342             &mFeatures, supportsAndroidNativeFenceSync,
2343             (mFeatures.supportsExternalFenceFd.enabled &&
2344              FencePropertiesCompatibleWithAndroid(mExternalFenceProperties) &&
2345              mFeatures.supportsExternalSemaphoreFd.enabled &&
2346              SemaphorePropertiesCompatibleWithAndroid(mExternalSemaphoreProperties)));
2347     }
2348     else
2349     {
2350         ANGLE_FEATURE_CONDITION(&mFeatures, supportsAndroidNativeFenceSync,
2351                                 (mFeatures.supportsExternalFenceFd.enabled &&
2352                                  mFeatures.supportsExternalSemaphoreFd.enabled));
2353     }
2354 #endif  // defined(ANGLE_PLATFORM_ANDROID)
2355 
2356     ANGLE_FEATURE_CONDITION(
2357         &mFeatures, supportsShaderStencilExport,
2358         ExtensionFound(VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME, deviceExtensionNames));
2359 
2360     ANGLE_FEATURE_CONDITION(
2361         &mFeatures, supportsRenderPassStoreOpNoneQCOM,
2362         ExtensionFound(VK_QCOM_RENDER_PASS_STORE_OPS_EXTENSION_NAME, deviceExtensionNames));
2363 
2364     ANGLE_FEATURE_CONDITION(&mFeatures, supportsTransformFeedbackExtension,
2365                             mTransformFeedbackFeatures.transformFeedback == VK_TRUE);
2366 
2367     ANGLE_FEATURE_CONDITION(&mFeatures, supportsIndexTypeUint8,
2368                             mIndexTypeUint8Features.indexTypeUint8 == VK_TRUE);
2369 
2370     ANGLE_FEATURE_CONDITION(&mFeatures, supportsDepthStencilResolve,
2371                             mFeatures.supportsRenderpass2.enabled &&
2372                                 mDepthStencilResolveProperties.supportedDepthResolveModes != 0);
2373 
2374     ANGLE_FEATURE_CONDITION(
2375         &mFeatures, supportsMultisampledRenderToSingleSampled,
2376         mFeatures.supportsRenderpass2.enabled && mFeatures.supportsDepthStencilResolve.enabled &&
2377             mMultisampledRenderToSingleSampledFeatures.multisampledRenderToSingleSampled ==
2378                 VK_TRUE);
2379 
2380     ANGLE_FEATURE_CONDITION(&mFeatures, supportsMultiview, mMultiviewFeatures.multiview == VK_TRUE);
2381 
2382     ANGLE_FEATURE_CONDITION(&mFeatures, emulateTransformFeedback,
2383                             (!mFeatures.supportsTransformFeedbackExtension.enabled &&
2384                              mPhysicalDeviceFeatures.vertexPipelineStoresAndAtomics == VK_TRUE));
2385 
2386     // TODO: http://anglebug.com/5927 - drop dependency on customBorderColorWithoutFormat.
2387     ANGLE_FEATURE_CONDITION(&mFeatures, supportsCustomBorderColorEXT,
2388                             (mCustomBorderColorFeatures.customBorderColors == VK_TRUE &&
2389                              mCustomBorderColorFeatures.customBorderColorWithoutFormat == VK_TRUE));
2390 
2391     ANGLE_FEATURE_CONDITION(&mFeatures, disableFifoPresentMode, IsLinux() && isIntel);
2392 
2393     ANGLE_FEATURE_CONDITION(&mFeatures, bindEmptyForUnusedDescriptorSets,
2394                             IsAndroid() && isQualcomm);
2395 
2396     ANGLE_FEATURE_CONDITION(&mFeatures, perFrameWindowSizeQuery,
2397                             isIntel || (IsWindows() && isAMD) || IsFuchsia());
2398 
2399     // Disabled on AMD/windows due to buggy behavior.
2400     ANGLE_FEATURE_CONDITION(&mFeatures, disallowSeamfulCubeMapEmulation, IsWindows() && isAMD);
2401 
2402     ANGLE_FEATURE_CONDITION(&mFeatures, padBuffersToMaxVertexAttribStride, isAMD);
2403     mMaxVertexAttribStride = std::min(static_cast<uint32_t>(gl::limits::kMaxVertexAttribStride),
2404                                       mPhysicalDeviceProperties.limits.maxVertexInputBindingStride);
2405 
2406     ANGLE_FEATURE_CONDITION(&mFeatures, forceD16TexFilter, IsAndroid() && isQualcomm);
2407 
2408     ANGLE_FEATURE_CONDITION(&mFeatures, disableFlippingBlitWithCommand, IsAndroid() && isQualcomm);
2409 
2410     // Allocation sanitization disabled by default because of a heaveyweight implementation
2411     // that can cause OOM and timeouts.
2412     ANGLE_FEATURE_CONDITION(&mFeatures, allocateNonZeroMemory, false);
2413 
2414     ANGLE_FEATURE_CONDITION(&mFeatures, shadowBuffers, false);
2415 
2416     ANGLE_FEATURE_CONDITION(&mFeatures, persistentlyMappedBuffers, true);
2417 
2418     ANGLE_FEATURE_CONDITION(&mFeatures, logMemoryReportCallbacks, false);
2419     ANGLE_FEATURE_CONDITION(&mFeatures, logMemoryReportStats, false);
2420 
2421     ANGLE_FEATURE_CONDITION(
2422         &mFeatures, supportsExternalMemoryHost,
2423         ExtensionFound(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME, deviceExtensionNames));
2424 
2425     // Android pre-rotation support can be disabled.
2426     ANGLE_FEATURE_CONDITION(&mFeatures, enablePreRotateSurfaces,
2427                             IsAndroid() && supportsNegativeViewport);
2428 
2429     // http://anglebug.com/3078
2430     ANGLE_FEATURE_CONDITION(
2431         &mFeatures, enablePrecisionQualifiers,
2432         !(IsPixel2(mPhysicalDeviceProperties.vendorID, mPhysicalDeviceProperties.deviceID) &&
2433           (mPhysicalDeviceProperties.driverVersion < kPixel2DriverWithRelaxedPrecision)) &&
2434             !IsPixel4(mPhysicalDeviceProperties.vendorID, mPhysicalDeviceProperties.deviceID));
2435 
2436     ANGLE_FEATURE_CONDITION(&mFeatures, preferAggregateBarrierCalls, isNvidia || isAMD || isIntel);
2437 
2438     // Currently disabled by default: http://anglebug.com/4324
2439     ANGLE_FEATURE_CONDITION(&mFeatures, asyncCommandQueue, false);
2440 
2441     ANGLE_FEATURE_CONDITION(&mFeatures, supportsYUVSamplerConversion,
2442                             mSamplerYcbcrConversionFeatures.samplerYcbcrConversion != VK_FALSE);
2443 
2444     ANGLE_FEATURE_CONDITION(&mFeatures, supportsShaderFloat16,
2445                             mShaderFloat16Int8Features.shaderFloat16 == VK_TRUE);
2446 
2447     // http://issuetracker.google.com/173636783 Qualcomm driver appears having issues with
2448     // specialization constant
2449     ANGLE_FEATURE_CONDITION(&mFeatures, forceDriverUniformOverSpecConst,
2450                             isQualcomm && mPhysicalDeviceProperties.driverVersion <
2451                                               kPixel4DriverWithWorkingSpecConstSupport);
2452 
2453     // The compute shader used to generate mipmaps uses a 256-wide workgroup.  This path is only
2454     // enabled on devices that meet this minimum requirement.  Furthermore,
2455     // VK_IMAGE_USAGE_STORAGE_BIT is detrimental to performance on many platforms, on which this
2456     // path is not enabled.  Platforms that are known to have better performance with this path are:
2457     //
2458     // - Nvidia
2459     // - AMD
2460     //
2461     // Additionally, this path is disabled on buggy drivers:
2462     //
2463     // - AMD/Windows: Unfortunately the trybots use ancient AMD cards and drivers.
2464     const uint32_t maxComputeWorkGroupInvocations =
2465         mPhysicalDeviceProperties.limits.maxComputeWorkGroupInvocations;
2466     ANGLE_FEATURE_CONDITION(
2467         &mFeatures, allowGenerateMipmapWithCompute,
2468         maxComputeWorkGroupInvocations >= 256 && (isNvidia || (isAMD && !IsWindows())));
2469 
2470     bool isAdreno540 = mPhysicalDeviceProperties.deviceID == angle::kDeviceID_Adreno540;
2471     ANGLE_FEATURE_CONDITION(&mFeatures, forceMaxUniformBufferSize16KB, isQualcomm && isAdreno540);
2472 
2473     ANGLE_FEATURE_CONDITION(
2474         &mFeatures, supportsImageFormatList,
2475         (ExtensionFound(VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME, deviceExtensionNames)) &&
2476             (isAMD || isARM));
2477 
2478     // Feature disabled due to driver bugs:
2479     //
2480     // - Swiftshader on mac: http://anglebug.com/4937
2481     // - Intel on windows: http://anglebug.com/5032
2482     // - AMD on windows: http://crbug.com/1132366
2483     ANGLE_FEATURE_CONDITION(
2484         &mFeatures, enableMultisampledRenderToTexture,
2485         mFeatures.supportsMultisampledRenderToSingleSampled.enabled ||
2486             !(IsApple() && isSwiftShader) && !(IsWindows() && (isIntel || isAMD)));
2487 
2488     // Currently we enable cube map arrays based on the imageCubeArray Vk feature.
2489     // TODO: Check device caps for full cube map array support. http://anglebug.com/5143
2490     ANGLE_FEATURE_CONDITION(&mFeatures, supportsImageCubeArray,
2491                             mPhysicalDeviceFeatures.imageCubeArray == VK_TRUE);
2492 
2493     // TODO: Only enable if VK_EXT_primitives_generated_query is not present.
2494     // http://anglebug.com/5430
2495     ANGLE_FEATURE_CONDITION(&mFeatures, supportsPipelineStatisticsQuery,
2496                             mPhysicalDeviceFeatures.pipelineStatisticsQuery == VK_TRUE);
2497 
2498     ANGLE_FEATURE_CONDITION(&mFeatures, preferredLargeHeapBlockSize4MB, !isQualcomm);
2499 
2500     // Defer glFLush call causes manhattan 3.0 perf regression. Let Qualcomm driver opt out from
2501     // this optimization.
2502     ANGLE_FEATURE_CONDITION(&mFeatures, deferFlushUntilEndRenderPass, !isQualcomm);
2503 
2504     // Android mistakenly destroys the old swapchain when creating a new one.
2505     ANGLE_FEATURE_CONDITION(&mFeatures, waitIdleBeforeSwapchainRecreation, IsAndroid() && isARM);
2506 
2507     for (size_t lodOffsetFeatureIdx = 0;
2508          lodOffsetFeatureIdx < mFeatures.forceTextureLODOffset.size(); lodOffsetFeatureIdx++)
2509     {
2510         ANGLE_FEATURE_CONDITION(&mFeatures, forceTextureLODOffset[lodOffsetFeatureIdx], false);
2511     }
2512     ANGLE_FEATURE_CONDITION(&mFeatures, forceNearestFiltering, false);
2513     ANGLE_FEATURE_CONDITION(&mFeatures, forceNearestMipFiltering, false);
2514 
2515     ANGLE_FEATURE_CONDITION(&mFeatures, compressVertexData, false);
2516 
2517     ANGLE_FEATURE_CONDITION(
2518         &mFeatures, preferDrawClearOverVkCmdClearAttachments,
2519         IsPixel2(mPhysicalDeviceProperties.vendorID, mPhysicalDeviceProperties.deviceID));
2520 
2521     // r32f image emulation is done unconditionally so VK_FORMAT_FEATURE_STORAGE_*_ATOMIC_BIT is not
2522     // required.
2523     ANGLE_FEATURE_CONDITION(&mFeatures, emulateR32fImageAtomicExchange, true);
2524 
2525     // Negative viewports are exposed in the Maintenance1 extension and in core Vulkan 1.1+.
2526     ANGLE_FEATURE_CONDITION(&mFeatures, supportsNegativeViewport, supportsNegativeViewport);
2527 
2528     // Whether non-conformant configurations and extensions should be exposed.
2529     ANGLE_FEATURE_CONDITION(&mFeatures, exposeNonConformantExtensionsAndVersions,
2530                             kExposeNonConformantExtensionsAndVersions);
2531 
2532     // Disabled by default. Only enable it for experimental purpose, as this will cause various
2533     // tests to fail.
2534     ANGLE_FEATURE_CONDITION(&mFeatures, forceFragmentShaderPrecisionHighpToMediump, false);
2535 
2536     // Testing shows that on ARM GPU, doing implicit flush at framebuffer boundary improves
2537     // performance. Most app traces shows frame time reduced and manhattan 3.1 offscreen score
2538     // improves 7%.
2539     ANGLE_FEATURE_CONDITION(&mFeatures, preferSubmitAtFBOBoundary, isARM);
2540 
2541     // In order to support immutable samplers tied to external formats, we need to overallocate
2542     // descriptor counts for such immutable samplers
2543     ANGLE_FEATURE_CONDITION(&mFeatures, useMultipleDescriptorsForExternalFormats, true);
2544 
2545     // When generating SPIR-V, the following workarounds are applied on buggy drivers:
2546     //
2547     // - AMD/Windows: Function parameters are passed in temporary variables even if they are already
2548     //   variables.
2549     //
2550     // http://anglebug.com/6110
2551     ANGLE_FEATURE_CONDITION(&mFeatures, directSPIRVGenerationWorkarounds, IsWindows() && isAMD);
2552 
2553     angle::PlatformMethods *platform = ANGLEPlatformCurrent();
2554     platform->overrideFeaturesVk(platform, &mFeatures);
2555 
2556     ApplyFeatureOverrides(&mFeatures, displayVk->getState());
2557 }
2558 
initPipelineCache(DisplayVk * display,vk::PipelineCache * pipelineCache,bool * success)2559 angle::Result RendererVk::initPipelineCache(DisplayVk *display,
2560                                             vk::PipelineCache *pipelineCache,
2561                                             bool *success)
2562 {
2563     angle::MemoryBuffer initialData;
2564     ANGLE_TRY(
2565         GetAndDecompressPipelineCacheVk(mPhysicalDeviceProperties, display, &initialData, success));
2566 
2567     VkPipelineCacheCreateInfo pipelineCacheCreateInfo = {};
2568 
2569     pipelineCacheCreateInfo.sType           = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
2570     pipelineCacheCreateInfo.flags           = 0;
2571     pipelineCacheCreateInfo.initialDataSize = *success ? initialData.size() : 0;
2572     pipelineCacheCreateInfo.pInitialData    = *success ? initialData.data() : nullptr;
2573 
2574     ANGLE_VK_TRY(display, pipelineCache->init(mDevice, pipelineCacheCreateInfo));
2575 
2576     return angle::Result::Continue;
2577 }
2578 
getPipelineCache(vk::PipelineCache ** pipelineCache)2579 angle::Result RendererVk::getPipelineCache(vk::PipelineCache **pipelineCache)
2580 {
2581     // Note that unless external synchronization is specifically requested the pipeline cache
2582     // is internally synchronized. See VK_EXT_pipeline_creation_cache_control. We might want
2583     // to investigate controlling synchronization manually in ANGLE at some point for perf.
2584     std::lock_guard<std::mutex> lock(mPipelineCacheMutex);
2585 
2586     if (mPipelineCacheInitialized)
2587     {
2588         *pipelineCache = &mPipelineCache;
2589         return angle::Result::Continue;
2590     }
2591 
2592     // We should now recreate the pipeline cache with the blob cache pipeline data.
2593     vk::PipelineCache pCache;
2594     bool success = false;
2595     ANGLE_TRY(initPipelineCache(vk::GetImpl(mDisplay), &pCache, &success));
2596     if (success)
2597     {
2598         // Merge the newly created pipeline cache into the existing one.
2599         mPipelineCache.merge(mDevice, mPipelineCache.getHandle(), 1, pCache.ptr());
2600     }
2601     mPipelineCacheInitialized = true;
2602     pCache.destroy(mDevice);
2603 
2604     *pipelineCache = &mPipelineCache;
2605     return angle::Result::Continue;
2606 }
2607 
getNativeCaps() const2608 const gl::Caps &RendererVk::getNativeCaps() const
2609 {
2610     ensureCapsInitialized();
2611     return mNativeCaps;
2612 }
2613 
getNativeTextureCaps() const2614 const gl::TextureCapsMap &RendererVk::getNativeTextureCaps() const
2615 {
2616     ensureCapsInitialized();
2617     return mNativeTextureCaps;
2618 }
2619 
getNativeExtensions() const2620 const gl::Extensions &RendererVk::getNativeExtensions() const
2621 {
2622     ensureCapsInitialized();
2623     return mNativeExtensions;
2624 }
2625 
getNativeLimitations() const2626 const gl::Limitations &RendererVk::getNativeLimitations() const
2627 {
2628     ensureCapsInitialized();
2629     return mNativeLimitations;
2630 }
2631 
getPipelineCacheSize(DisplayVk * displayVk,size_t * pipelineCacheSizeOut)2632 angle::Result RendererVk::getPipelineCacheSize(DisplayVk *displayVk, size_t *pipelineCacheSizeOut)
2633 {
2634     VkResult result = mPipelineCache.getCacheData(mDevice, pipelineCacheSizeOut, nullptr);
2635     ANGLE_VK_TRY(displayVk, result);
2636 
2637     return angle::Result::Continue;
2638 }
2639 
syncPipelineCacheVk(DisplayVk * displayVk,const gl::Context * context)2640 angle::Result RendererVk::syncPipelineCacheVk(DisplayVk *displayVk, const gl::Context *context)
2641 {
2642     // TODO: Synchronize access to the pipeline/blob caches?
2643     ASSERT(mPipelineCache.valid());
2644 
2645     if (--mPipelineCacheVkUpdateTimeout > 0)
2646     {
2647         return angle::Result::Continue;
2648     }
2649     if (!mPipelineCacheDirty)
2650     {
2651         mPipelineCacheVkUpdateTimeout = kPipelineCacheVkUpdatePeriod;
2652         return angle::Result::Continue;
2653     }
2654 
2655     mPipelineCacheVkUpdateTimeout = kPipelineCacheVkUpdatePeriod;
2656 
2657     size_t pipelineCacheSize = 0;
2658     ANGLE_TRY(getPipelineCacheSize(displayVk, &pipelineCacheSize));
2659     // Make sure we will receive enough data to hold the pipeline cache header
2660     // Table 7. Layout for pipeline cache header version VK_PIPELINE_CACHE_HEADER_VERSION_ONE
2661     const size_t kPipelineCacheHeaderSize = 16 + VK_UUID_SIZE;
2662     if (pipelineCacheSize < kPipelineCacheHeaderSize)
2663     {
2664         // No pipeline cache data to read, so return
2665         return angle::Result::Continue;
2666     }
2667 
2668     ContextVk *contextVk = vk::GetImpl(context);
2669 
2670     // Use worker thread pool to complete compression.
2671     // If the last task hasn't been finished, skip the syncing.
2672     if (mCompressEvent && (!mCompressEvent->isReady() || !mCompressEvent->getResult()))
2673     {
2674         ANGLE_PERF_WARNING(contextVk->getDebug(), GL_DEBUG_SEVERITY_LOW,
2675                            "Skip syncing pipeline cache data when the last task is not ready or "
2676                            "the compress task failed.");
2677         return angle::Result::Continue;
2678     }
2679 
2680     std::vector<uint8_t> pipelineCacheData(pipelineCacheSize);
2681 
2682     size_t oldPipelineCacheSize = pipelineCacheSize;
2683     VkResult result =
2684         mPipelineCache.getCacheData(mDevice, &pipelineCacheSize, pipelineCacheData.data());
2685     // We don't need all of the cache data, so just make sure we at least got the header
2686     // Vulkan Spec 9.6. Pipeline Cache
2687     // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/chap9.html#pipelines-cache
2688     // If pDataSize is less than what is necessary to store this header, nothing will be written to
2689     // pData and zero will be written to pDataSize.
2690     // Any data written to pData is valid and can be provided as the pInitialData member of the
2691     // VkPipelineCacheCreateInfo structure passed to vkCreatePipelineCache.
2692     if (ANGLE_UNLIKELY(pipelineCacheSize < kPipelineCacheHeaderSize))
2693     {
2694         WARN() << "Not enough pipeline cache data read.";
2695         return angle::Result::Continue;
2696     }
2697     else if (ANGLE_UNLIKELY(result == VK_INCOMPLETE))
2698     {
2699         WARN() << "Received VK_INCOMPLETE: Old: " << oldPipelineCacheSize
2700                << ", New: " << pipelineCacheSize;
2701     }
2702     else
2703     {
2704         ANGLE_VK_TRY(displayVk, result);
2705     }
2706 
2707     // If vkGetPipelineCacheData ends up writing fewer bytes than requested, zero out the rest of
2708     // the buffer to avoid leaking garbage memory.
2709     ASSERT(pipelineCacheSize <= pipelineCacheData.size());
2710     if (pipelineCacheSize < pipelineCacheData.size())
2711     {
2712         memset(pipelineCacheData.data() + pipelineCacheSize, 0,
2713                pipelineCacheData.size() - pipelineCacheSize);
2714     }
2715 
2716     if (context->getFrontendFeatures().enableCompressingPipelineCacheInThreadPool.enabled)
2717     {
2718         // The function zlib_internal::GzipCompressHelper() can compress 10M pipeline cache data
2719         // into about 2M, to save the time of compression, set kMaxTotalSize to 10M.
2720         constexpr size_t kMaxTotalSize = 10 * 1024 * 1024;
2721 
2722         // Create task to compress.
2723         auto compressAndStorePipelineCacheTask =
2724             std::make_shared<CompressAndStorePipelineCacheTask>(
2725                 displayVk, contextVk, std::move(pipelineCacheData), kMaxTotalSize);
2726         mCompressEvent = std::make_shared<WaitableCompressEventImpl>(
2727             angle::WorkerThreadPool::PostWorkerTask(context->getWorkerThreadPool(),
2728                                                     compressAndStorePipelineCacheTask),
2729             compressAndStorePipelineCacheTask);
2730         mPipelineCacheDirty = false;
2731     }
2732     else
2733     {
2734         // If enableCompressingPipelineCacheInThreadPool is diabled, to avoid the risk, set
2735         // kMaxTotalSize to 64k.
2736         constexpr size_t kMaxTotalSize = 64 * 1024;
2737         bool compressResult            = CompressAndStorePipelineCacheVk(
2738             mPhysicalDeviceProperties, displayVk, contextVk, pipelineCacheData, kMaxTotalSize);
2739 
2740         if (compressResult)
2741         {
2742             mPipelineCacheDirty = false;
2743         }
2744     }
2745 
2746     return angle::Result::Continue;
2747 }
2748 
issueShaderSerial()2749 Serial RendererVk::issueShaderSerial()
2750 {
2751     return mShaderSerialFactory.generate();
2752 }
2753 
2754 // These functions look at the mandatory format for support, and fallback to querying the device (if
2755 // necessary) to test the availability of the bits.
hasLinearImageFormatFeatureBits(angle::FormatID formatID,const VkFormatFeatureFlags featureBits) const2756 bool RendererVk::hasLinearImageFormatFeatureBits(angle::FormatID formatID,
2757                                                  const VkFormatFeatureFlags featureBits) const
2758 {
2759     return hasFormatFeatureBits<&VkFormatProperties::linearTilingFeatures>(formatID, featureBits);
2760 }
2761 
getLinearImageFormatFeatureBits(angle::FormatID formatID,const VkFormatFeatureFlags featureBits) const2762 VkFormatFeatureFlags RendererVk::getLinearImageFormatFeatureBits(
2763     angle::FormatID formatID,
2764     const VkFormatFeatureFlags featureBits) const
2765 {
2766     return getFormatFeatureBits<&VkFormatProperties::linearTilingFeatures>(formatID, featureBits);
2767 }
2768 
getImageFormatFeatureBits(angle::FormatID formatID,const VkFormatFeatureFlags featureBits) const2769 VkFormatFeatureFlags RendererVk::getImageFormatFeatureBits(
2770     angle::FormatID formatID,
2771     const VkFormatFeatureFlags featureBits) const
2772 {
2773     return getFormatFeatureBits<&VkFormatProperties::optimalTilingFeatures>(formatID, featureBits);
2774 }
2775 
hasImageFormatFeatureBits(angle::FormatID formatID,const VkFormatFeatureFlags featureBits) const2776 bool RendererVk::hasImageFormatFeatureBits(angle::FormatID formatID,
2777                                            const VkFormatFeatureFlags featureBits) const
2778 {
2779     return hasFormatFeatureBits<&VkFormatProperties::optimalTilingFeatures>(formatID, featureBits);
2780 }
2781 
hasBufferFormatFeatureBits(angle::FormatID formatID,const VkFormatFeatureFlags featureBits) const2782 bool RendererVk::hasBufferFormatFeatureBits(angle::FormatID formatID,
2783                                             const VkFormatFeatureFlags featureBits) const
2784 {
2785     return hasFormatFeatureBits<&VkFormatProperties::bufferFeatures>(formatID, featureBits);
2786 }
2787 
outputVmaStatString()2788 void RendererVk::outputVmaStatString()
2789 {
2790     // Output the VMA stats string
2791     // This JSON string can be passed to VmaDumpVis.py to generate a visualization of the
2792     // allocations the VMA has performed.
2793     char *statsString;
2794     mAllocator.buildStatsString(&statsString, true);
2795     INFO() << std::endl << statsString << std::endl;
2796     mAllocator.freeStatsString(statsString);
2797 }
2798 
queueSubmitOneOff(vk::Context * context,vk::PrimaryCommandBuffer && primary,bool hasProtectedContent,egl::ContextPriority priority,const vk::Fence * fence,vk::SubmitPolicy submitPolicy,Serial * serialOut)2799 angle::Result RendererVk::queueSubmitOneOff(vk::Context *context,
2800                                             vk::PrimaryCommandBuffer &&primary,
2801                                             bool hasProtectedContent,
2802                                             egl::ContextPriority priority,
2803                                             const vk::Fence *fence,
2804                                             vk::SubmitPolicy submitPolicy,
2805                                             Serial *serialOut)
2806 {
2807     ANGLE_TRACE_EVENT0("gpu.angle", "RendererVk::queueSubmitOneOff");
2808 
2809     std::lock_guard<std::mutex> commandQueueLock(mCommandQueueMutex);
2810 
2811     Serial submitQueueSerial;
2812     if (mFeatures.asyncCommandQueue.enabled)
2813     {
2814         submitQueueSerial = mCommandProcessor.reserveSubmitSerial();
2815         ANGLE_TRY(mCommandProcessor.queueSubmitOneOff(context, hasProtectedContent, priority,
2816                                                       primary.getHandle(), fence, submitPolicy,
2817                                                       submitQueueSerial));
2818     }
2819     else
2820     {
2821         submitQueueSerial = mCommandQueue.reserveSubmitSerial();
2822         ANGLE_TRY(mCommandQueue.queueSubmitOneOff(context, hasProtectedContent, priority,
2823                                                   primary.getHandle(), fence, submitPolicy,
2824                                                   submitQueueSerial));
2825     }
2826 
2827     *serialOut = submitQueueSerial;
2828 
2829     if (primary.valid())
2830     {
2831         mPendingOneOffCommands.push_back({*serialOut, std::move(primary)});
2832     }
2833 
2834     return angle::Result::Continue;
2835 }
2836 
2837 template <VkFormatFeatureFlags VkFormatProperties::*features>
getFormatFeatureBits(angle::FormatID formatID,const VkFormatFeatureFlags featureBits) const2838 VkFormatFeatureFlags RendererVk::getFormatFeatureBits(angle::FormatID formatID,
2839                                                       const VkFormatFeatureFlags featureBits) const
2840 {
2841     VkFormatProperties &deviceProperties = mFormatProperties[formatID];
2842 
2843     if (deviceProperties.bufferFeatures == kInvalidFormatFeatureFlags)
2844     {
2845         // If we don't have the actual device features, see if the requested features are mandatory.
2846         // If so, there's no need to query the device.
2847         const VkFormatProperties &mandatoryProperties = vk::GetMandatoryFormatSupport(formatID);
2848         if (IsMaskFlagSet(mandatoryProperties.*features, featureBits))
2849         {
2850             return featureBits;
2851         }
2852 
2853         VkFormat vkFormat = vk::GetVkFormatFromFormatID(formatID);
2854 
2855         // Otherwise query the format features and cache it.
2856         vkGetPhysicalDeviceFormatProperties(mPhysicalDevice, vkFormat, &deviceProperties);
2857         // Workaround for some Android devices that don't indicate filtering
2858         // support on D16_UNORM and they should.
2859         if (mFeatures.forceD16TexFilter.enabled && vkFormat == VK_FORMAT_D16_UNORM)
2860         {
2861             deviceProperties.*features |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
2862         }
2863     }
2864 
2865     return deviceProperties.*features & featureBits;
2866 }
2867 
2868 template <VkFormatFeatureFlags VkFormatProperties::*features>
hasFormatFeatureBits(angle::FormatID formatID,const VkFormatFeatureFlags featureBits) const2869 bool RendererVk::hasFormatFeatureBits(angle::FormatID formatID,
2870                                       const VkFormatFeatureFlags featureBits) const
2871 {
2872     return IsMaskFlagSet(getFormatFeatureBits<features>(formatID, featureBits), featureBits);
2873 }
2874 
haveSameFormatFeatureBits(angle::FormatID formatID1,angle::FormatID formatID2) const2875 bool RendererVk::haveSameFormatFeatureBits(angle::FormatID formatID1,
2876                                            angle::FormatID formatID2) const
2877 {
2878     if (formatID1 == angle::FormatID::NONE || formatID2 == angle::FormatID::NONE)
2879     {
2880         return false;
2881     }
2882 
2883     constexpr VkFormatFeatureFlags kImageUsageFeatureBits =
2884         VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT |
2885         VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
2886 
2887     VkFormatFeatureFlags fmt1LinearFeatureBits =
2888         getLinearImageFormatFeatureBits(formatID1, kImageUsageFeatureBits);
2889     VkFormatFeatureFlags fmt1OptimalFeatureBits =
2890         getImageFormatFeatureBits(formatID1, kImageUsageFeatureBits);
2891 
2892     return hasLinearImageFormatFeatureBits(formatID2, fmt1LinearFeatureBits) &&
2893            hasImageFormatFeatureBits(formatID2, fmt1OptimalFeatureBits);
2894 }
2895 
cleanupGarbage(Serial lastCompletedQueueSerial)2896 angle::Result RendererVk::cleanupGarbage(Serial lastCompletedQueueSerial)
2897 {
2898     std::lock_guard<std::mutex> lock(mGarbageMutex);
2899 
2900     for (auto garbageIter = mSharedGarbage.begin(); garbageIter != mSharedGarbage.end();)
2901     {
2902         // Possibly 'counter' should be always zero when we add the object to garbage.
2903         vk::SharedGarbage &garbage = *garbageIter;
2904         if (garbage.destroyIfComplete(this, lastCompletedQueueSerial))
2905         {
2906             garbageIter = mSharedGarbage.erase(garbageIter);
2907         }
2908         else
2909         {
2910             garbageIter++;
2911         }
2912     }
2913 
2914     return angle::Result::Continue;
2915 }
2916 
cleanupCompletedCommandsGarbage()2917 void RendererVk::cleanupCompletedCommandsGarbage()
2918 {
2919     (void)cleanupGarbage(getLastCompletedQueueSerial());
2920 }
2921 
onNewValidationMessage(const std::string & message)2922 void RendererVk::onNewValidationMessage(const std::string &message)
2923 {
2924     mLastValidationMessage = message;
2925     ++mValidationMessageCount;
2926 }
2927 
getAndClearLastValidationMessage(uint32_t * countSinceLastClear)2928 std::string RendererVk::getAndClearLastValidationMessage(uint32_t *countSinceLastClear)
2929 {
2930     *countSinceLastClear    = mValidationMessageCount;
2931     mValidationMessageCount = 0;
2932 
2933     return std::move(mLastValidationMessage);
2934 }
2935 
getMaxFenceWaitTimeNs() const2936 uint64_t RendererVk::getMaxFenceWaitTimeNs() const
2937 {
2938     constexpr uint64_t kMaxFenceWaitTimeNs = 120'000'000'000llu;
2939 
2940     return kMaxFenceWaitTimeNs;
2941 }
2942 
setGlobalDebugAnnotator()2943 void RendererVk::setGlobalDebugAnnotator()
2944 {
2945     // Install one of two DebugAnnotator classes:
2946     //
2947     // 1) The global class enables basic ANGLE debug functionality (e.g. Vulkan validation errors
2948     //    will cause dEQP tests to fail).
2949     //
2950     // 2) The DebugAnnotatorVk class processes OpenGL ES commands that the application uses.  It is
2951     //    installed for the following purposes:
2952     //
2953     //    1) To enable calling the vkCmd*DebugUtilsLabelEXT functions in order to communicate to
2954     //       debuggers (e.g. AGI) the OpenGL ES commands that the application uses.  In addition to
2955     //       simply installing DebugAnnotatorVk, also enable calling vkCmd*DebugUtilsLabelEXT.
2956     //
2957     //    2) To enable logging to Android logcat the OpenGL ES commands that the application uses.
2958     bool installDebugAnnotatorVk = false;
2959 
2960     // Enable calling the vkCmd*DebugUtilsLabelEXT functions if the vkCmd*DebugUtilsLabelEXT
2961     // functions exist, and if the kEnableDebugMarkersVarName environment variable is set.
2962     if (vkCmdBeginDebugUtilsLabelEXT)
2963     {
2964         std::string enabled = angle::GetEnvironmentVarOrAndroidProperty(
2965             kEnableDebugMarkersVarName, kEnableDebugMarkersPropertyName);
2966         if (!enabled.empty() && enabled.compare("0") != 0)
2967         {
2968             mAngleDebuggerMode      = true;
2969             installDebugAnnotatorVk = true;
2970         }
2971     }
2972 #if defined(ANGLE_ENABLE_TRACE_ANDROID_LOGCAT)
2973     // Only install DebugAnnotatorVk to log all API commands to Android's logcat.
2974     installDebugAnnotatorVk = true;
2975 #endif
2976 
2977     if (installDebugAnnotatorVk)
2978     {
2979         gl::InitializeDebugAnnotations(&mAnnotator);
2980     }
2981     else
2982     {
2983         mDisplay->setGlobalDebugAnnotator();
2984     }
2985 }
2986 
reloadVolkIfNeeded() const2987 void RendererVk::reloadVolkIfNeeded() const
2988 {
2989 #if defined(ANGLE_SHARED_LIBVULKAN)
2990     if ((mInstance != VK_NULL_HANDLE) && (volkGetLoadedInstance() != mInstance))
2991     {
2992         volkLoadInstance(mInstance);
2993     }
2994 
2995     if ((mDevice != VK_NULL_HANDLE) && (volkGetLoadedDevice() != mDevice))
2996     {
2997         volkLoadDevice(mDevice);
2998     }
2999 #endif  // defined(ANGLE_SHARED_LIBVULKAN)
3000 }
3001 
getCommandBufferOneOff(vk::Context * context,bool hasProtectedContent,vk::PrimaryCommandBuffer * commandBufferOut)3002 angle::Result RendererVk::getCommandBufferOneOff(vk::Context *context,
3003                                                  bool hasProtectedContent,
3004                                                  vk::PrimaryCommandBuffer *commandBufferOut)
3005 {
3006     if (!mOneOffCommandPool.valid())
3007     {
3008         VkCommandPoolCreateInfo createInfo = {};
3009         createInfo.sType                   = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
3010         createInfo.flags                   = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT |
3011                            (hasProtectedContent ? VK_COMMAND_POOL_CREATE_PROTECTED_BIT : 0);
3012         ANGLE_VK_TRY(context, mOneOffCommandPool.init(mDevice, createInfo));
3013     }
3014 
3015     if (!mPendingOneOffCommands.empty() &&
3016         mPendingOneOffCommands.front().serial < getLastCompletedQueueSerial())
3017     {
3018         *commandBufferOut = std::move(mPendingOneOffCommands.front().commandBuffer);
3019         mPendingOneOffCommands.pop_front();
3020         ANGLE_VK_TRY(context, commandBufferOut->reset());
3021     }
3022     else
3023     {
3024         VkCommandBufferAllocateInfo allocInfo = {};
3025         allocInfo.sType                       = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
3026         allocInfo.level                       = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
3027         allocInfo.commandBufferCount          = 1;
3028         allocInfo.commandPool                 = mOneOffCommandPool.getHandle();
3029 
3030         ANGLE_VK_TRY(context, commandBufferOut->init(context->getDevice(), allocInfo));
3031     }
3032 
3033     VkCommandBufferBeginInfo beginInfo = {};
3034     beginInfo.sType                    = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
3035     beginInfo.flags                    = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
3036     beginInfo.pInheritanceInfo         = nullptr;
3037     ANGLE_VK_TRY(context, commandBufferOut->begin(beginInfo));
3038 
3039     return angle::Result::Continue;
3040 }
3041 
submitFrame(vk::Context * context,bool hasProtectedContent,egl::ContextPriority contextPriority,std::vector<VkSemaphore> && waitSemaphores,std::vector<VkPipelineStageFlags> && waitSemaphoreStageMasks,const vk::Semaphore * signalSemaphore,std::vector<vk::ResourceUseList> && resourceUseLists,vk::GarbageList && currentGarbage,vk::CommandPool * commandPool)3042 angle::Result RendererVk::submitFrame(vk::Context *context,
3043                                       bool hasProtectedContent,
3044                                       egl::ContextPriority contextPriority,
3045                                       std::vector<VkSemaphore> &&waitSemaphores,
3046                                       std::vector<VkPipelineStageFlags> &&waitSemaphoreStageMasks,
3047                                       const vk::Semaphore *signalSemaphore,
3048                                       std::vector<vk::ResourceUseList> &&resourceUseLists,
3049                                       vk::GarbageList &&currentGarbage,
3050                                       vk::CommandPool *commandPool)
3051 {
3052     std::lock_guard<std::mutex> commandQueueLock(mCommandQueueMutex);
3053 
3054     Serial submitQueueSerial;
3055 
3056     if (mFeatures.asyncCommandQueue.enabled)
3057     {
3058         submitQueueSerial = mCommandProcessor.reserveSubmitSerial();
3059 
3060         ANGLE_TRY(mCommandProcessor.submitFrame(
3061             context, hasProtectedContent, contextPriority, waitSemaphores, waitSemaphoreStageMasks,
3062             signalSemaphore, std::move(currentGarbage), commandPool, submitQueueSerial));
3063     }
3064     else
3065     {
3066         submitQueueSerial = mCommandQueue.reserveSubmitSerial();
3067 
3068         ANGLE_TRY(mCommandQueue.submitFrame(
3069             context, hasProtectedContent, contextPriority, waitSemaphores, waitSemaphoreStageMasks,
3070             signalSemaphore, std::move(currentGarbage), commandPool, submitQueueSerial));
3071     }
3072 
3073     waitSemaphores.clear();
3074     waitSemaphoreStageMasks.clear();
3075     for (vk::ResourceUseList &it : resourceUseLists)
3076     {
3077         it.releaseResourceUsesAndUpdateSerials(submitQueueSerial);
3078     }
3079     resourceUseLists.clear();
3080 
3081     return angle::Result::Continue;
3082 }
3083 
handleDeviceLost()3084 void RendererVk::handleDeviceLost()
3085 {
3086     std::lock_guard<std::mutex> lock(mCommandQueueMutex);
3087 
3088     if (mFeatures.asyncCommandQueue.enabled)
3089     {
3090         mCommandProcessor.handleDeviceLost(this);
3091     }
3092     else
3093     {
3094         mCommandQueue.handleDeviceLost(this);
3095     }
3096 }
3097 
finishToSerial(vk::Context * context,Serial serial)3098 angle::Result RendererVk::finishToSerial(vk::Context *context, Serial serial)
3099 {
3100     std::lock_guard<std::mutex> lock(mCommandQueueMutex);
3101 
3102     if (mFeatures.asyncCommandQueue.enabled)
3103     {
3104         ANGLE_TRY(mCommandProcessor.finishToSerial(context, serial, getMaxFenceWaitTimeNs()));
3105     }
3106     else
3107     {
3108         ANGLE_TRY(mCommandQueue.finishToSerial(context, serial, getMaxFenceWaitTimeNs()));
3109     }
3110 
3111     return angle::Result::Continue;
3112 }
3113 
waitForSerialWithUserTimeout(vk::Context * context,Serial serial,uint64_t timeout,VkResult * result)3114 angle::Result RendererVk::waitForSerialWithUserTimeout(vk::Context *context,
3115                                                        Serial serial,
3116                                                        uint64_t timeout,
3117                                                        VkResult *result)
3118 {
3119     ANGLE_TRACE_EVENT0("gpu.angle", "RendererVk::waitForSerialWithUserTimeout");
3120 
3121     std::lock_guard<std::mutex> lock(mCommandQueueMutex);
3122     if (mFeatures.asyncCommandQueue.enabled)
3123     {
3124         ANGLE_TRY(mCommandProcessor.waitForSerialWithUserTimeout(context, serial, timeout, result));
3125     }
3126     else
3127     {
3128         ANGLE_TRY(mCommandQueue.waitForSerialWithUserTimeout(context, serial, timeout, result));
3129     }
3130 
3131     return angle::Result::Continue;
3132 }
3133 
finish(vk::Context * context,bool hasProtectedContent)3134 angle::Result RendererVk::finish(vk::Context *context, bool hasProtectedContent)
3135 {
3136     return finishToSerial(context, getLastSubmittedQueueSerial());
3137 }
3138 
checkCompletedCommands(vk::Context * context)3139 angle::Result RendererVk::checkCompletedCommands(vk::Context *context)
3140 {
3141     std::lock_guard<std::mutex> lock(mCommandQueueMutex);
3142     // TODO: https://issuetracker.google.com/169788986 - would be better if we could just wait
3143     // for the work we need but that requires QueryHelper to use the actual serial for the
3144     // query.
3145     if (mFeatures.asyncCommandQueue.enabled)
3146     {
3147         ANGLE_TRY(mCommandProcessor.checkCompletedCommands(context));
3148     }
3149     else
3150     {
3151         ANGLE_TRY(mCommandQueue.checkCompletedCommands(context));
3152     }
3153 
3154     return angle::Result::Continue;
3155 }
3156 
flushRenderPassCommands(vk::Context * context,bool hasProtectedContent,const vk::RenderPass & renderPass,vk::CommandBufferHelper ** renderPassCommands)3157 angle::Result RendererVk::flushRenderPassCommands(vk::Context *context,
3158                                                   bool hasProtectedContent,
3159                                                   const vk::RenderPass &renderPass,
3160                                                   vk::CommandBufferHelper **renderPassCommands)
3161 {
3162     ANGLE_TRACE_EVENT0("gpu.angle", "RendererVk::flushRenderPassCommands");
3163 
3164     std::lock_guard<std::mutex> lock(mCommandQueueMutex);
3165     if (mFeatures.asyncCommandQueue.enabled)
3166     {
3167         ANGLE_TRY(mCommandProcessor.flushRenderPassCommands(context, hasProtectedContent,
3168                                                             renderPass, renderPassCommands));
3169     }
3170     else
3171     {
3172         ANGLE_TRY(mCommandQueue.flushRenderPassCommands(context, hasProtectedContent, renderPass,
3173                                                         renderPassCommands));
3174     }
3175 
3176     return angle::Result::Continue;
3177 }
3178 
flushOutsideRPCommands(vk::Context * context,bool hasProtectedContent,vk::CommandBufferHelper ** outsideRPCommands)3179 angle::Result RendererVk::flushOutsideRPCommands(vk::Context *context,
3180                                                  bool hasProtectedContent,
3181                                                  vk::CommandBufferHelper **outsideRPCommands)
3182 {
3183     ANGLE_TRACE_EVENT0("gpu.angle", "RendererVk::flushOutsideRPCommands");
3184 
3185     std::lock_guard<std::mutex> lock(mCommandQueueMutex);
3186     if (mFeatures.asyncCommandQueue.enabled)
3187     {
3188         ANGLE_TRY(mCommandProcessor.flushOutsideRPCommands(context, hasProtectedContent,
3189                                                            outsideRPCommands));
3190     }
3191     else
3192     {
3193         ANGLE_TRY(
3194             mCommandQueue.flushOutsideRPCommands(context, hasProtectedContent, outsideRPCommands));
3195     }
3196 
3197     return angle::Result::Continue;
3198 }
3199 
queuePresent(vk::Context * context,egl::ContextPriority priority,const VkPresentInfoKHR & presentInfo)3200 VkResult RendererVk::queuePresent(vk::Context *context,
3201                                   egl::ContextPriority priority,
3202                                   const VkPresentInfoKHR &presentInfo)
3203 {
3204     std::lock_guard<std::mutex> lock(mCommandQueueMutex);
3205 
3206     VkResult result = VK_SUCCESS;
3207     if (mFeatures.asyncCommandQueue.enabled)
3208     {
3209         result = mCommandProcessor.queuePresent(priority, presentInfo);
3210     }
3211     else
3212     {
3213         result = mCommandQueue.queuePresent(priority, presentInfo);
3214     }
3215 
3216     if (getFeatures().logMemoryReportStats.enabled)
3217     {
3218         mMemoryReport.logMemoryReportStats();
3219     }
3220 
3221     return result;
3222 }
3223 
getCommandBufferHelper(bool hasRenderPass)3224 vk::CommandBufferHelper *RendererVk::getCommandBufferHelper(bool hasRenderPass)
3225 {
3226     ANGLE_TRACE_EVENT0("gpu.angle", "RendererVk::getCommandBufferHelper");
3227     std::unique_lock<std::mutex> lock(mCommandBufferHelperFreeListMutex);
3228 
3229     if (mCommandBufferHelperFreeList.empty())
3230     {
3231         vk::CommandBufferHelper *commandBuffer = new vk::CommandBufferHelper();
3232         commandBuffer->initialize(hasRenderPass);
3233         return commandBuffer;
3234     }
3235     else
3236     {
3237         vk::CommandBufferHelper *commandBuffer = mCommandBufferHelperFreeList.back();
3238         mCommandBufferHelperFreeList.pop_back();
3239         commandBuffer->setHasRenderPass(hasRenderPass);
3240         return commandBuffer;
3241     }
3242 }
3243 
recycleCommandBufferHelper(vk::CommandBufferHelper * commandBuffer)3244 void RendererVk::recycleCommandBufferHelper(vk::CommandBufferHelper *commandBuffer)
3245 {
3246     ANGLE_TRACE_EVENT0("gpu.angle", "RendererVk::recycleCommandBufferHelper");
3247     std::lock_guard<std::mutex> lock(mCommandBufferHelperFreeListMutex);
3248 
3249     ASSERT(commandBuffer->empty());
3250     commandBuffer->markOpen();
3251     mCommandBufferHelperFreeList.push_back(commandBuffer);
3252 }
3253 
logCacheStats() const3254 void RendererVk::logCacheStats() const
3255 {
3256     if (!vk::kOutputCumulativePerfCounters)
3257     {
3258         return;
3259     }
3260 
3261     int cacheType = 0;
3262     INFO() << "Vulkan object cache hit ratios: ";
3263     for (const CacheStats &stats : mVulkanCacheStats)
3264     {
3265         INFO() << "    CacheType " << cacheType++ << ": " << stats.getHitRatio();
3266     }
3267 }
3268 
getFormatDescriptorCountForVkFormat(ContextVk * contextVk,VkFormat format,uint32_t * descriptorCountOut)3269 angle::Result RendererVk::getFormatDescriptorCountForVkFormat(ContextVk *contextVk,
3270                                                               VkFormat format,
3271                                                               uint32_t *descriptorCountOut)
3272 {
3273     if (mVkFormatDescriptorCountMap.count(format) == 0)
3274     {
3275         // Query device for descriptor count with basic values for most of
3276         // VkPhysicalDeviceImageFormatInfo2 members.
3277         VkPhysicalDeviceImageFormatInfo2 imageFormatInfo = {};
3278         imageFormatInfo.sType  = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2;
3279         imageFormatInfo.format = format;
3280         imageFormatInfo.type   = VK_IMAGE_TYPE_2D;
3281         imageFormatInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
3282         imageFormatInfo.usage  = VK_IMAGE_USAGE_SAMPLED_BIT;
3283         imageFormatInfo.flags  = 0;
3284 
3285         VkImageFormatProperties imageFormatProperties                            = {};
3286         VkSamplerYcbcrConversionImageFormatProperties ycbcrImageFormatProperties = {};
3287         ycbcrImageFormatProperties.sType =
3288             VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES;
3289 
3290         VkImageFormatProperties2 imageFormatProperties2 = {};
3291         imageFormatProperties2.sType                 = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2;
3292         imageFormatProperties2.pNext                 = &ycbcrImageFormatProperties;
3293         imageFormatProperties2.imageFormatProperties = imageFormatProperties;
3294 
3295         ANGLE_VK_TRY(contextVk, vkGetPhysicalDeviceImageFormatProperties2(
3296                                     mPhysicalDevice, &imageFormatInfo, &imageFormatProperties2));
3297 
3298         mVkFormatDescriptorCountMap[format] =
3299             ycbcrImageFormatProperties.combinedImageSamplerDescriptorCount;
3300     }
3301 
3302     ASSERT(descriptorCountOut);
3303     *descriptorCountOut = mVkFormatDescriptorCountMap[format];
3304     return angle::Result::Continue;
3305 }
3306 
getFormatDescriptorCountForExternalFormat(ContextVk * contextVk,uint64_t format,uint32_t * descriptorCountOut)3307 angle::Result RendererVk::getFormatDescriptorCountForExternalFormat(ContextVk *contextVk,
3308                                                                     uint64_t format,
3309                                                                     uint32_t *descriptorCountOut)
3310 {
3311     // TODO: need to query for external formats as well once spec is fixed. http://anglebug.com/6141
3312     if (getFeatures().useMultipleDescriptorsForExternalFormats.enabled)
3313     {
3314         // Vulkan spec has a gap in that there is no mechanism available to query the immutable
3315         // sampler descriptor count of an external format. For now, return a default value.
3316         constexpr uint32_t kExternalFormatDefaultDescriptorCount = 4;
3317         ASSERT(descriptorCountOut);
3318         *descriptorCountOut = kExternalFormatDefaultDescriptorCount;
3319         return angle::Result::Continue;
3320     }
3321 
3322     ANGLE_VK_UNREACHABLE(contextVk);
3323     return angle::Result::Stop;
3324 }
3325 
MemoryReport()3326 vk::MemoryReport::MemoryReport()
3327     : mCurrentTotalAllocatedMemory(0),
3328       mMaxTotalAllocatedMemory(0),
3329       mCurrentTotalImportedMemory(0),
3330       mMaxTotalImportedMemory(0)
3331 {}
3332 
processCallback(const VkDeviceMemoryReportCallbackDataEXT & callbackData,bool logCallback)3333 void vk::MemoryReport::processCallback(const VkDeviceMemoryReportCallbackDataEXT &callbackData,
3334                                        bool logCallback)
3335 {
3336     std::lock_guard<std::mutex> lock(mMemoryReportMutex);
3337     VkDeviceSize size = 0;
3338     std::string reportType;
3339     switch (callbackData.type)
3340     {
3341         case VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATE_EXT:
3342             reportType = "Allocate";
3343             if ((mUniqueIDCounts[callbackData.memoryObjectId] += 1) > 1)
3344             {
3345                 break;
3346             }
3347             size = mSizesPerType[callbackData.objectType].allocatedMemory + callbackData.size;
3348             mSizesPerType[callbackData.objectType].allocatedMemory = size;
3349             if (mSizesPerType[callbackData.objectType].allocatedMemoryMax < size)
3350             {
3351                 mSizesPerType[callbackData.objectType].allocatedMemoryMax = size;
3352             }
3353             mCurrentTotalAllocatedMemory += callbackData.size;
3354             if (mMaxTotalAllocatedMemory < mCurrentTotalAllocatedMemory)
3355             {
3356                 mMaxTotalAllocatedMemory = mCurrentTotalAllocatedMemory;
3357             }
3358             break;
3359         case VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_FREE_EXT:
3360             reportType = "Free";
3361             ASSERT(mUniqueIDCounts[callbackData.memoryObjectId] > 0);
3362             mUniqueIDCounts[callbackData.memoryObjectId] -= 1;
3363             size = mSizesPerType[callbackData.objectType].allocatedMemory - callbackData.size;
3364             mSizesPerType[callbackData.objectType].allocatedMemory = size;
3365             mCurrentTotalAllocatedMemory -= callbackData.size;
3366             break;
3367         case VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_IMPORT_EXT:
3368             reportType = "Import";
3369             if ((mUniqueIDCounts[callbackData.memoryObjectId] += 1) > 1)
3370             {
3371                 break;
3372             }
3373             size = mSizesPerType[callbackData.objectType].importedMemory + callbackData.size;
3374             mSizesPerType[callbackData.objectType].importedMemory = size;
3375             if (mSizesPerType[callbackData.objectType].importedMemoryMax < size)
3376             {
3377                 mSizesPerType[callbackData.objectType].importedMemoryMax = size;
3378             }
3379             mCurrentTotalImportedMemory += callbackData.size;
3380             if (mMaxTotalImportedMemory < mCurrentTotalImportedMemory)
3381             {
3382                 mMaxTotalImportedMemory = mCurrentTotalImportedMemory;
3383             }
3384             break;
3385         case VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_UNIMPORT_EXT:
3386             reportType = "Un-Import";
3387             ASSERT(mUniqueIDCounts[callbackData.memoryObjectId] > 0);
3388             mUniqueIDCounts[callbackData.memoryObjectId] -= 1;
3389             size = mSizesPerType[callbackData.objectType].importedMemory - callbackData.size;
3390             mSizesPerType[callbackData.objectType].importedMemory = size;
3391             mCurrentTotalImportedMemory -= callbackData.size;
3392             break;
3393         case VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATION_FAILED_EXT:
3394             reportType = "allocFail";
3395             break;
3396         default:
3397             UNREACHABLE();
3398             return;
3399     }
3400     if (logCallback)
3401     {
3402         INFO() << std::right << std::setw(9) << reportType << ": size=" << std::setw(10)
3403                << callbackData.size << "; type=" << std::setw(15) << std::left
3404                << GetVkObjectTypeName(callbackData.objectType)
3405                << "; heapIdx=" << callbackData.heapIndex << "; id=" << std::hex
3406                << callbackData.memoryObjectId << "; handle=" << std::hex
3407                << callbackData.objectHandle << ": Total=" << std::right << std::setw(10) << std::dec
3408                << size;
3409     }
3410 }
3411 
logMemoryReportStats() const3412 void vk::MemoryReport::logMemoryReportStats() const
3413 {
3414     std::lock_guard<std::mutex> lock(mMemoryReportMutex);
3415 
3416     INFO() << std::right << "GPU Memory Totals:       Allocated=" << std::setw(10)
3417            << mCurrentTotalAllocatedMemory << " (max=" << std::setw(10) << mMaxTotalAllocatedMemory
3418            << ");  Imported=" << std::setw(10) << mCurrentTotalImportedMemory
3419            << " (max=" << std::setw(10) << mMaxTotalImportedMemory << ")";
3420     INFO() << "Sub-Totals per type:";
3421     for (const auto &it : mSizesPerType)
3422     {
3423         VkObjectType objectType         = it.first;
3424         MemorySizes memorySizes         = it.second;
3425         VkDeviceSize allocatedMemory    = memorySizes.allocatedMemory;
3426         VkDeviceSize allocatedMemoryMax = memorySizes.allocatedMemoryMax;
3427         VkDeviceSize importedMemory     = memorySizes.importedMemory;
3428         VkDeviceSize importedMemoryMax  = memorySizes.importedMemoryMax;
3429         INFO() << std::right << "- Type=" << std::setw(15) << GetVkObjectTypeName(objectType)
3430                << ":  Allocated=" << std::setw(10) << allocatedMemory << " (max=" << std::setw(10)
3431                << allocatedMemoryMax << ");  Imported=" << std::setw(10) << importedMemory
3432                << " (max=" << std::setw(10) << importedMemoryMax << ")";
3433     }
3434 }
3435 }  // namespace rx
3436