| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491 |
- // Copyright (C) 2009-2021, Panagiotis Christopoulos Charitos and contributors.
- // All rights reserved.
- // Code licensed under the BSD License.
- // http://www.anki3d.org/LICENSE
- #include <AnKi/Gr/Vulkan/GrManagerImpl.h>
- #include <AnKi/Gr/GrManager.h>
- #include <AnKi/Gr/Vulkan/CommandBufferImpl.h>
- #include <AnKi/Gr/CommandBuffer.h>
- #include <AnKi/Gr/Fence.h>
- #include <AnKi/Gr/Vulkan/FenceImpl.h>
- #include <AnKi/Util/Functions.h>
- #include <AnKi/Util/StringList.h>
- #include <AnKi/Core/ConfigSet.h>
- #include <glslang/Public/ShaderLang.h>
- namespace anki
- {
- GrManagerImpl::~GrManagerImpl()
- {
- // 1st THING: wait for the present fences because I don't know if waiting on queue will cover this
- for(PerFrame& frame : m_perFrame)
- {
- if(frame.m_presentFence.isCreated())
- {
- frame.m_presentFence->wait();
- }
- }
- // 2nd THING: wait for the GPU
- for(VkQueue& queue : m_queues)
- {
- LockGuard<Mutex> lock(m_globalMtx);
- if(queue)
- {
- vkQueueWaitIdle(queue);
- queue = VK_NULL_HANDLE;
- }
- }
- m_cmdbFactory.destroy();
- // 3rd THING: The destroy everything that has a reference to GrObjects.
- for(PerFrame& frame : m_perFrame)
- {
- frame.m_presentFence.reset(nullptr);
- frame.m_acquireSemaphore.reset(nullptr);
- frame.m_renderSemaphore.reset(nullptr);
- }
- m_crntSwapchain.reset(nullptr);
- // 4th THING: Continue with the rest
- m_gpuMemManager.destroy();
- m_barrierFactory.destroy(); // Destroy before fences
- m_semaphoreFactory.destroy(); // Destroy before fences
- m_swapchainFactory.destroy(); // Destroy before fences
- m_pplineLayoutFactory.destroy();
- m_descrFactory.destroy();
- m_pplineCache.destroy(m_device, m_physicalDevice, getAllocator());
- m_fenceFactory.destroy();
- m_samplerFactory.destroy();
- if(m_device)
- {
- vkDestroyDevice(m_device, nullptr);
- }
- if(m_surface)
- {
- vkDestroySurfaceKHR(m_instance, m_surface, nullptr);
- }
- if(m_debugCallback)
- {
- vkDestroyDebugReportCallbackEXT(m_instance, m_debugCallback, nullptr);
- }
- if(m_instance)
- {
- #if ANKI_GR_MANAGER_DEBUG_MEMMORY
- VkAllocationCallbacks* pallocCbs = &m_debugAllocCbs;
- #else
- VkAllocationCallbacks* pallocCbs = nullptr;
- #endif
- vkDestroyInstance(m_instance, pallocCbs);
- }
- m_vkHandleToName.destroy(getAllocator());
- }
- Error GrManagerImpl::init(const GrManagerInitInfo& init)
- {
- const Error err = initInternal(init);
- if(err)
- {
- ANKI_VK_LOGE("Vulkan initialization failed");
- return Error::FUNCTION_FAILED;
- }
- return Error::NONE;
- }
- Error GrManagerImpl::initInternal(const GrManagerInitInfo& init)
- {
- ANKI_VK_LOGI("Initializing Vulkan backend");
- ANKI_CHECK(initInstance(init));
- ANKI_CHECK(initSurface(init));
- ANKI_CHECK(initDevice(init));
- for(VulkanQueueType qtype : EnumIterable<VulkanQueueType>())
- {
- if(m_queueFamilyIndices[qtype] != MAX_U32)
- {
- vkGetDeviceQueue(m_device, m_queueFamilyIndices[qtype], 0, &m_queues[qtype]);
- }
- else
- {
- m_queues[qtype] = VK_NULL_HANDLE;
- }
- }
- m_swapchainFactory.init(this, init.m_config->getBool("gr_vsync"));
- m_crntSwapchain = m_swapchainFactory.newInstance();
- ANKI_CHECK(m_pplineCache.init(m_device, m_physicalDevice, init.m_cacheDirectory, *init.m_config, getAllocator()));
- ANKI_CHECK(initMemory(*init.m_config));
- ANKI_CHECK(m_cmdbFactory.init(getAllocator(), m_device, m_queueFamilyIndices));
- for(PerFrame& f : m_perFrame)
- {
- resetFrame(f);
- }
- glslang::InitializeProcess();
- m_fenceFactory.init(getAllocator(), m_device);
- m_semaphoreFactory.init(getAllocator(), m_device);
- m_samplerFactory.init(this);
- m_barrierFactory.init(getAllocator(), m_device);
- m_occlusionQueryFactory.init(getAllocator(), m_device, VK_QUERY_TYPE_OCCLUSION);
- m_timestampQueryFactory.init(getAllocator(), m_device, VK_QUERY_TYPE_TIMESTAMP);
- // Set m_r8g8b8ImagesSupported
- {
- VkImageFormatProperties props = {};
- const VkResult res = vkGetPhysicalDeviceImageFormatProperties(
- m_physicalDevice, VK_FORMAT_R8G8B8_UNORM, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
- VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 0, &props);
- if(res == VK_ERROR_FORMAT_NOT_SUPPORTED)
- {
- ANKI_VK_LOGI("R8G8B8 Images are not supported. Will workaround this");
- m_r8g8b8ImagesSupported = false;
- }
- else
- {
- ANKI_ASSERT(res == VK_SUCCESS);
- ANKI_VK_LOGI("R8G8B8 Images are supported");
- m_r8g8b8ImagesSupported = true;
- }
- }
- // Set m_s8ImagesSupported
- {
- VkImageFormatProperties props = {};
- const VkResult res = vkGetPhysicalDeviceImageFormatProperties(
- m_physicalDevice, VK_FORMAT_S8_UINT, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
- VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, 0, &props);
- if(res == VK_ERROR_FORMAT_NOT_SUPPORTED)
- {
- ANKI_VK_LOGI("S8 Images are not supported. Will workaround this");
- m_s8ImagesSupported = false;
- }
- else
- {
- ANKI_ASSERT(res == VK_SUCCESS);
- ANKI_VK_LOGI("S8 Images are supported");
- m_s8ImagesSupported = true;
- }
- }
- // Set m_d24S8ImagesSupported
- {
- VkImageFormatProperties props = {};
- VkResult res = vkGetPhysicalDeviceImageFormatProperties(
- m_physicalDevice, VK_FORMAT_D24_UNORM_S8_UINT, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
- VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, 0, &props);
- if(res == VK_ERROR_FORMAT_NOT_SUPPORTED)
- {
- ANKI_VK_LOGI("D24S8 Images are not supported. Will workaround this");
- m_d24S8ImagesSupported = false;
- }
- else
- {
- ANKI_ASSERT(res == VK_SUCCESS);
- ANKI_VK_LOGI("D24S8 Images are supported");
- m_d24S8ImagesSupported = true;
- }
- }
- m_bindlessLimits.m_bindlessTextureCount = init.m_config->getNumberU32("gr_maxBindlessTextures");
- m_bindlessLimits.m_bindlessImageCount = init.m_config->getNumberU32("gr_maxBindlessImages");
- ANKI_CHECK(m_descrFactory.init(getAllocator(), m_device, m_bindlessLimits));
- m_pplineLayoutFactory.init(getAllocator(), m_device);
- return Error::NONE;
- }
- Error GrManagerImpl::initInstance(const GrManagerInitInfo& init)
- {
- // Init VOLK
- //
- ANKI_VK_CHECK(volkInitialize());
- // Create the instance
- //
- const U8 vulkanMinor = init.m_config->getNumberU8("gr_vkminor");
- const U8 vulkanMajor = init.m_config->getNumberU8("gr_vkmajor");
- VkApplicationInfo app = {};
- app.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
- app.pApplicationName = "unamed";
- app.applicationVersion = 1;
- app.pEngineName = "AnKi 3D Engine";
- app.engineVersion = (ANKI_VERSION_MAJOR << 16) | ANKI_VERSION_MINOR;
- app.apiVersion = VK_MAKE_VERSION(vulkanMajor, vulkanMinor, 0);
- VkInstanceCreateInfo ci = {};
- ci.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
- ci.pApplicationInfo = &app;
- // Validation layers
- static Array<const char*, 1> LAYERS = {"VK_LAYER_KHRONOS_validation"};
- Array<const char*, LAYERS.getSize()> layersToEnable; // Keep it alive in the stack
- if(init.m_config->getBool("gr_validation") || init.m_config->getBool("gr_debugPrintf"))
- {
- uint32_t count;
- vkEnumerateInstanceLayerProperties(&count, nullptr);
- if(count)
- {
- DynamicArrayAuto<VkLayerProperties> layerProps(getAllocator());
- layerProps.create(count);
- vkEnumerateInstanceLayerProperties(&count, &layerProps[0]);
- U32 layersToEnableCount = 0;
- for(const char* c : LAYERS)
- {
- for(U32 i = 0; i < count; ++i)
- {
- if(CString(c) == layerProps[i].layerName)
- {
- layersToEnable[layersToEnableCount++] = c;
- break;
- }
- }
- }
- if(layersToEnableCount)
- {
- ANKI_VK_LOGI("Will enable the following layers:");
- for(U32 i = 0; i < layersToEnableCount; ++i)
- {
- ANKI_VK_LOGI("\t%s", layersToEnable[i]);
- }
- ci.enabledLayerCount = layersToEnableCount;
- ci.ppEnabledLayerNames = &layersToEnable[0];
- }
- }
- }
- // Validation features
- DynamicArrayAuto<VkValidationFeatureEnableEXT> enabledValidationFeatures(getAllocator());
- DynamicArrayAuto<VkValidationFeatureDisableEXT> disabledValidationFeatures(getAllocator());
- if(init.m_config->getBool("gr_debugPrintf"))
- {
- enabledValidationFeatures.emplaceBack(VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT);
- }
- if(!init.m_config->getBool("gr_validation"))
- {
- disabledValidationFeatures.emplaceBack(VK_VALIDATION_FEATURE_DISABLE_ALL_EXT);
- }
- VkValidationFeaturesEXT validationFeatures = {};
- if(enabledValidationFeatures.getSize() || disabledValidationFeatures.getSize())
- {
- validationFeatures.sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT;
- validationFeatures.disabledValidationFeatureCount = disabledValidationFeatures.getSize();
- validationFeatures.enabledValidationFeatureCount = enabledValidationFeatures.getSize();
- validationFeatures.pDisabledValidationFeatures = disabledValidationFeatures.getBegin();
- validationFeatures.pEnabledValidationFeatures = enabledValidationFeatures.getBegin();
- validationFeatures.pNext = ci.pNext;
- ci.pNext = &validationFeatures;
- }
- // Extensions
- DynamicArrayAuto<const char*> instExtensions(getAllocator());
- DynamicArrayAuto<VkExtensionProperties> instExtensionInf(getAllocator());
- U32 extCount = 0;
- vkEnumerateInstanceExtensionProperties(nullptr, &extCount, nullptr);
- if(extCount)
- {
- instExtensions.create(extCount);
- instExtensionInf.create(extCount);
- vkEnumerateInstanceExtensionProperties(nullptr, &extCount, &instExtensionInf[0]);
- ANKI_VK_LOGI("Found the following instance extensions:");
- for(U32 i = 0; i < extCount; ++i)
- {
- ANKI_VK_LOGI("\t%s", instExtensionInf[i].extensionName);
- }
- U32 instExtensionCount = 0;
- for(U32 i = 0; i < extCount; ++i)
- {
- #if ANKI_OS_LINUX
- if(CString(instExtensionInf[i].extensionName) == VK_KHR_XCB_SURFACE_EXTENSION_NAME)
- {
- m_extensions |= VulkanExtensions::KHR_XCB_SURFACE;
- instExtensions[instExtensionCount++] = VK_KHR_XCB_SURFACE_EXTENSION_NAME;
- }
- else if(CString(instExtensionInf[i].extensionName) == VK_KHR_XLIB_SURFACE_EXTENSION_NAME)
- {
- m_extensions |= VulkanExtensions::KHR_XLIB_SURFACE;
- instExtensions[instExtensionCount++] = VK_KHR_XLIB_SURFACE_EXTENSION_NAME;
- }
- #elif ANKI_OS_WINDOWS
- if(CString(instExtensionInf[i].extensionName) == VK_KHR_WIN32_SURFACE_EXTENSION_NAME)
- {
- m_extensions |= VulkanExtensions::KHR_WIN32_SURFACE;
- instExtensions[instExtensionCount++] = VK_KHR_WIN32_SURFACE_EXTENSION_NAME;
- }
- #elif ANKI_OS_ANDROID
- if(CString(instExtensionInf[i].extensionName) == VK_KHR_ANDROID_SURFACE_EXTENSION_NAME)
- {
- m_extensions |= VulkanExtensions::KHR_ANDROID_SURFACE;
- instExtensions[instExtensionCount++] = VK_KHR_ANDROID_SURFACE_EXTENSION_NAME;
- }
- #else
- # error Not implemented
- #endif
- else if(CString(instExtensionInf[i].extensionName) == VK_KHR_SURFACE_EXTENSION_NAME)
- {
- m_extensions |= VulkanExtensions::KHR_SURFACE;
- instExtensions[instExtensionCount++] = VK_KHR_SURFACE_EXTENSION_NAME;
- }
- else if(CString(instExtensionInf[i].extensionName) == VK_EXT_DEBUG_REPORT_EXTENSION_NAME
- && (init.m_config->getBool("gr_validation") || init.m_config->getBool("gr_debugPrintf")))
- {
- m_extensions |= VulkanExtensions::EXT_DEBUG_REPORT;
- instExtensions[instExtensionCount++] = VK_EXT_DEBUG_REPORT_EXTENSION_NAME;
- }
- }
- if(instExtensionCount)
- {
- ANKI_VK_LOGI("Will enable the following instance extensions:");
- for(U32 i = 0; i < instExtensionCount; ++i)
- {
- ANKI_VK_LOGI("\t%s", instExtensions[i]);
- }
- ci.enabledExtensionCount = instExtensionCount;
- ci.ppEnabledExtensionNames = &instExtensions[0];
- }
- }
- #if ANKI_GR_MANAGER_DEBUG_MEMMORY
- m_debugAllocCbs = {};
- m_debugAllocCbs.pUserData = this;
- m_debugAllocCbs.pfnAllocation = allocateCallback;
- m_debugAllocCbs.pfnReallocation = reallocateCallback;
- m_debugAllocCbs.pfnFree = freeCallback;
- VkAllocationCallbacks* pallocCbs = &m_debugAllocCbs;
- #else
- VkAllocationCallbacks* pallocCbs = nullptr;
- #endif
- ANKI_VK_CHECK(vkCreateInstance(&ci, pallocCbs, &m_instance));
- // Get symbolx
- //
- volkLoadInstance(m_instance);
- // Set debug callbacks
- //
- if(!!(m_extensions & VulkanExtensions::EXT_DEBUG_REPORT))
- {
- VkDebugReportCallbackCreateInfoEXT ci = {};
- ci.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
- ci.pfnCallback = debugReportCallbackEXT;
- ci.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT
- | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
- if(init.m_config->getBool("gr_debugPrintf"))
- {
- ci.flags |= VK_DEBUG_REPORT_INFORMATION_BIT_EXT;
- }
- ci.pUserData = this;
- vkCreateDebugReportCallbackEXT(m_instance, &ci, nullptr, &m_debugCallback);
- }
- // Create the physical device
- //
- uint32_t count = 0;
- ANKI_VK_CHECK(vkEnumeratePhysicalDevices(m_instance, &count, nullptr));
- ANKI_VK_LOGI("Number of physical devices: %u", count);
- if(count < 1)
- {
- ANKI_VK_LOGE("Wrong number of physical devices");
- return Error::FUNCTION_FAILED;
- }
- count = 1;
- ANKI_VK_CHECK(vkEnumeratePhysicalDevices(m_instance, &count, &m_physicalDevice));
- m_rtPipelineProps.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR;
- m_accelerationStructureProps.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_PROPERTIES_KHR;
- m_devProps.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
- m_devProps.pNext = &m_rtPipelineProps;
- m_rtPipelineProps.pNext = &m_accelerationStructureProps;
- vkGetPhysicalDeviceProperties2(m_physicalDevice, &m_devProps);
- // Find vendor
- switch(m_devProps.properties.vendorID)
- {
- case 0x13B5:
- m_capabilities.m_gpuVendor = GpuVendor::ARM;
- break;
- case 0x10DE:
- m_capabilities.m_gpuVendor = GpuVendor::NVIDIA;
- break;
- case 0x1002:
- case 0x1022:
- m_capabilities.m_gpuVendor = GpuVendor::AMD;
- break;
- case 0x8086:
- m_capabilities.m_gpuVendor = GpuVendor::INTEL;
- break;
- default:
- m_capabilities.m_gpuVendor = GpuVendor::UNKNOWN;
- }
- ANKI_VK_LOGI("GPU is %s. Vendor identified as %s", m_devProps.properties.deviceName,
- &GPU_VENDOR_STR[m_capabilities.m_gpuVendor][0]);
- // Set limits
- m_capabilities.m_uniformBufferBindOffsetAlignment =
- max<U32>(ANKI_SAFE_ALIGNMENT, U32(m_devProps.properties.limits.minUniformBufferOffsetAlignment));
- m_capabilities.m_uniformBufferMaxRange = m_devProps.properties.limits.maxUniformBufferRange;
- m_capabilities.m_storageBufferBindOffsetAlignment =
- max<U32>(ANKI_SAFE_ALIGNMENT, U32(m_devProps.properties.limits.minStorageBufferOffsetAlignment));
- m_capabilities.m_storageBufferMaxRange = m_devProps.properties.limits.maxStorageBufferRange;
- m_capabilities.m_textureBufferBindOffsetAlignment =
- max<U32>(ANKI_SAFE_ALIGNMENT, U32(m_devProps.properties.limits.minTexelBufferOffsetAlignment));
- m_capabilities.m_textureBufferMaxRange = MAX_U32;
- m_capabilities.m_majorApiVersion = vulkanMajor;
- m_capabilities.m_minorApiVersion = vulkanMinor;
- m_capabilities.m_shaderGroupHandleSize = m_rtPipelineProps.shaderGroupHandleSize;
- m_capabilities.m_sbtRecordAlignment = m_rtPipelineProps.shaderGroupBaseAlignment;
- return Error::NONE;
- }
- Error GrManagerImpl::initDevice(const GrManagerInitInfo& init)
- {
- uint32_t count = 0;
- vkGetPhysicalDeviceQueueFamilyProperties(m_physicalDevice, &count, nullptr);
- ANKI_VK_LOGI("Number of queue families: %u", count);
- DynamicArrayAuto<VkQueueFamilyProperties> queueInfos(getAllocator());
- queueInfos.create(count);
- vkGetPhysicalDeviceQueueFamilyProperties(m_physicalDevice, &count, &queueInfos[0]);
- const VkQueueFlags GENERAL_QUEUE_FLAGS = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT;
- for(U32 i = 0; i < count; ++i)
- {
- VkBool32 supportsPresent = false;
- ANKI_VK_CHECK(vkGetPhysicalDeviceSurfaceSupportKHR(m_physicalDevice, i, m_surface, &supportsPresent));
- if(supportsPresent)
- {
- if((queueInfos[i].queueFlags & GENERAL_QUEUE_FLAGS) == GENERAL_QUEUE_FLAGS)
- {
- m_queueFamilyIndices[VulkanQueueType::GENERAL] = i;
- }
- else if((queueInfos[i].queueFlags & VK_QUEUE_COMPUTE_BIT)
- && !(queueInfos[i].queueFlags & VK_QUEUE_GRAPHICS_BIT))
- {
- // This must be the async compute
- m_queueFamilyIndices[VulkanQueueType::COMPUTE] = i;
- }
- }
- }
- if(m_queueFamilyIndices[VulkanQueueType::GENERAL] == MAX_U32)
- {
- ANKI_VK_LOGE("Couldn't find a queue family with graphics+compute+transfer+present. "
- "Something is wrong");
- return Error::FUNCTION_FAILED;
- }
- if(!init.m_config->getBool("gr_asyncCompute"))
- {
- m_queueFamilyIndices[VulkanQueueType::COMPUTE] = MAX_U32;
- }
- if(m_queueFamilyIndices[VulkanQueueType::COMPUTE] == MAX_U32)
- {
- ANKI_VK_LOGW("Couldn't find an async compute queue. Will try to use the general queue instead");
- }
- else
- {
- ANKI_VK_LOGI("Async compute is enabled");
- }
- const F32 priority = 1.0f;
- Array<VkDeviceQueueCreateInfo, U32(VulkanQueueType::COUNT)> q = {};
- VkDeviceCreateInfo ci = {};
- ci.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
- ci.pQueueCreateInfos = &q[0];
- for(VulkanQueueType qtype : EnumIterable<VulkanQueueType>())
- {
- if(m_queueFamilyIndices[qtype] != MAX_U32)
- {
- q[qtype].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
- q[qtype].queueFamilyIndex = m_queueFamilyIndices[qtype];
- q[qtype].queueCount = 1;
- q[qtype].pQueuePriorities = &priority;
- ++ci.queueCreateInfoCount;
- }
- }
- // Extensions
- U32 extCount = 0;
- vkEnumerateDeviceExtensionProperties(m_physicalDevice, nullptr, &extCount, nullptr);
- DynamicArrayAuto<VkExtensionProperties> extensionInfos(getAllocator()); // Keep it alive in the stack
- DynamicArrayAuto<const char*> extensionsToEnable(getAllocator());
- if(extCount)
- {
- extensionInfos.create(extCount);
- extensionsToEnable.create(extCount);
- U32 extensionsToEnableCount = 0;
- vkEnumerateDeviceExtensionProperties(m_physicalDevice, nullptr, &extCount, &extensionInfos[0]);
- ANKI_VK_LOGI("Found the following device extensions:");
- for(U32 i = 0; i < extCount; ++i)
- {
- ANKI_VK_LOGI("\t%s", extensionInfos[i].extensionName);
- }
- while(extCount-- != 0)
- {
- const CString extensionName(&extensionInfos[extCount].extensionName[0]);
- if(extensionName == VK_KHR_SWAPCHAIN_EXTENSION_NAME)
- {
- m_extensions |= VulkanExtensions::KHR_SWAPCHAIN;
- extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
- }
- else if(extensionName == VK_EXT_DEBUG_MARKER_EXTENSION_NAME && init.m_config->getBool("gr_debugMarkers"))
- {
- m_extensions |= VulkanExtensions::EXT_DEBUG_MARKER;
- extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
- }
- else if(extensionName == VK_AMD_SHADER_INFO_EXTENSION_NAME && init.m_config->getBool("core_displayStats"))
- {
- m_extensions |= VulkanExtensions::AMD_SHADER_INFO;
- extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
- }
- else if(extensionName == VK_AMD_RASTERIZATION_ORDER_EXTENSION_NAME)
- {
- m_extensions |= VulkanExtensions::AMD_RASTERIZATION_ORDER;
- extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
- }
- else if(extensionName == VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME
- && init.m_config->getBool("gr_rayTracing"))
- {
- m_extensions |= VulkanExtensions::KHR_RAY_TRACING;
- extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
- m_capabilities.m_rayTracingEnabled = true;
- }
- else if(extensionName == VK_KHR_RAY_QUERY_EXTENSION_NAME && init.m_config->getBool("gr_rayTracing"))
- {
- extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
- }
- else if(extensionName == VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME
- && init.m_config->getBool("gr_rayTracing"))
- {
- extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
- }
- else if(extensionName == VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME
- && init.m_config->getBool("gr_rayTracing"))
- {
- extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
- }
- else if(extensionName == VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME && init.m_config->getBool("gr_rayTracing"))
- {
- extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
- }
- else if(extensionName == VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME
- && init.m_config->getBool("core_displayStats"))
- {
- m_extensions |= VulkanExtensions::KHR_PIPELINE_EXECUTABLE_PROPERTIES;
- extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
- }
- else if(extensionName == VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME
- && init.m_config->getBool("gr_debugPrintf"))
- {
- extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
- }
- else if(extensionName == VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME)
- {
- m_extensions |= VulkanExtensions::EXT_DESCRIPTOR_INDEXING;
- extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
- }
- else if(extensionName == VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME)
- {
- m_extensions |= VulkanExtensions::KHR_BUFFER_DEVICE_ADDRESS;
- extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
- }
- else if(extensionName == VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME)
- {
- m_extensions |= VulkanExtensions::EXT_SCALAR_BLOCK_LAYOUT;
- extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
- }
- else if(extensionName == VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME)
- {
- m_extensions |= VulkanExtensions::KHR_TIMELINE_SEMAPHORE;
- extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
- }
- else if(extensionName == VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME)
- {
- m_extensions |= VulkanExtensions::KHR_SHADER_FLOAT16_INT8;
- extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
- }
- else if(extensionName == VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME
- && init.m_config->getBool("gr_64bitAtomics"))
- {
- m_extensions |= VulkanExtensions::KHR_SHADER_ATOMIC_INT64;
- extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
- }
- else if(extensionName == VK_KHR_SPIRV_1_4_EXTENSION_NAME)
- {
- m_extensions |= VulkanExtensions::KHR_SPIRV_1_4;
- extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
- }
- else if(extensionName == VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME)
- {
- m_extensions |= VulkanExtensions::KHR_SHADER_FLOAT_CONTROLS;
- extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
- }
- else if(extensionName == VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME
- && init.m_config->getBool("gr_samplerFilterMinMax"))
- {
- m_extensions |= VulkanExtensions::EXT_SAMPLER_FILTER_MIN_MAX;
- extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
- }
- }
- ANKI_VK_LOGI("Will enable the following device extensions:");
- for(U32 i = 0; i < extensionsToEnableCount; ++i)
- {
- ANKI_VK_LOGI("\t%s", extensionsToEnable[i]);
- }
- ci.enabledExtensionCount = extensionsToEnableCount;
- ci.ppEnabledExtensionNames = &extensionsToEnable[0];
- }
- // Enable/disable generic features
- {
- VkPhysicalDeviceFeatures2 devFeatures = {};
- devFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
- vkGetPhysicalDeviceFeatures2(m_physicalDevice, &devFeatures);
- m_devFeatures = devFeatures.features;
- m_devFeatures.robustBufferAccess =
- (init.m_config->getBool("gr_validation") && m_devFeatures.robustBufferAccess) ? true : false;
- ANKI_VK_LOGI("Robust buffer access is %s", (m_devFeatures.robustBufferAccess) ? "enabled" : "disabled");
- ci.pEnabledFeatures = &m_devFeatures;
- }
- if(!!(m_extensions & VulkanExtensions::EXT_SAMPLER_FILTER_MIN_MAX))
- {
- m_capabilities.m_samplingFilterMinMax = true;
- }
- else
- {
- m_capabilities.m_samplingFilterMinMax = false;
- ANKI_VK_LOGI(VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME " is not supported or disabled");
- }
- // Descriptor indexing
- if(!(m_extensions & VulkanExtensions::EXT_DESCRIPTOR_INDEXING))
- {
- ANKI_VK_LOGE(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME " is not supported");
- return Error::FUNCTION_FAILED;
- }
- else
- {
- m_descriptorIndexingFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT;
- VkPhysicalDeviceFeatures2 features = {};
- features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
- features.pNext = &m_descriptorIndexingFeatures;
- vkGetPhysicalDeviceFeatures2(m_physicalDevice, &features);
- if(!m_descriptorIndexingFeatures.shaderSampledImageArrayNonUniformIndexing
- || !m_descriptorIndexingFeatures.shaderStorageImageArrayNonUniformIndexing)
- {
- ANKI_VK_LOGE("Non uniform indexing is not supported by the device");
- return Error::FUNCTION_FAILED;
- }
- if(!m_descriptorIndexingFeatures.descriptorBindingSampledImageUpdateAfterBind
- || !m_descriptorIndexingFeatures.descriptorBindingStorageImageUpdateAfterBind)
- {
- ANKI_VK_LOGE("Update descriptors after bind is not supported by the device");
- return Error::FUNCTION_FAILED;
- }
- if(!m_descriptorIndexingFeatures.descriptorBindingUpdateUnusedWhilePending)
- {
- ANKI_VK_LOGE("Update descriptors while cmd buffer is pending is not supported by the device");
- return Error::FUNCTION_FAILED;
- }
- m_descriptorIndexingFeatures.pNext = const_cast<void*>(ci.pNext);
- ci.pNext = &m_descriptorIndexingFeatures;
- }
- // Buffer address
- if(!(m_extensions & VulkanExtensions::KHR_BUFFER_DEVICE_ADDRESS))
- {
- ANKI_VK_LOGW(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME " is not supported");
- }
- else
- {
- m_deviceBufferFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_KHR;
- VkPhysicalDeviceFeatures2 features = {};
- features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
- features.pNext = &m_deviceBufferFeatures;
- vkGetPhysicalDeviceFeatures2(m_physicalDevice, &features);
- m_deviceBufferFeatures.bufferDeviceAddressCaptureReplay =
- m_deviceBufferFeatures.bufferDeviceAddressCaptureReplay && init.m_config->getBool("gr_debugMarkers");
- m_deviceBufferFeatures.bufferDeviceAddressMultiDevice = false;
- m_deviceBufferFeatures.pNext = const_cast<void*>(ci.pNext);
- ci.pNext = &m_deviceBufferFeatures;
- }
- // Scalar block layout
- if(!(m_extensions & VulkanExtensions::EXT_SCALAR_BLOCK_LAYOUT))
- {
- ANKI_VK_LOGE(VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME " is not supported");
- return Error::FUNCTION_FAILED;
- }
- else
- {
- m_scalarBlockLayout.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT;
- VkPhysicalDeviceFeatures2 features = {};
- features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
- features.pNext = &m_scalarBlockLayout;
- vkGetPhysicalDeviceFeatures2(m_physicalDevice, &features);
- if(!m_scalarBlockLayout.scalarBlockLayout)
- {
- ANKI_VK_LOGE("Scalar block layout is not supported by the device");
- return Error::FUNCTION_FAILED;
- }
- m_scalarBlockLayout.pNext = const_cast<void*>(ci.pNext);
- ci.pNext = &m_scalarBlockLayout;
- }
- // Timeline semaphore
- if(!(m_extensions & VulkanExtensions::KHR_TIMELINE_SEMAPHORE))
- {
- ANKI_VK_LOGE(VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME " is not supported");
- return Error::FUNCTION_FAILED;
- }
- else
- {
- m_timelineSemaphoreFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES_KHR;
- VkPhysicalDeviceFeatures2 features = {};
- features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
- features.pNext = &m_timelineSemaphoreFeatures;
- vkGetPhysicalDeviceFeatures2(m_physicalDevice, &features);
- if(!m_timelineSemaphoreFeatures.timelineSemaphore)
- {
- ANKI_VK_LOGE("Timeline semaphores are not supported by the device");
- return Error::FUNCTION_FAILED;
- }
- m_timelineSemaphoreFeatures.pNext = const_cast<void*>(ci.pNext);
- ci.pNext = &m_timelineSemaphoreFeatures;
- }
- // Set RT features
- if(!!(m_extensions & VulkanExtensions::KHR_RAY_TRACING))
- {
- m_rtPipelineFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR;
- m_rayQueryFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_QUERY_FEATURES_KHR;
- m_accelerationStructureFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR;
- VkPhysicalDeviceFeatures2 features = {};
- features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
- features.pNext = &m_rtPipelineFeatures;
- m_rtPipelineFeatures.pNext = &m_rayQueryFeatures;
- m_rayQueryFeatures.pNext = &m_accelerationStructureFeatures;
- vkGetPhysicalDeviceFeatures2(m_physicalDevice, &features);
- if(!m_rtPipelineFeatures.rayTracingPipeline || !m_rayQueryFeatures.rayQuery
- || !m_accelerationStructureFeatures.accelerationStructure)
- {
- ANKI_VK_LOGE("Ray tracing and ray query are both required");
- return Error::FUNCTION_FAILED;
- }
- // Only enable what's necessary
- m_rtPipelineFeatures.rayTracingPipelineShaderGroupHandleCaptureReplay = false;
- m_rtPipelineFeatures.rayTracingPipelineShaderGroupHandleCaptureReplayMixed = false;
- m_rtPipelineFeatures.rayTraversalPrimitiveCulling = false;
- m_accelerationStructureFeatures.accelerationStructureCaptureReplay = false;
- m_accelerationStructureFeatures.accelerationStructureHostCommands = false;
- m_accelerationStructureFeatures.descriptorBindingAccelerationStructureUpdateAfterBind = false;
- ANKI_ASSERT(m_accelerationStructureFeatures.pNext == nullptr);
- m_accelerationStructureFeatures.pNext = const_cast<void*>(ci.pNext);
- ci.pNext = &m_rtPipelineFeatures;
- }
- // Pipeline features
- if(!!(m_extensions & VulkanExtensions::KHR_PIPELINE_EXECUTABLE_PROPERTIES))
- {
- m_pplineExecutablePropertiesFeatures.sType =
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR;
- m_pplineExecutablePropertiesFeatures.pipelineExecutableInfo = true;
- m_pplineExecutablePropertiesFeatures.pNext = const_cast<void*>(ci.pNext);
- ci.pNext = &m_pplineExecutablePropertiesFeatures;
- }
- // F16 I8
- if(!(m_extensions & VulkanExtensions::KHR_SHADER_FLOAT16_INT8))
- {
- ANKI_VK_LOGE(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME " is not supported");
- return Error::FUNCTION_FAILED;
- }
- else
- {
- m_float16Int8Features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR;
- VkPhysicalDeviceFeatures2 features = {};
- features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
- features.pNext = &m_float16Int8Features;
- vkGetPhysicalDeviceFeatures2(m_physicalDevice, &features);
- m_float16Int8Features.pNext = const_cast<void*>(ci.pNext);
- ci.pNext = &m_float16Int8Features;
- }
- // 64bit atomics
- if(!(m_extensions & VulkanExtensions::KHR_SHADER_ATOMIC_INT64))
- {
- ANKI_VK_LOGW(VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME " is not supported or disabled");
- m_capabilities.m_64bitAtomics = false;
- }
- else
- {
- m_capabilities.m_64bitAtomics = true;
- m_atomicInt64Features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES_KHR;
- VkPhysicalDeviceFeatures2 features = {};
- features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
- features.pNext = &m_atomicInt64Features;
- vkGetPhysicalDeviceFeatures2(m_physicalDevice, &features);
- m_atomicInt64Features.pNext = const_cast<void*>(ci.pNext);
- ci.pNext = &m_atomicInt64Features;
- }
- ANKI_VK_CHECK(vkCreateDevice(m_physicalDevice, &ci, nullptr, &m_device));
- // Get debug marker
- if(!!(m_extensions & VulkanExtensions::EXT_DEBUG_MARKER))
- {
- m_pfnDebugMarkerSetObjectNameEXT = reinterpret_cast<PFN_vkDebugMarkerSetObjectNameEXT>(
- vkGetDeviceProcAddr(m_device, "vkDebugMarkerSetObjectNameEXT"));
- if(!m_pfnDebugMarkerSetObjectNameEXT)
- {
- ANKI_VK_LOGW("VK_EXT_debug_marker is present but vkDebugMarkerSetObjectNameEXT is not there");
- }
- m_pfnCmdDebugMarkerBeginEXT =
- reinterpret_cast<PFN_vkCmdDebugMarkerBeginEXT>(vkGetDeviceProcAddr(m_device, "vkCmdDebugMarkerBeginEXT"));
- if(!m_pfnCmdDebugMarkerBeginEXT)
- {
- ANKI_VK_LOGW("VK_EXT_debug_marker is present but vkCmdDebugMarkerBeginEXT is not there");
- }
- m_pfnCmdDebugMarkerEndEXT =
- reinterpret_cast<PFN_vkCmdDebugMarkerEndEXT>(vkGetDeviceProcAddr(m_device, "vkCmdDebugMarkerEndEXT"));
- if(!m_pfnCmdDebugMarkerEndEXT)
- {
- ANKI_VK_LOGW("VK_EXT_debug_marker is present but vkCmdDebugMarkerEndEXT is not there");
- }
- }
- // Get VK_AMD_shader_info entry points
- if(!!(m_extensions & VulkanExtensions::AMD_SHADER_INFO))
- {
- m_pfnGetShaderInfoAMD =
- reinterpret_cast<PFN_vkGetShaderInfoAMD>(vkGetDeviceProcAddr(m_device, "vkGetShaderInfoAMD"));
- if(!m_pfnGetShaderInfoAMD)
- {
- ANKI_VK_LOGW("VK_AMD_shader_info is present but vkGetShaderInfoAMD is not there");
- }
- }
- if(!(m_extensions & VulkanExtensions::KHR_SPIRV_1_4))
- {
- ANKI_VK_LOGE(VK_KHR_SPIRV_1_4_EXTENSION_NAME " is not supported");
- return Error::FUNCTION_FAILED;
- }
- if(!(m_extensions & VulkanExtensions::KHR_SHADER_FLOAT_CONTROLS))
- {
- ANKI_VK_LOGE(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME " is not supported");
- return Error::FUNCTION_FAILED;
- }
- return Error::NONE;
- }
- Error GrManagerImpl::initMemory(const ConfigSet& cfg)
- {
- vkGetPhysicalDeviceMemoryProperties(m_physicalDevice, &m_memoryProperties);
- // Print some info
- ANKI_VK_LOGI("Vulkan memory info:");
- for(U32 i = 0; i < m_memoryProperties.memoryHeapCount; ++i)
- {
- ANKI_VK_LOGI("\tHeap %u size %zu", i, m_memoryProperties.memoryHeaps[i].size);
- }
- for(U32 i = 0; i < m_memoryProperties.memoryTypeCount; ++i)
- {
- ANKI_VK_LOGI("\tMem type %u points to heap %u, flags %" ANKI_PRIb32, i,
- m_memoryProperties.memoryTypes[i].heapIndex,
- ANKI_FORMAT_U32(m_memoryProperties.memoryTypes[i].propertyFlags));
- }
- m_gpuMemManager.init(m_physicalDevice, m_device, getAllocator(),
- !!(m_extensions & VulkanExtensions::KHR_BUFFER_DEVICE_ADDRESS));
- return Error::NONE;
- }
- #if ANKI_GR_MANAGER_DEBUG_MEMMORY
- void* GrManagerImpl::allocateCallback(void* userData, size_t size, size_t alignment,
- VkSystemAllocationScope allocationScope)
- {
- if(ANKI_UNLIKELY(size == 0))
- {
- return nullptr;
- }
- ANKI_ASSERT(userData);
- ANKI_ASSERT(size);
- ANKI_ASSERT(isPowerOfTwo(alignment));
- ANKI_ASSERT(alignment <= MAX_ALLOC_ALIGNMENT);
- auto alloc = static_cast<GrManagerImpl*>(userData)->getAllocator();
- PtrSize newSize = size + sizeof(AllocHeader);
- AllocHeader* header = static_cast<AllocHeader*>(alloc.getMemoryPool().allocate(newSize, MAX_ALLOC_ALIGNMENT));
- header->m_sig = ALLOC_SIG;
- header->m_size = size;
- ++header;
- return static_cast<AllocHeader*>(header);
- }
- void* GrManagerImpl::reallocateCallback(void* userData, void* original, size_t size, size_t alignment,
- VkSystemAllocationScope allocationScope)
- {
- if(original && size == 0)
- {
- freeCallback(userData, original);
- return nullptr;
- }
- void* mem = allocateCallback(userData, size, alignment, allocationScope);
- if(original)
- {
- // Move the data
- AllocHeader* header = static_cast<AllocHeader*>(original);
- --header;
- ANKI_ASSERT(header->m_sig == ALLOC_SIG);
- memcpy(mem, original, header->m_size);
- }
- return mem;
- }
- void GrManagerImpl::freeCallback(void* userData, void* ptr)
- {
- if(ptr)
- {
- ANKI_ASSERT(userData);
- auto alloc = static_cast<GrManagerImpl*>(userData)->getAllocator();
- AllocHeader* header = static_cast<AllocHeader*>(ptr);
- --header;
- ANKI_ASSERT(header->m_sig == ALLOC_SIG);
- alloc.getMemoryPool().free(header);
- }
- }
- #endif
- TexturePtr GrManagerImpl::acquireNextPresentableTexture()
- {
- ANKI_TRACE_SCOPED_EVENT(VK_ACQUIRE_IMAGE);
- LockGuard<Mutex> lock(m_globalMtx);
- PerFrame& frame = m_perFrame[m_frame % MAX_FRAMES_IN_FLIGHT];
- // Create sync objects
- MicroFencePtr fence = m_fenceFactory.newInstance();
- frame.m_acquireSemaphore = m_semaphoreFactory.newInstance(fence, false);
- // Get new image
- uint32_t imageIdx;
- VkResult res = vkAcquireNextImageKHR(m_device, m_crntSwapchain->m_swapchain, UINT64_MAX,
- frame.m_acquireSemaphore->getHandle(), fence->getHandle(), &imageIdx);
- if(res == VK_ERROR_OUT_OF_DATE_KHR)
- {
- ANKI_VK_LOGW("Swapchain is out of date. Will wait for the queue and create a new one");
- for(VkQueue queue : m_queues)
- {
- if(queue)
- {
- vkQueueWaitIdle(queue);
- }
- }
- m_crntSwapchain.reset(nullptr);
- m_crntSwapchain = m_swapchainFactory.newInstance();
- // Can't fail a second time
- ANKI_VK_CHECKF(vkAcquireNextImageKHR(m_device, m_crntSwapchain->m_swapchain, UINT64_MAX,
- frame.m_acquireSemaphore->getHandle(), fence->getHandle(), &imageIdx));
- }
- else
- {
- ANKI_VK_CHECKF(res);
- }
- m_acquiredImageIdx = U8(imageIdx);
- return m_crntSwapchain->m_textures[imageIdx];
- }
- void GrManagerImpl::endFrame()
- {
- ANKI_TRACE_SCOPED_EVENT(VK_PRESENT);
- LockGuard<Mutex> lock(m_globalMtx);
- PerFrame& frame = m_perFrame[m_frame % MAX_FRAMES_IN_FLIGHT];
- // Wait for the fence of N-2 frame
- const U waitFrameIdx = (m_frame + 1) % MAX_FRAMES_IN_FLIGHT;
- PerFrame& waitFrame = m_perFrame[waitFrameIdx];
- if(waitFrame.m_presentFence)
- {
- waitFrame.m_presentFence->wait();
- }
- resetFrame(waitFrame);
- if(!frame.m_renderSemaphore)
- {
- ANKI_VK_LOGW("Nobody draw to the default framebuffer");
- }
- // Present
- VkResult res;
- VkPresentInfoKHR present = {};
- present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
- present.waitSemaphoreCount = (frame.m_renderSemaphore) ? 1 : 0;
- present.pWaitSemaphores = (frame.m_renderSemaphore) ? &frame.m_renderSemaphore->getHandle() : nullptr;
- present.swapchainCount = 1;
- present.pSwapchains = &m_crntSwapchain->m_swapchain;
- const U32 idx = m_acquiredImageIdx;
- present.pImageIndices = &idx;
- present.pResults = &res;
- const VkResult res1 = vkQueuePresentKHR(m_queues[frame.m_queueWroteToSwapchainImage], &present);
- if(res1 == VK_ERROR_OUT_OF_DATE_KHR)
- {
- ANKI_VK_LOGW("Swapchain is out of date. Will wait for the queues and create a new one");
- for(VkQueue queue : m_queues)
- {
- if(queue)
- {
- vkQueueWaitIdle(queue);
- }
- }
- vkDeviceWaitIdle(m_device);
- m_crntSwapchain.reset(nullptr);
- m_crntSwapchain = m_swapchainFactory.newInstance();
- }
- else
- {
- ANKI_VK_CHECKF(res1);
- ANKI_VK_CHECKF(res);
- }
- m_descrFactory.endFrame();
- // Finalize
- ++m_frame;
- }
- void GrManagerImpl::resetFrame(PerFrame& frame)
- {
- frame.m_presentFence.reset(nullptr);
- frame.m_acquireSemaphore.reset(nullptr);
- frame.m_renderSemaphore.reset(nullptr);
- }
- void GrManagerImpl::flushCommandBuffer(MicroCommandBufferPtr cmdb, Bool cmdbRenderedToSwapchain,
- WeakArray<MicroSemaphorePtr> userWaitSemaphores,
- MicroSemaphorePtr* userSignalSemaphore, Bool wait)
- {
- constexpr U32 maxSemaphores = 8;
- VkSubmitInfo submit = {};
- submit.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
- Array<VkSemaphore, maxSemaphores> waitSemaphores;
- submit.pWaitSemaphores = &waitSemaphores[0];
- Array<VkSemaphore, maxSemaphores> signalSemaphores;
- submit.pSignalSemaphores = &signalSemaphores[0];
- Array<VkPipelineStageFlags, maxSemaphores> waitStages;
- submit.pWaitDstStageMask = &waitStages[0];
- // First thing, create a fence
- MicroFencePtr fence = m_fenceFactory.newInstance();
- // Command buffer
- const VkCommandBuffer handle = cmdb->getHandle();
- cmdb->setFence(fence);
- submit.commandBufferCount = 1;
- submit.pCommandBuffers = &handle;
- // Handle user semaphores
- Array<U64, maxSemaphores> waitTimelineValues;
- Array<U64, maxSemaphores> signalTimelineValues;
- VkTimelineSemaphoreSubmitInfo timelineInfo = {};
- timelineInfo.sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO;
- timelineInfo.waitSemaphoreValueCount = userWaitSemaphores.getSize();
- timelineInfo.pWaitSemaphoreValues = &waitTimelineValues[0];
- timelineInfo.signalSemaphoreValueCount = (userSignalSemaphore != nullptr);
- timelineInfo.pSignalSemaphoreValues = &signalTimelineValues[0];
- submit.pNext = &timelineInfo;
- for(MicroSemaphorePtr& userWaitSemaphore : userWaitSemaphores)
- {
- ANKI_ASSERT(userWaitSemaphore.isCreated());
- ANKI_ASSERT(userWaitSemaphore->isTimeline());
- waitSemaphores[submit.waitSemaphoreCount] = userWaitSemaphore->getHandle();
- waitTimelineValues[submit.waitSemaphoreCount] = userWaitSemaphore->getSemaphoreValue();
- // Be a bit conservative
- waitStages[submit.waitSemaphoreCount] = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
- ++submit.waitSemaphoreCount;
- // Refresh the fence because the semaphore can't be recycled until the current submission is done
- userWaitSemaphore->setFence(fence);
- }
- if(userSignalSemaphore)
- {
- *userSignalSemaphore = m_semaphoreFactory.newInstance(fence, true);
- signalSemaphores[submit.signalSemaphoreCount] = (*userSignalSemaphore)->getHandle();
- signalTimelineValues[submit.signalSemaphoreCount] = (*userSignalSemaphore)->getNextSemaphoreValue();
- ++submit.signalSemaphoreCount;
- }
- // Protect the class, the queue and other stuff
- LockGuard<Mutex> lock(m_globalMtx);
- // Do some special stuff for the last command buffer
- PerFrame& frame = m_perFrame[m_frame % MAX_FRAMES_IN_FLIGHT];
- if(cmdbRenderedToSwapchain)
- {
- // Wait semaphore
- waitSemaphores[submit.waitSemaphoreCount] = frame.m_acquireSemaphore->getHandle();
- // That depends on how we use the swapchain img. Be a bit conservative
- waitStages[submit.waitSemaphoreCount] =
- VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
- ++submit.waitSemaphoreCount;
- // Refresh the fence because the semaphore can't be recycled until the current submission is done
- frame.m_acquireSemaphore->setFence(fence);
- // Create the semaphore to signal
- ANKI_ASSERT(!frame.m_renderSemaphore && "Only one begin/end render pass is allowed with the default fb");
- frame.m_renderSemaphore = m_semaphoreFactory.newInstance(fence, false);
- signalSemaphores[submit.signalSemaphoreCount++] = frame.m_renderSemaphore->getHandle();
- // Update the frame fence
- frame.m_presentFence = fence;
- // Update the swapchain's fence
- m_crntSwapchain->setFence(fence);
- frame.m_queueWroteToSwapchainImage = cmdb->getVulkanQueueType();
- }
- // Submit
- {
- ANKI_TRACE_SCOPED_EVENT(VK_QUEUE_SUBMIT);
- ANKI_VK_CHECKF(vkQueueSubmit(m_queues[cmdb->getVulkanQueueType()], 1, &submit, fence->getHandle()));
- }
- if(wait)
- {
- vkQueueWaitIdle(m_queues[cmdb->getVulkanQueueType()]);
- }
- }
- void GrManagerImpl::finish()
- {
- LockGuard<Mutex> lock(m_globalMtx);
- for(VkQueue queue : m_queues)
- {
- if(queue)
- {
- vkQueueWaitIdle(queue);
- }
- }
- }
- void GrManagerImpl::trySetVulkanHandleName(CString name, VkDebugReportObjectTypeEXT type, U64 handle) const
- {
- if(name && name.getLength())
- {
- if(m_pfnDebugMarkerSetObjectNameEXT)
- {
- VkDebugMarkerObjectNameInfoEXT inf = {};
- inf.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT;
- inf.objectType = type;
- inf.pObjectName = name.cstr();
- inf.object = handle;
- m_pfnDebugMarkerSetObjectNameEXT(m_device, &inf);
- }
- LockGuard<SpinLock> lock(m_vkHandleToNameLock);
- StringAuto newName(getAllocator());
- newName.create(name);
- m_vkHandleToName.emplace(getAllocator(), computeHash(&handle, sizeof(handle)), std::move(newName));
- }
- }
- StringAuto GrManagerImpl::tryGetVulkanHandleName(U64 handle) const
- {
- StringAuto out(getAllocator());
- LockGuard<SpinLock> lock(m_vkHandleToNameLock);
- auto it = m_vkHandleToName.find(computeHash(&handle, sizeof(handle)));
- CString objName;
- if(it != m_vkHandleToName.getEnd())
- {
- objName = it->toCString();
- }
- else
- {
- objName = "Unnamed";
- }
- out.create(objName);
- return out;
- }
- VkBool32 GrManagerImpl::debugReportCallbackEXT(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType,
- uint64_t object, size_t location, int32_t messageCode,
- const char* pLayerPrefix, const char* pMessage, void* pUserData)
- {
- // Get the object name
- GrManagerImpl* self = static_cast<GrManagerImpl*>(pUserData);
- StringAuto name = self->tryGetVulkanHandleName(object);
- if(flags & VK_DEBUG_REPORT_ERROR_BIT_EXT)
- {
- ANKI_VK_LOGE("%s (handle: %s)", pMessage, name.cstr());
- }
- else if(flags & (VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT))
- {
- ANKI_VK_LOGW("%s (handle: %s)", pMessage, name.cstr());
- }
- else
- {
- ANKI_VK_LOGI("%s (handle: %s)", pMessage, name.cstr());
- }
- return false;
- }
- void GrManagerImpl::printPipelineShaderInfo(VkPipeline ppline, CString name, ShaderTypeBit stages, U64 hash) const
- {
- if(printPipelineShaderInfoInternal(ppline, name, stages, hash))
- {
- ANKI_VK_LOGE("Ignoring previous errors");
- }
- }
- Error GrManagerImpl::printPipelineShaderInfoInternal(VkPipeline ppline, CString name, ShaderTypeBit stages,
- U64 hash) const
- {
- if(m_pfnGetShaderInfoAMD)
- {
- VkShaderStatisticsInfoAMD stats = {};
- LockGuard<SpinLock> lock(m_shaderStatsFileMtx);
- // Open the file
- if(!m_shaderStatsFile.isOpen())
- {
- ANKI_CHECK(m_shaderStatsFile.open(
- StringAuto(getAllocator()).sprintf("%s/../ppline_stats.csv", m_cacheDir.cstr()).toCString(),
- FileOpenFlag::WRITE));
- ANKI_CHECK(m_shaderStatsFile.writeText("ppline name,hash,"
- "stage 0 VGPR,stage 0 SGPR,"
- "stage 1 VGPR,stage 1 SGPR,"
- "stage 2 VGPR,stage 2 SGPR,"
- "stage 3 VGPR,stage 3 SGPR,"
- "stage 4 VGPR,stage 4 SGPR,"
- "stage 5 VGPR,stage 5 SGPR\n"));
- }
- ANKI_CHECK(m_shaderStatsFile.writeText("%s,0x%" PRIx64 ",", name.cstr(), hash));
- StringAuto str(getAllocator());
- for(ShaderType type = ShaderType::FIRST; type < ShaderType::COUNT; ++type)
- {
- ShaderTypeBit stage = stages & ShaderTypeBit(1 << type);
- if(!stage)
- {
- ANKI_CHECK(m_shaderStatsFile.writeText((type != ShaderType::LAST) ? "0,0," : "0,0\n"));
- continue;
- }
- size_t size = sizeof(stats);
- ANKI_VK_CHECK(m_pfnGetShaderInfoAMD(m_device, ppline, VkShaderStageFlagBits(convertShaderTypeBit(stage)),
- VK_SHADER_INFO_TYPE_STATISTICS_AMD, &size, &stats));
- str.append(StringAuto(getAllocator())
- .sprintf("Stage %u: VGRPS %02u, SGRPS %02u ", U32(type), stats.resourceUsage.numUsedVgprs,
- stats.resourceUsage.numUsedSgprs));
- ANKI_CHECK(m_shaderStatsFile.writeText((type != ShaderType::LAST) ? "%u,%u," : "%u,%u\n",
- stats.resourceUsage.numUsedVgprs, stats.resourceUsage.numUsedSgprs));
- }
- ANKI_VK_LOGI("Pipeline \"%s\" (0x%016" PRIx64 ") stats: %s", name.cstr(), hash, str.cstr());
- // Flush the file just in case
- ANKI_CHECK(m_shaderStatsFile.flush());
- }
- if(!!(m_extensions & VulkanExtensions::KHR_PIPELINE_EXECUTABLE_PROPERTIES))
- {
- StringListAuto log(m_alloc);
- VkPipelineInfoKHR pplineInf = {};
- pplineInf.sType = VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR;
- pplineInf.pipeline = ppline;
- U32 executableCount = 0;
- ANKI_VK_CHECK(vkGetPipelineExecutablePropertiesKHR(m_device, &pplineInf, &executableCount, nullptr));
- DynamicArrayAuto<VkPipelineExecutablePropertiesKHR> executableProps(m_alloc, executableCount);
- ANKI_VK_CHECK(
- vkGetPipelineExecutablePropertiesKHR(m_device, &pplineInf, &executableCount, &executableProps[0]));
- log.pushBackSprintf("Pipeline info \"%s\" (0x%016" PRIx64 "): ", name.cstr(), hash);
- for(U32 i = 0; i < executableCount; ++i)
- {
- const VkPipelineExecutablePropertiesKHR& p = executableProps[i];
- log.pushBackSprintf("%s: ", p.description);
- // Get stats
- VkPipelineExecutableInfoKHR exeInf = {};
- exeInf.sType = VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INFO_KHR;
- exeInf.executableIndex = i;
- exeInf.pipeline = ppline;
- U32 statCount = 0;
- vkGetPipelineExecutableStatisticsKHR(m_device, &exeInf, &statCount, nullptr);
- DynamicArrayAuto<VkPipelineExecutableStatisticKHR> stats(m_alloc, statCount);
- vkGetPipelineExecutableStatisticsKHR(m_device, &exeInf, &statCount, &stats[0]);
- for(U32 s = 0; s < statCount; ++s)
- {
- const VkPipelineExecutableStatisticKHR& ss = stats[s];
- switch(ss.format)
- {
- case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_BOOL32_KHR:
- log.pushBackSprintf("%s: %u, ", ss.name, ss.value.b32);
- break;
- case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_INT64_KHR:
- log.pushBackSprintf("%s: %" PRId64 ", ", ss.name, ss.value.i64);
- break;
- case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR:
- log.pushBackSprintf("%s: %" PRIu64 ", ", ss.name, ss.value.u64);
- break;
- case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_FLOAT64_KHR:
- log.pushBackSprintf("%s: %f, ", ss.name, ss.value.f64);
- break;
- default:
- ANKI_ASSERT(0);
- }
- }
- log.pushBackSprintf("Subgroup size: %u", p.subgroupSize);
- if(i < executableCount - 1)
- {
- log.pushBack(", ");
- }
- }
- StringAuto finalLog(m_alloc);
- log.join("", finalLog);
- ANKI_VK_LOGI("%s", finalLog.cstr());
- }
- return Error::NONE;
- }
- } // end namespace anki
|