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 {
EnumerateExtensions(const char * layer_name,std::vector<VkExtensionProperties> * extensions)27 bool EnumerateExtensions(const char* layer_name,
28                          std::vector<VkExtensionProperties>* extensions) {
29   VkResult result;
30   uint32_t count = 0;
31   result = vkEnumerateInstanceExtensionProperties(layer_name, &count, nullptr);
32   if (result != VK_SUCCESS)
33     return false;
34   extensions->resize(count);
35   result = vkEnumerateInstanceExtensionProperties(layer_name, &count,
36                                                   extensions->data());
37   if (result != VK_SUCCESS)
38     return false;
39   return true;
40 }
41 
42 }  // anonymous namespace
43 
VkJsonGetDevice(VkPhysicalDevice physical_device)44 VkJsonDevice VkJsonGetDevice(VkPhysicalDevice physical_device) {
45   VkJsonDevice device;
46   vkGetPhysicalDeviceProperties(physical_device, &device.properties);
47   vkGetPhysicalDeviceFeatures(physical_device, &device.features);
48   vkGetPhysicalDeviceMemoryProperties(physical_device, &device.memory);
49 
50   uint32_t queue_family_count = 0;
51   vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_family_count,
52                                            nullptr);
53   if (queue_family_count > 0) {
54     device.queues.resize(queue_family_count);
55     vkGetPhysicalDeviceQueueFamilyProperties(
56         physical_device, &queue_family_count, device.queues.data());
57   }
58 
59   // Only device extensions.
60   // TODO(piman): do we want to show layer extensions?
61   uint32_t extension_count = 0;
62   vkEnumerateDeviceExtensionProperties(physical_device, nullptr,
63                                        &extension_count, nullptr);
64   if (extension_count > 0) {
65     device.extensions.resize(extension_count);
66     vkEnumerateDeviceExtensionProperties(
67         physical_device, nullptr, &extension_count, device.extensions.data());
68   }
69 
70   uint32_t layer_count = 0;
71   vkEnumerateDeviceLayerProperties(physical_device, &layer_count, nullptr);
72   if (layer_count > 0) {
73     device.layers.resize(layer_count);
74     vkEnumerateDeviceLayerProperties(physical_device, &layer_count,
75                                      device.layers.data());
76   }
77 
78   VkFormatProperties format_properties = {};
79   for (VkFormat format = VK_FORMAT_R4G4_UNORM_PACK8;
80        format <= VK_FORMAT_END_RANGE;
81        format = static_cast<VkFormat>(format + 1)) {
82     vkGetPhysicalDeviceFormatProperties(physical_device, format,
83                                         &format_properties);
84     if (format_properties.linearTilingFeatures ||
85         format_properties.optimalTilingFeatures ||
86         format_properties.bufferFeatures) {
87       device.formats.insert(std::make_pair(format, format_properties));
88     }
89   }
90   return device;
91 }
92 
VkJsonGetInstance()93 VkJsonInstance VkJsonGetInstance() {
94   VkJsonInstance instance;
95   VkResult result;
96   uint32_t count;
97 
98   count = 0;
99   result = vkEnumerateInstanceLayerProperties(&count, nullptr);
100   if (result != VK_SUCCESS)
101     return VkJsonInstance();
102   if (count > 0) {
103     std::vector<VkLayerProperties> layers(count);
104     result = vkEnumerateInstanceLayerProperties(&count, layers.data());
105     if (result != VK_SUCCESS)
106       return VkJsonInstance();
107     instance.layers.reserve(count);
108     for (auto& layer : layers) {
109       instance.layers.push_back(VkJsonLayer{layer, std::vector<VkExtensionProperties>()});
110       if (!EnumerateExtensions(layer.layerName,
111                                &instance.layers.back().extensions))
112         return VkJsonInstance();
113     }
114   }
115 
116   if (!EnumerateExtensions(nullptr, &instance.extensions))
117     return VkJsonInstance();
118 
119   const VkApplicationInfo app_info = {VK_STRUCTURE_TYPE_APPLICATION_INFO,
120                                       nullptr,
121                                       "vkjson_info",
122                                       1,
123                                       "",
124                                       0,
125                                       VK_API_VERSION_1_0};
126   VkInstanceCreateInfo instance_info = {
127       VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
128       nullptr,
129       0,
130       &app_info,
131       0,
132       nullptr,
133       0,
134       nullptr};
135   VkInstance vkinstance;
136   result = vkCreateInstance(&instance_info, nullptr, &vkinstance);
137   if (result != VK_SUCCESS)
138     return VkJsonInstance();
139 
140   count = 0;
141   result = vkEnumeratePhysicalDevices(vkinstance, &count, nullptr);
142   if (result != VK_SUCCESS) {
143     vkDestroyInstance(vkinstance, nullptr);
144     return VkJsonInstance();
145   }
146   std::vector<VkPhysicalDevice> devices(count, VK_NULL_HANDLE);
147   result = vkEnumeratePhysicalDevices(vkinstance, &count, devices.data());
148   if (result != VK_SUCCESS) {
149     vkDestroyInstance(vkinstance, nullptr);
150     return VkJsonInstance();
151   }
152 
153   instance.devices.reserve(devices.size());
154   for (auto device : devices)
155     instance.devices.emplace_back(VkJsonGetDevice(device));
156 
157   vkDestroyInstance(vkinstance, nullptr);
158   return instance;
159 }
160