Add a basic WebGL test to Animometer
authordino@apple.com <dino@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 18 Mar 2016 20:48:39 +0000 (20:48 +0000)
committerdino@apple.com <dino@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 18 Mar 2016 20:48:39 +0000 (20:48 +0000)
https://bugs.webkit.org/show_bug.cgi?id=155475
<rdar://problem/25156860>

Reviewed by Simon Fraser and Jon Lee.

Add a pretty simple WebGL test to Animometer
which tries to draw a number of animated triangles.
The result still needs a bit of tuning.

* Animometer/resources/debug-runner/tests.js: Add a new
Suite for "3D" tests.
* Animometer/tests/3d/resources/webgl.js: Added.
* Animometer/tests/3d/webgl.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@198442 268f45cc-cd09-0410-ab3c-d52691b4dbfc

PerformanceTests/Animometer/resources/debug-runner/tests.js
PerformanceTests/Animometer/tests/3d/resources/webgl.js [new file with mode: 0644]
PerformanceTests/Animometer/tests/3d/webgl.html [new file with mode: 0644]
PerformanceTests/ChangeLog

index 0dcd4c246d7b7c915afb829bd763fc09dc8e18a0..b019cab8aad8e7e2a5a3426f72b6cccec19175de 100644 (file)
@@ -311,6 +311,15 @@ Suites.push(new Suite("Basic canvas path suite",
     ]
 ));
 
+Suites.push(new Suite("3D Graphics",
+    [
+        {
+            url: "3d/webgl.html",
+            name: "WebGL"
+        },
+    ]
+));
+
 Suites.push(new Suite("Miscellaneous Tests",
     [
         {
diff --git a/PerformanceTests/Animometer/tests/3d/resources/webgl.js b/PerformanceTests/Animometer/tests/3d/resources/webgl.js
new file mode 100644 (file)
index 0000000..58f5df3
--- /dev/null
@@ -0,0 +1,184 @@
+(function() {
+
+WebGLStage = Utilities.createSubclass(Stage,
+    function(element, options)
+    {
+        Stage.call(this);
+    },
+    {
+
+        initialize: function(benchmark, options)
+        {
+            Stage.prototype.initialize.call(this, benchmark, options);
+
+            this._numTriangles = 0;
+            this._bufferSize = 0;
+
+            this._gl = this.element.getContext("webgl");
+            var gl = this._gl;
+
+            gl.clearColor(0.5, 0.5, 0.5, 1);
+
+            // Create the vertex shader object.
+            var vertexShader = gl.createShader(gl.VERTEX_SHADER);
+
+            // The source code for the shader is extracted from the <script> element above.
+            gl.shaderSource(vertexShader, this._getFunctionSource("vertex"));
+
+            // Compile the shader.
+            gl.compileShader(vertexShader);
+            if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
+                // We failed to compile. Output to the console and quit.
+                console.error("Vertex Shader failed to compile.");
+                console.error(gl.getShaderInfoLog(vertexShader));
+                return;
+            }
+
+            // Now do the fragment shader.
+            var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
+            gl.shaderSource(fragmentShader, this._getFunctionSource("fragment"));
+            gl.compileShader(fragmentShader);
+            if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
+                console.error("Fragment Shader failed to compile.");
+                console.error(gl.getShaderInfoLog(fragmentShader));
+                return;
+            }
+
+            // We have two compiled shaders. Time to make the program.
+            var program = gl.createProgram();
+            gl.attachShader(program, vertexShader);
+            gl.attachShader(program, fragmentShader);
+            gl.linkProgram(program);
+
+            if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
+                console.error("Unable to link shaders into program.");
+                return;
+            }
+
+            // Our program has two inputs. We have a single uniform "color",
+            // and one vertex attribute "position".
+
+            gl.useProgram(program);
+            this._uScale = gl.getUniformLocation(program, "scale");
+            this._uTime = gl.getUniformLocation(program, "time");
+            this._uOffsetX = gl.getUniformLocation(program, "offsetX");
+            this._uOffsetY = gl.getUniformLocation(program, "offsetY");
+            this._uScalar = gl.getUniformLocation(program, "scalar");
+            this._uScalarOffset = gl.getUniformLocation(program, "scalarOffset");
+
+            this._aPosition = gl.getAttribLocation(program, "position");
+            gl.enableVertexAttribArray(this._aPosition);
+
+            this._aColor = gl.getAttribLocation(program, "color");
+            gl.enableVertexAttribArray(this._aColor);
+
+            this._positionData = new Float32Array([
+                // x y z 1
+                   0,  0.1, 0, 1,
+                -0.1, -0.1, 0, 1,
+                 0.1, -0.1, 0, 1
+            ]);
+            this._positionBuffer = gl.createBuffer();
+            gl.bindBuffer(gl.ARRAY_BUFFER, this._positionBuffer);
+            gl.bufferData(gl.ARRAY_BUFFER, this._positionData, gl.STATIC_DRAW);
+
+            this._colorData = new Float32Array([
+                1, 0, 0, 1,
+                0, 1, 0, 1,
+                0, 0, 1, 1
+            ]);
+            this._colorBuffer = gl.createBuffer();
+            gl.bindBuffer(gl.ARRAY_BUFFER, this._colorBuffer);
+            gl.bufferData(gl.ARRAY_BUFFER, this._colorData, gl.STATIC_DRAW);
+
+            this._resetIfNecessary();
+        },
+
+        _getFunctionSource: function(id)
+        {
+            return document.getElementById(id).text;
+        },
+
+        _resetIfNecessary: function()
+        {
+            if (this._numTriangles <= this._bufferSize)
+                return;
+
+            if (!this._bufferSize)
+                this._bufferSize = 128;
+
+            while (this._numTriangles > this._bufferSize)
+                this._bufferSize *= 4;
+
+            this._uniformData = new Float32Array(this._bufferSize * 6);
+            for (var i = 0; i < this._bufferSize; ++i) {
+                this._uniformData[i * 6 + 0] = Stage.random(0.2, 0.4);
+                this._uniformData[i * 6 + 1] = 0;
+                this._uniformData[i * 6 + 2] = Stage.random(-0.9, 0.9);
+                this._uniformData[i * 6 + 3] = Stage.random(-0.9, 0.9);
+                this._uniformData[i * 6 + 4] = Stage.random(0.5, 2);
+                this._uniformData[i * 6 + 5] = Stage.random(0, 10);
+            }
+        },
+
+        tune: function(count)
+        {
+            if (!count)
+                return;
+
+            this._numTriangles += count;
+            this._numTriangles = Math.max(this._numTriangles, 0);
+
+            this._resetIfNecessary();
+        },
+
+        animate: function(timeDelta)
+        {
+            var gl = this._gl;
+
+            gl.clear(gl.COLOR_BUFFER_BIT);
+
+            if (!this._startTime)
+                this._startTime = Stage.dateCounterValue(1000);
+            var elapsedTime = Stage.dateCounterValue(1000) - this._startTime;
+
+            for (var i = 0; i < this._numTriangles; ++i) {
+
+                this._uniformData[i * 6 + 1] = elapsedTime;
+
+                var uniformDataOffset = i * 6;
+                gl.uniform1f(this._uScale, this._uniformData[uniformDataOffset++]);
+                gl.uniform1f(this._uTime, this._uniformData[uniformDataOffset++]);
+                gl.uniform1f(this._uOffsetX, this._uniformData[uniformDataOffset++]);
+                gl.uniform1f(this._uOffsetY, this._uniformData[uniformDataOffset++]);
+                gl.uniform1f(this._uScalar, this._uniformData[uniformDataOffset++]);
+                gl.uniform1f(this._uScalarOffset, this._uniformData[uniformDataOffset++]);
+
+                gl.bindBuffer(gl.ARRAY_BUFFER, this._positionBuffer);
+                gl.vertexAttribPointer(this._aPosition, 4, gl.FLOAT, false, 0, 0);
+
+                gl.bindBuffer(gl.ARRAY_BUFFER, this._colorBuffer);
+                gl.vertexAttribPointer(this._aColor, 4, gl.FLOAT, false, 0, 0);
+
+                gl.drawArrays(gl.TRIANGLES, 0, 3);
+            }
+
+        },
+
+        complexity: function()
+        {
+            return this._numTriangles;
+        }
+    }
+);
+
+WebGLBenchmark = Utilities.createSubclass(Benchmark,
+    function(options)
+    {
+        Benchmark.call(this, new WebGLStage(), options);
+    }
+);
+
+window.benchmarkClass = WebGLBenchmark;
+
+})();
diff --git a/PerformanceTests/Animometer/tests/3d/webgl.html b/PerformanceTests/Animometer/tests/3d/webgl.html
new file mode 100644 (file)
index 0000000..cf6442a
--- /dev/null
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="utf-8">
+    <link rel="stylesheet" type="text/css" href="../resources/stage.css">
+</head>
+<body>
+    <canvas id="stage"></canvas>
+    <script id="vertex" type="x-shader/x-glsl">
+attribute vec4 position;
+attribute vec4 color;
+
+uniform float scale;
+uniform float time;
+uniform float offsetX;
+uniform float offsetY;
+uniform float scalar;
+uniform float scalarOffset;
+
+varying vec4 v_color;
+
+void main() {
+
+    float fade = mod(scalarOffset + time * scalar / 10.0, 1.0);
+
+    if (fade < 0.5) {
+        fade = fade * 2.0;
+    } else {
+        fade = (1.0 - fade) * 2.0;
+    }
+
+    float xpos = position.x * scale;
+    float ypos = position.y * scale;
+
+    float angle = 3.14159 * 2.0 * fade;
+    float xrot = xpos * cos(angle) - ypos * sin(angle);
+    float yrot = xpos * sin(angle) + ypos * cos(angle);
+
+    xpos = xrot + offsetX;
+    ypos = yrot + offsetY;
+
+    v_color = vec4(fade, 1.0 - fade, 0.0, 1.0) + color;
+    gl_Position = vec4(xpos, ypos, 0.0, 1.0);
+}
+    </script>
+    <script id="fragment" type="x-shader/x-glsl">
+#ifdef GL_ES
+precision mediump float;
+#endif
+
+varying vec4 v_color;
+
+void main() {
+    gl_FragColor = v_color;
+}
+    </script>
+    <script src="../../resources/strings.js"></script>
+    <script src="../../resources/extensions.js"></script>
+    <script src="../../resources/statistics.js"></script>
+    <script src="../resources/math.js"></script>
+    <script src="../resources/main.js"></script>
+    <script src="resources/webgl.js"></script>
+</body>
+</html>
index 9cfed53361a2068b0a167f7a231680ebbb833efc..7548d71c99c9fe159d7a7dd3136a237a3b826824 100644 (file)
@@ -1,3 +1,20 @@
+2016-03-18  Dean Jackson  <dino@apple.com>
+
+        Add a basic WebGL test to Animometer
+        https://bugs.webkit.org/show_bug.cgi?id=155475
+        <rdar://problem/25156860>
+
+        Reviewed by Simon Fraser and Jon Lee.
+
+        Add a pretty simple WebGL test to Animometer
+        which tries to draw a number of animated triangles.
+        The result still needs a bit of tuning.
+
+        * Animometer/resources/debug-runner/tests.js: Add a new
+        Suite for "3D" tests.
+        * Animometer/tests/3d/resources/webgl.js: Added.
+        * Animometer/tests/3d/webgl.html: Added.
+
 2016-03-18  Jon Lee  <jonlee@apple.com>
 
         Add support for statically linking to a specific test