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