blob: 8fa99cf9fc073ae5dcd3e15b3bf53beedec0a39f [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 "vk/GrVkExtensions.h"
#include "vk/GrVkUtil.h"
#include "SkTSearch.h"
#include "SkTSort.h"
namespace { // This cannot be static because it is used as a template parameter.
inline bool extension_compare(const SkString& a, const SkString& b) {
return strcmp(a.c_str(), b.c_str()) < 0;
}
}
// finds the index of ext in strings or a negative result if ext is not found.
static int find_string(const SkTArray<SkString>& strings, const char ext[]) {
if (strings.empty()) {
return -1;
}
SkString extensionStr(ext);
int idx = SkTSearch<SkString, extension_compare>(&strings.front(),
strings.count(),
extensionStr,
sizeof(SkString));
return idx;
}
GrVkExtensions::GrVkExtensions(const GrVkExtensions& that)
: fInstanceExtensionStrings(new SkTArray<SkString>)
, fDeviceExtensionStrings(new SkTArray<SkString>)
, fInstanceLayerStrings(new SkTArray<SkString>)
, fDeviceLayerStrings(new SkTArray<SkString>) {
*this = that;
}
GrVkExtensions& GrVkExtensions::operator=(const GrVkExtensions& that) {
*fInstanceExtensionStrings = *that.fInstanceExtensionStrings;
*fDeviceExtensionStrings = *that.fDeviceExtensionStrings;
*fInstanceLayerStrings = *that.fInstanceLayerStrings;
*fDeviceLayerStrings = *that.fDeviceLayerStrings;
fInitialized = that.fInitialized;
return *this;
}
bool GrVkExtensions::init(
uint32_t specVersion,
PFN_vkEnumerateInstanceExtensionProperties enumerateInstanceExtensionProperties,
PFN_vkEnumerateDeviceExtensionProperties enumerateDeviceExtensionProperties,
PFN_vkEnumerateInstanceLayerProperties enumerateInstanceLayerProperties,
PFN_vkEnumerateDeviceLayerProperties enumerateDeviceLayerProperties) {
fInitialized = false;
this->reset();
if (!enumerateInstanceExtensionProperties ||
!enumerateDeviceExtensionProperties ||
!enumerateInstanceLayerProperties ||
!enumerateDeviceLayerProperties) {
return false;
}
// instance extensions
uint32_t extensionCount = 0;
VkResult res = enumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
res = enumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions);
fInstanceExtensionStrings->push_back_n(extensionCount);
for (uint32_t i = 0; i < extensionCount; ++i) {
if (specVersion >= extensions[i].specVersion) {
(*fInstanceExtensionStrings)[i] = extensions[i].extensionName;
}
}
delete [] extensions;
if (!fInstanceExtensionStrings->empty()) {
SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp;
SkTQSort(&fInstanceExtensionStrings->front(), &fInstanceExtensionStrings->back(), cmp);
}
fInitialized = true;
return true;
}
bool GrVkExtensions::hasInstanceExtension(const char ext[]) const {
SkASSERT(fInitialized);
return find_string(*fInstanceExtensionStrings, ext) >= 0;
}
bool GrVkExtensions::hasDeviceExtension(const char ext[]) const {
SkASSERT(fInitialized);
return find_string(*fDeviceExtensionStrings, ext) >= 0;
}
bool GrVkExtensions::hasInstanceLayer(const char ext[]) const {
SkASSERT(fInitialized);
return find_string(*fInstanceLayerStrings, ext) >= 0;
}
bool GrVkExtensions::hasDeviceLayer(const char ext[]) const {
SkASSERT(fInitialized);
return find_string(*fDeviceLayerStrings, ext) >= 0;
}
bool GrVkExtensions::removeInstanceExtension(const char ext[]) {
SkASSERT(fInitialized);
int idx = find_string(*fInstanceExtensionStrings, ext);
if (idx >= 0) {
// This is not terribly effecient but we really only expect this function to be called at
// most a handful of times when our test programs start.
SkAutoTDelete< SkTArray<SkString> > oldStrings(fInstanceExtensionStrings.release());
fInstanceExtensionStrings.reset(new SkTArray<SkString>(oldStrings->count() - 1));
fInstanceExtensionStrings->push_back_n(idx, &oldStrings->front());
fInstanceExtensionStrings->push_back_n(oldStrings->count() - idx-1, &(*oldStrings)[idx]+1);
return true;
} else {
return false;
}
}
bool GrVkExtensions::removeDeviceExtension(const char ext[]) {
SkASSERT(fInitialized);
int idx = find_string(*fDeviceExtensionStrings, ext);
if (idx >= 0) {
// This is not terribly effecient but we really only expect this function to be called at
// most a handful of times when our test programs start.
SkAutoTDelete< SkTArray<SkString> > oldStrings(fDeviceExtensionStrings.release());
fDeviceExtensionStrings.reset(new SkTArray<SkString>(oldStrings->count() - 1));
fDeviceExtensionStrings->push_back_n(idx, &oldStrings->front());
fDeviceExtensionStrings->push_back_n(oldStrings->count() - idx-1, &(*oldStrings)[idx] + 1);
return true;
}
else {
return false;
}
}
bool GrVkExtensions::removeInstanceLayer(const char ext[]) {
SkASSERT(fInitialized);
int idx = find_string(*fInstanceLayerStrings, ext);
if (idx >= 0) {
// This is not terribly effecient but we really only expect this function to be called at
// most a handful of times when our test programs start.
SkAutoTDelete< SkTArray<SkString> > oldStrings(fInstanceLayerStrings.release());
fInstanceLayerStrings.reset(new SkTArray<SkString>(oldStrings->count() - 1));
fInstanceLayerStrings->push_back_n(idx, &oldStrings->front());
fInstanceLayerStrings->push_back_n(oldStrings->count() - idx - 1, &(*oldStrings)[idx] + 1);
return true;
}
else {
return false;
}
}
bool GrVkExtensions::removeDeviceLayer(const char ext[]) {
SkASSERT(fInitialized);
int idx = find_string(*fDeviceLayerStrings, ext);
if (idx >= 0) {
// This is not terribly effecient but we really only expect this function to be called at
// most a handful of times when our test programs start.
SkAutoTDelete< SkTArray<SkString> > oldStrings(fDeviceLayerStrings.release());
fDeviceLayerStrings.reset(new SkTArray<SkString>(oldStrings->count() - 1));
fDeviceLayerStrings->push_back_n(idx, &oldStrings->front());
fDeviceLayerStrings->push_back_n(oldStrings->count() - idx - 1, &(*oldStrings)[idx] + 1);
return true;
}
else {
return false;
}
}
void GrVkExtensions::addInstanceExtension(const char ext[]) {
int idx = find_string(*fInstanceExtensionStrings, ext);
if (idx < 0) {
// This is not the most effecient approach since we end up doing a full sort of the
// extensions after the add
fInstanceExtensionStrings->push_back().set(ext);
SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp;
SkTQSort(&fInstanceExtensionStrings->front(), &fInstanceExtensionStrings->back(), cmp);
}
}
void GrVkExtensions::addDeviceExtension(const char ext[]) {
int idx = find_string(*fDeviceExtensionStrings, ext);
if (idx < 0) {
// This is not the most effecient approach since we end up doing a full sort of the
// extensions after the add
fDeviceExtensionStrings->push_back().set(ext);
SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp;
SkTQSort(&fDeviceExtensionStrings->front(), &fDeviceExtensionStrings->back(), cmp);
}
}
void GrVkExtensions::addInstanceLayer(const char ext[]) {
int idx = find_string(*fInstanceLayerStrings, ext);
if (idx < 0) {
// This is not the most effecient approach since we end up doing a full sort of the
// extensions after the add
fInstanceLayerStrings->push_back().set(ext);
SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp;
SkTQSort(&fInstanceLayerStrings->front(), &fInstanceLayerStrings->back(), cmp);
}
}
void GrVkExtensions::addDeviceLayer(const char ext[]) {
int idx = find_string(*fDeviceLayerStrings, ext);
if (idx < 0) {
// This is not the most effecient approach since we end up doing a full sort of the
// extensions after the add
fDeviceLayerStrings->push_back().set(ext);
SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp;
SkTQSort(&fDeviceLayerStrings->front(), &fDeviceLayerStrings->back(), cmp);
}
}
void GrVkExtensions::print(const char* sep) const {
if (nullptr == sep) {
sep = " ";
}
int cnt = fInstanceExtensionStrings->count();
SkDebugf("Instance Extensions: ");
for (int i = 0; i < cnt; ++i) {
SkDebugf("%s%s", (*fInstanceExtensionStrings)[i].c_str(), (i < cnt - 1) ? sep : "");
}
cnt = fDeviceExtensionStrings->count();
SkDebugf("\nDevice Extensions: ");
for (int i = 0; i < cnt; ++i) {
SkDebugf("%s%s", (*fDeviceExtensionStrings)[i].c_str(), (i < cnt - 1) ? sep : "");
}
cnt = fInstanceLayerStrings->count();
SkDebugf("\nInstance Layers: ");
for (int i = 0; i < cnt; ++i) {
SkDebugf("%s%s", (*fInstanceLayerStrings)[i].c_str(), (i < cnt - 1) ? sep : "");
}
cnt = fDeviceLayerStrings->count();
SkDebugf("\nDevice Layers: ");
for (int i = 0; i < cnt; ++i) {
SkDebugf("%s%s", (*fDeviceLayerStrings)[i].c_str(), (i < cnt - 1) ? sep : "");
}
}