bool VulkanContext::EnableDebugReports() { // Already enabled? if (m_debug_report_callback != VK_NULL_HANDLE) return true; // Check for presence of the functions before calling if (!vkCreateDebugReportCallbackEXT || !vkDestroyDebugReportCallbackEXT || !vkDebugReportMessageEXT) { return false; } VkDebugReportCallbackCreateInfoEXT callback_info = { VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT, nullptr, VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT | VK_DEBUG_REPORT_INFORMATION_BIT_EXT | VK_DEBUG_REPORT_DEBUG_BIT_EXT, DebugReportCallback, nullptr}; VkResult res = vkCreateDebugReportCallbackEXT(m_instance, &callback_info, nullptr, &m_debug_report_callback); if (res != VK_SUCCESS) { LOG_VULKAN_ERROR(res, "vkCreateDebugReportCallbackEXT failed: "); return false; } return true; }
void vulkan_setup_debug_callback(ReaperRoot& root, VulkanBackend& backend) { VkDebugReportCallbackCreateInfoEXT callbackCreateInfo; callbackCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT; callbackCreateInfo.pNext = nullptr; callbackCreateInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT; callbackCreateInfo.pfnCallback = &debugReportCallback; callbackCreateInfo.pUserData = &root; #if defined(REAPER_DEBUG) Assert(vkCreateDebugReportCallbackEXT(backend.instance, &callbackCreateInfo, nullptr, &backend.debugCallback) == VK_SUCCESS); #endif }
bool VkContext::SetupValidation() { // Set debug validation callback vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr( instance, "vkCreateDebugReportCallbackEXT"); vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr( instance, "vkDestroyDebugReportCallbackEXT"); vkDebugReportMessageEXT = (PFN_vkDebugReportMessageEXT)vkGetInstanceProcAddr( instance, "vkDebugReportMessageEXT"); VkDebugReportCallbackCreateInfoEXT dbgCreateInfo = {}; dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT; dbgCreateInfo.pfnCallback = (PFN_vkDebugReportCallbackEXT)MessageCallback; dbgCreateInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT; CheckVkResult(vkCreateDebugReportCallbackEXT(instance, &dbgCreateInfo, nullptr, &msgCallback)); return true; }
C9::C9() : mGpuCount(0), mPhysicalDevices(nullptr), mReferenceCount(0), mInstance(VK_NULL_HANDLE), mLayerProperties(nullptr), mLayerPropertyCount(0), mValidationPresent(false), mResult(VK_SUCCESS), mOptionDescriptions("Allowed options") { //Setup configuration & logging. mOptionDescriptions.add_options() ("LogFile", boost::program_options::value<std::string>(), "The location of the log file."); boost::program_options::store(boost::program_options::parse_config_file<char>("SchaeferGL.conf", mOptionDescriptions), mOptions); boost::program_options::notify(mOptions); if (mOptions.count("LogFile")) { boost::log::add_file_log(mOptions["LogFile"].as<std::string>()); } else { boost::log::add_file_log("SchaeferGL.log"); } //Continue instance setup. mResult = vkEnumerateInstanceLayerProperties(&mLayerPropertyCount, nullptr); if (mResult != VK_SUCCESS) { BOOST_LOG_TRIVIAL(fatal) << "C9::C9 vkEnumerateInstanceLayerProperties failed with return code of " << mResult; return; } else { BOOST_LOG_TRIVIAL(info) << "C9::C9 vkEnumerateInstanceLayerProperties found " << mLayerPropertyCount << " layers."; } mLayerProperties = new VkLayerProperties[mLayerPropertyCount]; mResult = vkEnumerateInstanceLayerProperties(&mLayerPropertyCount, mLayerProperties); if (mResult == VK_SUCCESS) { for (size_t i = 0; i < mLayerPropertyCount; i++) { if (strcmp(mLayerProperties[i].layerName,"VK_LAYER_LUNARG_standard_validation")==0) { mValidationPresent = true; } BOOST_LOG_TRIVIAL(info) << "C9::C9 vkEnumerateInstanceLayerProperties - layerName: " << mLayerProperties[i].layerName; } } mExtensionNames.push_back("VK_KHR_surface"); mExtensionNames.push_back("VK_KHR_win32_surface"); #ifdef _DEBUG mExtensionNames.push_back("VK_EXT_debug_report"); mLayerExtensionNames.push_back("VK_LAYER_LUNARG_standard_validation"); #endif // _DEBUG // initialize the VkApplicationInfo structure VkApplicationInfo app_info = {}; app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; app_info.pNext = nullptr; app_info.pApplicationName = APP_SHORT_NAME; app_info.applicationVersion = 1; app_info.pEngineName = APP_SHORT_NAME; app_info.engineVersion = 1; app_info.apiVersion = 0; // VK_API_VERSION; // initialize the VkInstanceCreateInfo structure VkInstanceCreateInfo inst_info = { VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // VkStructureType sType; NULL, // const void* pNext; 0, // VkInstanceCreateFlags flags; &app_info, // const VkApplicationInfo* pApplicationInfo; mLayerExtensionNames.size(), // uint32_t enabledLayerNameCount; mLayerExtensionNames.size()>0 ? mLayerExtensionNames.data() : nullptr,// const char* const* ppEnabledLayerNames; mExtensionNames.size(), // uint32_t enabledExtensionNameCount; mExtensionNames.size()>0 ? mExtensionNames.data() : nullptr, // const char* const* ppEnabledExtensionNames; }; //Get an instance handle. if (VK_SUCCESS == vkCreateInstance(&inst_info, NULL, &mInstance)) { #ifdef _DEBUG /* Load VK_EXT_debug_report entry points in debug builds */ vkCreateDebugReportCallbackEXT = reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>(vkGetInstanceProcAddr(mInstance, "vkCreateDebugReportCallbackEXT")); vkDebugReportMessageEXT = reinterpret_cast<PFN_vkDebugReportMessageEXT>(vkGetInstanceProcAddr(mInstance, "vkDebugReportMessageEXT")); vkDestroyDebugReportCallbackEXT = reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>(vkGetInstanceProcAddr(mInstance, "vkDestroyDebugReportCallbackEXT")); VkDebugReportCallbackCreateInfoEXT callbackCreateInfo = {}; callbackCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT; callbackCreateInfo.pNext = nullptr; callbackCreateInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT; callbackCreateInfo.pfnCallback = &DebugReportCallback; callbackCreateInfo.pUserData = nullptr; /* Register the callback */ mResult = vkCreateDebugReportCallbackEXT(mInstance, &callbackCreateInfo, nullptr, &mCallback); if (mResult != VK_SUCCESS) { BOOST_LOG_TRIVIAL(fatal) << "C9::C9 vkCreateDebugReportCallbackEXT failed with return code of " << mResult; return; } else { BOOST_LOG_TRIVIAL(info) << "C9::C9 vkCreateDebugReportCallbackEXT succeeded."; } #endif //Fetch an array of available physical devices. mResult = vkEnumeratePhysicalDevices(mInstance, &mGpuCount, NULL); if (mResult != VK_SUCCESS) { BOOST_LOG_TRIVIAL(fatal) << "C9::C9 vkEnumeratePhysicalDevices failed with return code of " << mResult; return; } else { BOOST_LOG_TRIVIAL(info) << "There were " << mGpuCount << " physical devices found."; } if (mGpuCount > 0) { mPhysicalDevices = new VkPhysicalDevice[mGpuCount](); mResult = vkEnumeratePhysicalDevices(mInstance, &mGpuCount, mPhysicalDevices); if (mResult != VK_SUCCESS) { BOOST_LOG_TRIVIAL(fatal) << "C9::C9 vkEnumeratePhysicalDevices failed with return code of " << mResult; return; } } else { BOOST_LOG_TRIVIAL(fatal) << "No phyuscial devices were found."; } } else { BOOST_LOG_TRIVIAL(fatal) << "C9::C9 vkCreateInstance failed."; return; } }
Context::Context() { if(!loadVulkanLibrary()) { CV_Error(Error::StsError, "loadVulkanLibrary failed"); return; } else if (!loadVulkanEntry()) { CV_Error(Error::StsError, "loadVulkanEntry failed"); return; } else if (!loadVulkanGlobalFunctions()) { CV_Error(Error::StsError, "loadVulkanGlobalFunctions failed"); return; } // create VkInstance, VkPhysicalDevice std::vector<const char *> enabledExtensions; if (enableValidationLayers) { uint32_t layerCount; vkEnumerateInstanceLayerProperties(&layerCount, NULL); std::vector<VkLayerProperties> layerProperties(layerCount); vkEnumerateInstanceLayerProperties(&layerCount, layerProperties.data()); bool foundLayer = false; for (VkLayerProperties prop : layerProperties) { if (strcmp("VK_LAYER_LUNARG_standard_validation", prop.layerName) == 0) { foundLayer = true; break; } } if (!foundLayer) { throw std::runtime_error("Layer VK_LAYER_LUNARG_standard_validation not supported\n"); } kEnabledLayers.push_back("VK_LAYER_LUNARG_standard_validation"); uint32_t extensionCount; vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, NULL); std::vector<VkExtensionProperties> extensionProperties(extensionCount); vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensionProperties.data()); bool foundExtension = false; for (VkExtensionProperties prop : extensionProperties) { if (strcmp(VK_EXT_DEBUG_REPORT_EXTENSION_NAME, prop.extensionName) == 0) { foundExtension = true; break; } } if (!foundExtension) { throw std::runtime_error("Extension VK_EXT_DEBUG_REPORT_EXTENSION_NAME not supported\n"); } enabledExtensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME); } VkApplicationInfo applicationInfo = {}; applicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; applicationInfo.pApplicationName = "VkCom Library"; applicationInfo.applicationVersion = 0; applicationInfo.pEngineName = "vkcom"; applicationInfo.engineVersion = 0; applicationInfo.apiVersion = VK_API_VERSION_1_0;; VkInstanceCreateInfo createInfo = {}; createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; createInfo.flags = 0; createInfo.pApplicationInfo = &applicationInfo; // Give our desired layers and extensions to vulkan. createInfo.enabledLayerCount = kEnabledLayers.size(); createInfo.ppEnabledLayerNames = kEnabledLayers.data(); createInfo.enabledExtensionCount = enabledExtensions.size(); createInfo.ppEnabledExtensionNames = enabledExtensions.data(); VK_CHECK_RESULT(vkCreateInstance(&createInfo, NULL, &kInstance)); if (!loadVulkanFunctions(kInstance)) { CV_Error(Error::StsError, "loadVulkanFunctions failed"); return; } if (enableValidationLayers && vkCreateDebugReportCallbackEXT) { VkDebugReportCallbackCreateInfoEXT createInfo = {}; createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT; createInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT; createInfo.pfnCallback = &debugReportCallbackFn; // Create and register callback. VK_CHECK_RESULT(vkCreateDebugReportCallbackEXT(kInstance, &createInfo, NULL, &kDebugReportCallback)); } // find physical device uint32_t deviceCount; vkEnumeratePhysicalDevices(kInstance, &deviceCount, NULL); if (deviceCount == 0) { throw std::runtime_error("could not find a device with vulkan support"); } std::vector<VkPhysicalDevice> devices(deviceCount); vkEnumeratePhysicalDevices(kInstance, &deviceCount, devices.data()); for (VkPhysicalDevice device : devices) { if (true) { kPhysicalDevice = device; break; } } kQueueFamilyIndex = getComputeQueueFamilyIndex(); // create device, queue, command pool VkDeviceQueueCreateInfo queueCreateInfo = {}; queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; queueCreateInfo.queueFamilyIndex = kQueueFamilyIndex; queueCreateInfo.queueCount = 1; // create one queue in this family. We don't need more. float queuePriorities = 1.0; // we only have one queue, so this is not that imporant. queueCreateInfo.pQueuePriorities = &queuePriorities; VkDeviceCreateInfo deviceCreateInfo = {}; // Specify any desired device features here. We do not need any for this application, though. VkPhysicalDeviceFeatures deviceFeatures = {}; deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; deviceCreateInfo.enabledLayerCount = kEnabledLayers.size(); deviceCreateInfo.ppEnabledLayerNames = kEnabledLayers.data(); deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo; deviceCreateInfo.queueCreateInfoCount = 1; deviceCreateInfo.pEnabledFeatures = &deviceFeatures; VK_CHECK_RESULT(vkCreateDevice(kPhysicalDevice, &deviceCreateInfo, NULL, &kDevice)); // Get a handle to the only member of the queue family. vkGetDeviceQueue(kDevice, kQueueFamilyIndex, 0, &kQueue); // create command pool VkCommandPoolCreateInfo commandPoolCreateInfo = {}; commandPoolCreateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; commandPoolCreateInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; // the queue family of this command pool. All command buffers allocated from this command pool, // must be submitted to queues of this family ONLY. commandPoolCreateInfo.queueFamilyIndex = kQueueFamilyIndex; VK_CHECK_RESULT(vkCreateCommandPool(kDevice, &commandPoolCreateInfo, NULL, &kCmdPool)); }