Home | History | Annotate | Download | only in vkjson
      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