get-buffer-sub-data-validity.html (7572B)
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>WebGL2 getBufferSubData validity 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 <div id="description"></div> 18 <div id="console"></div> 19 20 <script id="vshader" type="x-shader/x-vertex">#version 300 es 21 in uint in_data; 22 flat out uint out_data; 23 void main() { 24 out_data = in_data; 25 } 26 </script> 27 <script id="fshader" type="x-shader/x-fragment">#version 300 es 28 void main() {} 29 </script> 30 31 <script> 32 "use strict"; 33 description("Test that getBufferSubData returns valid data in edge cases"); 34 35 var wtu = WebGLTestUtils; 36 37 var gl = wtu.create3DContext(undefined, undefined, 2); 38 39 const srcData = new Uint8Array([ 1, 2, 3, 4, 5, 6, 7, 8 ]); 40 const noData = new Uint8Array(8); 41 42 const srcBuffer = gl.createBuffer(); 43 gl.bindBuffer(gl.COPY_READ_BUFFER, srcBuffer); 44 gl.bufferData(gl.COPY_READ_BUFFER, srcData, gl.STATIC_DRAW); 45 46 const badBuffer = gl.createBuffer(); 47 gl.bindBuffer(gl.ARRAY_BUFFER, badBuffer); 48 gl.bufferData(gl.ARRAY_BUFFER, 8, gl.STATIC_DRAW); 49 50 let readbackBuffer; 51 function deleteReadbackBuffer() { 52 gl.deleteBuffer(readbackBuffer); 53 } 54 function recreateReadbackBuffer() { 55 readbackBuffer = gl.createBuffer(); 56 gl.bindBuffer(gl.COPY_WRITE_BUFFER, readbackBuffer); 57 gl.bufferData(gl.COPY_WRITE_BUFFER, 8, gl.STREAM_READ); 58 } 59 recreateReadbackBuffer(); 60 61 const dest = new Uint8Array(8); 62 63 // Makes a new "resolvable" Promise 64 function resolvable() { 65 let resolve; 66 const promise = new Promise(res => { resolve = res; }); 67 promise.resolve = resolve; 68 return promise; 69 } 70 71 function wait() { 72 return new Promise(res => { 73 setTimeout(res, 0); 74 }); 75 } 76 77 async function fence() { 78 const sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0); 79 gl.flush(); 80 81 let status; 82 do { 83 await wait(); 84 status = gl.clientWaitSync(sync, 0, 0); 85 } while (status != gl.ALREADY_SIGNALED && status != gl.CONDITION_SATISFIED); 86 gl.deleteSync(sync); 87 } 88 89 function checkGetBufferSubData(err, data) { 90 dest.fill(0); 91 wtu.shouldGenerateGLError(gl, err, "gl.getBufferSubData(gl.COPY_WRITE_BUFFER, 0, dest)"); 92 if (!err) { 93 shouldBeTrue(`areArraysEqual(dest, ${data})`); 94 } 95 } 96 97 const tfProgram = wtu.setupTransformFeedbackProgram(gl, ["vshader", "fshader"], 98 ["out_data"], gl.SEPARATE_ATTRIBS, 99 ["in_data"]); 100 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "linking transform feedback shader should not set an error"); 101 shouldBeNonNull("tfProgram"); 102 const tf = gl.createTransformFeedback(); 103 104 function copyBufferUsingTransformFeedback(src, dst) { 105 gl.enableVertexAttribArray(0); 106 gl.bindBuffer(gl.ARRAY_BUFFER, src); 107 gl.vertexAttribIPointer(0, 1, gl.UNSIGNED_INT, 0, 0); 108 109 gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf); 110 gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, dst); 111 112 gl.drawBuffers([gl.NONE]); 113 114 gl.enable(gl.RASTERIZER_DISCARD); 115 gl.beginTransformFeedback(gl.POINTS); 116 // treats the input and output data as two uint32s 117 gl.drawArrays(gl.POINTS, 0, 2); 118 gl.endTransformFeedback(); 119 gl.disable(gl.RASTERIZER_DISCARD); 120 121 gl.bindBuffer(gl.ARRAY_BUFFER, badBuffer); 122 gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, null); 123 gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null); 124 } 125 126 (async () => { 127 debug(""); 128 debug("write-read"); 129 gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8); 130 checkGetBufferSubData(gl.NO_ERROR, "srcData"); 131 132 debug(""); 133 debug("fence-wait-write-read"); 134 await fence(); 135 gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8); 136 checkGetBufferSubData(gl.NO_ERROR, "srcData"); 137 138 debug(""); 139 debug("write-read-fence-wait"); 140 gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8); 141 checkGetBufferSubData(gl.NO_ERROR, "srcData"); 142 await fence(); 143 144 debug(""); 145 debug("write-fence-fence-wait-read"); 146 gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8); 147 fence(); // no await 148 await fence(); 149 checkGetBufferSubData(gl.NO_ERROR, "srcData"); 150 151 debug(""); 152 debug("write-fence-wait-read"); 153 gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8); 154 await fence(); 155 checkGetBufferSubData(gl.NO_ERROR, "srcData"); 156 157 debug(""); 158 debug("write-fence-wait-write-read"); 159 gl.copyBufferSubData(gl.ARRAY_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8); 160 await fence(); 161 gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8); 162 checkGetBufferSubData(gl.NO_ERROR, "srcData"); 163 164 debug(""); 165 debug("write-fence-write-wait-read"); 166 gl.copyBufferSubData(gl.ARRAY_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8); 167 { 168 const p = fence(); 169 gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8); 170 await p; 171 } 172 checkGetBufferSubData(gl.NO_ERROR, "srcData"); 173 174 debug(""); 175 debug("write-fence-transformfeedback-wait-read"); 176 gl.copyBufferSubData(gl.ARRAY_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8); 177 { 178 const p = fence(); 179 gl.bindBuffer(gl.COPY_WRITE_BUFFER, null); 180 copyBufferUsingTransformFeedback(srcBuffer, readbackBuffer); 181 gl.bindBuffer(gl.COPY_WRITE_BUFFER, readbackBuffer); 182 await p; 183 } 184 checkGetBufferSubData(gl.NO_ERROR, "srcData"); 185 186 debug(""); 187 debug("write-unbind-fence-wait-bind-read"); 188 gl.bindBuffer(gl.COPY_WRITE_BUFFER, null); 189 gl.bindBuffer(gl.ARRAY_BUFFER, readbackBuffer); 190 gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.ARRAY_BUFFER, 0, 0, 8); 191 gl.bindBuffer(gl.ARRAY_BUFFER, badBuffer); 192 await fence(); 193 gl.bindBuffer(gl.COPY_WRITE_BUFFER, readbackBuffer); 194 checkGetBufferSubData(gl.NO_ERROR, "srcData"); 195 196 debug(""); 197 debug("write-fence-wait-delete-read"); 198 gl.copyBufferSubData(gl.ARRAY_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8); 199 await fence(); 200 deleteReadbackBuffer(); 201 checkGetBufferSubData(gl.INVALID_OPERATION, "noData"); 202 recreateReadbackBuffer(); 203 204 debug(""); 205 debug("write-fence-delete-wait-read"); 206 gl.copyBufferSubData(gl.ARRAY_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8); 207 { 208 const p = fence(); 209 deleteReadbackBuffer(); 210 await p; 211 } 212 checkGetBufferSubData(gl.INVALID_OPERATION, "noData"); 213 recreateReadbackBuffer(); 214 215 debug(""); 216 debug("write-fence-delete-wait-read"); 217 gl.copyBufferSubData(gl.ARRAY_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8); 218 deleteReadbackBuffer(); 219 await fence(); 220 checkGetBufferSubData(gl.INVALID_OPERATION, "noData"); 221 recreateReadbackBuffer(); 222 223 // crbug.com/941930 224 { 225 debug(""); 226 debug("write-delete-recreate-fence-wait-read"); 227 gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8); 228 deleteReadbackBuffer(); 229 recreateReadbackBuffer(); 230 await fence(); 231 checkGetBufferSubData(gl.NO_ERROR, "noData"); 232 233 debug(""); 234 debug("write-delete-fence-wait-read"); 235 gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8); 236 { 237 const p = fence(); 238 deleteReadbackBuffer(); 239 await p; 240 } 241 wtu.glErrorShouldBe(gl, gl.NO_ERROR); 242 } 243 244 finishTest(); 245 })(); 246 247 var successfullyParsed = true; 248 </script> 249 </body> 250 </html>