blob: c1ca2dd3a21e32c4d5c537188be86de7d8e93872 [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
jvanverthfd7bd452016-03-25 06:29:52 -070033#define GET_PROC_LOCAL(inst, F) PFN_vk ## F F = (PFN_vk ## F) vkGetInstanceProcAddr(inst, "vk" #F)
jvanverthd2497f32016-03-18 12:39:05 -070034
jvanverthfd7bd452016-03-25 06:29:52 -070035bool GrVkExtensions::initInstance(uint32_t specVersion) {
jvanverthd2497f32016-03-18 12:39:05 -070036
jvanverthfd7bd452016-03-25 06:29:52 -070037 GET_PROC_LOCAL(nullptr, EnumerateInstanceExtensionProperties);
38 GET_PROC_LOCAL(nullptr, EnumerateInstanceLayerProperties);
jvanverthd2497f32016-03-18 12:39:05 -070039
jvanverth633b3562016-03-23 11:01:22 -070040 SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp;
jvanverthd2497f32016-03-18 12:39:05 -070041
jvanverthfd7bd452016-03-25 06:29:52 -070042 if (!EnumerateInstanceExtensionProperties ||
43 !EnumerateInstanceLayerProperties) {
jvanverthd2497f32016-03-18 12:39:05 -070044 return false;
45 }
46
jvanverth633b3562016-03-23 11:01:22 -070047 // instance layers
48 uint32_t layerCount = 0;
jvanverthfd7bd452016-03-25 06:29:52 -070049 VkResult res = EnumerateInstanceLayerProperties(&layerCount, nullptr);
jvanverth633b3562016-03-23 11:01:22 -070050 if (VK_SUCCESS != res) {
51 return false;
52 }
53 VkLayerProperties* layers = new VkLayerProperties[layerCount];
jvanverthfd7bd452016-03-25 06:29:52 -070054 res = EnumerateInstanceLayerProperties(&layerCount, layers);
jvanverth633b3562016-03-23 11:01:22 -070055 if (VK_SUCCESS != res) {
egdaniel8af936d2016-04-07 10:17:47 -070056 delete[] layers;
jvanverth633b3562016-03-23 11:01:22 -070057 return false;
58 }
59 for (uint32_t i = 0; i < layerCount; ++i) {
60 if (specVersion >= layers[i].specVersion) {
61 fInstanceLayerStrings->push_back() = layers[i].layerName;
62 }
63 }
64 delete[] layers;
65 if (!fInstanceLayerStrings->empty()) {
66 SkTQSort(&fInstanceLayerStrings->front(), &fInstanceLayerStrings->back(), cmp);
67 }
jvanverthd2497f32016-03-18 12:39:05 -070068
jvanverth633b3562016-03-23 11:01:22 -070069 // instance extensions
70 // via Vulkan implementation and implicitly enabled layers
71 uint32_t extensionCount = 0;
jvanverthfd7bd452016-03-25 06:29:52 -070072 res = EnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
jvanverth633b3562016-03-23 11:01:22 -070073 if (VK_SUCCESS != res) {
74 return false;
75 }
jvanverthd2497f32016-03-18 12:39:05 -070076 VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
jvanverthfd7bd452016-03-25 06:29:52 -070077 res = EnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions);
jvanverth633b3562016-03-23 11:01:22 -070078 if (VK_SUCCESS != res) {
egdaniel8af936d2016-04-07 10:17:47 -070079 delete[] extensions;
jvanverth633b3562016-03-23 11:01:22 -070080 return false;
81 }
jvanverthd2497f32016-03-18 12:39:05 -070082 for (uint32_t i = 0; i < extensionCount; ++i) {
83 if (specVersion >= extensions[i].specVersion) {
jvanverth633b3562016-03-23 11:01:22 -070084 fInstanceExtensionStrings->push_back() = extensions[i].extensionName;
jvanverthd2497f32016-03-18 12:39:05 -070085 }
86 }
87 delete [] extensions;
jvanverth633b3562016-03-23 11:01:22 -070088 // sort so we can search
jvanverthd2497f32016-03-18 12:39:05 -070089 if (!fInstanceExtensionStrings->empty()) {
jvanverthd2497f32016-03-18 12:39:05 -070090 SkTQSort(&fInstanceExtensionStrings->front(), &fInstanceExtensionStrings->back(), cmp);
91 }
jvanverth633b3562016-03-23 11:01:22 -070092 // via explicitly enabled layers
93 layerCount = fInstanceLayerStrings->count();
94 for (uint32_t layerIndex = 0; layerIndex < layerCount; ++layerIndex) {
95 uint32_t extensionCount = 0;
halcanary9d524f22016-03-29 09:03:52 -070096 res = EnumerateInstanceExtensionProperties((*fInstanceLayerStrings)[layerIndex].c_str(),
jvanverth633b3562016-03-23 11:01:22 -070097 &extensionCount, nullptr);
98 if (VK_SUCCESS != res) {
99 return false;
100 }
101 VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
jvanverthfd7bd452016-03-25 06:29:52 -0700102 res = EnumerateInstanceExtensionProperties((*fInstanceLayerStrings)[layerIndex].c_str(),
jvanverth633b3562016-03-23 11:01:22 -0700103 &extensionCount, extensions);
104 if (VK_SUCCESS != res) {
egdaniel8af936d2016-04-07 10:17:47 -0700105 delete[] extensions;
jvanverth633b3562016-03-23 11:01:22 -0700106 return false;
107 }
108 for (uint32_t i = 0; i < extensionCount; ++i) {
109 // if not already in the list, add it
110 if (specVersion >= extensions[i].specVersion &&
111 find_string(*fInstanceExtensionStrings, extensions[i].extensionName) < 0) {
112 fInstanceExtensionStrings->push_back() = extensions[i].extensionName;
halcanary9d524f22016-03-29 09:03:52 -0700113 SkTQSort(&fInstanceExtensionStrings->front(), &fInstanceExtensionStrings->back(),
jvanverth633b3562016-03-23 11:01:22 -0700114 cmp);
115 }
116 }
117 delete[] extensions;
118 }
119
jvanverthfd7bd452016-03-25 06:29:52 -0700120 return true;
121}
122
123bool GrVkExtensions::initDevice(uint32_t specVersion, VkInstance inst, VkPhysicalDevice physDev) {
124
125 GET_PROC_LOCAL(inst, EnumerateDeviceExtensionProperties);
126 GET_PROC_LOCAL(inst, EnumerateDeviceLayerProperties);
127
128 SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp;
129
130 if (!EnumerateDeviceExtensionProperties ||
131 !EnumerateDeviceLayerProperties) {
132 return false;
133 }
134
jvanverth633b3562016-03-23 11:01:22 -0700135 // device layers
jvanverthfd7bd452016-03-25 06:29:52 -0700136 uint32_t layerCount = 0;
137 VkResult res = EnumerateDeviceLayerProperties(physDev, &layerCount, nullptr);
jvanverth633b3562016-03-23 11:01:22 -0700138 if (VK_SUCCESS != res) {
139 return false;
140 }
jvanverthfd7bd452016-03-25 06:29:52 -0700141 VkLayerProperties* layers = new VkLayerProperties[layerCount];
142 res = EnumerateDeviceLayerProperties(physDev, &layerCount, layers);
jvanverth633b3562016-03-23 11:01:22 -0700143 if (VK_SUCCESS != res) {
egdaniel8af936d2016-04-07 10:17:47 -0700144 delete[] layers;
jvanverth633b3562016-03-23 11:01:22 -0700145 return false;
146 }
147 for (uint32_t i = 0; i < layerCount; ++i) {
148 if (specVersion >= layers[i].specVersion) {
149 fDeviceLayerStrings->push_back() = layers[i].layerName;
150 }
151 }
152 delete[] layers;
153 if (!fDeviceLayerStrings->empty()) {
154 SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp;
155 SkTQSort(&fDeviceLayerStrings->front(), &fDeviceLayerStrings->back(), cmp);
156 }
157
158 // device extensions
159 // via Vulkan implementation and implicitly enabled layers
jvanverthfd7bd452016-03-25 06:29:52 -0700160 uint32_t extensionCount = 0;
161 res = EnumerateDeviceExtensionProperties(physDev, nullptr, &extensionCount, nullptr);
jvanverth633b3562016-03-23 11:01:22 -0700162 if (VK_SUCCESS != res) {
163 return false;
164 }
jvanverthfd7bd452016-03-25 06:29:52 -0700165 VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
166 res = EnumerateDeviceExtensionProperties(physDev, nullptr, &extensionCount, extensions);
jvanverth633b3562016-03-23 11:01:22 -0700167 if (VK_SUCCESS != res) {
egdaniel8af936d2016-04-07 10:17:47 -0700168 delete[] extensions;
jvanverth633b3562016-03-23 11:01:22 -0700169 return false;
170 }
171 for (uint32_t i = 0; i < extensionCount; ++i) {
172 if (specVersion >= extensions[i].specVersion) {
173 fDeviceExtensionStrings->push_back() = extensions[i].extensionName;
174 }
175 }
176 delete[] extensions;
177 if (!fDeviceExtensionStrings->empty()) {
178 SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp;
179 SkTQSort(&fDeviceExtensionStrings->front(), &fDeviceExtensionStrings->back(), cmp);
180 }
181 // via explicitly enabled layers
182 layerCount = fDeviceLayerStrings->count();
183 for (uint32_t layerIndex = 0; layerIndex < layerCount; ++layerIndex) {
184 uint32_t extensionCount = 0;
jvanverthfd7bd452016-03-25 06:29:52 -0700185 res = EnumerateDeviceExtensionProperties(physDev,
186 (*fDeviceLayerStrings)[layerIndex].c_str(),
187 &extensionCount, nullptr);
jvanverth633b3562016-03-23 11:01:22 -0700188 if (VK_SUCCESS != res) {
189 return false;
190 }
191 VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
jvanverthfd7bd452016-03-25 06:29:52 -0700192 res = EnumerateDeviceExtensionProperties(physDev,
193 (*fDeviceLayerStrings)[layerIndex].c_str(),
194 &extensionCount, extensions);
jvanverth633b3562016-03-23 11:01:22 -0700195 if (VK_SUCCESS != res) {
egdaniel8af936d2016-04-07 10:17:47 -0700196 delete[] extensions;
jvanverth633b3562016-03-23 11:01:22 -0700197 return false;
198 }
199 for (uint32_t i = 0; i < extensionCount; ++i) {
200 // if not already in the list, add it
201 if (specVersion >= extensions[i].specVersion &&
202 find_string(*fDeviceExtensionStrings, extensions[i].extensionName) < 0) {
203 fDeviceExtensionStrings->push_back() = extensions[i].extensionName;
204 SkTQSort(&fDeviceExtensionStrings->front(), &fDeviceExtensionStrings->back(), cmp);
205 }
206 }
207 delete[] extensions;
208 }
jvanverthd2497f32016-03-18 12:39:05 -0700209
jvanverthd2497f32016-03-18 12:39:05 -0700210 return true;
211}
212
jvanverthd2497f32016-03-18 12:39:05 -0700213bool GrVkExtensions::hasInstanceExtension(const char ext[]) const {
jvanverthd2497f32016-03-18 12:39:05 -0700214 return find_string(*fInstanceExtensionStrings, ext) >= 0;
215}
216
217bool GrVkExtensions::hasDeviceExtension(const char ext[]) const {
jvanverthd2497f32016-03-18 12:39:05 -0700218 return find_string(*fDeviceExtensionStrings, ext) >= 0;
219}
220
221bool GrVkExtensions::hasInstanceLayer(const char ext[]) const {
jvanverthd2497f32016-03-18 12:39:05 -0700222 return find_string(*fInstanceLayerStrings, ext) >= 0;
223}
224
225bool GrVkExtensions::hasDeviceLayer(const char ext[]) const {
jvanverthd2497f32016-03-18 12:39:05 -0700226 return find_string(*fDeviceLayerStrings, ext) >= 0;
227}
228
jvanverthd2497f32016-03-18 12:39:05 -0700229void GrVkExtensions::print(const char* sep) const {
230 if (nullptr == sep) {
231 sep = " ";
232 }
233 int cnt = fInstanceExtensionStrings->count();
234 SkDebugf("Instance Extensions: ");
235 for (int i = 0; i < cnt; ++i) {
236 SkDebugf("%s%s", (*fInstanceExtensionStrings)[i].c_str(), (i < cnt - 1) ? sep : "");
237 }
238 cnt = fDeviceExtensionStrings->count();
239 SkDebugf("\nDevice Extensions: ");
240 for (int i = 0; i < cnt; ++i) {
241 SkDebugf("%s%s", (*fDeviceExtensionStrings)[i].c_str(), (i < cnt - 1) ? sep : "");
242 }
243 cnt = fInstanceLayerStrings->count();
244 SkDebugf("\nInstance Layers: ");
245 for (int i = 0; i < cnt; ++i) {
246 SkDebugf("%s%s", (*fInstanceLayerStrings)[i].c_str(), (i < cnt - 1) ? sep : "");
247 }
248 cnt = fDeviceLayerStrings->count();
249 SkDebugf("\nDevice Layers: ");
250 for (int i = 0; i < cnt; ++i) {
251 SkDebugf("%s%s", (*fDeviceLayerStrings)[i].c_str(), (i < cnt - 1) ? sep : "");
252 }
253}