• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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