1 /*
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"
9 #include "vk/GrVkUtil.h"
10
11 #include "SkTSearch.h"
12 #include "SkTSort.h"
13
14 namespace { // This cannot be static because it is used as a template parameter.
extension_compare(const SkString & a,const SkString & b)15 inline bool extension_compare(const SkString& a, const SkString& b) {
16 return strcmp(a.c_str(), b.c_str()) < 0;
17 }
18 }
19
20 // finds the index of ext in strings or a negative result if ext is not found.
find_string(const SkTArray<SkString> & strings,const char ext[])21 static int find_string(const SkTArray<SkString>& strings, const char ext[]) {
22 if (strings.empty()) {
23 return -1;
24 }
25 SkString extensionStr(ext);
26 int idx = SkTSearch<SkString, extension_compare>(&strings.front(),
27 strings.count(),
28 extensionStr,
29 sizeof(SkString));
30 return idx;
31 }
32
33 #define GET_PROC_LOCAL(F, inst, device) PFN_vk ## F F = (PFN_vk ## F) fGetProc("vk" #F, inst, device)
34
remove_patch_version(uint32_t specVersion)35 static uint32_t remove_patch_version(uint32_t specVersion) {
36 return (specVersion >> 12) << 12;
37 }
38
initInstance(uint32_t specVersion)39 bool GrVkExtensions::initInstance(uint32_t specVersion) {
40 if (fGetProc == nullptr) {
41 return false;
42 }
43
44 uint32_t nonPatchVersion = remove_patch_version(specVersion);
45
46 GET_PROC_LOCAL(EnumerateInstanceExtensionProperties, VK_NULL_HANDLE, VK_NULL_HANDLE);
47 GET_PROC_LOCAL(EnumerateInstanceLayerProperties, VK_NULL_HANDLE, VK_NULL_HANDLE);
48
49 SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp;
50
51 if (!EnumerateInstanceExtensionProperties ||
52 !EnumerateInstanceLayerProperties) {
53 return false;
54 }
55
56 // instance layers
57 uint32_t layerCount = 0;
58 VkResult res = EnumerateInstanceLayerProperties(&layerCount, nullptr);
59 if (VK_SUCCESS != res) {
60 return false;
61 }
62 VkLayerProperties* layers = new VkLayerProperties[layerCount];
63 res = EnumerateInstanceLayerProperties(&layerCount, layers);
64 if (VK_SUCCESS != res) {
65 delete[] layers;
66 return false;
67 }
68 for (uint32_t i = 0; i < layerCount; ++i) {
69 if (nonPatchVersion >= remove_patch_version(layers[i].specVersion)) {
70 fInstanceLayerStrings->push_back() = layers[i].layerName;
71 }
72 }
73 delete[] layers;
74 if (!fInstanceLayerStrings->empty()) {
75 SkTQSort(&fInstanceLayerStrings->front(), &fInstanceLayerStrings->back(), cmp);
76 }
77
78 // instance extensions
79 // via Vulkan implementation and implicitly enabled layers
80 uint32_t extensionCount = 0;
81 res = EnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
82 if (VK_SUCCESS != res) {
83 return false;
84 }
85 VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
86 res = EnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions);
87 if (VK_SUCCESS != res) {
88 delete[] extensions;
89 return false;
90 }
91 for (uint32_t i = 0; i < extensionCount; ++i) {
92 if (nonPatchVersion >= remove_patch_version(extensions[i].specVersion)) {
93 fInstanceExtensionStrings->push_back() = extensions[i].extensionName;
94 }
95 }
96 delete [] extensions;
97 // sort so we can search
98 if (!fInstanceExtensionStrings->empty()) {
99 SkTQSort(&fInstanceExtensionStrings->front(), &fInstanceExtensionStrings->back(), cmp);
100 }
101 // via explicitly enabled layers
102 layerCount = fInstanceLayerStrings->count();
103 for (uint32_t layerIndex = 0; layerIndex < layerCount; ++layerIndex) {
104 uint32_t extensionCount = 0;
105 res = EnumerateInstanceExtensionProperties((*fInstanceLayerStrings)[layerIndex].c_str(),
106 &extensionCount, nullptr);
107 if (VK_SUCCESS != res) {
108 return false;
109 }
110 VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
111 res = EnumerateInstanceExtensionProperties((*fInstanceLayerStrings)[layerIndex].c_str(),
112 &extensionCount, extensions);
113 if (VK_SUCCESS != res) {
114 delete[] extensions;
115 return false;
116 }
117 for (uint32_t i = 0; i < extensionCount; ++i) {
118 // if not already in the list, add it
119 if (nonPatchVersion >= remove_patch_version(extensions[i].specVersion) &&
120 find_string(*fInstanceExtensionStrings, extensions[i].extensionName) < 0) {
121 fInstanceExtensionStrings->push_back() = extensions[i].extensionName;
122 SkTQSort(&fInstanceExtensionStrings->front(), &fInstanceExtensionStrings->back(),
123 cmp);
124 }
125 }
126 delete[] extensions;
127 }
128
129 return true;
130 }
131
initDevice(uint32_t specVersion,VkInstance inst,VkPhysicalDevice physDev)132 bool GrVkExtensions::initDevice(uint32_t specVersion, VkInstance inst, VkPhysicalDevice physDev) {
133 if (fGetProc == nullptr) {
134 return false;
135 }
136
137 uint32_t nonPatchVersion = remove_patch_version(specVersion);
138
139 GET_PROC_LOCAL(EnumerateDeviceExtensionProperties, inst, VK_NULL_HANDLE);
140 GET_PROC_LOCAL(EnumerateDeviceLayerProperties, inst, VK_NULL_HANDLE);
141
142 SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp;
143
144 if (!EnumerateDeviceExtensionProperties ||
145 !EnumerateDeviceLayerProperties) {
146 return false;
147 }
148
149 // device layers
150 uint32_t layerCount = 0;
151 VkResult res = EnumerateDeviceLayerProperties(physDev, &layerCount, nullptr);
152 if (VK_SUCCESS != res) {
153 return false;
154 }
155 VkLayerProperties* layers = new VkLayerProperties[layerCount];
156 res = EnumerateDeviceLayerProperties(physDev, &layerCount, layers);
157 if (VK_SUCCESS != res) {
158 delete[] layers;
159 return false;
160 }
161 for (uint32_t i = 0; i < layerCount; ++i) {
162 if (nonPatchVersion >= remove_patch_version(layers[i].specVersion)) {
163 fDeviceLayerStrings->push_back() = layers[i].layerName;
164 }
165 }
166 delete[] layers;
167 if (!fDeviceLayerStrings->empty()) {
168 SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp;
169 SkTQSort(&fDeviceLayerStrings->front(), &fDeviceLayerStrings->back(), cmp);
170 }
171
172 // device extensions
173 // via Vulkan implementation and implicitly enabled layers
174 uint32_t extensionCount = 0;
175 res = EnumerateDeviceExtensionProperties(physDev, nullptr, &extensionCount, nullptr);
176 if (VK_SUCCESS != res) {
177 return false;
178 }
179 VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
180 res = EnumerateDeviceExtensionProperties(physDev, nullptr, &extensionCount, extensions);
181 if (VK_SUCCESS != res) {
182 delete[] extensions;
183 return false;
184 }
185 for (uint32_t i = 0; i < extensionCount; ++i) {
186 if (nonPatchVersion >= remove_patch_version(extensions[i].specVersion)) {
187 fDeviceExtensionStrings->push_back() = extensions[i].extensionName;
188 }
189 }
190 delete[] extensions;
191 if (!fDeviceExtensionStrings->empty()) {
192 SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp;
193 SkTQSort(&fDeviceExtensionStrings->front(), &fDeviceExtensionStrings->back(), cmp);
194 }
195 // via explicitly enabled layers
196 layerCount = fDeviceLayerStrings->count();
197 for (uint32_t layerIndex = 0; layerIndex < layerCount; ++layerIndex) {
198 uint32_t extensionCount = 0;
199 res = EnumerateDeviceExtensionProperties(physDev,
200 (*fDeviceLayerStrings)[layerIndex].c_str(),
201 &extensionCount, nullptr);
202 if (VK_SUCCESS != res) {
203 return false;
204 }
205 VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
206 res = EnumerateDeviceExtensionProperties(physDev,
207 (*fDeviceLayerStrings)[layerIndex].c_str(),
208 &extensionCount, extensions);
209 if (VK_SUCCESS != res) {
210 delete[] extensions;
211 return false;
212 }
213 for (uint32_t i = 0; i < extensionCount; ++i) {
214 // if not already in the list, add it
215 if (nonPatchVersion >= remove_patch_version(extensions[i].specVersion) &&
216 find_string(*fDeviceExtensionStrings, extensions[i].extensionName) < 0) {
217 fDeviceExtensionStrings->push_back() = extensions[i].extensionName;
218 SkTQSort(&fDeviceExtensionStrings->front(), &fDeviceExtensionStrings->back(), cmp);
219 }
220 }
221 delete[] extensions;
222 }
223
224 return true;
225 }
226
hasInstanceExtension(const char ext[]) const227 bool GrVkExtensions::hasInstanceExtension(const char ext[]) const {
228 return find_string(*fInstanceExtensionStrings, ext) >= 0;
229 }
230
hasDeviceExtension(const char ext[]) const231 bool GrVkExtensions::hasDeviceExtension(const char ext[]) const {
232 return find_string(*fDeviceExtensionStrings, ext) >= 0;
233 }
234
hasInstanceLayer(const char ext[]) const235 bool GrVkExtensions::hasInstanceLayer(const char ext[]) const {
236 return find_string(*fInstanceLayerStrings, ext) >= 0;
237 }
238
hasDeviceLayer(const char ext[]) const239 bool GrVkExtensions::hasDeviceLayer(const char ext[]) const {
240 return find_string(*fDeviceLayerStrings, ext) >= 0;
241 }
242
print(const char * sep) const243 void GrVkExtensions::print(const char* sep) const {
244 if (nullptr == sep) {
245 sep = " ";
246 }
247 int cnt = fInstanceExtensionStrings->count();
248 SkDebugf("Instance Extensions: ");
249 for (int i = 0; i < cnt; ++i) {
250 SkDebugf("%s%s", (*fInstanceExtensionStrings)[i].c_str(), (i < cnt - 1) ? sep : "");
251 }
252 cnt = fDeviceExtensionStrings->count();
253 SkDebugf("\nDevice Extensions: ");
254 for (int i = 0; i < cnt; ++i) {
255 SkDebugf("%s%s", (*fDeviceExtensionStrings)[i].c_str(), (i < cnt - 1) ? sep : "");
256 }
257 cnt = fInstanceLayerStrings->count();
258 SkDebugf("\nInstance Layers: ");
259 for (int i = 0; i < cnt; ++i) {
260 SkDebugf("%s%s", (*fInstanceLayerStrings)[i].c_str(), (i < cnt - 1) ? sep : "");
261 }
262 cnt = fDeviceLayerStrings->count();
263 SkDebugf("\nDevice Layers: ");
264 for (int i = 0; i < cnt; ++i) {
265 SkDebugf("%s%s", (*fDeviceLayerStrings)[i].c_str(), (i < cnt - 1) ? sep : "");
266 }
267 }
268