summaryrefslogtreecommitdiffstats
path: root/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-matrix-attributes.html
blob: fc7ab56b0f7d5eb538b0ab5ccc0e95509a3a3eb8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
<!--
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">
<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>
<title>WebGL Matrix Attribute Conformance Test</title>
</head>
<body>
<div id="description"></div>
<div id="console"></div>
<canvas id="canvas" width="8" height="8" style="width: 8px; height: 8px;"></canvas>
<script>
"use strict";
description("This tests ensures that matrix attribute locations do not clash with other shader attributes.");

var wtu = WebGLTestUtils;
var canvas = document.getElementById("canvas");
var gl = wtu.create3DContext(canvas, {antialias: false});

// Make sure we have room for at least a mat4.
var maxAttributes = gl.getParameter(gl.MAX_VERTEX_ATTRIBS);
debug('MAX_VERTEX_ATTRIBUTES is ' + maxAttributes);
shouldBeGreaterThanOrEqual('maxAttributes', '4');

var glFragmentShader = wtu.loadShader(gl, wtu.simpleColorFragmentShader, gl.FRAGMENT_SHADER);

// prepareMatrixProgram creates a program with glFragmentShader as the fragment shader.
// The vertex shader has numVector number of vectors and a matrix with numMatrixDimensions
// dimensions at location numMatrixPosition in the list of attributes.
// Ensures that every vector and matrix is used by the program.
// Returns a valid program on successfull link; null on link failure.
function prepareMatrixProgram(numVectors, numMatrixDimensions, numMatrixPosition) {
    // Add the matrix and vector attribute declarations. Declare the vectors
    // to have the same number of components as the matrix so we can perform
    // operations on them when we assign to gl_Position later on.
    var strVertexShader = "";
    for (var ii = 1; ii <= numVectors; ++ii) {
        if (numMatrixPosition === ii) {
            strVertexShader += "attribute mat" + numMatrixDimensions + " matrix;\n";
        }
        strVertexShader += "attribute vec" + numMatrixDimensions + " vec_" + ii + ";\n";
    }
    // numMatrixPosition will be one past numVectors if the caller wants it to be
    // last. Hence, we need this check outside the loop as well as inside.
    if (numMatrixPosition === ii) {
        strVertexShader += "attribute mat" + numMatrixDimensions + " matrix;\n";
    }
    // Add the body of the shader. Add up all of the vectors and multiply by the matrix.
    // The operations we perform do not matter. We just need to ensure that all the vector and
    // matrix attributes are used.
    strVertexShader +=  "void main(void) { \ngl_Position = vec4((";
    for (var ii = 1; ii <= numVectors; ++ii) {
        if (ii > 1) {
            strVertexShader += "+"
        }
        strVertexShader += "vec_" + ii;
    }
    strVertexShader += ")*matrix";
    // Ensure the vec4 has the correct number of dimensions in order to be assignable
    // to gl_Position.
    for (var ii = numMatrixDimensions; ii < 4; ++ii) {
        strVertexShader += ",0.0";
    }
    strVertexShader += ");}\n";
    // Load the shader, attach it to a program, and return the link results
    var glVertexShader = wtu.loadShader(gl, strVertexShader, gl.VERTEX_SHADER);
    var strTest = 'Load shader with ' + numVectors + ' vectors and 1 matrix';
    if (glVertexShader !== null) {
        testPassed(strTest);

        var glProgram = gl.createProgram();
        gl.attachShader(glProgram, glVertexShader);
        gl.attachShader(glProgram, glFragmentShader);
        gl.linkProgram(glProgram);
        if (gl.getProgramParameter(glProgram, gl.LINK_STATUS)) {
            wtu.glErrorShouldBe(gl, gl.NO_ERROR, 'linkProgram');
            return glProgram;
        }
    } else {
        testFailed(strTest);
    }
    return null;
}

debug('');

// Test mat2, mat3 and mat4.
for (var mm = 2; mm <= 4; ++mm) {
    // Add maxAttribute number of attributes by saving enough room in the attribute
    // list for a matrix of mm dimensions. All of the other attribute slots will be
    // filled with vectors.
    var numVectors = maxAttributes - mm;
    for (var pp = 1; pp <= numVectors + 1; ++pp) {
        debug('Test ' + mm + ' dimensional matrix at position ' + pp);
        var glProgram = prepareMatrixProgram(numVectors, /*numMatrixDimensions*/mm, /*numMatrixPosition*/pp);
        shouldBeNonNull('glProgram');
        var attribMatrix = gl.getAttribLocation(glProgram, 'matrix');
        debug('Matrix is at attribute location ' + attribMatrix);
        shouldBeTrue('attribMatrix > -1');
        // Per the spec, when an attribute is a matrix attribute, getAttribLocation
        // returns the index of the first component of the matrix. The implementation must
        // leave sufficient room for all the components. Here we ensure none of the vectors
        // in the shader are assigned attribute locations that belong to the matrix.
        for (var vv = 1; vv <= numVectors; ++vv) {
            var strVector = 'vec_' + vv
            var attribVector = gl.getAttribLocation(glProgram, strVector);
            debug(strVector + ' is at attribute location ' + attribVector);
            // Begin with the first attribute location where the matrix begins and ensure
            // the vector's attribute location is not assigned to the matrix. Loop until
            // we've checked all of the attribute locations that belong to the matrix.
            for (var ii = attribMatrix; ii < attribMatrix + mm; ++ii) {
                var testStr = strVector + ' attribute location: ' + attribVector + '.  Should not be ' + ii;
                if (attribVector !== ii) {
                    testPassed(testStr);
                } else {
                    testFailed(testStr);
                }
            }
        }
        debug('');
    }
    debug('');
}

var successfullyParsed = true;
</script>
<script src="../../js/js-test-post.js"></script>
</body>
</html>