blob: e4768d95c99d7d68474f42029a91c7144e41b0ec [file] [log] [blame]
jvanverthd2497f32016-03-18 12:39:05 -07001/*
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"
Greg Danieldc13c212018-06-28 23:29:35 +00009#include "vk/GrVkUtil.h"
jvanverthd2497f32016-03-18 12:39:05 -070010
11#include "SkTSearch.h"
12#include "SkTSort.h"
13
14namespace { // This cannot be static because it is used as a template parameter.
15inline 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.
21static 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
Greg Danieldc13c212018-06-28 23:29:35 +000033#define GET_PROC_LOCAL(F, inst, device) PFN_vk ## F F = (PFN_vk ## F) fGetProc("vk" #F, inst, device)
34
35static uint32_t remove_patch_version(uint32_t specVersion) {
36 return (specVersion >> 12) << 12;
37}
38
39bool 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
jvanverth633b3562016-03-23 11:01:22 -070049 SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp;
jvanverthd2497f32016-03-18 12:39:05 -070050
Greg Danieldc13c212018-06-28 23:29:35 +000051 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;
jvanverth633b3562016-03-23 11:01:22 -070071 }
72 }
Greg Danieldc13c212018-06-28 23:29:35 +000073 delete[] layers;
74 if (!fInstanceLayerStrings->empty()) {
75 SkTQSort(&fInstanceLayerStrings->front(), &fInstanceLayerStrings->back(), cmp);
Greg Danielcb92b262018-06-27 15:03:36 +000076 }
Greg Danieldc13c212018-06-28 23:29:35 +000077
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 (find_string(*fInstanceExtensionStrings, extensions[i].extensionName) < 0) {
118 fInstanceExtensionStrings->push_back() = extensions[i].extensionName;
119 SkTQSort(&fInstanceExtensionStrings->front(), &fInstanceExtensionStrings->back(),
120 cmp);
121 }
122 }
123 delete[] extensions;
124 }
125
126 return true;
jvanverthfd7bd452016-03-25 06:29:52 -0700127}
128
Greg Danieldc13c212018-06-28 23:29:35 +0000129bool GrVkExtensions::initDevice(uint32_t specVersion, VkInstance inst, VkPhysicalDevice physDev) {
130 if (fGetProc == nullptr) {
131 return false;
132 }
133
134 uint32_t nonPatchVersion = remove_patch_version(specVersion);
135
136 GET_PROC_LOCAL(EnumerateDeviceExtensionProperties, inst, VK_NULL_HANDLE);
137 GET_PROC_LOCAL(EnumerateDeviceLayerProperties, inst, VK_NULL_HANDLE);
138
jvanverthfd7bd452016-03-25 06:29:52 -0700139 SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp;
140
Greg Danieldc13c212018-06-28 23:29:35 +0000141 if (!EnumerateDeviceExtensionProperties ||
142 !EnumerateDeviceLayerProperties) {
143 return false;
144 }
145
146 // device layers
147 uint32_t layerCount = 0;
148 VkResult res = EnumerateDeviceLayerProperties(physDev, &layerCount, nullptr);
149 if (VK_SUCCESS != res) {
150 return false;
151 }
152 VkLayerProperties* layers = new VkLayerProperties[layerCount];
153 res = EnumerateDeviceLayerProperties(physDev, &layerCount, layers);
154 if (VK_SUCCESS != res) {
155 delete[] layers;
156 return false;
157 }
158 for (uint32_t i = 0; i < layerCount; ++i) {
159 if (nonPatchVersion <= remove_patch_version(layers[i].specVersion)) {
160 fDeviceLayerStrings->push_back() = layers[i].layerName;
jvanverth633b3562016-03-23 11:01:22 -0700161 }
162 }
Greg Danieldc13c212018-06-28 23:29:35 +0000163 delete[] layers;
164 if (!fDeviceLayerStrings->empty()) {
165 SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp;
166 SkTQSort(&fDeviceLayerStrings->front(), &fDeviceLayerStrings->back(), cmp);
167 }
168
169 // device extensions
170 // via Vulkan implementation and implicitly enabled layers
171 uint32_t extensionCount = 0;
172 res = EnumerateDeviceExtensionProperties(physDev, nullptr, &extensionCount, nullptr);
173 if (VK_SUCCESS != res) {
174 return false;
175 }
176 VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
177 res = EnumerateDeviceExtensionProperties(physDev, nullptr, &extensionCount, extensions);
178 if (VK_SUCCESS != res) {
179 delete[] extensions;
180 return false;
181 }
182 for (uint32_t i = 0; i < extensionCount; ++i) {
183 fDeviceExtensionStrings->push_back() = extensions[i].extensionName;
184 }
185 delete[] extensions;
186 if (!fDeviceExtensionStrings->empty()) {
187 SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp;
188 SkTQSort(&fDeviceExtensionStrings->front(), &fDeviceExtensionStrings->back(), cmp);
189 }
190 // via explicitly enabled layers
191 layerCount = fDeviceLayerStrings->count();
192 for (uint32_t layerIndex = 0; layerIndex < layerCount; ++layerIndex) {
193 uint32_t extensionCount = 0;
194 res = EnumerateDeviceExtensionProperties(physDev,
195 (*fDeviceLayerStrings)[layerIndex].c_str(),
196 &extensionCount, nullptr);
197 if (VK_SUCCESS != res) {
198 return false;
199 }
200 VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
201 res = EnumerateDeviceExtensionProperties(physDev,
202 (*fDeviceLayerStrings)[layerIndex].c_str(),
203 &extensionCount, extensions);
204 if (VK_SUCCESS != res) {
205 delete[] extensions;
206 return false;
207 }
208 for (uint32_t i = 0; i < extensionCount; ++i) {
209 // if not already in the list, add it
210 if (find_string(*fDeviceExtensionStrings, extensions[i].extensionName) < 0) {
211 fDeviceExtensionStrings->push_back() = extensions[i].extensionName;
212 SkTQSort(&fDeviceExtensionStrings->front(), &fDeviceExtensionStrings->back(), cmp);
213 }
214 }
215 delete[] extensions;
216 }
217
218 return true;
jvanverthd2497f32016-03-18 12:39:05 -0700219}
220
Greg Danieldc13c212018-06-28 23:29:35 +0000221bool GrVkExtensions::hasInstanceExtension(const char ext[]) const {
222 return find_string(*fInstanceExtensionStrings, ext) >= 0;
jvanverthd2497f32016-03-18 12:39:05 -0700223}
224
Greg Danieldc13c212018-06-28 23:29:35 +0000225bool GrVkExtensions::hasDeviceExtension(const char ext[]) const {
226 return find_string(*fDeviceExtensionStrings, ext) >= 0;
jvanverthd2497f32016-03-18 12:39:05 -0700227}
228
Greg Danieldc13c212018-06-28 23:29:35 +0000229bool GrVkExtensions::hasInstanceLayer(const char ext[]) const {
230 return find_string(*fInstanceLayerStrings, ext) >= 0;
231}
232
233bool GrVkExtensions::hasDeviceLayer(const char ext[]) const {
234 return find_string(*fDeviceLayerStrings, ext) >= 0;
235}
236
237void GrVkExtensions::print(const char* sep) const {
238 if (nullptr == sep) {
239 sep = " ";
240 }
241 int cnt = fInstanceExtensionStrings->count();
242 SkDebugf("Instance Extensions: ");
243 for (int i = 0; i < cnt; ++i) {
244 SkDebugf("%s%s", (*fInstanceExtensionStrings)[i].c_str(), (i < cnt - 1) ? sep : "");
245 }
246 cnt = fDeviceExtensionStrings->count();
247 SkDebugf("\nDevice Extensions: ");
248 for (int i = 0; i < cnt; ++i) {
249 SkDebugf("%s%s", (*fDeviceExtensionStrings)[i].c_str(), (i < cnt - 1) ? sep : "");
250 }
251 cnt = fInstanceLayerStrings->count();
252 SkDebugf("\nInstance Layers: ");
253 for (int i = 0; i < cnt; ++i) {
254 SkDebugf("%s%s", (*fInstanceLayerStrings)[i].c_str(), (i < cnt - 1) ? sep : "");
255 }
256 cnt = fDeviceLayerStrings->count();
257 SkDebugf("\nDevice Layers: ");
258 for (int i = 0; i < cnt; ++i) {
259 SkDebugf("%s%s", (*fDeviceLayerStrings)[i].c_str(), (i < cnt - 1) ? sep : "");
260 }
261}