gfx/angle/angle-r1638.patch
author Kyle Machulis <kyle@nonpolynomial.com>
Fri, 29 Mar 2013 15:12:58 -0700
changeset 137136 0db3022ca2e6bec95897850f797f078464a7f529
parent 130853 57f2e0ad71a951ec321eb646cd627aad8f6d730e
child 143260 d256188763e7710c303c78fbc7a41fee92c15864
permissions -rw-r--r--
Backout for changeset 03452b187c14 (Bug 855465) due to bustage on a CLOSED TREE; r=qdot

# HG changeset patch
# Parent faf255e4400222ee23c29ddcc76fb3dce56145f4

diff --git a/gfx/angle/AUTHORS b/gfx/angle/AUTHORS
--- a/gfx/angle/AUTHORS
+++ b/gfx/angle/AUTHORS
@@ -7,16 +7,17 @@
 #	Name or Organization
 # Email addresses for individuals are tracked elsewhere to avoid spam.
 
 Google Inc.
 TransGaming Inc.
 3DLabs Inc. Ltd.
 
 Adobe Systems Inc.
+Apple Inc.
 Autodesk, Inc.
 Cloud Party, Inc.
 Intel Corporation
 Mozilla Corporation
 Turbulenz
 Klarälvdalens Datakonsult AB
 
 Jacek Caban
diff --git a/gfx/angle/Makefile.in b/gfx/angle/Makefile.in
--- a/gfx/angle/Makefile.in
+++ b/gfx/angle/Makefile.in
@@ -51,16 +51,17 @@ LOCAL_INCLUDES += \
   -I$(srcdir)/include/KHR \
   -I$(srcdir)/src
 
 DEFINES += -DCOMPILER_IMPLEMENTATION
 
 VPATH += $(srcdir)/src/compiler
 # src/compiler:
 CPPSRCS += \
+  ArrayBoundsClamper.cpp \
   BuiltInFunctionEmulator.cpp \
   Compiler.cpp \
   compiler_debug.cpp \
   DetectRecursion.cpp \
   Diagnostics.cpp \
   DirectiveHandler.cpp \
   ForLoopUnroll.cpp \
   glslang_lex.cpp \
diff --git a/gfx/angle/README.mozilla b/gfx/angle/README.mozilla
--- a/gfx/angle/README.mozilla
+++ b/gfx/angle/README.mozilla
@@ -21,16 +21,20 @@ In this order:
   
   angle-long-ident-spooky-hash.patch:
     Use Spooky Hash for long identifier hashing. See bug 676071.
   
   angle-faceforward-emu.patch:
     Adds emulation for faceforward(float,float,float), which is needed to
     prevent crashing on Mac+Intel. See bug 771406.
 
+  angle-r1638.patch
+    Adds uniform array index clamping on non-Windows platforms.
+    Windows would require r1719, r1733, r1734.
+
 In addition to these patches, the Makefile.in files are ours, they're not present in
 upsteam ANGLE. Therefore, changes made to the Makefile.in files should not be stored
 in the local .patch files.
 
 
 == How to do a clean-slate upgrade ==
 1.  Backup our moz-specific files:
       README.mozilla
diff --git a/gfx/angle/include/GLSLANG/ShaderLang.h b/gfx/angle/include/GLSLANG/ShaderLang.h
--- a/gfx/angle/include/GLSLANG/ShaderLang.h
+++ b/gfx/angle/include/GLSLANG/ShaderLang.h
@@ -145,17 +145,23 @@ typedef enum {
   // restrictions on fragment shaders.
   // This flag only has an effect if all of the following are true:
   // - The shader spec is SH_WEBGL_SPEC.
   // - The compile options contain the SH_TIMING_RESTRICTIONS flag.
   // - The shader type is SH_FRAGMENT_SHADER.
   SH_DEPENDENCY_GRAPH = 0x0400,
 
   // Enforce the GLSL 1.017 Appendix A section 7 packing restrictions.
-  SH_ENFORCE_PACKING_RESTRICTIONS = 0x0800
+  SH_ENFORCE_PACKING_RESTRICTIONS = 0x0800,
+
+  // This flag ensures all indirect (expression-based) array indexing
+  // is clamped to the bounds of the array. This ensures, for example,
+  // that you cannot read off the end of a uniform, whether an array
+  // vec234, or mat234 type.
+  SH_CLAMP_INDIRECT_ARRAY_BOUNDS = 0x1000
 } ShCompileOptions;
 
 //
 // Driver must call this first, once, before doing any other
 // compiler operations.
 // If the function succeeds, the return value is nonzero, else zero.
 //
 COMPILER_EXPORT int ShInitialize();
diff --git a/gfx/angle/src/build_angle.gypi b/gfx/angle/src/build_angle.gypi
--- a/gfx/angle/src/build_angle.gypi
+++ b/gfx/angle/src/build_angle.gypi
@@ -54,16 +54,18 @@
       'include_dirs': [
         '.',
         '../include',
       ],
       'defines': [
         'COMPILER_IMPLEMENTATION',
       ],
       'sources': [
+        'compiler/ArrayBoundsClamper.cpp',
+        'compiler/ArrayBoundsClamper.h',
         'compiler/BaseTypes.h',
         'compiler/BuiltInFunctionEmulator.cpp',
         'compiler/BuiltInFunctionEmulator.h',
         'compiler/Common.h',
         'compiler/Compiler.cpp',
         'compiler/ConstantUnion.h',
         'compiler/debug.cpp',
         'compiler/debug.h',
diff --git a/gfx/angle/src/compiler/Compiler.cpp b/gfx/angle/src/compiler/Compiler.cpp
--- a/gfx/angle/src/compiler/Compiler.cpp
+++ b/gfx/angle/src/compiler/Compiler.cpp
@@ -1,14 +1,15 @@
 //
 // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
 
+#include "compiler/ArrayBoundsClamper.h"
 #include "compiler/BuiltInFunctionEmulator.h"
 #include "compiler/DetectRecursion.h"
 #include "compiler/ForLoopUnroll.h"
 #include "compiler/Initialize.h"
 #include "compiler/InitializeParseContext.h"
 #include "compiler/MapLongVariableNames.h"
 #include "compiler/ParseHelper.h"
 #include "compiler/RenameFunction.h"
@@ -187,16 +188,20 @@ bool TCompiler::compile(const char* cons
         // Unroll for-loop markup needs to happen after validateLimitations pass.
         if (success && (compileOptions & SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX))
             ForLoopUnroll::MarkForLoopsWithIntegerIndicesForUnrolling(root);
 
         // Built-in function emulation needs to happen after validateLimitations pass.
         if (success && (compileOptions & SH_EMULATE_BUILT_IN_FUNCTIONS))
             builtInFunctionEmulator.MarkBuiltInFunctionsForEmulation(root);
 
+        // Clamping uniform array bounds needs to happen after validateLimitations pass.
+        if (success && (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS))
+            arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root);
+
         // Call mapLongVariableNames() before collectAttribsUniforms() so in
         // collectAttribsUniforms() we already have the mapped symbol names and
         // we could composite mapped and original variable names.
         // Also, if we hash all the names, then no need to do this for long names.
         if (success && (compileOptions & SH_MAP_LONG_VARIABLE_NAMES) && hashFunction == NULL)
             mapLongVariableNames(root);
 
         if (success && (compileOptions & SH_ATTRIBUTES_UNIFORMS)) {
@@ -232,16 +237,17 @@ bool TCompiler::InitBuiltInSymbolTable(c
 
     builtIns.initialize(shaderType, shaderSpec, resources);
     return InitializeSymbolTable(builtIns.getBuiltInStrings(),
         shaderType, shaderSpec, resources, infoSink, symbolTable);
 }
 
 void TCompiler::clearResults()
 {
+    arrayBoundsClamper.Cleanup();
     infoSink.info.erase();
     infoSink.obj.erase();
     infoSink.debug.erase();
 
     attribs.clear();
     uniforms.clear();
 
     builtInFunctionEmulator.Cleanup();
@@ -348,8 +354,14 @@ const TExtensionBehavior& TCompiler::get
 {
     return extensionBehavior;
 }
 
 const BuiltInFunctionEmulator& TCompiler::getBuiltInFunctionEmulator() const
 {
     return builtInFunctionEmulator;
 }
+
+const ArrayBoundsClamper& TCompiler::getArrayBoundsClamper() const
+{
+    return arrayBoundsClamper;
+}
+
diff --git a/gfx/angle/src/compiler/OutputGLSLBase.cpp b/gfx/angle/src/compiler/OutputGLSLBase.cpp
--- a/gfx/angle/src/compiler/OutputGLSLBase.cpp
+++ b/gfx/angle/src/compiler/OutputGLSLBase.cpp
@@ -207,18 +207,47 @@ bool TOutputGLSLBase::visitBinary(Visit 
         case EOpVectorTimesMatrixAssign:
         case EOpVectorTimesScalarAssign:
         case EOpMatrixTimesScalarAssign:
         case EOpMatrixTimesMatrixAssign:
             writeTriplet(visit, "(", " *= ", ")");
             break;
 
         case EOpIndexDirect:
+            writeTriplet(visit, NULL, "[", "]");
+            break;
         case EOpIndexIndirect:
-            writeTriplet(visit, NULL, "[", "]");
+            if (node->getAddIndexClamp())
+            {
+                if (visit == InVisit)
+                {
+                    out << "[webgl_int_clamp(";
+                }
+                else if (visit == PostVisit)
+                {
+                    int maxSize;
+                    TIntermTyped *left = node->getLeft();
+                    TType leftType = left->getType();
+
+                    if (left->isArray())
+                    {
+                        // The shader will fail validation if the array length is not > 0.
+                        maxSize = leftType.getArraySize() - 1;
+                    }
+                    else
+                    {
+                        maxSize = leftType.getNominalSize() - 1;
+                    }
+                    out << ", 0, " << maxSize << ")]";
+                }
+            }
+            else
+            {
+                writeTriplet(visit, NULL, "[", "]");
+            }
             break;
         case EOpIndexDirectStruct:
             if (visit == InVisit)
             {
                 out << ".";
                 // TODO(alokp): ASSERT
                 out << hashName(node->getType().getFieldName());
                 visitChildren = false;
diff --git a/gfx/angle/src/compiler/ShHandle.h b/gfx/angle/src/compiler/ShHandle.h
--- a/gfx/angle/src/compiler/ShHandle.h
+++ b/gfx/angle/src/compiler/ShHandle.h
@@ -11,16 +11,17 @@
 // Machine independent part of the compiler private objects
 // sent as ShHandle to the driver.
 //
 // This should not be included by driver code.
 //
 
 #include "GLSLANG/ShaderLang.h"
 
+#include "compiler/ArrayBoundsClamper.h"
 #include "compiler/BuiltInFunctionEmulator.h"
 #include "compiler/ExtensionBehavior.h"
 #include "compiler/HashNames.h"
 #include "compiler/InfoSink.h"
 #include "compiler/SymbolTable.h"
 #include "compiler/VariableInfo.h"
 
 class LongNameMap;
@@ -101,30 +102,32 @@ protected:
     // Returns true if the shader does not use samplers.
     bool enforceVertexShaderTimingRestrictions(TIntermNode* root);
     // Returns true if the shader does not use sampler dependent values to affect control 
     // flow or in operations whose time can depend on the input values.
     bool enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph);
     // Get built-in extensions with default behavior.
     const TExtensionBehavior& getExtensionBehavior() const;
 
+    const ArrayBoundsClamper& getArrayBoundsClamper() const;
     const BuiltInFunctionEmulator& getBuiltInFunctionEmulator() const;
 
 private:
     ShShaderType shaderType;
     ShShaderSpec shaderSpec;
 
     int maxUniformVectors;
 
     // Built-in symbol table for the given language, spec, and resources.
     // It is preserved from compile-to-compile.
     TSymbolTable symbolTable;
     // Built-in extensions with default behavior.
     TExtensionBehavior extensionBehavior;
 
+    ArrayBoundsClamper arrayBoundsClamper;
     BuiltInFunctionEmulator builtInFunctionEmulator;
 
     // Results of compilation.
     TInfoSink infoSink;  // Output sink.
     TVariableInfoList attribs;  // Active attributes in the compiled shader.
     TVariableInfoList uniforms;  // Active uniforms in the compiled shader.
 
     // Cached copy of the ref-counted singleton.
diff --git a/gfx/angle/src/compiler/TranslatorESSL.cpp b/gfx/angle/src/compiler/TranslatorESSL.cpp
--- a/gfx/angle/src/compiler/TranslatorESSL.cpp
+++ b/gfx/angle/src/compiler/TranslatorESSL.cpp
@@ -17,16 +17,19 @@ void TranslatorESSL::translate(TIntermNo
 
     // Write built-in extension behaviors.
     writeExtensionBehavior();
 
     // Write emulated built-in functions if needed.
     getBuiltInFunctionEmulator().OutputEmulatedFunctionDefinition(
         sink, getShaderType() == SH_FRAGMENT_SHADER);
 
+    // Write array bounds clamping emulation if needed.
+    getArrayBoundsClamper().OutputClampingFunctionDefinition(sink);
+
     // Write translated shader.
     TOutputESSL outputESSL(sink, getHashFunction(), getNameMap(), getSymbolTable());
     root->traverse(&outputESSL);
 }
 
 void TranslatorESSL::writeExtensionBehavior() {
     TInfoSinkBase& sink = getInfoSink().obj;
     const TExtensionBehavior& extensionBehavior = getExtensionBehavior();
diff --git a/gfx/angle/src/compiler/TranslatorGLSL.cpp b/gfx/angle/src/compiler/TranslatorGLSL.cpp
--- a/gfx/angle/src/compiler/TranslatorGLSL.cpp
+++ b/gfx/angle/src/compiler/TranslatorGLSL.cpp
@@ -30,12 +30,15 @@ void TranslatorGLSL::translate(TIntermNo
 
     // Write GLSL version.
     writeVersion(getShaderType(), root, sink);
 
     // Write emulated built-in functions if needed.
     getBuiltInFunctionEmulator().OutputEmulatedFunctionDefinition(
         sink, false);
 
+    // Write array bounds clamping emulation if needed.
+    getArrayBoundsClamper().OutputClampingFunctionDefinition(sink);
+
     // Write translated shader.
     TOutputGLSL outputGLSL(sink, getHashFunction(), getNameMap(), getSymbolTable());
     root->traverse(&outputGLSL);
 }
diff --git a/gfx/angle/src/compiler/intermOut.cpp b/gfx/angle/src/compiler/intermOut.cpp
--- a/gfx/angle/src/compiler/intermOut.cpp
+++ b/gfx/angle/src/compiler/intermOut.cpp
@@ -37,17 +37,17 @@ protected:
 
 TString TType::getCompleteString() const
 {
     TStringStream stream;
 
     if (qualifier != EvqTemporary && qualifier != EvqGlobal)
         stream << getQualifierString() << " " << getPrecisionString() << " ";
     if (array)
-        stream << "array of ";
+        stream << "array[" << getArraySize() << "] of ";
     if (matrix)
         stream << size << "X" << size << " matrix of ";
     else if (size > 1)
         stream << size << "-component vector of ";
 
     stream << getBasicString();
     return stream.str();
 }
diff --git a/gfx/angle/src/compiler/intermediate.h b/gfx/angle/src/compiler/intermediate.h
--- a/gfx/angle/src/compiler/intermediate.h
+++ b/gfx/angle/src/compiler/intermediate.h
@@ -386,30 +386,36 @@ protected:
     TOperator op;
 };
 
 //
 // Nodes for all the basic binary math operators.
 //
 class TIntermBinary : public TIntermOperator {
 public:
-    TIntermBinary(TOperator o) : TIntermOperator(o) {}
+    TIntermBinary(TOperator o) : TIntermOperator(o), addIndexClamp(false) {}
 
     virtual TIntermBinary* getAsBinaryNode() { return this; }
     virtual void traverse(TIntermTraverser*);
 
     void setLeft(TIntermTyped* n) { left = n; }
     void setRight(TIntermTyped* n) { right = n; }
     TIntermTyped* getLeft() const { return left; }
     TIntermTyped* getRight() const { return right; }
     bool promote(TInfoSink&);
 
+    void setAddIndexClamp() { addIndexClamp = true; }
+    bool getAddIndexClamp() { return addIndexClamp; }
+
 protected:
     TIntermTyped* left;
     TIntermTyped* right;
+
+    // If set to true, wrap any EOpIndexIndirect with a clamp to bounds.
+    bool addIndexClamp;
 };
 
 //
 // Nodes for unary math operators.
 //
 class TIntermUnary : public TIntermOperator {
 public:
     TIntermUnary(TOperator o, TType& t) : TIntermOperator(o, t), operand(0), useEmulatedFunction(false) {}
diff --git a/gfx/angle/src/compiler/translator_common.vcxproj b/gfx/angle/src/compiler/translator_common.vcxproj
--- a/gfx/angle/src/compiler/translator_common.vcxproj
+++ b/gfx/angle/src/compiler/translator_common.vcxproj
@@ -133,16 +133,17 @@
       </PrecompiledHeader>
       <WarningLevel>Level4</WarningLevel>
       <TreatWarningAsError>true</TreatWarningAsError>
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
       <DisableSpecificWarnings>4100;4127;4189;4239;4244;4245;4267;4512;4702;4718;%(DisableSpecificWarnings)</DisableSpecificWarnings>
     </ClCompile>
   </ItemDefinitionGroup>
   <ItemGroup>
+    <ClCompile Include="ArrayBoundsClamper.cpp" />
     <ClCompile Include="BuiltInFunctionEmulator.cpp" />
     <ClCompile Include="Compiler.cpp" />
     <ClCompile Include="debug.cpp" />
     <ClCompile Include="DetectRecursion.cpp" />
     <ClCompile Include="Diagnostics.cpp" />
     <ClCompile Include="DirectiveHandler.cpp" />
     <ClCompile Include="ForLoopUnroll.cpp" />
     <ClCompile Include="InfoSink.cpp" />
@@ -220,16 +221,17 @@
       <Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
       </Message>
       <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
       </Command>
       <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(Outputs)</Outputs>
     </CustomBuild>
   </ItemGroup>
   <ItemGroup>
+    <ClInclude Include="ArrayBoundsClamper.h" />
     <ClInclude Include="BaseTypes.h" />
     <ClInclude Include="BuiltInFunctionEmulator.h" />
     <ClInclude Include="Common.h" />
     <ClInclude Include="ConstantUnion.h" />
     <ClInclude Include="debug.h" />
     <ClInclude Include="DetectRecursion.h" />
     <ClInclude Include="Diagnostics.h" />
     <ClInclude Include="DirectiveHandler.h" />
@@ -274,9 +276,9 @@
       <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
       <LinkLibraryDependencies>true</LinkLibraryDependencies>
       <UseLibraryDependencyInputs>true</UseLibraryDependencyInputs>
     </ProjectReference>
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
   </ImportGroup>
-</Project>
\ No newline at end of file
+</Project>
diff --git a/gfx/angle/src/libGLESv2/Makefile.in b/gfx/angle/src/libGLESv2/Makefile.in
--- a/gfx/angle/src/libGLESv2/Makefile.in
+++ b/gfx/angle/src/libGLESv2/Makefile.in
@@ -64,16 +64,17 @@ LOCAL_INCLUDES = \
   -I$(srcdir)/../../include/KHR \
   -I$(srcdir)/..
 
 DEFINES += -DCOMPILER_IMPLEMENTATION
 
 VPATH += $(srcdir)/../compiler
 # src/compiler:
 CPPSRCS += \
+  ArrayBoundsClamper.cpp \
   BuiltInFunctionEmulator.cpp \
   Compiler.cpp \
   compiler_debug.cpp \
   DetectRecursion.cpp \
   Diagnostics.cpp \
   DirectiveHandler.cpp \
   ForLoopUnroll.cpp \
   glslang_lex.cpp \