1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES Utilities
3 * ------------------------------------------------
5 * Copyright 2014 The Android Open Source Project
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
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');
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;
35 /** @const {number} */ es3fSyncTests.NUM_CASE_ITERATIONS = 5;
36 /** @const {number} */ es3fSyncTests.MAX_VERIFY_WAIT = 5;
41 es3fSyncTests.WaitCommand = {
48 es3fSyncTests.CaseOptions = {
55 es3fSyncTests.State = {
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
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;
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;
87 es3fSyncTests.FenceSyncCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
88 es3fSyncTests.FenceSyncCase.prototype.constructor = es3fSyncTests.FenceSyncCase;
91 * @param {number} numPrimitives
92 * @param {deRandom.Random} rnd
93 * @return {Array<number>}
95 es3fSyncTests.generateVertices = function(numPrimitives, rnd) {
96 /** @type {Array<number>} */ var dst = [];
97 /** @type {number} */ var numVertices = 3 * numPrimitives;
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
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' +
112 'void main (void)\n' +
114 ' gl_Position = a_position;\n' +
117 /** @type {string} */ var fragShaderSource = '#version 300 es\n' +
118 'layout(location = 0) out mediump vec4 o_color;\n' +
120 'void main (void)\n' +
122 ' o_color = vec4(0.25, 0.5, 0.75, 1.0);\n' +
125 assertMsgOptions(!this.m_program, 'Program should be null.', false, true);
126 this.m_program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vertShaderSource, fragShaderSource));
128 if (!this.m_program.isOk())
129 throw new Error('Failed to compile shader program');
132 es3fSyncTests.FenceSyncCase.prototype.deinit = function() {
134 this.m_program = null;
136 if (this.m_syncObject) {
137 gl.deleteSync(this.m_syncObject);
138 this.m_syncObject = null;
143 * @return {tcuTestCase.IterateResult}
145 es3fSyncTests.FenceSyncCase.prototype.draw = function() {
146 /** @type {Array<number>} */ var vertices = [];
148 /** @type {string} */ var header = 'Case iteration ' + (this.m_iterNdx + 1) + ' / ' + es3fSyncTests.NUM_CASE_ITERATIONS;
149 bufferedLogToConsole(header);
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);
156 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
160 gl.enableVertexAttribArray(0);
161 vertices = es3fSyncTests.generateVertices(this.m_numPrimitives, this.m_rnd);
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);
170 gl.drawArrays(gl.TRIANGLES, 0, vertices.length / 4);
171 bufferedLogToConsole('Primitives drawn.');
173 // Create sync object
175 this.m_syncObject = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);
176 bufferedLogToConsole('Sync object created');
178 if (this.m_caseOptions & es3fSyncTests.CaseOptions.FLUSH_BEFORE_WAIT)
180 if (this.m_caseOptions & es3fSyncTests.CaseOptions.FINISH_BEFORE_WAIT)
182 this.m_state = es3fSyncTests.State.VERIFY;
186 es3fSyncTests.FenceSyncCase.prototype.verify = function() {
187 /** @type {number} */ var waitValue = 0;
188 /** @type {boolean} */ var testOk = true;
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.');
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:');
202 case gl.ALREADY_SIGNALED:
203 bufferedLogToConsole('gl.ALREADY_SIGNALED');
205 case gl.TIMEOUT_EXPIRED:
206 bufferedLogToConsole('gl.TIMEOUT_EXPIRED');
208 case gl.CONDITION_SATISFIED:
209 bufferedLogToConsole('gl.CONDITION_SATISFIED');
212 bufferedLogToConsole('gl.WAIT_FAILED');
216 bufferedLogToConsole('Illegal return value!');
222 // Delete sync object
224 if (this.m_syncObject && testOk) {
225 gl.deleteSync(this.m_syncObject);
226 this.m_syncObject = null;
227 bufferedLogToConsole('Sync object deleted.');
230 // Evaluate test result
232 bufferedLogToConsole('Test result: ' + (testOk ? 'Passed!' : 'Failed!'));
235 if (!this.m_verifyStart)
236 this.m_verifyStart = new Date();
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.');
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;
257 es3fSyncTests.FenceSyncCase.prototype.iterate = function() {
258 switch (this.m_state) {
259 case es3fSyncTests.State.DRAW:
262 case es3fSyncTests.State.VERIFY:
265 case es3fSyncTests.State.FINISH:
266 return tcuTestCase.IterateResult.STOP;
268 throw new Error('Invalid state: ' + this.m_state);
271 return tcuTestCase.IterateResult.CONTINUE;
276 * @extends {tcuTestCase.DeqpTest}
278 es3fSyncTests.SyncTests = function() {
279 tcuTestCase.DeqpTest.call(this, 'fence_sync', 'Fence Sync Tests');
282 es3fSyncTests.SyncTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
283 es3fSyncTests.SyncTests.prototype.constructor = es3fSyncTests.SyncTests;
285 es3fSyncTests.SyncTests.prototype.init = function() {
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));
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));
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));
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));
308 * @param {WebGL2RenderingContext} context
310 es3fSyncTests.run = function(context) {
312 //Set up Test Root parameters
313 var state = tcuTestCase.runner;
314 state.setRoot(new es3fSyncTests.SyncTests());
316 //Set up name and description of this test series.
317 setCurrentTestName(state.testCases.fullName());
318 description(state.testCases.getDescription());
322 tcuTestCase.runTestCases();
325 testFailedOptions('Failed to es3fSyncTests.run tests', false);
326 tcuTestCase.runner.terminate();