blob: 455027341c1af25f66da4e2821a80c5a0eeca42c [file] [log] [blame]
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "include/gpu/vk/VulkanExtensions.h"
#include "include/private/base/SkAssert.h"
#include "src/base/SkTSearch.h"
#include "src/base/SkTSort.h"
#include <utility>
using namespace skia_private;
namespace skgpu {
// finds the index of ext in infos or a negative result if ext is not found.
static int find_info(const TArray<VulkanExtensions::Info>& infos, const char ext[]) {
if (infos.empty()) {
return -1;
}
SkString extensionStr(ext);
VulkanExtensions::Info::Less less;
int idx = SkTSearch<VulkanExtensions::Info, SkString, VulkanExtensions::Info::Less>(
&infos.front(), infos.size(), extensionStr, sizeof(VulkanExtensions::Info),
less);
return idx;
}
namespace { // This cannot be static because it is used as a template parameter.
inline bool extension_compare(const VulkanExtensions::Info& a, const VulkanExtensions::Info& b) {
return strcmp(a.fName.c_str(), b.fName.c_str()) < 0;
}
} // namespace
void VulkanExtensions::init(VulkanGetProc getProc,
VkInstance instance,
VkPhysicalDevice physDev,
uint32_t instanceExtensionCount,
const char* const* instanceExtensions,
uint32_t deviceExtensionCount,
const char* const* deviceExtensions) {
for (uint32_t i = 0; i < instanceExtensionCount; ++i) {
const char* extension = instanceExtensions[i];
// if not already in the list, add it
if (find_info(fExtensions, extension) < 0) {
fExtensions.push_back() = Info(extension);
SkTQSort(fExtensions.begin(), fExtensions.end(), extension_compare);
}
}
for (uint32_t i = 0; i < deviceExtensionCount; ++i) {
const char* extension = deviceExtensions[i];
// if not already in the list, add it
if (find_info(fExtensions, extension) < 0) {
fExtensions.push_back() = Info(extension);
SkTQSort(fExtensions.begin(), fExtensions.end(), extension_compare);
}
}
this->getSpecVersions(std::move(getProc), instance, physDev);
}
#define GET_PROC(F, inst) \
PFN_vk##F grVk##F = (PFN_vk ## F) getProc("vk" #F, inst, VK_NULL_HANDLE)
void VulkanExtensions::getSpecVersions(const VulkanGetProc& getProc,
VkInstance instance,
VkPhysicalDevice physDevice) {
// We grab all the extensions for the VkInstance and VkDevice so we can look up what spec
// version each of the supported extensions are. We do not grab the extensions for layers
// because we don't know what layers the client has enabled and in general we don't do anything
// special for those extensions.
if (instance == VK_NULL_HANDLE) {
return;
}
GET_PROC(EnumerateInstanceExtensionProperties, VK_NULL_HANDLE);
SkASSERT(grVkEnumerateInstanceExtensionProperties);
VkResult res;
// instance extensions
uint32_t extensionCount = 0;
res = grVkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
if (VK_SUCCESS != res) {
return;
}
VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
res = grVkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions);
if (VK_SUCCESS != res) {
delete[] extensions;
return;
}
for (uint32_t i = 0; i < extensionCount; ++i) {
int idx = find_info(fExtensions, extensions[i].extensionName);
if (idx >= 0) {
fExtensions[idx].fSpecVersion = extensions[i].specVersion;
}
}
delete[] extensions;
if (physDevice == VK_NULL_HANDLE) {
return;
}
GET_PROC(EnumerateDeviceExtensionProperties, instance);
SkASSERT(grVkEnumerateDeviceExtensionProperties);
// device extensions
extensionCount = 0;
res = grVkEnumerateDeviceExtensionProperties(physDevice, nullptr, &extensionCount, nullptr);
if (VK_SUCCESS != res) {
return;
}
extensions = new VkExtensionProperties[extensionCount];
res = grVkEnumerateDeviceExtensionProperties(physDevice, nullptr, &extensionCount, extensions);
if (VK_SUCCESS != res) {
delete[] extensions;
return;
}
for (uint32_t i = 0; i < extensionCount; ++i) {
int idx = find_info(fExtensions, extensions[i].extensionName);
if (idx >= 0) {
fExtensions[idx].fSpecVersion = extensions[i].specVersion;
}
}
delete[] extensions;
}
bool VulkanExtensions::hasExtension(const char ext[], uint32_t minVersion) const {
int idx = find_info(fExtensions, ext);
return idx >= 0 && fExtensions[idx].fSpecVersion >= minVersion;
}
} // namespace skgpu