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
10 // Can remove this once we get rid of the extension flags.
11 #include "vk/GrVkBackendContext.h"
12
13 #include "SkTSearch.h"
14 #include "SkTSort.h"
15
16 // finds the index of ext in infos or a negative result if ext is not found.
find_info(const SkTArray<GrVkExtensions::Info> & infos,const char ext[])17 static int find_info(const SkTArray<GrVkExtensions::Info>& infos, const char ext[]) {
18 if (infos.empty()) {
19 return -1;
20 }
21 SkString extensionStr(ext);
22 GrVkExtensions::Info::Less less;
23 int idx = SkTSearch<GrVkExtensions::Info, SkString, GrVkExtensions::Info::Less>(
24 &infos.front(), infos.count(), extensionStr, sizeof(GrVkExtensions::Info),
25 less);
26 return idx;
27 }
28
29 namespace { // This cannot be static because it is used as a template parameter.
extension_compare(const GrVkExtensions::Info & a,const GrVkExtensions::Info & b)30 inline bool extension_compare(const GrVkExtensions::Info& a, const GrVkExtensions::Info& b) {
31 return strcmp(a.fName.c_str(), b.fName.c_str()) < 0;
32 }
33 }
34
init(GrVkGetProc getProc,VkInstance instance,VkPhysicalDevice physDev,uint32_t instanceExtensionCount,const char * const * instanceExtensions,uint32_t deviceExtensionCount,const char * const * deviceExtensions)35 void GrVkExtensions::init(GrVkGetProc getProc,
36 VkInstance instance,
37 VkPhysicalDevice physDev,
38 uint32_t instanceExtensionCount,
39 const char* const* instanceExtensions,
40 uint32_t deviceExtensionCount,
41 const char* const* deviceExtensions) {
42 SkTLessFunctionToFunctorAdaptor<GrVkExtensions::Info, extension_compare> cmp;
43
44 for (uint32_t i = 0; i < instanceExtensionCount; ++i) {
45 const char* extension = instanceExtensions[i];
46 // if not already in the list, add it
47 if (find_info(fExtensions, extension) < 0) {
48 fExtensions.push_back() = Info(extension);
49 SkTQSort(&fExtensions.front(), &fExtensions.back(), cmp);
50 }
51 }
52 for (uint32_t i = 0; i < deviceExtensionCount; ++i) {
53 const char* extension = deviceExtensions[i];
54 // if not already in the list, add it
55 if (find_info(fExtensions, extension) < 0) {
56 fExtensions.push_back() = Info(extension);
57 SkTQSort(&fExtensions.front(), &fExtensions.back(), cmp);
58 }
59 }
60 this->getSpecVersions(getProc, instance, physDev);
61 }
62
63 #define GET_PROC(F, inst) \
64 PFN_vk##F grVk##F = (PFN_vk ## F) getProc("vk" #F, inst, VK_NULL_HANDLE)
65
getSpecVersions(GrVkGetProc getProc,VkInstance instance,VkPhysicalDevice physDevice)66 void GrVkExtensions::getSpecVersions(GrVkGetProc getProc, VkInstance instance,
67 VkPhysicalDevice physDevice) {
68 // We grab all the extensions for the VkInstance and VkDevice so we can look up what spec
69 // version each of the supported extensions are. We do not grab the extensions for layers
70 // because we don't know what layers the client has enabled and in general we don't do anything
71 // special for those extensions.
72
73 if (instance == VK_NULL_HANDLE) {
74 return;
75 }
76 GET_PROC(EnumerateInstanceExtensionProperties, VK_NULL_HANDLE);
77 SkASSERT(grVkEnumerateInstanceExtensionProperties);
78
79 VkResult res;
80 // instance extensions
81 uint32_t extensionCount = 0;
82 res = grVkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
83 if (VK_SUCCESS != res) {
84 return;
85 }
86 VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
87 res = grVkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions);
88 if (VK_SUCCESS != res) {
89 delete[] extensions;
90 return;
91 }
92 for (uint32_t i = 0; i < extensionCount; ++i) {
93 int idx = find_info(fExtensions, extensions[i].extensionName);
94 if (idx >= 0) {
95 fExtensions[idx].fSpecVersion = extensions[i].specVersion;
96 }
97 }
98 delete[] extensions;
99
100 if (physDevice == VK_NULL_HANDLE) {
101 return;
102 }
103 GET_PROC(EnumerateDeviceExtensionProperties, instance);
104 SkASSERT(grVkEnumerateDeviceExtensionProperties);
105
106 // device extensions
107 extensionCount = 0;
108 res = grVkEnumerateDeviceExtensionProperties(physDevice, nullptr, &extensionCount, nullptr);
109 if (VK_SUCCESS != res) {
110 return;
111 }
112 extensions = new VkExtensionProperties[extensionCount];
113 res = grVkEnumerateDeviceExtensionProperties(physDevice, nullptr, &extensionCount, extensions);
114 if (VK_SUCCESS != res) {
115 delete[] extensions;
116 return;
117 }
118 for (uint32_t i = 0; i < extensionCount; ++i) {
119 int idx = find_info(fExtensions, extensions[i].extensionName);
120 if (idx >= 0) {
121 fExtensions[idx].fSpecVersion = extensions[i].specVersion;
122 }
123 }
124 delete[] extensions;
125 }
126
hasExtension(const char ext[],uint32_t minVersion) const127 bool GrVkExtensions::hasExtension(const char ext[], uint32_t minVersion) const {
128 int idx = find_info(fExtensions, ext);
129 return idx >= 0 && fExtensions[idx].fSpecVersion >= minVersion;
130 }
131
132