Select viewport index in GS for multi-view instanced rendering

The patch extends the OutputHLSL and DynamicHLSL translators to
select the viewport index in the geometry shader and propagate
the ViewID variable to the fragment shader.

BUG=angleproject:2062
TEST=angle_end2end_tests

Change-Id: I9e344a7521e2e1137e6eb38d0bfecea8bece778f
Reviewed-on: https://chromium-review.googlesource.com/608967
Commit-Queue: Martin Radev <mradev@nvidia.com>
Reviewed-by: Olli Etuaho <oetuaho@nvidia.com>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/renderer/d3d/ProgramD3D.cpp b/src/libANGLE/renderer/d3d/ProgramD3D.cpp
index 5953a66..3c4c432 100644
--- a/src/libANGLE/renderer/d3d/ProgramD3D.cpp
+++ b/src/libANGLE/renderer/d3d/ProgramD3D.cpp
@@ -343,6 +343,8 @@
       mUsesInstancedPointSpriteEmulation(
           renderer->getWorkarounds().useInstancedPointSpriteEmulation),
       mUsesViewScale(renderer->presentPathFastEnabled()),
+      mHasANGLEMultiviewEnabled(vertexShader->hasANGLEMultiviewEnabled()),
+      mUsesViewID(fragmentShader->usesViewID()),
       mVertexShader(vertexShader),
       mFragmentShader(fragmentShader)
 {
@@ -390,6 +392,16 @@
     return mUsesViewScale;
 }
 
+bool ProgramD3DMetadata::hasANGLEMultiviewEnabled() const
+{
+    return mHasANGLEMultiviewEnabled;
+}
+
+bool ProgramD3DMetadata::usesViewID() const
+{
+    return mUsesViewID;
+}
+
 bool ProgramD3DMetadata::addsPointCoordToVertexShader() const
 {
     // PointSprite emulation requiress that gl_PointCoord is present in the vertex shader
@@ -549,14 +561,22 @@
     return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4;
 }
 
+bool ProgramD3D::usesGeometryShaderForPointSpriteEmulation() const
+{
+    return usesPointSpriteEmulation() && !usesInstancedPointSpriteEmulation();
+}
+
 bool ProgramD3D::usesGeometryShader(GLenum drawMode) const
 {
+    if (mHasANGLEMultiviewEnabled)
+    {
+        return true;
+    }
     if (drawMode != GL_POINTS)
     {
         return mUsesFlatInterpolation;
     }
-
-    return usesPointSpriteEmulation() && !usesInstancedPointSpriteEmulation();
+    return usesGeometryShaderForPointSpriteEmulation();
 }
 
 bool ProgramD3D::usesInstancedPointSpriteEmulation() const
@@ -843,6 +863,8 @@
     stream->readBytes(reinterpret_cast<unsigned char *>(&mPixelWorkarounds),
                       sizeof(angle::CompilerWorkaroundsD3D));
     stream->readBool(&mUsesFragDepth);
+    stream->readBool(&mHasANGLEMultiviewEnabled);
+    stream->readBool(&mUsesViewID);
     stream->readBool(&mUsesPointSize);
     stream->readBool(&mUsesFlatInterpolation);
 
@@ -1066,6 +1088,8 @@
     stream->writeBytes(reinterpret_cast<unsigned char *>(&mPixelWorkarounds),
                        sizeof(angle::CompilerWorkaroundsD3D));
     stream->writeInt(mUsesFragDepth);
+    stream->writeInt(mHasANGLEMultiviewEnabled);
+    stream->writeInt(mUsesViewID);
     stream->writeInt(mUsesPointSize);
     stream->writeInt(mUsesFlatInterpolation);
 
@@ -1269,6 +1293,7 @@
 
     std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(
         geometryShaderType, data, mState, mRenderer->presentPathFastEnabled(),
+        mHasANGLEMultiviewEnabled, usesGeometryShaderForPointSpriteEmulation(),
         mGeometryShaderPreamble);
 
     gl::InfoLog tempInfoLog;
@@ -1558,6 +1583,8 @@
         mUsesPointSize = vertexShaderD3D->usesPointSize();
         mDynamicHLSL->getPixelShaderOutputKey(data, mState, metadata, &mPixelShaderKey);
         mUsesFragDepth = metadata.usesFragDepth();
+        mUsesViewID               = metadata.usesViewID();
+        mHasANGLEMultiviewEnabled = metadata.hasANGLEMultiviewEnabled();
 
         // Cache if we use flat shading
         mUsesFlatInterpolation =
@@ -1566,8 +1593,8 @@
 
         if (mRenderer->getMajorShaderModel() >= 4)
         {
-            mGeometryShaderPreamble =
-                mDynamicHLSL->generateGeometryShaderPreamble(packing, builtins);
+            mGeometryShaderPreamble = mDynamicHLSL->generateGeometryShaderPreamble(
+                packing, builtins, mHasANGLEMultiviewEnabled);
         }
 
         initAttribLocationsToD3DSemantic(context);
@@ -2330,6 +2357,8 @@
     mPixelHLSL.clear();
     mPixelWorkarounds = angle::CompilerWorkaroundsD3D();
     mUsesFragDepth = false;
+    mHasANGLEMultiviewEnabled = false;
+    mUsesViewID               = false;
     mPixelShaderKey.clear();
     mUsesPointSize = false;
     mUsesFlatInterpolation = false;