D3D11: Fix basic provoking vertex flat shading cases.

The enables geometry shaders that correct for the flat shading on
provoking vertexes. It does not fix it for triangle strips, or in
conjunction with primitive restart (which is not yet implemented
in D3D11).

Also ensure we do not regress with flat shading enabled and transform
feedback. In cases where we use flat shading, do a double draw call,
first with an untransformed vertex stream, and no geometry shader,
then with the geometry shader enabled.

This also fixes the dEQP fragment output tests with ints.

BUG=angleproject:754

Change-Id: Ib37e8ec32d19db17ea5d4dc88158cdae0c956bfc
Reviewed-on: https://chromium-review.googlesource.com/309155
Tryjob-Request: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Tested-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/renderer/d3d/ProgramD3D.cpp b/src/libANGLE/renderer/d3d/ProgramD3D.cpp
index 7f6bccb..5eba95c 100644
--- a/src/libANGLE/renderer/d3d/ProgramD3D.cpp
+++ b/src/libANGLE/renderer/d3d/ProgramD3D.cpp
@@ -411,6 +411,7 @@
       mDynamicHLSL(NULL),
       mGeometryExecutables(gl::PRIMITIVE_TYPE_MAX, nullptr),
       mUsesPointSize(false),
+      mUsesFlatInterpolation(false),
       mVertexUniformStorage(NULL),
       mFragmentUniformStorage(NULL),
       mUsedVertexSamplerRange(0),
@@ -432,8 +433,13 @@
     return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4;
 }
 
-bool ProgramD3D::usesGeometryShader() const
+bool ProgramD3D::usesGeometryShader(GLenum drawMode) const
 {
+    if (drawMode != GL_POINTS)
+    {
+        return mUsesFlatInterpolation;
+    }
+
     return usesPointSpriteEmulation() && !usesInstancedPointSpriteEmulation();
 }
 
@@ -680,6 +686,7 @@
                       sizeof(D3DCompilerWorkarounds));
     stream->readBool(&mUsesFragDepth);
     stream->readBool(&mUsesPointSize);
+    stream->readBool(&mUsesFlatInterpolation);
 
     const size_t pixelShaderKeySize = stream->readInt<unsigned int>();
     mPixelShaderKey.resize(pixelShaderKeySize);
@@ -882,6 +889,7 @@
                        sizeof(D3DCompilerWorkarounds));
     stream->writeInt(mUsesFragDepth);
     stream->writeInt(mUsesPointSize);
+    stream->writeInt(mUsesFlatInterpolation);
 
     const std::vector<PixelShaderOutputVariable> &pixelShaderKey = mPixelShaderKey;
     stream->writeInt(pixelShaderKey.size());
@@ -1083,6 +1091,18 @@
                                                             ShaderExecutableD3D **outExecutable,
                                                             gl::InfoLog *infoLog)
 {
+    if (outExecutable)
+    {
+        *outExecutable = nullptr;
+    }
+
+    // We only uses a geometry shader for point sprite emulation, or for fixing the provoking
+    // vertex problem. Otherwise, return a null shader.
+    if (drawMode != GL_POINTS && !mUsesFlatInterpolation)
+    {
+        return gl::Error(GL_NO_ERROR);
+    }
+
     gl::PrimitiveType geometryShaderType = GetGeometryShaderTypeFromDrawMode(drawMode);
 
     if (mGeometryExecutables[geometryShaderType] != nullptr)
@@ -1141,7 +1161,7 @@
     }
 
     // Auto-generate the geometry shader here, if we expect to be using point rendering in D3D11.
-    if (usesGeometryShader())
+    if (usesGeometryShader(GL_POINTS))
     {
         getGeometryExecutableForPrimitiveType(data, GL_POINTS, nullptr, &infoLog);
     }
@@ -1171,8 +1191,9 @@
     }
 #endif
 
-    bool linkSuccess = (defaultVertexExecutable && defaultPixelExecutable &&
-                        (!usesGeometryShader() || mGeometryExecutables[gl::PRIMITIVE_POINTS]));
+    bool linkSuccess =
+        (defaultVertexExecutable && defaultPixelExecutable &&
+         (!usesGeometryShader(GL_POINTS) || mGeometryExecutables[gl::PRIMITIVE_POINTS]));
     return LinkResult(linkSuccess, gl::Error(GL_NO_ERROR));
 }
 
@@ -1232,6 +1253,16 @@
 
     mUsesPointSize = vertexShaderD3D->usesPointSize();
 
+    // Cache if we use flat shading
+    for (const auto &varying : packedVaryings)
+    {
+        if (varying.varying->interpolation == sh::INTERPOLATION_FLAT)
+        {
+            mUsesFlatInterpolation = true;
+            break;
+        }
+    }
+
     if (mRenderer->getMajorShaderModel() >= 4)
     {
         mGeometryShaderPreamble = mDynamicHLSL->generateGeometryShaderPreamble(
@@ -1351,11 +1382,11 @@
     mFragmentUniformStorage = mRenderer->createUniformStorage(fragmentRegisters * 16u);
 }
 
-gl::Error ProgramD3D::applyUniforms()
+gl::Error ProgramD3D::applyUniforms(GLenum drawMode)
 {
     updateSamplerMapping();
 
-    gl::Error error = mRenderer->applyUniforms(*this, mD3DUniforms);
+    gl::Error error = mRenderer->applyUniforms(*this, drawMode, mD3DUniforms);
     if (error.isError())
     {
         return error;
@@ -1941,6 +1972,7 @@
     mUsesFragDepth = false;
     mPixelShaderKey.clear();
     mUsesPointSize = false;
+    mUsesFlatInterpolation = false;
 
     SafeDeleteContainer(mD3DUniforms);
     mD3DUniformBlocks.clear();