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