tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 });