vulkan_util.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. // Copyright 2019 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "gpu/vulkan/vulkan_util.h"
  5. #include "base/callback_helpers.h"
  6. #include "base/logging.h"
  7. #include "base/metrics/histogram_macros.h"
  8. #include "base/strings/pattern.h"
  9. #include "base/strings/string_split.h"
  10. #include "base/strings/string_util.h"
  11. #include "base/strings/stringprintf.h"
  12. #include "base/trace_event/trace_event.h"
  13. #include "build/build_config.h"
  14. #include "gpu/config/gpu_info.h" // nogncheck
  15. #include "gpu/config/vulkan_info.h"
  16. #include "gpu/vulkan/vulkan_function_pointers.h"
  17. #include "ui/gl/gl_switches.h"
  18. #if BUILDFLAG(IS_ANDROID)
  19. #include "base/android/build_info.h"
  20. #endif
  21. #define GL_NONE 0x00
  22. #define GL_LAYOUT_GENERAL_EXT 0x958D
  23. #define GL_LAYOUT_COLOR_ATTACHMENT_EXT 0x958E
  24. #define GL_LAYOUT_DEPTH_STENCIL_ATTACHMENT_EXT 0x958F
  25. #define GL_LAYOUT_DEPTH_STENCIL_READ_ONLY_EXT 0x9590
  26. #define GL_LAYOUT_SHADER_READ_ONLY_EXT 0x9591
  27. #define GL_LAYOUT_TRANSFER_SRC_EXT 0x9592
  28. #define GL_LAYOUT_TRANSFER_DST_EXT 0x9593
  29. #define GL_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_EXT 0x9530
  30. #define GL_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_EXT 0x9531
  31. namespace gpu {
  32. namespace {
  33. #if BUILDFLAG(IS_ANDROID)
  34. int GetEMUIVersion() {
  35. const auto* build_info = base::android::BuildInfo::GetInstance();
  36. base::StringPiece manufacturer(build_info->manufacturer());
  37. // TODO(crbug.com/1096222): check Honor devices as well.
  38. if (manufacturer != "HUAWEI")
  39. return -1;
  40. // Huawei puts EMUI version in the build version incremental.
  41. // Example: 11.0.0.130C00
  42. int version = 0;
  43. if (sscanf(build_info->version_incremental(), "%d.", &version) != 1)
  44. return -1;
  45. return version;
  46. }
  47. #endif
  48. }
  49. bool SubmitSignalVkSemaphores(VkQueue vk_queue,
  50. const base::span<VkSemaphore>& vk_semaphores,
  51. VkFence vk_fence) {
  52. // Structure specifying a queue submit operation.
  53. VkSubmitInfo submit_info = {VK_STRUCTURE_TYPE_SUBMIT_INFO};
  54. submit_info.signalSemaphoreCount = vk_semaphores.size();
  55. submit_info.pSignalSemaphores = vk_semaphores.data();
  56. const unsigned int submit_count = 1;
  57. return vkQueueSubmit(vk_queue, submit_count, &submit_info, vk_fence) ==
  58. VK_SUCCESS;
  59. }
  60. bool SubmitSignalVkSemaphore(VkQueue vk_queue,
  61. VkSemaphore vk_semaphore,
  62. VkFence vk_fence) {
  63. return SubmitSignalVkSemaphores(
  64. vk_queue, base::span<VkSemaphore>(&vk_semaphore, 1), vk_fence);
  65. }
  66. bool SubmitWaitVkSemaphores(VkQueue vk_queue,
  67. const base::span<VkSemaphore>& vk_semaphores,
  68. VkFence vk_fence) {
  69. DCHECK(!vk_semaphores.empty());
  70. std::vector<VkPipelineStageFlags> semaphore_stages(vk_semaphores.size());
  71. std::fill(semaphore_stages.begin(), semaphore_stages.end(),
  72. VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
  73. // Structure specifying a queue submit operation.
  74. VkSubmitInfo submit_info = {VK_STRUCTURE_TYPE_SUBMIT_INFO};
  75. submit_info.waitSemaphoreCount = vk_semaphores.size();
  76. submit_info.pWaitSemaphores = vk_semaphores.data();
  77. submit_info.pWaitDstStageMask = semaphore_stages.data();
  78. const unsigned int submit_count = 1;
  79. return vkQueueSubmit(vk_queue, submit_count, &submit_info, vk_fence) ==
  80. VK_SUCCESS;
  81. }
  82. bool SubmitWaitVkSemaphore(VkQueue vk_queue,
  83. VkSemaphore vk_semaphore,
  84. VkFence vk_fence) {
  85. return SubmitWaitVkSemaphores(
  86. vk_queue, base::span<VkSemaphore>(&vk_semaphore, 1), vk_fence);
  87. }
  88. VkSemaphore CreateExternalVkSemaphore(
  89. VkDevice vk_device,
  90. VkExternalSemaphoreHandleTypeFlags handle_types) {
  91. VkExportSemaphoreCreateInfo export_info = {
  92. .sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO,
  93. .handleTypes = handle_types,
  94. };
  95. VkSemaphoreCreateInfo sem_info = {
  96. .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
  97. .pNext = &export_info,
  98. };
  99. VkSemaphore semaphore = VK_NULL_HANDLE;
  100. VkResult result =
  101. vkCreateSemaphore(vk_device, &sem_info, nullptr, &semaphore);
  102. if (result != VK_SUCCESS) {
  103. DLOG(ERROR) << "Failed to create VkSemaphore: " << result;
  104. return VK_NULL_HANDLE;
  105. }
  106. return semaphore;
  107. }
  108. std::string VkVersionToString(uint32_t version) {
  109. return base::StringPrintf("%u.%u.%u", VK_VERSION_MAJOR(version),
  110. VK_VERSION_MINOR(version),
  111. VK_VERSION_PATCH(version));
  112. }
  113. VkResult CreateGraphicsPipelinesHook(
  114. VkDevice device,
  115. VkPipelineCache pipelineCache,
  116. uint32_t createInfoCount,
  117. const VkGraphicsPipelineCreateInfo* pCreateInfos,
  118. const VkAllocationCallbacks* pAllocator,
  119. VkPipeline* pPipelines) {
  120. base::ScopedClosureRunner uma_runner(base::BindOnce(
  121. [](base::Time time) {
  122. UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES(
  123. "GPU.Vulkan.PipelineCache.vkCreateGraphicsPipelines",
  124. base::Time::Now() - time, base::Microseconds(100),
  125. base::Microseconds(50000), 50);
  126. },
  127. base::Time::Now()));
  128. return vkCreateGraphicsPipelines(device, pipelineCache, createInfoCount,
  129. pCreateInfos, pAllocator, pPipelines);
  130. }
  131. VkResult VulkanQueueSubmitHook(VkQueue queue,
  132. uint32_t submitCount,
  133. const VkSubmitInfo* pSubmits,
  134. VkFence fence) {
  135. TRACE_EVENT0("gpu", "VulkanQueueSubmitHook");
  136. return vkQueueSubmit(queue, submitCount, pSubmits, fence);
  137. }
  138. VkResult VulkanQueueWaitIdleHook(VkQueue queue) {
  139. TRACE_EVENT0("gpu", "VulkanQueueWaitIdleHook");
  140. return vkQueueWaitIdle(queue);
  141. }
  142. VkResult VulkanQueuePresentKHRHook(VkQueue queue,
  143. const VkPresentInfoKHR* pPresentInfo) {
  144. TRACE_EVENT0("gpu", "VulkanQueuePresentKHRHook");
  145. return vkQueuePresentKHR(queue, pPresentInfo);
  146. }
  147. bool CheckVulkanCompabilities(const VulkanInfo& vulkan_info,
  148. const GPUInfo& gpu_info,
  149. std::string enable_by_device_name) {
  150. // Android uses AHB and SyncFD for interop. They are imported into GL with other
  151. // API.
  152. #if !BUILDFLAG(IS_ANDROID)
  153. #if BUILDFLAG(IS_WIN)
  154. constexpr char kMemoryObjectExtension[] = "GL_EXT_memory_object_win32";
  155. constexpr char kSemaphoreExtension[] = "GL_EXT_semaphore_win32";
  156. #elif BUILDFLAG(IS_FUCHSIA)
  157. constexpr char kMemoryObjectExtension[] = "GL_ANGLE_memory_object_fuchsia";
  158. constexpr char kSemaphoreExtension[] = "GL_ANGLE_semaphore_fuchsia";
  159. #else
  160. constexpr char kMemoryObjectExtension[] = "GL_EXT_memory_object_fd";
  161. constexpr char kSemaphoreExtension[] = "GL_EXT_semaphore_fd";
  162. #endif
  163. // If Chrome and ANGLE share the same VkQueue, they can share vulkan
  164. // resource without those extensions.
  165. if (!base::FeatureList::IsEnabled(features::kVulkanFromANGLE)) {
  166. // If both Vulkan and GL are using native GPU (non swiftshader), check
  167. // necessary extensions for GL and Vulkan interop.
  168. const auto extensions = gfx::MakeExtensionSet(gpu_info.gl_extensions);
  169. if (!gfx::HasExtension(extensions, kMemoryObjectExtension) ||
  170. !gfx::HasExtension(extensions, kSemaphoreExtension)) {
  171. DLOG(ERROR) << kMemoryObjectExtension << " or " << kSemaphoreExtension
  172. << " is not supported.";
  173. return false;
  174. }
  175. }
  176. #if BUILDFLAG(IS_LINUX) && !defined(OZONE_PLATFORM_IS_X11)
  177. // Vulkan is only supported with X11 on Linux for now.
  178. return false;
  179. #else
  180. return true;
  181. #endif
  182. #else // BUILDFLAG(IS_ANDROID)
  183. if (vulkan_info.physical_devices.empty())
  184. return false;
  185. const auto& device_info = vulkan_info.physical_devices.front();
  186. auto enable_patterns = base::SplitString(
  187. enable_by_device_name, "|", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
  188. for (const auto& enable_pattern : enable_patterns) {
  189. if (base::MatchPattern(device_info.properties.deviceName, enable_pattern))
  190. return true;
  191. }
  192. if (device_info.properties.vendorID == kVendorARM) {
  193. int emui_version = GetEMUIVersion();
  194. // TODO(crbug.com/1096222) Display problem with Huawei EMUI < 11 and Honor
  195. // devices with Mali GPU. The Mali driver version is < 19.0.0.
  196. if (device_info.properties.driverVersion < VK_MAKE_VERSION(19, 0, 0) &&
  197. emui_version < 11) {
  198. return false;
  199. }
  200. // Remove "Mali-" prefix.
  201. base::StringPiece device_name(device_info.properties.deviceName);
  202. if (!base::StartsWith(device_name, "Mali-")) {
  203. LOG(ERROR) << "Unexpected device_name " << device_name;
  204. return false;
  205. }
  206. device_name.remove_prefix(5);
  207. // Remove anything trailing a space (e.g. "G76 MC4" => "G76").
  208. device_name = device_name.substr(0, device_name.find(" "));
  209. // Older Mali GPUs are not performant with Vulkan -- this blocks all Utgard
  210. // gen, Midgard gen, and some Bifrost 1st & 2nd gen.
  211. std::vector<const char*> slow_gpus = {"2??", "3??", "4??", "T???",
  212. "G31", "G51", "G52"};
  213. for (base::StringPiece slow_gpu : slow_gpus) {
  214. if (base::MatchPattern(device_name, slow_gpu))
  215. return false;
  216. }
  217. }
  218. // https:://crbug.com/1165783: Performance is not yet as good as GL.
  219. if (device_info.properties.vendorID == kVendorQualcomm) {
  220. if (device_info.properties.deviceName ==
  221. base::StringPiece("Adreno (TM) 630"))
  222. return true;
  223. return false;
  224. }
  225. // https://crbug.com/1122650: Poor performance and untriaged crashes with
  226. // Imagination GPUs.
  227. if (device_info.properties.vendorID == kVendorImagination)
  228. return false;
  229. return true;
  230. #endif // BUILDFLAG(IS_ANDROID)
  231. }
  232. VkImageLayout GLImageLayoutToVkImageLayout(uint32_t layout) {
  233. switch (layout) {
  234. case GL_NONE:
  235. return VK_IMAGE_LAYOUT_UNDEFINED;
  236. case GL_LAYOUT_GENERAL_EXT:
  237. return VK_IMAGE_LAYOUT_GENERAL;
  238. case GL_LAYOUT_COLOR_ATTACHMENT_EXT:
  239. return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  240. case GL_LAYOUT_DEPTH_STENCIL_ATTACHMENT_EXT:
  241. return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
  242. case GL_LAYOUT_DEPTH_STENCIL_READ_ONLY_EXT:
  243. return VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
  244. case GL_LAYOUT_SHADER_READ_ONLY_EXT:
  245. return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
  246. case GL_LAYOUT_TRANSFER_SRC_EXT:
  247. return VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
  248. case GL_LAYOUT_TRANSFER_DST_EXT:
  249. return VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
  250. case GL_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_EXT:
  251. return VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR;
  252. case GL_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_EXT:
  253. return VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR;
  254. default:
  255. break;
  256. }
  257. NOTREACHED() << "Invalid image layout " << layout;
  258. return VK_IMAGE_LAYOUT_UNDEFINED;
  259. }
  260. uint32_t VkImageLayoutToGLImageLayout(VkImageLayout layout) {
  261. switch (layout) {
  262. case VK_IMAGE_LAYOUT_UNDEFINED:
  263. return GL_NONE;
  264. case VK_IMAGE_LAYOUT_GENERAL:
  265. return GL_LAYOUT_GENERAL_EXT;
  266. case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
  267. return GL_LAYOUT_COLOR_ATTACHMENT_EXT;
  268. case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
  269. return GL_LAYOUT_DEPTH_STENCIL_ATTACHMENT_EXT;
  270. case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
  271. return GL_LAYOUT_DEPTH_STENCIL_READ_ONLY_EXT;
  272. case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
  273. return GL_LAYOUT_SHADER_READ_ONLY_EXT;
  274. case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
  275. return GL_LAYOUT_TRANSFER_SRC_EXT;
  276. case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
  277. return GL_LAYOUT_TRANSFER_DST_EXT;
  278. case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR:
  279. return GL_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_EXT;
  280. case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR:
  281. return GL_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_EXT;
  282. default:
  283. NOTREACHED() << "Invalid image layout " << layout;
  284. return GL_NONE;
  285. }
  286. }
  287. } // namespace gpu