Store the std140 layout offsets in a pre-pass.

Instead of recording data and mutating a local table as we parse,
store all of the offsets for the std140 structs when we first
generate the struct. This should have no behavioural change, as
structs should always be defined first in any case.

BUG=angle:466

Change-Id: I1b732d67bd4f5b908211410e5e7796d72d836174
Reviewed-on: https://chromium-review.googlesource.com/202910
Tested-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Nicolas Capens <nicolascapens@chromium.org>
Reviewed-by: Zhenyao Mo <zmo@chromium.org>
diff --git a/src/compiler/translator/OutputHLSL.cpp b/src/compiler/translator/OutputHLSL.cpp
index ea0045f..f6831e2 100644
--- a/src/compiler/translator/OutputHLSL.cpp
+++ b/src/compiler/translator/OutputHLSL.cpp
@@ -3483,12 +3483,6 @@
     // Nameless structs do not finish with a semicolon and newline, to leave room for an instance variable
     string += (isNameless ? "} " : "};\n");
 
-    // Add remaining element index to the global map, for use with nested structs in standard layouts
-    if (useStd140Packing)
-    {
-        mStd140StructElementIndexes[structName] = elementIndex;
-    }
-
     return string;
 }
 
@@ -3543,6 +3537,10 @@
     {
         mStructNames.insert(name);
 
+        // Add element index
+        storeStd140ElementIndex(*structure, false);
+        storeStd140ElementIndex(*structure, true);
+
         const TString &structString = structureString(*structure, false, false);
 
         if (std::find(mStructDeclarations.begin(), mStructDeclarations.end(), structString) == mStructDeclarations.end())
@@ -3733,6 +3731,21 @@
     mConstructors.insert(constructor);
 }
 
+void OutputHLSL::storeStd140ElementIndex(const TStructure &structure, bool useHLSLRowMajorPacking)
+{
+    int elementIndex = 0;
+    const TFieldList &fields = structure.fields();
+
+    for (unsigned int i = 0; i < fields.size(); i++)
+    {
+        std140PrePaddingString(*fields[i]->type(), &elementIndex);
+    }
+
+    // Add remaining element index to the global map, for use with nested structs in standard layouts
+    const TString &structName = structureTypeName(structure, useHLSLRowMajorPacking, true);
+    mStd140StructElementIndexes[structName] = elementIndex;
+}
+
 const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const ConstantUnion *constUnion)
 {
     TInfoSinkBase &out = mBody;