gl-matrix-attributes.html (6013B)
1 <!-- 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. 5 --> 6 <!DOCTYPE html> 7 <html> 8 <head> 9 <meta charset="utf-8"> 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> 14 </head> 15 <body> 16 <div id="description"></div> 17 <div id="console"></div> 18 <canvas id="canvas" width="8" height="8" style="width: 8px; height: 8px;"></canvas> 19 <script> 20 "use strict"; 21 description("This tests ensures that matrix attribute locations do not clash with other shader attributes."); 22 23 var wtu = WebGLTestUtils; 24 var canvas = document.getElementById("canvas"); 25 var gl = wtu.create3DContext(canvas, {antialias: false}); 26 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'); 31 32 var glFragmentShader = wtu.loadShader(gl, wtu.simpleColorFragmentShader, gl.FRAGMENT_SHADER); 33 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"; 47 } 48 strVertexShader += "attribute vec" + numMatrixDimensions + " vec_" + ii + ";\n"; 49 } 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"; 54 } 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) { 60 if (ii > 1) { 61 strVertexShader += "+" 62 } 63 strVertexShader += "vec_" + ii; 64 } 65 strVertexShader += ")*matrix"; 66 // Ensure the vec4 has the correct number of dimensions in order to be assignable 67 // to gl_Position. 68 for (var ii = numMatrixDimensions; ii < 4; ++ii) { 69 strVertexShader += ",0.0"; 70 } 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) { 76 testPassed(strTest); 77 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'); 84 return glProgram; 85 } 86 } else { 87 testFailed(strTest); 88 } 89 return null; 90 } 91 92 debug(''); 93 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) { 121 testPassed(testStr); 122 } else { 123 testFailed(testStr); 124 } 125 } 126 } 127 debug(''); 128 } 129 debug(''); 130 } 131 132 var successfullyParsed = true; 133 </script> 134 <script src="../../js/js-test-post.js"></script> 135 </body> 136 </html>