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