blob: 41a49bced4c6a97d66812387ad9a9c4048f8f4df [file] [log] [blame]
/*
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.
*/
'use strict';
// ESSL 1.00 spec section 5.8 (also ESSL 3.00 spec section 5.8):
// "The l-value and the expression must satisfy the semantic requirements of both op and equals (=)"
// In the semantic requirements of assignment (=):
// "The lvalue-expression and rvalue-expression must have the same type"
var runTest = function(contextVersion) {
var vertexTemplateESSL1 = [
'precision mediump float;',
'uniform $(rtype) ur;',
'uniform $(ltype) ul;',
'void main() {',
' $(ltype) a = ul;',
' a $(op) ur;',
' gl_Position = vec4(float(a$(ltypeToScalar)));',
'}'
].join('\n');
var vertexTemplateESSL3 = [
'#version 300 es',
vertexTemplateESSL1
].join('\n');
var fragmentTemplateESSL1 = [
'precision mediump float;',
'uniform $(rtype) ur;',
'uniform $(ltype) ul;',
'void main() {',
' $(ltype) a = ul;',
' a $(op) ur;',
' gl_FragColor = vec4(float(a$(ltypeToScalar)));',
'}'
].join('\n');
var fragmentTemplateESSL3 = [
'#version 300 es',
'out mediump vec4 my_FragColor;',
fragmentTemplateESSL1
].join('\n').replace('gl_FragColor', 'my_FragColor');
var isNonSquareMatrix = function(typeStr) {
return typeStr.substring(0, 3) == 'mat' &&
typeStr.length > 5 &&
typeStr[3] != typeStr[5];
}
var vsTemplate = contextVersion < 2 ? vertexTemplateESSL1 : vertexTemplateESSL3;
var fsTemplate = contextVersion < 2 ? fragmentTemplateESSL1 : fragmentTemplateESSL3;
var wtu = WebGLTestUtils;
var tests = [];
var baseTypes = ['float', 'int'];
var vecTypes = [['vec2', 'vec3', 'vec4', 'mat2', 'mat3', 'mat4'], ['ivec2', 'ivec3', 'ivec4']];
if (contextVersion >= 2) {
vecTypes[0] = ['vec2', 'vec3', 'vec4', 'mat2x2', 'mat3x3', 'mat4x4', 'mat2x3', 'mat2x4', 'mat3x2', 'mat3x4', 'mat4x2', 'mat4x3'];
}
var ops = ['+=', '-=', '*=', '/='];
var fs, vs;
for (var k = 0; k < ops.length; ++k) {
var op = ops[k];
for (var i = 0; i < baseTypes.length; ++i) {
var baseType = baseTypes[i];
for (var j = 0; j < vecTypes[i].length; ++j) {
var vecType = vecTypes[i][j];
var vecTypeToScalar = vecType.substring(0, 3) == 'mat' ? '[0].x' : '.x';
var pushTest = function(ltype, rtype, ltypeToScalar, expectSuccess) {
vs = wtu.replaceParams(vsTemplate, {ltype: ltype, rtype: rtype, ltypeToScalar: ltypeToScalar, op: op});
fs = wtu.replaceParams(fsTemplate, {ltype: ltype, rtype: rtype, ltypeToScalar: ltypeToScalar, op: op});
tests.push({
vShaderSource: vs,
vShaderSuccess: expectSuccess,
linkSuccess: expectSuccess,
passMsg: ltype + " " + op + " " + rtype + " in a vertex shader should " + (expectSuccess ? "succeed." : "fail.")
});
tests.push({
fShaderSource: fs,
fShaderSuccess: expectSuccess,
linkSuccess: expectSuccess,
passMsg: ltype + " " + op + " " + rtype + " in a fragment shader should " + (expectSuccess ? "succeed." : "fail.")
});
}
// "scalar op= vector" is not okay, since the result of op is a vector,
// which can't be assigned to a scalar.
pushTest(baseType, vecType, '', false);
if (j > 0) {
var vecType2 = vecTypes[i][j - 1];
// "vector1 op= vector2" is not okay when vector1 and vector2 have
// non-matching dimensions.
pushTest(vecType, vecType2, vecTypeToScalar, false);
}
// "vector op= scalar" is okay.
pushTest(vecType, baseType, vecTypeToScalar, true);
// vecX *= matX is okay (effectively, this treats vector as a row vector).
if (vecType.substring(0, 3) == 'vec' && op == '*=') {
pushTest(vecType, 'mat' + vecType[3], vecTypeToScalar, true);
}
if (op != '*=' || !isNonSquareMatrix(vecType)) {
// "vector1 op= vector2" is okay when vector1 and vector2 have the same
// type (does a component-wise operation or matrix multiplication).
pushTest(vecType, vecType, vecTypeToScalar, true);
} else {
// non-square matrices can only be compound multiplied with a square matrix.
pushTest(vecType, vecType, vecTypeToScalar, false);
pushTest(vecType, 'mat' + vecType[3], vecTypeToScalar, true);
}
}
}
}
GLSLConformanceTester.runTests(tests, contextVersion);
}
var successfullyParsed = true;