es3fSyncTests.js (13256B)
1 /*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES Utilities 3 * ------------------------------------------------ 4 * 5 * Copyright 2014 The Android Open Source Project 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 */ 20 21 'use strict'; 22 goog.provide('functional.gles3.es3fSyncTests'); 23 goog.require('framework.common.tcuTestCase'); 24 goog.require('framework.delibs.debase.deRandom'); 25 goog.require('framework.delibs.debase.deString'); 26 goog.require('framework.opengl.gluShaderProgram'); 27 28 goog.scope(function() { 29 var es3fSyncTests = functional.gles3.es3fSyncTests; 30 var tcuTestCase = framework.common.tcuTestCase; 31 var deRandom = framework.delibs.debase.deRandom; 32 var gluShaderProgram = framework.opengl.gluShaderProgram; 33 var deString = framework.delibs.debase.deString; 34 35 /** @const {number} */ es3fSyncTests.NUM_CASE_ITERATIONS = 5; 36 /** @const {number} */ es3fSyncTests.MAX_VERIFY_WAIT = 5; 37 38 /** 39 * @enum 40 */ 41 es3fSyncTests.WaitCommand = { 42 WAIT_SYNC: 1, 43 CLIENT_WAIT_SYNC: 2 44 }; 45 46 /** @enum 47 */ 48 es3fSyncTests.CaseOptions = { 49 FLUSH_BEFORE_WAIT: 1, 50 FINISH_BEFORE_WAIT: 2 51 }; 52 53 /** @enum 54 */ 55 es3fSyncTests.State = { 56 DRAW: 0, 57 VERIFY: 1, 58 FINISH: 2 59 }; 60 61 /** 62 * @constructor 63 * @extends {tcuTestCase.DeqpTest} 64 * @param {string} name 65 * @param {string} description 66 * @param {number} numPrimitives 67 * @param {number} waitCommand 68 * @param {number} waitFlags 69 * @param {number} timeout 70 * @param {number} options 71 */ 72 es3fSyncTests.FenceSyncCase = function(name, description, numPrimitives, waitCommand, waitFlags, timeout, options) { 73 tcuTestCase.DeqpTest.call(this, name, description); 74 /** @type {number} */ this.m_numPrimitives = numPrimitives; 75 /** @type {number} */ this.m_waitCommand = waitCommand; 76 /** @type {number} */ this.m_waitFlags = waitFlags; 77 /** @type {number} */ this.m_timeout = timeout; 78 /** @type {number} */ this.m_caseOptions = options; 79 80 /** @type {gluShaderProgram.ShaderProgram} */ this.m_program = null; 81 /** @type {WebGLSync} */ this.m_syncObject = null; 82 /** @type {number} */ this.m_iterNdx = 0; 83 /** @type {deRandom.Random} */ this.m_rnd = new deRandom.Random(deString.deStringHash(this.name)); 84 /** @type {es3fSyncTests.State} */ this.m_state = es3fSyncTests.State.DRAW; 85 }; 86 87 es3fSyncTests.FenceSyncCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype); 88 es3fSyncTests.FenceSyncCase.prototype.constructor = es3fSyncTests.FenceSyncCase; 89 90 /** 91 * @param {number} numPrimitives 92 * @param {deRandom.Random} rnd 93 * @return {Array<number>} 94 */ 95 es3fSyncTests.generateVertices = function(numPrimitives, rnd) { 96 /** @type {Array<number>} */ var dst = []; 97 /** @type {number} */ var numVertices = 3 * numPrimitives; 98 99 for (var i = 0; i < numVertices; i++) { 100 dst.push(rnd.getFloat(-1.0, 1.0)); // x 101 dst.push(rnd.getFloat(-1.0, 1.0)); // y 102 dst.push(rnd.getFloat(0.0, 1.0)); // z 103 dst.push(1.0); // w 104 } 105 return dst; 106 }; 107 108 es3fSyncTests.FenceSyncCase.prototype.init = function() { 109 /** @type {string} */ var vertShaderSource = '#version 300 es\n' + 110 'layout(location = 0) in mediump vec4 a_position;\n' + 111 '\n' + 112 'void main (void)\n' + 113 '{\n' + 114 ' gl_Position = a_position;\n' + 115 '}\n'; 116 117 /** @type {string} */ var fragShaderSource = '#version 300 es\n' + 118 'layout(location = 0) out mediump vec4 o_color;\n' + 119 '\n' + 120 'void main (void)\n' + 121 '{\n' + 122 ' o_color = vec4(0.25, 0.5, 0.75, 1.0);\n' + 123 '}\n'; 124 125 assertMsgOptions(!this.m_program, 'Program should be null.', false, true); 126 this.m_program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vertShaderSource, fragShaderSource)); 127 128 if (!this.m_program.isOk()) 129 throw new Error('Failed to compile shader program'); 130 }; 131 132 es3fSyncTests.FenceSyncCase.prototype.deinit = function() { 133 if (this.m_program) 134 this.m_program = null; 135 136 if (this.m_syncObject) { 137 gl.deleteSync(this.m_syncObject); 138 this.m_syncObject = null; 139 } 140 }; 141 142 /** 143 * @return {tcuTestCase.IterateResult} 144 */ 145 es3fSyncTests.FenceSyncCase.prototype.draw = function() { 146 /** @type {Array<number>} */ var vertices = []; 147 148 /** @type {string} */ var header = 'Case iteration ' + (this.m_iterNdx + 1) + ' / ' + es3fSyncTests.NUM_CASE_ITERATIONS; 149 bufferedLogToConsole(header); 150 151 assertMsgOptions(this.m_program !== null, 'Expected program', false, true); 152 gl.useProgram(this.m_program.getProgram()); 153 gl.enable(gl.DEPTH_TEST); 154 gl.clearColor(0.3, 0.3, 0.3, 1.0); 155 gl.clearDepth(1.0); 156 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 157 158 // Generate vertices 159 160 gl.enableVertexAttribArray(0); 161 vertices = es3fSyncTests.generateVertices(this.m_numPrimitives, this.m_rnd); 162 163 /** @type {WebGLBuffer} */ var vertexGLBuffer = gl.createBuffer(); 164 gl.bindBuffer(gl.ARRAY_BUFFER, vertexGLBuffer); 165 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW); 166 gl.vertexAttribPointer(0, 4, gl.FLOAT, false, 0, 0); 167 168 // Draw 169 170 gl.drawArrays(gl.TRIANGLES, 0, vertices.length / 4); 171 bufferedLogToConsole('Primitives drawn.'); 172 173 // Create sync object 174 175 this.m_syncObject = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0); 176 bufferedLogToConsole('Sync object created'); 177 178 if (this.m_caseOptions & es3fSyncTests.CaseOptions.FLUSH_BEFORE_WAIT) 179 gl.flush(); 180 if (this.m_caseOptions & es3fSyncTests.CaseOptions.FINISH_BEFORE_WAIT) 181 gl.finish(); 182 this.m_state = es3fSyncTests.State.VERIFY; 183 }; 184 185 186 es3fSyncTests.FenceSyncCase.prototype.verify = function() { 187 /** @type {number} */ var waitValue = 0; 188 /** @type {boolean} */ var testOk = true; 189 190 // Wait for sync object 191 if (this.m_waitCommand & es3fSyncTests.WaitCommand.WAIT_SYNC) { 192 assertMsgOptions(this.m_timeout === gl.TIMEOUT_IGNORED, 'Expected TIMEOUT_IGNORED', false, true); 193 assertMsgOptions(this.m_waitFlags === 0, 'Expected waitFlags = 0', false, true); 194 gl.waitSync(this.m_syncObject, this.m_waitFlags, this.m_timeout); 195 bufferedLogToConsole('Wait command glWaitSync called with GL_TIMEOUT_IGNORED.'); 196 } 197 198 if (this.m_waitCommand & es3fSyncTests.WaitCommand.CLIENT_WAIT_SYNC) { 199 waitValue = gl.clientWaitSync(this.m_syncObject, this.m_waitFlags, this.m_timeout); 200 bufferedLogToConsole('glClientWaitSync return value:'); 201 switch (waitValue) { 202 case gl.ALREADY_SIGNALED: 203 bufferedLogToConsole('gl.ALREADY_SIGNALED'); 204 break; 205 case gl.TIMEOUT_EXPIRED: 206 bufferedLogToConsole('gl.TIMEOUT_EXPIRED'); 207 break; 208 case gl.CONDITION_SATISFIED: 209 bufferedLogToConsole('gl.CONDITION_SATISFIED'); 210 break; 211 case gl.WAIT_FAILED: 212 bufferedLogToConsole('gl.WAIT_FAILED'); 213 testOk = false; 214 break; 215 default: 216 bufferedLogToConsole('Illegal return value!'); 217 } 218 } 219 220 gl.finish(); 221 222 // Delete sync object 223 224 if (this.m_syncObject && testOk) { 225 gl.deleteSync(this.m_syncObject); 226 this.m_syncObject = null; 227 bufferedLogToConsole('Sync object deleted.'); 228 } 229 230 // Evaluate test result 231 232 bufferedLogToConsole('Test result: ' + (testOk ? 'Passed!' : 'Failed!')); 233 234 if (!testOk) { 235 if (!this.m_verifyStart) 236 this.m_verifyStart = new Date(); 237 else { 238 var current = new Date(); 239 var elapsedTime = 0.001 * (current.getTime() - this.m_verifyStart.getTime()); 240 if (elapsedTime > es3fSyncTests.MAX_VERIFY_WAIT) { 241 testFailedOptions('Fail', false); 242 this.m_state = es3fSyncTests.State.FINISH; 243 if (this.m_syncObject) { 244 gl.deleteSync(this.m_syncObject); 245 this.m_syncObject = null; 246 bufferedLogToConsole('Sync object deleted.'); 247 } 248 } 249 } 250 } else { 251 bufferedLogToConsole('Sync objects created and deleted successfully.'); 252 testPassedOptions('Pass', true); 253 this.m_state = (++this.m_iterNdx < es3fSyncTests.NUM_CASE_ITERATIONS) ? es3fSyncTests.State.DRAW : es3fSyncTests.State.FINISH; 254 } 255 }; 256 257 es3fSyncTests.FenceSyncCase.prototype.iterate = function() { 258 switch (this.m_state) { 259 case es3fSyncTests.State.DRAW: 260 this.draw(); 261 break; 262 case es3fSyncTests.State.VERIFY: 263 this.verify(); 264 break; 265 case es3fSyncTests.State.FINISH: 266 return tcuTestCase.IterateResult.STOP; 267 default: 268 throw new Error('Invalid state: ' + this.m_state); 269 } 270 271 return tcuTestCase.IterateResult.CONTINUE; 272 }; 273 274 /** 275 * @constructor 276 * @extends {tcuTestCase.DeqpTest} 277 */ 278 es3fSyncTests.SyncTests = function() { 279 tcuTestCase.DeqpTest.call(this, 'fence_sync', 'Fence Sync Tests'); 280 }; 281 282 es3fSyncTests.SyncTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype); 283 es3fSyncTests.SyncTests.prototype.constructor = es3fSyncTests.SyncTests; 284 285 es3fSyncTests.SyncTests.prototype.init = function() { 286 // Fence sync tests. 287 288 this.addChild(new es3fSyncTests.FenceSyncCase('wait_sync_smalldraw', '', 10, es3fSyncTests.WaitCommand.WAIT_SYNC, 0, gl.TIMEOUT_IGNORED, 0)); 289 this.addChild(new es3fSyncTests.FenceSyncCase('wait_sync_largedraw', '', 100000, es3fSyncTests.WaitCommand.WAIT_SYNC, 0, gl.TIMEOUT_IGNORED, 0)); 290 291 this.addChild(new es3fSyncTests.FenceSyncCase('client_wait_sync_smalldraw', '', 10, es3fSyncTests.WaitCommand.CLIENT_WAIT_SYNC, 0, 0, 0)); 292 this.addChild(new es3fSyncTests.FenceSyncCase('client_wait_sync_largedraw', '', 100000, es3fSyncTests.WaitCommand.CLIENT_WAIT_SYNC, 0, 0, 0)); 293 294 // Originally the next two test cases' timeout is 10, but in WebGL2 that could be illegal. 295 var max = gl.getParameter(gl.MAX_CLIENT_WAIT_TIMEOUT_WEBGL) || 0; 296 this.addChild(new es3fSyncTests.FenceSyncCase('client_wait_sync_timeout_smalldraw', '', 10, es3fSyncTests.WaitCommand.CLIENT_WAIT_SYNC, 0, max, 0)); 297 this.addChild(new es3fSyncTests.FenceSyncCase('client_wait_sync_timeout_largedraw', '', 100000, es3fSyncTests.WaitCommand.CLIENT_WAIT_SYNC, 0, max, 0)); 298 299 this.addChild(new es3fSyncTests.FenceSyncCase('client_wait_sync_flush_auto', '', 100000, es3fSyncTests.WaitCommand.CLIENT_WAIT_SYNC, gl.SYNC_FLUSH_COMMANDS_BIT, 0, 0)); 300 this.addChild(new es3fSyncTests.FenceSyncCase('client_wait_sync_flush_manual', '', 100000, es3fSyncTests.WaitCommand.CLIENT_WAIT_SYNC, 0, 0, es3fSyncTests.CaseOptions.FLUSH_BEFORE_WAIT)); 301 this.addChild(new es3fSyncTests.FenceSyncCase('client_wait_sync_noflush', '', 100000, es3fSyncTests.WaitCommand.CLIENT_WAIT_SYNC, 0, 0, 0)); 302 this.addChild(new es3fSyncTests.FenceSyncCase('client_wait_sync_finish', '', 100000, es3fSyncTests.WaitCommand.CLIENT_WAIT_SYNC, 0, 0, es3fSyncTests.CaseOptions.FINISH_BEFORE_WAIT)); 303 304 }; 305 306 /** 307 * Run test 308 * @param {WebGL2RenderingContext} context 309 */ 310 es3fSyncTests.run = function(context) { 311 gl = context; 312 //Set up Test Root parameters 313 var state = tcuTestCase.runner; 314 state.setRoot(new es3fSyncTests.SyncTests()); 315 316 //Set up name and description of this test series. 317 setCurrentTestName(state.testCases.fullName()); 318 description(state.testCases.getDescription()); 319 320 try { 321 //Run test cases 322 tcuTestCase.runTestCases(); 323 } 324 catch (err) { 325 testFailedOptions('Failed to es3fSyncTests.run tests', false); 326 tcuTestCase.runner.terminate(); 327 } 328 }; 329 330 });