glsDrawTests.js (148903B)
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('modules.shared.glsDrawTests'); 23 goog.require('framework.common.tcuFloat'); 24 goog.require('framework.common.tcuImageCompare'); 25 goog.require('framework.common.tcuPixelFormat'); 26 goog.require('framework.common.tcuRGBA'); 27 goog.require('framework.common.tcuSurface'); 28 goog.require('framework.common.tcuTestCase'); 29 goog.require('framework.common.tcuTextureUtil'); 30 goog.require('framework.delibs.debase.deMath'); 31 goog.require('framework.delibs.debase.deRandom'); 32 goog.require('framework.opengl.gluShaderUtil'); 33 goog.require('framework.opengl.gluStrUtil'); 34 goog.require('framework.opengl.simplereference.sglrGLContext'); 35 goog.require('framework.opengl.simplereference.sglrReferenceContext'); 36 goog.require('framework.opengl.simplereference.sglrShaderProgram'); 37 goog.require('framework.referencerenderer.rrFragmentOperations'); 38 goog.require('framework.referencerenderer.rrGenericVector'); 39 goog.require('framework.referencerenderer.rrShadingContext'); 40 goog.require('framework.referencerenderer.rrVertexAttrib'); 41 goog.require('framework.referencerenderer.rrVertexPacket'); 42 43 goog.scope(function() { 44 45 var glsDrawTests = modules.shared.glsDrawTests; 46 var tcuTestCase = framework.common.tcuTestCase; 47 var tcuRGBA = framework.common.tcuRGBA; 48 var tcuFloat = framework.common.tcuFloat; 49 var tcuPixelFormat = framework.common.tcuPixelFormat; 50 var tcuSurface = framework.common.tcuSurface; 51 var tcuImageCompare = framework.common.tcuImageCompare; 52 var tcuTextureUtil = framework.common.tcuTextureUtil; 53 var gluShaderUtil = framework.opengl.gluShaderUtil; 54 var gluStrUtil = framework.opengl.gluStrUtil; 55 var sglrGLContext = framework.opengl.simplereference.sglrGLContext; 56 var sglrReferenceContext = framework.opengl.simplereference.sglrReferenceContext; 57 var sglrShaderProgram = framework.opengl.simplereference.sglrShaderProgram; 58 var deMath = framework.delibs.debase.deMath; 59 var deRandom = framework.delibs.debase.deRandom; 60 var rrFragmentOperations = framework.referencerenderer.rrFragmentOperations; 61 var rrGenericVector = framework.referencerenderer.rrGenericVector; 62 var rrShadingContext = framework.referencerenderer.rrShadingContext; 63 var rrVertexAttrib = framework.referencerenderer.rrVertexAttrib; 64 var rrVertexPacket = framework.referencerenderer.rrVertexPacket; 65 66 /** @const {number} */ glsDrawTests.MAX_RENDER_TARGET_SIZE = 512; 67 68 // Utils 69 70 /** 71 * @param {glsDrawTests.DrawTestSpec.Target} target 72 * @return {number} 73 */ 74 glsDrawTests.targetToGL = function(target) { 75 assertMsgOptions(target != null, 'Target is null', false, true); 76 77 var targets = [ 78 gl.ELEMENT_ARRAY_BUFFER, // TARGET_ELEMENT_ARRAY = 0, 79 gl.ARRAY_BUFFER // TARGET_ARRAY, 80 ]; 81 82 return targets[target]; 83 }; 84 85 /** 86 * @param {?glsDrawTests.DrawTestSpec.Usage} usage 87 * @return {number} 88 */ 89 glsDrawTests.usageToGL = function(usage) { 90 assertMsgOptions(usage != null, 'Usage is null', false, true); 91 92 var usages = [ 93 gl.DYNAMIC_DRAW, // USAGE_DYNAMIC_DRAW = 0, 94 gl.STATIC_DRAW, // USAGE_STATIC_DRAW, 95 gl.STREAM_DRAW, // USAGE_STREAM_DRAW, 96 97 gl.STREAM_READ, // USAGE_STREAM_READ, 98 gl.STREAM_COPY, // USAGE_STREAM_COPY, 99 100 gl.STATIC_READ, // USAGE_STATIC_READ, 101 gl.STATIC_COPY, // USAGE_STATIC_COPY, 102 103 gl.DYNAMIC_READ, // USAGE_DYNAMIC_READ, 104 gl.DYNAMIC_COPY // USAGE_DYNAMIC_COPY, 105 ]; 106 assertMsgOptions(usages.length == Object.keys(glsDrawTests.DrawTestSpec.Usage).length, 107 'Amount of usage gl vlaues is different from amount of usages', false, true); 108 109 return usages[usage]; 110 }; 111 112 /** 113 * @param {?glsDrawTests.DrawTestSpec.InputType} type 114 * @return {number} 115 */ 116 glsDrawTests.inputTypeToGL = function(type) { 117 assertMsgOptions(type != null, 'Input type is null', false, true); 118 119 var types = [ 120 gl.FLOAT, // INPUTTYPE_FLOAT = 0, 121 gl.BYTE, // INPUTTYPE_BYTE, 122 gl.SHORT, // INPUTTYPE_SHORT, 123 gl.UNSIGNED_BYTE, // INPUTTYPE_UNSIGNED_BYTE, 124 gl.UNSIGNED_SHORT, // INPUTTYPE_UNSIGNED_SHORT, 125 126 gl.INT, // INPUTTYPE_INT, 127 gl.UNSIGNED_INT, // INPUTTYPE_UNSIGNED_INT, 128 gl.HALF_FLOAT, // INPUTTYPE_HALF, 129 gl.UNSIGNED_INT_2_10_10_10_REV, // INPUTTYPE_UNSIGNED_INT_2_10_10_10, 130 gl.INT_2_10_10_10_REV // INPUTTYPE_INT_2_10_10_10, 131 ]; 132 assertMsgOptions(types.length == Object.keys(glsDrawTests.DrawTestSpec.InputType).length, 133 'Amount of gl input types is different from amount of input types', false, true); 134 135 return types[type]; 136 }; 137 138 /** 139 * @param {?glsDrawTests.DrawTestSpec.OutputType} type 140 * @return {string} 141 */ 142 glsDrawTests.outputTypeToGLType = function(type) { 143 assertMsgOptions(type != null, 'Output type is null', false, true); 144 145 var types = [ 146 'float', // OUTPUTTYPE_FLOAT = 0, 147 'vec2', // OUTPUTTYPE_VEC2, 148 'vec3', // OUTPUTTYPE_VEC3, 149 'vec4', // OUTPUTTYPE_VEC4, 150 151 'int', // OUTPUTTYPE_INT, 152 'uint', // OUTPUTTYPE_UINT, 153 154 'ivec2', // OUTPUTTYPE_IVEC2, 155 'ivec3', // OUTPUTTYPE_IVEC3, 156 'ivec4', // OUTPUTTYPE_IVEC4, 157 158 'uvec2', // OUTPUTTYPE_UVEC2, 159 'uvec3', // OUTPUTTYPE_UVEC3, 160 'uvec4' // OUTPUTTYPE_UVEC4, 161 ]; 162 assertMsgOptions(types.length == Object.keys(glsDrawTests.DrawTestSpec.OutputType).length, 163 'Amount of output type names is different than amount of output types', false, true); 164 165 return types[type]; 166 }; 167 168 /** 169 * @param {?glsDrawTests.DrawTestSpec.Primitive} primitive 170 * @return {number} 171 */ 172 glsDrawTests.primitiveToGL = function(primitive) { 173 var primitives = [ 174 gl.POINTS, // PRIMITIVE_POINTS = 0, 175 gl.TRIANGLES, // PRIMITIVE_TRIANGLES, 176 gl.TRIANGLE_FAN, // PRIMITIVE_TRIANGLE_FAN, 177 gl.TRIANGLE_STRIP, // PRIMITIVE_TRIANGLE_STRIP, 178 gl.LINES, // PRIMITIVE_LINES 179 gl.LINE_STRIP, // PRIMITIVE_LINE_STRIP 180 gl.LINE_LOOP 181 ]; 182 assertMsgOptions(primitives.length == Object.keys(glsDrawTests.DrawTestSpec.Primitive).length, 183 'Amount of gl primitive values is different than amount of primitives', false, true); 184 185 return primitives[primitive]; 186 }; 187 188 /** 189 * @param {?glsDrawTests.DrawTestSpec.IndexType} indexType 190 * @return {number} 191 */ 192 glsDrawTests.indexTypeToGL = function(indexType) { 193 var indexTypes = [ 194 gl.UNSIGNED_BYTE, // INDEXTYPE_BYTE = 0, 195 gl.UNSIGNED_SHORT, // INDEXTYPE_SHORT, 196 gl.UNSIGNED_INT // INDEXTYPE_INT, 197 ]; 198 assertMsgOptions(indexTypes.length == Object.keys(glsDrawTests.DrawTestSpec.IndexType).length, 199 'Amount of gl index types is different than amount of index types', false, true); 200 201 return indexTypes[indexType]; 202 }; 203 204 /** 205 * @param {?glsDrawTests.DrawTestSpec.IndexType} indexType 206 * @return {?glsDrawTests.DrawTestSpec.InputType} 207 */ 208 glsDrawTests.indexTypeToInputType = function(indexType) { 209 var inputTypes = [ 210 glsDrawTests.DrawTestSpec.InputType.UNSIGNED_BYTE, // INDEXTYPE_BYTE = 0, 211 glsDrawTests.DrawTestSpec.InputType.UNSIGNED_SHORT, // INDEXTYPE_SHORT, 212 glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT // INDEXTYPE_INT, 213 ]; 214 assertMsgOptions(inputTypes.length == Object.keys(glsDrawTests.DrawTestSpec.IndexType).length, 215 'Amount of relevant input types is different than amount of index types', false, true); 216 217 return inputTypes[indexType]; 218 }; 219 220 /** 221 * @param {?glsDrawTests.DrawTestSpec.InputType} type 222 * @return {boolean} 223 */ 224 glsDrawTests.inputTypeIsFloatType = function(type) { 225 if (type == glsDrawTests.DrawTestSpec.InputType.FLOAT) 226 return true; 227 if (type == glsDrawTests.DrawTestSpec.InputType.HALF) 228 return true; 229 return false; 230 }; 231 232 /** 233 * @param {?glsDrawTests.DrawTestSpec.OutputType} type 234 * @return {boolean} 235 */ 236 glsDrawTests.outputTypeIsFloatType = function(type) { 237 if (type == glsDrawTests.DrawTestSpec.OutputType.FLOAT || 238 type == glsDrawTests.DrawTestSpec.OutputType.VEC2 || 239 type == glsDrawTests.DrawTestSpec.OutputType.VEC3 || 240 type == glsDrawTests.DrawTestSpec.OutputType.VEC4) 241 return true; 242 243 return false; 244 }; 245 246 /** 247 * @param {?glsDrawTests.DrawTestSpec.OutputType} type 248 * @return {boolean} 249 */ 250 glsDrawTests.outputTypeIsIntType = function(type) { 251 if (type == glsDrawTests.DrawTestSpec.OutputType.INT || 252 type == glsDrawTests.DrawTestSpec.OutputType.IVEC2 || 253 type == glsDrawTests.DrawTestSpec.OutputType.IVEC3 || 254 type == glsDrawTests.DrawTestSpec.OutputType.IVEC4) 255 return true; 256 257 return false; 258 }; 259 260 /** 261 * @param {?glsDrawTests.DrawTestSpec.OutputType} type 262 * @return {boolean} 263 */ 264 glsDrawTests.outputTypeIsUintType = function(type) { 265 if (type == glsDrawTests.DrawTestSpec.OutputType.UINT || 266 type == glsDrawTests.DrawTestSpec.OutputType.UVEC2 || 267 type == glsDrawTests.DrawTestSpec.OutputType.UVEC3 || 268 type == glsDrawTests.DrawTestSpec.OutputType.UVEC4) 269 return true; 270 271 return false; 272 }; 273 274 /** 275 * @param {?glsDrawTests.DrawTestSpec.Primitive} primitive 276 * @param {number} primitiveCount 277 * @return {number} 278 */ 279 glsDrawTests.getElementCount = function(primitive, primitiveCount) { 280 switch (primitive) { 281 case glsDrawTests.DrawTestSpec.Primitive.POINTS: return primitiveCount; 282 case glsDrawTests.DrawTestSpec.Primitive.TRIANGLES: return primitiveCount * 3; 283 case glsDrawTests.DrawTestSpec.Primitive.TRIANGLE_FAN: return primitiveCount + 2; 284 case glsDrawTests.DrawTestSpec.Primitive.TRIANGLE_STRIP: return primitiveCount + 2; 285 case glsDrawTests.DrawTestSpec.Primitive.LINES: return primitiveCount * 2; 286 case glsDrawTests.DrawTestSpec.Primitive.LINE_STRIP: return primitiveCount + 1; 287 case glsDrawTests.DrawTestSpec.Primitive.LINE_LOOP: return (primitiveCount == 1) ? (2) : (primitiveCount); 288 default: 289 throw new Error('Invalid primitive'); 290 } 291 }; 292 293 //MethodInfo 294 295 /** 296 * @typedef {{indexed: boolean, instanced: boolean, ranged: boolean, first: boolean}} 297 */ 298 glsDrawTests.MethodInfo = { 299 /** @type {boolean} */ indexed: false, 300 /** @type {boolean} */ instanced: false, 301 /** @type {boolean} */ ranged: false, 302 /** @type {boolean} */ first: false 303 }; 304 305 /** 306 * @param {?glsDrawTests.DrawTestSpec.DrawMethod} method 307 * @return {glsDrawTests.MethodInfo} 308 */ 309 glsDrawTests.getMethodInfo = function(method) { 310 /** @type {Array<glsDrawTests.MethodInfo>} */ var infos = [{ 311 indexed: false, instanced: false, ranged: false, first: true //!< DRAWMETHOD_DRAWARRAYS, 312 },{ 313 indexed: false, instanced: true, ranged: false, first: true //!< DRAWMETHOD_DRAWARRAYS_INSTANCED, 314 },{ 315 indexed: true, instanced: false, ranged: false, first: false //!< DRAWMETHOD_DRAWELEMENTS, 316 },{ 317 indexed: true, instanced: false, ranged: true, first: false //!< DRAWMETHOD_DRAWELEMENTS_RANGED, 318 },{ 319 indexed: true, instanced: true, ranged: false, first: false //!< DRAWMETHOD_DRAWELEMENTS_INSTANCED 320 } 321 ]; 322 323 assertMsgOptions(infos.length == Object.keys(glsDrawTests.DrawTestSpec.DrawMethod).length, 324 'Number of info names', false, true); 325 assertMsgOptions(method < infos.length, 'Invalid method', false, true); 326 return /** @type {glsDrawTests.MethodInfo} */ (infos[method]); 327 }; 328 329 /** 330 * @param {glsDrawTests.DrawTestSpec} a 331 * @param {glsDrawTests.DrawTestSpec} b 332 * @return {boolean} 333 */ 334 glsDrawTests.checkSpecsShaderCompatible = function(a, b) { 335 // Only the attributes matter 336 if (a.attribs.length != b.attribs.length) 337 return false; 338 339 for (var ndx = 0; ndx < a.attribs.length; ++ndx) { 340 // Only the output type (== shader input type) matters and the usage in the shader. 341 342 if (a.attribs[ndx].additionalPositionAttribute != b.attribs[ndx].additionalPositionAttribute) 343 return false; 344 345 // component counts need not to match 346 if (glsDrawTests.outputTypeIsFloatType(a.attribs[ndx].outputType) && glsDrawTests.outputTypeIsFloatType(b.attribs[ndx].outputType)) 347 continue; 348 if (glsDrawTests.outputTypeIsIntType(a.attribs[ndx].outputType) && glsDrawTests.outputTypeIsIntType(b.attribs[ndx].outputType)) 349 continue; 350 if (glsDrawTests.outputTypeIsUintType(a.attribs[ndx].outputType) && glsDrawTests.outputTypeIsUintType(b.attribs[ndx].outputType)) 351 continue; 352 353 return false; 354 } 355 356 return true; 357 }; 358 359 // generate random vectors in a way that does not depend on argument evaluation order 360 361 /** 362 * @param {deRandom.Random} random 363 * @return {Array<number>} 364 */ 365 glsDrawTests.generateRandomVec4 = function(random) { 366 /** @type {Array<number>} */ var retVal = []; 367 368 for (var i = 0; i < 4; ++i) 369 retVal[i] = random.getFloat(); 370 371 return retVal; 372 }; 373 374 /** 375 * @param {deRandom.Random} random 376 * @return {Array<number>} 377 */ 378 glsDrawTests.generateRandomIVec4 = function(random) { 379 /** @type {Array<number>} */ var retVal = []; 380 381 for (var i = 0; i < 4; ++i) 382 retVal[i] = random.getInt(); 383 384 return retVal; 385 }; 386 387 /** 388 * @param {deRandom.Random} random 389 * @return {Array<number>} 390 */ 391 glsDrawTests.generateRandomUVec4 = function(random) { 392 /** @type {Array<number>} */ var retVal = []; 393 394 for (var i = 0; i < 4; ++i) 395 retVal[i] = Math.abs(random.getInt()); 396 397 return retVal; 398 }; 399 400 //GLValue 401 402 /** 403 * glsDrawTests.GLValue class 404 * @constructor 405 */ 406 glsDrawTests.GLValue = function() { 407 /** @type {goog.NumberArray} */ this.m_value = [0]; 408 /** @type {?glsDrawTests.DrawTestSpec.InputType} */ this.m_type; 409 }; 410 411 /** 412 * @param {goog.TypedArray} dst 413 * @param {glsDrawTests.GLValue} val 414 */ 415 glsDrawTests.copyGLValueToArray = function(dst, val) { 416 /** @type {Uint8Array} */ var dst8 = new Uint8Array(dst.buffer).subarray(dst.byteOffset, dst.byteOffset + dst.byteLength); 417 /** @type {Uint8Array} */ var val8 = new Uint8Array(val.m_value.buffer); // TODO: Fix encapsulation issue 418 dst8.set(val8); 419 }; 420 421 /** 422 * @param {goog.TypedArray} dst 423 * @param {goog.TypedArray} src 424 */ 425 glsDrawTests.copyArray = function(dst, src) { 426 /** @type {Uint8Array} */ var dst8 = new Uint8Array(dst.buffer).subarray(dst.byteOffset, dst.byteOffset + dst.byteLength); 427 /** @type {Uint8Array} */ var src8 = new Uint8Array(src.buffer).subarray(src.byteOffset, src.byteOffset + src.byteLength); 428 dst8.set(src8); 429 }; 430 431 /** 432 * typeToTypedArray function. Determines which type of array will store the value, and stores it. 433 * @param {number} value 434 * @param {?glsDrawTests.DrawTestSpec.InputType} type 435 */ 436 glsDrawTests.GLValue.typeToTypedArray = function(value, type) { 437 var array; 438 439 switch (type) { 440 case glsDrawTests.DrawTestSpec.InputType.FLOAT: 441 array = new Float32Array(1); 442 break; 443 444 case glsDrawTests.DrawTestSpec.InputType.BYTE: 445 array = new Int8Array(1); 446 break; 447 case glsDrawTests.DrawTestSpec.InputType.SHORT: 448 array = new Int16Array(1); 449 break; 450 451 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_BYTE: 452 array = new Uint8Array(1); 453 break; 454 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_SHORT: 455 array = new Uint16Array(1); 456 break; 457 458 case glsDrawTests.DrawTestSpec.InputType.INT: 459 array = new Int32Array(1); 460 break; 461 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT: 462 array = new Uint32Array(1); 463 break; 464 case glsDrawTests.DrawTestSpec.InputType.HALF: 465 array = new Uint16Array(1); 466 value = glsDrawTests.GLValue.floatToHalf(value); 467 break; 468 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT_2_10_10_10: 469 array = new Uint32Array(1); 470 break; 471 case glsDrawTests.DrawTestSpec.InputType.INT_2_10_10_10: 472 array = new Int32Array(1); 473 break; 474 default: 475 throw new Error('glsDrawTests.GLValue.typeToTypedArray - Invalid InputType'); 476 } 477 478 array[0] = value; 479 return array; 480 }; 481 482 /** 483 * glsDrawTests.GLValue.create 484 * @param {number} value 485 * @param {?glsDrawTests.DrawTestSpec.InputType} type 486 */ 487 glsDrawTests.GLValue.create = function(value, type) { 488 var v = new glsDrawTests.GLValue(); 489 v.m_value = glsDrawTests.GLValue.typeToTypedArray(value, type); 490 v.m_type = type; 491 return v; 492 }; 493 494 /** 495 * glsDrawTests.GLValue.halfToFloat 496 * @param {number} value 497 * @return {number} 498 */ 499 glsDrawTests.GLValue.halfToFloat = function(value) { 500 return tcuFloat.halfFloatToNumberNoDenorm(value); 501 }; 502 503 /** 504 * @param {number} f 505 * @return {number} 506 */ 507 glsDrawTests.GLValue.floatToHalf = function(f) { 508 // No denorm support. 509 return tcuFloat.numberToHalfFloatNoDenorm(f); 510 }; 511 512 /** 513 * glsDrawTests.GLValue.getMaxValue 514 * @param {?glsDrawTests.DrawTestSpec.InputType} type 515 * @return {glsDrawTests.GLValue} 516 */ 517 glsDrawTests.GLValue.getMaxValue = function(type) { 518 var value = 0; 519 520 assertMsgOptions(type >= 0 && type < Object.keys(glsDrawTests.DrawTestSpec.InputType).length, 521 'Invalid type for GLValue', false, true); 522 523 switch (type) { 524 case glsDrawTests.DrawTestSpec.InputType.FLOAT: 525 value = 127; 526 break; 527 case glsDrawTests.DrawTestSpec.InputType.BYTE: 528 value = 127; 529 break; 530 case glsDrawTests.DrawTestSpec.InputType.SHORT: 531 value = 32760; 532 break; 533 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_BYTE: 534 value = 255; 535 break; 536 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_SHORT: 537 value = 65530; 538 break; 539 case glsDrawTests.DrawTestSpec.InputType.INT: 540 value = 2147483647; 541 break; 542 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT: 543 value = 4294967295; 544 break; 545 case glsDrawTests.DrawTestSpec.InputType.HALF: 546 value = 256; 547 break; 548 default: //For any other valid type, return 0 549 value = 0; 550 } 551 552 return glsDrawTests.GLValue.create(value, type); 553 }; 554 555 /** 556 * glsDrawTests.GLValue.getMinValue 557 * @param {?glsDrawTests.DrawTestSpec.InputType} type 558 * @return {glsDrawTests.GLValue} 559 */ 560 glsDrawTests.GLValue.getMinValue = function(type) { 561 var value = 0; 562 563 assertMsgOptions(type >= 0 && type < Object.keys(glsDrawTests.DrawTestSpec.InputType).length, 564 'Invalid type for GLValue', false, true); 565 566 switch (type) { 567 case glsDrawTests.DrawTestSpec.InputType.FLOAT: 568 value = -127; 569 break; 570 case glsDrawTests.DrawTestSpec.InputType.BYTE: 571 value = -127; 572 break; 573 case glsDrawTests.DrawTestSpec.InputType.SHORT: 574 value = -32760; 575 break; 576 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_BYTE: 577 value = 0; 578 break; 579 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_SHORT: 580 value = 0; 581 break; 582 case glsDrawTests.DrawTestSpec.InputType.INT: 583 value = -2147483647; 584 break; 585 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT: 586 value = 0; 587 break; 588 case glsDrawTests.DrawTestSpec.InputType.HALF: 589 value = -256; 590 break; 591 default: //For any other valid type, return 0 592 value = 0; 593 } 594 595 return glsDrawTests.GLValue.create(value, type); 596 }; 597 598 /** 599 * glsDrawTests.GLValue.getRandom 600 * @param {deRandom.Random} rnd 601 * @param {glsDrawTests.GLValue} min 602 * @param {glsDrawTests.GLValue} max 603 * @return {glsDrawTests.GLValue} 604 */ 605 glsDrawTests.GLValue.getRandom = function(rnd, min, max) { 606 assertMsgOptions(min.getType() == max.getType(), 'Min and max types differ', false, true); 607 608 var minv = min.interpret(); 609 var maxv = max.interpret(); 610 var type = min.getType(); 611 var value; 612 613 if (maxv < minv) 614 return min; 615 616 switch (type) { 617 case glsDrawTests.DrawTestSpec.InputType.FLOAT: 618 case glsDrawTests.DrawTestSpec.InputType.HALF: { 619 return glsDrawTests.GLValue.create(minv + rnd.getFloat() * (maxv - minv), type); 620 break; 621 } 622 623 case glsDrawTests.DrawTestSpec.InputType.SHORT: 624 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_SHORT: 625 case glsDrawTests.DrawTestSpec.InputType.BYTE: 626 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_BYTE: 627 case glsDrawTests.DrawTestSpec.InputType.INT: 628 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT: { 629 return glsDrawTests.GLValue.create(minv + rnd.getInt() % (maxv - minv), type); 630 break; 631 } 632 633 default: 634 throw new Error('glsDrawTests.GLValue.getRandom - Invalid input type'); 635 break; 636 } 637 }; 638 639 // Minimum difference required between coordinates 640 641 /** 642 * @param {?glsDrawTests.DrawTestSpec.InputType} type 643 * @return {glsDrawTests.GLValue} 644 */ 645 glsDrawTests.GLValue.minValue = function(type) { 646 switch (type) { 647 case glsDrawTests.DrawTestSpec.InputType.FLOAT: 648 case glsDrawTests.DrawTestSpec.InputType.BYTE: 649 case glsDrawTests.DrawTestSpec.InputType.HALF: 650 return glsDrawTests.GLValue.create(4, type); 651 case glsDrawTests.DrawTestSpec.InputType.SHORT: 652 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_SHORT: 653 return glsDrawTests.GLValue.create(4 * 256, type); 654 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_BYTE: 655 return glsDrawTests.GLValue.create(4 * 2, type); 656 case glsDrawTests.DrawTestSpec.InputType.INT: 657 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT: 658 return glsDrawTests.GLValue.create(4 * 16777216, type); 659 660 default: 661 throw new Error('glsDrawTests.GLValue.minValue - Invalid input type'); 662 } 663 }; 664 665 /** 666 * @param {glsDrawTests.GLValue} val 667 * @return {glsDrawTests.GLValue} 668 */ 669 glsDrawTests.GLValue.abs = function(val) { 670 var type = val.getType(); 671 switch (type) { 672 case glsDrawTests.DrawTestSpec.InputType.SHORT: 673 return glsDrawTests.GLValue.create(0x7FFF & val.getValue(), type); 674 case glsDrawTests.DrawTestSpec.InputType.BYTE: 675 return glsDrawTests.GLValue.create(0x7F & val.getValue(), type); 676 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_BYTE: 677 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_SHORT: 678 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT: 679 return val; 680 case glsDrawTests.DrawTestSpec.InputType.FLOAT: 681 case glsDrawTests.DrawTestSpec.InputType.HALF: 682 return glsDrawTests.GLValue.create(Math.abs(val.interpret()), type); 683 case glsDrawTests.DrawTestSpec.InputType.INT: 684 return glsDrawTests.GLValue.create(0x7FFFFFFF & val.getValue(), type); 685 default: 686 throw new Error('glsDrawTests.GLValue.abs - Invalid input type'); 687 } 688 }; 689 690 /** 691 * @return {?glsDrawTests.DrawTestSpec.InputType} 692 */ 693 glsDrawTests.GLValue.prototype.getType = function() { 694 return this.m_type; 695 }; 696 697 /** 698 * glsDrawTests.GLValue.toFloat 699 * @return {number} 700 */ 701 glsDrawTests.GLValue.prototype.toFloat = function() { 702 return this.interpret(); 703 }; 704 705 /** 706 * glsDrawTests.GLValue.getValue 707 * @return {number} 708 */ 709 glsDrawTests.GLValue.prototype.getValue = function() { 710 return this.m_value[0]; 711 }; 712 713 /** 714 * interpret function. Returns the m_value as a quantity so arithmetic operations can be performed on it 715 * Only some types require this. 716 * @return {number} 717 */ 718 glsDrawTests.GLValue.prototype.interpret = function() { 719 if (this.m_type == glsDrawTests.DrawTestSpec.InputType.HALF) 720 return glsDrawTests.GLValue.halfToFloat(this.m_value[0]); 721 722 return this.m_value[0]; 723 }; 724 725 /** 726 * @param {glsDrawTests.GLValue} other 727 * @return {glsDrawTests.GLValue} 728 */ 729 glsDrawTests.GLValue.prototype.add = function(other) { 730 return glsDrawTests.GLValue.create(this.interpret() + other.interpret(), this.m_type); 731 }; 732 733 /** 734 * @param {glsDrawTests.GLValue} other 735 * @return {glsDrawTests.GLValue} 736 */ 737 glsDrawTests.GLValue.prototype.mul = function(other) { 738 return glsDrawTests.GLValue.create(this.interpret() * other.interpret(), this.m_type); 739 }; 740 741 /** 742 * @param {glsDrawTests.GLValue} other 743 * @return {glsDrawTests.GLValue} 744 */ 745 glsDrawTests.GLValue.prototype.div = function(other) { 746 return glsDrawTests.GLValue.create(this.interpret() / other.interpret(), this.m_type); 747 }; 748 749 /** 750 * @param {glsDrawTests.GLValue} other 751 * @return {glsDrawTests.GLValue} 752 */ 753 glsDrawTests.GLValue.prototype.sub = function(other) { 754 return glsDrawTests.GLValue.create(this.interpret() - other.interpret(), this.m_type); 755 }; 756 757 /** 758 * @param {glsDrawTests.GLValue} other 759 * @return {glsDrawTests.GLValue} 760 */ 761 glsDrawTests.GLValue.prototype.addToSelf = function(other) { 762 this.m_value[0] = this.interpret() + other.interpret(); 763 return this; 764 }; 765 766 /** 767 * @param {glsDrawTests.GLValue} other 768 * @return {glsDrawTests.GLValue} 769 */ 770 glsDrawTests.GLValue.prototype.subToSelf = function(other) { 771 this.m_value[0] = this.interpret() - other.interpret(); 772 return this; 773 }; 774 775 /** 776 * @param {glsDrawTests.GLValue} other 777 * @return {glsDrawTests.GLValue} 778 */ 779 glsDrawTests.GLValue.prototype.mulToSelf = function(other) { 780 this.m_value[0] = this.interpret() * other.interpret(); 781 return this; 782 }; 783 784 /** 785 * @param {glsDrawTests.GLValue} other 786 * @return {glsDrawTests.GLValue} 787 */ 788 glsDrawTests.GLValue.prototype.divToSelf = function(other) { 789 this.m_value[0] = this.interpret() / other.interpret(); 790 return this; 791 }; 792 793 /** 794 * @param {glsDrawTests.GLValue} other 795 * @return {boolean} 796 */ 797 glsDrawTests.GLValue.prototype.equals = function(other) { 798 return this.m_value[0] == other.getValue(); 799 }; 800 801 /** 802 * @param {glsDrawTests.GLValue} other 803 * @return {boolean} 804 */ 805 glsDrawTests.GLValue.prototype.lessThan = function(other) { 806 return this.interpret() < other.interpret(); 807 }; 808 809 /** 810 * @param {glsDrawTests.GLValue} other 811 * @return {boolean} 812 */ 813 glsDrawTests.GLValue.prototype.greaterThan = function(other) { 814 return this.interpret() > other.interpret(); 815 }; 816 817 /** 818 * @param {glsDrawTests.GLValue} other 819 * @return {boolean} 820 */ 821 glsDrawTests.GLValue.prototype.lessOrEqualThan = function(other) { 822 return this.interpret() <= other.interpret(); 823 }; 824 825 /** 826 * @param {glsDrawTests.GLValue} other 827 * @return {boolean} 828 */ 829 glsDrawTests.GLValue.prototype.greaterOrEqualThan = function(other) { 830 return this.interpret() >= other.interpret(); 831 }; 832 833 // AttriuteArray 834 835 /** 836 * AttributeArray 837 * @constructor 838 * @param {?glsDrawTests.DrawTestSpec.Storage} storage 839 * @param {sglrGLContext.GLContext | sglrReferenceContext.ReferenceContext} context 840 */ 841 glsDrawTests.AttributeArray = function(storage, context) { 842 /** @type {?glsDrawTests.DrawTestSpec.Storage} */ this.m_storage = storage; 843 /** @type {sglrGLContext.GLContext | sglrReferenceContext.ReferenceContext} */ this.m_ctx = context; 844 /** @type {WebGLBuffer|sglrReferenceContext.DataBuffer|null} */ this.m_glBuffer; 845 846 /** @type {number} */ this.m_size = 0; 847 /** @type {Uint8Array} */ this.m_data; //NOTE: Used in unsupported user storage 848 /** @type {number} */ this.m_componentCount; 849 /** @type {boolean} */ this.m_bound = false; 850 /** @type {glsDrawTests.DrawTestSpec.Target} */ this.m_target = glsDrawTests.DrawTestSpec.Target.ARRAY; 851 /** @type {?glsDrawTests.DrawTestSpec.InputType} */ this.m_inputType = glsDrawTests.DrawTestSpec.InputType.FLOAT; 852 /** @type {?glsDrawTests.DrawTestSpec.OutputType} */ this.m_outputType = glsDrawTests.DrawTestSpec.OutputType.VEC4; 853 /** @type {boolean} */ this.m_normalize = false; 854 /** @type {number} */ this.m_stride = 0; 855 /** @type {number} */ this.m_offset = 0; 856 /** @type {Array<number>} */ this.m_defaultAttrib; 857 /** @type {number} */ this.m_instanceDivisor = 0; 858 /** @type {boolean} */ this.m_isPositionAttr = false; 859 860 if (this.m_storage == glsDrawTests.DrawTestSpec.Storage.BUFFER) { 861 this.m_glBuffer = this.m_ctx.createBuffer(); 862 } 863 }; 864 865 /** @return {number} */ glsDrawTests.AttributeArray.prototype.getComponentCount = function() {return this.m_componentCount;}; 866 867 /** @return {?glsDrawTests.DrawTestSpec.Target} */ glsDrawTests.AttributeArray.prototype.getTarget = function() {return this.m_target;}; 868 869 /** @return {?glsDrawTests.DrawTestSpec.InputType} */ glsDrawTests.AttributeArray.prototype.getInputType = function() {return this.m_inputType;}; 870 871 /** @return {?glsDrawTests.DrawTestSpec.OutputType} */ glsDrawTests.AttributeArray.prototype.getOutputType = function() {return this.m_outputType;}; 872 873 /** @return {?glsDrawTests.DrawTestSpec.Storage} */ glsDrawTests.AttributeArray.prototype.getStorageType = function() {return this.m_storage;}; 874 875 /** @return {boolean} */ glsDrawTests.AttributeArray.prototype.getNormalized = function() {return this.m_normalize;}; 876 877 /** @return {number} */ glsDrawTests.AttributeArray.prototype.getStride = function() {return this.m_stride;}; 878 879 /** @return {boolean} */ glsDrawTests.AttributeArray.prototype.isBound = function() {return this.m_bound;}; 880 881 /** @return {boolean} */ glsDrawTests.AttributeArray.prototype.isPositionAttribute = function() {return this.m_isPositionAttr;}; 882 883 /** 884 * @param {glsDrawTests.DrawTestSpec.Target} target 885 * @param {number} size 886 * @param {goog.TypedArray} ptr 887 * @param {?glsDrawTests.DrawTestSpec.Usage} usage 888 */ 889 glsDrawTests.AttributeArray.prototype.data = function(target, size, ptr, usage) { 890 this.m_size = size; 891 this.m_target = target; 892 893 if (this.m_storage == glsDrawTests.DrawTestSpec.Storage.BUFFER) { 894 this.m_ctx.bindBuffer(glsDrawTests.targetToGL(target), this.m_glBuffer); 895 this.m_ctx.bufferData(glsDrawTests.targetToGL(target), ptr, glsDrawTests.usageToGL(usage)); 896 } else 897 throw new Error('Wrong storage type'); 898 }; 899 900 /** 901 * @param {glsDrawTests.DrawTestSpec.Target} target 902 * @param {number} offset 903 * @param {number} size 904 * @param {goog.TypedArray} ptr 905 */ 906 glsDrawTests.AttributeArray.prototype.subdata = function(target, offset, size, ptr) { 907 this.m_target = target; 908 909 if (this.m_storage == glsDrawTests.DrawTestSpec.Storage.BUFFER) { 910 this.m_ctx.bindBuffer(glsDrawTests.targetToGL(target), this.m_glBuffer); 911 912 this.m_ctx.bufferSubData(glsDrawTests.targetToGL(target), offset, size, ptr); 913 } else 914 throw new Error('Wrong storage type'); 915 }; 916 917 /** 918 * @param {boolean} bound 919 * @param {number} offset 920 * @param {number} size 921 * @param {?glsDrawTests.DrawTestSpec.InputType} inputType 922 * @param {?glsDrawTests.DrawTestSpec.OutputType} outType 923 * @param {boolean} normalized 924 * @param {number} stride 925 * @param {number} instanceDivisor 926 * @param {Array<number>} defaultAttrib 927 * @param {boolean} isPositionAttr 928 */ 929 glsDrawTests.AttributeArray.prototype.setupArray = function(bound, offset, size, inputType, outType, 930 normalized, stride, instanceDivisor, defaultAttrib, isPositionAttr) { 931 this.m_componentCount = size; 932 this.m_bound = bound; 933 this.m_inputType = inputType; 934 this.m_outputType = outType; 935 this.m_normalize = normalized; 936 this.m_stride = stride; 937 this.m_offset = offset; 938 this.m_defaultAttrib = defaultAttrib; 939 this.m_instanceDivisor = instanceDivisor; 940 this.m_isPositionAttr = isPositionAttr; 941 }; 942 943 /** 944 * @param {number} loc (32-bit) 945 */ 946 glsDrawTests.AttributeArray.prototype.bindAttribute = function(loc) { 947 if (!this.isBound()) { 948 /** @type {Array<number>} */ var attr = this.m_defaultAttrib; 949 switch (this.m_inputType) { 950 case glsDrawTests.DrawTestSpec.InputType.FLOAT: { 951 switch (this.m_componentCount) { 952 case 1: this.m_ctx.vertexAttrib1f(loc, attr[0]); break; 953 case 2: this.m_ctx.vertexAttrib2f(loc, attr[0], attr[1]); break; 954 case 3: this.m_ctx.vertexAttrib3f(loc, attr[0], attr[1], attr[2]); break; 955 case 4: this.m_ctx.vertexAttrib4f(loc, attr[0], attr[1], attr[2], attr[3]); break; 956 default: throw new Error('Invalid component count'); break; 957 } 958 break; 959 } 960 case glsDrawTests.DrawTestSpec.InputType.INT: { 961 this.m_ctx.vertexAttribI4i(loc, attr[0], attr[1], attr[2], attr[3]); 962 break; 963 } 964 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT: { 965 this.m_ctx.vertexAttribI4ui(loc, attr[0], attr[1], attr[2], attr[3]); 966 break; 967 } 968 default: 969 throw new Error('Invalid input type'); 970 break; 971 } 972 } else { 973 /** @type {Uint8Array} */ var basePtr = null; 974 975 if (this.m_storage == glsDrawTests.DrawTestSpec.Storage.BUFFER) { 976 this.m_ctx.bindBuffer(glsDrawTests.targetToGL(this.m_target), this.m_glBuffer); 977 978 basePtr = null; 979 } else 980 throw new Error('Invalid storage type'); 981 982 if (!glsDrawTests.inputTypeIsFloatType(this.m_inputType)) { 983 // Input is not float type 984 985 if (glsDrawTests.outputTypeIsFloatType(this.m_outputType)) { 986 var size = this.m_componentCount; 987 988 // Output type is float type 989 this.m_ctx.vertexAttribPointer(loc, size, glsDrawTests.inputTypeToGL(this.m_inputType), this.m_normalize, this.m_stride, this.m_offset); 990 } else { 991 // Output type is int type 992 this.m_ctx.vertexAttribIPointer(loc, this.m_componentCount, glsDrawTests.inputTypeToGL(this.m_inputType), this.m_stride, this.m_offset); 993 } 994 } else { 995 // Input type is float type 996 997 // Output type must be float type 998 assertMsgOptions(glsDrawTests.outputTypeIsFloatType(this.m_outputType), 'Output type is not float', false, true); 999 1000 this.m_ctx.vertexAttribPointer(loc, this.m_componentCount, glsDrawTests.inputTypeToGL(this.m_inputType), this.m_normalize, 1001 this.m_stride, this.m_offset); 1002 } 1003 1004 if (this.m_instanceDivisor) 1005 this.m_ctx.vertexAttribDivisor(loc, this.m_instanceDivisor); 1006 } 1007 }; 1008 1009 /** 1010 * @param {glsDrawTests.DrawTestSpec.Target} target 1011 */ 1012 glsDrawTests.AttributeArray.prototype.bindIndexArray = function(target) { 1013 if (this.m_storage == glsDrawTests.DrawTestSpec.Storage.BUFFER) { 1014 this.m_ctx.bindBuffer(glsDrawTests.targetToGL(target), this.m_glBuffer); 1015 } 1016 }; 1017 1018 // DrawTestShaderProgram 1019 1020 /** 1021 * @constructor 1022 * @extends {sglrShaderProgram.ShaderProgram} 1023 * @param {Array<glsDrawTests.AttributeArray>} arrays 1024 */ 1025 glsDrawTests.DrawTestShaderProgram = function(arrays) { 1026 sglrShaderProgram.ShaderProgram.call(this, this.createProgramDeclaration(arrays)); 1027 1028 this.m_componentCount = []; 1029 this.m_isCoord = []; 1030 this.m_attrType = []; 1031 1032 for (var arrayNdx = 0; arrayNdx < arrays.length; arrayNdx++) { 1033 this.m_componentCount[arrayNdx] = this.getComponentCount(arrays[arrayNdx].getOutputType()); 1034 this.m_isCoord[arrayNdx] = arrays[arrayNdx].isPositionAttribute(); 1035 this.m_attrType[arrayNdx] = this.mapOutputType(arrays[arrayNdx].getOutputType()); 1036 } 1037 }; 1038 1039 glsDrawTests.DrawTestShaderProgram.prototype = Object.create(sglrShaderProgram.ShaderProgram.prototype); 1040 glsDrawTests.DrawTestShaderProgram.prototype.constructor = glsDrawTests.DrawTestShaderProgram; 1041 1042 /** 1043 * @param {Array<number>} color 1044 * @param {goog.NumberArray} attribValue 1045 * @param {number} numComponents 1046 * @return {Array<number>} 1047 */ 1048 glsDrawTests.calcShaderColor = function(color, attribValue, numComponents) { 1049 switch (numComponents) { 1050 case 1: 1051 color[0] = deMath.scale(color, attribValue[0])[0]; 1052 break; 1053 1054 case 2: 1055 color[0] = color[0] * attribValue[0]; 1056 color[1] = color[1] * attribValue[1]; 1057 break; 1058 1059 case 3: 1060 color[0] = color[0] * attribValue[0]; 1061 color[1] = color[1] * attribValue[1]; 1062 color[2] = color[2] * attribValue[2]; 1063 break; 1064 1065 case 4: 1066 color[0] = color[0] * attribValue[0] * attribValue[3]; 1067 color[1] = color[1] * attribValue[1] * attribValue[3]; 1068 color[2] = color[2] * attribValue[2] * attribValue[3]; 1069 break; 1070 1071 default: 1072 throw new Error('Invalid component count'); 1073 } 1074 1075 return color; 1076 }; 1077 1078 /** 1079 * @param {Array<number>} coord 1080 * @param {goog.NumberArray} attribValue 1081 * @param {number} numComponents 1082 * @return {Array<number>} 1083 */ 1084 glsDrawTests.calcShaderCoord = function(coord, attribValue, numComponents) { 1085 switch (numComponents) { 1086 case 1: 1087 1088 coord = deMath.add(coord, [attribValue[0], attribValue[0]]); 1089 coord[0] = coord[0]; 1090 coord[1] = coord[1]; 1091 break; 1092 case 2: 1093 coord = deMath.add(coord, [attribValue[0], attribValue[1]]); 1094 coord[0] = coord[0]; 1095 coord[1] = coord[1]; 1096 break; 1097 case 3: 1098 coord = deMath.add(coord, [attribValue[0] + attribValue[2], attribValue[1]]); 1099 coord[0] = coord[0]; 1100 coord[1] = coord[1]; 1101 coord[2] = coord[2]; 1102 break; 1103 case 4: 1104 coord = deMath.add(coord, [attribValue[0] + attribValue[2], attribValue[1] + attribValue[3]]); 1105 coord[0] = coord[0]; 1106 coord[1] = coord[1]; 1107 coord[2] = coord[2]; 1108 coord[3] = coord[3]; 1109 break; 1110 1111 default: 1112 throw new Error('Invalid component count'); 1113 } 1114 1115 return coord; 1116 }; 1117 1118 /** 1119 * @param {Array<rrVertexAttrib.VertexAttrib>} inputs 1120 * @param {Array<rrVertexPacket.VertexPacket>} packets 1121 * @param {number} numPackets 1122 */ 1123 glsDrawTests.DrawTestShaderProgram.prototype.shadeVertices = function(inputs, packets, numPackets) { 1124 var u_coordScale = this.getUniformByName('u_coordScale').value; 1125 var u_colorScale = this.getUniformByName('u_colorScale').value; 1126 1127 for (var packetNdx = 0; packetNdx < numPackets; ++packetNdx) { 1128 var varyingLocColor = 0; 1129 1130 /** @type {rrVertexPacket.VertexPacket} */ var packet = packets[packetNdx]; 1131 1132 // Calc output color 1133 /** @type {Array<number>} */ var coord = [0.0, 0.0]; 1134 /** @type {Array<number>} */ var color = [1.0, 1.0, 1.0]; 1135 1136 for (var attribNdx = 0; attribNdx < this.m_attrType.length; attribNdx++) { 1137 var numComponents = this.m_componentCount[attribNdx]; 1138 /** @type {boolean} */ var isCoord = this.m_isCoord[attribNdx]; 1139 1140 var attrib = rrVertexAttrib.readVertexAttrib(inputs[attribNdx], packet.instanceNdx, packet.vertexNdx, this.m_attrType[attribNdx]); 1141 1142 if (isCoord) { 1143 coord = glsDrawTests.calcShaderCoord( 1144 coord, 1145 attrib, 1146 numComponents 1147 ); 1148 } else { 1149 color = glsDrawTests.calcShaderColor( 1150 color, 1151 attrib, 1152 numComponents 1153 ); 1154 } 1155 } 1156 1157 // Transform position 1158 packet.position = [u_coordScale * coord[0], u_coordScale * coord[1], 1.0, 1.0]; 1159 packet.pointSize = 1.0; 1160 1161 // Pass color to FS 1162 packet.outputs[varyingLocColor] = deMath.add(deMath.scale([u_colorScale * color[0], u_colorScale * color[1], u_colorScale * color[2], 1.0], 0.5), [0.5, 0.5, 0.5, 0.5]); 1163 } 1164 }; 1165 1166 /** 1167 * @param {Array<rrFragmentOperations.Fragment>} packets 1168 * @param {rrShadingContext.FragmentShadingContext} context 1169 */ 1170 glsDrawTests.DrawTestShaderProgram.prototype.shadeFragments = function(packets, context) { 1171 var varyingLocColor = 0; 1172 1173 for (var packetNdx = 0; packetNdx < packets.length; ++packetNdx) { 1174 /** @type {rrFragmentOperations.Fragment} */ var packet = packets[packetNdx]; 1175 packet.value = rrShadingContext.readVarying(packet, context, varyingLocColor); 1176 } 1177 }; 1178 1179 /** 1180 * @param {Array<glsDrawTests.AttributeArray>} arrays 1181 * @return {string} 1182 */ 1183 glsDrawTests.DrawTestShaderProgram.prototype.genVertexSource = function(arrays) { 1184 /** @type {Array<string>}*/ var params; 1185 var vertexShaderTmpl = ''; 1186 1187 params = this.generateShaderParams(); 1188 1189 vertexShaderTmpl += params['VTX_HDR']; 1190 1191 for (var arrayNdx = 0; arrayNdx < arrays.length; arrayNdx++) { 1192 vertexShaderTmpl += params['VTX_IN'] + ' highp ' + glsDrawTests.outputTypeToGLType(arrays[arrayNdx].getOutputType()) + ' a_' + arrayNdx + ';\n'; 1193 } 1194 1195 vertexShaderTmpl += 1196 'uniform highp float u_coordScale;\n' + 1197 'uniform highp float u_colorScale;\n' + 1198 params['VTX_OUT'] + ' ' + params['COL_PRECISION'] + ' vec4 v_color;\n' + 1199 'void main(void)\n' + 1200 '{\n' + 1201 '\tgl_PointSize = 1.0;\n' + 1202 '\thighp vec2 coord = vec2(0.0, 0.0);\n' + 1203 '\thighp vec3 color = vec3(1.0, 1.0, 1.0);\n'; 1204 1205 for (var arrayNdx = 0; arrayNdx < arrays.length; arrayNdx++) { 1206 var isPositionAttr = arrays[arrayNdx].isPositionAttribute(); 1207 1208 if (isPositionAttr) { 1209 switch (arrays[arrayNdx].getOutputType()) { 1210 case glsDrawTests.DrawTestSpec.OutputType.FLOAT: 1211 case glsDrawTests.DrawTestSpec.OutputType.INT: 1212 case glsDrawTests.DrawTestSpec.OutputType.UINT: 1213 vertexShaderTmpl += 1214 '\tcoord += vec2(float(a_' + arrayNdx + '), float(a_' + arrayNdx + '));\n'; 1215 break; 1216 1217 case glsDrawTests.DrawTestSpec.OutputType.VEC2: 1218 case glsDrawTests.DrawTestSpec.OutputType.IVEC2: 1219 case glsDrawTests.DrawTestSpec.OutputType.UVEC2: 1220 vertexShaderTmpl += 1221 '\tcoord += vec2(a_' + arrayNdx + '.xy);\n'; 1222 break; 1223 1224 case glsDrawTests.DrawTestSpec.OutputType.VEC3: 1225 case glsDrawTests.DrawTestSpec.OutputType.IVEC3: 1226 case glsDrawTests.DrawTestSpec.OutputType.UVEC3: 1227 vertexShaderTmpl += 1228 '\tcoord += vec2(a_' + arrayNdx + '.xy);\n' + 1229 '\tcoord.x += float(a_' + arrayNdx + '.z);\n'; 1230 break; 1231 1232 case glsDrawTests.DrawTestSpec.OutputType.VEC4: 1233 case glsDrawTests.DrawTestSpec.OutputType.IVEC4: 1234 case glsDrawTests.DrawTestSpec.OutputType.UVEC4: 1235 vertexShaderTmpl += 1236 '\tcoord += vec2(a_' + arrayNdx + '.xy);\n' + 1237 '\tcoord += vec2(a_' + arrayNdx + '.zw);\n'; 1238 break; 1239 1240 default: 1241 throw new Error('Invalid output type'); 1242 break; 1243 } 1244 } else { 1245 switch (arrays[arrayNdx].getOutputType()) { 1246 case glsDrawTests.DrawTestSpec.OutputType.FLOAT: 1247 case glsDrawTests.DrawTestSpec.OutputType.INT: 1248 case glsDrawTests.DrawTestSpec.OutputType.UINT: 1249 vertexShaderTmpl += 1250 '\tcolor = color * float(a_' + arrayNdx + ');\n'; 1251 break; 1252 1253 case glsDrawTests.DrawTestSpec.OutputType.VEC2: 1254 case glsDrawTests.DrawTestSpec.OutputType.IVEC2: 1255 case glsDrawTests.DrawTestSpec.OutputType.UVEC2: 1256 vertexShaderTmpl += 1257 '\tcolor.rg = color.rg * vec2(a_' + arrayNdx + '.xy);\n'; 1258 break; 1259 1260 case glsDrawTests.DrawTestSpec.OutputType.VEC3: 1261 case glsDrawTests.DrawTestSpec.OutputType.IVEC3: 1262 case glsDrawTests.DrawTestSpec.OutputType.UVEC3: 1263 vertexShaderTmpl += 1264 '\tcolor = color.rgb * vec3(a_' + arrayNdx + '.xyz);\n'; 1265 break; 1266 1267 case glsDrawTests.DrawTestSpec.OutputType.VEC4: 1268 case glsDrawTests.DrawTestSpec.OutputType.IVEC4: 1269 case glsDrawTests.DrawTestSpec.OutputType.UVEC4: 1270 vertexShaderTmpl += 1271 '\tcolor = color.rgb * vec3(a_' + arrayNdx + '.xyz) * float(a_' + arrayNdx + '.w);\n'; 1272 break; 1273 1274 default: 1275 throw new Error('Invalid output type'); 1276 break; 1277 } 1278 } 1279 } 1280 1281 vertexShaderTmpl += 1282 '\tv_color = vec4(u_colorScale * color, 1.0) * 0.5 + vec4(0.5, 0.5, 0.5, 0.5);\n' + 1283 '\tgl_Position = vec4(u_coordScale * coord, 1.0, 1.0);\n' + 1284 '}\n'; 1285 1286 return vertexShaderTmpl; 1287 }; 1288 1289 /** 1290 * @return {string} 1291 */ 1292 glsDrawTests.DrawTestShaderProgram.prototype.genFragmentSource = function() { 1293 /** @type {Array<string>} */ var params; 1294 1295 params = this.generateShaderParams(); 1296 1297 var fragmentShaderTmpl = params['FRAG_HDR'] + 1298 params['FRAG_IN'] + ' ' + params['COL_PRECISION'] + ' vec4 v_color;\n' + 1299 'void main(void)\n' + 1300 '{\n' + 1301 '\t' + params['FRAG_COLOR'] + '= v_color;\n' + 1302 '}\n'; 1303 1304 return fragmentShaderTmpl; 1305 }; 1306 1307 /** 1308 * @return {Array<string>} 1309 */ 1310 glsDrawTests.DrawTestShaderProgram.prototype.generateShaderParams = function() { 1311 /** @type {Array<string>} */ var params = []; 1312 if (gluShaderUtil.isGLSLVersionSupported(gl, gluShaderUtil.GLSLVersion.V300_ES)) { 1313 params['VTX_IN'] = 'in'; 1314 params['VTX_OUT'] = 'out'; 1315 params['FRAG_IN'] = 'in'; 1316 params['FRAG_COLOR'] = 'dEQP_FragColor'; 1317 params['VTX_HDR'] = '#version 300 es\n'; 1318 params['FRAG_HDR'] = '#version 300 es\nlayout(location = 0) out mediump vec4 dEQP_FragColor;\n'; 1319 params['COL_PRECISION'] = 'mediump'; 1320 } else if (gluShaderUtil.isGLSLVersionSupported(gl, gluShaderUtil.GLSLVersion.V100_ES)) { 1321 params['VTX_IN'] = 'attribute'; 1322 params['VTX_OUT'] = 'varying'; 1323 params['FRAG_IN'] = 'varying'; 1324 params['FRAG_COLOR'] = 'gl_FragColor'; 1325 params['VTX_HDR'] = ''; 1326 params['FRAG_HDR'] = ''; 1327 params['COL_PRECISION'] = 'mediump'; 1328 } else 1329 throw new Error('Invalid GL version'); 1330 1331 return params; 1332 }; 1333 1334 /** 1335 * @param {?glsDrawTests.DrawTestSpec.OutputType} type 1336 * @return {rrGenericVector.GenericVecType} 1337 */ 1338 glsDrawTests.DrawTestShaderProgram.prototype.mapOutputType = function(type) { 1339 switch (type) { 1340 case glsDrawTests.DrawTestSpec.OutputType.FLOAT: 1341 case glsDrawTests.DrawTestSpec.OutputType.VEC2: 1342 case glsDrawTests.DrawTestSpec.OutputType.VEC3: 1343 case glsDrawTests.DrawTestSpec.OutputType.VEC4: 1344 return rrGenericVector.GenericVecType.FLOAT; 1345 1346 case glsDrawTests.DrawTestSpec.OutputType.INT: 1347 case glsDrawTests.DrawTestSpec.OutputType.IVEC2: 1348 case glsDrawTests.DrawTestSpec.OutputType.IVEC3: 1349 case glsDrawTests.DrawTestSpec.OutputType.IVEC4: 1350 return rrGenericVector.GenericVecType.INT32; 1351 1352 case glsDrawTests.DrawTestSpec.OutputType.UINT: 1353 case glsDrawTests.DrawTestSpec.OutputType.UVEC2: 1354 case glsDrawTests.DrawTestSpec.OutputType.UVEC3: 1355 case glsDrawTests.DrawTestSpec.OutputType.UVEC4: 1356 return rrGenericVector.GenericVecType.UINT32; 1357 1358 default: 1359 throw new Error('Invalid output type'); 1360 } 1361 }; 1362 1363 /** 1364 * @param {?glsDrawTests.DrawTestSpec.OutputType} type 1365 * @return {number} 1366 */ 1367 glsDrawTests.DrawTestShaderProgram.prototype.getComponentCount = function(type) { 1368 switch (type) { 1369 case glsDrawTests.DrawTestSpec.OutputType.FLOAT: 1370 case glsDrawTests.DrawTestSpec.OutputType.INT: 1371 case glsDrawTests.DrawTestSpec.OutputType.UINT: 1372 return 1; 1373 1374 case glsDrawTests.DrawTestSpec.OutputType.VEC2: 1375 case glsDrawTests.DrawTestSpec.OutputType.IVEC2: 1376 case glsDrawTests.DrawTestSpec.OutputType.UVEC2: 1377 return 2; 1378 1379 case glsDrawTests.DrawTestSpec.OutputType.VEC3: 1380 case glsDrawTests.DrawTestSpec.OutputType.IVEC3: 1381 case glsDrawTests.DrawTestSpec.OutputType.UVEC3: 1382 return 3; 1383 1384 case glsDrawTests.DrawTestSpec.OutputType.VEC4: 1385 case glsDrawTests.DrawTestSpec.OutputType.IVEC4: 1386 case glsDrawTests.DrawTestSpec.OutputType.UVEC4: 1387 return 4; 1388 1389 default: 1390 throw new Error('Invalid output type'); 1391 } 1392 }; 1393 1394 /** 1395 * @param {Array<glsDrawTests.AttributeArray>} arrays 1396 * @return {sglrShaderProgram.ShaderProgramDeclaration} 1397 */ 1398 glsDrawTests.DrawTestShaderProgram.prototype.createProgramDeclaration = function(arrays) { 1399 /** @type {sglrShaderProgram.ShaderProgramDeclaration} */ var decl = new sglrShaderProgram.ShaderProgramDeclaration(); 1400 1401 for (var arrayNdx = 0; arrayNdx < arrays.length; arrayNdx++) 1402 decl.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('a_' + arrayNdx, this.mapOutputType(arrays[arrayNdx].getOutputType()))); 1403 1404 decl.pushVertexToFragmentVarying(new sglrShaderProgram.VertexToFragmentVarying(rrGenericVector.GenericVecType.FLOAT)); 1405 decl.pushFragmentOutput(new sglrShaderProgram.FragmentOutput(rrGenericVector.GenericVecType.FLOAT)); 1406 1407 decl.pushVertexSource(new sglrShaderProgram.VertexSource(this.genVertexSource(arrays))); 1408 decl.pushFragmentSource(new sglrShaderProgram.FragmentSource(this.genFragmentSource())); 1409 1410 decl.pushUniform(new sglrShaderProgram.Uniform('u_coordScale', gluShaderUtil.DataType.FLOAT)); 1411 decl.pushUniform(new sglrShaderProgram.Uniform('u_colorScale', gluShaderUtil.DataType.FLOAT)); 1412 1413 return decl; 1414 }; 1415 1416 /** 1417 * @typedef {glsDrawTests.RandomArrayGenerator} 1418 */ 1419 glsDrawTests.RandomArrayGenerator = {}; 1420 1421 /** 1422 * @param {goog.TypedArray} data 1423 * @param {?glsDrawTests.DrawTestSpec.InputType} type 1424 * @param {deRandom.Random} rnd 1425 * @param {glsDrawTests.GLValue} min 1426 * @param {glsDrawTests.GLValue} max 1427 */ 1428 glsDrawTests.RandomArrayGenerator.setData = function(data, type, rnd, min, max) { 1429 switch (type) { 1430 case glsDrawTests.DrawTestSpec.InputType.FLOAT: 1431 case glsDrawTests.DrawTestSpec.InputType.SHORT: 1432 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_SHORT: 1433 case glsDrawTests.DrawTestSpec.InputType.BYTE: 1434 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_BYTE: 1435 case glsDrawTests.DrawTestSpec.InputType.INT: 1436 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT: 1437 case glsDrawTests.DrawTestSpec.InputType.HALF: 1438 glsDrawTests.copyGLValueToArray(data, glsDrawTests.GLValue.getRandom(rnd, min, max)); 1439 break; 1440 default: 1441 throw new Error('Invalid input type'); 1442 } 1443 }; 1444 1445 /** 1446 * createBasicArray 1447 * @param {number} seed 1448 * @param {number} elementCount 1449 * @param {number} componentCount 1450 * @param {number} offset 1451 * @param {number} stride 1452 * @param {?glsDrawTests.DrawTestSpec.InputType} type 1453 * @param {number} first 1454 * @param {?glsDrawTests.DrawTestSpec.Primitive} primitive 1455 * @param {?goog.TypedArray} indices 1456 * @param {number} indexSize 1457 * @return {goog.TypedArray} 1458 */ 1459 glsDrawTests.RandomArrayGenerator.createArray = function(seed, elementCount, componentCount, offset, stride, type, first, primitive, indices, indexSize) { 1460 assertMsgOptions(componentCount >= 1 && componentCount <= 4, 'Unacceptable number of components', false, true); 1461 1462 /** @type {glsDrawTests.GLValue} */ var min = glsDrawTests.GLValue.getMinValue(type); 1463 /** @type {glsDrawTests.GLValue} */ var max = glsDrawTests.GLValue.getMaxValue(type); 1464 1465 var packed = type == glsDrawTests.DrawTestSpec.InputType.INT_2_10_10_10 || 1466 type == glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT_2_10_10_10; 1467 /** @type {number} */ var limit10 = (1 << 10); 1468 /** @type {number} */ var limit2 = (1 << 2); 1469 1470 1471 /** @type {number} */ var componentSize = glsDrawTests.DrawTestSpec.inputTypeSize(type); 1472 /** @type {number} */ var elementSize = componentSize * componentCount; 1473 /** @type {number} */ var bufferSize = offset + Math.max(elementCount * stride, elementCount * elementSize); 1474 1475 var data = new ArrayBuffer(bufferSize); 1476 var writePtr = new Uint8Array(data, offset); 1477 1478 var previousComponentsFloat = [0, 0, 0, 0]; 1479 var rnd = new deRandom.Random(seed); 1480 1481 for (var vertexNdx = 0; vertexNdx < elementCount; vertexNdx++) { 1482 var components = []; 1483 1484 for (var componentNdx = 0; componentNdx < componentCount; componentNdx++) { 1485 var getRandomComponent = function() { 1486 // For packed formats we can't use GLValue 1487 if (packed) { 1488 if (componentNdx == 3) { 1489 return rnd.getInt() % limit2; 1490 } else { 1491 return rnd.getInt() % limit10; 1492 } 1493 } else { 1494 return glsDrawTests.GLValue.getRandom(rnd, min, max); 1495 } 1496 }; 1497 1498 var component = getRandomComponent(); 1499 var componentFloat = (component instanceof glsDrawTests.GLValue) ? component.toFloat() : component; 1500 1501 // Try to not create vertex near previous 1502 if (vertexNdx != 0 && Math.abs(componentFloat - previousComponentsFloat[componentNdx]) < min.toFloat()) { 1503 // Too close, try again (but only once) 1504 component = getRandomComponent(); 1505 componentFloat = (component instanceof glsDrawTests.GLValue) ? component.toFloat() : component; 1506 } 1507 1508 components.push(component); 1509 previousComponentsFloat[componentNdx] = componentFloat; 1510 } 1511 1512 if (packed) { 1513 var packedValue = deMath.binaryOp( 1514 deMath.shiftLeft(/** @type {Array<number>} */ (components)[3], 30), deMath.binaryOp( 1515 deMath.shiftLeft(/** @type {Array<number>} */ (components)[2], 20), deMath.binaryOp( 1516 deMath.shiftLeft(/** @type {Array<number>} */ (components)[1], 10), /** @type {Array<number>} */ (components)[0], deMath.BinaryOp.OR 1517 ), deMath.BinaryOp.OR 1518 ), deMath.BinaryOp.OR 1519 ); 1520 glsDrawTests.copyArray(writePtr, new Uint32Array([packedValue])); 1521 } else { 1522 for (var componentNdx = 0; componentNdx < componentCount; componentNdx++) { 1523 glsDrawTests.copyGLValueToArray(writePtr.subarray(componentNdx * componentSize), components[componentNdx]); 1524 } 1525 } 1526 1527 writePtr = writePtr.subarray(stride); 1528 } 1529 1530 return new Uint8Array(data); 1531 }; 1532 1533 /** 1534 * @param {number} seed 1535 * @param {number} elementCount 1536 * @param {?glsDrawTests.DrawTestSpec.IndexType} type 1537 * @param {number} offset 1538 * @param {number} min 1539 * @param {number} max 1540 * @return {goog.TypedArray} 1541 */ 1542 glsDrawTests.RandomArrayGenerator.generateIndices = function(seed, elementCount, type, offset, min, max) { 1543 return glsDrawTests.RandomArrayGenerator.createIndices(seed, elementCount, offset, min, max, type); 1544 }; 1545 1546 /** 1547 * @param {number} seed 1548 * @param {number} elementCount 1549 * @param {number} offset 1550 * @param {number} min 1551 * @param {number} max 1552 * @param {?glsDrawTests.DrawTestSpec.IndexType} type 1553 * @return {goog.TypedArray} 1554 */ 1555 glsDrawTests.RandomArrayGenerator.createIndices = function(seed, elementCount, offset, min, max, type) { 1556 /** @type {number}*/ var elementSize = glsDrawTests.DrawTestSpec.indexTypeSize(type); 1557 /** @type {number}*/ var bufferSize = offset + elementCount * elementSize; 1558 1559 var data = new ArrayBuffer(bufferSize); 1560 var writePtr = new Uint8Array(data).subarray(offset); 1561 1562 var rnd = new deRandom.Random(seed); 1563 1564 /* TODO: get limits for given index type --> if (min < 0 || min > std::numeric_limits<T>::max() || 1565 max < 0 || max > std::numeric_limits<T>::max() || 1566 min > max) 1567 DE_ASSERT(!"Invalid range");*/ 1568 1569 // JS refrast requires shuffled unique keys 1570 var keys = []; 1571 for (var key = 0; key < elementCount; key++) 1572 keys.push(glsDrawTests.GLValue.create(key, glsDrawTests.indexTypeToInputType(type))); 1573 1574 for (var elementNdx = 0; elementNdx < elementCount; ++elementNdx) { 1575 var randomkey = rnd.getInt(0, keys.length - 1); 1576 var ndx = keys[randomkey]; 1577 1578 keys.splice(randomkey, 1); 1579 1580 glsDrawTests.copyArray( 1581 writePtr.subarray(elementSize * elementNdx), 1582 new Uint8Array(ndx.m_value.buffer) 1583 ); 1584 } 1585 1586 return new Uint8Array(data); 1587 }; 1588 1589 /** 1590 * @param {number} seed 1591 * @param {?glsDrawTests.DrawTestSpec.InputType} type 1592 * @return {Array<number>} 1593 */ 1594 glsDrawTests.RandomArrayGenerator.generateAttributeValue = function(seed, type) { 1595 var random = new deRandom.Random(seed); 1596 1597 switch (type) { 1598 case glsDrawTests.DrawTestSpec.InputType.FLOAT: 1599 return glsDrawTests.generateRandomVec4(random); 1600 1601 case glsDrawTests.DrawTestSpec.InputType.INT: 1602 return glsDrawTests.generateRandomIVec4(random); 1603 1604 case glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT: 1605 return glsDrawTests.generateRandomUVec4(random); 1606 1607 default: 1608 throw new Error('Invalid attribute type'); 1609 } 1610 }; 1611 1612 // AttributePack 1613 1614 /** 1615 * @param {sglrReferenceContext.ReferenceContext | sglrGLContext.GLContext} drawContext 1616 * @param {Array<number>} screenSize (2 positive elements in array) 1617 * @param {boolean} useVao 1618 * @param {boolean} logEnabled 1619 * @constructor 1620 */ 1621 glsDrawTests.AttributePack = function(drawContext, screenSize, useVao, logEnabled) { 1622 /** @type {sglrReferenceContext.ReferenceContext | sglrGLContext.GLContext} */ this.m_ctx = drawContext; 1623 1624 /** @type {Array<glsDrawTests.AttributeArray>} */ this.m_arrays = []; 1625 /** @type {sglrShaderProgram.ShaderProgram} */ this.m_program; 1626 /** @type {tcuSurface.Surface} */ this.m_screen = new tcuSurface.Surface(screenSize[0], screenSize[1]); 1627 /** @type {boolean} */ this.m_useVao = useVao; 1628 /** @type {boolean} */ this.m_logEnabled = logEnabled; 1629 /** @type {WebGLProgram | sglrShaderProgram.ShaderProgram | null} */ this.m_programID = null; 1630 /** @type {WebGLVertexArrayObject|sglrReferenceContext.VertexArray|null} */ this.m_vaoID = null; 1631 1632 if (this.m_useVao) 1633 this.m_vaoID = this.m_ctx.createVertexArray(); 1634 }; 1635 1636 /** 1637 * @return {tcuSurface.Surface} 1638 */ 1639 glsDrawTests.AttributePack.prototype.getSurface = function() { 1640 return this.m_screen; 1641 }; 1642 1643 /** 1644 * @param {number} i 1645 * @return {glsDrawTests.AttributeArray} 1646 */ 1647 glsDrawTests.AttributePack.prototype.getArray = function(i) { 1648 return this.m_arrays[i]; 1649 }; 1650 1651 /** 1652 * @return number 1653 */ 1654 glsDrawTests.AttributePack.prototype.getArrayCount = function() { 1655 return this.m_arrays.length; 1656 }; 1657 1658 /** 1659 * @param {?glsDrawTests.DrawTestSpec.Storage} storage 1660 */ 1661 glsDrawTests.AttributePack.prototype.newArray = function(storage) { 1662 this.m_arrays.push(new glsDrawTests.AttributeArray(storage, this.m_ctx)); 1663 }; 1664 1665 /** 1666 * clearArrays 1667 */ 1668 glsDrawTests.AttributePack.prototype.clearArrays = function() { 1669 this.m_arrays.length = 0; 1670 }; 1671 1672 /** 1673 * updateProgram 1674 */ 1675 glsDrawTests.AttributePack.prototype.updateProgram = function() { 1676 if (this.m_programID) 1677 this.m_ctx.deleteProgram(this.m_programID); 1678 1679 this.m_program = new glsDrawTests.DrawTestShaderProgram(this.m_arrays); 1680 this.m_programID = this.m_ctx.createProgram(this.m_program); 1681 }; 1682 1683 /** 1684 * @param {?glsDrawTests.DrawTestSpec.Primitive} primitive 1685 * @param {?glsDrawTests.DrawTestSpec.DrawMethod} drawMethod 1686 * @param {number} firstVertex 1687 * @param {number} vertexCount 1688 * @param {?glsDrawTests.DrawTestSpec.IndexType} indexType 1689 * @param {number} indexOffset 1690 * @param {number} rangeStart 1691 * @param {number} rangeEnd 1692 * @param {number} instanceCount 1693 * @param {number} coordScale 1694 * @param {number} colorScale 1695 * @param {glsDrawTests.AttributeArray} indexArray 1696 */ 1697 glsDrawTests.AttributePack.prototype.render = function(primitive, drawMethod, firstVertex, vertexCount, indexType, 1698 indexOffset, rangeStart, rangeEnd, instanceCount, coordScale, colorScale, indexArray) { 1699 assertMsgOptions(this.m_program != null, 'Program is null', false, true); 1700 assertMsgOptions(this.m_programID != null, 'No context created program', false, true); 1701 1702 this.m_ctx.viewport(0, 0, this.m_screen.getWidth(), this.m_screen.getHeight()); 1703 this.m_ctx.clearColor(0.0, 0.0, 0.0, 1.0); 1704 this.m_ctx.clear(gl.COLOR_BUFFER_BIT); 1705 1706 this.m_ctx.useProgram(this.m_programID); 1707 1708 this.m_ctx.uniform1f(this.m_ctx.getUniformLocation(this.m_programID, 'u_coordScale'), coordScale); 1709 this.m_ctx.uniform1f(this.m_ctx.getUniformLocation(this.m_programID, 'u_colorScale'), colorScale); 1710 1711 if (this.m_useVao) 1712 this.m_ctx.bindVertexArray(this.m_vaoID); 1713 1714 if (indexArray) 1715 indexArray.bindIndexArray(glsDrawTests.DrawTestSpec.Target.ELEMENT_ARRAY); 1716 1717 for (var arrayNdx = 0; arrayNdx < this.m_arrays.length; arrayNdx++) { 1718 var attribName = ''; 1719 attribName += 'a_' + arrayNdx; 1720 1721 var loc = this.m_ctx.getAttribLocation(this.m_programID, attribName); 1722 1723 if (this.m_arrays[arrayNdx].isBound()) 1724 this.m_ctx.enableVertexAttribArray(loc); 1725 1726 this.m_arrays[arrayNdx].bindAttribute(loc); 1727 } 1728 1729 if (drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWARRAYS) 1730 this.m_ctx.drawArrays(glsDrawTests.primitiveToGL(primitive), firstVertex, vertexCount); 1731 else if (drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWARRAYS_INSTANCED) 1732 this.m_ctx.drawArraysInstanced(glsDrawTests.primitiveToGL(primitive), firstVertex, vertexCount, instanceCount); 1733 else if (drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWELEMENTS) 1734 this.m_ctx.drawElements(glsDrawTests.primitiveToGL(primitive), vertexCount, glsDrawTests.indexTypeToGL(indexType), indexOffset); 1735 else if (drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWELEMENTS_RANGED) 1736 this.m_ctx.drawRangeElements(glsDrawTests.primitiveToGL(primitive), rangeStart, rangeEnd, vertexCount, glsDrawTests.indexTypeToGL(indexType), indexOffset); 1737 else if (drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWELEMENTS_INSTANCED) 1738 this.m_ctx.drawElementsInstanced(glsDrawTests.primitiveToGL(primitive), vertexCount, glsDrawTests.indexTypeToGL(indexType), indexOffset, instanceCount); 1739 else 1740 throw new Error('Invalid draw method'); 1741 1742 for (var arrayNdx = 0; arrayNdx < this.m_arrays.length; arrayNdx++) { 1743 if (this.m_arrays[arrayNdx].isBound()) { 1744 var attribName = ''; 1745 attribName += 'a_' + arrayNdx; 1746 1747 var loc = this.m_ctx.getAttribLocation(this.m_programID, attribName); 1748 1749 this.m_ctx.disableVertexAttribArray(loc); 1750 } 1751 } 1752 1753 if (this.m_useVao) 1754 this.m_ctx.bindVertexArray(null); 1755 1756 this.m_ctx.useProgram(null); 1757 this.m_screen.readViewport(this.m_ctx, [0 , 0, this.m_screen.getWidth(), this.m_screen.getHeight()]); 1758 }; 1759 1760 // DrawTestSpec 1761 1762 /** 1763 * @constructor 1764 */ 1765 glsDrawTests.DrawTestSpec = function() { 1766 /** @type {?glsDrawTests.DrawTestSpec.Primitive} */ this.primitive = null; 1767 /** @type {number} */ this.primitiveCount = 0; //!< number of primitives to draw (per instance) 1768 1769 /** @type {?glsDrawTests.DrawTestSpec.DrawMethod} */ this.drawMethod = null; 1770 /** @type {?glsDrawTests.DrawTestSpec.IndexType} */ this.indexType = null; //!< used only if drawMethod = DrawElements* 1771 /** @type {number} */ this.indexPointerOffset = 0; //!< used only if drawMethod = DrawElements* 1772 /** @type {?glsDrawTests.DrawTestSpec.Storage} */ this.indexStorage = null; //!< used only if drawMethod = DrawElements* 1773 /** @type {number} */ this.first = 0; //!< used only if drawMethod = DrawArrays* 1774 /** @type {number} */ this.indexMin = 0; //!< used only if drawMethod = Draw*Ranged 1775 /** @type {number} */ this.indexMax = 0; //!< used only if drawMethod = Draw*Ranged 1776 /** @type {number} */ this.instanceCount = 0; //!< used only if drawMethod = Draw*Instanced or Draw*Indirect 1777 /** @type {number} */ this.indirectOffset = 0; //!< used only if drawMethod = Draw*Indirect 1778 /** @type {number} */ this.baseVertex = 0; //!< used only if drawMethod = DrawElementsIndirect or *BaseVertex 1779 1780 /** @type {Array<glsDrawTests.DrawTestSpec.AttributeSpec>} */ this.attribs = []; 1781 }; 1782 1783 /** 1784 * @param {glsDrawTests.DrawTestSpec.Target} target 1785 * @return {string} 1786 */ 1787 glsDrawTests.DrawTestSpec.targetToString = function(target) { 1788 assertMsgOptions(target != null, 'Target is null', false, true); 1789 1790 var targets = [ 1791 'element_array', // TARGET_ELEMENT_ARRAY = 0, 1792 'array' // TARGET_ARRAY, 1793 ]; 1794 assertMsgOptions(targets.length == Object.keys(glsDrawTests.DrawTestSpec.Target).length, 1795 'The amount of target names is different than the amount of targets', false, true); 1796 1797 return targets[target]; 1798 }; 1799 1800 /** 1801 * @param {?glsDrawTests.DrawTestSpec.InputType} type 1802 * @return {string} 1803 */ 1804 glsDrawTests.DrawTestSpec.inputTypeToString = function(type) { 1805 assertMsgOptions(type != null, 'Type is null', false, true); 1806 1807 var types = [ 1808 'float', // INPUTTYPE_FLOAT = 0, 1809 1810 'byte', // INPUTTYPE_BYTE, 1811 'short', // INPUTTYPE_SHORT, 1812 1813 'unsigned_byte', // INPUTTYPE_UNSIGNED_BYTE, 1814 'unsigned_short', // INPUTTYPE_UNSIGNED_SHORT, 1815 1816 'int', // INPUTTYPE_INT, 1817 'unsigned_int', // INPUTTYPE_UNSIGNED_INT, 1818 'half', // INPUTTYPE_HALF, 1819 'unsigned_int2_10_10_10', // INPUTTYPE_UNSIGNED_INT_2_10_10_10, 1820 'int2_10_10_10' // INPUTTYPE_INT_2_10_10_10, 1821 ]; 1822 assertMsgOptions(types.length == Object.keys(glsDrawTests.DrawTestSpec.InputType).length, 1823 'The amount of type names is different than the amount of types', false, true); 1824 1825 return types[type]; 1826 }; 1827 1828 /** 1829 * @param {?glsDrawTests.DrawTestSpec.OutputType} type 1830 * @return {string} 1831 */ 1832 glsDrawTests.DrawTestSpec.outputTypeToString = function(type) { 1833 assertMsgOptions(type != null, 'Type is null', false, true); 1834 1835 var types = [ 1836 'float', // OUTPUTTYPE_FLOAT = 0, 1837 'vec2', // OUTPUTTYPE_VEC2, 1838 'vec3', // OUTPUTTYPE_VEC3, 1839 'vec4', // OUTPUTTYPE_VEC4, 1840 1841 'int', // OUTPUTTYPE_INT, 1842 'uint', // OUTPUTTYPE_UINT, 1843 1844 'ivec2', // OUTPUTTYPE_IVEC2, 1845 'ivec3', // OUTPUTTYPE_IVEC3, 1846 'ivec4', // OUTPUTTYPE_IVEC4, 1847 1848 'uvec2', // OUTPUTTYPE_UVEC2, 1849 'uvec3', // OUTPUTTYPE_UVEC3, 1850 'uvec4' // OUTPUTTYPE_UVEC4, 1851 ]; 1852 assertMsgOptions(types.length == Object.keys(glsDrawTests.DrawTestSpec.OutputType).length, 1853 'The amount of type names is different than the amount of types', false, true); 1854 1855 return types[type]; 1856 }; 1857 1858 /** 1859 * @param {?glsDrawTests.DrawTestSpec.Usage} usage 1860 * @return {string} 1861 */ 1862 glsDrawTests.DrawTestSpec.usageTypeToString = function(usage) { 1863 assertMsgOptions(usage != null, 'Usage is null', false, true); 1864 1865 var usages = [ 1866 'dynamic_draw', // USAGE_DYNAMIC_DRAW = 0, 1867 'static_draw', // USAGE_STATIC_DRAW, 1868 'stream_draw', // USAGE_STREAM_DRAW, 1869 1870 'stream_read', // USAGE_STREAM_READ, 1871 'stream_copy', // USAGE_STREAM_COPY, 1872 1873 'static_read', // USAGE_STATIC_READ, 1874 'static_copy', // USAGE_STATIC_COPY, 1875 1876 'dynamic_read', // USAGE_DYNAMIC_READ, 1877 'dynamic_copy' // USAGE_DYNAMIC_COPY, 1878 ]; 1879 assertMsgOptions(usages.length == Object.keys(glsDrawTests.DrawTestSpec.Usage).length, 1880 'The amount of usage names is different than the amount of usages', false, true); 1881 1882 return usages[usage]; 1883 }; 1884 1885 /** 1886 * @param {?glsDrawTests.DrawTestSpec.Storage} storage 1887 * @return {string} 1888 */ 1889 glsDrawTests.DrawTestSpec.storageToString = function(storage) { 1890 assertMsgOptions(storage != null, 'Storage is null', false, true); 1891 1892 var storages = [ 1893 'user_ptr', // STORAGE_USER = 0, 1894 'buffer' // STORAGE_BUFFER, 1895 ]; 1896 assertMsgOptions(storages.length == Object.keys(glsDrawTests.DrawTestSpec.Storage).length, 1897 'The amount of storage names is different than the amount of storages', false, true); 1898 1899 return storages[storage]; 1900 }; 1901 1902 /** 1903 * @param {glsDrawTests.DrawTestSpec.Primitive} primitive 1904 * @return {string} 1905 */ 1906 glsDrawTests.DrawTestSpec.primitiveToString = function(primitive) { 1907 assertMsgOptions(primitive != null, 'Primitive is null', false, true); 1908 1909 var primitives = [ 1910 'points', // PRIMITIVE_POINTS , 1911 'triangles', // PRIMITIVE_TRIANGLES, 1912 'triangle_fan', // PRIMITIVE_TRIANGLE_FAN, 1913 'triangle_strip', // PRIMITIVE_TRIANGLE_STRIP, 1914 'lines', // PRIMITIVE_LINES 1915 'line_strip', // PRIMITIVE_LINE_STRIP 1916 'line_loop' 1917 ]; 1918 assertMsgOptions(primitives.length == Object.keys(glsDrawTests.DrawTestSpec.Primitive).length, 1919 'The amount of primitive names is different than the amount of primitives', false, true); 1920 1921 return primitives[primitive]; 1922 }; 1923 1924 /** 1925 * @param {?glsDrawTests.DrawTestSpec.IndexType} type 1926 * @return {string} 1927 */ 1928 glsDrawTests.DrawTestSpec.indexTypeToString = function(type) { 1929 assertMsgOptions(type != null, 'Index type is null', false, true); 1930 1931 var indexTypes = [ 1932 'byte', // INDEXTYPE_BYTE = 0, 1933 'short', // INDEXTYPE_SHORT, 1934 'int' // INDEXTYPE_INT, 1935 ]; 1936 assertMsgOptions(indexTypes.length == Object.keys(glsDrawTests.DrawTestSpec.IndexType).length, 1937 'The amount of index type names is different than the amount of index types', false, true); 1938 1939 return indexTypes[type]; 1940 }; 1941 1942 /** 1943 * @param {?glsDrawTests.DrawTestSpec.DrawMethod} method 1944 * @return {string} 1945 */ 1946 glsDrawTests.DrawTestSpec.drawMethodToString = function(method) { 1947 assertMsgOptions(method != null, 'Method is null', false, true); 1948 1949 var methods = [ 1950 'draw_arrays', //!< DRAWMETHOD_DRAWARRAYS 1951 'draw_arrays_instanced', //!< DRAWMETHOD_DRAWARRAYS_INSTANCED 1952 'draw_elements', //!< DRAWMETHOD_DRAWELEMENTS 1953 'draw_range_elements', //!< DRAWMETHOD_DRAWELEMENTS_RANGED 1954 'draw_elements_instanced' //!< DRAWMETHOD_DRAWELEMENTS_INSTANCED 1955 ]; 1956 assertMsgOptions(methods.length == Object.keys(glsDrawTests.DrawTestSpec.DrawMethod).length, 1957 'The amount of method names is different than the amount of methods', false, true); 1958 1959 return methods[method]; 1960 }; 1961 1962 /** 1963 * @param {?glsDrawTests.DrawTestSpec.InputType} type 1964 * @return {number} 1965 */ 1966 glsDrawTests.DrawTestSpec.inputTypeSize = function(type) { 1967 assertMsgOptions(type != null, 'Input type is null', false, true); 1968 1969 var size = [ 1970 4, // INPUTTYPE_FLOAT = 0, 1971 1972 1, // INPUTTYPE_BYTE, 1973 2, // INPUTTYPE_SHORT, 1974 1975 1, // INPUTTYPE_UNSIGNED_BYTE, 1976 2, // INPUTTYPE_UNSIGNED_SHORT, 1977 1978 4, // INPUTTYPE_INT, 1979 4, // INPUTTYPE_UNSIGNED_INT, 1980 2, // INPUTTYPE_HALF, 1981 4 / 4, // INPUTTYPE_UNSIGNED_INT_2_10_10_10, 1982 4 / 4 // INPUTTYPE_INT_2_10_10_10, 1983 ]; 1984 assertMsgOptions(size.length == Object.keys(glsDrawTests.DrawTestSpec.InputType).length, 1985 'The amount of type names is different than the amount of types', false, true); 1986 1987 return size[type]; 1988 }; 1989 1990 /** 1991 * @param {?glsDrawTests.DrawTestSpec.IndexType} type 1992 * @return {number} 1993 */ 1994 glsDrawTests.DrawTestSpec.indexTypeSize = function(type) { 1995 assertMsgOptions(type != null, 'Type is null', false, true); 1996 1997 var size = [ 1998 1, // INDEXTYPE_BYTE, 1999 2, // INDEXTYPE_SHORT, 2000 4 // INDEXTYPE_INT, 2001 ]; 2002 assertMsgOptions(size.length == Object.keys(glsDrawTests.DrawTestSpec.IndexType).length, 2003 'The amount of type names is different than the amount of types', false, true); 2004 2005 return size[type]; 2006 }; 2007 2008 /** 2009 * @return {string} 2010 */ 2011 glsDrawTests.DrawTestSpec.prototype.getName = function() { 2012 /** @type {glsDrawTests.MethodInfo} */ var methodInfo = glsDrawTests.getMethodInfo(this.drawMethod); 2013 /** @type {boolean} */ var hasFirst = methodInfo.first; 2014 /** @type {boolean} */ var instanced = methodInfo.instanced; 2015 /** @type {boolean} */ var ranged = methodInfo.ranged; 2016 /** @type {boolean} */ var indexed = methodInfo.indexed; 2017 2018 var name = ''; 2019 2020 for (var ndx = 0; ndx < this.attribs.length; ++ndx) { 2021 /** @type {glsDrawTests.DrawTestSpec.AttributeSpec}*/ var attrib = this.attribs[ndx]; 2022 2023 if (this.attribs.length > 1) 2024 name += 'attrib' + ndx + '_'; 2025 2026 if (ndx == 0 || attrib.additionalPositionAttribute) 2027 name += 'pos_'; 2028 else 2029 name += 'col_'; 2030 2031 if (attrib.useDefaultAttribute) { 2032 name += 'non_array_' + 2033 glsDrawTests.DrawTestSpec.inputTypeToString(/** @type {?glsDrawTests.DrawTestSpec.InputType} */ (attrib.inputType)) + '_' + 2034 attrib.componentCount + '_' + 2035 glsDrawTests.DrawTestSpec.outputTypeToString(attrib.outputType) + '_'; 2036 } else { 2037 name += glsDrawTests.DrawTestSpec.storageToString(attrib.storage) + '_' + 2038 attrib.offset + '_' + 2039 attrib.stride + '_' + 2040 glsDrawTests.DrawTestSpec.inputTypeToString(/** @type {?glsDrawTests.DrawTestSpec.InputType} */ (attrib.inputType)); 2041 if (attrib.inputType != glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT_2_10_10_10 && attrib.inputType != glsDrawTests.DrawTestSpec.InputType.INT_2_10_10_10) 2042 name += attrib.componentCount; 2043 name += '_' + 2044 (attrib.normalize ? 'normalized_' : '') + 2045 glsDrawTests.DrawTestSpec.outputTypeToString(attrib.outputType) + '_' + 2046 glsDrawTests.DrawTestSpec.usageTypeToString(attrib.usage) + '_' + 2047 attrib.instanceDivisor + '_'; 2048 } 2049 } 2050 2051 if (indexed) 2052 name += 'index_' + glsDrawTests.DrawTestSpec.indexTypeToString(this.indexType) + '_' + 2053 glsDrawTests.DrawTestSpec.storageToString(this.indexStorage) + '_' + 2054 'offset' + this.indexPointerOffset + '_'; 2055 if (hasFirst) 2056 name += 'first' + this.first + '_'; 2057 if (ranged) 2058 name += 'ranged_' + this.indexMin + '_' + this.indexMax + '_'; 2059 if (instanced) 2060 name += 'instances' + this.instanceCount + '_'; 2061 2062 switch (this.primitive) { 2063 case glsDrawTests.DrawTestSpec.Primitive.POINTS: 2064 name += 'points_'; 2065 break; 2066 case glsDrawTests.DrawTestSpec.Primitive.TRIANGLES: 2067 name += 'triangles_'; 2068 break; 2069 case glsDrawTests.DrawTestSpec.Primitive.TRIANGLE_FAN: 2070 name += 'triangle_fan_'; 2071 break; 2072 case glsDrawTests.DrawTestSpec.Primitive.TRIANGLE_STRIP: 2073 name += 'triangle_strip_'; 2074 break; 2075 case glsDrawTests.DrawTestSpec.Primitive.LINES: 2076 name += 'lines_'; 2077 break; 2078 case glsDrawTests.DrawTestSpec.Primitive.LINE_STRIP: 2079 name += 'line_strip_'; 2080 break; 2081 case glsDrawTests.DrawTestSpec.Primitive.LINE_LOOP: 2082 name += 'line_loop_'; 2083 break; 2084 default: 2085 throw new Error('Invalid primitive'); 2086 break; 2087 } 2088 2089 name += this.primitiveCount; 2090 2091 return name; 2092 }; 2093 2094 /** 2095 * @return {string} 2096 */ 2097 glsDrawTests.DrawTestSpec.prototype.getDesc = function() { 2098 var desc = ''; 2099 2100 for (var ndx = 0; ndx < this.attribs.length; ++ndx) { 2101 /** @type {glsDrawTests.DrawTestSpec.AttributeSpec} */ var attrib = this.attribs[ndx]; 2102 2103 if (attrib.useDefaultAttribute) { 2104 desc += 'Attribute ' + ndx + ': default, ' + ((ndx == 0 || attrib.additionalPositionAttribute) ? ('position ,') : ('color ,')) + 2105 'input datatype ' + glsDrawTests.DrawTestSpec.inputTypeToString(/** @type {?glsDrawTests.DrawTestSpec.InputType} */ (attrib.inputType)) + ', ' + 2106 'input component count ' + attrib.componentCount + ', ' + 2107 'used as ' + glsDrawTests.DrawTestSpec.outputTypeToString(attrib.outputType) + ', '; 2108 } else { 2109 desc += 'Attribute ' + ndx + ': ' + ((ndx == 0 || attrib.additionalPositionAttribute) ? ('position ,') : ('color ,')) + 2110 'Storage in ' + glsDrawTests.DrawTestSpec.storageToString(attrib.storage) + ', ' + 2111 'stride ' + attrib.stride + ', ' + 2112 'input datatype ' + glsDrawTests.DrawTestSpec.inputTypeToString(/** @type {?glsDrawTests.DrawTestSpec.InputType} */ (attrib.inputType)) + ', ' + 2113 'input component count ' + attrib.componentCount + ', ' + 2114 (attrib.normalize ? 'normalized, ' : '') + 2115 'used as ' + glsDrawTests.DrawTestSpec.outputTypeToString(attrib.outputType) + ', ' + 2116 'instance divisor ' + attrib.instanceDivisor + ', '; 2117 } 2118 } 2119 2120 if (this.drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWARRAYS) { 2121 desc += 'drawArrays(), ' + 2122 'first ' + this.first + ', '; 2123 } else if (this.drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWARRAYS_INSTANCED) { 2124 desc += 'drawArraysInstanced(), ' + 2125 'first ' + this.first + ', ' + 2126 'instance count ' + this.instanceCount + ', '; 2127 } else if (this.drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWELEMENTS) { 2128 desc += 'drawElements(), ' + 2129 'index type ' + glsDrawTests.DrawTestSpec.indexTypeToString(this.indexType) + ', ' + 2130 'index storage in ' + glsDrawTests.DrawTestSpec.storageToString(this.indexStorage) + ', ' + 2131 'index offset ' + this.indexPointerOffset + ', '; 2132 } else if (this.drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWELEMENTS_RANGED) { 2133 desc += 'drawElementsRanged(), ' + 2134 'index type ' + glsDrawTests.DrawTestSpec.indexTypeToString(this.indexType) + ', ' + 2135 'index storage in ' + glsDrawTests.DrawTestSpec.storageToString(this.indexStorage) + ', ' + 2136 'index offset ' + this.indexPointerOffset + ', ' + 2137 'range start ' + this.indexMin + ', ' + 2138 'range end ' + this.indexMax + ', '; 2139 } else if (this.drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWELEMENTS_INSTANCED) { 2140 desc += 'drawElementsInstanced(), ' + 2141 'index type ' + glsDrawTests.DrawTestSpec.indexTypeToString(this.indexType) + ', ' + 2142 'index storage in ' + glsDrawTests.DrawTestSpec.storageToString(this.indexStorage) + ', ' + 2143 'index offset ' + this.indexPointerOffset + ', ' + 2144 'instance count ' + this.instanceCount + ', '; 2145 } else 2146 throw new Error('Invalid draw method'); 2147 2148 desc += this.primitiveCount; 2149 2150 switch (this.primitive) { 2151 case glsDrawTests.DrawTestSpec.Primitive.POINTS: 2152 desc += 'points'; 2153 break; 2154 case glsDrawTests.DrawTestSpec.Primitive.TRIANGLES: 2155 desc += 'triangles'; 2156 break; 2157 case glsDrawTests.DrawTestSpec.Primitive.TRIANGLE_FAN: 2158 desc += 'triangles (fan)'; 2159 break; 2160 case glsDrawTests.DrawTestSpec.Primitive.TRIANGLE_STRIP: 2161 desc += 'triangles (strip)'; 2162 break; 2163 case glsDrawTests.DrawTestSpec.Primitive.LINES: 2164 desc += 'lines'; 2165 break; 2166 case glsDrawTests.DrawTestSpec.Primitive.LINE_STRIP: 2167 desc += 'lines (strip)'; 2168 break; 2169 case glsDrawTests.DrawTestSpec.Primitive.LINE_LOOP: 2170 desc += 'lines (loop)'; 2171 break; 2172 default: 2173 throw new Error('Invalid primitive'); 2174 break; 2175 } 2176 2177 return desc; 2178 }; 2179 2180 /** 2181 * @return {string} 2182 */ 2183 glsDrawTests.DrawTestSpec.prototype.getMultilineDesc = function() { 2184 var desc = ''; 2185 2186 for (var ndx = 0; ndx < this.attribs.length; ++ndx) { 2187 /** @type {glsDrawTests.DrawTestSpec.AttributeSpec} */ var attrib = this.attribs[ndx]; 2188 2189 if (attrib.useDefaultAttribute) { 2190 desc += 'Attribute ' + ndx + ': default, ' + ((ndx == 0 || attrib.additionalPositionAttribute) ? ('position\n') : ('color\n')) + 2191 '\tinput datatype ' + glsDrawTests.DrawTestSpec.inputTypeToString(/** @type {?glsDrawTests.DrawTestSpec.InputType} */ (attrib.inputType)) + '\n' + 2192 '\tinput component count ' + attrib.componentCount + '\n' + 2193 '\tused as ' + glsDrawTests.DrawTestSpec.outputTypeToString(attrib.outputType) + '\n'; 2194 } else { 2195 desc += 'Attribute ' + ndx + ': ' + ((ndx == 0 || attrib.additionalPositionAttribute) ? ('position\n') : ('color\n')) + 2196 '\tStorage in ' + glsDrawTests.DrawTestSpec.storageToString(attrib.storage) + '\n' + 2197 '\tstride ' + attrib.stride + '\n' + 2198 '\tinput datatype ' + glsDrawTests.DrawTestSpec.inputTypeToString(/** @type {?glsDrawTests.DrawTestSpec.InputType} */ (attrib.inputType)) + '\n' + 2199 '\tinput component count ' + attrib.componentCount + '\n' + 2200 (attrib.normalize ? '\tnormalized\n' : '') + 2201 '\tused as ' + glsDrawTests.DrawTestSpec.outputTypeToString(attrib.outputType) + '\n' + 2202 '\tinstance divisor ' + attrib.instanceDivisor + '\n'; 2203 } 2204 } 2205 2206 if (this.drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWARRAYS) { 2207 desc += 'drawArrays()\n' + 2208 '\tfirst ' + this.first + '\n'; 2209 } else if (this.drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWARRAYS_INSTANCED) { 2210 desc += 'drawArraysInstanced()\n' + 2211 '\tfirst ' + this.first + '\n' + 2212 '\tinstance count ' + this.instanceCount + '\n'; 2213 } else if (this.drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWELEMENTS) { 2214 desc += 'drawElements()\n' + 2215 '\tindex type ' + glsDrawTests.DrawTestSpec.indexTypeToString(this.indexType) + '\n' + 2216 '\tindex storage in ' + glsDrawTests.DrawTestSpec.storageToString(this.indexStorage) + '\n' + 2217 '\tindex offset ' + this.indexPointerOffset + '\n'; 2218 } else if (this.drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWELEMENTS_RANGED) { 2219 desc += 'drawElementsRanged()\n' + 2220 '\tindex type ' + glsDrawTests.DrawTestSpec.indexTypeToString(this.indexType) + '\n' + 2221 '\tindex storage in ' + glsDrawTests.DrawTestSpec.storageToString(this.indexStorage) + '\n' + 2222 '\tindex offset ' + this.indexPointerOffset + '\n' + 2223 '\trange start ' + this.indexMin + '\n' + 2224 '\trange end ' + this.indexMax + '\n'; 2225 } else if (this.drawMethod == glsDrawTests.DrawTestSpec.DrawMethod.DRAWELEMENTS_INSTANCED) { 2226 desc += 'drawElementsInstanced()\n' + 2227 '\tindex type ' + glsDrawTests.DrawTestSpec.indexTypeToString(this.indexType) + '\n' + 2228 '\tindex storage in ' + glsDrawTests.DrawTestSpec.storageToString(this.indexStorage) + '\n' + 2229 '\tindex offset ' + this.indexPointerOffset + '\n' + 2230 '\tinstance count ' + this.instanceCount + '\n'; 2231 } else 2232 throw new Error('Invalid draw method'); 2233 2234 desc += '\t' + this.primitiveCount + ' '; 2235 2236 switch (this.primitive) { 2237 case glsDrawTests.DrawTestSpec.Primitive.POINTS: 2238 desc += 'points'; 2239 break; 2240 case glsDrawTests.DrawTestSpec.Primitive.TRIANGLES: 2241 desc += 'triangles'; 2242 break; 2243 case glsDrawTests.DrawTestSpec.Primitive.TRIANGLE_FAN: 2244 desc += 'triangles (fan)'; 2245 break; 2246 case glsDrawTests.DrawTestSpec.Primitive.TRIANGLE_STRIP: 2247 desc += 'triangles (strip)'; 2248 break; 2249 case glsDrawTests.DrawTestSpec.Primitive.LINES: 2250 desc += 'lines'; 2251 break; 2252 case glsDrawTests.DrawTestSpec.Primitive.LINE_STRIP: 2253 desc += 'lines (strip)'; 2254 break; 2255 case glsDrawTests.DrawTestSpec.Primitive.LINE_LOOP: 2256 desc += 'lines (loop)'; 2257 break; 2258 default: 2259 throw new Error('Invalid primitive'); 2260 break; 2261 } 2262 2263 desc += '\n'; 2264 2265 return desc; 2266 }; 2267 2268 /** 2269 * @enum {number} 2270 */ 2271 glsDrawTests.DrawTestSpec.Target = { 2272 ELEMENT_ARRAY: 0, 2273 ARRAY: 1 2274 }; 2275 2276 /** 2277 * @enum {number} 2278 */ 2279 glsDrawTests.DrawTestSpec.InputType = { 2280 FLOAT: 0, 2281 2282 BYTE: 1, 2283 SHORT: 2, 2284 2285 UNSIGNED_BYTE: 3, 2286 UNSIGNED_SHORT: 4, 2287 2288 INT: 5, 2289 UNSIGNED_INT: 6, 2290 HALF: 7, 2291 UNSIGNED_INT_2_10_10_10: 8, 2292 INT_2_10_10_10: 9 2293 }; 2294 2295 /** 2296 * @enum {number} 2297 */ 2298 glsDrawTests.DrawTestSpec.OutputType = { 2299 FLOAT: 0, 2300 VEC2: 1, 2301 VEC3: 2, 2302 VEC4: 3, 2303 2304 INT: 4, 2305 UINT: 5, 2306 2307 IVEC2: 6, 2308 IVEC3: 7, 2309 IVEC4: 8, 2310 2311 UVEC2: 9, 2312 UVEC3: 10, 2313 UVEC4: 11 2314 }; 2315 2316 /** 2317 * @enum {number} 2318 */ 2319 glsDrawTests.DrawTestSpec.Usage = { 2320 DYNAMIC_DRAW: 0, 2321 STATIC_DRAW: 1, 2322 STREAM_DRAW: 2, 2323 2324 STREAM_READ: 3, 2325 STREAM_COPY: 4, 2326 2327 STATIC_READ: 5, 2328 STATIC_COPY: 6, 2329 2330 DYNAMIC_READ: 7, 2331 DYNAMIC_COPY: 8 2332 }; 2333 2334 /** 2335 * @enum {number} 2336 */ 2337 glsDrawTests.DrawTestSpec.Storage = { 2338 USER: 0, 2339 BUFFER: 1 2340 }; 2341 2342 /** 2343 * @enum {number} 2344 */ 2345 glsDrawTests.DrawTestSpec.Primitive = { 2346 POINTS: 0, 2347 TRIANGLES: 1, 2348 TRIANGLE_FAN: 2, 2349 TRIANGLE_STRIP: 3, 2350 LINES: 4, 2351 LINE_STRIP: 5, 2352 LINE_LOOP: 6 2353 }; 2354 2355 /** 2356 * @enum {number} 2357 */ 2358 glsDrawTests.DrawTestSpec.IndexType = { 2359 BYTE: 0, 2360 SHORT: 1, 2361 INT: 2 2362 }; 2363 2364 /** 2365 * @enum {number} 2366 */ 2367 glsDrawTests.DrawTestSpec.DrawMethod = { 2368 DRAWARRAYS: 0, 2369 DRAWARRAYS_INSTANCED: 1, 2370 DRAWELEMENTS: 2, 2371 DRAWELEMENTS_RANGED: 3, 2372 DRAWELEMENTS_INSTANCED: 4 2373 }; 2374 2375 /** 2376 * @enum {number} 2377 */ 2378 glsDrawTests.DrawTestSpec.CompatibilityTestType = { 2379 NONE: 0, 2380 UNALIGNED_OFFSET: 1, 2381 UNALIGNED_STRIDE: 2 2382 }; 2383 2384 /** 2385 * @return {number} 2386 */ 2387 glsDrawTests.DrawTestSpec.prototype.hash = function() { 2388 // Use only drawmode-relevant values in "hashing" as the unrelevant values might not be set (causing non-deterministic behavior). 2389 /** @type {glsDrawTests.MethodInfo} */ var methodInfo = glsDrawTests.getMethodInfo(this.drawMethod); 2390 /** @type {boolean} */ var arrayed = methodInfo.first; 2391 /** @type {boolean} */ var instanced = methodInfo.instanced; 2392 /** @type {boolean} */ var ranged = methodInfo.ranged; 2393 /** @type {boolean} */ var indexed = methodInfo.indexed; 2394 2395 /** @type {number} */ var indexHash = (!indexed) ? (0) : (this.indexType + 10 * this.indexPointerOffset + 100 * this.indexStorage); 2396 /** @type {number} */ var arrayHash = (!arrayed) ? (0) : (this.first); 2397 /** @type {number} */ var indexRangeHash = (!ranged) ? (0) : (this.indexMin + 10 * this.indexMax); 2398 /** @type {number} */ var instanceHash = (!instanced) ? (0) : (this.instanceCount); 2399 /** @type {number} */ var basicHash = this.primitive + 10 * this.primitiveCount + 100 * this.drawMethod; 2400 2401 return indexHash + 3 * arrayHash + 5 * indexRangeHash + 7 * instanceHash + 13 * basicHash + 17 * this.attribs.length + 19 * this.primitiveCount; 2402 }; 2403 2404 /** 2405 * @return {boolean} 2406 */ 2407 glsDrawTests.DrawTestSpec.prototype.valid = function() { 2408 assertMsgOptions(this.primitive != null, 'Primitive is null', false, true); 2409 assertMsgOptions(this.drawMethod != null, 'Draw method is null', false, true); 2410 2411 var methodInfo = glsDrawTests.getMethodInfo(this.drawMethod); 2412 2413 if (methodInfo.ranged) { 2414 var maxIndexValue = 0; 2415 if (this.indexType == glsDrawTests.DrawTestSpec.IndexType.BYTE) 2416 maxIndexValue = glsDrawTests.GLValue.getMaxValue(glsDrawTests.DrawTestSpec.InputType.UNSIGNED_BYTE).interpret(); 2417 else if (this.indexType == glsDrawTests.DrawTestSpec.IndexType.SHORT) 2418 maxIndexValue = glsDrawTests.GLValue.getMaxValue(glsDrawTests.DrawTestSpec.InputType.UNSIGNED_SHORT).interpret(); 2419 else if (this.indexType == glsDrawTests.DrawTestSpec.IndexType.INT) 2420 maxIndexValue = glsDrawTests.GLValue.getMaxValue(glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT).interpret(); 2421 else 2422 throw new Error('Invalid index type'); 2423 2424 if (this.indexMin > this.indexMax) 2425 return false; 2426 if (this.indexMin < 0 || this.indexMax < 0) 2427 return false; 2428 if (this.indexMin > maxIndexValue || this.indexMax > maxIndexValue) 2429 return false; 2430 } 2431 2432 if (methodInfo.first && this.first < 0) 2433 return false; 2434 2435 return true; 2436 }; 2437 2438 /** 2439 * @return {glsDrawTests.DrawTestSpec.CompatibilityTestType} 2440 */ 2441 glsDrawTests.DrawTestSpec.prototype.isCompatibilityTest = function() { 2442 var methodInfo = glsDrawTests.getMethodInfo(this.drawMethod); 2443 2444 var bufferAlignmentBad = false; 2445 var strideAlignmentBad = false; 2446 2447 // Attribute buffer alignment 2448 for (var ndx = 0; ndx < this.attribs.length; ++ndx) 2449 if (!this.attribs[ndx].isBufferAligned()) 2450 bufferAlignmentBad = true; 2451 2452 // Attribute stride alignment 2453 for (var ndx = 0; ndx < this.attribs.length; ++ndx) 2454 if (!this.attribs[ndx].isBufferStrideAligned()) 2455 strideAlignmentBad = true; 2456 2457 // Index buffer alignment 2458 if (methodInfo.indexed) { 2459 if (this.indexStorage == glsDrawTests.DrawTestSpec.Storage.BUFFER) { 2460 var indexSize = 0; 2461 if (this.indexType == glsDrawTests.DrawTestSpec.IndexType.BYTE) 2462 indexSize = 1; 2463 else if (this.indexType == glsDrawTests.DrawTestSpec.IndexType.SHORT) 2464 indexSize = 2; 2465 else if (this.indexType == glsDrawTests.DrawTestSpec.IndexType.INT) 2466 indexSize = 4; 2467 else 2468 throw new Error(''); 2469 2470 if (this.indexPointerOffset % indexSize != 0) 2471 bufferAlignmentBad = true; 2472 } 2473 } 2474 2475 // \note combination bad alignment & stride is treated as bad offset 2476 if (bufferAlignmentBad) 2477 return glsDrawTests.DrawTestSpec.CompatibilityTestType.UNALIGNED_OFFSET; 2478 else if (strideAlignmentBad) 2479 return glsDrawTests.DrawTestSpec.CompatibilityTestType.UNALIGNED_STRIDE; 2480 else 2481 return glsDrawTests.DrawTestSpec.CompatibilityTestType.NONE; 2482 }; 2483 2484 // DrawTestSpec.AttributeSpec 2485 2486 /** 2487 * @constructor 2488 */ 2489 glsDrawTests.DrawTestSpec.AttributeSpec = function() { 2490 /** @type {?glsDrawTests.DrawTestSpec.InputType} */ this.inputType = null; 2491 /** @type {?glsDrawTests.DrawTestSpec.OutputType} */ this.outputType = null; 2492 /** @type {?glsDrawTests.DrawTestSpec.Storage} */ this.storage = glsDrawTests.DrawTestSpec.Storage.BUFFER; //Always BUFFER in WebGL up to 2 2493 /** @type {?glsDrawTests.DrawTestSpec.Usage} */ this.usage = null; 2494 /** @type {number} */ this.componentCount = 0; 2495 /** @type {number} */ this.offset = 0; 2496 /** @type {number} */ this.stride = 0; 2497 /** @type {boolean} */ this.normalize = false; 2498 /** @type {number} */ this.instanceDivisor = 0; //!< used only if drawMethod = Draw*Instanced 2499 /** @type {boolean} */ this.useDefaultAttribute = false; 2500 2501 /** @type {boolean} */ this.additionalPositionAttribute = false; //!< treat this attribute as position attribute. Attribute at index 0 is alway treated as such. False by default 2502 }; 2503 2504 /** 2505 * @param {?glsDrawTests.DrawTestSpec.InputType} inputType 2506 * @param {?glsDrawTests.DrawTestSpec.OutputType} outputType 2507 * @param {?glsDrawTests.DrawTestSpec.Storage} storage 2508 * @param {?glsDrawTests.DrawTestSpec.Usage} usage 2509 * @param {number} componentCount 2510 * @param {number} offset 2511 * @param {number} stride 2512 * @param {boolean} normalize 2513 * @param {number} instanceDivisor 2514 * @return {glsDrawTests.DrawTestSpec.AttributeSpec} 2515 */ 2516 glsDrawTests.DrawTestSpec.AttributeSpec.createAttributeArray = function(inputType, outputType, storage, usage, componentCount, 2517 offset, stride, normalize, instanceDivisor) { 2518 /** @type {glsDrawTests.DrawTestSpec.AttributeSpec} */ var spec; 2519 2520 spec.inputType = inputType; 2521 spec.outputType = outputType; 2522 spec.storage = storage; 2523 spec.usage = usage; 2524 spec.componentCount = componentCount; 2525 spec.offset = offset; 2526 spec.stride = stride; 2527 spec.normalize = normalize; 2528 spec.instanceDivisor = instanceDivisor; 2529 2530 spec.useDefaultAttribute = false; 2531 2532 return spec; 2533 }; 2534 2535 /** 2536 * @param {?glsDrawTests.DrawTestSpec.InputType} inputType 2537 * @param {?glsDrawTests.DrawTestSpec.OutputType} outputType 2538 * @param {number} componentCount 2539 * @return {glsDrawTests.DrawTestSpec.AttributeSpec} 2540 */ 2541 glsDrawTests.DrawTestSpec.AttributeSpec.createDefaultAttribute = function(inputType, outputType, componentCount) { 2542 assertMsgOptions(inputType == glsDrawTests.DrawTestSpec.InputType.INT || inputType == glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT || inputType == glsDrawTests.DrawTestSpec.InputType.FLOAT, 'Invalid input type', false, true); 2543 assertMsgOptions(inputType == glsDrawTests.DrawTestSpec.InputType.FLOAT || componentCount == 4, 'If not float, input type should have 4 components', false, true); 2544 2545 /** @type {glsDrawTests.DrawTestSpec.AttributeSpec} */ var spec; 2546 2547 spec.inputType = inputType; 2548 spec.outputType = outputType; 2549 spec.storage = glsDrawTests.DrawTestSpec.Storage.BUFFER; //Always BUFFER in WebGL up to 2 2550 spec.usage = null; 2551 spec.componentCount = componentCount; 2552 spec.offset = 0; 2553 spec.stride = 0; 2554 spec.normalize = false; 2555 spec.instanceDivisor = 0; 2556 2557 spec.useDefaultAttribute = true; 2558 2559 return spec; 2560 }; 2561 2562 /** 2563 * @return {number} 2564 */ 2565 glsDrawTests.DrawTestSpec.AttributeSpec.prototype.hash = function() { 2566 if (this.useDefaultAttribute) { 2567 return 1 * this.inputType + 7 * this.outputType + 13 * this.componentCount; 2568 } else { 2569 return 1 * this.inputType + 2 * this.outputType + 3 * this.storage + 5 * this.usage + 7 * this.componentCount + 11 * this.offset + 13 * this.stride + 17 * (this.normalize ? 0 : 1) + 19 * this.instanceDivisor; 2570 } 2571 }; 2572 2573 /** 2574 * @return {boolean} 2575 */ 2576 glsDrawTests.DrawTestSpec.AttributeSpec.prototype.valid = function(/*ctxType*/) { 2577 /** @type {boolean} */ var inputTypeFloat = this.inputType == glsDrawTests.DrawTestSpec.InputType.FLOAT || this.inputType == glsDrawTests.DrawTestSpec.InputType.HALF; 2578 /** @type {boolean} */ var inputTypeUnsignedInteger = this.inputType == glsDrawTests.DrawTestSpec.InputType.UNSIGNED_BYTE || this.inputType == glsDrawTests.DrawTestSpec.InputType.UNSIGNED_SHORT || this.inputType == glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT || this.inputType == glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT_2_10_10_10; 2579 /** @type {boolean} */ var inputTypeSignedInteger = this.inputType == glsDrawTests.DrawTestSpec.InputType.BYTE || this.inputType == glsDrawTests.DrawTestSpec.InputType.SHORT || this.inputType == glsDrawTests.DrawTestSpec.InputType.INT || this.inputType == glsDrawTests.DrawTestSpec.InputType.INT_2_10_10_10; 2580 /** @type {boolean} */ var inputTypePacked = this.inputType == glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT_2_10_10_10 || this.inputType == glsDrawTests.DrawTestSpec.InputType.INT_2_10_10_10; 2581 2582 /** @type {boolean} */ var outputTypeFloat = this.outputType == glsDrawTests.DrawTestSpec.OutputType.FLOAT || this.outputType == glsDrawTests.DrawTestSpec.OutputType.VEC2 || this.outputType == glsDrawTests.DrawTestSpec.OutputType.VEC3 || this.outputType == glsDrawTests.DrawTestSpec.OutputType.VEC4; 2583 /** @type {boolean} */ var outputTypeSignedInteger = this.outputType == glsDrawTests.DrawTestSpec.OutputType.INT || this.outputType == glsDrawTests.DrawTestSpec.OutputType.IVEC2 || this.outputType == glsDrawTests.DrawTestSpec.OutputType.IVEC3 || this.outputType == glsDrawTests.DrawTestSpec.OutputType.IVEC4; 2584 /** @type {boolean} */ var outputTypeUnsignedInteger = this.outputType == glsDrawTests.DrawTestSpec.OutputType.UINT || this.outputType == glsDrawTests.DrawTestSpec.OutputType.UVEC2 || this.outputType == glsDrawTests.DrawTestSpec.OutputType.UVEC3 || this.outputType == glsDrawTests.DrawTestSpec.OutputType.UVEC4; 2585 2586 if (this.useDefaultAttribute) { 2587 if (this.inputType != glsDrawTests.DrawTestSpec.InputType.INT && this.inputType != glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT && this.inputType != glsDrawTests.DrawTestSpec.InputType.FLOAT) 2588 return false; 2589 2590 if (this.inputType != glsDrawTests.DrawTestSpec.InputType.FLOAT && this.componentCount != 4) 2591 return false; 2592 2593 // no casting allowed (undefined results) 2594 if (this.inputType == glsDrawTests.DrawTestSpec.InputType.INT && !outputTypeSignedInteger) 2595 return false; 2596 if (this.inputType == glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT && !outputTypeUnsignedInteger) 2597 return false; 2598 } 2599 2600 if (inputTypePacked && this.componentCount != 4) 2601 return false; 2602 2603 // Invalid conversions: 2604 2605 // float -> [u]int 2606 if (inputTypeFloat && !outputTypeFloat) 2607 return false; 2608 2609 // uint -> int (undefined results) 2610 if (inputTypeUnsignedInteger && outputTypeSignedInteger) 2611 return false; 2612 2613 // int -> uint (undefined results) 2614 if (inputTypeSignedInteger && outputTypeUnsignedInteger) 2615 return false; 2616 2617 // packed -> non-float (packed formats are converted to floats) 2618 if (inputTypePacked && !outputTypeFloat) 2619 return false; 2620 2621 // Invalid normalize. Normalize is only valid if output type is float 2622 if (this.normalize && !outputTypeFloat) 2623 return false; 2624 2625 return true; 2626 }; 2627 2628 /** 2629 * @return {boolean} 2630 */ 2631 glsDrawTests.DrawTestSpec.AttributeSpec.prototype.isBufferAligned = function() { 2632 var inputTypePacked = this.inputType == glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT_2_10_10_10 || this.inputType == glsDrawTests.DrawTestSpec.InputType.INT_2_10_10_10; 2633 2634 // Buffer alignment, offset is a multiple of underlying data type size? 2635 if (this.storage == glsDrawTests.DrawTestSpec.Storage.BUFFER) { 2636 var dataTypeSize = glsDrawTests.DrawTestSpec.inputTypeSize(this.inputType); 2637 if (inputTypePacked) 2638 dataTypeSize = 4; 2639 2640 if (this.offset % dataTypeSize != 0) 2641 return false; 2642 } 2643 2644 return true; 2645 }; 2646 2647 /** 2648 * @return {boolean} 2649 */ 2650 glsDrawTests.DrawTestSpec.AttributeSpec.prototype.isBufferStrideAligned = function() { 2651 var inputTypePacked = this.inputType == glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT_2_10_10_10 || this.inputType == glsDrawTests.DrawTestSpec.InputType.INT_2_10_10_10; 2652 2653 // Buffer alignment, offset is a multiple of underlying data type size? 2654 if (this.storage == glsDrawTests.DrawTestSpec.Storage.BUFFER) { 2655 var dataTypeSize = glsDrawTests.DrawTestSpec.inputTypeSize(this.inputType); 2656 if (inputTypePacked) 2657 dataTypeSize = 4; 2658 2659 if (this.stride % dataTypeSize != 0) 2660 return false; 2661 } 2662 2663 return true; 2664 }; 2665 2666 /** 2667 * @constructor 2668 * @extends {tcuTestCase.DeqpTest} 2669 * @param {glsDrawTests.DrawTestSpec} spec 2670 * @param {string} name 2671 * @param {string} desc 2672 */ 2673 glsDrawTests.DrawTest = function(spec, name, desc) { 2674 tcuTestCase.DeqpTest.call(this, name, desc, spec); 2675 2676 /** @type {WebGL2RenderingContext} */ this.m_renderCtx = gl; 2677 /** @type {tcuPixelFormat.PixelFormat} */ this.m_pixelformat = new tcuPixelFormat.PixelFormat( 2678 /** @type {number} */ (gl.getParameter(gl.RED_BITS)), /** @type {number} */ (gl.getParameter(gl.GREEN_BITS)), 2679 /** @type {number} */ (gl.getParameter(gl.BLUE_BITS)), /** @type {number} */ (gl.getParameter(gl.ALPHA_BITS)) 2680 ); 2681 2682 /** @type {sglrReferenceContext.ReferenceContextBuffers} */ this.m_refBuffers = null; 2683 /** @type {sglrReferenceContext.ReferenceContext} */ this.m_refContext = null; 2684 /** @type {sglrGLContext.GLContext} */ this.m_glesContext = null; 2685 2686 /** @type {glsDrawTests.AttributePack} */ this.m_glArrayPack = null; 2687 /** @type {glsDrawTests.AttributePack} */ this.m_rrArrayPack = null; 2688 2689 /** @type {number} */ this.m_maxDiffRed = -1; 2690 /** @type {number} */ this.m_maxDiffGreen = -1; 2691 /** @type {number} */ this.m_maxDiffBlue = -1; 2692 2693 /** @type {Array<glsDrawTests.DrawTestSpec>} */ this.m_specs = []; 2694 /** @type {Array<string>} */this.m_iteration_descriptions = []; 2695 /** @type {number} */ this.m_iteration = 0; 2696 2697 if (spec) 2698 this.addIteration(spec); 2699 }; 2700 2701 glsDrawTests.DrawTest.prototype = Object.create(tcuTestCase.DeqpTest.prototype); 2702 glsDrawTests.DrawTest.prototype.constructor = glsDrawTests.DrawTest; 2703 2704 /** 2705 * @param {glsDrawTests.DrawTestSpec} spec 2706 * @param {string=} description 2707 */ 2708 glsDrawTests.DrawTest.prototype.addIteration = function(spec, description) { 2709 // Validate spec 2710 /** @type {boolean} */ var validSpec = spec.valid(); 2711 2712 if (!validSpec) 2713 return; 2714 2715 this.m_specs.push(spec); 2716 2717 if (description) 2718 this.m_iteration_descriptions.push(description); 2719 else 2720 this.m_iteration_descriptions.push(''); 2721 }; 2722 2723 /** 2724 * init 2725 */ 2726 glsDrawTests.DrawTest.prototype.init = function() { 2727 var renderTargetWidth = Math.min(glsDrawTests.MAX_RENDER_TARGET_SIZE, gl.canvas.width); 2728 var renderTargetHeight = Math.min(glsDrawTests.MAX_RENDER_TARGET_SIZE, gl.canvas.height); 2729 /** @type {sglrReferenceContext.ReferenceContextLimits} */ var limits = new sglrReferenceContext.ReferenceContextLimits(gl); 2730 /** @type {boolean} */ var useVao = true; 2731 2732 this.m_glesContext = new sglrGLContext.GLContext(gl); 2733 2734 assertMsgOptions(this.m_specs.length > 0, 'Specs is empty', false, true); 2735 2736 this.m_refBuffers = new sglrReferenceContext.ReferenceContextBuffers(this.m_pixelformat, 0, 0, renderTargetWidth, renderTargetHeight); 2737 this.m_refContext = new sglrReferenceContext.ReferenceContext(limits, this.m_refBuffers.getColorbuffer(), this.m_refBuffers.getDepthbuffer(), this.m_refBuffers.getStencilbuffer()); 2738 2739 this.m_glArrayPack = new glsDrawTests.AttributePack(this.m_glesContext, [renderTargetWidth, renderTargetHeight], useVao, true); 2740 this.m_rrArrayPack = new glsDrawTests.AttributePack(this.m_refContext, [renderTargetWidth, renderTargetHeight], useVao, false); 2741 2742 this.m_maxDiffRed = Math.ceil(256.0 * (15.0 / (1 << this.m_pixelformat.redBits))); 2743 this.m_maxDiffGreen = Math.ceil(256.0 * (15.0 / (1 << this.m_pixelformat.greenBits))); 2744 this.m_maxDiffBlue = Math.ceil(256.0 * (15.0 / (1 << this.m_pixelformat.blueBits))); 2745 }; 2746 2747 /** 2748 * @return {tcuTestCase.IterateResult} 2749 */ 2750 glsDrawTests.DrawTest.prototype.iterate = function() { 2751 var specNdx = Math.floor(this.m_iteration / 2); 2752 var drawStep = (this.m_iteration % 2) == 0; 2753 var compareStep = (this.m_iteration % 2) == 1; 2754 /** @type {tcuTestCase.IterateResult} */ var iterateResult = (this.m_iteration + 1 == this.m_specs.length * 2) ? (tcuTestCase.IterateResult.STOP) : (tcuTestCase.IterateResult.CONTINUE); 2755 /** @type {glsDrawTests.DrawTestSpec} */ var spec = this.m_specs[specNdx]; 2756 var updateProgram = (this.m_iteration == 0) || (drawStep && !glsDrawTests.checkSpecsShaderCompatible(this.m_specs[specNdx], this.m_specs[specNdx - 1])); // try to use the same shader in all iterations 2757 2758 if (drawStep && this.m_specs.length != 1) 2759 debug('Iteration ' + specNdx + ' of ' + (this.m_specs.length - 1) + ': ' + this.m_iteration_descriptions[specNdx]); 2760 2761 this.m_iteration++; 2762 2763 if (drawStep) { 2764 /** @type {glsDrawTests.MethodInfo} */ var methodInfo = glsDrawTests.getMethodInfo(spec.drawMethod); 2765 /** @type {boolean} */ var indexed = methodInfo.indexed; 2766 /** @type {boolean} */ var instanced = methodInfo.instanced; 2767 /** @type {boolean} */ var ranged = methodInfo.ranged; 2768 /** @type {boolean} */ var hasFirst = methodInfo.first; 2769 2770 /** @type {number} */ var primitiveElementCount = glsDrawTests.getElementCount(spec.primitive, spec.primitiveCount); // !< elements to be drawn 2771 /** @type {number} */ var indexMin = (ranged) ? (spec.indexMin) : (0); 2772 /** @type {number} */ var firstAddition = (hasFirst) ? (spec.first) : (0); 2773 /** @type {number} */ var elementCount = primitiveElementCount + indexMin + firstAddition; // !< elements in buffer (buffer should have at least primitiveElementCount ACCESSIBLE (index range, first) elements) 2774 /** @type {number} */ var maxElementIndex = primitiveElementCount + indexMin + firstAddition - 1; 2775 /** @type {number} */ var indexMax = Math.max(0, (ranged) ? (deMath.clamp(spec.indexMax, 0, maxElementIndex)) : (maxElementIndex)); 2776 /** @type {number} */ var coordScale = this.getCoordScale(spec); 2777 /** @type {number} */ var colorScale = this.getColorScale(spec); 2778 2779 /** @type {Array<number>} */ var nullAttribValue = []; 2780 2781 // Log info 2782 bufferedLogToConsole(spec.getMultilineDesc()); 2783 2784 // Data 2785 this.m_glArrayPack.clearArrays(); 2786 this.m_rrArrayPack.clearArrays(); 2787 2788 // indices 2789 /** @type {number} */ var seed; 2790 /** @type {number} */ var indexElementSize; 2791 /** @type {number} */ var indexArraySize; 2792 /** @type {goog.TypedArray} */ var indexArray; 2793 /** @type {goog.TypedArray} */ var indexPointer; 2794 2795 /** @type {glsDrawTests.AttributeArray}*/ var glArray; 2796 /** @type {glsDrawTests.AttributeArray}*/ var rrArray; 2797 2798 if (indexed) { 2799 seed = spec.hash(); 2800 indexElementSize = glsDrawTests.DrawTestSpec.indexTypeSize(spec.indexType); 2801 indexArraySize = spec.indexPointerOffset + indexElementSize * elementCount; 2802 indexArray = glsDrawTests.RandomArrayGenerator.generateIndices(seed, elementCount, spec.indexType, spec.indexPointerOffset, indexMin, indexMax); 2803 indexPointer = indexArray.subarray(spec.indexPointerOffset); 2804 2805 glArray = new glsDrawTests.AttributeArray(spec.indexStorage, this.m_glesContext); 2806 rrArray = new glsDrawTests.AttributeArray(spec.indexStorage, this.m_refContext); 2807 2808 glArray.data(glsDrawTests.DrawTestSpec.Target.ELEMENT_ARRAY, indexArraySize, indexArray, glsDrawTests.DrawTestSpec.Usage.STATIC_DRAW); 2809 rrArray.data(glsDrawTests.DrawTestSpec.Target.ELEMENT_ARRAY, indexArraySize, indexArray, glsDrawTests.DrawTestSpec.Usage.STATIC_DRAW); 2810 2811 indexArray = null; 2812 } 2813 2814 // attributes 2815 for (var attribNdx = 0; attribNdx < spec.attribs.length; attribNdx++) { 2816 /** @type {glsDrawTests.DrawTestSpec.AttributeSpec} */ var attribSpec = spec.attribs[attribNdx]; 2817 var isPositionAttr = (attribNdx == 0) || (attribSpec.additionalPositionAttribute); 2818 2819 if (attribSpec.useDefaultAttribute) { 2820 seed = 10 * attribSpec.hash() + 100 * spec.hash() + attribNdx; 2821 /** @type {Array<number>} */ var attribValue = glsDrawTests.RandomArrayGenerator.generateAttributeValue(seed, attribSpec.inputType); 2822 2823 // changed USER for BUFFER in JS version 2824 this.m_glArrayPack.newArray(glsDrawTests.DrawTestSpec.Storage.BUFFER); 2825 this.m_rrArrayPack.newArray(glsDrawTests.DrawTestSpec.Storage.BUFFER); 2826 2827 this.m_glArrayPack.getArray(attribNdx).setupArray(false, 0, attribSpec.componentCount, attribSpec.inputType, attribSpec.outputType, false, 0, 0, attribValue, isPositionAttr); 2828 this.m_rrArrayPack.getArray(attribNdx).setupArray(false, 0, attribSpec.componentCount, attribSpec.inputType, attribSpec.outputType, false, 0, 0, attribValue, isPositionAttr); 2829 } else { 2830 seed = attribSpec.hash() + 100 * spec.hash() + attribNdx; 2831 /** @type {number} */ var elementSize = attribSpec.componentCount * glsDrawTests.DrawTestSpec.inputTypeSize(attribSpec.inputType); 2832 /** @type {number} */ var stride = (attribSpec.stride == 0) ? (elementSize) : (attribSpec.stride); 2833 /** @type {number} */ var evaluatedElementCount = (instanced && attribSpec.instanceDivisor > 0) ? (spec.instanceCount / attribSpec.instanceDivisor + 1) : (elementCount); 2834 /** @type {number} */ var referencedElementCount = (ranged) ? (Math.max(evaluatedElementCount, spec.indexMax + 1)) : (evaluatedElementCount); 2835 /** @type {number} */ var bufferSize = attribSpec.offset + stride * (referencedElementCount - 1) + elementSize; 2836 /** @type {goog.TypedArray} */ var data = glsDrawTests.RandomArrayGenerator.createArray( 2837 seed, 2838 referencedElementCount, 2839 attribSpec.componentCount, 2840 attribSpec.offset, 2841 stride, 2842 attribSpec.inputType, 2843 indexed ? 0 : spec.first, 2844 spec.primitive, 2845 indexed ? indexPointer : null, 2846 indexElementSize 2847 ); 2848 2849 this.m_glArrayPack.newArray(attribSpec.storage); 2850 this.m_rrArrayPack.newArray(attribSpec.storage); 2851 2852 this.m_glArrayPack.getArray(attribNdx).data(glsDrawTests.DrawTestSpec.Target.ARRAY, bufferSize, data, attribSpec.usage); 2853 this.m_rrArrayPack.getArray(attribNdx).data(glsDrawTests.DrawTestSpec.Target.ARRAY, bufferSize, data, attribSpec.usage); 2854 2855 this.m_glArrayPack.getArray(attribNdx).setupArray(true, attribSpec.offset, attribSpec.componentCount, attribSpec.inputType, attribSpec.outputType, attribSpec.normalize, attribSpec.stride, attribSpec.instanceDivisor, nullAttribValue, isPositionAttr); 2856 this.m_rrArrayPack.getArray(attribNdx).setupArray(true, attribSpec.offset, attribSpec.componentCount, attribSpec.inputType, attribSpec.outputType, attribSpec.normalize, attribSpec.stride, attribSpec.instanceDivisor, nullAttribValue, isPositionAttr); 2857 2858 data = null; 2859 } 2860 } 2861 2862 // Shader program 2863 if (updateProgram) { 2864 this.m_glArrayPack.updateProgram(); 2865 this.m_rrArrayPack.updateProgram(); 2866 } 2867 2868 /** @type {glsDrawTests.DrawTestSpec.CompatibilityTestType} */ var ctype; 2869 2870 // Draw 2871 try { 2872 // indices 2873 if (indexed) { 2874 this.m_glArrayPack.render(spec.primitive, spec.drawMethod, 0, primitiveElementCount, spec.indexType, spec.indexPointerOffset, spec.indexMin, spec.indexMax, spec.instanceCount, coordScale, colorScale, glArray); 2875 this.m_rrArrayPack.render(spec.primitive, spec.drawMethod, 0, primitiveElementCount, spec.indexType, spec.indexPointerOffset, spec.indexMin, spec.indexMax, spec.instanceCount, coordScale, colorScale, rrArray); 2876 } else { 2877 this.m_glArrayPack.render(spec.primitive, spec.drawMethod, spec.first, primitiveElementCount, null, 0, 0, 0, spec.instanceCount, coordScale, colorScale, null); 2878 this.m_rrArrayPack.render(spec.primitive, spec.drawMethod, spec.first, primitiveElementCount, null, 0, 0, 0, spec.instanceCount, coordScale, colorScale, null); 2879 } 2880 } catch (err) { 2881 if (err instanceof wtu.GLErrorException) { 2882 // GL Errors are ok if the mode is not properly aligned 2883 ctype = spec.isCompatibilityTest(); 2884 2885 bufferedLogToConsole('Got error: ' + err.message); 2886 2887 if (ctype == glsDrawTests.DrawTestSpec.CompatibilityTestType.UNALIGNED_OFFSET) 2888 checkMessage(false, 'Failed to draw with unaligned buffers.'); 2889 else if (ctype == glsDrawTests.DrawTestSpec.CompatibilityTestType.UNALIGNED_STRIDE) 2890 checkMessage(false, 'Failed to draw with unaligned stride.'); 2891 else 2892 throw err; 2893 } 2894 } 2895 } else if (compareStep) { 2896 if (!this.compare(spec.primitive)) { 2897 ctype = spec.isCompatibilityTest(); 2898 2899 if (ctype == glsDrawTests.DrawTestSpec.CompatibilityTestType.UNALIGNED_OFFSET) 2900 checkMessage(false, 'Failed to draw with unaligned buffers.'); 2901 else if (ctype == glsDrawTests.DrawTestSpec.CompatibilityTestType.UNALIGNED_STRIDE) 2902 checkMessage(false, 'Failed to draw with unaligned stride.'); 2903 else 2904 testFailedOptions('Image comparison failed.', false); 2905 return iterateResult; 2906 } 2907 } else { 2908 testFailedOptions('Image comparison failed.', false); 2909 return tcuTestCase.IterateResult.STOP; 2910 } 2911 2912 if (iterateResult == tcuTestCase.IterateResult.STOP) 2913 testPassed(''); 2914 2915 return iterateResult; 2916 }; 2917 2918 /** 2919 * @enum {number} PrimitiveClass 2920 */ 2921 glsDrawTests.PrimitiveClass = { 2922 POINT: 0, 2923 LINE: 1, 2924 TRIANGLE: 2 2925 }; 2926 2927 /** 2928 * @param {?glsDrawTests.DrawTestSpec.Primitive} primitiveType 2929 * @return {glsDrawTests.PrimitiveClass} 2930 */ 2931 glsDrawTests.getDrawPrimitiveClass = function(primitiveType) { 2932 switch (primitiveType) { 2933 case glsDrawTests.DrawTestSpec.Primitive.POINTS: 2934 return glsDrawTests.PrimitiveClass.POINT; 2935 2936 case glsDrawTests.DrawTestSpec.Primitive.LINES: 2937 case glsDrawTests.DrawTestSpec.Primitive.LINE_STRIP: 2938 case glsDrawTests.DrawTestSpec.Primitive.LINE_LOOP: 2939 return glsDrawTests.PrimitiveClass.LINE; 2940 2941 case glsDrawTests.DrawTestSpec.Primitive.TRIANGLES: 2942 case glsDrawTests.DrawTestSpec.Primitive.TRIANGLE_FAN: 2943 case glsDrawTests.DrawTestSpec.Primitive.TRIANGLE_STRIP: 2944 return glsDrawTests.PrimitiveClass.TRIANGLE; 2945 2946 default: 2947 throw new Error('Invalid primitive type'); 2948 } 2949 }; 2950 2951 /** 2952 * @param {number} c1 2953 * @param {number} c2 2954 * @param {Array<number>} threshold 2955 * @return {boolean} 2956 */ 2957 glsDrawTests.compareUintRGB8 = function(c1, c2, threshold) { 2958 return (Math.abs(((c1 >> 16) & 0xff) - ((c2 >> 16) & 0xff)) <= threshold[0] && // Red 2959 Math.abs(((c1 >> 8) & 0xff) - ((c2 >> 8) & 0xff)) <= threshold[1] && // Green 2960 Math.abs((c1 & 0xff) - (c2 & 0xff)) <= threshold[2]); // Blue 2961 }; 2962 2963 /** 2964 * @param {number} c1 2965 * @param {number} c2 2966 * @param {number} c3 2967 * @param {number} renderTargetDifference 2968 * @return {boolean} 2969 */ 2970 glsDrawTests.isEdgeTripletComponent = function(c1, c2, c3, renderTargetDifference) { 2971 /** @type {number} */ var roundingDifference = 2 * renderTargetDifference; // src and dst pixels rounded to different directions 2972 /** @type {number} */ var d1 = c2 - c1; 2973 /** @type {number} */ var d2 = c3 - c2; 2974 /** @type {number} */ var rampDiff = Math.abs(d2 - d1); 2975 2976 return rampDiff > roundingDifference; 2977 }; 2978 2979 /** 2980 * @param {tcuRGBA.RGBA} c1 2981 * @param {tcuRGBA.RGBA} c2 2982 * @param {tcuRGBA.RGBA} c3 2983 * @param {Array<number>} renderTargetThreshold 2984 * @return {boolean} 2985 */ 2986 glsDrawTests.isEdgeTriplet = function(c1, c2, c3, renderTargetThreshold) { 2987 // black (background color) and non-black is always an edge 2988 /** @type {boolean} */ var b1 = c1 == 0x000000; 2989 /** @type {boolean} */ var b2 = c2 == 0x000000; 2990 /** @type {boolean} */ var b3 = c3 == 0x000000; 2991 2992 // both pixels with coverage and pixels without coverage 2993 if ((b1 && b2 && b3) == false && (b1 || b2 || b3) == true) 2994 return true; 2995 // all black 2996 if (b1 && b2 && b3) 2997 return false; 2998 // all with coverage 2999 assertMsgOptions(!b1 && !b2 && !b3, 'All colors with coverage', false, true); 3000 3001 // Color is always linearly interpolated => component values change nearly linearly 3002 // in any constant direction on triangle hull. (df/dx ~= C). 3003 3004 // Edge detection (this function) is run against the reference image 3005 // => no dithering to worry about 3006 3007 return glsDrawTests.isEdgeTripletComponent((c1 >> 16) && 0xff, (c2 >> 16) && 0xff, (c3 >> 16) && 0xff, renderTargetThreshold[0]) || 3008 glsDrawTests.isEdgeTripletComponent((c1 >> 8) && 0xff, (c2 >> 8) && 0xff, (c3 >> 8) && 0xff, renderTargetThreshold[1]) || 3009 glsDrawTests.isEdgeTripletComponent(c1 && 0xff, c2 && 0xff, c3 && 0xff, renderTargetThreshold[2]); 3010 }; 3011 3012 /** 3013 * @param {number} x 3014 * @param {number} y 3015 * @param {tcuSurface.Surface} ref 3016 * @param {Array<number>} renderTargetThreshold 3017 * @return {boolean} 3018 */ 3019 glsDrawTests.pixelNearEdge = function(x, y, ref, renderTargetThreshold) { 3020 // should not be called for edge pixels 3021 assertMsgOptions(x >= 1 && x <= ref.getWidth() - 2, 'The pixel was on the edge', false, true); 3022 assertMsgOptions(y >= 1 && y <= ref.getHeight() - 2, 'The pixel was on the edge', false, true); 3023 3024 // horizontal 3025 3026 /** @type {number} */ var c1; 3027 /** @type {number} */ var c2; 3028 /** @type {number} */ var c3; 3029 3030 for (var dy = -1; dy < 2; ++dy) { 3031 c1 = ref.getPixelUintRGB8(x - 1, y + dy); 3032 c2 = ref.getPixelUintRGB8(x, y + dy); 3033 c3 = ref.getPixelUintRGB8(x + 1, y + dy); 3034 if (glsDrawTests.isEdgeTriplet(c1, c2, c3, renderTargetThreshold)) 3035 return true; 3036 } 3037 3038 // vertical 3039 3040 for (var dx = -1; dx < 2; ++dx) { 3041 c1 = ref.getPixelUintRGB8(x + dx, y - 1); 3042 c2 = ref.getPixelUintRGB8(x + dx, y); 3043 c3 = ref.getPixelUintRGB8(x + dx, y + 1); 3044 if (glsDrawTests.isEdgeTriplet(c1, c2, c3, renderTargetThreshold)) 3045 return true; 3046 } 3047 3048 return false; 3049 }; 3050 3051 /** 3052 * @param {number} c 3053 * @return {number} 3054 */ 3055 glsDrawTests.getVisualizationGrayscaleColorUintRGB8 = function(c) { 3056 // make triangle coverage and error pixels obvious by converting coverage to grayscale 3057 if (c == 0x000000) 3058 return 0; 3059 else 3060 return 50 + Math.floor((((c >> 16) & 0xff) + ((c >> 8) & 0xff) + (c & 0xff)) / 8); 3061 }; 3062 3063 /** 3064 * @param {number} x 3065 * @param {number} y 3066 * @param {tcuSurface.Surface} target 3067 * @return {boolean} 3068 */ 3069 glsDrawTests.pixelNearLineIntersection = function(x, y, target) { 3070 // should not be called for edge pixels 3071 assertMsgOptions(x >= 1 && x <= target.getWidth() - 2, 'Pixel is in the edge', false, true); 3072 assertMsgOptions(y >= 1 && y <= target.getHeight() - 2, 'Pixel is in the edge', false, true); 3073 3074 var coveredPixels = 0; 3075 3076 for (var dy = -1; dy < 2; dy++) 3077 for (var dx = -1; dx < 2; dx++) { 3078 var targetCoverage = target.getPixelUintRGB8(x + dx, y + dy); 3079 if (targetCoverage) { 3080 ++coveredPixels; 3081 3082 // A single thin line cannot have more than 3 covered pixels in a 3x3 area 3083 if (coveredPixels >= 4) 3084 return true; 3085 } 3086 } 3087 3088 return false; 3089 }; 3090 3091 // search 3x3 are for matching color 3092 /** 3093 * @param {tcuSurface.Surface} target 3094 * @param {number} x 3095 * @param {number} y 3096 * @param {tcuRGBA.RGBA} color 3097 * @param {Array<number>} compareThreshold 3098 * @return {boolean} 3099 */ 3100 glsDrawTests.pixelNeighborhoodContainsColor = function(target, x, y, color, compareThreshold) { 3101 // should not be called for edge pixels 3102 assertMsgOptions(x >= 1 && x <= target.getWidth() - 2, 'Pixel is in the edge', false, true); 3103 assertMsgOptions(y >= 1 && y <= target.getHeight() - 2, 'Pixel is in the edge', false, true); 3104 3105 for (var dy = -1; dy < 2; dy++) 3106 for (var dx = -1; dx < 2; dx++) { 3107 if (glsDrawTests.compareUintRGB8(color, target.getPixelUintRGB8(x + dx, y + dy), compareThreshold)) 3108 return true; 3109 } 3110 3111 return false; 3112 }; 3113 3114 // search 3x3 are for matching coverage (coverage == (color != background color)) 3115 /** 3116 * @param {tcuSurface.Surface} target 3117 * @param {number} x 3118 * @param {number} y 3119 * @param {boolean} coverage 3120 * @return {boolean} 3121 */ 3122 glsDrawTests.pixelNeighborhoodContainsCoverage = function(target, x, y, coverage) { 3123 // should not be called for edge pixels 3124 assertMsgOptions(x >= 1 && x <= target.getWidth() - 2, 'Pixel is in the edge', false, true); 3125 assertMsgOptions(y >= 1 && y <= target.getHeight() - 2, 'Pixel is in the edge', false, true); 3126 3127 for (var dy = -1; dy < 2; dy++) 3128 for (var dx = -1; dx < 2; dx++) { 3129 var targetCmpCoverage = target.getPixelUintRGB8(x + dx, y + dy) != 0x000000; // Pixel is not black 3130 if (targetCmpCoverage == coverage) 3131 return true; 3132 } 3133 3134 return false; 3135 }; 3136 3137 /** 3138 * @param {string} imageSetName 3139 * @param {string} imageSetDesc 3140 * @param {tcuSurface.Surface} reference 3141 * @param {tcuSurface.Surface} result 3142 * @param {Array<number>} compareThreshold 3143 * @param {Array<number>} renderTargetThreshold 3144 * @param {number} maxAllowedInvalidPixels 3145 * @return {boolean} 3146 */ 3147 glsDrawTests.edgeRelaxedImageCompare = function(imageSetName, imageSetDesc, reference, result, compareThreshold, renderTargetThreshold, maxAllowedInvalidPixels) { 3148 assertMsgOptions(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight(), 'Reference and result images have different dimensions', false, true); 3149 3150 /** @type {Array<number>} */ var green = [0, 255, 0, 255]; 3151 /** @type {Array<number>} */ var errorColor = [255, 0, 0, 255]; 3152 /** @type {number} */ var width = reference.getWidth(); 3153 /** @type {number} */ var height = reference.getHeight(); 3154 /** @type {tcuSurface.Surface} */ var errorMask = new tcuSurface.Surface(width, height); 3155 /** @type {number} */ var numFailingPixels = 0; 3156 3157 // clear errormask edges which would otherwise be transparent 3158 3159 tcuTextureUtil.getSubregion(errorMask.getAccess(), 0, 0, 0, width, 1, 1).clear(green); 3160 tcuTextureUtil.getSubregion(errorMask.getAccess(), 0, height - 1, 0, width, 1, 1).clear(green); 3161 tcuTextureUtil.getSubregion(errorMask.getAccess(), 0, 0, 0, 1, height, 1).clear(green); 3162 tcuTextureUtil.getSubregion(errorMask.getAccess(), width - 1, 0, 0, 1, height, 1).clear(green); 3163 3164 // skip edge pixels since coverage on edge cannot be verified 3165 3166 for (var y = 1; y < height - 1; ++y) 3167 for (var x = 1; x < width - 1; ++x) { 3168 /** @type {number} */ var refPixel = reference.getPixelUintRGB8(x, y); 3169 /** @type {number} */ var screenPixel = result.getPixelUintRGB8(x, y); 3170 /** @type {boolean} */ var isOkReferencePixel = glsDrawTests.pixelNeighborhoodContainsColor(result, x, y, refPixel, compareThreshold); // screen image has a matching pixel nearby (~= If something is drawn on reference, it must be drawn to screen too.) 3171 /** @type {boolean} */ var isOkScreenPixel = glsDrawTests.pixelNeighborhoodContainsColor(reference, x, y, screenPixel, compareThreshold); // reference image has a matching pixel nearby (~= If something is drawn on screen, it must be drawn to reference too.) 3172 3173 if (isOkScreenPixel && isOkReferencePixel) { 3174 // pixel valid, write greenish pixels to make the result image easier to read 3175 /** @type {number} */ var grayscaleValue = glsDrawTests.getVisualizationGrayscaleColorUintRGB8(screenPixel); 3176 errorMask.getAccess().setPixel([grayscaleValue / 255, 1, grayscaleValue / 255, 1], x, y); 3177 } else if (!glsDrawTests.pixelNearEdge(x, y, reference, renderTargetThreshold)) { 3178 // non-edge pixel values must be within threshold of the reference values 3179 errorMask.getAccess().setPixel(deMath.scale(errorColor, 1 / 255), x, y); 3180 ++numFailingPixels; 3181 } else { 3182 // we are on/near an edge, verify only coverage (coverage == not background colored) 3183 /** @type {boolean} */ var referenceCoverage = refPixel != 0x000000; // Not black 3184 /** @type {boolean} */ var screenCoverage = screenPixel != 0x000000; // Not black 3185 /** @type {boolean} */ var isOkReferenceCoverage = glsDrawTests.pixelNeighborhoodContainsCoverage(result, x, y, referenceCoverage); // Check reference pixel against screen pixel 3186 /** @type {boolean} */ var isOkScreenCoverage = glsDrawTests.pixelNeighborhoodContainsCoverage(reference, x, y, screenCoverage); // Check screen pixels against reference pixel 3187 3188 if (isOkScreenCoverage && isOkReferenceCoverage) { 3189 // pixel valid, write greenish pixels to make the result image easier to read 3190 var grayscaleValue = glsDrawTests.getVisualizationGrayscaleColorUintRGB8(screenPixel); 3191 errorMask.getAccess().setPixel([grayscaleValue / 255, 1, grayscaleValue / 255, 1], x, y); 3192 } else { 3193 // coverage does not match 3194 errorMask.getAccess().setPixel(deMath.scale(errorColor, 1 / 255), x, y); 3195 ++numFailingPixels; 3196 } 3197 } 3198 } 3199 3200 bufferedLogToConsole( 3201 'Comparing images:</br>' + 3202 '<span> </span>allowed deviation in pixel positions = 1</br>' + 3203 '<span> </span>number of allowed invalid pixels = ' + maxAllowedInvalidPixels + '</br>' + 3204 '<span> </span>number of invalid pixels = ' + numFailingPixels 3205 ); 3206 3207 if (numFailingPixels > maxAllowedInvalidPixels) { 3208 debug('Image comparison failed. Color threshold = (' + compareThreshold[0] + ', ' + compareThreshold[1] + ', ' + compareThreshold[2] + ')'); 3209 tcuImageCompare.displayImages(result.getAccess(), reference.getAccess(), errorMask.getAccess()); 3210 3211 return false; 3212 } else { 3213 return true; 3214 } 3215 }; 3216 3217 /** 3218 * @param {string} imageSetName 3219 * @param {string} imageSetDesc 3220 * @param {tcuSurface.Surface} reference 3221 * @param {tcuSurface.Surface} result 3222 * @param {Array<number>} compareThreshold 3223 * @param {number} maxAllowedInvalidPixels 3224 * @return {boolean} 3225 */ 3226 glsDrawTests.intersectionRelaxedLineImageCompare = function(imageSetName, imageSetDesc, reference, result, compareThreshold, maxAllowedInvalidPixels) { 3227 assertMsgOptions(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight(), 'Reference and result images have different dimensions', false, true); 3228 3229 /** @type {Array<number>} */ var green = [0, 255, 0, 255]; 3230 /** @type {Array<number>} */ var errorColor = [255, 0, 0, 255]; 3231 var width = reference.getWidth(); 3232 var height = reference.getHeight(); 3233 /** @type {tcuSurface.Surface} */ var errorMask = new tcuSurface.Surface(width, height); 3234 /** @type {number} */ var numFailingPixels = 0; 3235 3236 // clear errormask edges which would otherwise be transparent 3237 3238 tcuTextureUtil.getSubregion(errorMask.getAccess(), 0, 0, 0, width, 1, 1).clear(green); 3239 tcuTextureUtil.getSubregion(errorMask.getAccess(), 0, height - 1, 0, width, 1, 1).clear(green); 3240 tcuTextureUtil.getSubregion(errorMask.getAccess(), 0, 0, 0, 1, height, 1).clear(green); 3241 tcuTextureUtil.getSubregion(errorMask.getAccess(), width - 1, 0, 0, 1, height, 1).clear(green); 3242 3243 // skip edge pixels since coverage on edge cannot be verified 3244 3245 for (var y = 1; y < height - 1; ++y) 3246 for (var x = 1; x < width - 1; ++x) { 3247 /** @type {number} */ var refPixel = reference.getPixelUintRGB8(x, y); 3248 /** @type {number} */ var screenPixel = result.getPixelUintRGB8(x, y); 3249 /** @type {boolean} */ var isOkScreenPixel = glsDrawTests.pixelNeighborhoodContainsColor(reference, x, y, screenPixel, compareThreshold); // reference image has a matching pixel nearby (~= If something is drawn on screen, it must be drawn to reference too.) 3250 /** @type {boolean} */ var isOkReferencePixel = glsDrawTests.pixelNeighborhoodContainsColor(result, x, y, refPixel, compareThreshold); // screen image has a matching pixel nearby (~= If something is drawn on reference, it must be drawn to screen too.) 3251 3252 /** @type {number} */ var grayscaleValue; 3253 3254 if (isOkScreenPixel && isOkReferencePixel) { 3255 // pixel valid, write greenish pixels to make the result image easier to read 3256 grayscaleValue = glsDrawTests.getVisualizationGrayscaleColorUintRGB8(screenPixel); 3257 errorMask.getAccess().setPixel([grayscaleValue / 255, 1, grayscaleValue / 255, 1], x, y); 3258 } else if (!glsDrawTests.pixelNearLineIntersection(x, y, reference) && 3259 !glsDrawTests.pixelNearLineIntersection(x, y, result)) { 3260 // non-intersection pixel values must be within threshold of the reference values 3261 errorMask.getAccess().setPixel(deMath.scale(errorColor, 1 / 255), x, y); 3262 ++numFailingPixels; 3263 } else { 3264 // pixel is near a line intersection 3265 // we are on/near an edge, verify only coverage (coverage == not background colored) 3266 /** @type {boolean} */ var referenceCoverage = refPixel != 0x000000; // Not Black 3267 /** @type {boolean} */ var screenCoverage = screenPixel != 0x000000; // Not Black 3268 /** @type {boolean} */ var isOkScreenCoverage = glsDrawTests.pixelNeighborhoodContainsCoverage(reference, x, y, screenCoverage); // Check screen pixels against reference pixel 3269 /** @type {boolean} */ var isOkReferenceCoverage = glsDrawTests.pixelNeighborhoodContainsCoverage(result, x, y, referenceCoverage); // Check reference pixel against screen pixel 3270 3271 if (isOkScreenCoverage && isOkReferenceCoverage) { 3272 // pixel valid, write greenish pixels to make the result image easier to read 3273 grayscaleValue = glsDrawTests.getVisualizationGrayscaleColorUintRGB8(screenPixel); 3274 errorMask.getAccess().setPixel([grayscaleValue / 255, 1, grayscaleValue / 255, 1], x, y); 3275 } else { 3276 // coverage does not match 3277 errorMask.getAccess().setPixel(deMath.scale(errorColor, 1 / 255), x, y); 3278 ++numFailingPixels; 3279 } 3280 } 3281 } 3282 3283 bufferedLogToConsole( 3284 'Comparing images:</br>' + 3285 '<span> </span>allowed deviation in pixel positions = 1</br>' + 3286 '<span> </span>number of allowed invalid pixels = ' + maxAllowedInvalidPixels + '</br>' + 3287 '<span> </span>number of invalid pixels = ' + numFailingPixels 3288 ); 3289 3290 if (numFailingPixels > maxAllowedInvalidPixels) { 3291 debug('Image comparison failed. Color threshold = (' + compareThreshold[0] + ', ' + compareThreshold[1] + ', ' + compareThreshold[2] + ')'); 3292 tcuImageCompare.displayImages(result.getAccess(), reference.getAccess(), errorMask.getAccess()); 3293 3294 return false; 3295 } else { 3296 return true; 3297 } 3298 }; 3299 3300 /** 3301 * @param {?glsDrawTests.DrawTestSpec.Primitive} primitiveType 3302 * @return {boolean} 3303 */ 3304 glsDrawTests.DrawTest.prototype.compare = function(primitiveType) { 3305 /** @type {tcuSurface.Surface} */ var ref = this.m_rrArrayPack.getSurface(); 3306 /** @type {tcuSurface.Surface} */ var screen = this.m_glArrayPack.getSurface(); 3307 3308 if (/** @type {number} */ (gl.getParameter(gl.SAMPLES)) > 1) { 3309 // \todo [mika] Improve compare when using multisampling 3310 bufferedLogToConsole('Warning: Comparision of result from multisample render targets are not as strict as without multisampling. Might produce false positives!'); 3311 return tcuImageCompare.fuzzyCompare('Compare Results', 'Compare Results', ref.getAccess(), screen.getAccess(), 0.3, tcuImageCompare.CompareLogMode.RESULT); 3312 } else { 3313 /** @type {glsDrawTests.PrimitiveClass} */ var primitiveClass = glsDrawTests.getDrawPrimitiveClass(primitiveType); 3314 3315 switch (primitiveClass) { 3316 case glsDrawTests.PrimitiveClass.POINT: { 3317 // Point are extremely unlikely to have overlapping regions, don't allow any no extra / missing pixels 3318 /**@type {number} */ var maxAllowedInvalidPixelsWithPoints = 0; 3319 return tcuImageCompare.intThresholdPositionDeviationErrorThresholdCompare( 3320 'CompareResult', 3321 'Result of rendering', 3322 ref.getAccess(), 3323 screen.getAccess(), 3324 [this.m_maxDiffRed, this.m_maxDiffGreen, this.m_maxDiffBlue, 256], 3325 [1, 1, 0], //!< 3x3 search kernel 3326 true, //!< relax comparison on the image boundary 3327 maxAllowedInvalidPixelsWithPoints //!< error threshold 3328 ); 3329 } 3330 3331 case glsDrawTests.PrimitiveClass.LINE: { 3332 // Lines can potentially have a large number of overlapping pixels. Pixel comparison may potentially produce 3333 // false negatives in such pixels if for example the pixel in question is overdrawn by another line in the 3334 // reference image but not in the resultin image. Relax comparison near line intersection points (areas) and 3335 // compare only coverage, not color, in such pixels 3336 /**@type {number} */ var maxAllowedInvalidPixelsWithLines = 15; // line are allowed to have a few bad pixels 3337 return glsDrawTests.intersectionRelaxedLineImageCompare( 3338 'CompareResult', 3339 'Result of rendering', 3340 ref, 3341 screen, 3342 [this.m_maxDiffRed, this.m_maxDiffGreen, this.m_maxDiffBlue], 3343 maxAllowedInvalidPixelsWithLines 3344 ); 3345 } 3346 3347 case glsDrawTests.PrimitiveClass.TRIANGLE: { 3348 // Triangles are likely to partially or fully overlap. Pixel difference comparison is fragile in pixels 3349 // where there could be potential overlapping since the pixels might be covered by one triangle in the 3350 // reference image and by the other in the result image. Relax comparsion near primitive edges and 3351 // compare only coverage, not color, in such pixels. 3352 /** @type {number} */ var maxAllowedInvalidPixelsWithTriangles = 10; 3353 3354 /* TODO: Implement 3355 var renderTargetThreshold = //TODO: get color threshold from the pixel format --> m_renderCtx.getRenderTarget().getPixelFormat().getColorThreshold().toIVec().xyz(); 3356 */ 3357 3358 /** @type {Array<number>} */ var renderTargetThreshold = [3, 3, 3, 3]; 3359 3360 return glsDrawTests.edgeRelaxedImageCompare( 3361 'CompareResult', 3362 'Result of rendering', 3363 ref, 3364 screen, 3365 [this.m_maxDiffRed, this.m_maxDiffGreen, this.m_maxDiffBlue], 3366 renderTargetThreshold, 3367 maxAllowedInvalidPixelsWithTriangles 3368 ); 3369 } 3370 3371 default: 3372 throw new Error('Invalid primitive class'); 3373 } 3374 } 3375 }; 3376 3377 /** 3378 * @param {glsDrawTests.DrawTestSpec} spec 3379 * @return {number} 3380 */ 3381 glsDrawTests.DrawTest.prototype.getCoordScale = function(spec) { 3382 var maxValue = 1.0; 3383 3384 for (var arrayNdx = 0; arrayNdx < spec.attribs.length; arrayNdx++) { 3385 /** @type {glsDrawTests.DrawTestSpec.AttributeSpec} */ var attribSpec = spec.attribs[arrayNdx]; 3386 /** @type {boolean} */ var isPositionAttr = (arrayNdx == 0) || (attribSpec.additionalPositionAttribute); 3387 /** @type {number} */ var attrMaxValue = 0; 3388 3389 if (!isPositionAttr) 3390 continue; 3391 3392 if (attribSpec.inputType == glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT_2_10_10_10) { 3393 if (attribSpec.normalize) 3394 attrMaxValue += 1.0; 3395 else 3396 attrMaxValue += 1024.0; 3397 } else if (attribSpec.inputType == glsDrawTests.DrawTestSpec.InputType.INT_2_10_10_10) { 3398 if (attribSpec.normalize) 3399 attrMaxValue += 1.0; 3400 else 3401 attrMaxValue += 512.0; 3402 } else { 3403 var max = glsDrawTests.GLValue.getMaxValue(attribSpec.inputType).getValue(); 3404 3405 attrMaxValue += (attribSpec.normalize && !glsDrawTests.inputTypeIsFloatType(attribSpec.inputType)) ? (1.0) : (max * 1.1); 3406 } 3407 3408 if (attribSpec.outputType == glsDrawTests.DrawTestSpec.OutputType.VEC3 || attribSpec.outputType == glsDrawTests.DrawTestSpec.OutputType.VEC4 || 3409 attribSpec.outputType == glsDrawTests.DrawTestSpec.OutputType.IVEC3 || attribSpec.outputType == glsDrawTests.DrawTestSpec.OutputType.IVEC4 || 3410 attribSpec.outputType == glsDrawTests.DrawTestSpec.OutputType.UVEC3 || attribSpec.outputType == glsDrawTests.DrawTestSpec.OutputType.UVEC4) 3411 attrMaxValue *= 2; 3412 3413 maxValue += attrMaxValue; 3414 } 3415 3416 return 1.0 / maxValue; 3417 }; 3418 3419 /** 3420 * @param {glsDrawTests.DrawTestSpec} spec 3421 * @return {number} 3422 */ 3423 glsDrawTests.DrawTest.prototype.getColorScale = function(spec) { 3424 var colorScale = 1.0; 3425 3426 for (var arrayNdx = 1; arrayNdx < spec.attribs.length; arrayNdx++) { 3427 /** @type {glsDrawTests.DrawTestSpec.AttributeSpec} */ var attribSpec = spec.attribs[arrayNdx]; 3428 /** @type {boolean} */ var isPositionAttr = (arrayNdx == 0) || (attribSpec.additionalPositionAttribute); 3429 3430 if (isPositionAttr) 3431 continue; 3432 3433 if (attribSpec.inputType == glsDrawTests.DrawTestSpec.InputType.UNSIGNED_INT_2_10_10_10) { 3434 if (!attribSpec.normalize) 3435 colorScale *= 1.0 / 1024.0; 3436 } else if (attribSpec.inputType == glsDrawTests.DrawTestSpec.InputType.INT_2_10_10_10) { 3437 if (!attribSpec.normalize) 3438 colorScale *= 1.0 / 512.0; 3439 } else { 3440 var max = glsDrawTests.GLValue.getMaxValue(attribSpec.inputType).toFloat(); 3441 3442 colorScale *= (attribSpec.normalize && !glsDrawTests.inputTypeIsFloatType(attribSpec.inputType) ? 1.0 : (1.0 / max)); 3443 if (attribSpec.outputType == glsDrawTests.DrawTestSpec.OutputType.VEC4 || 3444 attribSpec.outputType == glsDrawTests.DrawTestSpec.OutputType.UVEC4 || 3445 attribSpec.outputType == glsDrawTests.DrawTestSpec.OutputType.IVEC4) 3446 colorScale *= (attribSpec.normalize && !glsDrawTests.inputTypeIsFloatType(attribSpec.inputType) ? 1.0 : 1.0 / max); 3447 } 3448 } 3449 3450 return colorScale; 3451 }; 3452 });