From 1af57a3ec4143286f12d32565dcd7ed44f01754c Mon Sep 17 00:00:00 2001 From: Charles Giessen Date: Thu, 27 Feb 2020 15:02:29 -0700 Subject: vulkaninfo: Refactor error handling Previously, if vulkaninfo encountered any errors, it shut down then and there. This is bad for json output where you are left with an invalid file. By using exceptions, vulkaninfo will catch errors, print it to cerr, then finish off the file so its left in a valid state. Change-Id: I2c0116b435713df6135b9c606fa95cfadbfdf8d8 --- vulkaninfo/vulkaninfo.cpp | 173 +++++++++++++++++++++++----------------------- 1 file changed, 87 insertions(+), 86 deletions(-) (limited to 'vulkaninfo/vulkaninfo.cpp') diff --git a/vulkaninfo/vulkaninfo.cpp b/vulkaninfo/vulkaninfo.cpp index 4dc1dfe8..d81749b4 100644 --- a/vulkaninfo/vulkaninfo.cpp +++ b/vulkaninfo/vulkaninfo.cpp @@ -74,7 +74,8 @@ void DumpLayers(Printer &p, std::vector layers, const std::v case OutputType::html: { p.SetHeader(); ArrayWrapper arr(p, "Layers", layers.size()); - p.IndentDecrease(); + IndentWrapper indent(p); + for (auto &layer : layers) { auto v_str = VkVersionString(layer.layer_properties.specVersion); auto props = layer.layer_properties; @@ -93,7 +94,6 @@ void DumpLayers(Printer &p, std::vector layers, const std::v p.AddNewline(); } } - p.IndentIncrease(); break; } @@ -212,7 +212,7 @@ void DumpPresentableSurfaces(Printer &p, AppInstance &inst, const std::vector> &surfaces) { p.SetHeader(); ObjectWrapper obj(p, "Presentable Surfaces"); - p.IndentDecrease(); + IndentWrapper indent(p); std::vector surface_list; @@ -240,7 +240,6 @@ void DumpPresentableSurfaces(Printer &p, AppInstance &inst, const std::vector> printers; + std::ostream out(std::cout.rdbuf()); + std::ofstream html_out; + std::ofstream vkconfig_out; - AppInstance instance = {}; - SetupWindowExtensions(instance); + // if any essential vulkan call fails, it throws an exception + try { + AppInstance instance = {}; + SetupWindowExtensions(instance); - auto pNext_chains = get_chain_infos(); + auto pNext_chains = get_chain_infos(); - auto phys_devices = instance.FindPhysicalDevices(); + auto phys_devices = instance.FindPhysicalDevices(); - std::vector> surfaces; + std::vector> surfaces; #if defined(VK_USE_PLATFORM_XCB_KHR) || defined(VK_USE_PLATFORM_XLIB_KHR) || defined(VK_USE_PLATFORM_WIN32_KHR) || \ defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT) || defined(VK_USE_PLATFORM_WAYLAND_KHR) - for (auto &surface_extension : instance.surface_extensions) { - surface_extension.create_window(instance); - surface_extension.surface = surface_extension.create_surface(instance); - for (auto &phys_device : phys_devices) { - surfaces.push_back(std::unique_ptr( - new AppSurface(instance, phys_device, surface_extension, pNext_chains.surface_capabilities2))); + for (auto &surface_extension : instance.surface_extensions) { + surface_extension.create_window(instance); + surface_extension.surface = surface_extension.create_surface(instance); + for (auto &phys_device : phys_devices) { + surfaces.push_back(std::unique_ptr( + new AppSurface(instance, phys_device, surface_extension, pNext_chains.surface_capabilities2))); + } } - } #endif - std::vector> gpus; + std::vector> gpus; - uint32_t gpu_counter = 0; - for (auto &phys_device : phys_devices) { - gpus.push_back(std::unique_ptr(new AppGpu(instance, gpu_counter++, phys_device, pNext_chains))); - } - - if (selected_gpu >= gpus.size()) { - std::cout << "The selected gpu (" << selected_gpu << ") is not in the valid range of 0 to " << gpus.size() - 1 << ".\n"; - return 0; - } - - std::vector> printers; + uint32_t gpu_counter = 0; + for (auto &phys_device : phys_devices) { + gpus.push_back(std::unique_ptr(new AppGpu(instance, gpu_counter++, phys_device, pNext_chains))); + } - std::streambuf *buf; - buf = std::cout.rdbuf(); - std::ostream out(buf); - std::ofstream html_out; - std::ofstream vkconfig_out; + if (selected_gpu >= gpus.size()) { + std::cout << "The selected gpu (" << selected_gpu << ") is not in the valid range of 0 to " << gpus.size() - 1 << ".\n"; + return 0; + } - if (human_readable_output) { - printers.push_back(std::unique_ptr(new Printer(OutputType::text, out, selected_gpu, instance.vk_version))); - } - if (html_output) { - html_out = std::ofstream("vulkaninfo.html"); - printers.push_back(std::unique_ptr(new Printer(OutputType::html, html_out, selected_gpu, instance.vk_version))); - } - if (json_output) { - printers.push_back(std::unique_ptr(new Printer(OutputType::json, out, selected_gpu, instance.vk_version))); - } - if (vkconfig_output) { + if (human_readable_output) { + printers.push_back(std::unique_ptr(new Printer(OutputType::text, out, selected_gpu, instance.vk_version))); + } + if (html_output) { + html_out = std::ofstream("vulkaninfo.html"); + printers.push_back( + std::unique_ptr(new Printer(OutputType::html, html_out, selected_gpu, instance.vk_version))); + } + if (json_output) { + printers.push_back(std::unique_ptr(new Printer(OutputType::json, out, selected_gpu, instance.vk_version))); + } + if (vkconfig_output) { #ifdef WIN32 - vkconfig_out = std::ofstream(std::string(output_path) + "\\vulkaninfo.json"); + vkconfig_out = std::ofstream(std::string(output_path) + "\\vulkaninfo.json"); #else - vkconfig_out = std::ofstream(std::string(output_path) + "/vulkaninfo.json"); + vkconfig_out = std::ofstream(std::string(output_path) + "/vulkaninfo.json"); #endif - printers.push_back( - std::unique_ptr(new Printer(OutputType::vkconfig_output, vkconfig_out, selected_gpu, instance.vk_version))); - } + printers.push_back(std::unique_ptr( + new Printer(OutputType::vkconfig_output, vkconfig_out, selected_gpu, instance.vk_version))); + } - for (auto &p : printers) { - if (p->Type() == OutputType::json) { - DumpLayers(*p.get(), instance.global_layers, gpus); - DumpGpuJson(*p.get(), *gpus.at(selected_gpu).get()); + for (auto &p : printers) { + if (p->Type() == OutputType::json) { + DumpLayers(*p.get(), instance.global_layers, gpus); + DumpGpuJson(*p.get(), *gpus.at(selected_gpu).get()); - } else { - p->SetHeader(); - DumpExtensions(*p.get(), "Instance", instance.global_extensions); - p->AddNewline(); + } else { + p->SetHeader(); + DumpExtensions(*p.get(), "Instance", instance.global_extensions); + p->AddNewline(); - DumpLayers(*p.get(), instance.global_layers, gpus); + DumpLayers(*p.get(), instance.global_layers, gpus); #if defined(VK_USE_PLATFORM_XCB_KHR) || defined(VK_USE_PLATFORM_XLIB_KHR) || defined(VK_USE_PLATFORM_WIN32_KHR) || \ defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT) || defined(VK_USE_PLATFORM_WAYLAND_KHR) - DumpPresentableSurfaces(*p.get(), instance, gpus, surfaces); + DumpPresentableSurfaces(*p.get(), instance, gpus, surfaces); #endif - DumpGroups(*p.get(), instance); + DumpGroups(*p.get(), instance); - p->SetHeader(); - ObjectWrapper obj(*p, "Device Properties and Extensions"); - p->IndentDecrease(); + p->SetHeader(); + ObjectWrapper obj(*p, "Device Properties and Extensions"); + IndentWrapper indent(*p); - for (auto &gpu : gpus) { - DumpGpu(*p.get(), *gpu.get(), show_formats); + for (auto &gpu : gpus) { + DumpGpu(*p.get(), *gpu.get(), show_formats); + } } - - p->IndentIncrease(); } - p.reset(); - } #if defined(VK_USE_PLATFORM_XCB_KHR) || defined(VK_USE_PLATFORM_XLIB_KHR) || defined(VK_USE_PLATFORM_WIN32_KHR) || \ defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT) || defined(VK_USE_PLATFORM_WAYLAND_KHR) - for (auto &surface_extension : instance.surface_extensions) { - AppDestroySurface(instance, surface_extension.surface); - surface_extension.destroy_window(instance); - } + for (auto &surface_extension : instance.surface_extensions) { + AppDestroySurface(instance, surface_extension.surface); + surface_extension.destroy_window(instance); + } #endif + } catch (std::exception &e) { + // Print the error to stderr and leave all outputs in a valid state (mainly for json) + std::cerr << "ERROR at " << e.what() << "\n"; + for (auto &p : printers) { + if (p) { + p->FinishOutput(); + } + } + } + // Call the printer's descrtuctor before the file handle gets closed + for (auto &p : printers) { + p.reset(nullptr); + } WAIT_FOR_CONSOLE_DESTROY; #ifdef _WIN32 -- cgit v1.2.3