Home | History | Annotate | Download | only in vk
      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(inst, F) PFN_vk ## F F = (PFN_vk ## F) vkGetInstanceProcAddr(inst, "vk" #F)
     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     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 
    128 bool 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 
    219 bool GrVkExtensions::hasInstanceExtension(const char ext[]) const {
    220     return find_string(*fInstanceExtensionStrings, ext) >= 0;
    221 }
    222 
    223 bool GrVkExtensions::hasDeviceExtension(const char ext[]) const {
    224     return find_string(*fDeviceExtensionStrings, ext) >= 0;
    225 }
    226 
    227 bool GrVkExtensions::hasInstanceLayer(const char ext[]) const {
    228     return find_string(*fInstanceLayerStrings, ext) >= 0;
    229 }
    230 
    231 bool GrVkExtensions::hasDeviceLayer(const char ext[]) const {
    232     return find_string(*fDeviceLayerStrings, ext) >= 0;
    233 }
    234 
    235 void 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