Enable extension support and debug layer.
BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1785813002 TBR=bsalomon@google.com Review URL: https://codereview.chromium.org/1785813002
This commit is contained in:
parent
e820dfebbc
commit
d2497f35ce
@ -447,6 +447,8 @@
|
||||
'<(skia_src_path)/gpu/vk/GrVkCommandBuffer.h',
|
||||
'<(skia_src_path)/gpu/vk/GrVkDescriptorPool.cpp',
|
||||
'<(skia_src_path)/gpu/vk/GrVkDescriptorPool.h',
|
||||
'<(skia_src_path)/gpu/vk/GrVkExtensions.cpp',
|
||||
'<(skia_src_path)/gpu/vk/GrVkExtensions.h',
|
||||
'<(skia_src_path)/gpu/vk/GrVkFramebuffer.cpp',
|
||||
'<(skia_src_path)/gpu/vk/GrVkFramebuffer.h',
|
||||
'<(skia_src_path)/gpu/vk/GrVkGpu.cpp',
|
||||
|
@ -10,6 +10,8 @@
|
||||
|
||||
#include "SkRefCnt.h"
|
||||
|
||||
#include "GrVkExtensions.h"
|
||||
|
||||
#include "vulkan/vulkan.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -54,6 +56,21 @@ public:
|
||||
// function pointers have been initialized for Vulkan version.
|
||||
bool validate() const;
|
||||
|
||||
GrVkExtensions fExtensions;
|
||||
|
||||
bool hasInstanceExtension(const char ext[]) const {
|
||||
return fExtensions.hasInstanceExtension(ext);
|
||||
}
|
||||
bool hasDeviceExtension(const char ext[]) const {
|
||||
return fExtensions.hasDeviceExtension(ext);
|
||||
}
|
||||
bool hasInstanceLayer(const char ext[]) const {
|
||||
return fExtensions.hasInstanceLayer(ext);
|
||||
}
|
||||
bool hasDeviceLayer(const char ext[]) const {
|
||||
return fExtensions.hasDeviceLayer(ext);
|
||||
}
|
||||
|
||||
/**
|
||||
* The function pointers are in a struct so that we can have a compiler generated assignment
|
||||
* operator.
|
||||
@ -212,7 +229,11 @@ public:
|
||||
VkPtr<PFN_vkGetDisplayPlaneCapabilitiesKHR> fGetDisplayPlaneCapabilitiesKHR;
|
||||
VkPtr<PFN_vkCreateDisplayPlaneSurfaceKHR> fCreateDisplayPlaneSurfaceKHR;
|
||||
VkPtr<PFN_vkCreateSharedSwapchainsKHR> fCreateSharedSwapchainsKHR;
|
||||
VkPtr<PFN_vkCreateDebugReportCallbackEXT> fCreateDebugReportCallbackEXT;
|
||||
VkPtr<PFN_vkDebugReportMessageEXT> fDebugReportMessageEXT;
|
||||
VkPtr<PFN_vkDestroyDebugReportCallbackEXT> fDestroyDebugReportCallbackEXT;
|
||||
} fFunctions;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
252
src/gpu/vk/GrVkExtensions.cpp
Normal file
252
src/gpu/vk/GrVkExtensions.cpp
Normal file
@ -0,0 +1,252 @@
|
||||
/*
|
||||
* 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 : "");
|
||||
}
|
||||
}
|
92
src/gpu/vk/GrVkExtensions.h
Normal file
92
src/gpu/vk/GrVkExtensions.h
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2016 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef GrVkExtensions_DEFINED
|
||||
#define GrVkExtensions_DEFINED
|
||||
|
||||
#include "../../private/SkTArray.h"
|
||||
#include "SkString.h"
|
||||
#include "vulkan/vulkan.h"
|
||||
|
||||
/**
|
||||
* This helper queries the current Vulkan context for its extensions and layers, remembers them,
|
||||
* and can be queried. It supports queries for both instance and device extensions and layers.
|
||||
*/
|
||||
class SK_API GrVkExtensions {
|
||||
public:
|
||||
GrVkExtensions() : fInitialized(false)
|
||||
, fInstanceExtensionStrings(new SkTArray<SkString>)
|
||||
, fDeviceExtensionStrings(new SkTArray<SkString>)
|
||||
, fInstanceLayerStrings(new SkTArray<SkString>)
|
||||
, fDeviceLayerStrings(new SkTArray<SkString>) {}
|
||||
|
||||
GrVkExtensions(const GrVkExtensions&);
|
||||
|
||||
GrVkExtensions& operator=(const GrVkExtensions&);
|
||||
|
||||
void swap(GrVkExtensions* that) {
|
||||
fInstanceExtensionStrings.swap(that->fInstanceExtensionStrings);
|
||||
fDeviceExtensionStrings.swap(that->fDeviceExtensionStrings);
|
||||
fInstanceLayerStrings.swap(that->fInstanceLayerStrings);
|
||||
fDeviceLayerStrings.swap(that->fDeviceLayerStrings);
|
||||
|
||||
SkTSwap(fInitialized, that->fInitialized);
|
||||
}
|
||||
|
||||
/**
|
||||
* We sometimes need to use this class without having yet created a GrVkInterface.
|
||||
*/
|
||||
bool init(uint32_t specVersion,
|
||||
PFN_vkEnumerateInstanceExtensionProperties enumerateInstanceExtensionProperties,
|
||||
PFN_vkEnumerateDeviceExtensionProperties enumerateDeviceExtensionProperties,
|
||||
PFN_vkEnumerateInstanceLayerProperties enumerateInstanceLayerProperties,
|
||||
PFN_vkEnumerateDeviceLayerProperties enumerateDeviceLayerProperties);
|
||||
|
||||
bool isInitialized() const { return fInitialized; }
|
||||
|
||||
/**
|
||||
* Queries whether an extension or layer is present. Will fail if init() has not been called.
|
||||
*/
|
||||
bool hasInstanceExtension(const char[]) const;
|
||||
bool hasDeviceExtension(const char[]) const;
|
||||
bool hasInstanceLayer(const char[]) const;
|
||||
bool hasDeviceLayer(const char[]) const;
|
||||
|
||||
/**
|
||||
* Removes an extension or layer if present. Returns true if it was present before the call.
|
||||
*/
|
||||
bool removeInstanceExtension(const char[]);
|
||||
bool removeDeviceExtension(const char[]);
|
||||
bool removeInstanceLayer(const char[]);
|
||||
bool removeDeviceLayer(const char[]);
|
||||
|
||||
/**
|
||||
* Adds an extension or layer to list
|
||||
*/
|
||||
void addInstanceExtension(const char[]);
|
||||
void addDeviceExtension(const char[]);
|
||||
void addInstanceLayer(const char[]);
|
||||
void addDeviceLayer(const char[]);
|
||||
|
||||
void reset() {
|
||||
fInstanceExtensionStrings->reset();
|
||||
fDeviceExtensionStrings->reset();
|
||||
fInstanceLayerStrings->reset();
|
||||
fDeviceLayerStrings->reset();
|
||||
}
|
||||
|
||||
void print(const char* sep = "\n") const;
|
||||
|
||||
private:
|
||||
bool fInitialized;
|
||||
SkAutoTDelete<SkTArray<SkString> > fInstanceExtensionStrings;
|
||||
SkAutoTDelete<SkTArray<SkString> > fDeviceExtensionStrings;
|
||||
SkAutoTDelete<SkTArray<SkString> > fInstanceLayerStrings;
|
||||
SkAutoTDelete<SkTArray<SkString> > fDeviceLayerStrings;
|
||||
};
|
||||
|
||||
#endif
|
@ -43,6 +43,124 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Stuff used to set up a GrVkGpu secrectly for now.
|
||||
|
||||
|
||||
#ifdef ENABLE_VK_LAYERS
|
||||
VKAPI_ATTR VkBool32 VKAPI_CALL DebugReportCallback(
|
||||
VkDebugReportFlagsEXT flags,
|
||||
VkDebugReportObjectTypeEXT objectType,
|
||||
uint64_t object,
|
||||
size_t location,
|
||||
int32_t messageCode,
|
||||
const char* pLayerPrefix,
|
||||
const char* pMessage,
|
||||
void* pUserData) {
|
||||
if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
|
||||
SkDebugf("Vulkan error [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
|
||||
} else if (flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
|
||||
SkDebugf("Vulkan warning [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
|
||||
} else if (flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) {
|
||||
SkDebugf("Vulkan perf warning [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
|
||||
} else {
|
||||
SkDebugf("Vulkan info/debug [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
|
||||
}
|
||||
return VK_FALSE;
|
||||
}
|
||||
|
||||
const char* kEnabledLayerNames[] = {
|
||||
// elements of VK_LAYER_LUNARG_standard_validation
|
||||
"VK_LAYER_LUNARG_threading",
|
||||
"VK_LAYER_LUNARG_param_checker",
|
||||
"VK_LAYER_LUNARG_device_limits",
|
||||
"VK_LAYER_LUNARG_object_tracker",
|
||||
"VK_LAYER_LUNARG_image",
|
||||
"VK_LAYER_LUNARG_mem_tracker",
|
||||
"VK_LAYER_LUNARG_draw_state",
|
||||
"VK_LAYER_LUNARG_swapchain",
|
||||
"VK_LAYER_GOOGLE_unique_objects",
|
||||
// not included in standard_validation
|
||||
//"VK_LAYER_LUNARG_api_dump",
|
||||
};
|
||||
const char* kEnabledInstanceExtensionNames[] = {
|
||||
VK_EXT_DEBUG_REPORT_EXTENSION_NAME
|
||||
};
|
||||
|
||||
bool verify_instance_layers() {
|
||||
// make sure we can actually use the extensions and layers above
|
||||
uint32_t extensionCount;
|
||||
VkResult res = vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
|
||||
if (VK_SUCCESS != res) {
|
||||
return false;
|
||||
}
|
||||
VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
|
||||
res = vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions);
|
||||
if (VK_SUCCESS != res) {
|
||||
return false;
|
||||
}
|
||||
int instanceExtensionsFound = 0;
|
||||
for (uint32_t j = 0; j < ARRAYSIZE(kEnabledInstanceExtensionNames); ++j) {
|
||||
for (uint32_t i = 0; i < extensionCount; ++i) {
|
||||
if (!strncmp(extensions[i].extensionName, kEnabledInstanceExtensionNames[j],
|
||||
strlen(kEnabledInstanceExtensionNames[j]))) {
|
||||
++instanceExtensionsFound;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
delete[] extensions;
|
||||
|
||||
uint32_t layerCount;
|
||||
res = vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
|
||||
if (VK_SUCCESS != res) {
|
||||
return false;
|
||||
}
|
||||
VkLayerProperties* layers = new VkLayerProperties[layerCount];
|
||||
res = vkEnumerateInstanceLayerProperties(&layerCount, layers);
|
||||
if (VK_SUCCESS != res) {
|
||||
return false;
|
||||
}
|
||||
int instanceLayersFound = 0;
|
||||
for (uint32_t j = 0; j < ARRAYSIZE(kEnabledLayerNames); ++j) {
|
||||
for (uint32_t i = 0; i < layerCount; ++i) {
|
||||
if (!strncmp(layers[i].layerName, kEnabledLayerNames[j],
|
||||
strlen(kEnabledLayerNames[j]))) {
|
||||
++instanceLayersFound;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
delete[] layers;
|
||||
|
||||
return instanceExtensionsFound == ARRAYSIZE(kEnabledInstanceExtensionNames) &&
|
||||
instanceLayersFound == ARRAYSIZE(kEnabledLayerNames);
|
||||
}
|
||||
|
||||
bool verify_device_layers(VkPhysicalDevice physDev) {
|
||||
uint32_t layerCount;
|
||||
VkResult res = vkEnumerateDeviceLayerProperties(physDev, &layerCount, nullptr);
|
||||
if (VK_SUCCESS != res) {
|
||||
return false;
|
||||
}
|
||||
VkLayerProperties* layers = new VkLayerProperties[layerCount];
|
||||
res = vkEnumerateDeviceLayerProperties(physDev, &layerCount, layers);
|
||||
if (VK_SUCCESS != res) {
|
||||
return false;
|
||||
}
|
||||
int deviceLayersFound = 0;
|
||||
for (uint32_t j = 0; j < ARRAYSIZE(kEnabledLayerNames); ++j) {
|
||||
for (uint32_t i = 0; i < layerCount; ++i) {
|
||||
if (!strncmp(layers[i].layerName, kEnabledLayerNames[j],
|
||||
strlen(kEnabledLayerNames[j]))) {
|
||||
++deviceLayersFound;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
delete[] layers;
|
||||
|
||||
return deviceLayersFound == ARRAYSIZE(kEnabledLayerNames);
|
||||
}
|
||||
#endif
|
||||
|
||||
// For now the VkGpuCreate is using the same signature as GL. This is mostly for ease of
|
||||
// hiding this code from offical skia. In the end the VkGpuCreate will not take a GrBackendContext
|
||||
// and mostly likely would take an optional device and queues to use.
|
||||
@ -62,18 +180,33 @@ GrGpu* vk_gpu_create(GrBackendContext backendContext, const GrContextOptions& op
|
||||
0, // applicationVersion
|
||||
"vktest", // pEngineName
|
||||
0, // engineVerison
|
||||
VK_API_VERSION, // apiVersion
|
||||
kGrVkMinimumVersion, // apiVersion
|
||||
};
|
||||
|
||||
const char** enabledLayerNames = nullptr;
|
||||
int enabledLayerCount = 0;
|
||||
const char** enabledInstanceExtensionNames = nullptr;
|
||||
int enabledInstanceExtensionCount = 0;
|
||||
#ifdef ENABLE_VK_LAYERS
|
||||
if (verify_instance_layers()) {
|
||||
enabledLayerNames = kEnabledLayerNames;
|
||||
enabledLayerCount = ARRAYSIZE(kEnabledLayerNames);
|
||||
enabledInstanceExtensionNames = kEnabledInstanceExtensionNames;
|
||||
enabledInstanceExtensionCount = ARRAYSIZE(kEnabledInstanceExtensionNames);
|
||||
}
|
||||
#endif
|
||||
|
||||
const VkInstanceCreateInfo instance_create = {
|
||||
VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // sType
|
||||
nullptr, // pNext
|
||||
0, // flags
|
||||
&app_info, // pApplicationInfo
|
||||
0, // enabledLayerNameCount
|
||||
nullptr, // ppEnabledLayerNames
|
||||
0, // enabledExtensionNameCount
|
||||
nullptr, // ppEnabledExtensionNames
|
||||
enabledLayerCount, // enabledLayerNameCount
|
||||
enabledLayerNames, // ppEnabledLayerNames
|
||||
enabledInstanceExtensionCount, // enabledExtensionNameCount
|
||||
enabledInstanceExtensionNames, // ppEnabledExtensionNames
|
||||
};
|
||||
|
||||
err = vkCreateInstance(&instance_create, nullptr, &inst);
|
||||
if (err < 0) {
|
||||
SkDebugf("vkCreateInstanced failed: %d\n", err);
|
||||
@ -116,6 +249,14 @@ GrGpu* vk_gpu_create(GrBackendContext backendContext, const GrContextOptions& op
|
||||
}
|
||||
SkASSERT(graphicsQueueIndex < queueCount);
|
||||
|
||||
#ifdef ENABLE_VK_LAYERS
|
||||
// unlikely that the device will have different layers than the instance, but good to check
|
||||
if (!verify_device_layers(physDev)) {
|
||||
enabledLayerNames = nullptr;
|
||||
enabledLayerCount = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
float queuePriorities[1] = { 0.0 };
|
||||
const VkDeviceQueueCreateInfo queueInfo = {
|
||||
VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
|
||||
@ -131,8 +272,8 @@ GrGpu* vk_gpu_create(GrBackendContext backendContext, const GrContextOptions& op
|
||||
0, // VkDeviceCreateFlags
|
||||
1, // queueCreateInfoCount
|
||||
&queueInfo, // pQueueCreateInfos
|
||||
0, // layerCount
|
||||
nullptr, // ppEnabledLayerNames
|
||||
enabledLayerCount, // layerCount
|
||||
enabledLayerNames, // ppEnabledLayerNames
|
||||
0, // extensionCount
|
||||
nullptr, // ppEnabledExtensionNames
|
||||
nullptr // ppEnabledFeatures
|
||||
@ -188,6 +329,25 @@ GrVkGpu::GrVkGpu(GrContext* context, const GrContextOptions& options,
|
||||
fCurrentCmdBuffer->begin(this);
|
||||
VK_CALL(GetPhysicalDeviceMemoryProperties(physDev, &fPhysDevMemProps));
|
||||
|
||||
#ifdef ENABLE_VK_LAYERS
|
||||
if (fInterface->hasInstanceExtension(VK_EXT_DEBUG_REPORT_EXTENSION_NAME)) {
|
||||
/* Setup callback creation information */
|
||||
VkDebugReportCallbackCreateInfoEXT callbackCreateInfo;
|
||||
callbackCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
|
||||
callbackCreateInfo.pNext = nullptr;
|
||||
callbackCreateInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT |
|
||||
VK_DEBUG_REPORT_WARNING_BIT_EXT |
|
||||
//VK_DEBUG_REPORT_INFORMATION_BIT_EXT |
|
||||
//VK_DEBUG_REPORT_DEBUG_BIT_EXT |
|
||||
VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
|
||||
callbackCreateInfo.pfnCallback = &DebugReportCallback;
|
||||
callbackCreateInfo.pUserData = nullptr;
|
||||
|
||||
/* Register the callback */
|
||||
GR_VK_CALL_ERRCHECK(fInterface, CreateDebugReportCallbackEXT(inst, &callbackCreateInfo,
|
||||
nullptr, &fCallback));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
GrVkGpu::~GrVkGpu() {
|
||||
@ -202,6 +362,10 @@ GrVkGpu::~GrVkGpu() {
|
||||
// must call this just before we destroy the VkDevice
|
||||
fResourceProvider.destroyResources();
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
VK_CALL(DestroyDebugReportCallbackEXT(fVkInstance, fCallback, nullptr));
|
||||
#endif
|
||||
|
||||
VK_CALL(DestroyCommandPool(fDevice, fCmdPool, nullptr));
|
||||
VK_CALL(DestroyDevice(fDevice, nullptr));
|
||||
VK_CALL(DestroyInstance(fVkInstance, nullptr));
|
||||
|
@ -30,6 +30,10 @@ class GrVkRenderPass;
|
||||
class GrVkTexture;
|
||||
struct GrVkInterface;
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
#define ENABLE_VK_LAYERS
|
||||
#endif
|
||||
|
||||
class GrVkGpu : public GrGpu {
|
||||
public:
|
||||
// Currently passing in the inst so that we can properly delete it when we are done.
|
||||
@ -218,6 +222,11 @@ private:
|
||||
GrVkCommandBuffer* fCurrentCmdBuffer;
|
||||
GrVkResourceProvider fResourceProvider;
|
||||
|
||||
#ifdef ENABLE_VK_LAYERS
|
||||
// For reporting validation layer errors
|
||||
VkDebugReportCallbackEXT fCallback;
|
||||
#endif
|
||||
|
||||
// Shaderc compiler used for compiling glsl in spirv. We only want to create the compiler once
|
||||
// since there is significant overhead to the first compile of any compiler.
|
||||
shaderc_compiler_t fCompiler;
|
||||
|
@ -6,14 +6,30 @@
|
||||
*/
|
||||
|
||||
#include "vk/GrVkInterface.h"
|
||||
#include "vk/GrVkUtil.h"
|
||||
|
||||
GrVkInterface::GrVkInterface() {
|
||||
}
|
||||
|
||||
#define GET_PROC(F) functions->f ## F = (PFN_vk ## F) vkGetInstanceProcAddr(instance, "vk" #F)
|
||||
#define GET_PROC_LOCAL(inst, F) PFN_vk ## F F = (PFN_vk ## F) vkGetInstanceProcAddr(inst, "vk" #F)
|
||||
|
||||
const GrVkInterface* GrVkCreateInterface(VkInstance instance) {
|
||||
|
||||
GET_PROC_LOCAL(nullptr, EnumerateInstanceExtensionProperties);
|
||||
GET_PROC_LOCAL(instance, EnumerateDeviceExtensionProperties);
|
||||
GET_PROC_LOCAL(nullptr, EnumerateInstanceLayerProperties);
|
||||
GET_PROC_LOCAL(instance, EnumerateDeviceLayerProperties);
|
||||
|
||||
GrVkExtensions extensions;
|
||||
if (!extensions.init(kGrVkMinimumVersion,
|
||||
EnumerateInstanceExtensionProperties,
|
||||
EnumerateDeviceExtensionProperties,
|
||||
EnumerateInstanceLayerProperties,
|
||||
EnumerateDeviceLayerProperties)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GrVkInterface* interface = new GrVkInterface();
|
||||
GrVkInterface::Functions* functions = &interface->fFunctions;
|
||||
|
||||
@ -152,6 +168,7 @@ const GrVkInterface* GrVkCreateInterface(VkInstance instance) {
|
||||
GET_PROC(CmdNextSubpass);
|
||||
GET_PROC(CmdEndRenderPass);
|
||||
GET_PROC(CmdExecuteCommands);
|
||||
// TODO: break these out with extension checks
|
||||
GET_PROC(DestroySurfaceKHR);
|
||||
GET_PROC(GetPhysicalDeviceSurfaceSupportKHR);
|
||||
GET_PROC(GetPhysicalDeviceSurfaceCapabilitiesKHR);
|
||||
@ -171,6 +188,14 @@ const GrVkInterface* GrVkCreateInterface(VkInstance instance) {
|
||||
GET_PROC(CreateDisplayPlaneSurfaceKHR);
|
||||
GET_PROC(CreateSharedSwapchainsKHR);
|
||||
|
||||
if (extensions.hasInstanceExtension(VK_EXT_DEBUG_REPORT_EXTENSION_NAME)) {
|
||||
GET_PROC(CreateDebugReportCallbackEXT);
|
||||
GET_PROC(DebugReportMessageEXT);
|
||||
GET_PROC(DestroyDebugReportCallbackEXT);
|
||||
}
|
||||
|
||||
interface->fExtensions.swap(&extensions);
|
||||
|
||||
return interface;
|
||||
}
|
||||
|
||||
@ -332,7 +357,10 @@ bool GrVkInterface::validate() const {
|
||||
NULL == fFunctions.fCreateDisplayModeKHR ||
|
||||
NULL == fFunctions.fGetDisplayPlaneCapabilitiesKHR ||
|
||||
NULL == fFunctions.fCreateDisplayPlaneSurfaceKHR ||
|
||||
NULL == fFunctions.fCreateSharedSwapchainsKHR) {
|
||||
NULL == fFunctions.fCreateSharedSwapchainsKHR ||
|
||||
NULL == fFunctions.fCreateDebugReportCallbackEXT ||
|
||||
NULL == fFunctions.fDebugReportMessageEXT ||
|
||||
NULL == fFunctions.fDestroyDebugReportCallbackEXT) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -14,6 +14,9 @@
|
||||
|
||||
#include "vulkan/vulkan.h"
|
||||
|
||||
// the minimum version of Vulkan supported
|
||||
const uint32_t kGrVkMinimumVersion = VK_MAKE_VERSION(1, 0, 3);
|
||||
|
||||
// makes a Vk call on the interface
|
||||
#define GR_VK_CALL(IFACE, X) (IFACE)->fFunctions.f##X;
|
||||
// same as GR_VK_CALL but checks for success
|
||||
|
Loading…
Reference in New Issue
Block a user