Title: [131933] trunk
Revision
131933
Author
[email protected]
Date
2012-10-19 12:45:03 -0700 (Fri, 19 Oct 2012)

Log Message

Shader translator needs option to clamp uniform array accesses in vertex shaders
https://bugs.webkit.org/show_bug.cgi?id=98977
https://code.google.com/p/angleproject/issues/detail?id=49

Reviewed by Alok Priyadarshi and Ken Russell.

Source/ThirdParty/ANGLE:

WebGL does not allow GLSL code to index a uniform array outside its bounds. Add a
flag to the ANGLE compiler to insert clamp statements around such indexing.
Since it is possible to access vec2/3/4 and mat2/3/4 components by array indexing,
they must be similarly clamped.

Unfortunately, it is currently not possible to always determine that the indexing is
operating on a uniform variable. For example, suppose we have "uniform mat4 a". ANGLE
is currently not able to tell us that the rvalue of "a[0]" is a uniform, just that
it has a size of 4. Therefore, the clamping is done on all indirect array indexing.

This will have a performance impact. Future enhancements may be able to determine
cases where the clamping is not necessary. Currently only direct indexing is skipped
(i.e. looking up a value using a constant index).

The clamp insertion is only performed on the GLSL output. Direct3D already guarantees
that out-of-bounds uniform array access returns a zero value.

* ANGLE.xcodeproj/project.pbxproj:
* Target.pri:
* include/GLSLANG/ShaderLang.h: New compiler option.
* src/compiler/ArrayBoundsClamper.cpp: Added.
(ArrayBoundsClamper::ArrayBoundsClamper):
(ArrayBoundsClamper::OutputClampingFunctionDefinition): Injects a clamping function for integers into GLSL source.
(ArrayBoundsClamper::MarkIndirectArrayBoundsForClamping): Examines the AST looking for non-direct array indexing.
* src/compiler/ArrayBoundsClamper.h: Added.
(ArrayBoundsClamper):
(ArrayBoundsClamper::GetArrayBoundsClampDefinitionNeeded):
(ArrayBoundsClamper::SetArrayBoundsClampDefinitionNeeded): Marks the object as needing to output the clamping function.
(ArrayBoundsClamper::Cleanup): Resets the state so that subsequent runs start fresh.
* src/compiler/Compiler.cpp:
(TCompiler::compile): Run the clamping code if the compile option was set.
(TCompiler::clearResults):
(TCompiler::getArrayBoundsClamper):
* src/compiler/OutputGLSLBase.cpp:
(TOutputGLSLBase::visitBinary): If the _expression_ has been flagged, insert an appropriate "clamp" statement.
* src/compiler/ShHandle.h:
(TCompiler):
* src/compiler/TranslatorESSL.cpp:
(TranslatorESSL::translate):
* src/compiler/TranslatorGLSL.cpp:
(TranslatorGLSL::translate):
* src/compiler/intermOut.cpp:
(TType::getCompleteString): Add array size to intermediate tree output.
* src/compiler/intermediate.h:
(TIntermBinary::setAddIndexClamp): New flag for indicating a binary _expression_ needs clamping.
(TIntermBinary::getAddIndexClamp):
(TIntermBinary):

Source/WebCore:

WebGL forbids out-of-bounds array access in shaders. Rewrite any shaders to
ensure that non-direct array indexing is clamped to the bounds of the array.

Test: fast/canvas/webgl/array-bounds-clamping.html

* platform/graphics/ANGLEWebKitBridge.cpp:
(WebCore::ANGLEWebKitBridge::compileShaderSource): Pass new compiler option SH_CLAMP_INDIRECT_ARRAY_BOUNDS

LayoutTests:

* fast/canvas/webgl/array-bounds-clamping-expected.txt: Added.
* fast/canvas/webgl/array-bounds-clamping.html: Added.
* platform/chromium/TestExpectations: Won't pass on Chromium until this patch is upstreamed.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (131932 => 131933)


--- trunk/LayoutTests/ChangeLog	2012-10-19 19:34:57 UTC (rev 131932)
+++ trunk/LayoutTests/ChangeLog	2012-10-19 19:45:03 UTC (rev 131933)
@@ -1,3 +1,15 @@
+2012-10-18  Dean Jackson  <[email protected]>
+
+        Shader translator needs option to clamp uniform array accesses in vertex shaders
+        https://bugs.webkit.org/show_bug.cgi?id=98977
+        https://code.google.com/p/angleproject/issues/detail?id=49
+
+        Reviewed by Alok Priyadarshi and Ken Russell.
+
+        * fast/canvas/webgl/array-bounds-clamping-expected.txt: Added.
+        * fast/canvas/webgl/array-bounds-clamping.html: Added.
+        * platform/chromium/TestExpectations: Won't pass on Chromium until this patch is upstreamed.
+
 2012-09-08  Alpha Lam  <[email protected]>
 
         [chromium] Implement deferred image decoding

Added: trunk/LayoutTests/fast/canvas/webgl/array-bounds-clamping-expected.txt (0 => 131933)


--- trunk/LayoutTests/fast/canvas/webgl/array-bounds-clamping-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/canvas/webgl/array-bounds-clamping-expected.txt	2012-10-19 19:45:03 UTC (rev 131933)
@@ -0,0 +1,12 @@
+ Checks that array access in a shader can not read out of bounds
+
+PASS Top left corner should clamp to index 0
+PASS Inside top right corner should clamp to index 0
+PASS Inside bottom left corner should clamp to index 0
+PASS Bottom right corner should clamp to index 7
+PASS Outside bottom left corner should clamp to index 7
+PASS Outside top right corner should clamp to index 7
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Property changes on: trunk/LayoutTests/fast/canvas/webgl/array-bounds-clamping-expected.txt
___________________________________________________________________

Added: svn:mime-type

Added: svn:keywords

Added: svn:eol-style

Added: trunk/LayoutTests/fast/canvas/webgl/array-bounds-clamping.html (0 => 131933)


--- trunk/LayoutTests/fast/canvas/webgl/array-bounds-clamping.html	                        (rev 0)
+++ trunk/LayoutTests/fast/canvas/webgl/array-bounds-clamping.html	2012-10-19 19:45:03 UTC (rev 131933)
@@ -0,0 +1,106 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+  "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<title>WebGL array bounds clamping conformance test.</title>
+<script src=""
+<script src="" </script>
+</head>
+<body>
+<canvas id="example" width="40" height="40" style="width: 40px; height: 40px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+#ifdef GL_ES
+precision highp float;
+#endif
+attribute vec4 vPosition;
+attribute float index;
+uniform float shades[8];
+varying vec4 texColor;
+void main()
+{
+    gl_Position = vPosition;
+    texColor = vec4(shades[int(index)], 0, 0, 1.0);
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+#ifdef GL_ES
+precision highp float;
+#endif
+varying vec4 texColor;
+void main()
+{
+    gl_FragColor = texColor;
+}
+</script>
+
+<script>
+function init()
+{
+    if (window.initNonKhronosFramework)
+        window.initNonKhronosFramework(false);
+
+    debug("Checks that array access in a shader can not read out of bounds");
+    debug("");
+
+    gl = initWebGL("example", "vshader", "fshader", [ "vPosition", "index" ],
+                   [ 1, 1, 1, 1 ], 1);
+
+    gl.disable(gl.DEPTH_TEST);
+    gl.disable(gl.BLEND);
+
+    var vertexObject = gl.createBuffer();
+    gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+    gl.bufferData(gl.ARRAY_BUFFER,
+                  new Float32Array([ -1,1,0, 1,1,0, -1,-1,0,
+                                     -1,-1,0, 1,1,0, 1,-1,0 ]),
+                  gl.STATIC_DRAW);
+    gl.enableVertexAttribArray(0);
+    gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+
+    var vertexObject = gl.createBuffer();
+    gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+    gl.bufferData(gl.ARRAY_BUFFER,
+                  // Create an array that exercises well outside the
+                  // limits on each side, near the limits, and the
+                  // exact limits.
+                  // This should be clamped to [0, 0, 0, 7, 7, 7]
+                  new Float32Array([ -Number.MAX_VALUE, -1, 0, 7, 8, Number.MAX_VALUE]),
+                  gl.STATIC_DRAW);
+    gl.enableVertexAttribArray(1);
+    gl.vertexAttribPointer(1, 1, gl.FLOAT, false, 0, 0);
+
+    var loc = gl.getUniformLocation(gl.program, "shades");
+    gl.uniform1fv(loc, [0.25, 0.5, 0, 0, 0, 0, 0.75, 1]);
+
+    checkRedValue(0, 38, 64, "Top left corner should clamp to index 0");
+    checkRedValue(37, 38, 64, "Inside top right corner should clamp to index 0");
+    checkRedValue(0, 1, 64, "Inside bottom left corner should clamp to index 0");
+
+    checkRedValue(38, 0, 255, "Bottom right corner should clamp to index 7");
+    checkRedValue(3, 1, 255, "Outside bottom left corner should clamp to index 7");
+    checkRedValue(38, 37, 255, "Outside top right corner should clamp to index 7");
+
+    function checkRedValue(x, y, value, msg) {
+        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+        gl.drawArrays(gl.TRIANGLES, 0, 6);
+        gl.flush();
+        var buf = new Uint8Array(4);
+        gl.readPixels(x, y, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+        if (buf[0] != value || buf[1] != 0 || buf[2] != 0 || buf[3] != 255) {
+            debug('expected: rgb(' + value + ', 0, 0, 255) was rgb(' + buf[0] + ', ' + buf[1] + ', ' + buf[2] + ', ' + buf[3] + ')');
+            testFailed(msg);
+            return;
+        }
+        testPassed(msg);
+    }
+}
+
+init();
+</script>
+<script src=""
+</body>
+</html>
+
Property changes on: trunk/LayoutTests/fast/canvas/webgl/array-bounds-clamping.html
___________________________________________________________________

Added: svn:mime-type

Added: svn:keywords

Added: svn:eol-style

Modified: trunk/LayoutTests/platform/chromium/TestExpectations (131932 => 131933)


--- trunk/LayoutTests/platform/chromium/TestExpectations	2012-10-19 19:34:57 UTC (rev 131932)
+++ trunk/LayoutTests/platform/chromium/TestExpectations	2012-10-19 19:45:03 UTC (rev 131933)
@@ -2363,6 +2363,9 @@
 crbug.com/60651 fast/canvas/webgl/uniform-location.html [ Failure Timeout ]
 crbug.com/60651 platform/chromium/virtual/gpu/fast/canvas/webgl/uniform-location.html [ Failure Timeout ]
 
+# This will fail in Chromium until the patch is upstreamed to ANGLE
+webkit.org/b/98977 fast/canvas/webgl/array-bounds-clamping.html [ Failure ]
+
 # Flaky since r68438:r68445 or before that.
 webkit.org/b/46693 [ Mac ] fast/repaint/repaint-svg-after-style-change.html [ Failure ]
 

Modified: trunk/Source/ThirdParty/ANGLE/ANGLE.xcodeproj/project.pbxproj (131932 => 131933)


--- trunk/Source/ThirdParty/ANGLE/ANGLE.xcodeproj/project.pbxproj	2012-10-19 19:34:57 UTC (rev 131932)
+++ trunk/Source/ThirdParty/ANGLE/ANGLE.xcodeproj/project.pbxproj	2012-10-19 19:45:03 UTC (rev 131933)
@@ -9,6 +9,8 @@
 /* Begin PBXBuildFile section */
 		312BDB0C15FECAC90097EBC7 /* ANGLE.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 312BDB0915FEC91E0097EBC7 /* ANGLE.plist */; };
 		312BDB0E15FECAE50097EBC7 /* ANGLE.txt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 312BDB0A15FECA3A0097EBC7 /* ANGLE.txt */; };
+		3158EA0E1630968D006BE5EE /* ArrayBoundsClamper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3158EA0C1630968D006BE5EE /* ArrayBoundsClamper.cpp */; };
+		3158EA0F1630968D006BE5EE /* ArrayBoundsClamper.h in Headers */ = {isa = PBXBuildFile; fileRef = 3158EA0D1630968D006BE5EE /* ArrayBoundsClamper.h */; };
 		49951C0314B7AAB30060E96E /* length_limits.h in Headers */ = {isa = PBXBuildFile; fileRef = 49951C0214B7AAB30060E96E /* length_limits.h */; };
 		49951C0914B7AAD80060E96E /* BuiltInFunctionEmulator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49951C0514B7AAD70060E96E /* BuiltInFunctionEmulator.cpp */; };
 		49951C0A14B7AAD80060E96E /* BuiltInFunctionEmulator.h in Headers */ = {isa = PBXBuildFile; fileRef = 49951C0614B7AAD80060E96E /* BuiltInFunctionEmulator.h */; };
@@ -136,6 +138,8 @@
 /* Begin PBXFileReference section */
 		312BDB0915FEC91E0097EBC7 /* ANGLE.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = ANGLE.plist; sourceTree = "<group>"; };
 		312BDB0A15FECA3A0097EBC7 /* ANGLE.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ANGLE.txt; sourceTree = "<group>"; };
+		3158EA0C1630968D006BE5EE /* ArrayBoundsClamper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArrayBoundsClamper.cpp; sourceTree = "<group>"; };
+		3158EA0D1630968D006BE5EE /* ArrayBoundsClamper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArrayBoundsClamper.h; sourceTree = "<group>"; };
 		49951C0214B7AAB30060E96E /* length_limits.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = length_limits.h; sourceTree = "<group>"; };
 		49951C0514B7AAD70060E96E /* BuiltInFunctionEmulator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BuiltInFunctionEmulator.cpp; sourceTree = "<group>"; };
 		49951C0614B7AAD80060E96E /* BuiltInFunctionEmulator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BuiltInFunctionEmulator.h; sourceTree = "<group>"; };
@@ -544,6 +548,8 @@
 		FB39D2201200F35A00088E69 /* compiler */ = {
 			isa = PBXGroup;
 			children = (
+				3158EA0C1630968D006BE5EE /* ArrayBoundsClamper.cpp */,
+				3158EA0D1630968D006BE5EE /* ArrayBoundsClamper.h */,
 				FB39D2211200F35A00088E69 /* BaseTypes.h */,
 				49951C0514B7AAD70060E96E /* BuiltInFunctionEmulator.cpp */,
 				49951C0614B7AAD80060E96E /* BuiltInFunctionEmulator.h */,
@@ -712,6 +718,7 @@
 				A265683E159C23E100398539 /* DependencyGraphOutput.h in Headers */,
 				A2656841159C23E100398539 /* RestrictFragmentShaderTiming.h in Headers */,
 				A2656843159C23E100398539 /* RestrictVertexShaderTiming.h in Headers */,
+				3158EA0F1630968D006BE5EE /* ArrayBoundsClamper.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -829,6 +836,7 @@
 				A265683F159C23E100398539 /* DependencyGraphTraverse.cpp in Sources */,
 				A2656840159C23E100398539 /* RestrictFragmentShaderTiming.cpp in Sources */,
 				A2656842159C23E100398539 /* RestrictVertexShaderTiming.cpp in Sources */,
+				3158EA0E1630968D006BE5EE /* ArrayBoundsClamper.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

Modified: trunk/Source/ThirdParty/ANGLE/ChangeLog (131932 => 131933)


--- trunk/Source/ThirdParty/ANGLE/ChangeLog	2012-10-19 19:34:57 UTC (rev 131932)
+++ trunk/Source/ThirdParty/ANGLE/ChangeLog	2012-10-19 19:45:03 UTC (rev 131933)
@@ -1,3 +1,59 @@
+2012-10-18  Dean Jackson  <[email protected]>
+
+        Shader translator needs option to clamp uniform array accesses in vertex shaders
+        https://bugs.webkit.org/show_bug.cgi?id=98977
+        https://code.google.com/p/angleproject/issues/detail?id=49
+
+        Reviewed by Alok Priyadarshi and Ken Russell.
+
+        WebGL does not allow GLSL code to index a uniform array outside its bounds. Add a
+        flag to the ANGLE compiler to insert clamp statements around such indexing.
+        Since it is possible to access vec2/3/4 and mat2/3/4 components by array indexing,
+        they must be similarly clamped.
+
+        Unfortunately, it is currently not possible to always determine that the indexing is
+        operating on a uniform variable. For example, suppose we have "uniform mat4 a". ANGLE
+        is currently not able to tell us that the rvalue of "a[0]" is a uniform, just that
+        it has a size of 4. Therefore, the clamping is done on all indirect array indexing.
+
+        This will have a performance impact. Future enhancements may be able to determine
+        cases where the clamping is not necessary. Currently only direct indexing is skipped
+        (i.e. looking up a value using a constant index).
+
+        The clamp insertion is only performed on the GLSL output. Direct3D already guarantees
+        that out-of-bounds uniform array access returns a zero value.
+
+        * ANGLE.xcodeproj/project.pbxproj:
+        * Target.pri:
+        * include/GLSLANG/ShaderLang.h: New compiler option.
+        * src/compiler/ArrayBoundsClamper.cpp: Added.
+        (ArrayBoundsClamper::ArrayBoundsClamper):
+        (ArrayBoundsClamper::OutputClampingFunctionDefinition): Injects a clamping function for integers into GLSL source.
+        (ArrayBoundsClamper::MarkIndirectArrayBoundsForClamping): Examines the AST looking for non-direct array indexing.
+        * src/compiler/ArrayBoundsClamper.h: Added.
+        (ArrayBoundsClamper):
+        (ArrayBoundsClamper::GetArrayBoundsClampDefinitionNeeded):
+        (ArrayBoundsClamper::SetArrayBoundsClampDefinitionNeeded): Marks the object as needing to output the clamping function.
+        (ArrayBoundsClamper::Cleanup): Resets the state so that subsequent runs start fresh.
+        * src/compiler/Compiler.cpp:
+        (TCompiler::compile): Run the clamping code if the compile option was set.
+        (TCompiler::clearResults):
+        (TCompiler::getArrayBoundsClamper):
+        * src/compiler/OutputGLSLBase.cpp:
+        (TOutputGLSLBase::visitBinary): If the _expression_ has been flagged, insert an appropriate "clamp" statement.
+        * src/compiler/ShHandle.h:
+        (TCompiler):
+        * src/compiler/TranslatorESSL.cpp:
+        (TranslatorESSL::translate):
+        * src/compiler/TranslatorGLSL.cpp:
+        (TranslatorGLSL::translate):
+        * src/compiler/intermOut.cpp:
+        (TType::getCompleteString): Add array size to intermediate tree output.
+        * src/compiler/intermediate.h:
+        (TIntermBinary::setAddIndexClamp): New flag for indicating a binary _expression_ needs clamping.
+        (TIntermBinary::getAddIndexClamp):
+        (TIntermBinary):
+
 2012-09-13  Mark Rowe  <[email protected]>
 
         <rdar://problem/12255720> Fix the build with newer Clang

Modified: trunk/Source/ThirdParty/ANGLE/Target.pri (131932 => 131933)


--- trunk/Source/ThirdParty/ANGLE/Target.pri	2012-10-19 19:34:57 UTC (rev 131932)
+++ trunk/Source/ThirdParty/ANGLE/Target.pri	2012-10-19 19:45:03 UTC (rev 131933)
@@ -17,6 +17,7 @@
     $$SOURCE_DIR/include
 
 HEADERS += \
+    src/compiler/ArrayBoundsClamper.h \
     src/compiler/BaseTypes.h \
     src/compiler/BuiltInFunctionEmulator.h \
     src/compiler/Common.h \
@@ -90,6 +91,7 @@
     src/compiler/VersionGLSL.h
 
 SOURCES += \
+    src/compiler/ArrayBoundsClamper.cpp \
     src/compiler/BuiltInFunctionEmulator.cpp \
     src/compiler/CodeGenGLSL.cpp \
     src/compiler/Compiler.cpp \

Modified: trunk/Source/ThirdParty/ANGLE/include/GLSLANG/ShaderLang.h (131932 => 131933)


--- trunk/Source/ThirdParty/ANGLE/include/GLSLANG/ShaderLang.h	2012-10-19 19:34:57 UTC (rev 131932)
+++ trunk/Source/ThirdParty/ANGLE/include/GLSLANG/ShaderLang.h	2012-10-19 19:45:03 UTC (rev 131933)
@@ -142,7 +142,13 @@
   // - 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
+  SH_DEPENDENCY_GRAPH = 0x0400,
+
+  // 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 = 0x0800
 } ShCompileOptions;
 
 //

Added: trunk/Source/ThirdParty/ANGLE/src/compiler/ArrayBoundsClamper.cpp (0 => 131933)


--- trunk/Source/ThirdParty/ANGLE/src/compiler/ArrayBoundsClamper.cpp	                        (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/ArrayBoundsClamper.cpp	2012-10-19 19:45:03 UTC (rev 131933)
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "compiler/ArrayBoundsClamper.h"
+
+const char* kIntClampBegin = "// BEGIN: Generated code for array bounds clamping\n\n";
+const char* kIntClampEnd = "// END: Generated code for array bounds clamping\n\n";
+const char* kIntClampDefinition = "int webgl_int_clamp(int value, int minValue, int maxValue) { return ((value < minValue) ? minValue : ((value > maxValue) ? maxValue : value)); }\n\n";
+
+namespace {
+
+class ArrayBoundsClamperMarker : public TIntermTraverser {
+public:
+    ArrayBoundsClamperMarker()
+        : mNeedsClamp(false)
+   {
+   }
+
+   virtual bool visitBinary(Visit visit, TIntermBinary* node)
+   {
+       if (node->getOp() == EOpIndexIndirect)
+       {
+           TIntermTyped* left = node->getLeft();
+           if (left->isArray() || left->isVector() || left->isMatrix())
+           {
+               node->setAddIndexClamp();
+               mNeedsClamp = true;
+           }
+       }
+       return true;
+   }
+
+    bool GetNeedsClamp() { return mNeedsClamp; }
+
+private:
+    bool mNeedsClamp;
+};
+
+}  // anonymous namespace
+
+ArrayBoundsClamper::ArrayBoundsClamper()
+    : mArrayBoundsClampDefinitionNeeded(false)
+{
+}
+
+void ArrayBoundsClamper::OutputClampingFunctionDefinition(TInfoSinkBase& out) const
+{
+    if (!mArrayBoundsClampDefinitionNeeded)
+    {
+        return;
+    }
+    out << kIntClampBegin << kIntClampDefinition << kIntClampEnd;
+}
+
+void ArrayBoundsClamper::MarkIndirectArrayBoundsForClamping(TIntermNode* root)
+{
+    ASSERT(root);
+
+    ArrayBoundsClamperMarker clamper;
+    root->traverse(&clamper);
+    if (clamper.GetNeedsClamp())
+    {
+        SetArrayBoundsClampDefinitionNeeded();
+    }
+}
+
Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/ArrayBoundsClamper.cpp
___________________________________________________________________

Added: svn:keywords

Added: svn:eol-style

Added: trunk/Source/ThirdParty/ANGLE/src/compiler/ArrayBoundsClamper.h (0 => 131933)


--- trunk/Source/ThirdParty/ANGLE/src/compiler/ArrayBoundsClamper.h	                        (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/ArrayBoundsClamper.h	2012-10-19 19:45:03 UTC (rev 131933)
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef COMPILER_ARRAY_BOUNDS_CLAMPER_H_
+#define COMPILER_ARRAY_BOUNDS_CLAMPER_H_
+
+#include "GLSLANG/ShaderLang.h"
+
+#include "compiler/InfoSink.h"
+#include "compiler/intermediate.h"
+
+class ArrayBoundsClamper {
+public:
+    ArrayBoundsClamper();
+
+    // Output array clamp function source into the shader source.
+    void OutputClampingFunctionDefinition(TInfoSinkBase& out) const;
+
+    // Marks nodes in the tree that index arrays indirectly as
+    // requiring clamping.
+    void MarkIndirectArrayBoundsForClamping(TIntermNode* root);
+
+    void Cleanup()
+    {
+        mArrayBoundsClampDefinitionNeeded = false;
+    }
+
+private:
+    bool GetArrayBoundsClampDefinitionNeeded() const { return mArrayBoundsClampDefinitionNeeded; }
+    void SetArrayBoundsClampDefinitionNeeded() { mArrayBoundsClampDefinitionNeeded = true; }
+    
+    bool mArrayBoundsClampDefinitionNeeded;
+};
+
+#endif // COMPILER_ARRAY_BOUNDS_CLAMPER_H_
Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/ArrayBoundsClamper.h
___________________________________________________________________

Added: svn:keywords

Added: svn:eol-style

Modified: trunk/Source/ThirdParty/ANGLE/src/compiler/Compiler.cpp (131932 => 131933)


--- trunk/Source/ThirdParty/ANGLE/src/compiler/Compiler.cpp	2012-10-19 19:34:57 UTC (rev 131932)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/Compiler.cpp	2012-10-19 19:45:03 UTC (rev 131933)
@@ -4,6 +4,7 @@
 // found in the LICENSE file.
 //
 
+#include "compiler/ArrayBoundsClamper.h"
 #include "compiler/BuiltInFunctionEmulator.h"
 #include "compiler/DetectRecursion.h"
 #include "compiler/ForLoopUnroll.h"
@@ -186,6 +187,10 @@
         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.
@@ -231,6 +236,7 @@
     uniforms.clear();
 
     builtInFunctionEmulator.Cleanup();
+    arrayBoundsClamper.Cleanup();
 }
 
 bool TCompiler::detectRecursion(TIntermNode* root)
@@ -331,3 +337,9 @@
 {
     return builtInFunctionEmulator;
 }
+
+const ArrayBoundsClamper& TCompiler::getArrayBoundsClamper() const
+{
+    return arrayBoundsClamper;
+}
+

Modified: trunk/Source/ThirdParty/ANGLE/src/compiler/OutputGLSLBase.cpp (131932 => 131933)


--- trunk/Source/ThirdParty/ANGLE/src/compiler/OutputGLSLBase.cpp	2012-10-19 19:34:57 UTC (rev 131932)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/OutputGLSLBase.cpp	2012-10-19 19:45:03 UTC (rev 131933)
@@ -235,9 +235,38 @@
             break;
 
         case EOpIndexDirect:
-        case EOpIndexIndirect:
             writeTriplet(visit, NULL, "[", "]");
             break;
+        case EOpIndexIndirect:
+            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)
             {

Modified: trunk/Source/ThirdParty/ANGLE/src/compiler/ShHandle.h (131932 => 131933)


--- trunk/Source/ThirdParty/ANGLE/src/compiler/ShHandle.h	2012-10-19 19:34:57 UTC (rev 131932)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/ShHandle.h	2012-10-19 19:45:03 UTC (rev 131933)
@@ -16,6 +16,7 @@
 
 #include "GLSLANG/ShaderLang.h"
 
+#include "compiler/ArrayBoundsClamper.h"
 #include "compiler/BuiltInFunctionEmulator.h"
 #include "compiler/ExtensionBehavior.h"
 #include "compiler/InfoSink.h"
@@ -98,6 +99,7 @@
     // Get built-in extensions with default behavior.
     const TExtensionBehavior& getExtensionBehavior() const;
 
+    const ArrayBoundsClamper& getArrayBoundsClamper() const;
     const BuiltInFunctionEmulator& getBuiltInFunctionEmulator() const;
 
 private:
@@ -110,6 +112,7 @@
     // Built-in extensions with default behavior.
     TExtensionBehavior extensionBehavior;
 
+    ArrayBoundsClamper arrayBoundsClamper;
     BuiltInFunctionEmulator builtInFunctionEmulator;
 
     // Results of compilation.

Modified: trunk/Source/ThirdParty/ANGLE/src/compiler/TranslatorESSL.cpp (131932 => 131933)


--- trunk/Source/ThirdParty/ANGLE/src/compiler/TranslatorESSL.cpp	2012-10-19 19:34:57 UTC (rev 131932)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/TranslatorESSL.cpp	2012-10-19 19:45:03 UTC (rev 131933)
@@ -22,6 +22,9 @@
     getBuiltInFunctionEmulator().OutputEmulatedFunctionDefinition(
         sink, getShaderType() == SH_FRAGMENT_SHADER);
 
+    // Write array bounds clamping emulation if needed.
+    getArrayBoundsClamper().OutputClampingFunctionDefinition(sink);
+
     // Write translated shader.
     TOutputESSL outputESSL(sink);
     root->traverse(&outputESSL);

Modified: trunk/Source/ThirdParty/ANGLE/src/compiler/TranslatorGLSL.cpp (131932 => 131933)


--- trunk/Source/ThirdParty/ANGLE/src/compiler/TranslatorGLSL.cpp	2012-10-19 19:34:57 UTC (rev 131932)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/TranslatorGLSL.cpp	2012-10-19 19:45:03 UTC (rev 131933)
@@ -35,6 +35,9 @@
     getBuiltInFunctionEmulator().OutputEmulatedFunctionDefinition(
         sink, false);
 
+    // Write array bounds clamping emulation if needed.
+    getArrayBoundsClamper().OutputClampingFunctionDefinition(sink);
+
     // Write translated shader.
     TOutputGLSL outputGLSL(sink);
     root->traverse(&outputGLSL);

Modified: trunk/Source/ThirdParty/ANGLE/src/compiler/intermOut.cpp (131932 => 131933)


--- trunk/Source/ThirdParty/ANGLE/src/compiler/intermOut.cpp	2012-10-19 19:34:57 UTC (rev 131932)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/intermOut.cpp	2012-10-19 19:45:03 UTC (rev 131933)
@@ -42,7 +42,7 @@
     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)

Modified: trunk/Source/ThirdParty/ANGLE/src/compiler/intermediate.h (131932 => 131933)


--- trunk/Source/ThirdParty/ANGLE/src/compiler/intermediate.h	2012-10-19 19:34:57 UTC (rev 131932)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/intermediate.h	2012-10-19 19:45:03 UTC (rev 131933)
@@ -400,9 +400,15 @@
     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;
 };
 
 //

Modified: trunk/Source/WebCore/ChangeLog (131932 => 131933)


--- trunk/Source/WebCore/ChangeLog	2012-10-19 19:34:57 UTC (rev 131932)
+++ trunk/Source/WebCore/ChangeLog	2012-10-19 19:45:03 UTC (rev 131933)
@@ -1,3 +1,19 @@
+2012-10-18  Dean Jackson  <[email protected]>
+
+        Shader translator needs option to clamp uniform array accesses in vertex shaders
+        https://bugs.webkit.org/show_bug.cgi?id=98977
+        https://code.google.com/p/angleproject/issues/detail?id=49
+
+        Reviewed by Alok Priyadarshi and Ken Russell.
+
+        WebGL forbids out-of-bounds array access in shaders. Rewrite any shaders to
+        ensure that non-direct array indexing is clamped to the bounds of the array.
+
+        Test: fast/canvas/webgl/array-bounds-clamping.html
+
+        * platform/graphics/ANGLEWebKitBridge.cpp:
+        (WebCore::ANGLEWebKitBridge::compileShaderSource): Pass new compiler option SH_CLAMP_INDIRECT_ARRAY_BOUNDS
+
 2012-10-19  Justin Novosad  <[email protected]>
 
         [Chromium] Reduce memory footprint of canvas pattern object with deferred rendering

Modified: trunk/Source/WebCore/platform/graphics/ANGLEWebKitBridge.cpp (131932 => 131933)


--- trunk/Source/WebCore/platform/graphics/ANGLEWebKitBridge.cpp	2012-10-19 19:34:57 UTC (rev 131932)
+++ trunk/Source/WebCore/platform/graphics/ANGLEWebKitBridge.cpp	2012-10-19 19:45:03 UTC (rev 131933)
@@ -173,6 +173,12 @@
 
     const char* const shaderSourceStrings[] = { shaderSource };
 
+#if !PLATFORM(CHROMIUM)
+    // Chromium does not use the ANGLE bundled in WebKit source, and thus
+    // does not yet have the symbol SH_CLAMP_INDIRECT_ARRAY_BOUNDS.
+    extraCompileOptions |= SH_CLAMP_INDIRECT_ARRAY_BOUNDS;
+#endif
+
     bool validateSuccess = ShCompile(compiler, shaderSourceStrings, 1, SH_OBJECT_CODE | SH_ATTRIBUTES_UNIFORMS | extraCompileOptions);
     if (!validateSuccess) {
         int logSize = getValidationResultValue(compiler, SH_INFO_LOG_LENGTH);
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to