Prevent D3D11 Feature Level 9_3 from sampling from SV_Position in Pixel Shaders

D3D11 FL9_3, like Shader Model 2.0 in D3D9, doesn't support reading from SV_Position in the pixel shader. We have to reconstruct gl_FragCoord using dx_ViewCoords instead.

Change-Id: I7e898038d210d73a9d224dcc18b033e5cd4a56f5
Reviewed-on: https://chromium-review.googlesource.com/234277
Tested-by: Austin Kinross <aukinros@microsoft.com>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/renderer/d3d/DynamicHLSL.cpp b/src/libANGLE/renderer/d3d/DynamicHLSL.cpp
index 8e0c2bd..1225f58 100644
--- a/src/libANGLE/renderer/d3d/DynamicHLSL.cpp
+++ b/src/libANGLE/renderer/d3d/DynamicHLSL.cpp
@@ -871,12 +871,14 @@
     {
         pixelHLSL += "    float rhw = 1.0 / input.gl_FragCoord.w;\n";
 
-        if (shaderModel >= 4)
+        // Certain Shader Models (4_0+ and 3_0) allow reading from dx_Position in the pixel shader.
+        // Other Shader Models (4_0_level_9_3 and 2_x) don't support this, so we emulate it using dx_ViewCoords.
+        if (shaderModel >= 4 && mRenderer->getShaderModelSuffix() == "")
         {
             pixelHLSL += "    gl_FragCoord.x = input.dx_Position.x;\n"
                          "    gl_FragCoord.y = input.dx_Position.y;\n";
         }
-        else if (shaderModel >= 3)
+        else if (shaderModel == 3)
         {
             pixelHLSL += "    gl_FragCoord.x = input.dx_Position.x + 0.5;\n"
                          "    gl_FragCoord.y = input.dx_Position.y + 0.5;\n";
diff --git a/src/libANGLE/renderer/d3d/RendererD3D.h b/src/libANGLE/renderer/d3d/RendererD3D.h
index 34f18f5..ccc0d01 100644
--- a/src/libANGLE/renderer/d3d/RendererD3D.h
+++ b/src/libANGLE/renderer/d3d/RendererD3D.h
@@ -76,6 +76,9 @@
     bool isDeviceLost() const override;
     std::string getVendorString() const override;
 
+    virtual int getMinorShaderModel() const = 0;
+    virtual std::string getShaderModelSuffix() const = 0;
+
     DisplayImpl *createDisplay() override;
 
     // Direct3D Specific methods
diff --git a/src/libANGLE/renderer/d3d/d3d11/Renderer11.h b/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
index 7acf58a..b4c8324 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
+++ b/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
@@ -114,6 +114,8 @@
     virtual bool getPostSubBufferSupport() const;
 
     virtual int getMajorShaderModel() const;
+    int getMinorShaderModel() const override;
+    std::string getShaderModelSuffix() const override;
     virtual int getMinSwapInterval() const;
     virtual int getMaxSwapInterval() const;
 
@@ -247,8 +249,6 @@
 
     void initializeDevice();
     void releaseDeviceResources();
-    int getMinorShaderModel() const;
-    std::string getShaderModelSuffix() const;
     void release();
 
     RenderStateCache mStateCache;
diff --git a/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp b/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
index 999ebde..b5f7a0c 100644
--- a/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
+++ b/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
@@ -2383,6 +2383,16 @@
     return D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion);
 }
 
+int Renderer9::getMinorShaderModel() const
+{
+    return D3DSHADER_VERSION_MINOR(mDeviceCaps.PixelShaderVersion);
+}
+
+std::string Renderer9::getShaderModelSuffix() const
+{
+    return "";
+}
+
 DWORD Renderer9::getCapsDeclTypes() const
 {
     return mDeviceCaps.DeclTypes;
diff --git a/src/libANGLE/renderer/d3d/d3d9/Renderer9.h b/src/libANGLE/renderer/d3d/d3d9/Renderer9.h
index 2127bf5..76527e8 100644
--- a/src/libANGLE/renderer/d3d/d3d9/Renderer9.h
+++ b/src/libANGLE/renderer/d3d/d3d9/Renderer9.h
@@ -117,6 +117,9 @@
     virtual bool getPostSubBufferSupport() const;
 
     virtual int getMajorShaderModel() const;
+    int getMinorShaderModel() const override;
+    std::string getShaderModelSuffix() const override;
+
     DWORD getCapsDeclTypes() const;
     virtual int getMinSwapInterval() const;
     virtual int getMaxSwapInterval() const;