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. 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. 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(F, inst, device) PFN_vk ## F F = (PFN_vk ## F) fGetProc("vk" #F, inst, device) 34 35 static uint32_t remove_patch_version(uint32_t specVersion) { 36 return (specVersion >> 12) << 12; 37 } 38 39 bool 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 49 SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp; 50 51 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; 71 } 72 } 73 delete[] layers; 74 if (!fInstanceLayerStrings->empty()) { 75 SkTQSort(&fInstanceLayerStrings->front(), &fInstanceLayerStrings->back(), cmp); 76 } 77 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 if (nonPatchVersion >= remove_patch_version(extensions[i].specVersion)) { 93 fInstanceExtensionStrings->push_back() = extensions[i].extensionName; 94 } 95 } 96 delete [] extensions; 97 // sort so we can search 98 if (!fInstanceExtensionStrings->empty()) { 99 SkTQSort(&fInstanceExtensionStrings->front(), &fInstanceExtensionStrings->back(), cmp); 100 } 101 // via explicitly enabled layers 102 layerCount = fInstanceLayerStrings->count(); 103 for (uint32_t layerIndex = 0; layerIndex < layerCount; ++layerIndex) { 104 uint32_t extensionCount = 0; 105 res = EnumerateInstanceExtensionProperties((*fInstanceLayerStrings)[layerIndex].c_str(), 106 &extensionCount, nullptr); 107 if (VK_SUCCESS != res) { 108 return false; 109 } 110 VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount]; 111 res = EnumerateInstanceExtensionProperties((*fInstanceLayerStrings)[layerIndex].c_str(), 112 &extensionCount, extensions); 113 if (VK_SUCCESS != res) { 114 delete[] extensions; 115 return false; 116 } 117 for (uint32_t i = 0; i < extensionCount; ++i) { 118 // if not already in the list, add it 119 if (nonPatchVersion >= remove_patch_version(extensions[i].specVersion) && 120 find_string(*fInstanceExtensionStrings, extensions[i].extensionName) < 0) { 121 fInstanceExtensionStrings->push_back() = extensions[i].extensionName; 122 SkTQSort(&fInstanceExtensionStrings->front(), &fInstanceExtensionStrings->back(), 123 cmp); 124 } 125 } 126 delete[] extensions; 127 } 128 129 return true; 130 } 131 132 bool GrVkExtensions::initDevice(uint32_t specVersion, VkInstance inst, VkPhysicalDevice physDev) { 133 if (fGetProc == nullptr) { 134 return false; 135 } 136 137 uint32_t nonPatchVersion = remove_patch_version(specVersion); 138 139 GET_PROC_LOCAL(EnumerateDeviceExtensionProperties, inst, VK_NULL_HANDLE); 140 GET_PROC_LOCAL(EnumerateDeviceLayerProperties, inst, VK_NULL_HANDLE); 141 142 SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp; 143 144 if (!EnumerateDeviceExtensionProperties || 145 !EnumerateDeviceLayerProperties) { 146 return false; 147 } 148 149 // device layers 150 uint32_t layerCount = 0; 151 VkResult res = EnumerateDeviceLayerProperties(physDev, &layerCount, nullptr); 152 if (VK_SUCCESS != res) { 153 return false; 154 } 155 VkLayerProperties* layers = new VkLayerProperties[layerCount]; 156 res = EnumerateDeviceLayerProperties(physDev, &layerCount, layers); 157 if (VK_SUCCESS != res) { 158 delete[] layers; 159 return false; 160 } 161 for (uint32_t i = 0; i < layerCount; ++i) { 162 if (nonPatchVersion >= remove_patch_version(layers[i].specVersion)) { 163 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 174 uint32_t extensionCount = 0; 175 res = EnumerateDeviceExtensionProperties(physDev, nullptr, &extensionCount, nullptr); 176 if (VK_SUCCESS != res) { 177 return false; 178 } 179 VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount]; 180 res = EnumerateDeviceExtensionProperties(physDev, nullptr, &extensionCount, extensions); 181 if (VK_SUCCESS != res) { 182 delete[] extensions; 183 return false; 184 } 185 for (uint32_t i = 0; i < extensionCount; ++i) { 186 if (nonPatchVersion >= remove_patch_version(extensions[i].specVersion)) { 187 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; 199 res = EnumerateDeviceExtensionProperties(physDev, 200 (*fDeviceLayerStrings)[layerIndex].c_str(), 201 &extensionCount, nullptr); 202 if (VK_SUCCESS != res) { 203 return false; 204 } 205 VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount]; 206 res = EnumerateDeviceExtensionProperties(physDev, 207 (*fDeviceLayerStrings)[layerIndex].c_str(), 208 &extensionCount, extensions); 209 if (VK_SUCCESS != res) { 210 delete[] extensions; 211 return false; 212 } 213 for (uint32_t i = 0; i < extensionCount; ++i) { 214 // if not already in the list, add it 215 if (nonPatchVersion >= remove_patch_version(extensions[i].specVersion) && 216 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 } 223 224 return true; 225 } 226 227 bool GrVkExtensions::hasInstanceExtension(const char ext[]) const { 228 return find_string(*fInstanceExtensionStrings, ext) >= 0; 229 } 230 231 bool GrVkExtensions::hasDeviceExtension(const char ext[]) const { 232 return find_string(*fDeviceExtensionStrings, ext) >= 0; 233 } 234 235 bool GrVkExtensions::hasInstanceLayer(const char ext[]) const { 236 return find_string(*fInstanceLayerStrings, ext) >= 0; 237 } 238 239 bool GrVkExtensions::hasDeviceLayer(const char ext[]) const { 240 return find_string(*fDeviceLayerStrings, ext) >= 0; 241 } 242 243 void 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 } 268