Source code

Revision control

Copy as Markdown

Other Tools

<!--
Copyright (c) 2019 The Khronos Group Inc.
Use of this source code is governed by an MIT-style license that can be
found in the LICENSE.txt file.
-->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>WebGL uniform array Conformance Tests</title>
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
<script src="../../js/js-test-pre.js"></script>
<script src="../../js/webgl-test-utils.js"></script>
</head>
<body>
<div id="description"></div>
<div id="console"></div>
<canvas id="example" width="2" height="2"> </canvas>
<script id="vshader" type="x-shader/x-vertex">#version 300 es
in vec4 a_position;
void main() {
gl_Position = a_position;
}
</script>
<script id="fshader" type="x-shader/x-fragment">#version 300 es
precision mediump float;
uniform $(type) color[3];
out vec4 myFragColor;
void main() {
myFragColor = vec4(color[0]$(elem), color[1]$(elem), color[2]$(elem), 1);
}
</script>
<script>
"use strict";
description();
debug("");
var wtu = WebGLTestUtils;
var gl = wtu.create3DContext("example", undefined, 2);
var vSrc = wtu.getScript("vshader");
var fTemplate = wtu.getScript("fshader");
// |color| is defined in fragment shader as an array of 3 elements.
var uniformArraySize = 3;
var initialUniformValue = 99;
var typeInfos = [
{ type: 'float',
setter: 'uniform1fv',
elem: '',
numElementsPerType: 1,
srcValues: [16, 15],
srcValuesWithOffset: [0, 0, 16, 15],
srcValuesWithOffsetAndLength: [0, 0, 16, 15, 0],
srcOffset: 2,
},
{ type: 'int',
setter: 'uniform1iv',
elem: '',
numElementsPerType: 1,
srcValues: [16, 15],
srcValuesWithOffset: [0, 0, 16, 15],
srcValuesWithOffsetAndLength: [0, 0, 16, 15, 0],
srcOffset: 2,
},
{ type: 'uint',
setter: 'uniform1uiv',
elem: '',
numElementsPerType: 1,
srcValues: [16, 15],
srcValuesWithOffset: [0, 0, 16, 15],
srcValuesWithOffsetAndLength: [0, 0, 16, 15, 0],
srcOffset: 2,
},
{ type: 'vec2',
setter: 'uniform2fv',
elem: '[1]',
numElementsPerType: 2,
srcValues: [16, 15, 14, 13],
srcValuesWithOffset: [0, 16, 15, 14, 13],
srcValuesWithOffsetAndLength: [0, 16, 15, 14, 13, 0],
srcOffset: 1,
},
{ type: 'ivec2',
setter: 'uniform2iv',
elem: '[1]',
numElementsPerType: 2,
srcValues: [16, 15, 14, 13],
srcValuesWithOffset: [0, 16, 15, 14, 13],
srcValuesWithOffsetAndLength: [0, 16, 15, 14, 13, 0],
srcOffset: 1,
},
{ type: 'uvec2',
setter: 'uniform2uiv',
elem: '[1]',
numElementsPerType: 2,
srcValues: [16, 15, 14, 13],
srcValuesWithOffset: [0, 16, 15, 14, 13],
srcValuesWithOffsetAndLength: [0, 16, 15, 14, 13, 0],
srcOffset: 1,
},
{ type: 'vec3',
setter: 'uniform3fv',
elem: '[2]',
numElementsPerType: 3,
srcValues: [16, 15, 14, 13, 12, 11],
srcValuesWithOffset: [0, 16, 15, 14, 13, 12, 11],
srcValuesWithOffsetAndLength: [0, 16, 15, 14, 13, 12, 11, 0, 0],
srcOffset: 1,
},
{ type: 'ivec3',
setter: 'uniform3iv',
elem: '[2]',
numElementsPerType: 3,
srcValues: [16, 15, 14, 13, 12, 11],
srcValuesWithOffset: [0, 16, 15, 14, 13, 12, 11],
srcValuesWithOffsetAndLength: [0, 16, 15, 14, 13, 12, 11, 0, 0],
srcOffset: 1,
},
{ type: 'uvec3',
setter: 'uniform3uiv',
elem: '[2]',
numElementsPerType: 3,
srcValues: [16, 15, 14, 13, 12, 11],
srcValuesWithOffset: [0, 16, 15, 14, 13, 12, 11],
srcValuesWithOffsetAndLength: [0, 16, 15, 14, 13, 12, 11, 0, 0],
srcOffset: 1,
},
{ type: 'vec4',
setter: 'uniform4fv',
elem: '[3]',
numElementsPerType: 4,
srcValues: [16, 15, 14, 13, 12, 11, 10, 9],
srcValuesWithOffset: [0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9],
srcValuesWithOffsetAndLength: [0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 0],
srcOffset: 3,
},
{ type: 'ivec4',
setter: 'uniform4iv',
elem: '[3]',
numElementsPerType: 4,
srcValues: [16, 15, 14, 13, 12, 11, 10, 9],
srcValuesWithOffset: [0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9],
srcValuesWithOffsetAndLength: [0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 0],
srcOffset: 3,
},
{ type: 'uvec4',
setter: 'uniform4uiv',
elem: '[3]',
numElementsPerType: 4,
srcValues: [16, 15, 14, 13, 12, 11, 10, 9],
srcValuesWithOffset: [0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9],
srcValuesWithOffsetAndLength: [0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 0],
srcOffset: 3,
},
// Matrix
{ type: 'mat2',
setter: 'uniformMatrix2fv',
elem: '[1][1]',
numElementsPerType: 4,
srcValues: [16, 15, 14, 13, 12, 11, 10, 9],
srcValuesWithOffset: [0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9],
srcValuesWithOffsetAndLength: [0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 0],
srcOffset: 3,
},
{ type: 'mat3',
setter: 'uniformMatrix3fv',
elem: '[2][2]',
numElementsPerType: 9,
srcValues: [16, 15, 14, 13, 12, 11, 10, 9, 8],
srcValuesWithOffset: [0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8],
srcValuesWithOffsetAndLength: [0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 0],
srcOffset: 3,
},
{ type: 'mat4',
setter: 'uniformMatrix4fv',
elem: '[3][3]',
numElementsPerType: 16,
srcValues: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
srcValuesWithOffset: [0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
srcValuesWithOffsetAndLength: [0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0],
srcOffset: 2,
},
{ type: 'mat2x3',
setter: 'uniformMatrix2x3fv',
elem: '[1][2]',
numElementsPerType: 6,
srcValues: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5],
srcValuesWithOffset: [0, 0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5],
srcValuesWithOffsetAndLength: [0, 0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 0, 0],
srcOffset: 4,
},
{ type: 'mat3x2',
setter: 'uniformMatrix3x2fv',
elem: '[2][1]',
numElementsPerType: 6,
srcValues: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5],
srcValuesWithOffset: [0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5],
srcValuesWithOffsetAndLength: [0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 0, 0, 0],
srcOffset: 3,
},
{ type: 'mat2x4',
setter: 'uniformMatrix2x4fv',
elem: '[1][3]',
numElementsPerType: 8,
srcValues: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
srcValuesWithOffset: [0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
srcValuesWithOffsetAndLength: [0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0],
srcOffset: 2,
},
{ type: 'mat4x2',
setter: 'uniformMatrix4x2fv',
elem: '[3][1]',
numElementsPerType: 8,
srcValues: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
srcValuesWithOffset: [0, 0, 0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
srcValuesWithOffsetAndLength: [0, 0, 0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0],
srcOffset: 5,
},
{ type: 'mat3x4',
setter: 'uniformMatrix3x4fv',
elem: '[2][3]',
numElementsPerType: 12,
srcValues: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5],
srcValuesWithOffset: [0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5],
srcValuesWithOffsetAndLength: [0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 0, 0, 0, 0],
srcOffset: 2,
},
{ type: 'mat4x3',
setter: 'uniformMatrix4x3fv',
elem: '[3][2]',
numElementsPerType: 12,
srcValues: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5],
srcValuesWithOffset: [0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5],
srcValuesWithOffsetAndLength: [0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 0, 0, 0, 0],
srcOffset: 2,
},
];
function checkUniformValues(program, typeInfo, useInitialValues) {
var numSrcValues = typeInfo.srcValues.length / typeInfo.numElementsPerType;
for (var ii = 0; ii < uniformArraySize; ++ii) {
var expectedValues;
if (useInitialValues || ii >= numSrcValues) {
expectedValues = new Array(typeInfo.numElementsPerType);
for (var jj = 0; jj < typeInfo.numElementsPerType; ++jj) {
expectedValues[jj] = initialUniformValue;
}
} else {
expectedValues = typeInfo.srcValues.slice(
typeInfo.numElementsPerType * ii, typeInfo.numElementsPerType * (ii + 1));
}
var elemLoc = gl.getUniformLocation(program, "color[" + ii + "]");
wtu.glErrorShouldBe(gl, gl.NO_ERROR,
"can get location of element " + ii + " of array from gl.getUniformLocation");
var value = gl.getUniform(program, elemLoc);
wtu.glErrorShouldBe(gl, gl.NO_ERROR,
"can get value of element " + ii + " of array from gl.getUniform");
var equal = true;
if (value === null) {
equal = false;
} else if (typeInfo.numElementsPerType == 1) {
if (value != expectedValues[0]) {
equal = false;
}
} else {
for (var jj = 0; jj < typeInfo.numElementsPerType; ++jj) {
if (value[jj] != expectedValues[jj]) {
equal = false;
break;
}
}
}
assertMsg(equal,
"value put in (" + expectedValues + ") matches value pulled out (" +
(value === null ? "null" : value) + ")");
}
}
for (var tt = 0; tt < typeInfos.length; ++tt) {
var typeInfo = typeInfos[tt];
debug("");
debug("check " + typeInfo.type);
var srcLength = typeInfo.srcValues.length;
var fSrc = wtu.replaceParams(fTemplate, typeInfo);
var program = wtu.loadProgram(gl, vSrc, fSrc);
if (!program) {
testFailed("Failed to create the program");
continue;
}
gl.useProgram(program);
var loc = gl.getUniformLocation(program, "color[0]");
if (!loc) {
testFailed("Failed to obtain the location of the uniform");
continue;
}
function setter(loc, array, srcOffset, srcLength) {
var isMatrix = (typeInfo.setter.indexOf("Matrix") == 7);
if (typeof(srcOffset) != 'undefined') {
if (isMatrix) {
gl[typeInfo.setter](loc, gl.FALSE, array, srcOffset, srcLength);
} else {
gl[typeInfo.setter](loc, array, srcOffset, srcLength);
}
} else if (typeof(srcLength) != 'undefined') {
if (isMatrix) {
gl[typeInfo.setter](loc, gl.FALSE, array, srcOffset);
} else {
gl[typeInfo.setter](loc, array, srcOffset);
}
} else {
if (isMatrix) {
gl[typeInfo.setter](loc, gl.FALSE, array);
} else {
gl[typeInfo.setter](loc, array);
}
}
}
// Initialize uniforms to value 99 and verify it.
var initValues = new Array(typeInfo.numElementsPerType * uniformArraySize);
for (var ii = 0; ii < typeInfo.numElementsPerType * uniformArraySize; ++ii) {
initValues[ii] = initialUniformValue;
}
setter(loc, initValues);
wtu.glErrorShouldBe(gl, gl.NO_ERROR,
"no error from initializing uniforms to 99");
checkUniformValues(program, typeInfo, true);
setter(loc, typeInfo.srcValues);
wtu.glErrorShouldBe(gl, gl.NO_ERROR,
"can set an array of uniforms with gl." + typeInfo.setter +
" without srcOffset / srcLength");
checkUniformValues(program, typeInfo);
setter(loc, typeInfo.srcValues, 0);
wtu.glErrorShouldBe(gl, gl.NO_ERROR,
"can set an array of uniforms with gl." + typeInfo.setter +
" with srcOffset = 0");
checkUniformValues(program, typeInfo);
setter(loc, typeInfo.srcValues, 0, 0);
wtu.glErrorShouldBe(gl, gl.NO_ERROR,
"can set an array of uniforms with gl." + typeInfo.setter +
" with srcOffset = 0 / srcLength = 0");
checkUniformValues(program, typeInfo);
setter(loc, typeInfo.srcValuesWithOffset, typeInfo.srcOffset);
wtu.glErrorShouldBe(gl, gl.NO_ERROR,
"can set an array of uniforms with gl." + typeInfo.setter +
" with srcOffset = " + typeInfo.srcOffset);
checkUniformValues(program, typeInfo);
setter(loc, typeInfo.srcValuesWithOffset, typeInfo.srcOffset, 0);
wtu.glErrorShouldBe(gl, gl.NO_ERROR,
"can set an array of uniforms with gl." + typeInfo.setter +
" with srcOffset = " + typeInfo.srcOffset + " / srcLength = 0");
checkUniformValues(program, typeInfo);
setter(loc, typeInfo.srcValuesWithOffsetAndLength, typeInfo.srcOffset, srcLength);
wtu.glErrorShouldBe(gl, gl.NO_ERROR,
"can set an array of uniforms with gl." + typeInfo.setter +
" with srcOffset = " + typeInfo.srcOffset + " / srcLength = " + srcLength);
checkUniformValues(program, typeInfo);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no errors");
// Negative tests
setter(loc, typeInfo.srcValues, typeInfo.srcValues.length + 1);
wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
"gl." + typeInfo.setter + " with srcOffset out-of-bounds");
setter(loc, typeInfo.srcValues, 0, typeInfo.srcValues.length + 1);
wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
"gl." + typeInfo.setter + " with srcLength out-of-bounds");
setter(loc, typeInfo.srcValues, typeInfo.srcOffset, srcLength);
wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
"gl." + typeInfo.setter + " with srcOffset + srcLength out-of-bounds");
setter(loc, typeInfo.srcValues, typeInfo.srcValues.length);
wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
"gl." + typeInfo.setter + " with 0 data");
if (typeInfo.numElementsPerType > 1) {
setter(loc, typeInfo.srcValuesWithOffsetAndLength, typeInfo.srcOffset);
wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
"gl." + typeInfo.setter + " with array length minus srcOffset not multiple of " + typeInfo.type);
}
}
debug("");
var successfullyParsed = true;
</script>
<script src="../../js/js-test-post.js"></script>
</body>
</html>