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 ¤t, 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 &¤tGarbage,
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