Vulkan config in dm

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1872283003

Review URL: https://codereview.chromium.org/1872283003
diff --git a/dm/DM.cpp b/dm/DM.cpp
index 93ebae1..fd06bc0 100644
--- a/dm/DM.cpp
+++ b/dm/DM.cpp
@@ -1347,7 +1347,6 @@
     }
     gather_sinks();
     gather_tests();
-
     gPending = gSrcs.count() * gSinks.count() + gParallelTests.count() + gSerialTests.count();
     info("%d srcs * %d sinks + %d tests == %d tasks",
          gSrcs.count(), gSinks.count(), gParallelTests.count() + gSerialTests.count(), gPending);
@@ -1420,6 +1419,9 @@
 bool IsGLContextType(sk_gpu_test::GrContextFactory::ContextType type) {
     return kOpenGL_GrBackend == GrContextFactory::ContextTypeBackend(type);
 }
+bool IsVulkanContextType(sk_gpu_test::GrContextFactory::ContextType type) {
+    return kVulkan_GrBackend == GrContextFactory::ContextTypeBackend(type);
+}
 bool IsRenderingGLContextType(sk_gpu_test::GrContextFactory::ContextType type) {
     return IsGLContextType(type) && GrContextFactory::IsRenderingContext(type);
 }
@@ -1428,6 +1430,7 @@
 }
 #else
 bool IsGLContextType(int) { return false; }
+bool IsVulkanContextType(int) { return false; }
 bool IsRenderingGLContextType(int) { return false; }
 bool IsNullGLContextType(int) { return false; }
 #endif
diff --git a/dm/DMGpuSupport.h b/dm/DMGpuSupport.h
index 42c5eb3..173befd 100644
--- a/dm/DMGpuSupport.h
+++ b/dm/DMGpuSupport.h
@@ -80,7 +80,8 @@
                              kNativeGL_ContextType      = 0,
                              kGL_ContextType            = 0,
                              kGLES_ContextType          = 0,
-                             kNullGL_ContextType        = 0;
+                             kNullGL_ContextType        = 0,
+                             kVulkan_ContextType        = 0;
     static const int kContextTypeCnt = 1;
     enum ContextOptions {
         kNone_ContextOptions = 0,
diff --git a/src/gpu/vk/GrVkBackendContext.cpp b/src/gpu/vk/GrVkBackendContext.cpp
index f5cd08c..d189840 100644
--- a/src/gpu/vk/GrVkBackendContext.cpp
+++ b/src/gpu/vk/GrVkBackendContext.cpp
@@ -109,7 +109,7 @@
     err = vkCreateInstance(&instance_create, nullptr, &inst);
     if (err < 0) {
         SkDebugf("vkCreateInstance failed: %d\n", err);
-        SkFAIL("failing");
+        return nullptr;
     }
 
     uint32_t gpuCount;
@@ -117,7 +117,7 @@
     if (err) {
         SkDebugf("vkEnumeratePhysicalDevices failed: %d\n", err);
         vkDestroyInstance(inst, nullptr);
-        SkFAIL("failing");
+        return nullptr;
     }
     SkASSERT(gpuCount > 0);
     // Just returning the first physical device instead of getting the whole array.
@@ -127,7 +127,7 @@
     if (err) {
         SkDebugf("vkEnumeratePhysicalDevices failed: %d\n", err);
         vkDestroyInstance(inst, nullptr);
-        SkFAIL("failing");
+        return nullptr;
     }
 
     // query to get the initial queue props size
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index 428c2ff..280346f 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -63,10 +63,10 @@
 
 GrGpu* GrVkGpu::Create(GrBackendContext backendContext, const GrContextOptions& options,
                        GrContext* context) {
-    SkAutoTUnref<const GrVkBackendContext> vkBackendContext(
-                                       reinterpret_cast<const GrVkBackendContext*>(backendContext));
+    const GrVkBackendContext* vkBackendContext =
+        reinterpret_cast<const GrVkBackendContext*>(backendContext);
     if (!vkBackendContext) {
-        vkBackendContext.reset(GrVkBackendContext::Create());
+        vkBackendContext = GrVkBackendContext::Create();
         if (!vkBackendContext) {
             return nullptr;
         }
diff --git a/tests/GrContextFactoryTest.cpp b/tests/GrContextFactoryTest.cpp
index 395fa6a..fe4f1ef 100644
--- a/tests/GrContextFactoryTest.cpp
+++ b/tests/GrContextFactoryTest.cpp
@@ -78,7 +78,9 @@
         if (!info1.fGrContext) {
             continue;
         }
-        REPORTER_ASSERT(reporter, info1.fGLContext);
+        if (GrContextFactory::ContextTypeBackend(ctxType) == kOpenGL_GrBackend) {
+            REPORTER_ASSERT(reporter, info1.fGLContext);
+        }
          // Ref for comparison. The API does not explicitly say that this stays alive.
         info1.fGrContext->ref();
         testFactory.abandonContexts();
@@ -86,7 +88,9 @@
         // Test that we get different context after abandon.
         ContextInfo info2 = testFactory.getContextInfo(ctxType);
         REPORTER_ASSERT(reporter, info2.fGrContext);
-        REPORTER_ASSERT(reporter, info2.fGLContext);
+        if (GrContextFactory::ContextTypeBackend(ctxType) == kOpenGL_GrBackend) {
+            REPORTER_ASSERT(reporter, info2.fGLContext);
+        }
         REPORTER_ASSERT(reporter, info1.fGrContext != info2.fGrContext);
         // fGLContext should also change, but it also could get the same address.
 
diff --git a/tests/Test.h b/tests/Test.h
index ac68ccc..b2cb180 100644
--- a/tests/Test.h
+++ b/tests/Test.h
@@ -88,6 +88,7 @@
 typedef bool GrContextTypeFilterFn(GrContextFactoryContextType);
 
 extern bool IsGLContextType(GrContextFactoryContextType);
+extern bool IsVulkanContextType(GrContextFactoryContextType);
 extern bool IsRenderingGLContextType(GrContextFactoryContextType);
 extern bool IsNullGLContextType(GrContextFactoryContextType);
 
@@ -173,6 +174,8 @@
         DEF_GPUTEST_FOR_CONTEXTS(name, &skiatest::IsRenderingGLContextType, reporter, context_info)
 #define DEF_GPUTEST_FOR_NULLGL_CONTEXT(name, reporter, context_info)                        \
         DEF_GPUTEST_FOR_CONTEXTS(name, &skiatest::IsNullGLContextType, reporter, context_info)
+#define DEF_GPUTEST_FOR_VULKAN_CONTEXT(name, reporter, context_info)                        \
+        DEF_GPUTEST_FOR_CONTEXTS(name, &skiatest::IsVulkanContextType, reporter, context_info)
 
 #define REQUIRE_PDF_DOCUMENT(TEST_NAME, REPORTER)                             \
     do {                                                                      \
diff --git a/tests/TestConfigParsing.cpp b/tests/TestConfigParsing.cpp
index ac7037f..4d64caf 100644
--- a/tests/TestConfigParsing.cpp
+++ b/tests/TestConfigParsing.cpp
@@ -77,7 +77,7 @@
         "565", "8888", "debug", "gpu", "gpudebug", "gpudft", "gpunull", "msaa16", "msaa4",
         "nonrendering", "null", "nullgpu", "nvpr16", "nvpr4", "nvprdit16", "nvprdit4", "pdf",
         "skp", "svg", "xps", "angle", "angle-gl", "commandbuffer", "mesa", "hwui",
-        "gpuf16", "gpusrgb", "gl", "glnvpr4", "glnvprdit4", "glsrgb", "glmsaa4"
+        "gpuf16", "gpusrgb", "gl", "glnvpr4", "glnvprdit4", "glsrgb", "glmsaa4", "vk"
     });
 
     SkCommandLineConfigArray configs;
@@ -161,6 +161,9 @@
                               kSRGB_SkColorProfileType);
     REPORTER_ASSERT(reporter, configs[31]->asConfigGpu());
     REPORTER_ASSERT(reporter, configs[31]->asConfigGpu()->getSamples() == 4);
+#ifdef SK_VULKAN
+    REPORTER_ASSERT(reporter, configs[32]->asConfigGpu());
+#endif
 #endif
 }
 
@@ -173,7 +176,8 @@
         "gpu(dit=true,api=commandbuffer)",
         "gpu()",
         "gpu(api=gles)",
-        "gpu(api=gl)"
+        "gpu(api=gl)",
+        "gpu(api=vulkan)",
     });
 
     SkCommandLineConfigArray configs;
@@ -229,6 +233,13 @@
     REPORTER_ASSERT(reporter, !configs[7]->asConfigGpu()->getUseNVPR());
     REPORTER_ASSERT(reporter, !configs[7]->asConfigGpu()->getUseDIText());
     REPORTER_ASSERT(reporter, configs[7]->asConfigGpu()->getSamples() == 0);
+#ifdef SK_VULKAN
+    REPORTER_ASSERT(reporter, configs[8]->asConfigGpu()->getContextType() ==
+                              GrContextFactory::kVulkan_ContextType);
+    REPORTER_ASSERT(reporter, !configs[7]->asConfigGpu()->getUseNVPR());
+    REPORTER_ASSERT(reporter, !configs[7]->asConfigGpu()->getUseDIText());
+    REPORTER_ASSERT(reporter, configs[7]->asConfigGpu()->getSamples() == 0);
+#endif
 #endif
 }
 
diff --git a/tests/VkClearTests.cpp b/tests/VkClearTests.cpp
index 5b8a30b..1f8e497 100644
--- a/tests/VkClearTests.cpp
+++ b/tests/VkClearTests.cpp
@@ -59,7 +59,7 @@
     surfDesc.fHeight = 5;
     surfDesc.fConfig = config;
     surfDesc.fSampleCnt = 0;
-    GrTexture* tex = gpu->createTexture(surfDesc, SkBudgeted::kNo, nullptr, 0);
+    GrTexture* tex = gpu->createTexture(surfDesc, SkBudgeted::kNo);
     SkASSERT(tex);
     SkASSERT(tex->asRenderTarget());
     SkIRect rect = SkIRect::MakeWH(5, 5);
@@ -114,7 +114,7 @@
     surfDesc.fHeight = height;
     surfDesc.fConfig = config;
     surfDesc.fSampleCnt = 0;
-    GrTexture* tex = gpu->createTexture(surfDesc, SkBudgeted::kNo, nullptr, 0);
+    GrTexture* tex = gpu->createTexture(surfDesc, SkBudgeted::kNo);
     SkASSERT(tex);
     SkASSERT(tex->asRenderTarget());
 
@@ -196,24 +196,11 @@
                                                                      subHeight));
 }
 
-DEF_GPUTEST(VkClearTests, reporter, factory) {
-    GrContextOptions opts;
-    opts.fSuppressPrints = true;
-    GrContextFactory debugFactory(opts);
-    for (int type = 0; type < GrContextFactory::kContextTypeCnt; ++type) {
-        if (static_cast<GrContextFactory::ContextType>(type) !=
-            GrContextFactory::kNativeGL_ContextType) {
-            continue;
-        }
-        GrContext* context = debugFactory.get(static_cast<GrContextFactory::ContextType>(type));
-        if (context) {
-            basic_clear_test(reporter, context, kRGBA_8888_GrPixelConfig);
-            basic_clear_test(reporter, context, kBGRA_8888_GrPixelConfig);
-            sub_clear_test(reporter, context, kRGBA_8888_GrPixelConfig);
-            sub_clear_test(reporter, context, kBGRA_8888_GrPixelConfig);
-        }
-
-    }
+DEF_GPUTEST_FOR_VULKAN_CONTEXT(VkClearTests, reporter, ctxInfo) {
+    basic_clear_test(reporter, ctxInfo.fGrContext, kRGBA_8888_GrPixelConfig);
+    basic_clear_test(reporter, ctxInfo.fGrContext, kBGRA_8888_GrPixelConfig);
+    sub_clear_test(reporter, ctxInfo.fGrContext, kRGBA_8888_GrPixelConfig);
+    sub_clear_test(reporter, ctxInfo.fGrContext, kBGRA_8888_GrPixelConfig);
 }
 
 #endif
diff --git a/tests/VkUploadPixelsTests.cpp b/tests/VkUploadPixelsTests.cpp
index e5f72dd..d4604e8 100644
--- a/tests/VkUploadPixelsTests.cpp
+++ b/tests/VkUploadPixelsTests.cpp
@@ -133,28 +133,15 @@
     }
 }
 
-DEF_GPUTEST(VkUploadPixelsTests, reporter, factory) {
-    GrContextOptions opts;
-    opts.fSuppressPrints = true;
-    GrContextFactory debugFactory(opts);
-    for (int type = 0; type < GrContextFactory::kContextTypeCnt; ++type) {
-        if (static_cast<GrContextFactory::ContextType>(type) !=
-            GrContextFactory::kNativeGL_ContextType) {
-            continue;
-        }
-        GrContext* context = debugFactory.get(static_cast<GrContextFactory::ContextType>(type));
-        if (context) {
-            basic_texture_test(reporter, context, kRGBA_8888_GrPixelConfig, false, false);
-            basic_texture_test(reporter, context, kRGBA_8888_GrPixelConfig, true, false);
-            basic_texture_test(reporter, context, kRGBA_8888_GrPixelConfig, false, true);
-            basic_texture_test(reporter, context, kRGBA_8888_GrPixelConfig, true, true);
-            basic_texture_test(reporter, context, kBGRA_8888_GrPixelConfig, false, false);
-            basic_texture_test(reporter, context, kBGRA_8888_GrPixelConfig, true, false);
-            basic_texture_test(reporter, context, kBGRA_8888_GrPixelConfig, false, true);
-            basic_texture_test(reporter, context, kBGRA_8888_GrPixelConfig, true, true);
-        }
-
-    }
+DEF_GPUTEST_FOR_VULKAN_CONTEXT(VkUploadPixelsTests, reporter, ctxInfo) {
+    basic_texture_test(reporter, ctxInfo.fGrContext, kRGBA_8888_GrPixelConfig, false, false);
+    basic_texture_test(reporter, ctxInfo.fGrContext, kRGBA_8888_GrPixelConfig, true, false);
+    basic_texture_test(reporter, ctxInfo.fGrContext, kRGBA_8888_GrPixelConfig, false, true);
+    basic_texture_test(reporter, ctxInfo.fGrContext, kRGBA_8888_GrPixelConfig, true, true);
+    basic_texture_test(reporter, ctxInfo.fGrContext, kBGRA_8888_GrPixelConfig, false, false);
+    basic_texture_test(reporter, ctxInfo.fGrContext, kBGRA_8888_GrPixelConfig, true, false);
+    basic_texture_test(reporter, ctxInfo.fGrContext, kBGRA_8888_GrPixelConfig, false, true);
+    basic_texture_test(reporter, ctxInfo.fGrContext, kBGRA_8888_GrPixelConfig, true, true);
 }
 
 #endif
diff --git a/tests/VkWrapTests.cpp b/tests/VkWrapTests.cpp
index a4fec08..626ee4c 100755
--- a/tests/VkWrapTests.cpp
+++ b/tests/VkWrapTests.cpp
@@ -158,23 +158,10 @@
     gpu->deleteTestingOnlyBackendTexture(backendObj, true);
 }
 
-DEF_GPUTEST(VkWrapTests, reporter, factory) {
-    GrContextOptions opts;
-    opts.fSuppressPrints = true;
-    GrContextFactory debugFactory(opts);
-    for (int type = 0; type < GrContextFactory::kLastContextType; ++type) {
-        if (static_cast<GrContextFactory::ContextType>(type) !=
-            GrContextFactory::kNativeGL_ContextType) {
-            continue;
-        }
-        GrContext* context = debugFactory.get(static_cast<GrContextFactory::ContextType>(type));
-        if (context) {
-            wrap_tex_test(reporter, context);
-            wrap_rt_test(reporter, context);
-            wrap_trt_test(reporter, context);
-        }
-
-    }
+DEF_GPUTEST_FOR_VULKAN_CONTEXT(VkWrapTests, reporter, ctxInfo) {
+    wrap_tex_test(reporter, ctxInfo.fGrContext);
+    wrap_rt_test(reporter, ctxInfo.fGrContext);
+    wrap_trt_test(reporter, ctxInfo.fGrContext);
 }
 
 #endif
diff --git a/tools/flags/SkCommonFlagsConfig.cpp b/tools/flags/SkCommonFlagsConfig.cpp
index 0847ae5..a0d1c77 100644
--- a/tools/flags/SkCommonFlagsConfig.cpp
+++ b/tools/flags/SkCommonFlagsConfig.cpp
@@ -44,6 +44,9 @@
 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
     " hwui"
 #endif
+#ifdef SK_VULKAN
+    " vk"
+#endif
     " or use extended form 'backend(option=value,...)'.\n";
 
 static const char configExtendedHelp[] =
@@ -72,6 +75,9 @@
 #if SK_MESA
     "\t\tmesa\t\t\tUse MESA.\n"
 #endif
+#ifdef SK_VULKAN
+    "\t\tvulkan\t\t\tUse Vulkan.\n"
+#endif
     "\tcolor\ttype: string\tdefault: 8888.\n"
     "\t    Select framebuffer color format.\n"
     "\t    Options:\n"
@@ -117,6 +123,9 @@
 #if SK_MESA
     "\tmesa      \t= gpu(api=mesa)\n"
 #endif
+#ifdef SK_VULKAN
+     "\vk        \t= gpu(api=vulkan)\n"
+#endif
 #endif
     ;
 
@@ -159,6 +168,10 @@
 #if SK_MESA
     , { "mesa", "gpu", "api=mesa" }
 #endif
+#ifdef SK_VULKAN
+    , { "vk", "gpu", "api=vulkan" }
+#endif
+
 #else
     { "", "", "" }
 #endif
@@ -251,6 +264,12 @@
         return true;
     }
 #endif
+#ifdef SK_VULKAN
+    if (value.equals("vulkan")) {
+        *outContextType = GrContextFactory::kVulkan_ContextType;
+        return true;
+    }
+#endif
     return false;
 }
 static bool parse_option_gpu_color(const SkString& value,
diff --git a/tools/gpu/GrContextFactory.cpp b/tools/gpu/GrContextFactory.cpp
index f54aa90..651f3fc 100755
--- a/tools/gpu/GrContextFactory.cpp
+++ b/tools/gpu/GrContextFactory.cpp
@@ -43,33 +43,42 @@
             context.fGLContext->makeCurrent();
         }
         if (!context.fGrContext->unique()) {
-            context.fGrContext->abandonContext();
+            context.fGrContext->releaseResourcesAndAbandonContext();
+            context.fAbandoned = true;
         }
         context.fGrContext->unref();
-        delete(context.fGLContext);
+        delete context.fGLContext;
     }
     fContexts.reset();
 }
 
 void GrContextFactory::abandonContexts() {
     for (Context& context : fContexts) {
-        if (context.fGLContext) {
-            context.fGLContext->makeCurrent();
-            context.fGLContext->testAbandon();
-            delete(context.fGLContext);
-            context.fGLContext = nullptr;
+        if (!context.fAbandoned) {
+            if (context.fGLContext) {
+                context.fGLContext->makeCurrent();
+                context.fGLContext->testAbandon();
+                delete(context.fGLContext);
+                context.fGLContext = nullptr;
+            }
+            context.fGrContext->abandonContext();
+            context.fAbandoned = true;
         }
-        context.fGrContext->abandonContext();
     }
 }
 
 void GrContextFactory::releaseResourcesAndAbandonContexts() {
     for (Context& context : fContexts) {
-        if (context.fGLContext) {
-            context.fGLContext->makeCurrent();
+        if (!context.fAbandoned) {
+            if (context.fGLContext) {
+                context.fGLContext->makeCurrent();
+            }
             context.fGrContext->releaseResourcesAndAbandonContext();
-            delete(context.fGLContext);
-            context.fGLContext = nullptr;
+            context.fAbandoned = true;
+            if (context.fGLContext) {
+                delete context.fGLContext;
+                context.fGLContext = nullptr;
+            }
         }
     }
 }
@@ -85,78 +94,103 @@
 ContextInfo GrContextFactory::getContextInfo(ContextType type, ContextOptions options) {
     for (int i = 0; i < fContexts.count(); ++i) {
         Context& context = fContexts[i];
-        if (!context.fGLContext) {
-            continue;
-        }
         if (context.fType == type &&
-            context.fOptions == options) {
-            context.fGLContext->makeCurrent();
+            context.fOptions == options &&
+            !context.fAbandoned) {
+            if (context.fGLContext) {
+                context.fGLContext->makeCurrent();
+            }
             return ContextInfo(context.fGrContext, context.fGLContext);
         }
     }
     SkAutoTDelete<GLTestContext> glCtx;
-    SkAutoTUnref<GrContext> grCtx;
-    switch (type) {
-        case kGL_ContextType:
-            glCtx.reset(CreatePlatformGLTestContext(kGL_GrGLStandard));
-            break;
-        case kGLES_ContextType:
-            glCtx.reset(CreatePlatformGLTestContext(kGLES_GrGLStandard));
-            break;
-#if SK_ANGLE
-#ifdef SK_BUILD_FOR_WIN
-        case kANGLE_ContextType:
-            glCtx.reset(CreateANGLEDirect3DGLTestContext());
-            break;
+    sk_sp<GrContext> grCtx;
+    GrBackendContext backendContext = 0;
+    sk_sp<const GrGLInterface> glInterface;
+#ifdef SK_VULKAN
+    sk_sp<const GrVkBackendContext> vkBackend;
 #endif
-        case kANGLE_GL_ContextType:
-            glCtx.reset(CreateANGLEOpenGLGLTestContext());
-            break;
+    GrBackend backend = ContextTypeBackend(type);
+    switch (backend) {
+        case kOpenGL_GrBackend:
+            switch (type) {
+                case kGL_ContextType:
+                    glCtx.reset(CreatePlatformGLTestContext(kGL_GrGLStandard));
+                    break;
+                case kGLES_ContextType:
+                    glCtx.reset(CreatePlatformGLTestContext(kGLES_GrGLStandard));
+                    break;
+#if SK_ANGLE
+#   ifdef SK_BUILD_FOR_WIN
+                case kANGLE_ContextType:
+                    glCtx.reset(CreateANGLEDirect3DGLTestContext());
+                    break;
+#   endif
+                case kANGLE_GL_ContextType:
+                    glCtx.reset(CreateANGLEOpenGLGLTestContext());
+                    break;
 #endif
 #if SK_COMMAND_BUFFER
-        case kCommandBuffer_ContextType:
-            glCtx.reset(CommandBufferGLTestContext::Create());
-            break;
+                case kCommandBuffer_ContextType:
+                    glCtx.reset(CommandBufferGLTestContext::Create());
+                    break;
 #endif
 #if SK_MESA
-        case kMESA_ContextType:
-            glCtx.reset(CreateMesaGLTestContext());
-            break;
+                case kMESA_ContextType:
+                    glCtx.reset(CreateMesaGLTestContext());
+                    break;
 #endif
-        case kNullGL_ContextType:
-            glCtx.reset(CreateNullGLTestContext());
+                case kNullGL_ContextType:
+                    glCtx.reset(CreateNullGLTestContext());
+                    break;
+                case kDebugGL_ContextType:
+                    glCtx.reset(CreateDebugGLTestContext());
+                    break;
+                default:
+                    return ContextInfo();
+            }
+            if (nullptr == glCtx.get()) {
+                return ContextInfo();
+            }
+            glInterface.reset(SkRef(glCtx->gl()));
+            // Block NVPR from non-NVPR types.
+            if (!(kEnableNVPR_ContextOptions & options)) {
+                glInterface.reset(GrGLInterfaceRemoveNVPR(glInterface.get()));
+                if (!glInterface) {
+                    return ContextInfo();
+                }
+            }
+            backendContext = reinterpret_cast<GrBackendContext>(glInterface.get());
+            glCtx->makeCurrent();
             break;
-        case kDebugGL_ContextType:
-            glCtx.reset(CreateDebugGLTestContext());
-            break;
-    }
-    if (nullptr == glCtx.get()) {
-        return ContextInfo();
-    }
-
-    SkASSERT(glCtx->isValid());
-
-    // Block NVPR from non-NVPR types.
-    SkAutoTUnref<const GrGLInterface> glInterface(SkRef(glCtx->gl()));
-    if (!(kEnableNVPR_ContextOptions & options)) {
-        glInterface.reset(GrGLInterfaceRemoveNVPR(glInterface));
-        if (!glInterface) {
-            return ContextInfo();
-        }
-    }
-
-    glCtx->makeCurrent();
 #ifdef SK_VULKAN
-    if (kEnableNVPR_ContextOptions & options) {
-        return ContextInfo();
-    } else {
-        GrBackendContext p3dctx = reinterpret_cast<GrBackendContext>(GrVkBackendContext::Create());
-        grCtx.reset(GrContext::Create(kVulkan_GrBackend, p3dctx, fGlobalOptions));
-    }
-#else
-    GrBackendContext p3dctx = reinterpret_cast<GrBackendContext>(glInterface.get());
-    grCtx.reset(GrContext::Create(kOpenGL_GrBackend, p3dctx, fGlobalOptions));
+        case kVulkan_GrBackend:
+            SkASSERT(kVulkan_ContextType == type);
+            if ((kEnableNVPR_ContextOptions & options) ||
+                (kRequireSRGBSupport_ContextOptions & options)) {
+                return ContextInfo();
+            }
+            vkBackend.reset(GrVkBackendContext::Create());
+            if (!vkBackend) {
+                return ContextInfo();
+            }
+            backendContext = reinterpret_cast<GrBackendContext>(vkBackend.get());
+            // There is some bug (either in Skia or the NV Vulkan driver) where VkDevice
+            // destruction will hang occaisonally. For some reason having an existing GL
+            // context fixes this.
+            if (!fSentinelGLContext) {
+                fSentinelGLContext.reset(CreatePlatformGLTestContext(kGL_GrGLStandard));
+                if (!fSentinelGLContext) {
+                    fSentinelGLContext.reset(CreatePlatformGLTestContext(kGLES_GrGLStandard));
+                }
+            }
+            break;
 #endif
+        default:
+            return ContextInfo();
+    }
+
+    grCtx.reset(GrContext::Create(backend, backendContext, fGlobalOptions));
     if (!grCtx.get()) {
         return ContextInfo();
     }
@@ -176,6 +210,7 @@
     context.fGrContext = SkRef(grCtx.get());
     context.fType = type;
     context.fOptions = options;
+    context.fAbandoned = false;
     return ContextInfo(context.fGrContext, context.fGLContext);
 }
 }  // namespace sk_gpu_test
diff --git a/tools/gpu/GrContextFactory.h b/tools/gpu/GrContextFactory.h
index 89ca9ca..0dc8c20 100644
--- a/tools/gpu/GrContextFactory.h
+++ b/tools/gpu/GrContextFactory.h
@@ -14,6 +14,8 @@
 #include "gl/GLTestContext.h"
 #include "SkTArray.h"
 
+struct GrVkBackendContext;
+
 namespace sk_gpu_test {
 
 struct ContextInfo {
@@ -23,7 +25,7 @@
         : fGrContext(grContext), fGLContext(glContext) { }
     GrContext* fGrContext;
     GLTestContext* fGLContext; //! Valid until the factory destroys it via abandonContexts() or
-                               //! destroyContexts().
+                               //! destroyContexts(). Null if context is not based on OpenGL.
 };
 
 /**
@@ -35,24 +37,19 @@
  */
 class GrContextFactory : SkNoncopyable {
 public:
+    // The availability of context types is subject to platform and build configuration
+    // restrictions.
     enum ContextType {
         kGL_ContextType,            //! OpenGL context.
         kGLES_ContextType,          //! OpenGL ES context.
-#if SK_ANGLE
-#ifdef SK_BUILD_FOR_WIN
         kANGLE_ContextType,         //! ANGLE on DirectX OpenGL ES context.
-#endif
         kANGLE_GL_ContextType,      //! ANGLE on OpenGL OpenGL ES context.
-#endif
-#if SK_COMMAND_BUFFER
         kCommandBuffer_ContextType, //! Chromium command buffer OpenGL ES context.
-#endif
-#if SK_MESA
         kMESA_ContextType,          //! MESA OpenGL context
-#endif
         kNullGL_ContextType,        //! Non-rendering OpenGL mock context.
         kDebugGL_ContextType,       //! Non-rendering, state verifying OpenGL context.
-        kLastContextType = kDebugGL_ContextType
+        kVulkan_ContextType,        //! Vulkan
+        kLastContextType = kVulkan_ContextType
     };
 
     //! OpenGL or OpenGL ES context depending on the platform. To be removed.
@@ -81,8 +78,12 @@
     }
 
     static GrBackend ContextTypeBackend(ContextType type) {
-        // Currently all the context types use the GL backed
-        return kOpenGL_GrBackend;
+        switch (type) {
+            case kVulkan_ContextType:
+                return kVulkan_GrBackend;
+            default:
+                return kOpenGL_GrBackend;
+        }
     }
 
     static const char* ContextTypeName(ContextType type) {
@@ -91,28 +92,20 @@
                 return "gl";
             case kGLES_ContextType:
                 return "gles";
-#if SK_ANGLE
-#ifdef SK_BUILD_FOR_WIN
             case kANGLE_ContextType:
                 return "angle";
-#endif
             case kANGLE_GL_ContextType:
                 return "angle-gl";
-#endif
-#if SK_COMMAND_BUFFER
             case kCommandBuffer_ContextType:
                 return "commandbuffer";
-#endif
-#if SK_MESA
             case kMESA_ContextType:
                 return "mesa";
-#endif
             case kNullGL_ContextType:
-                return "null";
+                return "nullgl";
             case kDebugGL_ContextType:
-                return "debug";
-            default:
-                SkFAIL("Unknown GL Context type.");
+                return "debuggl";
+            case kVulkan_ContextType:
+                return "vulkan";
         }
     }
 
@@ -140,13 +133,15 @@
 
 private:
     struct Context {
-        ContextType         fType;
-        ContextOptions      fOptions;
-        GLTestContext*      fGLContext; //  null if non-GL
-        GrContext*          fGrContext;
+        ContextType     fType;
+        ContextOptions  fOptions;
+        GLTestContext*  fGLContext; //  null if non-GL
+        GrContext*      fGrContext;
+        bool            fAbandoned;
     };
-    SkTArray<Context, true> fContexts;
-    const GrContextOptions  fGlobalOptions;
+    SkTArray<Context, true>         fContexts;
+    SkAutoTDelete<GLTestContext>    fSentinelGLContext;
+    const GrContextOptions          fGlobalOptions;
 };
 }  // namespace sk_gpu_test
 #endif
diff --git a/tools/vulkan/VulkanTestContext.cpp b/tools/vulkan/VulkanTestContext.cpp
index 05ebfe7..b940656 100644
--- a/tools/vulkan/VulkanTestContext.cpp
+++ b/tools/vulkan/VulkanTestContext.cpp
@@ -33,7 +33,6 @@
 void VulkanTestContext::initializeContext(void* platformData) {
 
     fBackendContext.reset(GrVkBackendContext::Create());
-    fBackendContext->ref();
 
     fContext = GrContext::Create(kVulkan_GrBackend, (GrBackendContext)fBackendContext.get());