blob: 17737f17998fddf9d8d367e26b7c1fa931ecd872 [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"
9#include "vk/GrVkUtil.h"
10
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
Michael Jurka3251ed82017-04-05 09:52:55 -070033#define GET_PROC_LOCAL(F, inst, device) PFN_vk ## F F = (PFN_vk ## F) fGetProc("vk" #F, inst, device)
jvanverthd2497f32016-03-18 12:39:05 -070034
egdanieldde2c032016-05-12 11:42:00 -070035static uint32_t remove_patch_version(uint32_t specVersion) {
36 return (specVersion >> 12) << 12;
37}
38
jvanverthfd7bd452016-03-25 06:29:52 -070039bool GrVkExtensions::initInstance(uint32_t specVersion) {
Michael Jurka3251ed82017-04-05 09:52:55 -070040 if (fGetProc == nullptr) {
41 return false;
42 }
43
egdanieldde2c032016-05-12 11:42:00 -070044 uint32_t nonPatchVersion = remove_patch_version(specVersion);
jvanverthd2497f32016-03-18 12:39:05 -070045
Michael Jurka3251ed82017-04-05 09:52:55 -070046 GET_PROC_LOCAL(EnumerateInstanceExtensionProperties, VK_NULL_HANDLE, VK_NULL_HANDLE);
47 GET_PROC_LOCAL(EnumerateInstanceLayerProperties, VK_NULL_HANDLE, VK_NULL_HANDLE);
jvanverthd2497f32016-03-18 12:39:05 -070048
jvanverth633b3562016-03-23 11:01:22 -070049 SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp;
jvanverthd2497f32016-03-18 12:39:05 -070050
jvanverthfd7bd452016-03-25 06:29:52 -070051 if (!EnumerateInstanceExtensionProperties ||
52 !EnumerateInstanceLayerProperties) {
jvanverthd2497f32016-03-18 12:39:05 -070053 return false;
54 }
55
jvanverth633b3562016-03-23 11:01:22 -070056 // instance layers
57 uint32_t layerCount = 0;
jvanverthfd7bd452016-03-25 06:29:52 -070058 VkResult res = EnumerateInstanceLayerProperties(&layerCount, nullptr);
jvanverth633b3562016-03-23 11:01:22 -070059 if (VK_SUCCESS != res) {
60 return false;
61 }
62 VkLayerProperties* layers = new VkLayerProperties[layerCount];
jvanverthfd7bd452016-03-25 06:29:52 -070063 res = EnumerateInstanceLayerProperties(&layerCount, layers);
jvanverth633b3562016-03-23 11:01:22 -070064 if (VK_SUCCESS != res) {
egdaniel8af936d2016-04-07 10:17:47 -070065 delete[] layers;
jvanverth633b3562016-03-23 11:01:22 -070066 return false;
67 }
68 for (uint32_t i = 0; i < layerCount; ++i) {
egdanieldde2c032016-05-12 11:42:00 -070069 if (nonPatchVersion >= remove_patch_version(layers[i].specVersion)) {
jvanverth633b3562016-03-23 11:01:22 -070070 fInstanceLayerStrings->push_back() = layers[i].layerName;
71 }
72 }
73 delete[] layers;
74 if (!fInstanceLayerStrings->empty()) {
75 SkTQSort(&fInstanceLayerStrings->front(), &fInstanceLayerStrings->back(), cmp);
76 }
jvanverthd2497f32016-03-18 12:39:05 -070077
jvanverth633b3562016-03-23 11:01:22 -070078 // instance extensions
79 // via Vulkan implementation and implicitly enabled layers
80 uint32_t extensionCount = 0;
jvanverthfd7bd452016-03-25 06:29:52 -070081 res = EnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
jvanverth633b3562016-03-23 11:01:22 -070082 if (VK_SUCCESS != res) {
83 return false;
84 }
jvanverthd2497f32016-03-18 12:39:05 -070085 VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
jvanverthfd7bd452016-03-25 06:29:52 -070086 res = EnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions);
jvanverth633b3562016-03-23 11:01:22 -070087 if (VK_SUCCESS != res) {
egdaniel8af936d2016-04-07 10:17:47 -070088 delete[] extensions;
jvanverth633b3562016-03-23 11:01:22 -070089 return false;
90 }
jvanverthd2497f32016-03-18 12:39:05 -070091 for (uint32_t i = 0; i < extensionCount; ++i) {
egdanieldde2c032016-05-12 11:42:00 -070092 if (nonPatchVersion >= remove_patch_version(extensions[i].specVersion)) {
jvanverth633b3562016-03-23 11:01:22 -070093 fInstanceExtensionStrings->push_back() = extensions[i].extensionName;
jvanverthd2497f32016-03-18 12:39:05 -070094 }
95 }
96 delete [] extensions;
jvanverth633b3562016-03-23 11:01:22 -070097 // sort so we can search
jvanverthd2497f32016-03-18 12:39:05 -070098 if (!fInstanceExtensionStrings->empty()) {
jvanverthd2497f32016-03-18 12:39:05 -070099 SkTQSort(&fInstanceExtensionStrings->front(), &fInstanceExtensionStrings->back(), cmp);
100 }
jvanverth633b3562016-03-23 11:01:22 -0700101 // via explicitly enabled layers
102 layerCount = fInstanceLayerStrings->count();
103 for (uint32_t layerIndex = 0; layerIndex < layerCount; ++layerIndex) {
104 uint32_t extensionCount = 0;
halcanary9d524f22016-03-29 09:03:52 -0700105 res = EnumerateInstanceExtensionProperties((*fInstanceLayerStrings)[layerIndex].c_str(),
jvanverth633b3562016-03-23 11:01:22 -0700106 &extensionCount, nullptr);
107 if (VK_SUCCESS != res) {
108 return false;
109 }
110 VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
jvanverthfd7bd452016-03-25 06:29:52 -0700111 res = EnumerateInstanceExtensionProperties((*fInstanceLayerStrings)[layerIndex].c_str(),
jvanverth633b3562016-03-23 11:01:22 -0700112 &extensionCount, extensions);
113 if (VK_SUCCESS != res) {
egdaniel8af936d2016-04-07 10:17:47 -0700114 delete[] extensions;
jvanverth633b3562016-03-23 11:01:22 -0700115 return false;
116 }
117 for (uint32_t i = 0; i < extensionCount; ++i) {
118 // if not already in the list, add it
egdanieldde2c032016-05-12 11:42:00 -0700119 if (nonPatchVersion >= remove_patch_version(extensions[i].specVersion) &&
jvanverth633b3562016-03-23 11:01:22 -0700120 find_string(*fInstanceExtensionStrings, extensions[i].extensionName) < 0) {
121 fInstanceExtensionStrings->push_back() = extensions[i].extensionName;
halcanary9d524f22016-03-29 09:03:52 -0700122 SkTQSort(&fInstanceExtensionStrings->front(), &fInstanceExtensionStrings->back(),
jvanverth633b3562016-03-23 11:01:22 -0700123 cmp);
124 }
125 }
126 delete[] extensions;
127 }
128
jvanverthfd7bd452016-03-25 06:29:52 -0700129 return true;
130}
131
132bool GrVkExtensions::initDevice(uint32_t specVersion, VkInstance inst, VkPhysicalDevice physDev) {
Michael Jurka3251ed82017-04-05 09:52:55 -0700133 if (fGetProc == nullptr) {
134 return false;
135 }
136
egdanieldde2c032016-05-12 11:42:00 -0700137 uint32_t nonPatchVersion = remove_patch_version(specVersion);
jvanverthfd7bd452016-03-25 06:29:52 -0700138
Michael Jurka3251ed82017-04-05 09:52:55 -0700139 GET_PROC_LOCAL(EnumerateDeviceExtensionProperties, inst, VK_NULL_HANDLE);
140 GET_PROC_LOCAL(EnumerateDeviceLayerProperties, inst, VK_NULL_HANDLE);
jvanverthfd7bd452016-03-25 06:29:52 -0700141
142 SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp;
143
144 if (!EnumerateDeviceExtensionProperties ||
145 !EnumerateDeviceLayerProperties) {
146 return false;
147 }
148
jvanverth633b3562016-03-23 11:01:22 -0700149 // device layers
jvanverthfd7bd452016-03-25 06:29:52 -0700150 uint32_t layerCount = 0;
151 VkResult res = EnumerateDeviceLayerProperties(physDev, &layerCount, nullptr);
jvanverth633b3562016-03-23 11:01:22 -0700152 if (VK_SUCCESS != res) {
153 return false;
154 }
jvanverthfd7bd452016-03-25 06:29:52 -0700155 VkLayerProperties* layers = new VkLayerProperties[layerCount];
156 res = EnumerateDeviceLayerProperties(physDev, &layerCount, layers);
jvanverth633b3562016-03-23 11:01:22 -0700157 if (VK_SUCCESS != res) {
egdaniel8af936d2016-04-07 10:17:47 -0700158 delete[] layers;
jvanverth633b3562016-03-23 11:01:22 -0700159 return false;
160 }
161 for (uint32_t i = 0; i < layerCount; ++i) {
egdanieldde2c032016-05-12 11:42:00 -0700162 if (nonPatchVersion >= remove_patch_version(layers[i].specVersion)) {
jvanverth633b3562016-03-23 11:01:22 -0700163 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
jvanverthfd7bd452016-03-25 06:29:52 -0700174 uint32_t extensionCount = 0;
175 res = EnumerateDeviceExtensionProperties(physDev, nullptr, &extensionCount, nullptr);
jvanverth633b3562016-03-23 11:01:22 -0700176 if (VK_SUCCESS != res) {
177 return false;
178 }
jvanverthfd7bd452016-03-25 06:29:52 -0700179 VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
180 res = EnumerateDeviceExtensionProperties(physDev, nullptr, &extensionCount, extensions);
jvanverth633b3562016-03-23 11:01:22 -0700181 if (VK_SUCCESS != res) {
egdaniel8af936d2016-04-07 10:17:47 -0700182 delete[] extensions;
jvanverth633b3562016-03-23 11:01:22 -0700183 return false;
184 }
185 for (uint32_t i = 0; i < extensionCount; ++i) {
egdanieldde2c032016-05-12 11:42:00 -0700186 if (nonPatchVersion >= remove_patch_version(extensions[i].specVersion)) {
jvanverth633b3562016-03-23 11:01:22 -0700187 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;
jvanverthfd7bd452016-03-25 06:29:52 -0700199 res = EnumerateDeviceExtensionProperties(physDev,
200 (*fDeviceLayerStrings)[layerIndex].c_str(),
201 &extensionCount, nullptr);
jvanverth633b3562016-03-23 11:01:22 -0700202 if (VK_SUCCESS != res) {
203 return false;
204 }
205 VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
jvanverthfd7bd452016-03-25 06:29:52 -0700206 res = EnumerateDeviceExtensionProperties(physDev,
207 (*fDeviceLayerStrings)[layerIndex].c_str(),
208 &extensionCount, extensions);
jvanverth633b3562016-03-23 11:01:22 -0700209 if (VK_SUCCESS != res) {
egdaniel8af936d2016-04-07 10:17:47 -0700210 delete[] extensions;
jvanverth633b3562016-03-23 11:01:22 -0700211 return false;
212 }
213 for (uint32_t i = 0; i < extensionCount; ++i) {
214 // if not already in the list, add it
egdanieldde2c032016-05-12 11:42:00 -0700215 if (nonPatchVersion >= remove_patch_version(extensions[i].specVersion) &&
jvanverth633b3562016-03-23 11:01:22 -0700216 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 }
jvanverthd2497f32016-03-18 12:39:05 -0700223
jvanverthd2497f32016-03-18 12:39:05 -0700224 return true;
225}
226
jvanverthd2497f32016-03-18 12:39:05 -0700227bool GrVkExtensions::hasInstanceExtension(const char ext[]) const {
jvanverthd2497f32016-03-18 12:39:05 -0700228 return find_string(*fInstanceExtensionStrings, ext) >= 0;
229}
230
231bool GrVkExtensions::hasDeviceExtension(const char ext[]) const {
jvanverthd2497f32016-03-18 12:39:05 -0700232 return find_string(*fDeviceExtensionStrings, ext) >= 0;
233}
234
235bool GrVkExtensions::hasInstanceLayer(const char ext[]) const {
jvanverthd2497f32016-03-18 12:39:05 -0700236 return find_string(*fInstanceLayerStrings, ext) >= 0;
237}
238
239bool GrVkExtensions::hasDeviceLayer(const char ext[]) const {
jvanverthd2497f32016-03-18 12:39:05 -0700240 return find_string(*fDeviceLayerStrings, ext) >= 0;
241}
242
jvanverthd2497f32016-03-18 12:39:05 -0700243void 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}