es3fTransformFeedbackTests.js (86411B)
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.es3fTransformFeedbackTests'); 23 goog.require('framework.common.tcuImageCompare'); 24 goog.require('framework.common.tcuSurface'); 25 goog.require('framework.common.tcuTestCase'); 26 goog.require('framework.delibs.debase.deMath'); 27 goog.require('framework.delibs.debase.deRandom'); 28 goog.require('framework.delibs.debase.deString'); 29 goog.require('framework.opengl.gluDrawUtil'); 30 goog.require('framework.opengl.gluShaderProgram'); 31 goog.require('framework.opengl.gluShaderUtil'); 32 goog.require('framework.opengl.gluVarType'); 33 goog.require('framework.opengl.gluVarTypeUtil'); 34 35 goog.scope(function() { 36 37 var es3fTransformFeedbackTests = functional.gles3.es3fTransformFeedbackTests; 38 var gluShaderUtil = framework.opengl.gluShaderUtil; 39 var gluDrawUtil = framework.opengl.gluDrawUtil; 40 var gluVarType = framework.opengl.gluVarType; 41 var gluVarTypeUtil = framework.opengl.gluVarTypeUtil; 42 var gluShaderProgram = framework.opengl.gluShaderProgram; 43 var deRandom = framework.delibs.debase.deRandom; 44 var deMath = framework.delibs.debase.deMath; 45 var deString = framework.delibs.debase.deString; 46 var tcuTestCase = framework.common.tcuTestCase; 47 var tcuSurface = framework.common.tcuSurface; 48 var tcuImageCompare = framework.common.tcuImageCompare; 49 50 /** @type {WebGL2RenderingContext} */ var gl; 51 52 var setParentClass = function(child, parent) { 53 child.prototype = Object.create(parent.prototype); 54 child.prototype.constructor = child; 55 }; 56 57 /** 58 * @enum 59 */ 60 es3fTransformFeedbackTests.State = { 61 DRAW: 0, 62 VERIFY: 1, 63 FINISH: 2 64 }; 65 66 /* Maximum time to wait for query result (in seconds) */ 67 /** @const */ es3fTransformFeedbackTests.MAX_VERIFY_WAIT = 5; 68 69 /** @const @type {number} */ es3fTransformFeedbackTests.VIEWPORT_WIDTH = 128; 70 /** @const @type {number} */ es3fTransformFeedbackTests.VIEWPORT_HEIGHT = 128; 71 /** @const @type {number} */ es3fTransformFeedbackTests.BUFFER_GUARD_MULTIPLIER = 2; 72 73 /** 74 * Enums for es3fTransformFeedbackTests.interpolation 75 * @enum {number} 76 */ 77 es3fTransformFeedbackTests.interpolation = { 78 SMOOTH: 0, 79 FLAT: 1, 80 CENTROID: 2 81 82 }; 83 84 /** 85 * Returns es3fTransformFeedbackTests.interpolation name: smooth, flat or centroid 86 * @param {number} interpol es3fTransformFeedbackTests.interpolation enum value 87 * @return {string} 88 */ 89 es3fTransformFeedbackTests.getInterpolationName = function(interpol) { 90 91 switch (interpol) { 92 case es3fTransformFeedbackTests.interpolation.SMOOTH: return 'smooth'; 93 case es3fTransformFeedbackTests.interpolation.FLAT: return 'flat'; 94 case es3fTransformFeedbackTests.interpolation.CENTROID: return 'centroid'; 95 default: 96 throw new Error('Unrecognized es3fTransformFeedbackTests.interpolation name ' + interpol); 97 } 98 99 }; 100 101 /** 102 * @struct 103 * @param {string} name 104 * @param {gluVarType.VarType} type 105 * @param {number} interpolation 106 * @constructor 107 */ 108 es3fTransformFeedbackTests.Varying = function(name, type, interpolation) { 109 this.name = name; 110 this.type = type; 111 this.interpolation = interpolation; 112 }; 113 114 /** es3fTransformFeedbackTests.findAttributeNameEquals 115 * Replaces original implementation of "VaryingNameEquals" and "AttributeNameEquals" in the C++ version 116 * Returns an es3fTransformFeedbackTests.Attribute or es3fTransformFeedbackTests.Varying object which matches its name with the passed string value in the function 117 * @param {(Array<es3fTransformFeedbackTests.Attribute> | Array<es3fTransformFeedbackTests.Varying>)} array 118 * @param {string} name 119 * @return { (es3fTransformFeedbackTests.Attribute | es3fTransformFeedbackTests.Varying | null)} 120 */ 121 es3fTransformFeedbackTests.findAttributeNameEquals = function(array, name) { 122 for (var pos = 0; pos < array.length; pos++) { 123 if (array[pos].name === name) { 124 return array[pos]; 125 } 126 } 127 return null; 128 }; 129 130 /** 131 * @struct 132 * @param {string} name 133 * @param {gluVarType.VarType} type 134 * @param {number} offset 135 * @constructor 136 */ 137 es3fTransformFeedbackTests.Attribute = function(name, type, offset) { 138 this.name = name; 139 this.type = type; 140 this.offset = offset; 141 }; 142 143 /** 144 * Constructs an es3fTransformFeedbackTests.Output object 145 * @constructor 146 */ 147 es3fTransformFeedbackTests.Output = function() { 148 /** @type {number} */ this.bufferNdx = 0; 149 /** @type {number} */ this.offset = 0; 150 /** @type {string} */ this.name; 151 /** @type {gluVarType.VarType} */ this.type = null; 152 /** @type {Array<es3fTransformFeedbackTests.Attribute>} */ this.inputs = []; 153 }; 154 155 /** 156 * Constructs an object type es3fTransformFeedbackTests.DrawCall. 157 * Contains the number of elements as well as whether the Transform Feedback is enabled or not. 158 * @struct 159 * @param {number} numElements 160 * @param {boolean} tfEnabled is Transform Feedback enabled or not 161 * @constructor 162 */ 163 es3fTransformFeedbackTests.DrawCall = function(numElements, tfEnabled) { 164 this.numElements = numElements; 165 this.transformFeedbackEnabled = tfEnabled; 166 }; 167 168 /** 169 * @constructor 170 */ 171 es3fTransformFeedbackTests.ProgramSpec = function() { 172 173 /** @type {Array<gluVarType.StructType>} */ var m_structs = []; 174 /** @type {Array<es3fTransformFeedbackTests.Varying>} */ var m_varyings = []; 175 /** @type {Array<string>} */ var m_transformFeedbackVaryings = []; 176 177 this.createStruct = function(name) { 178 var struct = gluVarType.newStructType(name); 179 m_structs.push(struct); 180 return struct; 181 }; 182 183 this.addVarying = function(name, type, interp) { 184 m_varyings.push(new es3fTransformFeedbackTests.Varying(name, type, interp)); 185 }; 186 187 this.addTransformFeedbackVarying = function(name) { 188 m_transformFeedbackVaryings.push(name); 189 }; 190 191 this.getStructs = function() { 192 return m_structs; 193 }; 194 this.getVaryings = function() { 195 return m_varyings; 196 }; 197 this.getTransformFeedbackVaryings = function() { 198 return m_transformFeedbackVaryings; 199 }; 200 201 this.isPointSizeUsed = function() { 202 for (var i = 0; i < m_transformFeedbackVaryings.length; ++i) { 203 if (m_transformFeedbackVaryings[i] == 'gl_PointSize') return true; 204 } 205 return false; 206 }; 207 208 }; 209 210 /** Returns if the program is supported or not 211 * @param {es3fTransformFeedbackTests.ProgramSpec} spec 212 * @param {number} tfMode 213 * @return {boolean} 214 */ 215 es3fTransformFeedbackTests.isProgramSupported = function(spec, tfMode) { 216 var maxVertexAttribs = Number(gl.getParameter(gl.MAX_VERTEX_ATTRIBS)); 217 var maxTfInterleavedComponents = Number(gl.getParameter(gl.MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS)); 218 var maxTfSeparateAttribs = Number(gl.getParameter(gl.MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS)); 219 var maxTfSeparateComponents = Number(gl.getParameter(gl.MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS)); 220 221 // Check vertex attribs. 222 /** @type {number} */ var totalVertexAttribs = ( 223 1 /* a_position */ + (spec.isPointSizeUsed() ? 1 : 0) 224 ); 225 226 for (var i = 0; i < spec.getVaryings().length; ++i) { 227 for (var v_iter = new gluVarTypeUtil.VectorTypeIterator(spec.getVaryings()[i].type); !v_iter.end(); v_iter.next()) { 228 totalVertexAttribs += 1; 229 } 230 } 231 232 if (totalVertexAttribs > maxVertexAttribs) 233 return false; // Vertex attribute es3fTransformFeedbackTests.count exceeded. 234 235 // check varyings 236 /** @type {number} */ var totalTfComponents = 0; 237 /** @type {number} */ var totalTfAttribs = 0; 238 /** @type {Object.<number, number>} */ var presetNumComponents = { 239 gl_Position: 4, 240 gl_PointSize: 1 241 }; 242 for (var i = 0; i < spec.getTransformFeedbackVaryings().length; ++i) { 243 var name = spec.getTransformFeedbackVaryings()[i]; 244 var numComponents = 0; 245 246 if (typeof(presetNumComponents[name]) != 'undefined') { 247 numComponents = presetNumComponents[name]; 248 } else { 249 var varName = gluVarTypeUtil.parseVariableName(name); 250 // find the varying called varName 251 /** @type {es3fTransformFeedbackTests.Varying} */ var varying = (function(varyings) { 252 for (var i = 0; i < varyings.length; ++i) { 253 if (varyings[i].name == varName) { 254 return varyings[i]; 255 } 256 } 257 return null; 258 }(spec.getVaryings())); 259 260 // glu::TypeComponentVector 261 var varPath = gluVarTypeUtil.parseTypePath(name, varying.type); 262 numComponents = gluVarTypeUtil.getVarType(varying.type, varPath).getScalarSize(); 263 } 264 265 if (tfMode == gl.SEPARATE_ATTRIBS && numComponents > maxTfSeparateComponents) 266 return false; // Per-attribute component es3fTransformFeedbackTests.count exceeded. 267 268 totalTfComponents += numComponents; 269 totalTfAttribs += 1; 270 } 271 272 if (tfMode == gl.SEPARATE_ATTRIBS && totalTfAttribs > maxTfSeparateAttribs) 273 return false; 274 275 if (tfMode == gl.INTERLEAVED_ATTRIBS && totalTfComponents > maxTfInterleavedComponents) 276 return false; 277 278 return true; 279 280 }; 281 282 /** 283 * @param {string} varyingName 284 * @param {Array<gluVarTypeUtil.VarTypeComponent>} path 285 * @return {string} 286 */ 287 es3fTransformFeedbackTests.getAttributeName = function(varyingName, path) { 288 /** @type {string} */ var str = 'a_' + varyingName.substr(/^v_/.test(varyingName) ? 2 : 0); 289 290 for (var i = 0; i < path.length; ++i) { 291 /** @type {string} */ var prefix; 292 293 switch (path[i].type) { 294 case gluVarTypeUtil.VarTypeComponent.s_Type.STRUCT_MEMBER: prefix = '_m'; break; 295 case gluVarTypeUtil.VarTypeComponent.s_Type.ARRAY_ELEMENT: prefix = '_e'; break; 296 case gluVarTypeUtil.VarTypeComponent.s_Type.MATRIX_COLUMN: prefix = '_c'; break; 297 case gluVarTypeUtil.VarTypeComponent.s_Type.VECTOR_COMPONENT: prefix = '_s'; break; 298 default: 299 throw new Error('invalid type in the component path.'); 300 } 301 str += prefix + path[i].index; 302 } 303 return str; 304 }; 305 306 /** 307 * original definition: 308 * static void es3fTransformFeedbackTests.genShaderSources (const es3fTransformFeedbackTests.ProgramSpec& spec, std::string& vertSource, std::string& fragSource, bool pointSizeRequired) 309 * in place of the std::string references, this function returns those params in an object 310 * 311 * @param {es3fTransformFeedbackTests.ProgramSpec} spec 312 * @param {boolean} pointSizeRequired 313 * @return {Object.<string, string>} 314 */ 315 es3fTransformFeedbackTests.genShaderSources = function(spec, pointSizeRequired) { 316 317 var vtx = { str: null }; 318 var frag = { str: null }; 319 var addPointSize = spec.isPointSizeUsed(); 320 321 vtx.str = '#version 300 es\n' + 322 'in highp vec4 a_position;\n'; 323 frag.str = '#version 300 es\n' + 324 'layout(location = 0) out mediump vec4 o_color;\n' + 325 'uniform highp vec4 u_scale;\n' + 326 'uniform highp vec4 u_bias;\n'; 327 //vtx.str = 'attribute highp vec4 a_position;\n'; 328 //frag.str = 'uniform highp vec4 u_scale;\n' + 329 // 'uniform highp vec4 u_bias;\n'; 330 331 if (addPointSize) { 332 vtx.str += 'in highp float a_pointSize;\n'; 333 //vtx.str += 'attribute highp float a_pointSize;\n'; 334 } 335 336 // Declare attributes. 337 for (var i = 0; i < spec.getVaryings().length; ++i) { 338 339 /** @type {string} */ var name = spec.getVaryings()[i].name; 340 /** @type {gluVarType.VarType} */ var type = spec.getVaryings()[i].type; 341 342 for (var vecIter = new gluVarTypeUtil.VectorTypeIterator(type); !vecIter.end(); vecIter.next()) { 343 344 /** @type {gluVarType.VarType} */ 345 var attribType = gluVarTypeUtil.getVarType(type, vecIter.getPath()); 346 347 /** @type {string} */ 348 var attribName = es3fTransformFeedbackTests.getAttributeName(name, vecIter.getPath()); 349 vtx.str += 'in ' + gluVarType.declareVariable(attribType, attribName) + ';\n'; 350 351 } 352 } 353 354 // Declare varyings. 355 for (var ndx = 0; ndx < 2; ++ndx) { 356 var inout = ndx ? 'in' : 'out'; 357 var shader = ndx ? frag : vtx; 358 359 for (var i = 0; i < spec.getStructs().length; ++i) { 360 var struct = spec.getStructs()[i]; 361 if (struct.hasTypeName()) { 362 shader.str += gluVarType.declareStructType(struct) + ';\n'; 363 } 364 } 365 366 /** @type {Array<es3fTransformFeedbackTests.Varying>} */ var varyings = spec.getVaryings(); 367 for (var i = 0; i < varyings.length; ++i) { 368 var varying = varyings[i]; 369 shader.str += es3fTransformFeedbackTests.getInterpolationName(varying.interpolation) + 370 ' ' + inout + ' ' + 371 gluVarType.declareVariable(varying.type, varying.name) + 372 ';\n'; 373 } 374 } 375 376 vtx.str += '\nvoid main (void)\n {\n' + 377 '\tgl_Position = a_position;\n'; 378 frag.str += '\nvoid main (void)\n {\n' + 379 '\thighp vec4 res = vec4(0.0);\n'; 380 381 if (addPointSize) { 382 vtx.str += '\tgl_PointSize = a_pointSize;\n'; 383 } else if (pointSizeRequired) { 384 vtx.str += '\tgl_PointSize = 1.0;\n'; 385 } 386 387 for (var i = 0; i < spec.getVaryings().length; ++i) { 388 var name = spec.getVaryings()[i].name; 389 var type = spec.getVaryings()[i].type; 390 391 for (var vecIter = new gluVarTypeUtil.VectorTypeIterator(type); !vecIter.end(); vecIter.next()) { 392 /** @type {gluVarType.VarType} */var subType = gluVarTypeUtil.getVarType(type, vecIter.getPath()); 393 var attribName = es3fTransformFeedbackTests.getAttributeName(name, vecIter.getPath()); 394 395 if (!( 396 subType.isBasicType() && 397 gluShaderUtil.isDataTypeScalarOrVector(subType.getBasicType()) 398 )) throw new Error('Not a scalar or vector.'); 399 400 // Vertex: assign from attribute. 401 vtx.str += '\t' + name + vecIter.toString() + ' = ' + attribName + ';\n'; 402 403 // Fragment: add to res variable. 404 var scalarSize = gluShaderUtil.getDataTypeScalarSize(subType.getBasicType()); 405 406 frag.str += '\tres += '; 407 if (scalarSize == 1) frag.str += 'vec4(' + name + vecIter.toString() + ')'; 408 else if (scalarSize == 2) frag.str += 'vec2(' + name + vecIter.toString() + ').xxyy'; 409 else if (scalarSize == 3) frag.str += 'vec3(' + name + vecIter.toString() + ').xyzx'; 410 else if (scalarSize == 4) frag.str += 'vec4(' + name + vecIter.toString() + ')'; 411 412 frag.str += ';\n'; 413 } 414 } 415 416 frag.str += '\to_color = res * u_scale + u_bias;\n}\n'; 417 //frag.str += '\tgl_FragColor = res * u_scale + u_bias;\n}\n'; 418 vtx.str += '}\n'; 419 420 return { 421 vertSource: vtx.str, 422 fragSource: frag.str 423 }; 424 }; 425 426 /** 427 * Returns a Shader program 428 * @param {es3fTransformFeedbackTests.ProgramSpec} spec 429 * @param {number} bufferMode 430 * @param {gluDrawUtil.primitiveType} primitiveType GLenum that specifies what kind of primitive is 431 * @return {gluShaderProgram.ShaderProgram} 432 */ 433 es3fTransformFeedbackTests.createVertexCaptureProgram = function(spec, bufferMode, primitiveType) { 434 435 /** @type {Object.<string, string>} */ var source = es3fTransformFeedbackTests.genShaderSources(spec, primitiveType === gluDrawUtil.primitiveType.POINTS /* Is point size required? */); 436 437 var programSources = new gluShaderProgram.ProgramSources(); 438 programSources.add(new gluShaderProgram.VertexSource(source.vertSource)) 439 .add(new gluShaderProgram.FragmentSource(source.fragSource)) 440 .add(new gluShaderProgram.TransformFeedbackVaryings(spec.getTransformFeedbackVaryings())) 441 .add(new gluShaderProgram.TransformFeedbackMode(bufferMode)); 442 443 return new gluShaderProgram.ShaderProgram(gl, programSources); 444 445 }; 446 447 /** 448 * @param {Array<es3fTransformFeedbackTests.Attribute>} attributes 449 * @param {Array<es3fTransformFeedbackTests.Varying>} varyings 450 * @param {boolean} usePointSize 451 * @return {number} input stride 452 */ 453 es3fTransformFeedbackTests.computeInputLayout = function(attributes, varyings, usePointSize) { 454 455 var inputStride = 0; 456 457 // Add position 458 var dataTypeVec4 = gluVarType.newTypeBasic(gluShaderUtil.DataType.FLOAT_VEC4, gluShaderUtil.precision.PRECISION_HIGHP); 459 attributes.push(new es3fTransformFeedbackTests.Attribute('a_position', dataTypeVec4, inputStride)); 460 inputStride += 4 * 4; /*sizeof(deUint32)*/ 461 462 if (usePointSize) { 463 var dataTypeFloat = gluVarType.newTypeBasic(gluShaderUtil.DataType.FLOAT, gluShaderUtil.precision.PRECISION_HIGHP); 464 attributes.push(new es3fTransformFeedbackTests.Attribute('a_pointSize', dataTypeFloat, inputStride)); 465 inputStride += 1 * 4; /*sizeof(deUint32)*/ 466 } 467 468 for (var i = 0; i < varyings.length; i++) { 469 for (var vecIter = new gluVarTypeUtil.VectorTypeIterator(varyings[i].type); !vecIter.end(); vecIter.next()) { 470 var type = vecIter.getType(); // originally getType() in getVarType() within gluVARTypeUtil.hpp. 471 var name = es3fTransformFeedbackTests.getAttributeName(varyings[i].name, vecIter.getPath()); 472 473 attributes.push(new es3fTransformFeedbackTests.Attribute(name, type, inputStride)); 474 inputStride += gluShaderUtil.getDataTypeScalarSize(type.getBasicType()) * 4; /*sizeof(deUint32)*/ 475 } 476 } 477 478 return inputStride; 479 }; 480 481 /** 482 * @param {Array<es3fTransformFeedbackTests.Output>} transformFeedbackOutputs 483 * @param {Array<es3fTransformFeedbackTests.Attribute>} attributes 484 * @param {Array<es3fTransformFeedbackTests.Varying>} varyings 485 * @param {Array<string>} transformFeedbackVaryings 486 * @param {number} bufferMode 487 */ 488 es3fTransformFeedbackTests.computeTransformFeedbackOutputs = function(transformFeedbackOutputs, attributes, varyings, transformFeedbackVaryings, bufferMode) { 489 490 /** @type {number} */ var accumulatedSize = 0; 491 492 // transformFeedbackOutputs.resize(transformFeedbackVaryings.size()); 493 for (var varNdx = 0; varNdx < transformFeedbackVaryings.length; varNdx++) { 494 /** @type {string} */ var name = transformFeedbackVaryings[varNdx]; 495 /** @type {number} */ var bufNdx = (bufferMode === gl.SEPARATE_ATTRIBS ? varNdx : 0); 496 /** @type {number} */ var offset = (bufferMode === gl.SEPARATE_ATTRIBS ? 0 : accumulatedSize); 497 /** @type {es3fTransformFeedbackTests.Output} */ var output = new es3fTransformFeedbackTests.Output(); 498 499 output.name = name; 500 output.bufferNdx = bufNdx; 501 output.offset = offset; 502 503 if (name === 'gl_Position') { 504 var posIn = es3fTransformFeedbackTests.findAttributeNameEquals(attributes, 'a_position'); 505 output.type = posIn.type; 506 output.inputs.push(posIn); 507 } else if (name === 'gl_PointSize') { 508 var sizeIn = es3fTransformFeedbackTests.findAttributeNameEquals(attributes, 'a_pointSize'); 509 output.type = sizeIn.type; 510 output.inputs.push(sizeIn); 511 } else { 512 var varName = gluVarTypeUtil.parseVariableName(name); 513 var varying = es3fTransformFeedbackTests.findAttributeNameEquals(varyings, varName); 514 515 var varPath = gluVarTypeUtil.parseTypePath(name, varying.type); 516 output.type = gluVarTypeUtil.getVarType(varying.type, varPath); 517 518 // Add all vectorized attributes as inputs. 519 for (var iter = new gluVarTypeUtil.VectorTypeIterator(output.type); !iter.end(); iter.next()) { 520 var fullpath = varPath.concat(iter.getPath()); 521 var attribName = es3fTransformFeedbackTests.getAttributeName(varName, fullpath); 522 var attrib = es3fTransformFeedbackTests.findAttributeNameEquals(attributes, attribName); 523 output.inputs.push(attrib); 524 } 525 } 526 transformFeedbackOutputs.push(output); 527 accumulatedSize += output.type.getScalarSize() * 4; /*sizeof(deUint32)*/ 528 } 529 }; 530 531 /** 532 * @param {es3fTransformFeedbackTests.Attribute} attrib 533 * @param {ArrayBuffer} buffer 534 * @param {number} stride 535 * @param {number} numElements 536 * @param {deRandom.Random} rnd 537 */ 538 es3fTransformFeedbackTests.genAttributeData = function(attrib, buffer, stride, numElements, rnd) { 539 540 /** @type {number} */ var elementSize = 4; /*sizeof(deUint32)*/ 541 /** @type {boolean} */ var isFloat = gluShaderUtil.isDataTypeFloatOrVec(attrib.type.getBasicType()); 542 /** @type {boolean} */ var isInt = gluShaderUtil.isDataTypeIntOrIVec(attrib.type.getBasicType()); 543 /** @type {boolean} */ var isUint = gluShaderUtil.isDataTypeUintOrUVec(attrib.type.getBasicType()); 544 545 /** @type {gluShaderUtil.precision} */ var precision = attrib.type.getPrecision(); 546 547 /** @type {number} */ var numComps = gluShaderUtil.getDataTypeScalarSize(attrib.type.getBasicType()); 548 549 for (var elemNdx = 0; elemNdx < numElements; elemNdx++) { 550 for (var compNdx = 0; compNdx < numComps; compNdx++) { 551 /** @type {number} */ var offset = attrib.offset + elemNdx * stride + compNdx * elementSize; 552 if (isFloat) { 553 var pos = new Float32Array(buffer, offset, 1); 554 switch (precision) { 555 case gluShaderUtil.precision.PRECISION_LOWP: pos[0] = 0.25 * rnd.getInt(0, 4); break; 556 case gluShaderUtil.precision.PRECISION_MEDIUMP: pos[0] = rnd.getFloat(-1e3, 1e3); break; 557 case gluShaderUtil.precision.PRECISION_HIGHP: pos[0] = rnd.getFloat(-1e5, 1e5); break; 558 default: throw new Error('Unknown precision: ' + precision); 559 } 560 } else if (isInt) { 561 var pos = new Int32Array(buffer, offset, 1); 562 switch (precision) { 563 case gluShaderUtil.precision.PRECISION_LOWP: pos[0] = rnd.getInt(-128, 127); break; 564 case gluShaderUtil.precision.PRECISION_MEDIUMP: pos[0] = rnd.getInt(-32768, 32767); break; 565 case gluShaderUtil.precision.PRECISION_HIGHP: pos[0] = rnd.getInt(); break; 566 default: throw new Error('Unknown precision: ' + precision); 567 } 568 } else if (isUint) { 569 var pos = new Uint32Array(buffer, offset, 1); 570 switch (precision) { 571 case gluShaderUtil.precision.PRECISION_LOWP: pos[0] = rnd.getInt(0, 255); break; 572 case gluShaderUtil.precision.PRECISION_MEDIUMP: pos[0] = rnd.getInt(0, 65535); break; 573 case gluShaderUtil.precision.PRECISION_HIGHP: pos[0] = Math.abs(rnd.getInt()); break; 574 default: throw new Error('Unknown precision: ' + precision); 575 } 576 } 577 } 578 } 579 }; 580 581 /** 582 * @param {Array<es3fTransformFeedbackTests.Attribute>} attributes 583 * @param {number} numInputs 584 * @param {number} inputStride 585 * @param {deRandom.Random} rnd 586 * @return {ArrayBuffer} 587 */ 588 es3fTransformFeedbackTests.genInputData = function(attributes, numInputs, inputStride, rnd) { 589 var buffer = new ArrayBuffer(numInputs * inputStride); 590 591 var position = es3fTransformFeedbackTests.findAttributeNameEquals(attributes, 'a_position'); 592 if (!position) 593 throw new Error('Position attribute not found.'); 594 595 for (var ndx = 0; ndx < numInputs; ndx++) { 596 var pos = new Float32Array(buffer, position.offset + inputStride * ndx, 4); 597 pos[0] = rnd.getFloat(-1.2, 1.2); 598 pos[1] = rnd.getFloat(-1.2, 1.2); 599 pos[2] = rnd.getFloat(-1.2, 1.2); 600 pos[3] = rnd.getFloat(0.1, 2.0); 601 } 602 603 var pointSizePos = es3fTransformFeedbackTests.findAttributeNameEquals(attributes, 'a_pointSize'); 604 if (pointSizePos) { 605 for (var ndx = 0; ndx < numInputs; ndx++) { 606 var pos = new Float32Array(buffer, pointSizePos.offset + inputStride * ndx, 1); 607 pos[0] = rnd.getFloat(1, 8); 608 } 609 } 610 611 // Random data for rest of components. 612 for (var i = 0; i < attributes.length; i++) { 613 if (attributes[i].name != 'a_position' && attributes[i].name != 'a_pointSize') 614 es3fTransformFeedbackTests.genAttributeData(attributes[i], buffer, inputStride, numInputs, rnd); 615 } 616 617 return buffer; 618 }; 619 620 /** 621 * Returns the number of outputs with the es3fTransformFeedbackTests.count for the Primitives in the Transform Feedback. 622 * @param {gluDrawUtil.primitiveType} primitiveType GLenum that specifies what kind of primitive is 623 * @param {number} numElements 624 * @return {number} 625 */ 626 es3fTransformFeedbackTests.getTransformFeedbackOutputCount = function(primitiveType, numElements) { 627 628 switch (primitiveType) { 629 case gluDrawUtil.primitiveType.TRIANGLES: return numElements - numElements % 3; 630 case gluDrawUtil.primitiveType.TRIANGLE_STRIP: return Math.max(0, numElements - 2) * 3; 631 case gluDrawUtil.primitiveType.TRIANGLE_FAN: return Math.max(0, numElements - 2) * 3; 632 case gluDrawUtil.primitiveType.LINES: return numElements - numElements % 2; 633 case gluDrawUtil.primitiveType.LINE_STRIP: return Math.max(0, numElements - 1) * 2; 634 case gluDrawUtil.primitiveType.LINE_LOOP: return numElements > 1 ? numElements * 2 : 0; 635 case gluDrawUtil.primitiveType.POINTS: return numElements; 636 default: 637 throw new Error('Unrecognized primitiveType ' + primitiveType); 638 } 639 640 }; 641 642 /** 643 * Returns a number with the es3fTransformFeedbackTests.count for the Primitives in the Transform Feedback. 644 * @param {gluDrawUtil.primitiveType} primitiveType GLenum that specifies what kind of primitive is 645 * @param {number} numElements 646 * @return {number} 647 */ 648 es3fTransformFeedbackTests.getTransformFeedbackPrimitiveCount = function(primitiveType, numElements) { 649 650 switch (primitiveType) { 651 case gluDrawUtil.primitiveType.TRIANGLES: return Math.floor(numElements / 3); 652 case gluDrawUtil.primitiveType.TRIANGLE_STRIP: return Math.max(0, numElements - 2); 653 case gluDrawUtil.primitiveType.TRIANGLE_FAN: return Math.max(0, numElements - 2); 654 case gluDrawUtil.primitiveType.LINES: return Math.floor(numElements / 2); 655 case gluDrawUtil.primitiveType.LINE_STRIP: return Math.max(0, numElements - 1); 656 case gluDrawUtil.primitiveType.LINE_LOOP: return numElements > 1 ? numElements : 0; 657 case gluDrawUtil.primitiveType.POINTS: return numElements; 658 default: 659 throw new Error('Unrecognized primitiveType ' + primitiveType); 660 } 661 662 }; 663 664 /** 665 * Returns the type of Primitive Mode: Triangles for all Triangle Primitive's type and same for Line and Points. 666 * @param {gluDrawUtil.primitiveType} primitiveType GLenum that specifies what kind of primitive is 667 * @return {number} primitiveType 668 */ 669 es3fTransformFeedbackTests.getTransformFeedbackPrimitiveMode = function(primitiveType) { 670 671 switch (primitiveType) { 672 case gluDrawUtil.primitiveType.TRIANGLES: 673 case gluDrawUtil.primitiveType.TRIANGLE_STRIP: 674 case gluDrawUtil.primitiveType.TRIANGLE_FAN: 675 return gl.TRIANGLES; 676 677 case gluDrawUtil.primitiveType.LINES: 678 case gluDrawUtil.primitiveType.LINE_STRIP: 679 case gluDrawUtil.primitiveType.LINE_LOOP: 680 return gl.LINES; 681 682 case gluDrawUtil.primitiveType.POINTS: 683 return gl.POINTS; 684 685 default: 686 throw new Error('Unrecognized primitiveType ' + primitiveType); 687 } 688 689 }; 690 691 /** 692 * Returns the attribute index for a certain primitive type. 693 * @param {gluDrawUtil.primitiveType} primitiveType GLenum that specifies what kind of primitive is 694 * @param {number} numInputs 695 * @param {number} outNdx 696 * @return {number} 697 */ 698 es3fTransformFeedbackTests.getAttributeIndex = function(primitiveType, numInputs, outNdx) { 699 700 switch (primitiveType) { 701 702 case gluDrawUtil.primitiveType.TRIANGLES: return outNdx; 703 case gluDrawUtil.primitiveType.LINES: return outNdx; 704 case gluDrawUtil.primitiveType.POINTS: return outNdx; 705 706 case gluDrawUtil.primitiveType.TRIANGLE_STRIP: { 707 /** @type {number} */ var triNdx = outNdx / 3; 708 /** @type {number} */ var vtxNdx = outNdx % 3; 709 return (triNdx % 2 != 0 && vtxNdx < 2) ? (triNdx + 1 - vtxNdx) : (triNdx + vtxNdx); 710 } 711 712 case gluDrawUtil.primitiveType.TRIANGLE_FAN: 713 return (outNdx % 3 != 0) ? (outNdx / 3 + outNdx % 3) : 0; 714 715 case gluDrawUtil.primitiveType.LINE_STRIP: 716 return outNdx / 2 + outNdx % 2; 717 718 case gluDrawUtil.primitiveType.LINE_LOOP: { 719 var inNdx = outNdx / 2 + outNdx % 2; 720 return inNdx < numInputs ? inNdx : 0; 721 } 722 723 default: 724 throw new Error('Unrecognized primitiveType ' + primitiveType); 725 } 726 727 }; 728 729 /** 730 * @param {gluDrawUtil.primitiveType} primitiveType type number in gluDrawUtil.primitiveType 731 * @param {es3fTransformFeedbackTests.Output} output 732 * @param {number} numInputs 733 * @param {Object} buffers 734 * @return {boolean} isOk 735 */ 736 es3fTransformFeedbackTests.compareTransformFeedbackOutput = function(primitiveType, output, numInputs, buffers) { 737 /** @type {boolean} */ var isOk = true; 738 /** @type {number} */ var outOffset = output.offset; 739 740 for (var attrNdx = 0; attrNdx < output.inputs.length; attrNdx++) { 741 /** @type {es3fTransformFeedbackTests.Attribute} */ var attribute = output.inputs[attrNdx]; 742 /** @type {gluShaderUtil.DataType} */ var type = attribute.type.getBasicType(); 743 /** @type {number} */ var numComponents = gluShaderUtil.getDataTypeScalarSize(type); 744 745 /** @type {gluShaderUtil.precision} */ var precision = attribute.type.getPrecision(); 746 747 /** @type {string} */ var scalarType = gluShaderUtil.getDataTypeScalarType(type); 748 /** @type {number} */ var numOutputs = es3fTransformFeedbackTests.getTransformFeedbackOutputCount(primitiveType, numInputs); 749 750 for (var outNdx = 0; outNdx < numOutputs; outNdx++) { 751 /** @type {number} */ var inNdx = es3fTransformFeedbackTests.getAttributeIndex(primitiveType, numInputs, outNdx); 752 753 for (var compNdx = 0; compNdx < numComponents; compNdx++) { 754 /** @type {boolean} */ var isEqual = false; 755 756 if (scalarType === 'float') { 757 var outBuffer = new Float32Array(buffers.output.buffer, buffers.output.offset + buffers.output.stride * outNdx + outOffset + compNdx * 4, 1); 758 var inBuffer = new Float32Array(buffers.input.buffer, buffers.input.offset + buffers.input.stride * inNdx + attribute.offset + compNdx * 4, 1); 759 var difInOut = inBuffer[0] - outBuffer[0]; 760 /* TODO: Original code used ULP comparison for highp and mediump precision. This could cause failures. */ 761 switch (precision) { 762 case gluShaderUtil.precision.PRECISION_HIGHP: { 763 isEqual = Math.abs(difInOut) < 0.1; 764 break; 765 } 766 767 case gluShaderUtil.precision.PRECISION_MEDIUMP: { 768 isEqual = Math.abs(difInOut) < 0.1; 769 break; 770 } 771 772 case gluShaderUtil.precision.PRECISION_LOWP: { 773 isEqual = Math.abs(difInOut) < 0.1; 774 break; 775 } 776 default: 777 throw new Error('Unknown precision: ' + precision); 778 } 779 } else { 780 var outBuffer = new Uint32Array(buffers.output.buffer, buffers.output.offset + buffers.output.stride * outNdx + outOffset + compNdx * 4, 1); 781 var inBuffer = new Uint32Array(buffers.input.buffer, buffers.input.offset + buffers.input.stride * inNdx + attribute.offset + compNdx * 4, 1); 782 isEqual = (inBuffer[0] == outBuffer[0]); // Bit-exact match required for integer types. 783 } 784 785 if (!isEqual) { 786 bufferedLogToConsole('Mismatch in ' + output.name + ' (' + attribute.name + '), output = ' + outNdx + ', input = ' + inNdx + ', component = ' + compNdx); 787 isOk = false; 788 break; 789 } 790 } 791 792 if (!isOk) 793 break; 794 } 795 796 if (!isOk) 797 break; 798 799 outOffset += numComponents * 4; /*sizeof(deUint32)*/ 800 } 801 802 return isOk; 803 }; 804 805 /** 806 * Returns (for all the draw calls) the type of Primitive Mode, as it calls "es3fTransformFeedbackTests.getTransformFeedbackPrimitiveCount". 807 * @param {gluDrawUtil.primitiveType} primitiveType GLenum that specifies what kind of primitive is 808 * @param {Array<es3fTransformFeedbackTests.DrawCall>} array Object.<number, boolean> 809 * @return {number} primCount 810 */ 811 es3fTransformFeedbackTests.computeTransformFeedbackPrimitiveCount = function(primitiveType, array) { 812 813 /** @type {number} */ var primCount = 0; 814 815 for (var i = 0; i < array.length; ++ i) { 816 817 if (array[i].transformFeedbackEnabled) 818 primCount += es3fTransformFeedbackTests.getTransformFeedbackPrimitiveCount(primitiveType, array[i].numElements); 819 } 820 821 return primCount; 822 }; 823 824 /** 825 * @param {number} target 826 * @param {number} bufferSize 827 * @param {number} guardSize 828 */ 829 es3fTransformFeedbackTests.writeBufferGuard = function(target, bufferSize, guardSize) { 830 var buffer = new ArrayBuffer(guardSize); 831 var view = new Uint8Array(buffer); 832 for (var i = 0; i < guardSize; ++i) view[i] = 0xcd; 833 gl.bufferSubData(target, bufferSize, buffer); 834 }; 835 836 /** 837 * Verifies guard 838 * @param {ArrayBuffer} buffer 839 * @param {number} start 840 * @return {boolean} 841 */ 842 es3fTransformFeedbackTests.verifyGuard = function(buffer, start) { 843 start = start || 0; 844 var view = new Uint8Array(buffer, start); 845 for (var i = 0; i < view.length; i++) { 846 if (view[i] != 0xcd) 847 return false; 848 } 849 return true; 850 }; 851 852 /** 853 * @extends {tcuTestCase.DeqpTest} 854 * @param {string} name 855 * @param {string} desc 856 * @param {number} bufferMode 857 * @param {gluDrawUtil.primitiveType} primitiveType GLenum that specifies what kind of primitive is 858 * @constructor 859 */ 860 es3fTransformFeedbackTests.TransformFeedbackCase = function(name, desc, bufferMode, primitiveType) { 861 tcuTestCase.DeqpTest.call(this, name, desc); 862 this.m_bufferMode = bufferMode; 863 this.m_primitiveType = primitiveType; 864 this.m_progSpec = new es3fTransformFeedbackTests.ProgramSpec(); 865 866 // Derived from es3fTransformFeedbackTests.ProgramSpec in es3fTransformFeedbackTests.init() 867 this.m_inputStride = 0; 868 this.m_attributes = []; // vector<es3fTransformFeedbackTests.Attribute> 869 this.m_transformFeedbackOutputs = []; // vector<es3fTransformFeedbackTests.Output> 870 this.m_bufferStrides = []; // vector<int> 871 872 // GL state. 873 this.m_program = null; // glu::ShaderProgram 874 this.m_transformFeedback = null; // glu::TransformFeedback 875 this.m_outputBuffers = []; // vector<deUint32> 876 877 this.m_iterNdx = 0; // int 878 this.m_testPassed = true; 879 // State machine 880 this.m_state = es3fTransformFeedbackTests.State.DRAW; 881 this.m_verifyStart = null; 882 883 this.m_frameWithTf = null; 884 this.m_frameWithoutTf = null; 885 886 this.m_viewportW = 0; 887 this.m_viewportH = 0; 888 this.m_viewportX = 0; 889 this.m_viewportY = 0; 890 891 this.m_primitiveQuery = null; 892 this.m_outputsOk = true; 893 894 }; 895 896 setParentClass(es3fTransformFeedbackTests.TransformFeedbackCase, tcuTestCase.DeqpTest); 897 898 es3fTransformFeedbackTests.TransformFeedbackCase.prototype.createVerificationResult = function(retry, result) { 899 return { retry: retry, result: result }; 900 } 901 902 es3fTransformFeedbackTests.TransformFeedbackCase.prototype.dumpShaderText = function() { 903 var dbgext = gl.getExtension('WEBGL_debug_shaders'); 904 for (var ii = 0; ii < this.m_program.shaders.length; ++ii) { 905 debug('Shader source ' + ii + ' before translation:') 906 debug(this.m_program.shaders[ii].info.source); 907 debug(''); 908 debug('Shader source ' + ii + ' after translation:'); 909 debug(dbgext.getTranslatedShaderSource(this.m_program.shaders[ii].shader)); 910 } 911 }; 912 913 es3fTransformFeedbackTests.TransformFeedbackCase.prototype.init = function() { 914 this.m_program = es3fTransformFeedbackTests.createVertexCaptureProgram( 915 this.m_progSpec, 916 this.m_bufferMode, 917 this.m_primitiveType 918 ); 919 920 if (!this.m_program.isOk()) { 921 // this.dumpShaderText(); 922 923 var linkFail = this.m_program.shadersOK && 924 !this.m_program.getProgramInfo().linkOk; 925 926 if (linkFail) { 927 if (!es3fTransformFeedbackTests.isProgramSupported(this.m_progSpec, this.m_bufferMode)) { 928 var msg = 'Not Supported. Implementation limits exceeded.'; 929 checkMessage(false, msg); 930 throw new TestFailedException(msg); 931 } else if (es3fTransformFeedbackTests.hasArraysInTFVaryings(this.m_progSpec)) { 932 msg = 'Capturing arrays is not supported (undefined in specification)'; 933 checkMessage(false, msg); 934 throw new TestFailedException(msg); 935 } else { 936 throw new Error('Link failed: ' + this.m_program.getProgramInfo().infoLog); 937 } 938 } else { 939 throw new Error('Compile failed'); 940 } 941 } else { 942 // debug('Program is ' + 943 // (gl.getProgramParameter(this.m_program.getProgram(), gl.LINK_STATUS) ? 'linked' : 'not linked')); 944 // this.dumpShaderText(); 945 } 946 947 // bufferedLogToConsole('Transform feedback varyings: ' + tcu.formatArray(this.m_progSpec.getTransformFeedbackVaryings())); 948 bufferedLogToConsole('Transform feedback varyings: ' + this.m_progSpec.getTransformFeedbackVaryings()); 949 950 // Print out transform feedback points reported by GL. 951 // bufferedLogToConsole('Transform feedback varyings reported by compiler:'); 952 //logTransformFeedbackVaryings(log, gl, this.m_program.getProgram()); 953 954 // Compute input specification. 955 this.m_inputStride = es3fTransformFeedbackTests.computeInputLayout(this.m_attributes, this.m_progSpec.getVaryings(), this.m_progSpec.isPointSizeUsed()); 956 957 // Build list of varyings used in transform feedback. 958 es3fTransformFeedbackTests.computeTransformFeedbackOutputs( 959 this.m_transformFeedbackOutputs, 960 this.m_attributes, 961 this.m_progSpec.getVaryings(), 962 this.m_progSpec.getTransformFeedbackVaryings(), 963 this.m_bufferMode 964 ); 965 if (!this.m_transformFeedbackOutputs.length) { 966 throw new Error('transformFeedbackOutputs cannot be empty.'); 967 } 968 969 if (this.m_bufferMode == gl.SEPARATE_ATTRIBS) { 970 for (var i = 0; i < this.m_transformFeedbackOutputs.length; ++i) { 971 this.m_bufferStrides.push(this.m_transformFeedbackOutputs[i].type.getScalarSize() * 4 /*sizeof(deUint32)*/); 972 } 973 } else { 974 var totalSize = 0; 975 for (var i = 0; i < this.m_transformFeedbackOutputs.length; ++i) { 976 totalSize += this.m_transformFeedbackOutputs[i].type.getScalarSize() * 4 /*sizeof(deUint32)*/; 977 } 978 this.m_bufferStrides.push(totalSize); 979 } 980 981 this.m_outputBuffers.length = this.m_bufferStrides.length; 982 for (var i = 0; i < this.m_outputBuffers.length; i++) 983 this.m_outputBuffers[i] = gl.createBuffer(); 984 985 this.m_transformFeedback = gl.createTransformFeedback(); 986 987 this.m_iterNdx = 0; 988 // this.m_testCtx.setTestResult(QP_TEST_RESULT_PASS, 'Pass'); 989 990 }; 991 992 es3fTransformFeedbackTests.TransformFeedbackCase.prototype.deinit = function() { 993 for (var i = 0; i < this.m_outputBuffers.length; i++) 994 gl.deleteBuffer(this.m_outputBuffers[i]); 995 996 // delete this.m_transformFeedback; 997 this.m_transformFeedback = null; 998 999 // delete this.m_program; 1000 this.m_program = null; 1001 1002 // Clean up state. 1003 this.m_attributes = []; 1004 this.m_transformFeedbackOutputs = []; 1005 this.m_bufferStrides = []; 1006 this.m_inputStride = 0; 1007 1008 }; 1009 1010 es3fTransformFeedbackTests.TransformFeedbackCase.prototype.iterate = function() { 1011 var s = es3fTransformFeedbackTests.TransformFeedbackCase.s_iterate; 1012 var numIterations = s.iterations.length; 1013 var seed = deMath.deMathHash(this.m_iterNdx); 1014 switch(this.m_state) { 1015 case es3fTransformFeedbackTests.State.DRAW: 1016 bufferedLogToConsole('Testing ' + 1017 s.testCases[s.iterations[this.m_iterNdx]].length + 1018 ' draw calls, (element es3fTransformFeedbackTests.count, TF state): ' + 1019 s.testCases[s.iterations[this.m_iterNdx]] 1020 ); 1021 this.draw(s.testCases[s.iterations[this.m_iterNdx]], seed); 1022 this.m_state = es3fTransformFeedbackTests.State.VERIFY; 1023 break; 1024 case es3fTransformFeedbackTests.State.VERIFY: 1025 var verifyResult = this.verify(s.testCases[s.iterations[this.m_iterNdx]]); 1026 if (verifyResult.retry) { 1027 break; 1028 } 1029 this.m_testPassed = verifyResult.result; 1030 this.m_iterNdx += 1; 1031 if (this.m_testPassed && this.m_iterNdx < numIterations) { 1032 this.m_state = es3fTransformFeedbackTests.State.DRAW; 1033 break; 1034 } 1035 // Fall through 1036 case es3fTransformFeedbackTests.State.FINISH: 1037 if (!this.m_testPassed) testFailedOptions('Result comparison failed for iteration ' + s.iterations[this.m_iterNdx - 1], false); 1038 else testPassedOptions('Result comparison succeeded', true); 1039 return tcuTestCase.IterateResult.STOP; 1040 } 1041 1042 return tcuTestCase.IterateResult.CONTINUE; 1043 1044 }; 1045 1046 es3fTransformFeedbackTests.TransformFeedbackCase.prototype.draw = function(calls, seed) { 1047 var _min = function(x, y) { return x < y ? x : y; }; 1048 1049 var rnd = new deRandom.Random(seed); 1050 var numInputs = 0; 1051 var numOutputs = 0; 1052 var width = gl.drawingBufferWidth; 1053 var height = gl.drawingBufferHeight; 1054 this.m_viewportW = _min(es3fTransformFeedbackTests.VIEWPORT_WIDTH, width); 1055 this.m_viewportH = _min(es3fTransformFeedbackTests.VIEWPORT_HEIGHT, height); 1056 this.m_viewportX = rnd.getInt(0, width - this.m_viewportW); 1057 this.m_viewportY = rnd.getInt(0, height - this.m_viewportH); 1058 this.m_frameWithTf = new tcuSurface.Surface(this.m_viewportW, this.m_viewportH); // tcu::Surface 1059 this.m_frameWithoutTf = new tcuSurface.Surface(this.m_viewportW, this.m_viewportH); // tcu::Surface 1060 this.m_primitiveQuery = gl.createQuery(); 1061 this.m_outputsOk = true; 1062 1063 // Compute totals. 1064 for (var i = 0; i < calls.length; ++i) { 1065 var call = calls[i]; 1066 numInputs += call.numElements; 1067 numOutputs += call.transformFeedbackEnabled ? es3fTransformFeedbackTests.getTransformFeedbackOutputCount(this.m_primitiveType, call.numElements) : 0; 1068 } 1069 1070 // Input data. 1071 var inputData = es3fTransformFeedbackTests.genInputData(this.m_attributes, numInputs, this.m_inputStride, rnd); 1072 1073 gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, this.m_transformFeedback); 1074 1075 // Allocate storage for transform feedback output buffers and bind to targets. 1076 for (var bufNdx = 0; bufNdx < this.m_outputBuffers.length; ++bufNdx) { 1077 var buffer = this.m_outputBuffers[bufNdx]; // deUint32 1078 var stride = this.m_bufferStrides[bufNdx]; // int 1079 var target = bufNdx; // int 1080 var size = stride * numOutputs; // int 1081 var guardSize = stride * es3fTransformFeedbackTests.BUFFER_GUARD_MULTIPLIER; // int 1082 var usage = gl.DYNAMIC_READ; // const deUint32 1083 1084 gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, buffer); 1085 gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, size + guardSize, usage); 1086 es3fTransformFeedbackTests.writeBufferGuard(gl.TRANSFORM_FEEDBACK_BUFFER, size, guardSize); 1087 1088 // \todo [2012-07-30 pyry] glBindBufferRange()? 1089 gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, target, buffer); 1090 } 1091 1092 var attribBuffer = gl.createBuffer(); 1093 gl.bindBuffer(gl.ARRAY_BUFFER, attribBuffer); 1094 gl.bufferData(gl.ARRAY_BUFFER, inputData, gl.STATIC_DRAW); 1095 1096 // Setup attributes. 1097 for (var i = 0; i < this.m_attributes.length; ++i) { 1098 var attrib = this.m_attributes[i]; 1099 var loc = gl.getAttribLocation(this.m_program.getProgram(), attrib.name); 1100 /** @type {string} */ 1101 var scalarType = gluShaderUtil.getDataTypeScalarType(attrib.type.getBasicType()); 1102 /** @type {number} */ 1103 var numComponents = gluShaderUtil.getDataTypeScalarSize(attrib.type.getBasicType()); 1104 1105 if (loc >= 0) { 1106 gl.enableVertexAttribArray(loc); 1107 switch (scalarType) { 1108 case 'float': 1109 gl.vertexAttribPointer(loc, numComponents, gl.FLOAT, false, this.m_inputStride, attrib.offset); break; 1110 case 'int': 1111 gl.vertexAttribIPointer(loc, numComponents, gl.INT, this.m_inputStride, attrib.offset); break; 1112 case 'uint': 1113 gl.vertexAttribIPointer(loc, numComponents, gl.UNSIGNED_INT, this.m_inputStride, attrib.offset); break; 1114 } 1115 } 1116 } 1117 1118 // Setup viewport. 1119 gl.viewport(this.m_viewportX, this.m_viewportY, this.m_viewportW, this.m_viewportH); 1120 1121 // Setup program. 1122 gl.useProgram(this.m_program.getProgram()); 1123 1124 gl.uniform4fv( 1125 gl.getUniformLocation(this.m_program.getProgram(), 'u_scale'), 1126 [0.01, 0.01, 0.01, 0.01] 1127 ); 1128 gl.uniform4fv( 1129 gl.getUniformLocation(this.m_program.getProgram(), 'u_bias'), 1130 [0.5, 0.5, 0.5, 0.5] 1131 ); 1132 1133 // Enable query. 1134 gl.beginQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, this.m_primitiveQuery); 1135 1136 // Draw 1137 var offset = 0; 1138 var tfEnabled = true; 1139 1140 gl.clear(gl.COLOR_BUFFER_BIT); 1141 1142 var tfPrimitiveMode = es3fTransformFeedbackTests.getTransformFeedbackPrimitiveMode(this.m_primitiveType); 1143 gl.beginTransformFeedback(tfPrimitiveMode); 1144 1145 for (var i = 0; i < calls.length; ++i) { 1146 var call = calls[i]; 1147 1148 // Pause or resume transform feedback if necessary. 1149 if (call.transformFeedbackEnabled != tfEnabled) { 1150 if (call.transformFeedbackEnabled) 1151 gl.resumeTransformFeedback(); 1152 else 1153 gl.pauseTransformFeedback(); 1154 tfEnabled = call.transformFeedbackEnabled; 1155 } 1156 1157 gl.drawArrays(gluDrawUtil.getPrimitiveGLType(gl, this.m_primitiveType), offset, call.numElements); 1158 offset += call.numElements; 1159 } 1160 1161 // Resume feedback before finishing it. 1162 if (!tfEnabled) 1163 gl.resumeTransformFeedback(); 1164 1165 gl.endTransformFeedback(); 1166 1167 gl.endQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN); 1168 1169 // Check and log query status right after submit 1170 var query = this.m_primitiveQuery; 1171 1172 var available = gl.getQueryParameter(query, gl.QUERY_RESULT_AVAILABLE); 1173 1174 if (available) { 1175 this.m_testPassed = false; 1176 this.m_state = es3fTransformFeedbackTests.State.FINISH; 1177 testFailedOptions('Transform feedback query result must not be available the same frame as they are issued.', true); 1178 } 1179 1180 // Compare result buffers. 1181 for (var bufferNdx = 0; bufferNdx < this.m_outputBuffers.length; ++bufferNdx) { 1182 var stride = this.m_bufferStrides[bufferNdx]; // int 1183 var size = stride * numOutputs; // int 1184 var guardSize = stride * es3fTransformFeedbackTests.BUFFER_GUARD_MULTIPLIER; // int 1185 var buffer = new ArrayBuffer(size + guardSize); // const void* 1186 1187 // Bind buffer for reading. 1188 gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, this.m_outputBuffers[bufferNdx]); 1189 1190 gl.getBufferSubData(gl.TRANSFORM_FEEDBACK_BUFFER, 0, new Uint8Array(buffer)); 1191 1192 // Verify all output variables that are written to this buffer. 1193 for (var i = 0; i < this.m_transformFeedbackOutputs.length; ++i) { 1194 var out = this.m_transformFeedbackOutputs[i]; 1195 1196 if (out.bufferNdx != bufferNdx) 1197 continue; 1198 1199 var inputOffset = 0; 1200 var outputOffset = 0; 1201 1202 // Process all draw calls and check ones with transform feedback enabled 1203 for (var callNdx = 0; callNdx < calls.length; ++callNdx) { 1204 var call = calls[callNdx]; 1205 1206 if (call.transformFeedbackEnabled) { 1207 var inputPtr = inputData[0] + inputOffset * this.m_inputStride; // const deUint8* 1208 var outputPtr = outputOffset * stride; // const deUint8* 1209 1210 if (!es3fTransformFeedbackTests.compareTransformFeedbackOutput(this.m_primitiveType, out, call.numElements, { 1211 input: { 1212 buffer: inputData, 1213 offset: inputOffset * this.m_inputStride, 1214 stride: this.m_inputStride 1215 }, 1216 output: { 1217 buffer: buffer, 1218 offset: outputOffset * stride, 1219 stride: stride 1220 } 1221 })) { 1222 this.m_outputsOk = false; 1223 break; 1224 } 1225 } 1226 1227 inputOffset += call.numElements; 1228 outputOffset += call.transformFeedbackEnabled ? es3fTransformFeedbackTests.getTransformFeedbackOutputCount(this.m_primitiveType, call.numElements) : 0; 1229 } 1230 } 1231 1232 // Verify guardband. 1233 if (!es3fTransformFeedbackTests.verifyGuard(buffer, size)) { 1234 bufferedLogToConsole('Error: Transform feedback buffer overrun detected'); 1235 this.m_outputsOk = false; 1236 } 1237 } 1238 }; 1239 1240 es3fTransformFeedbackTests.TransformFeedbackCase.prototype.verify = function(calls) { 1241 // Check status after mapping buffers. 1242 var mustBeReady = this.m_outputBuffers.length > 0; // Mapping buffer forces synchronization. // const bool 1243 var expectedCount = es3fTransformFeedbackTests.computeTransformFeedbackPrimitiveCount(this.m_primitiveType, calls); // const int 1244 var available = /** @type {boolean} */ (gl.getQueryParameter(this.m_primitiveQuery, gl.QUERY_RESULT_AVAILABLE)); 1245 var verify_offset = 0; 1246 var queryOk = true; 1247 if (!available) { 1248 if (!this.m_verifyStart) 1249 this.m_verifyStart = new Date(); 1250 else { 1251 var current = new Date(); 1252 var elapsedTime = 0.001 * (current.getTime() - this.m_verifyStart.getTime()); 1253 if (elapsedTime > es3fTransformFeedbackTests.MAX_VERIFY_WAIT) { 1254 testFailed('Query result not available after ' + elapsedTime + ' seconds.'); 1255 this.m_state = es3fTransformFeedbackTests.State.FINISH; 1256 return this.createVerificationResult(false, false); 1257 } 1258 } 1259 return this.createVerificationResult(true, false); 1260 } 1261 1262 var numPrimitives = /** @type {number} */ (gl.getQueryParameter(this.m_primitiveQuery, gl.QUERY_RESULT)); 1263 1264 if (!mustBeReady && available == false) 1265 bufferedLogToConsole('ERROR: gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN result not available after mapping buffers!'); 1266 1267 bufferedLogToConsole('gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN = ' + numPrimitives); 1268 1269 if (numPrimitives != expectedCount) { 1270 queryOk = false; 1271 bufferedLogToConsole('ERROR: Expected ' + expectedCount + ' primitives!'); 1272 } 1273 1274 // Clear transform feedback state. 1275 gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null); 1276 for (var bufNdx = 0; bufNdx < this.m_outputBuffers.length; ++bufNdx) { 1277 gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, null); 1278 gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, bufNdx, null); 1279 } 1280 1281 gl.bindBuffer(gl.ARRAY_BUFFER, null); 1282 1283 // Read back rendered image. 1284 this.m_frameWithTf.readViewport(gl, [this.m_viewportX, this.m_viewportY, this.m_viewportW, this.m_viewportH]); 1285 1286 // Render without transform feedback. 1287 1288 gl.clear(gl.COLOR_BUFFER_BIT); 1289 1290 for (var i = 0; i < calls.length; ++i) { 1291 var call = calls[i]; 1292 gl.drawArrays(gluDrawUtil.getPrimitiveGLType(gl, this.m_primitiveType), verify_offset, call.numElements); 1293 verify_offset += call.numElements; 1294 } 1295 this.m_frameWithoutTf.readViewport(gl, [this.m_viewportX, this.m_viewportY, this.m_viewportW, this.m_viewportH]); 1296 1297 // Compare images with and without transform feedback. 1298 var imagesOk = tcuImageCompare.pixelThresholdCompare('Result', 'Image comparison result', this.m_frameWithoutTf, this.m_frameWithTf, [1, 1, 1, 1], tcuImageCompare.CompareLogMode.ON_ERROR); 1299 1300 if (imagesOk) 1301 bufferedLogToConsole('Rendering result comparison between TF enabled and TF disabled passed.'); 1302 else 1303 bufferedLogToConsole('ERROR: Rendering result comparison between TF enabled and TF disabled failed!'); 1304 1305 return this.createVerificationResult(false, this.m_outputsOk && imagesOk && queryOk); 1306 1307 }; 1308 1309 es3fTransformFeedbackTests.dc = function(numElements, tfEnabled) { 1310 return new es3fTransformFeedbackTests.DrawCall(numElements, tfEnabled); 1311 }; 1312 1313 // static data 1314 es3fTransformFeedbackTests.TransformFeedbackCase.s_iterate = { 1315 1316 testCases: { 1317 elemCount1: [es3fTransformFeedbackTests.dc(1, true)], 1318 elemCount2: [es3fTransformFeedbackTests.dc(2, true)], 1319 elemCount3: [es3fTransformFeedbackTests.dc(3, true)], 1320 elemCount4: [es3fTransformFeedbackTests.dc(4, true)], 1321 elemCount123: [es3fTransformFeedbackTests.dc(123, true)], 1322 basicPause1: [es3fTransformFeedbackTests.dc(64, true), es3fTransformFeedbackTests.dc(64, false), es3fTransformFeedbackTests.dc(64, true)], 1323 basicPause2: [es3fTransformFeedbackTests.dc(13, true), es3fTransformFeedbackTests.dc(5, true), es3fTransformFeedbackTests.dc(17, false), 1324 es3fTransformFeedbackTests.dc(3, true), es3fTransformFeedbackTests.dc(7, false)], 1325 startPaused: [es3fTransformFeedbackTests.dc(123, false), es3fTransformFeedbackTests.dc(123, true)], 1326 random1: [es3fTransformFeedbackTests.dc(65, true), es3fTransformFeedbackTests.dc(135, false), es3fTransformFeedbackTests.dc(74, true), 1327 es3fTransformFeedbackTests.dc(16, false), es3fTransformFeedbackTests.dc(226, false), es3fTransformFeedbackTests.dc(9, true), 1328 es3fTransformFeedbackTests.dc(174, false)], 1329 random2: [es3fTransformFeedbackTests.dc(217, true), es3fTransformFeedbackTests.dc(171, true), es3fTransformFeedbackTests.dc(147, true), 1330 es3fTransformFeedbackTests.dc(152, false), es3fTransformFeedbackTests.dc(55, true)] 1331 }, 1332 iterations: [ 1333 'elemCount1', 'elemCount2', 'elemCount3', 'elemCount4', 'elemCount123', 1334 'basicPause1', 'basicPause2', 'startPaused', 1335 'random1', 'random2' 1336 ] 1337 }; 1338 1339 es3fTransformFeedbackTests.hasArraysInTFVaryings = function(spec) { 1340 1341 for (var i = 0; i < spec.getTransformFeedbackVaryings().length; ++i) { 1342 var tfVar = spec.getTransformFeedbackVaryings()[i]; 1343 var varName = gluVarTypeUtil.parseVariableName(tfVar); 1344 1345 var attr = es3fTransformFeedbackTests.findAttributeNameEquals(spec.getVaryings(), varName); 1346 if (attr && attr.type.isArrayType()) 1347 return true; 1348 } 1349 return false; 1350 1351 }; 1352 1353 /** es3fTransformFeedbackTests.PositionCase 1354 * @extends {es3fTransformFeedbackTests.TransformFeedbackCase} 1355 * @param {string} name 1356 * @param {string} desc 1357 * @param {number} bufferMode 1358 * @param {gluDrawUtil.primitiveType} primitiveType GLenum that specifies what kind of primitive is 1359 * @constructor 1360 */ 1361 es3fTransformFeedbackTests.PositionCase = function(name, desc, bufferMode, primitiveType) { 1362 es3fTransformFeedbackTests.TransformFeedbackCase.call(this, name, desc, bufferMode, primitiveType); 1363 this.m_progSpec.addTransformFeedbackVarying('gl_Position'); 1364 }; 1365 1366 setParentClass(es3fTransformFeedbackTests.PositionCase, es3fTransformFeedbackTests.TransformFeedbackCase); 1367 1368 /** es3fTransformFeedbackTests.PointSizeCase 1369 * @extends {es3fTransformFeedbackTests.TransformFeedbackCase} 1370 * @param {string} name 1371 * @param {string} desc 1372 * @param {number} bufferMode 1373 * @param {gluDrawUtil.primitiveType} primitiveType GLenum that specifies what kind of primitive is 1374 * @constructor 1375 */ 1376 es3fTransformFeedbackTests.PointSizeCase = function(name, desc, bufferMode, primitiveType) { 1377 es3fTransformFeedbackTests.TransformFeedbackCase.call(this, name, desc, bufferMode, primitiveType); 1378 this.m_progSpec.addTransformFeedbackVarying('gl_PointSize'); 1379 1380 }; 1381 1382 setParentClass(es3fTransformFeedbackTests.PointSizeCase, es3fTransformFeedbackTests.TransformFeedbackCase); 1383 1384 /** es3fTransformFeedbackTests.BasicTypeCase 1385 * @extends {es3fTransformFeedbackTests.TransformFeedbackCase} 1386 * @param {string} name 1387 * @param {string} desc 1388 * @param {number} bufferMode 1389 * @param {gluDrawUtil.primitiveType} primitiveType GLenum that specifies what kind of primitive is 1390 * @param {gluShaderUtil.DataType} type 1391 * @param {gluShaderUtil.precision} precision 1392 * @param {es3fTransformFeedbackTests.interpolation} interpolation enum number in this javascript 1393 * @constructor 1394 */ 1395 es3fTransformFeedbackTests.BasicTypeCase = function(name, desc, bufferMode, primitiveType, type, precision, interpolation) { 1396 es3fTransformFeedbackTests.TransformFeedbackCase.call(this, name, desc, bufferMode, primitiveType); 1397 1398 this.m_progSpec.addVarying('v_varA', gluVarType.newTypeBasic(type, precision), interpolation); 1399 this.m_progSpec.addVarying('v_varB', gluVarType.newTypeBasic(type, precision), interpolation); 1400 1401 this.m_progSpec.addTransformFeedbackVarying('v_varA'); 1402 this.m_progSpec.addTransformFeedbackVarying('v_varB'); 1403 1404 }; 1405 1406 setParentClass(es3fTransformFeedbackTests.BasicTypeCase, es3fTransformFeedbackTests.TransformFeedbackCase); 1407 1408 /** es3fTransformFeedbackTests.BasicArrayCase 1409 * @extends {es3fTransformFeedbackTests.TransformFeedbackCase} 1410 * @param {string} name 1411 * @param {string} desc 1412 * @param {number} bufferMode 1413 * @param {gluDrawUtil.primitiveType} primitiveType GLenum that specifies what kind of primitive is 1414 * @param {gluShaderUtil.DataType} type 1415 * @param {gluShaderUtil.precision} precision 1416 * @param {es3fTransformFeedbackTests.interpolation} interpolation enum number in this javascript 1417 * @constructor 1418 */ 1419 es3fTransformFeedbackTests.BasicArrayCase = function(name, desc, bufferMode, primitiveType, type, precision, interpolation) { 1420 es3fTransformFeedbackTests.TransformFeedbackCase.call(this, name, desc, bufferMode, primitiveType); 1421 1422 if (gluShaderUtil.isDataTypeMatrix(type) || this.m_bufferMode === gl.SEPARATE_ATTRIBS) { 1423 // note For matrix types we need to use reduced array sizes or otherwise we will exceed maximum attribute (16) 1424 // or transform feedback component es3fTransformFeedbackTests.count (64). 1425 // On separate attribs mode maximum component es3fTransformFeedbackTests.count per varying is 4. 1426 this.m_progSpec.addVarying('v_varA', gluVarType.newTypeArray(gluVarType.newTypeBasic(type, precision), 1), interpolation); 1427 this.m_progSpec.addVarying('v_varB', gluVarType.newTypeArray(gluVarType.newTypeBasic(type, precision), 2), interpolation); 1428 } else { 1429 this.m_progSpec.addVarying('v_varA', gluVarType.newTypeArray(gluVarType.newTypeBasic(type, precision), 3), interpolation); 1430 this.m_progSpec.addVarying('v_varB', gluVarType.newTypeArray(gluVarType.newTypeBasic(type, precision), 4), interpolation); 1431 } 1432 1433 this.m_progSpec.addTransformFeedbackVarying('v_varA'); 1434 this.m_progSpec.addTransformFeedbackVarying('v_varB'); 1435 1436 }; 1437 1438 setParentClass(es3fTransformFeedbackTests.BasicArrayCase, es3fTransformFeedbackTests.TransformFeedbackCase); 1439 1440 /** es3fTransformFeedbackTests.ArrayElementCase 1441 * @extends {es3fTransformFeedbackTests.TransformFeedbackCase} 1442 * @param {string} name 1443 * @param {string} desc 1444 * @param {number} bufferMode 1445 * @param {gluDrawUtil.primitiveType} primitiveType GLenum that specifies what kind of primitive is 1446 * @param {gluShaderUtil.DataType} type 1447 * @param {gluShaderUtil.precision} precision 1448 * @param {es3fTransformFeedbackTests.interpolation} interpolation enum number in this javascript 1449 * @constructor 1450 */ 1451 es3fTransformFeedbackTests.ArrayElementCase = function(name, desc, bufferMode, primitiveType, type, precision, interpolation) { 1452 1453 es3fTransformFeedbackTests.TransformFeedbackCase.call(this, name, desc, bufferMode, primitiveType); 1454 1455 this.m_progSpec.addVarying('v_varA', gluVarType.newTypeArray(gluVarType.newTypeBasic(type, precision), 3), interpolation); 1456 this.m_progSpec.addVarying('v_varB', gluVarType.newTypeArray(gluVarType.newTypeBasic(type, precision), 4), interpolation); 1457 1458 this.m_progSpec.addTransformFeedbackVarying('v_varA[1]'); 1459 this.m_progSpec.addTransformFeedbackVarying('v_varB[0]'); 1460 this.m_progSpec.addTransformFeedbackVarying('v_varB[3]'); 1461 1462 }; 1463 1464 setParentClass(es3fTransformFeedbackTests.ArrayElementCase, es3fTransformFeedbackTests.TransformFeedbackCase); 1465 1466 /** es3fTransformFeedbackTests.RandomCase 1467 * @extends {es3fTransformFeedbackTests.TransformFeedbackCase} 1468 * @param {string} name 1469 * @param {string} desc 1470 * @param {number} bufferMode 1471 * @param {gluDrawUtil.primitiveType} primitiveType GLenum that specifies what kind of primitive is 1472 * @param {number} seed 1473 * @constructor 1474 */ 1475 es3fTransformFeedbackTests.RandomCase = function(name, desc, bufferMode, primitiveType, seed) { 1476 es3fTransformFeedbackTests.TransformFeedbackCase.call(this, name, desc, bufferMode, primitiveType); 1477 1478 }; 1479 1480 setParentClass(es3fTransformFeedbackTests.RandomCase, es3fTransformFeedbackTests.TransformFeedbackCase); 1481 1482 es3fTransformFeedbackTests.RandomCase.prototype.init = function() { 1483 1484 /** @type {number} */ 1485 var seed = /*deString.deStringHash(getName()) ^ */ deMath.deMathHash(this.m_iterNdx); 1486 1487 /** @type {Array<gluShaderUtil.DataType>} */ 1488 var typeCandidates = [ 1489 gluShaderUtil.DataType.FLOAT, 1490 gluShaderUtil.DataType.FLOAT_VEC2, 1491 gluShaderUtil.DataType.FLOAT_VEC3, 1492 gluShaderUtil.DataType.FLOAT_VEC4, 1493 gluShaderUtil.DataType.INT, 1494 gluShaderUtil.DataType.INT_VEC2, 1495 gluShaderUtil.DataType.INT_VEC3, 1496 gluShaderUtil.DataType.INT_VEC4, 1497 gluShaderUtil.DataType.UINT, 1498 gluShaderUtil.DataType.UINT_VEC2, 1499 gluShaderUtil.DataType.UINT_VEC3, 1500 gluShaderUtil.DataType.UINT_VEC4, 1501 1502 gluShaderUtil.DataType.FLOAT_MAT2, 1503 gluShaderUtil.DataType.FLOAT_MAT2X3, 1504 gluShaderUtil.DataType.FLOAT_MAT2X4, 1505 1506 gluShaderUtil.DataType.FLOAT_MAT3X2, 1507 gluShaderUtil.DataType.FLOAT_MAT3, 1508 gluShaderUtil.DataType.FLOAT_MAT3X4, 1509 1510 gluShaderUtil.DataType.FLOAT_MAT4X2, 1511 gluShaderUtil.DataType.FLOAT_MAT4X3, 1512 gluShaderUtil.DataType.FLOAT_MAT4 1513 ]; 1514 1515 /** @type {Array<gluShaderUtil.precision>} */ 1516 var precisions = [ 1517 gluShaderUtil.precision.PRECISION_LOWP, 1518 gluShaderUtil.precision.PRECISION_MEDIUMP, 1519 gluShaderUtil.precision.PRECISION_HIGHP 1520 ]; 1521 1522 var interpModes = [{name: 'smooth', interp: es3fTransformFeedbackTests.interpolation.SMOOTH}, {name: 'flat', interp: es3fTransformFeedbackTests.interpolation.FLAT}, {name: 'centroid', interp: es3fTransformFeedbackTests.interpolation.CENTROID} 1523 ]; 1524 1525 /** @type {number} */ var maxAttributeVectors = 16; 1526 //** @type {number} */ var maxTransformFeedbackComponents = 64; // note It is enough to limit attribute set size. 1527 /** @type {boolean} */ var isSeparateMode = (this.m_bufferMode === gl.SEPARATE_ATTRIBS); 1528 /** @type {number} */ var maxTransformFeedbackVars = isSeparateMode ? 4 : maxAttributeVectors; 1529 /** @type {number} */ var arrayWeight = 0.3; 1530 /** @type {number} */ var positionWeight = 0.7; 1531 /** @type {number} */ var pointSizeWeight = 0.1; 1532 /** @type {number} */ var captureFullArrayWeight = 0.5; 1533 1534 /** @type {deRandom.Random} */ 1535 var rnd = new deRandom.Random(seed); 1536 /** @type {boolean} */ var usePosition = rnd.getFloat() < positionWeight; 1537 /** @type {boolean} */ var usePointSize = rnd.getFloat() < pointSizeWeight; 1538 /** @type {number} */ var numAttribVectorsToUse = rnd.getInt( 1539 1, maxAttributeVectors - 1/*position*/ - (usePointSize ? 1 : 0) 1540 ); 1541 1542 /** @type {number} */ var numAttributeVectors = 0; 1543 /** @type {number} */ var varNdx = 0; 1544 1545 // Generate varyings. 1546 while (numAttributeVectors < numAttribVectorsToUse) { 1547 /** @type {number} */ 1548 var maxVecs = isSeparateMode ? Math.min(2 /*at most 2*mat2*/, numAttribVectorsToUse - numAttributeVectors) : numAttribVectorsToUse - numAttributeVectors; 1549 /** @type {gluShaderUtil.DataType} */ 1550 var begin = typeCandidates[0]; 1551 /** @type {number} */ 1552 var endCandidates = begin + ( 1553 maxVecs >= 4 ? 21 : ( 1554 maxVecs >= 3 ? 18 : ( 1555 maxVecs >= 2 ? (isSeparateMode ? 13 : 15) : 12 1556 ) 1557 ) 1558 ); 1559 /** @type {gluShaderUtil.DataType} */ 1560 var end = typeCandidates[endCandidates]; 1561 1562 /** @type {gluShaderUtil.DataType} */ 1563 var type = rnd.choose(typeCandidates)[0]; 1564 1565 /** @type {gluShaderUtil.precision} */ 1566 var precision = rnd.choose(precisions)[0]; 1567 1568 /** @type {es3fTransformFeedbackTests.interpolation} */ 1569 var interp = (type === gluShaderUtil.DataType.FLOAT) ? 1570 rnd.choose(interpModes)[0].interp : 1571 es3fTransformFeedbackTests.interpolation.FLAT; 1572 1573 /** @type {number} */ 1574 var numVecs = gluShaderUtil.isDataTypeMatrix(type) ? gluShaderUtil.getDataTypeMatrixNumColumns(type) : 1; 1575 /** @type {number} */ 1576 var numComps = gluShaderUtil.getDataTypeScalarSize(type); 1577 /** @type {number} */ 1578 var maxArrayLen = Math.max(1, isSeparateMode ? (4 / numComps) : (maxVecs / numVecs)); 1579 /** @type {boolean} */ 1580 var useArray = rnd.getFloat() < arrayWeight; 1581 /** @type {number} */ 1582 var arrayLen = useArray ? rnd.getInt(1, maxArrayLen) : 1; 1583 /** @type {string} */ 1584 var name = 'v_var' + varNdx; 1585 1586 if (useArray) 1587 this.m_progSpec.addVarying(name, gluVarType.newTypeArray(gluVarType.newTypeBasic(type, precision), arrayLen), interp); 1588 else 1589 this.m_progSpec.addVarying(name, gluVarType.newTypeBasic(type, precision), interp); 1590 1591 numAttributeVectors += arrayLen * numVecs; 1592 varNdx += 1; 1593 } 1594 1595 // Generate transform feedback candidate set. 1596 /** @type {Array<string>} */ var tfCandidates = []; 1597 1598 if (usePosition) tfCandidates.push('gl_Position'); 1599 if (usePointSize) tfCandidates.push('gl_PointSize'); 1600 1601 for (var ndx = 0; ndx < varNdx; ndx++) { 1602 /** @type {es3fTransformFeedbackTests.Varying} */ 1603 var varying = this.m_progSpec.getVaryings()[ndx]; 1604 1605 if (varying.type.isArrayType()) { 1606 /** @type {boolean} */ 1607 var captureFull = rnd.getFloat() < captureFullArrayWeight; 1608 1609 if (captureFull) { 1610 tfCandidates.push(varying.name); 1611 } else { 1612 /** @type {number} */ 1613 var numElem = varying.type.getArraySize(); 1614 for (var elemNdx = 0; elemNdx < numElem; elemNdx++) 1615 tfCandidates.push(varying.name + '[' + elemNdx + ']'); 1616 } 1617 } else 1618 tfCandidates.push(varying.name); 1619 } 1620 1621 // Pick random selection. 1622 var tfVaryings = []; 1623 rnd.choose(tfCandidates, tfVaryings, Math.min(tfCandidates.length, maxTransformFeedbackVars)); 1624 rnd.shuffle(tfVaryings); 1625 for (var i = 0; i < tfVaryings.length; i++) 1626 this.m_progSpec.addTransformFeedbackVarying(tfVaryings[i]); 1627 1628 es3fTransformFeedbackTests.TransformFeedbackCase.prototype.init.call(this); 1629 1630 }; 1631 1632 /** 1633 * Creates the test in order to be executed 1634 **/ 1635 es3fTransformFeedbackTests.init = function() { 1636 1637 /** @const @type {tcuTestCase.DeqpTest} */ 1638 var testGroup = tcuTestCase.runner.testCases; 1639 1640 var bufferModes = [{name: 'separate', mode: gl.SEPARATE_ATTRIBS}, {name: 'interleaved', mode: gl.INTERLEAVED_ATTRIBS} 1641 ]; 1642 1643 var primitiveTypes = [{name: 'points', type: gluDrawUtil.primitiveType.POINTS}, {name: 'lines', type: gluDrawUtil.primitiveType.LINES}, {name: 'triangles', type: gluDrawUtil.primitiveType.TRIANGLES} 1644 ]; 1645 1646 /** @type {Array<gluShaderUtil.DataType>} */ 1647 var basicTypes = [ 1648 gluShaderUtil.DataType.FLOAT, 1649 gluShaderUtil.DataType.FLOAT_VEC2, 1650 gluShaderUtil.DataType.FLOAT_VEC3, 1651 gluShaderUtil.DataType.FLOAT_VEC4, 1652 gluShaderUtil.DataType.FLOAT_MAT2, 1653 gluShaderUtil.DataType.FLOAT_MAT2X3, 1654 gluShaderUtil.DataType.FLOAT_MAT2X4, 1655 gluShaderUtil.DataType.FLOAT_MAT3X2, 1656 gluShaderUtil.DataType.FLOAT_MAT3, 1657 gluShaderUtil.DataType.FLOAT_MAT3X4, 1658 gluShaderUtil.DataType.FLOAT_MAT4X2, 1659 gluShaderUtil.DataType.FLOAT_MAT4X3, 1660 gluShaderUtil.DataType.FLOAT_MAT4, 1661 gluShaderUtil.DataType.INT, 1662 gluShaderUtil.DataType.INT_VEC2, 1663 gluShaderUtil.DataType.INT_VEC3, 1664 gluShaderUtil.DataType.INT_VEC4, 1665 gluShaderUtil.DataType.UINT, 1666 gluShaderUtil.DataType.UINT_VEC2, 1667 gluShaderUtil.DataType.UINT_VEC3, 1668 gluShaderUtil.DataType.UINT_VEC4 1669 ]; 1670 1671 /** @type {Array<gluShaderUtil.precision>} */ 1672 var precisions = [ 1673 1674 gluShaderUtil.precision.PRECISION_LOWP, 1675 gluShaderUtil.precision.PRECISION_MEDIUMP, 1676 gluShaderUtil.precision.PRECISION_HIGHP 1677 1678 // glsUBC.UniformFlags.PRECISION_LOW, 1679 // glsUBC.UniformFlags.PRECISION_MEDIUM, 1680 // glsUBC.UniformFlags.PRECISION_HIGH 1681 ]; 1682 1683 var interpModes = [{name: 'smooth', interp: es3fTransformFeedbackTests.interpolation.SMOOTH}, {name: 'flat', interp: es3fTransformFeedbackTests.interpolation.FLAT}, {name: 'centroid', interp: es3fTransformFeedbackTests.interpolation.CENTROID} 1684 ]; 1685 1686 // .position 1687 /** @type {tcuTestCase.DeqpTest} */ 1688 var positionGroup = tcuTestCase.newTest('position', 'gl_Position capture using transform feedback'); 1689 testGroup.addChild(positionGroup); 1690 1691 for (var primitiveType = 0; primitiveType < primitiveTypes.length; primitiveType++) { 1692 for (var bufferMode = 0; bufferMode < bufferModes.length; bufferMode++) { 1693 /** @type {string} */ 1694 var name = primitiveTypes[primitiveType].name + '_' + bufferModes[bufferMode].name; 1695 1696 positionGroup.addChild(new es3fTransformFeedbackTests.PositionCase( 1697 name, 1698 '', 1699 bufferModes[bufferMode].mode, 1700 primitiveTypes[primitiveType].type 1701 )); 1702 } 1703 } 1704 1705 // .point_size 1706 /** @type {tcuTestCase.DeqpTest} */ var pointSizeGroup = tcuTestCase.newTest('point_size', 'gl_PointSize capture using transform feedback'); 1707 testGroup.addChild(pointSizeGroup); 1708 1709 for (var primitiveType = 0; primitiveType < primitiveTypes.length; primitiveType++) { 1710 for (var bufferMode = 0; bufferMode < bufferModes.length; bufferMode++) { 1711 var name = primitiveTypes[primitiveType].name + '_' + bufferModes[bufferMode].name; 1712 1713 pointSizeGroup.addChild(new es3fTransformFeedbackTests.PointSizeCase( 1714 name, 1715 '', 1716 bufferModes[bufferMode].mode, 1717 primitiveTypes[primitiveType].type 1718 )); 1719 } 1720 } 1721 1722 // .basic_type 1723 for (var bufferModeNdx = 0; bufferModeNdx < bufferModes.length; bufferModeNdx++) { 1724 /** @type {number} */ 1725 var bufferMode = bufferModes[bufferModeNdx].mode; 1726 for (var primitiveTypeNdx = 0; primitiveTypeNdx < primitiveTypes.length; primitiveTypeNdx++) { 1727 /** @type {tcuTestCase.DeqpTest} */ 1728 var primitiveGroup = tcuTestCase.newTest( 1729 'basic_types.' + bufferModes[bufferModeNdx].name + '.' + primitiveTypes[primitiveTypeNdx].name, 1730 'Basic types in transform feedback'); 1731 /** @type {number} */ 1732 var primitiveType = primitiveTypes[primitiveTypeNdx].type; 1733 testGroup.addChild(primitiveGroup); 1734 1735 for (var typeNdx = 0; typeNdx < basicTypes.length; typeNdx++) { 1736 /** @type {gluShaderUtil.DataType} */ 1737 var type = basicTypes[typeNdx]; 1738 /** @type {boolean} */ 1739 var isFloat = gluShaderUtil.getDataTypeScalarType(type) == gluShaderUtil.DataType.FLOAT; 1740 1741 for (var precNdx = 0; precNdx < precisions.length; precNdx++) { 1742 /** @type {gluShaderUtil.precision} */ 1743 var precision = precisions[precNdx]; 1744 var name = gluShaderUtil.getPrecisionName(precision) + '_' + gluShaderUtil.getDataTypeName(type); 1745 1746 primitiveGroup.addChild(new es3fTransformFeedbackTests.BasicTypeCase( 1747 name, 1748 '', 1749 bufferMode, 1750 primitiveType, 1751 type, 1752 precision, 1753 isFloat ? es3fTransformFeedbackTests.interpolation.SMOOTH : es3fTransformFeedbackTests.interpolation.FLAT 1754 )); 1755 } 1756 } 1757 } 1758 } 1759 1760 // .array 1761 for (var bufferModeNdx = 0; bufferModeNdx < bufferModes.length; bufferModeNdx++) { 1762 var bufferMode = bufferModes[bufferModeNdx].mode; 1763 for (var primitiveTypeNdx = 0; primitiveTypeNdx < primitiveTypes.length; primitiveTypeNdx++) { 1764 var primitiveGroup = tcuTestCase.newTest( 1765 'array.' + bufferModes[bufferModeNdx].name + '.' + primitiveTypes[primitiveTypeNdx].name, 1766 'Capturing whole array in TF'); 1767 /** @type {number} */ 1768 var primitiveType = primitiveTypes[primitiveTypeNdx].type; 1769 testGroup.addChild(primitiveGroup); 1770 1771 for (var typeNdx = 0; typeNdx < basicTypes.length; typeNdx++) { 1772 var type = basicTypes[typeNdx]; 1773 var isFloat = gluShaderUtil.getDataTypeScalarType(type) == gluShaderUtil.DataType.FLOAT; 1774 1775 for (var precNdx = 0; precNdx < precisions.length; precNdx++) { 1776 var precision = precisions[precNdx]; 1777 var name = gluShaderUtil.getPrecisionName(precision) + '_' + gluShaderUtil.getDataTypeName(type); 1778 1779 primitiveGroup.addChild(new es3fTransformFeedbackTests.BasicArrayCase( 1780 name, 1781 '', 1782 bufferMode, 1783 primitiveType, 1784 type, 1785 precision, 1786 isFloat ? es3fTransformFeedbackTests.interpolation.SMOOTH : es3fTransformFeedbackTests.interpolation.FLAT 1787 )); 1788 } 1789 } 1790 } 1791 } 1792 1793 // .array_element 1794 for (var bufferModeNdx = 0; bufferModeNdx < bufferModes.length; bufferModeNdx++) { 1795 var bufferMode = bufferModes[bufferModeNdx].mode; 1796 for (var primitiveTypeNdx = 0; primitiveTypeNdx < primitiveTypes.length; primitiveTypeNdx++) { 1797 var primitiveGroup = tcuTestCase.newTest( 1798 'array_element.' + bufferModes[bufferModeNdx].name + '.' + primitiveTypes[primitiveTypeNdx].name, 1799 'Capturing single array element in TF'); 1800 var primitiveType = primitiveTypes[primitiveTypeNdx].type; 1801 testGroup.addChild(primitiveGroup); 1802 1803 for (var typeNdx = 0; typeNdx < basicTypes.length; typeNdx++) { 1804 var type = basicTypes[typeNdx]; 1805 var isFloat = gluShaderUtil.getDataTypeScalarType(type) == gluShaderUtil.DataType.FLOAT; 1806 1807 for (var precNdx = 0; precNdx < precisions.length; precNdx++) { 1808 var precision = precisions[precNdx]; 1809 var name = gluShaderUtil.getPrecisionName(precision) + '_' + gluShaderUtil.getDataTypeName(type); 1810 1811 primitiveGroup.addChild(new es3fTransformFeedbackTests.ArrayElementCase( 1812 name, 1813 '', 1814 bufferMode, 1815 primitiveType, 1816 type, 1817 precision, 1818 isFloat ? es3fTransformFeedbackTests.interpolation.SMOOTH : es3fTransformFeedbackTests.interpolation.FLAT 1819 )); 1820 } 1821 } 1822 } 1823 } 1824 1825 // .interpolation 1826 for (var modeNdx = 0; modeNdx < interpModes.length; modeNdx++) { 1827 var interp = interpModes[modeNdx].interp; 1828 var modeGroup = tcuTestCase.newTest( 1829 'interpolation.' + interpModes[modeNdx].name, 1830 'Different interpolation modes in transform feedback varyings'); 1831 testGroup.addChild(modeGroup); 1832 1833 for (var precNdx = 0; precNdx < precisions.length; precNdx++) { 1834 var precision = precisions[precNdx]; 1835 1836 for (var primitiveType = 0; primitiveType < primitiveTypes.length; primitiveType++) { 1837 for (var bufferMode = 0; bufferMode < bufferModes.length; bufferMode++) { 1838 var name = ( 1839 gluShaderUtil.getPrecisionName(precision) + 1840 '_vec4_' + primitiveTypes[primitiveType].name + 1841 '_' + bufferModes[bufferMode].name 1842 ); 1843 1844 modeGroup.addChild(new es3fTransformFeedbackTests.BasicTypeCase( 1845 name, 1846 '', 1847 bufferModes[bufferMode].mode, 1848 primitiveTypes[primitiveType].type, 1849 gluShaderUtil.DataType.FLOAT_VEC4, 1850 precision, 1851 interp 1852 )); 1853 } 1854 } 1855 } 1856 } 1857 1858 // .random 1859 for (var bufferModeNdx = 0; bufferModeNdx < bufferModes.length; bufferModeNdx++) { 1860 /** @type {number} */ 1861 var bufferMode = bufferModes[bufferModeNdx].mode; 1862 for (var primitiveTypeNdx = 0; primitiveTypeNdx < primitiveTypes.length; primitiveTypeNdx++) { 1863 var primitiveGroup = tcuTestCase.newTest( 1864 'random.' + bufferModes[bufferModeNdx].name + '.' + primitiveTypes[primitiveTypeNdx].name, 1865 'Randomized transform feedback cases'); 1866 /** @type {number} */ 1867 var primitiveType = primitiveTypes[primitiveTypeNdx].type; 1868 testGroup.addChild(primitiveGroup); 1869 1870 for (var ndx = 0; ndx < 10; ndx++) { 1871 /** @type {number} */ 1872 var seed = deMath.deMathHash(bufferMode) ^ deMath.deMathHash(primitiveType) ^ deMath.deMathHash(ndx); 1873 1874 primitiveGroup.addChild(new es3fTransformFeedbackTests.RandomCase( 1875 (ndx + 1).toString(), 1876 '', 1877 bufferMode, 1878 primitiveType, 1879 seed 1880 )); 1881 } 1882 } 1883 } 1884 1885 }; 1886 1887 /** 1888 * Create and execute the test cases 1889 */ 1890 es3fTransformFeedbackTests.run = function(context, range) { 1891 gl = context; 1892 var testName = 'transform_feedback'; 1893 var testDescription = 'Transform Feedback Tests'; 1894 var state = tcuTestCase.runner; 1895 1896 state.testName = testName; 1897 state.testCases = tcuTestCase.newTest(testName, testDescription, null); 1898 1899 //Set up name and description of this test series. 1900 setCurrentTestName(testName); 1901 description(testDescription); 1902 try { 1903 es3fTransformFeedbackTests.init(); 1904 if (range) 1905 state.setRange(range); 1906 tcuTestCase.runTestCases(); 1907 } catch (err) { 1908 bufferedLogToConsole(err); 1909 tcuTestCase.runner.terminate(); 1910 } 1911 1912 }; 1913 1914 });