Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Tree: a64b433ec1
Fetching contributors…

Cannot retrieve contributors at this time

243 lines (225 sloc) 7.735 kB
<html>
<head>
<title>JS Bones Benchmark</title>
<style>
input {
vertical-align: top;
height: 12px;
}
input[type=range]:after {
content: attr(value);
display: inline-block;
padding-top: 4px;
}
input[disabled] {
opacity: 0.2;
}
body {
font-family: sans-serif;
}
</style>
</head>
<body>
<div style="display:inline-block; vertical-align:top;">
<h3>Performance fiddles</h3>
<p>Worker count <input id="workercount" type="range" value="4" min="1" max="16" step="1">
<p>Mesh size in verts <input id="verts" type="range" value="125000" min="25000" max="2000000" step="25000">
<p>Use SSE-like version <input id="sse" type="checkbox">
<p>Single-threaded <input id="singlethreaded" type="checkbox">
<p>Lockstep update & draw <input id="lockstep" type="checkbox">
<p>Update vertices with JS <input id="update" type="checkbox" checked>
</div>
<div style="display:inline-block; vertical-align:top;">
<h3>Visual fiddles</h3>
<p>xFac <input type="range" value="165" min="5" max="320" step="5" onchange="Bones.xFac=1/this.value">
<p>yFac <input type="range" value="165" min="5" max="320" step="5" onchange="Bones.yFac=1/this.value">
<p>xtFac <input type="range" value="3" min="0" max="8" step="0.5" onchange="Bones.xtFac=this.value-0">
<p>ytFac <input type="range" value="4" min="0" max="8" step="0.5" onchange="Bones.ytFac=this.value-0">
</div>
<p><button id="b" disabled="disabled">Run Benchmark</button>
<p id="r">Initializing...</p>
<script src="bones.js"></script>
<script src="webgl-utils.js"></script>
<script id="2d-vertex-shader" type="x-shader/x-vertex">
precision mediump float;
attribute vec4 a_position;
varying float z;
uniform float t;
void main() {
z = a_position.z;
gl_Position = vec4(sin(t/300.0)*0.2, cos(t/300.0)*0.2, 0.0, 0.0) + a_position;
}
</script>
<script id="2d-fragment-shader" type="x-shader/x-fragment">
precision mediump float;
varying float z;
void main() {
gl_FragColor = vec4(0.4+z*0.6,z*z*0.9,0.3-0.3*z*z,1.0);
}
</script>
<script>
var rs = document.querySelectorAll("input[type=range]");
for (var i=0; i<rs.length; i++) {
rs[i].addEventListener('change', function(){
this.setAttribute("value", this.value);
}, false);
}
var prev_verts = 0;
var prev_workerCount = 0;
var b = document.getElementById('b');
b.disabled = false;
document.getElementById('r').innerHTML = '';
var c = document.createElement('canvas');
c.style.display='block';
c.width = 404;
c.height = 100;
var ctx = c.getContext('2d');
document.body.appendChild(c);
var glC = document.createElement('canvas');
glC.style.display='block';
glC.width = glC.height = 400;
document.body.appendChild(glC);
var gl = glC.getContext('experimental-webgl');
var buf = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
// setup a GLSL program
var vertexShader = createShaderFromScriptElement(gl, "2d-vertex-shader");
var fragmentShader = createShaderFromScriptElement(gl, "2d-fragment-shader");
var program = createProgram(gl, [vertexShader, fragmentShader]);
gl.useProgram(program);
var uniform_t = gl.getUniformLocation(program, 't');
// look up where the vertex data needs to go.
var positionLocation = gl.getAttribLocation(program, "a_position");
gl.enableVertexAttribArray(positionLocation);
gl.vertexAttribPointer(positionLocation, 4, gl.FLOAT, false, 0, 0);
b.stopped = true;
var lockstep_elem = document.getElementById('lockstep');
var update_elem = document.getElementById('update');
var needUpdate = true;
var st_elem = document.getElementById('singlethreaded');
var sse_elem = document.getElementById('sse');
b.onclick = function() {
this.stopped = !this.stopped;
if (this.stopped) {
this.innerHTML = 'Run Benchmark';
this.disabled = true;
document.getElementById('workercount').disabled =
document.getElementById('verts').disabled = false;
return;
}
this.innerHTML = 'Stop Benchmark';
var workerCount = parseInt(document.getElementById('workercount').value);
var verts = parseFloat(document.getElementById('verts').value);
document.getElementById('workercount').disabled =
document.getElementById('verts').disabled = true;
var sse = sse_elem.checked;
var st = st_elem.checked;
var lockstep = lockstep_elem.checked;
Bones.useSSE = sse;
Bones.singleThreaded = st;
document.getElementById('r').innerHTML = '';
Bones.workerCount = workerCount;
if (prev_verts != verts || prev_workerCount != workerCount) {
Bones.initBenchmark(verts);
gl.bufferData(gl.ARRAY_BUFFER, verts*4*4, gl.DYNAMIC_DRAW);
prev_verts = verts;
prev_workerCount = workerCount;
}
var frameTimes = [];
var bonesTimes = [];
var prev_t = performance.webkitNow();
var bm = function(t) {
if (b.stopped) return;
bonesTimes.push(t);
};
var tick = function() { Bones.runBenchmark(bm); };
var draw = function() {
if (b.stopped) {
b.disabled = false;
return;
}
var now_t = performance.webkitNow();
var sse = sse_elem.checked;
var st = st_elem.checked;
var lockstep = lockstep_elem.checked;
Bones.useSSE = sse;
Bones.singleThreaded = st;
if (Bones.dstVertices) {
if (needUpdate) {
var off = 0;
Bones.dstVertices.forEach(function(ab) {
gl.bufferSubData(gl.ARRAY_BUFFER, off, ab);
off += ab.byteLength;
});
needUpdate = false;
}
if (update.checked) {
needUpdate = true;
tick();
}
} else if (lockstep) {
window.requestAnimFrame(draw);
return;
}
frameTimes.push(now_t - prev_t);
prev_t = now_t;
gl.clear(gl.DEPTH_BUFFER_BIT | gl.COLOR_BUFFER_BIT);
gl.uniform1f(uniform_t, now_t);
gl.drawArrays(gl.TRIANGLES, i, verts);
var minT = Math.min.apply(Math, bonesTimes);
var maxT = Math.max.apply(Math, bonesTimes);
var fminT = Math.min.apply(Math, frameTimes);
var fmaxT = Math.max.apply(Math, frameTimes);
var avg = bonesTimes.reduce(function(s,i){ return s+i; }, 0) / bonesTimes.length;
var favg = frameTimes.reduce(function(s,i){ return s+i; }, 0) / frameTimes.length;
ctx.clearRect(0,0,c.width,c.height);
ctx.fillStyle = '#000000';
bonesTimes.forEach(function(e, i) {
var h = e / 100 * 100;
ctx.fillRect(i*2, 100-h, 2, h);
});
ctx.fillStyle = '#ff0000';
frameTimes.forEach(function(e, i) {
var h = e / 100 * 100;
ctx.fillRect(i*2, 100-h, 2, 1);
});
ctx.fillStyle = '#cccccc';
ctx.fillRect(0, 100 - (avg/100)*100, c.width, 1);
ctx.fillStyle = '#eeeeee';
ctx.fillRect(0, 100 - (minT/100)*100, c.width, 1);
ctx.fillStyle = '#888888';
ctx.fillRect(0, 100 - (maxT/100)*100, c.width, 1);
ctx.fillStyle = '#ffcccc';
ctx.fillRect(0, 100 - (favg/100)*100, c.width, 1);
ctx.fillStyle = '#ffeeee';
ctx.fillRect(0, 100 - (fminT/100)*100, c.width, 1);
ctx.fillStyle = '#ff8888';
ctx.fillRect(0, 100 - (fmaxT/100)*100, c.width, 1);
while (bonesTimes.length > 199) {
bonesTimes.shift();
}
while (frameTimes.length > 199) {
frameTimes.shift();
}
ctx.fillStyle = '#000000';
for (var i=0; i<100; i+=5) {
ctx.fillRect(400, 99-i, (i % 10) ? 2 : 4, 1);
}
window.requestAnimFrame(draw);
}
tick();
draw();
};
</script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-1485935-6']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
</body>
</html>
Jump to Line
Something went wrong with that request. Please try again.