4 ** Copyright (c) 2014 The Khronos Group Inc.
6 ** Permission is hereby granted, free of charge, to any person obtaining a
7 ** copy of this software and/or associated documentation files (the
8 ** "Materials"), to deal in the Materials without restriction, including
9 ** without limitation the rights to use, copy, modify, merge, publish,
10 ** distribute, sublicense, and/or sell copies of the Materials, and to
11 ** permit persons to whom the Materials are furnished to do so, subject to
12 ** the following conditions:
14 ** The above copyright notice and this permission notice shall be included
15 ** in all copies or substantial portions of the Materials.
17 ** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21 ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
30 <meta charset="utf-8">
31 <link rel="stylesheet" href="../../resources/js-test-style.css"/>
32 <script src="../../resources/js-test-pre.js"></script>
33 <script src="../resources/webgl-test-utils.js"></script>
34 <title>WebGL Matrix Attribute Conformance Test</title>
37 <div id="description"></div>
38 <div id="console"></div>
39 <canvas id="canvas" width="8" height="8" style="width: 8px; height: 8px;"></canvas>
42 description("This tests ensures that matrix attribute locations do not clash with other shader attributes.");
44 var wtu = WebGLTestUtils;
45 var canvas = document.getElementById("canvas");
46 var gl = wtu.create3DContext(canvas, {antialias: false});
48 // Make sure we have room for at least a mat4.
49 var maxAttributes = gl.getParameter(gl.MAX_VERTEX_ATTRIBS);
50 debug('MAX_VERTEX_ATTRIBUTES is ' + maxAttributes);
51 shouldBeGreaterThanOrEqual('maxAttributes', '4');
53 var glFragmentShader = wtu.setupSimpleColorFragmentShader(gl);
55 // prepareMatrixProgram creates a program with glFragmentShader as the fragment shader.
56 // The vertex shader has numVector number of vectors and a matrix with numMatrixDimensions
57 // dimensions at location numMatrixPosition in the list of attributes.
58 // Ensures that every vector and matrix is used by the program.
59 // Returns a valid program on successfull link; null on link failure.
60 function prepareMatrixProgram(numVectors, numMatrixDimensions, numMatrixPosition) {
61 // Add the matrix and vector attribute declarations. Declare the vectors
62 // to have the same number of components as the matrix so we can perform
63 // operations on them when we assign to gl_Position later on.
64 var strVertexShader = "";
65 for (var ii = 1; ii <= numVectors; ++ii) {
66 if (numMatrixPosition === ii) {
67 strVertexShader += "attribute mat" + numMatrixDimensions + " matrix;\n";
69 strVertexShader += "attribute vec" + numMatrixDimensions + " vec_" + ii + ";\n";
71 // numMatrixPosition will be one past numVectors if the caller wants it to be
72 // last. Hence, we need this check outside the loop as well as inside.
73 if (numMatrixPosition === ii) {
74 strVertexShader += "attribute mat" + numMatrixDimensions + " matrix;\n";
76 // Add the body of the shader. Add up all of the vectors and multiply by the matrix.
77 // The operations we perform do not matter. We just need to ensure that all the vector and
78 // matrix attributes are used.
79 strVertexShader += "void main(void) { \ngl_Position = vec4((";
80 for (var ii = 1; ii <= numVectors; ++ii) {
82 strVertexShader += "+"
84 strVertexShader += "vec_" + ii;
86 strVertexShader += ")*matrix";
87 // Ensure the vec4 has the correct number of dimensions in order to be assignable
89 for (var ii = numMatrixDimensions; ii < 4; ++ii) {
90 strVertexShader += ",0.0";
92 strVertexShader += ");}\n";
93 // Load the shader, attach it to a program, and return the link results
94 var glVertexShader = wtu.loadShader(gl, strVertexShader, gl.VERTEX_SHADER);
95 var strTest = 'Load shader with ' + numVectors + ' vectors and 1 matrix';
96 if (glVertexShader !== null) {
99 var glProgram = gl.createProgram();
100 gl.attachShader(glProgram, glVertexShader);
101 gl.attachShader(glProgram, glFragmentShader);
102 gl.linkProgram(glProgram);
103 if (gl.getProgramParameter(glProgram, gl.LINK_STATUS)) {
104 wtu.glErrorShouldBe(gl, gl.NO_ERROR, 'linkProgram');
115 // Test mat2, mat3 and mat4.
116 for (var mm = 2; mm <= 4; ++mm) {
117 // Add maxAttribute number of attributes by saving enough room in the attribute
118 // list for a matrix of mm dimensions. All of the other attribute slots will be
119 // filled with vectors.
120 var numVectors = maxAttributes - mm;
121 for (var pp = 1; pp <= numVectors + 1; ++pp) {
122 debug('Test ' + mm + ' dimensional matrix at position ' + pp);
123 var glProgram = prepareMatrixProgram(numVectors, /*numMatrixDimensions*/mm, /*numMatrixPosition*/pp);
124 shouldBeNonNull('glProgram');
125 var attribMatrix = gl.getAttribLocation(glProgram, 'matrix');
126 debug('Matrix is at attribute location ' + attribMatrix);
127 shouldBeTrue('attribMatrix > -1');
128 // Per the spec, when an attribute is a matrix attribute, getAttribLocation
129 // returns the index of the first component of the matrix. The implementation must
130 // leave sufficient room for all the components. Here we ensure none of the vectors
131 // in the shader are assigned attribute locations that belong to the matrix.
132 for (var vv = 1; vv <= numVectors; ++vv) {
133 var strVector = 'vec_' + vv
134 var attribVector = gl.getAttribLocation(glProgram, strVector);
135 debug(strVector + ' is at attribute location ' + attribVector);
136 // Begin with the first attribute location where the matrix begins and ensure
137 // the vector's attribute location is not assigned to the matrix. Loop until
138 // we've checked all of the attribute locations that belong to the matrix.
139 for (var ii = attribMatrix; ii < attribMatrix + mm; ++ii) {
140 var testStr = strVector + ' attribute location: ' + attribVector + '. Should not be ' + ii;
141 if (attribVector !== ii) {
153 var successfullyParsed = true;
155 <script src="../../resources/js-test-post.js"></script>