• 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 // vk_renderer.cpp:
7 //    Implements the class methods for Renderer.
8 //
9 
10 #include "libANGLE/renderer/vulkan/vk_renderer.h"
11 
12 // Placing this first seems to solve an intellisense bug.
13 #include "libANGLE/angletypes.h"
14 #include "libANGLE/renderer/vulkan/vk_utils.h"
15 
16 #include <EGL/eglext.h>
17 #include <fstream>
18 
19 #include "common/debug.h"
20 #include "common/platform.h"
21 #include "common/system_utils.h"
22 #include "common/vulkan/libvulkan_loader.h"
23 #include "common/vulkan/vulkan_icd.h"
24 #include "gpu_info_util/SystemInfo_vulkan.h"
25 #include "libANGLE/Context.h"
26 #include "libANGLE/Display.h"
27 #include "libANGLE/renderer/driver_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/SyncVk.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/renderer/vulkan/vk_resource.h"
38 #include "libANGLE/trace.h"
39 #include "platform/PlatformMethods.h"
40 #include "vulkan/vulkan_core.h"
41 
42 // Consts
43 namespace
44 {
45 #if defined(ANGLE_PLATFORM_ANDROID)
46 constexpr const char *kDefaultPipelineCacheGraphDumpPath = "/data/local/tmp/angle_dumps/";
47 #else
48 constexpr const char *kDefaultPipelineCacheGraphDumpPath = "";
49 #endif  // ANGLE_PLATFORM_ANDROID
50 
51 constexpr VkFormatFeatureFlags kInvalidFormatFeatureFlags = static_cast<VkFormatFeatureFlags>(-1);
52 
53 #if defined(ANGLE_EXPOSE_NON_CONFORMANT_EXTENSIONS_AND_VERSIONS)
54 constexpr bool kExposeNonConformantExtensionsAndVersions = true;
55 #else
56 constexpr bool kExposeNonConformantExtensionsAndVersions = false;
57 #endif
58 
59 #if defined(ANGLE_ENABLE_CRC_FOR_PIPELINE_CACHE)
60 constexpr bool kEnableCRCForPipelineCache = true;
61 #else
62 constexpr bool kEnableCRCForPipelineCache = false;
63 #endif
64 
65 #if defined(ANGLE_ENABLE_VULKAN_API_DUMP_LAYER)
66 constexpr bool kEnableVulkanAPIDumpLayer = true;
67 #else
68 constexpr bool kEnableVulkanAPIDumpLayer = false;
69 #endif
70 }  // anonymous namespace
71 
72 namespace rx
73 {
74 namespace vk
75 {
76 namespace
77 {
78 constexpr uint32_t kMinDefaultUniformBufferSize = 16 * 1024u;
79 // This size is picked based on experience. Majority of devices support 64K
80 // maxUniformBufferSize. Since this is per context buffer, a bigger buffer size reduces the
81 // number of descriptor set allocations, so we picked the maxUniformBufferSize that most
82 // devices supports. It may needs further tuning based on specific device needs and balance
83 // between performance and memory usage.
84 constexpr uint32_t kPreferredDefaultUniformBufferSize = 64 * 1024u;
85 
86 // Maximum size to use VMA image suballocation. Any allocation greater than or equal to this
87 // value will use a dedicated VkDeviceMemory.
88 constexpr size_t kImageSizeThresholdForDedicatedMemoryAllocation = 4 * 1024 * 1024;
89 
90 // Pipeline cache header version. It should be incremented any time there is an update to the cache
91 // header or data structure.
92 constexpr uint32_t kPipelineCacheVersion = 3;
93 
94 // Update the pipeline cache every this many swaps.
95 constexpr uint32_t kPipelineCacheVkUpdatePeriod = 60;
96 
97 // Per the Vulkan specification, ANGLE must indicate the highest version of Vulkan functionality
98 // that it uses.  The Vulkan validation layers will issue messages for any core functionality that
99 // requires a higher version.
100 //
101 // ANGLE specifically limits its core version to Vulkan 1.1 and relies on availability of
102 // extensions.  While implementations are not required to expose an extension that is promoted to
103 // later versions, they always do so in practice.  Avoiding later core versions helps keep the
104 // initialization logic simpler.
105 constexpr uint32_t kPreferredVulkanAPIVersion = VK_API_VERSION_1_1;
106 
IsVulkan11(uint32_t apiVersion)107 bool IsVulkan11(uint32_t apiVersion)
108 {
109     return apiVersion >= VK_API_VERSION_1_1;
110 }
111 
IsRADV(uint32_t vendorId,uint32_t driverId,const char * deviceName)112 bool IsRADV(uint32_t vendorId, uint32_t driverId, const char *deviceName)
113 {
114     // Check against RADV driver id first.
115     if (driverId == VK_DRIVER_ID_MESA_RADV)
116     {
117         return true;
118     }
119 
120     // Otherwise, look for RADV in the device name.  This works for both RADV
121     // and Venus-over-RADV.
122     return IsAMD(vendorId) && strstr(deviceName, "RADV") != nullptr;
123 }
124 
IsQualcommOpenSource(uint32_t vendorId,uint32_t driverId,const char * deviceName)125 bool IsQualcommOpenSource(uint32_t vendorId, uint32_t driverId, const char *deviceName)
126 {
127     if (!IsQualcomm(vendorId))
128     {
129         return false;
130     }
131 
132     // Where driver id is available, distinguish by driver id:
133     if (driverId != 0)
134     {
135         return driverId != VK_DRIVER_ID_QUALCOMM_PROPRIETARY;
136     }
137 
138     // Otherwise, look for Venus or Turnip in the device name.
139     return strstr(deviceName, "Venus") != nullptr || strstr(deviceName, "Turnip") != nullptr;
140 }
141 
IsXclipse()142 bool IsXclipse()
143 {
144     if (!IsAndroid())
145     {
146         return false;
147     }
148 
149     std::string modelName;
150     if (!angle::android::GetSystemProperty(angle::android::kModelSystemPropertyName, &modelName))
151     {
152         return 0;
153     }
154 
155     // Improve this when more Xclipse devices are available
156     return strstr(modelName.c_str(), "SM-S901B") != nullptr ||
157            strstr(modelName.c_str(), "SM-S926B") != nullptr;
158 }
159 
StrLess(const char * a,const char * b)160 bool StrLess(const char *a, const char *b)
161 {
162     return strcmp(a, b) < 0;
163 }
164 
ExtensionFound(const char * needle,const vk::ExtensionNameList & haystack)165 bool ExtensionFound(const char *needle, const vk::ExtensionNameList &haystack)
166 {
167     // NOTE: The list must be sorted.
168     return std::binary_search(haystack.begin(), haystack.end(), needle, StrLess);
169 }
170 
VerifyExtensionsPresent(const vk::ExtensionNameList & haystack,const vk::ExtensionNameList & needles)171 VkResult VerifyExtensionsPresent(const vk::ExtensionNameList &haystack,
172                                  const vk::ExtensionNameList &needles)
173 {
174     // NOTE: The lists must be sorted.
175     if (std::includes(haystack.begin(), haystack.end(), needles.begin(), needles.end(), StrLess))
176     {
177         return VK_SUCCESS;
178     }
179     for (const char *needle : needles)
180     {
181         if (!ExtensionFound(needle, haystack))
182         {
183             ERR() << "Extension not supported: " << needle;
184         }
185     }
186     return VK_ERROR_EXTENSION_NOT_PRESENT;
187 }
188 
189 // Array of Validation error/warning messages that will be ignored, should include bugID
190 constexpr const char *kSkippedMessages[] = {
191     // http://anglebug.com/42266825
192     "Undefined-Value-ShaderOutputNotConsumed",
193     "Undefined-Value-ShaderInputNotProduced",
194     // ANGLE sets gl_Layer when the framebuffer is not layered, but VVL does not see that.  When
195     // layered, if gl_Layer is out of bounds, the results are undefined in both GL and Vulkan.
196     // http://anglebug.com/372390039
197     "Undefined-Layer-Written",
198     // http://anglebug.com/42263850
199     "VUID-vkCmdDraw-magFilter-04553",
200     "VUID-vkCmdDrawIndexed-magFilter-04553",
201     // http://anglebug.com/42265014
202     "vkEnumeratePhysicalDevices: One or more layers modified physical devices",
203     // http://anglebug.com/42265797
204     "VUID-vkCmdBindVertexBuffers2-pStrides-06209",
205     // http://anglebug.com/42266199
206     "VUID-vkDestroySemaphore-semaphore-01137",
207     "VUID-vkDestroySemaphore-semaphore-05149",
208     // https://issuetracker.google.com/303219657
209     "VUID-VkGraphicsPipelineCreateInfo-pStages-00738",
210     // http://anglebug.com/42266334
211     "VUID-vkCmdDraw-None-06887",
212     "VUID-vkCmdDraw-None-06886",
213     "VUID-vkCmdDrawIndexed-None-06887",
214     // http://anglebug.com/42266819
215     "VUID-vkCmdDraw-None-09000",
216     "VUID-vkCmdDrawIndexed-None-09002",
217     // http://anglebug.com/40644894
218     "VUID-VkDescriptorImageInfo-imageView-06711",
219     "VUID-VkDescriptorImageInfo-descriptorType-06713",
220     // http://crbug.com/1412096
221     "VUID-VkImageCreateInfo-pNext-00990",
222     // http://anglebug.com/42266565
223     "VUID-VkGraphicsPipelineCreateInfo-Input-07904",
224     "VUID-VkGraphicsPipelineCreateInfo-Input-07905",
225     "VUID-vkCmdDrawIndexed-None-07835",
226     "VUID-VkGraphicsPipelineCreateInfo-Input-08733",
227     "VUID-vkCmdDraw-Input-08734",
228     // https://anglebug.com/42266575#comment4
229     "VUID-VkBufferViewCreateInfo-format-08779",
230     // https://anglebug.com/42266639
231     "VUID-VkVertexInputBindingDivisorDescriptionKHR-divisor-01870",
232     "VUID-VkVertexInputBindingDivisorDescription-divisor-01870",
233     // https://anglebug.com/42266675
234     "VUID-VkGraphicsPipelineCreateInfo-topology-08773",
235     // https://anglebug.com/42265766
236     "VUID-vkCmdBlitImage-srcImage-00240",
237     // https://anglebug.com/42266678
238     // VVL bug: https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/7858
239     "VUID-vkCmdDraw-None-08608",
240     "VUID-vkCmdDrawIndexed-None-08608",
241     "VUID-vkCmdDraw-None-07843",
242     "VUID-vkCmdDrawIndexed-None-07843",
243     "VUID-vkCmdDraw-None-07844",
244     "VUID-vkCmdDrawIndexed-None-07844",
245     "VUID-vkCmdDraw-None-07847",
246     "VUID-vkCmdDrawIndexed-None-07847",
247     // Invalid feedback loop caused by the application
248     "VUID-vkCmdDraw-None-09000",
249     "VUID-vkCmdDrawIndexed-None-09000",
250     "VUID-vkCmdDraw-None-09002",
251     "VUID-vkCmdDrawIndexed-None-09002",
252     "VUID-vkCmdDraw-None-09003",
253     "VUID-vkCmdDrawIndexed-None-09003",
254     // https://anglebug.com/42266764
255     "VUID-VkDescriptorImageInfo-imageView-07796",
256     // https://issuetracker.google.com/303441816
257     "VUID-VkRenderPassBeginInfo-renderPass-00904",
258     // http://anglebug.com/42266888
259     "VUID-VkMemoryAllocateInfo-allocationSize-01742",
260     "VUID-VkMemoryDedicatedAllocateInfo-image-01878",
261     // http://anglebug.com/42266890
262     "VUID-vkCmdDraw-pNext-09461",
263     // http://anglebug.com/42266893
264     "VUID-VkImportMemoryFdInfoKHR-handleType-00667",
265     // http://anglebug.com/42266904
266     "VUID-VkImportMemoryWin32HandleInfoKHR-handleType-00658",
267     // https://anglebug.com/42266920
268     "VUID-vkCmdEndDebugUtilsLabelEXT-commandBuffer-01912",
269     // https://anglebug.com/42266947
270     "VUID-VkPipelineVertexInputStateCreateInfo-pNext-pNext",
271     // https://issuetracker.google.com/319228278
272     "VUID-vkCmdDrawIndexed-format-07753",
273     "VUID-vkCmdDraw-format-07753",
274     "Undefined-Value-ShaderFragmentOutputMismatch",
275     // https://anglebug.com/336652255
276     "VUID-vkCmdDraw-None-09600",
277     // https://issuetracker.google.com/336847261
278     "VUID-VkImageCreateInfo-pNext-02397",
279     "VUID-vkCmdDraw-None-06550",
280     // https://anglebug.com/345304850
281     "WARNING-Shader-OutputNotConsumed",
282     // https://anglebug.com/383311444
283     "VUID-vkCmdDraw-None-09462",
284     // https://anglebug.com/394598758
285     "VUID-vkBindBufferMemory-size-01037",
286 };
287 
288 // Validation messages that should be ignored only when VK_EXT_primitive_topology_list_restart is
289 // not present.
290 constexpr const char *kNoListRestartSkippedMessages[] = {
291     // http://anglebug.com/42262476
292     "VUID-VkPipelineInputAssemblyStateCreateInfo-topology-06252",
293 };
294 
295 // Validation messages that should be ignored only when exposeNonConformantExtensionsAndVersions is
296 // enabled on certain test platforms.
297 constexpr const char *kExposeNonConformantSkippedMessages[] = {
298     // http://issuetracker.google.com/376899587
299     "VUID-VkSwapchainCreateInfoKHR-presentMode-01427",
300 };
301 
302 // VVL appears has a bug tracking stageMask on VkEvent with secondary command buffer.
303 // https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/7849
304 constexpr const char *kSkippedMessagesWithVulkanSecondaryCommandBuffer[] = {
305     "VUID-vkCmdWaitEvents-srcStageMask-parameter",
306 };
307 
308 // When using Vulkan secondary command buffers, the command buffer is begun with the current
309 // framebuffer specified in pInheritanceInfo::framebuffer.  If the framebuffer is multisampled
310 // and is resolved, an optimization would change the framebuffer to add the resolve target and
311 // use a subpass resolve operation instead.  The following error complains that the framebuffer
312 // used to start the render pass and the one specified in pInheritanceInfo::framebuffer must be
313 // equal, which is not true in that case.  In practice, this is benign, as the part of the
314 // framebuffer that's accessed by the command buffer is identically laid out.
315 // http://anglebug.com/42265307
316 constexpr const char *kSkippedMessagesWithRenderPassObjectsAndVulkanSCB[] = {
317     "VUID-vkCmdExecuteCommands-pCommandBuffers-00099",
318 };
319 
320 // VVL bugs with dynamic rendering
321 constexpr const char *kSkippedMessagesWithDynamicRendering[] = {
322     // https://anglebug.com/42266678
323     // VVL bugs with rasterizer discard:
324     // https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/7858
325     "VUID-vkCmdDraw-dynamicRenderingUnusedAttachments-08914",
326     "VUID-vkCmdDraw-dynamicRenderingUnusedAttachments-08917",
327     "VUID-vkCmdDrawIndexed-dynamicRenderingUnusedAttachments-08914",
328     "VUID-vkCmdDrawIndexed-dynamicRenderingUnusedAttachments-08917",
329     "VUID-vkCmdDraw-pDepthAttachment-08964",
330     "VUID-vkCmdDraw-pStencilAttachment-08965",
331     "VUID-vkCmdDrawIndexed-pDepthAttachment-08964",
332     "VUID-vkCmdDrawIndexed-pStencilAttachment-08965",
333     "VUID-vkCmdDraw-None-07843",
334     "VUID-vkCmdDraw-None-07844",
335     "VUID-vkCmdDraw-None-07847",
336     "VUID-vkCmdDrawIndexed-None-07843",
337     "VUID-vkCmdDrawIndexed-None-07844",
338     "VUID-vkCmdDrawIndexed-None-07847",
339     "VUID-vkCmdDraw-multisampledRenderToSingleSampled-07285",
340     "VUID-vkCmdDraw-multisampledRenderToSingleSampled-07286",
341     "VUID-vkCmdDraw-multisampledRenderToSingleSampled-07287",
342     "VUID-vkCmdDrawIndexed-multisampledRenderToSingleSampled-07285",
343     "VUID-vkCmdDrawIndexed-multisampledRenderToSingleSampled-07286",
344     "VUID-vkCmdDrawIndexed-multisampledRenderToSingleSampled-07287",
345 };
346 
347 // Some syncval errors are resolved in the presence of the NONE load or store render pass ops.  For
348 // those, ANGLE makes no further attempt to resolve them and expects vendor support for the
349 // extensions instead.  The list of skipped messages is split based on this support.
350 constexpr vk::SkippedSyncvalMessage kSkippedSyncvalMessages[] = {
351     // https://issuetracker.google.com/316337308
352     // DifferentStencilMasksTest.DrawWithSameEffectiveMask/ES2_Vulkan_SwiftShader
353     // VulkanPerformanceCounterTest.NewTextureDoesNotBreakRenderPass for both depth and stencil
354     // Hit in the asphalt_9 trace
355     // Also other errors with similar message structure.
356     {"SYNC-HAZARD-WRITE-AFTER-WRITE",
357      nullptr,
358      nullptr,
359      false,
360      {
361          "message_type = BeginRenderingError",
362          "access = "
363          "VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT(VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_"
364          "BIT)",
365          "prior_access = SYNC_IMAGE_LAYOUT_TRANSITION",
366          "command = vkCmdBeginRenderingKHR",
367          "prior_command = vkCmdPipelineBarrier",
368          "load_op = VK_ATTACHMENT_LOAD_OP_DONT_CARE",
369      }},
370     {"SYNC-HAZARD-WRITE-AFTER-WRITE",
371      nullptr,
372      nullptr,
373      false,
374      {
375          "message_type = RenderPassLoadOpError",
376          "access = "
377          "VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT(VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_"
378          "BIT)",
379          "prior_access = SYNC_IMAGE_LAYOUT_TRANSITION",
380          "command = vkCmdBeginRenderPass",
381          "prior_command = vkCmdPipelineBarrier",
382          "load_op = VK_ATTACHMENT_LOAD_OP_DONT_CARE",
383      }},
384     // From various tests. The validation layer does not calculate the exact vertexCounts that's
385     // being accessed. http://anglebug.com/42265220
386     {"SYNC-HAZARD-READ-AFTER-WRITE",
387      "Hazard READ_AFTER_WRITE for vertex",
388      "usage: SYNC_VERTEX_ATTRIBUTE_INPUT_VERTEX_ATTRIBUTE_READ",
389      false,
390      {
391          "message_type = DrawVertexBufferError",
392          "access = "
393          "VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT(VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT)",
394      }},
395     {
396         "SYNC-HAZARD-READ-AFTER-WRITE",
397         "Hazard READ_AFTER_WRITE for index",
398         "usage: SYNC_INDEX_INPUT_INDEX_READ",
399     },
400     {
401         "SYNC-HAZARD-WRITE-AFTER-READ",
402         "Hazard WRITE_AFTER_READ for",
403         "Access info (usage: SYNC_VERTEX_SHADER_SHADER_STORAGE_WRITE, prior_usage: "
404         "SYNC_VERTEX_ATTRIBUTE_INPUT_VERTEX_ATTRIBUTE_READ",
405     },
406     {"SYNC-HAZARD-WRITE-AFTER-READ",
407      "Hazard WRITE_AFTER_READ for dstBuffer VkBuffer",
408      "Access info (usage: SYNC_COPY_TRANSFER_WRITE, prior_usage: "
409      "SYNC_VERTEX_ATTRIBUTE_INPUT_VERTEX_ATTRIBUTE_READ",
410      false,
411      {"message_type = BufferRegionError", "resource_parameter = dstBuffer",
412       "access = VK_PIPELINE_STAGE_2_COPY_BIT(VK_ACCESS_2_TRANSFER_WRITE_BIT)",
413       "prior_access = "
414       "VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT(VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT)"}},
415     {
416         "SYNC-HAZARD-WRITE-AFTER-READ",
417         "Hazard WRITE_AFTER_READ for VkBuffer",
418         "Access info (usage: SYNC_COMPUTE_SHADER_SHADER_STORAGE_WRITE, prior_usage: "
419         "SYNC_VERTEX_ATTRIBUTE_INPUT_VERTEX_ATTRIBUTE_READ",
420     },
421     // http://anglebug.com/42266506 (VkNonDispatchableHandle on x86 bots)
422     {
423         "SYNC-HAZARD-READ-AFTER-WRITE",
424         "Hazard READ_AFTER_WRITE for VkBuffer",
425         "usage: SYNC_VERTEX_SHADER_SHADER_STORAGE_READ",
426     },
427     {
428         "SYNC-HAZARD-READ-AFTER-WRITE",
429         "Hazard READ_AFTER_WRITE for VkNonDispatchableHandle",
430         "usage: SYNC_VERTEX_SHADER_SHADER_STORAGE_READ",
431     },
432     // Coherent framebuffer fetch is enabled on some platforms that are known a priori to have the
433     // needed behavior, even though this is not specified in the Vulkan spec.  These generate
434     // syncval errors that are benign on those platforms.
435     // http://anglebug.com/42265363
436     // From: TraceTest.dead_by_daylight
437     // From: TraceTest.genshin_impact
438     {"SYNC-HAZARD-READ-AFTER-WRITE",
439      "with loadOp VK_ATTACHMENT_LOAD_OP_LOAD. Access info (usage: "
440      "SYNC_COLOR_ATTACHMENT_OUTPUT_COLOR_ATTACHMENT_READ, prior_usage: "
441      "SYNC_IMAGE_LAYOUT_TRANSITION, write_barriers: 0",
442      "",
443      true,
444      {
445          "message_type = RenderPassLoadOpError",
446          "load_op = VK_ATTACHMENT_LOAD_OP_LOAD",
447          "access = "
448          "VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT(VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT)",
449          "prior_access = SYNC_IMAGE_LAYOUT_TRANSITION",
450          "write_barriers = 0",
451      }},
452     {"SYNC-HAZARD-WRITE-AFTER-WRITE",
453      "image layout transition (old_layout: VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, "
454      "new_layout: "
455      "VK_IMAGE_LAYOUT_GENERAL). Access info (usage: SYNC_IMAGE_LAYOUT_TRANSITION, prior_usage: "
456      "SYNC_COLOR_ATTACHMENT_OUTPUT_COLOR_ATTACHMENT_WRITE, write_barriers:",
457      "",
458      true,
459      {
460          "message_type = RenderPassLayoutTransitionError",
461          "old_layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL",
462          "new_layout = VK_IMAGE_LAYOUT_GENERAL",
463          "access = SYNC_IMAGE_LAYOUT_TRANSITION",  // probably not needed, message_type implies this
464          "prior_access = "
465          "VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT(VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT)",
466      }},
467     // From: TraceTest.special_forces_group_2 http://anglebug.com/42264123
468     {
469         "SYNC-HAZARD-WRITE-AFTER-READ",
470         "Access info (usage: SYNC_IMAGE_LAYOUT_TRANSITION, prior_usage: "
471         "SYNC_FRAGMENT_SHADER_SHADER_",
472     },
473     // http://anglebug.com/42265504
474     {"SYNC-HAZARD-READ-AFTER-WRITE",
475      "type: VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, imageLayout: "
476      "VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, binding #0, index 0. Access info (usage: "
477      "SYNC_COMPUTE_SHADER_SHADER_",
478      "", false},
479     // http://anglebug.com/42265925
480     {
481         "SYNC-HAZARD-READ-AFTER-WRITE",
482         "type: VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, "
483         "imageLayout: VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL",
484         "Access info (usage: SYNC_FRAGMENT_SHADER_SHADER_",
485     },
486     // From: TraceTest.life_is_strange http://anglebug.com/42266180
487     {"SYNC-HAZARD-WRITE-AFTER-READ",
488      "with storeOp VK_ATTACHMENT_STORE_OP_DONT_CARE. "
489      "Access info (usage: SYNC_LATE_FRAGMENT_TESTS_DEPTH_STENCIL_ATTACHMENT_WRITE, "
490      "prior_usage: SYNC_FRAGMENT_SHADER_SHADER_"},
491     // From: TraceTest.life_is_strange http://anglebug.com/42266180
492     {"SYNC-HAZARD-READ-AFTER-WRITE",
493      "type: VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, "
494      "imageLayout: VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL",
495      "usage: SYNC_FRAGMENT_SHADER_SHADER_"},
496     // From: TraceTest.diablo_immortal http://anglebug.com/42266309
497     {"SYNC-HAZARD-WRITE-AFTER-WRITE",
498      "Access info (usage: "
499      "SYNC_COLOR_ATTACHMENT_OUTPUT_COLOR_ATTACHMENT_WRITE, prior_usage: "
500      "SYNC_IMAGE_LAYOUT_TRANSITION, write_barriers: 0"},
501     // From: TraceTest.diablo_immortal http://anglebug.com/42266309
502     {"SYNC-HAZARD-WRITE-AFTER-READ",
503      "with loadOp VK_ATTACHMENT_LOAD_OP_DONT_CARE. Access info (usage: "
504      "SYNC_EARLY_FRAGMENT_TESTS_DEPTH_STENCIL_ATTACHMENT_WRITE, prior_usage: "
505      "SYNC_FRAGMENT_SHADER_SHADER_"},
506     // From: TraceTest.catalyst_black http://anglebug.com/42266390
507     {"SYNC-HAZARD-WRITE-AFTER-READ",
508      "with storeOp VK_ATTACHMENT_STORE_OP_STORE. Access info (usage: "
509      "SYNC_LATE_FRAGMENT_TESTS_DEPTH_STENCIL_ATTACHMENT_WRITE, prior_usage: "
510      "SYNC_FRAGMENT_SHADER_SHADER_"},
511     // http://anglebug.com/352094384
512     {
513         "SYNC-HAZARD-WRITE-AFTER-WRITE",
514         "Hazard WRITE_AFTER_WRITE for VkImageView",
515         "Access info (usage: SYNC_ACCESS_INDEX_NONE, prior_usage: SYNC_IMAGE_LAYOUT_TRANSITION, ",
516     },
517     // http://anglebug.com/394598470
518     {
519         "SYNC-HAZARD-WRITE-AFTER-READ",
520         "access = VK_PIPELINE_STAGE_2_COPY_BIT(VK_ACCESS_2_TRANSFER_WRITE_BIT)",
521         "prior_access = "
522         "VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT(VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT)",
523     },
524     // http://anglebug.com/397775556
525     {
526         "SYNC-HAZARD-READ-AFTER-WRITE",
527         "vkCmdDrawIndexed reads vertex VkBuffer",
528         "which was previously written by vkCmdCopyBuffer.",
529     },
530     // http://anglebug.com/399191283
531     {"SYNC-HAZARD-WRITE-AFTER-WRITE",
532      "vkCmdBeginRenderingKHR potentially modifies",
533      "which was previously written during an image layout transition initiated by "
534      "vkCmdPipelineBarrier",
535      false,
536      {"message_type = GeneralError", "hazard_type = WRITE_AFTER_WRITE",
537       "access = "
538       "VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT(VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_"
539       "BIT)",
540       "prior_access = SYNC_IMAGE_LAYOUT_TRANSITION", "prior_command = vkCmdPipelineBarrier",
541       "command = vkCmdBeginRenderingKHR"}},
542     // http://anglebug.com/399191283
543     {"SYNC-HAZARD-WRITE-AFTER-WRITE",
544      "vkCmdBeginRenderPass potentially modifies",
545      "which was previously written during an image layout transition initiated by "
546      "vkCmdPipelineBarrier",
547      false,
548      {"message_type = GeneralError", "hazard_type = WRITE_AFTER_WRITE",
549       "access = "
550       "VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT(VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_"
551       "BIT)",
552       "prior_access = SYNC_IMAGE_LAYOUT_TRANSITION", "prior_command = vkCmdPipelineBarrier",
553       "command = vkCmdBeginRenderPass"}},
554     // http://anglebug.com/399191283
555     {"SYNC-HAZARD-WRITE-AFTER-WRITE",
556      nullptr,
557      nullptr,
558      false,
559      {"message_type = GeneralError", "hazard_type = WRITE_AFTER_WRITE",
560       "access = SYNC_IMAGE_LAYOUT_TRANSITION",
561       "prior_access = "
562       "VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT(VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT)",
563       "command = vkCmdBeginRenderPass", "prior_command = vkCmdDrawIndexed",
564       "old_layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL",
565       "new_layout = VK_IMAGE_LAYOUT_GENERAL"}},
566     // http://anglebug.com/399191283
567     {"SYNC-HAZARD-WRITE-AFTER-WRITE",
568      nullptr,
569      nullptr,
570      false,
571      {"message_type = GeneralError", "hazard_type = WRITE_AFTER_WRITE",
572       "access = SYNC_IMAGE_LAYOUT_TRANSITION",
573       "prior_access = "
574       "VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT(VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT)",
575       "command = vkCmdBeginRenderPass", "prior_command = vkCmdEndRenderPass",
576       "old_layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL",
577       "new_layout = VK_IMAGE_LAYOUT_GENERAL"}},
578     // http://anglebug.com/399191283
579     {"SYNC-HAZARD-WRITE-AFTER-WRITE",
580      nullptr,
581      nullptr,
582      false,
583      {"message_type = GeneralError", "hazard_type = WRITE_AFTER_WRITE",
584       "access = SYNC_IMAGE_LAYOUT_TRANSITION",
585       "prior_access = "
586       "VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT(VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT)",
587       "command = vkCmdBeginRenderPass", "prior_command = vkCmdEndRenderPass",
588       "old_layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL",
589       "new_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL"}},
590     // http://anglebug.com/399191283
591     {"SYNC-HAZARD-WRITE-AFTER-WRITE",
592      nullptr,
593      nullptr,
594      false,
595      {"message_type = GeneralError", "hazard_type = WRITE_AFTER_WRITE",
596       "access = "
597       "VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT(VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT)",
598       "prior_access = SYNC_IMAGE_LAYOUT_TRANSITION", "command = vkCmdDrawIndexed",
599       "prior_command = vkCmdEndRenderPass", "subcmd = 1"}},
600     // http://anglebug.com/399191283
601     {"SYNC-HAZARD-WRITE-AFTER-WRITE",
602      nullptr,
603      nullptr,
604      false,
605      {"message_type = GeneralError", "hazard_type = WRITE_AFTER_WRITE",
606       "access = SYNC_IMAGE_LAYOUT_TRANSITION",
607       "prior_access = "
608       "VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT(VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT)",
609       "command = vkCmdPipelineBarrier", "prior_command = vkCmdEndRenderPass"}},
610     // http://anglebug.com/399191283
611     {"SYNC-HAZARD-READ-AFTER-WRITE",
612      nullptr,
613      nullptr,
614      false,
615      {"message_type = GeneralError", "hazard_type = READ_AFTER_WRITE",
616       "access = "
617       "VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT(VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT)",
618       "prior_access = SYNC_IMAGE_LAYOUT_TRANSITION", "command = vkCmdBeginRenderPass",
619       "prior_command = vkCmdEndRenderPass", "load_op = VK_ATTACHMENT_LOAD_OP_LOAD", "subcmd = 1"}},
620     // https://anglebug.com/400789178
621     {"SYNC-HAZARD-WRITE-AFTER-WRITE",
622      nullptr,
623      nullptr,
624      false,
625      {"message_type = ImageBarrierError", "hazard_type = WRITE_AFTER_WRITE",
626       "access = SYNC_IMAGE_LAYOUT_TRANSITION",
627       "prior_access = "
628       "VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT(VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT)",
629       "command = vkCmdPipelineBarrier", "prior_command = vkCmdEndRenderPass"}},
630     // https://anglebug.com/400789178
631     {"SYNC-HAZARD-WRITE-AFTER-WRITE",
632      nullptr,
633      nullptr,
634      false,
635      {"message_type = RenderPassAttachmentError", "hazard_type = WRITE_AFTER_WRITE",
636       "access = "
637       "VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT(VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT)",
638       "prior_access = SYNC_IMAGE_LAYOUT_TRANSITION", "command = vkCmdDrawIndexed",
639       "prior_command = vkCmdEndRenderPass"}},
640 };
641 
642 // Messages that shouldn't be generated if storeOp=NONE is supported, otherwise they are expected.
643 constexpr vk::SkippedSyncvalMessage kSkippedSyncvalMessagesWithoutStoreOpNone[] = {
644     // These errors are generated when simultaneously using a read-only depth/stencil attachment as
645     // sampler.  This is valid Vulkan.
646     //
647     // When storeOp=NONE is not present, ANGLE uses storeOp=STORE, but considers the image read-only
648     // and produces a hazard.  ANGLE relies on storeOp=NONE and so this is not expected to be worked
649     // around.
650     //
651     // With storeOp=NONE, there is another bug where a depth/stencil attachment may use storeOp=NONE
652     // for depth while storeOp=DONT_CARE for stencil, and the latter causes a synchronization error
653     // (similarly to the previous case as DONT_CARE is also a write operation).
654     // http://anglebug.com/42264496
655     {
656         "SYNC-HAZARD-WRITE-AFTER-READ",
657         "VK_ATTACHMENT_STORE_OP_STORE. Access info (usage: "
658         "SYNC_LATE_FRAGMENT_TESTS_DEPTH_STENCIL_ATTACHMENT_WRITE",
659         "usage: SYNC_FRAGMENT_SHADER_SHADER_",
660     },
661     {
662         "SYNC-HAZARD-READ-AFTER-WRITE",
663         "imageLayout: VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL",
664         "usage: SYNC_FRAGMENT_SHADER_SHADER_",
665     },
666     // From: TraceTest.antutu_refinery http://anglebug.com/42265159
667     {
668         "SYNC-HAZARD-READ-AFTER-WRITE",
669         "imageLayout: VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL",
670         "usage: SYNC_COMPUTE_SHADER_SHADER_SAMPLED_READ",
671     },
672 };
673 
674 // Messages that shouldn't be generated if both loadOp=NONE and storeOp=NONE are supported,
675 // otherwise they are expected.
676 constexpr vk::SkippedSyncvalMessage kSkippedSyncvalMessagesWithoutLoadStoreOpNone[] = {
677     // This error is generated for multiple reasons:
678     //
679     // - http://anglebug.com/42264926
680     // - http://anglebug.com/42263911: This is resolved with storeOp=NONE
681     {
682         "SYNC-HAZARD-WRITE-AFTER-WRITE",
683         "Access info (usage: SYNC_IMAGE_LAYOUT_TRANSITION, prior_usage: "
684         "SYNC_LATE_FRAGMENT_TESTS_DEPTH_STENCIL_ATTACHMENT_WRITE, write_barriers: 0",
685     },
686     // http://anglebug.com/42264926
687     // http://anglebug.com/42265079
688     // http://anglebug.com/42264496
689     {
690         "SYNC-HAZARD-WRITE-AFTER-WRITE",
691         "with loadOp VK_ATTACHMENT_LOAD_OP_DONT_CARE. Access info "
692         "(usage: "
693         "SYNC_EARLY_FRAGMENT_TESTS_DEPTH_STENCIL_ATTACHMENT_WRITE",
694     },
695 };
696 
697 // Messages that are only generated with MSRTT emulation.  Some of these are syncval bugs (discussed
698 // in https://gitlab.khronos.org/vulkan/vulkan/-/issues/3840)
699 constexpr vk::SkippedSyncvalMessage kSkippedSyncvalMessagesWithMSRTTEmulation[] = {
700     // False positive: https://gitlab.khronos.org/vulkan/vulkan/-/issues/3840
701     {
702         "SYNC-HAZARD-READ-AFTER-WRITE",
703         "during depth/stencil resolve read",
704         "SYNC_COLOR_ATTACHMENT_OUTPUT_COLOR_ATTACHMENT_READ",
705     },
706     // Unknown whether ANGLE or syncval bug.
707     {"SYNC-HAZARD-WRITE-AFTER-WRITE",
708      "image layout transition (old_layout: VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, "
709      "new_layout: VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL). Access info (usage: "
710      "SYNC_IMAGE_LAYOUT_TRANSITION",
711      "",
712      false,
713      // TODO: it seems if this filter is removed then the error will be
714      // intersepted by a different filter. Investigate the nature of the
715      // error if necessary how to improve its detection.
716      {
717          "message_type = RenderPassLayoutTransitionError",
718          "old_layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL",
719          "new_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL",
720          "access = SYNC_IMAGE_LAYOUT_TRANSITION",  // probably not needed, message_type implies this
721      }},
722 };
723 
724 enum class DebugMessageReport
725 {
726     Ignore,
727     Print,
728 };
729 
IsMessageInSkipList(const char * message,const char * const skippedList[],size_t skippedListSize)730 bool IsMessageInSkipList(const char *message,
731                          const char *const skippedList[],
732                          size_t skippedListSize)
733 {
734     for (size_t index = 0; index < skippedListSize; ++index)
735     {
736         if (strstr(message, skippedList[index]) != nullptr)
737         {
738             return true;
739         }
740     }
741 
742     return false;
743 }
744 
SyncvalMessageMatchesSkip(const char * messageId,const char * message,const vk::SkippedSyncvalMessage & skip)745 bool SyncvalMessageMatchesSkip(const char *messageId,
746                                const char *message,
747                                const vk::SkippedSyncvalMessage &skip)
748 {
749     // TODO(http://angleproject:391284743): Ongoing transition: textual matches -> extraProperties.
750     // When a skip includes the extraProperties list, use that list and ignore messageContents1/2.
751     // When extraProperties list is not present, use messageContents1/2 as before.
752     if (skip.extraProperties[0])
753     {
754         if (strstr(messageId, skip.messageId) == nullptr)
755         {
756             return false;
757         }
758         // Check that all extraProperties entries are present in the message
759         bool mismatch = false;
760         for (uint32_t i = 0; i < kMaxSyncValExtraProperties; i++)
761         {
762             if (skip.extraProperties[i] == nullptr)
763             {
764                 break;
765             }
766             if (strstr(message, skip.extraProperties[i]) == nullptr)
767             {
768                 mismatch = true;
769                 break;
770             }
771         }
772         return !mismatch;
773     }
774     else
775     {
776         return (strstr(messageId, skip.messageId) != nullptr &&
777                 strstr(message, skip.messageContents1) != nullptr &&
778                 strstr(message, skip.messageContents2) != nullptr);
779     }
780 }
781 
782 // Suppress validation errors that are known.  Returns DebugMessageReport::Ignore in that case.
ShouldReportDebugMessage(Renderer * renderer,const char * messageId,const char * message)783 DebugMessageReport ShouldReportDebugMessage(Renderer *renderer,
784                                             const char *messageId,
785                                             const char *message)
786 {
787     if (message == nullptr || messageId == nullptr)
788     {
789         return DebugMessageReport::Print;
790     }
791 
792     // Check with non-syncval messages:
793     const std::vector<const char *> &skippedMessages = renderer->getSkippedValidationMessages();
794     if (IsMessageInSkipList(message, skippedMessages.data(), skippedMessages.size()))
795     {
796         return DebugMessageReport::Ignore;
797     }
798 
799     // Then check with syncval messages:
800     const bool isColorFramebufferFetchUsed = renderer->isColorFramebufferFetchUsed();
801 
802     for (const vk::SkippedSyncvalMessage &skip : renderer->getSkippedSyncvalMessages())
803     {
804         if (!SyncvalMessageMatchesSkip(messageId, message, skip))
805         {
806             continue;
807         }
808 
809         if (skip.isDueToNonConformantCoherentColorFramebufferFetch)
810         {
811             // If the error is due to exposing coherent framebuffer fetch (without
812             // VK_EXT_rasterization_order_attachment_access), but framebuffer fetch has not been
813             // used by the application, report it.
814             //
815             // Note that currently syncval doesn't support the
816             // VK_EXT_rasterization_order_attachment_access extension, so the syncval messages would
817             // continue to be produced despite the extension.
818             constexpr bool kSyncValSupportsRasterizationOrderExtension = false;
819             const bool hasRasterizationOrderExtension =
820                 renderer->getFeatures().supportsRasterizationOrderAttachmentAccess.enabled &&
821                 kSyncValSupportsRasterizationOrderExtension;
822             if (!isColorFramebufferFetchUsed || hasRasterizationOrderExtension)
823             {
824                 return DebugMessageReport::Print;
825             }
826         }
827 
828         // Ignore the message as it matched one the the skips
829         return DebugMessageReport::Ignore;
830     }
831 
832     // Message didn't match any skips, report
833     return DebugMessageReport::Print;
834 }
835 
GetVkObjectTypeName(VkObjectType type)836 const char *GetVkObjectTypeName(VkObjectType type)
837 {
838     switch (type)
839     {
840         case VK_OBJECT_TYPE_UNKNOWN:
841             return "Unknown";
842         case VK_OBJECT_TYPE_INSTANCE:
843             return "Instance";
844         case VK_OBJECT_TYPE_PHYSICAL_DEVICE:
845             return "Physical Device";
846         case VK_OBJECT_TYPE_DEVICE:
847             return "Device";
848         case VK_OBJECT_TYPE_QUEUE:
849             return "Queue";
850         case VK_OBJECT_TYPE_SEMAPHORE:
851             return "Semaphore";
852         case VK_OBJECT_TYPE_COMMAND_BUFFER:
853             return "Command Buffer";
854         case VK_OBJECT_TYPE_FENCE:
855             return "Fence";
856         case VK_OBJECT_TYPE_DEVICE_MEMORY:
857             return "Device Memory";
858         case VK_OBJECT_TYPE_BUFFER:
859             return "Buffer";
860         case VK_OBJECT_TYPE_IMAGE:
861             return "Image";
862         case VK_OBJECT_TYPE_EVENT:
863             return "Event";
864         case VK_OBJECT_TYPE_QUERY_POOL:
865             return "Query Pool";
866         case VK_OBJECT_TYPE_BUFFER_VIEW:
867             return "Buffer View";
868         case VK_OBJECT_TYPE_IMAGE_VIEW:
869             return "Image View";
870         case VK_OBJECT_TYPE_SHADER_MODULE:
871             return "Shader Module";
872         case VK_OBJECT_TYPE_PIPELINE_CACHE:
873             return "Pipeline Cache";
874         case VK_OBJECT_TYPE_PIPELINE_LAYOUT:
875             return "Pipeline Layout";
876         case VK_OBJECT_TYPE_RENDER_PASS:
877             return "Render Pass";
878         case VK_OBJECT_TYPE_PIPELINE:
879             return "Pipeline";
880         case VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT:
881             return "Descriptor Set Layout";
882         case VK_OBJECT_TYPE_SAMPLER:
883             return "Sampler";
884         case VK_OBJECT_TYPE_DESCRIPTOR_POOL:
885             return "Descriptor Pool";
886         case VK_OBJECT_TYPE_DESCRIPTOR_SET:
887             return "Descriptor Set";
888         case VK_OBJECT_TYPE_FRAMEBUFFER:
889             return "Framebuffer";
890         case VK_OBJECT_TYPE_COMMAND_POOL:
891             return "Command Pool";
892         case VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION:
893             return "Sampler YCbCr Conversion";
894         case VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE:
895             return "Descriptor Update Template";
896         case VK_OBJECT_TYPE_SURFACE_KHR:
897             return "Surface";
898         case VK_OBJECT_TYPE_SWAPCHAIN_KHR:
899             return "Swapchain";
900         case VK_OBJECT_TYPE_DISPLAY_KHR:
901             return "Display";
902         case VK_OBJECT_TYPE_DISPLAY_MODE_KHR:
903             return "Display Mode";
904         case VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NV:
905             return "Indirect Commands Layout";
906         case VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT:
907             return "Debug Utils Messenger";
908         case VK_OBJECT_TYPE_VALIDATION_CACHE_EXT:
909             return "Validation Cache";
910         case VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV:
911             return "Acceleration Structure";
912         default:
913             return "<Unrecognized>";
914     }
915 }
916 
917 VKAPI_ATTR VkBool32 VKAPI_CALL
DebugUtilsMessenger(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,VkDebugUtilsMessageTypeFlagsEXT messageTypes,const VkDebugUtilsMessengerCallbackDataEXT * callbackData,void * userData)918 DebugUtilsMessenger(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
919                     VkDebugUtilsMessageTypeFlagsEXT messageTypes,
920                     const VkDebugUtilsMessengerCallbackDataEXT *callbackData,
921                     void *userData)
922 {
923     Renderer *renderer = static_cast<Renderer *>(userData);
924 
925     // VUID-VkDebugUtilsMessengerCallbackDataEXT-pMessage-parameter
926     // pMessage must be a null-terminated UTF-8 string
927     ASSERT(callbackData->pMessage != nullptr);
928 
929     // See if it's an issue we are aware of and don't want to be spammed about.
930     // Always report the debug message if message ID is missing
931     if (callbackData->pMessageIdName != nullptr &&
932         ShouldReportDebugMessage(renderer, callbackData->pMessageIdName, callbackData->pMessage) ==
933             DebugMessageReport::Ignore)
934     {
935         return VK_FALSE;
936     }
937 
938     std::ostringstream log;
939     if (callbackData->pMessageIdName != nullptr)
940     {
941         log << "[ " << callbackData->pMessageIdName << " ] ";
942     }
943     log << callbackData->pMessage << std::endl;
944 
945     // Aesthetic value based on length of the function name, line number, etc.
946     constexpr size_t kStartIndent = 28;
947 
948     // Output the debug marker hierarchy under which this error has occurred.
949     size_t indent = kStartIndent;
950     if (callbackData->queueLabelCount > 0)
951     {
952         log << std::string(indent++, ' ') << "<Queue Label Hierarchy:>" << std::endl;
953         for (uint32_t i = 0; i < callbackData->queueLabelCount; ++i)
954         {
955             log << std::string(indent++, ' ') << callbackData->pQueueLabels[i].pLabelName
956                 << std::endl;
957         }
958     }
959     if (callbackData->cmdBufLabelCount > 0)
960     {
961         log << std::string(indent++, ' ') << "<Command Buffer Label Hierarchy:>" << std::endl;
962         for (uint32_t i = 0; i < callbackData->cmdBufLabelCount; ++i)
963         {
964             log << std::string(indent++, ' ') << callbackData->pCmdBufLabels[i].pLabelName
965                 << std::endl;
966         }
967     }
968     // Output the objects involved in this error message.
969     if (callbackData->objectCount > 0)
970     {
971         for (uint32_t i = 0; i < callbackData->objectCount; ++i)
972         {
973             const char *objectName = callbackData->pObjects[i].pObjectName;
974             const char *objectType = GetVkObjectTypeName(callbackData->pObjects[i].objectType);
975             uint64_t objectHandle  = callbackData->pObjects[i].objectHandle;
976             log << std::string(indent, ' ') << "Object: ";
977             if (objectHandle == 0)
978             {
979                 log << "VK_NULL_HANDLE";
980             }
981             else
982             {
983                 log << "0x" << std::hex << objectHandle << std::dec;
984             }
985             log << " (type = " << objectType << "(" << callbackData->pObjects[i].objectType << "))";
986             if (objectName)
987             {
988                 log << " [" << objectName << "]";
989             }
990             log << std::endl;
991         }
992     }
993 
994     bool isError    = (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) != 0;
995     std::string msg = log.str();
996 
997     renderer->onNewValidationMessage(msg);
998 
999     if (isError)
1000     {
1001         ERR() << msg;
1002     }
1003     else
1004     {
1005         WARN() << msg;
1006     }
1007 
1008     return VK_FALSE;
1009 }
1010 
1011 VKAPI_ATTR void VKAPI_CALL
MemoryReportCallback(const VkDeviceMemoryReportCallbackDataEXT * callbackData,void * userData)1012 MemoryReportCallback(const VkDeviceMemoryReportCallbackDataEXT *callbackData, void *userData)
1013 {
1014     Renderer *renderer = static_cast<Renderer *>(userData);
1015     renderer->processMemoryReportCallback(*callbackData);
1016 }
1017 
LimitVersionTo(const gl::Version & current,const gl::Version & lower)1018 gl::Version LimitVersionTo(const gl::Version &current, const gl::Version &lower)
1019 {
1020     return std::min(current, lower);
1021 }
1022 
FencePropertiesCompatibleWithAndroid(const VkExternalFenceProperties & externalFenceProperties)1023 [[maybe_unused]] bool FencePropertiesCompatibleWithAndroid(
1024     const VkExternalFenceProperties &externalFenceProperties)
1025 {
1026     // handleType here is the external fence type -
1027     // we want type compatible with creating and export/dup() Android FD
1028 
1029     // Imported handleType that can be exported - need for vkGetFenceFdKHR()
1030     if ((externalFenceProperties.exportFromImportedHandleTypes &
1031          VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR) == 0)
1032     {
1033         return false;
1034     }
1035 
1036     // HandleTypes which can be specified at creating a fence
1037     if ((externalFenceProperties.compatibleHandleTypes &
1038          VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR) == 0)
1039     {
1040         return false;
1041     }
1042 
1043     constexpr VkExternalFenceFeatureFlags kFeatureFlags =
1044         (VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT_KHR |
1045          VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT_KHR);
1046     if ((externalFenceProperties.externalFenceFeatures & kFeatureFlags) != kFeatureFlags)
1047     {
1048         return false;
1049     }
1050 
1051     return true;
1052 }
1053 
SemaphorePropertiesCompatibleWithAndroid(const VkExternalSemaphoreProperties & externalSemaphoreProperties)1054 [[maybe_unused]] bool SemaphorePropertiesCompatibleWithAndroid(
1055     const VkExternalSemaphoreProperties &externalSemaphoreProperties)
1056 {
1057     // handleType here is the external semaphore type -
1058     // we want type compatible with importing an Android FD
1059 
1060     constexpr VkExternalSemaphoreFeatureFlags kFeatureFlags =
1061         (VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHR);
1062     if ((externalSemaphoreProperties.externalSemaphoreFeatures & kFeatureFlags) != kFeatureFlags)
1063     {
1064         return false;
1065     }
1066 
1067     return true;
1068 }
1069 
1070 // Exclude memory type indices that include the host-visible bit from VMA image suballocation.
GetMemoryTypeBitsExcludingHostVisible(Renderer * renderer,VkMemoryPropertyFlags propertyFlags,uint32_t availableMemoryTypeBits)1071 uint32_t GetMemoryTypeBitsExcludingHostVisible(Renderer *renderer,
1072                                                VkMemoryPropertyFlags propertyFlags,
1073                                                uint32_t availableMemoryTypeBits)
1074 {
1075     const vk::MemoryProperties &memoryProperties = renderer->getMemoryProperties();
1076     ASSERT(memoryProperties.getMemoryTypeCount() <= 32);
1077     uint32_t memoryTypeBitsOut = availableMemoryTypeBits;
1078 
1079     // For best allocation results, the memory type indices that include the host-visible flag bit
1080     // are removed.
1081     for (size_t memoryIndex : angle::BitSet<32>(availableMemoryTypeBits))
1082     {
1083         VkMemoryPropertyFlags memoryFlags =
1084             memoryProperties.getMemoryType(static_cast<uint32_t>(memoryIndex)).propertyFlags;
1085         if ((memoryFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0)
1086         {
1087             memoryTypeBitsOut &= ~(angle::Bit<uint32_t>(memoryIndex));
1088             continue;
1089         }
1090 
1091         // If the protected bit is not required, all memory type indices with this bit should be
1092         // ignored.
1093         if ((memoryFlags & ~propertyFlags & VK_MEMORY_PROPERTY_PROTECTED_BIT) != 0)
1094         {
1095             memoryTypeBitsOut &= ~(angle::Bit<uint32_t>(memoryIndex));
1096         }
1097     }
1098 
1099     return memoryTypeBitsOut;
1100 }
1101 
1102 // Header data type used for the pipeline cache.
1103 ANGLE_ENABLE_STRUCT_PADDING_WARNINGS
1104 
1105 class CacheDataHeader
1106 {
1107   public:
setData(uint32_t compressedDataCRC,uint32_t cacheDataSize,size_t numChunks,size_t chunkIndex,uint32_t chunkCRC)1108     void setData(uint32_t compressedDataCRC,
1109                  uint32_t cacheDataSize,
1110                  size_t numChunks,
1111                  size_t chunkIndex,
1112                  uint32_t chunkCRC)
1113     {
1114         mVersion           = kPipelineCacheVersion;
1115         mCompressedDataCRC = compressedDataCRC;
1116         mCacheDataSize     = cacheDataSize;
1117         SetBitField(mNumChunks, numChunks);
1118         SetBitField(mChunkIndex, chunkIndex);
1119         mChunkCRC = chunkCRC;
1120     }
1121 
getData(uint32_t * versionOut,uint32_t * compressedDataCRCOut,uint32_t * cacheDataSizeOut,size_t * numChunksOut,size_t * chunkIndexOut,uint32_t * chunkCRCOut) const1122     void getData(uint32_t *versionOut,
1123                  uint32_t *compressedDataCRCOut,
1124                  uint32_t *cacheDataSizeOut,
1125                  size_t *numChunksOut,
1126                  size_t *chunkIndexOut,
1127                  uint32_t *chunkCRCOut) const
1128     {
1129         *versionOut           = mVersion;
1130         *compressedDataCRCOut = mCompressedDataCRC;
1131         *cacheDataSizeOut     = mCacheDataSize;
1132         *numChunksOut         = static_cast<size_t>(mNumChunks);
1133         *chunkIndexOut        = static_cast<size_t>(mChunkIndex);
1134         *chunkCRCOut          = mChunkCRC;
1135     }
1136 
1137   private:
1138     // For pipeline cache, the values stored in key data has the following order:
1139     // {headerVersion, compressedDataCRC, originalCacheSize, numChunks, chunkIndex, chunkCRC;
1140     // chunkCompressedData}. The header values are used to validate the data. For example, if the
1141     // original and compressed sizes are 70000 bytes (68k) and 68841 bytes (67k), the compressed
1142     // data will be divided into two chunks: {ver,crc0,70000,2,0;34421 bytes} and
1143     // {ver,crc1,70000,2,1;34420 bytes}.
1144     // The version is used to keep track of the cache format. Please note that kPipelineCacheVersion
1145     // must be incremented by 1 in case of any updates to the cache header or data structure. While
1146     // it is possible to modify the fields in the header, it is recommended to keep the version on
1147     // top and the same size unless absolutely necessary.
1148 
1149     uint32_t mVersion;
1150     uint32_t mCompressedDataCRC;
1151     uint32_t mCacheDataSize;
1152     uint16_t mNumChunks;
1153     uint16_t mChunkIndex;
1154     uint32_t mChunkCRC;
1155 };
1156 
1157 ANGLE_DISABLE_STRUCT_PADDING_WARNINGS
1158 
1159 // Pack header data for the pipeline cache key data.
PackHeaderDataForPipelineCache(uint32_t compressedDataCRC,uint32_t cacheDataSize,size_t numChunks,size_t chunkIndex,uint32_t chunkCRC,CacheDataHeader * dataOut)1160 void PackHeaderDataForPipelineCache(uint32_t compressedDataCRC,
1161                                     uint32_t cacheDataSize,
1162                                     size_t numChunks,
1163                                     size_t chunkIndex,
1164                                     uint32_t chunkCRC,
1165                                     CacheDataHeader *dataOut)
1166 {
1167     dataOut->setData(compressedDataCRC, cacheDataSize, numChunks, chunkIndex, chunkCRC);
1168 }
1169 
1170 // Unpack header data from the pipeline cache key data.
UnpackHeaderDataForPipelineCache(CacheDataHeader * data,uint32_t * versionOut,uint32_t * compressedDataCRCOut,uint32_t * cacheDataSizeOut,size_t * numChunksOut,size_t * chunkIndexOut,uint32_t * chunkCRCOut)1171 void UnpackHeaderDataForPipelineCache(CacheDataHeader *data,
1172                                       uint32_t *versionOut,
1173                                       uint32_t *compressedDataCRCOut,
1174                                       uint32_t *cacheDataSizeOut,
1175                                       size_t *numChunksOut,
1176                                       size_t *chunkIndexOut,
1177                                       uint32_t *chunkCRCOut)
1178 {
1179     data->getData(versionOut, compressedDataCRCOut, cacheDataSizeOut, numChunksOut, chunkIndexOut,
1180                   chunkCRCOut);
1181 }
1182 
ComputePipelineCacheVkChunkKey(const VkPhysicalDeviceProperties & physicalDeviceProperties,const size_t slotIndex,const size_t chunkIndex,angle::BlobCacheKey * hashOut)1183 void ComputePipelineCacheVkChunkKey(const VkPhysicalDeviceProperties &physicalDeviceProperties,
1184                                     const size_t slotIndex,
1185                                     const size_t chunkIndex,
1186                                     angle::BlobCacheKey *hashOut)
1187 {
1188     std::ostringstream hashStream("ANGLE Pipeline Cache: ", std::ios_base::ate);
1189     // Add the pipeline cache UUID to make sure the blob cache always gives a compatible pipeline
1190     // cache.  It's not particularly necessary to write it as a hex number as done here, so long as
1191     // there is no '\0' in the result.
1192     for (const uint32_t c : physicalDeviceProperties.pipelineCacheUUID)
1193     {
1194         hashStream << std::hex << c;
1195     }
1196     // Add the vendor and device id too for good measure.
1197     hashStream << std::hex << physicalDeviceProperties.vendorID;
1198     hashStream << std::hex << physicalDeviceProperties.deviceID;
1199 
1200     // Add slotIndex to generate unique keys for each slot.
1201     hashStream << std::hex << static_cast<uint32_t>(slotIndex);
1202 
1203     // Add chunkIndex to generate unique key for chunks.
1204     hashStream << std::hex << static_cast<uint32_t>(chunkIndex);
1205 
1206     const std::string &hashString = hashStream.str();
1207     angle::base::SHA1HashBytes(reinterpret_cast<const unsigned char *>(hashString.c_str()),
1208                                hashString.length(), hashOut->data());
1209 }
1210 
1211 struct PipelineCacheVkChunkInfo
1212 {
1213     const uint8_t *data;
1214     size_t dataSize;
1215     uint32_t crc;
1216     angle::BlobCacheKey cacheHash;
1217 };
1218 
1219 // Enough to store 32M data using 64K chunks.
1220 constexpr size_t kFastPipelineCacheVkChunkInfosSize = 512;
1221 using PipelineCacheVkChunkInfos =
1222     angle::FastVector<PipelineCacheVkChunkInfo, kFastPipelineCacheVkChunkInfosSize>;
1223 
1224 PipelineCacheVkChunkInfos GetPipelineCacheVkChunkInfos(Renderer *renderer,
1225                                                        const angle::MemoryBuffer &compressedData,
1226                                                        const size_t numChunks,
1227                                                        const size_t chunkSize,
1228                                                        const size_t slotIndex);
1229 
1230 // Returns the number of stored chunks.  "lastNumStoredChunks" is the number of chunks,
1231 // stored in the last call.  If it is positive, function will only restore missing chunks.
1232 size_t StorePipelineCacheVkChunks(vk::GlobalOps *globalOps,
1233                                   Renderer *renderer,
1234                                   const size_t lastNumStoredChunks,
1235                                   const PipelineCacheVkChunkInfos &chunkInfos,
1236                                   const size_t cacheDataSize,
1237                                   angle::MemoryBuffer *scratchBuffer);
1238 
1239 // Erasing is done by writing 1/0-sized chunks starting from the startChunk.
1240 void ErasePipelineCacheVkChunks(vk::GlobalOps *globalOps,
1241                                 Renderer *renderer,
1242                                 const size_t startChunk,
1243                                 const size_t numChunks,
1244                                 const size_t slotIndex,
1245                                 angle::MemoryBuffer *scratchBuffer);
1246 
CompressAndStorePipelineCacheVk(vk::GlobalOps * globalOps,Renderer * renderer,const std::vector<uint8_t> & cacheData,const size_t maxTotalSize)1247 void CompressAndStorePipelineCacheVk(vk::GlobalOps *globalOps,
1248                                      Renderer *renderer,
1249                                      const std::vector<uint8_t> &cacheData,
1250                                      const size_t maxTotalSize)
1251 {
1252     // Though the pipeline cache will be compressed and divided into several chunks to store in blob
1253     // cache, the largest total size of blob cache is only 2M in android now, so there is no use to
1254     // handle big pipeline cache when android will reject it finally.
1255     if (cacheData.size() >= maxTotalSize)
1256     {
1257         static bool warned = false;
1258         if (!warned)
1259         {
1260             // TODO: handle the big pipeline cache. http://anglebug.com/42263322
1261             WARN() << "Skip syncing pipeline cache data when it's larger than maxTotalSize. "
1262                       "(this message will no longer repeat)";
1263             warned = true;
1264         }
1265         return;
1266     }
1267 
1268     // To make it possible to store more pipeline cache data, compress the whole pipelineCache.
1269     angle::MemoryBuffer compressedData;
1270 
1271     if (!angle::CompressBlob(cacheData.size(), cacheData.data(), &compressedData))
1272     {
1273         WARN() << "Skip syncing pipeline cache data as it failed compression.";
1274         return;
1275     }
1276 
1277     // If the size of compressedData is larger than (kMaxBlobCacheSize - sizeof(numChunks)),
1278     // the pipelineCache still can't be stored in blob cache. Divide the large compressed
1279     // pipelineCache into several parts to store separately. There is no function to
1280     // query the limit size in android.
1281     constexpr size_t kMaxBlobCacheSize = 64 * 1024;
1282 
1283     const size_t numChunks = UnsignedCeilDivide(static_cast<unsigned int>(compressedData.size()),
1284                                                 kMaxBlobCacheSize - sizeof(CacheDataHeader));
1285     ASSERT(numChunks <= UINT16_MAX);
1286     const size_t chunkSize = UnsignedCeilDivide(static_cast<unsigned int>(compressedData.size()),
1287                                                 static_cast<unsigned int>(numChunks));
1288 
1289     angle::MemoryBuffer scratchBuffer;
1290     if (!scratchBuffer.resize(sizeof(CacheDataHeader) + chunkSize))
1291     {
1292         WARN() << "Skip syncing pipeline cache data due to out of memory.";
1293         return;
1294     }
1295 
1296     size_t previousSlotIndex = 0;
1297     const size_t slotIndex   = renderer->getNextPipelineCacheBlobCacheSlotIndex(&previousSlotIndex);
1298     const size_t previousNumChunks = renderer->updatePipelineCacheChunkCount(numChunks);
1299     const bool isSlotChanged       = (slotIndex != previousSlotIndex);
1300 
1301     PipelineCacheVkChunkInfos chunkInfos =
1302         GetPipelineCacheVkChunkInfos(renderer, compressedData, numChunks, chunkSize, slotIndex);
1303 
1304     // Store all chunks without checking if they already exist (because they can't).
1305     size_t numStoredChunks = StorePipelineCacheVkChunks(globalOps, renderer, 0, chunkInfos,
1306                                                         cacheData.size(), &scratchBuffer);
1307     ASSERT(numStoredChunks == numChunks);
1308 
1309     // Erase all chunks from the previous slot or any trailing chunks from the current slot.
1310     ASSERT(renderer->getFeatures().useDualPipelineBlobCacheSlots.enabled == isSlotChanged);
1311     if (isSlotChanged || previousNumChunks > numChunks)
1312     {
1313         const size_t startChunk = isSlotChanged ? 0 : numChunks;
1314         ErasePipelineCacheVkChunks(globalOps, renderer, startChunk, previousNumChunks,
1315                                    previousSlotIndex, &scratchBuffer);
1316     }
1317 
1318     if (!renderer->getFeatures().verifyPipelineCacheInBlobCache.enabled)
1319     {
1320         // No need to verify and restore possibly evicted chunks.
1321         return;
1322     }
1323 
1324     // Verify and restore possibly evicted chunks.
1325     do
1326     {
1327         const size_t lastNumStoredChunks = numStoredChunks;
1328         numStoredChunks = StorePipelineCacheVkChunks(globalOps, renderer, lastNumStoredChunks,
1329                                                      chunkInfos, cacheData.size(), &scratchBuffer);
1330         // Number of stored chunks must decrease so the loop can eventually exit.
1331         ASSERT(numStoredChunks < lastNumStoredChunks);
1332 
1333         // If blob cache evicts old items first, any possibly evicted chunks in the first call,
1334         // should have been restored in the above call without triggering another eviction, so no
1335         // need to continue the loop.
1336     } while (!renderer->getFeatures().hasBlobCacheThatEvictsOldItemsFirst.enabled &&
1337              numStoredChunks > 0);
1338 }
1339 
GetPipelineCacheVkChunkInfos(Renderer * renderer,const angle::MemoryBuffer & compressedData,const size_t numChunks,const size_t chunkSize,const size_t slotIndex)1340 PipelineCacheVkChunkInfos GetPipelineCacheVkChunkInfos(Renderer *renderer,
1341                                                        const angle::MemoryBuffer &compressedData,
1342                                                        const size_t numChunks,
1343                                                        const size_t chunkSize,
1344                                                        const size_t slotIndex)
1345 {
1346     const VkPhysicalDeviceProperties &physicalDeviceProperties =
1347         renderer->getPhysicalDeviceProperties();
1348 
1349     PipelineCacheVkChunkInfos chunkInfos(numChunks);
1350     uint32_t chunkCrc = kEnableCRCForPipelineCache ? angle::InitCRC32() : 0;
1351 
1352     for (size_t chunkIndex = 0; chunkIndex < numChunks; ++chunkIndex)
1353     {
1354         const size_t compressedOffset = chunkIndex * chunkSize;
1355         const uint8_t *data           = compressedData.data() + compressedOffset;
1356         const size_t dataSize = std::min(chunkSize, compressedData.size() - compressedOffset);
1357 
1358         // Create unique hash key.
1359         angle::BlobCacheKey cacheHash;
1360         ComputePipelineCacheVkChunkKey(physicalDeviceProperties, slotIndex, chunkIndex, &cacheHash);
1361 
1362         if (kEnableCRCForPipelineCache)
1363         {
1364             // Generate running CRC. Last chunk will have CRC of the entire data.
1365             chunkCrc = angle::UpdateCRC32(chunkCrc, data, dataSize);
1366         }
1367 
1368         chunkInfos[chunkIndex] = PipelineCacheVkChunkInfo{data, dataSize, chunkCrc, cacheHash};
1369     }
1370 
1371     return chunkInfos;
1372 }
1373 
StorePipelineCacheVkChunks(vk::GlobalOps * globalOps,Renderer * renderer,const size_t lastNumStoredChunks,const PipelineCacheVkChunkInfos & chunkInfos,const size_t cacheDataSize,angle::MemoryBuffer * scratchBuffer)1374 size_t StorePipelineCacheVkChunks(vk::GlobalOps *globalOps,
1375                                   Renderer *renderer,
1376                                   const size_t lastNumStoredChunks,
1377                                   const PipelineCacheVkChunkInfos &chunkInfos,
1378                                   const size_t cacheDataSize,
1379                                   angle::MemoryBuffer *scratchBuffer)
1380 {
1381     // Store chunks in revers order, so when 0 chunk is available - all chunks are available.
1382 
1383     angle::FastVector<bool, kFastPipelineCacheVkChunkInfosSize> isMissing;
1384     size_t numChunksToStore = chunkInfos.size();
1385 
1386     // Need to check existing chunks if this is not the first time this function is called.
1387     if (lastNumStoredChunks > 0)
1388     {
1389         isMissing.resize(chunkInfos.size());
1390         numChunksToStore = 0;
1391 
1392         // Defer storing chunks until all missing chunks are found to avoid unnecessary stores.
1393         size_t chunkIndex = chunkInfos.size();
1394         while (chunkIndex > 0)
1395         {
1396             --chunkIndex;
1397             const PipelineCacheVkChunkInfo &chunkInfo = chunkInfos[chunkIndex];
1398 
1399             angle::BlobCacheValue value;
1400             if (globalOps->getBlob(chunkInfo.cacheHash, &value) &&
1401                 value.size() == sizeof(CacheDataHeader) + chunkInfo.dataSize)
1402             {
1403                 if (renderer->getFeatures().hasBlobCacheThatEvictsOldItemsFirst.enabled)
1404                 {
1405                     // No need to check next chunks, since they are newer than the current and
1406                     // should also be present.
1407                     break;
1408                 }
1409                 continue;
1410             }
1411 
1412             isMissing[chunkIndex] = true;
1413             ++numChunksToStore;
1414 
1415             if (numChunksToStore == lastNumStoredChunks)
1416             {
1417                 // No need to restore missing chunks, since new number is already same as was stored
1418                 // last time.
1419                 static bool warned = false;
1420                 if (!warned)
1421                 {
1422                     WARN() << "Skip syncing pipeline cache data due to not able to store "
1423                            << numChunksToStore << " chunks (out of " << chunkInfos.size()
1424                            << ") into the blob cache. (this message will no longer repeat)";
1425                     warned = true;
1426                 }
1427                 return 0;
1428             }
1429         }
1430 
1431         if (numChunksToStore == 0)
1432         {
1433             return 0;
1434         }
1435     }
1436 
1437     // Now store/restore chunks.
1438 
1439     // Last chunk have CRC of the entire data.
1440     const uint32_t compressedDataCRC = chunkInfos.back().crc;
1441 
1442     ASSERT(scratchBuffer != nullptr);
1443     angle::MemoryBuffer &keyData = *scratchBuffer;
1444 
1445     size_t chunkIndex = chunkInfos.size();
1446     while (chunkIndex > 0)
1447     {
1448         --chunkIndex;
1449         if (lastNumStoredChunks > 0 && !isMissing[chunkIndex])
1450         {
1451             // Skip restoring chunk if it is not missing.
1452             continue;
1453         }
1454         const PipelineCacheVkChunkInfo &chunkInfo = chunkInfos[chunkIndex];
1455 
1456         // Add the header data, followed by the compressed data.
1457         ASSERT(cacheDataSize <= UINT32_MAX);
1458         CacheDataHeader headerData = {};
1459         PackHeaderDataForPipelineCache(compressedDataCRC, static_cast<uint32_t>(cacheDataSize),
1460                                        chunkInfos.size(), chunkIndex, chunkInfo.crc, &headerData);
1461         keyData.setSize(sizeof(CacheDataHeader) + chunkInfo.dataSize);
1462         memcpy(keyData.data(), &headerData, sizeof(CacheDataHeader));
1463         memcpy(keyData.data() + sizeof(CacheDataHeader), chunkInfo.data, chunkInfo.dataSize);
1464 
1465         globalOps->putBlob(chunkInfo.cacheHash, keyData);
1466     }
1467 
1468     return numChunksToStore;
1469 }
1470 
ErasePipelineCacheVkChunks(vk::GlobalOps * globalOps,Renderer * renderer,const size_t startChunk,const size_t numChunks,const size_t slotIndex,angle::MemoryBuffer * scratchBuffer)1471 void ErasePipelineCacheVkChunks(vk::GlobalOps *globalOps,
1472                                 Renderer *renderer,
1473                                 const size_t startChunk,
1474                                 const size_t numChunks,
1475                                 const size_t slotIndex,
1476                                 angle::MemoryBuffer *scratchBuffer)
1477 {
1478     const VkPhysicalDeviceProperties &physicalDeviceProperties =
1479         renderer->getPhysicalDeviceProperties();
1480 
1481     ASSERT(scratchBuffer != nullptr);
1482     angle::MemoryBuffer &keyData = *scratchBuffer;
1483 
1484     keyData.setSize(
1485         renderer->getFeatures().useEmptyBlobsToEraseOldPipelineCacheFromBlobCache.enabled ? 0 : 1);
1486 
1487     // Fill data (if any) with zeroes for security.
1488     memset(keyData.data(), 0, keyData.size());
1489 
1490     for (size_t chunkIndex = startChunk; chunkIndex < numChunks; ++chunkIndex)
1491     {
1492         egl::BlobCache::Key chunkCacheHash;
1493         ComputePipelineCacheVkChunkKey(physicalDeviceProperties, slotIndex, chunkIndex,
1494                                        &chunkCacheHash);
1495         globalOps->putBlob(chunkCacheHash, keyData);
1496     }
1497 }
1498 
1499 class CompressAndStorePipelineCacheTask : public angle::Closure
1500 {
1501   public:
CompressAndStorePipelineCacheTask(vk::GlobalOps * globalOps,Renderer * renderer,std::vector<uint8_t> && cacheData,size_t kMaxTotalSize)1502     CompressAndStorePipelineCacheTask(vk::GlobalOps *globalOps,
1503                                       Renderer *renderer,
1504                                       std::vector<uint8_t> &&cacheData,
1505                                       size_t kMaxTotalSize)
1506         : mGlobalOps(globalOps),
1507           mRenderer(renderer),
1508           mCacheData(std::move(cacheData)),
1509           mMaxTotalSize(kMaxTotalSize)
1510     {}
1511 
operator ()()1512     void operator()() override
1513     {
1514         ANGLE_TRACE_EVENT0("gpu.angle", "CompressAndStorePipelineCacheVk");
1515         CompressAndStorePipelineCacheVk(mGlobalOps, mRenderer, mCacheData, mMaxTotalSize);
1516     }
1517 
1518   private:
1519     vk::GlobalOps *mGlobalOps;
1520     Renderer *mRenderer;
1521     std::vector<uint8_t> mCacheData;
1522     size_t mMaxTotalSize;
1523 };
1524 
GetAndDecompressPipelineCacheVk(vk::ErrorContext * context,vk::GlobalOps * globalOps,angle::MemoryBuffer * uncompressedData,bool * success)1525 angle::Result GetAndDecompressPipelineCacheVk(vk::ErrorContext *context,
1526                                               vk::GlobalOps *globalOps,
1527                                               angle::MemoryBuffer *uncompressedData,
1528                                               bool *success)
1529 {
1530     // Make sure that the bool output is initialized to false.
1531     *success = false;
1532 
1533     Renderer *renderer = context->getRenderer();
1534 
1535     const VkPhysicalDeviceProperties &physicalDeviceProperties =
1536         renderer->getPhysicalDeviceProperties();
1537 
1538     const size_t firstSlotIndex = renderer->getNextPipelineCacheBlobCacheSlotIndex(nullptr);
1539     size_t slotIndex            = firstSlotIndex;
1540 
1541     angle::BlobCacheKey chunkCacheHash;
1542     angle::BlobCacheValue keyData;
1543 
1544     // Iterate over available slots until data is found (only expected single slot with data).
1545     while (true)
1546     {
1547         // Compute the hash key of chunkIndex 0 and find the first cache data in blob cache.
1548         ComputePipelineCacheVkChunkKey(physicalDeviceProperties, slotIndex, 0, &chunkCacheHash);
1549 
1550         if (globalOps->getBlob(chunkCacheHash, &keyData) &&
1551             keyData.size() >= sizeof(CacheDataHeader))
1552         {
1553             // Found slot with data.
1554             break;
1555         }
1556         // Nothing in the cache for current slotIndex.
1557 
1558         slotIndex = renderer->getNextPipelineCacheBlobCacheSlotIndex(nullptr);
1559         if (slotIndex == firstSlotIndex)
1560         {
1561             // Nothing in all slots.
1562             return angle::Result::Continue;
1563         }
1564         // Try next slot.
1565     }
1566 
1567     // Get the number of chunks and other values from the header for data validation.
1568     uint32_t cacheVersion;
1569     uint32_t compressedDataCRC;
1570     uint32_t uncompressedCacheDataSize;
1571     size_t numChunks;
1572     size_t chunkIndex0;
1573     uint32_t chunkCRC;
1574 
1575     CacheDataHeader headerData = {};
1576     memcpy(&headerData, keyData.data(), sizeof(CacheDataHeader));
1577     UnpackHeaderDataForPipelineCache(&headerData, &cacheVersion, &compressedDataCRC,
1578                                      &uncompressedCacheDataSize, &numChunks, &chunkIndex0,
1579                                      &chunkCRC);
1580     if (cacheVersion == kPipelineCacheVersion)
1581     {
1582         // The data must not contain corruption.
1583         if (chunkIndex0 != 0 || numChunks == 0 || uncompressedCacheDataSize == 0)
1584         {
1585             FATAL() << "Unexpected values while unpacking chunk index 0: " << "cacheVersion = "
1586                     << cacheVersion << ", chunkIndex = " << chunkIndex0
1587                     << ", numChunks = " << numChunks
1588                     << ", uncompressedCacheDataSize = " << uncompressedCacheDataSize;
1589         }
1590     }
1591     else
1592     {
1593         WARN() << "Change in cache header version detected: " << "newVersion = "
1594                << kPipelineCacheVersion << ", existingVersion = " << cacheVersion;
1595 
1596         return angle::Result::Continue;
1597     }
1598 
1599     renderer->updatePipelineCacheChunkCount(numChunks);
1600 
1601     size_t chunkSize      = keyData.size() - sizeof(CacheDataHeader);
1602     size_t compressedSize = 0;
1603 
1604     uint32_t computedChunkCRC = kEnableCRCForPipelineCache ? angle::InitCRC32() : 0;
1605 
1606     // Allocate enough memory.
1607     angle::MemoryBuffer compressedData;
1608     ANGLE_VK_CHECK(context, compressedData.resize(chunkSize * numChunks),
1609                    VK_ERROR_INITIALIZATION_FAILED);
1610 
1611     // To combine the parts of the pipelineCache data.
1612     for (size_t chunkIndex = 0; chunkIndex < numChunks; ++chunkIndex)
1613     {
1614         // Avoid processing 0 chunk again.
1615         if (chunkIndex > 0)
1616         {
1617             // Get the unique key by chunkIndex.
1618             ComputePipelineCacheVkChunkKey(physicalDeviceProperties, slotIndex, chunkIndex,
1619                                            &chunkCacheHash);
1620 
1621             if (!globalOps->getBlob(chunkCacheHash, &keyData) ||
1622                 keyData.size() < sizeof(CacheDataHeader))
1623             {
1624                 // Can't find every part of the cache data.
1625                 WARN() << "Failed to get pipeline cache chunk " << chunkIndex << " of "
1626                        << numChunks;
1627                 return angle::Result::Continue;
1628             }
1629 
1630             // Validate the header values and ensure there is enough space to store.
1631             uint32_t checkCacheVersion;
1632             uint32_t checkCompressedDataCRC;
1633             uint32_t checkUncompressedCacheDataSize;
1634             size_t checkNumChunks;
1635             size_t checkChunkIndex;
1636 
1637             memcpy(&headerData, keyData.data(), sizeof(CacheDataHeader));
1638             UnpackHeaderDataForPipelineCache(
1639                 &headerData, &checkCacheVersion, &checkCompressedDataCRC,
1640                 &checkUncompressedCacheDataSize, &checkNumChunks, &checkChunkIndex, &chunkCRC);
1641 
1642             chunkSize = keyData.size() - sizeof(CacheDataHeader);
1643             bool isHeaderDataCorrupted =
1644                 (checkCacheVersion != cacheVersion) || (checkNumChunks != numChunks) ||
1645                 (checkUncompressedCacheDataSize != uncompressedCacheDataSize) ||
1646                 (checkCompressedDataCRC != compressedDataCRC) || (checkChunkIndex != chunkIndex) ||
1647                 (compressedData.size() < compressedSize + chunkSize);
1648             if (isHeaderDataCorrupted)
1649             {
1650                 WARN() << "Pipeline cache chunk header corrupted or old chunk: "
1651                        << "checkCacheVersion = " << checkCacheVersion
1652                        << ", cacheVersion = " << cacheVersion
1653                        << ", checkNumChunks = " << checkNumChunks << ", numChunks = " << numChunks
1654                        << ", checkUncompressedCacheDataSize = " << checkUncompressedCacheDataSize
1655                        << ", uncompressedCacheDataSize = " << uncompressedCacheDataSize
1656                        << ", checkCompressedDataCRC = " << checkCompressedDataCRC
1657                        << ", compressedDataCRC = " << compressedDataCRC
1658                        << ", checkChunkIndex = " << checkChunkIndex
1659                        << ", chunkIndex = " << chunkIndex
1660                        << ", compressedData.size() = " << compressedData.size()
1661                        << ", (compressedSize + chunkSize) = " << (compressedSize + chunkSize);
1662                 return angle::Result::Continue;
1663             }
1664         }
1665 
1666         // CRC of the chunk should match the values in the header.
1667         if (kEnableCRCForPipelineCache)
1668         {
1669             computedChunkCRC = angle::UpdateCRC32(
1670                 computedChunkCRC, keyData.data() + sizeof(CacheDataHeader), chunkSize);
1671             if (computedChunkCRC != chunkCRC)
1672             {
1673                 if (chunkCRC == 0)
1674                 {
1675                     // This could be due to the cache being populated before
1676                     // kEnableCRCForPipelineCache was enabled.
1677                     WARN() << "Expected chunk CRC = " << chunkCRC
1678                            << ", Actual chunk CRC = " << computedChunkCRC;
1679                     return angle::Result::Continue;
1680                 }
1681 
1682                 // If the expected CRC is non-zero and does not match the actual CRC from the data,
1683                 // there has been an unexpected data corruption.
1684                 ERR() << "Expected chunk CRC = " << chunkCRC
1685                       << ", Actual chunk CRC = " << computedChunkCRC;
1686 
1687                 ERR() << "Data extracted from the cache headers: " << std::hex
1688                       << ", compressedDataCRC = 0x" << compressedDataCRC << "numChunks = 0x"
1689                       << numChunks << ", uncompressedCacheDataSize = 0x"
1690                       << uncompressedCacheDataSize;
1691 
1692                 FATAL() << "CRC check failed; possible pipeline cache data corruption.";
1693                 return angle::Result::Stop;
1694             }
1695         }
1696 
1697         memcpy(compressedData.data() + compressedSize, keyData.data() + sizeof(CacheDataHeader),
1698                chunkSize);
1699         compressedSize += chunkSize;
1700     }
1701 
1702     // CRC for compressed data and size for decompressed data should match the values in the header.
1703     if (kEnableCRCForPipelineCache)
1704     {
1705         // Last chunk have CRC of the entire data.
1706         uint32_t computedCompressedDataCRC = computedChunkCRC;
1707         // Per chunk CRC check must handle any data corruption.  Assert is possible only if header
1708         // was incorrectly written in the first place (bug in the code), or all chunks headers were
1709         // corrupted in the exact same way, which is almost impossible.
1710         ASSERT(computedCompressedDataCRC == compressedDataCRC);
1711     }
1712 
1713     ANGLE_VK_CHECK(context,
1714                    angle::DecompressBlob(compressedData.data(), compressedSize,
1715                                          uncompressedCacheDataSize, uncompressedData),
1716                    VK_ERROR_INITIALIZATION_FAILED);
1717 
1718     if (uncompressedData->size() != uncompressedCacheDataSize)
1719     {
1720         WARN() << "Expected uncompressed size = " << uncompressedCacheDataSize
1721                << ", Actual uncompressed size = " << uncompressedData->size();
1722         return angle::Result::Continue;
1723     }
1724 
1725     *success = true;
1726     return angle::Result::Continue;
1727 }
1728 
1729 // Environment variable (and associated Android property) to enable Vulkan debug-utils markers
1730 constexpr char kEnableDebugMarkersVarName[]      = "ANGLE_ENABLE_DEBUG_MARKERS";
1731 constexpr char kEnableDebugMarkersPropertyName[] = "debug.angle.markers";
1732 
GetShadingRateFromVkExtent(const VkExtent2D & extent)1733 ANGLE_INLINE gl::ShadingRate GetShadingRateFromVkExtent(const VkExtent2D &extent)
1734 {
1735     if (extent.width == 1)
1736     {
1737         if (extent.height == 1)
1738         {
1739             return gl::ShadingRate::_1x1;
1740         }
1741         else if (extent.height == 2)
1742         {
1743             return gl::ShadingRate::_1x2;
1744         }
1745     }
1746     else if (extent.width == 2)
1747     {
1748         if (extent.height == 1)
1749         {
1750             return gl::ShadingRate::_2x1;
1751         }
1752         else if (extent.height == 2)
1753         {
1754             return gl::ShadingRate::_2x2;
1755         }
1756     }
1757     else if (extent.width == 4)
1758     {
1759         if (extent.height == 2)
1760         {
1761             return gl::ShadingRate::_4x2;
1762         }
1763         else if (extent.height == 4)
1764         {
1765             return gl::ShadingRate::_4x4;
1766         }
1767     }
1768 
1769     return gl::ShadingRate::Undefined;
1770 }
1771 
DumpPipelineCacheGraph(Renderer * renderer,const std::ostringstream & graph)1772 void DumpPipelineCacheGraph(Renderer *renderer, const std::ostringstream &graph)
1773 {
1774     std::string dumpPath = renderer->getPipelineCacheGraphDumpPath();
1775     if (dumpPath.size() == 0)
1776     {
1777         WARN() << "No path supplied for pipeline cache graph dump!";
1778         return;
1779     }
1780 
1781     static std::atomic<uint32_t> sContextIndex(0);
1782     std::string filename = dumpPath;
1783     filename += angle::GetExecutableName();
1784     filename += std::to_string(sContextIndex.fetch_add(1));
1785     filename += ".dump";
1786 
1787     INFO() << "Dumping pipeline cache transition graph to: \"" << filename << "\"";
1788 
1789     std::ofstream out = std::ofstream(filename, std::ofstream::binary);
1790     if (!out.is_open())
1791     {
1792         ERR() << "Failed to open \"" << filename << "\"";
1793     }
1794 
1795     out << "digraph {\n" << " node [shape=box";
1796     if (renderer->getFeatures().supportsPipelineCreationFeedback.enabled)
1797     {
1798         out << ",color=green";
1799     }
1800     out << "]\n";
1801     out << graph.str();
1802     out << "}\n";
1803     out.close();
1804 }
1805 
CanSupportMSRTSSForRGBA8(Renderer * renderer)1806 bool CanSupportMSRTSSForRGBA8(Renderer *renderer)
1807 {
1808     // The support is checked for a basic 2D texture.
1809     constexpr VkImageUsageFlags kImageUsageFlags =
1810         VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
1811         VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
1812     VkImageCreateFlags imageCreateFlags =
1813         GetMinimalImageCreateFlags(renderer, gl::TextureType::_2D, kImageUsageFlags) |
1814         VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT;
1815 
1816     bool supportsMSRTTUsageRGBA8 = vk::ImageHelper::FormatSupportsUsage(
1817         renderer, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
1818         kImageUsageFlags, imageCreateFlags, nullptr, nullptr,
1819         vk::ImageHelper::FormatSupportCheck::RequireMultisampling);
1820     bool supportsMSRTTUsageRGBA8SRGB = vk::ImageHelper::FormatSupportsUsage(
1821         renderer, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
1822         kImageUsageFlags, imageCreateFlags, nullptr, nullptr,
1823         vk::ImageHelper::FormatSupportCheck::RequireMultisampling);
1824 
1825     return supportsMSRTTUsageRGBA8 && supportsMSRTTUsageRGBA8SRGB;
1826 }
1827 
RetrieveDeviceLostInfoFromDevice(VkDevice device,VkPhysicalDeviceFaultFeaturesEXT faultFeatures)1828 VkResult RetrieveDeviceLostInfoFromDevice(VkDevice device,
1829                                           VkPhysicalDeviceFaultFeaturesEXT faultFeatures)
1830 {
1831     // For VkDeviceFaultAddressTypeEXT in VK_EXT_device_fault
1832     constexpr const char *kDeviceFaultAddressTypeMessage[] = {
1833         "None",
1834         "InvalidRead",
1835         "InvalidWrite",
1836         "InvalidExecute",
1837         "InstructionPointerUnknown",
1838         "InstructionPointerInvalid",
1839         "InstructionPointerFault",
1840     };
1841 
1842     // At first, the data regarding the number of faults is collected, so the proper allocations can
1843     // be made to store the incoming data.
1844     VkDeviceFaultCountsEXT faultCounts = {};
1845     faultCounts.sType                  = VK_STRUCTURE_TYPE_DEVICE_FAULT_COUNTS_EXT;
1846 
1847     VkResult result = vkGetDeviceFaultInfoEXT(device, &faultCounts, nullptr);
1848     if (result != VK_SUCCESS)
1849     {
1850         return result;
1851     }
1852 
1853     VkDeviceFaultInfoEXT faultInfos = {};
1854     faultInfos.sType                = VK_STRUCTURE_TYPE_DEVICE_FAULT_INFO_EXT;
1855 
1856     std::vector<VkDeviceFaultAddressInfoEXT> addressInfos(faultCounts.addressInfoCount);
1857     faultInfos.pAddressInfos = addressInfos.data();
1858 
1859     std::vector<VkDeviceFaultVendorInfoEXT> vendorInfos(faultCounts.vendorInfoCount);
1860     faultInfos.pVendorInfos = vendorInfos.data();
1861 
1862     // The vendor binary data will be logged in chunks of 4 bytes.
1863     uint32_t vendorBinaryDataChunkCount =
1864         (static_cast<uint32_t>(faultCounts.vendorBinarySize) + 3) / 4;
1865     std::vector<uint32_t> vendorBinaryDataChunks(vendorBinaryDataChunkCount, 0);
1866     faultInfos.pVendorBinaryData = vendorBinaryDataChunks.data();
1867 
1868     result = vkGetDeviceFaultInfoEXT(device, &faultCounts, &faultInfos);
1869     if (result != VK_SUCCESS)
1870     {
1871         return result;
1872     }
1873 
1874     // Collect the fault information from the device.
1875     std::stringstream faultString;
1876     faultString << "Fault description: <" << faultInfos.description << ">" << std::endl;
1877 
1878     for (auto &addressFault : addressInfos)
1879     {
1880         // Based on the spec, The address precision is a power of two, and shows the lower and upper
1881         // address ranges where the error could be:
1882         // - lowerAddress = (reportedAddress & ~(addressPrecision - 1))
1883         // - upperAddress = (reportedAddress |  (addressPrecision - 1))
1884         // For example, if the reported address is 0x12345 and the precision is 16, it shows that
1885         // the address could be between 0x12340 and 0x1234F.
1886         faultString << "--> Address fault reported at 0x" << std::hex
1887                     << addressFault.reportedAddress << " | Precision range: 0x"
1888                     << addressFault.addressPrecision << " (" << std::dec
1889                     << std::log2(addressFault.addressPrecision) << " bits) | Operation: "
1890                     << kDeviceFaultAddressTypeMessage[addressFault.addressType] << std::endl;
1891     }
1892 
1893     for (auto &vendorFault : vendorInfos)
1894     {
1895         faultString << "--> Vendor-specific fault reported (Code " << std::dec
1896                     << vendorFault.vendorFaultCode << "): <" << vendorFault.description
1897                     << "> | Fault Data: 0x" << std::hex << vendorFault.vendorFaultData << std::endl;
1898     }
1899 
1900     if (faultFeatures.deviceFaultVendorBinary)
1901     {
1902         // The binary data must start with the header in the format of the following type:
1903         // - VkDeviceFaultVendorBinaryHeaderVersionOneEXT (56 bytes)
1904         faultString << "--> Vendor-specific binary crash dump (" << faultCounts.vendorBinarySize
1905                     << " bytes, in hex):" << std::endl;
1906 
1907         constexpr uint32_t kVendorBinaryDataChunksPerLine = 8;
1908         for (uint32_t i = 0; i < vendorBinaryDataChunkCount; i++)
1909         {
1910             faultString << "0x" << std::hex << std::setw(8) << std::setfill('0')
1911                         << vendorBinaryDataChunks[i]
1912                         << ((i + 1) % kVendorBinaryDataChunksPerLine != 0 ? " " : "\n");
1913         }
1914         faultString << std::endl;
1915     }
1916     else
1917     {
1918         faultString << "--> Vendor-specific binary crash dump not available." << std::endl;
1919     }
1920 
1921     // Output the log stream.
1922     WARN() << faultString.str();
1923     return VK_SUCCESS;
1924 }
1925 }  // namespace
1926 
1927 // OneOffCommandPool implementation.
OneOffCommandPool()1928 OneOffCommandPool::OneOffCommandPool() : mProtectionType(vk::ProtectionType::InvalidEnum) {}
1929 
init(vk::ProtectionType protectionType)1930 void OneOffCommandPool::init(vk::ProtectionType protectionType)
1931 {
1932     ASSERT(!mCommandPool.valid());
1933     mProtectionType = protectionType;
1934 }
1935 
destroy(VkDevice device)1936 void OneOffCommandPool::destroy(VkDevice device)
1937 {
1938     std::unique_lock<angle::SimpleMutex> lock(mMutex);
1939     for (PendingOneOffCommands &pending : mPendingCommands)
1940     {
1941         pending.commandBuffer.releaseHandle();
1942     }
1943     mCommandPool.destroy(device);
1944     mProtectionType = vk::ProtectionType::InvalidEnum;
1945 }
1946 
getCommandBuffer(vk::ErrorContext * context,vk::ScopedPrimaryCommandBuffer * commandBufferOut)1947 angle::Result OneOffCommandPool::getCommandBuffer(vk::ErrorContext *context,
1948                                                   vk::ScopedPrimaryCommandBuffer *commandBufferOut)
1949 {
1950     std::unique_lock<angle::SimpleMutex> lock(mMutex);
1951 
1952     if (!mPendingCommands.empty() &&
1953         context->getRenderer()->hasResourceUseFinished(mPendingCommands.front().use))
1954     {
1955         commandBufferOut->assign(std::move(lock),
1956                                  std::move(mPendingCommands.front().commandBuffer));
1957         mPendingCommands.pop_front();
1958         // No need to explicitly call reset() on |commandBufferOut|, since the begin() call below
1959         // will do it implicitly.
1960     }
1961     else
1962     {
1963         if (!mCommandPool.valid())
1964         {
1965             VkCommandPoolCreateInfo createInfo = {};
1966             createInfo.sType                   = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
1967             createInfo.flags                   = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT |
1968                                VK_COMMAND_POOL_CREATE_TRANSIENT_BIT;
1969             ASSERT(mProtectionType == vk::ProtectionType::Unprotected ||
1970                    mProtectionType == vk::ProtectionType::Protected);
1971             if (mProtectionType == vk::ProtectionType::Protected)
1972             {
1973                 createInfo.flags |= VK_COMMAND_POOL_CREATE_PROTECTED_BIT;
1974             }
1975             createInfo.queueFamilyIndex = context->getRenderer()->getQueueFamilyIndex();
1976             ANGLE_VK_TRY(context, mCommandPool.init(context->getDevice(), createInfo));
1977         }
1978 
1979         VkCommandBufferAllocateInfo allocInfo = {};
1980         allocInfo.sType                       = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
1981         allocInfo.level                       = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
1982         allocInfo.commandBufferCount          = 1;
1983         allocInfo.commandPool                 = mCommandPool.getHandle();
1984 
1985         PrimaryCommandBuffer newCommandBuffer;
1986         ANGLE_VK_TRY(context, newCommandBuffer.init(context->getDevice(), allocInfo));
1987         commandBufferOut->assign(std::move(lock), std::move(newCommandBuffer));
1988     }
1989 
1990     VkCommandBufferBeginInfo beginInfo = {};
1991     beginInfo.sType                    = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
1992     beginInfo.flags                    = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
1993     beginInfo.pInheritanceInfo         = nullptr;
1994     ANGLE_VK_TRY(context, commandBufferOut->get().begin(beginInfo));
1995 
1996     return angle::Result::Continue;
1997 }
1998 
releaseCommandBuffer(const QueueSerial & submitQueueSerial,vk::PrimaryCommandBuffer && primary)1999 void OneOffCommandPool::releaseCommandBuffer(const QueueSerial &submitQueueSerial,
2000                                              vk::PrimaryCommandBuffer &&primary)
2001 {
2002     std::unique_lock<angle::SimpleMutex> lock(mMutex);
2003     mPendingCommands.push_back({vk::ResourceUse(submitQueueSerial), std::move(primary)});
2004 }
2005 
2006 // Renderer implementation.
Renderer()2007 Renderer::Renderer()
2008     : mGlobalOps(nullptr),
2009       mLibVulkanLibrary(nullptr),
2010       mCapsInitialized(false),
2011       mInstanceVersion(0),
2012       mDeviceVersion(0),
2013       mInstance(VK_NULL_HANDLE),
2014       mEnableValidationLayers(false),
2015       mEnableDebugUtils(false),
2016       mAngleDebuggerMode(false),
2017       mEnabledICD(angle::vk::ICD::Default),
2018       mDebugUtilsMessenger(VK_NULL_HANDLE),
2019       mPhysicalDevice(VK_NULL_HANDLE),
2020       mPhysicalDeviceProperties(mPhysicalDeviceProperties2.properties),
2021       mCurrentQueueFamilyIndex(std::numeric_limits<uint32_t>::max()),
2022       mMaxVertexAttribDivisor(1),
2023       mMaxVertexAttribStride(0),
2024       mMaxColorInputAttachmentCount(0),
2025       mDefaultUniformBufferSize(kPreferredDefaultUniformBufferSize),
2026       mDevice(VK_NULL_HANDLE),
2027       mDeviceLost(false),
2028       mStagingBufferAlignment(1),
2029       mHostVisibleVertexConversionBufferMemoryTypeIndex(kInvalidMemoryTypeIndex),
2030       mDeviceLocalVertexConversionBufferMemoryTypeIndex(kInvalidMemoryTypeIndex),
2031       mVertexConversionBufferAlignment(1),
2032       mCurrentPipelineCacheBlobCacheSlotIndex(0),
2033       mPipelineCacheChunkCount(0),
2034       mPipelineCacheVkUpdateTimeout(kPipelineCacheVkUpdatePeriod),
2035       mPipelineCacheSizeAtLastSync(0),
2036       mPipelineCacheInitialized(false),
2037       mValidationMessageCount(0),
2038       mIsColorFramebufferFetchCoherent(false),
2039       mIsColorFramebufferFetchUsed(false),
2040       mCleanUpThread(this, &mCommandQueue),
2041       mSupportedBufferWritePipelineStageMask(0),
2042       mSupportedVulkanShaderStageMask(0),
2043       mMemoryAllocationTracker(MemoryAllocationTracker(this)),
2044       mMaxBufferMemorySizeLimit(0)
2045 {
2046     VkFormatProperties invalid = {0, 0, kInvalidFormatFeatureFlags};
2047     mFormatProperties.fill(invalid);
2048     mStagingBufferMemoryTypeIndex.fill(kInvalidMemoryTypeIndex);
2049 
2050     // We currently don't have any big-endian devices in the list of supported platforms.  There are
2051     // a number of places in the Vulkan backend that make this assumption.  This assertion is made
2052     // early to fail immediately on big-endian platforms.
2053     ASSERT(IsLittleEndian());
2054 
2055     mDumpPipelineCacheGraph =
2056         (angle::GetEnvironmentVarOrAndroidProperty("ANGLE_DUMP_PIPELINE_CACHE_GRAPH",
2057                                                    "angle.dump_pipeline_cache_graph") == "1");
2058 
2059     mPipelineCacheGraphDumpPath = angle::GetEnvironmentVarOrAndroidProperty(
2060         "ANGLE_PIPELINE_CACHE_GRAPH_DUMP_PATH", "angle.pipeline_cache_graph_dump_path");
2061     if (mPipelineCacheGraphDumpPath.size() == 0)
2062     {
2063         mPipelineCacheGraphDumpPath = kDefaultPipelineCacheGraphDumpPath;
2064     }
2065 }
2066 
~Renderer()2067 Renderer::~Renderer() {}
2068 
hasSharedGarbage()2069 bool Renderer::hasSharedGarbage()
2070 {
2071     return !mSharedGarbageList.empty() || !mSuballocationGarbageList.empty();
2072 }
2073 
onDestroy(vk::ErrorContext * context)2074 void Renderer::onDestroy(vk::ErrorContext *context)
2075 {
2076     if (isDeviceLost())
2077     {
2078         handleDeviceLost();
2079     }
2080 
2081     if (mPlaceHolderDescriptorSetLayout)
2082     {
2083         ASSERT(mPlaceHolderDescriptorSetLayout.unique());
2084         mPlaceHolderDescriptorSetLayout.reset();
2085     }
2086 
2087     mCleanUpThread.destroy(context);
2088     mCommandQueue.destroy(context);
2089 
2090     // mCommandQueue.destroy should already set "last completed" serials to infinite.
2091     cleanupGarbage(nullptr);
2092     ASSERT(!hasSharedGarbage());
2093     ASSERT(mOrphanedBufferBlockList.empty());
2094 
2095     mRefCountedEventRecycler.destroy(mDevice);
2096 
2097     for (OneOffCommandPool &oneOffCommandPool : mOneOffCommandPoolMap)
2098     {
2099         oneOffCommandPool.destroy(mDevice);
2100     }
2101 
2102     mPipelineCacheInitialized = false;
2103     mPipelineCache.destroy(mDevice);
2104 
2105     mSamplerCache.destroy(this);
2106     mYuvConversionCache.destroy(this);
2107     mVkFormatDescriptorCountMap.clear();
2108 
2109     mOutsideRenderPassCommandBufferRecycler.onDestroy();
2110     mRenderPassCommandBufferRecycler.onDestroy();
2111 
2112     mImageMemorySuballocator.destroy(this);
2113     mAllocator.destroy();
2114 
2115     // When the renderer is being destroyed, it is possible to check if all the allocated memory
2116     // throughout the execution has been freed.
2117     mMemoryAllocationTracker.onDestroy();
2118 
2119     if (mDevice)
2120     {
2121         vkDestroyDevice(mDevice, nullptr);
2122         mDevice = VK_NULL_HANDLE;
2123     }
2124 
2125     if (mDebugUtilsMessenger)
2126     {
2127         vkDestroyDebugUtilsMessengerEXT(mInstance, mDebugUtilsMessenger, nullptr);
2128     }
2129 
2130     logCacheStats();
2131 
2132     if (mInstance)
2133     {
2134         vkDestroyInstance(mInstance, nullptr);
2135         mInstance = VK_NULL_HANDLE;
2136     }
2137 
2138     if (mCompressEvent)
2139     {
2140         mCompressEvent->wait();
2141         mCompressEvent.reset();
2142     }
2143 
2144     mMemoryProperties.destroy();
2145     mPhysicalDevice = VK_NULL_HANDLE;
2146 
2147     mEnabledInstanceExtensions.clear();
2148     mEnabledDeviceExtensions.clear();
2149 
2150     ASSERT(!hasSharedGarbage());
2151 
2152     if (mLibVulkanLibrary)
2153     {
2154         angle::CloseSystemLibrary(mLibVulkanLibrary);
2155         mLibVulkanLibrary = nullptr;
2156     }
2157 
2158     if (!mPipelineCacheGraph.str().empty())
2159     {
2160         DumpPipelineCacheGraph(this, mPipelineCacheGraph);
2161     }
2162 }
2163 
retrieveDeviceLostDetails() const2164 VkResult Renderer::retrieveDeviceLostDetails() const
2165 {
2166     if (!getFeatures().supportsDeviceFault.enabled)
2167     {
2168         return VK_SUCCESS;
2169     }
2170     return RetrieveDeviceLostInfoFromDevice(mDevice, mFaultFeatures);
2171 }
2172 
notifyDeviceLost()2173 void Renderer::notifyDeviceLost()
2174 {
2175     mDeviceLost = true;
2176     mGlobalOps->notifyDeviceLost();
2177 }
2178 
isDeviceLost() const2179 bool Renderer::isDeviceLost() const
2180 {
2181     return mDeviceLost;
2182 }
2183 
enableInstanceExtensions(vk::ErrorContext * context,const VulkanLayerVector & enabledInstanceLayerNames,const char * wsiExtension,UseVulkanSwapchain useVulkanSwapchain,bool canLoadDebugUtils)2184 angle::Result Renderer::enableInstanceExtensions(vk::ErrorContext *context,
2185                                                  const VulkanLayerVector &enabledInstanceLayerNames,
2186                                                  const char *wsiExtension,
2187                                                  UseVulkanSwapchain useVulkanSwapchain,
2188                                                  bool canLoadDebugUtils)
2189 {
2190     // Enumerate instance extensions that are provided by the vulkan implementation and implicit
2191     // layers.
2192     uint32_t instanceExtensionCount = 0;
2193     {
2194         ANGLE_SCOPED_DISABLE_LSAN();
2195         ANGLE_SCOPED_DISABLE_MSAN();
2196         ANGLE_VK_TRY(context, vkEnumerateInstanceExtensionProperties(
2197                                   nullptr, &instanceExtensionCount, nullptr));
2198     }
2199 
2200     std::vector<VkExtensionProperties> instanceExtensionProps(instanceExtensionCount);
2201     if (instanceExtensionCount > 0)
2202     {
2203         ANGLE_SCOPED_DISABLE_LSAN();
2204         ANGLE_SCOPED_DISABLE_MSAN();
2205         ANGLE_VK_TRY(context, vkEnumerateInstanceExtensionProperties(
2206                                   nullptr, &instanceExtensionCount, instanceExtensionProps.data()));
2207         // In case fewer items were returned than requested, resize instanceExtensionProps to the
2208         // number of extensions returned (i.e. instanceExtensionCount).
2209         instanceExtensionProps.resize(instanceExtensionCount);
2210     }
2211 
2212     // Enumerate instance extensions that are provided by explicit layers.
2213     for (const char *layerName : enabledInstanceLayerNames)
2214     {
2215         uint32_t previousExtensionCount      = static_cast<uint32_t>(instanceExtensionProps.size());
2216         uint32_t instanceLayerExtensionCount = 0;
2217         {
2218             ANGLE_SCOPED_DISABLE_LSAN();
2219             ANGLE_SCOPED_DISABLE_MSAN();
2220             ANGLE_VK_TRY(context, vkEnumerateInstanceExtensionProperties(
2221                                       layerName, &instanceLayerExtensionCount, nullptr));
2222         }
2223         instanceExtensionProps.resize(previousExtensionCount + instanceLayerExtensionCount);
2224         {
2225             ANGLE_SCOPED_DISABLE_LSAN();
2226             ANGLE_SCOPED_DISABLE_MSAN();
2227             ANGLE_VK_TRY(context, vkEnumerateInstanceExtensionProperties(
2228                                       layerName, &instanceLayerExtensionCount,
2229                                       instanceExtensionProps.data() + previousExtensionCount));
2230         }
2231         // In case fewer items were returned than requested, resize instanceExtensionProps to the
2232         // number of extensions returned (i.e. instanceLayerExtensionCount).
2233         instanceExtensionProps.resize(previousExtensionCount + instanceLayerExtensionCount);
2234     }
2235 
2236     // Get the list of instance extensions that are available.
2237     vk::ExtensionNameList instanceExtensionNames;
2238     if (!instanceExtensionProps.empty())
2239     {
2240         for (const VkExtensionProperties &i : instanceExtensionProps)
2241         {
2242             instanceExtensionNames.push_back(i.extensionName);
2243         }
2244         std::sort(instanceExtensionNames.begin(), instanceExtensionNames.end(), StrLess);
2245     }
2246 
2247     // Set ANGLE features that depend on instance extensions
2248     ANGLE_FEATURE_CONDITION(
2249         &mFeatures, supportsSurfaceCapabilities2Extension,
2250         ExtensionFound(VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME, instanceExtensionNames) &&
2251             useVulkanSwapchain == UseVulkanSwapchain::Yes);
2252 
2253     ANGLE_FEATURE_CONDITION(&mFeatures, supportsSurfaceProtectedCapabilitiesExtension,
2254                             ExtensionFound(VK_KHR_SURFACE_PROTECTED_CAPABILITIES_EXTENSION_NAME,
2255                                            instanceExtensionNames) &&
2256                                 useVulkanSwapchain == UseVulkanSwapchain::Yes);
2257 
2258     // TODO: Validation layer has a bug when vkGetPhysicalDeviceSurfaceFormats2KHR is called
2259     // on Mock ICD with surface handle set as VK_NULL_HANDLE. http://anglebug.com/42266098
2260     // b/267953710: VK_GOOGLE_surfaceless_query isn't working on some Samsung Xclipse builds
2261     ANGLE_FEATURE_CONDITION(
2262         &mFeatures, supportsSurfacelessQueryExtension,
2263         ExtensionFound(VK_GOOGLE_SURFACELESS_QUERY_EXTENSION_NAME, instanceExtensionNames) &&
2264             useVulkanSwapchain == UseVulkanSwapchain::Yes && !isMockICDEnabled() && !IsXclipse());
2265 
2266     // VK_KHR_external_fence_capabilities and VK_KHR_extenral_semaphore_capabilities are promoted to
2267     // core in Vulkan 1.1
2268     ANGLE_FEATURE_CONDITION(&mFeatures, supportsExternalFenceCapabilities, true);
2269     ANGLE_FEATURE_CONDITION(&mFeatures, supportsExternalSemaphoreCapabilities, true);
2270 
2271     // On macOS, there is no native Vulkan driver, so we need to enable the
2272     // portability enumeration extension to allow use of MoltenVK.
2273     ANGLE_FEATURE_CONDITION(
2274         &mFeatures, supportsPortabilityEnumeration,
2275         ExtensionFound(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME, instanceExtensionNames));
2276 
2277     ANGLE_FEATURE_CONDITION(&mFeatures, enablePortabilityEnumeration,
2278                             mFeatures.supportsPortabilityEnumeration.enabled && IsApple());
2279 
2280     // Enable extensions that could be used
2281     if (useVulkanSwapchain == UseVulkanSwapchain::Yes)
2282     {
2283         mEnabledInstanceExtensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
2284         if (ExtensionFound(VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME, instanceExtensionNames))
2285         {
2286             mEnabledInstanceExtensions.push_back(VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME);
2287         }
2288 
2289         ANGLE_FEATURE_CONDITION(
2290             &mFeatures, supportsSurfaceMaintenance1,
2291             !isMockICDEnabled() && ExtensionFound(VK_EXT_SURFACE_MAINTENANCE_1_EXTENSION_NAME,
2292                                                   instanceExtensionNames));
2293 
2294         if (mFeatures.supportsSurfaceMaintenance1.enabled)
2295         {
2296             mEnabledInstanceExtensions.push_back(VK_EXT_SURFACE_MAINTENANCE_1_EXTENSION_NAME);
2297         }
2298     }
2299 
2300     if (wsiExtension)
2301     {
2302         mEnabledInstanceExtensions.push_back(wsiExtension);
2303     }
2304 
2305     mEnableDebugUtils = canLoadDebugUtils && mEnableValidationLayers &&
2306                         ExtensionFound(VK_EXT_DEBUG_UTILS_EXTENSION_NAME, instanceExtensionNames);
2307 
2308     if (mEnableDebugUtils)
2309     {
2310         mEnabledInstanceExtensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
2311     }
2312 
2313     if (mFeatures.supportsSurfaceCapabilities2Extension.enabled)
2314     {
2315         mEnabledInstanceExtensions.push_back(VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME);
2316     }
2317 
2318     if (mFeatures.supportsSurfaceProtectedCapabilitiesExtension.enabled)
2319     {
2320         mEnabledInstanceExtensions.push_back(VK_KHR_SURFACE_PROTECTED_CAPABILITIES_EXTENSION_NAME);
2321     }
2322 
2323     if (mFeatures.supportsSurfacelessQueryExtension.enabled)
2324     {
2325         mEnabledInstanceExtensions.push_back(VK_GOOGLE_SURFACELESS_QUERY_EXTENSION_NAME);
2326     }
2327 
2328     if (mFeatures.enablePortabilityEnumeration.enabled)
2329     {
2330         mEnabledInstanceExtensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
2331     }
2332 
2333     // Verify the required extensions are in the extension names set. Fail if not.
2334     std::sort(mEnabledInstanceExtensions.begin(), mEnabledInstanceExtensions.end(), StrLess);
2335     ANGLE_VK_TRY(context,
2336                  VerifyExtensionsPresent(instanceExtensionNames, mEnabledInstanceExtensions));
2337 
2338     return angle::Result::Continue;
2339 }
2340 
initialize(vk::ErrorContext * context,vk::GlobalOps * globalOps,angle::vk::ICD desiredICD,uint32_t preferredVendorId,uint32_t preferredDeviceId,const uint8_t * preferredDeviceUuid,const uint8_t * preferredDriverUuid,VkDriverId preferredDriverId,UseDebugLayers useDebugLayers,const char * wsiExtension,const char * wsiLayer,angle::NativeWindowSystem nativeWindowSystem,const angle::FeatureOverrides & featureOverrides)2341 angle::Result Renderer::initialize(vk::ErrorContext *context,
2342                                    vk::GlobalOps *globalOps,
2343                                    angle::vk::ICD desiredICD,
2344                                    uint32_t preferredVendorId,
2345                                    uint32_t preferredDeviceId,
2346                                    const uint8_t *preferredDeviceUuid,
2347                                    const uint8_t *preferredDriverUuid,
2348                                    VkDriverId preferredDriverId,
2349                                    UseDebugLayers useDebugLayers,
2350                                    const char *wsiExtension,
2351                                    const char *wsiLayer,
2352                                    angle::NativeWindowSystem nativeWindowSystem,
2353                                    const angle::FeatureOverrides &featureOverrides)
2354 {
2355     bool canLoadDebugUtils = true;
2356 #if defined(ANGLE_SHARED_LIBVULKAN)
2357     {
2358         ANGLE_SCOPED_DISABLE_MSAN();
2359         mLibVulkanLibrary = angle::vk::OpenLibVulkan();
2360         ANGLE_VK_CHECK(context, mLibVulkanLibrary, VK_ERROR_INITIALIZATION_FAILED);
2361 
2362         PFN_vkGetInstanceProcAddr vulkanLoaderGetInstanceProcAddr =
2363             reinterpret_cast<PFN_vkGetInstanceProcAddr>(
2364                 angle::GetLibrarySymbol(mLibVulkanLibrary, "vkGetInstanceProcAddr"));
2365 
2366         // Set all vk* function ptrs
2367         volkInitializeCustom(vulkanLoaderGetInstanceProcAddr);
2368 
2369         uint32_t ver = volkGetInstanceVersion();
2370         if (!IsAndroid() && ver < VK_MAKE_VERSION(1, 1, 91))
2371         {
2372             // http://crbug.com/1205999 - non-Android Vulkan Loader versions before 1.1.91 have a
2373             // bug which prevents loading VK_EXT_debug_utils function pointers.
2374             canLoadDebugUtils = false;
2375         }
2376     }
2377 #endif  // defined(ANGLE_SHARED_LIBVULKAN)
2378 
2379     mGlobalOps = globalOps;
2380 
2381     // While the validation layer is loaded by default whenever present, apidump layer
2382     // activation is controlled by an environment variable/android property allowing
2383     // the two layers to be controlled independently.
2384     bool enableApiDumpLayer =
2385         kEnableVulkanAPIDumpLayer && angle::GetEnvironmentVarOrAndroidProperty(
2386                                          "ANGLE_ENABLE_VULKAN_API_DUMP_LAYER",
2387                                          "debug.angle.enable_vulkan_api_dump_layer") == "1";
2388 
2389     bool loadLayers = (useDebugLayers != UseDebugLayers::No) || enableApiDumpLayer;
2390     angle::vk::ScopedVkLoaderEnvironment scopedEnvironment(loadLayers, desiredICD);
2391     bool debugLayersLoaded  = scopedEnvironment.canEnableDebugLayers();
2392     mEnableValidationLayers = debugLayersLoaded;
2393     enableApiDumpLayer      = enableApiDumpLayer && debugLayersLoaded;
2394     mEnabledICD             = scopedEnvironment.getEnabledICD();
2395 
2396     // Gather global layer properties.
2397     uint32_t instanceLayerCount = 0;
2398     {
2399         ANGLE_SCOPED_DISABLE_LSAN();
2400         ANGLE_SCOPED_DISABLE_MSAN();
2401         ANGLE_VK_TRY(context, vkEnumerateInstanceLayerProperties(&instanceLayerCount, nullptr));
2402     }
2403 
2404     std::vector<VkLayerProperties> instanceLayerProps(instanceLayerCount);
2405     if (instanceLayerCount > 0)
2406     {
2407         ANGLE_SCOPED_DISABLE_LSAN();
2408         ANGLE_SCOPED_DISABLE_MSAN();
2409         ANGLE_VK_TRY(context, vkEnumerateInstanceLayerProperties(&instanceLayerCount,
2410                                                                  instanceLayerProps.data()));
2411     }
2412 
2413     VulkanLayerVector enabledInstanceLayerNames;
2414 
2415     if (enableApiDumpLayer)
2416     {
2417         enabledInstanceLayerNames.push_back("VK_LAYER_LUNARG_api_dump");
2418     }
2419 
2420     if (mEnableValidationLayers)
2421     {
2422         const bool layersRequested = useDebugLayers == UseDebugLayers::Yes;
2423         mEnableValidationLayers = GetAvailableValidationLayers(instanceLayerProps, layersRequested,
2424                                                                &enabledInstanceLayerNames);
2425     }
2426 
2427     if (wsiLayer != nullptr)
2428     {
2429         enabledInstanceLayerNames.push_back(wsiLayer);
2430     }
2431 
2432     auto enumerateInstanceVersion = reinterpret_cast<PFN_vkEnumerateInstanceVersion>(
2433         vkGetInstanceProcAddr(nullptr, "vkEnumerateInstanceVersion"));
2434 
2435     uint32_t highestApiVersion = mInstanceVersion = VK_API_VERSION_1_0;
2436     if (enumerateInstanceVersion)
2437     {
2438         {
2439             ANGLE_SCOPED_DISABLE_LSAN();
2440             ANGLE_SCOPED_DISABLE_MSAN();
2441             ANGLE_VK_TRY(context, enumerateInstanceVersion(&mInstanceVersion));
2442         }
2443 
2444         if (IsVulkan11(mInstanceVersion))
2445         {
2446             // This is the highest version of core Vulkan functionality that ANGLE uses.  Per the
2447             // Vulkan spec, the application is allowed to specify a higher version than supported by
2448             // the instance.  ANGLE still respects the *device's* version.
2449             highestApiVersion = kPreferredVulkanAPIVersion;
2450         }
2451     }
2452 
2453     if (mInstanceVersion < angle::vk::kMinimumVulkanAPIVersion)
2454     {
2455         WARN() << "ANGLE Requires a minimum Vulkan instance version of 1.1";
2456         ANGLE_VK_TRY(context, VK_ERROR_INCOMPATIBLE_DRIVER);
2457     }
2458 
2459     const UseVulkanSwapchain useVulkanSwapchain = wsiExtension != nullptr || wsiLayer != nullptr
2460                                                       ? UseVulkanSwapchain::Yes
2461                                                       : UseVulkanSwapchain::No;
2462     ANGLE_TRY(enableInstanceExtensions(context, enabledInstanceLayerNames, wsiExtension,
2463                                        useVulkanSwapchain, canLoadDebugUtils));
2464 
2465     const std::string appName = angle::GetExecutableName();
2466 
2467     mApplicationInfo                    = {};
2468     mApplicationInfo.sType              = VK_STRUCTURE_TYPE_APPLICATION_INFO;
2469     mApplicationInfo.pApplicationName   = appName.c_str();
2470     mApplicationInfo.applicationVersion = 1;
2471     mApplicationInfo.pEngineName        = "ANGLE";
2472     mApplicationInfo.engineVersion      = 1;
2473     mApplicationInfo.apiVersion         = highestApiVersion;
2474 
2475     VkInstanceCreateInfo instanceInfo = {};
2476     instanceInfo.sType                = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
2477     instanceInfo.flags                = 0;
2478     instanceInfo.pApplicationInfo     = &mApplicationInfo;
2479 
2480     // Enable requested layers and extensions.
2481     instanceInfo.enabledExtensionCount = static_cast<uint32_t>(mEnabledInstanceExtensions.size());
2482     instanceInfo.ppEnabledExtensionNames =
2483         mEnabledInstanceExtensions.empty() ? nullptr : mEnabledInstanceExtensions.data();
2484 
2485     instanceInfo.enabledLayerCount   = static_cast<uint32_t>(enabledInstanceLayerNames.size());
2486     instanceInfo.ppEnabledLayerNames = enabledInstanceLayerNames.data();
2487 
2488     // On macOS, there is no native Vulkan driver, so we need to enable the
2489     // portability enumeration extension to allow use of MoltenVK.
2490     if (mFeatures.enablePortabilityEnumeration.enabled)
2491     {
2492         instanceInfo.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
2493     }
2494 
2495     // Fine grain control of validation layer features
2496     const char *name                     = "VK_LAYER_KHRONOS_validation";
2497     const VkBool32 setting_validate_core = VK_TRUE;
2498     // SyncVal is very slow (https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/7285)
2499     // for VkEvent which causes a few tests fail on the bots. Disable syncVal if VkEvent is enabled
2500     // for now.
2501     const VkBool32 setting_validate_sync = IsAndroid() ? VK_FALSE : VK_TRUE;
2502     const VkBool32 setting_thread_safety = VK_TRUE;
2503     // http://anglebug.com/42265520 - Shader validation caching is broken on Android
2504     const VkBool32 setting_check_shaders = IsAndroid() ? VK_FALSE : VK_TRUE;
2505     // http://b/316013423 Disable QueueSubmit Synchronization Validation. Lots of failures and some
2506     // test timeout due to https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/7285
2507     const VkBool32 setting_syncval_submit_time_validation   = VK_FALSE;
2508     const VkBool32 setting_syncval_message_extra_properties = VK_TRUE;
2509     const VkLayerSettingEXT layerSettings[]                 = {
2510         {name, "validate_core", VK_LAYER_SETTING_TYPE_BOOL32_EXT, 1, &setting_validate_core},
2511         {name, "validate_sync", VK_LAYER_SETTING_TYPE_BOOL32_EXT, 1, &setting_validate_sync},
2512         {name, "thread_safety", VK_LAYER_SETTING_TYPE_BOOL32_EXT, 1, &setting_thread_safety},
2513         {name, "check_shaders", VK_LAYER_SETTING_TYPE_BOOL32_EXT, 1, &setting_check_shaders},
2514         {name, "syncval_submit_time_validation", VK_LAYER_SETTING_TYPE_BOOL32_EXT, 1,
2515                          &setting_syncval_submit_time_validation},
2516         {name, "syncval_message_extra_properties", VK_LAYER_SETTING_TYPE_BOOL32_EXT, 1,
2517                          &setting_syncval_message_extra_properties},
2518     };
2519     VkLayerSettingsCreateInfoEXT layerSettingsCreateInfo = {
2520         VK_STRUCTURE_TYPE_LAYER_SETTINGS_CREATE_INFO_EXT, nullptr,
2521         static_cast<uint32_t>(std::size(layerSettings)), layerSettings};
2522     if (mEnableValidationLayers)
2523     {
2524         vk::AddToPNextChain(&instanceInfo, &layerSettingsCreateInfo);
2525     }
2526 
2527     {
2528         ANGLE_SCOPED_DISABLE_MSAN();
2529         ANGLE_VK_TRY(context, vkCreateInstance(&instanceInfo, nullptr, &mInstance));
2530 #if defined(ANGLE_SHARED_LIBVULKAN)
2531         // Load volk if we are linking dynamically
2532         volkLoadInstance(mInstance);
2533 #endif  // defined(ANGLE_SHARED_LIBVULKAN)
2534 
2535         // For promoted extensions, initialize their entry points from the core version.
2536         initializeInstanceExtensionEntryPointsFromCore();
2537     }
2538 
2539     if (mEnableDebugUtils)
2540     {
2541         // Use the newer EXT_debug_utils if it exists.
2542 #if !defined(ANGLE_SHARED_LIBVULKAN)
2543         InitDebugUtilsEXTFunctions(mInstance);
2544 #endif  // !defined(ANGLE_SHARED_LIBVULKAN)
2545 
2546         // Create the messenger callback.
2547         VkDebugUtilsMessengerCreateInfoEXT messengerInfo = {};
2548 
2549         constexpr VkDebugUtilsMessageSeverityFlagsEXT kSeveritiesToLog =
2550             VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT |
2551             VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
2552 
2553         constexpr VkDebugUtilsMessageTypeFlagsEXT kMessagesToLog =
2554             VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
2555             VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
2556             VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
2557 
2558         messengerInfo.sType           = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
2559         messengerInfo.messageSeverity = kSeveritiesToLog;
2560         messengerInfo.messageType     = kMessagesToLog;
2561         messengerInfo.pfnUserCallback = &DebugUtilsMessenger;
2562         messengerInfo.pUserData       = this;
2563 
2564         ANGLE_VK_TRY(context, vkCreateDebugUtilsMessengerEXT(mInstance, &messengerInfo, nullptr,
2565                                                              &mDebugUtilsMessenger));
2566     }
2567 
2568     uint32_t physicalDeviceCount = 0;
2569     ANGLE_VK_TRY(context, vkEnumeratePhysicalDevices(mInstance, &physicalDeviceCount, nullptr));
2570     ANGLE_VK_CHECK(context, physicalDeviceCount > 0, VK_ERROR_INITIALIZATION_FAILED);
2571 
2572     std::vector<VkPhysicalDevice> physicalDevices(physicalDeviceCount);
2573     ANGLE_VK_TRY(context, vkEnumeratePhysicalDevices(mInstance, &physicalDeviceCount,
2574                                                      physicalDevices.data()));
2575     ChoosePhysicalDevice(vkGetPhysicalDeviceProperties2, physicalDevices, mEnabledICD,
2576                          preferredVendorId, preferredDeviceId, preferredDeviceUuid,
2577                          preferredDriverUuid, preferredDriverId, &mPhysicalDevice,
2578                          &mPhysicalDeviceProperties2, &mPhysicalDeviceIDProperties,
2579                          &mDriverProperties);
2580 
2581     // The device version that is assumed by ANGLE is the minimum of the actual device version and
2582     // the highest it's allowed to use.
2583     mDeviceVersion = std::min(mPhysicalDeviceProperties.apiVersion, highestApiVersion);
2584 
2585     if (mDeviceVersion < angle::vk::kMinimumVulkanAPIVersion)
2586     {
2587         WARN() << "ANGLE Requires a minimum Vulkan device version of 1.1";
2588         ANGLE_VK_TRY(context, VK_ERROR_INCOMPATIBLE_DRIVER);
2589     }
2590 
2591     mGarbageCollectionFlushThreshold =
2592         static_cast<uint32_t>(mPhysicalDeviceProperties.limits.maxMemoryAllocationCount *
2593                               kPercentMaxMemoryAllocationCount);
2594     vkGetPhysicalDeviceFeatures(mPhysicalDevice, &mPhysicalDeviceFeatures);
2595 
2596     // Ensure we can find a graphics queue family.
2597     uint32_t queueFamilyCount = 0;
2598     vkGetPhysicalDeviceQueueFamilyProperties(mPhysicalDevice, &queueFamilyCount, nullptr);
2599 
2600     ANGLE_VK_CHECK(context, queueFamilyCount > 0, VK_ERROR_INITIALIZATION_FAILED);
2601 
2602     mQueueFamilyProperties.resize(queueFamilyCount);
2603     vkGetPhysicalDeviceQueueFamilyProperties(mPhysicalDevice, &queueFamilyCount,
2604                                              mQueueFamilyProperties.data());
2605 
2606     uint32_t queueFamilyMatchCount = 0;
2607 
2608     VkQueueFlags queueFamilyBits = VK_QUEUE_FLAG_BITS_MAX_ENUM;
2609     uint32_t firstQueueFamily    = QueueFamily::kInvalidIndex;
2610     if (nativeWindowSystem == angle::NativeWindowSystem::NullCompute)
2611     {
2612         queueFamilyBits = VK_QUEUE_COMPUTE_BIT;
2613         firstQueueFamily =
2614             QueueFamily::FindIndex(mQueueFamilyProperties, queueFamilyBits, VK_QUEUE_PROTECTED_BIT,
2615                                    VK_QUEUE_GRAPHICS_BIT, &queueFamilyMatchCount);
2616     }
2617     if (queueFamilyMatchCount == 0)
2618     {
2619         queueFamilyBits = VK_QUEUE_COMPUTE_BIT | VK_QUEUE_GRAPHICS_BIT;
2620         firstQueueFamily =
2621             QueueFamily::FindIndex(mQueueFamilyProperties, queueFamilyBits, VK_QUEUE_PROTECTED_BIT,
2622                                    0, &queueFamilyMatchCount);
2623     }
2624 
2625     ANGLE_VK_CHECK(context,
2626                    queueFamilyMatchCount > 0 && firstQueueFamily != QueueFamily::kInvalidIndex,
2627                    VK_ERROR_INITIALIZATION_FAILED);
2628 
2629     // Store the physical device memory properties so we can find the right memory pools.
2630     mMemoryProperties.init(mPhysicalDevice);
2631     ANGLE_VK_CHECK(context, mMemoryProperties.getMemoryTypeCount() > 0,
2632                    VK_ERROR_INITIALIZATION_FAILED);
2633 
2634     // The counters for the memory allocation tracker should be initialized.
2635     // Each memory allocation could be made in one of the available memory heaps. We initialize the
2636     // per-heap memory allocation trackers for MemoryAllocationType objects here, after
2637     // mMemoryProperties has been set up.
2638     mMemoryAllocationTracker.initMemoryTrackers();
2639 
2640     // Determine the threshold for pending garbage sizes.
2641     calculatePendingGarbageSizeLimit();
2642 
2643     ANGLE_TRY(
2644         setupDevice(context, featureOverrides, wsiLayer, useVulkanSwapchain, nativeWindowSystem));
2645 
2646     // If only one queue family, that's the only choice and the device is initialize with that.  If
2647     // there is more than one queue, we still create the device with the first queue family and hope
2648     // for the best.  We cannot wait for a window surface to know which supports present because of
2649     // EGL_KHR_surfaceless_context or simply pbuffers.  So far, only MoltenVk seems to expose
2650     // multiple queue families, and using the first queue family is fine with it.
2651     ANGLE_TRY(createDeviceAndQueue(context, firstQueueFamily));
2652 
2653     // Initialize the format table.
2654     mFormatTable.initialize(this, &mNativeTextureCaps);
2655 
2656     // Null terminate the extension list returned for EGL_VULKAN_INSTANCE_EXTENSIONS_ANGLE.
2657     mEnabledInstanceExtensions.push_back(nullptr);
2658 
2659     for (vk::ProtectionType protectionType : angle::AllEnums<vk::ProtectionType>())
2660     {
2661         mOneOffCommandPoolMap[protectionType].init(protectionType);
2662     }
2663 
2664     // Initialize place holder descriptor set layout for empty DescriptorSetLayoutDesc
2665     ASSERT(!mPlaceHolderDescriptorSetLayout);
2666     VkDescriptorSetLayoutCreateInfo createInfo = {};
2667     createInfo.sType        = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
2668     createInfo.flags        = 0;
2669     createInfo.bindingCount = 0;
2670     createInfo.pBindings    = nullptr;
2671 
2672     mPlaceHolderDescriptorSetLayout = vk::DescriptorSetLayoutPtr::MakeShared(context->getDevice());
2673     ANGLE_VK_TRY(context, mPlaceHolderDescriptorSetLayout->init(context->getDevice(), createInfo));
2674     ASSERT(mPlaceHolderDescriptorSetLayout->valid());
2675 
2676     return angle::Result::Continue;
2677 }
2678 
initializeMemoryAllocator(vk::ErrorContext * context)2679 angle::Result Renderer::initializeMemoryAllocator(vk::ErrorContext *context)
2680 {
2681     // This number matches Chromium and was picked by looking at memory usage of
2682     // Android apps. The allocator will start making blocks at 1/8 the max size
2683     // and builds up block size as needed before capping at the max set here.
2684     mPreferredLargeHeapBlockSize = 4 * 1024 * 1024;
2685 
2686     // Create VMA allocator
2687     ANGLE_VK_TRY(context,
2688                  mAllocator.init(mPhysicalDevice, mDevice, mInstance, mApplicationInfo.apiVersion,
2689                                  mPreferredLargeHeapBlockSize));
2690 
2691     // Figure out the alignment for default buffer allocations
2692     VkBufferCreateInfo createInfo    = {};
2693     createInfo.sType                 = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
2694     createInfo.flags                 = 0;
2695     createInfo.size                  = 4096;
2696     createInfo.usage                 = GetDefaultBufferUsageFlags(this);
2697     createInfo.sharingMode           = VK_SHARING_MODE_EXCLUSIVE;
2698     createInfo.queueFamilyIndexCount = 0;
2699     createInfo.pQueueFamilyIndices   = nullptr;
2700 
2701     vk::DeviceScoped<vk::Buffer> tempBuffer(mDevice);
2702     tempBuffer.get().init(mDevice, createInfo);
2703 
2704     VkMemoryRequirements defaultBufferMemoryRequirements;
2705     tempBuffer.get().getMemoryRequirements(mDevice, &defaultBufferMemoryRequirements);
2706     ASSERT(gl::isPow2(defaultBufferMemoryRequirements.alignment));
2707 
2708     const VkPhysicalDeviceLimits &limitsVk = getPhysicalDeviceProperties().limits;
2709     ASSERT(gl::isPow2(limitsVk.minUniformBufferOffsetAlignment));
2710     ASSERT(gl::isPow2(limitsVk.minStorageBufferOffsetAlignment));
2711     ASSERT(gl::isPow2(limitsVk.minTexelBufferOffsetAlignment));
2712     ASSERT(gl::isPow2(limitsVk.minMemoryMapAlignment));
2713 
2714     mDefaultBufferAlignment =
2715         std::max({static_cast<size_t>(limitsVk.minUniformBufferOffsetAlignment),
2716                   static_cast<size_t>(limitsVk.minStorageBufferOffsetAlignment),
2717                   static_cast<size_t>(limitsVk.minTexelBufferOffsetAlignment),
2718                   static_cast<size_t>(limitsVk.minMemoryMapAlignment),
2719                   static_cast<size_t>(defaultBufferMemoryRequirements.alignment)});
2720 
2721     // Initialize staging buffer memory type index and alignment.
2722     // These buffers will only be used as transfer sources or transfer targets.
2723     createInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
2724     VkMemoryPropertyFlags requiredFlags, preferredFlags;
2725     bool persistentlyMapped = mFeatures.persistentlyMappedBuffers.enabled;
2726 
2727     // Uncached coherent staging buffer.
2728     requiredFlags  = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
2729     preferredFlags = VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
2730     ANGLE_VK_TRY(context,
2731                  mAllocator.findMemoryTypeIndexForBufferInfo(
2732                      createInfo, requiredFlags, preferredFlags, persistentlyMapped,
2733                      &mStagingBufferMemoryTypeIndex[vk::MemoryCoherency::UnCachedCoherent]));
2734     ASSERT(mStagingBufferMemoryTypeIndex[vk::MemoryCoherency::UnCachedCoherent] !=
2735            kInvalidMemoryTypeIndex);
2736 
2737     // Cached coherent staging buffer.  Note coherent is preferred but not required, which means we
2738     // may get non-coherent memory type.
2739     requiredFlags   = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
2740     preferredFlags  = VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
2741     VkResult result = mAllocator.findMemoryTypeIndexForBufferInfo(
2742         createInfo, requiredFlags, preferredFlags, persistentlyMapped,
2743         &mStagingBufferMemoryTypeIndex[vk::MemoryCoherency::CachedPreferCoherent]);
2744     if (result == VK_SUCCESS)
2745     {
2746         ASSERT(mStagingBufferMemoryTypeIndex[vk::MemoryCoherency::CachedPreferCoherent] !=
2747                kInvalidMemoryTypeIndex);
2748     }
2749     else
2750     {
2751         // Android studio may not expose host cached memory pool. Fall back to host uncached.
2752         mStagingBufferMemoryTypeIndex[vk::MemoryCoherency::CachedPreferCoherent] =
2753             mStagingBufferMemoryTypeIndex[vk::MemoryCoherency::UnCachedCoherent];
2754     }
2755 
2756     // Cached Non-coherent staging buffer
2757     requiredFlags  = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
2758     preferredFlags = 0;
2759     result         = mAllocator.findMemoryTypeIndexForBufferInfo(
2760         createInfo, requiredFlags, preferredFlags, persistentlyMapped,
2761         &mStagingBufferMemoryTypeIndex[vk::MemoryCoherency::CachedNonCoherent]);
2762     if (result == VK_SUCCESS)
2763     {
2764         ASSERT(mStagingBufferMemoryTypeIndex[vk::MemoryCoherency::CachedNonCoherent] !=
2765                kInvalidMemoryTypeIndex);
2766     }
2767     else
2768     {
2769         // Android studio may not expose host cached memory pool. Fall back to host uncached.
2770         mStagingBufferMemoryTypeIndex[vk::MemoryCoherency::CachedNonCoherent] =
2771             mStagingBufferMemoryTypeIndex[vk::MemoryCoherency::UnCachedCoherent];
2772     }
2773 
2774     // Alignment
2775     mStagingBufferAlignment =
2776         static_cast<size_t>(mPhysicalDeviceProperties.limits.minMemoryMapAlignment);
2777     ASSERT(gl::isPow2(mPhysicalDeviceProperties.limits.nonCoherentAtomSize));
2778     ASSERT(gl::isPow2(mPhysicalDeviceProperties.limits.optimalBufferCopyOffsetAlignment));
2779     // Usually minTexelBufferOffsetAlignment is much smaller than  nonCoherentAtomSize
2780     ASSERT(gl::isPow2(mPhysicalDeviceProperties.limits.minTexelBufferOffsetAlignment));
2781     mStagingBufferAlignment = std::max(
2782         {mStagingBufferAlignment,
2783          static_cast<size_t>(mPhysicalDeviceProperties.limits.optimalBufferCopyOffsetAlignment),
2784          static_cast<size_t>(mPhysicalDeviceProperties.limits.nonCoherentAtomSize),
2785          static_cast<size_t>(mPhysicalDeviceProperties.limits.minTexelBufferOffsetAlignment)});
2786     ASSERT(gl::isPow2(mStagingBufferAlignment));
2787 
2788     // Device local vertex conversion buffer
2789     createInfo.usage = vk::kVertexBufferUsageFlags;
2790     requiredFlags    = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
2791     preferredFlags   = 0;
2792     ANGLE_VK_TRY(context, mAllocator.findMemoryTypeIndexForBufferInfo(
2793                               createInfo, requiredFlags, preferredFlags, persistentlyMapped,
2794                               &mDeviceLocalVertexConversionBufferMemoryTypeIndex));
2795     ASSERT(mDeviceLocalVertexConversionBufferMemoryTypeIndex != kInvalidMemoryTypeIndex);
2796 
2797     // Host visible and non-coherent vertex conversion buffer, which is the same as non-coherent
2798     // staging buffer
2799     mHostVisibleVertexConversionBufferMemoryTypeIndex =
2800         mStagingBufferMemoryTypeIndex[vk::MemoryCoherency::CachedNonCoherent];
2801 
2802     // We may use compute shader to do conversion, so we must meet
2803     // minStorageBufferOffsetAlignment requirement as well. Also take into account non-coherent
2804     // alignment requirements.
2805     mVertexConversionBufferAlignment = std::max(
2806         {vk::kVertexBufferAlignment,
2807          static_cast<size_t>(mPhysicalDeviceProperties.limits.minStorageBufferOffsetAlignment),
2808          static_cast<size_t>(mPhysicalDeviceProperties.limits.nonCoherentAtomSize),
2809          static_cast<size_t>(defaultBufferMemoryRequirements.alignment)});
2810     ASSERT(gl::isPow2(mVertexConversionBufferAlignment));
2811 
2812     return angle::Result::Continue;
2813 }
2814 
2815 // The following features and properties are not promoted to any core Vulkan versions (up to Vulkan
2816 // 1.3):
2817 //
2818 // - VK_EXT_line_rasterization:                        bresenhamLines (feature)
2819 // - VK_EXT_provoking_vertex:                          provokingVertexLast (feature)
2820 // - VK_EXT_vertex_attribute_divisor:                  vertexAttributeInstanceRateDivisor (feature),
2821 //                                                     maxVertexAttribDivisor (property)
2822 // - VK_EXT_transform_feedback:                        transformFeedback (feature),
2823 //                                                     geometryStreams (feature)
2824 // - VK_EXT_index_type_uint8:                          indexTypeUint8 (feature)
2825 // - VK_EXT_device_memory_report:                      deviceMemoryReport (feature)
2826 // - VK_EXT_multisampled_render_to_single_sampled:     multisampledRenderToSingleSampled (feature)
2827 // - VK_EXT_image_2d_view_of_3d:                       image2DViewOf3D (feature)
2828 //                                                     sampler2DViewOf3D (feature)
2829 // - VK_EXT_custom_border_color:                       customBorderColors (feature)
2830 //                                                     customBorderColorWithoutFormat (feature)
2831 // - VK_EXT_depth_clamp_zero_one:                      depthClampZeroOne (feature)
2832 // - VK_EXT_depth_clip_control:                        depthClipControl (feature)
2833 // - VK_EXT_primitives_generated_query:                primitivesGeneratedQuery (feature),
2834 //                                                     primitivesGeneratedQueryWithRasterizerDiscard
2835 //                                                                                        (property)
2836 // - VK_EXT_primitive_topology_list_restart:           primitiveTopologyListRestart (feature)
2837 // - VK_EXT_graphics_pipeline_library:                 graphicsPipelineLibrary (feature),
2838 //                                                     graphicsPipelineLibraryFastLinking (property)
2839 // - VK_KHR_fragment_shading_rate:                     pipelineFragmentShadingRate (feature)
2840 // - VK_EXT_fragment_shader_interlock:                 fragmentShaderPixelInterlock (feature)
2841 // - VK_EXT_pipeline_robustness:                       pipelineRobustness (feature)
2842 // - VK_EXT_pipeline_protected_access:                 pipelineProtectedAccess (feature)
2843 // - VK_EXT_rasterization_order_attachment_access or
2844 //   VK_ARM_rasterization_order_attachment_access:     rasterizationOrderColorAttachmentAccess
2845 //                                                                                   (feature)
2846 //                                                     rasterizationOrderDepthAttachmentAccess
2847 //                                                                                   (feature)
2848 //                                                     rasterizationOrderStencilAttachmentAccess
2849 //                                                                                   (feature)
2850 // - VK_EXT_swapchain_maintenance1:                    swapchainMaintenance1 (feature)
2851 // - VK_EXT_legacy_dithering:                          supportsLegacyDithering (feature)
2852 // - VK_EXT_physical_device_drm:                       hasPrimary (property),
2853 //                                                     hasRender (property)
2854 // - VK_EXT_host_image_copy:                           hostImageCopy (feature),
2855 //                                                     pCopySrcLayouts (property),
2856 //                                                     pCopyDstLayouts (property),
2857 //                                                     identicalMemoryTypeRequirements (property)
2858 // - VK_ANDROID_external_format_resolve:               externalFormatResolve (feature)
2859 // - VK_EXT_vertex_input_dynamic_state:                vertexInputDynamicState (feature)
2860 // - VK_KHR_dynamic_rendering_local_read:              dynamicRenderingLocalRead (feature)
2861 // - VK_EXT_shader_atomic_float                        shaderImageFloat32Atomics (feature)
2862 // - VK_EXT_image_compression_control                  imageCompressionControl (feature)
2863 // - VK_EXT_image_compression_control_swapchain        imageCompressionControlSwapchain (feature)
2864 // - VK_EXT_device_fault                               deviceFault (feature),
2865 //                                                     deviceFaultVendorBinary (feature)
2866 //
appendDeviceExtensionFeaturesNotPromoted(const vk::ExtensionNameList & deviceExtensionNames,VkPhysicalDeviceFeatures2KHR * deviceFeatures,VkPhysicalDeviceProperties2 * deviceProperties)2867 void Renderer::appendDeviceExtensionFeaturesNotPromoted(
2868     const vk::ExtensionNameList &deviceExtensionNames,
2869     VkPhysicalDeviceFeatures2KHR *deviceFeatures,
2870     VkPhysicalDeviceProperties2 *deviceProperties)
2871 {
2872     if (ExtensionFound(VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME, deviceExtensionNames))
2873     {
2874         vk::AddToPNextChain(deviceFeatures, &mLineRasterizationFeatures);
2875     }
2876 
2877     if (ExtensionFound(VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME, deviceExtensionNames))
2878     {
2879         vk::AddToPNextChain(deviceFeatures, &mProvokingVertexFeatures);
2880     }
2881 
2882     if (ExtensionFound(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME, deviceExtensionNames))
2883     {
2884         vk::AddToPNextChain(deviceFeatures, &mVertexAttributeDivisorFeatures);
2885         vk::AddToPNextChain(deviceProperties, &mVertexAttributeDivisorProperties);
2886     }
2887 
2888     if (ExtensionFound(VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME, deviceExtensionNames))
2889     {
2890         vk::AddToPNextChain(deviceFeatures, &mTransformFeedbackFeatures);
2891     }
2892 
2893     if (ExtensionFound(VK_EXT_INDEX_TYPE_UINT8_EXTENSION_NAME, deviceExtensionNames))
2894     {
2895         vk::AddToPNextChain(deviceFeatures, &mIndexTypeUint8Features);
2896     }
2897 
2898     if (ExtensionFound(VK_EXT_DEVICE_MEMORY_REPORT_EXTENSION_NAME, deviceExtensionNames))
2899     {
2900         vk::AddToPNextChain(deviceFeatures, &mMemoryReportFeatures);
2901     }
2902 
2903     if (ExtensionFound(VK_EXT_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_EXTENSION_NAME,
2904                        deviceExtensionNames))
2905     {
2906         vk::AddToPNextChain(deviceFeatures, &mMultisampledRenderToSingleSampledFeatures);
2907     }
2908 
2909     if (ExtensionFound(VK_EXT_IMAGE_2D_VIEW_OF_3D_EXTENSION_NAME, deviceExtensionNames))
2910     {
2911         vk::AddToPNextChain(deviceFeatures, &mImage2dViewOf3dFeatures);
2912     }
2913 
2914     if (ExtensionFound(VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME, deviceExtensionNames))
2915     {
2916         vk::AddToPNextChain(deviceFeatures, &mCustomBorderColorFeatures);
2917     }
2918 
2919     if (ExtensionFound(VK_EXT_DEPTH_CLAMP_ZERO_ONE_EXTENSION_NAME, deviceExtensionNames))
2920     {
2921         vk::AddToPNextChain(deviceFeatures, &mDepthClampZeroOneFeatures);
2922     }
2923 
2924     if (ExtensionFound(VK_EXT_DEPTH_CLIP_CONTROL_EXTENSION_NAME, deviceExtensionNames))
2925     {
2926         vk::AddToPNextChain(deviceFeatures, &mDepthClipControlFeatures);
2927     }
2928 
2929     if (ExtensionFound(VK_EXT_PRIMITIVES_GENERATED_QUERY_EXTENSION_NAME, deviceExtensionNames))
2930     {
2931         vk::AddToPNextChain(deviceFeatures, &mPrimitivesGeneratedQueryFeatures);
2932     }
2933 
2934     if (ExtensionFound(VK_EXT_PRIMITIVE_TOPOLOGY_LIST_RESTART_EXTENSION_NAME, deviceExtensionNames))
2935     {
2936         vk::AddToPNextChain(deviceFeatures, &mPrimitiveTopologyListRestartFeatures);
2937     }
2938 
2939     if (ExtensionFound(VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME, deviceExtensionNames))
2940     {
2941         vk::AddToPNextChain(deviceFeatures, &mGraphicsPipelineLibraryFeatures);
2942         vk::AddToPNextChain(deviceProperties, &mGraphicsPipelineLibraryProperties);
2943     }
2944 
2945     if (ExtensionFound(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME, deviceExtensionNames))
2946     {
2947         vk::AddToPNextChain(deviceFeatures, &mFragmentShadingRateFeatures);
2948         vk::AddToPNextChain(deviceProperties, &mFragmentShadingRateProperties);
2949     }
2950 
2951     if (ExtensionFound(VK_EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME, deviceExtensionNames))
2952     {
2953         vk::AddToPNextChain(deviceFeatures, &mFragmentShaderInterlockFeatures);
2954     }
2955 
2956     if (ExtensionFound(VK_EXT_PIPELINE_ROBUSTNESS_EXTENSION_NAME, deviceExtensionNames))
2957     {
2958         vk::AddToPNextChain(deviceFeatures, &mPipelineRobustnessFeatures);
2959     }
2960 
2961     if (ExtensionFound(VK_EXT_PIPELINE_PROTECTED_ACCESS_EXTENSION_NAME, deviceExtensionNames))
2962     {
2963         vk::AddToPNextChain(deviceFeatures, &mPipelineProtectedAccessFeatures);
2964     }
2965 
2966     // The EXT and ARM versions are interchangeable. The structs and enums alias each other.
2967     if (ExtensionFound(VK_EXT_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_EXTENSION_NAME,
2968                        deviceExtensionNames))
2969     {
2970         vk::AddToPNextChain(deviceFeatures, &mRasterizationOrderAttachmentAccessFeatures);
2971     }
2972     else if (ExtensionFound(VK_ARM_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_EXTENSION_NAME,
2973                             deviceExtensionNames))
2974     {
2975         vk::AddToPNextChain(deviceFeatures, &mRasterizationOrderAttachmentAccessFeatures);
2976     }
2977 
2978     if (ExtensionFound(VK_EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME, deviceExtensionNames))
2979     {
2980         vk::AddToPNextChain(deviceFeatures, &mShaderAtomicFloatFeatures);
2981     }
2982 
2983     if (ExtensionFound(VK_EXT_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME, deviceExtensionNames))
2984     {
2985         vk::AddToPNextChain(deviceFeatures, &mSwapchainMaintenance1Features);
2986     }
2987 
2988     if (ExtensionFound(VK_EXT_LEGACY_DITHERING_EXTENSION_NAME, deviceExtensionNames))
2989     {
2990         vk::AddToPNextChain(deviceFeatures, &mDitheringFeatures);
2991     }
2992 
2993     if (ExtensionFound(VK_EXT_PHYSICAL_DEVICE_DRM_EXTENSION_NAME, deviceExtensionNames))
2994     {
2995         vk::AddToPNextChain(deviceProperties, &mDrmProperties);
2996     }
2997 
2998     if (ExtensionFound(VK_EXT_HOST_IMAGE_COPY_EXTENSION_NAME, deviceExtensionNames))
2999     {
3000         // VkPhysicalDeviceHostImageCopyPropertiesEXT has a count + array query.  Typically, that
3001         // requires getting the properties once with a nullptr array, to get the count, and then
3002         // again with an array of that size.  For simplicity, ANGLE just uses an array that's big
3003         // enough.  If that array goes terribly large in the future, ANGLE may lose knowledge of
3004         // some likely esoteric layouts, which doesn't really matter.
3005         constexpr uint32_t kMaxLayoutCount = 50;
3006         mHostImageCopySrcLayoutsStorage.resize(kMaxLayoutCount, VK_IMAGE_LAYOUT_UNDEFINED);
3007         mHostImageCopyDstLayoutsStorage.resize(kMaxLayoutCount, VK_IMAGE_LAYOUT_UNDEFINED);
3008         mHostImageCopyProperties.copySrcLayoutCount = kMaxLayoutCount;
3009         mHostImageCopyProperties.copyDstLayoutCount = kMaxLayoutCount;
3010         mHostImageCopyProperties.pCopySrcLayouts    = mHostImageCopySrcLayoutsStorage.data();
3011         mHostImageCopyProperties.pCopyDstLayouts    = mHostImageCopyDstLayoutsStorage.data();
3012 
3013         vk::AddToPNextChain(deviceFeatures, &mHostImageCopyFeatures);
3014         vk::AddToPNextChain(deviceProperties, &mHostImageCopyProperties);
3015     }
3016 
3017     if (ExtensionFound(VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME, deviceExtensionNames))
3018     {
3019         vk::AddToPNextChain(deviceFeatures, &mVertexInputDynamicStateFeatures);
3020     }
3021 
3022 #if defined(ANGLE_PLATFORM_ANDROID)
3023     if (ExtensionFound(VK_ANDROID_EXTERNAL_FORMAT_RESOLVE_EXTENSION_NAME, deviceExtensionNames))
3024     {
3025         vk::AddToPNextChain(deviceFeatures, &mExternalFormatResolveFeatures);
3026         vk::AddToPNextChain(deviceProperties, &mExternalFormatResolveProperties);
3027     }
3028 #endif
3029 
3030     if (ExtensionFound(VK_KHR_DYNAMIC_RENDERING_LOCAL_READ_EXTENSION_NAME, deviceExtensionNames))
3031     {
3032         vk::AddToPNextChain(deviceFeatures, &mDynamicRenderingLocalReadFeatures);
3033     }
3034 
3035     if (ExtensionFound(VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME, deviceExtensionNames))
3036     {
3037         vk::AddToPNextChain(deviceFeatures, &mBlendOperationAdvancedFeatures);
3038     }
3039 
3040     if (ExtensionFound(VK_EXT_IMAGE_COMPRESSION_CONTROL_EXTENSION_NAME, deviceExtensionNames))
3041     {
3042         vk::AddToPNextChain(deviceFeatures, &mImageCompressionControlFeatures);
3043     }
3044     if (ExtensionFound(VK_EXT_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_EXTENSION_NAME,
3045                        deviceExtensionNames))
3046     {
3047         vk::AddToPNextChain(deviceFeatures, &mImageCompressionControlSwapchainFeatures);
3048     }
3049     if (ExtensionFound(VK_EXT_DEVICE_FAULT_EXTENSION_NAME, deviceExtensionNames))
3050     {
3051         vk::AddToPNextChain(deviceFeatures, &mFaultFeatures);
3052     }
3053 }
3054 
3055 // The following features and properties used by ANGLE have been promoted to Vulkan 1.1:
3056 //
3057 // - (unpublished VK_KHR_subgroup):         supportedStages (property),
3058 //                                          supportedOperations (property)
3059 // - (unpublished VK_KHR_protected_memory): protectedMemory (feature)
3060 // - VK_KHR_sampler_ycbcr_conversion:       samplerYcbcrConversion (feature)
3061 // - VK_KHR_multiview:                      multiview (feature),
3062 //                                          maxMultiviewViewCount (property)
3063 // - VK_KHR_16bit_storage:                  storageBuffer16BitAccess (feature)
3064 //                                          uniformAndStorageBuffer16BitAccess (feature)
3065 //                                          storagePushConstant16 (feature)
3066 //                                          storageInputOutput16 (feature)
3067 // - VK_KHR_variable_pointers:              variablePointers (feature)
3068 //                                          variablePointersStorageBuffer (feature)
3069 //
3070 //
3071 // Note that subgroup and protected memory features and properties came from unpublished extensions
3072 // and are core in Vulkan 1.1.
3073 //
appendDeviceExtensionFeaturesPromotedTo11(const vk::ExtensionNameList & deviceExtensionNames,VkPhysicalDeviceFeatures2KHR * deviceFeatures,VkPhysicalDeviceProperties2 * deviceProperties)3074 void Renderer::appendDeviceExtensionFeaturesPromotedTo11(
3075     const vk::ExtensionNameList &deviceExtensionNames,
3076     VkPhysicalDeviceFeatures2KHR *deviceFeatures,
3077     VkPhysicalDeviceProperties2 *deviceProperties)
3078 {
3079     vk::AddToPNextChain(deviceProperties, &mSubgroupProperties);
3080     vk::AddToPNextChain(deviceFeatures, &mProtectedMemoryFeatures);
3081     vk::AddToPNextChain(deviceFeatures, &mSamplerYcbcrConversionFeatures);
3082     vk::AddToPNextChain(deviceFeatures, &mMultiviewFeatures);
3083     vk::AddToPNextChain(deviceProperties, &mMultiviewProperties);
3084     vk::AddToPNextChain(deviceFeatures, &m16BitStorageFeatures);
3085     vk::AddToPNextChain(deviceFeatures, &mVariablePointersFeatures);
3086     vk::AddToPNextChain(deviceProperties, &mMaintenance3Properties);
3087 }
3088 
3089 // The following features and properties used by ANGLE have been promoted to Vulkan 1.2:
3090 //
3091 // - VK_KHR_shader_float16_int8:            shaderFloat16 (feature),
3092 //                                          shaderInt8 (feature)
3093 // - VK_KHR_depth_stencil_resolve:          supportedDepthResolveModes (property),
3094 //                                          independentResolveNone (property)
3095 // - VK_KHR_driver_properties:              driverName (property),
3096 //                                          driverID (property)
3097 // - VK_KHR_shader_subgroup_extended_types: shaderSubgroupExtendedTypes (feature)
3098 // - VK_EXT_host_query_reset:               hostQueryReset (feature)
3099 // - VK_KHR_imageless_framebuffer:          imagelessFramebuffer (feature)
3100 // - VK_KHR_timeline_semaphore:             timelineSemaphore (feature)
3101 // - VK_KHR_8bit_storage                    storageBuffer8BitAccess (feature)
3102 //                                          uniformAndStorageBuffer8BitAccess (feature)
3103 //                                          storagePushConstant8 (feature)
3104 // - VK_KHR_shader_float_controls           shaderRoundingModeRTEFloat16 (property)
3105 //                                          shaderRoundingModeRTEFloat32 (property)
3106 //                                          shaderRoundingModeRTEFloat64 (property)
3107 //                                          shaderRoundingModeRTZFloat16 (property)
3108 //                                          shaderRoundingModeRTZFloat32 (property)
3109 //                                          shaderRoundingModeRTZFloat64 (property)
3110 //                                          shaderDenormPreserveFloat16 (property)
3111 //                                          shaderDenormPreserveFloat16 (property)
3112 //                                          shaderDenormPreserveFloat16 (property)
3113 //                                          shaderDenormFlushToZeroFloat16 (property)
3114 //                                          shaderDenormFlushToZeroFloat32 (property)
3115 //                                          shaderDenormFlushToZeroFloat64 (property)
3116 //                                          shaderSignedZeroInfNanPreserveFloat16 (property)
3117 //                                          shaderSignedZeroInfNanPreserveFloat32 (property)
3118 //                                          shaderSignedZeroInfNanPreserveFloat64 (property)
3119 // - VK_KHR_uniform_buffer_standard_layout: uniformBufferStandardLayout (feature)
3120 //
3121 // Note that supportedDepthResolveModes is used just to check if the property struct is populated.
3122 // ANGLE always uses VK_RESOLVE_MODE_SAMPLE_ZERO_BIT for both depth and stencil, and support for
3123 // this bit is mandatory as long as the extension (or Vulkan 1.2) exists.
3124 //
appendDeviceExtensionFeaturesPromotedTo12(const vk::ExtensionNameList & deviceExtensionNames,VkPhysicalDeviceFeatures2KHR * deviceFeatures,VkPhysicalDeviceProperties2 * deviceProperties)3125 void Renderer::appendDeviceExtensionFeaturesPromotedTo12(
3126     const vk::ExtensionNameList &deviceExtensionNames,
3127     VkPhysicalDeviceFeatures2KHR *deviceFeatures,
3128     VkPhysicalDeviceProperties2 *deviceProperties)
3129 {
3130     if (ExtensionFound(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME, deviceExtensionNames))
3131     {
3132         vk::AddToPNextChain(deviceProperties, &mFloatControlProperties);
3133     }
3134 
3135     if (ExtensionFound(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME, deviceExtensionNames))
3136     {
3137         vk::AddToPNextChain(deviceFeatures, &mShaderFloat16Int8Features);
3138     }
3139 
3140     if (ExtensionFound(VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME, deviceExtensionNames))
3141     {
3142         vk::AddToPNextChain(deviceProperties, &mDepthStencilResolveProperties);
3143     }
3144 
3145     if (ExtensionFound(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME, deviceExtensionNames))
3146     {
3147         vk::AddToPNextChain(deviceProperties, &mDriverProperties);
3148     }
3149 
3150     if (ExtensionFound(VK_KHR_SHADER_SUBGROUP_EXTENDED_TYPES_EXTENSION_NAME, deviceExtensionNames))
3151     {
3152         vk::AddToPNextChain(deviceFeatures, &mSubgroupExtendedTypesFeatures);
3153     }
3154 
3155     if (ExtensionFound(VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME, deviceExtensionNames))
3156     {
3157         vk::AddToPNextChain(deviceFeatures, &mHostQueryResetFeatures);
3158     }
3159 
3160     if (ExtensionFound(VK_KHR_IMAGELESS_FRAMEBUFFER_EXTENSION_NAME, deviceExtensionNames))
3161     {
3162         vk::AddToPNextChain(deviceFeatures, &mImagelessFramebufferFeatures);
3163     }
3164 
3165     if (ExtensionFound(VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME, deviceExtensionNames))
3166     {
3167         vk::AddToPNextChain(deviceFeatures, &mTimelineSemaphoreFeatures);
3168     }
3169 
3170     if (ExtensionFound(VK_KHR_8BIT_STORAGE_EXTENSION_NAME, deviceExtensionNames))
3171     {
3172         vk::AddToPNextChain(deviceFeatures, &m8BitStorageFeatures);
3173     }
3174 
3175     if (ExtensionFound(VK_KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_EXTENSION_NAME, deviceExtensionNames))
3176     {
3177         vk::AddToPNextChain(deviceFeatures, &mUniformBufferStandardLayoutFeatures);
3178     }
3179 }
3180 
3181 // The following features and properties used by ANGLE have been promoted to Vulkan 1.3:
3182 //
3183 // - VK_EXT_extended_dynamic_state:          extendedDynamicState (feature)
3184 // - VK_EXT_extended_dynamic_state2:         extendedDynamicState2 (feature),
3185 //                                           extendedDynamicState2LogicOp (feature)
3186 // - VK_KHR_synchronization2:                synchronization2 (feature)
3187 // - VK_KHR_dynamic_rendering:               dynamicRendering (feature)
3188 // - VK_KHR_maintenance5:                    maintenance5 (feature)
3189 // - VK_EXT_texture_compression_astc_hdr:    textureCompressionASTC_HDR(feature)
3190 //
3191 // Note that VK_EXT_extended_dynamic_state2 is partially promoted to Vulkan 1.3.  If ANGLE creates a
3192 // Vulkan 1.3 device, it would still need to enable this extension separately for
3193 // extendedDynamicState2LogicOp.
3194 //
appendDeviceExtensionFeaturesPromotedTo13(const vk::ExtensionNameList & deviceExtensionNames,VkPhysicalDeviceFeatures2KHR * deviceFeatures,VkPhysicalDeviceProperties2 * deviceProperties)3195 void Renderer::appendDeviceExtensionFeaturesPromotedTo13(
3196     const vk::ExtensionNameList &deviceExtensionNames,
3197     VkPhysicalDeviceFeatures2KHR *deviceFeatures,
3198     VkPhysicalDeviceProperties2 *deviceProperties)
3199 {
3200     if (ExtensionFound(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME, deviceExtensionNames))
3201     {
3202         vk::AddToPNextChain(deviceFeatures, &mExtendedDynamicStateFeatures);
3203     }
3204 
3205     if (ExtensionFound(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME, deviceExtensionNames))
3206     {
3207         vk::AddToPNextChain(deviceFeatures, &mExtendedDynamicState2Features);
3208     }
3209 
3210     if (ExtensionFound(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME, deviceExtensionNames))
3211     {
3212         vk::AddToPNextChain(deviceFeatures, &mSynchronization2Features);
3213     }
3214 
3215     if (ExtensionFound(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME, deviceExtensionNames))
3216     {
3217         vk::AddToPNextChain(deviceFeatures, &mDynamicRenderingFeatures);
3218     }
3219 
3220     if (ExtensionFound(VK_KHR_MAINTENANCE_5_EXTENSION_NAME, deviceExtensionNames))
3221     {
3222         vk::AddToPNextChain(deviceFeatures, &mMaintenance5Features);
3223     }
3224 
3225     if (ExtensionFound(VK_EXT_TEXTURE_COMPRESSION_ASTC_HDR_EXTENSION_NAME, deviceExtensionNames))
3226     {
3227         vk::AddToPNextChain(deviceFeatures, &mTextureCompressionASTCHDRFeatures);
3228     }
3229 }
3230 
queryDeviceExtensionFeatures(const vk::ExtensionNameList & deviceExtensionNames)3231 void Renderer::queryDeviceExtensionFeatures(const vk::ExtensionNameList &deviceExtensionNames)
3232 {
3233     // Default initialize all extension features to false.
3234     mLineRasterizationFeatures = {};
3235     mLineRasterizationFeatures.sType =
3236         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT;
3237 
3238     mProvokingVertexFeatures = {};
3239     mProvokingVertexFeatures.sType =
3240         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT;
3241 
3242     mVertexAttributeDivisorFeatures = {};
3243     mVertexAttributeDivisorFeatures.sType =
3244         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT;
3245 
3246     mVertexAttributeDivisorProperties = {};
3247     mVertexAttributeDivisorProperties.sType =
3248         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT;
3249 
3250     mTransformFeedbackFeatures = {};
3251     mTransformFeedbackFeatures.sType =
3252         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT;
3253 
3254     mIndexTypeUint8Features       = {};
3255     mIndexTypeUint8Features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT;
3256 
3257     mSubgroupProperties       = {};
3258     mSubgroupProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES;
3259 
3260     mSubgroupExtendedTypesFeatures = {};
3261     mSubgroupExtendedTypesFeatures.sType =
3262         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES;
3263 
3264     mMemoryReportFeatures = {};
3265     mMemoryReportFeatures.sType =
3266         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_MEMORY_REPORT_FEATURES_EXT;
3267 
3268     mShaderFloat16Int8Features = {};
3269     mShaderFloat16Int8Features.sType =
3270         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES;
3271 
3272     mDepthStencilResolveProperties = {};
3273     mDepthStencilResolveProperties.sType =
3274         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES;
3275 
3276     mCustomBorderColorFeatures = {};
3277     mCustomBorderColorFeatures.sType =
3278         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT;
3279 
3280     mMultisampledRenderToSingleSampledFeatures = {};
3281     mMultisampledRenderToSingleSampledFeatures.sType =
3282         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_FEATURES_EXT;
3283 
3284     mImage2dViewOf3dFeatures = {};
3285     mImage2dViewOf3dFeatures.sType =
3286         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_2D_VIEW_OF_3D_FEATURES_EXT;
3287 
3288     mMultiviewFeatures       = {};
3289     mMultiviewFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES;
3290 
3291     mMultiviewProperties       = {};
3292     mMultiviewProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES;
3293 
3294     mMaintenance3Properties       = {};
3295     mMaintenance3Properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES;
3296 
3297     mFaultFeatures       = {};
3298     mFaultFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FAULT_FEATURES_EXT;
3299 
3300     mDriverProperties       = {};
3301     mDriverProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES;
3302 
3303     mSamplerYcbcrConversionFeatures = {};
3304     mSamplerYcbcrConversionFeatures.sType =
3305         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES;
3306 
3307     mProtectedMemoryFeatures       = {};
3308     mProtectedMemoryFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES;
3309 
3310     mHostQueryResetFeatures       = {};
3311     mHostQueryResetFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT;
3312 
3313     mDepthClampZeroOneFeatures = {};
3314     mDepthClampZeroOneFeatures.sType =
3315         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLAMP_ZERO_ONE_FEATURES_EXT;
3316 
3317     mDepthClipControlFeatures = {};
3318     mDepthClipControlFeatures.sType =
3319         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_CONTROL_FEATURES_EXT;
3320 
3321     mPrimitivesGeneratedQueryFeatures = {};
3322     mPrimitivesGeneratedQueryFeatures.sType =
3323         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVES_GENERATED_QUERY_FEATURES_EXT;
3324 
3325     mPrimitiveTopologyListRestartFeatures = {};
3326     mPrimitiveTopologyListRestartFeatures.sType =
3327         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVE_TOPOLOGY_LIST_RESTART_FEATURES_EXT;
3328 
3329     mExtendedDynamicStateFeatures = {};
3330     mExtendedDynamicStateFeatures.sType =
3331         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT;
3332 
3333     mExtendedDynamicState2Features = {};
3334     mExtendedDynamicState2Features.sType =
3335         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_2_FEATURES_EXT;
3336 
3337     mGraphicsPipelineLibraryFeatures = {};
3338     mGraphicsPipelineLibraryFeatures.sType =
3339         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_FEATURES_EXT;
3340 
3341     mGraphicsPipelineLibraryProperties = {};
3342     mGraphicsPipelineLibraryProperties.sType =
3343         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_PROPERTIES_EXT;
3344 
3345     mVertexInputDynamicStateFeatures = {};
3346     mVertexInputDynamicStateFeatures.sType =
3347         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_INPUT_DYNAMIC_STATE_FEATURES_EXT;
3348 
3349     mDynamicRenderingFeatures = {};
3350     mDynamicRenderingFeatures.sType =
3351         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES_KHR;
3352 
3353     mDynamicRenderingLocalReadFeatures = {};
3354     mDynamicRenderingLocalReadFeatures.sType =
3355         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_LOCAL_READ_FEATURES_KHR;
3356 
3357     mFragmentShadingRateFeatures = {};
3358     mFragmentShadingRateFeatures.sType =
3359         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR;
3360 
3361     mFragmentShadingRateProperties = {};
3362     mFragmentShadingRateProperties.sType =
3363         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_PROPERTIES_KHR;
3364 
3365     mFragmentShaderInterlockFeatures = {};
3366     mFragmentShaderInterlockFeatures.sType =
3367         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT;
3368 
3369     mImagelessFramebufferFeatures = {};
3370     mImagelessFramebufferFeatures.sType =
3371         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES_KHR;
3372 
3373     mPipelineRobustnessFeatures = {};
3374     mPipelineRobustnessFeatures.sType =
3375         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_FEATURES_EXT;
3376 
3377     mPipelineProtectedAccessFeatures = {};
3378     mPipelineProtectedAccessFeatures.sType =
3379         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROTECTED_ACCESS_FEATURES_EXT;
3380 
3381     mRasterizationOrderAttachmentAccessFeatures = {};
3382     mRasterizationOrderAttachmentAccessFeatures.sType =
3383         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_EXT;
3384 
3385     mMaintenance5Features       = {};
3386     mMaintenance5Features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_FEATURES_KHR;
3387 
3388     mShaderAtomicFloatFeatures = {};
3389     mShaderAtomicFloatFeatures.sType =
3390         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT;
3391 
3392     mSwapchainMaintenance1Features = {};
3393     mSwapchainMaintenance1Features.sType =
3394         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_EXT;
3395 
3396     mDitheringFeatures       = {};
3397     mDitheringFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LEGACY_DITHERING_FEATURES_EXT;
3398 
3399     mDrmProperties       = {};
3400     mDrmProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRM_PROPERTIES_EXT;
3401 
3402     mTimelineSemaphoreFeatures = {};
3403     mTimelineSemaphoreFeatures.sType =
3404         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES_KHR;
3405 
3406     mHostImageCopyFeatures       = {};
3407     mHostImageCopyFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_FEATURES_EXT;
3408 
3409     mHostImageCopyProperties = {};
3410     mHostImageCopyProperties.sType =
3411         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_PROPERTIES_EXT;
3412 
3413     m8BitStorageFeatures       = {};
3414     m8BitStorageFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR;
3415 
3416     m16BitStorageFeatures       = {};
3417     m16BitStorageFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR;
3418 
3419     mSynchronization2Features       = {};
3420     mSynchronization2Features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES;
3421 
3422     mBlendOperationAdvancedFeatures = {};
3423     mBlendOperationAdvancedFeatures.sType =
3424         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT;
3425 
3426     mVariablePointersFeatures = {};
3427     mVariablePointersFeatures.sType =
3428         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES_KHR;
3429 
3430     // Rounding and denormal caps from VK_KHR_float_controls_properties
3431     mFloatControlProperties       = {};
3432     mFloatControlProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES;
3433 
3434     mImageCompressionControlFeatures = {};
3435     mImageCompressionControlFeatures.sType =
3436         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_COMPRESSION_CONTROL_FEATURES_EXT;
3437 
3438     mImageCompressionControlSwapchainFeatures = {};
3439     mImageCompressionControlSwapchainFeatures.sType =
3440         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_FEATURES_EXT;
3441 
3442     mTextureCompressionASTCHDRFeatures = {};
3443     mTextureCompressionASTCHDRFeatures.sType =
3444         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_HDR_FEATURES;
3445 
3446     mUniformBufferStandardLayoutFeatures = {};
3447     mUniformBufferStandardLayoutFeatures.sType =
3448         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES;
3449 
3450 #if defined(ANGLE_PLATFORM_ANDROID)
3451     mExternalFormatResolveFeatures = {};
3452     mExternalFormatResolveFeatures.sType =
3453         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FORMAT_RESOLVE_FEATURES_ANDROID;
3454 
3455     mExternalFormatResolveProperties = {};
3456     mExternalFormatResolveProperties.sType =
3457         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FORMAT_RESOLVE_PROPERTIES_ANDROID;
3458 #endif
3459 
3460     // Query features and properties.
3461     VkPhysicalDeviceFeatures2KHR deviceFeatures = {};
3462     deviceFeatures.sType                        = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
3463 
3464     VkPhysicalDeviceProperties2 deviceProperties = {};
3465     deviceProperties.sType                       = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
3466 
3467     appendDeviceExtensionFeaturesNotPromoted(deviceExtensionNames, &deviceFeatures,
3468                                              &deviceProperties);
3469     appendDeviceExtensionFeaturesPromotedTo11(deviceExtensionNames, &deviceFeatures,
3470                                               &deviceProperties);
3471     appendDeviceExtensionFeaturesPromotedTo12(deviceExtensionNames, &deviceFeatures,
3472                                               &deviceProperties);
3473     appendDeviceExtensionFeaturesPromotedTo13(deviceExtensionNames, &deviceFeatures,
3474                                               &deviceProperties);
3475 
3476     vkGetPhysicalDeviceFeatures2(mPhysicalDevice, &deviceFeatures);
3477     vkGetPhysicalDeviceProperties2(mPhysicalDevice, &deviceProperties);
3478 
3479     // Clean up pNext chains
3480     mLineRasterizationFeatures.pNext                  = nullptr;
3481     mMemoryReportFeatures.pNext                       = nullptr;
3482     mProvokingVertexFeatures.pNext                    = nullptr;
3483     mVertexAttributeDivisorFeatures.pNext             = nullptr;
3484     mVertexAttributeDivisorProperties.pNext           = nullptr;
3485     mTransformFeedbackFeatures.pNext                  = nullptr;
3486     mIndexTypeUint8Features.pNext                     = nullptr;
3487     mSubgroupProperties.pNext                         = nullptr;
3488     mSubgroupExtendedTypesFeatures.pNext              = nullptr;
3489     mCustomBorderColorFeatures.pNext                  = nullptr;
3490     mShaderFloat16Int8Features.pNext                  = nullptr;
3491     mDepthStencilResolveProperties.pNext              = nullptr;
3492     mMultisampledRenderToSingleSampledFeatures.pNext  = nullptr;
3493     mImage2dViewOf3dFeatures.pNext                    = nullptr;
3494     mMultiviewFeatures.pNext                          = nullptr;
3495     mMultiviewProperties.pNext                        = nullptr;
3496     mDriverProperties.pNext                           = nullptr;
3497     mSamplerYcbcrConversionFeatures.pNext             = nullptr;
3498     mProtectedMemoryFeatures.pNext                    = nullptr;
3499     mHostQueryResetFeatures.pNext                     = nullptr;
3500     mDepthClampZeroOneFeatures.pNext                  = nullptr;
3501     mDepthClipControlFeatures.pNext                   = nullptr;
3502     mPrimitivesGeneratedQueryFeatures.pNext           = nullptr;
3503     mPrimitiveTopologyListRestartFeatures.pNext       = nullptr;
3504     mExtendedDynamicStateFeatures.pNext               = nullptr;
3505     mExtendedDynamicState2Features.pNext              = nullptr;
3506     mGraphicsPipelineLibraryFeatures.pNext            = nullptr;
3507     mGraphicsPipelineLibraryProperties.pNext          = nullptr;
3508     mVertexInputDynamicStateFeatures.pNext            = nullptr;
3509     mDynamicRenderingFeatures.pNext                   = nullptr;
3510     mDynamicRenderingLocalReadFeatures.pNext          = nullptr;
3511     mFragmentShadingRateFeatures.pNext                = nullptr;
3512     mFragmentShaderInterlockFeatures.pNext            = nullptr;
3513     mImagelessFramebufferFeatures.pNext               = nullptr;
3514     mPipelineRobustnessFeatures.pNext                 = nullptr;
3515     mPipelineProtectedAccessFeatures.pNext            = nullptr;
3516     mRasterizationOrderAttachmentAccessFeatures.pNext = nullptr;
3517     mShaderAtomicFloatFeatures.pNext                  = nullptr;
3518     mMaintenance5Features.pNext                       = nullptr;
3519     mSwapchainMaintenance1Features.pNext              = nullptr;
3520     mDitheringFeatures.pNext                          = nullptr;
3521     mDrmProperties.pNext                              = nullptr;
3522     mTimelineSemaphoreFeatures.pNext                  = nullptr;
3523     mHostImageCopyFeatures.pNext                      = nullptr;
3524     mHostImageCopyProperties.pNext                    = nullptr;
3525     m8BitStorageFeatures.pNext                        = nullptr;
3526     m16BitStorageFeatures.pNext                       = nullptr;
3527     mSynchronization2Features.pNext                   = nullptr;
3528     mBlendOperationAdvancedFeatures.pNext             = nullptr;
3529     mVariablePointersFeatures.pNext                   = nullptr;
3530     mFloatControlProperties.pNext                     = nullptr;
3531     mImageCompressionControlFeatures.pNext            = nullptr;
3532     mImageCompressionControlSwapchainFeatures.pNext   = nullptr;
3533     mTextureCompressionASTCHDRFeatures.pNext          = nullptr;
3534     mUniformBufferStandardLayoutFeatures.pNext        = nullptr;
3535     mMaintenance3Properties.pNext                     = nullptr;
3536     mFaultFeatures.pNext                              = nullptr;
3537 #if defined(ANGLE_PLATFORM_ANDROID)
3538     mExternalFormatResolveFeatures.pNext   = nullptr;
3539     mExternalFormatResolveProperties.pNext = nullptr;
3540 #endif
3541 }
3542 
3543 // See comment above appendDeviceExtensionFeaturesNotPromoted.  Additional extensions are enabled
3544 // here which don't have feature structs:
3545 //
3546 // - VK_KHR_shared_presentable_image
3547 // - VK_EXT_device_memory_report
3548 // - VK_EXT_memory_budget
3549 // - VK_KHR_incremental_present
3550 // - VK_EXT_queue_family_foreign
3551 // - VK_ANDROID_external_memory_android_hardware_buffer
3552 // - VK_KHR_external_memory_fd
3553 // - VK_KHR_external_memory_fuchsia
3554 // - VK_KHR_external_semaphore_fd
3555 // - VK_KHR_external_fence_fd
3556 // - VK_FUCHSIA_external_semaphore
3557 // - VK_EXT_shader_stencil_export
3558 // - VK_EXT_load_store_op_none
3559 // - VK_QCOM_render_pass_store_ops
3560 // - VK_GOOGLE_display_timing
3561 // - VK_EXT_external_memory_dma_buf
3562 // - VK_EXT_image_drm_format_modifier
3563 // - VK_EXT_blend_operation_advanced
3564 // - VK_EXT_full_screen_exclusive
3565 // - VK_EXT_image_compression_control
3566 // - VK_EXT_image_compression_control_swapchain
3567 //
enableDeviceExtensionsNotPromoted(const vk::ExtensionNameList & deviceExtensionNames)3568 void Renderer::enableDeviceExtensionsNotPromoted(const vk::ExtensionNameList &deviceExtensionNames)
3569 {
3570     if (mFeatures.supportsSharedPresentableImageExtension.enabled)
3571     {
3572         mEnabledDeviceExtensions.push_back(VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME);
3573     }
3574 
3575     if (mFeatures.supportsDepthClampZeroOne.enabled)
3576     {
3577         mEnabledDeviceExtensions.push_back(VK_EXT_DEPTH_CLAMP_ZERO_ONE_EXTENSION_NAME);
3578         vk::AddToPNextChain(&mEnabledFeatures, &mDepthClampZeroOneFeatures);
3579     }
3580 
3581     if (mFeatures.supportsMemoryBudget.enabled)
3582     {
3583         mEnabledDeviceExtensions.push_back(VK_EXT_MEMORY_BUDGET_EXTENSION_NAME);
3584     }
3585 
3586     if (mFeatures.supportsIncrementalPresent.enabled)
3587     {
3588         mEnabledDeviceExtensions.push_back(VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME);
3589     }
3590 
3591 #if defined(ANGLE_PLATFORM_ANDROID)
3592     if (mFeatures.supportsAndroidHardwareBuffer.enabled)
3593     {
3594         mEnabledDeviceExtensions.push_back(VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME);
3595         mEnabledDeviceExtensions.push_back(
3596             VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME);
3597     }
3598 #else
3599     ASSERT(!mFeatures.supportsAndroidHardwareBuffer.enabled);
3600 #endif
3601 
3602     if (mFeatures.supportsExternalMemoryFd.enabled)
3603     {
3604         mEnabledDeviceExtensions.push_back(VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME);
3605     }
3606 
3607     if (mFeatures.supportsExternalMemoryFuchsia.enabled)
3608     {
3609         mEnabledDeviceExtensions.push_back(VK_FUCHSIA_EXTERNAL_MEMORY_EXTENSION_NAME);
3610     }
3611 
3612     if (mFeatures.supportsExternalSemaphoreFd.enabled)
3613     {
3614         mEnabledDeviceExtensions.push_back(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME);
3615     }
3616 
3617     if (mFeatures.supportsExternalFenceFd.enabled)
3618     {
3619         mEnabledDeviceExtensions.push_back(VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME);
3620     }
3621 
3622     if (mFeatures.supportsExternalSemaphoreFuchsia.enabled)
3623     {
3624         mEnabledDeviceExtensions.push_back(VK_FUCHSIA_EXTERNAL_SEMAPHORE_EXTENSION_NAME);
3625     }
3626 
3627     if (mFeatures.supportsShaderStencilExport.enabled)
3628     {
3629         mEnabledDeviceExtensions.push_back(VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME);
3630     }
3631 
3632     if (mFeatures.supportsRenderPassLoadStoreOpNone.enabled)
3633     {
3634         mEnabledDeviceExtensions.push_back(VK_EXT_LOAD_STORE_OP_NONE_EXTENSION_NAME);
3635     }
3636     else if (mFeatures.supportsRenderPassStoreOpNone.enabled)
3637     {
3638         mEnabledDeviceExtensions.push_back(VK_QCOM_RENDER_PASS_STORE_OPS_EXTENSION_NAME);
3639     }
3640 
3641     if (mFeatures.supportsTimestampSurfaceAttribute.enabled)
3642     {
3643         mEnabledDeviceExtensions.push_back(VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME);
3644     }
3645 
3646     if (mFeatures.bresenhamLineRasterization.enabled)
3647     {
3648         mEnabledDeviceExtensions.push_back(VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME);
3649         vk::AddToPNextChain(&mEnabledFeatures, &mLineRasterizationFeatures);
3650     }
3651 
3652     if (mFeatures.provokingVertex.enabled)
3653     {
3654         mEnabledDeviceExtensions.push_back(VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME);
3655         vk::AddToPNextChain(&mEnabledFeatures, &mProvokingVertexFeatures);
3656     }
3657 
3658     if (mVertexAttributeDivisorFeatures.vertexAttributeInstanceRateDivisor)
3659     {
3660         mEnabledDeviceExtensions.push_back(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME);
3661         vk::AddToPNextChain(&mEnabledFeatures, &mVertexAttributeDivisorFeatures);
3662 
3663         // We only store 8 bit divisor in GraphicsPipelineDesc so capping value & we emulate if
3664         // exceeded
3665         mMaxVertexAttribDivisor =
3666             std::min(mVertexAttributeDivisorProperties.maxVertexAttribDivisor,
3667                      static_cast<uint32_t>(std::numeric_limits<uint8_t>::max()));
3668     }
3669 
3670     if (mFeatures.supportsTransformFeedbackExtension.enabled)
3671     {
3672         mEnabledDeviceExtensions.push_back(VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME);
3673         vk::AddToPNextChain(&mEnabledFeatures, &mTransformFeedbackFeatures);
3674     }
3675 
3676     if (mFeatures.supportsCustomBorderColor.enabled)
3677     {
3678         mEnabledDeviceExtensions.push_back(VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME);
3679         vk::AddToPNextChain(&mEnabledFeatures, &mCustomBorderColorFeatures);
3680     }
3681 
3682     if (mFeatures.supportsIndexTypeUint8.enabled)
3683     {
3684         mEnabledDeviceExtensions.push_back(VK_EXT_INDEX_TYPE_UINT8_EXTENSION_NAME);
3685         vk::AddToPNextChain(&mEnabledFeatures, &mIndexTypeUint8Features);
3686     }
3687 
3688     if (mFeatures.supportsMultisampledRenderToSingleSampled.enabled)
3689     {
3690         mEnabledDeviceExtensions.push_back(
3691             VK_EXT_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_EXTENSION_NAME);
3692         vk::AddToPNextChain(&mEnabledFeatures, &mMultisampledRenderToSingleSampledFeatures);
3693     }
3694 
3695     if (mFeatures.logMemoryReportCallbacks.enabled || mFeatures.logMemoryReportStats.enabled)
3696     {
3697         ASSERT(mMemoryReportFeatures.deviceMemoryReport);
3698         mEnabledDeviceExtensions.push_back(VK_EXT_DEVICE_MEMORY_REPORT_EXTENSION_NAME);
3699         vk::AddToPNextChain(&mEnabledFeatures, &mMemoryReportFeatures);
3700     }
3701 
3702     if (mFeatures.supportsExternalMemoryDmaBufAndModifiers.enabled)
3703     {
3704         mEnabledDeviceExtensions.push_back(VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME);
3705         mEnabledDeviceExtensions.push_back(VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME);
3706     }
3707 
3708     if (mFeatures.supportsExternalMemoryHost.enabled)
3709     {
3710         mEnabledDeviceExtensions.push_back(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME);
3711     }
3712 
3713     if (mFeatures.supportsDepthClipControl.enabled)
3714     {
3715         mEnabledDeviceExtensions.push_back(VK_EXT_DEPTH_CLIP_CONTROL_EXTENSION_NAME);
3716         vk::AddToPNextChain(&mEnabledFeatures, &mDepthClipControlFeatures);
3717     }
3718 
3719     if (mFeatures.supportsPrimitivesGeneratedQuery.enabled)
3720     {
3721         mEnabledDeviceExtensions.push_back(VK_EXT_PRIMITIVES_GENERATED_QUERY_EXTENSION_NAME);
3722         vk::AddToPNextChain(&mEnabledFeatures, &mPrimitivesGeneratedQueryFeatures);
3723     }
3724 
3725     if (mFeatures.supportsPrimitiveTopologyListRestart.enabled)
3726     {
3727         mEnabledDeviceExtensions.push_back(VK_EXT_PRIMITIVE_TOPOLOGY_LIST_RESTART_EXTENSION_NAME);
3728         vk::AddToPNextChain(&mEnabledFeatures, &mPrimitiveTopologyListRestartFeatures);
3729     }
3730 
3731     if (mFeatures.supportsBlendOperationAdvanced.enabled)
3732     {
3733         mEnabledDeviceExtensions.push_back(VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME);
3734         vk::AddToPNextChain(&mEnabledFeatures, &mBlendOperationAdvancedFeatures);
3735     }
3736 
3737     if (mFeatures.supportsGraphicsPipelineLibrary.enabled)
3738     {
3739         // VK_EXT_graphics_pipeline_library requires VK_KHR_pipeline_library
3740         ASSERT(ExtensionFound(VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME, deviceExtensionNames));
3741         mEnabledDeviceExtensions.push_back(VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME);
3742 
3743         mEnabledDeviceExtensions.push_back(VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME);
3744         vk::AddToPNextChain(&mEnabledFeatures, &mGraphicsPipelineLibraryFeatures);
3745     }
3746 
3747     if (mFeatures.supportsFragmentShadingRate.enabled)
3748     {
3749         mEnabledDeviceExtensions.push_back(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME);
3750         vk::AddToPNextChain(&mEnabledFeatures, &mFragmentShadingRateFeatures);
3751     }
3752 
3753     if (mFeatures.supportsFragmentShaderPixelInterlock.enabled)
3754     {
3755         mEnabledDeviceExtensions.push_back(VK_EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME);
3756         vk::AddToPNextChain(&mEnabledFeatures, &mFragmentShaderInterlockFeatures);
3757     }
3758 
3759     if (mFeatures.supportsPipelineRobustness.enabled)
3760     {
3761         mEnabledDeviceExtensions.push_back(VK_EXT_PIPELINE_ROBUSTNESS_EXTENSION_NAME);
3762         vk::AddToPNextChain(&mEnabledFeatures, &mPipelineRobustnessFeatures);
3763     }
3764 
3765     if (mFeatures.supportsPipelineProtectedAccess.enabled)
3766     {
3767         mEnabledDeviceExtensions.push_back(VK_EXT_PIPELINE_PROTECTED_ACCESS_EXTENSION_NAME);
3768         vk::AddToPNextChain(&mEnabledFeatures, &mPipelineProtectedAccessFeatures);
3769     }
3770 
3771     if (mFeatures.supportsRasterizationOrderAttachmentAccess.enabled)
3772     {
3773         if (ExtensionFound(VK_EXT_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_EXTENSION_NAME,
3774                            deviceExtensionNames))
3775         {
3776             mEnabledDeviceExtensions.push_back(
3777                 VK_EXT_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_EXTENSION_NAME);
3778         }
3779         else
3780         {
3781             ASSERT(ExtensionFound(VK_ARM_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_EXTENSION_NAME,
3782                                   deviceExtensionNames));
3783             mEnabledDeviceExtensions.push_back(
3784                 VK_ARM_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_EXTENSION_NAME);
3785         }
3786         vk::AddToPNextChain(&mEnabledFeatures, &mRasterizationOrderAttachmentAccessFeatures);
3787     }
3788 
3789     if (!mFeatures.emulateR32fImageAtomicExchange.enabled)
3790     {
3791         ASSERT(ExtensionFound(VK_EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME, deviceExtensionNames));
3792         mEnabledDeviceExtensions.push_back(VK_EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME);
3793         vk::AddToPNextChain(&mEnabledFeatures, &mShaderAtomicFloatFeatures);
3794     }
3795 
3796     if (mFeatures.supportsImage2dViewOf3d.enabled)
3797     {
3798         mEnabledDeviceExtensions.push_back(VK_EXT_IMAGE_2D_VIEW_OF_3D_EXTENSION_NAME);
3799         vk::AddToPNextChain(&mEnabledFeatures, &mImage2dViewOf3dFeatures);
3800     }
3801 
3802     if (mFeatures.supportsSwapchainMaintenance1.enabled)
3803     {
3804         mEnabledDeviceExtensions.push_back(VK_EXT_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME);
3805         vk::AddToPNextChain(&mEnabledFeatures, &mSwapchainMaintenance1Features);
3806     }
3807 
3808     if (mFeatures.supportsLegacyDithering.enabled)
3809     {
3810         mEnabledDeviceExtensions.push_back(VK_EXT_LEGACY_DITHERING_EXTENSION_NAME);
3811         vk::AddToPNextChain(&mEnabledFeatures, &mDitheringFeatures);
3812     }
3813 
3814     if (mFeatures.supportsFormatFeatureFlags2.enabled)
3815     {
3816         mEnabledDeviceExtensions.push_back(VK_KHR_FORMAT_FEATURE_FLAGS_2_EXTENSION_NAME);
3817     }
3818 
3819     if (mFeatures.supportsHostImageCopy.enabled)
3820     {
3821         // VK_EXT_host_image_copy requires VK_KHR_copy_commands2 and VK_KHR_format_feature_flags2.
3822         // VK_KHR_format_feature_flags2 is enabled separately.
3823         ASSERT(ExtensionFound(VK_KHR_COPY_COMMANDS_2_EXTENSION_NAME, deviceExtensionNames));
3824         ASSERT(ExtensionFound(VK_KHR_FORMAT_FEATURE_FLAGS_2_EXTENSION_NAME, deviceExtensionNames));
3825         mEnabledDeviceExtensions.push_back(VK_KHR_COPY_COMMANDS_2_EXTENSION_NAME);
3826 
3827         mEnabledDeviceExtensions.push_back(VK_EXT_HOST_IMAGE_COPY_EXTENSION_NAME);
3828         vk::AddToPNextChain(&mEnabledFeatures, &mHostImageCopyFeatures);
3829     }
3830 
3831     if (getFeatures().supportsVertexInputDynamicState.enabled)
3832     {
3833         mEnabledDeviceExtensions.push_back(VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
3834         vk::AddToPNextChain(&mEnabledFeatures, &mVertexInputDynamicStateFeatures);
3835     }
3836 
3837     if (getFeatures().supportsDynamicRenderingLocalRead.enabled)
3838     {
3839         mEnabledDeviceExtensions.push_back(VK_KHR_DYNAMIC_RENDERING_LOCAL_READ_EXTENSION_NAME);
3840         vk::AddToPNextChain(&mEnabledFeatures, &mDynamicRenderingLocalReadFeatures);
3841     }
3842 
3843     if (getFeatures().supportsImageCompressionControl.enabled)
3844     {
3845         mEnabledDeviceExtensions.push_back(VK_EXT_IMAGE_COMPRESSION_CONTROL_EXTENSION_NAME);
3846         vk::AddToPNextChain(&mEnabledFeatures, &mImageCompressionControlFeatures);
3847     }
3848 
3849     if (getFeatures().supportsImageCompressionControlSwapchain.enabled)
3850     {
3851         mEnabledDeviceExtensions.push_back(
3852             VK_EXT_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_EXTENSION_NAME);
3853         vk::AddToPNextChain(&mEnabledFeatures, &mImageCompressionControlSwapchainFeatures);
3854     }
3855 
3856     if (mFeatures.supportsSwapchainMutableFormat.enabled)
3857     {
3858         mEnabledDeviceExtensions.push_back(VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_EXTENSION_NAME);
3859     }
3860 
3861     if (mFeatures.supportsDeviceFault.enabled)
3862     {
3863         mEnabledDeviceExtensions.push_back(VK_EXT_DEVICE_FAULT_EXTENSION_NAME);
3864         vk::AddToPNextChain(&mEnabledFeatures, &mFaultFeatures);
3865     }
3866 
3867 #if defined(ANGLE_PLATFORM_WINDOWS)
3868     // We only need the VK_EXT_full_screen_exclusive extension if we are opting
3869     // out of it via VK_FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT (i.e. working
3870     // around driver bugs).
3871     if (getFeatures().supportsFullScreenExclusive.enabled &&
3872         getFeatures().forceDisableFullScreenExclusive.enabled)
3873     {
3874         mEnabledDeviceExtensions.push_back(VK_EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME);
3875     }
3876 #endif
3877 
3878 #if defined(ANGLE_PLATFORM_ANDROID)
3879     if (mFeatures.supportsExternalFormatResolve.enabled)
3880     {
3881         mEnabledDeviceExtensions.push_back(VK_ANDROID_EXTERNAL_FORMAT_RESOLVE_EXTENSION_NAME);
3882         vk::AddToPNextChain(&mEnabledFeatures, &mExternalFormatResolveFeatures);
3883     }
3884 #endif
3885 }
3886 
3887 // See comment above appendDeviceExtensionFeaturesPromotedTo11.  Additional extensions are enabled
3888 // here which don't have feature structs:
3889 //
3890 // - VK_KHR_get_memory_requirements2
3891 // - VK_KHR_bind_memory2
3892 // - VK_KHR_maintenance1
3893 // - VK_KHR_external_memory
3894 // - VK_KHR_external_semaphore
3895 // - VK_KHR_external_fence
3896 //
enableDeviceExtensionsPromotedTo11(const vk::ExtensionNameList & deviceExtensionNames)3897 void Renderer::enableDeviceExtensionsPromotedTo11(const vk::ExtensionNameList &deviceExtensionNames)
3898 {
3899     // OVR_multiview disallows multiview with geometry and tessellation, so don't request these
3900     // features.
3901     mMultiviewFeatures.multiviewGeometryShader     = VK_FALSE;
3902     mMultiviewFeatures.multiviewTessellationShader = VK_FALSE;
3903 
3904     if (mFeatures.supportsMultiview.enabled)
3905     {
3906         vk::AddToPNextChain(&mEnabledFeatures, &mMultiviewFeatures);
3907     }
3908 
3909     if (mFeatures.supportsYUVSamplerConversion.enabled)
3910     {
3911         vk::AddToPNextChain(&mEnabledFeatures, &mSamplerYcbcrConversionFeatures);
3912     }
3913 
3914     if (mFeatures.supportsProtectedMemory.enabled)
3915     {
3916         vk::AddToPNextChain(&mEnabledFeatures, &mProtectedMemoryFeatures);
3917     }
3918 
3919     if (mFeatures.supports16BitStorageBuffer.enabled ||
3920         mFeatures.supports16BitUniformAndStorageBuffer.enabled ||
3921         mFeatures.supports16BitPushConstant.enabled || mFeatures.supports16BitInputOutput.enabled)
3922     {
3923         vk::AddToPNextChain(&mEnabledFeatures, &m16BitStorageFeatures);
3924     }
3925 
3926     vk::AddToPNextChain(&mEnabledFeatures, &mVariablePointersFeatures);
3927 }
3928 
3929 // See comment above appendDeviceExtensionFeaturesPromotedTo12.  Additional extensions are enabled
3930 // here which don't have feature structs:
3931 //
3932 // - VK_KHR_create_renderpass2
3933 // - VK_KHR_image_format_list
3934 // - VK_KHR_shader_float_controls
3935 // - VK_KHR_spirv_1_4
3936 // - VK_KHR_sampler_mirror_clamp_to_edge
3937 // - VK_KHR_depth_stencil_resolve
3938 //
enableDeviceExtensionsPromotedTo12(const vk::ExtensionNameList & deviceExtensionNames)3939 void Renderer::enableDeviceExtensionsPromotedTo12(const vk::ExtensionNameList &deviceExtensionNames)
3940 {
3941     if (mFeatures.supportsRenderpass2.enabled)
3942     {
3943         mEnabledDeviceExtensions.push_back(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
3944     }
3945 
3946     if (mFeatures.supportsImageFormatList.enabled)
3947     {
3948         mEnabledDeviceExtensions.push_back(VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME);
3949     }
3950 
3951     // There are several FP related modes defined as properties from
3952     // VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION, and there could be a scenario where the extension is
3953     // supported but none of the modes are supported. Here we enable the extension if it is found.
3954     if (ExtensionFound(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME, deviceExtensionNames))
3955     {
3956         mEnabledDeviceExtensions.push_back(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME);
3957     }
3958 
3959     if (mFeatures.supportsSPIRV14.enabled)
3960     {
3961         mEnabledDeviceExtensions.push_back(VK_KHR_SPIRV_1_4_EXTENSION_NAME);
3962     }
3963 
3964     if (mFeatures.supportsSamplerMirrorClampToEdge.enabled)
3965     {
3966         mEnabledDeviceExtensions.push_back(VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME);
3967     }
3968 
3969     if (mFeatures.supportsDepthStencilResolve.enabled)
3970     {
3971         mEnabledDeviceExtensions.push_back(VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME);
3972     }
3973 
3974     if (mFeatures.allowGenerateMipmapWithCompute.enabled)
3975     {
3976         mEnabledDeviceExtensions.push_back(VK_KHR_SHADER_SUBGROUP_EXTENDED_TYPES_EXTENSION_NAME);
3977         vk::AddToPNextChain(&mEnabledFeatures, &mSubgroupExtendedTypesFeatures);
3978     }
3979 
3980     if (mFeatures.supportsShaderFloat16.enabled)
3981     {
3982         mEnabledDeviceExtensions.push_back(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME);
3983         vk::AddToPNextChain(&mEnabledFeatures, &mShaderFloat16Int8Features);
3984     }
3985 
3986     if (mFeatures.supportsHostQueryReset.enabled)
3987     {
3988         mEnabledDeviceExtensions.push_back(VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME);
3989         vk::AddToPNextChain(&mEnabledFeatures, &mHostQueryResetFeatures);
3990     }
3991 
3992     if (mFeatures.supportsImagelessFramebuffer.enabled)
3993     {
3994         mEnabledDeviceExtensions.push_back(VK_KHR_IMAGELESS_FRAMEBUFFER_EXTENSION_NAME);
3995         vk::AddToPNextChain(&mEnabledFeatures, &mImagelessFramebufferFeatures);
3996     }
3997 
3998     if (mFeatures.supportsTimelineSemaphore.enabled)
3999     {
4000         mEnabledDeviceExtensions.push_back(VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME);
4001         vk::AddToPNextChain(&mEnabledFeatures, &mTimelineSemaphoreFeatures);
4002     }
4003 
4004     if (mFeatures.supports8BitStorageBuffer.enabled ||
4005         mFeatures.supports8BitUniformAndStorageBuffer.enabled ||
4006         mFeatures.supports8BitPushConstant.enabled)
4007     {
4008         mEnabledDeviceExtensions.push_back(VK_KHR_8BIT_STORAGE_EXTENSION_NAME);
4009         vk::AddToPNextChain(&mEnabledFeatures, &m8BitStorageFeatures);
4010     }
4011     if (mFeatures.supportsUniformBufferStandardLayout.enabled)
4012     {
4013         mEnabledDeviceExtensions.push_back(VK_KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_EXTENSION_NAME);
4014         vk::AddToPNextChain(&mEnabledFeatures, &mUniformBufferStandardLayoutFeatures);
4015     }
4016 }
4017 
4018 // See comment above appendDeviceExtensionFeaturesPromotedTo13.
enableDeviceExtensionsPromotedTo13(const vk::ExtensionNameList & deviceExtensionNames)4019 void Renderer::enableDeviceExtensionsPromotedTo13(const vk::ExtensionNameList &deviceExtensionNames)
4020 {
4021     if (mFeatures.supportsPipelineCreationFeedback.enabled)
4022     {
4023         mEnabledDeviceExtensions.push_back(VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME);
4024     }
4025 
4026     if (mFeatures.supportsExtendedDynamicState.enabled)
4027     {
4028         mEnabledDeviceExtensions.push_back(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
4029         vk::AddToPNextChain(&mEnabledFeatures, &mExtendedDynamicStateFeatures);
4030     }
4031 
4032     if (mFeatures.supportsExtendedDynamicState2.enabled)
4033     {
4034         mEnabledDeviceExtensions.push_back(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
4035         vk::AddToPNextChain(&mEnabledFeatures, &mExtendedDynamicState2Features);
4036     }
4037 
4038     if (mFeatures.supportsSynchronization2.enabled)
4039     {
4040         mEnabledDeviceExtensions.push_back(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
4041         vk::AddToPNextChain(&mEnabledFeatures, &mSynchronization2Features);
4042     }
4043 
4044     if (getFeatures().supportsDynamicRendering.enabled)
4045     {
4046         mEnabledDeviceExtensions.push_back(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME);
4047         vk::AddToPNextChain(&mEnabledFeatures, &mDynamicRenderingFeatures);
4048     }
4049 
4050     if (getFeatures().supportsMaintenance5.enabled)
4051     {
4052         mEnabledDeviceExtensions.push_back(VK_KHR_MAINTENANCE_5_EXTENSION_NAME);
4053         vk::AddToPNextChain(&mEnabledFeatures, &mMaintenance5Features);
4054     }
4055 
4056     if (getFeatures().supportsTextureCompressionAstcHdr.enabled)
4057     {
4058         mEnabledDeviceExtensions.push_back(VK_EXT_TEXTURE_COMPRESSION_ASTC_HDR_EXTENSION_NAME);
4059         vk::AddToPNextChain(&mEnabledFeatures, &mTextureCompressionASTCHDRFeatures);
4060     }
4061 }
4062 
enableDeviceExtensions(vk::ErrorContext * context,const angle::FeatureOverrides & featureOverrides,UseVulkanSwapchain useVulkanSwapchain,angle::NativeWindowSystem nativeWindowSystem)4063 angle::Result Renderer::enableDeviceExtensions(vk::ErrorContext *context,
4064                                                const angle::FeatureOverrides &featureOverrides,
4065                                                UseVulkanSwapchain useVulkanSwapchain,
4066                                                angle::NativeWindowSystem nativeWindowSystem)
4067 {
4068     // Enumerate device extensions that are provided by the vulkan
4069     // implementation and implicit layers.
4070     uint32_t deviceExtensionCount = 0;
4071     ANGLE_VK_TRY(context, vkEnumerateDeviceExtensionProperties(mPhysicalDevice, nullptr,
4072                                                                &deviceExtensionCount, nullptr));
4073 
4074     // Work-around a race condition in the Android platform during Android start-up, that can cause
4075     // the second call to vkEnumerateDeviceExtensionProperties to have an additional extension.  In
4076     // that case, the second call will return VK_INCOMPLETE.  To work-around that, add 1 to
4077     // deviceExtensionCount and ask for one more extension property than the first call said there
4078     // were.  See: http://anglebug.com/42265209 and internal-to-Google bug: b/206733351.
4079     deviceExtensionCount++;
4080     std::vector<VkExtensionProperties> deviceExtensionProps(deviceExtensionCount);
4081     ANGLE_VK_TRY(context,
4082                  vkEnumerateDeviceExtensionProperties(
4083                      mPhysicalDevice, nullptr, &deviceExtensionCount, deviceExtensionProps.data()));
4084     // In case fewer items were returned than requested, resize deviceExtensionProps to the number
4085     // of extensions returned (i.e. deviceExtensionCount).  See: b/208937840
4086     deviceExtensionProps.resize(deviceExtensionCount);
4087 
4088     // Enumerate device extensions that are provided by explicit layers.
4089     for (const char *layerName : mEnabledDeviceLayerNames)
4090     {
4091         uint32_t previousExtensionCount    = static_cast<uint32_t>(deviceExtensionProps.size());
4092         uint32_t deviceLayerExtensionCount = 0;
4093         ANGLE_VK_TRY(context, vkEnumerateDeviceExtensionProperties(
4094                                   mPhysicalDevice, layerName, &deviceLayerExtensionCount, nullptr));
4095         deviceExtensionProps.resize(previousExtensionCount + deviceLayerExtensionCount);
4096         ANGLE_VK_TRY(context, vkEnumerateDeviceExtensionProperties(
4097                                   mPhysicalDevice, layerName, &deviceLayerExtensionCount,
4098                                   deviceExtensionProps.data() + previousExtensionCount));
4099         // In case fewer items were returned than requested, resize deviceExtensionProps to the
4100         // number of extensions returned (i.e. deviceLayerExtensionCount).
4101         deviceExtensionProps.resize(previousExtensionCount + deviceLayerExtensionCount);
4102     }
4103 
4104     // Get the list of device extensions that are available.
4105     vk::ExtensionNameList deviceExtensionNames;
4106     if (!deviceExtensionProps.empty())
4107     {
4108         ASSERT(deviceExtensionNames.size() <= deviceExtensionProps.size());
4109         for (const VkExtensionProperties &prop : deviceExtensionProps)
4110         {
4111             deviceExtensionNames.push_back(prop.extensionName);
4112 
4113             if (strcmp(prop.extensionName, VK_EXT_LEGACY_DITHERING_EXTENSION_NAME) == 0)
4114             {
4115                 mLegacyDitheringVersion = prop.specVersion;
4116             }
4117         }
4118         std::sort(deviceExtensionNames.begin(), deviceExtensionNames.end(), StrLess);
4119     }
4120 
4121     if (useVulkanSwapchain == UseVulkanSwapchain::Yes)
4122     {
4123         mEnabledDeviceExtensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
4124     }
4125 
4126     // Query extensions and their features.
4127     queryDeviceExtensionFeatures(deviceExtensionNames);
4128 
4129     // Initialize features and workarounds.
4130     initFeatures(deviceExtensionNames, featureOverrides, useVulkanSwapchain, nativeWindowSystem);
4131 
4132     // App based feature overrides.
4133     appBasedFeatureOverrides(deviceExtensionNames);
4134 
4135     // App based feature overrides for Desktop devices.
4136     // TODO (b/372694741): Remove once run-time control is supported.
4137     appBasedFeatureOverridesAndroidDesktop(deviceExtensionNames);
4138 
4139     // Enable extensions that could be used
4140     enableDeviceExtensionsNotPromoted(deviceExtensionNames);
4141     enableDeviceExtensionsPromotedTo11(deviceExtensionNames);
4142     enableDeviceExtensionsPromotedTo12(deviceExtensionNames);
4143     enableDeviceExtensionsPromotedTo13(deviceExtensionNames);
4144 
4145     std::sort(mEnabledDeviceExtensions.begin(), mEnabledDeviceExtensions.end(), StrLess);
4146     ANGLE_VK_TRY(context, VerifyExtensionsPresent(deviceExtensionNames, mEnabledDeviceExtensions));
4147 
4148     return angle::Result::Continue;
4149 }
4150 
initDeviceExtensionEntryPoints()4151 void Renderer::initDeviceExtensionEntryPoints()
4152 {
4153 #if !defined(ANGLE_SHARED_LIBVULKAN)
4154     // Device entry points
4155     if (mFeatures.supportsTransformFeedbackExtension.enabled)
4156     {
4157         InitTransformFeedbackEXTFunctions(mDevice);
4158     }
4159     if (getFeatures().supportsLogicOpDynamicState.enabled)
4160     {
4161         // VK_EXT_extended_dynamic_state2 is only partially core in Vulkan 1.3.  If the logicOp
4162         // dynamic state (only from the extension) is used, need to load the entry points from the
4163         // extension
4164         InitExtendedDynamicState2EXTFunctions(mDevice);
4165     }
4166     if (mFeatures.supportsFragmentShadingRate.enabled)
4167     {
4168         InitFragmentShadingRateKHRDeviceFunction(mDevice);
4169     }
4170     if (mFeatures.supportsTimestampSurfaceAttribute.enabled)
4171     {
4172         InitGetPastPresentationTimingGoogleFunction(mDevice);
4173     }
4174     if (mFeatures.supportsHostImageCopy.enabled)
4175     {
4176         InitHostImageCopyFunctions(mDevice);
4177     }
4178     if (mFeatures.supportsVertexInputDynamicState.enabled)
4179     {
4180         InitVertexInputDynamicStateEXTFunctions(mDevice);
4181     }
4182     if (mFeatures.supportsDynamicRenderingLocalRead.enabled)
4183     {
4184         InitDynamicRenderingLocalReadFunctions(mDevice);
4185     }
4186     if (mFeatures.supportsExternalSemaphoreFd.enabled ||
4187         mFeatures.supportsExternalSemaphoreFuchsia.enabled)
4188     {
4189         InitExternalSemaphoreFdFunctions(mDevice);
4190     }
4191 
4192     if (mFeatures.supportsExternalFenceFd.enabled)
4193     {
4194         InitExternalFenceFdFunctions(mDevice);
4195     }
4196 
4197 #    if defined(ANGLE_PLATFORM_ANDROID)
4198     if (mFeatures.supportsAndroidHardwareBuffer.enabled)
4199     {
4200         InitExternalMemoryHardwareBufferANDROIDFunctions(mDevice);
4201     }
4202 #    endif
4203     if (mFeatures.supportsSynchronization2.enabled)
4204     {
4205         InitSynchronization2Functions(mDevice);
4206     }
4207     if (mFeatures.supportsDeviceFault.enabled)
4208     {
4209         InitDeviceFaultFunctions(mDevice);
4210     }
4211     // Extensions promoted to Vulkan 1.2
4212     {
4213         if (mFeatures.supportsHostQueryReset.enabled)
4214         {
4215             InitHostQueryResetFunctions(mDevice);
4216         }
4217         if (mFeatures.supportsRenderpass2.enabled)
4218         {
4219             InitRenderPass2KHRFunctions(mDevice);
4220         }
4221     }
4222     // Extensions promoted to Vulkan 1.3
4223     {
4224         if (mFeatures.supportsExtendedDynamicState.enabled)
4225         {
4226             InitExtendedDynamicStateEXTFunctions(mDevice);
4227         }
4228         if (mFeatures.supportsExtendedDynamicState2.enabled)
4229         {
4230             InitExtendedDynamicState2EXTFunctions(mDevice);
4231         }
4232         if (mFeatures.supportsDynamicRendering.enabled)
4233         {
4234             InitDynamicRenderingFunctions(mDevice);
4235         }
4236     }
4237 #endif  // !defined(ANGLE_SHARED_LIBVULKAN)
4238 
4239     // For promoted extensions, initialize their entry points from the core version.
4240     initializeDeviceExtensionEntryPointsFromCore();
4241 }
4242 
setupDevice(vk::ErrorContext * context,const angle::FeatureOverrides & featureOverrides,const char * wsiLayer,UseVulkanSwapchain useVulkanSwapchain,angle::NativeWindowSystem nativeWindowSystem)4243 angle::Result Renderer::setupDevice(vk::ErrorContext *context,
4244                                     const angle::FeatureOverrides &featureOverrides,
4245                                     const char *wsiLayer,
4246                                     UseVulkanSwapchain useVulkanSwapchain,
4247                                     angle::NativeWindowSystem nativeWindowSystem)
4248 {
4249     uint32_t deviceLayerCount = 0;
4250     ANGLE_VK_TRY(context,
4251                  vkEnumerateDeviceLayerProperties(mPhysicalDevice, &deviceLayerCount, nullptr));
4252 
4253     std::vector<VkLayerProperties> deviceLayerProps(deviceLayerCount);
4254     ANGLE_VK_TRY(context, vkEnumerateDeviceLayerProperties(mPhysicalDevice, &deviceLayerCount,
4255                                                            deviceLayerProps.data()));
4256 
4257     mEnabledDeviceLayerNames.clear();
4258     if (mEnableValidationLayers)
4259     {
4260         mEnableValidationLayers =
4261             GetAvailableValidationLayers(deviceLayerProps, false, &mEnabledDeviceLayerNames);
4262     }
4263 
4264     if (wsiLayer != nullptr)
4265     {
4266         mEnabledDeviceLayerNames.push_back(wsiLayer);
4267     }
4268 
4269     mEnabledFeatures       = {};
4270     mEnabledFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
4271 
4272     ANGLE_TRY(
4273         enableDeviceExtensions(context, featureOverrides, useVulkanSwapchain, nativeWindowSystem));
4274 
4275     // Used to support cubemap array:
4276     mEnabledFeatures.features.imageCubeArray = mFeatures.supportsImageCubeArray.enabled;
4277     // Used to support framebuffers with multiple attachments:
4278     mEnabledFeatures.features.independentBlend = mPhysicalDeviceFeatures.independentBlend;
4279     // Used to support multi_draw_indirect
4280     mEnabledFeatures.features.multiDrawIndirect = mPhysicalDeviceFeatures.multiDrawIndirect;
4281     mEnabledFeatures.features.drawIndirectFirstInstance =
4282         mPhysicalDeviceFeatures.drawIndirectFirstInstance;
4283     // Used to support robust buffer access, if VK_EXT_pipeline_robustness is not supported.
4284     if (!mFeatures.supportsPipelineRobustness.enabled)
4285     {
4286         mEnabledFeatures.features.robustBufferAccess = mPhysicalDeviceFeatures.robustBufferAccess;
4287     }
4288     // Used to support Anisotropic filtering:
4289     mEnabledFeatures.features.samplerAnisotropy = mPhysicalDeviceFeatures.samplerAnisotropy;
4290     // Used to support wide lines:
4291     mEnabledFeatures.features.wideLines = mPhysicalDeviceFeatures.wideLines;
4292     // Used to emulate transform feedback:
4293     mEnabledFeatures.features.vertexPipelineStoresAndAtomics =
4294         mPhysicalDeviceFeatures.vertexPipelineStoresAndAtomics;
4295     // Used to implement storage buffers and images in the fragment shader:
4296     mEnabledFeatures.features.fragmentStoresAndAtomics =
4297         mPhysicalDeviceFeatures.fragmentStoresAndAtomics;
4298     // Used to emulate the primitives generated query:
4299     mEnabledFeatures.features.pipelineStatisticsQuery =
4300         !mFeatures.supportsPrimitivesGeneratedQuery.enabled &&
4301         mFeatures.supportsPipelineStatisticsQuery.enabled;
4302     // Used to support geometry shaders:
4303     mEnabledFeatures.features.geometryShader = mPhysicalDeviceFeatures.geometryShader;
4304     // Used to support EXT/OES_gpu_shader5:
4305     mEnabledFeatures.features.shaderImageGatherExtended =
4306         mPhysicalDeviceFeatures.shaderImageGatherExtended;
4307     // Used to support EXT/OES_gpu_shader5:
4308     mEnabledFeatures.features.shaderUniformBufferArrayDynamicIndexing =
4309         mPhysicalDeviceFeatures.shaderUniformBufferArrayDynamicIndexing;
4310     mEnabledFeatures.features.shaderSampledImageArrayDynamicIndexing =
4311         mPhysicalDeviceFeatures.shaderSampledImageArrayDynamicIndexing;
4312     // Used to support APPLE_clip_distance
4313     mEnabledFeatures.features.shaderClipDistance = mPhysicalDeviceFeatures.shaderClipDistance;
4314     // Used to support OES_sample_shading
4315     mEnabledFeatures.features.sampleRateShading = mPhysicalDeviceFeatures.sampleRateShading;
4316     // Used to support EXT_depth_clamp and depth clears through draw calls
4317     mEnabledFeatures.features.depthClamp = mPhysicalDeviceFeatures.depthClamp;
4318     // Used to support EXT_polygon_offset_clamp
4319     mEnabledFeatures.features.depthBiasClamp = mPhysicalDeviceFeatures.depthBiasClamp;
4320     // Used to support NV_polygon_mode / ANGLE_polygon_mode
4321     mEnabledFeatures.features.fillModeNonSolid = mPhysicalDeviceFeatures.fillModeNonSolid;
4322     // Used to support EXT_clip_cull_distance
4323     mEnabledFeatures.features.shaderCullDistance = mPhysicalDeviceFeatures.shaderCullDistance;
4324     // Used to support tessellation Shader:
4325     mEnabledFeatures.features.tessellationShader = mPhysicalDeviceFeatures.tessellationShader;
4326     // Used to support EXT_blend_func_extended
4327     mEnabledFeatures.features.dualSrcBlend = mPhysicalDeviceFeatures.dualSrcBlend;
4328     // Used to support ANGLE_logic_op and GLES1
4329     mEnabledFeatures.features.logicOp = mPhysicalDeviceFeatures.logicOp;
4330     // Used to support EXT_multisample_compatibility
4331     mEnabledFeatures.features.alphaToOne = mPhysicalDeviceFeatures.alphaToOne;
4332     // Used to support 16bit-integers in shader code
4333     mEnabledFeatures.features.shaderInt16 = mPhysicalDeviceFeatures.shaderInt16;
4334     // Used to support 64bit-integers in shader code
4335     mEnabledFeatures.features.shaderInt64 = mPhysicalDeviceFeatures.shaderInt64;
4336     // Used to support 64bit-floats in shader code
4337     mEnabledFeatures.features.shaderFloat64 =
4338         mFeatures.supportsShaderFloat64.enabled && mPhysicalDeviceFeatures.shaderFloat64;
4339 
4340     if (!vk::OutsideRenderPassCommandBuffer::ExecutesInline() ||
4341         !vk::RenderPassCommandBuffer::ExecutesInline())
4342     {
4343         mEnabledFeatures.features.inheritedQueries = mPhysicalDeviceFeatures.inheritedQueries;
4344     }
4345 
4346     return angle::Result::Continue;
4347 }
4348 
createDeviceAndQueue(vk::ErrorContext * context,uint32_t queueFamilyIndex)4349 angle::Result Renderer::createDeviceAndQueue(vk::ErrorContext *context, uint32_t queueFamilyIndex)
4350 {
4351     mCurrentQueueFamilyIndex = queueFamilyIndex;
4352 
4353     vk::QueueFamily queueFamily;
4354     queueFamily.initialize(mQueueFamilyProperties[queueFamilyIndex], queueFamilyIndex);
4355     ANGLE_VK_CHECK(context, queueFamily.getDeviceQueueCount() > 0, VK_ERROR_INITIALIZATION_FAILED);
4356 
4357     // We enable protected context only if both supportsProtectedMemory and device also supports
4358     // protected. There are cases we have to disable supportsProtectedMemory feature due to driver
4359     // bugs.
4360     bool enableProtectedContent =
4361         queueFamily.supportsProtected() && mFeatures.supportsProtectedMemory.enabled;
4362 
4363     uint32_t queueCount = std::min(queueFamily.getDeviceQueueCount(),
4364                                    static_cast<uint32_t>(egl::ContextPriority::EnumCount));
4365 
4366     uint32_t queueCreateInfoCount              = 1;
4367     VkDeviceQueueCreateInfo queueCreateInfo[1] = {};
4368     queueCreateInfo[0].sType                   = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
4369     queueCreateInfo[0].flags = enableProtectedContent ? VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT : 0;
4370     queueCreateInfo[0].queueFamilyIndex = queueFamilyIndex;
4371     queueCreateInfo[0].queueCount       = queueCount;
4372     queueCreateInfo[0].pQueuePriorities = vk::QueueFamily::kQueuePriorities;
4373 
4374     // Setup device initialization struct
4375     VkDeviceCreateInfo createInfo    = {};
4376     createInfo.sType                 = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
4377     createInfo.flags                 = 0;
4378     createInfo.queueCreateInfoCount  = queueCreateInfoCount;
4379     createInfo.pQueueCreateInfos     = queueCreateInfo;
4380     createInfo.enabledLayerCount     = static_cast<uint32_t>(mEnabledDeviceLayerNames.size());
4381     createInfo.ppEnabledLayerNames   = mEnabledDeviceLayerNames.data();
4382     createInfo.enabledExtensionCount = static_cast<uint32_t>(mEnabledDeviceExtensions.size());
4383     createInfo.ppEnabledExtensionNames =
4384         mEnabledDeviceExtensions.empty() ? nullptr : mEnabledDeviceExtensions.data();
4385     mEnabledDeviceExtensions.push_back(nullptr);
4386 
4387     // Enable core features without assuming VkPhysicalDeviceFeatures2KHR is accepted in the
4388     // pNext chain of VkDeviceCreateInfo.
4389     createInfo.pEnabledFeatures = &mEnabledFeatures.features;
4390 
4391     // Append the feature structs chain to the end of createInfo structs chain.
4392     if (mEnabledFeatures.pNext)
4393     {
4394         vk::AppendToPNextChain(&createInfo, mEnabledFeatures.pNext);
4395     }
4396 
4397     if (mFeatures.logMemoryReportCallbacks.enabled || mFeatures.logMemoryReportStats.enabled)
4398     {
4399         ASSERT(mMemoryReportFeatures.deviceMemoryReport);
4400 
4401         mMemoryReportCallback       = {};
4402         mMemoryReportCallback.sType = VK_STRUCTURE_TYPE_DEVICE_DEVICE_MEMORY_REPORT_CREATE_INFO_EXT;
4403         mMemoryReportCallback.pfnUserCallback = &MemoryReportCallback;
4404         mMemoryReportCallback.pUserData       = this;
4405         vk::AddToPNextChain(&createInfo, &mMemoryReportCallback);
4406     }
4407 
4408     // Create the list of expected VVL messages to suppress.  Done before creating the device, as it
4409     // may also generate messages.
4410     initializeValidationMessageSuppressions();
4411 
4412     ANGLE_VK_TRY(context, vkCreateDevice(mPhysicalDevice, &createInfo, nullptr, &mDevice));
4413 #if defined(ANGLE_SHARED_LIBVULKAN)
4414     // Load volk if we are loading dynamically
4415     volkLoadDevice(mDevice);
4416 #endif  // defined(ANGLE_SHARED_LIBVULKAN)
4417 
4418     initDeviceExtensionEntryPoints();
4419 
4420     ANGLE_TRY(mCommandQueue.init(context, queueFamily, enableProtectedContent, queueCount));
4421     ANGLE_TRY(mCleanUpThread.init());
4422 
4423     if (mFeatures.forceMaxUniformBufferSize16KB.enabled)
4424     {
4425         mDefaultUniformBufferSize = kMinDefaultUniformBufferSize;
4426     }
4427     // Cap it with the driver limit
4428     mDefaultUniformBufferSize = std::min(
4429         mDefaultUniformBufferSize, getPhysicalDeviceProperties().limits.maxUniformBufferRange);
4430 
4431     // Vulkan pipeline cache will be initialized lazily in ensurePipelineCacheInitialized() method.
4432     ASSERT(!mPipelineCacheInitialized);
4433     ASSERT(!mPipelineCache.valid());
4434 
4435     // Track the set of supported pipeline stages.  This is used when issuing image layout
4436     // transitions that cover many stages (such as AllGraphicsReadOnly) to mask out unsupported
4437     // stages, which avoids enumerating every possible combination of stages in the layouts.
4438     VkPipelineStageFlags unsupportedStages = 0;
4439     mSupportedVulkanShaderStageMask =
4440         VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_COMPUTE_BIT;
4441     mSupportedBufferWritePipelineStageMask =
4442         VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
4443         VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
4444 
4445     if (!mPhysicalDeviceFeatures.tessellationShader)
4446     {
4447         unsupportedStages |= VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT |
4448                              VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT;
4449     }
4450     else
4451     {
4452         mSupportedVulkanShaderStageMask |=
4453             VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
4454         mSupportedBufferWritePipelineStageMask |=
4455             VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT |
4456             VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT;
4457     }
4458     if (!mPhysicalDeviceFeatures.geometryShader)
4459     {
4460         unsupportedStages |= VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
4461     }
4462     else
4463     {
4464         mSupportedVulkanShaderStageMask |= VK_SHADER_STAGE_GEOMETRY_BIT;
4465         mSupportedBufferWritePipelineStageMask |= VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
4466     }
4467 
4468     if (getFeatures().supportsTransformFeedbackExtension.enabled)
4469     {
4470         mSupportedBufferWritePipelineStageMask |= VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT;
4471     }
4472 
4473     // Initialize the barrierData tables by removing unsupported pipeline stage bits
4474     InitializeEventStageToVkPipelineStageFlagsMap(&mEventStageToPipelineStageFlagsMap,
4475                                                   ~unsupportedStages);
4476     InitializeImageLayoutAndMemoryBarrierDataMap(&mImageLayoutAndMemoryBarrierDataMap,
4477                                                  ~unsupportedStages);
4478 
4479     ANGLE_TRY(initializeMemoryAllocator(context));
4480 
4481     // Log the memory heap stats when the device has been initialized (when debugging).
4482     mMemoryAllocationTracker.onDeviceInit();
4483 
4484     return angle::Result::Continue;
4485 }
4486 
calculatePendingGarbageSizeLimit()4487 void Renderer::calculatePendingGarbageSizeLimit()
4488 {
4489     // To find the threshold, we want the memory heap that has the largest size among other heaps.
4490     VkPhysicalDeviceMemoryProperties memoryProperties;
4491     vkGetPhysicalDeviceMemoryProperties(mPhysicalDevice, &memoryProperties);
4492     ASSERT(memoryProperties.memoryHeapCount > 0);
4493 
4494     VkDeviceSize maxHeapSize = memoryProperties.memoryHeaps[0].size;
4495     for (size_t i = 0; i < memoryProperties.memoryHeapCount; i++)
4496     {
4497         VkDeviceSize heapSize = memoryProperties.memoryHeaps[i].size;
4498         if (maxHeapSize < heapSize)
4499         {
4500             maxHeapSize = heapSize;
4501         }
4502     }
4503 
4504     // We set the limit to a portion of the heap size we found.
4505     constexpr float kGarbageSizeLimitCoefficient = 0.2f;
4506     mPendingGarbageSizeLimit =
4507         static_cast<VkDeviceSize>(maxHeapSize * kGarbageSizeLimitCoefficient);
4508 }
4509 
initializeValidationMessageSuppressions()4510 void Renderer::initializeValidationMessageSuppressions()
4511 {
4512     // Build the list of validation errors that are currently expected and should be skipped.
4513     mSkippedValidationMessages.insert(mSkippedValidationMessages.end(), kSkippedMessages,
4514                                       kSkippedMessages + ArraySize(kSkippedMessages));
4515     if (!getFeatures().supportsPrimitiveTopologyListRestart.enabled)
4516     {
4517         mSkippedValidationMessages.insert(
4518             mSkippedValidationMessages.end(), kNoListRestartSkippedMessages,
4519             kNoListRestartSkippedMessages + ArraySize(kNoListRestartSkippedMessages));
4520     }
4521 
4522     if (getFeatures().exposeES32ForTesting.enabled)
4523     {
4524         mSkippedValidationMessages.insert(
4525             mSkippedValidationMessages.end(), kExposeNonConformantSkippedMessages,
4526             kExposeNonConformantSkippedMessages + ArraySize(kExposeNonConformantSkippedMessages));
4527     }
4528 
4529     if (getFeatures().useVkEventForImageBarrier.enabled &&
4530         (!vk::OutsideRenderPassCommandBuffer::ExecutesInline() ||
4531          !vk::RenderPassCommandBuffer::ExecutesInline()))
4532     {
4533         mSkippedValidationMessages.insert(
4534             mSkippedValidationMessages.end(), kSkippedMessagesWithVulkanSecondaryCommandBuffer,
4535             kSkippedMessagesWithVulkanSecondaryCommandBuffer +
4536                 ArraySize(kSkippedMessagesWithVulkanSecondaryCommandBuffer));
4537     }
4538 
4539     if (!getFeatures().preferDynamicRendering.enabled &&
4540         !vk::RenderPassCommandBuffer::ExecutesInline())
4541     {
4542         mSkippedValidationMessages.insert(
4543             mSkippedValidationMessages.end(), kSkippedMessagesWithRenderPassObjectsAndVulkanSCB,
4544             kSkippedMessagesWithRenderPassObjectsAndVulkanSCB +
4545                 ArraySize(kSkippedMessagesWithRenderPassObjectsAndVulkanSCB));
4546     }
4547 
4548     if (getFeatures().preferDynamicRendering.enabled)
4549     {
4550         mSkippedValidationMessages.insert(
4551             mSkippedValidationMessages.end(), kSkippedMessagesWithDynamicRendering,
4552             kSkippedMessagesWithDynamicRendering + ArraySize(kSkippedMessagesWithDynamicRendering));
4553     }
4554 
4555     // Build the list of syncval errors that are currently expected and should be skipped.
4556     mSkippedSyncvalMessages.insert(mSkippedSyncvalMessages.end(), kSkippedSyncvalMessages,
4557                                    kSkippedSyncvalMessages + ArraySize(kSkippedSyncvalMessages));
4558     if (!getFeatures().supportsRenderPassStoreOpNone.enabled &&
4559         !getFeatures().supportsRenderPassLoadStoreOpNone.enabled)
4560     {
4561         mSkippedSyncvalMessages.insert(mSkippedSyncvalMessages.end(),
4562                                        kSkippedSyncvalMessagesWithoutStoreOpNone,
4563                                        kSkippedSyncvalMessagesWithoutStoreOpNone +
4564                                            ArraySize(kSkippedSyncvalMessagesWithoutStoreOpNone));
4565     }
4566     if (!getFeatures().supportsRenderPassLoadStoreOpNone.enabled)
4567     {
4568         mSkippedSyncvalMessages.insert(
4569             mSkippedSyncvalMessages.end(), kSkippedSyncvalMessagesWithoutLoadStoreOpNone,
4570             kSkippedSyncvalMessagesWithoutLoadStoreOpNone +
4571                 ArraySize(kSkippedSyncvalMessagesWithoutLoadStoreOpNone));
4572     }
4573     if (getFeatures().enableMultisampledRenderToTexture.enabled &&
4574         !getFeatures().supportsMultisampledRenderToSingleSampled.enabled)
4575     {
4576         mSkippedSyncvalMessages.insert(mSkippedSyncvalMessages.end(),
4577                                        kSkippedSyncvalMessagesWithMSRTTEmulation,
4578                                        kSkippedSyncvalMessagesWithMSRTTEmulation +
4579                                            ArraySize(kSkippedSyncvalMessagesWithMSRTTEmulation));
4580     }
4581 }
4582 
checkQueueForSurfacePresent(vk::ErrorContext * context,VkSurfaceKHR surface,bool * supportedOut)4583 angle::Result Renderer::checkQueueForSurfacePresent(vk::ErrorContext *context,
4584                                                     VkSurfaceKHR surface,
4585                                                     bool *supportedOut)
4586 {
4587     // We've already initialized a device, and can't re-create it unless it's never been used.
4588     // If recreation is ever necessary, it should be able to deal with contexts currently running in
4589     // other threads using the existing queue.  For example, multiple contexts (not in a share
4590     // group) may be currently recording commands and rendering to pbuffers or using
4591     // EGL_KHR_surfaceless_context.
4592     ASSERT(mDevice != VK_NULL_HANDLE);
4593     ASSERT(mCurrentQueueFamilyIndex != std::numeric_limits<uint32_t>::max());
4594 
4595     // Check if the current device supports present on this surface.
4596     VkBool32 supportsPresent = VK_FALSE;
4597     ANGLE_VK_TRY(context,
4598                  vkGetPhysicalDeviceSurfaceSupportKHR(mPhysicalDevice, mCurrentQueueFamilyIndex,
4599                                                       surface, &supportsPresent));
4600 
4601     *supportedOut = supportsPresent == VK_TRUE;
4602     return angle::Result::Continue;
4603 }
4604 
getVendorString() const4605 std::string Renderer::getVendorString() const
4606 {
4607     return GetVendorString(mPhysicalDeviceProperties.vendorID);
4608 }
4609 
getRendererDescription() const4610 std::string Renderer::getRendererDescription() const
4611 {
4612     std::stringstream strstr;
4613 
4614     uint32_t apiVersion = mPhysicalDeviceProperties.apiVersion;
4615 
4616     strstr << "Vulkan ";
4617     strstr << VK_VERSION_MAJOR(apiVersion) << ".";
4618     strstr << VK_VERSION_MINOR(apiVersion) << ".";
4619     strstr << VK_VERSION_PATCH(apiVersion);
4620 
4621     strstr << " (";
4622 
4623     // In the case of NVIDIA, deviceName does not necessarily contain "NVIDIA". Add "NVIDIA" so that
4624     // Vulkan end2end tests can be selectively disabled on NVIDIA. TODO(jmadill): should not be
4625     // needed after http://anglebug.com/40096421 is fixed and end2end_tests use more sophisticated
4626     // driver detection.
4627     if (mPhysicalDeviceProperties.vendorID == VENDOR_ID_NVIDIA)
4628     {
4629         strstr << GetVendorString(mPhysicalDeviceProperties.vendorID) << " ";
4630     }
4631 
4632     strstr << mPhysicalDeviceProperties.deviceName;
4633     strstr << " (" << gl::FmtHex(mPhysicalDeviceProperties.deviceID) << ")";
4634 
4635     strstr << ")";
4636 
4637     return strstr.str();
4638 }
4639 
getVersionString(bool includeFullVersion) const4640 std::string Renderer::getVersionString(bool includeFullVersion) const
4641 {
4642     std::stringstream strstr;
4643 
4644     uint32_t driverVersion = mPhysicalDeviceProperties.driverVersion;
4645     std::string driverName = std::string(mDriverProperties.driverName);
4646 
4647     if (!driverName.empty())
4648     {
4649         strstr << driverName;
4650     }
4651     else
4652     {
4653         strstr << GetVendorString(mPhysicalDeviceProperties.vendorID);
4654     }
4655 
4656     if (includeFullVersion)
4657     {
4658         strstr << "-";
4659 
4660         if (mPhysicalDeviceProperties.vendorID == VENDOR_ID_NVIDIA)
4661         {
4662             strstr << ANGLE_VK_VERSION_MAJOR_NVIDIA(driverVersion) << ".";
4663             strstr << ANGLE_VK_VERSION_MINOR_NVIDIA(driverVersion) << ".";
4664             strstr << ANGLE_VK_VERSION_SUB_MINOR_NVIDIA(driverVersion) << ".";
4665             strstr << ANGLE_VK_VERSION_PATCH_NVIDIA(driverVersion);
4666         }
4667         else if (mPhysicalDeviceProperties.vendorID == VENDOR_ID_INTEL && IsWindows())
4668         {
4669             strstr << ANGLE_VK_VERSION_MAJOR_WIN_INTEL(driverVersion) << ".";
4670             strstr << ANGLE_VK_VERSION_MINOR_WIN_INTEL(driverVersion);
4671         }
4672         // All other drivers use the Vulkan standard
4673         else
4674         {
4675             strstr << VK_VERSION_MAJOR(driverVersion) << ".";
4676             strstr << VK_VERSION_MINOR(driverVersion) << ".";
4677             strstr << VK_VERSION_PATCH(driverVersion);
4678         }
4679     }
4680 
4681     return strstr.str();
4682 }
4683 
getMaxSupportedESVersion() const4684 gl::Version Renderer::getMaxSupportedESVersion() const
4685 {
4686     // Current highest supported version
4687     gl::Version maxVersion = gl::Version(3, 2);
4688 
4689     // Early out without downgrading ES version if mock ICD enabled.
4690     // Mock ICD doesn't expose sufficient capabilities yet.
4691     // https://github.com/KhronosGroup/Vulkan-Tools/issues/84
4692     if (isMockICDEnabled())
4693     {
4694         return maxVersion;
4695     }
4696 
4697     ensureCapsInitialized();
4698 
4699     // Limit to ES3.1 if there are any blockers for 3.2.
4700     if (mFeatures.exposeES32ForTesting.enabled)
4701     {
4702         return maxVersion;
4703     }
4704     if (!CanSupportGLES32(mNativeExtensions))
4705     {
4706         maxVersion = LimitVersionTo(maxVersion, {3, 1});
4707     }
4708 
4709     // Limit to ES3.0 if there are any blockers for 3.1.
4710 
4711     // ES3.1 requires at least one atomic counter buffer and four storage buffers in compute.
4712     // Atomic counter buffers are emulated with storage buffers.  For simplicity, we always support
4713     // either none or IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS atomic counter buffers.  So if
4714     // Vulkan doesn't support at least that many storage buffers in compute, we don't support 3.1.
4715     const uint32_t kMinimumStorageBuffersForES31 =
4716         gl::limits::kMinimumComputeStorageBuffers +
4717         gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS;
4718     if (mPhysicalDeviceProperties.limits.maxPerStageDescriptorStorageBuffers <
4719         kMinimumStorageBuffersForES31)
4720     {
4721         maxVersion = LimitVersionTo(maxVersion, {3, 0});
4722     }
4723 
4724     // ES3.1 requires at least a maximum offset of at least 2047.
4725     // If the Vulkan implementation can't support that, we cannot support 3.1.
4726     if (mPhysicalDeviceProperties.limits.maxVertexInputAttributeOffset < 2047)
4727     {
4728         maxVersion = LimitVersionTo(maxVersion, {3, 0});
4729     }
4730 
4731     // SSO is in ES3.1 core, so we have to cap to ES3.0 for SSO disablement.
4732     if (mFeatures.disableSeparateShaderObjects.enabled)
4733     {
4734         maxVersion = LimitVersionTo(maxVersion, {3, 0});
4735     }
4736 
4737     // Limit to ES2.0 if there are any blockers for 3.0.
4738     // TODO: http://anglebug.com/42262611 Limit to GLES 2.0 if flat shading can't be emulated
4739 
4740     // Multisample textures (ES3.1) and multisample renderbuffers (ES3.0) require the Vulkan driver
4741     // to support the standard sample locations (in order to pass dEQP tests that check these
4742     // locations).  If the Vulkan implementation can't support that, we cannot support 3.0/3.1.
4743     if (mPhysicalDeviceProperties.limits.standardSampleLocations != VK_TRUE)
4744     {
4745         maxVersion = LimitVersionTo(maxVersion, {2, 0});
4746     }
4747 
4748     // If independentBlend is not supported, we can't have a mix of has-alpha and emulated-alpha
4749     // render targets in a framebuffer.  We also cannot perform masked clears of multiple render
4750     // targets.
4751     if (!mPhysicalDeviceFeatures.independentBlend)
4752     {
4753         maxVersion = LimitVersionTo(maxVersion, {2, 0});
4754     }
4755 
4756     // If the Vulkan transform feedback extension is not present, we use an emulation path that
4757     // requires the vertexPipelineStoresAndAtomics feature. Without the extension or this feature,
4758     // we can't currently support transform feedback.
4759     if (!vk::CanSupportTransformFeedbackExtension(mTransformFeedbackFeatures) &&
4760         !vk::CanSupportTransformFeedbackEmulation(mPhysicalDeviceFeatures))
4761     {
4762         maxVersion = LimitVersionTo(maxVersion, {2, 0});
4763     }
4764 
4765     // Limit to GLES 2.0 if maxPerStageDescriptorUniformBuffers is too low.
4766     // Table 6.31 MAX_VERTEX_UNIFORM_BLOCKS minimum value = 12
4767     // Table 6.32 MAX_FRAGMENT_UNIFORM_BLOCKS minimum value = 12
4768     // NOTE: We reserve some uniform buffers for emulation, so use the NativeCaps which takes this
4769     // into account, rather than the physical device maxPerStageDescriptorUniformBuffers limits.
4770     for (gl::ShaderType shaderType : gl::AllShaderTypes())
4771     {
4772         if (static_cast<GLuint>(getNativeCaps().maxShaderUniformBlocks[shaderType]) <
4773             gl::limits::kMinimumShaderUniformBlocks)
4774         {
4775             maxVersion = LimitVersionTo(maxVersion, {2, 0});
4776         }
4777     }
4778 
4779     // Limit to GLES 2.0 if maxVertexOutputComponents is too low.
4780     // Table 6.31 MAX VERTEX OUTPUT COMPONENTS minimum value = 64
4781     // NOTE: We reserve some vertex output components for emulation, so use the NativeCaps which
4782     // takes this into account, rather than the physical device maxVertexOutputComponents limits.
4783     if (static_cast<GLuint>(getNativeCaps().maxVertexOutputComponents) <
4784         gl::limits::kMinimumVertexOutputComponents)
4785     {
4786         maxVersion = LimitVersionTo(maxVersion, {2, 0});
4787     }
4788 
4789     return maxVersion;
4790 }
4791 
getMaxConformantESVersion() const4792 gl::Version Renderer::getMaxConformantESVersion() const
4793 {
4794     return getMaxSupportedESVersion();
4795 }
4796 
getDeviceVersion() const4797 uint32_t Renderer::getDeviceVersion() const
4798 {
4799     return mDeviceVersion == 0 ? mInstanceVersion : mDeviceVersion;
4800 }
4801 
queryAndCacheFragmentShadingRates()4802 void Renderer::queryAndCacheFragmentShadingRates()
4803 {
4804     // Init required functions
4805 #if !defined(ANGLE_SHARED_LIBVULKAN)
4806     InitFragmentShadingRateKHRInstanceFunction(mInstance);
4807 #endif  // !defined(ANGLE_SHARED_LIBVULKAN)
4808     ASSERT(vkGetPhysicalDeviceFragmentShadingRatesKHR);
4809 
4810     // Query number of supported shading rates first
4811     uint32_t shadingRatesCount = 0;
4812     VkResult result =
4813         vkGetPhysicalDeviceFragmentShadingRatesKHR(mPhysicalDevice, &shadingRatesCount, nullptr);
4814     ASSERT(result == VK_SUCCESS);
4815     ASSERT(shadingRatesCount > 0);
4816 
4817     std::vector<VkPhysicalDeviceFragmentShadingRateKHR> shadingRates(
4818         shadingRatesCount,
4819         {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_KHR, nullptr, 0, {0, 0}});
4820 
4821     // Query supported shading rates
4822     result = vkGetPhysicalDeviceFragmentShadingRatesKHR(mPhysicalDevice, &shadingRatesCount,
4823                                                         shadingRates.data());
4824     ASSERT(result == VK_SUCCESS);
4825 
4826     // Cache supported fragment shading rates
4827     mSupportedFragmentShadingRates.reset();
4828     mSupportedFragmentShadingRateSampleCounts.fill(0u);
4829     for (const VkPhysicalDeviceFragmentShadingRateKHR &shadingRate : shadingRates)
4830     {
4831         if (shadingRate.sampleCounts == 0)
4832         {
4833             continue;
4834         }
4835         const gl::ShadingRate rate = GetShadingRateFromVkExtent(shadingRate.fragmentSize);
4836         mSupportedFragmentShadingRates.set(rate);
4837         mSupportedFragmentShadingRateSampleCounts[rate] = shadingRate.sampleCounts;
4838     }
4839 }
4840 
canSupportFragmentShadingRate() const4841 bool Renderer::canSupportFragmentShadingRate() const
4842 {
4843     // VK_KHR_create_renderpass2 is required for VK_KHR_fragment_shading_rate
4844     if (!mFeatures.supportsRenderpass2.enabled)
4845     {
4846         return false;
4847     }
4848 
4849     // Device needs to support VK_KHR_fragment_shading_rate and specifically
4850     // pipeline fragment shading rate.
4851     if (mFragmentShadingRateFeatures.pipelineFragmentShadingRate != VK_TRUE)
4852     {
4853         return false;
4854     }
4855 
4856     ASSERT(mSupportedFragmentShadingRates.any());
4857 
4858     // To implement GL_QCOM_shading_rate extension the Vulkan ICD needs to support at least the
4859     // following shading rates -
4860     //     {1, 1}
4861     //     {1, 2}
4862     //     {2, 1}
4863     //     {2, 2}
4864     return mSupportedFragmentShadingRates.test(gl::ShadingRate::_1x1) &&
4865            mSupportedFragmentShadingRates.test(gl::ShadingRate::_1x2) &&
4866            mSupportedFragmentShadingRates.test(gl::ShadingRate::_2x1) &&
4867            mSupportedFragmentShadingRates.test(gl::ShadingRate::_2x2);
4868 }
4869 
canSupportFoveatedRendering() const4870 bool Renderer::canSupportFoveatedRendering() const
4871 {
4872     // Device needs to support attachment fragment shading rate.
4873     if (mFragmentShadingRateFeatures.attachmentFragmentShadingRate != VK_TRUE)
4874     {
4875         return false;
4876     }
4877 
4878     ASSERT(mSupportedFragmentShadingRates.any());
4879     ASSERT(!mSupportedFragmentShadingRateSampleCounts.empty());
4880 
4881     // To implement QCOM foveated rendering extensions the Vulkan ICD needs to support all sample
4882     // count bits listed in VkPhysicalDeviceLimits::framebufferColorSampleCounts for these shading
4883     // rates -
4884     //     {1, 1}
4885     //     {1, 2}
4886     //     {2, 1}
4887     //     {2, 2}
4888     VkSampleCountFlags framebufferSampleCounts =
4889         getPhysicalDeviceProperties().limits.framebufferColorSampleCounts &
4890         vk_gl::kSupportedSampleCounts;
4891 
4892     return (mSupportedFragmentShadingRateSampleCounts[gl::ShadingRate::_1x1] &
4893             framebufferSampleCounts) == framebufferSampleCounts &&
4894            (mSupportedFragmentShadingRateSampleCounts[gl::ShadingRate::_1x2] &
4895             framebufferSampleCounts) == framebufferSampleCounts &&
4896            (mSupportedFragmentShadingRateSampleCounts[gl::ShadingRate::_2x1] &
4897             framebufferSampleCounts) == framebufferSampleCounts &&
4898            (mSupportedFragmentShadingRateSampleCounts[gl::ShadingRate::_2x2] &
4899             framebufferSampleCounts) == framebufferSampleCounts;
4900 }
4901 
canPreferDeviceLocalMemoryHostVisible(VkPhysicalDeviceType deviceType)4902 bool Renderer::canPreferDeviceLocalMemoryHostVisible(VkPhysicalDeviceType deviceType)
4903 {
4904     if (deviceType == VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU)
4905     {
4906         const vk::MemoryProperties &memoryProperties = getMemoryProperties();
4907         static constexpr VkMemoryPropertyFlags kHostVisiableDeviceLocalFlags =
4908             VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
4909         VkDeviceSize minHostVisiableDeviceLocalHeapSize = std::numeric_limits<VkDeviceSize>::max();
4910         VkDeviceSize maxDeviceLocalHeapSize             = 0;
4911         for (uint32_t i = 0; i < memoryProperties.getMemoryTypeCount(); ++i)
4912         {
4913             if ((memoryProperties.getMemoryType(i).propertyFlags &
4914                  VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) != 0)
4915             {
4916                 maxDeviceLocalHeapSize =
4917                     std::max(maxDeviceLocalHeapSize, memoryProperties.getHeapSizeForMemoryType(i));
4918             }
4919             if ((memoryProperties.getMemoryType(i).propertyFlags & kHostVisiableDeviceLocalFlags) ==
4920                 kHostVisiableDeviceLocalFlags)
4921             {
4922                 minHostVisiableDeviceLocalHeapSize =
4923                     std::min(minHostVisiableDeviceLocalHeapSize,
4924                              memoryProperties.getHeapSizeForMemoryType(i));
4925             }
4926         }
4927         return minHostVisiableDeviceLocalHeapSize != std::numeric_limits<VkDeviceSize>::max() &&
4928                minHostVisiableDeviceLocalHeapSize >=
4929                    static_cast<VkDeviceSize>(maxDeviceLocalHeapSize * 0.8);
4930     }
4931     return deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU;
4932 }
4933 
initFeatures(const vk::ExtensionNameList & deviceExtensionNames,const angle::FeatureOverrides & featureOverrides,UseVulkanSwapchain useVulkanSwapchain,angle::NativeWindowSystem nativeWindowSystem)4934 void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames,
4935                             const angle::FeatureOverrides &featureOverrides,
4936                             UseVulkanSwapchain useVulkanSwapchain,
4937                             angle::NativeWindowSystem nativeWindowSystem)
4938 {
4939     ApplyFeatureOverrides(&mFeatures, featureOverrides);
4940 
4941     if (featureOverrides.allDisabled)
4942     {
4943         return;
4944     }
4945 
4946     const bool isAMD      = IsAMD(mPhysicalDeviceProperties.vendorID);
4947     const bool isApple    = IsAppleGPU(mPhysicalDeviceProperties.vendorID);
4948     const bool isARM      = IsARM(mPhysicalDeviceProperties.vendorID);
4949     const bool isIntel    = IsIntel(mPhysicalDeviceProperties.vendorID);
4950     const bool isNvidia   = IsNvidia(mPhysicalDeviceProperties.vendorID);
4951     const bool isPowerVR  = IsPowerVR(mPhysicalDeviceProperties.vendorID);
4952     const bool isQualcomm = IsQualcomm(mPhysicalDeviceProperties.vendorID);
4953     const bool isBroadcom = IsBroadcom(mPhysicalDeviceProperties.vendorID);
4954     const bool isSamsung  = IsSamsung(mPhysicalDeviceProperties.vendorID);
4955     const bool isSwiftShader =
4956         IsSwiftshader(mPhysicalDeviceProperties.vendorID, mPhysicalDeviceProperties.deviceID);
4957 
4958     const bool isGalaxyS23 =
4959         IsGalaxyS23(mPhysicalDeviceProperties.vendorID, mPhysicalDeviceProperties.deviceID);
4960 
4961     // Distinguish between the open source and proprietary Qualcomm drivers
4962     const bool isQualcommOpenSource =
4963         IsQualcommOpenSource(mPhysicalDeviceProperties.vendorID, mDriverProperties.driverID,
4964                              mPhysicalDeviceProperties.deviceName);
4965     const bool isQualcommProprietary = isQualcomm && !isQualcommOpenSource;
4966 
4967     // Lacking other explicit ways to tell if mali GPU is job manager based or command stream front
4968     // end based, we use maxDrawIndirectCount as equivalent since all JM based has
4969     // maxDrawIndirectCount==1 and all CSF based has maxDrawIndirectCount>1.
4970     bool isMaliJobManagerBasedGPU =
4971         isARM && getPhysicalDeviceProperties().limits.maxDrawIndirectCount <= 1;
4972 
4973     // Distinguish between the mesa and proprietary drivers
4974     const bool isRADV = IsRADV(mPhysicalDeviceProperties.vendorID, mDriverProperties.driverID,
4975                                mPhysicalDeviceProperties.deviceName);
4976 
4977     angle::VersionInfo driverVersion = {};
4978     if (isARM)
4979     {
4980         driverVersion = angle::ParseArmVulkanDriverVersion(mPhysicalDeviceProperties.driverVersion);
4981     }
4982     else if (isQualcommProprietary)
4983     {
4984         driverVersion =
4985             angle::ParseQualcommVulkanDriverVersion(mPhysicalDeviceProperties.driverVersion);
4986     }
4987     else if (isNvidia)
4988     {
4989         driverVersion =
4990             angle::ParseNvidiaVulkanDriverVersion(mPhysicalDeviceProperties.driverVersion);
4991     }
4992     else if (IsLinux() && (isIntel || isRADV))
4993     {
4994         driverVersion =
4995             angle::ParseMesaVulkanDriverVersion(mPhysicalDeviceProperties.driverVersion);
4996     }
4997     else if (IsWindows() && isIntel)
4998     {
4999         driverVersion =
5000             angle::ParseIntelWindowsVulkanDriverVersion(mPhysicalDeviceProperties.driverVersion);
5001     }
5002     else if (isAMD && !isRADV)
5003     {
5004         driverVersion = angle::ParseAMDVulkanDriverVersion(mPhysicalDeviceProperties.driverVersion);
5005     }
5006     else if (isSamsung)
5007     {
5008         driverVersion =
5009             angle::ParseSamsungVulkanDriverVersion(mPhysicalDeviceProperties.driverVersion);
5010     }
5011 
5012     // Classify devices based on general architecture:
5013     //
5014     // - IMR (Immediate-Mode Rendering) devices generally progress through draw calls once and use
5015     //   the main GPU memory (accessed through caches) to store intermediate rendering results.
5016     // - TBR (Tile-Based Rendering) devices issue a pre-rendering geometry pass, then run through
5017     //   draw calls once per tile and store intermediate rendering results on the tile cache.
5018     //
5019     // Due to these key architectural differences, some operations improve performance on one while
5020     // deteriorating performance on the other.  ANGLE will accordingly make some decisions based on
5021     // the device architecture for optimal performance on both.
5022     const bool isImmediateModeRenderer = isNvidia || isAMD || isIntel || isSamsung || isSwiftShader;
5023     const bool isTileBasedRenderer     = isARM || isPowerVR || isQualcomm || isBroadcom || isApple;
5024 
5025     // Make sure all known architectures are accounted for.
5026     if (!isImmediateModeRenderer && !isTileBasedRenderer && !isMockICDEnabled())
5027     {
5028         WARN() << "Unknown GPU architecture";
5029     }
5030 
5031     ANGLE_FEATURE_CONDITION(&mFeatures, appendAliasedMemoryDecorations, true);
5032 
5033     ANGLE_FEATURE_CONDITION(
5034         &mFeatures, supportsSharedPresentableImageExtension,
5035         ExtensionFound(VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME, deviceExtensionNames));
5036 
5037     ANGLE_FEATURE_CONDITION(&mFeatures, supportsGetMemoryRequirements2, true);
5038 
5039     ANGLE_FEATURE_CONDITION(&mFeatures, supportsBindMemory2, true);
5040 
5041     ANGLE_FEATURE_CONDITION(&mFeatures, bresenhamLineRasterization,
5042                             mLineRasterizationFeatures.bresenhamLines == VK_TRUE);
5043 
5044     ANGLE_FEATURE_CONDITION(&mFeatures, provokingVertex,
5045                             mProvokingVertexFeatures.provokingVertexLast == VK_TRUE);
5046 
5047     // http://b/208458772. ARM driver supports this protected memory extension but we are seeing
5048     // excessive load/store unit activity when this extension is enabled, even if not been used.
5049     // Disable this extension on older ARM platforms that don't support
5050     // VK_EXT_pipeline_protected_access.
5051     // http://anglebug.com/42266183
5052     //
5053     // http://b/381285096. On Intel platforms, we want to prevent protected queues being used as
5054     // we cannot handle the teardown scenario if PXP termination occurs.
5055     ANGLE_FEATURE_CONDITION(
5056         &mFeatures, supportsProtectedMemory,
5057         mProtectedMemoryFeatures.protectedMemory == VK_TRUE &&
5058             (!isARM || mPipelineProtectedAccessFeatures.pipelineProtectedAccess == VK_TRUE) &&
5059             !isIntel);
5060 
5061     ANGLE_FEATURE_CONDITION(&mFeatures, supportsHostQueryReset,
5062                             mHostQueryResetFeatures.hostQueryReset == VK_TRUE);
5063     // Avoid any inefficiency that may be caused by host image copy by default.  To be experimented
5064     // with to see on which hardware VkHostImageCopyDevicePerformanceQueryEXT::optimalDeviceAccess
5065     // is really performing as well as
5066     // VkHostImageCopyDevicePerformanceQueryEXT::identicalMemoryLayout.
5067     ANGLE_FEATURE_CONDITION(&mFeatures, allowHostImageCopyDespiteNonIdenticalLayout, false);
5068 
5069     // VK_EXT_pipeline_creation_feedback is promoted to core in Vulkan 1.3.
5070     ANGLE_FEATURE_CONDITION(
5071         &mFeatures, supportsPipelineCreationFeedback,
5072         ExtensionFound(VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME, deviceExtensionNames));
5073 
5074     // Note: Protected Swapchains is not determined until we have a VkSurface to query.
5075     // So here vendors should indicate support so that protected_content extension
5076     // is enabled.
5077     ANGLE_FEATURE_CONDITION(&mFeatures, supportsSurfaceProtectedSwapchains, IsAndroid());
5078 
5079     // Work around incorrect NVIDIA point size range clamping.
5080     // http://anglebug.com/40644663#comment11
5081     // Clamp if driver version is:
5082     //   < 430 on Windows
5083     //   < 421 otherwise
5084     ANGLE_FEATURE_CONDITION(
5085         &mFeatures, clampPointSize,
5086         isNvidia && driverVersion < angle::VersionTriple(IsWindows() ? 430 : 421, 0, 0));
5087 
5088     // Affecting Nvidia drivers 535 through 551.
5089     ANGLE_FEATURE_CONDITION(&mFeatures, avoidOpSelectWithMismatchingRelaxedPrecision,
5090                             isNvidia && (driverVersion >= angle::VersionTriple(535, 0, 0) &&
5091                                          driverVersion < angle::VersionTriple(552, 0, 0)));
5092 
5093     // Affecting Linux/Intel (unknown range).
5094     ANGLE_FEATURE_CONDITION(&mFeatures, wrapSwitchInIfTrue, isIntel && IsLinux());
5095 
5096     // Vulkan implementations are not required to clamp gl_FragDepth to [0, 1] by default.
5097     ANGLE_FEATURE_CONDITION(&mFeatures, supportsDepthClampZeroOne,
5098                             mDepthClampZeroOneFeatures.depthClampZeroOne == VK_TRUE);
5099 
5100     ANGLE_FEATURE_CONDITION(&mFeatures, clampFragDepth,
5101                             isNvidia && !mFeatures.supportsDepthClampZeroOne.enabled);
5102 
5103     ANGLE_FEATURE_CONDITION(
5104         &mFeatures, supportsRenderpass2,
5105         ExtensionFound(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME, deviceExtensionNames));
5106 
5107     ANGLE_FEATURE_CONDITION(
5108         &mFeatures, supportsIncrementalPresent,
5109         ExtensionFound(VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME, deviceExtensionNames));
5110 
5111 #if defined(ANGLE_PLATFORM_ANDROID)
5112     ANGLE_FEATURE_CONDITION(
5113         &mFeatures, supportsAndroidHardwareBuffer,
5114         IsAndroid() &&
5115             ExtensionFound(VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME,
5116                            deviceExtensionNames) &&
5117             ExtensionFound(VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME, deviceExtensionNames));
5118 #endif
5119 
5120     ANGLE_FEATURE_CONDITION(
5121         &mFeatures, supportsExternalMemoryFd,
5122         ExtensionFound(VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, deviceExtensionNames));
5123 
5124 #if defined(ANGLE_PLATFORM_WINDOWS)
5125     ANGLE_FEATURE_CONDITION(
5126         &mFeatures, supportsFullScreenExclusive,
5127         ExtensionFound(VK_EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME, deviceExtensionNames));
5128 
5129     // On Windows+AMD, drivers before version 0x800106 (2.0.262) would
5130     // implicitly enable VK_EXT_full_screen_exclusive and start returning
5131     // extension-specific error codes in swapchain functions. Since the
5132     // extension was not enabled by ANGLE, it was impossible to handle these
5133     // error codes correctly. On these earlier drivers, we want to explicitly
5134     // enable the extension and opt out of it to avoid seeing those error codes
5135     // entirely.
5136     ANGLE_FEATURE_CONDITION(&mFeatures, forceDisableFullScreenExclusive,
5137                             isAMD && driverVersion < angle::VersionTriple(2, 0, 262));
5138 #endif
5139 
5140     ANGLE_FEATURE_CONDITION(
5141         &mFeatures, supportsExternalMemoryFuchsia,
5142         ExtensionFound(VK_FUCHSIA_EXTERNAL_MEMORY_EXTENSION_NAME, deviceExtensionNames));
5143 
5144     ANGLE_FEATURE_CONDITION(
5145         &mFeatures, supportsExternalSemaphoreFd,
5146         ExtensionFound(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, deviceExtensionNames));
5147 
5148     ANGLE_FEATURE_CONDITION(
5149         &mFeatures, supportsExternalSemaphoreFuchsia,
5150         ExtensionFound(VK_FUCHSIA_EXTERNAL_SEMAPHORE_EXTENSION_NAME, deviceExtensionNames));
5151 
5152     ANGLE_FEATURE_CONDITION(
5153         &mFeatures, supportsExternalFenceFd,
5154         ExtensionFound(VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME, deviceExtensionNames));
5155 
5156 #if defined(ANGLE_PLATFORM_ANDROID) || defined(ANGLE_PLATFORM_LINUX)
5157     if (mFeatures.supportsExternalFenceCapabilities.enabled &&
5158         mFeatures.supportsExternalSemaphoreCapabilities.enabled)
5159     {
5160         VkExternalFenceProperties externalFenceProperties = {};
5161         externalFenceProperties.sType = VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES;
5162 
5163         VkPhysicalDeviceExternalFenceInfo externalFenceInfo = {};
5164         externalFenceInfo.sType      = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO;
5165         externalFenceInfo.handleType = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR;
5166 
5167         vkGetPhysicalDeviceExternalFenceProperties(mPhysicalDevice, &externalFenceInfo,
5168                                                    &externalFenceProperties);
5169 
5170         VkExternalSemaphoreProperties externalSemaphoreProperties = {};
5171         externalSemaphoreProperties.sType = VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES;
5172 
5173         VkPhysicalDeviceExternalSemaphoreInfo externalSemaphoreInfo = {};
5174         externalSemaphoreInfo.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO;
5175         externalSemaphoreInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR;
5176 
5177         vkGetPhysicalDeviceExternalSemaphoreProperties(mPhysicalDevice, &externalSemaphoreInfo,
5178                                                        &externalSemaphoreProperties);
5179 
5180         ANGLE_FEATURE_CONDITION(
5181             &mFeatures, supportsAndroidNativeFenceSync,
5182             (mFeatures.supportsExternalFenceFd.enabled &&
5183              FencePropertiesCompatibleWithAndroid(externalFenceProperties) &&
5184              mFeatures.supportsExternalSemaphoreFd.enabled &&
5185              SemaphorePropertiesCompatibleWithAndroid(externalSemaphoreProperties)));
5186     }
5187     else
5188     {
5189         ANGLE_FEATURE_CONDITION(&mFeatures, supportsAndroidNativeFenceSync,
5190                                 (mFeatures.supportsExternalFenceFd.enabled &&
5191                                  mFeatures.supportsExternalSemaphoreFd.enabled));
5192     }
5193 #endif  // defined(ANGLE_PLATFORM_ANDROID) || defined(ANGLE_PLATFORM_LINUX)
5194 
5195     // Disabled on SwiftShader due to http://crbug.com/40942995
5196     ANGLE_FEATURE_CONDITION(
5197         &mFeatures, supportsShaderStencilExport,
5198         ExtensionFound(VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME, deviceExtensionNames) &&
5199             !isSwiftShader);
5200 
5201     ANGLE_FEATURE_CONDITION(
5202         &mFeatures, supportsRenderPassLoadStoreOpNone,
5203         ExtensionFound(VK_EXT_LOAD_STORE_OP_NONE_EXTENSION_NAME, deviceExtensionNames));
5204 
5205     ANGLE_FEATURE_CONDITION(&mFeatures, disallowMixedDepthStencilLoadOpNoneAndLoad,
5206                             isARM && driverVersion < angle::VersionTriple(38, 1, 0));
5207 
5208     ANGLE_FEATURE_CONDITION(
5209         &mFeatures, supportsRenderPassStoreOpNone,
5210         !mFeatures.supportsRenderPassLoadStoreOpNone.enabled &&
5211             ExtensionFound(VK_QCOM_RENDER_PASS_STORE_OPS_EXTENSION_NAME, deviceExtensionNames));
5212 
5213     ANGLE_FEATURE_CONDITION(&mFeatures, supportsDepthClipControl,
5214                             mDepthClipControlFeatures.depthClipControl == VK_TRUE);
5215 
5216     ANGLE_FEATURE_CONDITION(
5217         &mFeatures, supportsPrimitiveTopologyListRestart,
5218         mPrimitiveTopologyListRestartFeatures.primitiveTopologyListRestart == VK_TRUE);
5219 
5220     ANGLE_FEATURE_CONDITION(
5221         &mFeatures, supportsBlendOperationAdvanced,
5222         ExtensionFound(VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME, deviceExtensionNames));
5223 
5224     ANGLE_FEATURE_CONDITION(
5225         &mFeatures, supportsFormatFeatureFlags2,
5226         ExtensionFound(VK_KHR_FORMAT_FEATURE_FLAGS_2_EXTENSION_NAME, deviceExtensionNames));
5227 
5228     ANGLE_FEATURE_CONDITION(&mFeatures, supportsTransformFeedbackExtension,
5229                             vk::CanSupportTransformFeedbackExtension(mTransformFeedbackFeatures));
5230 
5231     ANGLE_FEATURE_CONDITION(&mFeatures, supportsGeometryStreamsCapability,
5232                             mFeatures.supportsTransformFeedbackExtension.enabled &&
5233                                 mTransformFeedbackFeatures.geometryStreams == VK_TRUE);
5234 
5235     ANGLE_FEATURE_CONDITION(
5236         &mFeatures, supportsPrimitivesGeneratedQuery,
5237         mFeatures.supportsTransformFeedbackExtension.enabled &&
5238             mPrimitivesGeneratedQueryFeatures.primitivesGeneratedQuery == VK_TRUE);
5239 
5240     ANGLE_FEATURE_CONDITION(&mFeatures, emulateTransformFeedback,
5241                             !mFeatures.supportsTransformFeedbackExtension.enabled &&
5242                                 vk::CanSupportTransformFeedbackEmulation(mPhysicalDeviceFeatures));
5243 
5244     ANGLE_FEATURE_CONDITION(&mFeatures, supportsIndexTypeUint8,
5245                             mIndexTypeUint8Features.indexTypeUint8 == VK_TRUE);
5246 
5247     ANGLE_FEATURE_CONDITION(&mFeatures, supportsDepthStencilResolve,
5248                             mFeatures.supportsRenderpass2.enabled &&
5249                                 mDepthStencilResolveProperties.supportedDepthResolveModes != 0);
5250     ANGLE_FEATURE_CONDITION(&mFeatures, supportsDepthStencilIndependentResolveNone,
5251                             mFeatures.supportsDepthStencilResolve.enabled &&
5252                                 mDepthStencilResolveProperties.independentResolveNone);
5253     // Disable optimizing depth/stencil resolve through glBlitFramebuffer for buggy drivers:
5254     //
5255     // - Nvidia: http://anglebug.com/42267095
5256     // - Pixel4: http://anglebug.com/42267096
5257     //
5258     ANGLE_FEATURE_CONDITION(&mFeatures, disableDepthStencilResolveThroughAttachment,
5259                             isNvidia || isQualcommProprietary);
5260 
5261     // MSRTSS is disabled if the driver does not support it for RGBA8 and RGBA8_SRGB.
5262     // This is used to filter out known drivers where support for sRGB formats are missing.
5263     ANGLE_FEATURE_CONDITION(
5264         &mFeatures, supportsMultisampledRenderToSingleSampled,
5265         mMultisampledRenderToSingleSampledFeatures.multisampledRenderToSingleSampled == VK_TRUE &&
5266             mFeatures.supportsRenderpass2.enabled &&
5267             mFeatures.supportsDepthStencilResolve.enabled && CanSupportMSRTSSForRGBA8(this));
5268 
5269     // Preferring the MSRTSS flag is for texture initialization. If the MSRTSS is not used at first,
5270     // it will be used (if available) when recreating the image if it is bound to an MSRTT
5271     // framebuffer.
5272     ANGLE_FEATURE_CONDITION(&mFeatures, preferMSRTSSFlagByDefault,
5273                             mFeatures.supportsMultisampledRenderToSingleSampled.enabled && isARM);
5274 
5275     ANGLE_FEATURE_CONDITION(&mFeatures, supportsImage2dViewOf3d,
5276                             mImage2dViewOf3dFeatures.image2DViewOf3D == VK_TRUE);
5277 
5278     // Note: sampler2DViewOf3D is only useful for supporting EGL_KHR_gl_texture_3D_image.  If the
5279     // VK_IMAGE_CREATE_2D_VIEW_COMPATIBLE_BIT_EXT added to 3D images measurable hurts sampling
5280     // performance, it might be better to remove support for EGL_KHR_gl_texture_3D_image in favor of
5281     // faster 3D images.
5282     ANGLE_FEATURE_CONDITION(&mFeatures, supportsSampler2dViewOf3d,
5283                             mFeatures.supportsImage2dViewOf3d.enabled &&
5284                                 mImage2dViewOf3dFeatures.sampler2DViewOf3D == VK_TRUE);
5285 
5286     ANGLE_FEATURE_CONDITION(&mFeatures, supportsMultiview, mMultiviewFeatures.multiview == VK_TRUE);
5287 
5288     // VK_EXT_device_fault can provide more information when the device is lost.
5289     ANGLE_FEATURE_CONDITION(
5290         &mFeatures, supportsDeviceFault,
5291         ExtensionFound(VK_EXT_DEVICE_FAULT_EXTENSION_NAME, deviceExtensionNames) &&
5292             mFaultFeatures.deviceFault == VK_TRUE);
5293 
5294     // TODO: http://anglebug.com/42264464 - drop dependency on customBorderColorWithoutFormat.
5295     ANGLE_FEATURE_CONDITION(
5296         &mFeatures, supportsCustomBorderColor,
5297         mCustomBorderColorFeatures.customBorderColors == VK_TRUE &&
5298             mCustomBorderColorFeatures.customBorderColorWithoutFormat == VK_TRUE);
5299 
5300     ANGLE_FEATURE_CONDITION(&mFeatures, supportsMultiDrawIndirect,
5301                             mPhysicalDeviceFeatures.multiDrawIndirect == VK_TRUE);
5302 
5303     ANGLE_FEATURE_CONDITION(&mFeatures, perFrameWindowSizeQuery,
5304                             IsAndroid() || isIntel || (IsWindows() && (isAMD || isNvidia)) ||
5305                                 IsFuchsia() || isSamsung ||
5306                                 nativeWindowSystem == angle::NativeWindowSystem::Wayland);
5307 
5308     ANGLE_FEATURE_CONDITION(&mFeatures, padBuffersToMaxVertexAttribStride, isAMD || isSamsung);
5309     mMaxVertexAttribStride = std::min(static_cast<uint32_t>(gl::limits::kMaxVertexAttribStride),
5310                                       mPhysicalDeviceProperties.limits.maxVertexInputBindingStride);
5311 
5312     // The limits related to buffer size should also take the max memory allocation size and padding
5313     // (if applicable) into account.
5314     mMaxBufferMemorySizeLimit = getFeatures().padBuffersToMaxVertexAttribStride.enabled
5315                                     ? getMaxMemoryAllocationSize() - mMaxVertexAttribStride
5316                                     : getMaxMemoryAllocationSize();
5317 
5318     ANGLE_FEATURE_CONDITION(&mFeatures, forceD16TexFilter, IsAndroid() && isQualcommProprietary);
5319 
5320     ANGLE_FEATURE_CONDITION(&mFeatures, disableFlippingBlitWithCommand,
5321                             IsAndroid() && isQualcommProprietary);
5322 
5323     // Allocation sanitization disabled by default because of a heaveyweight implementation
5324     // that can cause OOM and timeouts.
5325     ANGLE_FEATURE_CONDITION(&mFeatures, allocateNonZeroMemory, false);
5326 
5327     // ARM does buffer copy on geometry pipeline, which may create a GPU pipeline bubble that
5328     // prevents vertex shader to overlap with fragment shader on job manager based architecture. For
5329     // now we always choose CPU to do copy on ARM job manager based GPU.
5330     ANGLE_FEATURE_CONDITION(&mFeatures, preferCPUForBufferSubData, isARM);
5331 
5332     // On android, we usually are GPU limited, we try to use CPU to do data copy when other
5333     // conditions are the same. Set to zero will use GPU to do copy. This is subject to further
5334     // tuning for each platform https://issuetracker.google.com/201826021
5335     mMaxCopyBytesUsingCPUWhenPreservingBufferData =
5336         IsAndroid() ? std::numeric_limits<uint32_t>::max() : 0;
5337 
5338     ANGLE_FEATURE_CONDITION(&mFeatures, persistentlyMappedBuffers, true);
5339 
5340     ANGLE_FEATURE_CONDITION(&mFeatures, logMemoryReportCallbacks, false);
5341     ANGLE_FEATURE_CONDITION(&mFeatures, logMemoryReportStats, false);
5342 
5343     ANGLE_FEATURE_CONDITION(
5344         &mFeatures, supportsExternalMemoryDmaBufAndModifiers,
5345         ExtensionFound(VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME, deviceExtensionNames) &&
5346             ExtensionFound(VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME, deviceExtensionNames));
5347 
5348     ANGLE_FEATURE_CONDITION(
5349         &mFeatures, supportsExternalMemoryHost,
5350         ExtensionFound(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME, deviceExtensionNames));
5351 
5352     // Android pre-rotation support can be disabled.
5353     ANGLE_FEATURE_CONDITION(&mFeatures, enablePreRotateSurfaces, IsAndroid());
5354 
5355     // http://anglebug.com/42261756
5356     // Precision qualifiers are disabled for Pixel 2 before the driver included relaxed precision.
5357     ANGLE_FEATURE_CONDITION(
5358         &mFeatures, enablePrecisionQualifiers,
5359         !(IsPixel2(mPhysicalDeviceProperties.vendorID, mPhysicalDeviceProperties.deviceID) &&
5360           (driverVersion < angle::VersionTriple(512, 490, 0))) &&
5361             !IsPixel4(mPhysicalDeviceProperties.vendorID, mPhysicalDeviceProperties.deviceID));
5362 
5363     // http://anglebug.com/42265957
5364     ANGLE_FEATURE_CONDITION(&mFeatures, varyingsRequireMatchingPrecisionInSpirv, isPowerVR);
5365 
5366     // IMR devices are less sensitive to the src/dst stage masks in barriers, and behave more
5367     // efficiently when all barriers are aggregated, rather than individually and precisely
5368     // specified.
5369     ANGLE_FEATURE_CONDITION(&mFeatures, preferAggregateBarrierCalls, isImmediateModeRenderer);
5370 
5371     // For IMR devices, it's more efficient to ignore invalidate of framebuffer attachments with
5372     // emulated formats that have extra channels.  For TBR devices, the invalidate will be followed
5373     // by a clear to retain valid values in said extra channels.
5374     ANGLE_FEATURE_CONDITION(&mFeatures, preferSkippingInvalidateForEmulatedFormats,
5375                             isImmediateModeRenderer);
5376 
5377     ANGLE_FEATURE_CONDITION(&mFeatures, asyncCommandBufferResetAndGarbageCleanup, true);
5378 
5379     ANGLE_FEATURE_CONDITION(&mFeatures, supportsYUVSamplerConversion,
5380                             mSamplerYcbcrConversionFeatures.samplerYcbcrConversion != VK_FALSE);
5381 
5382     ANGLE_FEATURE_CONDITION(&mFeatures, supportsShaderFloat16,
5383                             mShaderFloat16Int8Features.shaderFloat16 == VK_TRUE);
5384     ANGLE_FEATURE_CONDITION(&mFeatures, supportsShaderInt8,
5385                             mShaderFloat16Int8Features.shaderInt8 == VK_TRUE);
5386 
5387     ANGLE_FEATURE_CONDITION(&mFeatures, supportsShaderFloat64,
5388                             mPhysicalDeviceFeatures.shaderFloat64 == VK_TRUE);
5389 
5390     // Prefer driver uniforms over specialization constants in the following:
5391     //
5392     // - Older Qualcomm drivers where specialization constants severely degrade the performance of
5393     //   pipeline creation.  http://issuetracker.google.com/173636783
5394     // - ARM hardware
5395     // - Imagination hardware
5396     // - Samsung hardware
5397     // - SwiftShader
5398     //
5399     ANGLE_FEATURE_CONDITION(
5400         &mFeatures, preferDriverUniformOverSpecConst,
5401         (isQualcommProprietary && driverVersion < angle::VersionTriple(512, 513, 0)) || isARM ||
5402             isPowerVR || isSamsung || isSwiftShader);
5403 
5404     ANGLE_FEATURE_CONDITION(&mFeatures, preferCachedNoncoherentForDynamicStreamBufferUsage,
5405                             IsMeteorLake(mPhysicalDeviceProperties.deviceID));
5406 
5407     // The compute shader used to generate mipmaps needs -
5408     // 1. subgroup quad operations in compute shader stage.
5409     // 2. subgroup operations that can use extended types.
5410     // 3. 256-wide workgroup.
5411     //
5412     // Furthermore, VK_IMAGE_USAGE_STORAGE_BIT is detrimental to performance on many platforms, on
5413     // which this path is not enabled.  Platforms that are known to have better performance with
5414     // this path are:
5415     //
5416     // - AMD
5417     // - Nvidia
5418     // - Samsung
5419     //
5420     // Additionally, this path is disabled on buggy drivers:
5421     //
5422     // - AMD/Windows: Unfortunately the trybots use ancient AMD cards and drivers.
5423     const bool supportsSubgroupQuadOpsInComputeShader =
5424         (mSubgroupProperties.supportedStages & VK_SHADER_STAGE_COMPUTE_BIT) &&
5425         (mSubgroupProperties.supportedOperations & VK_SUBGROUP_FEATURE_QUAD_BIT);
5426 
5427     const uint32_t maxComputeWorkGroupInvocations =
5428         mPhysicalDeviceProperties.limits.maxComputeWorkGroupInvocations;
5429 
5430     ANGLE_FEATURE_CONDITION(&mFeatures, allowGenerateMipmapWithCompute,
5431                             supportsSubgroupQuadOpsInComputeShader &&
5432                                 mSubgroupExtendedTypesFeatures.shaderSubgroupExtendedTypes &&
5433                                 maxComputeWorkGroupInvocations >= 256 &&
5434                                 ((isAMD && !IsWindows()) || isNvidia || isSamsung));
5435 
5436     bool isAdreno540 = mPhysicalDeviceProperties.deviceID == angle::kDeviceID_Adreno540;
5437     ANGLE_FEATURE_CONDITION(&mFeatures, forceMaxUniformBufferSize16KB,
5438                             isQualcommProprietary && isAdreno540);
5439 
5440     ANGLE_FEATURE_CONDITION(
5441         &mFeatures, supportsImageFormatList,
5442         ExtensionFound(VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME, deviceExtensionNames));
5443 
5444     ANGLE_FEATURE_CONDITION(
5445         &mFeatures, supportsSamplerMirrorClampToEdge,
5446         ExtensionFound(VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME, deviceExtensionNames));
5447 
5448     // Emulation of GL_EXT_multisampled_render_to_texture is only really useful on tiling hardware,
5449     // but is exposed on any configuration deployed on Android, such as Samsung's AMD-based GPU.
5450     //
5451     // During testing, it was also discovered that emulation triggers bugs on some platforms:
5452     //
5453     // - Swiftshader:
5454     //   * Failure on mac: http://anglebug.com/40644747
5455     //   * OOM: http://crbug.com/1263046
5456     // - Intel on windows: http://anglebug.com/42263602
5457     // - AMD on windows: http://crbug.com/1132366
5458     // - Old ARM drivers on Android fail multiple tests, though newer drivers don't (although they
5459     //   support MSRTSS and emulation is unnecessary)
5460     //
5461     ANGLE_FEATURE_CONDITION(&mFeatures, allowMultisampledRenderToTextureEmulation,
5462                             (isTileBasedRenderer && !isARM) || isSamsung);
5463     ANGLE_FEATURE_CONDITION(&mFeatures, enableMultisampledRenderToTexture,
5464                             mFeatures.supportsMultisampledRenderToSingleSampled.enabled ||
5465                                 (mFeatures.supportsDepthStencilResolve.enabled &&
5466                                  mFeatures.allowMultisampledRenderToTextureEmulation.enabled));
5467 
5468     // Currently we enable cube map arrays based on the imageCubeArray Vk feature.
5469     // TODO: Check device caps for full cube map array support. http://anglebug.com/42263705
5470     ANGLE_FEATURE_CONDITION(&mFeatures, supportsImageCubeArray,
5471                             mPhysicalDeviceFeatures.imageCubeArray == VK_TRUE);
5472 
5473     ANGLE_FEATURE_CONDITION(&mFeatures, supportsPipelineStatisticsQuery,
5474                             mPhysicalDeviceFeatures.pipelineStatisticsQuery == VK_TRUE);
5475 
5476     ANGLE_FEATURE_CONDITION(&mFeatures, allowPipelineStatisticsForPrimitivesGeneratedQuery,
5477                             mFeatures.supportsPipelineStatisticsQuery.enabled && isSamsung);
5478 
5479     // Android mistakenly destroys the old swapchain when creating a new one.
5480     ANGLE_FEATURE_CONDITION(&mFeatures, waitIdleBeforeSwapchainRecreation, IsAndroid() && isARM);
5481 
5482     ANGLE_FEATURE_CONDITION(&mFeatures, destroyOldSwapchainInSharedPresentMode, IsAndroid());
5483 
5484     // vkCmdClearAttachments races with draw calls on Qualcomm hardware as observed on Pixel2 and
5485     // Pixel4.  https://issuetracker.google.com/issues/166809097
5486     ANGLE_FEATURE_CONDITION(
5487         &mFeatures, preferDrawClearOverVkCmdClearAttachments,
5488         isQualcommProprietary && driverVersion < angle::VersionTriple(512, 762, 12));
5489 
5490     // R32F imageAtomicExchange emulation is done if shaderImageFloat32Atomics feature is not
5491     // supported.
5492     ANGLE_FEATURE_CONDITION(&mFeatures, emulateR32fImageAtomicExchange,
5493                             mShaderAtomicFloatFeatures.shaderImageFloat32Atomics != VK_TRUE);
5494 
5495     // Whether non-conformant configurations and extensions should be exposed.
5496     ANGLE_FEATURE_CONDITION(&mFeatures, exposeNonConformantExtensionsAndVersions,
5497                             kExposeNonConformantExtensionsAndVersions);
5498 
5499     // http://issuetracker.google.com/376899587
5500     // Currently some testing platforms do not fully support ES 3.2 due to lack of certain features
5501     // or extensions. For the purpose of testing coverage, we would still enable ES 3.2 on these
5502     // platforms. However, once a listed test platform is updated to a version that does support
5503     // ES 3.2, it should be unlisted.
5504     ANGLE_FEATURE_CONDITION(
5505         &mFeatures, exposeES32ForTesting,
5506         mFeatures.exposeNonConformantExtensionsAndVersions.enabled &&
5507             (isSwiftShader ||
5508              IsPixel4(mPhysicalDeviceProperties.vendorID, mPhysicalDeviceProperties.deviceID) ||
5509              (IsLinux() && isNvidia && driverVersion < angle::VersionTriple(441, 0, 0)) ||
5510              (IsWindows() && isIntel)));
5511 
5512     ANGLE_FEATURE_CONDITION(
5513         &mFeatures, supportsMemoryBudget,
5514         ExtensionFound(VK_EXT_MEMORY_BUDGET_EXTENSION_NAME, deviceExtensionNames));
5515 
5516     // Disabled by default. Only enable it for experimental purpose, as this will cause various
5517     // tests to fail.
5518     ANGLE_FEATURE_CONDITION(&mFeatures, forceFragmentShaderPrecisionHighpToMediump, false);
5519 
5520     // Testing shows that on ARM and Qualcomm GPU, doing implicit flush at framebuffer boundary
5521     // improves performance. Most app traces shows frame time reduced and manhattan 3.1 offscreen
5522     // score improves 7%.
5523     ANGLE_FEATURE_CONDITION(&mFeatures, preferSubmitAtFBOBoundary,
5524                             isTileBasedRenderer || isSwiftShader);
5525 
5526     // In order to support immutable samplers tied to external formats, we need to overallocate
5527     // descriptor counts for such immutable samplers
5528     ANGLE_FEATURE_CONDITION(&mFeatures, useMultipleDescriptorsForExternalFormats, true);
5529 
5530     // http://anglebug.com/42265147
5531     // When creating a surface with the format GL_RGB8, override the format to be GL_RGBA8, since
5532     // Android prevents creating swapchain images with VK_FORMAT_R8G8B8_UNORM.
5533     // Do this for all platforms, since few (none?) IHVs support 24-bit formats with their HW
5534     // natively anyway.
5535     ANGLE_FEATURE_CONDITION(&mFeatures, overrideSurfaceFormatRGB8ToRGBA8, true);
5536 
5537     // We set the following when there is color framebuffer fetch:
5538     //
5539     // - VK_PIPELINE_COLOR_BLEND_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_BIT_EXT
5540     // - VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_COLOR_ACCESS_BIT_EXT
5541     //
5542     // and the following with depth/stencil framebuffer fetch:
5543     //
5544     // - VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_EXT
5545     // -
5546     // VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_EXT
5547     //
5548     // But the check for framebuffer fetch is not accurate enough and those bits can have great
5549     // impact on Qualcomm (it only affects the open source driver because the proprietary driver
5550     // does not expose the extension).  Let's disable it on Qualcomm.
5551     //
5552     // https://issuetracker.google.com/issues/255837430
5553     ANGLE_FEATURE_CONDITION(
5554         &mFeatures, supportsRasterizationOrderAttachmentAccess,
5555         !isQualcomm &&
5556             mRasterizationOrderAttachmentAccessFeatures.rasterizationOrderColorAttachmentAccess ==
5557                 VK_TRUE);
5558 
5559     // The VK_EXT_surface_maintenance1 and VK_EXT_swapchain_maintenance1 extensions are used for a
5560     // variety of improvements:
5561     //
5562     // - Recycling present semaphores
5563     // - Avoiding swapchain recreation when present modes change
5564     // - Amortizing the cost of memory allocation for swapchain creation over multiple frames
5565     //
5566     ANGLE_FEATURE_CONDITION(&mFeatures, supportsSwapchainMaintenance1,
5567                             mSwapchainMaintenance1Features.swapchainMaintenance1 == VK_TRUE &&
5568                                 useVulkanSwapchain == UseVulkanSwapchain::Yes);
5569 
5570     // The VK_EXT_legacy_dithering extension enables dithering support without emulation
5571     // Disable the usage of VK_EXT_legacy_dithering on ARM until the driver bug
5572     // http://issuetracker.google.com/293136916, http://issuetracker.google.com/292282210 are fixed.
5573     ANGLE_FEATURE_CONDITION(&mFeatures, supportsLegacyDithering,
5574                             mDitheringFeatures.legacyDithering == VK_TRUE);
5575 
5576     // Applications on Android have come to rely on hardware dithering, and visually regress without
5577     // it.  On desktop GPUs, OpenGL's dithering is a no-op.  The following setting mimics that
5578     // behavior.  Dithering is also currently not enabled on SwiftShader, but can be as needed
5579     // (which would require Chromium and Capture/Replay test expectations updates).
5580     ANGLE_FEATURE_CONDITION(&mFeatures, emulateDithering,
5581                             IsAndroid() && !mFeatures.supportsLegacyDithering.enabled);
5582 
5583     // Enable additional blend factors when dithering for Samsung
5584     ANGLE_FEATURE_CONDITION(&mFeatures, enableAdditionalBlendFactorsForDithering, isSamsung);
5585 
5586     ANGLE_FEATURE_CONDITION(&mFeatures, adjustClearColorPrecision,
5587                             IsAndroid() && mFeatures.supportsLegacyDithering.enabled && isARM &&
5588                                 driverVersion < angle::VersionTriple(50, 0, 0));
5589 
5590     // ANGLE always exposes framebuffer fetch because too many apps assume it's there.  See comments
5591     // on |mIsColorFramebufferFetchCoherent| for details.  Non-coherent framebuffer fetch is always
5592     // supported by Vulkan.
5593     //
5594     // Without exposeNonConformantExtensionsAndVersions, this feature is disable on Intel/windows
5595     // due to lack of input attachment support for swapchain images, and Intel/mesa before mesa
5596     // 22.0 for the same reason.  Without VK_GOOGLE_surfaceless_query, there is no way to
5597     // automatically deduce this support.
5598     //
5599     // http://issuetracker.google.com/376899587
5600     // Advanced blend emulation depends on this functionality, lack of which prevents support for
5601     // ES 3.2; exposeNonConformantExtensionsAndVersions is used to force this.
5602     const bool supportsFramebufferFetchInSurface =
5603         IsAndroid() || !isIntel ||
5604         (isIntel && IsLinux() && driverVersion >= angle::VersionTriple(22, 0, 0)) ||
5605         mFeatures.exposeNonConformantExtensionsAndVersions.enabled;
5606 
5607     ANGLE_FEATURE_CONDITION(&mFeatures, supportsShaderFramebufferFetch,
5608                             supportsFramebufferFetchInSurface);
5609     ANGLE_FEATURE_CONDITION(&mFeatures, supportsShaderFramebufferFetchNonCoherent,
5610                             supportsFramebufferFetchInSurface);
5611 
5612     // On ARM hardware, framebuffer-fetch-like behavior on Vulkan is known to be coherent even
5613     // without the Vulkan extension.
5614     //
5615     // On IMG hardware, similarly framebuffer-fetch-like behavior on Vulkan is known to be coherent,
5616     // but the Vulkan extension cannot be exposed.  This is because the Vulkan extension guarantees
5617     // coherence when accessing all samples of a pixel from any other sample, but IMG hardware is
5618     // _not_ coherent in that case.  This is not a problem for GLES because the invocation for each
5619     // sample can only access values for the same sample by reading "the current color value",
5620     // unlike Vulkan-GLSL's |subpassLoad()| which takes a sample index.
5621     mIsColorFramebufferFetchCoherent =
5622         isARM || isPowerVR || mFeatures.supportsRasterizationOrderAttachmentAccess.enabled;
5623 
5624     // Support EGL_KHR_lock_surface3 extension.
5625     ANGLE_FEATURE_CONDITION(&mFeatures, supportsLockSurfaceExtension, IsAndroid());
5626 
5627     // http://anglebug.com/42265370
5628     // Android needs swapbuffers to update image and present to display.
5629     ANGLE_FEATURE_CONDITION(&mFeatures, swapbuffersOnFlushOrFinishWithSingleBuffer, IsAndroid());
5630 
5631     // Workaround a Qualcomm imprecision with dithering
5632     ANGLE_FEATURE_CONDITION(&mFeatures, roundOutputAfterDithering, isQualcomm);
5633 
5634     // GL_KHR_blend_equation_advanced is emulated when the equivalent Vulkan extension is not
5635     // usable.
5636     ANGLE_FEATURE_CONDITION(
5637         &mFeatures, emulateAdvancedBlendEquations,
5638         !mFeatures.supportsBlendOperationAdvanced.enabled && supportsFramebufferFetchInSurface);
5639 
5640     // GL_KHR_blend_equation_advanced_coherent ensures that the blending operations are performed in
5641     // API primitive order.
5642     ANGLE_FEATURE_CONDITION(
5643         &mFeatures, supportsBlendOperationAdvancedCoherent,
5644         mFeatures.supportsBlendOperationAdvanced.enabled &&
5645             mBlendOperationAdvancedFeatures.advancedBlendCoherentOperations == VK_TRUE);
5646 
5647     // http://anglebug.com/42265410
5648     // Android expects VkPresentRegionsKHR rectangles with a bottom-left origin, while spec
5649     // states they should have a top-left origin.
5650     ANGLE_FEATURE_CONDITION(&mFeatures, bottomLeftOriginPresentRegionRectangles, IsAndroid());
5651 
5652     // Use VMA for image suballocation.
5653     ANGLE_FEATURE_CONDITION(&mFeatures, useVmaForImageSuballocation, true);
5654 
5655     // Emit SPIR-V 1.4 when supported.  The following old drivers have various bugs with SPIR-V 1.4:
5656     //
5657     // - Nvidia drivers - Crashes when creating pipelines, not using any SPIR-V 1.4 features.  Known
5658     //                    good since at least version 525.  http://anglebug.com/343249127
5659     // - Qualcomm drivers - Crashes when creating pipelines in the presence of OpCopyLogical with
5660     //                      some types.  http://anglebug.com/343218484
5661     // - ARM drivers - Fail tests when OpSelect uses a scalar to select between vectors.  Known good
5662     //                 since at least version 47.  http://anglebug.com/343218491
5663     ANGLE_FEATURE_CONDITION(&mFeatures, supportsSPIRV14,
5664                             ExtensionFound(VK_KHR_SPIRV_1_4_EXTENSION_NAME, deviceExtensionNames) &&
5665                                 !(isNvidia && driverVersion < angle::VersionTriple(525, 0, 0)) &&
5666                                 !isQualcommProprietary &&
5667                                 !(isARM && driverVersion < angle::VersionTriple(47, 0, 0)));
5668 
5669     // Rounding features from VK_KHR_float_controls extension
5670     ANGLE_FEATURE_CONDITION(&mFeatures, supportsDenormFtzFp16,
5671                             mFloatControlProperties.shaderDenormFlushToZeroFloat16 == VK_TRUE);
5672     ANGLE_FEATURE_CONDITION(&mFeatures, supportsDenormFtzFp32,
5673                             mFloatControlProperties.shaderDenormFlushToZeroFloat32 == VK_TRUE);
5674     ANGLE_FEATURE_CONDITION(&mFeatures, supportsDenormFtzFp64,
5675                             mFloatControlProperties.shaderDenormFlushToZeroFloat64 == VK_TRUE);
5676     ANGLE_FEATURE_CONDITION(&mFeatures, supportsDenormPreserveFp16,
5677                             mFloatControlProperties.shaderDenormPreserveFloat16 == VK_TRUE);
5678     ANGLE_FEATURE_CONDITION(&mFeatures, supportsDenormPreserveFp32,
5679                             mFloatControlProperties.shaderDenormPreserveFloat32 == VK_TRUE);
5680     ANGLE_FEATURE_CONDITION(&mFeatures, supportsDenormPreserveFp64,
5681                             mFloatControlProperties.shaderDenormPreserveFloat64 == VK_TRUE);
5682     ANGLE_FEATURE_CONDITION(&mFeatures, supportsRoundingModeRteFp16,
5683                             mFloatControlProperties.shaderRoundingModeRTEFloat16 == VK_TRUE);
5684     ANGLE_FEATURE_CONDITION(&mFeatures, supportsRoundingModeRteFp32,
5685                             mFloatControlProperties.shaderRoundingModeRTEFloat32 == VK_TRUE);
5686     ANGLE_FEATURE_CONDITION(&mFeatures, supportsRoundingModeRteFp64,
5687                             mFloatControlProperties.shaderRoundingModeRTEFloat64 == VK_TRUE);
5688     ANGLE_FEATURE_CONDITION(&mFeatures, supportsRoundingModeRtzFp16,
5689                             mFloatControlProperties.shaderRoundingModeRTZFloat16 == VK_TRUE);
5690     ANGLE_FEATURE_CONDITION(&mFeatures, supportsRoundingModeRtzFp32,
5691                             mFloatControlProperties.shaderRoundingModeRTZFloat32 == VK_TRUE);
5692     ANGLE_FEATURE_CONDITION(&mFeatures, supportsRoundingModeRtzFp64,
5693                             mFloatControlProperties.shaderRoundingModeRTZFloat64 == VK_TRUE);
5694     ANGLE_FEATURE_CONDITION(
5695         &mFeatures, supportsSignedZeroInfNanPreserveFp16,
5696         mFloatControlProperties.shaderSignedZeroInfNanPreserveFloat16 == VK_TRUE);
5697     ANGLE_FEATURE_CONDITION(
5698         &mFeatures, supportsSignedZeroInfNanPreserveFp32,
5699         mFloatControlProperties.shaderSignedZeroInfNanPreserveFloat32 == VK_TRUE);
5700     ANGLE_FEATURE_CONDITION(
5701         &mFeatures, supportsSignedZeroInfNanPreserveFp64,
5702         mFloatControlProperties.shaderSignedZeroInfNanPreserveFloat64 == VK_TRUE);
5703 
5704     // Retain debug info in SPIR-V blob.
5705     ANGLE_FEATURE_CONDITION(&mFeatures, retainSPIRVDebugInfo, getEnableValidationLayers());
5706 
5707     // For discrete GPUs, most of device local memory is host invisible. We should not force the
5708     // host visible flag for them and result in allocation failure.
5709     ANGLE_FEATURE_CONDITION(
5710         &mFeatures, preferDeviceLocalMemoryHostVisible,
5711         canPreferDeviceLocalMemoryHostVisible(mPhysicalDeviceProperties.deviceType));
5712 
5713     // Multiple dynamic state issues on ARM have been fixed.
5714     // http://issuetracker.google.com/285124778
5715     // http://issuetracker.google.com/285196249
5716     // http://issuetracker.google.com/286224923
5717     // http://issuetracker.google.com/287318431
5718     //
5719     // On Pixel devices, the issues have been fixed since r44, but on others since r44p1.
5720     //
5721     // Regressions have been detected using r46 on older architectures though
5722     // http://issuetracker.google.com/336411904
5723     const bool isExtendedDynamicStateBuggy =
5724         (isARM && driverVersion < angle::VersionTriple(44, 1, 0)) ||
5725         (isMaliJobManagerBasedGPU && driverVersion >= angle::VersionTriple(46, 0, 0));
5726 
5727     // Vertex input binding stride is buggy for Windows/Intel drivers before 100.9684.
5728     const bool isVertexInputBindingStrideBuggy =
5729         IsWindows() && isIntel && driverVersion < angle::VersionTriple(100, 9684, 0);
5730 
5731     // Intel driver has issues with VK_EXT_vertex_input_dynamic_state
5732     // http://anglebug.com/42265637#comment9
5733     //
5734     // On ARM drivers prior to r48, |vkCmdBindVertexBuffers2| applies strides to the wrong index,
5735     // according to the errata: https://developer.arm.com/documentation/SDEN-3735689/0100/?lang=en
5736     //
5737     // On Qualcomm drivers prior to 777, this feature had a bug.
5738     // http://anglebug.com/381384988
5739     ANGLE_FEATURE_CONDITION(
5740         &mFeatures, supportsVertexInputDynamicState,
5741         mVertexInputDynamicStateFeatures.vertexInputDynamicState == VK_TRUE &&
5742             !(IsWindows() && isIntel) &&
5743             !(isARM && driverVersion < angle::VersionTriple(48, 0, 0)) &&
5744             !(isQualcommProprietary && driverVersion < angle::VersionTriple(512, 777, 0)));
5745 
5746     ANGLE_FEATURE_CONDITION(&mFeatures, supportsExtendedDynamicState,
5747                             mExtendedDynamicStateFeatures.extendedDynamicState == VK_TRUE &&
5748                                 !isExtendedDynamicStateBuggy);
5749 
5750     // VK_EXT_vertex_input_dynamic_state enables dynamic state for the full vertex input state. As
5751     // such, when available use supportsVertexInputDynamicState instead of
5752     // useVertexInputBindingStrideDynamicState.
5753     ANGLE_FEATURE_CONDITION(&mFeatures, useVertexInputBindingStrideDynamicState,
5754                             mFeatures.supportsExtendedDynamicState.enabled &&
5755                                 !mFeatures.supportsVertexInputDynamicState.enabled &&
5756                                 !isExtendedDynamicStateBuggy && !isVertexInputBindingStrideBuggy);
5757     // On ARM drivers prior to r52, |vkCmdSetCullMode| incorrectly culls non-triangle topologies,
5758     // according to the errata: https://developer.arm.com/documentation/SDEN-3735689/0100/?lang=en
5759     ANGLE_FEATURE_CONDITION(&mFeatures, useCullModeDynamicState,
5760                             mFeatures.supportsExtendedDynamicState.enabled &&
5761                                 !isExtendedDynamicStateBuggy &&
5762                                 !(isARM && driverVersion < angle::VersionTriple(52, 0, 0)));
5763     ANGLE_FEATURE_CONDITION(&mFeatures, useDepthCompareOpDynamicState,
5764                             mFeatures.supportsExtendedDynamicState.enabled);
5765     ANGLE_FEATURE_CONDITION(&mFeatures, useDepthTestEnableDynamicState,
5766                             mFeatures.supportsExtendedDynamicState.enabled);
5767     ANGLE_FEATURE_CONDITION(
5768         &mFeatures, useDepthWriteEnableDynamicState,
5769         mFeatures.supportsExtendedDynamicState.enabled && !isExtendedDynamicStateBuggy);
5770     ANGLE_FEATURE_CONDITION(&mFeatures, useFrontFaceDynamicState,
5771                             mFeatures.supportsExtendedDynamicState.enabled);
5772     ANGLE_FEATURE_CONDITION(&mFeatures, useStencilOpDynamicState,
5773                             mFeatures.supportsExtendedDynamicState.enabled);
5774     ANGLE_FEATURE_CONDITION(&mFeatures, useStencilTestEnableDynamicState,
5775                             mFeatures.supportsExtendedDynamicState.enabled);
5776 
5777     ANGLE_FEATURE_CONDITION(&mFeatures, supportsExtendedDynamicState2,
5778                             mExtendedDynamicState2Features.extendedDynamicState2 == VK_TRUE &&
5779                                 !isExtendedDynamicStateBuggy);
5780 
5781     ANGLE_FEATURE_CONDITION(
5782         &mFeatures, usePrimitiveRestartEnableDynamicState,
5783         mFeatures.supportsExtendedDynamicState2.enabled && !isExtendedDynamicStateBuggy);
5784     ANGLE_FEATURE_CONDITION(&mFeatures, useRasterizerDiscardEnableDynamicState,
5785                             mFeatures.supportsExtendedDynamicState2.enabled);
5786     ANGLE_FEATURE_CONDITION(&mFeatures, useDepthBiasEnableDynamicState,
5787                             mFeatures.supportsExtendedDynamicState2.enabled);
5788 
5789     // Disabled on Intel/Mesa due to driver bug (crbug.com/1379201).  This bug is fixed since Mesa
5790     // 22.2.0.
5791     ANGLE_FEATURE_CONDITION(
5792         &mFeatures, supportsLogicOpDynamicState,
5793         mFeatures.supportsExtendedDynamicState2.enabled &&
5794             mExtendedDynamicState2Features.extendedDynamicState2LogicOp == VK_TRUE &&
5795             !(IsLinux() && isIntel && driverVersion < angle::VersionTriple(22, 2, 0)) &&
5796             !(IsAndroid() && isGalaxyS23));
5797 
5798     // Older Samsung drivers with version < 24.0.0 have a bug in imageless framebuffer support.
5799     const bool isSamsungDriverWithImagelessFramebufferBug =
5800         isSamsung && driverVersion < angle::VersionTriple(24, 0, 0);
5801     // Qualcomm with imageless framebuffers, vkCreateFramebuffer loops forever.
5802     // http://issuetracker.google.com/369693310
5803     const bool isQualcommWithImagelessFramebufferBug =
5804         isQualcommProprietary && driverVersion < angle::VersionTriple(512, 802, 0);
5805     // Some ARM-based phones with the 38.0 and 38.1 driver crash when creating imageless
5806     // framebuffers.
5807     const bool isArmDriverWithImagelessFramebufferBug =
5808         isARM && driverVersion >= angle::VersionTriple(38, 0, 0) &&
5809         driverVersion < angle::VersionTriple(38, 2, 0);
5810     // PowerVR with imageless framebuffer spends enormous amounts of time in framebuffer destruction
5811     // and creation. ANGLE doesn't cache imageless framebuffers, instead adding them to garbage
5812     // collection, expecting them to be lightweight.
5813     // http://issuetracker.google.com/372273294
5814     ANGLE_FEATURE_CONDITION(&mFeatures, supportsImagelessFramebuffer,
5815                             mImagelessFramebufferFeatures.imagelessFramebuffer == VK_TRUE &&
5816                                 !isSamsungDriverWithImagelessFramebufferBug &&
5817                                 !isArmDriverWithImagelessFramebufferBug &&
5818                                 !isQualcommWithImagelessFramebufferBug && !isPowerVR);
5819 
5820     if (ExtensionFound(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME, deviceExtensionNames))
5821     {
5822         queryAndCacheFragmentShadingRates();
5823     }
5824 
5825     // Support GL_QCOM_shading_rate extension
5826     ANGLE_FEATURE_CONDITION(&mFeatures, supportsFragmentShadingRate,
5827                             canSupportFragmentShadingRate());
5828 
5829     // Support QCOM foveated rendering extensions.
5830     // Gated on supportsImagelessFramebuffer and supportsRenderPassLoadStoreOpNone
5831     // to reduce code complexity.
5832     ANGLE_FEATURE_CONDITION(&mFeatures, supportsFoveatedRendering,
5833                             mFeatures.supportsImagelessFramebuffer.enabled &&
5834                                 mFeatures.supportsRenderPassLoadStoreOpNone.enabled &&
5835                                 mFeatures.supportsFragmentShadingRate.enabled &&
5836                                 canSupportFoveatedRendering());
5837 
5838     // Force CPU based generation of fragment shading rate attachment data if
5839     // VkPhysicalDeviceFeatures::shaderStorageImageExtendedFormats is not supported
5840     ANGLE_FEATURE_CONDITION(&mFeatures, generateFragmentShadingRateAttchementWithCpu,
5841                             mPhysicalDeviceFeatures.shaderStorageImageExtendedFormats != VK_TRUE);
5842 
5843     // We can use the interlock to support GL_ANGLE_shader_pixel_local_storage_coherent.
5844     ANGLE_FEATURE_CONDITION(
5845         &mFeatures, supportsFragmentShaderPixelInterlock,
5846         mFragmentShaderInterlockFeatures.fragmentShaderPixelInterlock == VK_TRUE);
5847 
5848     // The VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_EXT behavior is used by
5849     // ANGLE, which requires the robustBufferAccess feature to be available.
5850     ANGLE_FEATURE_CONDITION(&mFeatures, supportsPipelineRobustness,
5851                             mPipelineRobustnessFeatures.pipelineRobustness == VK_TRUE &&
5852                                 mPhysicalDeviceFeatures.robustBufferAccess);
5853 
5854     ANGLE_FEATURE_CONDITION(&mFeatures, supportsPipelineProtectedAccess,
5855                             mPipelineProtectedAccessFeatures.pipelineProtectedAccess == VK_TRUE &&
5856                                 mProtectedMemoryFeatures.protectedMemory == VK_TRUE);
5857 
5858     // VK_EXT_graphics_pipeline_library is available on NVIDIA drivers earlier
5859     // than version 531, but there are transient visual glitches with rendering
5860     // on those earlier versions.  http://anglebug.com/42266655
5861     //
5862     // On RADV, creating graphics pipeline can crash in the driver.  http://crbug.com/1497512
5863     ANGLE_FEATURE_CONDITION(&mFeatures, supportsGraphicsPipelineLibrary,
5864                             mGraphicsPipelineLibraryFeatures.graphicsPipelineLibrary == VK_TRUE &&
5865                                 (!isNvidia || driverVersion >= angle::VersionTriple(531, 0, 0)) &&
5866                                 !isRADV);
5867 
5868     // When VK_EXT_graphics_pipeline_library is not used:
5869     //
5870     //   The following drivers are known to key the pipeline cache blobs with vertex input and
5871     //   fragment output state, causing draw-time pipeline creation to miss the cache regardless of
5872     //   warm up:
5873     //
5874     //     - ARM drivers
5875     //     - Imagination drivers
5876     //
5877     //   The following drivers are instead known to _not_ include said state, and hit the cache at
5878     //   draw time.
5879     //
5880     //     - SwiftShader
5881     //     - Open source Qualcomm drivers
5882     //
5883     //   The situation is unknown for other drivers.
5884     //
5885     //   Additionally, numerous tests that previously never created a Vulkan pipeline fail or crash
5886     //   on proprietary Qualcomm drivers when they do during cache warm up.  On Intel/Linux, one
5887     //   trace shows flakiness with this.
5888     //
5889     // When VK_EXT_graphics_pipeline_library is used, warm up is always enabled as the chances of
5890     // blobs being reused is very high.
5891     const bool libraryBlobsAreReusedByMonolithicPipelines = !isARM && !isPowerVR;
5892     ANGLE_FEATURE_CONDITION(
5893         &mFeatures, warmUpPipelineCacheAtLink,
5894         mFeatures.supportsGraphicsPipelineLibrary.enabled ||
5895             (libraryBlobsAreReusedByMonolithicPipelines && !isQualcommProprietary &&
5896              !(IsLinux() && isIntel) && !(IsChromeOS() && isSwiftShader)));
5897 
5898     // On SwiftShader, no data is retrieved from the pipeline cache, so there is no reason to
5899     // serialize it or put it in the blob cache.
5900     // For Windows NVIDIA Vulkan driver, Vulkan pipeline cache will only generate one
5901     // single huge cache for one process shared by all graphics pipelines in the same process,
5902     // which can be huge. zlib take long time to compress it.
5903     ANGLE_FEATURE_CONDITION(&mFeatures, skipPipelineCacheSerialization, isSwiftShader || isNvidia);
5904 
5905     // Practically all drivers still prefer to do cross-stage linking.
5906     // graphicsPipelineLibraryFastLinking allows them to quickly produce working pipelines, but it
5907     // is typically not as efficient as complete pipelines.
5908     //
5909     // Unfortunately, the monolithic pipeline is not required to produce the exact same output as
5910     // linked-pipelines, which violates OpenGL ES rules:
5911     //
5912     //   Rule 4 The same vertex or fragment shader will produce the same result when run multiple
5913     //   times with the same input. The wording 'the same shader' means a program object that is
5914     //   populated with the same source strings, which are compiled and then linked, possibly
5915     //   multiple times, and which program object is then executed using the same GL state vector.
5916     //   Invariance is relaxed for shaders with side effects, such as image stores, image atomic
5917     //   operations, or accessing atomic counters (see section A.5)
5918     //
5919     // For that reason, this feature is disabled by default.  An application that does not rely on
5920     // the above rule and would like to benefit from the gains may override this.
5921     ANGLE_FEATURE_CONDITION(&mFeatures, preferMonolithicPipelinesOverLibraries,
5922                             mFeatures.supportsGraphicsPipelineLibrary.enabled && false);
5923 
5924     // Whether the pipeline caches should merge into the global pipeline cache.  This should only be
5925     // enabled on platforms if:
5926     //
5927     // - VK_EXT_graphics_pipeline_library is not supported.  In that case, only the program's cache
5928     //   used during warm up is merged into the global cache for later monolithic pipeline creation.
5929     // - VK_EXT_graphics_pipeline_library is supported, monolithic pipelines are preferred, and the
5930     //   driver is able to reuse blobs from partial pipelines when creating monolithic pipelines.
5931     ANGLE_FEATURE_CONDITION(&mFeatures, mergeProgramPipelineCachesToGlobalCache,
5932                             !mFeatures.supportsGraphicsPipelineLibrary.enabled ||
5933                                 (mFeatures.preferMonolithicPipelinesOverLibraries.enabled &&
5934                                  libraryBlobsAreReusedByMonolithicPipelines));
5935 
5936     ANGLE_FEATURE_CONDITION(&mFeatures, enableAsyncPipelineCacheCompression, true);
5937 
5938     // Sync monolithic pipelines to the blob cache occasionally on platforms that would benefit from
5939     // it:
5940     //
5941     // - VK_EXT_graphics_pipeline_library is not supported, and the program cache is not warmed up:
5942     //   If the pipeline cache is being warmed up at link time, the blobs corresponding to each
5943     //   program is individually retrieved and stored in the blob cache already.
5944     // - VK_EXT_graphics_pipeline_library is supported, but monolithic pipelines are still
5945     //   preferred, and the cost of syncing the large cache is acceptable.
5946     //
5947     // Otherwise monolithic pipelines are recreated on every run.
5948     const bool hasNoPipelineWarmUp = !mFeatures.supportsGraphicsPipelineLibrary.enabled &&
5949                                      !mFeatures.warmUpPipelineCacheAtLink.enabled;
5950     const bool canSyncLargeMonolithicCache =
5951         mFeatures.supportsGraphicsPipelineLibrary.enabled &&
5952         mFeatures.preferMonolithicPipelinesOverLibraries.enabled &&
5953         (!IsAndroid() || mFeatures.enableAsyncPipelineCacheCompression.enabled);
5954     ANGLE_FEATURE_CONDITION(&mFeatures, syncMonolithicPipelinesToBlobCache,
5955                             !mFeatures.skipPipelineCacheSerialization.enabled &&
5956                                 (hasNoPipelineWarmUp || canSyncLargeMonolithicCache));
5957 
5958     // Enable the feature on Samsung by default, because it has big blob cache.
5959     ANGLE_FEATURE_CONDITION(&mFeatures, useDualPipelineBlobCacheSlots, isSamsung);
5960 
5961     // Disable by default, because currently it is uncommon that blob cache supports storing
5962     // zero sized blobs (or erasing blobs).
5963     ANGLE_FEATURE_CONDITION(&mFeatures, useEmptyBlobsToEraseOldPipelineCacheFromBlobCache, false);
5964 
5965     // Assume that platform has blob cache that has LRU eviction.
5966     ANGLE_FEATURE_CONDITION(&mFeatures, hasBlobCacheThatEvictsOldItemsFirst, true);
5967     // Also assume that platform blob cache evicts only minimum number of items when it has LRU,
5968     // in which case verification is not required.
5969     ANGLE_FEATURE_CONDITION(&mFeatures, verifyPipelineCacheInBlobCache,
5970                             !mFeatures.hasBlobCacheThatEvictsOldItemsFirst.enabled);
5971 
5972     // On ARM, dynamic state for stencil write mask doesn't work correctly in the presence of
5973     // discard or alpha to coverage, if the static state provided when creating the pipeline has a
5974     // value of 0.
5975     ANGLE_FEATURE_CONDITION(&mFeatures, useNonZeroStencilWriteMaskStaticState,
5976                             isARM && driverVersion < angle::VersionTriple(43, 0, 0));
5977 
5978     // On some vendors per-sample shading is not enabled despite the presence of a Sample
5979     // decoration. Guard against this by parsing shader for "sample" decoration and explicitly
5980     // enabling per-sample shading pipeline state.
5981     ANGLE_FEATURE_CONDITION(&mFeatures, explicitlyEnablePerSampleShading, !isQualcommProprietary);
5982 
5983     ANGLE_FEATURE_CONDITION(&mFeatures, explicitlyCastMediumpFloatTo16Bit, isARM);
5984 
5985     // Force to create swapchain with continuous refresh on shared present. Disabled by default.
5986     // Only enable it on integrations without EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID passthrough.
5987     ANGLE_FEATURE_CONDITION(&mFeatures, forceContinuousRefreshOnSharedPresent, false);
5988 
5989     // Enable setting frame timestamp surface attribute on Android platform.
5990     // Frame timestamp is enabled by calling into "vkGetPastPresentationTimingGOOGLE"
5991     // which, on Android platforms, makes the necessary ANativeWindow API calls.
5992     ANGLE_FEATURE_CONDITION(&mFeatures, supportsTimestampSurfaceAttribute,
5993                             IsAndroid() && ExtensionFound(VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME,
5994                                                           deviceExtensionNames));
5995 
5996     // Only enable VK_EXT_host_image_copy on hardware where identicalMemoryTypeRequirements is set.
5997     // That lets ANGLE avoid having to fallback to non-host-copyable image allocations if the
5998     // host-copyable one fails due to out-of-that-specific-kind-of-memory.
5999     //
6000     // Disabled on Fuchsia until they upgrade their version of VVL.
6001     ANGLE_FEATURE_CONDITION(&mFeatures, supportsHostImageCopy,
6002                             mHostImageCopyFeatures.hostImageCopy == VK_TRUE &&
6003                                 mHostImageCopyProperties.identicalMemoryTypeRequirements &&
6004                                 !IsFuchsia());
6005 
6006     // 1) host vk driver does not natively support ETC format.
6007     // 2) host vk driver supports BC format.
6008     // 3) host vk driver supports subgroup instructions: clustered, shuffle.
6009     //    * This limitation can be removed if necessary.
6010     // 4) host vk driver has maxTexelBufferSize >= 64M.
6011     //    * Usually on desktop device the limit is more than 128M. we may switch to dynamic
6012     //    decide cpu or gpu upload texture based on texture size.
6013     constexpr VkSubgroupFeatureFlags kRequiredSubgroupOp =
6014         VK_SUBGROUP_FEATURE_SHUFFLE_BIT | VK_SUBGROUP_FEATURE_CLUSTERED_BIT;
6015     static constexpr bool kSupportTranscodeEtcToBc = false;
6016     static constexpr uint32_t kMaxTexelBufferSize  = 64 * 1024 * 1024;
6017     const VkPhysicalDeviceLimits &limitsVk         = mPhysicalDeviceProperties.limits;
6018     ANGLE_FEATURE_CONDITION(&mFeatures, supportsComputeTranscodeEtcToBc,
6019                             !mPhysicalDeviceFeatures.textureCompressionETC2 &&
6020                                 kSupportTranscodeEtcToBc &&
6021                                 (mSubgroupProperties.supportedOperations & kRequiredSubgroupOp) ==
6022                                     kRequiredSubgroupOp &&
6023                                 (limitsVk.maxTexelBufferElements >= kMaxTexelBufferSize));
6024 
6025     // Limit GL_MAX_SHADER_STORAGE_BLOCK_SIZE to 256MB on older ARM hardware.
6026     ANGLE_FEATURE_CONDITION(&mFeatures, limitMaxStorageBufferSize, isMaliJobManagerBasedGPU);
6027 
6028     // http://anglebug.com/42265782
6029     // Flushing mutable textures causes flakes in perf tests using Windows/Intel GPU. Failures are
6030     // due to lost context/device.
6031     // http://b/278600575
6032     // Flushing mutable texture is disabled for discrete GPUs to mitigate possible VRAM OOM.
6033     ANGLE_FEATURE_CONDITION(
6034         &mFeatures, mutableMipmapTextureUpload,
6035         canPreferDeviceLocalMemoryHostVisible(mPhysicalDeviceProperties.deviceType));
6036 
6037     // Allow passthrough of EGL colorspace attributes on Android platform and for vendors that
6038     // are known to support wide color gamut.
6039     ANGLE_FEATURE_CONDITION(&mFeatures, eglColorspaceAttributePassthrough,
6040                             IsAndroid() && isSamsung);
6041 
6042     // GBM does not have a VkSurface hence it does not support presentation through a Vulkan queue.
6043     ANGLE_FEATURE_CONDITION(&mFeatures, supportsPresentation,
6044                             nativeWindowSystem != angle::NativeWindowSystem::Gbm);
6045 
6046     // For tiled renderer, the renderpass query result may not available until the entire renderpass
6047     // is completed. This may cause a bubble in the application thread waiting result to be
6048     // available. When this feature flag is enabled, we will issue an immediate flush when we detect
6049     // there is switch from query enabled draw to query disabled draw. Since most apps uses bunch of
6050     // query back to back, this should only introduce one extra flush per frame.
6051     // https://issuetracker.google.com/250706693
6052     ANGLE_FEATURE_CONDITION(&mFeatures, preferSubmitOnAnySamplesPassedQueryEnd,
6053                             isTileBasedRenderer);
6054 
6055     // ARM driver appears having a bug that if we did not wait for submission to complete, but call
6056     // vkGetQueryPoolResults(VK_QUERY_RESULT_WAIT_BIT), it may result VK_NOT_READY.
6057     // https://issuetracker.google.com/253522366
6058     //
6059     // Workaround for nvidia earlier version driver which appears having a bug that On older nvidia
6060     // driver, vkGetQueryPoolResult() with VK_QUERY_RESULT_WAIT_BIT may result in incorrect result.
6061     // In that case we force into CPU wait for submission to complete. http://anglebug.com/42265186
6062     ANGLE_FEATURE_CONDITION(&mFeatures, forceWaitForSubmissionToCompleteForQueryResult,
6063                             isARM || (isNvidia && driverVersion < angle::VersionTriple(470, 0, 0)));
6064 
6065     // Some ARM drivers may not free memory in "vkFreeCommandBuffers()" without
6066     // VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT flag.
6067     ANGLE_FEATURE_CONDITION(&mFeatures, useResetCommandBufferBitForSecondaryPools, isARM);
6068 
6069     // Intel and AMD mesa drivers need depthBiasConstantFactor to be doubled to align with GL.
6070     ANGLE_FEATURE_CONDITION(&mFeatures, doubleDepthBiasConstantFactor,
6071                             (isIntel && !IsWindows()) || isRADV || isNvidia);
6072 
6073     // Required to pass android.media.codec.cts.EncodeDecodeTest
6074     // https://issuetracker.google.com/246218584
6075     ANGLE_FEATURE_CONDITION(
6076         &mFeatures, mapUnspecifiedColorSpaceToPassThrough,
6077         ExtensionFound(VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME, mEnabledInstanceExtensions));
6078 
6079     ANGLE_FEATURE_CONDITION(&mFeatures, enablePipelineCacheDataCompression, true);
6080 
6081     ANGLE_FEATURE_CONDITION(&mFeatures, supportsTimelineSemaphore,
6082                             mTimelineSemaphoreFeatures.timelineSemaphore == VK_TRUE);
6083 
6084     // 8bit storage features
6085     ANGLE_FEATURE_CONDITION(&mFeatures, supports8BitStorageBuffer,
6086                             m8BitStorageFeatures.storageBuffer8BitAccess == VK_TRUE);
6087 
6088     ANGLE_FEATURE_CONDITION(&mFeatures, supports8BitUniformAndStorageBuffer,
6089                             m8BitStorageFeatures.uniformAndStorageBuffer8BitAccess == VK_TRUE);
6090 
6091     ANGLE_FEATURE_CONDITION(&mFeatures, supports8BitPushConstant,
6092                             m8BitStorageFeatures.storagePushConstant8 == VK_TRUE);
6093 
6094     // 16bit storage features
6095     ANGLE_FEATURE_CONDITION(&mFeatures, supports16BitStorageBuffer,
6096                             m16BitStorageFeatures.storageBuffer16BitAccess == VK_TRUE);
6097 
6098     ANGLE_FEATURE_CONDITION(&mFeatures, supports16BitUniformAndStorageBuffer,
6099                             m16BitStorageFeatures.uniformAndStorageBuffer16BitAccess == VK_TRUE);
6100 
6101     ANGLE_FEATURE_CONDITION(&mFeatures, supports16BitPushConstant,
6102                             m16BitStorageFeatures.storagePushConstant16 == VK_TRUE);
6103 
6104     ANGLE_FEATURE_CONDITION(&mFeatures, supports16BitInputOutput,
6105                             m16BitStorageFeatures.storageInputOutput16 == VK_TRUE);
6106 
6107 #if defined(ANGLE_PLATFORM_ANDROID)
6108     ANGLE_FEATURE_CONDITION(&mFeatures, supportsExternalFormatResolve,
6109                             mExternalFormatResolveFeatures.externalFormatResolve == VK_TRUE);
6110 
6111     // We can fully support GL_EXT_YUV_target iff we have support for
6112     // VK_ANDROID_external_format_resolve and Vulkan ICD supports
6113     // nullColorAttachmentWithExternalFormatResolve. ANGLE cannot yet support vendors that lack
6114     // support for nullColorAttachmentWithExternalFormatResolve.
6115     ANGLE_FEATURE_CONDITION(
6116         &mFeatures, supportsYuvTarget,
6117         mFeatures.supportsExternalFormatResolve.enabled &&
6118             mExternalFormatResolveProperties.nullColorAttachmentWithExternalFormatResolve ==
6119                 VK_TRUE);
6120 
6121 #else
6122     ANGLE_FEATURE_CONDITION(&mFeatures, supportsExternalFormatResolve, false);
6123     ANGLE_FEATURE_CONDITION(&mFeatures, supportsYuvTarget, false);
6124 #endif
6125 
6126     // VkEvent has much bigger overhead. Until we know that it helps desktop GPUs, we restrict it to
6127     // TBRs. Also enabled for SwiftShader so that we get more test coverage in bots.
6128     ANGLE_FEATURE_CONDITION(&mFeatures, useVkEventForImageBarrier,
6129                             isTileBasedRenderer || isSwiftShader);
6130     ANGLE_FEATURE_CONDITION(&mFeatures, useVkEventForBufferBarrier,
6131                             isTileBasedRenderer || isSwiftShader);
6132 
6133     // Disable for Samsung, details here -> http://anglebug.com/386749841#comment21
6134     ANGLE_FEATURE_CONDITION(&mFeatures, supportsDynamicRendering,
6135                             mDynamicRenderingFeatures.dynamicRendering == VK_TRUE && !isSamsung);
6136 
6137     // Don't enable VK_KHR_maintenance5 without VK_KHR_dynamic_rendering
6138     ANGLE_FEATURE_CONDITION(&mFeatures, supportsMaintenance5,
6139                             mFeatures.supportsDynamicRendering.enabled &&
6140                                 mMaintenance5Features.maintenance5 == VK_TRUE);
6141 
6142     // Disabled on Nvidia driver due to a bug with attachment location mapping, resulting in
6143     // incorrect rendering in the presence of gaps in locations.  http://anglebug.com/372883691.
6144     //
6145     // Disable for Samsung, details here -> http://anglebug.com/386749841#comment21
6146     ANGLE_FEATURE_CONDITION(
6147         &mFeatures, supportsDynamicRenderingLocalRead,
6148         mDynamicRenderingLocalReadFeatures.dynamicRenderingLocalRead == VK_TRUE &&
6149             !(isNvidia || isSamsung));
6150 
6151     // Using dynamic rendering when VK_KHR_dynamic_rendering_local_read is available, because that's
6152     // needed for framebuffer fetch, MSRTT and advanced blend emulation.
6153     //
6154     // VK_EXT_legacy_dithering needs to be at version 2 and VK_KHR_maintenance5 to be usable with
6155     // dynamic rendering.  If only version 1 is exposed, it's not sacrificied for dynamic rendering
6156     // and render pass objects are continued to be used.
6157     //
6158     // Emulation of GL_EXT_multisampled_render_to_texture is not possible with dynamic rendering.
6159     // That support is also not sacrificed for dynamic rendering.
6160     //
6161     // Use of dynamic rendering is disabled on older ARM drivers due to driver bugs
6162     // (http://issuetracker.google.com/356051947).
6163     //
6164     // Use of dynamic rendering on PowerVR devices is disabled for performance reasons
6165     // (http://issuetracker.google.com/372273294).
6166     const bool hasLegacyDitheringV1 =
6167         mFeatures.supportsLegacyDithering.enabled &&
6168         (mLegacyDitheringVersion < 2 || !mFeatures.supportsMaintenance5.enabled);
6169     const bool emulatesMultisampledRenderToTexture =
6170         mFeatures.enableMultisampledRenderToTexture.enabled &&
6171         !mFeatures.supportsMultisampledRenderToSingleSampled.enabled;
6172     ANGLE_FEATURE_CONDITION(&mFeatures, preferDynamicRendering,
6173                             mFeatures.supportsDynamicRendering.enabled &&
6174                                 mFeatures.supportsDynamicRenderingLocalRead.enabled &&
6175                                 !hasLegacyDitheringV1 && !emulatesMultisampledRenderToTexture &&
6176                                 !(isARM && driverVersion < angle::VersionTriple(52, 0, 0)) &&
6177                                 !isPowerVR);
6178 
6179     // On tile-based renderers, breaking the render pass is costly.  Changing into and out of
6180     // framebuffer fetch causes the render pass to break so that the layout of the color attachments
6181     // can be adjusted.  On such hardware, the switch to framebuffer fetch mode is made permanent so
6182     // such render pass breaks don't happen.
6183     //
6184     // This only applies to legacy render passes; with dynamic rendering there is no render pass
6185     // break when switching framebuffer fetch usage.
6186     ANGLE_FEATURE_CONDITION(&mFeatures, permanentlySwitchToFramebufferFetchMode,
6187                             isTileBasedRenderer && !mFeatures.preferDynamicRendering.enabled);
6188 
6189     // Vulkan supports depth/stencil input attachments same as it does with color.
6190     // GL_ARM_shader_framebuffer_fetch_depth_stencil requires coherent behavior however, so this
6191     // extension is exposed only where coherent framebuffer fetch is available.
6192     //
6193     // Additionally, the implementation assumes VK_KHR_dynamic_rendering_local_read to avoid
6194     // complications with VkRenderPass objects.
6195     ANGLE_FEATURE_CONDITION(
6196         &mFeatures, supportsShaderFramebufferFetchDepthStencil,
6197         mFeatures.supportsShaderFramebufferFetch.enabled &&
6198             mRasterizationOrderAttachmentAccessFeatures.rasterizationOrderDepthAttachmentAccess ==
6199                 VK_TRUE &&
6200             mRasterizationOrderAttachmentAccessFeatures.rasterizationOrderStencilAttachmentAccess ==
6201                 VK_TRUE &&
6202             mFeatures.preferDynamicRendering.enabled);
6203 
6204     ANGLE_FEATURE_CONDITION(&mFeatures, supportsSynchronization2,
6205                             mSynchronization2Features.synchronization2 == VK_TRUE);
6206 
6207     // Disable descriptorSet cache for SwiftShader to ensure the code path gets tested.
6208     ANGLE_FEATURE_CONDITION(&mFeatures, descriptorSetCache, !isSwiftShader);
6209 
6210     ANGLE_FEATURE_CONDITION(&mFeatures, supportsImageCompressionControl,
6211                             mImageCompressionControlFeatures.imageCompressionControl == VK_TRUE);
6212 
6213     ANGLE_FEATURE_CONDITION(
6214         &mFeatures, supportsImageCompressionControlSwapchain,
6215         mImageCompressionControlSwapchainFeatures.imageCompressionControlSwapchain == VK_TRUE);
6216 
6217     ANGLE_FEATURE_CONDITION(&mFeatures, supportsAstcSliced3d, isARM);
6218 
6219     ANGLE_FEATURE_CONDITION(
6220         &mFeatures, supportsTextureCompressionAstcHdr,
6221         mTextureCompressionASTCHDRFeatures.textureCompressionASTC_HDR == VK_TRUE);
6222 
6223     ANGLE_FEATURE_CONDITION(
6224         &mFeatures, supportsUniformBufferStandardLayout,
6225         mUniformBufferStandardLayoutFeatures.uniformBufferStandardLayout == VK_TRUE);
6226 
6227     // Disable memory report feature overrides if extension is not supported.
6228     if ((mFeatures.logMemoryReportCallbacks.enabled || mFeatures.logMemoryReportStats.enabled) &&
6229         !mMemoryReportFeatures.deviceMemoryReport)
6230     {
6231         WARN() << "Disabling the following feature(s) because driver does not support "
6232                   "VK_EXT_device_memory_report extension:";
6233         if (getFeatures().logMemoryReportStats.enabled)
6234         {
6235             WARN() << "\tlogMemoryReportStats";
6236             mFeatures.logMemoryReportStats.applyOverride(false);
6237         }
6238         if (getFeatures().logMemoryReportCallbacks.enabled)
6239         {
6240             WARN() << "\tlogMemoryReportCallbacks";
6241             mFeatures.logMemoryReportCallbacks.applyOverride(false);
6242         }
6243     }
6244 
6245     // Check if VK implementation needs to strip-out non-semantic reflection info from shader module
6246     // (Default is to assume not supported)
6247     ANGLE_FEATURE_CONDITION(&mFeatures, supportsShaderNonSemanticInfo, false);
6248 
6249     // Don't expose these 2 extensions on Samsung devices -
6250     // 1. ANGLE_rgbx_internal_format
6251     // 2. GL_APPLE_clip_distance
6252     ANGLE_FEATURE_CONDITION(&mFeatures, supportsAngleRgbxInternalFormat, !isSamsung);
6253     ANGLE_FEATURE_CONDITION(&mFeatures, supportsAppleClipDistance, !isSamsung);
6254 
6255     // Enable the use of below native kernels
6256     // Each builtin kernel gets its own feature and condition, for now a single feature condition is
6257     // setup
6258     ANGLE_FEATURE_CONDITION(&mFeatures, usesNativeBuiltinClKernel, isSamsung);
6259 
6260     // Force enable sample usage for AHB images for Samsung
6261     ANGLE_FEATURE_CONDITION(&mFeatures, forceSampleUsageForAhbBackedImages, isSamsung);
6262 }
6263 
appBasedFeatureOverrides(const vk::ExtensionNameList & extensions)6264 void Renderer::appBasedFeatureOverrides(const vk::ExtensionNameList &extensions) {}
6265 
6266 // TODO (b/372694741): Remove once run-time control is supported.
appBasedFeatureOverridesAndroidDesktop(const vk::ExtensionNameList & extensions)6267 void Renderer::appBasedFeatureOverridesAndroidDesktop(const vk::ExtensionNameList &extensions)
6268 {
6269     if (!IsAndroid())
6270     {
6271         return;
6272     }
6273 
6274     constexpr char kHwPropAndroidDesktop[] = "android-desktop";
6275     std::string hardware =
6276             angle::GetEnvironmentVarOrAndroidProperty("ANGLE_HARDWARE", "ro.hardware");
6277     if (hardware != kHwPropAndroidDesktop)
6278     {
6279         return;
6280     }
6281 
6282     std::string pkgName = angle::GetExecutableName();
6283 
6284     // Dota Underlords
6285     // b/309028728: Disable SSO on Android
6286     if (pkgName == "com.valvesoftware.underlords")
6287     {
6288         ANGLE_FEATURE_CONDITION(&mFeatures, disableSeparateShaderObjects, true);
6289     }
6290 }
6291 
initPipelineCache(vk::ErrorContext * context,vk::PipelineCache * pipelineCache,bool * success)6292 angle::Result Renderer::initPipelineCache(vk::ErrorContext *context,
6293                                           vk::PipelineCache *pipelineCache,
6294                                           bool *success)
6295 {
6296     angle::MemoryBuffer initialData;
6297     if (!mFeatures.disablePipelineCacheLoadForTesting.enabled)
6298     {
6299         ANGLE_TRY(GetAndDecompressPipelineCacheVk(context, mGlobalOps, &initialData, success));
6300     }
6301 
6302     VkPipelineCacheCreateInfo pipelineCacheCreateInfo = {};
6303 
6304     pipelineCacheCreateInfo.sType           = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
6305     pipelineCacheCreateInfo.flags           = 0;
6306     pipelineCacheCreateInfo.initialDataSize = *success ? initialData.size() : 0;
6307     pipelineCacheCreateInfo.pInitialData    = *success ? initialData.data() : nullptr;
6308 
6309     ANGLE_VK_TRY(context, pipelineCache->init(mDevice, pipelineCacheCreateInfo));
6310 
6311     return angle::Result::Continue;
6312 }
6313 
ensurePipelineCacheInitialized(vk::ErrorContext * context)6314 angle::Result Renderer::ensurePipelineCacheInitialized(vk::ErrorContext *context)
6315 {
6316     // If it is initialized already, there is nothing to do
6317     if (mPipelineCacheInitialized)
6318     {
6319         return angle::Result::Continue;
6320     }
6321 
6322     std::unique_lock<angle::SimpleMutex> lock(mPipelineCacheMutex);
6323 
6324     // If another thread initialized it first don't redo it
6325     if (mPipelineCacheInitialized)
6326     {
6327         return angle::Result::Continue;
6328     }
6329 
6330     // We should now create the pipeline cache with the blob cache pipeline data.
6331     bool loadedFromBlobCache = false;
6332     ANGLE_TRY(initPipelineCache(context, &mPipelineCache, &loadedFromBlobCache));
6333     if (loadedFromBlobCache)
6334     {
6335         ANGLE_TRY(getLockedPipelineCacheDataIfNew(context, &mPipelineCacheSizeAtLastSync,
6336                                                   mPipelineCacheSizeAtLastSync, nullptr));
6337     }
6338 
6339     mPipelineCacheInitialized = true;
6340 
6341     return angle::Result::Continue;
6342 }
6343 
getNextPipelineCacheBlobCacheSlotIndex(size_t * previousSlotIndexOut)6344 size_t Renderer::getNextPipelineCacheBlobCacheSlotIndex(size_t *previousSlotIndexOut)
6345 {
6346     if (previousSlotIndexOut != nullptr)
6347     {
6348         *previousSlotIndexOut = mCurrentPipelineCacheBlobCacheSlotIndex;
6349     }
6350     if (getFeatures().useDualPipelineBlobCacheSlots.enabled)
6351     {
6352         mCurrentPipelineCacheBlobCacheSlotIndex = 1 - mCurrentPipelineCacheBlobCacheSlotIndex;
6353     }
6354     return mCurrentPipelineCacheBlobCacheSlotIndex;
6355 }
6356 
updatePipelineCacheChunkCount(size_t chunkCount)6357 size_t Renderer::updatePipelineCacheChunkCount(size_t chunkCount)
6358 {
6359     const size_t previousChunkCount = mPipelineCacheChunkCount;
6360     mPipelineCacheChunkCount        = chunkCount;
6361     return previousChunkCount;
6362 }
6363 
getPipelineCache(vk::ErrorContext * context,vk::PipelineCacheAccess * pipelineCacheOut)6364 angle::Result Renderer::getPipelineCache(vk::ErrorContext *context,
6365                                          vk::PipelineCacheAccess *pipelineCacheOut)
6366 {
6367     ANGLE_TRY(ensurePipelineCacheInitialized(context));
6368 
6369     angle::SimpleMutex *pipelineCacheMutex =
6370         context->getFeatures().mergeProgramPipelineCachesToGlobalCache.enabled ||
6371                 context->getFeatures().preferMonolithicPipelinesOverLibraries.enabled
6372             ? &mPipelineCacheMutex
6373             : nullptr;
6374 
6375     pipelineCacheOut->init(&mPipelineCache, pipelineCacheMutex);
6376     return angle::Result::Continue;
6377 }
6378 
mergeIntoPipelineCache(vk::ErrorContext * context,const vk::PipelineCache & pipelineCache)6379 angle::Result Renderer::mergeIntoPipelineCache(vk::ErrorContext *context,
6380                                                const vk::PipelineCache &pipelineCache)
6381 {
6382     // It is an error to call into this method when the feature is disabled.
6383     ASSERT(context->getFeatures().mergeProgramPipelineCachesToGlobalCache.enabled);
6384 
6385     vk::PipelineCacheAccess globalCache;
6386     ANGLE_TRY(getPipelineCache(context, &globalCache));
6387 
6388     globalCache.merge(this, pipelineCache);
6389 
6390     return angle::Result::Continue;
6391 }
6392 
getNativeCaps() const6393 const gl::Caps &Renderer::getNativeCaps() const
6394 {
6395     ensureCapsInitialized();
6396     return mNativeCaps;
6397 }
6398 
getNativeTextureCaps() const6399 const gl::TextureCapsMap &Renderer::getNativeTextureCaps() const
6400 {
6401     ensureCapsInitialized();
6402     return mNativeTextureCaps;
6403 }
6404 
getNativeExtensions() const6405 const gl::Extensions &Renderer::getNativeExtensions() const
6406 {
6407     ensureCapsInitialized();
6408     return mNativeExtensions;
6409 }
6410 
getNativeLimitations() const6411 const gl::Limitations &Renderer::getNativeLimitations() const
6412 {
6413     ensureCapsInitialized();
6414     return mNativeLimitations;
6415 }
6416 
getNativePixelLocalStorageOptions() const6417 const ShPixelLocalStorageOptions &Renderer::getNativePixelLocalStorageOptions() const
6418 {
6419     return mNativePLSOptions;
6420 }
6421 
initializeFrontendFeatures(angle::FrontendFeatures * features) const6422 void Renderer::initializeFrontendFeatures(angle::FrontendFeatures *features) const
6423 {
6424     const bool isSwiftShader =
6425         IsSwiftshader(mPhysicalDeviceProperties.vendorID, mPhysicalDeviceProperties.deviceID);
6426     const bool isSamsung = IsSamsung(mPhysicalDeviceProperties.vendorID);
6427 
6428     // Hopefully-temporary work-around for a crash on SwiftShader.  An Android process is turning
6429     // off GL error checking, and then asking ANGLE to write past the end of a buffer.
6430     // https://issuetracker.google.com/issues/220069903
6431     ANGLE_FEATURE_CONDITION(features, forceGlErrorChecking, (IsAndroid() && isSwiftShader));
6432 
6433     // Disable shader and program caching on Samsung devices.
6434     ANGLE_FEATURE_CONDITION(features, cacheCompiledShader, !isSamsung);
6435     ANGLE_FEATURE_CONDITION(features, disableProgramCaching, isSamsung);
6436 
6437     // https://issuetracker.google.com/292285899
6438     ANGLE_FEATURE_CONDITION(features, uncurrentEglSurfaceUponSurfaceDestroy, true);
6439 
6440     // The Vulkan backend's handling of compile and link is thread-safe
6441     ANGLE_FEATURE_CONDITION(features, compileJobIsThreadSafe, true);
6442     ANGLE_FEATURE_CONDITION(features, linkJobIsThreadSafe, true);
6443     // Always run the link's warm up job in a thread.  It's an optimization only, and does not block
6444     // the link resolution.
6445     ANGLE_FEATURE_CONDITION(features, alwaysRunLinkSubJobsThreaded, true);
6446 }
6447 
getLockedPipelineCacheDataIfNew(vk::ErrorContext * context,size_t * pipelineCacheSizeOut,size_t lastSyncSize,std::vector<uint8_t> * pipelineCacheDataOut)6448 angle::Result Renderer::getLockedPipelineCacheDataIfNew(vk::ErrorContext *context,
6449                                                         size_t *pipelineCacheSizeOut,
6450                                                         size_t lastSyncSize,
6451                                                         std::vector<uint8_t> *pipelineCacheDataOut)
6452 {
6453     // Because this function may call |getCacheData| twice, |mPipelineCacheMutex| is not passed to
6454     // |PipelineAccessCache|, and is expected to be locked once **by the caller**.
6455     mPipelineCacheMutex.assertLocked();
6456 
6457     vk::PipelineCacheAccess globalCache;
6458     globalCache.init(&mPipelineCache, nullptr);
6459 
6460     ANGLE_VK_TRY(context, globalCache.getCacheData(context, pipelineCacheSizeOut, nullptr));
6461 
6462     // If the cache data is unchanged since last sync, don't retrieve the data.  Also, make sure we
6463     // will receive enough data to hold the pipeline cache header Table 7.  Layout for pipeline
6464     // cache header version VK_PIPELINE_CACHE_HEADER_VERSION_ONE.
6465     const size_t kPipelineCacheHeaderSize = 16 + VK_UUID_SIZE;
6466     if (*pipelineCacheSizeOut <= lastSyncSize || *pipelineCacheSizeOut < kPipelineCacheHeaderSize ||
6467         pipelineCacheDataOut == nullptr)
6468     {
6469         return angle::Result::Continue;
6470     }
6471 
6472     pipelineCacheDataOut->resize(*pipelineCacheSizeOut);
6473     VkResult result =
6474         globalCache.getCacheData(context, pipelineCacheSizeOut, pipelineCacheDataOut->data());
6475     if (ANGLE_UNLIKELY(result == VK_INCOMPLETE))
6476     {
6477         WARN()
6478             << "Received VK_INCOMPLETE when retrieving pipeline cache data, which should be "
6479                "impossible as the size query was previously done under the same lock, but this is "
6480                "a recoverable error";
6481     }
6482     else
6483     {
6484         ANGLE_VK_TRY(context, result);
6485     }
6486 
6487     // If vkGetPipelineCacheData ends up writing fewer bytes than requested, shrink the buffer to
6488     // avoid leaking garbage memory and potential rejection of the data by subsequent
6489     // vkCreatePipelineCache call.  Some drivers may ignore entire buffer if there padding present.
6490     ASSERT(*pipelineCacheSizeOut <= pipelineCacheDataOut->size());
6491     pipelineCacheDataOut->resize(*pipelineCacheSizeOut);
6492 
6493     return angle::Result::Continue;
6494 }
6495 
syncPipelineCacheVk(vk::ErrorContext * context,vk::GlobalOps * globalOps,const gl::Context * contextGL)6496 angle::Result Renderer::syncPipelineCacheVk(vk::ErrorContext *context,
6497                                             vk::GlobalOps *globalOps,
6498                                             const gl::Context *contextGL)
6499 {
6500     // Skip syncing until pipeline cache is initialized.
6501     if (!mPipelineCacheInitialized)
6502     {
6503         return angle::Result::Continue;
6504     }
6505     ASSERT(mPipelineCache.valid());
6506 
6507     if (!mFeatures.syncMonolithicPipelinesToBlobCache.enabled)
6508     {
6509         return angle::Result::Continue;
6510     }
6511 
6512     if (--mPipelineCacheVkUpdateTimeout > 0)
6513     {
6514         return angle::Result::Continue;
6515     }
6516 
6517     mPipelineCacheVkUpdateTimeout = kPipelineCacheVkUpdatePeriod;
6518 
6519     ContextVk *contextVk = vk::GetImpl(contextGL);
6520 
6521     // Use worker thread pool to complete compression.
6522     // If the last task hasn't been finished, skip the syncing.
6523     if (mCompressEvent && !mCompressEvent->isReady())
6524     {
6525         ANGLE_PERF_WARNING(contextVk->getDebug(), GL_DEBUG_SEVERITY_LOW,
6526                            "Skip syncing pipeline cache data when the last task is not ready.");
6527         return angle::Result::Continue;
6528     }
6529 
6530     size_t pipelineCacheSize = 0;
6531     std::vector<uint8_t> pipelineCacheData;
6532     {
6533         std::unique_lock<angle::SimpleMutex> lock(mPipelineCacheMutex);
6534         ANGLE_TRY(getLockedPipelineCacheDataIfNew(
6535             context, &pipelineCacheSize, mPipelineCacheSizeAtLastSync, &pipelineCacheData));
6536     }
6537     if (pipelineCacheData.empty())
6538     {
6539         return angle::Result::Continue;
6540     }
6541     mPipelineCacheSizeAtLastSync = pipelineCacheSize;
6542 
6543     if (mFeatures.enableAsyncPipelineCacheCompression.enabled)
6544     {
6545         // zlib compression ratio normally ranges from 2:1 to 5:1. Set kMaxTotalSize to 64M to
6546         // ensure the size can fit into the 32MB blob cache limit on supported platforms.
6547         constexpr size_t kMaxTotalSize = 64 * 1024 * 1024;
6548 
6549         // Create task to compress.
6550         mCompressEvent = contextGL->getWorkerThreadPool()->postWorkerTask(
6551             std::make_shared<CompressAndStorePipelineCacheTask>(
6552                 globalOps, this, std::move(pipelineCacheData), kMaxTotalSize));
6553     }
6554     else
6555     {
6556         // If enableAsyncPipelineCacheCompression is disabled, to avoid the risk, set kMaxTotalSize
6557         // to 64k.
6558         constexpr size_t kMaxTotalSize = 64 * 1024;
6559         CompressAndStorePipelineCacheVk(globalOps, this, pipelineCacheData, kMaxTotalSize);
6560     }
6561 
6562     return angle::Result::Continue;
6563 }
6564 
6565 // These functions look at the mandatory format for support, and fallback to querying the device (if
6566 // necessary) to test the availability of the bits.
hasLinearImageFormatFeatureBits(angle::FormatID formatID,const VkFormatFeatureFlags featureBits) const6567 bool Renderer::hasLinearImageFormatFeatureBits(angle::FormatID formatID,
6568                                                const VkFormatFeatureFlags featureBits) const
6569 {
6570     return hasFormatFeatureBits<&VkFormatProperties::linearTilingFeatures>(formatID, featureBits);
6571 }
6572 
getLinearImageFormatFeatureBits(angle::FormatID formatID,const VkFormatFeatureFlags featureBits) const6573 VkFormatFeatureFlags Renderer::getLinearImageFormatFeatureBits(
6574     angle::FormatID formatID,
6575     const VkFormatFeatureFlags featureBits) const
6576 {
6577     return getFormatFeatureBits<&VkFormatProperties::linearTilingFeatures>(formatID, featureBits);
6578 }
6579 
getImageFormatFeatureBits(angle::FormatID formatID,const VkFormatFeatureFlags featureBits) const6580 VkFormatFeatureFlags Renderer::getImageFormatFeatureBits(
6581     angle::FormatID formatID,
6582     const VkFormatFeatureFlags featureBits) const
6583 {
6584     return getFormatFeatureBits<&VkFormatProperties::optimalTilingFeatures>(formatID, featureBits);
6585 }
6586 
hasImageFormatFeatureBits(angle::FormatID formatID,const VkFormatFeatureFlags featureBits) const6587 bool Renderer::hasImageFormatFeatureBits(angle::FormatID formatID,
6588                                          const VkFormatFeatureFlags featureBits) const
6589 {
6590     return hasFormatFeatureBits<&VkFormatProperties::optimalTilingFeatures>(formatID, featureBits);
6591 }
6592 
hasBufferFormatFeatureBits(angle::FormatID formatID,const VkFormatFeatureFlags featureBits) const6593 bool Renderer::hasBufferFormatFeatureBits(angle::FormatID formatID,
6594                                           const VkFormatFeatureFlags featureBits) const
6595 {
6596     return hasFormatFeatureBits<&VkFormatProperties::bufferFeatures>(formatID, featureBits);
6597 }
6598 
outputVmaStatString()6599 void Renderer::outputVmaStatString()
6600 {
6601     // Output the VMA stats string
6602     // This JSON string can be passed to VmaDumpVis.py to generate a visualization of the
6603     // allocations the VMA has performed.
6604     char *statsString;
6605     mAllocator.buildStatsString(&statsString, true);
6606     INFO() << std::endl << statsString << std::endl;
6607     mAllocator.freeStatsString(statsString);
6608 }
6609 
queueSubmitOneOff(vk::ErrorContext * context,vk::ScopedPrimaryCommandBuffer && scopedCommandBuffer,vk::ProtectionType protectionType,egl::ContextPriority priority,VkSemaphore waitSemaphore,VkPipelineStageFlags waitSemaphoreStageMasks,QueueSerial * queueSerialOut)6610 angle::Result Renderer::queueSubmitOneOff(vk::ErrorContext *context,
6611                                           vk::ScopedPrimaryCommandBuffer &&scopedCommandBuffer,
6612                                           vk::ProtectionType protectionType,
6613                                           egl::ContextPriority priority,
6614                                           VkSemaphore waitSemaphore,
6615                                           VkPipelineStageFlags waitSemaphoreStageMasks,
6616                                           QueueSerial *queueSerialOut)
6617 {
6618     ANGLE_TRACE_EVENT0("gpu.angle", "Renderer::queueSubmitOneOff");
6619     DeviceScoped<PrimaryCommandBuffer> commandBuffer = scopedCommandBuffer.unlockAndRelease();
6620     PrimaryCommandBuffer &primary                    = commandBuffer.get();
6621 
6622     // Allocate a one off SerialIndex and generate a QueueSerial and then use it and release the
6623     // index.
6624     vk::ScopedQueueSerialIndex index;
6625     ANGLE_TRY(allocateScopedQueueSerialIndex(&index));
6626     QueueSerial submitQueueSerial(index.get(), generateQueueSerial(index.get()));
6627 
6628     ANGLE_TRY(mCommandQueue.queueSubmitOneOff(context, protectionType, priority,
6629                                               primary.getHandle(), waitSemaphore,
6630                                               waitSemaphoreStageMasks, submitQueueSerial));
6631 
6632     *queueSerialOut = submitQueueSerial;
6633     if (primary.valid())
6634     {
6635         mOneOffCommandPoolMap[protectionType].releaseCommandBuffer(submitQueueSerial,
6636                                                                    std::move(primary));
6637     }
6638 
6639     ANGLE_TRY(mCommandQueue.postSubmitCheck(context));
6640 
6641     return angle::Result::Continue;
6642 }
6643 
queueSubmitWaitSemaphore(vk::ErrorContext * context,egl::ContextPriority priority,const vk::Semaphore & waitSemaphore,VkPipelineStageFlags waitSemaphoreStageMasks,QueueSerial submitQueueSerial)6644 angle::Result Renderer::queueSubmitWaitSemaphore(vk::ErrorContext *context,
6645                                                  egl::ContextPriority priority,
6646                                                  const vk::Semaphore &waitSemaphore,
6647                                                  VkPipelineStageFlags waitSemaphoreStageMasks,
6648                                                  QueueSerial submitQueueSerial)
6649 {
6650     return mCommandQueue.queueSubmitOneOff(context, vk::ProtectionType::Unprotected, priority,
6651                                            VK_NULL_HANDLE, waitSemaphore.getHandle(),
6652                                            waitSemaphoreStageMasks, submitQueueSerial);
6653 }
6654 
6655 template <VkFormatFeatureFlags VkFormatProperties::*features>
getFormatFeatureBits(angle::FormatID formatID,const VkFormatFeatureFlags featureBits) const6656 VkFormatFeatureFlags Renderer::getFormatFeatureBits(angle::FormatID formatID,
6657                                                     const VkFormatFeatureFlags featureBits) const
6658 {
6659     ASSERT(formatID != angle::FormatID::NONE);
6660     VkFormatProperties &deviceProperties = mFormatProperties[formatID];
6661 
6662     if (deviceProperties.bufferFeatures == kInvalidFormatFeatureFlags)
6663     {
6664         // If we don't have the actual device features, see if the requested features are mandatory.
6665         // If so, there's no need to query the device.
6666         const VkFormatProperties &mandatoryProperties = vk::GetMandatoryFormatSupport(formatID);
6667         if (IsMaskFlagSet(mandatoryProperties.*features, featureBits))
6668         {
6669             return featureBits;
6670         }
6671 
6672         if (vk::IsYUVExternalFormat(formatID))
6673         {
6674             const vk::ExternalYuvFormatInfo &externalFormatInfo =
6675                 mExternalFormatTable.getExternalFormatInfo(formatID);
6676             deviceProperties.optimalTilingFeatures = externalFormatInfo.formatFeatures;
6677         }
6678         else
6679         {
6680             VkFormat vkFormat = vk::GetVkFormatFromFormatID(this, formatID);
6681             ASSERT(vkFormat != VK_FORMAT_UNDEFINED);
6682 
6683             // Otherwise query the format features and cache it.
6684             vkGetPhysicalDeviceFormatProperties(mPhysicalDevice, vkFormat, &deviceProperties);
6685             // Workaround for some Android devices that don't indicate filtering
6686             // support on D16_UNORM and they should.
6687             if (mFeatures.forceD16TexFilter.enabled && vkFormat == VK_FORMAT_D16_UNORM)
6688             {
6689                 deviceProperties.*features |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
6690             }
6691         }
6692     }
6693 
6694     return deviceProperties.*features & featureBits;
6695 }
6696 
6697 template <VkFormatFeatureFlags VkFormatProperties::*features>
hasFormatFeatureBits(angle::FormatID formatID,const VkFormatFeatureFlags featureBits) const6698 bool Renderer::hasFormatFeatureBits(angle::FormatID formatID,
6699                                     const VkFormatFeatureFlags featureBits) const
6700 {
6701     return IsMaskFlagSet(getFormatFeatureBits<features>(formatID, featureBits), featureBits);
6702 }
6703 
haveSameFormatFeatureBits(angle::FormatID formatID1,angle::FormatID formatID2) const6704 bool Renderer::haveSameFormatFeatureBits(angle::FormatID formatID1, angle::FormatID formatID2) const
6705 {
6706     if (formatID1 == angle::FormatID::NONE || formatID2 == angle::FormatID::NONE)
6707     {
6708         return false;
6709     }
6710 
6711     constexpr VkFormatFeatureFlags kImageUsageFeatureBits =
6712         VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT |
6713         VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
6714 
6715     VkFormatFeatureFlags fmt1LinearFeatureBits =
6716         getLinearImageFormatFeatureBits(formatID1, kImageUsageFeatureBits);
6717     VkFormatFeatureFlags fmt1OptimalFeatureBits =
6718         getImageFormatFeatureBits(formatID1, kImageUsageFeatureBits);
6719 
6720     return hasLinearImageFormatFeatureBits(formatID2, fmt1LinearFeatureBits) &&
6721            hasImageFormatFeatureBits(formatID2, fmt1OptimalFeatureBits);
6722 }
6723 
cleanupGarbage(bool * anyGarbageCleanedOut)6724 void Renderer::cleanupGarbage(bool *anyGarbageCleanedOut)
6725 {
6726     bool anyCleaned = false;
6727 
6728     // Clean up general garbage
6729     anyCleaned = (mSharedGarbageList.cleanupSubmittedGarbage(this) > 0) || anyCleaned;
6730 
6731     // Clean up suballocation garbages
6732     anyCleaned = (mSuballocationGarbageList.cleanupSubmittedGarbage(this) > 0) || anyCleaned;
6733 
6734     // Note: do this after clean up mSuballocationGarbageList so that we will have more chances to
6735     // find orphaned blocks being empty.
6736     anyCleaned = (mOrphanedBufferBlockList.pruneEmptyBufferBlocks(this) > 0) || anyCleaned;
6737 
6738     // Clean up RefCountedEvent that are done resetting
6739     anyCleaned = (mRefCountedEventRecycler.cleanupResettingEvents(this) > 0) || anyCleaned;
6740 
6741     if (anyGarbageCleanedOut != nullptr)
6742     {
6743         *anyGarbageCleanedOut = anyCleaned;
6744     }
6745 }
6746 
cleanupPendingSubmissionGarbage()6747 void Renderer::cleanupPendingSubmissionGarbage()
6748 {
6749     // Check if pending garbage is still pending. If not, move them to the garbage list.
6750     mSharedGarbageList.cleanupUnsubmittedGarbage(this);
6751     mSuballocationGarbageList.cleanupUnsubmittedGarbage(this);
6752 }
6753 
onNewValidationMessage(const std::string & message)6754 void Renderer::onNewValidationMessage(const std::string &message)
6755 {
6756     mLastValidationMessage = message;
6757     ++mValidationMessageCount;
6758 }
6759 
getAndClearLastValidationMessage(uint32_t * countSinceLastClear)6760 std::string Renderer::getAndClearLastValidationMessage(uint32_t *countSinceLastClear)
6761 {
6762     *countSinceLastClear    = mValidationMessageCount;
6763     mValidationMessageCount = 0;
6764 
6765     return std::move(mLastValidationMessage);
6766 }
6767 
getMaxFenceWaitTimeNs() const6768 uint64_t Renderer::getMaxFenceWaitTimeNs() const
6769 {
6770     constexpr uint64_t kMaxFenceWaitTimeNs = std::numeric_limits<uint64_t>::max();
6771 
6772     return kMaxFenceWaitTimeNs;
6773 }
6774 
setGlobalDebugAnnotator(bool * installedAnnotatorOut)6775 void Renderer::setGlobalDebugAnnotator(bool *installedAnnotatorOut)
6776 {
6777     // Install one of two DebugAnnotator classes:
6778     //
6779     // 1) The global class enables basic ANGLE debug functionality (e.g. Vulkan validation errors
6780     //    will cause dEQP tests to fail).
6781     //
6782     // 2) The DebugAnnotatorVk class processes OpenGL ES commands that the application uses.  It is
6783     //    installed for the following purposes:
6784     //
6785     //    1) To enable calling the vkCmd*DebugUtilsLabelEXT functions in order to communicate to
6786     //       debuggers (e.g. AGI) the OpenGL ES commands that the application uses.  In addition to
6787     //       simply installing DebugAnnotatorVk, also enable calling vkCmd*DebugUtilsLabelEXT.
6788     //
6789     //    2) To enable logging to Android logcat the OpenGL ES commands that the application uses.
6790     bool installDebugAnnotatorVk = false;
6791 
6792     // Enable calling the vkCmd*DebugUtilsLabelEXT functions if the vkCmd*DebugUtilsLabelEXT
6793     // functions exist, and if the kEnableDebugMarkersVarName environment variable is set.
6794     if (vkCmdBeginDebugUtilsLabelEXT)
6795     {
6796         // Use the GetAndSet variant to improve future lookup times
6797         std::string enabled = angle::GetAndSetEnvironmentVarOrUnCachedAndroidProperty(
6798             kEnableDebugMarkersVarName, kEnableDebugMarkersPropertyName);
6799         if (!enabled.empty() && enabled.compare("0") != 0)
6800         {
6801             mAngleDebuggerMode      = true;
6802             installDebugAnnotatorVk = true;
6803         }
6804     }
6805 #if defined(ANGLE_ENABLE_TRACE_ANDROID_LOGCAT)
6806     // Only install DebugAnnotatorVk to log all API commands to Android's logcat.
6807     installDebugAnnotatorVk = true;
6808 #endif
6809 
6810     {
6811         if (installDebugAnnotatorVk)
6812         {
6813             std::unique_lock<angle::SimpleMutex> lock(gl::GetDebugMutex());
6814             gl::InitializeDebugAnnotations(&mAnnotator);
6815         }
6816     }
6817 
6818     *installedAnnotatorOut = installDebugAnnotatorVk;
6819 }
6820 
reloadVolkIfNeeded() const6821 void Renderer::reloadVolkIfNeeded() const
6822 {
6823 #if defined(ANGLE_SHARED_LIBVULKAN)
6824     if ((mInstance != VK_NULL_HANDLE) && (volkGetLoadedInstance() != mInstance))
6825     {
6826         volkLoadInstance(mInstance);
6827     }
6828 
6829     if ((mDevice != VK_NULL_HANDLE) && (volkGetLoadedDevice() != mDevice))
6830     {
6831         volkLoadDevice(mDevice);
6832     }
6833 
6834     initializeInstanceExtensionEntryPointsFromCore();
6835     initializeDeviceExtensionEntryPointsFromCore();
6836 #endif  // defined(ANGLE_SHARED_LIBVULKAN)
6837 }
6838 
initializeInstanceExtensionEntryPointsFromCore() const6839 void Renderer::initializeInstanceExtensionEntryPointsFromCore() const
6840 {
6841     // Initialize extension entry points from core ones.  In some cases, such as VMA, the extension
6842     // entry point is unconditionally used.
6843     InitGetPhysicalDeviceProperties2KHRFunctionsFromCore();
6844     if (mFeatures.supportsExternalFenceCapabilities.enabled)
6845     {
6846         InitExternalFenceCapabilitiesFunctionsFromCore();
6847     }
6848     if (mFeatures.supportsExternalSemaphoreCapabilities.enabled)
6849     {
6850         InitExternalSemaphoreCapabilitiesFunctionsFromCore();
6851     }
6852 }
6853 
initializeDeviceExtensionEntryPointsFromCore() const6854 void Renderer::initializeDeviceExtensionEntryPointsFromCore() const
6855 {
6856     if (mFeatures.supportsGetMemoryRequirements2.enabled)
6857     {
6858         InitGetMemoryRequirements2KHRFunctionsFromCore();
6859     }
6860     if (mFeatures.supportsBindMemory2.enabled)
6861     {
6862         InitBindMemory2KHRFunctionsFromCore();
6863     }
6864     if (mFeatures.supportsYUVSamplerConversion.enabled)
6865     {
6866         InitSamplerYcbcrKHRFunctionsFromCore();
6867     }
6868 }
6869 
submitCommands(vk::ErrorContext * context,vk::ProtectionType protectionType,egl::ContextPriority contextPriority,const vk::Semaphore * signalSemaphore,const vk::SharedExternalFence * externalFence,std::vector<VkImageMemoryBarrier> && imagesToTransitionToForeign,const QueueSerial & submitQueueSerial)6870 angle::Result Renderer::submitCommands(
6871     vk::ErrorContext *context,
6872     vk::ProtectionType protectionType,
6873     egl::ContextPriority contextPriority,
6874     const vk::Semaphore *signalSemaphore,
6875     const vk::SharedExternalFence *externalFence,
6876     std::vector<VkImageMemoryBarrier> &&imagesToTransitionToForeign,
6877     const QueueSerial &submitQueueSerial)
6878 {
6879     ASSERT(signalSemaphore == nullptr || signalSemaphore->valid());
6880     const VkSemaphore signalVkSemaphore =
6881         signalSemaphore ? signalSemaphore->getHandle() : VK_NULL_HANDLE;
6882 
6883     vk::SharedExternalFence externalFenceCopy;
6884     if (externalFence != nullptr)
6885     {
6886         externalFenceCopy = *externalFence;
6887     }
6888 
6889     ANGLE_TRY(mCommandQueue.submitCommands(
6890         context, protectionType, contextPriority, signalVkSemaphore, std::move(externalFenceCopy),
6891         std::move(imagesToTransitionToForeign), submitQueueSerial));
6892 
6893     ANGLE_TRY(mCommandQueue.postSubmitCheck(context));
6894 
6895     return angle::Result::Continue;
6896 }
6897 
submitPriorityDependency(vk::ErrorContext * context,vk::ProtectionTypes protectionTypes,egl::ContextPriority srcContextPriority,egl::ContextPriority dstContextPriority,SerialIndex index)6898 angle::Result Renderer::submitPriorityDependency(vk::ErrorContext *context,
6899                                                  vk::ProtectionTypes protectionTypes,
6900                                                  egl::ContextPriority srcContextPriority,
6901                                                  egl::ContextPriority dstContextPriority,
6902                                                  SerialIndex index)
6903 {
6904     RendererScoped<vk::ReleasableResource<vk::Semaphore>> semaphore(this);
6905     ANGLE_VK_TRY(context, semaphore.get().get().init(mDevice));
6906 
6907     // First, submit already flushed commands / wait semaphores into the source Priority VkQueue.
6908     // Commands that are in the Secondary Command Buffers will be flushed into the new VkQueue.
6909 
6910     // Submit commands and attach Signal Semaphore.
6911     ASSERT(protectionTypes.any());
6912     while (protectionTypes.any())
6913     {
6914         vk::ProtectionType protectionType = protectionTypes.first();
6915         protectionTypes.reset(protectionType);
6916 
6917         QueueSerial queueSerial(index, generateQueueSerial(index));
6918         // Submit semaphore only if this is the last submission (all into the same VkQueue).
6919         const vk::Semaphore *signalSemaphore = nullptr;
6920         if (protectionTypes.none())
6921         {
6922             // Update QueueSerial to collect semaphore using the latest possible queueSerial.
6923             semaphore.get().setQueueSerial(queueSerial);
6924             signalSemaphore = &semaphore.get().get();
6925         }
6926         ANGLE_TRY(submitCommands(context, protectionType, srcContextPriority, signalSemaphore,
6927                                  nullptr, {}, queueSerial));
6928     }
6929 
6930     // Submit only Wait Semaphore into the destination Priority (VkQueue).
6931     QueueSerial queueSerial(index, generateQueueSerial(index));
6932     semaphore.get().setQueueSerial(queueSerial);
6933     ANGLE_TRY(queueSubmitWaitSemaphore(context, dstContextPriority, semaphore.get().get(),
6934                                        VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, queueSerial));
6935 
6936     return angle::Result::Continue;
6937 }
6938 
handleDeviceLost()6939 void Renderer::handleDeviceLost()
6940 {
6941     mCommandQueue.handleDeviceLost(this);
6942 }
6943 
finishResourceUse(vk::ErrorContext * context,const vk::ResourceUse & use)6944 angle::Result Renderer::finishResourceUse(vk::ErrorContext *context, const vk::ResourceUse &use)
6945 {
6946     return mCommandQueue.finishResourceUse(context, use, getMaxFenceWaitTimeNs());
6947 }
6948 
finishQueueSerial(vk::ErrorContext * context,const QueueSerial & queueSerial)6949 angle::Result Renderer::finishQueueSerial(vk::ErrorContext *context, const QueueSerial &queueSerial)
6950 {
6951     ASSERT(queueSerial.valid());
6952     return mCommandQueue.finishQueueSerial(context, queueSerial, getMaxFenceWaitTimeNs());
6953 }
6954 
waitForResourceUseToFinishWithUserTimeout(vk::ErrorContext * context,const vk::ResourceUse & use,uint64_t timeout,VkResult * result)6955 angle::Result Renderer::waitForResourceUseToFinishWithUserTimeout(vk::ErrorContext *context,
6956                                                                   const vk::ResourceUse &use,
6957                                                                   uint64_t timeout,
6958                                                                   VkResult *result)
6959 {
6960     ANGLE_TRACE_EVENT0("gpu.angle", "Renderer::waitForResourceUseToFinishWithUserTimeout");
6961     return mCommandQueue.waitForResourceUseToFinishWithUserTimeout(context, use, timeout, result);
6962 }
6963 
flushWaitSemaphores(vk::ProtectionType protectionType,egl::ContextPriority priority,std::vector<VkSemaphore> && waitSemaphores,std::vector<VkPipelineStageFlags> && waitSemaphoreStageMasks)6964 angle::Result Renderer::flushWaitSemaphores(
6965     vk::ProtectionType protectionType,
6966     egl::ContextPriority priority,
6967     std::vector<VkSemaphore> &&waitSemaphores,
6968     std::vector<VkPipelineStageFlags> &&waitSemaphoreStageMasks)
6969 {
6970     ANGLE_TRACE_EVENT0("gpu.angle", "Renderer::flushWaitSemaphores");
6971     mCommandQueue.flushWaitSemaphores(protectionType, priority, std::move(waitSemaphores),
6972                                       std::move(waitSemaphoreStageMasks));
6973 
6974     return angle::Result::Continue;
6975 }
6976 
flushRenderPassCommands(vk::Context * context,vk::ProtectionType protectionType,egl::ContextPriority priority,const vk::RenderPass & renderPass,VkFramebuffer framebufferOverride,vk::RenderPassCommandBufferHelper ** renderPassCommands)6977 angle::Result Renderer::flushRenderPassCommands(
6978     vk::Context *context,
6979     vk::ProtectionType protectionType,
6980     egl::ContextPriority priority,
6981     const vk::RenderPass &renderPass,
6982     VkFramebuffer framebufferOverride,
6983     vk::RenderPassCommandBufferHelper **renderPassCommands)
6984 {
6985     ANGLE_TRACE_EVENT0("gpu.angle", "Renderer::flushRenderPassCommands");
6986     return mCommandQueue.flushRenderPassCommands(context, protectionType, priority, renderPass,
6987                                                  framebufferOverride, renderPassCommands);
6988 }
6989 
flushOutsideRPCommands(vk::Context * context,vk::ProtectionType protectionType,egl::ContextPriority priority,vk::OutsideRenderPassCommandBufferHelper ** outsideRPCommands)6990 angle::Result Renderer::flushOutsideRPCommands(
6991     vk::Context *context,
6992     vk::ProtectionType protectionType,
6993     egl::ContextPriority priority,
6994     vk::OutsideRenderPassCommandBufferHelper **outsideRPCommands)
6995 {
6996     ANGLE_TRACE_EVENT0("gpu.angle", "Renderer::flushOutsideRPCommands");
6997     return mCommandQueue.flushOutsideRPCommands(context, protectionType, priority,
6998                                                 outsideRPCommands);
6999 }
7000 
queuePresent(vk::ErrorContext * context,egl::ContextPriority priority,const VkPresentInfoKHR & presentInfo)7001 VkResult Renderer::queuePresent(vk::ErrorContext *context,
7002                                 egl::ContextPriority priority,
7003                                 const VkPresentInfoKHR &presentInfo)
7004 {
7005     VkResult result = mCommandQueue.queuePresent(priority, presentInfo);
7006 
7007     if (getFeatures().logMemoryReportStats.enabled)
7008     {
7009         mMemoryReport.logMemoryReportStats();
7010     }
7011 
7012     return result;
7013 }
7014 
7015 template <typename CommandBufferHelperT, typename RecyclerT>
getCommandBufferImpl(vk::ErrorContext * context,vk::SecondaryCommandPool * commandPool,vk::SecondaryCommandMemoryAllocator * commandsAllocator,RecyclerT * recycler,CommandBufferHelperT ** commandBufferHelperOut)7016 angle::Result Renderer::getCommandBufferImpl(vk::ErrorContext *context,
7017                                              vk::SecondaryCommandPool *commandPool,
7018                                              vk::SecondaryCommandMemoryAllocator *commandsAllocator,
7019                                              RecyclerT *recycler,
7020                                              CommandBufferHelperT **commandBufferHelperOut)
7021 {
7022     return recycler->getCommandBufferHelper(context, commandPool, commandsAllocator,
7023                                             commandBufferHelperOut);
7024 }
7025 
getOutsideRenderPassCommandBufferHelper(vk::ErrorContext * context,vk::SecondaryCommandPool * commandPool,vk::SecondaryCommandMemoryAllocator * commandsAllocator,vk::OutsideRenderPassCommandBufferHelper ** commandBufferHelperOut)7026 angle::Result Renderer::getOutsideRenderPassCommandBufferHelper(
7027     vk::ErrorContext *context,
7028     vk::SecondaryCommandPool *commandPool,
7029     vk::SecondaryCommandMemoryAllocator *commandsAllocator,
7030     vk::OutsideRenderPassCommandBufferHelper **commandBufferHelperOut)
7031 {
7032     ANGLE_TRACE_EVENT0("gpu.angle", "Renderer::getOutsideRenderPassCommandBufferHelper");
7033     return getCommandBufferImpl(context, commandPool, commandsAllocator,
7034                                 &mOutsideRenderPassCommandBufferRecycler, commandBufferHelperOut);
7035 }
7036 
getRenderPassCommandBufferHelper(vk::ErrorContext * context,vk::SecondaryCommandPool * commandPool,vk::SecondaryCommandMemoryAllocator * commandsAllocator,vk::RenderPassCommandBufferHelper ** commandBufferHelperOut)7037 angle::Result Renderer::getRenderPassCommandBufferHelper(
7038     vk::ErrorContext *context,
7039     vk::SecondaryCommandPool *commandPool,
7040     vk::SecondaryCommandMemoryAllocator *commandsAllocator,
7041     vk::RenderPassCommandBufferHelper **commandBufferHelperOut)
7042 {
7043     ANGLE_TRACE_EVENT0("gpu.angle", "Renderer::getRenderPassCommandBufferHelper");
7044     return getCommandBufferImpl(context, commandPool, commandsAllocator,
7045                                 &mRenderPassCommandBufferRecycler, commandBufferHelperOut);
7046 }
7047 
recycleOutsideRenderPassCommandBufferHelper(vk::OutsideRenderPassCommandBufferHelper ** commandBuffer)7048 void Renderer::recycleOutsideRenderPassCommandBufferHelper(
7049     vk::OutsideRenderPassCommandBufferHelper **commandBuffer)
7050 {
7051     ANGLE_TRACE_EVENT0("gpu.angle", "Renderer::recycleOutsideRenderPassCommandBufferHelper");
7052     mOutsideRenderPassCommandBufferRecycler.recycleCommandBufferHelper(commandBuffer);
7053 }
7054 
recycleRenderPassCommandBufferHelper(vk::RenderPassCommandBufferHelper ** commandBuffer)7055 void Renderer::recycleRenderPassCommandBufferHelper(
7056     vk::RenderPassCommandBufferHelper **commandBuffer)
7057 {
7058     ANGLE_TRACE_EVENT0("gpu.angle", "Renderer::recycleRenderPassCommandBufferHelper");
7059     mRenderPassCommandBufferRecycler.recycleCommandBufferHelper(commandBuffer);
7060 }
7061 
logCacheStats() const7062 void Renderer::logCacheStats() const
7063 {
7064     if (!vk::kOutputCumulativePerfCounters)
7065     {
7066         return;
7067     }
7068 
7069     std::unique_lock<angle::SimpleMutex> localLock(mCacheStatsMutex);
7070 
7071     int cacheType = 0;
7072     INFO() << "Vulkan object cache hit ratios: ";
7073     for (const CacheStats &stats : mVulkanCacheStats)
7074     {
7075         INFO() << "    CacheType " << cacheType++ << ": " << stats.getHitRatio();
7076     }
7077 }
7078 
getFormatDescriptorCountForVkFormat(vk::ErrorContext * context,VkFormat format,uint32_t * descriptorCountOut)7079 angle::Result Renderer::getFormatDescriptorCountForVkFormat(vk::ErrorContext *context,
7080                                                             VkFormat format,
7081                                                             uint32_t *descriptorCountOut)
7082 {
7083     if (mVkFormatDescriptorCountMap.count(format) == 0)
7084     {
7085         // Query device for descriptor count with basic values for most of
7086         // VkPhysicalDeviceImageFormatInfo2 members.
7087         VkPhysicalDeviceImageFormatInfo2 imageFormatInfo = {};
7088         imageFormatInfo.sType  = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2;
7089         imageFormatInfo.format = format;
7090         imageFormatInfo.type   = VK_IMAGE_TYPE_2D;
7091         imageFormatInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
7092         imageFormatInfo.usage  = VK_IMAGE_USAGE_SAMPLED_BIT;
7093         imageFormatInfo.flags  = 0;
7094 
7095         VkImageFormatProperties imageFormatProperties                            = {};
7096         VkSamplerYcbcrConversionImageFormatProperties ycbcrImageFormatProperties = {};
7097         ycbcrImageFormatProperties.sType =
7098             VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES;
7099 
7100         VkImageFormatProperties2 imageFormatProperties2 = {};
7101         imageFormatProperties2.sType                 = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2;
7102         imageFormatProperties2.pNext                 = &ycbcrImageFormatProperties;
7103         imageFormatProperties2.imageFormatProperties = imageFormatProperties;
7104 
7105         ANGLE_VK_TRY(context, vkGetPhysicalDeviceImageFormatProperties2(
7106                                   mPhysicalDevice, &imageFormatInfo, &imageFormatProperties2));
7107 
7108         mVkFormatDescriptorCountMap[format] =
7109             ycbcrImageFormatProperties.combinedImageSamplerDescriptorCount;
7110     }
7111 
7112     ASSERT(descriptorCountOut);
7113     *descriptorCountOut = mVkFormatDescriptorCountMap[format];
7114     return angle::Result::Continue;
7115 }
7116 
getFormatDescriptorCountForExternalFormat(vk::ErrorContext * context,uint64_t format,uint32_t * descriptorCountOut)7117 angle::Result Renderer::getFormatDescriptorCountForExternalFormat(vk::ErrorContext *context,
7118                                                                   uint64_t format,
7119                                                                   uint32_t *descriptorCountOut)
7120 {
7121     ASSERT(descriptorCountOut);
7122 
7123     // TODO: need to query for external formats as well once spec is fixed.
7124     // http://anglebug.com/42264669
7125     ANGLE_VK_CHECK(context, getFeatures().useMultipleDescriptorsForExternalFormats.enabled,
7126                    VK_ERROR_INCOMPATIBLE_DRIVER);
7127 
7128     // Vulkan spec has a gap in that there is no mechanism available to query the immutable
7129     // sampler descriptor count of an external format. For now, return a default value.
7130     constexpr uint32_t kExternalFormatDefaultDescriptorCount = 4;
7131     *descriptorCountOut = kExternalFormatDefaultDescriptorCount;
7132     return angle::Result::Continue;
7133 }
7134 
onAllocateHandle(vk::HandleType handleType)7135 void Renderer::onAllocateHandle(vk::HandleType handleType)
7136 {
7137     std::unique_lock<angle::SimpleMutex> localLock(mActiveHandleCountsMutex);
7138     mActiveHandleCounts.onAllocate(handleType);
7139 }
7140 
onDeallocateHandle(vk::HandleType handleType,uint32_t count)7141 void Renderer::onDeallocateHandle(vk::HandleType handleType, uint32_t count)
7142 {
7143     std::unique_lock<angle::SimpleMutex> localLock(mActiveHandleCountsMutex);
7144     mActiveHandleCounts.onDeallocate(handleType, count);
7145 }
7146 
getPreferedBufferBlockSize(uint32_t memoryTypeIndex) const7147 VkDeviceSize Renderer::getPreferedBufferBlockSize(uint32_t memoryTypeIndex) const
7148 {
7149     // Try not to exceed 1/64 of heap size to begin with.
7150     const VkDeviceSize heapSize = getMemoryProperties().getHeapSizeForMemoryType(memoryTypeIndex);
7151     return std::min(heapSize / 64, mPreferredLargeHeapBlockSize);
7152 }
7153 
allocateScopedQueueSerialIndex(vk::ScopedQueueSerialIndex * indexOut)7154 angle::Result Renderer::allocateScopedQueueSerialIndex(vk::ScopedQueueSerialIndex *indexOut)
7155 {
7156     SerialIndex index;
7157     ANGLE_TRY(allocateQueueSerialIndex(&index));
7158     indexOut->init(index, &mQueueSerialIndexAllocator);
7159     return angle::Result::Continue;
7160 }
7161 
allocateQueueSerialIndex(SerialIndex * serialIndexOut)7162 angle::Result Renderer::allocateQueueSerialIndex(SerialIndex *serialIndexOut)
7163 {
7164     *serialIndexOut = mQueueSerialIndexAllocator.allocate();
7165     if (*serialIndexOut == kInvalidQueueSerialIndex)
7166     {
7167         return angle::Result::Stop;
7168     }
7169     return angle::Result::Continue;
7170 }
7171 
releaseQueueSerialIndex(SerialIndex index)7172 void Renderer::releaseQueueSerialIndex(SerialIndex index)
7173 {
7174     mQueueSerialIndexAllocator.release(index);
7175 }
7176 
cleanupSomeGarbage(ErrorContext * context,bool * anyGarbageCleanedOut)7177 angle::Result Renderer::cleanupSomeGarbage(ErrorContext *context, bool *anyGarbageCleanedOut)
7178 {
7179     return mCommandQueue.cleanupSomeGarbage(context, 0, anyGarbageCleanedOut);
7180 }
7181 
7182 // static
GetVulkanObjectTypeName(VkObjectType type)7183 const char *Renderer::GetVulkanObjectTypeName(VkObjectType type)
7184 {
7185     return GetVkObjectTypeName(type);
7186 }
7187 
ImageMemorySuballocator()7188 ImageMemorySuballocator::ImageMemorySuballocator() {}
~ImageMemorySuballocator()7189 ImageMemorySuballocator::~ImageMemorySuballocator() {}
7190 
destroy(Renderer * renderer)7191 void ImageMemorySuballocator::destroy(Renderer *renderer) {}
7192 
allocateAndBindMemory(ErrorContext * context,Image * image,const VkImageCreateInfo * imageCreateInfo,VkMemoryPropertyFlags requiredFlags,VkMemoryPropertyFlags preferredFlags,const VkMemoryRequirements * memoryRequirements,const bool allocateDedicatedMemory,MemoryAllocationType memoryAllocationType,Allocation * allocationOut,VkMemoryPropertyFlags * memoryFlagsOut,uint32_t * memoryTypeIndexOut,VkDeviceSize * sizeOut)7193 VkResult ImageMemorySuballocator::allocateAndBindMemory(
7194     ErrorContext *context,
7195     Image *image,
7196     const VkImageCreateInfo *imageCreateInfo,
7197     VkMemoryPropertyFlags requiredFlags,
7198     VkMemoryPropertyFlags preferredFlags,
7199     const VkMemoryRequirements *memoryRequirements,
7200     const bool allocateDedicatedMemory,
7201     MemoryAllocationType memoryAllocationType,
7202     Allocation *allocationOut,
7203     VkMemoryPropertyFlags *memoryFlagsOut,
7204     uint32_t *memoryTypeIndexOut,
7205     VkDeviceSize *sizeOut)
7206 {
7207     ASSERT(image && image->valid());
7208     ASSERT(allocationOut && !allocationOut->valid());
7209     Renderer *renderer         = context->getRenderer();
7210     const Allocator &allocator = renderer->getAllocator();
7211 
7212     // The required size must not be greater than the maximum allocation size allowed by the driver.
7213     if (memoryRequirements->size > renderer->getMaxMemoryAllocationSize())
7214     {
7215         renderer->getMemoryAllocationTracker()->onExceedingMaxMemoryAllocationSize(
7216             memoryRequirements->size);
7217         return VK_ERROR_OUT_OF_DEVICE_MEMORY;
7218     }
7219 
7220     // Avoid device-local and host-visible combinations if possible. Here, "preferredFlags" is
7221     // expected to be the same as "requiredFlags" except in the device-local bit.
7222     ASSERT((preferredFlags & ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) ==
7223            (requiredFlags & ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
7224 
7225     uint32_t memoryTypeBits = memoryRequirements->memoryTypeBits;
7226     if ((requiredFlags & preferredFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) != 0)
7227     {
7228         memoryTypeBits = GetMemoryTypeBitsExcludingHostVisible(renderer, preferredFlags,
7229                                                                memoryRequirements->memoryTypeBits);
7230     }
7231 
7232     // Allocate and bind memory for the image. Try allocating on the device first.
7233     VkResult result = vma::AllocateAndBindMemoryForImage(
7234         allocator.getHandle(), &image->mHandle, requiredFlags, preferredFlags, memoryTypeBits,
7235         allocateDedicatedMemory, &allocationOut->mHandle, memoryTypeIndexOut, sizeOut);
7236 
7237     // We need to get the property flags of the allocated memory if successful.
7238     if (result == VK_SUCCESS)
7239     {
7240         *memoryFlagsOut =
7241             renderer->getMemoryProperties().getMemoryType(*memoryTypeIndexOut).propertyFlags;
7242 
7243         renderer->onMemoryAlloc(memoryAllocationType, *sizeOut, *memoryTypeIndexOut,
7244                                 allocationOut->getHandle());
7245     }
7246     return result;
7247 }
7248 
mapMemoryAndInitWithNonZeroValue(Renderer * renderer,Allocation * allocation,VkDeviceSize size,int value,VkMemoryPropertyFlags flags)7249 VkResult ImageMemorySuballocator::mapMemoryAndInitWithNonZeroValue(Renderer *renderer,
7250                                                                    Allocation *allocation,
7251                                                                    VkDeviceSize size,
7252                                                                    int value,
7253                                                                    VkMemoryPropertyFlags flags)
7254 {
7255     ASSERT(allocation && allocation->valid());
7256     const Allocator &allocator = renderer->getAllocator();
7257 
7258     void *mappedMemoryData;
7259     VkResult result = vma::MapMemory(allocator.getHandle(), allocation->mHandle, &mappedMemoryData);
7260     if (result != VK_SUCCESS)
7261     {
7262         return result;
7263     }
7264 
7265     memset(mappedMemoryData, value, static_cast<size_t>(size));
7266     vma::UnmapMemory(allocator.getHandle(), allocation->mHandle);
7267 
7268     // If the memory type is not host coherent, we perform an explicit flush.
7269     if ((flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) == 0)
7270     {
7271         vma::FlushAllocation(allocator.getHandle(), allocation->mHandle, 0, VK_WHOLE_SIZE);
7272     }
7273 
7274     return VK_SUCCESS;
7275 }
7276 
needsDedicatedMemory(VkDeviceSize size) const7277 bool ImageMemorySuballocator::needsDedicatedMemory(VkDeviceSize size) const
7278 {
7279     return size >= kImageSizeThresholdForDedicatedMemoryAllocation;
7280 }
7281 
7282 }  // namespace vk
7283 }  // namespace rx
7284