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