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 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 33#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 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 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 (nonPatchVersion >= remove_patch_version(extensions[i].specVersion) && 118 find_string(*fInstanceExtensionStrings, extensions[i].extensionName) < 0) { 119 fInstanceExtensionStrings->push_back() = extensions[i].extensionName; 120 SkTQSort(&fInstanceExtensionStrings->front(), &fInstanceExtensionStrings->back(), 121 cmp); 122 } 123 } 124 delete[] extensions; 125 } 126 127 return true; 128} 129 130bool GrVkExtensions::initDevice(uint32_t specVersion, VkInstance inst, VkPhysicalDevice physDev) { 131 if (fGetProc == nullptr) { 132 return false; 133 } 134 135 uint32_t nonPatchVersion = remove_patch_version(specVersion); 136 137 GET_PROC_LOCAL(EnumerateDeviceExtensionProperties, inst, VK_NULL_HANDLE); 138 GET_PROC_LOCAL(EnumerateDeviceLayerProperties, inst, VK_NULL_HANDLE); 139 140 SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp; 141 142 if (!EnumerateDeviceExtensionProperties || 143 !EnumerateDeviceLayerProperties) { 144 return false; 145 } 146 147 // device layers 148 uint32_t layerCount = 0; 149 VkResult res = EnumerateDeviceLayerProperties(physDev, &layerCount, nullptr); 150 if (VK_SUCCESS != res) { 151 return false; 152 } 153 VkLayerProperties* layers = new VkLayerProperties[layerCount]; 154 res = EnumerateDeviceLayerProperties(physDev, &layerCount, layers); 155 if (VK_SUCCESS != res) { 156 delete[] layers; 157 return false; 158 } 159 for (uint32_t i = 0; i < layerCount; ++i) { 160 if (nonPatchVersion >= remove_patch_version(layers[i].specVersion)) { 161 fDeviceLayerStrings->push_back() = layers[i].layerName; 162 } 163 } 164 delete[] layers; 165 if (!fDeviceLayerStrings->empty()) { 166 SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp; 167 SkTQSort(&fDeviceLayerStrings->front(), &fDeviceLayerStrings->back(), cmp); 168 } 169 170 // device extensions 171 // via Vulkan implementation and implicitly enabled layers 172 uint32_t extensionCount = 0; 173 res = EnumerateDeviceExtensionProperties(physDev, nullptr, &extensionCount, nullptr); 174 if (VK_SUCCESS != res) { 175 return false; 176 } 177 VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount]; 178 res = EnumerateDeviceExtensionProperties(physDev, nullptr, &extensionCount, extensions); 179 if (VK_SUCCESS != res) { 180 delete[] extensions; 181 return false; 182 } 183 for (uint32_t i = 0; i < extensionCount; ++i) { 184 fDeviceExtensionStrings->push_back() = extensions[i].extensionName; 185 } 186 delete[] extensions; 187 if (!fDeviceExtensionStrings->empty()) { 188 SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp; 189 SkTQSort(&fDeviceExtensionStrings->front(), &fDeviceExtensionStrings->back(), cmp); 190 } 191 // via explicitly enabled layers 192 layerCount = fDeviceLayerStrings->count(); 193 for (uint32_t layerIndex = 0; layerIndex < layerCount; ++layerIndex) { 194 uint32_t extensionCount = 0; 195 res = EnumerateDeviceExtensionProperties(physDev, 196 (*fDeviceLayerStrings)[layerIndex].c_str(), 197 &extensionCount, nullptr); 198 if (VK_SUCCESS != res) { 199 return false; 200 } 201 VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount]; 202 res = EnumerateDeviceExtensionProperties(physDev, 203 (*fDeviceLayerStrings)[layerIndex].c_str(), 204 &extensionCount, extensions); 205 if (VK_SUCCESS != res) { 206 delete[] extensions; 207 return false; 208 } 209 for (uint32_t i = 0; i < extensionCount; ++i) { 210 // if not already in the list, add it 211 if (nonPatchVersion >= remove_patch_version(extensions[i].specVersion) && 212 find_string(*fDeviceExtensionStrings, extensions[i].extensionName) < 0) { 213 fDeviceExtensionStrings->push_back() = extensions[i].extensionName; 214 SkTQSort(&fDeviceExtensionStrings->front(), &fDeviceExtensionStrings->back(), cmp); 215 } 216 } 217 delete[] extensions; 218 } 219 220 return true; 221} 222 223bool GrVkExtensions::hasInstanceExtension(const char ext[]) const { 224 return find_string(*fInstanceExtensionStrings, ext) >= 0; 225} 226 227bool GrVkExtensions::hasDeviceExtension(const char ext[]) const { 228 return find_string(*fDeviceExtensionStrings, ext) >= 0; 229} 230 231bool GrVkExtensions::hasInstanceLayer(const char ext[]) const { 232 return find_string(*fInstanceLayerStrings, ext) >= 0; 233} 234 235bool GrVkExtensions::hasDeviceLayer(const char ext[]) const { 236 return find_string(*fDeviceLayerStrings, ext) >= 0; 237} 238 239void GrVkExtensions::print(const char* sep) const { 240 if (nullptr == sep) { 241 sep = " "; 242 } 243 int cnt = fInstanceExtensionStrings->count(); 244 SkDebugf("Instance Extensions: "); 245 for (int i = 0; i < cnt; ++i) { 246 SkDebugf("%s%s", (*fInstanceExtensionStrings)[i].c_str(), (i < cnt - 1) ? sep : ""); 247 } 248 cnt = fDeviceExtensionStrings->count(); 249 SkDebugf("\nDevice Extensions: "); 250 for (int i = 0; i < cnt; ++i) { 251 SkDebugf("%s%s", (*fDeviceExtensionStrings)[i].c_str(), (i < cnt - 1) ? sep : ""); 252 } 253 cnt = fInstanceLayerStrings->count(); 254 SkDebugf("\nInstance Layers: "); 255 for (int i = 0; i < cnt; ++i) { 256 SkDebugf("%s%s", (*fInstanceLayerStrings)[i].c_str(), (i < cnt - 1) ? sep : ""); 257 } 258 cnt = fDeviceLayerStrings->count(); 259 SkDebugf("\nDevice Layers: "); 260 for (int i = 0; i < cnt; ++i) { 261 SkDebugf("%s%s", (*fDeviceLayerStrings)[i].c_str(), (i < cnt - 1) ? sep : ""); 262 } 263} 264