blob: db0450d2c231362e505e13404cf12d890694047d [file] [log] [blame]
Yiwei Zhangf9a57e62018-04-05 00:17:22 -07001///////////////////////////////////////////////////////////////////////////////
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
30namespace {
31const char* kSupportedInstanceExtensions[] = {
32 "VK_KHR_get_physical_device_properties2"};
33
34bool 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
49bool 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
58bool 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
68VkJsonDevice 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
295VkJsonInstance 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}