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 <algorithm> 28 #include <utility> 29 30 namespace { 31 const char* kSupportedInstanceExtensions[] = { 32 "VK_KHR_get_physical_device_properties2"}; 33 34 bool EnumerateExtensions(const char* layer_name, 35 std::vector<VkExtensionProperties>* extensions) { 36 VkResult result; 37 uint32_t count = 0; 38 result = vkEnumerateInstanceExtensionProperties(layer_name, &count, nullptr); 39 if (result != VK_SUCCESS) 40 return false; 41 extensions->resize(count); 42 result = vkEnumerateInstanceExtensionProperties(layer_name, &count, 43 extensions->data()); 44 if (result != VK_SUCCESS) 45 return false; 46 return true; 47 } 48 49 bool HasExtension(const char* extension_name, 50 uint32_t count, 51 const char* const* extensions) { 52 return std::find_if(extensions, extensions + count, 53 [extension_name](const char* extension) { 54 return strcmp(extension, extension_name) == 0; 55 }) != extensions + count; 56 } 57 58 bool HasExtension(const char* extension_name, 59 const std::vector<VkExtensionProperties>& extensions) { 60 return std::find_if(extensions.cbegin(), extensions.cend(), 61 [extension_name](const VkExtensionProperties& extension) { 62 return strcmp(extension.extensionName, 63 extension_name) == 0; 64 }) != extensions.cend(); 65 } 66 } // anonymous namespace 67 68 VkJsonDevice VkJsonGetDevice(VkInstance instance, 69 VkPhysicalDevice physical_device, 70 uint32_t instance_extension_count, 71 const char* const* instance_extensions) { 72 VkJsonDevice device; 73 74 PFN_vkGetPhysicalDeviceProperties2KHR vkpGetPhysicalDeviceProperties2KHR = 75 nullptr; 76 PFN_vkGetPhysicalDeviceFeatures2KHR vkpGetPhysicalDeviceFeatures2KHR = 77 nullptr; 78 if (instance != VK_NULL_HANDLE && 79 HasExtension("VK_KHR_get_physical_device_properties2", 80 instance_extension_count, instance_extensions)) { 81 vkpGetPhysicalDeviceProperties2KHR = 82 reinterpret_cast<PFN_vkGetPhysicalDeviceProperties2KHR>( 83 vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties2KHR")); 84 vkpGetPhysicalDeviceFeatures2KHR = 85 reinterpret_cast<PFN_vkGetPhysicalDeviceFeatures2KHR>( 86 vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFeatures2KHR")); 87 } 88 89 uint32_t extension_count = 0; 90 vkEnumerateDeviceExtensionProperties(physical_device, nullptr, 91 &extension_count, nullptr); 92 if (extension_count > 0) { 93 device.extensions.resize(extension_count); 94 vkEnumerateDeviceExtensionProperties( 95 physical_device, nullptr, &extension_count, device.extensions.data()); 96 } 97 98 uint32_t layer_count = 0; 99 vkEnumerateDeviceLayerProperties(physical_device, &layer_count, nullptr); 100 if (layer_count > 0) { 101 device.layers.resize(layer_count); 102 vkEnumerateDeviceLayerProperties(physical_device, &layer_count, 103 device.layers.data()); 104 } 105 106 if (HasExtension("VK_KHR_get_physical_device_properties2", 107 instance_extension_count, instance_extensions)) { 108 VkPhysicalDeviceProperties2KHR properties = { 109 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR, 110 nullptr, 111 {} // properties 112 }; 113 if (HasExtension("VK_KHR_driver_properties", device.extensions)) { 114 device.ext_driver_properties.reported = true; 115 device.ext_driver_properties.driver_properties_khr.sType = 116 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR; 117 device.ext_driver_properties.driver_properties_khr.pNext = 118 properties.pNext; 119 properties.pNext = 120 &device.ext_driver_properties.driver_properties_khr; 121 } 122 vkpGetPhysicalDeviceProperties2KHR(physical_device, &properties); 123 device.properties = properties.properties; 124 125 VkPhysicalDeviceFeatures2KHR features = { 126 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR, 127 nullptr, 128 {} // features 129 }; 130 if (HasExtension("VK_KHR_variable_pointers", device.extensions)) { 131 device.ext_variable_pointer_features.reported = true; 132 device.ext_variable_pointer_features.variable_pointer_features_khr.sType = 133 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR; 134 device.ext_variable_pointer_features.variable_pointer_features_khr.pNext = 135 features.pNext; 136 features.pNext = 137 &device.ext_variable_pointer_features.variable_pointer_features_khr; 138 } 139 vkpGetPhysicalDeviceFeatures2KHR(physical_device, &features); 140 device.features = features.features; 141 } else { 142 vkGetPhysicalDeviceProperties(physical_device, &device.properties); 143 vkGetPhysicalDeviceFeatures(physical_device, &device.features); 144 } 145 vkGetPhysicalDeviceMemoryProperties(physical_device, &device.memory); 146 147 uint32_t queue_family_count = 0; 148 vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_family_count, 149 nullptr); 150 if (queue_family_count > 0) { 151 device.queues.resize(queue_family_count); 152 vkGetPhysicalDeviceQueueFamilyProperties( 153 physical_device, &queue_family_count, device.queues.data()); 154 } 155 156 VkFormatProperties format_properties = {}; 157 for (VkFormat format = VK_FORMAT_R4G4_UNORM_PACK8; 158 format <= VK_FORMAT_END_RANGE; 159 format = static_cast<VkFormat>(format + 1)) { 160 vkGetPhysicalDeviceFormatProperties(physical_device, format, 161 &format_properties); 162 if (format_properties.linearTilingFeatures || 163 format_properties.optimalTilingFeatures || 164 format_properties.bufferFeatures) { 165 device.formats.insert(std::make_pair(format, format_properties)); 166 } 167 } 168 169 if (device.properties.apiVersion >= VK_API_VERSION_1_1) { 170 for (VkFormat format = VK_FORMAT_G8B8G8R8_422_UNORM; 171 format <= VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM; 172 format = static_cast<VkFormat>(format + 1)) { 173 vkGetPhysicalDeviceFormatProperties(physical_device, format, 174 &format_properties); 175 if (format_properties.linearTilingFeatures || 176 format_properties.optimalTilingFeatures || 177 format_properties.bufferFeatures) { 178 device.formats.insert(std::make_pair(format, format_properties)); 179 } 180 } 181 182 PFN_vkGetPhysicalDeviceProperties2 vkpGetPhysicalDeviceProperties2 = 183 reinterpret_cast<PFN_vkGetPhysicalDeviceProperties2>( 184 vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties2")); 185 if (vkpGetPhysicalDeviceProperties2) { 186 VkPhysicalDeviceProperties2 properties2 = { 187 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, nullptr, {}}; 188 189 device.subgroup_properties.sType = 190 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES; 191 device.subgroup_properties.pNext = properties2.pNext; 192 properties2.pNext = &device.subgroup_properties; 193 194 device.point_clipping_properties.sType = 195 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES; 196 device.point_clipping_properties.pNext = properties2.pNext; 197 properties2.pNext = &device.point_clipping_properties; 198 199 device.multiview_properties.sType = 200 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES; 201 device.multiview_properties.pNext = properties2.pNext; 202 properties2.pNext = &device.multiview_properties; 203 204 device.id_properties.sType = 205 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES; 206 device.id_properties.pNext = properties2.pNext; 207 properties2.pNext = &device.id_properties; 208 209 device.maintenance3_properties.sType = 210 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES; 211 device.maintenance3_properties.pNext = properties2.pNext; 212 properties2.pNext = &device.maintenance3_properties; 213 214 (*vkpGetPhysicalDeviceProperties2)(physical_device, &properties2); 215 } 216 217 PFN_vkGetPhysicalDeviceFeatures2 vkpGetPhysicalDeviceFeatures2 = 218 reinterpret_cast<PFN_vkGetPhysicalDeviceFeatures2>( 219 vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFeatures2")); 220 if (vkpGetPhysicalDeviceFeatures2) { 221 VkPhysicalDeviceFeatures2 features2 = { 222 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, nullptr, {}}; 223 224 device.bit16_storage_features.sType = 225 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES; 226 device.bit16_storage_features.pNext = features2.pNext; 227 features2.pNext = &device.bit16_storage_features; 228 229 device.multiview_features.sType = 230 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES; 231 device.multiview_features.pNext = features2.pNext; 232 features2.pNext = &device.multiview_features; 233 234 device.variable_pointer_features.sType = 235 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES; 236 device.variable_pointer_features.pNext = features2.pNext; 237 features2.pNext = &device.variable_pointer_features; 238 239 device.protected_memory_features.sType = 240 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES; 241 device.protected_memory_features.pNext = features2.pNext; 242 features2.pNext = &device.protected_memory_features; 243 244 device.sampler_ycbcr_conversion_features.sType = 245 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES; 246 device.sampler_ycbcr_conversion_features.pNext = features2.pNext; 247 features2.pNext = &device.sampler_ycbcr_conversion_features; 248 249 device.shader_draw_parameter_features.sType = 250 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES; 251 device.shader_draw_parameter_features.pNext = features2.pNext; 252 features2.pNext = &device.shader_draw_parameter_features; 253 254 (*vkpGetPhysicalDeviceFeatures2)(physical_device, &features2); 255 } 256 257 PFN_vkGetPhysicalDeviceExternalFenceProperties 258 vkpGetPhysicalDeviceExternalFenceProperties = 259 reinterpret_cast<PFN_vkGetPhysicalDeviceExternalFenceProperties>( 260 vkGetInstanceProcAddr( 261 instance, "vkGetPhysicalDeviceExternalFenceProperties")); 262 if (vkpGetPhysicalDeviceExternalFenceProperties) { 263 VkPhysicalDeviceExternalFenceInfo external_fence_info = { 264 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO, nullptr, 265 VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT}; 266 VkExternalFenceProperties external_fence_properties = {}; 267 268 for (VkExternalFenceHandleTypeFlagBits handle_type = 269 VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT; 270 handle_type <= VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT; 271 handle_type = static_cast<VkExternalFenceHandleTypeFlagBits>( 272 handle_type << 1)) { 273 external_fence_info.handleType = handle_type; 274 (*vkpGetPhysicalDeviceExternalFenceProperties)( 275 physical_device, &external_fence_info, &external_fence_properties); 276 if (external_fence_properties.exportFromImportedHandleTypes || 277 external_fence_properties.compatibleHandleTypes || 278 external_fence_properties.externalFenceFeatures) { 279 device.external_fence_properties.insert( 280 std::make_pair(handle_type, external_fence_properties)); 281 } 282 } 283 } 284 285 PFN_vkGetPhysicalDeviceExternalSemaphoreProperties 286 vkpGetPhysicalDeviceExternalSemaphoreProperties = reinterpret_cast< 287 PFN_vkGetPhysicalDeviceExternalSemaphoreProperties>( 288 vkGetInstanceProcAddr( 289 instance, "vkGetPhysicalDeviceExternalSemaphoreProperties")); 290 if (vkpGetPhysicalDeviceExternalSemaphoreProperties) { 291 VkPhysicalDeviceExternalSemaphoreInfo external_semaphore_info = { 292 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO, nullptr, 293 VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT}; 294 VkExternalSemaphoreProperties external_semaphore_properties = {}; 295 296 for (VkExternalSemaphoreHandleTypeFlagBits handle_type = 297 VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT; 298 handle_type <= VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT; 299 handle_type = static_cast<VkExternalSemaphoreHandleTypeFlagBits>( 300 handle_type << 1)) { 301 external_semaphore_info.handleType = handle_type; 302 (*vkpGetPhysicalDeviceExternalSemaphoreProperties)( 303 physical_device, &external_semaphore_info, 304 &external_semaphore_properties); 305 if (external_semaphore_properties.exportFromImportedHandleTypes || 306 external_semaphore_properties.compatibleHandleTypes || 307 external_semaphore_properties.externalSemaphoreFeatures) { 308 device.external_semaphore_properties.insert( 309 std::make_pair(handle_type, external_semaphore_properties)); 310 } 311 } 312 } 313 } 314 315 return device; 316 } 317 318 VkJsonInstance VkJsonGetInstance() { 319 VkJsonInstance instance; 320 VkResult result; 321 uint32_t count; 322 323 count = 0; 324 result = vkEnumerateInstanceLayerProperties(&count, nullptr); 325 if (result != VK_SUCCESS) 326 return VkJsonInstance(); 327 if (count > 0) { 328 std::vector<VkLayerProperties> layers(count); 329 result = vkEnumerateInstanceLayerProperties(&count, layers.data()); 330 if (result != VK_SUCCESS) 331 return VkJsonInstance(); 332 instance.layers.reserve(count); 333 for (auto& layer : layers) { 334 instance.layers.push_back(VkJsonLayer{layer, std::vector<VkExtensionProperties>()}); 335 if (!EnumerateExtensions(layer.layerName, 336 &instance.layers.back().extensions)) 337 return VkJsonInstance(); 338 } 339 } 340 341 if (!EnumerateExtensions(nullptr, &instance.extensions)) 342 return VkJsonInstance(); 343 344 std::vector<const char*> instance_extensions; 345 for (const auto extension : kSupportedInstanceExtensions) { 346 if (HasExtension(extension, instance.extensions)) 347 instance_extensions.push_back(extension); 348 } 349 350 const VkApplicationInfo app_info = {VK_STRUCTURE_TYPE_APPLICATION_INFO, 351 nullptr, 352 "vkjson_info", 353 1, 354 "", 355 0, 356 VK_API_VERSION_1_1}; 357 VkInstanceCreateInfo instance_info = { 358 VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, 359 nullptr, 360 0, 361 &app_info, 362 0, 363 nullptr, 364 static_cast<uint32_t>(instance_extensions.size()), 365 instance_extensions.data()}; 366 VkInstance vkinstance; 367 result = vkCreateInstance(&instance_info, nullptr, &vkinstance); 368 if (result != VK_SUCCESS) 369 return VkJsonInstance(); 370 371 count = 0; 372 result = vkEnumeratePhysicalDevices(vkinstance, &count, nullptr); 373 if (result != VK_SUCCESS) { 374 vkDestroyInstance(vkinstance, nullptr); 375 return VkJsonInstance(); 376 } 377 378 std::vector<VkPhysicalDevice> devices(count, VK_NULL_HANDLE); 379 result = vkEnumeratePhysicalDevices(vkinstance, &count, devices.data()); 380 if (result != VK_SUCCESS) { 381 vkDestroyInstance(vkinstance, nullptr); 382 return VkJsonInstance(); 383 } 384 385 std::map<VkPhysicalDevice, uint32_t> device_map; 386 const uint32_t sz = devices.size(); 387 instance.devices.reserve(sz); 388 for (uint32_t i = 0; i < sz; ++i) { 389 device_map.insert(std::make_pair(devices[i], i)); 390 instance.devices.emplace_back(VkJsonGetDevice(vkinstance, devices[i], 391 instance_extensions.size(), 392 instance_extensions.data())); 393 } 394 395 PFN_vkEnumerateInstanceVersion vkpEnumerateInstanceVersion = 396 reinterpret_cast<PFN_vkEnumerateInstanceVersion>( 397 vkGetInstanceProcAddr(nullptr, "vkEnumerateInstanceVersion")); 398 if (!vkpEnumerateInstanceVersion) { 399 instance.api_version = VK_API_VERSION_1_0; 400 } else { 401 result = (*vkpEnumerateInstanceVersion)(&instance.api_version); 402 if (result != VK_SUCCESS) { 403 vkDestroyInstance(vkinstance, nullptr); 404 return VkJsonInstance(); 405 } 406 } 407 408 PFN_vkEnumeratePhysicalDeviceGroups vkpEnumeratePhysicalDeviceGroups = 409 reinterpret_cast<PFN_vkEnumeratePhysicalDeviceGroups>( 410 vkGetInstanceProcAddr(vkinstance, "vkEnumeratePhysicalDeviceGroups")); 411 if (vkpEnumeratePhysicalDeviceGroups) { 412 count = 0; 413 result = (*vkpEnumeratePhysicalDeviceGroups)(vkinstance, &count, nullptr); 414 if (result != VK_SUCCESS) { 415 vkDestroyInstance(vkinstance, nullptr); 416 return VkJsonInstance(); 417 } 418 419 VkJsonDeviceGroup device_group; 420 std::vector<VkPhysicalDeviceGroupProperties> group_properties; 421 group_properties.resize(count); 422 result = (*vkpEnumeratePhysicalDeviceGroups)(vkinstance, &count, 423 group_properties.data()); 424 if (result != VK_SUCCESS) { 425 vkDestroyInstance(vkinstance, nullptr); 426 return VkJsonInstance(); 427 } 428 for (auto properties : group_properties) { 429 device_group.properties = properties; 430 for (uint32_t i = 0; i < properties.physicalDeviceCount; ++i) { 431 device_group.device_inds.push_back( 432 device_map[properties.physicalDevices[i]]); 433 } 434 instance.device_groups.push_back(device_group); 435 } 436 } 437 438 vkDestroyInstance(vkinstance, nullptr); 439 return instance; 440 } 441