HLSL output: Fix nested dynamic indexing in an l-value

This fixes cases where a matrix is indexed and then the resulting
vector is indexed in the same expression inside an l-value.

BUG=angleproject:1672
TEST=angle_end2end_tests

Change-Id: Ia0593d75da67e0aa582003e1c381f2a1c89f948c
Reviewed-on: https://chromium-review.googlesource.com/427938
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/compiler/translator/RemoveDynamicIndexing.cpp b/src/compiler/translator/RemoveDynamicIndexing.cpp
index b51ffa5..d439235 100644
--- a/src/compiler/translator/RemoveDynamicIndexing.cpp
+++ b/src/compiler/translator/RemoveDynamicIndexing.cpp
@@ -433,6 +433,18 @@
                     mRemoveIndexSideEffectsInSubtree = true;
                     return true;
                 }
+
+                TIntermBinary *leftBinary = node->getLeft()->getAsBinaryNode();
+                if (leftBinary != nullptr &&
+                    IntermNodePatternMatcher::IsDynamicIndexingOfVectorOrMatrix(leftBinary))
+                {
+                    // This is a case like:
+                    // mat2 m;
+                    // m[a][b]++;
+                    // Process the child node m[a] first.
+                    return true;
+                }
+
                 // TODO(oetuaho@nvidia.com): This is not optimal if the expression using the value
                 // only writes it and doesn't need the previous value. http://anglebug.com/1116
 
diff --git a/src/tests/gl_tests/GLSLTest.cpp b/src/tests/gl_tests/GLSLTest.cpp
index 987fff2..d24253a 100644
--- a/src/tests/gl_tests/GLSLTest.cpp
+++ b/src/tests/gl_tests/GLSLTest.cpp
@@ -2537,6 +2537,27 @@
     ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
 }
 
+// Test that dynamic indexing of a matrix inside a dynamic indexing of a vector in an l-value works
+// correctly.
+TEST_P(GLSLTest_ES3, NestedDynamicIndexingInLValue)
+{
+    const std::string &fragmentShader =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "uniform int u_zero;\n"
+        "void main() {\n"
+        "    mat2 m = mat2(0.0, 0.0, 0.0, 0.0);\n"
+        "    m[u_zero + 1][u_zero + 1] = float(u_zero + 1);\n"
+        "    float f = m[1][1];\n"
+        "    my_FragColor = vec4(1.0 - f, f, 0.0, 1.0);\n"
+        "}\n";
+
+    ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
+    drawQuad(program.get(), "inputAttribute", 0.5f);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+}
+
 class WebGLGLSLTest : public GLSLTest
 {
   protected: