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