blob: 4d7fc11d6bb7b7f4746c81f2a26997594a85b720 [file] [log] [blame]
jvanverthd2497f32016-03-18 12:39:05 -07001/*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "vk/GrVkExtensions.h"
Greg Daniel98bffae2018-08-01 13:25:41 -04009
10// Can remove this once we get rid of the extension flags.
11#include "vk/GrVkBackendContext.h"
jvanverthd2497f32016-03-18 12:39:05 -070012
13#include "SkTSearch.h"
14#include "SkTSort.h"
15
Greg Daniela31f4e52018-08-01 16:48:52 -040016// finds the index of ext in infos or a negative result if ext is not found.
17static int find_info(const SkTArray<GrVkExtensions::Info>& infos, const char ext[]) {
18 if (infos.empty()) {
jvanverthd2497f32016-03-18 12:39:05 -070019 return -1;
20 }
21 SkString extensionStr(ext);
Greg Daniela31f4e52018-08-01 16:48:52 -040022 GrVkExtensions::Info::Less less;
23 int idx = SkTSearch<GrVkExtensions::Info, SkString, GrVkExtensions::Info::Less>(
24 &infos.front(), infos.count(), extensionStr, sizeof(GrVkExtensions::Info),
25 less);
jvanverthd2497f32016-03-18 12:39:05 -070026 return idx;
27}
28
Greg Daniela31f4e52018-08-01 16:48:52 -040029namespace { // This cannot be static because it is used as a template parameter.
30inline bool extension_compare(const GrVkExtensions::Info& a, const GrVkExtensions::Info& b) {
31 return strcmp(a.fName.c_str(), b.fName.c_str()) < 0;
32}
33}
34
35void GrVkExtensions::init(GrVkGetProc getProc,
36 VkInstance instance,
37 VkPhysicalDevice physDev,
38 uint32_t instanceExtensionCount,
Greg Daniel98bffae2018-08-01 13:25:41 -040039 const char* const* instanceExtensions,
40 uint32_t deviceExtensionCount,
41 const char* const* deviceExtensions) {
Greg Daniela31f4e52018-08-01 16:48:52 -040042 SkTLessFunctionToFunctorAdaptor<GrVkExtensions::Info, extension_compare> cmp;
jvanverthd2497f32016-03-18 12:39:05 -070043
Greg Daniel98bffae2018-08-01 13:25:41 -040044 for (uint32_t i = 0; i < instanceExtensionCount; ++i) {
45 const char* extension = instanceExtensions[i];
46 // if not already in the list, add it
Greg Daniela31f4e52018-08-01 16:48:52 -040047 if (find_info(fExtensions, extension) < 0) {
48 fExtensions.push_back() = Info(extension);
49 SkTQSort(&fExtensions.front(), &fExtensions.back(), cmp);
jvanverth633b3562016-03-23 11:01:22 -070050 }
51 }
Greg Daniel98bffae2018-08-01 13:25:41 -040052 for (uint32_t i = 0; i < deviceExtensionCount; ++i) {
53 const char* extension = deviceExtensions[i];
54 // if not already in the list, add it
Greg Daniela31f4e52018-08-01 16:48:52 -040055 if (find_info(fExtensions, extension) < 0) {
56 fExtensions.push_back() = Info(extension);
57 SkTQSort(&fExtensions.front(), &fExtensions.back(), cmp);
Greg Danieldc13c212018-06-28 23:29:35 +000058 }
Greg Danieldc13c212018-06-28 23:29:35 +000059 }
Greg Daniela31f4e52018-08-01 16:48:52 -040060 this->getSpecVersions(getProc, instance, physDev);
jvanverthfd7bd452016-03-25 06:29:52 -070061}
62
Greg Daniela31f4e52018-08-01 16:48:52 -040063#define GET_PROC(F, inst) \
64 PFN_vk##F grVk##F = (PFN_vk ## F) getProc("vk" #F, inst, VK_NULL_HANDLE)
65
66void GrVkExtensions::getSpecVersions(GrVkGetProc getProc, VkInstance instance,
67 VkPhysicalDevice physDevice) {
68 // We grab all the extensions for the VkInstance and VkDevice so we can look up what spec
69 // version each of the supported extensions are. We do not grab the extensions for layers
70 // because we don't know what layers the client has enabled and in general we don't do anything
71 // special for those extensions.
72
73 if (instance == VK_NULL_HANDLE) {
74 return;
75 }
76 GET_PROC(EnumerateInstanceExtensionProperties, VK_NULL_HANDLE);
77 SkASSERT(grVkEnumerateInstanceExtensionProperties);
78
79 VkResult res;
80 // instance extensions
81 uint32_t extensionCount = 0;
82 res = grVkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
83 if (VK_SUCCESS != res) {
84 return;
85 }
86 VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
87 res = grVkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions);
88 if (VK_SUCCESS != res) {
89 delete[] extensions;
90 return;
91 }
92 for (uint32_t i = 0; i < extensionCount; ++i) {
93 int idx = find_info(fExtensions, extensions[i].extensionName);
94 if (idx >= 0) {
95 fExtensions[idx].fSpecVersion = extensions[i].specVersion;
96 }
97 }
98 delete[] extensions;
99
100 if (physDevice == VK_NULL_HANDLE) {
101 return;
102 }
103 GET_PROC(EnumerateDeviceExtensionProperties, instance);
104 SkASSERT(grVkEnumerateDeviceExtensionProperties);
105
106 // device extensions
107 extensionCount = 0;
108 res = grVkEnumerateDeviceExtensionProperties(physDevice, nullptr, &extensionCount, nullptr);
109 if (VK_SUCCESS != res) {
110 return;
111 }
112 extensions = new VkExtensionProperties[extensionCount];
113 res = grVkEnumerateDeviceExtensionProperties(physDevice, nullptr, &extensionCount, extensions);
114 if (VK_SUCCESS != res) {
115 delete[] extensions;
116 return;
117 }
118 for (uint32_t i = 0; i < extensionCount; ++i) {
119 int idx = find_info(fExtensions, extensions[i].extensionName);
120 if (idx >= 0) {
121 fExtensions[idx].fSpecVersion = extensions[i].specVersion;
122 }
123 }
124 delete[] extensions;
125}
126
127bool GrVkExtensions::hasExtension(const char ext[], uint32_t minVersion) const {
128 int idx = find_info(fExtensions, ext);
129 return idx >= 0 && fExtensions[idx].fSpecVersion >= minVersion;
jvanverthd2497f32016-03-18 12:39:05 -0700130}
131