es3fFragmentOutputTests.js (71637B)
1 /*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES Utilities 3 * ------------------------------------------------ 4 * 5 * Copyright 2014 The Android Open Source Project 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 */ 20 21 'use strict'; 22 goog.provide('functional.gles3.es3fFragmentOutputTests'); 23 goog.require('framework.common.tcuImageCompare'); 24 goog.require('framework.common.tcuTestCase'); 25 goog.require('framework.common.tcuTexture'); 26 goog.require('framework.common.tcuTextureUtil'); 27 goog.require('framework.delibs.debase.deMath'); 28 goog.require('framework.delibs.debase.deRandom'); 29 goog.require('framework.opengl.gluShaderProgram'); 30 goog.require('framework.opengl.gluShaderUtil'); 31 goog.require('framework.opengl.gluTextureUtil'); 32 goog.require('functional.gles3.es3fFboTestUtil'); 33 34 goog.scope(function() { 35 36 var es3fFragmentOutputTests = functional.gles3.es3fFragmentOutputTests; 37 var gluShaderProgram = framework.opengl.gluShaderProgram; 38 var es3fFboTestUtil = functional.gles3.es3fFboTestUtil; 39 var gluShaderUtil = framework.opengl.gluShaderUtil; 40 var deRandom = framework.delibs.debase.deRandom; 41 var tcuTestCase = framework.common.tcuTestCase; 42 var gluTextureUtil = framework.opengl.gluTextureUtil; 43 var tcuTexture = framework.common.tcuTexture; 44 var tcuTextureUtil = framework.common.tcuTextureUtil; 45 var deMath = framework.delibs.debase.deMath; 46 var tcuImageCompare = framework.common.tcuImageCompare; 47 48 /** @type {WebGL2RenderingContext} */ var gl; 49 50 var DE_ASSERT = function(x) { 51 if (!x) 52 throw new Error('Assert failed'); 53 }; 54 55 /** 56 * es3fFragmentOutputTests.BufferSpec. Constructs the es3fFragmentOutputTests.BufferSpec object 57 * @constructor 58 * @param {WebGLRenderingContextBase.GLenum} format_ 59 * @param {number} width_ 60 * @param {number} height_ 61 * @param {number} samples_ 62 */ 63 es3fFragmentOutputTests.BufferSpec = function(format_, width_, height_, samples_) { 64 this.format = format_; 65 this.width = width_; 66 this.height = height_; 67 this.samples = samples_; 68 }; 69 70 /** 71 * es3fFragmentOutputTests.FragmentOutput. Constructs the es3fFragmentOutputTests.FragmentOutput object 72 * @constructor 73 * @param {gluShaderUtil.DataType} type_ 74 * @param {gluShaderUtil.precision} precision_ 75 * @param {number} location_ 76 * @param {number=} arrayLength_ 77 */ 78 es3fFragmentOutputTests.FragmentOutput = function(type_, precision_, location_, arrayLength_) { 79 this.type = type_; 80 this.precision = precision_; 81 this.location = location_; 82 this.arrayLength = arrayLength_ || 0; 83 }; 84 85 /** 86 * es3fFragmentOutputTests.FragmentOutputCase. Constructs the es3fFragmentOutputTests.FragmentOutputCase object 87 * @constructor 88 * @extends {tcuTestCase.DeqpTest} 89 * @param {string} name 90 * @param {string} description 91 * @param {Array<es3fFragmentOutputTests.BufferSpec>} fboSpec 92 * @param {Array<es3fFragmentOutputTests.FragmentOutput>} outputs 93 * @return {Object} The currently modified object 94 */ 95 es3fFragmentOutputTests.FragmentOutputCase = function(name, description, fboSpec, outputs) { 96 tcuTestCase.DeqpTest.call(this, name, description); 97 /** @type {Array<es3fFragmentOutputTests.BufferSpec>} */ this.m_fboSpec = fboSpec; 98 /** @type {Array<es3fFragmentOutputTests.FragmentOutput>} */ this.m_outputs = outputs; 99 /** @type {gluShaderProgram.ShaderProgram} */ this.m_program = null; 100 /** @type {WebGLFramebuffer} */ this.m_framebuffer = null; 101 102 /** @type {WebGLRenderbuffer} */ this.m_renderbuffer = null; 103 }; 104 105 es3fFragmentOutputTests.FragmentOutputCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype); 106 es3fFragmentOutputTests.FragmentOutputCase.prototype.constructor = es3fFragmentOutputTests.FragmentOutputCase; 107 108 /** 109 * es3fFragmentOutputTests.createProgram. Returns a ShaderProgram object 110 * @param {Array<es3fFragmentOutputTests.FragmentOutput>} outputs 111 * @return {gluShaderProgram.ShaderProgram} program 112 */ 113 es3fFragmentOutputTests.createProgram = function(outputs) { 114 115 var vtx = ''; 116 var frag = ''; 117 118 vtx = '#version 300 es\n' + 'in highp vec4 a_position;\n'; 119 frag = '#version 300 es\n'; 120 121 /** @type {es3fFragmentOutputTests.FragmentOutput} */ var output = null; 122 /** @type {boolean} */ var isArray = false; 123 // Input-output declarations. 124 for (var outNdx = 0; outNdx < outputs.length; outNdx++) { 125 output = outputs[outNdx]; 126 isArray = output.arrayLength > 0; 127 /** @type {string} */ var typeName = gluShaderUtil.getDataTypeName(output.type); 128 /** @type {string} */ var precName = gluShaderUtil.getPrecisionName(output.precision); 129 /** @type {boolean} */ var isFloat = gluShaderUtil.isDataTypeFloatOrVec(output.type); 130 /** @type {string} */ var interp = isFloat ? 'smooth' : 'flat'; 131 132 if (isArray) { 133 for (var elemNdx = 0; elemNdx < output.arrayLength; elemNdx++) { 134 vtx += 'in ' + precName + ' ' + typeName + ' in' + outNdx + '_' + elemNdx + ';\n' + 135 interp + ' out ' + precName + ' ' + typeName + ' var' + outNdx + '_' + elemNdx + ';\n'; 136 frag += interp + ' in ' + precName + ' ' + typeName + ' var' + outNdx + '_' + elemNdx + ';\n'; 137 } 138 frag += 'layout(location = ' + output.location + ') out ' + precName + ' ' + typeName + ' out' + outNdx + '[' + output.arrayLength + '];\n'; 139 } else { 140 vtx += 'in ' + precName + ' ' + typeName + ' in' + outNdx + ';\n' + 141 interp + ' out ' + precName + ' ' + typeName + ' var' + outNdx + ';\n'; 142 frag += interp + ' in ' + precName + ' ' + typeName + ' var' + outNdx + ';\n' + 143 'layout(location = ' + output.location + ') out ' + precName + ' ' + typeName + ' out' + outNdx + ';\n'; 144 } 145 } 146 147 vtx += '\nvoid main()\n{\n'; 148 frag += '\nvoid main()\n{\n'; 149 150 vtx += ' gl_Position = a_position;\n'; 151 152 // Copy body 153 for (var outNdx = 0; outNdx < outputs.length; outNdx++) { 154 output = outputs[outNdx]; 155 isArray = output.arrayLength > 0; 156 157 if (isArray) { 158 for (var elemNdx = 0; elemNdx < output.arrayLength; elemNdx++) { 159 vtx += '\tvar' + outNdx + '_' + elemNdx + ' = in' + outNdx + '_' + elemNdx + ';\n'; 160 frag += '\tout' + outNdx + '[' + elemNdx + '] = var' + outNdx + '_' + elemNdx + ';\n'; 161 } 162 } else { 163 vtx += '\tvar' + outNdx + ' = in' + outNdx + ';\n'; 164 frag += '\tout' + outNdx + ' = var' + outNdx + ';\n'; 165 } 166 } 167 168 vtx += '}\n'; 169 frag += '}\n'; 170 171 /** @type {gluShaderProgram.ShaderProgram} */ 172 var program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vtx, frag)); 173 return program; 174 }; 175 176 es3fFragmentOutputTests.FragmentOutputCase.prototype.init = function() { 177 // Check that all attachments are supported 178 for (var iter = 0; iter < this.m_fboSpec.length; ++iter) { 179 if (!gluTextureUtil.isSizedFormatColorRenderable(this.m_fboSpec[iter].format)) 180 throw new Error('Unsupported attachment format'); 181 } 182 183 DE_ASSERT(!this.m_program); 184 this.m_program = es3fFragmentOutputTests.createProgram(this.m_outputs); 185 186 // log << *m_program; 187 if (!this.m_program.isOk()) 188 throw new Error('Compile failed. Program no created'); 189 190 /* 191 // Print render target info to log. 192 log << TestLog::Section("Framebuffer", "Framebuffer configuration"); 193 194 for (int ndx = 0; ndx < (int)m_fboSpec.size(); ndx++) 195 log << TestLog::Message << "COLOR_ATTACHMENT" << ndx << ": " 196 << glu::getPixelFormatStr(m_fboSpec[ndx].format) << ", " 197 << m_fboSpec[ndx].width << "x" << m_fboSpec[ndx].height << ", " 198 << m_fboSpec[ndx].samples << " samples" 199 << TestLog::EndMessage; 200 201 log << TestLog::EndSection;*/ 202 203 // Create framebuffer. 204 this.m_framebuffer = gl.createFramebuffer(); 205 gl.bindFramebuffer(gl.FRAMEBUFFER, this.m_framebuffer); 206 207 for (var bufNdx = 0; bufNdx < /* m_renderbuffers.size() */ this.m_fboSpec.length; bufNdx++) { 208 this.m_renderbuffer = gl.createRenderbuffer(); 209 /** @type {es3fFragmentOutputTests.BufferSpec} */ var bufSpec = this.m_fboSpec[bufNdx]; 210 /** @type {number} */ var attachment = gl.COLOR_ATTACHMENT0 + bufNdx; 211 212 gl.bindRenderbuffer(gl.RENDERBUFFER, this.m_renderbuffer); 213 214 gl.renderbufferStorageMultisample(gl.RENDERBUFFER, bufSpec.samples, bufSpec.format, bufSpec.width, bufSpec.height); 215 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment, gl.RENDERBUFFER, this.m_renderbuffer); 216 } 217 /** @type {number} */ var fboStatus = gl.checkFramebufferStatus(gl.FRAMEBUFFER); 218 219 if (fboStatus == gl.FRAMEBUFFER_UNSUPPORTED) 220 throw new Error('Framebuffer not supported'); 221 else if (fboStatus != gl.FRAMEBUFFER_COMPLETE) 222 throw new Error('Incomplete framebuffer'); 223 // throw tcu::TestError((string("Incomplete framebuffer: ") + glu::getFramebufferStatusStr(fboStatus), "", __FILE__, __LINE__); 224 225 // gl.bindRenderbuffer(gl.RENDERBUFFER, null); // TODO: maybe needed? 226 gl.bindFramebuffer(gl.FRAMEBUFFER, null); 227 }; 228 229 es3fFragmentOutputTests.FragmentOutputCase.prototype.deinit = function() { 230 // TODO: implement? 231 }; 232 233 /** 234 * es3fFragmentOutputTests.getMinSize. 235 * @param {Array<es3fFragmentOutputTests.BufferSpec>} fboSpec 236 * @return {Array<number>} minSize 237 */ 238 es3fFragmentOutputTests.getMinSize = function(fboSpec) { 239 /** @type {Array<number>} */ var minSize = [0x7fffffff, 0x7fffffff]; 240 for (var i = 0; i < fboSpec.length; i++) { 241 minSize[0] = Math.min(minSize[0], fboSpec[i].width); 242 minSize[1] = Math.min(minSize[1], fboSpec[i].height); 243 } 244 return minSize; 245 }; 246 247 /** 248 * es3fFragmentOutputTests.getNumInputVectors. Returns the length of the array of all the outputs (es3fFragmentOutputTests.FragmentOutput object) 249 * @param {Array<es3fFragmentOutputTests.FragmentOutput>} outputs 250 * @return {number} numVecs 251 */ 252 es3fFragmentOutputTests.getNumInputVectors = function(outputs) { 253 /** @type {number} */ var numVecs = 0; 254 for (var i = 0; i < outputs.length; i++) 255 numVecs += (outputs[i].arrayLength > 0 ? outputs[i].arrayLength : 1); 256 return numVecs; 257 }; 258 259 /** 260 * es3fFragmentOutputTests.getFloatRange 261 * @param {gluShaderUtil.precision} precision 262 * @return {Array<number>} Vec2 263 */ 264 es3fFragmentOutputTests.getFloatRange = function(precision) { 265 /** @type {Array<Array<number>>} */ 266 var ranges = // Vec2 267 [ 268 [-2.0, 2.0], 269 [-16000.0, 16000.0], 270 [-1e35, 1e35] 271 ]; 272 // DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(ranges) == glu::PRECISION_LAST); 273 // DE_ASSERT(de::inBounds<int>(precision, 0, DE_LENGTH_OF_ARRAY(ranges))); 274 return ranges[precision]; 275 }; 276 277 /** 278 * es3fFragmentOutputTests.getIntRange 279 * @param {gluShaderUtil.precision} precision 280 * @return {Array<number>} IVec2 281 */ 282 es3fFragmentOutputTests.getIntRange = function(precision) { 283 /** @type {Array<Array<number>>} */ 284 var ranges = // IVec2 285 [ 286 [-(1 << 7), (1 << 7) - 1], 287 [-(1 << 15), (1 << 15) - 1], 288 [-0x80000000, 0x7fffffff] 289 ]; 290 // DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(ranges) == glu::PRECISION_LAST); 291 // DE_ASSERT(de::inBounds<int>(precision, 0, DE_LENGTH_OF_ARRAY(ranges))); 292 return ranges[precision]; 293 }; 294 295 /** 296 * es3fFragmentOutputTests.getUintRange 297 * @param {gluShaderUtil.precision} precision 298 * @return {Array<number>} UVec2 299 */ 300 es3fFragmentOutputTests.getUintRange = function(precision) { 301 /** @type {Array<Array<number>>} */ 302 var ranges = // UVec2 303 [ 304 [0, (1 << 8) - 1], 305 [0, (1 << 16) - 1], 306 [0, 0xffffffff] 307 ]; 308 // DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(ranges) == glu::PRECISION_LAST); 309 // DE_ASSERT(de::inBounds<int>(precision, 0, DE_LENGTH_OF_ARRAY(ranges))); 310 return ranges[precision]; 311 312 }; 313 314 /** 315 * es3fFragmentOutputTests.readVec4 316 * @param {Array<number>} ptr 317 * @param {number} index 318 * @param {number} numComponents 319 * @return {Array<number>} Vec4 320 */ 321 es3fFragmentOutputTests.readVec4 = function(ptr, index, numComponents) { 322 DE_ASSERT(numComponents >= 1); 323 return [ 324 ptr[index + 0], 325 numComponents >= 2 ? ptr[index + 1] : 0.0, 326 numComponents >= 3 ? ptr[index + 2] : 0.0, 327 numComponents >= 4 ? ptr[index + 3] : 0.0 328 ]; 329 }; 330 331 /** 332 * es3fFragmentOutputTests.readIVec4 333 * @param {Array<number>} ptr 334 * @param {number} numComponents 335 * @return {Array<number>} IVec4 336 */ 337 es3fFragmentOutputTests.readIVec4 = function(ptr, index, numComponents) { 338 DE_ASSERT(numComponents >= 1); 339 return [ 340 ptr[index + 0], 341 numComponents >= 2 ? ptr[index + 1] : 0, 342 numComponents >= 3 ? ptr[index + 2] : 0, 343 numComponents >= 4 ? ptr[index + 3] : 0 344 ]; 345 }; 346 347 /** 348 * es3fFragmentOutputTests.renderFloatReference 349 * @param {tcuTexture.PixelBufferAccess} dst 350 * @param {number} gridWidth 351 * @param {number} gridHeight 352 * @param {number} numComponents 353 * @param {Array<number>} vertices 354 */ 355 es3fFragmentOutputTests.renderFloatReference = function(dst, gridWidth, gridHeight, numComponents, vertices) { 356 357 /** @type {boolean} */ var isSRGB = dst.getFormat().order == tcuTexture.ChannelOrder.sRGB || dst.getFormat().order == tcuTexture.ChannelOrder.sRGBA; 358 /** @type {number} */ var cellW = dst.getWidth() / (gridWidth - 1); 359 /** @type {number} */ var cellH = dst.getHeight() / (gridHeight - 1); 360 361 for (var y = 0; y < dst.getHeight(); y++) { 362 for (var x = 0; x < dst.getWidth(); x++) { 363 /** @type {number} */ var cellX = deMath.clamp(Math.floor(x / cellW), 0, gridWidth - 2); 364 /** @type {number} */ var cellY = deMath.clamp(Math.floor(y / cellH), 0, gridHeight - 2); 365 /** @type {number} */ var xf = (x - cellX * cellW + 0.5) / cellW; 366 /** @type {number} */ var yf = (y - cellY * cellH + 0.5) / cellH; 367 368 /** @type {Array<number>} */ var v00 = es3fFragmentOutputTests.readVec4(vertices, ((cellY + 0) * gridWidth + cellX + 0) * numComponents, numComponents); // Vec4 369 /** @type {Array<number>} */ var v01 = es3fFragmentOutputTests.readVec4(vertices, ((cellY + 1) * gridWidth + cellX + 0) * numComponents, numComponents); // Vec4 370 /** @type {Array<number>} */ var v10 = es3fFragmentOutputTests.readVec4(vertices, ((cellY + 0) * gridWidth + cellX + 1) * numComponents, numComponents); // Vec4 371 /** @type {Array<number>} */ var v11 = es3fFragmentOutputTests.readVec4(vertices, ((cellY + 1) * gridWidth + cellX + 1) * numComponents, numComponents); // Vec4 372 373 /** @type {boolean} */ var tri = xf + yf >= 1.0; 374 /** @type {Array<number>} */ var v0 = tri ? v11 : v00; // Vec4& 375 /** @type {Array<number>} */ var v1 = tri ? v01 : v10; // Vec4& 376 /** @type {Array<number>} */ var v2 = tri ? v10 : v01; // Vec4& 377 /** @type {number} */ var s = tri ? 1.0 - xf : xf; 378 /** @type {number} */ var t = tri ? 1.0 - yf : yf; 379 /** @type {Array<number>} */ var color = deMath.add(v0, deMath.add(deMath.multiply((deMath.subtract(v1, v0)), [s, s, s, s]), deMath.multiply((deMath.subtract(v2, v0)), [t, t, t, t]))); // Vec4 380 381 dst.setPixel(isSRGB ? tcuTextureUtil.linearToSRGB(color) : color, x, y); 382 } 383 } 384 }; 385 386 /** 387 * es3fFragmentOutputTests.renderIntReference 388 * @param {tcuTexture.PixelBufferAccess} dst 389 * @param {number} gridWidth 390 * @param {number} gridHeight 391 * @param {number} numComponents 392 * @param {Array<number>} vertices 393 */ 394 es3fFragmentOutputTests.renderIntReference = function(dst, gridWidth, gridHeight, numComponents, vertices) { 395 396 /** @type {number} */ var cellW = dst.getWidth() / (gridWidth - 1); 397 /** @type {number} */ var cellH = dst.getHeight() / (gridHeight - 1); 398 399 for (var y = 0; y < dst.getHeight(); y++) { 400 for (var x = 0; x < dst.getWidth(); x++) { 401 /** @type {number} */ var cellX = deMath.clamp(Math.floor(x / cellW), 0, gridWidth - 2); 402 /** @type {number} */ var cellY = deMath.clamp(Math.floor(y / cellH), 0, gridHeight - 2); 403 /** @type {Array<number>} */ var c = es3fFragmentOutputTests.readIVec4(vertices, (cellY * gridWidth + cellX + 1) * numComponents, numComponents); // IVec4 404 405 dst.setPixelInt(c, x, y); 406 } 407 } 408 }; 409 410 /** 411 * es3fFragmentOutputTests.s_swizzles 412 * @return {Array<Array<number>>} 413 */ 414 es3fFragmentOutputTests.s_swizzles = function() { 415 var mat_swizzles = [ 416 [0, 1, 2, 3], 417 [1, 2, 3, 0], 418 [2, 3, 0, 1], 419 [3, 0, 1, 2], 420 [3, 2, 1, 0], 421 [2, 1, 0, 3], 422 [1, 0, 3, 2], 423 [0, 3, 2, 1] 424 ]; 425 426 return mat_swizzles; 427 }; 428 429 /** 430 * es3fFragmentOutputTests.swizzleVec. Returns an Array from a position contained in the Array es3fFragmentOutputTests.s_swizzles [] 431 * @param {Array<number>} vec 432 * @param {number} swzNdx 433 * @return {Array<number>} Swizzled array 434 */ 435 es3fFragmentOutputTests.swizzleVec = function(vec, swzNdx) { 436 /** @type {Array<number>} */ var swz = es3fFragmentOutputTests.s_swizzles()[swzNdx % es3fFragmentOutputTests.s_swizzles().length]; 437 438 return deMath.swizzle(vec, swz); 439 }; 440 441 /** 442 * es3fFragmentOutputTests.AttachmentData struct class 443 * @constructor 444 * @return {Object} 445 */ 446 es3fFragmentOutputTests.AttachmentData = function() { 447 return { 448 /** @type {tcuTexture.TextureFormat} */ format: null, //!< Actual format of attachment. 449 /** @type {tcuTexture.TextureFormat} */ referenceFormat: null, //!< Used for reference rendering. 450 /** @type {tcuTexture.TextureFormat} */ readFormat: null, 451 /** @type {number} */ numWrittenChannels: 0, 452 /** @type {gluShaderUtil.precision} */ outPrecision: gluShaderUtil.precision.PRECISION_LOWP, 453 /** @type {ArrayBuffer} */ renderedData: null, 454 /** @type {ArrayBuffer} */ referenceData: null 455 }; 456 }; 457 458 es3fFragmentOutputTests.FragmentOutputCase.prototype.iterate = function() { 459 // Compute grid size & index list. 460 /** @type {number} */ var minCellSize = 8; 461 /** @type {Array<number>} */ var minBufSize = es3fFragmentOutputTests.getMinSize(this.m_fboSpec); // IVec2 462 /** @type {number} */ var gridWidth = deMath.clamp(Math.floor(minBufSize[0] / minCellSize), 1, 255) + 1; 463 /** @type {number} */ var gridHeight = deMath.clamp(Math.floor(minBufSize[1] / minCellSize), 1, 255) + 1; 464 /** @type {number} */ var numVertices = gridWidth * gridHeight; 465 /** @type {number} */ var numQuads = (gridWidth - 1) * (gridHeight - 1); 466 /** @type {number} */ var numIndices = numQuads * 6; 467 468 /** @type {number} */ var numInputVecs = es3fFragmentOutputTests.getNumInputVectors(this.m_outputs); 469 /** @type {Array<Array<number>>} */ var inputs = []; // originally vector<vector<deUint32> 470 471 for (var inputNdx = 0; inputNdx < numInputVecs; inputNdx++) 472 inputs[inputNdx] = []; // inputs.length = numInputVecs; 473 474 /** @type {Array<number>} */ var positions = []; // originally vector<float> 475 /** @type {Array<number>} */ var indices = []; // originally vector<deUint16> 476 477 /** @type {number} */ var readAlignment = 4; 478 /** @type {number} */ var viewportW = minBufSize[0]; 479 /** @type {number} */ var viewportH = minBufSize[1]; 480 /** @type {number} */ var numAttachments = this.m_fboSpec.length; 481 482 /** @type {Array<number>} */ var drawBuffers = []; // originally vector<deUint32> 483 /** @type {Array<es3fFragmentOutputTests.AttachmentData>} */ var attachments = []; 484 /** @type {number} */ var attachmentW; 485 /** @type {number} */ var attachmentH; 486 487 // Initialize attachment data. 488 for (var ndx = 0; ndx < numAttachments; ndx++) { 489 /** @type {tcuTexture.TextureFormat} */ var texFmt = gluTextureUtil.mapGLInternalFormat(this.m_fboSpec[ndx].format); 490 /** @type {tcuTexture.TextureChannelClass} */ var chnClass = tcuTexture.getTextureChannelClass(texFmt.type); 491 /** @type {boolean} */ var isFixedPoint = (chnClass == tcuTexture.TextureChannelClass.SIGNED_FIXED_POINT || 492 chnClass == tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT); 493 494 // \note Fixed-point formats use float reference to enable more accurate result verification. 495 /** @type {tcuTexture.TextureFormat} */ var refFmt = isFixedPoint ? new tcuTexture.TextureFormat(texFmt.order, tcuTexture.ChannelType.FLOAT) : texFmt; 496 /** @type {tcuTexture.TextureFormat} */ var readFmt = es3fFboTestUtil.getFramebufferReadFormat(texFmt); 497 attachmentW = this.m_fboSpec[ndx].width; 498 attachmentH = this.m_fboSpec[ndx].height; 499 500 drawBuffers[ndx] = gl.COLOR_ATTACHMENT0 + ndx; 501 attachments[ndx] = new es3fFragmentOutputTests.AttachmentData(); 502 attachments[ndx].format = texFmt; 503 attachments[ndx].readFormat = readFmt; 504 attachments[ndx].referenceFormat = refFmt; 505 attachments[ndx].renderedData = new ArrayBuffer(readFmt.getPixelSize() * attachmentW * attachmentH); 506 attachments[ndx].referenceData = new ArrayBuffer(refFmt.getPixelSize() * attachmentW * attachmentH); 507 } 508 509 // Initialize indices. 510 for (var quadNdx = 0; quadNdx < numQuads; quadNdx++) { 511 /** @type {number} */ var quadY = Math.floor(quadNdx / (gridWidth - 1)); 512 /** @type {number} */ var quadX = quadNdx - quadY * (gridWidth - 1); 513 514 indices[quadNdx * 6 + 0] = quadX + quadY * gridWidth; 515 indices[quadNdx * 6 + 1] = quadX + (quadY + 1) * gridWidth; 516 indices[quadNdx * 6 + 2] = quadX + quadY * gridWidth + 1; 517 indices[quadNdx * 6 + 3] = indices[quadNdx * 6 + 1]; 518 indices[quadNdx * 6 + 4] = quadX + (quadY + 1) * gridWidth + 1; 519 indices[quadNdx * 6 + 5] = indices[quadNdx * 6 + 2]; 520 } 521 522 /** @type {number} */ var xf = 0; 523 /** @type {number} */ var yf = 0; 524 for (var y = 0; y < gridHeight; y++) { 525 for (var x = 0; x < gridWidth; x++) { 526 xf = x / (gridWidth - 1); 527 yf = y / (gridHeight - 1); 528 529 positions[(y * gridWidth + x) * 4 + 0] = 2.0 * xf - 1.0; 530 positions[(y * gridWidth + x) * 4 + 1] = 2.0 * yf - 1.0; 531 positions[(y * gridWidth + x) * 4 + 2] = 0.0; 532 positions[(y * gridWidth + x) * 4 + 3] = 1.0; 533 } 534 } 535 /** @type {es3fFragmentOutputTests.FragmentOutput} */ var output; 536 /** @type {boolean} */ var isArray; 537 /** @type {boolean} */ var isFloat; 538 /** @type {boolean} */ var isInt; 539 /** @type {boolean} */ var isUint; 540 /** @type {number} */ var numVecs; 541 /** @type {number} */ var numScalars; 542 543 var curInVec = 0; 544 for (var outputNdx = 0; outputNdx < this.m_outputs.length; outputNdx++) { 545 output = this.m_outputs[outputNdx]; 546 isFloat = gluShaderUtil.isDataTypeFloatOrVec(output.type); 547 isInt = gluShaderUtil.isDataTypeIntOrIVec(output.type); 548 isUint = gluShaderUtil.isDataTypeUintOrUVec(output.type); 549 numVecs = output.arrayLength > 0 ? output.arrayLength : 1; 550 numScalars = gluShaderUtil.getDataTypeScalarSize(output.type); 551 552 for (var vecNdx = 0; vecNdx < numVecs; vecNdx++) { 553 inputs[curInVec].length = numVertices * numScalars; 554 555 // Record how many outputs are written in attachment. 556 DE_ASSERT(output.location + vecNdx < attachments.length); 557 attachments[output.location + vecNdx].numWrittenChannels = numScalars; 558 attachments[output.location + vecNdx].outPrecision = output.precision; 559 560 /** @type {Array<number>} */ var range = null; 561 /** @type {Array<number>} */ var minVal = null; 562 /** @type {Array<number>} */ var maxVal = null; 563 /** @type {Array<number>} */ var fmtBits = null; 564 /** @type {Array<number>} */ var fmtMaxVal = []; 565 /** @type {Array<number>} */ var rangeDiv = null; 566 /** @type {Array<number>} */ var step = []; 567 /** @type {number} */ var ix = 0; 568 /** @type {number} */ var iy = 0; 569 /** @type {Array<number>} */ var c = null; 570 /** @type {number} */ var pos = 0; 571 if (isFloat) { 572 range = es3fFragmentOutputTests.getFloatRange(output.precision); // Vec2 573 minVal = [range[0], range[0], range[0], range[0]]; // Vec4 574 maxVal = [range[1], range[1], range[1], range[1]]; // Vec4 575 576 if (deMath.deInBounds32(output.location + vecNdx, 0, attachments.length)) { 577 // \note Floating-point precision conversion is not well-defined. For that reason we must 578 // limit value range to intersection of both data type and render target value ranges. 579 /** @type {tcuTextureUtil.TextureFormatInfo} */ var fmtInfo = tcuTextureUtil.getTextureFormatInfo(attachments[output.location + vecNdx].format); 580 minVal = deMath.max(minVal, fmtInfo.valueMin); 581 maxVal = deMath.min(maxVal, fmtInfo.valueMax); 582 } 583 584 bufferedLogToConsole('out ' + curInVec + ' value range: ' + minVal + ' -> ' + maxVal); 585 586 for (var y = 0; y < gridHeight; y++) { 587 for (var x = 0; x < gridWidth; x++) { 588 xf = x / (gridWidth - 1); 589 yf = y / (gridHeight - 1); 590 /** @type {number} */ var f0 = (xf + yf) * 0.5; 591 /** @type {number} */ var f1 = 0.5 + (xf - yf) * 0.5; 592 593 /** @type {Array<number>} */ var f = es3fFragmentOutputTests.swizzleVec([f0, f1, 1.0 - f0, 1.0 - f1], curInVec); // Vec4 594 c = deMath.add(minVal, deMath.multiply(deMath.subtract(maxVal, minVal), f)); // Vec4 595 596 pos = (y * gridWidth + x) * numScalars; 597 598 for (var ndx = 0; ndx < numScalars; ndx++) 599 inputs[curInVec][pos + ndx] = c[ndx]; 600 } 601 } 602 } else if (isInt) { 603 range = es3fFragmentOutputTests.getIntRange(output.precision); // IVec2 604 minVal = [range[0], range[0], range[0], range[0]]; // IVec4 605 maxVal = [range[1], range[1], range[1], range[1]]; // IVec4 606 607 if (deMath.deInBounds32(output.location + vecNdx, 0, attachments.length)) { 608 // Limit to range of output format as conversion mode is not specified. 609 fmtBits = tcuTextureUtil.getTextureFormatBitDepth(attachments[output.location + vecNdx].format); // IVec4 610 /** @type {Array<boolean>} */ var isZero = deMath.lessThanEqual(fmtBits, [0, 0, 0, 0]); // BVec4, array of booleans, size = 4 611 612 /** @type {Array<number>} */ var fmtMinVal = []; // IVec4 613 614 for (var i = 0; i < 4; i++) { 615 616 // const IVec4 fmtMinVal = (-(tcu::Vector<deInt64, 4>(1) << (fmtBits - 1 ).cast<deInt64>())).asInt(); 617 fmtMinVal[i] = -1 * Math.pow(2, fmtBits[i] - 1); // TODO: check implementation, original above 618 // const IVec4 fmtMaxVal = ((tcu::Vector<deInt64, 4>(1) << (fmtBits - 1 ).cast<deInt64>()) - deInt64(1)).asInt(); 619 fmtMaxVal[i] = Math.pow(2, fmtBits[i] - 1) - 1; // TODO: check implementation, original above 620 } 621 622 minVal = tcuTextureUtil.select(minVal, deMath.max(minVal, fmtMinVal), isZero); 623 maxVal = tcuTextureUtil.select(maxVal, deMath.min(maxVal, fmtMaxVal), isZero); 624 } 625 626 bufferedLogToConsole('out ' + curInVec + ' value range: ' + minVal + ' -> ' + maxVal); 627 628 rangeDiv = es3fFragmentOutputTests.swizzleVec([gridWidth - 1, gridHeight - 1, gridWidth - 1, gridHeight - 1], curInVec); // IVec4 629 for (var i = 0; i < 4; i++) { 630 // const IVec4 step = ((maxVal.cast<deInt64>() - minVal.cast<deInt64>()) / (rangeDiv.cast<deInt64>())).asInt(); 631 step[i] = Math.floor((maxVal[i] - minVal[i]) / rangeDiv[i]); // TODO: check with the above line of code 632 } 633 634 for (var y = 0; y < gridHeight; y++) { 635 for (var x = 0; x < gridWidth; x++) { 636 ix = gridWidth - x - 1; 637 iy = gridHeight - y - 1; 638 c = deMath.add(minVal, deMath.multiply(step, es3fFragmentOutputTests.swizzleVec([x, y, ix, iy], curInVec))); // IVec4 639 640 pos = (y * gridWidth + x) * numScalars; 641 642 for (var ndx = 0; ndx < numScalars; ndx++) 643 inputs[curInVec][pos + ndx] = c[ndx]; 644 } 645 } 646 } else if (isUint) { 647 range = es3fFragmentOutputTests.getUintRange(output.precision); // UVec2 648 maxVal = [range[1], range[1], range[1], range[1]]; // UVec4 649 650 if (deMath.deInBounds32(output.location + vecNdx, 0, attachments.length)) { 651 // Limit to range of output format as conversion mode is not specified. 652 fmtBits = tcuTextureUtil.getTextureFormatBitDepth(attachments[output.location + vecNdx].format); // IVec4 653 654 for (var i = 0; i < 4; i++) { 655 fmtMaxVal[i] = Math.pow(2, fmtBits[i]) - 1; 656 } 657 658 maxVal = deMath.min(maxVal, fmtMaxVal); 659 } 660 661 bufferedLogToConsole('out ' + curInVec + ' value range: ' + minVal + ' -> ' + maxVal); 662 663 rangeDiv = es3fFragmentOutputTests.swizzleVec([gridWidth - 1, gridHeight - 1, gridWidth - 1, gridHeight - 1], curInVec); // IVec4 664 665 for (var stepPos = 0; stepPos < maxVal.length; stepPos++) { 666 step[stepPos] = Math.floor(maxVal[stepPos] / rangeDiv[stepPos]); 667 } 668 669 DE_ASSERT(range[0] == 0); 670 671 for (var y = 0; y < gridHeight; y++) { 672 for (var x = 0; x < gridWidth; x++) { 673 ix = gridWidth - x - 1; 674 iy = gridHeight - y - 1; 675 c = deMath.multiply(step, es3fFragmentOutputTests.swizzleVec([x, y, ix, iy], curInVec)); // UVec4 676 pos = (y * gridWidth + x) * numScalars; 677 678 DE_ASSERT(deMath.boolAll(deMath.lessThanEqual(c, maxVal))); // TODO: sometimes crashes here, condition not asserted 679 680 for (var ndx = 0; ndx < numScalars; ndx++) 681 inputs[curInVec][pos + ndx] = c[ndx]; 682 } 683 } 684 } else 685 DE_ASSERT(false); 686 687 curInVec += 1; 688 } 689 } 690 691 // Render using gl. 692 gl.useProgram(this.m_program.getProgram()); 693 gl.bindFramebuffer(gl.FRAMEBUFFER, this.m_framebuffer); 694 gl.viewport(0, 0, viewportW, viewportH); 695 gl.drawBuffers(drawBuffers); 696 gl.disable(gl.DITHER); // Dithering causes issues with unorm formats. Those issues could be worked around in threshold, but it makes validation less accurate. 697 698 /** @type {WebGLBuffer} */ var buffer = null; 699 /** @type {string} */ var name; 700 curInVec = 0; 701 for (var outputNdx = 0; outputNdx < this.m_outputs.length; outputNdx++) { 702 output = this.m_outputs[outputNdx]; 703 isArray = output.arrayLength > 0; 704 isFloat = gluShaderUtil.isDataTypeFloatOrVec(output.type); 705 isInt = gluShaderUtil.isDataTypeIntOrIVec(output.type); 706 isUint = gluShaderUtil.isDataTypeUintOrUVec(output.type); 707 /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(output.type); 708 /** @type {number} */ var glScalarType = isFloat ? /* gluShaderUtil.DataType.FLOAT */ gl.FLOAT : 709 isInt ? /* gluShaderUtil.DataType.INT */ gl.INT : 710 isUint ? /* gluShaderUtil.DataType.UINT */ gl.UNSIGNED_INT : /* gluShaderUtil.DataType.INVALID */ gl.NONE; 711 numVecs = isArray ? output.arrayLength : 1; 712 713 for (var vecNdx = 0; vecNdx < numVecs; vecNdx++) { 714 name = 'in' + outputNdx + (isArray ? '_' + vecNdx : ''); 715 /** @type {number} */ var loc = gl.getAttribLocation(this.m_program.getProgram(), name); 716 717 if (loc >= 0) { 718 buffer = gl.createBuffer(); 719 gl.bindBuffer(gl.ARRAY_BUFFER, buffer); 720 721 gl.enableVertexAttribArray(loc); 722 if (isFloat) { 723 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(inputs[curInVec]), gl.STATIC_DRAW); 724 // KHRONOS WebGL 1.0 specification: 725 // void vertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLintptr offset); 726 gl.vertexAttribPointer(loc, scalarSize, glScalarType, false, 0, 0); // offset = 0 727 } else { 728 gl.bufferData(gl.ARRAY_BUFFER, new Int32Array(inputs[curInVec]), gl.STATIC_DRAW); 729 // KHRONOS WebGL 2.0 specification: 730 // void vertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset) 731 gl.vertexAttribIPointer(loc, scalarSize, glScalarType, 0, 0); // offset = 0 732 } 733 } else 734 bufferedLogToConsole('Warning: No location for attribute "' + name + '" found.'); 735 736 curInVec += 1; 737 } 738 } 739 740 /** @type {number} */ var posLoc = gl.getAttribLocation(this.m_program.getProgram(), 'a_position'); 741 // TCU_CHECK(posLoc >= 0); 742 buffer = gl.createBuffer(); 743 gl.bindBuffer(gl.ARRAY_BUFFER, buffer); 744 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW); 745 746 gl.enableVertexAttribArray(posLoc); 747 gl.vertexAttribPointer(posLoc, 4, gl.FLOAT, false, 0, 0); // offset = 0 748 749 /** @type {WebGLBuffer} */ var indexObject = gl.createBuffer(); 750 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexObject); 751 gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW); 752 753 gl.drawElements(gl.TRIANGLES, numIndices, gl.UNSIGNED_SHORT, 0); // offset = 0 754 755 // Render reference images. 756 757 var curInNdx = 0; 758 for (var outputNdx = 0; outputNdx < this.m_outputs.length; outputNdx++) { 759 output = this.m_outputs[outputNdx]; 760 isArray = output.arrayLength > 0; 761 isFloat = gluShaderUtil.isDataTypeFloatOrVec(output.type); 762 isInt = gluShaderUtil.isDataTypeIntOrIVec(output.type); 763 isUint = gluShaderUtil.isDataTypeUintOrUVec(output.type); 764 scalarSize = gluShaderUtil.getDataTypeScalarSize(output.type); 765 numVecs = isArray ? output.arrayLength : 1; 766 767 for (var vecNdx = 0; vecNdx < numVecs; vecNdx++) { 768 /** @type {number} */ var location = output.location + vecNdx; 769 /** @type {Array<number>} */ var inputData = inputs[curInNdx]; 770 771 DE_ASSERT(deMath.deInBounds32(location, 0, this.m_fboSpec.length)); 772 773 /** @type {number} */ var bufW = this.m_fboSpec[location].width; 774 /** @type {number} */ var bufH = this.m_fboSpec[location].height; 775 /** @type {Object} */ var descriptor = { 776 format: attachments[location].referenceFormat, 777 width: bufW, 778 height: bufH, 779 depth: 1, 780 data: attachments[location].referenceData // ArrayBuffer 781 }; 782 /** @type {tcuTexture.PixelBufferAccess} */ var buf = new tcuTexture.PixelBufferAccess(descriptor); 783 /** @type {tcuTexture.PixelBufferAccess} */ var viewportBuf = tcuTextureUtil.getSubregion(buf, 0, 0, 0, viewportW, viewportH, 1); 784 785 if (isInt || isUint) 786 es3fFragmentOutputTests.renderIntReference(viewportBuf, gridWidth, gridHeight, scalarSize, inputData); 787 else if (isFloat) 788 es3fFragmentOutputTests.renderFloatReference(viewportBuf, gridWidth, gridHeight, scalarSize, inputData); 789 else 790 DE_ASSERT(false); 791 792 curInNdx += 1; 793 } 794 } 795 796 // Compare all images. 797 /** @type {boolean} */ var allLevelsOk = true; 798 for (var attachNdx = 0; attachNdx < numAttachments; attachNdx++) { 799 attachmentW = this.m_fboSpec[attachNdx].width; 800 attachmentH = this.m_fboSpec[attachNdx].height; 801 /** @type {number} */ var numValidChannels = attachments[attachNdx].numWrittenChannels; 802 /** @type {Array<boolean>} */ var cmpMask = [numValidChannels >= 1, numValidChannels >= 2, numValidChannels >= 3, numValidChannels >= 4]; 803 /** @type {gluShaderUtil.precision} */ var outPrecision = attachments[attachNdx].outPrecision; 804 /** @type {tcuTexture.TextureFormat} */ var format = attachments[attachNdx].format; 805 /** @type {Object} */ 806 var renderedDescriptor = { 807 format: attachments[attachNdx].readFormat, 808 width: attachmentW, 809 height: attachmentH, 810 depth: 1, 811 rowPitch: deMath.deAlign32(attachments[attachNdx].readFormat.getPixelSize() * attachmentW, readAlignment), 812 slicePitch: 0, 813 data: attachments[attachNdx].renderedData // ArrayBuffer 814 }; 815 /** @type {tcuTexture.PixelBufferAccess} */ var rendered = new tcuTexture.PixelBufferAccess(renderedDescriptor); 816 /** @type {gluTextureUtil.TransferFormat} */ var transferFmt = gluTextureUtil.getTransferFormat(attachments[attachNdx].readFormat); 817 gl.readBuffer(gl.COLOR_ATTACHMENT0 + attachNdx); 818 gl.readPixels(0, 0, attachmentW, attachmentH, transferFmt.format, transferFmt.dataType, rendered.getDataPtr()); 819 820 /** @type {Object} */ 821 var referenceDescriptor = { 822 format: attachments[attachNdx].referenceFormat, 823 width: attachmentW, 824 height: attachmentH, 825 depth: 1, 826 data: attachments[attachNdx].referenceData // ArrayBuffer 827 }; 828 /** @type {tcuTexture.ConstPixelBufferAccess} */ var reference = new tcuTexture.ConstPixelBufferAccess(referenceDescriptor); 829 /** @type {tcuTexture.TextureChannelClass} */ var texClass = tcuTexture.getTextureChannelClass(format.type); 830 /** @type {boolean} */ var isOk = true; 831 name = 'Attachment ' + attachNdx; 832 /** @type {string} */ var desc = 'Color attachment ' + attachNdx; 833 /** @type {Array<number>} */ var threshold; 834 835 bufferedLogToConsole('Attachment ' + attachNdx + ': ' + numValidChannels + ' channels have defined values and used for comparison'); 836 837 switch (texClass) { 838 case tcuTexture.TextureChannelClass.FLOATING_POINT: { 839 /** @type {Array<number>} */ var formatThreshold = []; // UVec4 //!< Threshold computed based on format. 840 formatThreshold.length = 4; 841 /** @type {number} */ var precThreshold = 0; // deUint32 //!< Threshold computed based on output type precision 842 /** @type {Array<number>} */ var finalThreshold = []; // UVec4 843 finalThreshold.length = 4; 844 845 switch (format.type) { 846 case tcuTexture.ChannelType.FLOAT: 847 formatThreshold = [4, 4, 4, 4]; // UVec4 848 break; 849 case tcuTexture.ChannelType.HALF_FLOAT: 850 formatThreshold = [(1 << 13) + 4, (1 << 13) + 4, (1 << 13) + 4, (1 << 13) + 4]; // UVec4 851 break; 852 case tcuTexture.ChannelType.UNSIGNED_INT_11F_11F_10F_REV: 853 formatThreshold = [(1 << 17) + 4, (1 << 17) + 4, (1 << 18) + 4, 4]; // UVec4 854 break; 855 default: 856 DE_ASSERT(false); 857 break; 858 } 859 860 switch (outPrecision) { 861 case gluShaderUtil.precision.PRECISION_LOWP: 862 precThreshold = (1 << 21); 863 break; 864 case gluShaderUtil.precision.PRECISION_MEDIUMP: 865 precThreshold = (1 << 13); 866 break; 867 case gluShaderUtil.precision.PRECISION_HIGHP: 868 precThreshold = 0; 869 break; 870 default: 871 DE_ASSERT(false); 872 } 873 874 finalThreshold = tcuTextureUtil.select( 875 deMath.max(formatThreshold, [precThreshold, precThreshold, precThreshold, precThreshold]), 876 [0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff], // C++ version: UVec4(~0u) bitwise not, all bits in the integer will be flipped 877 cmpMask); 878 879 isOk = tcuImageCompare.floatUlpThresholdCompare(name, desc, reference, rendered, finalThreshold /*, tcu::COMPARE_LOG_RESULT*/); 880 break; 881 } 882 883 case tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT: { 884 // \note glReadPixels() allows only 8 bits to be read. This means that RGB10_A2 will loose some 885 // bits in the process and it must be taken into account when computing threshold. 886 /** @type {Array<number>} */ var bits = deMath.min([8, 8, 8, 8], tcuTextureUtil.getTextureFormatBitDepth(format)); // IVec4 887 888 /** @type {Array<number>} */ var baseThreshold = []; // Vec4 889 baseThreshold.length = 4; 890 for (var inc = 0; inc < baseThreshold.length; inc++) { 891 // TODO: check the operation below: baseThreshold = 1.0f / ((IVec4(1) << bits)-1).asFloat(); 892 baseThreshold[inc] = 1.0 / ((1 << bits[inc]) - 1); 893 } 894 895 threshold = tcuTextureUtil.select(baseThreshold, [2.0, 2.0, 2.0, 2.0], cmpMask); // Vec4 896 897 isOk = tcuImageCompare.floatThresholdCompare(name, desc, reference, rendered, threshold/*, tcu::COMPARE_LOG_RESULT*/); 898 break; 899 } 900 901 case tcuTexture.TextureChannelClass.SIGNED_INTEGER: 902 case tcuTexture.TextureChannelClass.UNSIGNED_INTEGER: { 903 // The C++ dEQP code uses ~0u but ~0 is -1 in Javascript 904 var UINT_MAX = Math.pow(2.0, 32.0) - 1; 905 threshold = tcuTextureUtil.select( 906 [0, 0, 0, 0], 907 [UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX], 908 cmpMask 909 ); // UVec4 910 isOk = tcuImageCompare.intThresholdCompare(name, desc, reference, rendered, threshold/*, tcu::COMPARE_LOG_RESULT*/); 911 break; 912 } 913 914 default: 915 testFailedOptions('Unsupported comparison', true); 916 break; 917 } 918 919 if (!isOk) 920 allLevelsOk = false; 921 } 922 923 if (numAttachments > 1) { 924 if (allLevelsOk) 925 testPassed('Image comparison passed for ' + numAttachments + ' attachments'); 926 else 927 testFailed('Image comparison failed for some of ' + numAttachments + ' attachments'); 928 } else { 929 if (allLevelsOk) 930 testPassed('Image comparison passed'); 931 else 932 testFailed('Image comparison failed'); 933 } 934 935 return tcuTestCase.IterateResult.STOP; 936 }; 937 938 /** 939 * es3fFragmentOutputTests.createRandomCase. Constructs the es3fFragmentOutputTests.createRandomCase, child class of es3fFragmentOutputTests.FragmentOutputCase 940 * @constructor 941 * @param {number} minRenderTargets 942 * @param {number} maxRenderTargets 943 * @param {number} seed 944 * @return {es3fFragmentOutputTests.FragmentOutputCase} The currently modified object 945 */ 946 es3fFragmentOutputTests.createRandomCase = function(minRenderTargets, maxRenderTargets, seed, colorBufferFloatSupported) { 947 948 /** @type {Array<gluShaderUtil.DataType>} */ 949 var outputTypes = [ 950 gluShaderUtil.DataType.FLOAT, 951 gluShaderUtil.DataType.FLOAT_VEC2, 952 gluShaderUtil.DataType.FLOAT_VEC3, 953 gluShaderUtil.DataType.FLOAT_VEC4, 954 gluShaderUtil.DataType.INT, 955 gluShaderUtil.DataType.INT_VEC2, 956 gluShaderUtil.DataType.INT_VEC3, 957 gluShaderUtil.DataType.INT_VEC4, 958 gluShaderUtil.DataType.UINT, 959 gluShaderUtil.DataType.UINT_VEC2, 960 gluShaderUtil.DataType.UINT_VEC3, 961 gluShaderUtil.DataType.UINT_VEC4 962 ]; 963 964 /** @type {Array<gluShaderUtil.precision>} */ 965 var precisions = [ 966 gluShaderUtil.precision.PRECISION_LOWP, 967 gluShaderUtil.precision.PRECISION_MEDIUMP, 968 gluShaderUtil.precision.PRECISION_HIGHP 969 ]; 970 971 /** @type {Array<WebGLRenderingContextBase.GLenum>} */ 972 var floatFormats = [ 973 gl.RGBA32F, 974 gl.RGBA16F, 975 gl.R11F_G11F_B10F, 976 gl.RG32F, 977 gl.RG16F, 978 gl.R32F, 979 gl.R16F, 980 gl.RGBA8, 981 gl.SRGB8_ALPHA8, 982 gl.RGB10_A2, 983 gl.RGBA4, 984 gl.RGB5_A1, 985 gl.RGB8, 986 gl.RGB565, 987 gl.RG8, 988 gl.R8 989 ]; 990 991 /** @type {Array<WebGLRenderingContextBase.GLenum>} */ 992 var colorBufferFloatFormats = [ 993 gl.RGBA32F, 994 gl.RGBA16F, 995 gl.R11F_G11F_B10F, 996 gl.RG32F, 997 gl.RG16F, 998 gl.R32F, 999 gl.R16F 1000 ]; 1001 1002 1003 /** @type {Array<WebGLRenderingContextBase.GLenum>} */ 1004 var intFormats = [ 1005 gl.RGBA32I, 1006 gl.RGBA16I, 1007 gl.RGBA8I, 1008 gl.RG32I, 1009 gl.RG16I, 1010 gl.RG8I, 1011 gl.R32I, 1012 gl.R16I, 1013 gl.R8I 1014 ]; 1015 1016 /** @type {Array<WebGLRenderingContextBase.GLenum>} */ 1017 var uintFormats = [ 1018 gl.RGBA32UI, 1019 gl.RGBA16UI, 1020 gl.RGBA8UI, 1021 gl.RGB10_A2UI, 1022 gl.RG32UI, 1023 gl.RG16UI, 1024 gl.RG8UI, 1025 gl.R32UI, 1026 gl.R16UI, 1027 gl.R8UI 1028 ]; 1029 1030 /** @type {deRandom.Random} */ var rnd = new deRandom.Random(seed); 1031 /** @type {Array<es3fFragmentOutputTests.FragmentOutput>} */ var outputs = []; 1032 /** @type {Array<es3fFragmentOutputTests.BufferSpec>} */ var targets = []; 1033 /** @type {Array<gluShaderUtil.DataType>} */ var outTypes = []; 1034 1035 /** @type {number} */ var numTargets = rnd.getInt(minRenderTargets, maxRenderTargets); 1036 /** @type {number} */ var width = 128; // \todo [2012-04-10 pyry] Separate randomized sizes per target? 1037 /** @type {number} */ var height = 64; 1038 /** @type {number} */ var samples = 0; 1039 1040 // Compute outputs. 1041 /** @type {number} */ var curLoc = 0; 1042 while (curLoc < numTargets) { 1043 /** @type {boolean} */ var useArray = rnd.getFloat() < 0.3; 1044 /** @type {number} */ var maxArrayLen = numTargets - curLoc; 1045 /** @type {number} */ var arrayLen = useArray ? rnd.getInt(1, maxArrayLen) : 0; 1046 /** @type {Array<gluShaderUtil.DataType>} */ var basicTypeArray = rnd.choose(outputTypes, undefined, 1); 1047 /** @type {gluShaderUtil.DataType} */ var basicType = basicTypeArray[0]; 1048 /** @type {Array<gluShaderUtil.precision>} */ var precisionArray = rnd.choose(precisions, undefined, 1); 1049 /** @type {gluShaderUtil.precision} */ var precision = precisionArray[0]; 1050 /** @type {number} */ var numLocations = useArray ? arrayLen : 1; 1051 1052 outputs.push(new es3fFragmentOutputTests.FragmentOutput(basicType, precision, curLoc, arrayLen)); 1053 1054 for (var ndx = 0; ndx < numLocations; ndx++) 1055 outTypes.push(basicType); 1056 1057 curLoc += numLocations; 1058 } 1059 DE_ASSERT(curLoc == numTargets); 1060 DE_ASSERT(outTypes.length == numTargets); 1061 1062 // Compute buffers. 1063 while (targets.length < numTargets) { 1064 /** @type {gluShaderUtil.DataType} */ var outType = outTypes[targets.length]; 1065 /** @type {boolean} */ var isFloat = gluShaderUtil.isDataTypeFloatOrVec(outType); 1066 /** @type {boolean} */ var isInt = gluShaderUtil.isDataTypeIntOrIVec(outType); 1067 /** @type {boolean} */ var isUint = gluShaderUtil.isDataTypeUintOrUVec(outType); 1068 /** @type {Array} */ var formatArray = []; 1069 /** @type {number} */ var format = 0; 1070 1071 if (isFloat) { 1072 formatArray = rnd.choose(floatFormats, undefined, 1); 1073 format = formatArray[0]; 1074 if (colorBufferFloatFormats.indexOf(format) >= 0 && !colorBufferFloatSupported) 1075 return null; 1076 } else if (isInt) { 1077 formatArray = rnd.choose(intFormats, undefined, 1); 1078 format = formatArray[0]; 1079 } else if (isUint) { 1080 formatArray = rnd.choose(uintFormats, undefined, 1); 1081 format = formatArray[0]; 1082 } else 1083 DE_ASSERT(false); 1084 1085 targets.push(new es3fFragmentOutputTests.BufferSpec(format, width, height, samples)); 1086 } 1087 1088 return new es3fFragmentOutputTests.FragmentOutputCase(seed.toString(), '', targets, outputs); 1089 1090 }; 1091 1092 es3fFragmentOutputTests.init = function(gl) { 1093 var state = tcuTestCase.runner; 1094 state.testCases = tcuTestCase.newTest('fragment_outputs', 'Top level'); 1095 /** @const @type {tcuTestCase.DeqpTest} */ var testGroup = state.testCases; 1096 1097 /** @type {Array<WebGLRenderingContextBase.GLenum>} */ 1098 var requiredFloatFormats = [ 1099 gl.RGBA32F, 1100 gl.RGBA16F, 1101 gl.R11F_G11F_B10F, 1102 gl.RG32F, 1103 gl.RG16F, 1104 gl.R32F, 1105 gl.R16F 1106 ]; 1107 1108 /** @type {Array<WebGLRenderingContextBase.GLenum>} */ 1109 var requiredFixedFormats = [ 1110 gl.RGBA8, 1111 gl.SRGB8_ALPHA8, 1112 gl.RGB10_A2, 1113 gl.RGBA4, 1114 gl.RGB5_A1, 1115 gl.RGB8, 1116 gl.RGB565, 1117 gl.RG8, 1118 gl.R8 1119 ]; 1120 1121 /** @type {Array<WebGLRenderingContextBase.GLenum>} */ 1122 var requiredIntFormats = [ 1123 gl.RGBA32I, 1124 gl.RGBA16I, 1125 gl.RGBA8I, 1126 gl.RG32I, 1127 gl.RG16I, 1128 gl.RG8I, 1129 gl.R32I, 1130 gl.R16I, 1131 gl.R8I 1132 ]; 1133 1134 /** @type {Array<WebGLRenderingContextBase.GLenum>} */ 1135 var requiredUintFormats = [ 1136 gl.RGBA32UI, 1137 gl.RGBA16UI, 1138 gl.RGBA8UI, 1139 gl.RGB10_A2UI, 1140 gl.RG32UI, 1141 gl.RG16UI, 1142 gl.RG8UI, 1143 gl.R32UI, 1144 gl.R16UI, 1145 gl.R8UI 1146 ]; 1147 1148 /** @type {Array<gluShaderUtil.precision>} */ 1149 var precisions = [ 1150 1151 gluShaderUtil.precision.PRECISION_LOWP, 1152 gluShaderUtil.precision.PRECISION_MEDIUMP, 1153 gluShaderUtil.precision.PRECISION_HIGHP 1154 1155 ]; 1156 1157 // .basic. 1158 1159 /** @const @type {number} */ var width = 64; 1160 /** @const @type {number} */ var height = 64; 1161 /** @const @type {number} */ var samples = 0; 1162 /** @type {Array<es3fFragmentOutputTests.BufferSpec>} */ var fboSpec = null; 1163 /** @type {gluShaderUtil.precision} */ var prec; 1164 /** @type {string} */ var precName; 1165 1166 // .float 1167 if (gl.getExtension('EXT_color_buffer_float')) { 1168 /** @type {tcuTestCase.DeqpTest} */ var floatGroup = tcuTestCase.newTest('basic.float', 'Floating-point output tests'); 1169 testGroup.addChild(floatGroup); 1170 1171 for (var fmtNdx = 0; fmtNdx < requiredFloatFormats.length; fmtNdx++) { 1172 var format = requiredFloatFormats[fmtNdx]; 1173 var fmtName = es3fFboTestUtil.getFormatName(format); 1174 fboSpec = []; 1175 1176 fboSpec.push(new es3fFragmentOutputTests.BufferSpec(format, width, height, samples)); 1177 1178 for (var precNdx = 0; precNdx < precisions.length; precNdx++) { 1179 prec = precisions[precNdx]; 1180 precName = gluShaderUtil.getPrecisionName(prec); 1181 1182 // NOTE: Eliminated original OutputVec and toVec(), as it only returned an element of the outputs array in OutputVec 1183 floatGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_float', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.FLOAT, prec, 0)])); 1184 floatGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_vec2', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.FLOAT_VEC2, prec, 0)])); 1185 floatGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_vec3', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.FLOAT_VEC3, prec, 0)])); 1186 floatGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_vec4', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.FLOAT_VEC4, prec, 0)])); 1187 } 1188 } 1189 } 1190 1191 // .fixed 1192 /** @type {tcuTestCase.DeqpTest} */ var fixedGroup = tcuTestCase.newTest('basic.fixed', 'Fixed-point output tests'); 1193 testGroup.addChild(fixedGroup); 1194 for (var fmtNdx = 0; fmtNdx < requiredFixedFormats.length; fmtNdx++) { 1195 var format = requiredFixedFormats[fmtNdx]; 1196 var fmtName = es3fFboTestUtil.getFormatName(format); 1197 fboSpec = []; 1198 1199 fboSpec.push(new es3fFragmentOutputTests.BufferSpec(format, width, height, samples)); 1200 1201 for (var precNdx = 0; precNdx < precisions.length; precNdx++) { 1202 prec = precisions[precNdx]; 1203 precName = gluShaderUtil.getPrecisionName(prec); 1204 1205 fixedGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_float', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.FLOAT, prec, 0)])); 1206 fixedGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_vec2', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.FLOAT_VEC2, prec, 0)])); 1207 fixedGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_vec3', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.FLOAT_VEC3, prec, 0)])); 1208 fixedGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_vec4', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.FLOAT_VEC4, prec, 0)])); 1209 } 1210 } 1211 1212 // .int 1213 /** @type {tcuTestCase.DeqpTest} */ var intGroup = tcuTestCase.newTest('basic.int', 'Integer output tests'); 1214 testGroup.addChild(intGroup); 1215 for (var fmtNdx = 0; fmtNdx < requiredIntFormats.length; fmtNdx++) { 1216 var format = requiredIntFormats[fmtNdx]; 1217 var fmtName = es3fFboTestUtil.getFormatName(format); 1218 fboSpec = []; 1219 1220 fboSpec.push(new es3fFragmentOutputTests.BufferSpec(format, width, height, samples)); 1221 1222 for (var precNdx = 0; precNdx < precisions.length; precNdx++) { 1223 prec = precisions[precNdx]; 1224 precName = gluShaderUtil.getPrecisionName(prec); 1225 1226 intGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_int', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.INT, prec, 0)])); 1227 intGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_ivec2', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.INT_VEC2, prec, 0)])); 1228 intGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_ivec3', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.INT_VEC3, prec, 0)])); 1229 intGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_ivec4', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.INT_VEC4, prec, 0)])); 1230 } 1231 } 1232 1233 // .uint 1234 /** @type {tcuTestCase.DeqpTest} */ var uintGroup = tcuTestCase.newTest('basic.uint', 'Usigned integer output tests'); 1235 testGroup.addChild(uintGroup); 1236 for (var fmtNdx = 0; fmtNdx < requiredUintFormats.length; fmtNdx++) { 1237 var format = requiredUintFormats[fmtNdx]; 1238 var fmtName = es3fFboTestUtil.getFormatName(format); 1239 fboSpec = []; 1240 1241 fboSpec.push(new es3fFragmentOutputTests.BufferSpec(format, width, height, samples)); 1242 1243 for (var precNdx = 0; precNdx < precisions.length; precNdx++) { 1244 prec = precisions[precNdx]; 1245 precName = gluShaderUtil.getPrecisionName(prec); 1246 1247 uintGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_uint', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.UINT, prec, 0)])); 1248 uintGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_uvec2', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.UINT_VEC2, prec, 0)])); 1249 uintGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_uvec3', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.UINT_VEC3, prec, 0)])); 1250 uintGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_uvec4', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.UINT_VEC4, prec, 0)])); 1251 1252 } 1253 } 1254 1255 // .array 1256 1257 /** @type {number} */ var numTargets = 3; 1258 1259 // .float 1260 if (gl.getExtension('EXT_color_buffer_float')) { 1261 /** @type {tcuTestCase.DeqpTest} */ var arrayFloatGroup = tcuTestCase.newTest('array.float', 'Floating-point output tests'); 1262 testGroup.addChild(arrayFloatGroup); 1263 for (var fmtNdx = 0; fmtNdx < requiredFloatFormats.length; fmtNdx++) { 1264 var format = requiredFloatFormats[fmtNdx]; 1265 var fmtName = es3fFboTestUtil.getFormatName(format); 1266 fboSpec = []; 1267 1268 for (var ndx = 0; ndx < numTargets; ndx++) 1269 fboSpec.push(new es3fFragmentOutputTests.BufferSpec(format, width, height, samples)); 1270 1271 for (var precNdx = 0; precNdx < precisions.length; precNdx++) { 1272 prec = precisions[precNdx]; 1273 precName = gluShaderUtil.getPrecisionName(prec); 1274 1275 arrayFloatGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_float', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.FLOAT, prec, 0, numTargets)])); 1276 arrayFloatGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_vec2', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.FLOAT_VEC2, prec, 0, numTargets)])); 1277 arrayFloatGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_vec3', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.FLOAT_VEC3, prec, 0, numTargets)])); 1278 arrayFloatGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_vec4', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.FLOAT_VEC4, prec, 0, numTargets)])); 1279 } 1280 } 1281 } 1282 1283 // .fixed 1284 /** @type {tcuTestCase.DeqpTest} */ var arrayFixedGroup = tcuTestCase.newTest('array.fixed', 'Fixed-point output tests'); 1285 testGroup.addChild(arrayFixedGroup); 1286 for (var fmtNdx = 0; fmtNdx < requiredFixedFormats.length; fmtNdx++) { 1287 var format = requiredFixedFormats[fmtNdx]; 1288 var fmtName = es3fFboTestUtil.getFormatName(format); 1289 fboSpec = []; 1290 1291 for (var ndx = 0; ndx < numTargets; ndx++) 1292 fboSpec.push(new es3fFragmentOutputTests.BufferSpec(format, width, height, samples)); 1293 1294 for (var precNdx = 0; precNdx < precisions.length; precNdx++) { 1295 prec = precisions[precNdx]; 1296 precName = gluShaderUtil.getPrecisionName(prec); 1297 1298 arrayFixedGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_float', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.FLOAT, prec, 0, numTargets)])); 1299 arrayFixedGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_vec2', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.FLOAT_VEC2, prec, 0, numTargets)])); 1300 arrayFixedGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_vec3', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.FLOAT_VEC3, prec, 0, numTargets)])); 1301 arrayFixedGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_vec4', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.FLOAT_VEC4, prec, 0, numTargets)])); 1302 } 1303 } 1304 1305 // .int 1306 /** @type {tcuTestCase.DeqpTest} */ var arrayIntGroup = tcuTestCase.newTest('array.int', 'Integer output tests'); 1307 testGroup.addChild(arrayIntGroup); 1308 for (var fmtNdx = 0; fmtNdx < requiredIntFormats.length; fmtNdx++) { 1309 var format = requiredIntFormats[fmtNdx]; 1310 var fmtName = es3fFboTestUtil.getFormatName(format); 1311 fboSpec = []; 1312 1313 for (var ndx = 0; ndx < numTargets; ndx++) 1314 fboSpec.push(new es3fFragmentOutputTests.BufferSpec(format, width, height, samples)); 1315 1316 for (var precNdx = 0; precNdx < precisions.length; precNdx++) { 1317 prec = precisions[precNdx]; 1318 precName = gluShaderUtil.getPrecisionName(prec); 1319 1320 arrayIntGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_int', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.INT, prec, 0, numTargets)])); 1321 arrayIntGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_ivec2', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.INT_VEC2, prec, 0, numTargets)])); 1322 arrayIntGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_ivec3', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.INT_VEC3, prec, 0, numTargets)])); 1323 arrayIntGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_ivec4', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.INT_VEC4, prec, 0, numTargets)])); 1324 } 1325 } 1326 1327 // .uint 1328 /** @type {tcuTestCase.DeqpTest} */ var arrayUintGroup = tcuTestCase.newTest('array.uint', 'Usigned integer output tests'); 1329 testGroup.addChild(arrayUintGroup); 1330 for (var fmtNdx = 0; fmtNdx < requiredUintFormats.length; fmtNdx++) { 1331 var format = requiredUintFormats[fmtNdx]; 1332 var fmtName = es3fFboTestUtil.getFormatName(format); 1333 fboSpec = []; 1334 1335 for (var ndx = 0; ndx < numTargets; ndx++) 1336 fboSpec.push(new es3fFragmentOutputTests.BufferSpec(format, width, height, samples)); 1337 1338 for (var precNdx = 0; precNdx < precisions.length; precNdx++) { 1339 prec = precisions[precNdx]; 1340 precName = gluShaderUtil.getPrecisionName(prec); 1341 1342 arrayUintGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_uint', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.UINT, prec, 0, numTargets)])); 1343 arrayUintGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_uvec2', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.UINT_VEC2, prec, 0, numTargets)])); 1344 arrayUintGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_uvec3', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.UINT_VEC3, prec, 0, numTargets)])); 1345 arrayUintGroup.addChild(new es3fFragmentOutputTests.FragmentOutputCase(fmtName + '_' + precName + '_uvec4', '', fboSpec, [new es3fFragmentOutputTests.FragmentOutput(gluShaderUtil.DataType.UINT_VEC4, prec, 0, numTargets)])); 1346 } 1347 } 1348 1349 // .random 1350 1351 /** @type {Array<tcuTestCase.DeqpTest>} */ var randomGroup = []; 1352 var numRandomGroups = 3; 1353 for (var ii = 0; ii < numRandomGroups; ++ii) { 1354 randomGroup[ii] = tcuTestCase.newTest('random', 'Random fragment output cases'); 1355 testGroup.addChild(randomGroup[ii]); 1356 } 1357 1358 /** @type {boolean} */ var colorBufferFloatSupported = (gl.getExtension('EXT_color_buffer_float') != null); 1359 for (var seed = 0; seed < 100; seed++) { 1360 var test = es3fFragmentOutputTests.createRandomCase(2, 4, seed, colorBufferFloatSupported); 1361 if (test !== null) { 1362 randomGroup[seed % numRandomGroups].addChild(test); 1363 } 1364 } 1365 1366 }; 1367 1368 /** 1369 * Create and execute the test cases 1370 */ 1371 es3fFragmentOutputTests.run = function(context, range) { 1372 gl = context; 1373 //Set up Test Root parameters 1374 var testName = 'fragment_output'; 1375 var testDescription = 'Fragment Output Tests'; 1376 var state = tcuTestCase.runner; 1377 1378 state.testName = testName; 1379 state.testCases = tcuTestCase.newTest(testName, testDescription, null); 1380 1381 //Set up name and description of this test series. 1382 setCurrentTestName(testName); 1383 description(testDescription); 1384 1385 try { 1386 es3fFragmentOutputTests.init(gl); 1387 if (range) 1388 state.setRange(range); 1389 tcuTestCase.runTestCases(); 1390 } catch (err) { 1391 testFailedOptions('Failed to es3fFragmentOutputTests.run tests', false); 1392 bufferedLogToConsole(err); 1393 tcuTestCase.runner.terminate(); 1394 } 1395 1396 }; 1397 1398 });