2 Copyright (c) 2019 The Khronos Group Inc.
3 Use of this source code is governed by an MIT-style license that can be
4 found in the LICENSE.txt file.
10 <link rel=
"stylesheet" href=
"../../resources/js-test-style.css"/>
11 <script src=
"../../js/js-test-pre.js"></script>
12 <script src=
"../../js/webgl-test-utils.js"></script>
13 <title>WebGL Matrix Attribute Conformance Test
</title>
16 <div id=
"description"></div>
17 <div id=
"console"></div>
18 <canvas id=
"canvas" width=
"8" height=
"8" style=
"width: 8px; height: 8px;"></canvas>
21 description("This tests ensures that matrix attribute locations do not clash with other shader attributes.");
23 var wtu
= WebGLTestUtils
;
24 var canvas
= document
.getElementById("canvas");
25 var gl
= wtu
.create3DContext(canvas
, {antialias
: false});
27 // Make sure we have room for at least a mat4.
28 var maxAttributes
= gl
.getParameter(gl
.MAX_VERTEX_ATTRIBS
);
29 debug('MAX_VERTEX_ATTRIBUTES is ' + maxAttributes
);
30 shouldBeGreaterThanOrEqual('maxAttributes', '4');
32 var glFragmentShader
= wtu
.loadShader(gl
, wtu
.simpleColorFragmentShader
, gl
.FRAGMENT_SHADER
);
34 // prepareMatrixProgram creates a program with glFragmentShader as the fragment shader.
35 // The vertex shader has numVector number of vectors and a matrix with numMatrixDimensions
36 // dimensions at location numMatrixPosition in the list of attributes.
37 // Ensures that every vector and matrix is used by the program.
38 // Returns a valid program on successfull link; null on link failure.
39 function prepareMatrixProgram(numVectors
, numMatrixDimensions
, numMatrixPosition
) {
40 // Add the matrix and vector attribute declarations. Declare the vectors
41 // to have the same number of components as the matrix so we can perform
42 // operations on them when we assign to gl_Position later on.
43 var strVertexShader
= "";
44 for (var ii
= 1; ii
<= numVectors
; ++ii
) {
45 if (numMatrixPosition
=== ii
) {
46 strVertexShader
+= "attribute mat" + numMatrixDimensions
+ " matrix;\n";
48 strVertexShader
+= "attribute vec" + numMatrixDimensions
+ " vec_" + ii
+ ";\n";
50 // numMatrixPosition will be one past numVectors if the caller wants it to be
51 // last. Hence, we need this check outside the loop as well as inside.
52 if (numMatrixPosition
=== ii
) {
53 strVertexShader
+= "attribute mat" + numMatrixDimensions
+ " matrix;\n";
55 // Add the body of the shader. Add up all of the vectors and multiply by the matrix.
56 // The operations we perform do not matter. We just need to ensure that all the vector and
57 // matrix attributes are used.
58 strVertexShader
+= "void main(void) { \ngl_Position = vec4((";
59 for (var ii
= 1; ii
<= numVectors
; ++ii
) {
61 strVertexShader
+= "+"
63 strVertexShader
+= "vec_" + ii
;
65 strVertexShader
+= ")*matrix";
66 // Ensure the vec4 has the correct number of dimensions in order to be assignable
68 for (var ii
= numMatrixDimensions
; ii
< 4; ++ii
) {
69 strVertexShader
+= ",0.0";
71 strVertexShader
+= ");}\n";
72 // Load the shader, attach it to a program, and return the link results
73 var glVertexShader
= wtu
.loadShader(gl
, strVertexShader
, gl
.VERTEX_SHADER
);
74 var strTest
= 'Load shader with ' + numVectors
+ ' vectors and 1 matrix';
75 if (glVertexShader
!== null) {
78 var glProgram
= gl
.createProgram();
79 gl
.attachShader(glProgram
, glVertexShader
);
80 gl
.attachShader(glProgram
, glFragmentShader
);
81 gl
.linkProgram(glProgram
);
82 if (gl
.getProgramParameter(glProgram
, gl
.LINK_STATUS
)) {
83 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, 'linkProgram');
94 // Test mat2, mat3 and mat4.
95 for (var mm
= 2; mm
<= 4; ++mm
) {
96 // Add maxAttribute number of attributes by saving enough room in the attribute
97 // list for a matrix of mm dimensions. All of the other attribute slots will be
98 // filled with vectors.
99 var numVectors
= maxAttributes
- mm
;
100 for (var pp
= 1; pp
<= numVectors
+ 1; ++pp
) {
101 debug('Test ' + mm
+ ' dimensional matrix at position ' + pp
);
102 var glProgram
= prepareMatrixProgram(numVectors
, /*numMatrixDimensions*/mm
, /*numMatrixPosition*/pp
);
103 shouldBeNonNull('glProgram');
104 var attribMatrix
= gl
.getAttribLocation(glProgram
, 'matrix');
105 debug('Matrix is at attribute location ' + attribMatrix
);
106 shouldBeTrue('attribMatrix > -1');
107 // Per the spec, when an attribute is a matrix attribute, getAttribLocation
108 // returns the index of the first component of the matrix. The implementation must
109 // leave sufficient room for all the components. Here we ensure none of the vectors
110 // in the shader are assigned attribute locations that belong to the matrix.
111 for (var vv
= 1; vv
<= numVectors
; ++vv
) {
112 var strVector
= 'vec_' + vv
113 var attribVector
= gl
.getAttribLocation(glProgram
, strVector
);
114 debug(strVector
+ ' is at attribute location ' + attribVector
);
115 // Begin with the first attribute location where the matrix begins and ensure
116 // the vector's attribute location is not assigned to the matrix. Loop until
117 // we've checked all of the attribute locations that belong to the matrix.
118 for (var ii
= attribMatrix
; ii
< attribMatrix
+ mm
; ++ii
) {
119 var testStr
= strVector
+ ' attribute location: ' + attribVector
+ '. Should not be ' + ii
;
120 if (attribVector
!== ii
) {
132 var successfullyParsed
= true;
134 <script src=
"../../js/js-test-post.js"></script>