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. 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. 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 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 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 127 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