big-fbos-example.html (6891B)
1 <!-- 2 Copyright (c) 2019 The Khronos Group Inc. 3 Use of this source code is governed by an MIT-style license that can be 4 found in the LICENSE.txt file. 5 --> 6 7 <!DOCTYPE html> 8 <html> 9 <head> 10 <meta charset="utf-8"> 11 <title>WebGL Big FBO Test</title> 12 <link rel="stylesheet" href="../resources/js-test-style.css"/> 13 <script src="../../devtools/src/debug/webgl-debug.js"></script> 14 <script src="../js/js-test-pre.js"></script> 15 <script src="../js/webgl-test-utils.js"></script> 16 </head> 17 <body> 18 <canvas id="canvas" width="256" height="256"> </canvas> 19 <div id="description"></div> 20 <div id="console"></div> 21 <script id="vshader" type="x-shader/x-vertex"> 22 attribute vec4 vPosition; 23 attribute vec2 texCoord0; 24 varying vec2 texCoord; 25 void main() 26 { 27 gl_Position = vec4(vPosition.xyz, 1.0); 28 texCoord = texCoord0; 29 } 30 </script> 31 32 <script id="fshader" type="x-shader/x-fragment"> 33 precision mediump float; 34 uniform sampler2D tex; 35 varying vec2 texCoord; 36 void main() 37 { 38 gl_FragColor = texture2D(tex, texCoord); 39 } 40 </script> 41 <script> 42 "use strict"; 43 window.onload = init; 44 45 var g_textures = []; 46 47 debug("Tests the performance of using lots of large FBOs"); 48 49 function init() { 50 if (confirm( 51 "After clicking OK your machine may become unresponsive or crash.")) { 52 main(); 53 } else { 54 debug("cancelled"); 55 } 56 } 57 58 function checkFBOStatus(gl) { 59 var err = gl.getError(); 60 if (err != gl.NO_ERROR) { 61 if (err != gl.OUT_OF_MEMORY) 62 testFailed("gl.getError returned " + err); 63 else 64 testPassed("OUT-OF-MEMORY"); 65 return false; 66 } 67 var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER); 68 if (status != gl.FRAMEBUFFER_COMPLETE) { 69 testFailed("gl.checkFramebufferStatus() returned " + WebGLTestUtils.glEnumToString(gl, status)); 70 return false; 71 } 72 return true; 73 } 74 75 function setupFBO(gl, size) { 76 var tex = gl.createTexture(); 77 gl.bindTexture(gl.TEXTURE_2D, tex); 78 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); 79 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); 80 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); 81 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); 82 83 var fb = gl.createFramebuffer(); 84 gl.bindFramebuffer(gl.FRAMEBUFFER, fb); 85 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0); 86 87 gl.texImage2D(gl.TEXTURE_2D, 88 0, // level 89 gl.RGBA, // internalFormat 90 size, // width 91 size, // height 92 0, // border 93 gl.RGBA, // format 94 gl.UNSIGNED_BYTE, // type 95 null); // data 96 if (!checkFBOStatus(gl)) 97 return null; 98 99 return { fb: fb, tex: tex }; 100 } 101 102 function checkPixels(gl) { 103 var width = 256; 104 var height = 256; 105 106 var thresh = 3; 107 108 var buf = new Uint8Array(width * height * 4); 109 gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf); 110 for (var yy = 0; yy < height; ++yy) { 111 for (var xx = 0; xx < width; ++xx) { 112 var offset = (yy * width + xx) * 4; 113 if (Math.abs(buf[offset] - 255) > thresh || 114 Math.abs(buf[offset + 1] - 0) > thresh || 115 Math.abs(buf[offset + 2] - 0) > thresh) { 116 testFailed("drawing results incorrect"); 117 return false; 118 } 119 } 120 } 121 return true; 122 } 123 124 function handleContextLost() { 125 debug("context lost"); 126 } 127 128 function main() { 129 debug(""); 130 debug("Checking for out of memory handling."); 131 132 var canvas = document.getElementById("canvas"); 133 canvas.addEventListener('webglcontextlost', handleContextLost); 134 var wtu = WebGLTestUtils; 135 var gl = wtu.create3DContext("canvas"); 136 var prog = wtu.setupProgram(gl, ["vshader", "fshader"], ["vPosition", "texCoord0"]); 137 138 WebGLDebugUtils.init(gl); 139 140 gl.disable(gl.DEPTH_TEST); 141 gl.disable(gl.BLEND); 142 143 var vertexObject = gl.createBuffer(); 144 gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject); 145 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 146 -1,1,0, 1,1,0, -1,-1,0, 147 -1,-1,0, 1,1,0, 1,-1,0 148 ]), gl.STATIC_DRAW); 149 gl.enableVertexAttribArray(0); 150 gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0); 151 152 var vertexObject = gl.createBuffer(); 153 gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject); 154 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0,0, 1,0, 0,1, 155 0,1, 1,0, 1,1 156 ]), gl.STATIC_DRAW); 157 gl.enableVertexAttribArray(1); 158 gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, 0); 159 160 var texLoc = gl.getUniformLocation(prog, "tex"); 161 gl.uniform1i(texLoc, 0); 162 163 gl.clearColor(0, 0, 0, 1); 164 gl.clear(gl.COLOR_BUFFER_BIT); 165 166 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "setup should succeed"); 167 168 var size = gl.getParameter(gl.MAX_RENDERBUFFER_SIZE); 169 debug("max render buffer size: " + size + 170 ", size used: " + (size / 2)); 171 size /= 2; 172 173 var maxFBOs = 200; 174 var numFBOs = 0; 175 allocateNextFBO(); 176 177 function allocateNextFBO() { 178 if (numFBOs >= maxFBOs) { 179 phase2(); 180 return; 181 } 182 if (!allocateFBO()) { 183 phase2(); 184 return; 185 } 186 ++numFBOs; 187 setTimeout(allocateNextFBO, 100); 188 } 189 190 function allocateFBO() { 191 debug(""); 192 debug("trying to create fbo #" + (numFBOs + 1)); 193 var t = setupFBO(gl, 2); 194 if (!t) { 195 return false; 196 } 197 198 var tex = t.tex; 199 var fb = t.fb; 200 201 debug("allocating fbo color buffer of size " + size + " x " + size); 202 gl.texImage2D(gl.TEXTURE_2D, 203 0, // level 204 gl.RGBA, // internalFormat 205 size, // width 206 size, // height 207 0, // border 208 gl.RGBA, // format 209 gl.UNSIGNED_BYTE, // type 210 null); // data 211 if (!checkFBOStatus(gl)) { 212 return false; 213 } 214 g_textures.push(tex); 215 debug("succeeded in creating fbo"); 216 217 debug("clearing the fbo with red color"); 218 gl.bindFramebuffer(gl.FRAMEBUFFER, fb); 219 gl.clearColor(1, 0, 0, 1); 220 gl.clear(gl.COLOR_BUFFER_BIT); 221 222 debug("deleting fbo, but the now red texture should be untouched"); 223 gl.bindFramebuffer(gl.FRAMEBUFFER, null); 224 gl.deleteFramebuffer(fb); 225 226 debug("drawing to the canvas using the red texture"); 227 gl.clearColor(0, 0, 0, 1); 228 gl.clear(gl.COLOR_BUFFER_BIT); 229 gl.drawArrays(gl.TRIANGLES, 0, 6); 230 if (!checkPixels(gl)) { 231 return false; 232 } 233 234 debug("succeeded in drawing"); 235 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "each run with no error"); 236 return true; 237 } 238 239 function phase2() { 240 gl.bindFramebuffer(gl.FRAMEBUFFER, null); 241 242 debug(""); 243 debug("fbos allocated:" + numFBOs); 244 if (!checkPixels(gl)) { 245 testFailed("final check of canvas drawing buffer pixels failed"); 246 } 247 debug(""); 248 finishTest(); 249 } 250 } 251 252 var successfullyParsed = true; 253 </script> 254 255 </body> 256 </html>