bool VulkanWrapper::VWGraphicInstance::CheckValidationLayerSupport() { uint32_t layerCount; vkEnumerateInstanceLayerProperties(&layerCount, nullptr); std::vector<VkLayerProperties> availableLayers(layerCount); vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data()); for (const char* layerName : validationLayers) { bool layerFound = false; for (const auto& layerProperties : availableLayers) { if (strcmp(layerName, layerProperties.layerName) == 0) { layerFound = true; break; } } if (!layerFound) { return false; } } return true; }
Instance::Instance() { // Get layers uint32_t layerCount; vkEnumerateInstanceLayerProperties(&layerCount, nullptr); layersProperties.resize(layerCount); vkEnumerateInstanceLayerProperties(&layerCount, layersProperties.data()); // Get extensions uint32_t extensionCount; vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr); extensionProperties.resize(extensionCount); vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensionProperties.data()); #if defined(_WIN32) enabledExtensions = { "VK_KHR_surface", "VK_KHR_win32_surface", }; #elif defined(__linux__) enabledExtensions = { "VK_KHR_surface", "VK_KHR_xcb_surface", }; #endif applicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; applicationInfo.pApplicationName = "Application"; applicationInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0); applicationInfo.apiVersion = VK_API_VERSION_1_0; createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; createInfo.pApplicationInfo = &applicationInfo; }
bool VulkanContext::CheckValidationLayerAvailablility() { u32 extension_count = 0; VkResult res = vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, nullptr); if (res != VK_SUCCESS) { LOG_VULKAN_ERROR(res, "vkEnumerateInstanceExtensionProperties failed: "); return false; } std::vector<VkExtensionProperties> extension_list(extension_count); res = vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extension_list.data()); ASSERT(res == VK_SUCCESS); u32 layer_count = 0; res = vkEnumerateInstanceLayerProperties(&layer_count, nullptr); if (res != VK_SUCCESS) { LOG_VULKAN_ERROR(res, "vkEnumerateInstanceExtensionProperties failed: "); return false; } std::vector<VkLayerProperties> layer_list(layer_count); res = vkEnumerateInstanceLayerProperties(&layer_count, layer_list.data()); ASSERT(res == VK_SUCCESS); // Check for both VK_EXT_debug_report and VK_LAYER_LUNARG_standard_validation return (std::find_if(extension_list.begin(), extension_list.end(), [](const auto& it) { return strcmp(it.extensionName, VK_EXT_DEBUG_REPORT_EXTENSION_NAME) == 0; }) != extension_list.end() && std::find_if(layer_list.begin(), layer_list.end(), [](const auto& it) { return strcmp(it.layerName, "VK_LAYER_LUNARG_standard_validation") == 0; }) != layer_list.end()); }
void RHIRoot::EnumLayers() { uint32 layerCount = 0; K3D_VK_VERIFY(vkEnumerateInstanceLayerProperties(&layerCount, nullptr)); if(layerCount>0) { s_LayerProps.resize(layerCount); K3D_VK_VERIFY(vkEnumerateInstanceLayerProperties(&layerCount, s_LayerProps.data())); } VKLOG(Info, "layerCount = %d. ", layerCount); }
void checkGlobalLayerPresent(const char* layerName) { uint32_t layerCount = 0; std::vector<VkLayerProperties> layers; vkEnumerateInstanceLayerProperties(&layerCount, NULL); layers.resize(layerCount); vkEnumerateInstanceLayerProperties(&layerCount, layers.data()); for (auto& layer : layers) { if (!strcmp(layerName, layer.layerName)) { return; } } cerr << "ERROR: cannot find layer: " << layerName << endl; exit(1); }
bool hasLayer(const char * name) { uint32_t count = 0; std::vector<VkLayerProperties> layerprops; vkEnumerateInstanceLayerProperties(&count, nullptr); if (count != 0) { layerprops = std::vector<VkLayerProperties>(count); vkEnumerateInstanceLayerProperties(&count, layerprops.data()); for (auto prop : layerprops) { if (strcmp(name, prop.layerName) == 0) { std::cout << "found layer: " << prop.layerName << std::endl; return true; } } } return false; }
TEST_F(EnumerateInstanceLayerProperties, OnePass) { // Count required for this test. if(std::find(arguments.begin(), arguments.end(), "count") == arguments.end()) { return; } uint32_t count = std::stoul(arguments[2]); std::unique_ptr<VkLayerProperties[]> properties(new VkLayerProperties[count]); VkResult result = vkEnumerateInstanceLayerProperties(&count, properties.get()); ASSERT_EQ(result, VK_SUCCESS); if(std::find(arguments.begin(), arguments.end(), "properties") != arguments.end()) { for(uint32_t p = 0; p < count; ++p) { std::cout << "properties[" << p << "] =" << ' ' << properties[p].layerName << ' ' << properties[p].specVersion << ' ' << properties[p].implementationVersion << ' ' << properties[p].description << '\n'; } } }
TEST_F(EnumerateInstanceLayerProperties, PropertyCountLessThanAvailable) { uint32_t count = 0u; VkResult result = vkEnumerateInstanceLayerProperties(&count, nullptr); ASSERT_EQ(result, VK_SUCCESS); // We need atleast two for the test to be relevant. if(count < 2u) { return; } std::unique_ptr<VkLayerProperties[]> properties(new VkLayerProperties[count]); count = 1; result = vkEnumerateInstanceLayerProperties(&count, properties.get()); ASSERT_EQ(result, VK_INCOMPLETE); }
TEST_F(EnumerateInstanceLayerProperties, Count) { uint32_t count = 0u; VkResult result = vkEnumerateInstanceLayerProperties(&count, nullptr); ASSERT_EQ(result, VK_SUCCESS); if(std::find(arguments.begin(), arguments.end(), "count") != arguments.end()) { std::cout << "count=" << count << '\n'; } }
void vulkan_instance_check_layers(const std::vector<const char*>& layers) { uint32_t layers_count = 0; Assert(vkEnumerateInstanceLayerProperties(&layers_count, nullptr) == VK_SUCCESS); Assert(layers_count > 0); std::vector<VkLayerProperties> available_layers(layers_count); Assert(vkEnumerateInstanceLayerProperties(&layers_count, &available_layers[0]) == VK_SUCCESS); for (size_t i = 0; i < layers.size(); ++i) { bool found = false; for (size_t j = 0; j < available_layers.size(); ++j) { if (std::strcmp(available_layers[j].layerName, layers[i]) == 0) found = true; } Assert(found, fmt::format("vulkan: layer '{}' not supported by the instance", layers[i])); } }
/* * Return list of Global layers available */ std::vector<VkLayerProperties> GetGlobalLayers() { VkResult err; std::vector<VkLayerProperties> layers; uint32_t layer_count; do { layer_count = 0; err = vkEnumerateInstanceLayerProperties(&layer_count, NULL); if (err == VK_SUCCESS) { layers.reserve(layer_count); err = vkEnumerateInstanceLayerProperties(&layer_count, layers.data()); } } while (err == VK_INCOMPLETE); assert(err == VK_SUCCESS); return layers; }
TEST_F(EnumerateInstanceLayerProperties, TwoPass) { uint32_t count = 0u; VkResult result = vkEnumerateInstanceLayerProperties(&count, nullptr); ASSERT_EQ(result, VK_SUCCESS); std::unique_ptr<VkLayerProperties[]> properties(new VkLayerProperties[count]); result = vkEnumerateInstanceLayerProperties(&count, properties.get()); ASSERT_EQ(result, VK_SUCCESS); if(std::find(arguments.begin(), arguments.end(), "properties") != arguments.end()) { for(uint32_t p = 0; p < count; ++p) { std::cout << "properties[" << p << "] =" << ' ' << properties[p].layerName << ' ' << properties[p].specVersion << ' ' << properties[p].implementationVersion << ' ' << properties[p].description << '\n'; } } }
// Check for the availabilty of some validation layers bool checkValidationLayerSupport() { uint32_t layerCount; vkEnumerateInstanceLayerProperties(&layerCount, nullptr); // Get the available validation layers std::vector<VkLayerProperties> availableLayers(layerCount); vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data()); // Convert to a set std::unordered_set<std::string> availableLayersSet; std::for_each(availableLayers.begin(), availableLayers.end(), [&availableLayersSet] (VkLayerProperties& p) { availableLayersSet.emplace(p.layerName); }); // Construct other set std::unordered_set<std::string> validationLayersSet(validationLayers.begin(), validationLayers.end()); // Ensure selected validation layers is a subset of available layers return std::includes(availableLayersSet.begin(), availableLayersSet.end(), validationLayersSet.begin(), validationLayersSet.end()); }
VkResult VulkanContext::GetInstanceLayerProperties() { /* * It's possible, though very rare, that the number of * instance layers could change. For example, installing something * could include new layers that the loader would pick up * between the initial query for the count and the * request for VkLayerProperties. The loader indicates that * by returning a VK_INCOMPLETE status and will update the * the count parameter. * The count parameter will be updated with the number of * entries loaded into the data pointer - in case the number * of layers went down or is smaller than the size given. */ uint32_t instance_layer_count; std::vector<VkLayerProperties> vk_props; VkResult res; do { res = vkEnumerateInstanceLayerProperties(&instance_layer_count, nullptr); if (res != VK_SUCCESS) return res; if (!instance_layer_count) return VK_SUCCESS; vk_props.resize(instance_layer_count); res = vkEnumerateInstanceLayerProperties(&instance_layer_count, vk_props.data()); } while (res == VK_INCOMPLETE); // Now gather the extension list for each instance layer. for (uint32_t i = 0; i < instance_layer_count; i++) { LayerProperties layer_props; layer_props.properties = vk_props[i]; res = GetInstanceLayerExtensionList(layer_props.properties.layerName, layer_props.extensions); if (res != VK_SUCCESS) return res; instance_layer_properties_.push_back(layer_props); } return res; }
/** Enumerates and caches all layers supported by the Vulkan Instance. */ void Anvil::Instance::enumerate_instance_layers() { std::vector<VkLayerProperties> layer_props; uint32_t n_layers = 0; VkResult result = VK_ERROR_INITIALIZATION_FAILED; ANVIL_REDUNDANT_VARIABLE(result); /* Retrieve layer data */ result = vkEnumerateInstanceLayerProperties(&n_layers, nullptr); /* pProperties */ anvil_assert_vk_call_succeeded(result); layer_props.resize(n_layers + 1 /* global layer */); result = vkEnumerateInstanceLayerProperties(&n_layers, &layer_props[0]); anvil_assert_vk_call_succeeded(result); /* Convert raw layer props data to internal descriptors */ for (uint32_t n_layer = 0; n_layer < n_layers + 1; ++n_layer) { Anvil::Layer* layer_ptr = nullptr; if (n_layer < n_layers) { m_supported_layers.push_back(Anvil::Layer(layer_props[n_layer]) ); layer_ptr = &m_supported_layers[n_layer]; } enumerate_layer_extensions(layer_ptr); } }
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; } }
int sample_main(int argc, char *argv[]) { VkResult res; struct sample_info info; uint32_t instance_layer_count; VkLayerProperties *vk_props = NULL; init_global_layer_properties(info); /* VULKAN_KEY_START */ /* * It's possible, though very rare, that the number of * instance layers could change. For example, installing something * could include new layers that the loader would pick up * between the initial query for the count and the * request for VkLayerProperties. The loader indicates that * by returning a VK_INCOMPLETE status and will update the * the count parameter. * The count parameter will be updated with the number of * entries loaded into the data pointer - in case the number * of layers went down or is smaller than the size given. */ do { res = vkEnumerateInstanceLayerProperties(&instance_layer_count, NULL); if (res) break; if (instance_layer_count == 0) { break; } vk_props = (VkLayerProperties *)realloc( vk_props, instance_layer_count * sizeof(VkLayerProperties)); res = vkEnumerateInstanceLayerProperties(&instance_layer_count, vk_props); } while (res == VK_INCOMPLETE); std::cout << "Instance Layers:" << std::endl; for (uint32_t i = 0; i < instance_layer_count; i++) { VkLayerProperties *props = &vk_props[i]; uint32_t major, minor, patch; std::cout << props->layerName << ":" << std::endl; extract_version(props->specVersion, major, minor, patch); std::cout << "\tVersion: " << props->implementationVersion << std::endl; std::cout << "\tAPI Version: " << "(" << major << "." << minor << "." << patch << ")" << std::endl; std::cout << "\tDescription: " << props->description << std::endl; std::cout << std::endl << std::endl; } std::cout << std::endl; free(vk_props); /* VULKAN_KEY_END */ return 0; }
// Devices void Renderer::_InitDevice() { { uint32_t gpu_count = 0; // Read number of GPU's vkEnumeratePhysicalDevices(_instance, &gpu_count, nullptr); std::vector<VkPhysicalDevice> gpu_list(gpu_count); // Populate list vkEnumeratePhysicalDevices(_instance, &gpu_count, gpu_list.data()); _gpu = gpu_list[0]; // Get the first available list vkGetPhysicalDeviceProperties(_gpu, &_gpu_properties); vkGetPhysicalDeviceMemoryProperties(_gpu, &_gpu_memory_properties); } { uint32_t family_count = 0; // Read number of GPU queue family properties vkGetPhysicalDeviceQueueFamilyProperties(_gpu, &family_count, nullptr); std::vector<VkQueueFamilyProperties> family_property_list(family_count); // Populate list vkGetPhysicalDeviceQueueFamilyProperties(_gpu, &family_count, family_property_list.data()); // Find the graphics family bool found = false; for (uint32_t i = 0; i < family_count; ++i) { if (family_property_list[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) { found = true; _graphics_family_index = i; } } if (!found) { assert(0 && "Vulkan ERROR: Queue family supporting graphics not found."); std::exit(-1); } } // Instance Layers { uint32_t layer_count = 0; // Read the number of layers vkEnumerateInstanceLayerProperties(&layer_count, nullptr); std::vector<VkLayerProperties> layer_property_list(layer_count); // Populate list vkEnumerateInstanceLayerProperties(&layer_count, layer_property_list.data()); #if BUILD_ENABLE_VULKAN_RUNTIME_DEBUG std::cout << "Instance layers: \n"; for (auto &i : layer_property_list) { std::cout << " " << i.layerName << "\t\t | " << i.description << std::endl; } std::cout << std::endl; #endif } // Instance Extensions { uint32_t extension_count = 0; // Read the number of extensions vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, nullptr); std::vector<VkExtensionProperties> extension_property_list(extension_count); // Populate list vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extension_property_list.data()); #if BUILD_ENABLE_VULKAN_RUNTIME_DEBUG std::cout << "Instance extensions: \n"; for (auto &i : extension_property_list) { std::cout << " " << i.extensionName << "\t\t | " << i.specVersion << std::endl; } std::cout << std::endl; #endif } // Device Layers { uint32_t layer_count = 0; // Read the number of layers vkEnumerateDeviceLayerProperties(_gpu, &layer_count, nullptr); std::vector<VkLayerProperties> layer_property_list(layer_count); // Populate list vkEnumerateDeviceLayerProperties(_gpu, &layer_count, layer_property_list.data()); #if BUILD_ENABLE_VULKAN_RUNTIME_DEBUG std::cout << "Device layers: \n"; for (auto &i : layer_property_list) { std::cout << " " << i.layerName << "\t\t | " << i.description << std::endl; } std::cout << std::endl; #endif } // Device Extensions { uint32_t extension_count = 0; // Read the number of extensions vkEnumerateDeviceExtensionProperties(_gpu, nullptr, &extension_count, nullptr); std::vector<VkExtensionProperties> extension_property_list(extension_count); // Populate list vkEnumerateDeviceExtensionProperties(_gpu, nullptr, &extension_count, extension_property_list.data()); #if BUILD_ENABLE_VULKAN_RUNTIME_DEBUG std::cout << "Device extensions: \n"; for (auto &i : extension_property_list) { std::cout << " " << i.extensionName << "\t\t | " << i.specVersion << std::endl; } std::cout << std::endl; #endif } float queue_priorities[] {1.0f}; VkDeviceQueueCreateInfo device_queue_create_info {}; device_queue_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; device_queue_create_info.queueFamilyIndex = _graphics_family_index; device_queue_create_info.queueCount = 1; device_queue_create_info.pQueuePriorities = queue_priorities; VkDeviceCreateInfo device_create_info = {}; device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; device_create_info.queueCreateInfoCount = 1; device_create_info.pQueueCreateInfos = &device_queue_create_info; device_create_info.enabledLayerCount = (uint32_t) _device_layer_list.size(); device_create_info.ppEnabledLayerNames = _device_layer_list.data(); device_create_info.enabledExtensionCount = (uint32_t) _device_extension_list.size(); device_create_info.ppEnabledExtensionNames = _device_extension_list.data(); ErrorCheck(vkCreateDevice(_gpu, &device_create_info, nullptr, &_device)); vkGetDeviceQueue(_device, _graphics_family_index, 0, &_queue); }
int main(int argc, char** argv) { g_validationLayers = std::vector<const char*> { "VK_LAYER_LUNARG_mem_tracker", "VK_LAYER_GOOGLE_unique_objects", }; // Init GLFW { // Handle GLFW errors glfwSetErrorCallback([](int error, const char* description) { std::cout << "GLFW error: " << error << " - " << description << std::endl; }); // Initialize GLFW if (!glfwInit()) error("Cannot initialize GLFW."); // Check Vulkan support if (!glfwVulkanSupported()) error("Cannot find compatible Vulkan client driver."); } // Get Validation layers { uint32_t numInstanceLayers = 0; // Get numInstanceLayers if (vkEnumerateInstanceLayerProperties(&numInstanceLayers, nullptr)) error("Vulkan: Could not enumerate instance layer properties."); if (numInstanceLayers > 0) { std::vector<VkLayerProperties> instanceLayers(numInstanceLayers); if (vkEnumerateInstanceLayerProperties(&numInstanceLayers, instanceLayers.data())) error("Vulkan: Could not enumerate instance layer properties."); // Print layers: std::cout << "Validation layers: " << std::endl; for (int i = 0; i < numInstanceLayers; ++i) { std::cout << "\t" << instanceLayers[i].layerName << std::endl; std::cout << "\t\t" << instanceLayers[i].description << std::endl; std::cout << std::endl; } std::cout << std::endl; } else std::cout << "No validation layers found!" << std::endl; // TODO: Check Layers } // Check instance extensions { int numRequiredExtensions; const char** requiredExtensions; // Get required extensions from GLFW { requiredExtensions = glfwGetRequiredInstanceExtensions((int*)&numRequiredExtensions); if (numRequiredExtensions > 0) { // Write to global g_extensions for (int i = 0; i < numRequiredExtensions; ++i) g_extensions.push_back(requiredExtensions[i]); // Print std::cout << "Required Instance Extensions(GLFW):" << std::endl; for (int i = 0; i < numRequiredExtensions; ++i) { std::cout << "\t" << requiredExtensions[i] << std::endl; } std::cout << std::endl; } // TODO: Check extensions } // Get Instance extensions { VkResult err; uint32_t numInstanceExtensions; err = vkEnumerateInstanceExtensionProperties(nullptr, &numInstanceExtensions, nullptr); if (numInstanceExtensions > 0) { std::vector<VkExtensionProperties> instanceExtensions(numInstanceExtensions); err = vkEnumerateInstanceExtensionProperties(NULL, &numInstanceExtensions, instanceExtensions.data()); // Print std::cout << "Instance Extensions: " << std::endl; for (int i = 0; i < numInstanceExtensions; ++i) { std::cout << "\t" <<instanceExtensions[i].extensionName << std::endl; std::cout << "\t\t" << instanceExtensions[i].specVersion << std::endl; std::cout << std::endl; } std::cout << std::endl; } // TODO: Check instance extensions(with required instance extensions) } } // Create Vulkan Instance { VkApplicationInfo app; { app.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; app.pNext = nullptr; app.pApplicationName = "Vulkan test 1"; app.applicationVersion = 0; app.pEngineName = "Vulkan test 1"; app.engineVersion = 0; app.apiVersion = VK_API_VERSION; } VkInstanceCreateInfo instanceInfo; { instanceInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; instanceInfo.pNext = nullptr; instanceInfo.pApplicationInfo = &app; instanceInfo.enabledLayerCount = g_validationLayers.size(); instanceInfo.ppEnabledLayerNames = g_validationLayers.data(); instanceInfo.enabledExtensionCount = g_extensions.size(); instanceInfo.ppEnabledExtensionNames = g_extensions.data(); } // TODO: Aligned allocators VkAllocationCallbacks allocator; { allocator.pUserData = nullptr; allocator.pfnAllocation = [](void* pUserData, size_t size, size_t alignment, VkSystemAllocationScope allocationScope)->void* { return malloc(size); }; allocator.pfnFree = [](void* pUserData, void* pMemory) { free(pMemory); }; allocator.pfnReallocation = [](void* pUserData, void *pOriginal, size_t size, size_t alignment, VkSystemAllocationScope allocationScope) { free(pOriginal); return malloc(size); }; allocator.pfnInternalAllocation = nullptr; allocator.pfnInternalFree = nullptr; allocator.pfnReallocation = nullptr; } // Create vulkan instance VkResult vkError = vkCreateInstance(&instanceInfo, &allocator, &g_vkInstance); // Handle errors switch (vkError) { case VK_ERROR_INCOMPATIBLE_DRIVER: error("Drivers do not support vulkan. Drivers could be outdated."); break; case VK_ERROR_EXTENSION_NOT_PRESENT: error("Cannot find specified extension."); break; case VK_SUCCESS: // Succes! (prevent default from catching success as error) std::cout << "Vulkan instance created!" << std::endl; break; default: error("Could not create vulkan Instance. Drivers could be outdated."); break; } } // Look for GPU device { uint32_t numGPUs; VkResult vkError = vkEnumeratePhysicalDevices(g_vkInstance, &numGPUs, nullptr); if (numGPUs < 0) error("vkEnumeratePhysicalDevices could not find any GPU devices."); if (vkError) error("vkEnumeratePhysicalDevices could not enumerate GPU devices."); if (numGPUs > 0) { std::vector<VkPhysicalDevice> physicalDevices(numGPUs); if (vkEnumeratePhysicalDevices(g_vkInstance, &numGPUs, physicalDevices.data())) error("vkEnumeratePhysicalDevices could not enumerate GPU devices."); g_vkGPU = physicalDevices[0]; std::cout << numGPUs << " GPUs found!" << std::endl; } } // Get queue properties { uint32_t numQueues; vkGetPhysicalDeviceProperties(g_vkGPU, &g_vkGPUProperties); vkGetPhysicalDeviceQueueFamilyProperties(g_vkGPU, &numQueues, nullptr); if (numQueues == 0) error("vkGetPhysicalDeviceQueueFamilyProperties could not find any queues."); g_vkQueueProperties = std::vector<VkQueueFamilyProperties>(numQueues); vkGetPhysicalDeviceQueueFamilyProperties(g_vkGPU, &numQueues, g_vkQueueProperties.data()); } // Look for device layers (Unecessary code that does nothing) { uint32_t numDeviceLayers; if (vkEnumerateDeviceLayerProperties(g_vkGPU, &numDeviceLayers, nullptr)) error("vkEnumerateDeviceLayerProperties failed!"); if (numDeviceLayers > 0) { std::vector<VkLayerProperties> deviceLayers(numDeviceLayers); if (vkEnumerateDeviceLayerProperties(g_vkGPU, &numDeviceLayers, deviceLayers.data())) error("vkEnumerateDeviceLayerProperties failed!"); // TODO: Check device layers. } } // Look for device extensions (swapchain extension) { uint32_t numDeviceExtensions; bool extensionSwapChainFound = false; if (vkEnumerateDeviceExtensionProperties(g_vkGPU, nullptr, &numDeviceExtensions, nullptr)) error("vkEnumerateDeviceExtensionProperties failed!"); if (numDeviceExtensions > 0) { std::vector<VkExtensionProperties> deviceExtensions(numDeviceExtensions); if (vkEnumerateDeviceExtensionProperties(g_vkGPU, nullptr, &numDeviceExtensions, deviceExtensions.data())) error("vkEnumerateDeviceExtensionProperties failed!"); // Search for swapchain extension for (VkExtensionProperties extension : deviceExtensions) { if (!strcmp(extension.extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME)) extensionSwapChainFound = true; } // Print std::cout << std::endl << "Extensions:" << std::endl; for (VkExtensionProperties extension : deviceExtensions) { std::cout << extension.extensionName << "(" << extension.specVersion << ")" << std::endl; } std::cout << std::endl; } if (!extensionSwapChainFound) error("Failed to find the " VK_KHR_SWAPCHAIN_EXTENSION_NAME " extension!"); } // TODO: Validate // Get instance function adresses { GET_INSTANCE_PROC_ADDR(g_vkInstance, GetPhysicalDeviceSurfaceCapabilitiesKHR); GET_INSTANCE_PROC_ADDR(g_vkInstance, GetPhysicalDeviceSurfaceFormatsKHR); GET_INSTANCE_PROC_ADDR(g_vkInstance, GetPhysicalDeviceSurfacePresentModesKHR); GET_INSTANCE_PROC_ADDR(g_vkInstance, GetPhysicalDeviceSurfaceSupportKHR); GET_INSTANCE_PROC_ADDR(g_vkInstance, CreateSwapchainKHR); GET_INSTANCE_PROC_ADDR(g_vkInstance, DestroySwapchainKHR); GET_INSTANCE_PROC_ADDR(g_vkInstance, GetSwapchainImagesKHR); GET_INSTANCE_PROC_ADDR(g_vkInstance, AcquireNextImageKHR); GET_INSTANCE_PROC_ADDR(g_vkInstance, QueuePresentKHR); } // Create window { glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); g_window = glfwCreateWindow(g_width, g_height, "Vulkan test", NULL, NULL); if (!g_window) error("Could not create window!"); glfwSetWindowRefreshCallback(g_window, [](GLFWwindow* window) { // TODO: draw(); }); glfwSetFramebufferSizeCallback(g_window, [](GLFWwindow* window, int width, int height) { g_width = width; g_height = height; // TODO: resize(); }); } // Init swapchain { glfwCreateWindowSurface(g_vkInstance, g_window, nullptr, &g_vkSurface); std::vector<VkBool32> supportsPresent(g_vkQueueProperties.size()); for (uint32_t i = 0; i < g_vkQueueProperties.size(); ++i) g_vkFPGetPhysicalDeviceSurfaceSupportKHR(g_vkGPU, i, g_vkSurface, &supportsPresent[i]); uint32_t graphicsQueueNodeIndex = UINT32_MAX; uint32_t presentQueueNodeIndex = UINT32_MAX; for (uint32_t i = 0; i < g_vkQueueProperties.size(); ++i) { if (graphicsQueueNodeIndex == UINT32_MAX) { graphicsQueueNodeIndex = i; } if (supportsPresent[i] == VK_TRUE) { graphicsQueueNodeIndex = i; presentQueueNodeIndex = i; break; } } //if (presentQueueNodeIndex == UINT32_MAX) { // for (uint32_t i = 0; i < g_vkQueueProperties.size(); ++i) { // if (supportsPresent[i] == VK_TRUE) { // presentQueueNodeIndex = i; // } // } //} if (graphicsQueueNodeIndex == UINT32_MAX || presentQueueNodeIndex == UINT32_MAX) error("Could not find a graphics and a present queue."); if (graphicsQueueNodeIndex != presentQueueNodeIndex) error("Could not find a common graphics and present queue."); g_vkGraphicsQueueNodeIndex = graphicsQueueNodeIndex; //TODO: init device { float queuePriotities = 0.f; VkDeviceQueueCreateInfo queue; { queue.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; queue.pNext = NULL; queue.queueFamilyIndex = g_vkGraphicsQueueNodeIndex; queue.queueCount = 1; queue.pQueuePriorities = &queuePriotities; } } //vkGetDeviceQueue(g_vkDevice, g_vkGraphicsQueueNodeIndex, 0, g_vkQueue); } std::cin.get(); return 0; }
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)); }
gboolean gst_vulkan_instance_open (GstVulkanInstance * instance, GError ** error) { VkExtensionProperties *instance_extensions; char *extension_names[64]; /* FIXME: make dynamic */ VkLayerProperties *instance_layers; uint32_t instance_extension_count = 0; uint32_t enabled_extension_count = 0; uint32_t instance_layer_count = 0; uint32_t enabled_layer_count = 0; gchar **enabled_layers; VkResult err; GST_OBJECT_LOCK (instance); if (instance->priv->opened) { GST_OBJECT_UNLOCK (instance); return TRUE; } /* Look for validation layers */ err = vkEnumerateInstanceLayerProperties (&instance_layer_count, NULL); if (gst_vulkan_error_to_g_error (err, error, "vKEnumerateInstanceLayerProperties") < 0) goto error; instance_layers = g_new0 (VkLayerProperties, instance_layer_count); err = vkEnumerateInstanceLayerProperties (&instance_layer_count, instance_layers); if (gst_vulkan_error_to_g_error (err, error, "vKEnumerateInstanceLayerProperties") < 0) { g_free (instance_layers); goto error; } /* TODO: allow outside selection */ _check_for_all_layers (G_N_ELEMENTS (instance_validation_layers), instance_validation_layers, instance_layer_count, instance_layers, &enabled_layer_count, &enabled_layers); g_free (instance_layers); err = vkEnumerateInstanceExtensionProperties (NULL, &instance_extension_count, NULL); if (gst_vulkan_error_to_g_error (err, error, "vkEnumerateInstanceExtensionProperties") < 0) { g_strfreev (enabled_layers); goto error; } GST_DEBUG_OBJECT (instance, "Found %u extensions", instance_extension_count); memset (extension_names, 0, sizeof (extension_names)); instance_extensions = g_new0 (VkExtensionProperties, instance_extension_count); err = vkEnumerateInstanceExtensionProperties (NULL, &instance_extension_count, instance_extensions); if (gst_vulkan_error_to_g_error (err, error, "vkEnumerateInstanceExtensionProperties") < 0) { g_strfreev (enabled_layers); g_free (instance_extensions); goto error; } { GstVulkanDisplayType display_type; gboolean swapchain_ext_found = FALSE; gboolean winsys_ext_found = FALSE; const gchar *winsys_ext_name; display_type = gst_vulkan_display_choose_type (instance); winsys_ext_name = gst_vulkan_display_type_to_extension_string (display_type); if (!winsys_ext_name) { GST_WARNING_OBJECT (instance, "No window system extension enabled"); winsys_ext_found = TRUE; /* Don't error out completely */ } /* TODO: allow outside selection */ for (uint32_t i = 0; i < instance_extension_count; i++) { GST_TRACE_OBJECT (instance, "checking instance extension %s", instance_extensions[i].extensionName); if (!g_strcmp0 (VK_KHR_SURFACE_EXTENSION_NAME, instance_extensions[i].extensionName)) { swapchain_ext_found = TRUE; extension_names[enabled_extension_count++] = (gchar *) VK_KHR_SURFACE_EXTENSION_NAME; } if (!g_strcmp0 (VK_EXT_DEBUG_REPORT_EXTENSION_NAME, instance_extensions[i].extensionName)) { extension_names[enabled_extension_count++] = (gchar *) VK_EXT_DEBUG_REPORT_EXTENSION_NAME; } if (!g_strcmp0 (winsys_ext_name, instance_extensions[i].extensionName)) { winsys_ext_found = TRUE; extension_names[enabled_extension_count++] = (gchar *) winsys_ext_name; } g_assert (enabled_extension_count < 64); } if (!swapchain_ext_found) { g_set_error (error, GST_VULKAN_ERROR, VK_ERROR_INITIALIZATION_FAILED, "vkEnumerateInstanceExtensionProperties failed to find the required " "\"" VK_KHR_SURFACE_EXTENSION_NAME "\" extension"); g_strfreev (enabled_layers); g_free (instance_extensions); goto error; } if (!winsys_ext_found) { g_set_error (error, GST_VULKAN_ERROR, VK_ERROR_INITIALIZATION_FAILED, "vkEnumerateInstanceExtensionProperties failed to find the required " "\"%s\" window system extension", winsys_ext_name); g_strfreev (enabled_layers); g_free (instance_extensions); goto error; } } { VkApplicationInfo app = { 0, }; VkInstanceCreateInfo inst_info = { 0, }; app.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; app.pNext = NULL; app.pApplicationName = APP_SHORT_NAME; app.applicationVersion = 0; app.pEngineName = APP_SHORT_NAME; app.engineVersion = 0; app.apiVersion = VK_API_VERSION_1_0; inst_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; inst_info.pNext = NULL; inst_info.pApplicationInfo = &app; #if 0 inst_info.enabledLayerCount = enabled_layer_count; inst_info.ppEnabledLayerNames = (const char *const *) enabled_layers; #else inst_info.enabledLayerCount = 0; inst_info.ppEnabledLayerNames = NULL; #endif inst_info.enabledExtensionCount = enabled_extension_count; inst_info.ppEnabledExtensionNames = (const char *const *) extension_names; err = vkCreateInstance (&inst_info, NULL, &instance->instance); if (gst_vulkan_error_to_g_error (err, error, "vkCreateInstance") < 0) { g_strfreev (enabled_layers); g_free (instance_extensions); goto error; } } g_free (instance_extensions); g_strfreev (enabled_layers); err = vkEnumeratePhysicalDevices (instance->instance, &instance->n_physical_devices, NULL); if (gst_vulkan_error_to_g_error (err, error, "vkEnumeratePhysicalDevices") < 0) goto error; g_assert (instance->n_physical_devices > 0); instance->physical_devices = g_new0 (VkPhysicalDevice, instance->n_physical_devices); err = vkEnumeratePhysicalDevices (instance->instance, &instance->n_physical_devices, instance->physical_devices); if (gst_vulkan_error_to_g_error (err, error, "vkEnumeratePhysicalDevices") < 0) goto error; instance->dbgCreateDebugReportCallback = (PFN_vkCreateDebugReportCallbackEXT) gst_vulkan_instance_get_proc_address (instance, "vkCreateDebugReportCallbackEXT"); if (!instance->dbgCreateDebugReportCallback) { g_set_error (error, GST_VULKAN_ERROR, VK_ERROR_INITIALIZATION_FAILED, "Failed to retreive vkCreateDebugReportCallback"); goto error; } instance->dbgDestroyDebugReportCallback = (PFN_vkDestroyDebugReportCallbackEXT) gst_vulkan_instance_get_proc_address (instance, "vkDestroyDebugReportCallbackEXT"); if (!instance->dbgDestroyDebugReportCallback) { g_set_error (error, GST_VULKAN_ERROR, VK_ERROR_INITIALIZATION_FAILED, "Failed to retreive vkDestroyDebugReportCallback"); goto error; } instance->dbgReportMessage = (PFN_vkDebugReportMessageEXT) gst_vulkan_instance_get_proc_address (instance, "vkDebugReportMessageEXT"); if (!instance->dbgReportMessage) { g_set_error (error, GST_VULKAN_ERROR, VK_ERROR_INITIALIZATION_FAILED, "Failed to retreive vkDebugReportMessage"); goto error; } { VkDebugReportCallbackCreateInfoEXT info = { 0, }; info.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT; info.pNext = NULL; info.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_INFORMATION_BIT_EXT | VK_DEBUG_REPORT_DEBUG_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT; info.pfnCallback = (PFN_vkDebugReportCallbackEXT) _gst_vk_debug_callback; info.pUserData = NULL; err = instance->dbgCreateDebugReportCallback (instance->instance, &info, NULL, &instance->msg_callback); if (gst_vulkan_error_to_g_error (err, error, "vkCreateDebugReportCallback") < 0) goto error; } instance->priv->opened = TRUE; GST_OBJECT_UNLOCK (instance); return TRUE; error: { GST_OBJECT_UNLOCK (instance); return FALSE; } }
bool Renderer::CreateInstance() { //Get Layer count and layer properties uint32_t layerPropertiesCount; auto err = vkEnumerateInstanceLayerProperties(&layerPropertiesCount, nullptr); if (err != VK_SUCCESS) { //TODO output an error return false; } if (layerPropertiesCount == 0) { return true; } std::unique_ptr<VkLayerProperties[]> layerPropertiesArray(new VkLayerProperties[layerPropertiesCount]); err = vkEnumerateInstanceLayerProperties(&layerPropertiesCount, layerPropertiesArray.get()); if (err != VK_SUCCESS) { //TODO output debug error return false; } // Get extension count and properties uint32_t extensionCount; err = vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr); if (err != VK_SUCCESS) { //TODO output an error return false; } std::unique_ptr<VkExtensionProperties[]> extensionsArray( new VkExtensionProperties[extensionCount] ); err = vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensionsArray.get()); if (err != VK_SUCCESS) { //TODO output an error return false; } //Get layer names char ** layerNames = new char*[layerPropertiesCount]; for (uint32_t i = 0; i < layerPropertiesCount; ++i) { size_t nameLength = strlen(layerPropertiesArray[i].layerName) + 1; layerNames[i] = new char[nameLength]; strcpy_s(layerNames[i], nameLength, layerPropertiesArray[i].layerName); } //Get extension names char** extensionNames = new char*[extensionCount]; for (uint32_t i = 0; i < extensionCount; ++i) { size_t nameLength = strlen(extensionsArray[i].extensionName) + 1; extensionNames[i] = new char[nameLength]; strcpy_s(extensionNames[i], nameLength, extensionsArray[i].extensionName); } //Create instance VkApplicationInfo appInfo {}; appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; appInfo.pApplicationName = "Test"; appInfo.apiVersion = VK_MAKE_VERSION(1, 0, 8); // VK_API_VERSION; is deprecated VkInstanceCreateInfo createInfo {}; createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; createInfo.pApplicationInfo = &appInfo; createInfo.enabledLayerCount = layerPropertiesCount; createInfo.ppEnabledLayerNames = layerNames; createInfo.enabledExtensionCount = extensionCount; createInfo.ppEnabledExtensionNames = extensionNames; err = vkCreateInstance(&createInfo, nullptr, &instance); if (err != VK_SUCCESS) { //TODO output an error return false; } //Create device return true; }
int main() { //Настроем вывод. setlocale(LC_ALL, "Russian"); //Подготовим данные приложения VkApplicationInfo app_info; memset(&app_info, 0, sizeof(app_info)); app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; app_info.pApplicationName = app_name; #ifdef VK_API_VERSION_1_0 app_info.apiVersion = VK_API_VERSION_1_0; #else app_info.apiVersion = VK_API_VERSION; #endif app_info.applicationVersion = VK_MAKE_VERSION(0, 1, 25); VkResult res; //заранее подготовим переменную для результата, она нам понадобится несколько раз. //Данные экземпляра VkInstanceCreateInfo instance_info; memset(&instance_info, 0, sizeof(instance_info)); instance_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; instance_info.pApplicationInfo = &app_info; uint32_t available_instance_layer_count = 0; //узнаём кол-во установленных слоёв. res = vkEnumerateInstanceLayerProperties(&available_instance_layer_count, nullptr); if (res != VK_SUCCESS) { std::wcout << "Не удалось получить кол-во слоёв.\n"; return -1; } //настраиваем массив std::vector<VkLayerProperties> available_instance_layers(available_instance_layer_count); //Получаем слои res = vkEnumerateInstanceLayerProperties(&available_instance_layer_count, available_instance_layers.data()); if (available_instance_layer_count) { //А теперь выводим на экран. std::wcout << L"\n\nСлои экземпляра:\n"; for (uint32_t i = 0; i < available_instance_layer_count; i++) { VkLayerProperties &properties = available_instance_layers[i]; std::cout << properties.layerName << (strlen(properties.layerName) < 24 ? "\t" : "") << (strlen(properties.layerName) < 32 ? "\t" : "") << "\t|" << properties.description << "\n"; } } std::cout << "\n\n"; std::vector<const char *> instance_layers; instance_layers.push_back("VK_LAYER_LUNARG_standard_validation"); //И затем отправим их в стурктуру с информацией. instance_info.enabledLayerCount = instance_layers.size(); instance_info.ppEnabledLayerNames = instance_layers.data(); //Кол-во расширений. uint32_t available_instance_extension_count = 0; //Забираем кол-во расширений. res = vkEnumerateInstanceExtensionProperties(NULL, &available_instance_extension_count, nullptr); if (res != VK_SUCCESS) //Проверка { std::wcout << "Не удалось получить кол-во расширений.\n"; return -1; } //настраиваем массив std::vector<VkExtensionProperties> available_instance_extensions(available_instance_extension_count); //Получаем расширения res = vkEnumerateInstanceExtensionProperties(NULL, &available_instance_extension_count, available_instance_extensions.data()); if (available_instance_extension_count) { //Вывод на экран. std::wcout << L"\n\nРасширения экземпляра:\n"; for (uint32_t i = 0; i < available_instance_extensions.size(); i++) { VkExtensionProperties &properties = available_instance_extensions[i]; std::cout << properties.extensionName << "\n"; } std::cout << "\n\n"; } //Настройка расширений std::vector<const char *> instance_extensions; instance_extensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME); instance_info.enabledExtensionCount = instance_extensions.size(); instance_info.ppEnabledExtensionNames = instance_extensions.data(); VkInstance instance = VK_NULL_HANDLE; res = vkCreateInstance(&instance_info, NULL, &instance); if (res != VK_SUCCESS) //С проверками особо заморачиваться не будем. { std::wcerr << L"Что-то не так...\n"; return -1; } else std::wcout << L"Экземпляр Vulkan создан.\n"; //Создадим указатели на функции таким образом. PFN_vkCreateDebugReportCallbackEXT fvkCreateDebugReportCallbackEXT = NULL; PFN_vkDestroyDebugReportCallbackEXT fvkDestroyDebugReportCallbackEXT = NULL; //И получим их. fvkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT) vkGetInstanceProcAddr(instance, "vkCreateDebugReportCallbackEXT"); fvkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT) vkGetInstanceProcAddr(instance, "vkDestroyDebugReportCallbackEXT"); /* Отлично, мы получили эти функции! Теперь, нам нужно подготовить информацию для callback'ов, а также * оставить хэндл, который мы конечно же потом уничтожим. */ //Структура, которую мы должны заполнить VkDebugReportCallbackCreateInfoEXT debug_report_callback_info; memset(&debug_report_callback_info, 0, sizeof(debug_report_callback_info)); debug_report_callback_info.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT; debug_report_callback_info.flags = VK_DEBUG_REPORT_DEBUG_BIT_EXT | VK_DEBUG_REPORT_INFORMATION_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT | VK_DEBUG_REPORT_ERROR_BIT_EXT; // Настало время прикрепить наш прототип здесь: debug_report_callback_info.pfnCallback = DebugReportCallback; VkDebugReportCallbackEXT debug_report_callback = VK_NULL_HANDLE; //И наконец-таки привзяываем наш Callback: res = fvkCreateDebugReportCallbackEXT(instance, &debug_report_callback_info, NULL, &debug_report_callback); if (res != VK_SUCCESS) { std::wcerr << L"Не удалось создать debug-report callback.\n"; return -1; } std::vector<VkPhysicalDevice> gpu_list; //здесь будем хранить физические устройства. uint32_t gpu_count; //кол-во девайсов //получаем колв-о девайсов и сразу проверяем на удачу. if (vkEnumeratePhysicalDevices(instance, &gpu_count, VK_NULL_HANDLE) != VK_SUCCESS) { std::wcerr << L"Посчитать физические устройства не удалось :(\n"; return -1; } gpu_list.resize(gpu_count); //заранее изменим размер под самый оптимальный. //Забираем физические девайсы if (vkEnumeratePhysicalDevices(instance, &gpu_count, gpu_list.data()) != VK_SUCCESS) { std::wcerr << L"Заполучить твои физические устройства не удалось, но я приду за ними в следующий раз!\n"; return -1; } //Выбираем видеокарту VkPhysicalDevice gpu = gpu_list[0]; //Теперь, семейства. uint32_t family_count = 0; //кол-во семейтсв vkGetPhysicalDeviceQueueFamilyProperties(gpu, &family_count, nullptr); std::vector<VkQueueFamilyProperties> family_properties_list(family_count); vkGetPhysicalDeviceQueueFamilyProperties(gpu, &family_count, family_properties_list.data()); //Листаем семейтсва и получаем нужное. uint32_t valid_family_index = (uint32_t) -1; //значение -1 будем использовать как "не найдено, 404". for (uint32_t i = 0; i < family_count; i++) //листаем все семейства. { VkQueueFamilyProperties &properties = family_properties_list[i]; if (properties.queueFlags & VK_QUEUE_GRAPHICS_BIT) { if (valid_family_index == (uint32_t) -1) valid_family_index = i; } } //И если наш индекс всё ещё не перезаписан, то.. if (valid_family_index == (uint32_t) -1) return -1; //Описываем очереди. VkDeviceQueueCreateInfo device_queue_info; memset(&device_queue_info, 0, sizeof(device_queue_info)); device_queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; float device_queue_priority[] = {1.0f}; device_queue_info.queueCount = 1; device_queue_info.queueFamilyIndex = valid_family_index; device_queue_info.pQueuePriorities = device_queue_priority; VkDeviceCreateInfo device_info; memset(&device_info, 0, sizeof(device_info)); device_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; device_info.queueCreateInfoCount = 1; device_info.pQueueCreateInfos = &device_queue_info; uint32_t available_device_layer_count = 0; res = vkEnumerateDeviceLayerProperties(gpu, &available_device_layer_count, VK_NULL_HANDLE); if (res != VK_SUCCESS) { std::wcout << "Не удалось получить кол-во слоёв.\n"; return -1; } //настраиваем массив std::vector<VkLayerProperties> available_device_layers(available_device_layer_count); res = vkEnumerateDeviceLayerProperties(gpu, &available_device_layer_count, available_device_layers.data()); if (res != VK_SUCCESS) { std::wcout << "Не удалось получить слои.\n"; return -1; } if (available_device_layer_count) { //А теперь выводим на экран. std::wcout << L"\n\nСлои устройства:\n"; for (uint32_t i = 0; i < available_device_layer_count; i++) { //Сделаем красивый вывод для имени и описания слоя. VkLayerProperties &properties = available_device_layers[i]; std::cout << properties.layerName << (strlen(properties.layerName) < 24 ? "\t" : "") << (strlen(properties.layerName) < 32 ? "\t" : "") << "\t|" << properties.description << "\n"; } } std::cout << "\n\n"; //Кол-во расширений. uint32_t available_device_extension_count = 0; //Забираем кол-во расширений. res = vkEnumerateDeviceExtensionProperties(gpu, NULL, &available_device_extension_count, VK_NULL_HANDLE); if (res != VK_SUCCESS) //Проверка { std::wcout << "Не удалось получить кол-во расширений.\n"; return -1; } //настраиваем массив std::vector<VkExtensionProperties> available_device_extensions(available_device_extension_count); //Получаем расширения res = vkEnumerateDeviceExtensionProperties(gpu, NULL, &available_device_extension_count, available_device_extensions.data()); if (available_device_extension_count) { //Вывод на экран. std::wcout << L"\n\nРасширения устройства:\n"; for (uint32_t i = 0; i < available_device_extensions.size(); i++) { VkExtensionProperties &properties = available_device_extensions[i]; std::cout << properties.extensionName << "\n"; } std::cout << "\n\n"; } std::vector<const char *> device_layers = instance_layers; //Расширения и слои device_info.enabledLayerCount = device_layers.size(); device_info.ppEnabledLayerNames = device_layers.data(); //А расширения устройства оставим и на сей раз пустым. std::vector<const char *> device_extensions; device_info.enabledExtensionCount = device_extensions.size(); device_info.ppEnabledExtensionNames = device_extensions.data(); VkDevice device = VK_NULL_HANDLE; if (vkCreateDevice(gpu, &device_info, NULL, &device) != VK_SUCCESS) return -1; vkDestroyDevice(device, NULL); fvkDestroyDebugReportCallbackEXT(instance, debug_report_callback, NULL); vkDestroyInstance(instance, NULL); std::wcout << L"Пожарено!\n"; return 0; }