Revert "Let client pass in full extension to GrVkBackendContext."

This reverts commit 45c9dab4c3ec43cedb28d1b8c08e166fe0c2e767.

Reason for revert: fucshia uses GrVkBackendContext. Need to revert earlier changes

Original change's description:
> Let client pass in full extension to GrVkBackendContext.
> 
> Bug: skia:
> Change-Id: I772ab4ccbca0f4f7e7d429d6c421b07d97f0606f
> Reviewed-on: https://skia-review.googlesource.com/131880
> Reviewed-by: Jim Van Verth <jvanverth@google.com>
> Commit-Queue: Greg Daniel <egdaniel@google.com>

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

Change-Id: I1a765ff406c83cb234c3614b804fbed677d5a382
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: skia:
Reviewed-on: https://skia-review.googlesource.com/137901
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Greg Daniel <egdaniel@google.com>
diff --git a/src/gpu/vk/GrVkCaps.cpp b/src/gpu/vk/GrVkCaps.cpp
index d1dfcf0..1a14648 100644
--- a/src/gpu/vk/GrVkCaps.cpp
+++ b/src/gpu/vk/GrVkCaps.cpp
@@ -15,8 +15,9 @@
 #include "vk/GrVkInterface.h"
 
 GrVkCaps::GrVkCaps(const GrContextOptions& contextOptions, const GrVkInterface* vkInterface,
-                   VkPhysicalDevice physDev, uint32_t featureFlags)
+                   VkPhysicalDevice physDev, uint32_t featureFlags, uint32_t extensionFlags)
     : INHERITED(contextOptions) {
+    fCanUseGLSLForShaderModule = false;
     fMustDoCopiesFromOrigin = false;
     fMustSubmitCommandsBeforeCopyOp = false;
     fMustSleepOnTearDown  = false;
@@ -47,7 +48,7 @@
 
     fShaderCaps.reset(new GrShaderCaps(contextOptions));
 
-    this->init(contextOptions, vkInterface, physDev, featureFlags);
+    this->init(contextOptions, vkInterface, physDev, featureFlags, extensionFlags);
 }
 
 bool GrVkCaps::initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc* desc,
@@ -195,7 +196,7 @@
 }
 
 void GrVkCaps::init(const GrContextOptions& contextOptions, const GrVkInterface* vkInterface,
-                    VkPhysicalDevice physDev, uint32_t featureFlags) {
+                    VkPhysicalDevice physDev, uint32_t featureFlags, uint32_t extensionFlags) {
 
     VkPhysicalDeviceProperties properties;
     GR_VK_CALL(vkInterface, GetPhysicalDeviceProperties(physDev, &properties));
diff --git a/src/gpu/vk/GrVkCaps.h b/src/gpu/vk/GrVkCaps.h
index 6e23af0..2ed2254 100644
--- a/src/gpu/vk/GrVkCaps.h
+++ b/src/gpu/vk/GrVkCaps.h
@@ -27,7 +27,7 @@
      * be called to fill out the caps.
      */
     GrVkCaps(const GrContextOptions& contextOptions, const GrVkInterface* vkInterface,
-             VkPhysicalDevice device, uint32_t featureFlags);
+             VkPhysicalDevice device, uint32_t featureFlags, uint32_t extensionFlags);
 
     bool isConfigTexturable(GrPixelConfig config) const override {
         return SkToBool(ConfigInfo::kTextureable_Flag & fConfigTable[config].fOptimalFlags);
@@ -64,6 +64,11 @@
         return SkToBool(ConfigInfo::kBlitSrc_Flag & flags);
     }
 
+    // Tells of if we can pass in straight GLSL string into vkCreateShaderModule
+    bool canUseGLSLForShaderModule() const {
+        return fCanUseGLSLForShaderModule;
+    }
+
     // On Adreno vulkan, they do not respect the imageOffset parameter at least in
     // copyImageToBuffer. This flag says that we must do the copy starting from the origin always.
     bool mustDoCopiesFromOrigin() const {
@@ -146,7 +151,7 @@
     };
 
     void init(const GrContextOptions& contextOptions, const GrVkInterface* vkInterface,
-              VkPhysicalDevice device, uint32_t featureFlags);
+              VkPhysicalDevice device, uint32_t featureFlags, uint32_t extensionFlags);
     void initGrCaps(const VkPhysicalDeviceProperties&,
                     const VkPhysicalDeviceMemoryProperties&,
                     uint32_t featureFlags);
@@ -182,6 +187,7 @@
 
     StencilFormat fPreferedStencilFormat;
 
+    bool fCanUseGLSLForShaderModule;
     bool fMustDoCopiesFromOrigin;
     bool fMustSubmitCommandsBeforeCopyOp;
     bool fMustSleepOnTearDown;
diff --git a/src/gpu/vk/GrVkExtensions.cpp b/src/gpu/vk/GrVkExtensions.cpp
index 46bb94d..e4768d9 100644
--- a/src/gpu/vk/GrVkExtensions.cpp
+++ b/src/gpu/vk/GrVkExtensions.cpp
@@ -6,9 +6,7 @@
  */
 
 #include "vk/GrVkExtensions.h"
-
-// Can remove this once we get rid of the extension flags.
-#include "vk/GrVkBackendContext.h"
+#include "vk/GrVkUtil.h"
 
 #include "SkTSearch.h"
 #include "SkTSort.h"
@@ -32,82 +30,232 @@
     return idx;
 }
 
-GrVkExtensions::GrVkExtensions(uint32_t instanceExtensionCount,
-                               const char* const* instanceExtensions,
-                               uint32_t deviceExtensionCount,
-                               const char* const* deviceExtensions)
-        : fExtensionStrings() {
+#define GET_PROC_LOCAL(F, inst, device) PFN_vk ## F F = (PFN_vk ## F) fGetProc("vk" #F, inst, device)
+
+static uint32_t remove_patch_version(uint32_t specVersion) {
+    return (specVersion >> 12) << 12;
+}
+
+bool GrVkExtensions::initInstance(uint32_t specVersion) {
+    if (fGetProc == nullptr) {
+        return false;
+    }
+
+    uint32_t nonPatchVersion = remove_patch_version(specVersion);
+
+    GET_PROC_LOCAL(EnumerateInstanceExtensionProperties, VK_NULL_HANDLE, VK_NULL_HANDLE);
+    GET_PROC_LOCAL(EnumerateInstanceLayerProperties, VK_NULL_HANDLE, VK_NULL_HANDLE);
+
     SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp;
 
-    for (uint32_t i = 0; i < instanceExtensionCount; ++i) {
-        const char* extension = instanceExtensions[i];
-        // if not already in the list, add it
-        if (find_string(fExtensionStrings, extension) < 0) {
-            fExtensionStrings.push_back() = extension;
-            SkTQSort(&fExtensionStrings.front(), &fExtensionStrings.back(), cmp);
+    if (!EnumerateInstanceExtensionProperties ||
+        !EnumerateInstanceLayerProperties) {
+        return false;
+    }
+
+    // instance layers
+    uint32_t layerCount = 0;
+    VkResult res = EnumerateInstanceLayerProperties(&layerCount, nullptr);
+    if (VK_SUCCESS != res) {
+        return false;
+    }
+    VkLayerProperties* layers = new VkLayerProperties[layerCount];
+    res = EnumerateInstanceLayerProperties(&layerCount, layers);
+    if (VK_SUCCESS != res) {
+        delete[] layers;
+        return false;
+    }
+    for (uint32_t i = 0; i < layerCount; ++i) {
+        if (nonPatchVersion <= remove_patch_version(layers[i].specVersion)) {
+            fInstanceLayerStrings->push_back() = layers[i].layerName;
         }
     }
-    for (uint32_t i = 0; i < deviceExtensionCount; ++i) {
-        const char* extension = deviceExtensions[i];
-        // if not already in the list, add it
-        if (find_string(fExtensionStrings, extension) < 0) {
-            fExtensionStrings.push_back() = extension;
-            SkTQSort(&fExtensionStrings.front(), &fExtensionStrings.back(), cmp);
-        }
+    delete[] layers;
+    if (!fInstanceLayerStrings->empty()) {
+        SkTQSort(&fInstanceLayerStrings->front(), &fInstanceLayerStrings->back(), cmp);
     }
+
+    // instance extensions
+    // via Vulkan implementation and implicitly enabled layers
+    uint32_t extensionCount = 0;
+    res = EnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
+    if (VK_SUCCESS != res) {
+        return false;
+    }
+    VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
+    res = EnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions);
+    if (VK_SUCCESS != res) {
+        delete[] extensions;
+        return false;
+    }
+    for (uint32_t i = 0; i < extensionCount; ++i) {
+        fInstanceExtensionStrings->push_back() = extensions[i].extensionName;
+    }
+    delete [] extensions;
+    // sort so we can search
+    if (!fInstanceExtensionStrings->empty()) {
+        SkTQSort(&fInstanceExtensionStrings->front(), &fInstanceExtensionStrings->back(), cmp);
+    }
+    // via explicitly enabled layers
+    layerCount = fInstanceLayerStrings->count();
+    for (uint32_t layerIndex = 0; layerIndex < layerCount; ++layerIndex) {
+        uint32_t extensionCount = 0;
+        res = EnumerateInstanceExtensionProperties((*fInstanceLayerStrings)[layerIndex].c_str(),
+                                                   &extensionCount, nullptr);
+        if (VK_SUCCESS != res) {
+            return false;
+        }
+        VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
+        res = EnumerateInstanceExtensionProperties((*fInstanceLayerStrings)[layerIndex].c_str(),
+                                                   &extensionCount, extensions);
+        if (VK_SUCCESS != res) {
+            delete[] extensions;
+            return false;
+        }
+        for (uint32_t i = 0; i < extensionCount; ++i) {
+            // if not already in the list, add it
+            if (find_string(*fInstanceExtensionStrings, extensions[i].extensionName) < 0) {
+                fInstanceExtensionStrings->push_back() = extensions[i].extensionName;
+                SkTQSort(&fInstanceExtensionStrings->front(), &fInstanceExtensionStrings->back(),
+                         cmp);
+            }
+        }
+        delete[] extensions;
+    }
+
+    return true;
 }
 
-GrVkExtensions::GrVkExtensions(uint32_t extensionFlags)
-        : fExtensionStrings() {
+bool GrVkExtensions::initDevice(uint32_t specVersion, VkInstance inst, VkPhysicalDevice physDev) {
+    if (fGetProc == nullptr) {
+        return false;
+    }
+
+    uint32_t nonPatchVersion = remove_patch_version(specVersion);
+
+    GET_PROC_LOCAL(EnumerateDeviceExtensionProperties, inst, VK_NULL_HANDLE);
+    GET_PROC_LOCAL(EnumerateDeviceLayerProperties, inst, VK_NULL_HANDLE);
+
     SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp;
 
-    SkTArray<const char*> extensionNames;
-    GetExtensionArrayFromFlags(extensionFlags, &extensionNames);
-    for (int i = 0; i < extensionNames.count(); ++i) {
-        // if not already in the list, add it
-        if (find_string(fExtensionStrings, extensionNames[i]) < 0) {
-            fExtensionStrings.push_back() = extensionNames[i];
-            SkTQSort(&fExtensionStrings.front(), &fExtensionStrings.back(), cmp);
+    if (!EnumerateDeviceExtensionProperties ||
+        !EnumerateDeviceLayerProperties) {
+        return false;
+    }
+
+    // device layers
+    uint32_t layerCount = 0;
+    VkResult res = EnumerateDeviceLayerProperties(physDev, &layerCount, nullptr);
+    if (VK_SUCCESS != res) {
+        return false;
+    }
+    VkLayerProperties* layers = new VkLayerProperties[layerCount];
+    res = EnumerateDeviceLayerProperties(physDev, &layerCount, layers);
+    if (VK_SUCCESS != res) {
+        delete[] layers;
+        return false;
+    }
+    for (uint32_t i = 0; i < layerCount; ++i) {
+        if (nonPatchVersion <= remove_patch_version(layers[i].specVersion)) {
+            fDeviceLayerStrings->push_back() = layers[i].layerName;
         }
     }
+    delete[] layers;
+    if (!fDeviceLayerStrings->empty()) {
+        SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp;
+        SkTQSort(&fDeviceLayerStrings->front(), &fDeviceLayerStrings->back(), cmp);
+    }
+
+    // device extensions
+    // via Vulkan implementation and implicitly enabled layers
+    uint32_t extensionCount = 0;
+    res = EnumerateDeviceExtensionProperties(physDev, nullptr, &extensionCount, nullptr);
+    if (VK_SUCCESS != res) {
+        return false;
+    }
+    VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
+    res = EnumerateDeviceExtensionProperties(physDev, nullptr, &extensionCount, extensions);
+    if (VK_SUCCESS != res) {
+        delete[] extensions;
+        return false;
+    }
+    for (uint32_t i = 0; i < extensionCount; ++i) {
+        fDeviceExtensionStrings->push_back() = extensions[i].extensionName;
+    }
+    delete[] extensions;
+    if (!fDeviceExtensionStrings->empty()) {
+        SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp;
+        SkTQSort(&fDeviceExtensionStrings->front(), &fDeviceExtensionStrings->back(), cmp);
+    }
+    // via explicitly enabled layers
+    layerCount = fDeviceLayerStrings->count();
+    for (uint32_t layerIndex = 0; layerIndex < layerCount; ++layerIndex) {
+        uint32_t extensionCount = 0;
+        res = EnumerateDeviceExtensionProperties(physDev,
+            (*fDeviceLayerStrings)[layerIndex].c_str(),
+            &extensionCount, nullptr);
+        if (VK_SUCCESS != res) {
+            return false;
+        }
+        VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
+        res = EnumerateDeviceExtensionProperties(physDev,
+            (*fDeviceLayerStrings)[layerIndex].c_str(),
+            &extensionCount, extensions);
+        if (VK_SUCCESS != res) {
+            delete[] extensions;
+            return false;
+        }
+        for (uint32_t i = 0; i < extensionCount; ++i) {
+            // if not already in the list, add it
+            if (find_string(*fDeviceExtensionStrings, extensions[i].extensionName) < 0) {
+                fDeviceExtensionStrings->push_back() = extensions[i].extensionName;
+                SkTQSort(&fDeviceExtensionStrings->front(), &fDeviceExtensionStrings->back(), cmp);
+            }
+        }
+        delete[] extensions;
+    }
+
+    return true;
 }
 
-bool GrVkExtensions::hasExtension(const char ext[]) const {
-    return find_string(fExtensionStrings, ext) >= 0;
+bool GrVkExtensions::hasInstanceExtension(const char ext[]) const {
+    return find_string(*fInstanceExtensionStrings, ext) >= 0;
 }
 
-void GrVkExtensions::GetExtensionArrayFromFlags(uint32_t extensionFlags,
-                                                SkTArray<const char*>* extensions) {
-#ifdef SK_ENABLE_VK_LAYERS
-    if (extensionFlags & kEXT_debug_report_GrVkExtensionFlag) {
-        extensions->push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
-    }
-#endif
-    if (extensionFlags & kKHR_surface_GrVkExtensionFlag) {
-        extensions->push_back(VK_KHR_SURFACE_EXTENSION_NAME);
-    }
-    if (extensionFlags & kKHR_swapchain_GrVkExtensionFlag) {
-        extensions->push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
-    }
-#ifdef SK_BUILD_FOR_WIN
-    if (extensionFlags & kKHR_win32_surface_GrVkExtensionFlag) {
-        extensions->push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
-    }
-#elif defined(SK_BUILD_FOR_ANDROID)
-    if (extensionFlags & kKHR_android_surface_GrVkExtensionFlag) {
-        extensions->push_back(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME);
-    }
-#elif defined(SK_BUILD_FOR_UNIX) && !defined(__Fuchsia__)
-    if (extensionFlags & kKHR_xcb_surface_GrVkExtensionFlag) {
-        extensions->push_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME);
-    }
-#endif
-    // Device extensions
-    if (extensionFlags & kKHR_swapchain_GrVkExtensionFlag) {
-        extensions->push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
-    }
-    if (extensionFlags & kNV_glsl_shader_GrVkExtensionFlag) {
-        extensions->push_back("VK_NV_glsl_shader");
-    }
+bool GrVkExtensions::hasDeviceExtension(const char ext[]) const {
+    return find_string(*fDeviceExtensionStrings, ext) >= 0;
 }
 
+bool GrVkExtensions::hasInstanceLayer(const char ext[]) const {
+    return find_string(*fInstanceLayerStrings, ext) >= 0;
+}
+
+bool GrVkExtensions::hasDeviceLayer(const char ext[]) const {
+    return find_string(*fDeviceLayerStrings, ext) >= 0;
+}
+
+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 : "");
+    }
+}
diff --git a/src/gpu/vk/GrVkExtensions.h b/src/gpu/vk/GrVkExtensions.h
new file mode 100644
index 0000000..8de28f4
--- /dev/null
+++ b/src/gpu/vk/GrVkExtensions.h
@@ -0,0 +1,50 @@
+/*
+ * 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 "vk/GrVkDefines.h"
+#include "vk/GrVkInterface.h"
+
+/**
+ * This helper queries the Vulkan driver for available 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(GrVkInterface::GetProc getProc)
+                     : fGetProc(getProc)
+                     , fInstanceExtensionStrings(new SkTArray<SkString>)
+                     , fDeviceExtensionStrings(new SkTArray<SkString>)
+                     , fInstanceLayerStrings(new SkTArray<SkString>)
+                     , fDeviceLayerStrings(new SkTArray<SkString>) {}
+
+    bool initInstance(uint32_t specVersion);
+    bool initDevice(uint32_t specVersion, VkInstance, VkPhysicalDevice);
+
+    /**
+     * Queries whether an extension or layer is present. Will fail if not initialized.
+     */
+    bool hasInstanceExtension(const char[]) const;
+    bool hasDeviceExtension(const char[]) const;
+    bool hasInstanceLayer(const char[]) const;
+    bool hasDeviceLayer(const char[]) const;
+
+    void print(const char* sep = "\n") const;
+
+private:
+    GrVkInterface::GetProc fGetProc;
+    std::unique_ptr<SkTArray<SkString>>  fInstanceExtensionStrings;
+    std::unique_ptr<SkTArray<SkString>>  fDeviceExtensionStrings;
+    std::unique_ptr<SkTArray<SkString>>  fInstanceLayerStrings;
+    std::unique_ptr<SkTArray<SkString>>  fDeviceLayerStrings;
+};
+
+#endif
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index 81787b2..65225d9 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -36,7 +36,6 @@
 #include "SkMipMap.h"
 #include "SkSLCompiler.h"
 #include "SkTo.h"
-
 #include "vk/GrVkInterface.h"
 #include "vk/GrVkTypes.h"
 
@@ -59,7 +58,7 @@
         return nullptr;
     }
     if (!backendContext.fInterface ||
-        !backendContext.fInterface->validate()) {
+        !backendContext.fInterface->validate(backendContext.fExtensions)) {
         return nullptr;
     }
 
@@ -89,7 +88,7 @@
     fCompiler = new SkSL::Compiler();
 
     fVkCaps.reset(new GrVkCaps(options, this->vkInterface(), backendContext.fPhysicalDevice,
-                               backendContext.fFeatures));
+                               backendContext.fFeatures, backendContext.fExtensions));
     fCaps.reset(SkRef(fVkCaps.get()));
 
     VK_CALL(GetPhysicalDeviceProperties(backendContext.fPhysicalDevice, &fPhysDevProps));
diff --git a/src/gpu/vk/GrVkGpu.h b/src/gpu/vk/GrVkGpu.h
index a8138923..266c916 100644
--- a/src/gpu/vk/GrVkGpu.h
+++ b/src/gpu/vk/GrVkGpu.h
@@ -144,7 +144,7 @@
     bool updateBuffer(GrVkBuffer* buffer, const void* src, VkDeviceSize offset, VkDeviceSize size);
 
 private:
-    GrVkGpu(GrContext*, const GrContextOptions&, const GrVkBackendContext&);
+    GrVkGpu(GrContext*, const GrContextOptions&, const GrVkBackendContext& backendContext);
 
     void onResetContext(uint32_t resetBits) override {}
 
diff --git a/src/gpu/vk/GrVkInterface.cpp b/src/gpu/vk/GrVkInterface.cpp
index c8f3371..dedc264 100644
--- a/src/gpu/vk/GrVkInterface.cpp
+++ b/src/gpu/vk/GrVkInterface.cpp
@@ -22,27 +22,20 @@
     };
 }
 
-GrVkInterface::GrVkInterface(GetProc getProc,
+GrVkInterface::GrVkInterface(const GetInstanceProc& getInstanceProc,
+                             const GetDeviceProc& getDeviceProc,
                              VkInstance instance,
                              VkDevice device,
                              uint32_t extensionFlags)
-        : fExtensions(extensionFlags) {
-    this->init(getProc, instance, device);
-}
+        : GrVkInterface(make_unified_getter(getInstanceProc, getDeviceProc),
+                        instance,
+                        device,
+                        extensionFlags) {}
 
 GrVkInterface::GrVkInterface(GetProc getProc,
                              VkInstance instance,
                              VkDevice device,
-                             uint32_t instanceExtensionCount,
-                             const char* const* instanceExtensions,
-                             uint32_t deviceExtensionCount,
-                             const char* const* deviceExtensions)
-        : fExtensions(instanceExtensionCount, instanceExtensions, deviceExtensionCount,
-                      deviceExtensions) {
-    this->init(getProc, instance, device);
-}
-
-void GrVkInterface::init(GetProc getProc, VkInstance instance, VkDevice device) {
+                             uint32_t extensionFlags) {
     if (getProc == nullptr) {
         return;
     }
@@ -66,7 +59,7 @@
     ACQUIRE_PROC(EnumerateDeviceExtensionProperties, instance, VK_NULL_HANDLE);
     ACQUIRE_PROC(EnumerateDeviceLayerProperties, instance, VK_NULL_HANDLE);
 
-    if (fExtensions.hasExtension(VK_EXT_DEBUG_REPORT_EXTENSION_NAME)) {
+    if (extensionFlags & kEXT_debug_report_GrVkExtensionFlag) {
         // Also instance Procs.
         ACQUIRE_PROC(CreateDebugReportCallbackEXT, instance, VK_NULL_HANDLE);
         ACQUIRE_PROC(DebugReportMessageEXT, instance, VK_NULL_HANDLE);
@@ -205,7 +198,7 @@
     if (kIsDebug) { SkDebugf("%s:%d GrVkInterface::validate() failed.\n", __FILE__, __LINE__); } \
     return false;
 
-bool GrVkInterface::validate() const {
+bool GrVkInterface::validate(uint32_t extensionFlags) const {
     // functions that are always required
     if (nullptr == fFunctions.fCreateInstance ||
         nullptr == fFunctions.fDestroyInstance ||
@@ -345,7 +338,7 @@
         RETURN_FALSE_INTERFACE
     }
 
-    if (fExtensions.hasExtension(VK_EXT_DEBUG_REPORT_EXTENSION_NAME)) {
+    if (extensionFlags & kEXT_debug_report_GrVkExtensionFlag) {
         if (nullptr == fFunctions.fCreateDebugReportCallbackEXT ||
             nullptr == fFunctions.fDebugReportMessageEXT ||
             nullptr == fFunctions.fDestroyDebugReportCallbackEXT) {