ParallelCompile: Parallelize D3D linking

This adds a new linking state to Program. If a Program is in linking
state, on the one hand the foreground thread may continue issuing more
GL calls, and on the other hand the background linking threads may be
accessing Program internally too. Without a proper constraint there
must be conflicts between them. For this purpose, we block any further
GL calls to Program until it's actually linked. In addition, we
prohibit parallel linking an active program, so that ProgramD3D does
not have to worry about such similar conflicts.

Also changes the WorkerThread to support limiting the number of
concurrently running worker threads.

BUG=chromium:849576

Change-Id: I52618647539323f8bf27201320bdf7301c4982e6
Reviewed-on: https://chromium-review.googlesource.com/1127495
Commit-Queue: Jie A Chen <jie.a.chen@intel.com>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/renderer/ProgramImpl.h b/src/libANGLE/renderer/ProgramImpl.h
index 09b6f87..713e2f4 100644
--- a/src/libANGLE/renderer/ProgramImpl.h
+++ b/src/libANGLE/renderer/ProgramImpl.h
@@ -30,6 +30,35 @@
 
 namespace rx
 {
+
+// Provides a mechanism to access the result of asynchronous linking.
+class LinkEvent : angle::NonCopyable
+{
+  public:
+    virtual ~LinkEvent(){};
+
+    // Please be aware that these methods may be called under a gl::Context other
+    // than the one where the LinkEvent was created.
+    //
+    // Waits until the linking is actually done. Returns true if the linking
+    // succeeded, false otherwise.
+    virtual bool wait() = 0;
+    // Peeks whether the linking is still ongoing.
+    virtual bool isLinking() = 0;
+};
+
+// Wraps an already done linking.
+class LinkEventDone final : public LinkEvent
+{
+  public:
+    LinkEventDone(const gl::LinkResult &result) : mResult(result) {}
+    bool wait() override { return (!mResult.isError() && mResult.getResult()); }
+    bool isLinking() override { return false; }
+
+  private:
+    gl::LinkResult mResult;
+};
+
 class ProgramImpl : angle::NonCopyable
 {
   public:
@@ -44,9 +73,9 @@
     virtual void setBinaryRetrievableHint(bool retrievable) = 0;
     virtual void setSeparable(bool separable)               = 0;
 
-    virtual gl::LinkResult link(const gl::Context *context,
-                                const gl::ProgramLinkedResources &resources,
-                                gl::InfoLog &infoLog)                      = 0;
+    virtual std::unique_ptr<LinkEvent> link(const gl::Context *context,
+                                            const gl::ProgramLinkedResources &resources,
+                                            gl::InfoLog &infoLog)          = 0;
     virtual GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) = 0;
 
     virtual void setUniform1fv(GLint location, GLsizei count, const GLfloat *v) = 0;