rendering-sampling-feedback-loop.html (5247B)
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 Rendering and Sampling Feedback Loop Tests</title> 12 <link rel="stylesheet" href="../../resources/js-test-style.css"/> 13 <script src="../../js/js-test-pre.js"></script> 14 <script src="../../js/webgl-test-utils.js"></script> 15 </head> 16 <body> 17 <canvas id="example" width="8" height="8"></canvas> 18 <div id="description"></div> 19 <div id="console"></div> 20 21 <script id="vs100" type="x-shader/x-vertex"> 22 attribute vec4 aPosition; 23 attribute vec2 aTexCoord; 24 varying vec2 texCoord; 25 void main() { 26 gl_Position = aPosition; 27 texCoord = aTexCoord; 28 } 29 </script> 30 31 <script id="fs100" type="x-shader/x-fragment"> 32 #extension GL_EXT_draw_buffers : require 33 precision mediump float; 34 uniform sampler2D tex; 35 varying vec2 texCoord; 36 void main() { 37 gl_FragData[0] = texture2D(tex, texCoord); 38 gl_FragData[1] = texture2D(tex, texCoord); 39 } 40 </script> 41 42 <script id="fs100-no-ext-draw-buffers" type="x-shader/x-fragment"> 43 precision mediump float; 44 uniform sampler2D tex; 45 varying vec2 texCoord; 46 void main() { 47 gl_FragData[0] = texture2D(tex, texCoord); 48 } 49 </script> 50 51 <script id="vs300" type="x-shader/x-vertex">#version 300 es 52 in highp vec4 aPosition; 53 in vec2 aTexCoord; 54 out vec2 texCoord; 55 void main() { 56 gl_Position = aPosition; 57 texCoord = aTexCoord; 58 } 59 </script> 60 61 <script id="fs300" type="x-shader/x-fragment">#version 300 es 62 precision mediump float; 63 uniform sampler2D tex; 64 in vec2 texCoord; 65 out vec4 oColor; 66 void main() { 67 oColor = texture(tex, texCoord); 68 } 69 </script> 70 71 <script> 72 "use strict"; 73 74 const wtu = WebGLTestUtils; 75 description("This test verifies the functionality of rendering to the same texture where it samples from."); 76 77 const gl = wtu.create3DContext("example"); 78 79 const width = 8; 80 const height = 8; 81 let tex; 82 let fbo; 83 let drawBuffers = null; 84 85 if (!gl) { 86 testFailed("WebGL context does not exist"); 87 } else { 88 testPassed("WebGL context exists"); 89 90 if (gl.drawBuffers) { 91 debug("Using webgl2.drawBuffers."); 92 drawBuffers = (x) => gl.drawBuffers(x); 93 } else { 94 const ext = gl.getExtension("WEBGL_draw_buffers"); 95 if (ext) { 96 debug("Using WEBGL_draw_buffers.drawBuffersWEBGL."); 97 drawBuffers = (x) => ext.drawBuffersWEBGL(x); 98 } 99 } 100 101 init(); 102 103 // The sampling texture is bound to COLOR_ATTACHMENT1 during resource allocation 104 allocate_resource(); 105 106 rendering_sampling_feedback_loop(null); 107 if (drawBuffers) { 108 rendering_sampling_feedback_loop([gl.NONE]); 109 rendering_sampling_feedback_loop([gl.COLOR_ATTACHMENT0, 110 gl.COLOR_ATTACHMENT0+1]); 111 rendering_sampling_feedback_loop([gl.NONE, 112 gl.COLOR_ATTACHMENT0+1]); 113 } 114 } 115 116 function init() { 117 let shaders = ["vs100", "fs100"]; 118 if (gl.texStorage2D) { 119 shaders = ["vs300", "fs300"]; 120 } else if (!drawBuffers) { 121 shaders = ["vs100", "fs100-no-ext-draw-buffers"]; 122 } 123 const program = wtu.setupProgram(gl, shaders, ["aPosition", "aTexCoord"], [0, 1]); 124 const positionLoc = gl.getAttribLocation(program, "aPosition"); 125 const texCoordLoc = gl.getAttribLocation(program, "aTexCoord"); 126 if (!program || positionLoc < 0 || texCoordLoc < 0) { 127 testFailed("Set up program failed"); 128 return; 129 } 130 const texLoc = gl.getUniformLocation(program, "tex"); 131 gl.uniform1i(texLoc, 0); 132 testPassed("Set up program succeeded"); 133 134 wtu.setupUnitQuad(gl, 0, 1); 135 gl.viewport(0, 0, width, height); 136 } 137 138 function allocate_resource() { 139 tex = gl.createTexture(); 140 gl.bindTexture(gl.TEXTURE_2D, tex); 141 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 142 143 fbo = gl.createFramebuffer(); 144 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); 145 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0); 146 } 147 148 function rendering_sampling_feedback_loop(draw_buffers) { 149 debug("draw_buffers: " + JSON.stringify(draw_buffers)); 150 151 if (draw_buffers) { 152 drawBuffers(draw_buffers); 153 } 154 155 // Make sure framebuffer is complete before feedback loop detection 156 if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) { 157 testFailed("Framebuffer incomplete."); 158 return; 159 } 160 161 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); 162 wtu.clearAndDrawUnitQuad(gl); 163 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Feedback loop detection should ignore drawBuffers settings."); 164 165 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_NEAREST); 166 // The texture will be mipmap incomplete, so feedback cannot occur nor be consistently evaluated. 167 wtu.clearAndDrawUnitQuad(gl); 168 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Feedback loop detection should ignore sampled incomplete textures."); 169 170 if (draw_buffers) { 171 drawBuffers([gl.COLOR_ATTACHMENT0]); 172 } 173 } 174 175 gl.deleteTexture(tex); 176 gl.deleteFramebuffer(fbo); 177 178 var successfullyParsed = true; 179 </script> 180 <script src="../../js/js-test-post.js"></script> 181 182 </body> 183 </html>