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