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 fInstanceExtensionStrings->push_back() = extensions[i].extensionName;
93 }
94 delete [] extensions;
95 // sort so we can search
96 if (!fInstanceExtensionStrings->empty()) {
97 SkTQSort(&fInstanceExtensionStrings->front(), &fInstanceExtensionStrings->back(), cmp);
98 }
99 // via explicitly enabled layers
100 layerCount = fInstanceLayerStrings->count();
101 for (uint32_t layerIndex = 0; layerIndex < layerCount; ++layerIndex) {
102 uint32_t extensionCount = 0;
103 res = EnumerateInstanceExtensionProperties((*fInstanceLayerStrings)[layerIndex].c_str(),
104 &extensionCount, nullptr);
105 if (VK_SUCCESS != res) {
106 return false;
107 }
108 VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
109 res = EnumerateInstanceExtensionProperties((*fInstanceLayerStrings)[layerIndex].c_str(),
110 &extensionCount, extensions);
111 if (VK_SUCCESS != res) {
112 delete[] extensions;
113 return false;
114 }
115 for (uint32_t i = 0; i < extensionCount; ++i) {
116 // if not already in the list, add it
117 if (nonPatchVersion >= remove_patch_version(extensions[i].specVersion) &&
118 find_string(*fInstanceExtensionStrings, extensions[i].extensionName) < 0) {
119 fInstanceExtensionStrings->push_back() = extensions[i].extensionName;
120 SkTQSort(&fInstanceExtensionStrings->front(), &fInstanceExtensionStrings->back(),
121 cmp);
122 }
123 }
124 delete[] extensions;
125 }
126
127 return true;
128 }
129
initDevice(uint32_t specVersion,VkInstance inst,VkPhysicalDevice physDev)130 bool GrVkExtensions::initDevice(uint32_t specVersion, VkInstance inst, VkPhysicalDevice physDev) {
131 if (fGetProc == nullptr) {
132 return false;
133 }
134
135 uint32_t nonPatchVersion = remove_patch_version(specVersion);
136
137 GET_PROC_LOCAL(EnumerateDeviceExtensionProperties, inst, VK_NULL_HANDLE);
138 GET_PROC_LOCAL(EnumerateDeviceLayerProperties, inst, VK_NULL_HANDLE);
139
140 SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp;
141
142 if (!EnumerateDeviceExtensionProperties ||
143 !EnumerateDeviceLayerProperties) {
144 return false;
145 }
146
147 // device layers
148 uint32_t layerCount = 0;
149 VkResult res = EnumerateDeviceLayerProperties(physDev, &layerCount, nullptr);
150 if (VK_SUCCESS != res) {
151 return false;
152 }
153 VkLayerProperties* layers = new VkLayerProperties[layerCount];
154 res = EnumerateDeviceLayerProperties(physDev, &layerCount, layers);
155 if (VK_SUCCESS != res) {
156 delete[] layers;
157 return false;
158 }
159 for (uint32_t i = 0; i < layerCount; ++i) {
160 if (nonPatchVersion >= remove_patch_version(layers[i].specVersion)) {
161 fDeviceLayerStrings->push_back() = layers[i].layerName;
162 }
163 }
164 delete[] layers;
165 if (!fDeviceLayerStrings->empty()) {
166 SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp;
167 SkTQSort(&fDeviceLayerStrings->front(), &fDeviceLayerStrings->back(), cmp);
168 }
169
170 // device extensions
171 // via Vulkan implementation and implicitly enabled layers
172 uint32_t extensionCount = 0;
173 res = EnumerateDeviceExtensionProperties(physDev, nullptr, &extensionCount, nullptr);
174 if (VK_SUCCESS != res) {
175 return false;
176 }
177 VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
178 res = EnumerateDeviceExtensionProperties(physDev, nullptr, &extensionCount, extensions);
179 if (VK_SUCCESS != res) {
180 delete[] extensions;
181 return false;
182 }
183 for (uint32_t i = 0; i < extensionCount; ++i) {
184 fDeviceExtensionStrings->push_back() = extensions[i].extensionName;
185 }
186 delete[] extensions;
187 if (!fDeviceExtensionStrings->empty()) {
188 SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp;
189 SkTQSort(&fDeviceExtensionStrings->front(), &fDeviceExtensionStrings->back(), cmp);
190 }
191 // via explicitly enabled layers
192 layerCount = fDeviceLayerStrings->count();
193 for (uint32_t layerIndex = 0; layerIndex < layerCount; ++layerIndex) {
194 uint32_t extensionCount = 0;
195 res = EnumerateDeviceExtensionProperties(physDev,
196 (*fDeviceLayerStrings)[layerIndex].c_str(),
197 &extensionCount, nullptr);
198 if (VK_SUCCESS != res) {
199 return false;
200 }
201 VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
202 res = EnumerateDeviceExtensionProperties(physDev,
203 (*fDeviceLayerStrings)[layerIndex].c_str(),
204 &extensionCount, extensions);
205 if (VK_SUCCESS != res) {
206 delete[] extensions;
207 return false;
208 }
209 for (uint32_t i = 0; i < extensionCount; ++i) {
210 // if not already in the list, add it
211 if (nonPatchVersion >= remove_patch_version(extensions[i].specVersion) &&
212 find_string(*fDeviceExtensionStrings, extensions[i].extensionName) < 0) {
213 fDeviceExtensionStrings->push_back() = extensions[i].extensionName;
214 SkTQSort(&fDeviceExtensionStrings->front(), &fDeviceExtensionStrings->back(), cmp);
215 }
216 }
217 delete[] extensions;
218 }
219
220 return true;
221 }
222
hasInstanceExtension(const char ext[]) const223 bool GrVkExtensions::hasInstanceExtension(const char ext[]) const {
224 return find_string(*fInstanceExtensionStrings, ext) >= 0;
225 }
226
hasDeviceExtension(const char ext[]) const227 bool GrVkExtensions::hasDeviceExtension(const char ext[]) const {
228 return find_string(*fDeviceExtensionStrings, ext) >= 0;
229 }
230
hasInstanceLayer(const char ext[]) const231 bool GrVkExtensions::hasInstanceLayer(const char ext[]) const {
232 return find_string(*fInstanceLayerStrings, ext) >= 0;
233 }
234
hasDeviceLayer(const char ext[]) const235 bool GrVkExtensions::hasDeviceLayer(const char ext[]) const {
236 return find_string(*fDeviceLayerStrings, ext) >= 0;
237 }
238
print(const char * sep) const239 void GrVkExtensions::print(const char* sep) const {
240 if (nullptr == sep) {
241 sep = " ";
242 }
243 int cnt = fInstanceExtensionStrings->count();
244 SkDebugf("Instance Extensions: ");
245 for (int i = 0; i < cnt; ++i) {
246 SkDebugf("%s%s", (*fInstanceExtensionStrings)[i].c_str(), (i < cnt - 1) ? sep : "");
247 }
248 cnt = fDeviceExtensionStrings->count();
249 SkDebugf("\nDevice Extensions: ");
250 for (int i = 0; i < cnt; ++i) {
251 SkDebugf("%s%s", (*fDeviceExtensionStrings)[i].c_str(), (i < cnt - 1) ? sep : "");
252 }
253 cnt = fInstanceLayerStrings->count();
254 SkDebugf("\nInstance Layers: ");
255 for (int i = 0; i < cnt; ++i) {
256 SkDebugf("%s%s", (*fInstanceLayerStrings)[i].c_str(), (i < cnt - 1) ? sep : "");
257 }
258 cnt = fDeviceLayerStrings->count();
259 SkDebugf("\nDevice Layers: ");
260 for (int i = 0; i < cnt; ++i) {
261 SkDebugf("%s%s", (*fDeviceLayerStrings)[i].c_str(), (i < cnt - 1) ? sep : "");
262 }
263 }
264