256 lines
6.7 KiB
HTML
256 lines
6.7 KiB
HTML
<!--
|
|
Copyright (c) 2019 The Khronos Group Inc.
|
|
Use of this source code is governed by an MIT-style license that can be
|
|
found in the LICENSE.txt file.
|
|
-->
|
|
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<title>WebGL Big FBO Test</title>
|
|
<link rel="stylesheet" href="../resources/js-test-style.css"/>
|
|
<script src="../../devtools/src/debug/webgl-debug.js"></script>
|
|
<script src="../js/js-test-pre.js"></script>
|
|
<script src="../js/webgl-test-utils.js"></script>
|
|
</head>
|
|
<body>
|
|
<canvas id="canvas" width="256" height="256"> </canvas>
|
|
<div id="description"></div>
|
|
<div id="console"></div>
|
|
<script id="vshader" type="x-shader/x-vertex">
|
|
attribute vec4 vPosition;
|
|
attribute vec2 texCoord0;
|
|
varying vec2 texCoord;
|
|
void main()
|
|
{
|
|
gl_Position = vec4(vPosition.xyz, 1.0);
|
|
texCoord = texCoord0;
|
|
}
|
|
</script>
|
|
|
|
<script id="fshader" type="x-shader/x-fragment">
|
|
precision mediump float;
|
|
uniform sampler2D tex;
|
|
varying vec2 texCoord;
|
|
void main()
|
|
{
|
|
gl_FragColor = texture2D(tex, texCoord);
|
|
}
|
|
</script>
|
|
<script>
|
|
"use strict";
|
|
window.onload = init;
|
|
|
|
var g_textures = [];
|
|
|
|
debug("Tests the performance of using lots of large FBOs");
|
|
|
|
function init() {
|
|
if (confirm(
|
|
"After clicking OK your machine may become unresponsive or crash.")) {
|
|
main();
|
|
} else {
|
|
debug("cancelled");
|
|
}
|
|
}
|
|
|
|
function checkFBOStatus(gl) {
|
|
var err = gl.getError();
|
|
if (err != gl.NO_ERROR) {
|
|
if (err != gl.OUT_OF_MEMORY)
|
|
testFailed("gl.getError returned " + err);
|
|
else
|
|
testPassed("OUT-OF-MEMORY");
|
|
return false;
|
|
}
|
|
var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
|
|
if (status != gl.FRAMEBUFFER_COMPLETE) {
|
|
testFailed("gl.checkFramebufferStatus() returned " + WebGLTestUtils.glEnumToString(gl, status));
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
function setupFBO(gl, size) {
|
|
var tex = gl.createTexture();
|
|
gl.bindTexture(gl.TEXTURE_2D, tex);
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
|
|
var fb = gl.createFramebuffer();
|
|
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
|
|
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
|
|
|
|
gl.texImage2D(gl.TEXTURE_2D,
|
|
0, // level
|
|
gl.RGBA, // internalFormat
|
|
size, // width
|
|
size, // height
|
|
0, // border
|
|
gl.RGBA, // format
|
|
gl.UNSIGNED_BYTE, // type
|
|
null); // data
|
|
if (!checkFBOStatus(gl))
|
|
return null;
|
|
|
|
return { fb: fb, tex: tex };
|
|
}
|
|
|
|
function checkPixels(gl) {
|
|
var width = 256;
|
|
var height = 256;
|
|
|
|
var thresh = 3;
|
|
|
|
var buf = new Uint8Array(width * height * 4);
|
|
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
|
|
for (var yy = 0; yy < height; ++yy) {
|
|
for (var xx = 0; xx < width; ++xx) {
|
|
var offset = (yy * width + xx) * 4;
|
|
if (Math.abs(buf[offset] - 255) > thresh ||
|
|
Math.abs(buf[offset + 1] - 0) > thresh ||
|
|
Math.abs(buf[offset + 2] - 0) > thresh) {
|
|
testFailed("drawing results incorrect");
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
function handleContextLost() {
|
|
debug("context lost");
|
|
}
|
|
|
|
function main() {
|
|
debug("");
|
|
debug("Checking for out of memory handling.");
|
|
|
|
var canvas = document.getElementById("canvas");
|
|
canvas.addEventListener('webglcontextlost', handleContextLost);
|
|
var wtu = WebGLTestUtils;
|
|
var gl = wtu.create3DContext("canvas");
|
|
var prog = wtu.setupProgram(gl, ["vshader", "fshader"], ["vPosition", "texCoord0"]);
|
|
|
|
WebGLDebugUtils.init(gl);
|
|
|
|
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, new Float32Array([ 0,0, 1,0, 0,1,
|
|
0,1, 1,0, 1,1
|
|
]), gl.STATIC_DRAW);
|
|
gl.enableVertexAttribArray(1);
|
|
gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, 0);
|
|
|
|
var texLoc = gl.getUniformLocation(prog, "tex");
|
|
gl.uniform1i(texLoc, 0);
|
|
|
|
gl.clearColor(0, 0, 0, 1);
|
|
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
|
|
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "setup should succeed");
|
|
|
|
var size = gl.getParameter(gl.MAX_RENDERBUFFER_SIZE);
|
|
debug("max render buffer size: " + size +
|
|
", size used: " + (size / 2));
|
|
size /= 2;
|
|
|
|
var maxFBOs = 200;
|
|
var numFBOs = 0;
|
|
allocateNextFBO();
|
|
|
|
function allocateNextFBO() {
|
|
if (numFBOs >= maxFBOs) {
|
|
phase2();
|
|
return;
|
|
}
|
|
if (!allocateFBO()) {
|
|
phase2();
|
|
return;
|
|
}
|
|
++numFBOs;
|
|
setTimeout(allocateNextFBO, 100);
|
|
}
|
|
|
|
function allocateFBO() {
|
|
debug("");
|
|
debug("trying to create fbo #" + (numFBOs + 1));
|
|
var t = setupFBO(gl, 2);
|
|
if (!t) {
|
|
return false;
|
|
}
|
|
|
|
var tex = t.tex;
|
|
var fb = t.fb;
|
|
|
|
debug("allocating fbo color buffer of size " + size + " x " + size);
|
|
gl.texImage2D(gl.TEXTURE_2D,
|
|
0, // level
|
|
gl.RGBA, // internalFormat
|
|
size, // width
|
|
size, // height
|
|
0, // border
|
|
gl.RGBA, // format
|
|
gl.UNSIGNED_BYTE, // type
|
|
null); // data
|
|
if (!checkFBOStatus(gl)) {
|
|
return false;
|
|
}
|
|
g_textures.push(tex);
|
|
debug("succeeded in creating fbo");
|
|
|
|
debug("clearing the fbo with red color");
|
|
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
|
|
gl.clearColor(1, 0, 0, 1);
|
|
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
|
|
debug("deleting fbo, but the now red texture should be untouched");
|
|
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
gl.deleteFramebuffer(fb);
|
|
|
|
debug("drawing to the canvas using the red texture");
|
|
gl.clearColor(0, 0, 0, 1);
|
|
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
|
if (!checkPixels(gl)) {
|
|
return false;
|
|
}
|
|
|
|
debug("succeeded in drawing");
|
|
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "each run with no error");
|
|
return true;
|
|
}
|
|
|
|
function phase2() {
|
|
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
|
|
debug("");
|
|
debug("fbos allocated:" + numFBOs);
|
|
if (!checkPixels(gl)) {
|
|
testFailed("final check of canvas drawing buffer pixels failed");
|
|
}
|
|
debug("");
|
|
finishTest();
|
|
}
|
|
}
|
|
|
|
var successfullyParsed = true;
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|