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:
jvanverth 2016-03-18 12:39:05 -07:00 committed by Commit bot
parent e820dfebbc
commit d2497f35ce
8 changed files with 579 additions and 8 deletions

View File

@ -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',

View File

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

View 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 : "");
}
}

View 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

View File

@ -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));

View File

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

View File

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

View File

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