• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "include/gpu/vk/VulkanExtensions.h"
9 
10 #include "src/base/SkTSearch.h"
11 #include "src/base/SkTSort.h"
12 
13 namespace skgpu {
14 
15 // finds the index of ext in infos or a negative result if ext is not found.
find_info(const SkTArray<VulkanExtensions::Info> & infos,const char ext[])16 static int find_info(const SkTArray<VulkanExtensions::Info>& infos, const char ext[]) {
17     if (infos.empty()) {
18         return -1;
19     }
20     SkString extensionStr(ext);
21     VulkanExtensions::Info::Less less;
22     int idx = SkTSearch<VulkanExtensions::Info, SkString, VulkanExtensions::Info::Less>(
23             &infos.front(), infos.size(), extensionStr, sizeof(VulkanExtensions::Info),
24             less);
25     return idx;
26 }
27 
28 namespace { // This cannot be static because it is used as a template parameter.
extension_compare(const VulkanExtensions::Info & a,const VulkanExtensions::Info & b)29 inline bool extension_compare(const VulkanExtensions::Info& a, const VulkanExtensions::Info& b) {
30     return strcmp(a.fName.c_str(), b.fName.c_str()) < 0;
31 }
32 }  // namespace
33 
init(VulkanGetProc getProc,VkInstance instance,VkPhysicalDevice physDev,uint32_t instanceExtensionCount,const char * const * instanceExtensions,uint32_t deviceExtensionCount,const char * const * deviceExtensions)34 void VulkanExtensions::init(VulkanGetProc getProc,
35                             VkInstance instance,
36                             VkPhysicalDevice physDev,
37                             uint32_t instanceExtensionCount,
38                             const char* const* instanceExtensions,
39                             uint32_t deviceExtensionCount,
40                             const char* const* deviceExtensions) {
41     for (uint32_t i = 0; i < instanceExtensionCount; ++i) {
42         const char* extension = instanceExtensions[i];
43         // if not already in the list, add it
44         if (find_info(fExtensions, extension) < 0) {
45             fExtensions.push_back() = Info(extension);
46             SkTQSort(fExtensions.begin(), fExtensions.end(), extension_compare);
47         }
48     }
49     for (uint32_t i = 0; i < deviceExtensionCount; ++i) {
50         const char* extension = deviceExtensions[i];
51         // if not already in the list, add it
52         if (find_info(fExtensions, extension) < 0) {
53             fExtensions.push_back() = Info(extension);
54             SkTQSort(fExtensions.begin(), fExtensions.end(), extension_compare);
55         }
56     }
57     this->getSpecVersions(getProc, instance, physDev);
58 }
59 
60 #define GET_PROC(F, inst)                                                        \
61         PFN_vk##F grVk##F = (PFN_vk ## F) getProc("vk" #F, inst, VK_NULL_HANDLE)
62 
getSpecVersions(VulkanGetProc getProc,VkInstance instance,VkPhysicalDevice physDevice)63 void VulkanExtensions::getSpecVersions(VulkanGetProc getProc,
64                                        VkInstance instance,
65                                        VkPhysicalDevice physDevice) {
66     // We grab all the extensions for the VkInstance and VkDevice so we can look up what spec
67     // version each of the supported extensions are. We do not grab the extensions for layers
68     // because we don't know what layers the client has enabled and in general we don't do anything
69     // special for those extensions.
70 
71     if (instance == VK_NULL_HANDLE) {
72         return;
73     }
74     GET_PROC(EnumerateInstanceExtensionProperties, VK_NULL_HANDLE);
75     SkASSERT(grVkEnumerateInstanceExtensionProperties);
76 
77     VkResult res;
78     // instance extensions
79     uint32_t extensionCount = 0;
80     res = grVkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
81     if (VK_SUCCESS != res) {
82         return;
83     }
84     VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
85     res = grVkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions);
86     if (VK_SUCCESS != res) {
87         delete[] extensions;
88         return;
89     }
90     for (uint32_t i = 0; i < extensionCount; ++i) {
91         int idx = find_info(fExtensions, extensions[i].extensionName);
92         if (idx >= 0) {
93             fExtensions[idx].fSpecVersion = extensions[i].specVersion;
94         }
95     }
96     delete[] extensions;
97 
98     if (physDevice == VK_NULL_HANDLE) {
99         return;
100     }
101     GET_PROC(EnumerateDeviceExtensionProperties, instance);
102     SkASSERT(grVkEnumerateDeviceExtensionProperties);
103 
104     // device extensions
105     extensionCount = 0;
106     res = grVkEnumerateDeviceExtensionProperties(physDevice, nullptr, &extensionCount, nullptr);
107     if (VK_SUCCESS != res) {
108         return;
109     }
110     extensions = new VkExtensionProperties[extensionCount];
111     res = grVkEnumerateDeviceExtensionProperties(physDevice, nullptr, &extensionCount, extensions);
112     if (VK_SUCCESS != res) {
113         delete[] extensions;
114         return;
115     }
116     for (uint32_t i = 0; i < extensionCount; ++i) {
117         int idx = find_info(fExtensions, extensions[i].extensionName);
118         if (idx >= 0) {
119             fExtensions[idx].fSpecVersion = extensions[i].specVersion;
120         }
121     }
122     delete[] extensions;
123 }
124 
hasExtension(const char ext[],uint32_t minVersion) const125 bool VulkanExtensions::hasExtension(const char ext[], uint32_t minVersion) const {
126     int idx = find_info(fExtensions, ext);
127     return  idx >= 0 && fExtensions[idx].fSpecVersion >= minVersion;
128 }
129 
130 } // namespace skgpu
131