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 #define VK_PROTOTYPES 22 #include "vkjson.h" 23 24 #include <utility> 25 26 namespace { 27 const char* kSupportedInstanceExtensions[] = { 28 "VK_KHR_get_physical_device_properties2"}; 29 30 bool EnumerateExtensions(const char* layer_name, 31 std::vector<VkExtensionProperties>* extensions) { 32 VkResult result; 33 uint32_t count = 0; 34 result = vkEnumerateInstanceExtensionProperties(layer_name, &count, nullptr); 35 if (result != VK_SUCCESS) 36 return false; 37 extensions->resize(count); 38 result = vkEnumerateInstanceExtensionProperties(layer_name, &count, 39 extensions->data()); 40 if (result != VK_SUCCESS) 41 return false; 42 return true; 43 } 44 45 bool HasExtension(const char* extension_name, 46 uint32_t count, 47 const char* const* extensions) { 48 return std::find_if(extensions, extensions + count, 49 [extension_name](const char* extension) { 50 return strcmp(extension, extension_name) == 0; 51 }) != extensions + count; 52 } 53 54 bool HasExtension(const char* extension_name, 55 const std::vector<VkExtensionProperties>& extensions) { 56 return std::find_if(extensions.cbegin(), extensions.cend(), 57 [extension_name](const VkExtensionProperties& extension) { 58 return strcmp(extension.extensionName, 59 extension_name) == 0; 60 }) != extensions.cend(); 61 } 62 } // anonymous namespace 63 64 VkJsonDevice VkJsonGetDevice(VkInstance instance, 65 VkPhysicalDevice physical_device, 66 uint32_t instance_extension_count, 67 const char* const* instance_extensions) { 68 VkJsonDevice device; 69 70 PFN_vkGetPhysicalDeviceFeatures2KHR vkpGetPhysicalDeviceFeatures2KHR = 71 nullptr; 72 if (instance != VK_NULL_HANDLE && 73 HasExtension("VK_KHR_get_physical_device_properties2", 74 instance_extension_count, instance_extensions)) { 75 vkpGetPhysicalDeviceFeatures2KHR = 76 reinterpret_cast<PFN_vkGetPhysicalDeviceFeatures2KHR>( 77 vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFeatures2KHR")); 78 } 79 80 // Only device extensions. 81 // TODO(piman): do we want to show layer extensions? 82 uint32_t extension_count = 0; 83 vkEnumerateDeviceExtensionProperties(physical_device, nullptr, 84 &extension_count, nullptr); 85 if (extension_count > 0) { 86 device.extensions.resize(extension_count); 87 vkEnumerateDeviceExtensionProperties( 88 physical_device, nullptr, &extension_count, device.extensions.data()); 89 } 90 91 uint32_t layer_count = 0; 92 vkEnumerateDeviceLayerProperties(physical_device, &layer_count, nullptr); 93 if (layer_count > 0) { 94 device.layers.resize(layer_count); 95 vkEnumerateDeviceLayerProperties(physical_device, &layer_count, 96 device.layers.data()); 97 } 98 99 vkGetPhysicalDeviceProperties(physical_device, &device.properties); 100 if (HasExtension("VK_KHR_get_physical_device_properties2", 101 instance_extension_count, instance_extensions)) { 102 VkPhysicalDeviceFeatures2KHR features = { 103 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR, 104 nullptr, 105 {} // features 106 }; 107 if (HasExtension("VK_KHR_variable_pointers", device.extensions)) { 108 device.variable_pointer_features.sType = 109 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR; 110 device.variable_pointer_features.pNext = features.pNext; 111 features.pNext = &device.variable_pointer_features; 112 } 113 vkpGetPhysicalDeviceFeatures2KHR(physical_device, &features); 114 device.features = features.features; 115 } else { 116 vkGetPhysicalDeviceFeatures(physical_device, &device.features); 117 } 118 vkGetPhysicalDeviceMemoryProperties(physical_device, &device.memory); 119 120 uint32_t queue_family_count = 0; 121 vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_family_count, 122 nullptr); 123 if (queue_family_count > 0) { 124 device.queues.resize(queue_family_count); 125 vkGetPhysicalDeviceQueueFamilyProperties( 126 physical_device, &queue_family_count, device.queues.data()); 127 } 128 129 VkFormatProperties format_properties = {}; 130 for (VkFormat format = VK_FORMAT_R4G4_UNORM_PACK8; 131 format <= VK_FORMAT_END_RANGE; 132 format = static_cast<VkFormat>(format + 1)) { 133 vkGetPhysicalDeviceFormatProperties(physical_device, format, 134 &format_properties); 135 if (format_properties.linearTilingFeatures || 136 format_properties.optimalTilingFeatures || 137 format_properties.bufferFeatures) { 138 device.formats.insert(std::make_pair(format, format_properties)); 139 } 140 } 141 return device; 142 } 143 144 VkJsonInstance VkJsonGetInstance() { 145 VkJsonInstance instance; 146 VkResult result; 147 uint32_t count; 148 149 count = 0; 150 result = vkEnumerateInstanceLayerProperties(&count, nullptr); 151 if (result != VK_SUCCESS) 152 return VkJsonInstance(); 153 if (count > 0) { 154 std::vector<VkLayerProperties> layers(count); 155 result = vkEnumerateInstanceLayerProperties(&count, layers.data()); 156 if (result != VK_SUCCESS) 157 return VkJsonInstance(); 158 instance.layers.reserve(count); 159 for (auto& layer : layers) { 160 instance.layers.push_back(VkJsonLayer{layer, std::vector<VkExtensionProperties>()}); 161 if (!EnumerateExtensions(layer.layerName, 162 &instance.layers.back().extensions)) 163 return VkJsonInstance(); 164 } 165 } 166 167 if (!EnumerateExtensions(nullptr, &instance.extensions)) 168 return VkJsonInstance(); 169 170 std::vector<const char*> instance_extensions; 171 for (const auto extension : kSupportedInstanceExtensions) { 172 if (HasExtension(extension, instance.extensions)) 173 instance_extensions.push_back(extension); 174 } 175 176 const VkApplicationInfo app_info = {VK_STRUCTURE_TYPE_APPLICATION_INFO, 177 nullptr, 178 "vkjson_info", 179 1, 180 "", 181 0, 182 VK_API_VERSION_1_0}; 183 VkInstanceCreateInfo instance_info = { 184 VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, 185 nullptr, 186 0, 187 &app_info, 188 0, 189 nullptr, 190 static_cast<uint32_t>(instance_extensions.size()), 191 instance_extensions.data()}; 192 VkInstance vkinstance; 193 result = vkCreateInstance(&instance_info, nullptr, &vkinstance); 194 if (result != VK_SUCCESS) 195 return VkJsonInstance(); 196 197 count = 0; 198 result = vkEnumeratePhysicalDevices(vkinstance, &count, nullptr); 199 if (result != VK_SUCCESS) { 200 vkDestroyInstance(vkinstance, nullptr); 201 return VkJsonInstance(); 202 } 203 std::vector<VkPhysicalDevice> devices(count, VK_NULL_HANDLE); 204 result = vkEnumeratePhysicalDevices(vkinstance, &count, devices.data()); 205 if (result != VK_SUCCESS) { 206 vkDestroyInstance(vkinstance, nullptr); 207 return VkJsonInstance(); 208 } 209 210 instance.devices.reserve(devices.size()); 211 for (auto device : devices) 212 instance.devices.emplace_back(VkJsonGetDevice(vkinstance, device, 213 instance_extensions.size(), 214 instance_extensions.data())); 215 216 vkDestroyInstance(vkinstance, nullptr); 217 return instance; 218 } 219