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(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