Reland "Move Vulkan DebugCallback code into tools."

This reverts commit 05d3fe3f100b794abe3f99a770734057960d7da5.

Reason for revert: relanding after fuchsia fixes are in

Original change's description:
> Revert "Move Vulkan DebugCallback code into tools."
> 
> This reverts commit d4b2adeaa929edd1664754ac6621ec524992ef03.
> 
> Reason for revert: Need to revert earlier changes cause of fucshia
> 
> Original change's description:
> > Move Vulkan DebugCallback code into tools.
> > 
> > Bug: skia:
> > Change-Id: Ib356200e86e54f9ff0ba16396874e6fd10cf0465
> > Reviewed-on: https://skia-review.googlesource.com/137424
> > Reviewed-by: Brian Salomon <bsalomon@google.com>
> > Commit-Queue: Greg Daniel <egdaniel@google.com>
> 
> TBR=egdaniel@google.com,jvanverth@google.com,bsalomon@google.com
> 
> # Not skipping CQ checks because original CL landed > 1 day ago.
> 
> Bug: skia:
> Change-Id: I38d4e71dc29c6503f92712be54e22c58956498c5
> Reviewed-on: https://skia-review.googlesource.com/137902
> Reviewed-by: Greg Daniel <egdaniel@google.com>
> Commit-Queue: Greg Daniel <egdaniel@google.com>

TBR=egdaniel@google.com,jvanverth@google.com,bsalomon@google.com

# Not skipping CQ checks because original CL landed > 1 day ago.

Bug: skia:
Change-Id: Idb88f21018b9c0e23b62f0a5b12f0fab60373921
Reviewed-on: https://skia-review.googlesource.com/138300
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Greg Daniel <egdaniel@google.com>
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index 0b160a6..65225d9 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -49,30 +49,6 @@
 #define VK_CALL_RET(RET, X) GR_VK_CALL_RET(this->vkInterface(), RET, X)
 #define VK_CALL_ERRCHECK(X) GR_VK_CALL_ERRCHECK(this->vkInterface(), X)
 
-#ifdef SK_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);
-        return VK_TRUE; // skip further layers
-    } 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;
-}
-#endif
-
 sk_sp<GrGpu> GrVkGpu::Make(const GrVkBackendContext& backendContext,
                            const GrContextOptions& options, GrContext* context) {
     if (backendContext.fInstance == VK_NULL_HANDLE ||
@@ -102,27 +78,6 @@
         , fResourceProvider(this)
         , fDisconnected(false) {
     SkASSERT(!backendContext.fOwnsInstanceAndDevice);
-#ifdef SK_ENABLE_VK_LAYERS
-    fCallback = VK_NULL_HANDLE;
-    if (backendContext.fExtensions & kEXT_debug_report_GrVkExtensionFlag) {
-        // 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(this->vkInterface(),
-                            CreateDebugReportCallbackEXT(backendContext.fInstance,
-                                                         &callbackCreateInfo, nullptr, &fCallback));
-    }
-#endif
 
     if (!fMemoryAllocator) {
         // We were not given a memory allocator at creation
@@ -204,12 +159,6 @@
         VK_CALL(DestroyCommandPool(fDevice, fCmdPool, nullptr));
     }
 
-#ifdef SK_ENABLE_VK_LAYERS
-    if (fCallback) {
-        VK_CALL(DestroyDebugReportCallbackEXT(fInstance, fCallback, nullptr));
-    }
-#endif
-
     fMemoryAllocator.reset();
 
     fQueue = VK_NULL_HANDLE;
@@ -245,9 +194,6 @@
         }
         fSemaphoresToWaitOn.reset();
         fSemaphoresToSignal.reset();
-#ifdef SK_ENABLE_VK_LAYERS
-        fCallback = VK_NULL_HANDLE;
-#endif
         fCurrentCmdBuffer = nullptr;
         fCmdPool = VK_NULL_HANDLE;
         fDisconnected = true;
diff --git a/src/gpu/vk/GrVkGpu.h b/src/gpu/vk/GrVkGpu.h
index f506d28..266c916 100644
--- a/src/gpu/vk/GrVkGpu.h
+++ b/src/gpu/vk/GrVkGpu.h
@@ -244,11 +244,6 @@
 
     GrVkCopyManager                        fCopyManager;
 
-#ifdef SK_ENABLE_VK_LAYERS
-    // For reporting validation layer errors
-    VkDebugReportCallbackEXT               fCallback;
-#endif
-
     // compiler used for compiling sksl into spirv. We only want to create the compiler once since
     // there is significant overhead to the first compile of any compiler.
     SkSL::Compiler*                        fCompiler;
diff --git a/tools/gpu/vk/VkTestContext.cpp b/tools/gpu/vk/VkTestContext.cpp
index 592fb0f..32a1205 100644
--- a/tools/gpu/vk/VkTestContext.cpp
+++ b/tools/gpu/vk/VkTestContext.cpp
@@ -112,6 +112,7 @@
     static VkTestContext* Create(VkTestContext* sharedContext) {
         GrVkBackendContext backendContext;
         bool ownsContext = true;
+        VkDebugReportCallbackEXT debugCallback = VK_NULL_HANDLE;
         if (sharedContext) {
             backendContext = sharedContext->getVkBackendContext();
             // We always delete the parent context last so make sure the child does not think they
@@ -123,11 +124,12 @@
             if (!sk_gpu_test::LoadVkLibraryAndGetProcAddrFuncs(&instProc, &devProc)) {
                 return nullptr;
             }
-            if (!sk_gpu_test::CreateVkBackendContext(instProc, devProc, &backendContext)) {
+            if (!sk_gpu_test::CreateVkBackendContext(instProc, devProc, &backendContext,
+                                                     &debugCallback)) {
                 return nullptr;
             }
         }
-        return new VkTestContextImpl(backendContext, ownsContext);
+        return new VkTestContextImpl(backendContext, ownsContext, debugCallback);
     }
 
     ~VkTestContextImpl() override { this->teardown(); }
@@ -150,13 +152,20 @@
         if (fOwnsContext) {
             GR_VK_CALL(this->vk(), DeviceWaitIdle(fVk.fDevice));
             GR_VK_CALL(this->vk(), DestroyDevice(fVk.fDevice, nullptr));
+#ifdef SK_ENABLE_VK_LAYERS
+            if (fDebugCallback != VK_NULL_HANDLE) {
+                GR_VK_CALL(this->vk(), DestroyDebugReportCallbackEXT(fVk.fInstance, fDebugCallback,
+                                                                     nullptr));
+            }
+#endif
             GR_VK_CALL(this->vk(), DestroyInstance(fVk.fInstance, nullptr));
         }
     }
 
 private:
-    VkTestContextImpl(const GrVkBackendContext& backendContext, bool ownsContext)
-            : VkTestContext(backendContext, ownsContext) {
+    VkTestContextImpl(const GrVkBackendContext& backendContext, bool ownsContext,
+                      VkDebugReportCallbackEXT debugCallback)
+            : VkTestContext(backendContext, ownsContext, debugCallback) {
         fFenceSync.reset(new VkFenceSync(fVk.fInterface, fVk.fDevice, fVk.fQueue,
                                          fVk.fGraphicsQueueIndex));
     }
diff --git a/tools/gpu/vk/VkTestContext.h b/tools/gpu/vk/VkTestContext.h
index 0e62cc0..920f535 100644
--- a/tools/gpu/vk/VkTestContext.h
+++ b/tools/gpu/vk/VkTestContext.h
@@ -26,11 +26,13 @@
     const GrVkInterface* vk() const { return fVk.fInterface.get(); }
 
 protected:
-    VkTestContext(const GrVkBackendContext& vk, bool ownsContext)
-            : fVk(vk), fOwnsContext(ownsContext) {}
+    VkTestContext(const GrVkBackendContext& vk, bool ownsContext,
+                  VkDebugReportCallbackEXT debugCallback)
+            : fVk(vk), fOwnsContext(ownsContext), fDebugCallback(debugCallback) {}
 
     GrVkBackendContext fVk;
     bool fOwnsContext;
+    VkDebugReportCallbackEXT fDebugCallback = VK_NULL_HANDLE;
 
 private:
     typedef TestContext INHERITED;
diff --git a/tools/gpu/vk/VkTestUtils.cpp b/tools/gpu/vk/VkTestUtils.cpp
index 927f4fb..e6ddda2 100644
--- a/tools/gpu/vk/VkTestUtils.cpp
+++ b/tools/gpu/vk/VkTestUtils.cpp
@@ -82,12 +82,60 @@
         reinterpret_cast<PFN_vk##name>(getProc("vk" #name, instance, device)); \
     if (grVk##name == nullptr) {                                               \
         SkDebugf("Function ptr for vk%s could not be acquired\n", #name);      \
+        if (device != VK_NULL_HANDLE) {                                        \
+            destroy_instance(getProc, inst, debugCallback, hasDebugExtension); \
+        }                                                                      \
         return false;                                                          \
     }
 
+#ifdef SK_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);
+        return VK_TRUE; // skip further layers
+    } 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;
+}
+#endif
+
+#define ACQUIRE_VK_PROC_LOCAL(name, instance, device)                          \
+    PFN_vk##name grVk##name =                                                  \
+        reinterpret_cast<PFN_vk##name>(getProc("vk" #name, instance, device)); \
+    if (grVk##name == nullptr) {                                               \
+        SkDebugf("Function ptr for vk%s could not be acquired\n", #name);      \
+        return;                                                                \
+    }
+
+static void destroy_instance(GrVkInterface::GetProc getProc, VkInstance inst,
+                             VkDebugReportCallbackEXT* debugCallback,
+                             bool hasDebugExtension) {
+    if (hasDebugExtension && *debugCallback != VK_NULL_HANDLE) {
+        ACQUIRE_VK_PROC_LOCAL(DestroyDebugReportCallbackEXT, inst, VK_NULL_HANDLE);
+        grVkDestroyDebugReportCallbackEXT(inst, *debugCallback, nullptr);
+        *debugCallback = VK_NULL_HANDLE;
+    }
+    ACQUIRE_VK_PROC_LOCAL(DestroyInstance, inst, VK_NULL_HANDLE);
+    grVkDestroyInstance(inst, nullptr);
+}
+
 bool CreateVkBackendContext(const GrVkInterface::GetInstanceProc& getInstanceProc,
                             const GrVkInterface::GetDeviceProc& getDeviceProc,
                             GrVkBackendContext* ctx,
+                            VkDebugReportCallbackEXT* debugCallback,
                             uint32_t* presentQueueIndexPtr,
                             CanPresentFn canPresent) {
     auto getProc = [&getInstanceProc, &getDeviceProc](const char* proc_name,
@@ -119,6 +167,7 @@
     SkTArray<const char*> instanceLayerNames;
     SkTArray<const char*> instanceExtensionNames;
     uint32_t extensionFlags = 0;
+    bool hasDebugExtension = false;
 #ifdef SK_ENABLE_VK_LAYERS
     for (size_t i = 0; i < SK_ARRAY_COUNT(kDebugLayerNames); ++i) {
         if (extensions.hasInstanceLayer(kDebugLayerNames[i])) {
@@ -128,6 +177,7 @@
     if (extensions.hasInstanceExtension(VK_EXT_DEBUG_REPORT_EXTENSION_NAME)) {
         instanceExtensionNames.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
         extensionFlags |= kEXT_debug_report_GrVkExtensionFlag;
+        hasDebugExtension = true;
     }
 #endif
 
@@ -174,6 +224,32 @@
         return false;
     }
 
+#ifdef SK_ENABLE_VK_LAYERS
+    *debugCallback = VK_NULL_HANDLE;
+    for (int i = 0; i < instanceExtensionNames.count() && !hasDebugExtension; ++i) {
+        if (!strcmp(instanceExtensionNames[i], VK_EXT_DEBUG_REPORT_EXTENSION_NAME)) {
+            hasDebugExtension = true;
+        }
+    }
+    if (hasDebugExtension) {
+        // 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;
+
+        ACQUIRE_VK_PROC(CreateDebugReportCallbackEXT, inst, VK_NULL_HANDLE);
+        // Register the callback
+        grVkCreateDebugReportCallbackEXT(inst, &callbackCreateInfo, nullptr, debugCallback);
+    }
+#endif
+
     ACQUIRE_VK_PROC(DestroyInstance, inst, VK_NULL_HANDLE);
     ACQUIRE_VK_PROC(EnumeratePhysicalDevices, inst, VK_NULL_HANDLE);
     ACQUIRE_VK_PROC(GetPhysicalDeviceQueueFamilyProperties, inst, VK_NULL_HANDLE);
@@ -187,12 +263,12 @@
     err = grVkEnumeratePhysicalDevices(inst, &gpuCount, nullptr);
     if (err) {
         SkDebugf("vkEnumeratePhysicalDevices failed: %d\n", err);
-        grVkDestroyInstance(inst, nullptr);
+        destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
         return false;
     }
     if (!gpuCount) {
         SkDebugf("vkEnumeratePhysicalDevices returned no supported devices.\n");
-        grVkDestroyInstance(inst, nullptr);
+        destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
         return false;
     }
     // Just returning the first physical device instead of getting the whole array.
@@ -202,7 +278,7 @@
     // VK_INCOMPLETE is returned when the count we provide is less than the total device count.
     if (err && VK_INCOMPLETE != err) {
         SkDebugf("vkEnumeratePhysicalDevices failed: %d\n", err);
-        grVkDestroyInstance(inst, nullptr);
+        destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
         return false;
     }
 
@@ -211,7 +287,7 @@
     grVkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, nullptr);
     if (!queueCount) {
         SkDebugf("vkGetPhysicalDeviceQueueFamilyProperties returned no queues.\n");
-        grVkDestroyInstance(inst, nullptr);
+        destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
         return false;
     }
 
@@ -231,7 +307,7 @@
     }
     if (graphicsQueueIndex == queueCount) {
         SkDebugf("Could not find any supported graphics queues.\n");
-        grVkDestroyInstance(inst, nullptr);
+        destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
         return false;
     }
 
@@ -246,7 +322,7 @@
         }
         if (presentQueueIndex == queueCount) {
             SkDebugf("Could not find any supported present queues.\n");
-            grVkDestroyInstance(inst, nullptr);
+            destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
             return false;
         }
         *presentQueueIndexPtr = presentQueueIndex;
@@ -260,13 +336,6 @@
 
     SkTArray<const char*> deviceLayerNames;
     SkTArray<const char*> deviceExtensionNames;
-#ifdef SK_ENABLE_VK_LAYERS
-    for (size_t i = 0; i < SK_ARRAY_COUNT(kDebugLayerNames); ++i) {
-        if (extensions.hasDeviceLayer(kDebugLayerNames[i])) {
-            deviceLayerNames.push_back(kDebugLayerNames[i]);
-        }
-    }
-#endif
     if (extensions.hasDeviceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME)) {
         deviceExtensionNames.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
         extensionFlags |= kKHR_swapchain_GrVkExtensionFlag;
@@ -333,7 +402,7 @@
     err = grVkCreateDevice(physDev, &deviceInfo, nullptr, &device);
     if (err) {
         SkDebugf("CreateDevice failed: %d\n", err);
-        grVkDestroyInstance(inst, nullptr);
+        destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
         return false;
     }
 
@@ -343,7 +412,7 @@
         SkDebugf("Vulkan interface validation failed\n");
         grVkDeviceWaitIdle(device);
         grVkDestroyDevice(device, nullptr);
-        grVkDestroyInstance(inst, nullptr);
+        destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
         return false;
     }
 
@@ -362,8 +431,6 @@
     ctx->fOwnsInstanceAndDevice = false;
 
     return true;
-
-
 }
 
 }
diff --git a/tools/gpu/vk/VkTestUtils.h b/tools/gpu/vk/VkTestUtils.h
index 30471a78..0046d6d 100644
--- a/tools/gpu/vk/VkTestUtils.h
+++ b/tools/gpu/vk/VkTestUtils.h
@@ -26,6 +26,7 @@
     bool CreateVkBackendContext(const GrVkInterface::GetInstanceProc& getInstanceProc,
                                 const GrVkInterface::GetDeviceProc& getDeviceProc,
                                 GrVkBackendContext* ctx,
+                                VkDebugReportCallbackEXT* debugCallback,
                                 uint32_t* presentQueueIndexPtr = nullptr,
                                 CanPresentFn canPresent = CanPresentFn());
 }
diff --git a/tools/sk_app/VulkanWindowContext.cpp b/tools/sk_app/VulkanWindowContext.cpp
index 411f114..8e0749e 100644
--- a/tools/sk_app/VulkanWindowContext.cpp
+++ b/tools/sk_app/VulkanWindowContext.cpp
@@ -51,7 +51,8 @@
 
     GrVkBackendContext backendContext;
     if (!sk_gpu_test::CreateVkBackendContext(fGetInstanceProcAddr, fGetDeviceProcAddr,
-                                             &backendContext, &fPresentQueueIndex, fCanPresentFn)) {
+                                             &backendContext, &fDebugCallback,
+                                             &fPresentQueueIndex, fCanPresentFn)) {
         return;
     }
 
@@ -409,28 +410,26 @@
 }
 
 void VulkanWindowContext::destroyContext() {
-    if (!this->isValid()) {
-        return;
-    }
+    if (this->isValid()) {
+        fQueueWaitIdle(fPresentQueue);
+        fDeviceWaitIdle(fDevice);
 
-    fQueueWaitIdle(fPresentQueue);
-    fDeviceWaitIdle(fDevice);
+        this->destroyBuffers();
 
-    this->destroyBuffers();
+        if (VK_NULL_HANDLE != fCommandPool) {
+            GR_VK_CALL(fInterface, DestroyCommandPool(fDevice, fCommandPool, nullptr));
+            fCommandPool = VK_NULL_HANDLE;
+        }
 
-    if (VK_NULL_HANDLE != fCommandPool) {
-        GR_VK_CALL(fInterface, DestroyCommandPool(fDevice, fCommandPool, nullptr));
-        fCommandPool = VK_NULL_HANDLE;
-    }
+        if (VK_NULL_HANDLE != fSwapchain) {
+            fDestroySwapchainKHR(fDevice, fSwapchain, nullptr);
+            fSwapchain = VK_NULL_HANDLE;
+        }
 
-    if (VK_NULL_HANDLE != fSwapchain) {
-        fDestroySwapchainKHR(fDevice, fSwapchain, nullptr);
-        fSwapchain = VK_NULL_HANDLE;
-    }
-
-    if (VK_NULL_HANDLE != fSurface) {
-        fDestroySurfaceKHR(fInstance, fSurface, nullptr);
-        fSurface = VK_NULL_HANDLE;
+        if (VK_NULL_HANDLE != fSurface) {
+            fDestroySurfaceKHR(fInstance, fSurface, nullptr);
+            fSurface = VK_NULL_HANDLE;
+        }
     }
 
     fContext.reset();
@@ -440,6 +439,14 @@
         fDestroyDevice(fDevice, nullptr);
         fDevice = VK_NULL_HANDLE;
     }
+
+#ifdef SK_ENABLE_VK_LAYERS
+    if (fDebugCallback != VK_NULL_HANDLE) {
+        GR_VK_CALL(fInterface, DestroyDebugReportCallbackEXT(fInstance, fDebugCallback,
+                                                             nullptr));
+    }
+#endif
+
     fPhysicalDevice = VK_NULL_HANDLE;
 
     if (VK_NULL_HANDLE != fInstance) {
diff --git a/tools/sk_app/VulkanWindowContext.h b/tools/sk_app/VulkanWindowContext.h
index 79298f6..3d9687b 100644
--- a/tools/sk_app/VulkanWindowContext.h
+++ b/tools/sk_app/VulkanWindowContext.h
@@ -68,6 +68,7 @@
     VkInstance fInstance = VK_NULL_HANDLE;
     VkPhysicalDevice fPhysicalDevice = VK_NULL_HANDLE;
     VkDevice fDevice = VK_NULL_HANDLE;
+    VkDebugReportCallbackEXT fDebugCallback = VK_NULL_HANDLE;
 
     // simple wrapper class that exists only to initialize a pointer to NULL
     template <typename FNPTR_TYPE> class VkPtr {