Compile GLSL in a critical section

Our copy of glslang is not thread safe, so we need to ensure a mutex is
held during GLSL compilation. With shared contexts this was already the
case because we lock a mutex belonging to the shared resource manager
(through es2::getContext()), but using independent contexts in multiple
threads was unsafe.

Use of glReleaseShaderCompiler() was also unsafe, even with shared
contexts, because no lock was taken.

Bug: b/137828018
Change-Id: I90028035868f95c5a121777aee05c2128a2f8180
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/34488
Presubmit-Ready: Nicolas Capens <nicolascapens@google.com>
Tested-by: Nicolas Capens <nicolascapens@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
diff --git a/src/OpenGL/libGLESv2/Shader.cpp b/src/OpenGL/libGLESv2/Shader.cpp
index 269d884..db5efeb 100644
--- a/src/OpenGL/libGLESv2/Shader.cpp
+++ b/src/OpenGL/libGLESv2/Shader.cpp
@@ -26,6 +26,7 @@
 
 namespace es2
 {
+std::mutex Shader::mutex;
 bool Shader::compilerInitialized = false;
 
 Shader::Shader(ResourceManager *manager, GLuint handle) : mHandle(handle), mResourceManager(manager)
@@ -206,6 +207,9 @@
 
 void Shader::compile()
 {
+	// Our version of glslang is not thread safe.
+	std::lock_guard<std::mutex> lock(mutex);
+
 	clear();
 
 	createShader();
@@ -295,6 +299,9 @@
 
 void Shader::releaseCompiler()
 {
+	// Our version of glslang is not thread safe.
+	std::lock_guard<std::mutex> lock(mutex);
+
 	FreeCompilerGlobals();
 	compilerInitialized = false;
 }
diff --git a/src/OpenGL/libGLESv2/Shader.h b/src/OpenGL/libGLESv2/Shader.h
index 63d50ae..32cbaf6 100644
--- a/src/OpenGL/libGLESv2/Shader.h
+++ b/src/OpenGL/libGLESv2/Shader.h
@@ -28,6 +28,7 @@
 
 #include <string>
 #include <list>
+#include <mutex>
 #include <vector>
 
 namespace glsl
@@ -69,7 +70,9 @@
 	static void releaseCompiler();
 
 protected:
+	static std::mutex mutex;
 	static bool compilerInitialized;
+
 	TranslatorASM *createCompiler(GLenum shaderType);
 	void clear();