glsUniformBlockCase.js (103418B)
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.glsUniformBlockCase'); 23 goog.require('framework.common.tcuTestCase'); 24 goog.require('framework.delibs.debase.deMath'); 25 goog.require('framework.delibs.debase.deRandom'); 26 goog.require('framework.delibs.debase.deString'); 27 goog.require('framework.delibs.debase.deUtil'); 28 goog.require('framework.opengl.gluDrawUtil'); 29 goog.require('framework.opengl.gluShaderProgram'); 30 goog.require('framework.opengl.gluShaderUtil'); 31 32 goog.scope(function() { 33 34 var glsUniformBlockCase = modules.shared.glsUniformBlockCase; 35 var tcuTestCase = framework.common.tcuTestCase; 36 var gluShaderProgram = framework.opengl.gluShaderProgram; 37 var gluShaderUtil = framework.opengl.gluShaderUtil; 38 var gluDrawUtil = framework.opengl.gluDrawUtil; 39 var deUtil = framework.delibs.debase.deUtil; 40 var deMath = framework.delibs.debase.deMath; 41 var deRandom = framework.delibs.debase.deRandom; 42 var deString = framework.delibs.debase.deString; 43 44 var DE_ASSERT = function(x) { 45 if (!x) 46 throw new Error('Assert failed'); 47 }; 48 49 var littleEndian = (function() { 50 var buffer = new ArrayBuffer(2); 51 new DataView(buffer).setInt16(0, 256, true /* littleEndian */); 52 // Int16Array uses the platform's endianness. 53 return new Int16Array(buffer)[0] === 256; 54 })(); 55 56 /** 57 * Class to implement some pointers functionality. 58 * @constructor 59 */ 60 glsUniformBlockCase.BlockPointers = function() { 61 /** @type {ArrayBuffer} */ this.data; //!< Data (vector<deUint8>). 62 /** @type {Array<number>} */ this.offsets = []; //!< Reference block pointers (map<int, void*>). 63 /** @type {Array<number>} */ this.sizes = []; 64 }; 65 66 /** 67 * push - Adds an offset/size pair to the collection 68 * @param {number} offset Offset of the element to refer. 69 * @param {number} size Size of the referred element. 70 */ 71 glsUniformBlockCase.BlockPointers.prototype.push = function(offset, size) { 72 this.offsets.push(offset); 73 this.sizes.push(size); 74 }; 75 76 /** 77 * find - Finds and maps the data at the given offset, and returns a Uint8Array 78 * @param {number} index of the element to find. 79 * @return {Uint8Array} 80 */ 81 glsUniformBlockCase.BlockPointers.prototype.find = function(index) { 82 return new Uint8Array(this.data, this.offsets[index], this.sizes[index]); 83 }; 84 85 /** 86 * resize - Replaces resize of a vector in C++. Sets the size of the data buffer. 87 * NOTE: In this case however, if you resize, the data is lost. 88 * @param {number} newsize The new size of the data buffer. 89 */ 90 glsUniformBlockCase.BlockPointers.prototype.resize = function(newsize) { 91 this.data = new ArrayBuffer(newsize); 92 }; 93 94 /** 95 * glsUniformBlockCase.isSupportedGLSLVersion 96 * @param {gluShaderUtil.GLSLVersion} version 97 * @return {boolean} 98 */ 99 glsUniformBlockCase.isSupportedGLSLVersion = function(version) { 100 return version >= gluShaderUtil.GLSLVersion.V300_ES; 101 }; 102 103 /** 104 * @enum {number} 105 */ 106 glsUniformBlockCase.UniformFlags = { 107 PRECISION_LOW: (1 << 0), 108 PRECISION_MEDIUM: (1 << 1), 109 PRECISION_HIGH: (1 << 2), 110 111 LAYOUT_SHARED: (1 << 3), 112 LAYOUT_PACKED: (1 << 4), 113 LAYOUT_STD140: (1 << 5), 114 LAYOUT_ROW_MAJOR: (1 << 6), 115 LAYOUT_COLUMN_MAJOR: (1 << 7), //!< \note Lack of both flags means column-major matrix. 116 117 DECLARE_VERTEX: (1 << 8), 118 DECLARE_FRAGMENT: (1 << 9), 119 120 UNUSED_VERTEX: (1 << 10), //!< glsUniformBlockCase.Uniform or struct member is not read in vertex shader. 121 UNUSED_FRAGMENT: (1 << 11) //!< glsUniformBlockCase.Uniform or struct member is not read in fragment shader. 122 }; 123 124 /** @const */ glsUniformBlockCase.UniformFlags.PRECISION_MASK = glsUniformBlockCase.UniformFlags.PRECISION_LOW | glsUniformBlockCase.UniformFlags.PRECISION_MEDIUM | glsUniformBlockCase.UniformFlags.PRECISION_HIGH; 125 /** @const */ glsUniformBlockCase.UniformFlags.LAYOUT_MASK = glsUniformBlockCase.UniformFlags.LAYOUT_SHARED | glsUniformBlockCase.UniformFlags.LAYOUT_PACKED | glsUniformBlockCase.UniformFlags.LAYOUT_STD140 | glsUniformBlockCase.UniformFlags.LAYOUT_ROW_MAJOR | glsUniformBlockCase.UniformFlags.LAYOUT_COLUMN_MAJOR; 126 /** @const */ glsUniformBlockCase.UniformFlags.DECLARE_BOTH = glsUniformBlockCase.UniformFlags.DECLARE_VERTEX | glsUniformBlockCase.UniformFlags.DECLARE_FRAGMENT; 127 /** @const */ glsUniformBlockCase.UniformFlags.UNUSED_BOTH = glsUniformBlockCase.UniformFlags.UNUSED_VERTEX | glsUniformBlockCase.UniformFlags.UNUSED_FRAGMENT; 128 129 /** 130 * glsUniformBlockCase.VarType types enum 131 * @enum {number} 132 */ 133 glsUniformBlockCase.Type = { 134 TYPE_BASIC: 0, 135 TYPE_ARRAY: 1, 136 TYPE_STRUCT: 2 137 }; 138 139 glsUniformBlockCase.Type.TYPE_LAST = Object.keys(glsUniformBlockCase.Type).length; 140 141 /** 142 * glsUniformBlockCase.TypeArray struct (nothing to do with JS's TypedArrays) 143 * @param {glsUniformBlockCase.VarType} elementType 144 * @param {number} arraySize 145 * @constructor 146 */ 147 glsUniformBlockCase.TypeArray = function(elementType, arraySize) { 148 /** @type {glsUniformBlockCase.VarType} */ this.elementType = elementType; 149 /** @type {number} */ this.size = arraySize; 150 }; 151 152 /** 153 * glsUniformBlockCase.VarType class 154 * @constructor 155 */ 156 glsUniformBlockCase.VarType = function() { 157 /** @type {glsUniformBlockCase.Type} */ this.m_type; 158 /** @type {number} */ this.m_flags = 0; 159 160 /* 161 * m_data used to be a 'Data' union in C++. Using a var is enough here. 162 * it will contain any necessary value. 163 */ 164 165 /** @type {(gluShaderUtil.DataType|glsUniformBlockCase.TypeArray|glsUniformBlockCase.StructType)} */ 166 this.m_data; 167 }; 168 169 /** 170 * Creates a basic type glsUniformBlockCase.VarType. Use this after the constructor call. 171 * @param {gluShaderUtil.DataType} basicType 172 * @param {number} flags 173 * @return {glsUniformBlockCase.VarType} The currently modified object 174 */ 175 glsUniformBlockCase.VarType.prototype.VarTypeBasic = function(basicType, flags) { 176 this.m_type = glsUniformBlockCase.Type.TYPE_BASIC; 177 this.m_flags = flags; 178 this.m_data = basicType; 179 180 return this; 181 }; 182 183 /** 184 * Creates an array type glsUniformBlockCase.VarType. Use this after the constructor call. 185 * @param {glsUniformBlockCase.VarType} elementType 186 * @param {number} arraySize 187 * @return {glsUniformBlockCase.VarType} The currently modified object 188 */ 189 glsUniformBlockCase.VarType.prototype.VarTypeArray = function(elementType, arraySize) { 190 this.m_type = glsUniformBlockCase.Type.TYPE_ARRAY; 191 this.m_flags = 0; 192 this.m_data = new glsUniformBlockCase.TypeArray(elementType, arraySize); 193 194 return this; 195 }; 196 197 /** 198 * Creates a struct type glsUniformBlockCase.VarType. Use this after the constructor call. 199 * @param {glsUniformBlockCase.StructType} structPtr 200 * @return {glsUniformBlockCase.VarType} The currently modified object 201 */ 202 glsUniformBlockCase.VarType.prototype.VarTypeStruct = function(structPtr) { 203 this.m_type = glsUniformBlockCase.Type.TYPE_STRUCT; 204 this.m_flags = 0; 205 this.m_data = structPtr; 206 207 return this; 208 }; 209 210 /** isBasicType 211 * @return {boolean} true if the glsUniformBlockCase.VarType represents a basic type. 212 **/ 213 glsUniformBlockCase.VarType.prototype.isBasicType = function() { 214 return this.m_type == glsUniformBlockCase.Type.TYPE_BASIC; 215 }; 216 217 /** isArrayType 218 * @return {boolean} true if the glsUniformBlockCase.VarType represents an array. 219 **/ 220 glsUniformBlockCase.VarType.prototype.isArrayType = function() { 221 return this.m_type == glsUniformBlockCase.Type.TYPE_ARRAY; 222 }; 223 224 /** isStructType 225 * @return {boolean} true if the glsUniformBlockCase.VarType represents a struct. 226 **/ 227 glsUniformBlockCase.VarType.prototype.isStructType = function() { 228 return this.m_type == glsUniformBlockCase.Type.TYPE_STRUCT; 229 }; 230 231 /** getFlags 232 * @return {number} returns the flags of the glsUniformBlockCase.VarType. 233 **/ 234 glsUniformBlockCase.VarType.prototype.getFlags = function() { 235 return this.m_flags; 236 }; 237 238 /** getBasicType 239 * @return {gluShaderUtil.DataType} returns the basic data type of the glsUniformBlockCase.VarType. 240 **/ 241 glsUniformBlockCase.VarType.prototype.getBasicType = function() { 242 return /** @type {gluShaderUtil.DataType} */ (this.m_data); 243 }; 244 245 /** getElementType 246 * @return {glsUniformBlockCase.VarType} returns the glsUniformBlockCase.VarType of the element in case of an Array. 247 **/ 248 glsUniformBlockCase.VarType.prototype.getElementType = function() { 249 return this.m_data.elementType; 250 }; 251 252 /** getArraySize 253 * (not to be confused with a javascript array) 254 * @return {number} returns the size of the array in case it is an array. 255 **/ 256 glsUniformBlockCase.VarType.prototype.getArraySize = function() { 257 return this.m_data.size; 258 }; 259 260 /** getStruct 261 * @return {glsUniformBlockCase.StructType} returns the structure when it is a glsUniformBlockCase.StructType. 262 **/ 263 glsUniformBlockCase.VarType.prototype.getStruct = function() { 264 return /** @type {glsUniformBlockCase.StructType} */ (this.m_data); 265 }; 266 267 /** 268 * Creates a basic type glsUniformBlockCase.VarType. 269 * @param {gluShaderUtil.DataType} basicType 270 * @param {number} flags 271 * @return {glsUniformBlockCase.VarType} 272 */ 273 glsUniformBlockCase.newVarTypeBasic = function(basicType, flags) { 274 return new glsUniformBlockCase.VarType().VarTypeBasic(basicType, flags); 275 }; 276 277 /** 278 * Creates an array type glsUniformBlockCase.VarType. 279 * @param {glsUniformBlockCase.VarType} elementType 280 * @param {number} arraySize 281 * @return {glsUniformBlockCase.VarType} 282 */ 283 glsUniformBlockCase.newVarTypeArray = function(elementType, arraySize) { 284 return new glsUniformBlockCase.VarType().VarTypeArray(elementType, arraySize); 285 }; 286 287 /** 288 * Creates a struct type glsUniformBlockCase.VarType. 289 * @param {glsUniformBlockCase.StructType} structPtr 290 * @return {glsUniformBlockCase.VarType} 291 */ 292 glsUniformBlockCase.newVarTypeStruct = function(structPtr) { 293 return new glsUniformBlockCase.VarType().VarTypeStruct(structPtr); 294 }; 295 296 /** glsUniformBlockCase.StructMember 297 * in the JSDoc annotations or if a number would do. 298 * @constructor 299 **/ 300 glsUniformBlockCase.StructMember = function() { 301 /** @type {string} */ this.m_name; 302 /** @type {glsUniformBlockCase.VarType} */ this.m_type; 303 /** @type {number} */ this.m_flags = 0; 304 }; 305 306 /** 307 * Creates a glsUniformBlockCase.StructMember. Use this after the constructor call. 308 * @param {string} name 309 * @param {glsUniformBlockCase.VarType} type 310 * @param {number} flags 311 * @return {glsUniformBlockCase.StructMember} The currently modified object 312 */ 313 glsUniformBlockCase.StructMember.prototype.Constructor = function(name, type, flags) { 314 this.m_type = type; 315 this.m_name = name; 316 this.m_flags = flags; 317 318 return this; 319 }; 320 321 /** getName 322 * @return {string} the name of the member 323 **/ 324 glsUniformBlockCase.StructMember.prototype.getName = function() { return this.m_name; }; 325 326 /** getType 327 * @return {glsUniformBlockCase.VarType} the type of the member 328 **/ 329 glsUniformBlockCase.StructMember.prototype.getType = function() { return this.m_type; }; 330 331 /** getFlags 332 * @return {number} the flags in the member 333 **/ 334 glsUniformBlockCase.StructMember.prototype.getFlags = function() { return this.m_flags; }; 335 336 /** 337 * Creates a glsUniformBlockCase.StructMember with name, type and flags. 338 * @param {string} name 339 * @param {glsUniformBlockCase.VarType} type 340 * @return {glsUniformBlockCase.StructMember} 341 */ 342 glsUniformBlockCase.newStructMember = function(name, type, flags) { 343 return new glsUniformBlockCase.StructMember().Constructor(name, type, flags); 344 }; 345 346 /** 347 * glsUniformBlockCase.StructType 348 * @constructor 349 */ 350 glsUniformBlockCase.StructType = function() { 351 /** @type {string}*/ this.m_typeName; 352 /** @type {Array<glsUniformBlockCase.StructMember>} */ this.m_members = []; 353 }; 354 355 /** 356 * glsUniformBlockCase.StructType - Constructor with type name 357 * @param {string} typeName 358 * @return {glsUniformBlockCase.StructType} The currently modified object. 359 */ 360 glsUniformBlockCase.StructType.prototype.Constructor = function(typeName) { 361 /** @type {string}*/ this.m_typeName = typeName; 362 return this; 363 }; 364 365 /** getTypeName 366 * @return {string} 367 **/ 368 glsUniformBlockCase.StructType.prototype.getTypeName = function() { 369 return this.m_typeName; 370 }; 371 372 /* 373 * Instead of iterators, we'll add 374 * a getter for a specific element (getMember), 375 * and current members amount (getSize). 376 */ 377 378 /** getMember 379 * @param {number} memberNdx The index of the member to retrieve. 380 * @return {glsUniformBlockCase.StructMember} 381 **/ 382 glsUniformBlockCase.StructType.prototype.getMember = function(memberNdx) { 383 if (memberNdx >= 0 && memberNdx < this.m_members.length) 384 return this.m_members[memberNdx]; 385 else { 386 throw new Error("Invalid member index for glsUniformBlockCase.StructType's members"); 387 } 388 }; 389 390 /** getSize 391 * @return {number} The size of the m_members array. 392 **/ 393 glsUniformBlockCase.StructType.prototype.getSize = function() { 394 return this.m_members.length; 395 }; 396 397 /** addMember 398 * @param {string} member_name 399 * @param {glsUniformBlockCase.VarType} member_type 400 * @param {number=} member_flags 401 **/ 402 glsUniformBlockCase.StructType.prototype.addMember = function(member_name, member_type, member_flags) { 403 var member = glsUniformBlockCase.newStructMember(member_name, member_type, member_flags); 404 405 this.m_members.push(member); 406 }; 407 408 /** 409 * Creates a glsUniformBlockCase.StructType. 410 * @param {string} name 411 * @return {glsUniformBlockCase.StructType} 412 */ 413 glsUniformBlockCase.newStructType = function(name) { 414 return new glsUniformBlockCase.StructType().Constructor(name); 415 }; 416 417 /** glsUniformBlockCase.Uniform 418 * @param {string} name 419 * @param {glsUniformBlockCase.VarType} type 420 * @param {number=} flags 421 * @constructor 422 **/ 423 glsUniformBlockCase.Uniform = function(name, type, flags) { 424 /** @type {string} */ this.m_name = name; 425 /** @type {glsUniformBlockCase.VarType} */ this.m_type = type; 426 /** @type {number} */ this.m_flags = (typeof flags === 'undefined') ? 0 : flags; 427 }; 428 429 /** getName 430 * @return {string} 431 */ 432 glsUniformBlockCase.Uniform.prototype.getName = function() { 433 return this.m_name; 434 }; 435 436 /** getType 437 * @return {glsUniformBlockCase.VarType} 438 */ 439 glsUniformBlockCase.Uniform.prototype.getType = function() { 440 return this.m_type; 441 }; 442 443 /** getFlags 444 * @return {number} 445 **/ 446 glsUniformBlockCase.Uniform.prototype.getFlags = function() { 447 return this.m_flags; 448 }; 449 450 /** glsUniformBlockCase.UniformBlock 451 * @param {string} blockName 452 * @constructor 453 **/ 454 glsUniformBlockCase.UniformBlock = function(blockName) { 455 /** @type {string} */ this.m_blockName = blockName; 456 /** @type {string} */ this.m_instanceName; 457 /** @type {Array<glsUniformBlockCase.Uniform>} */ this.m_uniforms = []; 458 /** @type {number} */ this.m_arraySize = 0; //!< Array size or 0 if not interface block array. 459 /** @type {number} */ this.m_flags = 0; 460 }; 461 462 /** getBlockName 463 * @return {string} 464 **/ 465 glsUniformBlockCase.UniformBlock.prototype.getBlockName = function() { 466 return this.m_blockName; 467 }; 468 469 /** getInstanceName 470 * @return {string} 471 **/ 472 glsUniformBlockCase.UniformBlock.prototype.getInstanceName = function() { 473 return this.m_instanceName; 474 }; 475 476 /** isArray 477 * @return {boolean} 478 **/ 479 glsUniformBlockCase.UniformBlock.prototype.isArray = function() { 480 return this.m_arraySize > 0; 481 }; 482 483 /** getArraySize 484 * @return {number} 485 **/ 486 glsUniformBlockCase.UniformBlock.prototype.getArraySize = function() { 487 return this.m_arraySize; 488 }; 489 490 /** getFlags 491 * @return {number} 492 **/ 493 glsUniformBlockCase.UniformBlock.prototype.getFlags = function() { 494 return this.m_flags; 495 }; 496 497 /** setInstanceName 498 * @param {string} name 499 **/ 500 glsUniformBlockCase.UniformBlock.prototype.setInstanceName = function(name) { 501 this.m_instanceName = name; 502 }; 503 504 /** setFlags 505 * @param {number} flags 506 **/ 507 glsUniformBlockCase.UniformBlock.prototype.setFlags = function(flags) { 508 this.m_flags = flags; 509 }; 510 511 /** setArraySize 512 * @param {number} arraySize 513 **/ 514 glsUniformBlockCase.UniformBlock.prototype.setArraySize = function(arraySize) { 515 this.m_arraySize = arraySize; 516 }; 517 518 /** addUniform 519 * @param {glsUniformBlockCase.Uniform} uniform 520 **/ 521 glsUniformBlockCase.UniformBlock.prototype.addUniform = function(uniform) { 522 this.m_uniforms.push(uniform); 523 }; 524 525 /* 526 * Using uniform getter (getUniform), 527 * and uniform array size getter (countUniforms) 528 * instead of iterators. 529 */ 530 531 /** 532 * getUniform 533 * @param {number} index 534 * @return {glsUniformBlockCase.Uniform} 535 */ 536 glsUniformBlockCase.UniformBlock.prototype.getUniform = function(index) { 537 if (index >= 0 && index < this.m_uniforms.length) 538 return this.m_uniforms[index]; 539 else { 540 throw new Error("Invalid uniform index for glsUniformBlockCase.UniformBlock's uniforms"); 541 } 542 }; 543 544 /** 545 * countUniforms 546 * @return {number} 547 */ 548 glsUniformBlockCase.UniformBlock.prototype.countUniforms = function() { 549 return this.m_uniforms.length; 550 }; 551 552 /** 553 * glsUniformBlockCase.ShaderInterface 554 * @constructor 555 */ 556 glsUniformBlockCase.ShaderInterface = function() { 557 /** @type {Array<glsUniformBlockCase.StructType>} */ this.m_structs = []; 558 /** @type {Array<glsUniformBlockCase.UniformBlock>} */ this.m_uniformBlocks = []; 559 }; 560 561 /** allocStruct 562 * @param {string} name 563 * @return {glsUniformBlockCase.StructType} 564 **/ 565 glsUniformBlockCase.ShaderInterface.prototype.allocStruct = function(name) { 566 //m_structs.reserve(m_structs.length + 1); 567 this.m_structs.push(glsUniformBlockCase.newStructType(name)); 568 return this.m_structs[this.m_structs.length - 1]; 569 }; 570 571 /** findStruct 572 * @param {string} name 573 * @return {glsUniformBlockCase.StructType} 574 **/ 575 glsUniformBlockCase.ShaderInterface.prototype.findStruct = function(name) { 576 for (var pos = 0; pos < this.m_structs.length; pos++) { 577 if (this.m_structs[pos].getTypeName() == name) 578 return this.m_structs[pos]; 579 } 580 return null; 581 }; 582 583 /** getNamedStructs 584 * @param {Array<glsUniformBlockCase.StructType>} structs 585 **/ 586 glsUniformBlockCase.ShaderInterface.prototype.getNamedStructs = function(structs) { 587 for (var pos = 0; pos < this.m_structs.length; pos++) { 588 if (this.m_structs[pos].getTypeName() != undefined) 589 structs.push(this.m_structs[pos]); 590 } 591 }; 592 593 /** allocBlock 594 * @param {string} name 595 * @return {glsUniformBlockCase.UniformBlock} 596 **/ 597 glsUniformBlockCase.ShaderInterface.prototype.allocBlock = function(name) { 598 this.m_uniformBlocks.push(new glsUniformBlockCase.UniformBlock(name)); 599 return this.m_uniformBlocks[this.m_uniformBlocks.length - 1]; 600 }; 601 602 /** getNumUniformBlocks 603 * @return {number} 604 **/ 605 glsUniformBlockCase.ShaderInterface.prototype.getNumUniformBlocks = function() { 606 return this.m_uniformBlocks.length; 607 }; 608 609 /** getUniformBlock 610 * @param {number} ndx 611 * @return {glsUniformBlockCase.UniformBlock} 612 **/ 613 glsUniformBlockCase.ShaderInterface.prototype.getUniformBlock = function(ndx) { 614 return this.m_uniformBlocks[ndx]; 615 }; 616 617 /** 618 * @constructor 619 */ 620 glsUniformBlockCase.BlockLayoutEntry = function() { 621 return { 622 /** @type {number} */ size: 0, 623 /** @type {string} */ name: '', 624 /** @type {Array<number>} */ activeUniformIndices: [] 625 }; 626 }; 627 628 /** 629 * @constructor 630 */ 631 glsUniformBlockCase.UniformLayoutEntry = function() { 632 return { 633 /** @type {string} */ name: '', 634 /** @type {gluShaderUtil.DataType} */ type: gluShaderUtil.DataType.INVALID, 635 /** @type {number} */ size: 0, 636 /** @type {number} */ blockNdx: -1, 637 /** @type {number} */ offset: -1, 638 /** @type {number} */ arrayStride: -1, 639 /** @type {number} */ matrixStride: -1, 640 /** @type {boolean} */ isRowMajor: false 641 }; 642 }; 643 644 /** 645 * @constructor 646 */ 647 glsUniformBlockCase.UniformLayout = function() { 648 /** @type {Array<glsUniformBlockCase.BlockLayoutEntry>}*/ this.blocks = []; 649 /** @type {Array<glsUniformBlockCase.UniformLayoutEntry>}*/ this.uniforms = []; 650 }; 651 652 /** getUniformIndex, returns a uniform index number in the layout, 653 * given the uniform's name. 654 * @param {string} name 655 * @return {number} uniform's index 656 */ 657 glsUniformBlockCase.UniformLayout.prototype.getUniformIndex = function(name) { 658 for (var ndx = 0; ndx < this.uniforms.length; ndx++) { 659 if (this.uniforms[ndx].name == name) 660 return ndx; 661 } 662 return -1; 663 }; 664 665 /** getBlockIndex, returns a block index number in the layout, 666 * given the block's name. 667 * @param {string} name the name of the block 668 * @return {number} block's index 669 */ 670 glsUniformBlockCase.UniformLayout.prototype.getBlockIndex = function(name) { 671 for (var ndx = 0; ndx < this.blocks.length; ndx++) { 672 if (this.blocks[ndx].name == name) 673 return ndx; 674 } 675 return -1; 676 }; 677 678 /** 679 * @enum {number} 680 */ 681 glsUniformBlockCase.BufferMode = { 682 BUFFERMODE_SINGLE: 0, //!< Single buffer shared between uniform blocks. 683 BUFFERMODE_PER_BLOCK: 1 //!< Per-block buffers 684 }; 685 686 glsUniformBlockCase.BufferMode.BUFFERMODE_LAST = Object.keys(glsUniformBlockCase.BufferMode).length; 687 688 /** 689 * glsUniformBlockCase.PrecisionFlagsFmt 690 * @param {number} flags 691 * @return {string} 692 */ 693 glsUniformBlockCase.PrecisionFlagsFmt = function(flags) { 694 // Precision. 695 DE_ASSERT(deMath.dePop32(flags & (glsUniformBlockCase.UniformFlags.PRECISION_LOW | glsUniformBlockCase.UniformFlags.PRECISION_MEDIUM | glsUniformBlockCase.UniformFlags.PRECISION_HIGH)) <= 1); 696 var str = ''; 697 str += (flags & glsUniformBlockCase.UniformFlags.PRECISION_LOW ? 'lowp' : 698 flags & glsUniformBlockCase.UniformFlags.PRECISION_MEDIUM ? 'mediump' : 699 flags & glsUniformBlockCase.UniformFlags.PRECISION_HIGH ? 'highp' : ''); 700 701 return str; 702 }; 703 704 /** 705 * glsUniformBlockCase.LayoutFlagsFmt 706 * @param {number} flags_ 707 * @return {string} 708 */ 709 glsUniformBlockCase.LayoutFlagsFmt = function(flags_) { 710 var str = ''; 711 var bitDesc = 712 [{ bit: glsUniformBlockCase.UniformFlags.LAYOUT_SHARED, token: 'shared' }, { bit: glsUniformBlockCase.UniformFlags.LAYOUT_PACKED, token: 'packed' }, { bit: glsUniformBlockCase.UniformFlags.LAYOUT_STD140, token: 'std140' }, { bit: glsUniformBlockCase.UniformFlags.LAYOUT_ROW_MAJOR, token: 'row_major' }, { bit: glsUniformBlockCase.UniformFlags.LAYOUT_COLUMN_MAJOR, token: 'column_major' } 713 ]; 714 715 /** @type {number} */ var remBits = flags_; 716 for (var descNdx = 0; descNdx < bitDesc.length; descNdx++) { 717 if (remBits & bitDesc[descNdx].bit) { 718 if (remBits != flags_) 719 str += ', '; 720 str += bitDesc[descNdx].token; 721 remBits &= (~bitDesc[descNdx].bit) & 0xFFFFFFFF; //0xFFFFFFFF truncate to 32 bit value 722 } 723 } 724 DE_ASSERT(remBits == 0); 725 726 return str; 727 }; 728 729 /** 730 * @constructor 731 */ 732 glsUniformBlockCase.UniformBufferManager = function(renderCtx) { 733 this.m_renderCtx = renderCtx; 734 /** @type {Array<number>} */ this.m_buffers = []; 735 }; 736 737 /** 738 * allocBuffer 739 * @return {WebGLBuffer} 740 */ 741 glsUniformBlockCase.UniformBufferManager.prototype.allocBuffer = function() { 742 /** @type {WebGLBuffer} */ var buf = this.m_renderCtx.createBuffer(); 743 744 this.m_buffers.push(buf); 745 746 return buf; 747 }; 748 749 /** 750 * @param {string} name 751 * @param {string} description 752 * @param {glsUniformBlockCase.BufferMode} bufferMode 753 * @constructor 754 * @extends {tcuTestCase.DeqpTest} 755 */ 756 glsUniformBlockCase.UniformBlockCase = function(name, description, bufferMode) { 757 tcuTestCase.DeqpTest.call(this, name, description); 758 /** @type {string} */ this.m_name = name; 759 /** @type {string} */ this.m_description = description; 760 /** @type {glsUniformBlockCase.BufferMode} */ this.m_bufferMode = bufferMode; 761 /** @type {glsUniformBlockCase.ShaderInterface} */ this.m_interface = new glsUniformBlockCase.ShaderInterface(); 762 }; 763 764 glsUniformBlockCase.UniformBlockCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype); 765 glsUniformBlockCase.UniformBlockCase.prototype.constructor = glsUniformBlockCase.UniformBlockCase; 766 767 /** 768 * glsUniformBlockCase.getDataTypeByteSize 769 * @param {gluShaderUtil.DataType} type 770 * @return {number} 771 */ 772 glsUniformBlockCase.getDataTypeByteSize = function(type) { 773 return gluShaderUtil.getDataTypeScalarSize(type) * deMath.INT32_SIZE; 774 }; 775 776 /** 777 * glsUniformBlockCase.getDataTypeByteAlignment 778 * @param {gluShaderUtil.DataType} type 779 * @return {number} 780 */ 781 glsUniformBlockCase.getDataTypeByteAlignment = function(type) { 782 switch (type) { 783 case gluShaderUtil.DataType.FLOAT: 784 case gluShaderUtil.DataType.INT: 785 case gluShaderUtil.DataType.UINT: 786 case gluShaderUtil.DataType.BOOL: return 1 * deMath.INT32_SIZE; 787 788 case gluShaderUtil.DataType.FLOAT_VEC2: 789 case gluShaderUtil.DataType.INT_VEC2: 790 case gluShaderUtil.DataType.UINT_VEC2: 791 case gluShaderUtil.DataType.BOOL_VEC2: return 2 * deMath.INT32_SIZE; 792 793 case gluShaderUtil.DataType.FLOAT_VEC3: 794 case gluShaderUtil.DataType.INT_VEC3: 795 case gluShaderUtil.DataType.UINT_VEC3: 796 case gluShaderUtil.DataType.BOOL_VEC3: // Fall-through to vec4 797 798 case gluShaderUtil.DataType.FLOAT_VEC4: 799 case gluShaderUtil.DataType.INT_VEC4: 800 case gluShaderUtil.DataType.UINT_VEC4: 801 case gluShaderUtil.DataType.BOOL_VEC4: return 4 * deMath.INT32_SIZE; 802 803 default: 804 DE_ASSERT(false); 805 return 0; 806 } 807 }; 808 809 /** 810 * glsUniformBlockCase.getDataTypeArrayStride 811 * @param {gluShaderUtil.DataType} type 812 * @return {number} 813 */ 814 glsUniformBlockCase.getDataTypeArrayStride = function(type) { 815 DE_ASSERT(!gluShaderUtil.isDataTypeMatrix(type)); 816 817 /** @type {number} */ var baseStride = glsUniformBlockCase.getDataTypeByteSize(type); 818 /** @type {number} */ var vec4Alignment = deMath.INT32_SIZE * 4; 819 820 DE_ASSERT(baseStride <= vec4Alignment); 821 return Math.max(baseStride, vec4Alignment); // Really? See rule 4. 822 }; 823 824 /** 825 * glsUniformBlockCase.deRoundUp32 Rounds up 'a' in case the 826 * relationship with 'b' has a decimal part. 827 * @param {number} a 828 * @param {number} b 829 * @return {number} 830 */ 831 glsUniformBlockCase.deRoundUp32 = function(a, b) { 832 var d = Math.trunc(a / b); 833 return d * b == a ? a : (d + 1) * b; 834 }; 835 836 /** 837 * glsUniformBlockCase.computeStd140BaseAlignment 838 * @param {glsUniformBlockCase.VarType} type 839 * @return {number} 840 */ 841 glsUniformBlockCase.computeStd140BaseAlignment = function(type) { 842 /** @type {number} */ var vec4Alignment = deMath.INT32_SIZE * 4; 843 844 if (type.isBasicType()) { 845 /** @type {gluShaderUtil.DataType} */ var basicType = type.getBasicType(); 846 847 if (gluShaderUtil.isDataTypeMatrix(basicType)) { 848 /** @type {boolean} */ var isRowMajor = !!(type.getFlags() & glsUniformBlockCase.UniformFlags.LAYOUT_ROW_MAJOR); 849 /** @type {number} */ var vecSize = isRowMajor ? gluShaderUtil.getDataTypeMatrixNumColumns(basicType) : 850 gluShaderUtil.getDataTypeMatrixNumRows(basicType); 851 852 return glsUniformBlockCase.getDataTypeArrayStride(gluShaderUtil.getDataTypeFloatVec(vecSize)); 853 } else 854 return glsUniformBlockCase.getDataTypeByteAlignment(basicType); 855 } else if (type.isArrayType()) { 856 /** @type {number} */ var elemAlignment = glsUniformBlockCase.computeStd140BaseAlignment(type.getElementType()); 857 858 // Round up to alignment of vec4 859 return glsUniformBlockCase.deRoundUp32(elemAlignment, vec4Alignment); 860 } else { 861 DE_ASSERT(type.isStructType()); 862 863 /** @type {number} */ var maxBaseAlignment = 0; 864 865 for (var memberNdx = 0; memberNdx < type.getStruct().getSize(); memberNdx++) { 866 /** @type {glsUniformBlockCase.StructMember} */ var memberIter = type.getStruct().getMember(memberNdx); 867 maxBaseAlignment = Math.max(maxBaseAlignment, glsUniformBlockCase.computeStd140BaseAlignment(memberIter.getType())); 868 } 869 870 return glsUniformBlockCase.deRoundUp32(maxBaseAlignment, vec4Alignment); 871 } 872 }; 873 874 /** 875 * mergeLayoutflags 876 * @param {number} prevFlags 877 * @param {number} newFlags 878 * @return {number} 879 */ 880 glsUniformBlockCase.mergeLayoutFlags = function(prevFlags, newFlags) { 881 /** @type {number} */ var packingMask = glsUniformBlockCase.UniformFlags.LAYOUT_PACKED | glsUniformBlockCase.UniformFlags.LAYOUT_SHARED | glsUniformBlockCase.UniformFlags.LAYOUT_STD140; 882 /** @type {number} */ var matrixMask = glsUniformBlockCase.UniformFlags.LAYOUT_ROW_MAJOR | glsUniformBlockCase.UniformFlags.LAYOUT_COLUMN_MAJOR; 883 884 /** @type {number} */ var mergedFlags = 0; 885 886 mergedFlags |= ((newFlags & packingMask) ? newFlags : prevFlags) & packingMask; 887 mergedFlags |= ((newFlags & matrixMask) ? newFlags : prevFlags) & matrixMask; 888 889 return mergedFlags; 890 }; 891 892 /** 893 * glsUniformBlockCase.computeStd140Layout_B 894 * @param {glsUniformBlockCase.UniformLayout} layout 895 * @param {number} curOffset 896 * @param {number} curBlockNdx 897 * @param {string} curPrefix 898 * @param {glsUniformBlockCase.VarType} type 899 * @param {number} layoutFlags 900 * @return {number} //This is what would return in the curOffset output parameter in the original C++ project. 901 */ 902 glsUniformBlockCase.computeStd140Layout_B = function(layout, curOffset, curBlockNdx, curPrefix, type, layoutFlags) { 903 /** @type {number} */ var baseAlignment = glsUniformBlockCase.computeStd140BaseAlignment(type); 904 /** @type {glsUniformBlockCase.UniformLayoutEntry} */ var entry; 905 /** @type {number} */ var stride; 906 /** @type {gluShaderUtil.DataType} */ var elemBasicType; 907 /** @type {boolean} */ var isRowMajor; 908 /** @type {number} */ var vecSize; 909 /** @type {number} */ var numVecs; 910 911 curOffset = deMath.deAlign32(curOffset, baseAlignment); 912 913 if (type.isBasicType()) { 914 /** @type {gluShaderUtil.DataType} */ var basicType = type.getBasicType(); 915 entry = new glsUniformBlockCase.UniformLayoutEntry(); 916 917 entry.name = curPrefix; 918 entry.type = basicType; 919 entry.size = 1; 920 entry.arrayStride = 0; 921 entry.matrixStride = 0; 922 entry.blockNdx = curBlockNdx; 923 924 if (gluShaderUtil.isDataTypeMatrix(basicType)) { 925 // Array of vectors as specified in rules 5 & 7. 926 isRowMajor = !!(layoutFlags & glsUniformBlockCase.UniformFlags.LAYOUT_ROW_MAJOR); 927 vecSize = isRowMajor ? gluShaderUtil.getDataTypeMatrixNumColumns(basicType) : 928 gluShaderUtil.getDataTypeMatrixNumRows(basicType); 929 numVecs = isRowMajor ? gluShaderUtil.getDataTypeMatrixNumRows(basicType) : 930 gluShaderUtil.getDataTypeMatrixNumColumns(basicType); 931 stride = glsUniformBlockCase.getDataTypeArrayStride(gluShaderUtil.getDataTypeFloatVec(vecSize)); 932 933 entry.offset = curOffset; 934 entry.matrixStride = stride; 935 entry.isRowMajor = isRowMajor; 936 937 curOffset += numVecs * stride; 938 } else { 939 // Scalar or vector. 940 entry.offset = curOffset; 941 942 curOffset += glsUniformBlockCase.getDataTypeByteSize(basicType); 943 } 944 945 layout.uniforms.push(entry); 946 } else if (type.isArrayType()) { 947 /** @type {glsUniformBlockCase.VarType} */ var elemType = type.getElementType(); 948 949 if (elemType.isBasicType() && !gluShaderUtil.isDataTypeMatrix(elemType.getBasicType())) { 950 // Array of scalars or vectors. 951 elemBasicType = elemType.getBasicType(); 952 entry = new glsUniformBlockCase.UniformLayoutEntry(); 953 stride = glsUniformBlockCase.getDataTypeArrayStride(elemBasicType); 954 955 entry.name = curPrefix + '[0]'; // Array uniforms are always postfixed with [0] 956 entry.type = elemBasicType; 957 entry.blockNdx = curBlockNdx; 958 entry.offset = curOffset; 959 entry.size = type.getArraySize(); 960 entry.arrayStride = stride; 961 entry.matrixStride = 0; 962 963 curOffset += stride * type.getArraySize(); 964 965 layout.uniforms.push(entry); 966 } else if (elemType.isBasicType() && gluShaderUtil.isDataTypeMatrix(elemType.getBasicType())) { 967 // Array of matrices. 968 elemBasicType = elemType.getBasicType(); 969 isRowMajor = !!(layoutFlags & glsUniformBlockCase.UniformFlags.LAYOUT_ROW_MAJOR); 970 vecSize = isRowMajor ? gluShaderUtil.getDataTypeMatrixNumColumns(elemBasicType) : 971 gluShaderUtil.getDataTypeMatrixNumRows(elemBasicType); 972 numVecs = isRowMajor ? gluShaderUtil.getDataTypeMatrixNumRows(elemBasicType) : 973 gluShaderUtil.getDataTypeMatrixNumColumns(elemBasicType); 974 stride = glsUniformBlockCase.getDataTypeArrayStride(gluShaderUtil.getDataTypeFloatVec(vecSize)); 975 entry = new glsUniformBlockCase.UniformLayoutEntry(); 976 977 entry.name = curPrefix + '[0]'; // Array uniforms are always postfixed with [0] 978 entry.type = elemBasicType; 979 entry.blockNdx = curBlockNdx; 980 entry.offset = curOffset; 981 entry.size = type.getArraySize(); 982 entry.arrayStride = stride * numVecs; 983 entry.matrixStride = stride; 984 entry.isRowMajor = isRowMajor; 985 986 curOffset += numVecs * type.getArraySize() * stride; 987 988 layout.uniforms.push(entry); 989 } else { 990 DE_ASSERT(elemType.isStructType() || elemType.isArrayType()); 991 992 for (var elemNdx = 0; elemNdx < type.getArraySize(); elemNdx++) 993 curOffset = glsUniformBlockCase.computeStd140Layout_B(layout, curOffset, curBlockNdx, curPrefix + '[' + elemNdx + ']', type.getElementType(), layoutFlags); 994 } 995 } else { 996 DE_ASSERT(type.isStructType()); 997 998 for (var memberNdx = 0; memberNdx < type.getStruct().getSize(); memberNdx++) { 999 /** @type {glsUniformBlockCase.StructMember} */ var memberIter = type.getStruct().getMember(memberNdx); 1000 curOffset = glsUniformBlockCase.computeStd140Layout_B(layout, curOffset, curBlockNdx, curPrefix + '.' + memberIter.getName(), memberIter.getType(), layoutFlags); 1001 } 1002 1003 curOffset = deMath.deAlign32(curOffset, baseAlignment); 1004 } 1005 1006 return curOffset; 1007 }; 1008 1009 /** 1010 * glsUniformBlockCase.computeStd140Layout 1011 * @param {glsUniformBlockCase.UniformLayout} layout 1012 * @param {glsUniformBlockCase.ShaderInterface} sinterface 1013 */ 1014 glsUniformBlockCase.computeStd140Layout = function(layout, sinterface) { 1015 // \todo [2012-01-23 pyry] Uniforms in default block. 1016 1017 /** @type {number} */ var numUniformBlocks = sinterface.getNumUniformBlocks(); 1018 1019 for (var blockNdx = 0; blockNdx < numUniformBlocks; blockNdx++) { 1020 /** @type {glsUniformBlockCase.UniformBlock} */ var block = sinterface.getUniformBlock(blockNdx); 1021 /** @type {boolean} */ var hasInstanceName = block.getInstanceName() !== undefined; 1022 /** @type {string} */ var blockPrefix = hasInstanceName ? (block.getBlockName() + '.') : ''; 1023 /** @type {number} */ var curOffset = 0; 1024 /** @type {number} */ var activeBlockNdx = layout.blocks.length; 1025 /** @type {number} */ var firstUniformNdx = layout.uniforms.length; 1026 1027 for (var ubNdx = 0; ubNdx < block.countUniforms(); ubNdx++) { 1028 /** @type {glsUniformBlockCase.Uniform} */ var uniform = block.getUniform(ubNdx); 1029 curOffset = glsUniformBlockCase.computeStd140Layout_B(layout, curOffset, activeBlockNdx, blockPrefix + uniform.getName(), uniform.getType(), glsUniformBlockCase.mergeLayoutFlags(block.getFlags(), uniform.getFlags())); 1030 } 1031 1032 /** @type {number} */ var uniformIndicesEnd = layout.uniforms.length; 1033 /** @type {number} */ var blockSize = curOffset; 1034 /** @type {number} */ var numInstances = block.isArray() ? block.getArraySize() : 1; 1035 1036 // Create block layout entries for each instance. 1037 for (var instanceNdx = 0; instanceNdx < numInstances; instanceNdx++) { 1038 // Allocate entry for instance. 1039 layout.blocks.push(new glsUniformBlockCase.BlockLayoutEntry()); 1040 /** @type {glsUniformBlockCase.BlockLayoutEntry} */ var blockEntry = layout.blocks[layout.blocks.length - 1]; 1041 1042 blockEntry.name = block.getBlockName(); 1043 blockEntry.size = blockSize; 1044 1045 // Compute active uniform set for block. 1046 for (var uniformNdx = firstUniformNdx; uniformNdx < uniformIndicesEnd; uniformNdx++) 1047 blockEntry.activeUniformIndices.push(uniformNdx); 1048 1049 if (block.isArray()) 1050 blockEntry.name += '[' + instanceNdx + ']'; 1051 } 1052 } 1053 }; 1054 1055 /** 1056 * glsUniformBlockCase.generateValue - Value generator 1057 * @param {glsUniformBlockCase.UniformLayoutEntry} entry 1058 * @param {Uint8Array} basePtr 1059 * @param {deRandom.Random} rnd 1060 */ 1061 glsUniformBlockCase.generateValue = function(entry, basePtr, rnd) { 1062 /** @type {gluShaderUtil.DataType}*/ var scalarType = gluShaderUtil.getDataTypeScalarTypeAsDataType(entry.type); //Using a more appropriate function in this case. 1063 /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(entry.type); 1064 /** @type {boolean} */ var isMatrix = gluShaderUtil.isDataTypeMatrix(entry.type); 1065 /** @type {number} */ var numVecs = isMatrix ? (entry.isRowMajor ? gluShaderUtil.getDataTypeMatrixNumRows(entry.type) : gluShaderUtil.getDataTypeMatrixNumColumns(entry.type)) : 1; 1066 /** @type {number} */ var vecSize = scalarSize / numVecs; 1067 /** @type {boolean} */ var isArray = entry.size > 1; 1068 /** @type {number} */ var compSize = deMath.INT32_SIZE; 1069 1070 DE_ASSERT(scalarSize % numVecs == 0); 1071 1072 for (var elemNdx = 0; elemNdx < entry.size; elemNdx++) { 1073 /** @type {Uint8Array} */ var elemPtr = basePtr.subarray(entry.offset + (isArray ? elemNdx * entry.arrayStride : 0)); 1074 1075 for (var vecNdx = 0; vecNdx < numVecs; vecNdx++) { 1076 /** @type {Uint8Array} */ var vecPtr = elemPtr.subarray(isMatrix ? vecNdx * entry.matrixStride : 0); 1077 1078 for (var compNdx = 0; compNdx < vecSize; compNdx++) { 1079 /** @type {Uint8Array} */ var compPtr = vecPtr.subarray(compSize * compNdx); 1080 /** @type {number} */ var _random; 1081 1082 //Copy the random data byte per byte 1083 var _size = glsUniformBlockCase.getDataTypeByteSize(scalarType); 1084 1085 var nbuffer = new ArrayBuffer(_size); 1086 var nview = new DataView(nbuffer); 1087 1088 switch (scalarType) { 1089 case gluShaderUtil.DataType.FLOAT: 1090 _random = rnd.getInt(-9, 9); 1091 nview.setFloat32(0, _random, littleEndian); 1092 break; 1093 case gluShaderUtil.DataType.INT: 1094 _random = rnd.getInt(-9, 9); 1095 nview.setInt32(0, _random, littleEndian); 1096 break; 1097 case gluShaderUtil.DataType.UINT: 1098 _random = rnd.getInt(0, 9); 1099 nview.setUint32(0, _random, littleEndian); 1100 break; 1101 // \note Random bit pattern is used for true values. Spec states that all non-zero values are 1102 // interpreted as true but some implementations fail this. 1103 case gluShaderUtil.DataType.BOOL: 1104 _random = rnd.getBool() ? 1 : 0; 1105 nview.setUint32(0, _random, littleEndian); 1106 break; 1107 default: 1108 DE_ASSERT(false); 1109 } 1110 1111 for (var i = 0; i < _size; i++) { 1112 compPtr[i] = nview.getUint8(i); 1113 } 1114 } 1115 } 1116 } 1117 }; 1118 1119 /** 1120 * glsUniformBlockCase.generateValues 1121 * @param {glsUniformBlockCase.UniformLayout} layout 1122 * @param {glsUniformBlockCase.BlockPointers} blockPointers 1123 * @param {number} seed 1124 */ 1125 glsUniformBlockCase.generateValues = function(layout, blockPointers, seed) { 1126 /** @type {deRandom.Random} */ var rnd = new deRandom.Random(seed); 1127 /** @type {number} */ var numBlocks = layout.blocks.length; 1128 1129 for (var blockNdx = 0; blockNdx < numBlocks; blockNdx++) { 1130 /** @type {Uint8Array} */ var basePtr = blockPointers.find(blockNdx); 1131 /** @type {number} */ var numEntries = layout.blocks[blockNdx].activeUniformIndices.length; 1132 1133 for (var entryNdx = 0; entryNdx < numEntries; entryNdx++) { 1134 /** @type {glsUniformBlockCase.UniformLayoutEntry} */ var entry = layout.uniforms[layout.blocks[blockNdx].activeUniformIndices[entryNdx]]; 1135 glsUniformBlockCase.generateValue(entry, basePtr, rnd); 1136 } 1137 } 1138 }; 1139 1140 // Shader generator. 1141 1142 /** 1143 * glsUniformBlockCase.getCompareFuncForType 1144 * @param {gluShaderUtil.DataType} type 1145 * @return {string} 1146 */ 1147 glsUniformBlockCase.getCompareFuncForType = function(type) { 1148 switch (type) { 1149 case gluShaderUtil.DataType.FLOAT: return 'mediump float compare_float (highp float a, highp float b) { return abs(a - b) < 0.05 ? 1.0 : 0.0; }\n'; 1150 case gluShaderUtil.DataType.FLOAT_VEC2: return 'mediump float compare_vec2 (highp vec2 a, highp vec2 b) { return compare_float(a.x, b.x)*compare_float(a.y, b.y); }\n'; 1151 case gluShaderUtil.DataType.FLOAT_VEC3: return 'mediump float compare_vec3 (highp vec3 a, highp vec3 b) { return compare_float(a.x, b.x)*compare_float(a.y, b.y)*compare_float(a.z, b.z); }\n'; 1152 case gluShaderUtil.DataType.FLOAT_VEC4: return 'mediump float compare_vec4 (highp vec4 a, highp vec4 b) { return compare_float(a.x, b.x)*compare_float(a.y, b.y)*compare_float(a.z, b.z)*compare_float(a.w, b.w); }\n'; 1153 case gluShaderUtil.DataType.FLOAT_MAT2: return 'mediump float compare_mat2 (highp mat2 a, highp mat2 b) { return compare_vec2(a[0], b[0])*compare_vec2(a[1], b[1]); }\n'; 1154 case gluShaderUtil.DataType.FLOAT_MAT2X3: return 'mediump float compare_mat2x3 (highp mat2x3 a, highp mat2x3 b) { return compare_vec3(a[0], b[0])*compare_vec3(a[1], b[1]); }\n'; 1155 case gluShaderUtil.DataType.FLOAT_MAT2X4: return 'mediump float compare_mat2x4 (highp mat2x4 a, highp mat2x4 b) { return compare_vec4(a[0], b[0])*compare_vec4(a[1], b[1]); }\n'; 1156 case gluShaderUtil.DataType.FLOAT_MAT3X2: return 'mediump float compare_mat3x2 (highp mat3x2 a, highp mat3x2 b) { return compare_vec2(a[0], b[0])*compare_vec2(a[1], b[1])*compare_vec2(a[2], b[2]); }\n'; 1157 case gluShaderUtil.DataType.FLOAT_MAT3: return 'mediump float compare_mat3 (highp mat3 a, highp mat3 b) { return compare_vec3(a[0], b[0])*compare_vec3(a[1], b[1])*compare_vec3(a[2], b[2]); }\n'; 1158 case gluShaderUtil.DataType.FLOAT_MAT3X4: return 'mediump float compare_mat3x4 (highp mat3x4 a, highp mat3x4 b) { return compare_vec4(a[0], b[0])*compare_vec4(a[1], b[1])*compare_vec4(a[2], b[2]); }\n'; 1159 case gluShaderUtil.DataType.FLOAT_MAT4X2: return 'mediump float compare_mat4x2 (highp mat4x2 a, highp mat4x2 b) { return compare_vec2(a[0], b[0])*compare_vec2(a[1], b[1])*compare_vec2(a[2], b[2])*compare_vec2(a[3], b[3]); }\n'; 1160 case gluShaderUtil.DataType.FLOAT_MAT4X3: return 'mediump float compare_mat4x3 (highp mat4x3 a, highp mat4x3 b) { return compare_vec3(a[0], b[0])*compare_vec3(a[1], b[1])*compare_vec3(a[2], b[2])*compare_vec3(a[3], b[3]); }\n'; 1161 case gluShaderUtil.DataType.FLOAT_MAT4: return 'mediump float compare_mat4 (highp mat4 a, highp mat4 b) { return compare_vec4(a[0], b[0])*compare_vec4(a[1], b[1])*compare_vec4(a[2], b[2])*compare_vec4(a[3], b[3]); }\n'; 1162 case gluShaderUtil.DataType.INT: return 'mediump float compare_int (highp int a, highp int b) { return a == b ? 1.0 : 0.0; }\n'; 1163 case gluShaderUtil.DataType.INT_VEC2: return 'mediump float compare_ivec2 (highp ivec2 a, highp ivec2 b) { return a == b ? 1.0 : 0.0; }\n'; 1164 case gluShaderUtil.DataType.INT_VEC3: return 'mediump float compare_ivec3 (highp ivec3 a, highp ivec3 b) { return a == b ? 1.0 : 0.0; }\n'; 1165 case gluShaderUtil.DataType.INT_VEC4: return 'mediump float compare_ivec4 (highp ivec4 a, highp ivec4 b) { return a == b ? 1.0 : 0.0; }\n'; 1166 case gluShaderUtil.DataType.UINT: return 'mediump float compare_uint (highp uint a, highp uint b) { return a == b ? 1.0 : 0.0; }\n'; 1167 case gluShaderUtil.DataType.UINT_VEC2: return 'mediump float compare_uvec2 (highp uvec2 a, highp uvec2 b) { return a == b ? 1.0 : 0.0; }\n'; 1168 case gluShaderUtil.DataType.UINT_VEC3: return 'mediump float compare_uvec3 (highp uvec3 a, highp uvec3 b) { return a == b ? 1.0 : 0.0; }\n'; 1169 case gluShaderUtil.DataType.UINT_VEC4: return 'mediump float compare_uvec4 (highp uvec4 a, highp uvec4 b) { return a == b ? 1.0 : 0.0; }\n'; 1170 case gluShaderUtil.DataType.BOOL: return 'mediump float compare_bool (bool a, bool b) { return a == b ? 1.0 : 0.0; }\n'; 1171 case gluShaderUtil.DataType.BOOL_VEC2: return 'mediump float compare_bvec2 (bvec2 a, bvec2 b) { return a == b ? 1.0 : 0.0; }\n'; 1172 case gluShaderUtil.DataType.BOOL_VEC3: return 'mediump float compare_bvec3 (bvec3 a, bvec3 b) { return a == b ? 1.0 : 0.0; }\n'; 1173 case gluShaderUtil.DataType.BOOL_VEC4: return 'mediump float compare_bvec4 (bvec4 a, bvec4 b) { return a == b ? 1.0 : 0.0; }\n'; 1174 default: 1175 throw new Error('Type "' + type + '" not supported.'); 1176 1177 } 1178 }; 1179 1180 /** 1181 * glsUniformBlockCase.getCompareDependencies 1182 * @param {Array<gluShaderUtil.DataType>} compareFuncs Should contain unique elements 1183 * @param {gluShaderUtil.DataType} basicType 1184 */ 1185 glsUniformBlockCase.getCompareDependencies = function(compareFuncs, basicType) { 1186 switch (basicType) { 1187 case gluShaderUtil.DataType.FLOAT_VEC2: 1188 case gluShaderUtil.DataType.FLOAT_VEC3: 1189 case gluShaderUtil.DataType.FLOAT_VEC4: 1190 deUtil.dePushUniqueToArray(compareFuncs, gluShaderUtil.DataType.FLOAT); 1191 deUtil.dePushUniqueToArray(compareFuncs, basicType); 1192 break; 1193 1194 case gluShaderUtil.DataType.FLOAT_MAT2: 1195 case gluShaderUtil.DataType.FLOAT_MAT2X3: 1196 case gluShaderUtil.DataType.FLOAT_MAT2X4: 1197 case gluShaderUtil.DataType.FLOAT_MAT3X2: 1198 case gluShaderUtil.DataType.FLOAT_MAT3: 1199 case gluShaderUtil.DataType.FLOAT_MAT3X4: 1200 case gluShaderUtil.DataType.FLOAT_MAT4X2: 1201 case gluShaderUtil.DataType.FLOAT_MAT4X3: 1202 case gluShaderUtil.DataType.FLOAT_MAT4: 1203 deUtil.dePushUniqueToArray(compareFuncs, gluShaderUtil.DataType.FLOAT); 1204 deUtil.dePushUniqueToArray(compareFuncs, gluShaderUtil.getDataTypeFloatVec(gluShaderUtil.getDataTypeMatrixNumRows(basicType))); 1205 deUtil.dePushUniqueToArray(compareFuncs, basicType); 1206 break; 1207 1208 default: 1209 deUtil.dePushUniqueToArray(compareFuncs, basicType); 1210 break; 1211 } 1212 }; 1213 1214 /** 1215 * glsUniformBlockCase.collectUniqueBasicTypes_B 1216 * @param {Array<gluShaderUtil.DataType>} basicTypes Should contain unique elements 1217 * @param {glsUniformBlockCase.VarType} type 1218 */ 1219 glsUniformBlockCase.collectUniqueBasicTypes_B = function(basicTypes, type) { 1220 if (type.isStructType()) { 1221 /** @type {glsUniformBlockCase.StructType} */ var stype = type.getStruct(); 1222 for (var memberNdx = 0; memberNdx < stype.getSize(); memberNdx++) 1223 glsUniformBlockCase.collectUniqueBasicTypes_B(basicTypes, stype.getMember(memberNdx).getType()); 1224 } else if (type.isArrayType()) 1225 glsUniformBlockCase.collectUniqueBasicTypes_B(basicTypes, type.getElementType()); 1226 else { 1227 DE_ASSERT(type.isBasicType()); 1228 deUtil.dePushUniqueToArray(basicTypes, type.getBasicType()); 1229 } 1230 }; 1231 1232 /** 1233 * glsUniformBlockCase.collectUniqueBasicTypes_A 1234 * @param {Array<gluShaderUtil.DataType>} basicTypes Should contain unique elements 1235 * @param {glsUniformBlockCase.UniformBlock} uniformBlock 1236 */ 1237 glsUniformBlockCase.collectUniqueBasicTypes_A = function(basicTypes, uniformBlock) { 1238 for (var uniformNdx = 0; uniformNdx < uniformBlock.countUniforms(); uniformNdx++) 1239 glsUniformBlockCase.collectUniqueBasicTypes_B(basicTypes, uniformBlock.getUniform(uniformNdx).getType()); 1240 }; 1241 1242 /** 1243 * glsUniformBlockCase.collectUniqueBasicTypes 1244 * @param {Array<gluShaderUtil.DataType>} basicTypes Should contain unique elements 1245 * @param {glsUniformBlockCase.ShaderInterface} sinterface 1246 */ 1247 glsUniformBlockCase.collectUniqueBasicTypes = function(basicTypes, sinterface) { 1248 for (var ndx = 0; ndx < sinterface.getNumUniformBlocks(); ++ndx) 1249 glsUniformBlockCase.collectUniqueBasicTypes_A(basicTypes, sinterface.getUniformBlock(ndx)); 1250 }; 1251 1252 /** 1253 * glsUniformBlockCase.collectUniqueBasicTypes 1254 * @return {string} Was originally an output parameter. As it is a basic type, we have to return it instead. 1255 * @param {glsUniformBlockCase.ShaderInterface} sinterface 1256 */ 1257 glsUniformBlockCase.generateCompareFuncs = function(sinterface) { 1258 /** @type {string} */ var str = ''; 1259 /** @type {Array<gluShaderUtil.DataType>} */ var types = []; //Will contain unique elements. 1260 /** @type {Array<gluShaderUtil.DataType>} */ var compareFuncs = []; //Will contain unique elements. 1261 1262 // Collect unique basic types 1263 glsUniformBlockCase.collectUniqueBasicTypes(types, sinterface); 1264 1265 // Set of compare functions required 1266 for (var typeNdx = 0; typeNdx < types.length; typeNdx++) 1267 glsUniformBlockCase.getCompareDependencies(compareFuncs, types[typeNdx]); 1268 1269 for (var type in gluShaderUtil.DataType) { 1270 if (compareFuncs.indexOf(gluShaderUtil.DataType[type]) > -1) 1271 str += glsUniformBlockCase.getCompareFuncForType(gluShaderUtil.DataType[type]); 1272 } 1273 1274 return str; 1275 }; 1276 1277 /** 1278 * glsUniformBlockCase.Indent - Prints level_ number of tab chars 1279 * @param {number} level_ 1280 * @return {string} 1281 */ 1282 glsUniformBlockCase.Indent = function(level_) { 1283 var str = ''; 1284 for (var i = 0; i < level_; i++) 1285 str += '\t'; 1286 1287 return str; 1288 }; 1289 1290 /** 1291 * glsUniformBlockCase.generateDeclaration_C 1292 * @return {string} src 1293 * @param {glsUniformBlockCase.StructType} structType 1294 * @param {number} indentLevel 1295 */ 1296 glsUniformBlockCase.generateDeclaration_C = function(structType, indentLevel) { 1297 /** @type {string} */ var src = ''; 1298 1299 DE_ASSERT(structType.getTypeName() !== undefined); 1300 src += glsUniformBlockCase.generateFullDeclaration(structType, indentLevel); 1301 src += ';\n'; 1302 1303 return src; 1304 }; 1305 1306 /** 1307 * glsUniformBlockCase.generateFullDeclaration 1308 * @return {string} src 1309 * @param {glsUniformBlockCase.StructType} structType 1310 * @param {number} indentLevel 1311 */ 1312 glsUniformBlockCase.generateFullDeclaration = function(structType, indentLevel) { 1313 var src = 'struct'; 1314 if (structType.getTypeName()) 1315 src += ' ' + structType.getTypeName(); 1316 src += '\n' + glsUniformBlockCase.Indent(indentLevel) + ' {\n'; 1317 1318 for (var memberNdx = 0; memberNdx < structType.getSize(); memberNdx++) { 1319 src += glsUniformBlockCase.Indent(indentLevel + 1); 1320 /** @type {glsUniformBlockCase.StructMember} */ var memberIter = structType.getMember(memberNdx); 1321 src += glsUniformBlockCase.generateDeclaration_B(memberIter.getType(), memberIter.getName(), indentLevel + 1, memberIter.getFlags() & glsUniformBlockCase.UniformFlags.UNUSED_BOTH); 1322 } 1323 1324 src += glsUniformBlockCase.Indent(indentLevel) + '}'; 1325 1326 return src; 1327 }; 1328 1329 /** 1330 * glsUniformBlockCase.generateLocalDeclaration 1331 * @return {string} src 1332 * @param {glsUniformBlockCase.StructType} structType 1333 * @param {number} indentLevel 1334 */ 1335 glsUniformBlockCase.generateLocalDeclaration = function(structType, indentLevel) { 1336 /** @type {string} */ var src = ''; 1337 1338 if (structType.getTypeName() === undefined) 1339 src += glsUniformBlockCase.generateFullDeclaration(structType, indentLevel); 1340 else 1341 src += structType.getTypeName(); 1342 1343 return src; 1344 }; 1345 1346 /** 1347 * glsUniformBlockCase.generateDeclaration_B 1348 * @return {string} src 1349 * @param {glsUniformBlockCase.VarType} type 1350 * @param {string} name 1351 * @param {number} indentLevel 1352 * @param {number} unusedHints 1353 */ 1354 glsUniformBlockCase.generateDeclaration_B = function(type, name, indentLevel, unusedHints) { 1355 /** @type {string} */ var src = ''; 1356 /** @type {number} */ var flags = type.getFlags(); 1357 1358 if ((flags & glsUniformBlockCase.UniformFlags.LAYOUT_MASK) != 0) 1359 src += 'layout(' + glsUniformBlockCase.LayoutFlagsFmt(flags & glsUniformBlockCase.UniformFlags.LAYOUT_MASK) + ') '; 1360 1361 if ((flags & glsUniformBlockCase.UniformFlags.PRECISION_MASK) != 0) 1362 src += glsUniformBlockCase.PrecisionFlagsFmt(flags & glsUniformBlockCase.UniformFlags.PRECISION_MASK) + ' '; 1363 1364 if (type.isBasicType()) 1365 src += gluShaderUtil.getDataTypeName(type.getBasicType()) + ' ' + name; 1366 else if (type.isArrayType()) { 1367 /** @type {Array<number>} */ var arraySizes = []; 1368 /** @type {glsUniformBlockCase.VarType} */ var curType = type; 1369 while (curType.isArrayType()) { 1370 arraySizes.push(curType.getArraySize()); 1371 curType = curType.getElementType(); 1372 } 1373 1374 if (curType.isBasicType()) { 1375 if ((curType.getFlags() & glsUniformBlockCase.UniformFlags.PRECISION_MASK) != 0) 1376 src += glsUniformBlockCase.PrecisionFlagsFmt(curType.getFlags() & glsUniformBlockCase.UniformFlags.PRECISION_MASK) + ' '; 1377 src += gluShaderUtil.getDataTypeName(curType.getBasicType()); 1378 } else { 1379 DE_ASSERT(curType.isStructType()); 1380 src += glsUniformBlockCase.generateLocalDeclaration(curType.getStruct(), indentLevel + 1); 1381 } 1382 1383 src += ' ' + name; 1384 1385 for (var sizeNdx = 0; sizeNdx < arraySizes.length; sizeNdx++) 1386 src += '[' + arraySizes[sizeNdx] + ']'; 1387 } else { 1388 src += glsUniformBlockCase.generateLocalDeclaration(type.getStruct(), indentLevel + 1); 1389 src += ' ' + name; 1390 } 1391 1392 src += ';'; 1393 1394 // Print out unused hints. 1395 if (unusedHints != 0) 1396 src += ' // unused in ' + (unusedHints == glsUniformBlockCase.UniformFlags.UNUSED_BOTH ? 'both shaders' : 1397 unusedHints == glsUniformBlockCase.UniformFlags.UNUSED_VERTEX ? 'vertex shader' : 1398 unusedHints == glsUniformBlockCase.UniformFlags.UNUSED_FRAGMENT ? 'fragment shader' : '???'); 1399 1400 src += '\n'; 1401 1402 return src; 1403 }; 1404 1405 /** 1406 * glsUniformBlockCase.generateDeclaration_A 1407 * @return {string} src 1408 * @param {glsUniformBlockCase.Uniform} uniform 1409 * @param {number} indentLevel 1410 */ 1411 glsUniformBlockCase.generateDeclaration_A = function(uniform, indentLevel) { 1412 /** @type {string} */ var src = ''; 1413 1414 if ((uniform.getFlags() & glsUniformBlockCase.UniformFlags.LAYOUT_MASK) != 0) 1415 src += 'layout(' + glsUniformBlockCase.LayoutFlagsFmt(uniform.getFlags() & glsUniformBlockCase.UniformFlags.LAYOUT_MASK) + ') '; 1416 1417 src += glsUniformBlockCase.generateDeclaration_B(uniform.getType(), uniform.getName(), indentLevel, uniform.getFlags() & glsUniformBlockCase.UniformFlags.UNUSED_BOTH); 1418 1419 return src; 1420 }; 1421 1422 /** 1423 * glsUniformBlockCase.generateDeclaration 1424 * @return {string} src 1425 * @param {glsUniformBlockCase.UniformBlock} block 1426 */ 1427 glsUniformBlockCase.generateDeclaration = function(block) { 1428 /** @type {string} */ var src = ''; 1429 1430 if ((block.getFlags() & glsUniformBlockCase.UniformFlags.LAYOUT_MASK) != 0) 1431 src += 'layout(' + glsUniformBlockCase.LayoutFlagsFmt(block.getFlags() & glsUniformBlockCase.UniformFlags.LAYOUT_MASK) + ') '; 1432 1433 src += 'uniform ' + block.getBlockName(); 1434 src += '\n {\n'; 1435 1436 for (var uniformNdx = 0; uniformNdx < block.countUniforms(); uniformNdx++) { 1437 src += glsUniformBlockCase.Indent(1); 1438 src += glsUniformBlockCase.generateDeclaration_A(block.getUniform(uniformNdx), 1 /* indent level */); 1439 } 1440 1441 src += '}'; 1442 1443 if (block.getInstanceName() !== undefined) { 1444 src += ' ' + block.getInstanceName(); 1445 if (block.isArray()) 1446 src += '[' + block.getArraySize() + ']'; 1447 } else 1448 DE_ASSERT(!block.isArray()); 1449 1450 src += ';\n'; 1451 1452 return src; 1453 }; 1454 1455 /** 1456 * glsUniformBlockCase.newArrayBufferFromView - Creates a new buffer copying data from a given view 1457 * @param {goog.NumberArray} view 1458 * @return {ArrayBuffer} The newly created buffer 1459 */ 1460 glsUniformBlockCase.newArrayBufferFromView = function(view) { 1461 var buffer = new ArrayBuffer(view.length * view.BYTES_PER_ELEMENT); 1462 var copyview; 1463 switch (view.BYTES_PER_ELEMENT) { 1464 case 1: 1465 copyview = new Uint8Array(buffer); break; 1466 case 2: 1467 copyview = new Uint16Array(buffer); break; 1468 case 4: 1469 copyview = new Uint32Array(buffer); break; 1470 default: 1471 assertMsgOptions(false, 'Unexpected value for BYTES_PER_ELEMENT in view', false, true); 1472 } 1473 for (var i = 0; i < view.length; i++) 1474 copyview[i] = view[i]; 1475 1476 return buffer; 1477 }; 1478 1479 /** 1480 * glsUniformBlockCase.generateValueSrc 1481 * @return {string} Used to be an output parameter in C++ project 1482 * @param {glsUniformBlockCase.UniformLayoutEntry} entry 1483 * @param {Uint8Array} basePtr 1484 * @param {number} elementNdx 1485 */ 1486 glsUniformBlockCase.generateValueSrc = function(entry, basePtr, elementNdx) { 1487 /** @type {string} */ var src = ''; 1488 /** @type {gluShaderUtil.DataType} */ var scalarType = gluShaderUtil.getDataTypeScalarTypeAsDataType(entry.type); 1489 /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(entry.type); 1490 /** @type {boolean} */ var isArray = entry.size > 1; 1491 /** @type {Uint8Array} */ var elemPtr = basePtr.subarray(entry.offset + (isArray ? elementNdx * entry.arrayStride : 0)); 1492 /** @type {number} */ var compSize = deMath.INT32_SIZE; 1493 /** @type {Uint8Array} */ var compPtr; 1494 if (scalarSize > 1) 1495 src += gluShaderUtil.getDataTypeName(entry.type) + '('; 1496 1497 if (gluShaderUtil.isDataTypeMatrix(entry.type)) { 1498 /** @type {number} */ var numRows = gluShaderUtil.getDataTypeMatrixNumRows(entry.type); 1499 /** @type {number} */ var numCols = gluShaderUtil.getDataTypeMatrixNumColumns(entry.type); 1500 1501 DE_ASSERT(scalarType == gluShaderUtil.DataType.FLOAT); 1502 1503 // Constructed in column-wise order. 1504 for (var colNdx = 0; colNdx < numCols; colNdx++) { 1505 for (var rowNdx = 0; rowNdx < numRows; rowNdx++) { 1506 compPtr = elemPtr.subarray(entry.isRowMajor ? rowNdx * entry.matrixStride + colNdx * compSize : 1507 colNdx * entry.matrixStride + rowNdx * compSize); 1508 1509 if (colNdx > 0 || rowNdx > 0) 1510 src += ', '; 1511 1512 var newbuffer = new Uint8Array(compPtr.subarray(0, 4)).buffer; 1513 var newview = new DataView(newbuffer); 1514 src += parseFloat(newview.getFloat32(0, littleEndian)).toFixed(1); 1515 } 1516 } 1517 } else { 1518 for (var scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++) { 1519 compPtr = elemPtr.subarray(scalarNdx * compSize); 1520 1521 if (scalarNdx > 0) 1522 src += ', '; 1523 1524 var newbuffer = glsUniformBlockCase.newArrayBufferFromView(compPtr.subarray(0, 4)); 1525 var newview = new DataView(newbuffer); 1526 1527 switch (scalarType) { 1528 case gluShaderUtil.DataType.FLOAT: src += parseFloat(newview.getFloat32(0, littleEndian) * 100 / 100).toFixed(1); break; 1529 case gluShaderUtil.DataType.INT: src += newview.getInt32(0, littleEndian); break; 1530 case gluShaderUtil.DataType.UINT: src += newview.getUint32(0, littleEndian) + 'u'; break; 1531 case gluShaderUtil.DataType.BOOL: src += (newview.getUint32(0, littleEndian) != 0 ? 'true' : 'false'); break; 1532 default: 1533 DE_ASSERT(false); 1534 } 1535 } 1536 } 1537 1538 if (scalarSize > 1) 1539 src += ')'; 1540 1541 return src; 1542 }; 1543 1544 /** 1545 * glsUniformBlockCase.generateCompareSrc_A 1546 * @return {string} Used to be an output parameter in C++ project 1547 * @param {string} resultVar 1548 * @param {glsUniformBlockCase.VarType} type 1549 * @param {string} srcName 1550 * @param {string} apiName 1551 * @param {glsUniformBlockCase.UniformLayout} layout 1552 * @param {Uint8Array} basePtr 1553 * @param {number} unusedMask 1554 */ 1555 glsUniformBlockCase.generateCompareSrc_A = function(resultVar, type, srcName, apiName, layout, basePtr, unusedMask) { 1556 /** @type {string} */ var src = ''; 1557 /** @type {string} */ var op; 1558 /** @type {glsUniformBlockCase.VarType|gluShaderUtil.DataType} */ var elementType; 1559 1560 if (type.isBasicType() || (type.isArrayType() && type.getElementType().isBasicType())) { 1561 // Basic type or array of basic types. 1562 /** @type {boolean} */ var isArray = type.isArrayType(); 1563 elementType = isArray ? type.getElementType().getBasicType() : type.getBasicType(); 1564 /** @type {string} */ var typeName = gluShaderUtil.getDataTypeName(elementType); 1565 /** @type {string} */ var fullApiName = apiName + (isArray ? '[0]' : ''); // Arrays are always postfixed with [0] 1566 /** @type {number} */ var uniformNdx = layout.getUniformIndex(fullApiName); 1567 /** @type {glsUniformBlockCase.UniformLayoutEntry} */ var entry = layout.uniforms[uniformNdx]; 1568 1569 if (isArray) { 1570 for (var elemNdx = 0; elemNdx < type.getArraySize(); elemNdx++) { 1571 src += '\tresult *= compare_' + typeName + '(' + srcName + '[' + elemNdx + '], '; 1572 src += glsUniformBlockCase.generateValueSrc(entry, basePtr, elemNdx); 1573 src += ');\n'; 1574 } 1575 } else { 1576 src += '\tresult *= compare_' + typeName + '(' + srcName + ', '; 1577 src += glsUniformBlockCase.generateValueSrc(entry, basePtr, 0); 1578 src += ');\n'; 1579 } 1580 } else if (type.isArrayType()) { 1581 elementType = type.getElementType(); 1582 1583 for (var elementNdx = 0; elementNdx < type.getArraySize(); elementNdx++) { 1584 op = '[' + elementNdx + ']'; 1585 src += glsUniformBlockCase.generateCompareSrc_A(resultVar, elementType, srcName + op, apiName + op, layout, basePtr, unusedMask); 1586 } 1587 } else { 1588 DE_ASSERT(type.isStructType()); 1589 1590 /** @type {glsUniformBlockCase.StructType} */ var stype = type.getStruct(); 1591 for (var memberNdx = 0; memberNdx < stype.getSize(); memberNdx++) { 1592 /** @type {glsUniformBlockCase.StructMember} */ var memberIter = stype.getMember(memberNdx); 1593 if (memberIter.getFlags() & unusedMask) 1594 continue; // Skip member. 1595 1596 op = '.' + memberIter.getName(); 1597 src += glsUniformBlockCase.generateCompareSrc_A(resultVar, memberIter.getType(), srcName + op, apiName + op, layout, basePtr, unusedMask); 1598 } 1599 } 1600 1601 return src; 1602 }; 1603 1604 /** 1605 * glsUniformBlockCase.generateCompareSrc 1606 * @return {string} Used to be an output parameter in C++ project 1607 * @param {string} resultVar 1608 * @param {glsUniformBlockCase.ShaderInterface} sinterface 1609 * @param {glsUniformBlockCase.UniformLayout} layout 1610 * @param {glsUniformBlockCase.BlockPointers} blockPointers 1611 * @param {boolean} isVertex 1612 */ 1613 glsUniformBlockCase.generateCompareSrc = function(resultVar, sinterface, layout, blockPointers, isVertex) { 1614 /** @type {string} */ var src = ''; 1615 /** @type {number} */ var unusedMask = isVertex ? glsUniformBlockCase.UniformFlags.UNUSED_VERTEX : glsUniformBlockCase.UniformFlags.UNUSED_FRAGMENT; 1616 1617 for (var blockNdx = 0; blockNdx < sinterface.getNumUniformBlocks(); blockNdx++) { 1618 /** @type {glsUniformBlockCase.UniformBlock} */ var block = sinterface.getUniformBlock(blockNdx); 1619 1620 if ((block.getFlags() & (isVertex ? glsUniformBlockCase.UniformFlags.DECLARE_VERTEX : glsUniformBlockCase.UniformFlags.DECLARE_FRAGMENT)) == 0) 1621 continue; // Skip. 1622 1623 /** @type {boolean} */ var hasInstanceName = block.getInstanceName() !== undefined; 1624 /** @type {boolean} */ var isArray = block.isArray(); 1625 /** @type {number} */ var numInstances = isArray ? block.getArraySize() : 1; 1626 /** @type {string} */ var apiPrefix = hasInstanceName ? block.getBlockName() + '.' : ''; 1627 1628 DE_ASSERT(!isArray || hasInstanceName); 1629 1630 for (var instanceNdx = 0; instanceNdx < numInstances; instanceNdx++) { 1631 /** @type {string} */ var instancePostfix = isArray ? '[' + instanceNdx + ']' : ''; 1632 /** @type {string} */ var blockInstanceName = block.getBlockName() + instancePostfix; 1633 /** @type {string} */ var srcPrefix = hasInstanceName ? block.getInstanceName() + instancePostfix + '.' : ''; 1634 /** @type {number} */ var activeBlockNdx = layout.getBlockIndex(blockInstanceName); 1635 /** @type {Uint8Array} */ var basePtr = blockPointers.find(activeBlockNdx); 1636 1637 for (var uniformNdx = 0; uniformNdx < block.countUniforms(); uniformNdx++) { 1638 /** @type {glsUniformBlockCase.Uniform} */ var uniform = block.getUniform(uniformNdx); 1639 1640 if (uniform.getFlags() & unusedMask) 1641 continue; // Don't read from that uniform. 1642 1643 src += glsUniformBlockCase.generateCompareSrc_A(resultVar, uniform.getType(), srcPrefix + uniform.getName(), apiPrefix + uniform.getName(), layout, basePtr, unusedMask); 1644 } 1645 } 1646 } 1647 1648 return src; 1649 }; 1650 1651 /** 1652 * glsUniformBlockCase.generateVertexShader 1653 * @return {string} src 1654 * @param {glsUniformBlockCase.ShaderInterface} sinterface 1655 * @param {glsUniformBlockCase.UniformLayout} layout 1656 * @param {glsUniformBlockCase.BlockPointers} blockPointers 1657 */ 1658 glsUniformBlockCase.generateVertexShader = function(sinterface, layout, blockPointers) { 1659 /** @type {string} */ var src = ''; 1660 1661 DE_ASSERT(glsUniformBlockCase.isSupportedGLSLVersion(gluShaderUtil.getGLSLVersion(gl))); 1662 1663 src += gluShaderUtil.getGLSLVersionDeclaration(gluShaderUtil.getGLSLVersion(gl)) + '\n'; 1664 src += 'in highp vec4 a_position;\n'; 1665 src += 'out mediump float v_vtxResult;\n'; 1666 src += '\n'; 1667 1668 /** @type {Array<glsUniformBlockCase.StructType>} */ var namedStructs = []; 1669 sinterface.getNamedStructs(namedStructs); 1670 for (var structNdx = 0; structNdx < namedStructs.length; structNdx++) 1671 src += glsUniformBlockCase.generateDeclaration_C(namedStructs[structNdx], 0); 1672 1673 for (var blockNdx = 0; blockNdx < sinterface.getNumUniformBlocks(); blockNdx++) { 1674 /** @type {glsUniformBlockCase.UniformBlock} */ var block = sinterface.getUniformBlock(blockNdx); 1675 if (block.getFlags() & glsUniformBlockCase.UniformFlags.DECLARE_VERTEX) 1676 src += glsUniformBlockCase.generateDeclaration(block); 1677 } 1678 1679 // Comparison utilities. 1680 src += '\n'; 1681 src += glsUniformBlockCase.generateCompareFuncs(sinterface); 1682 1683 src += '\n' + 1684 'void main (void)\n' + 1685 ' {\n' + 1686 ' gl_Position = a_position;\n' + 1687 ' mediump float result = 1.0;\n'; 1688 1689 // Value compare. 1690 src += glsUniformBlockCase.generateCompareSrc('result', sinterface, layout, blockPointers, true); 1691 1692 src += ' v_vtxResult = result;\n' + 1693 '}\n'; 1694 1695 return src; 1696 }; 1697 1698 /** 1699 * glsUniformBlockCase.generateFragmentShader 1700 * @return {string} Used to be an output parameter 1701 * @param {glsUniformBlockCase.ShaderInterface} sinterface 1702 * @param {glsUniformBlockCase.UniformLayout} layout 1703 * @param {glsUniformBlockCase.BlockPointers} blockPointers 1704 */ 1705 glsUniformBlockCase.generateFragmentShader = function(sinterface, layout, blockPointers) { 1706 /** @type {string} */ var src = ''; 1707 DE_ASSERT(glsUniformBlockCase.isSupportedGLSLVersion(gluShaderUtil.getGLSLVersion(gl))); 1708 1709 src += gluShaderUtil.getGLSLVersionDeclaration(gluShaderUtil.getGLSLVersion(gl)) + '\n'; 1710 src += 'in mediump float v_vtxResult;\n'; 1711 src += 'layout(location = 0) out mediump vec4 dEQP_FragColor;\n'; 1712 src += '\n'; 1713 1714 /** @type {Array<glsUniformBlockCase.StructType>} */ var namedStructs = []; 1715 sinterface.getNamedStructs(namedStructs); 1716 for (var structNdx = 0; structNdx < namedStructs.length; structNdx++) 1717 src += glsUniformBlockCase.generateDeclaration_C(namedStructs[structNdx], 0); 1718 1719 for (var blockNdx = 0; blockNdx < sinterface.getNumUniformBlocks(); blockNdx++) { 1720 /** @type {glsUniformBlockCase.UniformBlock} */ var block = sinterface.getUniformBlock(blockNdx); 1721 if (block.getFlags() & glsUniformBlockCase.UniformFlags.DECLARE_FRAGMENT) 1722 src += glsUniformBlockCase.generateDeclaration(block); 1723 } 1724 1725 // Comparison utilities. 1726 src += '\n'; 1727 src += glsUniformBlockCase.generateCompareFuncs(sinterface); 1728 1729 src += '\n' + 1730 'void main (void)\n' + 1731 ' {\n' + 1732 ' mediump float result = 1.0;\n'; 1733 1734 // Value compare. 1735 src += glsUniformBlockCase.generateCompareSrc('result', sinterface, layout, blockPointers, false); 1736 1737 src += ' dEQP_FragColor = vec4(1.0, v_vtxResult, result, 1.0);\n' + 1738 '}\n'; 1739 1740 return src; 1741 }; 1742 1743 /** 1744 * TODO: test glsUniformBlockCase.getGLUniformLayout Gets the uniform blocks and uniforms in the program. 1745 * @param {WebGL2RenderingContext} gl 1746 * @param {glsUniformBlockCase.UniformLayout} layout To store the layout described in program. 1747 * @param {WebGLProgram} program id 1748 */ 1749 glsUniformBlockCase.getGLUniformLayout = function(gl, layout, program) { 1750 /** @type {number} */ var numActiveUniforms = 0; 1751 /** @type {number} */ var numActiveBlocks = 0; 1752 1753 numActiveUniforms = /** @type {number} */ (gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS)); // ACTIVE_UNIFORM* returns GLInt 1754 numActiveBlocks = /** @type {number} */ (gl.getProgramParameter(program, gl.ACTIVE_UNIFORM_BLOCKS)); 1755 1756 /** @type {glsUniformBlockCase.BlockLayoutEntry} */ var entryBlock; 1757 /** @type {glsUniformBlockCase.UniformLayoutEntry} */ var entryUniform; 1758 /** @type {number} */ var size; 1759 /** @type {number} */ var nameLen; 1760 /** @type {string} */ var nameBuf; 1761 /** @type {number} */ var numBlockUniforms; 1762 1763 // Block entries. 1764 //No need to allocate these beforehand: layout.blocks.resize(numActiveBlocks); 1765 for (var blockNdx = 0; blockNdx < numActiveBlocks; blockNdx++) { 1766 entryBlock = new glsUniformBlockCase.BlockLayoutEntry(); 1767 1768 size = /** @type {number} */ (gl.getActiveUniformBlockParameter(program, blockNdx, gl.UNIFORM_BLOCK_DATA_SIZE)); 1769 // nameLen not used so this line is removed. 1770 // nameLen = gl.getActiveUniformBlockParameter(program, blockNdx, gl.UNIFORM_BLOCK_NAME_LENGTH); // TODO: UNIFORM_BLOCK_NAME_LENGTH is removed in WebGL2 1771 numBlockUniforms = /** @type {number} */ (gl.getActiveUniformBlockParameter(program, blockNdx, gl.UNIFORM_BLOCK_ACTIVE_UNIFORMS)); 1772 1773 nameBuf = gl.getActiveUniformBlockName(program, blockNdx); 1774 1775 entryBlock.name = nameBuf; 1776 entryBlock.size = size; 1777 //entry.activeUniformIndices.resize(numBlockUniforms); 1778 1779 if (numBlockUniforms > 0) 1780 entryBlock.activeUniformIndices = gl.getActiveUniformBlockParameter(program, blockNdx, gl.UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES); 1781 1782 layout.blocks.push(entryBlock); //Pushing the block into the array here. 1783 } 1784 1785 if (numActiveUniforms > 0) { 1786 // glsUniformBlockCase.Uniform entries. 1787 /** @type {Array<number>} */ var uniformIndices = []; 1788 for (var i = 0; i < numActiveUniforms; i++) 1789 uniformIndices.push(i); 1790 1791 /** @type {Array<number>} */ var types = []; 1792 /** @type {Array<number>} */ var sizes = []; 1793 /** @type {Array<number>} */ var nameLengths = []; 1794 /** @type {Array<number>} */ var blockIndices = []; 1795 /** @type {Array<number>} */ var offsets = []; 1796 /** @type {Array<number>} */ var arrayStrides = []; 1797 /** @type {Array<number>} */ var matrixStrides = []; 1798 /** @type {Array<number>} */ var rowMajorFlags = []; 1799 1800 // Execute queries. 1801 types = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_TYPE); 1802 sizes = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_SIZE); 1803 // Remove this: nameLengths = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_NAME_LENGTH); 1804 blockIndices = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_BLOCK_INDEX); 1805 offsets = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_OFFSET); 1806 arrayStrides = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_ARRAY_STRIDE); 1807 matrixStrides = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_MATRIX_STRIDE); 1808 rowMajorFlags = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_IS_ROW_MAJOR); 1809 1810 // Translate to LayoutEntries 1811 // No resize needed. Will push them: layout.uniforms.resize(numActiveUniforms); 1812 for (var uniformNdx = 0; uniformNdx < numActiveUniforms; uniformNdx++) { 1813 entryUniform = new glsUniformBlockCase.UniformLayoutEntry(); 1814 1815 // Remove this: nameLen = 0; 1816 size = 0; 1817 /** @type {number} */ var type = gl.NONE; 1818 1819 var uniform = gl.getActiveUniform(program, uniformNdx); 1820 1821 nameBuf = uniform.name; 1822 // Remove this: nameLen = nameBuf.length; 1823 size = uniform.size; 1824 type = uniform.type; 1825 1826 // Remove this: nameLen != nameLengths[uniformNdx] || 1827 if (size != sizes[uniformNdx] || 1828 type != types[uniformNdx]) 1829 testFailedOptions("Values returned by gl.getActiveUniform() don't match with values queried with gl.getActiveUniforms().", true); 1830 1831 entryUniform.name = nameBuf; 1832 entryUniform.type = gluShaderUtil.getDataTypeFromGLType(types[uniformNdx]); 1833 entryUniform.size = sizes[uniformNdx]; 1834 entryUniform.blockNdx = blockIndices[uniformNdx]; 1835 entryUniform.offset = offsets[uniformNdx]; 1836 entryUniform.arrayStride = arrayStrides[uniformNdx]; 1837 entryUniform.matrixStride = matrixStrides[uniformNdx]; 1838 entryUniform.isRowMajor = rowMajorFlags[uniformNdx] != false; 1839 1840 layout.uniforms.push(entryUniform); //Pushing this uniform in the end. 1841 } 1842 } 1843 }; 1844 1845 /** 1846 * glsUniformBlockCase.copyUniformData_A - Copies a source uniform buffer segment to a destination uniform buffer segment. 1847 * @param {glsUniformBlockCase.UniformLayoutEntry} dstEntry 1848 * @param {Uint8Array} dstBlockPtr 1849 * @param {glsUniformBlockCase.UniformLayoutEntry} srcEntry 1850 * @param {Uint8Array} srcBlockPtr 1851 */ 1852 glsUniformBlockCase.copyUniformData_A = function(dstEntry, dstBlockPtr, srcEntry, srcBlockPtr) { 1853 /** @type {Uint8Array} */ var dstBasePtr = dstBlockPtr.subarray(dstEntry.offset); 1854 /** @type {Uint8Array} */ var srcBasePtr = srcBlockPtr.subarray(srcEntry.offset); 1855 1856 DE_ASSERT(dstEntry.size <= srcEntry.size); 1857 DE_ASSERT(dstEntry.type == srcEntry.type); 1858 1859 /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(dstEntry.type); 1860 /** @type {boolean} */ var isMatrix = gluShaderUtil.isDataTypeMatrix(dstEntry.type); 1861 /** @type {number} */ var compSize = deMath.INT32_SIZE; 1862 1863 for (var elementNdx = 0; elementNdx < dstEntry.size; elementNdx++) { 1864 /** @type {Uint8Array} */ var dstElemPtr = dstBasePtr.subarray(elementNdx * dstEntry.arrayStride); 1865 /** @type {Uint8Array} */ var srcElemPtr = srcBasePtr.subarray(elementNdx * srcEntry.arrayStride); 1866 1867 if (isMatrix) { 1868 /** @type {number} */ var numRows = gluShaderUtil.getDataTypeMatrixNumRows(dstEntry.type); 1869 /** @type {number} */ var numCols = gluShaderUtil.getDataTypeMatrixNumColumns(dstEntry.type); 1870 1871 for (var colNdx = 0; colNdx < numCols; colNdx++) { 1872 for (var rowNdx = 0; rowNdx < numRows; rowNdx++) { 1873 var srcoffset = dstEntry.isRowMajor ? rowNdx * dstEntry.matrixStride + colNdx * compSize : 1874 colNdx * dstEntry.matrixStride + rowNdx * compSize; 1875 /** @type {Uint8Array} */ var dstCompPtr = dstElemPtr.subarray(srcoffset, srcoffset + compSize); 1876 var dstoffset = srcEntry.isRowMajor ? rowNdx * srcEntry.matrixStride + colNdx * compSize : 1877 colNdx * srcEntry.matrixStride + rowNdx * compSize; 1878 /** @type {Uint8Array} */ var srcCompPtr = srcElemPtr.subarray(dstoffset, dstoffset + compSize); 1879 1880 //Copy byte per byte 1881 for (var i = 0; i < compSize; i++) 1882 dstCompPtr[i] = srcCompPtr[i]; 1883 } 1884 } 1885 } else 1886 //Copy byte per byte 1887 for (var i = 0; i < scalarSize * compSize; i++) 1888 dstElemPtr[i] = srcElemPtr[i]; 1889 } 1890 }; 1891 1892 /** 1893 * glsUniformBlockCase.copyUniformData - Copies a source uniform buffer to a destination uniform buffer. 1894 * @param {glsUniformBlockCase.UniformLayout} dstLayout 1895 * @param {glsUniformBlockCase.BlockPointers} dstBlockPointers 1896 * @param {glsUniformBlockCase.UniformLayout} srcLayout 1897 * @param {glsUniformBlockCase.BlockPointers} srcBlockPointers 1898 */ 1899 glsUniformBlockCase.copyUniformData = function(dstLayout, dstBlockPointers, srcLayout, srcBlockPointers) { 1900 // \note Src layout is used as reference in case of activeUniforms happens to be incorrect in dstLayout blocks. 1901 /** @type {number} */ var numBlocks = srcLayout.blocks.length; 1902 1903 for (var srcBlockNdx = 0; srcBlockNdx < numBlocks; srcBlockNdx++) { 1904 /** @type {glsUniformBlockCase.BlockLayoutEntry} */ var srcBlock = srcLayout.blocks[srcBlockNdx]; 1905 /** @type {Uint8Array} */ var srcBlockPtr = srcBlockPointers.find(srcBlockNdx); 1906 /** @type {number} */ var dstBlockNdx = dstLayout.getBlockIndex(srcBlock.name); 1907 /** @type {Uint8Array} */ var dstBlockPtr = dstBlockNdx >= 0 ? dstBlockPointers.find(dstBlockNdx) : null; 1908 1909 if (dstBlockNdx < 0) 1910 continue; 1911 1912 for (var srcUniformNdx = 0; srcUniformNdx < srcBlock.activeUniformIndices.length; srcUniformNdx++) { 1913 /** @type {number} */ var srcUniformNdxIter = srcBlock.activeUniformIndices[srcUniformNdx]; 1914 /** @type {glsUniformBlockCase.UniformLayoutEntry} */ var srcEntry = srcLayout.uniforms[srcUniformNdxIter]; 1915 /** @type {number} */ var dstUniformNdx = dstLayout.getUniformIndex(srcEntry.name); 1916 1917 if (dstUniformNdx < 0) 1918 continue; 1919 1920 glsUniformBlockCase.copyUniformData_A(dstLayout.uniforms[dstUniformNdx], dstBlockPtr, srcEntry, srcBlockPtr); 1921 } 1922 } 1923 }; 1924 1925 /** 1926 * TODO: Test with an actual WebGL 2.0 context 1927 * iterate - The actual execution of the test. 1928 * @return {tcuTestCase.IterateResult} 1929 */ 1930 glsUniformBlockCase.UniformBlockCase.prototype.iterate = function() { 1931 /** @type {glsUniformBlockCase.UniformLayout} */ var refLayout = new glsUniformBlockCase.UniformLayout(); //!< std140 layout. 1932 /** @type {glsUniformBlockCase.BlockPointers} */ var blockPointers = new glsUniformBlockCase.BlockPointers(); 1933 1934 // Compute reference layout. 1935 glsUniformBlockCase.computeStd140Layout(refLayout, this.m_interface); 1936 1937 // Assign storage for reference values. 1938 /** @type {number} */ var totalSize = 0; 1939 for (var blockNdx = 0; blockNdx < refLayout.blocks.length; blockNdx++) { 1940 /** @type {glsUniformBlockCase.BlockLayoutEntry} */ var blockIter = refLayout.blocks[blockNdx]; 1941 totalSize += blockIter.size; 1942 } 1943 blockPointers.resize(totalSize); 1944 1945 // Pointers for each block. 1946 var curOffset = 0; 1947 for (var blockNdx = 0; blockNdx < refLayout.blocks.length; blockNdx++) { 1948 var size = refLayout.blocks[blockNdx].size; 1949 blockPointers.push(curOffset, size); 1950 curOffset += size; 1951 } 1952 1953 // Generate values. 1954 glsUniformBlockCase.generateValues(refLayout, blockPointers, 1 /* seed */); 1955 1956 // Generate shaders and build program. 1957 /** @type {string} */ var vtxSrc = glsUniformBlockCase.generateVertexShader(this.m_interface, refLayout, blockPointers); 1958 /** @type {string} */ var fragSrc = glsUniformBlockCase.generateFragmentShader(this.m_interface, refLayout, blockPointers); 1959 1960 /** @type {gluShaderProgram.ShaderProgram}*/ var program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vtxSrc, fragSrc)); 1961 bufferedLogToConsole(program.getProgramInfo().infoLog); 1962 1963 if (!program.isOk()) { 1964 // Compile failed. 1965 testFailedOptions('Compile failed', false); 1966 return tcuTestCase.IterateResult.STOP; 1967 } 1968 1969 // Query layout from GL. 1970 /** @type {glsUniformBlockCase.UniformLayout} */ var glLayout = new glsUniformBlockCase.UniformLayout(); 1971 glsUniformBlockCase.getGLUniformLayout(gl, glLayout, program.getProgram()); 1972 1973 // Print layout to log. 1974 bufferedLogToConsole('Active glsUniformBlockCase.Uniform Blocks'); 1975 for (var blockNdx = 0; blockNdx < glLayout.blocks.length; blockNdx++) 1976 bufferedLogToConsole(blockNdx + ': ' + glLayout.blocks[blockNdx]); 1977 1978 bufferedLogToConsole('Active Uniforms'); 1979 for (var uniformNdx = 0; uniformNdx < glLayout.uniforms.length; uniformNdx++) 1980 bufferedLogToConsole(uniformNdx + ': ' + glLayout.uniforms[uniformNdx]); 1981 1982 // Check that we can even try rendering with given layout. 1983 if (!this.checkLayoutIndices(glLayout) || !this.checkLayoutBounds(glLayout) || !this.compareTypes(refLayout, glLayout)) { 1984 testFailedOptions('Invalid layout', false); 1985 return tcuTestCase.IterateResult.STOP; // It is not safe to use the given layout. 1986 } 1987 1988 // Verify all std140 blocks. 1989 if (!this.compareStd140Blocks(refLayout, glLayout)) 1990 testFailedOptions('Invalid std140 layout', false); 1991 1992 // Verify all shared blocks - all uniforms should be active, and certain properties match. 1993 if (!this.compareSharedBlocks(refLayout, glLayout)) 1994 testFailedOptions('Invalid shared layout', false); 1995 1996 // Check consistency with index queries 1997 if (!this.checkIndexQueries(program.getProgram(), glLayout)) 1998 testFailedOptions('Inconsintent block index query results', false); 1999 2000 // Use program. 2001 gl.useProgram(program.getProgram()); 2002 2003 /** @type {number} */ var binding; 2004 /** @type {WebGLBuffer} */ var buffer; 2005 2006 // Assign binding points to all active uniform blocks. 2007 for (var blockNdx = 0; blockNdx < glLayout.blocks.length; blockNdx++) { 2008 binding = blockNdx; // \todo [2012-01-25 pyry] Randomize order? 2009 gl.uniformBlockBinding(program.getProgram(), blockNdx, binding); 2010 } 2011 2012 /** @type {number} */ var numBlocks; 2013 /** @type {glsUniformBlockCase.BlockPointers} */ var glBlockPointers; 2014 2015 // Allocate buffers, write data and bind to targets. 2016 /** @type {glsUniformBlockCase.UniformBufferManager} */ var bufferManager = new glsUniformBlockCase.UniformBufferManager(gl); 2017 if (this.m_bufferMode == glsUniformBlockCase.BufferMode.BUFFERMODE_PER_BLOCK) { 2018 numBlocks = glLayout.blocks.length; 2019 glBlockPointers = new glsUniformBlockCase.BlockPointers(); 2020 2021 var totalsize = 0; 2022 for (var blockNdx = 0; blockNdx < numBlocks; blockNdx++) 2023 totalsize += glLayout.blocks[blockNdx].size; 2024 2025 glBlockPointers.resize(totalsize); 2026 2027 var offset = 0; 2028 for (var blockNdx = 0; blockNdx < numBlocks; blockNdx++) { 2029 glBlockPointers.push(offset, glLayout.blocks[blockNdx].size); 2030 offset += glLayout.blocks[blockNdx].size; 2031 } 2032 2033 glsUniformBlockCase.copyUniformData(glLayout, glBlockPointers, refLayout, blockPointers); 2034 2035 for (var blockNdx = 0; blockNdx < numBlocks; blockNdx++) { 2036 buffer = bufferManager.allocBuffer(); 2037 binding = blockNdx; 2038 gl.bindBuffer(gl.UNIFORM_BUFFER, buffer); 2039 gl.bufferData(gl.UNIFORM_BUFFER, glBlockPointers.find(blockNdx) /*(glw::GLsizeiptr)glData[blockNdx].size(), &glData[blockNdx][0]*/, gl.STATIC_DRAW); 2040 gl.bindBufferBase(gl.UNIFORM_BUFFER, binding, buffer); 2041 } 2042 } else { 2043 DE_ASSERT(this.m_bufferMode == glsUniformBlockCase.BufferMode.BUFFERMODE_SINGLE); 2044 2045 totalSize = 0; 2046 curOffset = 0; 2047 numBlocks = glLayout.blocks.length; 2048 /** @type {number} */ var bindingAlignment = 0; 2049 glBlockPointers = new glsUniformBlockCase.BlockPointers(); 2050 2051 bindingAlignment = /** @type {number} */ (gl.getParameter(gl.UNIFORM_BUFFER_OFFSET_ALIGNMENT)); 2052 2053 // Compute total size and offsets. 2054 curOffset = 0; 2055 for (var blockNdx = 0; blockNdx < numBlocks; blockNdx++) { 2056 if (bindingAlignment > 0) 2057 curOffset = glsUniformBlockCase.deRoundUp32(curOffset, bindingAlignment); 2058 glBlockPointers.push(curOffset, glLayout.blocks[blockNdx].size); 2059 curOffset += glLayout.blocks[blockNdx].size; 2060 } 2061 totalSize = curOffset; 2062 glBlockPointers.resize(totalSize); 2063 2064 // Copy to gl format. 2065 glsUniformBlockCase.copyUniformData(glLayout, glBlockPointers, refLayout, blockPointers); 2066 2067 // Allocate buffer and upload data. 2068 buffer = bufferManager.allocBuffer(); 2069 gl.bindBuffer(gl.UNIFORM_BUFFER, buffer); 2070 if (glBlockPointers.data.byteLength > 0 /*!glData.empty()*/) 2071 gl.bufferData(gl.UNIFORM_BUFFER, glBlockPointers.find(blockNdx) /*(glw::GLsizeiptr)glData.size(), &glData[0]*/, gl.STATIC_DRAW); 2072 2073 // Bind ranges to binding points. 2074 for (var blockNdx = 0; blockNdx < numBlocks; blockNdx++) { 2075 binding = blockNdx; 2076 gl.bindBufferRange(gl.UNIFORM_BUFFER, binding, buffer, glBlockPointers.offsets[blockNdx], glLayout.blocks[blockNdx].size); 2077 } 2078 } 2079 2080 /** @type {boolean} */ var renderOk = this.render(program); 2081 if (!renderOk) 2082 testFailedOptions('Image compare failed', false); 2083 else 2084 assertMsgOptions(renderOk, '', true, false); 2085 2086 return tcuTestCase.IterateResult.STOP; 2087 }; 2088 2089 /** 2090 * compareStd140Blocks 2091 * @param {glsUniformBlockCase.UniformLayout} refLayout 2092 * @param {glsUniformBlockCase.UniformLayout} cmpLayout 2093 **/ 2094 glsUniformBlockCase.UniformBlockCase.prototype.compareStd140Blocks = function(refLayout, cmpLayout) { 2095 /**@type {boolean} */ var isOk = true; 2096 /**@type {number} */ var numBlocks = this.m_interface.getNumUniformBlocks(); 2097 2098 for (var blockNdx = 0; blockNdx < numBlocks; blockNdx++) { 2099 /**@type {glsUniformBlockCase.UniformBlock} */ var block = this.m_interface.getUniformBlock(blockNdx); 2100 /**@type {boolean} */ var isArray = block.isArray(); 2101 /**@type {string} */ var instanceName = block.getBlockName() + (isArray ? '[0]' : ''); 2102 /**@type {number} */ var refBlockNdx = refLayout.getBlockIndex(instanceName); 2103 /**@type {number} */ var cmpBlockNdx = cmpLayout.getBlockIndex(instanceName); 2104 /**@type {boolean} */ var isUsed = (block.getFlags() & (glsUniformBlockCase.UniformFlags.DECLARE_VERTEX | glsUniformBlockCase.UniformFlags.DECLARE_FRAGMENT)) != 0; 2105 2106 if ((block.getFlags() & glsUniformBlockCase.UniformFlags.LAYOUT_STD140) == 0) 2107 continue; // Not std140 layout. 2108 2109 DE_ASSERT(refBlockNdx >= 0); 2110 2111 if (cmpBlockNdx < 0) { 2112 // Not found, should it? 2113 if (isUsed) { 2114 bufferedLogToConsole("Error: glsUniformBlockCase.Uniform block '" + instanceName + "' not found"); 2115 isOk = false; 2116 } 2117 2118 continue; // Skip block. 2119 } 2120 2121 /** @type {glsUniformBlockCase.BlockLayoutEntry} */ var refBlockLayout = refLayout.blocks[refBlockNdx]; 2122 /** @type {glsUniformBlockCase.BlockLayoutEntry} */ var cmpBlockLayout = cmpLayout.blocks[cmpBlockNdx]; 2123 2124 // \todo [2012-01-24 pyry] Verify that activeUniformIndices is correct. 2125 // \todo [2012-01-24 pyry] Verify all instances. 2126 if (refBlockLayout.activeUniformIndices.length != cmpBlockLayout.activeUniformIndices.length) { 2127 bufferedLogToConsole("Error: Number of active uniforms differ in block '" + instanceName + 2128 "' (expected " + refBlockLayout.activeUniformIndices.length + 2129 ', got ' + cmpBlockLayout.activeUniformIndices.length + 2130 ')'); 2131 isOk = false; 2132 } 2133 2134 for (var ndx = 0; ndx < refBlockLayout.activeUniformIndices.length; ndx++) { 2135 /** @type {number} */ var ndxIter = refBlockLayout.activeUniformIndices[ndx]; 2136 /** @type {glsUniformBlockCase.UniformLayoutEntry} */ var refEntry = refLayout.uniforms[ndxIter]; 2137 /** @type {number} */ var cmpEntryNdx = cmpLayout.getUniformIndex(refEntry.name); 2138 2139 if (cmpEntryNdx < 0) { 2140 bufferedLogToConsole("Error: glsUniformBlockCase.Uniform '" + refEntry.name + "' not found"); 2141 isOk = false; 2142 continue; 2143 } 2144 2145 /** @type {glsUniformBlockCase.UniformLayoutEntry} */ var cmpEntry = cmpLayout.uniforms[cmpEntryNdx]; 2146 2147 if (refEntry.type != cmpEntry.type || 2148 refEntry.size != cmpEntry.size || 2149 refEntry.offset != cmpEntry.offset || 2150 refEntry.arrayStride != cmpEntry.arrayStride || 2151 refEntry.matrixStride != cmpEntry.matrixStride || 2152 refEntry.isRowMajor != cmpEntry.isRowMajor) { 2153 bufferedLogToConsole("Error: Layout mismatch in '" + refEntry.name + "':\n" + 2154 ' expected: type = ' + gluShaderUtil.getDataTypeName(refEntry.type) + ', size = ' + refEntry.size + ', row major = ' + (refEntry.isRowMajor ? 'true' : 'false') + '\n' + 2155 ' got: type = ' + gluShaderUtil.getDataTypeName(cmpEntry.type) + ', size = ' + cmpEntry.size + ', row major = ' + (cmpEntry.isRowMajor ? 'true' : 'false')); 2156 isOk = false; 2157 } 2158 } 2159 } 2160 2161 return isOk; 2162 }; 2163 2164 /** 2165 * compareSharedBlocks 2166 * @param {glsUniformBlockCase.UniformLayout} refLayout 2167 * @param {glsUniformBlockCase.UniformLayout} cmpLayout 2168 **/ 2169 glsUniformBlockCase.UniformBlockCase.prototype.compareSharedBlocks = function(refLayout, cmpLayout) { 2170 /** @type {boolean} */ var isOk = true; 2171 /** @type {number} */ var numBlocks = this.m_interface.getNumUniformBlocks(); 2172 2173 for (var blockNdx = 0; blockNdx < numBlocks; blockNdx++) { 2174 /** @type {glsUniformBlockCase.UniformBlock} */ var block = this.m_interface.getUniformBlock(blockNdx); 2175 /** @type {boolean} */ var isArray = block.isArray(); 2176 /** @type {string} */ var instanceName = block.getBlockName() + (isArray ? '[0]' : ''); 2177 /** @type {number} */ var refBlockNdx = refLayout.getBlockIndex(instanceName); 2178 /** @type {number} */ var cmpBlockNdx = cmpLayout.getBlockIndex(instanceName); 2179 /** @type {boolean} */ var isUsed = (block.getFlags() & (glsUniformBlockCase.UniformFlags.DECLARE_VERTEX | glsUniformBlockCase.UniformFlags.DECLARE_FRAGMENT)) != 0; 2180 2181 if ((block.getFlags() & glsUniformBlockCase.UniformFlags.LAYOUT_SHARED) == 0) 2182 continue; // Not shared layout. 2183 2184 DE_ASSERT(refBlockNdx >= 0); 2185 2186 if (cmpBlockNdx < 0) { 2187 // Not found, should it? 2188 if (isUsed) { 2189 bufferedLogToConsole("Error: glsUniformBlockCase.Uniform block '" + instanceName + "' not found"); 2190 isOk = false; 2191 } 2192 2193 continue; // Skip block. 2194 } 2195 2196 /** @type {glsUniformBlockCase.BlockLayoutEntry} */ var refBlockLayout = refLayout.blocks[refBlockNdx]; 2197 /** @type {glsUniformBlockCase.BlockLayoutEntry} */ var cmpBlockLayout = cmpLayout.blocks[cmpBlockNdx]; 2198 2199 if (refBlockLayout.activeUniformIndices.length != cmpBlockLayout.activeUniformIndices.length) { 2200 bufferedLogToConsole("Error: Number of active uniforms differ in block '" + instanceName + 2201 "' (expected " + refBlockLayout.activeUniformIndices.length + 2202 ', got ' + cmpBlockLayout.activeUniformIndices.length + 2203 ')'); 2204 isOk = false; 2205 } 2206 2207 for (var ndx = 0; ndx < refBlockLayout.activeUniformIndices.length; ndx++) { 2208 /** @type {number} */ var ndxIter = refBlockLayout.activeUniformIndices[ndx]; 2209 /** @type {glsUniformBlockCase.UniformLayoutEntry} */ var refEntry = refLayout.uniforms[ndxIter]; 2210 /** @type {number} */ var cmpEntryNdx = cmpLayout.getUniformIndex(refEntry.name); 2211 2212 if (cmpEntryNdx < 0) { 2213 bufferedLogToConsole("Error: glsUniformBlockCase.Uniform '" + refEntry.name + "' not found"); 2214 isOk = false; 2215 continue; 2216 } 2217 2218 /** @type {glsUniformBlockCase.UniformLayoutEntry} */ var cmpEntry = cmpLayout.uniforms[cmpEntryNdx]; 2219 2220 if (refEntry.type != cmpEntry.type || 2221 refEntry.size != cmpEntry.size || 2222 refEntry.isRowMajor != cmpEntry.isRowMajor) { 2223 bufferedLogToConsole("Error: Layout mismatch in '" + refEntry.name + "':\n" + 2224 ' expected: type = ' + gluShaderUtil.getDataTypeName(refEntry.type) + ', size = ' + refEntry.size + ', row major = ' + (refEntry.isRowMajor ? 'true' : 'false') + '\n' + 2225 ' got: type = ' + gluShaderUtil.getDataTypeName(cmpEntry.type) + ', size = ' + cmpEntry.size + ', row major = ' + (cmpEntry.isRowMajor ? 'true' : 'false')); 2226 isOk = false; 2227 } 2228 } 2229 } 2230 2231 return isOk; 2232 }; 2233 2234 /** compareTypes 2235 * @param {glsUniformBlockCase.UniformLayout} refLayout 2236 * @param {glsUniformBlockCase.UniformLayout} cmpLayout 2237 * @return {boolean} true if uniform types are the same 2238 **/ 2239 glsUniformBlockCase.UniformBlockCase.prototype.compareTypes = function(refLayout, cmpLayout) { 2240 /** @type {boolean} */ var isOk = true; 2241 /** @type {number} */ var numBlocks = this.m_interface.getNumUniformBlocks(); 2242 2243 for (var blockNdx = 0; blockNdx < numBlocks; blockNdx++) { 2244 /** @type {glsUniformBlockCase.UniformBlock} */ var block = this.m_interface.getUniformBlock(blockNdx); 2245 /** @type {boolean} */ var isArray = block.isArray(); 2246 /** @type {number} */ var numInstances = isArray ? block.getArraySize() : 1; 2247 2248 for (var instanceNdx = 0; instanceNdx < numInstances; instanceNdx++) { 2249 /** @type {string} */ var instanceName; 2250 2251 instanceName += block.getBlockName(); 2252 if (isArray) 2253 instanceName = instanceName + '[' + instanceNdx + ']'; 2254 2255 /** @type {number} */ var cmpBlockNdx = cmpLayout.getBlockIndex(instanceName); 2256 2257 if (cmpBlockNdx < 0) 2258 continue; 2259 2260 /** @type {glsUniformBlockCase.BlockLayoutEntry} */ var cmpBlockLayout = cmpLayout.blocks[cmpBlockNdx]; 2261 2262 for (var ndx = 0; ndx < cmpBlockLayout.activeUniformIndices.length; ndx++) { 2263 /** @type {number} */ var ndxIter = cmpBlockLayout.activeUniformIndices[ndx]; 2264 /** @type {glsUniformBlockCase.UniformLayoutEntry} */ var cmpEntry = cmpLayout.uniforms[ndxIter]; 2265 /** @type {number} */ var refEntryNdx = refLayout.getUniformIndex(cmpEntry.name); 2266 2267 if (refEntryNdx < 0) { 2268 bufferedLogToConsole("Error: glsUniformBlockCase.Uniform '" + cmpEntry.name + "' not found in reference layout"); 2269 isOk = false; 2270 continue; 2271 } 2272 2273 /** @type {glsUniformBlockCase.UniformLayoutEntry} */ var refEntry = refLayout.uniforms[refEntryNdx]; 2274 2275 // \todo [2012-11-26 pyry] Should we check other properties as well? 2276 if (refEntry.type != cmpEntry.type) { 2277 bufferedLogToConsole("Error: glsUniformBlockCase.Uniform type mismatch in '" + refEntry.name + "':</br>" + 2278 "' expected: '" + gluShaderUtil.getDataTypeName(refEntry.type) + "'</br>" + 2279 "' got: '" + gluShaderUtil.getDataTypeName(cmpEntry.type) + "'"); 2280 isOk = false; 2281 } 2282 } 2283 } 2284 } 2285 2286 return isOk; 2287 }; 2288 2289 /** checkLayoutIndices 2290 * @param {glsUniformBlockCase.UniformLayout} layout Layout whose indices are to be checked 2291 * @return {boolean} true if all is ok 2292 **/ 2293 glsUniformBlockCase.UniformBlockCase.prototype.checkLayoutIndices = function(layout) { 2294 /** @type {number} */ var numUniforms = layout.uniforms.length; 2295 /** @type {number} */ var numBlocks = layout.blocks.length; 2296 /** @type {boolean} */ var isOk = true; 2297 2298 // Check uniform block indices. 2299 for (var uniformNdx = 0; uniformNdx < numUniforms; uniformNdx++) { 2300 /** @type {glsUniformBlockCase.UniformLayoutEntry} */ var uniform = layout.uniforms[uniformNdx]; 2301 2302 if (uniform.blockNdx < 0 || !deMath.deInBounds32(uniform.blockNdx, 0, numBlocks)) { 2303 bufferedLogToConsole("Error: Invalid block index in uniform '" + uniform.name + "'"); 2304 isOk = false; 2305 } 2306 } 2307 2308 // Check active uniforms. 2309 for (var blockNdx = 0; blockNdx < numBlocks; blockNdx++) { 2310 /** @type {glsUniformBlockCase.BlockLayoutEntry} */ var block = layout.blocks[blockNdx]; 2311 2312 for (var uniformNdx = 0; uniformNdx < block.activeUniformIndices.length; uniformNdx++) { 2313 /** @type {glsUniformBlockCase.UniformLayoutEntry} */ var activeUniformNdx = block.activeUniformIndices[uniformNdx]; 2314 if (!deMath.deInBounds32(activeUniformNdx, 0, numUniforms)) { 2315 bufferedLogToConsole('Error: Invalid active uniform index ' + activeUniformNdx + " in block '" + block.name); 2316 isOk = false; 2317 } 2318 } 2319 } 2320 return isOk; 2321 }; 2322 2323 /** checkLayoutBounds 2324 * @param {glsUniformBlockCase.UniformLayout} layout The uniform layout to check 2325 * @return {boolean} true if all is within bounds 2326 **/ 2327 glsUniformBlockCase.UniformBlockCase.prototype.checkLayoutBounds = function(layout) { 2328 /** @type {number} */ var numUniforms = layout.uniforms.length; 2329 /** @type {boolean}*/ var isOk = true; 2330 2331 for (var uniformNdx = 0; uniformNdx < numUniforms; uniformNdx++) { 2332 /** @type {glsUniformBlockCase.UniformLayoutEntry}*/ var uniform = layout.uniforms[uniformNdx]; 2333 2334 if (uniform.blockNdx < 0) 2335 continue; 2336 2337 /** @type {glsUniformBlockCase.BlockLayoutEntry}*/ var block = layout.blocks[uniform.blockNdx]; 2338 /** @type {boolean}*/ var isMatrix = gluShaderUtil.isDataTypeMatrix(uniform.type); 2339 /** @type {number}*/ var numVecs = isMatrix ? (uniform.isRowMajor ? gluShaderUtil.getDataTypeMatrixNumRows(uniform.type) : gluShaderUtil.getDataTypeMatrixNumColumns(uniform.type)) : 1; 2340 /** @type {number}*/ var numComps = isMatrix ? (uniform.isRowMajor ? gluShaderUtil.getDataTypeMatrixNumColumns(uniform.type) : gluShaderUtil.getDataTypeMatrixNumRows(uniform.type)) : gluShaderUtil.getDataTypeScalarSize(uniform.type); 2341 /** @type {number}*/ var numElements = uniform.size; 2342 /** @type {number}*/ var compSize = deMath.INT32_SIZE; 2343 /** @type {number}*/ var vecSize = numComps * compSize; 2344 2345 /** @type {number}*/ var minOffset = 0; 2346 /** @type {number}*/ var maxOffset = 0; 2347 2348 // For negative strides. 2349 minOffset = Math.min(minOffset, (numVecs - 1) * uniform.matrixStride); 2350 minOffset = Math.min(minOffset, (numElements - 1) * uniform.arrayStride); 2351 minOffset = Math.min(minOffset, (numElements - 1) * uniform.arrayStride + (numVecs - 1) * uniform.matrixStride); 2352 2353 maxOffset = Math.max(maxOffset, vecSize); 2354 maxOffset = Math.max(maxOffset, (numVecs - 1) * uniform.matrixStride + vecSize); 2355 maxOffset = Math.max(maxOffset, (numElements - 1) * uniform.arrayStride + vecSize); 2356 maxOffset = Math.max(maxOffset, (numElements - 1) * uniform.arrayStride + (numVecs - 1) * uniform.matrixStride + vecSize); 2357 2358 if (uniform.offset + minOffset < 0 || uniform.offset + maxOffset > block.size) { 2359 bufferedLogToConsole("Error: glsUniformBlockCase.Uniform '" + uniform.name + "' out of block bounds"); 2360 isOk = false; 2361 } 2362 } 2363 2364 return isOk; 2365 }; 2366 2367 /** checkIndexQueries 2368 * @param {WebGLProgram} program The shader program to be checked against 2369 * @param {glsUniformBlockCase.UniformLayout} layout The layout to check 2370 * @return {boolean} true if everything matches. 2371 **/ 2372 glsUniformBlockCase.UniformBlockCase.prototype.checkIndexQueries = function(program, layout) { 2373 /** @type {boolean}*/ var allOk = true; 2374 2375 // \note Spec mandates that uniform blocks are assigned consecutive locations from 0 2376 // to ACTIVE_UNIFORM_BLOCKS. BlockLayoutEntries are stored in that order in glsUniformBlockCase.UniformLayout. 2377 for (var blockNdx = 0; blockNdx < layout.blocks.length; blockNdx++) { 2378 /** @const */ var block = layout.blocks[blockNdx]; 2379 /** @const */ var queriedNdx = gl.getUniformBlockIndex(program, block.name); 2380 2381 if (queriedNdx != blockNdx) { 2382 bufferedLogToConsole('ERROR: glGetUniformBlockIndex(' + block.name + ') returned ' + queriedNdx + ', expected ' + blockNdx + '!'); 2383 allOk = false; 2384 } 2385 } 2386 2387 return allOk; 2388 }; 2389 2390 /** @const @type {number} */ glsUniformBlockCase.VIEWPORT_WIDTH = 128; 2391 /** @const @type {number} */ glsUniformBlockCase.VIEWPORT_HEIGHT = 128; 2392 2393 /** Renders a white square, and then tests all pixels are 2394 * effectively white in the color buffer. 2395 * @param {gluShaderProgram.ShaderProgram} program The shader program to use. 2396 * @return {boolean} false if there was at least one incorrect pixel 2397 **/ 2398 glsUniformBlockCase.UniformBlockCase.prototype.render = function(program) { 2399 // Compute viewport. 2400 /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name)); 2401 /** @const */ var viewportW = Math.min(gl.canvas.width, glsUniformBlockCase.VIEWPORT_WIDTH); 2402 /** @const */ var viewportH = Math.min(gl.canvas.height, glsUniformBlockCase.VIEWPORT_HEIGHT); 2403 /** @const */ var viewportX = rnd.getInt(0, gl.canvas.width); 2404 /** @const */ var viewportY = rnd.getInt(0, gl.canvas.height); 2405 2406 gl.clearColor(0.125, 0.25, 0.5, 1.0); 2407 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT); 2408 2409 //Draw 2410 var position = [ 2411 -1.0, -1.0, 0.0, 1.0, 2412 -1.0, 1.0, 0.0, 1.0, 2413 1.0, -1.0, 0.0, 1.0, 2414 1.0, 1.0, 0.0, 1.0 2415 ]; 2416 var indices = [0, 1, 2, 2, 1, 3]; 2417 2418 gl.viewport(viewportX, viewportY, viewportW, viewportH); 2419 2420 // Access 2421 var posLoc = gl.getAttribLocation(program.getProgram(), 'a_position'); 2422 var posArray = [new gluDrawUtil.VertexArrayBinding(gl.FLOAT, posLoc, 4, 4, position)]; 2423 gluDrawUtil.draw(gl, program.getProgram(), posArray, gluDrawUtil.triangles(indices)); 2424 2425 // Verify that all pixels are white. 2426 var pixels = new gluDrawUtil.Surface(); 2427 var numFailedPixels = 0; 2428 2429 var readPixelsX = (viewportX + viewportW) > gl.canvas.width 2430 ? (gl.canvas.width - viewportX) : viewportW; 2431 var readPixelsY = (viewportY + viewportH) > gl.canvas.height 2432 ? (gl.canvas.height - viewportY) : viewportH; 2433 2434 var buffer = pixels.readSurface(gl, viewportX, viewportY, readPixelsX, readPixelsY); 2435 2436 var whitePixel = new gluDrawUtil.Pixel([255.0, 255.0, 255.0, 255.0]); 2437 for (var y = 0; y < readPixelsY; y++) { 2438 for (var x = 0; x < readPixelsX; x++) { 2439 if (!pixels.getPixel(x, y).equals(whitePixel)) 2440 numFailedPixels += 1; 2441 } 2442 } 2443 2444 if (numFailedPixels > 0) { 2445 bufferedLogToConsole('Image comparison failed, got ' + numFailedPixels + ' non-white pixels.'); 2446 } 2447 2448 return numFailedPixels == 0; 2449 }; 2450 2451 });