GrManagerImpl.cpp 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621
  1. // Copyright (C) 2009-2022, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <AnKi/Gr/Vulkan/GrManagerImpl.h>
  6. #include <AnKi/Gr/GrManager.h>
  7. #include <AnKi/Gr/Vulkan/CommandBufferImpl.h>
  8. #include <AnKi/Gr/CommandBuffer.h>
  9. #include <AnKi/Gr/Fence.h>
  10. #include <AnKi/Gr/Vulkan/FenceImpl.h>
  11. #include <AnKi/Util/Functions.h>
  12. #include <AnKi/Util/StringList.h>
  13. #include <AnKi/Core/ConfigSet.h>
  14. namespace anki {
  15. GrManagerImpl::~GrManagerImpl()
  16. {
  17. ANKI_VK_LOGI("Destroying Vulkan backend");
  18. // 1st THING: wait for the present fences because I don't know if waiting on queue will cover this
  19. for(PerFrame& frame : m_perFrame)
  20. {
  21. if(frame.m_presentFence.isCreated())
  22. {
  23. frame.m_presentFence->wait();
  24. }
  25. }
  26. // 2nd THING: wait for the GPU
  27. for(VkQueue& queue : m_queues)
  28. {
  29. LockGuard<Mutex> lock(m_globalMtx);
  30. if(queue)
  31. {
  32. vkQueueWaitIdle(queue);
  33. queue = VK_NULL_HANDLE;
  34. }
  35. }
  36. // 3rd THING: The destroy everything that has a reference to GrObjects.
  37. m_cmdbFactory.destroy();
  38. for(PerFrame& frame : m_perFrame)
  39. {
  40. frame.m_presentFence.reset(nullptr);
  41. frame.m_acquireSemaphore.reset(nullptr);
  42. frame.m_renderSemaphore.reset(nullptr);
  43. }
  44. m_crntSwapchain.reset(nullptr);
  45. // 4th THING: Continue with the rest
  46. m_barrierFactory.destroy(); // Destroy before fences
  47. m_semaphoreFactory.destroy(); // Destroy before fences
  48. m_swapchainFactory.destroy(); // Destroy before fences
  49. m_frameGarbageCollector.destroy();
  50. m_gpuMemManager.destroy();
  51. m_pplineLayoutFactory.destroy();
  52. m_descrFactory.destroy();
  53. m_pplineCache.destroy(m_device, m_physicalDevice, getAllocator());
  54. m_fenceFactory.destroy();
  55. m_samplerFactory.destroy();
  56. if(m_device)
  57. {
  58. vkDestroyDevice(m_device, nullptr);
  59. }
  60. if(m_surface)
  61. {
  62. vkDestroySurfaceKHR(m_instance, m_surface, nullptr);
  63. }
  64. if(m_debugUtilsMessager)
  65. {
  66. vkDestroyDebugUtilsMessengerEXT(m_instance, m_debugUtilsMessager, nullptr);
  67. }
  68. if(m_instance)
  69. {
  70. #if ANKI_GR_MANAGER_DEBUG_MEMMORY
  71. VkAllocationCallbacks* pallocCbs = &m_debugAllocCbs;
  72. #else
  73. VkAllocationCallbacks* pallocCbs = nullptr;
  74. #endif
  75. vkDestroyInstance(m_instance, pallocCbs);
  76. }
  77. #if ANKI_PLATFORM_MOBILE
  78. m_alloc.deleteInstance(m_globalCreatePipelineMtx);
  79. #endif
  80. }
  81. Error GrManagerImpl::init(const GrManagerInitInfo& init)
  82. {
  83. const Error err = initInternal(init);
  84. if(err)
  85. {
  86. ANKI_VK_LOGE("Vulkan initialization failed");
  87. return Error::FUNCTION_FAILED;
  88. }
  89. return Error::NONE;
  90. }
  91. Error GrManagerImpl::initInternal(const GrManagerInitInfo& init)
  92. {
  93. ANKI_VK_LOGI("Initializing Vulkan backend");
  94. m_config = init.m_config;
  95. ANKI_ASSERT(m_config);
  96. ANKI_CHECK(initInstance());
  97. ANKI_CHECK(initSurface(init));
  98. ANKI_CHECK(initDevice(init));
  99. for(VulkanQueueType qtype : EnumIterable<VulkanQueueType>())
  100. {
  101. if(m_queueFamilyIndices[qtype] != MAX_U32)
  102. {
  103. vkGetDeviceQueue(m_device, m_queueFamilyIndices[qtype], 0, &m_queues[qtype]);
  104. }
  105. else
  106. {
  107. m_queues[qtype] = VK_NULL_HANDLE;
  108. }
  109. }
  110. m_swapchainFactory.init(this, m_config->getGrVsync());
  111. m_crntSwapchain = m_swapchainFactory.newInstance();
  112. ANKI_CHECK(m_pplineCache.init(m_device, m_physicalDevice, init.m_cacheDirectory, *m_config, getAllocator()));
  113. ANKI_CHECK(initMemory());
  114. ANKI_CHECK(m_cmdbFactory.init(getAllocator(), m_device, m_queueFamilyIndices));
  115. for(PerFrame& f : m_perFrame)
  116. {
  117. resetFrame(f);
  118. }
  119. m_fenceFactory.init(getAllocator(), m_device);
  120. m_semaphoreFactory.init(getAllocator(), m_device);
  121. m_samplerFactory.init(this);
  122. m_barrierFactory.init(getAllocator(), m_device);
  123. m_occlusionQueryFactory.init(getAllocator(), m_device, VK_QUERY_TYPE_OCCLUSION);
  124. m_timestampQueryFactory.init(getAllocator(), m_device, VK_QUERY_TYPE_TIMESTAMP);
  125. // See if unaligned formats are supported
  126. {
  127. m_capabilities.m_unalignedBbpTextureFormats = true;
  128. VkImageFormatProperties props = {};
  129. VkResult res = vkGetPhysicalDeviceImageFormatProperties(
  130. m_physicalDevice, VK_FORMAT_R8G8B8_UNORM, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
  131. VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 0, &props);
  132. if(res == VK_ERROR_FORMAT_NOT_SUPPORTED)
  133. {
  134. m_capabilities.m_unalignedBbpTextureFormats = false;
  135. }
  136. res = vkGetPhysicalDeviceImageFormatProperties(
  137. m_physicalDevice, VK_FORMAT_R16G16B16_UNORM, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
  138. VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 0, &props);
  139. if(res == VK_ERROR_FORMAT_NOT_SUPPORTED)
  140. {
  141. m_capabilities.m_unalignedBbpTextureFormats = false;
  142. }
  143. res = vkGetPhysicalDeviceImageFormatProperties(
  144. m_physicalDevice, VK_FORMAT_R32G32B32_SFLOAT, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
  145. VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 0, &props);
  146. if(res == VK_ERROR_FORMAT_NOT_SUPPORTED)
  147. {
  148. m_capabilities.m_unalignedBbpTextureFormats = false;
  149. }
  150. if(!m_capabilities.m_unalignedBbpTextureFormats)
  151. {
  152. ANKI_VK_LOGI("R8G8B8, R16G16B16 and R32G32B32 image formats are not supported");
  153. }
  154. }
  155. ANKI_CHECK(
  156. m_descrFactory.init(getAllocator(), m_device, MAX_BINDLESS_TEXTURES, MAX_BINDLESS_READONLY_TEXTURE_BUFFERS));
  157. m_pplineLayoutFactory.init(getAllocator(), m_device);
  158. m_frameGarbageCollector.init(this);
  159. return Error::NONE;
  160. }
  161. Error GrManagerImpl::initInstance()
  162. {
  163. // Init VOLK
  164. //
  165. ANKI_VK_CHECK(volkInitialize());
  166. // Create the instance
  167. //
  168. const U8 vulkanMinor = m_config->getGrVkMinor();
  169. const U8 vulkanMajor = m_config->getGrVkMajor();
  170. VkApplicationInfo app = {};
  171. app.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
  172. app.pApplicationName = "unamed";
  173. app.applicationVersion = 1;
  174. app.pEngineName = "AnKi 3D Engine";
  175. app.engineVersion = (ANKI_VERSION_MAJOR << 16) | ANKI_VERSION_MINOR;
  176. app.apiVersion = VK_MAKE_VERSION(vulkanMajor, vulkanMinor, 0);
  177. VkInstanceCreateInfo ci = {};
  178. ci.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
  179. ci.pApplicationInfo = &app;
  180. // Validation layers
  181. static Array<const char*, 1> LAYERS = {"VK_LAYER_KHRONOS_validation"};
  182. Array<const char*, LAYERS.getSize()> layersToEnable; // Keep it alive in the stack
  183. if(m_config->getGrValidation() || m_config->getGrDebugPrintf())
  184. {
  185. uint32_t count;
  186. vkEnumerateInstanceLayerProperties(&count, nullptr);
  187. if(count)
  188. {
  189. DynamicArrayAuto<VkLayerProperties> layerProps(getAllocator());
  190. layerProps.create(count);
  191. vkEnumerateInstanceLayerProperties(&count, &layerProps[0]);
  192. U32 layersToEnableCount = 0;
  193. for(const char* c : LAYERS)
  194. {
  195. for(U32 i = 0; i < count; ++i)
  196. {
  197. if(CString(c) == layerProps[i].layerName)
  198. {
  199. layersToEnable[layersToEnableCount++] = c;
  200. break;
  201. }
  202. }
  203. }
  204. if(layersToEnableCount)
  205. {
  206. ANKI_VK_LOGI("Will enable the following layers:");
  207. for(U32 i = 0; i < layersToEnableCount; ++i)
  208. {
  209. ANKI_VK_LOGI("\t%s", layersToEnable[i]);
  210. }
  211. ci.enabledLayerCount = layersToEnableCount;
  212. ci.ppEnabledLayerNames = &layersToEnable[0];
  213. }
  214. }
  215. }
  216. // Validation features
  217. DynamicArrayAuto<VkValidationFeatureEnableEXT> enabledValidationFeatures(getAllocator());
  218. DynamicArrayAuto<VkValidationFeatureDisableEXT> disabledValidationFeatures(getAllocator());
  219. if(m_config->getGrDebugPrintf())
  220. {
  221. enabledValidationFeatures.emplaceBack(VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT);
  222. }
  223. if(!m_config->getGrValidation())
  224. {
  225. disabledValidationFeatures.emplaceBack(VK_VALIDATION_FEATURE_DISABLE_ALL_EXT);
  226. }
  227. VkValidationFeaturesEXT validationFeatures = {};
  228. if(enabledValidationFeatures.getSize() || disabledValidationFeatures.getSize())
  229. {
  230. validationFeatures.sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT;
  231. validationFeatures.disabledValidationFeatureCount = disabledValidationFeatures.getSize();
  232. validationFeatures.enabledValidationFeatureCount = enabledValidationFeatures.getSize();
  233. validationFeatures.pDisabledValidationFeatures = disabledValidationFeatures.getBegin();
  234. validationFeatures.pEnabledValidationFeatures = enabledValidationFeatures.getBegin();
  235. validationFeatures.pNext = ci.pNext;
  236. ci.pNext = &validationFeatures;
  237. }
  238. // Extensions
  239. DynamicArrayAuto<const char*> instExtensions(getAllocator());
  240. DynamicArrayAuto<VkExtensionProperties> instExtensionInf(getAllocator());
  241. U32 extCount = 0;
  242. vkEnumerateInstanceExtensionProperties(nullptr, &extCount, nullptr);
  243. if(extCount)
  244. {
  245. instExtensions.create(extCount);
  246. instExtensionInf.create(extCount);
  247. vkEnumerateInstanceExtensionProperties(nullptr, &extCount, &instExtensionInf[0]);
  248. ANKI_VK_LOGV("Found the following instance extensions:");
  249. for(U32 i = 0; i < extCount; ++i)
  250. {
  251. ANKI_VK_LOGV("\t%s", instExtensionInf[i].extensionName);
  252. }
  253. U32 instExtensionCount = 0;
  254. for(U32 i = 0; i < extCount; ++i)
  255. {
  256. const CString extensionName = instExtensionInf[i].extensionName;
  257. #if ANKI_WINDOWING_SYSTEM_HEADLESS
  258. if(extensionName == VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME)
  259. {
  260. m_extensions |= VulkanExtensions::EXT_HEADLESS_SURFACE;
  261. instExtensions[instExtensionCount++] = VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME;
  262. }
  263. #elif ANKI_OS_LINUX
  264. if(extensionName == VK_KHR_XCB_SURFACE_EXTENSION_NAME)
  265. {
  266. m_extensions |= VulkanExtensions::KHR_XCB_SURFACE;
  267. instExtensions[instExtensionCount++] = VK_KHR_XCB_SURFACE_EXTENSION_NAME;
  268. }
  269. else if(extensionName == VK_KHR_XLIB_SURFACE_EXTENSION_NAME)
  270. {
  271. m_extensions |= VulkanExtensions::KHR_XLIB_SURFACE;
  272. instExtensions[instExtensionCount++] = VK_KHR_XLIB_SURFACE_EXTENSION_NAME;
  273. }
  274. #elif ANKI_OS_WINDOWS
  275. if(extensionName == VK_KHR_WIN32_SURFACE_EXTENSION_NAME)
  276. {
  277. m_extensions |= VulkanExtensions::KHR_WIN32_SURFACE;
  278. instExtensions[instExtensionCount++] = VK_KHR_WIN32_SURFACE_EXTENSION_NAME;
  279. }
  280. #elif ANKI_OS_ANDROID
  281. if(extensionName == VK_KHR_ANDROID_SURFACE_EXTENSION_NAME)
  282. {
  283. m_extensions |= VulkanExtensions::KHR_ANDROID_SURFACE;
  284. instExtensions[instExtensionCount++] = VK_KHR_ANDROID_SURFACE_EXTENSION_NAME;
  285. }
  286. #else
  287. # error Not implemented
  288. #endif
  289. else if(extensionName == VK_KHR_SURFACE_EXTENSION_NAME)
  290. {
  291. m_extensions |= VulkanExtensions::KHR_SURFACE;
  292. instExtensions[instExtensionCount++] = VK_KHR_SURFACE_EXTENSION_NAME;
  293. }
  294. else if(extensionName == VK_EXT_DEBUG_UTILS_EXTENSION_NAME
  295. && (m_config->getGrDebugMarkers() || m_config->getGrValidation() || m_config->getGrDebugPrintf()))
  296. {
  297. m_extensions |= VulkanExtensions::EXT_DEBUG_UTILS;
  298. instExtensions[instExtensionCount++] = VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
  299. }
  300. }
  301. if(!(m_extensions
  302. & (VulkanExtensions::EXT_HEADLESS_SURFACE | VulkanExtensions::KHR_XCB_SURFACE
  303. | VulkanExtensions::KHR_XLIB_SURFACE | VulkanExtensions::KHR_WIN32_SURFACE
  304. | VulkanExtensions::KHR_ANDROID_SURFACE)))
  305. {
  306. ANKI_VK_LOGE("Couldn't find suitable surface extension");
  307. return Error::FUNCTION_FAILED;
  308. }
  309. if(instExtensionCount)
  310. {
  311. ANKI_VK_LOGI("Will enable the following instance extensions:");
  312. for(U32 i = 0; i < instExtensionCount; ++i)
  313. {
  314. ANKI_VK_LOGI("\t%s", instExtensions[i]);
  315. }
  316. ci.enabledExtensionCount = instExtensionCount;
  317. ci.ppEnabledExtensionNames = &instExtensions[0];
  318. }
  319. }
  320. #if ANKI_GR_MANAGER_DEBUG_MEMMORY
  321. m_debugAllocCbs = {};
  322. m_debugAllocCbs.pUserData = this;
  323. m_debugAllocCbs.pfnAllocation = allocateCallback;
  324. m_debugAllocCbs.pfnReallocation = reallocateCallback;
  325. m_debugAllocCbs.pfnFree = freeCallback;
  326. VkAllocationCallbacks* pallocCbs = &m_debugAllocCbs;
  327. #else
  328. VkAllocationCallbacks* pallocCbs = nullptr;
  329. #endif
  330. ANKI_VK_CHECK(vkCreateInstance(&ci, pallocCbs, &m_instance));
  331. // Get symbolx
  332. //
  333. volkLoadInstance(m_instance);
  334. // Set debug callbacks
  335. if(!!(m_extensions & VulkanExtensions::EXT_DEBUG_UTILS))
  336. {
  337. VkDebugUtilsMessengerCreateInfoEXT info = {};
  338. info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
  339. info.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT
  340. | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT
  341. | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
  342. info.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT
  343. | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT
  344. | VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
  345. info.pfnUserCallback = debugReportCallbackEXT;
  346. info.pUserData = this;
  347. vkCreateDebugUtilsMessengerEXT(m_instance, &info, nullptr, &m_debugUtilsMessager);
  348. }
  349. // Create the physical device
  350. //
  351. uint32_t count = 0;
  352. ANKI_VK_CHECK(vkEnumeratePhysicalDevices(m_instance, &count, nullptr));
  353. ANKI_VK_LOGI("Number of physical devices: %u", count);
  354. if(count < 1)
  355. {
  356. ANKI_VK_LOGE("Wrong number of physical devices");
  357. return Error::FUNCTION_FAILED;
  358. }
  359. // Find the correct physical device
  360. {
  361. DynamicArrayAuto<VkPhysicalDevice> physicalDevices(m_alloc, count);
  362. ANKI_VK_CHECK(vkEnumeratePhysicalDevices(m_instance, &count, &physicalDevices[0]));
  363. VkPhysicalDevice firstChoice = VK_NULL_HANDLE;
  364. VkPhysicalDevice secondChoice = VK_NULL_HANDLE;
  365. for(U32 devIdx = 0; devIdx < count; ++devIdx)
  366. {
  367. VkPhysicalDeviceProperties2 props = {};
  368. props.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
  369. vkGetPhysicalDeviceProperties2(physicalDevices[devIdx], &props);
  370. if(props.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
  371. {
  372. // Found it
  373. firstChoice = physicalDevices[devIdx];
  374. }
  375. else if(props.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU)
  376. {
  377. secondChoice = physicalDevices[devIdx];
  378. }
  379. }
  380. if(firstChoice != VK_NULL_HANDLE)
  381. {
  382. m_capabilities.m_discreteGpu = true;
  383. m_physicalDevice = firstChoice;
  384. }
  385. else if(secondChoice != VK_NULL_HANDLE)
  386. {
  387. m_capabilities.m_discreteGpu = false;
  388. m_physicalDevice = secondChoice;
  389. }
  390. else
  391. {
  392. ANKI_VK_LOGE("Couldn't find a suitable descrete or integrated physical device");
  393. return Error::FUNCTION_FAILED;
  394. }
  395. }
  396. m_rtPipelineProps.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR;
  397. m_accelerationStructureProps.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_PROPERTIES_KHR;
  398. m_devProps.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
  399. m_devProps.pNext = &m_rtPipelineProps;
  400. m_rtPipelineProps.pNext = &m_accelerationStructureProps;
  401. vkGetPhysicalDeviceProperties2(m_physicalDevice, &m_devProps);
  402. // Find vendor
  403. switch(m_devProps.properties.vendorID)
  404. {
  405. case 0x13B5:
  406. m_capabilities.m_gpuVendor = GpuVendor::ARM;
  407. m_capabilities.m_minSubgroupSize = 16;
  408. m_capabilities.m_maxSubgroupSize = 16;
  409. break;
  410. case 0x10DE:
  411. m_capabilities.m_gpuVendor = GpuVendor::NVIDIA;
  412. m_capabilities.m_minSubgroupSize = 32;
  413. m_capabilities.m_maxSubgroupSize = 32;
  414. break;
  415. case 0x1002:
  416. case 0x1022:
  417. m_capabilities.m_gpuVendor = GpuVendor::AMD;
  418. m_capabilities.m_minSubgroupSize = 32;
  419. m_capabilities.m_maxSubgroupSize = 64;
  420. break;
  421. case 0x8086:
  422. m_capabilities.m_gpuVendor = GpuVendor::INTEL;
  423. m_capabilities.m_minSubgroupSize = 8;
  424. m_capabilities.m_maxSubgroupSize = 32;
  425. break;
  426. case 0x5143:
  427. m_capabilities.m_gpuVendor = GpuVendor::QUALCOMM;
  428. m_capabilities.m_minSubgroupSize = 64;
  429. m_capabilities.m_maxSubgroupSize = 128;
  430. break;
  431. default:
  432. m_capabilities.m_gpuVendor = GpuVendor::UNKNOWN;
  433. // Choose something really low
  434. m_capabilities.m_minSubgroupSize = 8;
  435. m_capabilities.m_maxSubgroupSize = 8;
  436. }
  437. ANKI_VK_LOGI("GPU is %s. Vendor identified as %s", m_devProps.properties.deviceName,
  438. &GPU_VENDOR_STR[m_capabilities.m_gpuVendor][0]);
  439. // Set limits
  440. m_capabilities.m_uniformBufferBindOffsetAlignment =
  441. max<U32>(ANKI_SAFE_ALIGNMENT, U32(m_devProps.properties.limits.minUniformBufferOffsetAlignment));
  442. m_capabilities.m_uniformBufferMaxRange = m_devProps.properties.limits.maxUniformBufferRange;
  443. m_capabilities.m_storageBufferBindOffsetAlignment =
  444. max<U32>(ANKI_SAFE_ALIGNMENT, U32(m_devProps.properties.limits.minStorageBufferOffsetAlignment));
  445. m_capabilities.m_storageBufferMaxRange = m_devProps.properties.limits.maxStorageBufferRange;
  446. m_capabilities.m_textureBufferBindOffsetAlignment =
  447. max<U32>(ANKI_SAFE_ALIGNMENT, U32(m_devProps.properties.limits.minTexelBufferOffsetAlignment));
  448. m_capabilities.m_textureBufferMaxRange = MAX_U32;
  449. m_capabilities.m_computeSharedMemorySize = m_devProps.properties.limits.maxComputeSharedMemorySize;
  450. m_capabilities.m_majorApiVersion = vulkanMajor;
  451. m_capabilities.m_minorApiVersion = vulkanMinor;
  452. m_capabilities.m_shaderGroupHandleSize = m_rtPipelineProps.shaderGroupHandleSize;
  453. m_capabilities.m_sbtRecordAlignment = m_rtPipelineProps.shaderGroupBaseAlignment;
  454. #if ANKI_PLATFORM_MOBILE
  455. if(m_capabilities.m_gpuVendor == GpuVendor::QUALCOMM)
  456. {
  457. // Calling vkCreateGraphicsPipeline from multiple threads crashes qualcomm's compiler
  458. ANKI_VK_LOGI("Enabling workaround for vkCreateGraphicsPipeline crashing when called from multiple threads");
  459. m_globalCreatePipelineMtx = m_alloc.newInstance<Mutex>();
  460. }
  461. #endif
  462. return Error::NONE;
  463. }
  464. Error GrManagerImpl::initDevice(const GrManagerInitInfo& init)
  465. {
  466. uint32_t count = 0;
  467. vkGetPhysicalDeviceQueueFamilyProperties(m_physicalDevice, &count, nullptr);
  468. ANKI_VK_LOGI("Number of queue families: %u", count);
  469. DynamicArrayAuto<VkQueueFamilyProperties> queueInfos(getAllocator());
  470. queueInfos.create(count);
  471. vkGetPhysicalDeviceQueueFamilyProperties(m_physicalDevice, &count, &queueInfos[0]);
  472. const VkQueueFlags GENERAL_QUEUE_FLAGS = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT;
  473. for(U32 i = 0; i < count; ++i)
  474. {
  475. VkBool32 supportsPresent = false;
  476. ANKI_VK_CHECK(vkGetPhysicalDeviceSurfaceSupportKHR(m_physicalDevice, i, m_surface, &supportsPresent));
  477. if(supportsPresent)
  478. {
  479. if((queueInfos[i].queueFlags & GENERAL_QUEUE_FLAGS) == GENERAL_QUEUE_FLAGS)
  480. {
  481. m_queueFamilyIndices[VulkanQueueType::GENERAL] = i;
  482. }
  483. else if((queueInfos[i].queueFlags & VK_QUEUE_COMPUTE_BIT)
  484. && !(queueInfos[i].queueFlags & VK_QUEUE_GRAPHICS_BIT))
  485. {
  486. // This must be the async compute
  487. m_queueFamilyIndices[VulkanQueueType::COMPUTE] = i;
  488. }
  489. }
  490. }
  491. if(m_queueFamilyIndices[VulkanQueueType::GENERAL] == MAX_U32)
  492. {
  493. ANKI_VK_LOGE("Couldn't find a queue family with graphics+compute+transfer+present. "
  494. "Something is wrong");
  495. return Error::FUNCTION_FAILED;
  496. }
  497. if(!m_config->getGrAsyncCompute())
  498. {
  499. m_queueFamilyIndices[VulkanQueueType::COMPUTE] = MAX_U32;
  500. }
  501. if(m_queueFamilyIndices[VulkanQueueType::COMPUTE] == MAX_U32)
  502. {
  503. ANKI_VK_LOGW("Couldn't find an async compute queue. Will try to use the general queue instead");
  504. }
  505. else
  506. {
  507. ANKI_VK_LOGI("Async compute is enabled");
  508. }
  509. const F32 priority = 1.0f;
  510. Array<VkDeviceQueueCreateInfo, U32(VulkanQueueType::COUNT)> q = {};
  511. VkDeviceCreateInfo ci = {};
  512. ci.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
  513. ci.pQueueCreateInfos = &q[0];
  514. for(VulkanQueueType qtype : EnumIterable<VulkanQueueType>())
  515. {
  516. if(m_queueFamilyIndices[qtype] != MAX_U32)
  517. {
  518. q[qtype].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
  519. q[qtype].queueFamilyIndex = m_queueFamilyIndices[qtype];
  520. q[qtype].queueCount = 1;
  521. q[qtype].pQueuePriorities = &priority;
  522. ++ci.queueCreateInfoCount;
  523. }
  524. }
  525. // Extensions
  526. U32 extCount = 0;
  527. vkEnumerateDeviceExtensionProperties(m_physicalDevice, nullptr, &extCount, nullptr);
  528. DynamicArrayAuto<VkExtensionProperties> extensionInfos(getAllocator()); // Keep it alive in the stack
  529. DynamicArrayAuto<const char*> extensionsToEnable(getAllocator());
  530. if(extCount)
  531. {
  532. extensionInfos.create(extCount);
  533. extensionsToEnable.create(extCount);
  534. U32 extensionsToEnableCount = 0;
  535. vkEnumerateDeviceExtensionProperties(m_physicalDevice, nullptr, &extCount, &extensionInfos[0]);
  536. ANKI_VK_LOGV("Found the following device extensions:");
  537. for(U32 i = 0; i < extCount; ++i)
  538. {
  539. ANKI_VK_LOGV("\t%s", extensionInfos[i].extensionName);
  540. }
  541. while(extCount-- != 0)
  542. {
  543. const CString extensionName(&extensionInfos[extCount].extensionName[0]);
  544. if(extensionName == VK_KHR_SWAPCHAIN_EXTENSION_NAME)
  545. {
  546. m_extensions |= VulkanExtensions::KHR_SWAPCHAIN;
  547. extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
  548. }
  549. else if(extensionName == VK_AMD_SHADER_INFO_EXTENSION_NAME && m_config->getCoreDisplayStats())
  550. {
  551. m_extensions |= VulkanExtensions::AMD_SHADER_INFO;
  552. extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
  553. }
  554. else if(extensionName == VK_AMD_RASTERIZATION_ORDER_EXTENSION_NAME)
  555. {
  556. m_extensions |= VulkanExtensions::AMD_RASTERIZATION_ORDER;
  557. extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
  558. }
  559. else if(extensionName == VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME && init.m_config->getGrRayTracing())
  560. {
  561. m_extensions |= VulkanExtensions::KHR_RAY_TRACING;
  562. extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
  563. m_capabilities.m_rayTracingEnabled = true;
  564. }
  565. else if(extensionName == VK_KHR_RAY_QUERY_EXTENSION_NAME && init.m_config->getGrRayTracing())
  566. {
  567. extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
  568. }
  569. else if(extensionName == VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME && init.m_config->getGrRayTracing())
  570. {
  571. extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
  572. }
  573. else if(extensionName == VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME && init.m_config->getGrRayTracing())
  574. {
  575. extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
  576. }
  577. else if(extensionName == VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME && init.m_config->getGrRayTracing())
  578. {
  579. extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
  580. }
  581. else if(extensionName == VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME
  582. && m_config->getCoreDisplayStats())
  583. {
  584. m_extensions |= VulkanExtensions::KHR_PIPELINE_EXECUTABLE_PROPERTIES;
  585. extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
  586. }
  587. else if(extensionName == VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME && m_config->getGrDebugPrintf())
  588. {
  589. extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
  590. }
  591. else if(extensionName == VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME)
  592. {
  593. m_extensions |= VulkanExtensions::EXT_DESCRIPTOR_INDEXING;
  594. extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
  595. }
  596. else if(extensionName == VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME)
  597. {
  598. m_extensions |= VulkanExtensions::KHR_BUFFER_DEVICE_ADDRESS;
  599. extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
  600. }
  601. else if(extensionName == VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME)
  602. {
  603. m_extensions |= VulkanExtensions::EXT_SCALAR_BLOCK_LAYOUT;
  604. extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
  605. }
  606. else if(extensionName == VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME)
  607. {
  608. m_extensions |= VulkanExtensions::KHR_TIMELINE_SEMAPHORE;
  609. extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
  610. }
  611. else if(extensionName == VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME)
  612. {
  613. m_extensions |= VulkanExtensions::KHR_SHADER_FLOAT16_INT8;
  614. extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
  615. }
  616. else if(extensionName == VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME && m_config->getGr64bitAtomics())
  617. {
  618. m_extensions |= VulkanExtensions::KHR_SHADER_ATOMIC_INT64;
  619. extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
  620. }
  621. else if(extensionName == VK_KHR_SPIRV_1_4_EXTENSION_NAME)
  622. {
  623. m_extensions |= VulkanExtensions::KHR_SPIRV_1_4;
  624. extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
  625. }
  626. else if(extensionName == VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME)
  627. {
  628. m_extensions |= VulkanExtensions::KHR_SHADER_FLOAT_CONTROLS;
  629. extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
  630. }
  631. else if(extensionName == VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME
  632. && m_config->getGrSamplerFilterMinMax())
  633. {
  634. m_extensions |= VulkanExtensions::EXT_SAMPLER_FILTER_MIN_MAX;
  635. extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
  636. }
  637. else if(extensionName == VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME)
  638. {
  639. m_extensions |= VulkanExtensions::KHR_CREATE_RENDERPASS_2;
  640. extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
  641. }
  642. else if(extensionName == VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME && m_config->getGrVrs())
  643. {
  644. m_extensions |= VulkanExtensions::KHR_FRAGMENT_SHADING_RATE;
  645. extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
  646. }
  647. else if(extensionName == VK_EXT_ASTC_DECODE_MODE_EXTENSION_NAME)
  648. {
  649. m_extensions |= VulkanExtensions::EXT_ASTC_DECODE_MODE;
  650. extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
  651. }
  652. else if(extensionName == VK_EXT_TEXTURE_COMPRESSION_ASTC_HDR_EXTENSION_NAME)
  653. {
  654. m_extensions |= VulkanExtensions::EXT_TEXTURE_COMPRESSION_ASTC_HDR;
  655. extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
  656. }
  657. }
  658. ANKI_VK_LOGI("Will enable the following device extensions:");
  659. for(U32 i = 0; i < extensionsToEnableCount; ++i)
  660. {
  661. ANKI_VK_LOGI("\t%s", extensionsToEnable[i]);
  662. }
  663. ci.enabledExtensionCount = extensionsToEnableCount;
  664. ci.ppEnabledExtensionNames = &extensionsToEnable[0];
  665. }
  666. // Enable/disable generic features
  667. {
  668. VkPhysicalDeviceFeatures2 devFeatures = {};
  669. devFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
  670. vkGetPhysicalDeviceFeatures2(m_physicalDevice, &devFeatures);
  671. m_devFeatures = devFeatures.features;
  672. m_devFeatures.robustBufferAccess =
  673. (m_config->getGrValidation() && m_devFeatures.robustBufferAccess) ? true : false;
  674. ANKI_VK_LOGI("Robust buffer access is %s", (m_devFeatures.robustBufferAccess) ? "enabled" : "disabled");
  675. ci.pEnabledFeatures = &m_devFeatures;
  676. }
  677. #if ANKI_PLATFORM_MOBILE
  678. if(!(m_extensions & VulkanExtensions::EXT_TEXTURE_COMPRESSION_ASTC_HDR))
  679. {
  680. ANKI_VK_LOGE(VK_EXT_TEXTURE_COMPRESSION_ASTC_HDR_EXTENSION_NAME " is not supported");
  681. return Error::FUNCTION_FAILED;
  682. }
  683. #endif
  684. if(!(m_extensions & VulkanExtensions::KHR_CREATE_RENDERPASS_2))
  685. {
  686. ANKI_VK_LOGE(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME " is not supported");
  687. return Error::FUNCTION_FAILED;
  688. }
  689. if(!!(m_extensions & VulkanExtensions::EXT_SAMPLER_FILTER_MIN_MAX))
  690. {
  691. m_capabilities.m_samplingFilterMinMax = true;
  692. }
  693. else
  694. {
  695. m_capabilities.m_samplingFilterMinMax = false;
  696. ANKI_VK_LOGI(VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME " is not supported or disabled");
  697. }
  698. // Descriptor indexing
  699. if(!(m_extensions & VulkanExtensions::EXT_DESCRIPTOR_INDEXING))
  700. {
  701. ANKI_VK_LOGE(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME " is not supported");
  702. return Error::FUNCTION_FAILED;
  703. }
  704. else
  705. {
  706. m_descriptorIndexingFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT;
  707. VkPhysicalDeviceFeatures2 features = {};
  708. features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
  709. features.pNext = &m_descriptorIndexingFeatures;
  710. vkGetPhysicalDeviceFeatures2(m_physicalDevice, &features);
  711. if(!m_descriptorIndexingFeatures.shaderSampledImageArrayNonUniformIndexing
  712. || !m_descriptorIndexingFeatures.shaderStorageImageArrayNonUniformIndexing)
  713. {
  714. ANKI_VK_LOGE("Non uniform indexing is not supported by the device");
  715. return Error::FUNCTION_FAILED;
  716. }
  717. if(!m_descriptorIndexingFeatures.descriptorBindingSampledImageUpdateAfterBind
  718. || !m_descriptorIndexingFeatures.descriptorBindingStorageImageUpdateAfterBind)
  719. {
  720. ANKI_VK_LOGE("Update descriptors after bind is not supported by the device");
  721. return Error::FUNCTION_FAILED;
  722. }
  723. if(!m_descriptorIndexingFeatures.descriptorBindingUpdateUnusedWhilePending)
  724. {
  725. ANKI_VK_LOGE("Update descriptors while cmd buffer is pending is not supported by the device");
  726. return Error::FUNCTION_FAILED;
  727. }
  728. m_descriptorIndexingFeatures.pNext = const_cast<void*>(ci.pNext);
  729. ci.pNext = &m_descriptorIndexingFeatures;
  730. }
  731. // Buffer address
  732. if(!(m_extensions & VulkanExtensions::KHR_BUFFER_DEVICE_ADDRESS))
  733. {
  734. ANKI_VK_LOGW(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME " is not supported");
  735. }
  736. else
  737. {
  738. m_deviceBufferFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_KHR;
  739. VkPhysicalDeviceFeatures2 features = {};
  740. features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
  741. features.pNext = &m_deviceBufferFeatures;
  742. vkGetPhysicalDeviceFeatures2(m_physicalDevice, &features);
  743. m_deviceBufferFeatures.bufferDeviceAddressCaptureReplay =
  744. m_deviceBufferFeatures.bufferDeviceAddressCaptureReplay && m_config->getGrDebugMarkers();
  745. m_deviceBufferFeatures.bufferDeviceAddressMultiDevice = false;
  746. m_deviceBufferFeatures.pNext = const_cast<void*>(ci.pNext);
  747. ci.pNext = &m_deviceBufferFeatures;
  748. }
  749. // Scalar block layout
  750. if(!(m_extensions & VulkanExtensions::EXT_SCALAR_BLOCK_LAYOUT))
  751. {
  752. ANKI_VK_LOGE(VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME " is not supported");
  753. return Error::FUNCTION_FAILED;
  754. }
  755. else
  756. {
  757. m_scalarBlockLayout.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT;
  758. VkPhysicalDeviceFeatures2 features = {};
  759. features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
  760. features.pNext = &m_scalarBlockLayout;
  761. vkGetPhysicalDeviceFeatures2(m_physicalDevice, &features);
  762. if(!m_scalarBlockLayout.scalarBlockLayout)
  763. {
  764. ANKI_VK_LOGE("Scalar block layout is not supported by the device");
  765. return Error::FUNCTION_FAILED;
  766. }
  767. m_scalarBlockLayout.pNext = const_cast<void*>(ci.pNext);
  768. ci.pNext = &m_scalarBlockLayout;
  769. }
  770. // Timeline semaphore
  771. if(!(m_extensions & VulkanExtensions::KHR_TIMELINE_SEMAPHORE))
  772. {
  773. ANKI_VK_LOGE(VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME " is not supported");
  774. return Error::FUNCTION_FAILED;
  775. }
  776. else
  777. {
  778. m_timelineSemaphoreFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES_KHR;
  779. VkPhysicalDeviceFeatures2 features = {};
  780. features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
  781. features.pNext = &m_timelineSemaphoreFeatures;
  782. vkGetPhysicalDeviceFeatures2(m_physicalDevice, &features);
  783. if(!m_timelineSemaphoreFeatures.timelineSemaphore)
  784. {
  785. ANKI_VK_LOGE("Timeline semaphores are not supported by the device");
  786. return Error::FUNCTION_FAILED;
  787. }
  788. m_timelineSemaphoreFeatures.pNext = const_cast<void*>(ci.pNext);
  789. ci.pNext = &m_timelineSemaphoreFeatures;
  790. }
  791. // Set RT features
  792. if(!!(m_extensions & VulkanExtensions::KHR_RAY_TRACING))
  793. {
  794. m_rtPipelineFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR;
  795. m_rayQueryFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_QUERY_FEATURES_KHR;
  796. m_accelerationStructureFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR;
  797. VkPhysicalDeviceFeatures2 features = {};
  798. features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
  799. features.pNext = &m_rtPipelineFeatures;
  800. m_rtPipelineFeatures.pNext = &m_rayQueryFeatures;
  801. m_rayQueryFeatures.pNext = &m_accelerationStructureFeatures;
  802. vkGetPhysicalDeviceFeatures2(m_physicalDevice, &features);
  803. if(!m_rtPipelineFeatures.rayTracingPipeline || !m_rayQueryFeatures.rayQuery
  804. || !m_accelerationStructureFeatures.accelerationStructure)
  805. {
  806. ANKI_VK_LOGE("Ray tracing and ray query are both required");
  807. return Error::FUNCTION_FAILED;
  808. }
  809. // Only enable what's necessary
  810. m_rtPipelineFeatures.rayTracingPipelineShaderGroupHandleCaptureReplay = false;
  811. m_rtPipelineFeatures.rayTracingPipelineShaderGroupHandleCaptureReplayMixed = false;
  812. m_rtPipelineFeatures.rayTraversalPrimitiveCulling = false;
  813. m_accelerationStructureFeatures.accelerationStructureCaptureReplay = false;
  814. m_accelerationStructureFeatures.accelerationStructureHostCommands = false;
  815. m_accelerationStructureFeatures.descriptorBindingAccelerationStructureUpdateAfterBind = false;
  816. ANKI_ASSERT(m_accelerationStructureFeatures.pNext == nullptr);
  817. m_accelerationStructureFeatures.pNext = const_cast<void*>(ci.pNext);
  818. ci.pNext = &m_rtPipelineFeatures;
  819. }
  820. // Pipeline features
  821. if(!!(m_extensions & VulkanExtensions::KHR_PIPELINE_EXECUTABLE_PROPERTIES))
  822. {
  823. m_pplineExecutablePropertiesFeatures.sType =
  824. VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR;
  825. m_pplineExecutablePropertiesFeatures.pipelineExecutableInfo = true;
  826. m_pplineExecutablePropertiesFeatures.pNext = const_cast<void*>(ci.pNext);
  827. ci.pNext = &m_pplineExecutablePropertiesFeatures;
  828. }
  829. // F16 I8
  830. if(!(m_extensions & VulkanExtensions::KHR_SHADER_FLOAT16_INT8))
  831. {
  832. ANKI_VK_LOGE(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME " is not supported");
  833. return Error::FUNCTION_FAILED;
  834. }
  835. else
  836. {
  837. m_float16Int8Features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR;
  838. VkPhysicalDeviceFeatures2 features = {};
  839. features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
  840. features.pNext = &m_float16Int8Features;
  841. vkGetPhysicalDeviceFeatures2(m_physicalDevice, &features);
  842. m_float16Int8Features.pNext = const_cast<void*>(ci.pNext);
  843. ci.pNext = &m_float16Int8Features;
  844. }
  845. // 64bit atomics
  846. if(!(m_extensions & VulkanExtensions::KHR_SHADER_ATOMIC_INT64))
  847. {
  848. ANKI_VK_LOGW(VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME " is not supported or disabled");
  849. m_capabilities.m_64bitAtomics = false;
  850. }
  851. else
  852. {
  853. m_capabilities.m_64bitAtomics = true;
  854. m_atomicInt64Features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES_KHR;
  855. VkPhysicalDeviceFeatures2 features = {};
  856. features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
  857. features.pNext = &m_atomicInt64Features;
  858. vkGetPhysicalDeviceFeatures2(m_physicalDevice, &features);
  859. m_atomicInt64Features.pNext = const_cast<void*>(ci.pNext);
  860. ci.pNext = &m_atomicInt64Features;
  861. }
  862. // VRS
  863. if(!(m_extensions & VulkanExtensions::KHR_FRAGMENT_SHADING_RATE))
  864. {
  865. ANKI_VK_LOGI(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME " is not supported or disabled");
  866. m_capabilities.m_vrs = false;
  867. }
  868. else
  869. {
  870. m_capabilities.m_vrs = true;
  871. m_fragmentShadingRateFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR;
  872. VkPhysicalDeviceFeatures2 features = {};
  873. features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
  874. features.pNext = &m_fragmentShadingRateFeatures;
  875. vkGetPhysicalDeviceFeatures2(m_physicalDevice, &features);
  876. // Some checks
  877. if(!m_fragmentShadingRateFeatures.attachmentFragmentShadingRate
  878. || !m_fragmentShadingRateFeatures.pipelineFragmentShadingRate)
  879. {
  880. ANKI_VK_LOGW(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME
  881. " doesn't support attachment and/or pipeline rates. Will disable VRS");
  882. m_capabilities.m_vrs = false;
  883. }
  884. else
  885. {
  886. // Disable some things
  887. m_fragmentShadingRateFeatures.primitiveFragmentShadingRate = false;
  888. }
  889. if(m_capabilities.m_vrs)
  890. {
  891. VkPhysicalDeviceFragmentShadingRatePropertiesKHR fragmentShadingRateProperties = {};
  892. fragmentShadingRateProperties.sType =
  893. VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_PROPERTIES_KHR;
  894. VkPhysicalDeviceProperties2 properties = {};
  895. properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
  896. properties.pNext = &fragmentShadingRateProperties;
  897. vkGetPhysicalDeviceProperties2(m_physicalDevice, &properties);
  898. if(fragmentShadingRateProperties.minFragmentShadingRateAttachmentTexelSize.width > 16
  899. || fragmentShadingRateProperties.minFragmentShadingRateAttachmentTexelSize.height > 16
  900. || fragmentShadingRateProperties.maxFragmentShadingRateAttachmentTexelSize.width < 8
  901. || fragmentShadingRateProperties.maxFragmentShadingRateAttachmentTexelSize.height < 8)
  902. {
  903. ANKI_VK_LOGW(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME
  904. " doesn't support 8x8 or 16x16 shading rate attachment texel size. Will disable VRS");
  905. m_capabilities.m_vrs = false;
  906. }
  907. else
  908. {
  909. m_capabilities.m_minShadingRateImageTexelSize =
  910. max(fragmentShadingRateProperties.minFragmentShadingRateAttachmentTexelSize.width,
  911. fragmentShadingRateProperties.minFragmentShadingRateAttachmentTexelSize.height);
  912. }
  913. }
  914. if(m_capabilities.m_vrs)
  915. {
  916. m_fragmentShadingRateFeatures.pNext = const_cast<void*>(ci.pNext);
  917. ci.pNext = &m_fragmentShadingRateFeatures;
  918. }
  919. }
  920. ANKI_VK_CHECK(vkCreateDevice(m_physicalDevice, &ci, nullptr, &m_device));
  921. // Get VK_AMD_shader_info entry points
  922. if(!!(m_extensions & VulkanExtensions::AMD_SHADER_INFO))
  923. {
  924. m_pfnGetShaderInfoAMD =
  925. reinterpret_cast<PFN_vkGetShaderInfoAMD>(vkGetDeviceProcAddr(m_device, "vkGetShaderInfoAMD"));
  926. if(!m_pfnGetShaderInfoAMD)
  927. {
  928. ANKI_VK_LOGW("VK_AMD_shader_info is present but vkGetShaderInfoAMD is not there");
  929. }
  930. }
  931. if(!(m_extensions & VulkanExtensions::KHR_SPIRV_1_4))
  932. {
  933. ANKI_VK_LOGE(VK_KHR_SPIRV_1_4_EXTENSION_NAME " is not supported");
  934. return Error::FUNCTION_FAILED;
  935. }
  936. if(!(m_extensions & VulkanExtensions::KHR_SHADER_FLOAT_CONTROLS))
  937. {
  938. ANKI_VK_LOGE(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME " is not supported");
  939. return Error::FUNCTION_FAILED;
  940. }
  941. return Error::NONE;
  942. }
  943. Error GrManagerImpl::initMemory()
  944. {
  945. vkGetPhysicalDeviceMemoryProperties(m_physicalDevice, &m_memoryProperties);
  946. // Print some info
  947. ANKI_VK_LOGI("Vulkan memory info:");
  948. for(U32 i = 0; i < m_memoryProperties.memoryHeapCount; ++i)
  949. {
  950. ANKI_VK_LOGI("\tHeap %u size %zu", i, m_memoryProperties.memoryHeaps[i].size);
  951. }
  952. for(U32 i = 0; i < m_memoryProperties.memoryTypeCount; ++i)
  953. {
  954. ANKI_VK_LOGI("\tMem type %u points to heap %u, flags %" ANKI_PRIb32, i,
  955. m_memoryProperties.memoryTypes[i].heapIndex,
  956. ANKI_FORMAT_U32(m_memoryProperties.memoryTypes[i].propertyFlags));
  957. }
  958. m_gpuMemManager.init(m_physicalDevice, m_device, getAllocator(),
  959. !!(m_extensions & VulkanExtensions::KHR_BUFFER_DEVICE_ADDRESS));
  960. return Error::NONE;
  961. }
  962. #if ANKI_GR_MANAGER_DEBUG_MEMMORY
  963. void* GrManagerImpl::allocateCallback(void* userData, size_t size, size_t alignment,
  964. VkSystemAllocationScope allocationScope)
  965. {
  966. if(ANKI_UNLIKELY(size == 0))
  967. {
  968. return nullptr;
  969. }
  970. ANKI_ASSERT(userData);
  971. ANKI_ASSERT(size);
  972. ANKI_ASSERT(isPowerOfTwo(alignment));
  973. ANKI_ASSERT(alignment <= MAX_ALLOC_ALIGNMENT);
  974. auto alloc = static_cast<GrManagerImpl*>(userData)->getAllocator();
  975. PtrSize newSize = size + sizeof(AllocHeader);
  976. AllocHeader* header = static_cast<AllocHeader*>(alloc.getMemoryPool().allocate(newSize, MAX_ALLOC_ALIGNMENT));
  977. header->m_sig = ALLOC_SIG;
  978. header->m_size = size;
  979. ++header;
  980. return static_cast<AllocHeader*>(header);
  981. }
  982. void* GrManagerImpl::reallocateCallback(void* userData, void* original, size_t size, size_t alignment,
  983. VkSystemAllocationScope allocationScope)
  984. {
  985. if(original && size == 0)
  986. {
  987. freeCallback(userData, original);
  988. return nullptr;
  989. }
  990. void* mem = allocateCallback(userData, size, alignment, allocationScope);
  991. if(original)
  992. {
  993. // Move the data
  994. AllocHeader* header = static_cast<AllocHeader*>(original);
  995. --header;
  996. ANKI_ASSERT(header->m_sig == ALLOC_SIG);
  997. memcpy(mem, original, header->m_size);
  998. }
  999. return mem;
  1000. }
  1001. void GrManagerImpl::freeCallback(void* userData, void* ptr)
  1002. {
  1003. if(ptr)
  1004. {
  1005. ANKI_ASSERT(userData);
  1006. auto alloc = static_cast<GrManagerImpl*>(userData)->getAllocator();
  1007. AllocHeader* header = static_cast<AllocHeader*>(ptr);
  1008. --header;
  1009. ANKI_ASSERT(header->m_sig == ALLOC_SIG);
  1010. alloc.getMemoryPool().free(header);
  1011. }
  1012. }
  1013. #endif
  1014. TexturePtr GrManagerImpl::acquireNextPresentableTexture()
  1015. {
  1016. ANKI_TRACE_SCOPED_EVENT(VK_ACQUIRE_IMAGE);
  1017. LockGuard<Mutex> lock(m_globalMtx);
  1018. PerFrame& frame = m_perFrame[m_frame % MAX_FRAMES_IN_FLIGHT];
  1019. // Create sync objects
  1020. MicroFencePtr fence = m_fenceFactory.newInstance();
  1021. frame.m_acquireSemaphore = m_semaphoreFactory.newInstance(fence, false);
  1022. // Get new image
  1023. uint32_t imageIdx;
  1024. VkResult res = vkAcquireNextImageKHR(m_device, m_crntSwapchain->m_swapchain, UINT64_MAX,
  1025. frame.m_acquireSemaphore->getHandle(), fence->getHandle(), &imageIdx);
  1026. if(res == VK_ERROR_OUT_OF_DATE_KHR)
  1027. {
  1028. ANKI_VK_LOGW("Swapchain is out of date. Will wait for the queue and create a new one");
  1029. for(VkQueue queue : m_queues)
  1030. {
  1031. if(queue)
  1032. {
  1033. vkQueueWaitIdle(queue);
  1034. }
  1035. }
  1036. m_crntSwapchain.reset(nullptr);
  1037. m_crntSwapchain = m_swapchainFactory.newInstance();
  1038. // Can't fail a second time
  1039. ANKI_VK_CHECKF(vkAcquireNextImageKHR(m_device, m_crntSwapchain->m_swapchain, UINT64_MAX,
  1040. frame.m_acquireSemaphore->getHandle(), fence->getHandle(), &imageIdx));
  1041. }
  1042. else
  1043. {
  1044. ANKI_VK_CHECKF(res);
  1045. }
  1046. m_acquiredImageIdx = U8(imageIdx);
  1047. return m_crntSwapchain->m_textures[imageIdx];
  1048. }
  1049. void GrManagerImpl::endFrame()
  1050. {
  1051. ANKI_TRACE_SCOPED_EVENT(VK_PRESENT);
  1052. LockGuard<Mutex> lock(m_globalMtx);
  1053. PerFrame& frame = m_perFrame[m_frame % MAX_FRAMES_IN_FLIGHT];
  1054. // Wait for the fence of N-2 frame
  1055. const U waitFrameIdx = (m_frame + 1) % MAX_FRAMES_IN_FLIGHT;
  1056. PerFrame& waitFrame = m_perFrame[waitFrameIdx];
  1057. if(waitFrame.m_presentFence)
  1058. {
  1059. waitFrame.m_presentFence->wait();
  1060. }
  1061. resetFrame(waitFrame);
  1062. if(!frame.m_renderSemaphore)
  1063. {
  1064. ANKI_VK_LOGW("Nobody draw to the default framebuffer");
  1065. }
  1066. // Present
  1067. VkResult res;
  1068. VkPresentInfoKHR present = {};
  1069. present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
  1070. present.waitSemaphoreCount = (frame.m_renderSemaphore) ? 1 : 0;
  1071. present.pWaitSemaphores = (frame.m_renderSemaphore) ? &frame.m_renderSemaphore->getHandle() : nullptr;
  1072. present.swapchainCount = 1;
  1073. present.pSwapchains = &m_crntSwapchain->m_swapchain;
  1074. const U32 idx = m_acquiredImageIdx;
  1075. present.pImageIndices = &idx;
  1076. present.pResults = &res;
  1077. const VkResult res1 = vkQueuePresentKHR(m_queues[frame.m_queueWroteToSwapchainImage], &present);
  1078. if(res1 == VK_ERROR_OUT_OF_DATE_KHR)
  1079. {
  1080. ANKI_VK_LOGW("Swapchain is out of date. Will wait for the queues and create a new one");
  1081. for(VkQueue queue : m_queues)
  1082. {
  1083. if(queue)
  1084. {
  1085. vkQueueWaitIdle(queue);
  1086. }
  1087. }
  1088. vkDeviceWaitIdle(m_device);
  1089. m_crntSwapchain.reset(nullptr);
  1090. m_crntSwapchain = m_swapchainFactory.newInstance();
  1091. }
  1092. else
  1093. {
  1094. ANKI_VK_CHECKF(res1);
  1095. ANKI_VK_CHECKF(res);
  1096. }
  1097. m_descrFactory.endFrame();
  1098. // Finalize
  1099. ++m_frame;
  1100. }
  1101. void GrManagerImpl::resetFrame(PerFrame& frame)
  1102. {
  1103. frame.m_presentFence.reset(nullptr);
  1104. frame.m_acquireSemaphore.reset(nullptr);
  1105. frame.m_renderSemaphore.reset(nullptr);
  1106. }
  1107. void GrManagerImpl::flushCommandBuffer(MicroCommandBufferPtr cmdb, Bool cmdbRenderedToSwapchain,
  1108. WeakArray<MicroSemaphorePtr> userWaitSemaphores,
  1109. MicroSemaphorePtr* userSignalSemaphore, Bool wait)
  1110. {
  1111. constexpr U32 maxSemaphores = 8;
  1112. VkSubmitInfo submit = {};
  1113. submit.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
  1114. Array<VkSemaphore, maxSemaphores> waitSemaphores;
  1115. submit.pWaitSemaphores = &waitSemaphores[0];
  1116. Array<VkSemaphore, maxSemaphores> signalSemaphores;
  1117. submit.pSignalSemaphores = &signalSemaphores[0];
  1118. Array<VkPipelineStageFlags, maxSemaphores> waitStages;
  1119. submit.pWaitDstStageMask = &waitStages[0];
  1120. // First thing, create a fence
  1121. MicroFencePtr fence = m_fenceFactory.newInstance();
  1122. // Command buffer
  1123. const VkCommandBuffer handle = cmdb->getHandle();
  1124. cmdb->setFence(fence);
  1125. submit.commandBufferCount = 1;
  1126. submit.pCommandBuffers = &handle;
  1127. // Handle user semaphores
  1128. Array<U64, maxSemaphores> waitTimelineValues;
  1129. Array<U64, maxSemaphores> signalTimelineValues;
  1130. VkTimelineSemaphoreSubmitInfo timelineInfo = {};
  1131. timelineInfo.sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO;
  1132. timelineInfo.waitSemaphoreValueCount = userWaitSemaphores.getSize();
  1133. timelineInfo.pWaitSemaphoreValues = &waitTimelineValues[0];
  1134. timelineInfo.signalSemaphoreValueCount = (userSignalSemaphore != nullptr);
  1135. timelineInfo.pSignalSemaphoreValues = &signalTimelineValues[0];
  1136. submit.pNext = &timelineInfo;
  1137. for(MicroSemaphorePtr& userWaitSemaphore : userWaitSemaphores)
  1138. {
  1139. ANKI_ASSERT(userWaitSemaphore.isCreated());
  1140. ANKI_ASSERT(userWaitSemaphore->isTimeline());
  1141. waitSemaphores[submit.waitSemaphoreCount] = userWaitSemaphore->getHandle();
  1142. waitTimelineValues[submit.waitSemaphoreCount] = userWaitSemaphore->getSemaphoreValue();
  1143. // Be a bit conservative
  1144. waitStages[submit.waitSemaphoreCount] = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
  1145. ++submit.waitSemaphoreCount;
  1146. // Refresh the fence because the semaphore can't be recycled until the current submission is done
  1147. userWaitSemaphore->setFence(fence);
  1148. }
  1149. if(userSignalSemaphore)
  1150. {
  1151. *userSignalSemaphore = m_semaphoreFactory.newInstance(fence, true);
  1152. signalSemaphores[submit.signalSemaphoreCount] = (*userSignalSemaphore)->getHandle();
  1153. signalTimelineValues[submit.signalSemaphoreCount] = (*userSignalSemaphore)->getNextSemaphoreValue();
  1154. ++submit.signalSemaphoreCount;
  1155. }
  1156. // Submit
  1157. {
  1158. // Protect the class, the queue and other stuff
  1159. LockGuard<Mutex> lock(m_globalMtx);
  1160. // Do some special stuff for the last command buffer
  1161. PerFrame& frame = m_perFrame[m_frame % MAX_FRAMES_IN_FLIGHT];
  1162. if(cmdbRenderedToSwapchain)
  1163. {
  1164. // Wait semaphore
  1165. waitSemaphores[submit.waitSemaphoreCount] = frame.m_acquireSemaphore->getHandle();
  1166. // That depends on how we use the swapchain img. Be a bit conservative
  1167. waitStages[submit.waitSemaphoreCount] =
  1168. VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
  1169. ++submit.waitSemaphoreCount;
  1170. // Refresh the fence because the semaphore can't be recycled until the current submission is done
  1171. frame.m_acquireSemaphore->setFence(fence);
  1172. // Create the semaphore to signal
  1173. ANKI_ASSERT(!frame.m_renderSemaphore && "Only one begin/end render pass is allowed with the default fb");
  1174. frame.m_renderSemaphore = m_semaphoreFactory.newInstance(fence, false);
  1175. signalSemaphores[submit.signalSemaphoreCount++] = frame.m_renderSemaphore->getHandle();
  1176. // Update the frame fence
  1177. frame.m_presentFence = fence;
  1178. // Update the swapchain's fence
  1179. m_crntSwapchain->setFence(fence);
  1180. frame.m_queueWroteToSwapchainImage = cmdb->getVulkanQueueType();
  1181. }
  1182. // Submit
  1183. ANKI_TRACE_SCOPED_EVENT(VK_QUEUE_SUBMIT);
  1184. ANKI_VK_CHECKF(vkQueueSubmit(m_queues[cmdb->getVulkanQueueType()], 1, &submit, fence->getHandle()));
  1185. if(wait)
  1186. {
  1187. vkQueueWaitIdle(m_queues[cmdb->getVulkanQueueType()]);
  1188. }
  1189. }
  1190. // Garbage work
  1191. if(cmdbRenderedToSwapchain)
  1192. {
  1193. m_frameGarbageCollector.setNewFrame(fence);
  1194. }
  1195. }
  1196. void GrManagerImpl::finish()
  1197. {
  1198. LockGuard<Mutex> lock(m_globalMtx);
  1199. for(VkQueue queue : m_queues)
  1200. {
  1201. if(queue)
  1202. {
  1203. vkQueueWaitIdle(queue);
  1204. }
  1205. }
  1206. }
  1207. void GrManagerImpl::trySetVulkanHandleName(CString name, VkObjectType type, U64 handle) const
  1208. {
  1209. if(name && name.getLength() && !!(m_extensions & VulkanExtensions::EXT_DEBUG_UTILS))
  1210. {
  1211. VkDebugUtilsObjectNameInfoEXT info = {};
  1212. info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
  1213. info.objectHandle = handle;
  1214. info.objectType = type;
  1215. info.pObjectName = name.cstr();
  1216. vkSetDebugUtilsObjectNameEXT(m_device, &info);
  1217. }
  1218. }
  1219. VkBool32 GrManagerImpl::debugReportCallbackEXT(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
  1220. [[maybe_unused]] VkDebugUtilsMessageTypeFlagsEXT messageTypes,
  1221. const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
  1222. void* pUserData)
  1223. {
  1224. // Get all names of affected objects
  1225. GrManagerImpl* self = static_cast<GrManagerImpl*>(pUserData);
  1226. StringAuto objectNames(self->m_alloc);
  1227. if(pCallbackData->objectCount)
  1228. {
  1229. for(U32 i = 0; i < pCallbackData->objectCount; ++i)
  1230. {
  1231. const Char* name = pCallbackData->pObjects[i].pObjectName;
  1232. objectNames.append((name) ? name : "?");
  1233. if(i < pCallbackData->objectCount - 1)
  1234. {
  1235. objectNames.append(", ");
  1236. }
  1237. }
  1238. }
  1239. else
  1240. {
  1241. objectNames.create("N/A");
  1242. }
  1243. if(messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT)
  1244. {
  1245. ANKI_VK_LOGE("VK debug report: %s. Affected objects: %s", pCallbackData->pMessage, objectNames.cstr());
  1246. }
  1247. else if(messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT)
  1248. {
  1249. ANKI_VK_LOGW("VK debug report: %s. Affected objects: %s", pCallbackData->pMessage, objectNames.cstr());
  1250. }
  1251. else
  1252. {
  1253. ANKI_VK_LOGI("VK debug report: %s. Affected objects: %s", pCallbackData->pMessage, objectNames.cstr());
  1254. }
  1255. return false;
  1256. }
  1257. void GrManagerImpl::printPipelineShaderInfo(VkPipeline ppline, CString name, ShaderTypeBit stages, U64 hash) const
  1258. {
  1259. if(printPipelineShaderInfoInternal(ppline, name, stages, hash))
  1260. {
  1261. ANKI_VK_LOGE("Ignoring previous errors");
  1262. }
  1263. }
  1264. Error GrManagerImpl::printPipelineShaderInfoInternal(VkPipeline ppline, CString name, ShaderTypeBit stages,
  1265. U64 hash) const
  1266. {
  1267. if(m_pfnGetShaderInfoAMD)
  1268. {
  1269. VkShaderStatisticsInfoAMD stats = {};
  1270. LockGuard<SpinLock> lock(m_shaderStatsFileMtx);
  1271. // Open the file
  1272. if(!m_shaderStatsFile.isOpen())
  1273. {
  1274. ANKI_CHECK(m_shaderStatsFile.open(
  1275. StringAuto(getAllocator()).sprintf("%s/../ppline_stats.csv", m_cacheDir.cstr()).toCString(),
  1276. FileOpenFlag::WRITE));
  1277. ANKI_CHECK(m_shaderStatsFile.writeText("ppline name,hash,"
  1278. "stage 0 VGPR,stage 0 SGPR,"
  1279. "stage 1 VGPR,stage 1 SGPR,"
  1280. "stage 2 VGPR,stage 2 SGPR,"
  1281. "stage 3 VGPR,stage 3 SGPR,"
  1282. "stage 4 VGPR,stage 4 SGPR,"
  1283. "stage 5 VGPR,stage 5 SGPR\n"));
  1284. }
  1285. ANKI_CHECK(m_shaderStatsFile.writeText("%s,0x%" PRIx64 ",", name.cstr(), hash));
  1286. StringAuto str(getAllocator());
  1287. for(ShaderType type = ShaderType::FIRST; type < ShaderType::COUNT; ++type)
  1288. {
  1289. ShaderTypeBit stage = stages & ShaderTypeBit(1 << type);
  1290. if(!stage)
  1291. {
  1292. ANKI_CHECK(m_shaderStatsFile.writeText((type != ShaderType::LAST) ? "0,0," : "0,0\n"));
  1293. continue;
  1294. }
  1295. size_t size = sizeof(stats);
  1296. ANKI_VK_CHECK(m_pfnGetShaderInfoAMD(m_device, ppline, VkShaderStageFlagBits(convertShaderTypeBit(stage)),
  1297. VK_SHADER_INFO_TYPE_STATISTICS_AMD, &size, &stats));
  1298. str.append(StringAuto(getAllocator())
  1299. .sprintf("Stage %u: VGRPS %02u, SGRPS %02u ", U32(type), stats.resourceUsage.numUsedVgprs,
  1300. stats.resourceUsage.numUsedSgprs));
  1301. ANKI_CHECK(m_shaderStatsFile.writeText((type != ShaderType::LAST) ? "%u,%u," : "%u,%u\n",
  1302. stats.resourceUsage.numUsedVgprs, stats.resourceUsage.numUsedSgprs));
  1303. }
  1304. ANKI_VK_LOGI("Pipeline \"%s\" (0x%016" PRIx64 ") stats: %s", name.cstr(), hash, str.cstr());
  1305. // Flush the file just in case
  1306. ANKI_CHECK(m_shaderStatsFile.flush());
  1307. }
  1308. if(!!(m_extensions & VulkanExtensions::KHR_PIPELINE_EXECUTABLE_PROPERTIES))
  1309. {
  1310. StringListAuto log(m_alloc);
  1311. VkPipelineInfoKHR pplineInf = {};
  1312. pplineInf.sType = VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR;
  1313. pplineInf.pipeline = ppline;
  1314. U32 executableCount = 0;
  1315. ANKI_VK_CHECK(vkGetPipelineExecutablePropertiesKHR(m_device, &pplineInf, &executableCount, nullptr));
  1316. DynamicArrayAuto<VkPipelineExecutablePropertiesKHR> executableProps(m_alloc, executableCount);
  1317. for(VkPipelineExecutablePropertiesKHR& prop : executableProps)
  1318. {
  1319. prop = {};
  1320. prop.sType = VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_PROPERTIES_KHR;
  1321. }
  1322. ANKI_VK_CHECK(
  1323. vkGetPipelineExecutablePropertiesKHR(m_device, &pplineInf, &executableCount, &executableProps[0]));
  1324. log.pushBackSprintf("Pipeline info \"%s\" (0x%016" PRIx64 "): ", name.cstr(), hash);
  1325. for(U32 i = 0; i < executableCount; ++i)
  1326. {
  1327. const VkPipelineExecutablePropertiesKHR& p = executableProps[i];
  1328. log.pushBackSprintf("%s: ", p.description);
  1329. // Get stats
  1330. VkPipelineExecutableInfoKHR exeInf = {};
  1331. exeInf.sType = VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INFO_KHR;
  1332. exeInf.executableIndex = i;
  1333. exeInf.pipeline = ppline;
  1334. U32 statCount = 0;
  1335. vkGetPipelineExecutableStatisticsKHR(m_device, &exeInf, &statCount, nullptr);
  1336. DynamicArrayAuto<VkPipelineExecutableStatisticKHR> stats(m_alloc, statCount);
  1337. for(VkPipelineExecutableStatisticKHR& s : stats)
  1338. {
  1339. s = {};
  1340. s.sType = VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_STATISTIC_KHR;
  1341. }
  1342. vkGetPipelineExecutableStatisticsKHR(m_device, &exeInf, &statCount, &stats[0]);
  1343. for(U32 s = 0; s < statCount; ++s)
  1344. {
  1345. const VkPipelineExecutableStatisticKHR& ss = stats[s];
  1346. switch(ss.format)
  1347. {
  1348. case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_BOOL32_KHR:
  1349. log.pushBackSprintf("%s: %u, ", ss.name, ss.value.b32);
  1350. break;
  1351. case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_INT64_KHR:
  1352. log.pushBackSprintf("%s: %" PRId64 ", ", ss.name, ss.value.i64);
  1353. break;
  1354. case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR:
  1355. log.pushBackSprintf("%s: %" PRIu64 ", ", ss.name, ss.value.u64);
  1356. break;
  1357. case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_FLOAT64_KHR:
  1358. log.pushBackSprintf("%s: %f, ", ss.name, ss.value.f64);
  1359. break;
  1360. default:
  1361. ANKI_ASSERT(0);
  1362. }
  1363. }
  1364. log.pushBackSprintf("Subgroup size: %u", p.subgroupSize);
  1365. if(i < executableCount - 1)
  1366. {
  1367. log.pushBack(", ");
  1368. }
  1369. }
  1370. StringAuto finalLog(m_alloc);
  1371. log.join("", finalLog);
  1372. ANKI_VK_LOGV("%s", finalLog.cstr());
  1373. }
  1374. return Error::NONE;
  1375. }
  1376. } // end namespace anki