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