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(inst, F) PFN_vk ## F F = (PFN_vk ## F) vkGetInstanceProcAddr(inst, "vk" #F) 34 35static uint32_t remove_patch_version(uint32_t specVersion) { 36 return (specVersion >> 12) << 12; 37} 38 39bool GrVkExtensions::initInstance(uint32_t specVersion) { 40 uint32_t nonPatchVersion = remove_patch_version(specVersion); 41 42 GET_PROC_LOCAL(nullptr, EnumerateInstanceExtensionProperties); 43 GET_PROC_LOCAL(nullptr, EnumerateInstanceLayerProperties); 44 45 SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp; 46 47 if (!EnumerateInstanceExtensionProperties || 48 !EnumerateInstanceLayerProperties) { 49 return false; 50 } 51 52 // instance layers 53 uint32_t layerCount = 0; 54 VkResult res = EnumerateInstanceLayerProperties(&layerCount, nullptr); 55 if (VK_SUCCESS != res) { 56 return false; 57 } 58 VkLayerProperties* layers = new VkLayerProperties[layerCount]; 59 res = EnumerateInstanceLayerProperties(&layerCount, layers); 60 if (VK_SUCCESS != res) { 61 delete[] layers; 62 return false; 63 } 64 for (uint32_t i = 0; i < layerCount; ++i) { 65 if (nonPatchVersion >= remove_patch_version(layers[i].specVersion)) { 66 fInstanceLayerStrings->push_back() = layers[i].layerName; 67 } 68 } 69 delete[] layers; 70 if (!fInstanceLayerStrings->empty()) { 71 SkTQSort(&fInstanceLayerStrings->front(), &fInstanceLayerStrings->back(), cmp); 72 } 73 74 // instance extensions 75 // via Vulkan implementation and implicitly enabled layers 76 uint32_t extensionCount = 0; 77 res = EnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr); 78 if (VK_SUCCESS != res) { 79 return false; 80 } 81 VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount]; 82 res = EnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions); 83 if (VK_SUCCESS != res) { 84 delete[] extensions; 85 return false; 86 } 87 for (uint32_t i = 0; i < extensionCount; ++i) { 88 if (nonPatchVersion >= remove_patch_version(extensions[i].specVersion)) { 89 fInstanceExtensionStrings->push_back() = extensions[i].extensionName; 90 } 91 } 92 delete [] extensions; 93 // sort so we can search 94 if (!fInstanceExtensionStrings->empty()) { 95 SkTQSort(&fInstanceExtensionStrings->front(), &fInstanceExtensionStrings->back(), cmp); 96 } 97 // via explicitly enabled layers 98 layerCount = fInstanceLayerStrings->count(); 99 for (uint32_t layerIndex = 0; layerIndex < layerCount; ++layerIndex) { 100 uint32_t extensionCount = 0; 101 res = EnumerateInstanceExtensionProperties((*fInstanceLayerStrings)[layerIndex].c_str(), 102 &extensionCount, nullptr); 103 if (VK_SUCCESS != res) { 104 return false; 105 } 106 VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount]; 107 res = EnumerateInstanceExtensionProperties((*fInstanceLayerStrings)[layerIndex].c_str(), 108 &extensionCount, extensions); 109 if (VK_SUCCESS != res) { 110 delete[] extensions; 111 return false; 112 } 113 for (uint32_t i = 0; i < extensionCount; ++i) { 114 // if not already in the list, add it 115 if (nonPatchVersion >= remove_patch_version(extensions[i].specVersion) && 116 find_string(*fInstanceExtensionStrings, extensions[i].extensionName) < 0) { 117 fInstanceExtensionStrings->push_back() = extensions[i].extensionName; 118 SkTQSort(&fInstanceExtensionStrings->front(), &fInstanceExtensionStrings->back(), 119 cmp); 120 } 121 } 122 delete[] extensions; 123 } 124 125 return true; 126} 127 128bool GrVkExtensions::initDevice(uint32_t specVersion, VkInstance inst, VkPhysicalDevice physDev) { 129 uint32_t nonPatchVersion = remove_patch_version(specVersion); 130 131 GET_PROC_LOCAL(inst, EnumerateDeviceExtensionProperties); 132 GET_PROC_LOCAL(inst, EnumerateDeviceLayerProperties); 133 134 SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp; 135 136 if (!EnumerateDeviceExtensionProperties || 137 !EnumerateDeviceLayerProperties) { 138 return false; 139 } 140 141 // device layers 142 uint32_t layerCount = 0; 143 VkResult res = EnumerateDeviceLayerProperties(physDev, &layerCount, nullptr); 144 if (VK_SUCCESS != res) { 145 return false; 146 } 147 VkLayerProperties* layers = new VkLayerProperties[layerCount]; 148 res = EnumerateDeviceLayerProperties(physDev, &layerCount, layers); 149 if (VK_SUCCESS != res) { 150 delete[] layers; 151 return false; 152 } 153 for (uint32_t i = 0; i < layerCount; ++i) { 154 if (nonPatchVersion >= remove_patch_version(layers[i].specVersion)) { 155 fDeviceLayerStrings->push_back() = layers[i].layerName; 156 } 157 } 158 delete[] layers; 159 if (!fDeviceLayerStrings->empty()) { 160 SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp; 161 SkTQSort(&fDeviceLayerStrings->front(), &fDeviceLayerStrings->back(), cmp); 162 } 163 164 // device extensions 165 // via Vulkan implementation and implicitly enabled layers 166 uint32_t extensionCount = 0; 167 res = EnumerateDeviceExtensionProperties(physDev, nullptr, &extensionCount, nullptr); 168 if (VK_SUCCESS != res) { 169 return false; 170 } 171 VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount]; 172 res = EnumerateDeviceExtensionProperties(physDev, nullptr, &extensionCount, extensions); 173 if (VK_SUCCESS != res) { 174 delete[] extensions; 175 return false; 176 } 177 for (uint32_t i = 0; i < extensionCount; ++i) { 178 if (nonPatchVersion >= remove_patch_version(extensions[i].specVersion)) { 179 fDeviceExtensionStrings->push_back() = extensions[i].extensionName; 180 } 181 } 182 delete[] extensions; 183 if (!fDeviceExtensionStrings->empty()) { 184 SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp; 185 SkTQSort(&fDeviceExtensionStrings->front(), &fDeviceExtensionStrings->back(), cmp); 186 } 187 // via explicitly enabled layers 188 layerCount = fDeviceLayerStrings->count(); 189 for (uint32_t layerIndex = 0; layerIndex < layerCount; ++layerIndex) { 190 uint32_t extensionCount = 0; 191 res = EnumerateDeviceExtensionProperties(physDev, 192 (*fDeviceLayerStrings)[layerIndex].c_str(), 193 &extensionCount, nullptr); 194 if (VK_SUCCESS != res) { 195 return false; 196 } 197 VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount]; 198 res = EnumerateDeviceExtensionProperties(physDev, 199 (*fDeviceLayerStrings)[layerIndex].c_str(), 200 &extensionCount, extensions); 201 if (VK_SUCCESS != res) { 202 delete[] extensions; 203 return false; 204 } 205 for (uint32_t i = 0; i < extensionCount; ++i) { 206 // if not already in the list, add it 207 if (nonPatchVersion >= remove_patch_version(extensions[i].specVersion) && 208 find_string(*fDeviceExtensionStrings, extensions[i].extensionName) < 0) { 209 fDeviceExtensionStrings->push_back() = extensions[i].extensionName; 210 SkTQSort(&fDeviceExtensionStrings->front(), &fDeviceExtensionStrings->back(), cmp); 211 } 212 } 213 delete[] extensions; 214 } 215 216 return true; 217} 218 219bool GrVkExtensions::hasInstanceExtension(const char ext[]) const { 220 return find_string(*fInstanceExtensionStrings, ext) >= 0; 221} 222 223bool GrVkExtensions::hasDeviceExtension(const char ext[]) const { 224 return find_string(*fDeviceExtensionStrings, ext) >= 0; 225} 226 227bool GrVkExtensions::hasInstanceLayer(const char ext[]) const { 228 return find_string(*fInstanceLayerStrings, ext) >= 0; 229} 230 231bool GrVkExtensions::hasDeviceLayer(const char ext[]) const { 232 return find_string(*fDeviceLayerStrings, ext) >= 0; 233} 234 235void GrVkExtensions::print(const char* sep) const { 236 if (nullptr == sep) { 237 sep = " "; 238 } 239 int cnt = fInstanceExtensionStrings->count(); 240 SkDebugf("Instance Extensions: "); 241 for (int i = 0; i < cnt; ++i) { 242 SkDebugf("%s%s", (*fInstanceExtensionStrings)[i].c_str(), (i < cnt - 1) ? sep : ""); 243 } 244 cnt = fDeviceExtensionStrings->count(); 245 SkDebugf("\nDevice Extensions: "); 246 for (int i = 0; i < cnt; ++i) { 247 SkDebugf("%s%s", (*fDeviceExtensionStrings)[i].c_str(), (i < cnt - 1) ? sep : ""); 248 } 249 cnt = fInstanceLayerStrings->count(); 250 SkDebugf("\nInstance Layers: "); 251 for (int i = 0; i < cnt; ++i) { 252 SkDebugf("%s%s", (*fInstanceLayerStrings)[i].c_str(), (i < cnt - 1) ? sep : ""); 253 } 254 cnt = fDeviceLayerStrings->count(); 255 SkDebugf("\nDevice Layers: "); 256 for (int i = 0; i < cnt; ++i) { 257 SkDebugf("%s%s", (*fDeviceLayerStrings)[i].c_str(), (i < cnt - 1) ? sep : ""); 258 } 259} 260