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