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