1/////////////////////////////////////////////////////////////////////////////// 2// 3// Copyright (c) 2015-2016 The Khronos Group Inc. 4// Copyright (c) 2015-2016 Valve Corporation 5// Copyright (c) 2015-2016 LunarG, Inc. 6// Copyright (c) 2015-2016 Google, Inc. 7// 8// Licensed under the Apache License, Version 2.0 (the "License"); 9// you may not use this file except in compliance with the License. 10// You may obtain a copy of the License at 11// 12// http://www.apache.org/licenses/LICENSE-2.0 13// 14// Unless required by applicable law or agreed to in writing, software 15// distributed under the License is distributed on an "AS IS" BASIS, 16// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17// See the License for the specific language governing permissions and 18// limitations under the License. 19/////////////////////////////////////////////////////////////////////////////// 20 21#ifndef VK_PROTOTYPES 22#define VK_PROTOTYPES 23#endif 24 25#include "vkjson.h" 26 27#include <assert.h> 28#include <stdio.h> 29#include <string.h> 30 31#include <iostream> 32#include <vector> 33 34const uint32_t unsignedNegOne = (uint32_t)(-1); 35 36struct Options { 37 bool instance = false; 38 uint32_t device_index = unsignedNegOne; 39 std::string device_name; 40 std::string output_file; 41}; 42 43bool ParseOptions(int argc, char* argv[], Options* options) { 44 for (int i = 1; i < argc; ++i) { 45 std::string arg(argv[i]); 46 if (arg == "--instance" || arg == "-i") { 47 options->instance = true; 48 } else if (arg == "--first" || arg == "-f") { 49 options->device_index = 0; 50 } else { 51 ++i; 52 if (i >= argc) { 53 std::cerr << "Missing parameter after: " << arg << std::endl; 54 return false; 55 } 56 std::string arg2(argv[i]); 57 if (arg == "--device-index" || arg == "-d") { 58 int result = sscanf(arg2.c_str(), "%u", &options->device_index); 59 if (result != 1) { 60 options->device_index = static_cast<uint32_t>(-1); 61 std::cerr << "Unable to parse index: " << arg2 << std::endl; 62 return false; 63 } 64 } else if (arg == "--device-name" || arg == "-n") { 65 options->device_name = arg2; 66 } else if (arg == "--output" || arg == "-o") { 67 options->output_file = arg2; 68 } else { 69 std::cerr << "Unknown argument: " << arg << std::endl; 70 return false; 71 } 72 } 73 } 74 if (options->instance && (options->device_index != unsignedNegOne || 75 !options->device_name.empty())) { 76 std::cerr << "Specifying a specific device is incompatible with dumping " 77 "the whole instance." << std::endl; 78 return false; 79 } 80 if (options->device_index != unsignedNegOne && !options->device_name.empty()) { 81 std::cerr << "Must specify only one of device index and device name." 82 << std::endl; 83 return false; 84 } 85 if (options->instance && options->output_file.empty()) { 86 std::cerr << "Must specify an output file when dumping the whole instance." 87 << std::endl; 88 return false; 89 } 90 if (!options->output_file.empty() && !options->instance && 91 options->device_index == unsignedNegOne && options->device_name.empty()) { 92 std::cerr << "Must specify instance, device index, or device name when " 93 "specifying " 94 "output file." << std::endl; 95 return false; 96 } 97 return true; 98} 99 100bool Dump(const VkJsonInstance& instance, const Options& options) { 101 const VkJsonDevice* out_device = nullptr; 102 if (options.device_index != unsignedNegOne) { 103 if (static_cast<uint32_t>(options.device_index) >= 104 instance.devices.size()) { 105 std::cerr << "Error: device " << options.device_index 106 << " requested but only " << instance.devices.size() 107 << " devices found." << std::endl; 108 return false; 109 } 110 out_device = &instance.devices[options.device_index]; 111 } else if (!options.device_name.empty()) { 112 for (const auto& device : instance.devices) { 113 if (device.properties.deviceName == options.device_name) { 114 out_device = &device; 115 } 116 } 117 if (!out_device) { 118 std::cerr << "Error: device '" << options.device_name 119 << "' requested but not found." << std::endl; 120 return false; 121 } 122 } 123 124 std::string output_file; 125 if (options.output_file.empty()) { 126 assert(out_device); 127#if defined(ANDROID) 128 output_file.assign("/sdcard/Android/" + std::string(out_device->properties.deviceName)); 129#else 130 output_file.assign(out_device->properties.deviceName); 131#endif 132 output_file.append(".json"); 133 } else { 134 output_file = options.output_file; 135 } 136 FILE* file = nullptr; 137 if (output_file == "-") { 138 file = stdout; 139 } else { 140 file = fopen(output_file.c_str(), "w"); 141 if (!file) { 142 std::cerr << "Unable to open file " << output_file << "." << std::endl; 143 return false; 144 } 145 } 146 147 std::string json = out_device ? VkJsonDeviceToJson(*out_device) 148 : VkJsonInstanceToJson(instance); 149 fwrite(json.data(), 1, json.size(), file); 150 fputc('\n', file); 151 152 if (output_file != "-") { 153 fclose(file); 154 std::cout << "Wrote file " << output_file; 155 if (out_device) 156 std::cout << " for device " << out_device->properties.deviceName; 157 std::cout << "." << std::endl; 158 } 159 return true; 160} 161 162int main(int argc, char* argv[]) { 163#if defined(ANDROID) 164 int vulkanSupport = InitVulkan(); 165 if (vulkanSupport == 0) 166 return 1; 167#endif 168 Options options; 169 if (!ParseOptions(argc, argv, &options)) 170 return 1; 171 172 VkJsonInstance instance = VkJsonGetInstance(); 173 if (options.instance || options.device_index != unsignedNegOne || 174 !options.device_name.empty()) { 175 Dump(instance, options); 176 } else { 177 for (uint32_t i = 0, n = static_cast<uint32_t>(instance.devices.size()); i < n; i++) { 178 options.device_index = i; 179 Dump(instance, options); 180 } 181 } 182 183 return 0; 184} 185