glslang: enforce initialize and release as once per process

Bug: angleproject:4354
Change-Id: Ice0912a90d4e9a4fe3fdaf67d67292afc0eba8a2
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2073201
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/renderer/metal/DisplayMtl.h b/src/libANGLE/renderer/metal/DisplayMtl.h
index 8190042..f093750 100644
--- a/src/libANGLE/renderer/metal/DisplayMtl.h
+++ b/src/libANGLE/renderer/metal/DisplayMtl.h
@@ -156,6 +156,9 @@
     mutable gl::Limitations mNativeLimitations;
 
     angle::FeaturesMtl mFeatures;
+
+    // track whether we initialized (or released) glslang
+    bool mGlslangInitialized;
 };
 
 }  // namespace rx
diff --git a/src/libANGLE/renderer/metal/DisplayMtl.mm b/src/libANGLE/renderer/metal/DisplayMtl.mm
index 8da9700..0c8c281 100644
--- a/src/libANGLE/renderer/metal/DisplayMtl.mm
+++ b/src/libANGLE/renderer/metal/DisplayMtl.mm
@@ -37,7 +37,9 @@
     return new DisplayMtl(state);
 }
 
-DisplayMtl::DisplayMtl(const egl::DisplayState &state) : DisplayImpl(state), mUtils(this) {}
+DisplayMtl::DisplayMtl(const egl::DisplayState &state)
+    : DisplayImpl(state), mUtils(this), mGlslangInitialized(false)
+{}
 
 DisplayMtl::~DisplayMtl() {}
 
@@ -67,7 +69,11 @@
 
         mCapsInitialized = false;
 
-        GlslangInitialize();
+        if (!mGlslangInitialized)
+        {
+            GlslangInitialize();
+            mGlslangInitialized = true;
+        }
 
         if (!mState.featuresAllDisabled)
         {
@@ -91,7 +97,11 @@
     mMetalDevice     = nil;
     mCapsInitialized = false;
 
-    GlslangRelease();
+    if (mGlslangInitialized)
+    {
+        GlslangRelease();
+        mGlslangInitialized = false;
+    }
 }
 
 bool DisplayMtl::testDeviceLost()
diff --git a/src/libANGLE/renderer/vulkan/RendererVk.cpp b/src/libANGLE/renderer/vulkan/RendererVk.cpp
index ebd05df..ee39d64 100644
--- a/src/libANGLE/renderer/vulkan/RendererVk.cpp
+++ b/src/libANGLE/renderer/vulkan/RendererVk.cpp
@@ -575,7 +575,8 @@
       mDeviceLost(false),
       mPipelineCacheVkUpdateTimeout(kPipelineCacheVkUpdatePeriod),
       mPipelineCacheDirty(false),
-      mPipelineCacheInitialized(false)
+      mPipelineCacheInitialized(false),
+      mGlslangInitialized(false)
 {
     VkFormatProperties invalid = {0, 0, kInvalidFormatFeatureFlags};
     mFormatProperties.fill(invalid);
@@ -621,7 +622,11 @@
 
     mPipelineCache.destroy(mDevice);
 
-    GlslangRelease();
+    if (mGlslangInitialized)
+    {
+        GlslangRelease();
+        mGlslangInitialized = false;
+    }
 
     if (mDevice)
     {
@@ -922,7 +927,11 @@
     // Store the physical device memory properties so we can find the right memory pools.
     mMemoryProperties.init(mPhysicalDevice);
 
-    GlslangInitialize();
+    if (!mGlslangInitialized)
+    {
+        GlslangInitialize();
+        mGlslangInitialized = true;
+    }
 
     // Initialize the format table.
     mFormatTable.initialize(this, &mNativeTextureCaps, &mNativeCaps.compressedTextureFormats);
diff --git a/src/libANGLE/renderer/vulkan/RendererVk.h b/src/libANGLE/renderer/vulkan/RendererVk.h
index d03da2a..00e84cc 100644
--- a/src/libANGLE/renderer/vulkan/RendererVk.h
+++ b/src/libANGLE/renderer/vulkan/RendererVk.h
@@ -352,6 +352,9 @@
         vk::PrimaryCommandBuffer commandBuffer;
     };
     std::deque<PendingOneOffCommands> mPendingOneOffCommands;
+
+    // track whether we initialized (or released) glslang
+    bool mGlslangInitialized;
 };
 
 }  // namespace rx