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