| Index: src/gpu/vk/GrVkGpu.cpp
|
| diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
|
| index 180ba3be66b85686d0a3c2e59b32b4f1c9af3e5f..65ec31e7b04f6936a4ed6e8e40fb99dc1547ac13 100644
|
| --- a/src/gpu/vk/GrVkGpu.cpp
|
| +++ b/src/gpu/vk/GrVkGpu.cpp
|
| @@ -42,6 +42,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.
|
| @@ -61,18 +179,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);
|
| @@ -115,6 +248,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
|
| @@ -130,8 +271,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
|
| @@ -187,6 +328,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() {
|
| @@ -200,6 +360,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));
|
|
|