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