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