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
26namespace {
27bool 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
44VkJsonDevice 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
93VkJsonInstance 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