Bug 1945965 – remove new tab April Fools logo. r=home-newtab-reviewers,reemhamz
[gecko.git] / dom / canvas / test / webgl-conf / checkout / conformance / glsl / misc / shader-uniform-packing-restrictions.html
blob22a968470f151a50524a35d00fd66509e3d6d236
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 -->
7 <!DOCTYPE html>
8 <html>
9 <head>
10 <meta charset="utf-8">
11 <title>WebGL uniform packing restrctions Conformance Test</title>
12 <link rel="stylesheet" href="../../../resources/js-test-style.css"/>
13 <link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
14 <script src="../../../js/js-test-pre.js"></script>
15 <script src="../../../js/webgl-test-utils.js"></script>
16 <script src="../../../js/glsl-conformance-test.js"></script>
17 </head>
18 <body>
19 <div id="description"></div>
20 <div id="console"></div>
21 <canvas id="example" width="2" height="2"> </canvas>
22 <script id="vshader" type="x-shader/x-vertex">
23 attribute vec4 a_position;
24 void main()
26 gl_Position = a_position;
28 </script>
29 <script id="fshader" type="x-shader/x-vertex">
30 precision mediump float;
31 varying vec4 v_varying;
32 void main()
34 gl_FragColor = v_varying;
36 </script>
37 <script id="vshaderArrayTest" type="x-shader/x-vertex">
38 attribute vec4 a_position;
39 varying vec4 v_varying;
40 uniform $(type) u_uniform[$(numTestType)];
41 void main()
43 v_varying = $(result);
44 gl_Position = a_position;
46 </script>
47 <script id="fshaderArrayTest" type="x-shader/x-fragment">
48 precision mediump float;
49 uniform $(type) u_uniform[$(numTestType)];
50 void main()
52 gl_FragColor = $(result);
54 </script>
55 <script id="vshaderUniformTest" type="x-shader/x-fragment">
56 attribute vec4 a_position;
57 varying vec4 v_varying;
58 $(uniforms)
59 void main()
61 $(code)
62 v_varying = $(result);
63 gl_Position = a_position;
65 </script>
66 <script id="fshaderUniformTest" type="x-shader/x-fragment">
67 precision mediump float;
68 $(uniforms)
69 void main()
71 $(code)
72 gl_FragColor = $(result);
74 </script>
75 <script>
76 "use strict";
77 description();
78 debug("");
79 var wtu = WebGLTestUtils;
80 var gl = wtu.create3DContext("example");
82 var uniformTypes = [
83 { type: "bool", componentsPerRow: 1, rows: 1, fType: "float", uniToF: "float(u_uniform$(id)$(index))", fToVec4: "vec4($(f), 0, 0, 0)"},
84 { type: "float", componentsPerRow: 1, rows: 1, fType: "float", uniToF: "u_uniform$(id)$(index)", fToVec4: "vec4($(f), 0, 0, 0)"},
85 { type: "int", componentsPerRow: 1, rows: 1, fType: "float", uniToF: "float(u_uniform$(id)$(index))", fToVec4: "vec4($(f), 0, 0, 0)"},
86 { type: "vec2", componentsPerRow: 2, rows: 1, fType: "vec2", uniToF: "u_uniform$(id)$(index)", fToVec4: "vec4($(f), 0, 0)"},
87 { type: "ivec2", componentsPerRow: 2, rows: 1, fType: "vec2", uniToF: "vec2(u_uniform$(id)$(index))", fToVec4: "vec4($(f), 0, 0)"},
88 { type: "bvec2", componentsPerRow: 2, rows: 1, fType: "vec2", uniToF: "vec2(u_uniform$(id)$(index))", fToVec4: "vec4($(f), 0, 0)"},
89 { type: "vec3", componentsPerRow: 3, rows: 1, fType: "vec3", uniToF: "u_uniform$(id)$(index)", fToVec4: "vec4($(f), 0)"},
90 { type: "ivec3", componentsPerRow: 3, rows: 1, fType: "vec3", uniToF: "vec3(u_uniform$(id)$(index))", fToVec4: "vec4($(f), 0)"},
91 { type: "bvec3", componentsPerRow: 3, rows: 1, fType: "vec3", uniToF: "vec3(u_uniform$(id)$(index))", fToVec4: "vec4($(f), 0)"},
92 { type: "vec4", componentsPerRow: 4, rows: 1, fType: "vec4", uniToF: "u_uniform$(id)$(index)", fToVec4: "$(f)"},
93 { type: "ivec4", componentsPerRow: 4, rows: 1, fType: "vec4", uniToF: "vec4(u_uniform$(id)$(index))", fToVec4: "$(f)"},
94 { type: "bvec4", componentsPerRow: 4, rows: 1, fType: "vec4", uniToF: "vec4(u_uniform$(id)$(index))", fToVec4: "$(f)"},
95 // Yes, the spec says mat2 takes 4 columns, 2 rows.
96 { type: "mat2", componentsPerRow: 4, rows: 2, fType: "vec2", uniToF: "vec2(u_uniform$(id)$(index)[0])", fToVec4: "vec4($(f), 0, 0)"},
97 { type: "mat3", componentsPerRow: 3, rows: 3, fType: "vec3", uniToF: "vec3(u_uniform$(id)$(index)[0])", fToVec4: "vec4($(f), 0)"},
98 { type: "mat4", componentsPerRow: 4, rows: 4, fType: "vec4", uniToF: "vec4(u_uniform$(id)$(index)[0])", fToVec4: "$(f)"},
99 // Samplers generally have more restrictive limits.
100 // { type: "sampler2D", componentsPerRow: 1, rows: 1, code: "vec4(texture2D(u_uniform[$(index)], vec2(0, 0)))", },
101 // { type: "samplerCube", componentsPerRow: 1, rows: 1, code: "vec4(textureCube(u_uniform[$(index)], vec3(0, 0, 0)))", },
104 var vBaseSource = wtu.getScript("vshader");
105 var fBaseSource = wtu.getScript("fshader");
106 var vArrayTestSource = wtu.getScript("vshaderArrayTest");
107 var fArrayTestSource = wtu.getScript("fshaderArrayTest");
108 var vUniformTestSource = wtu.getScript("vshaderUniformTest");
109 var fUniformTestSource = wtu.getScript("fshaderUniformTest");
111 var tests = [];
112 var shaderTypes = [
113 { type: "vertex",
114 // For tests that expect failure which shader might fail.
115 vertExpectation: false,
116 fragExpectation: true,
117 vertArrayTest: vArrayTestSource,
118 fragArrayTest: fBaseSource,
119 vertUniformTest: vUniformTestSource,
120 fragUniformTest: fBaseSource,
121 maxVectors: gl.getParameter(gl.MAX_VERTEX_UNIFORM_VECTORS),
122 minVectors: 127, // GLSL ES 1.0.17 Appendix A.7 and A.8. Reserve one row for constants in the code, hence 128 - 1.
124 { type: "fragment",
125 // For tests that expect failure which shader might fail.
126 vertExpectation: true,
127 fragExpectation: false,
128 vertArrayTest: vBaseSource,
129 fragArrayTest: fArrayTestSource,
130 vertUniformTest: vBaseSource,
131 fragUniformTest: fUniformTestSource,
132 maxVectors: gl.getParameter(gl.MAX_FRAGMENT_UNIFORM_VECTORS),
133 minVectors: 15, // GLSL ES 1.0.17 Appendix A.8 - minimum value of gl_maxFragmentUniformVectors is 16. Again, reserve a row for constants.
136 for (var ss = 0; ss < shaderTypes.length; ++ss) {
137 var shaderType = shaderTypes[ss];
138 debug("max " + shaderType.type + ": " + shaderType.maxVectors);
139 for (var ii = 0; ii < uniformTypes.length; ++ii) {
140 var info = uniformTypes[ii];
141 wtu.log("checking: " + info.type);
142 // Compute the maximum amount of this type allowed in a single array.
143 var maxInArray = Math.floor(shaderType.maxVectors / info.rows);
144 // Compute the minimum required to work in a single array.
145 var minVars = Math.floor(shaderType.minVectors / info.rows);
146 // Compute the maximum allowed as single elements
147 var maxPerRow = Math.floor(4 / info.componentsPerRow);
148 var maxPacked = Math.floor(shaderType.maxVectors * maxPerRow / info.rows);
150 // Test array[1] of the type
151 var uniToF = wtu.replaceParams(info.uniToF, {id: "", index: "[0]"});
152 var vec4 = wtu.replaceParams(info.fToVec4, {f: uniToF});
153 tests.push({
154 vShaderSource: wtu.replaceParams(shaderType.vertArrayTest, {numTestType: 1, result: vec4}, info),
155 vShaderSuccess: true,
156 fShaderSource: wtu.replaceParams(shaderType.fragArrayTest, {numTestType: 1, result: vec4}, info),
157 fShaderSuccess: true,
158 linkSuccess: true,
159 passMsg: shaderType.type + " shader with uniform array of " + info.type + " with 1 element should succeed",
162 // Note: We can't test an array filling all uniform space as actual GL drivers are
163 // only required to be able to do the minimum number. After that it can fail for
164 // multiple reasons, including uniform registers being reserved for the implementation's
165 // own use. Constants also take up uniform registers.
167 // Test required number of uniforms
168 var uniToF = wtu.replaceParams(info.uniToF, {id: "", index: "[" + (minVars - 1) + "]"});
169 var vec4 = wtu.replaceParams(info.fToVec4, {f: uniToF});
170 tests.push({
171 vShaderSource: wtu.replaceParams(shaderType.vertArrayTest, {numTestType: minVars, result: vec4}, info),
172 vShaderSuccess: true,
173 fShaderSource: wtu.replaceParams(shaderType.fragArrayTest, {numTestType: minVars, result: vec4}, info),
174 fShaderSuccess: true,
175 linkSuccess: true,
176 passMsg: shaderType.type + " shader with uniform array of " + info.type + " with " + minVars + " elements (the minimum required) should succeed",
179 // Test array[max + 1] accessing last element. WebGL requires this to fail.
180 var uniToF = wtu.replaceParams(info.uniToF, {id: "", index: "[" + maxInArray + "]"});
181 var vec4 = wtu.replaceParams(info.fToVec4, {f: uniToF});
182 tests.push({
183 vShaderSource: wtu.replaceParams(shaderType.vertArrayTest, {numTestType: maxInArray + 1, result: vec4}, info),
184 vShaderSuccess: shaderType.vertExpectation,
185 fShaderSource: wtu.replaceParams(shaderType.fragArrayTest, {numTestType: maxInArray + 1, result: vec4}, info),
186 fShaderSuccess: shaderType.fragExpectation,
187 linkSuccess: false,
188 passMsg: shaderType.type + " shader with uniform array of " + info.type + " with " + (maxInArray + 1) + " elements (one past maximum) accessing last element should fail",
191 // Test array[max + 1] accessing first element. WebGL requires this to fail but ES allows truncating array.
192 var uniToF = wtu.replaceParams(info.uniToF, {id: "", index: "[0]"});
193 var vec4 = wtu.replaceParams(info.fToVec4, {f: uniToF});
194 tests.push({
195 vShaderSource: wtu.replaceParams(shaderType.vertArrayTest, {numTestType: maxInArray + 1, result: vec4}, info),
196 vShaderSuccess: shaderType.vertExpectation,
197 fShaderSource: wtu.replaceParams(shaderType.fragArrayTest, {numTestType: maxInArray + 1, result: vec4}, info),
198 fShaderSuccess: shaderType.fragExpectation,
199 linkSuccess: false,
200 passMsg: shaderType.type + " shader with uniform array of " + info.type + " with " + (maxInArray + 1) + " elements (one past maximum) accessing first element should fail",
203 // Note: We can't test max uniforms as actual GL drivers are only required to be able
204 // to do the minimum number. After that it can fail for multiple reasons, including
205 // uniform registers being reserved for the implementation's own use or also instruction
206 // space limitations. Strictly speaking, guaranteed supported length of a shader
207 // executable is defined by the GLES2 conformance tests according to GLSL ES 1.0.17
208 // Appendix A.2. This does not give us an exact limit: this test only aims to fit within
209 // instruction space limits imposed by existing GLES2 compliant hardware.
211 var generateCode = function(numVars) {
212 var uniforms = [];
213 var sumTerms = [];
214 for (var uu = 0; uu < numVars; ++uu) {
215 uniforms.push(" uniform " + info.type + " u_uniform" + uu + ";");
216 sumTerms.push(wtu.replaceParams(info.uniToF, {id: uu, index: ""}));
218 return {
219 uniforms: uniforms.join("\n"),
220 code: info.fType + " sum = " + sumTerms.join(" + \n ") + ";",
221 result: wtu.replaceParams(info.fToVec4, {f: 'sum'})
225 // Test max+1 uniforms of type.
226 tests.push({
227 vShaderSource: wtu.replaceParams(shaderType.vertUniformTest, generateCode(maxPacked + 1), info),
228 vShaderSuccess: shaderType.vertExpectation,
229 fShaderSource: wtu.replaceParams(shaderType.fragUniformTest, generateCode(maxPacked + 1), info),
230 fShaderSuccess: shaderType.fragExpectation,
231 linkSuccess: false,
232 passMsg: shaderType.type + " shader with " + (maxPacked + 1) + " uniforms of " + info.type + " (one past maximum) should fail",
235 // Test required uniforms of type.
236 tests.push({
237 vShaderSource: wtu.replaceParams(shaderType.vertUniformTest, generateCode(minVars), info),
238 vShaderSuccess: true,
239 fShaderSource: wtu.replaceParams(shaderType.fragUniformTest, generateCode(minVars), info),
240 fShaderSuccess: true,
241 linkSuccess: true,
242 passMsg: shaderType.type + " shader with " + minVars + " uniforms of " + info.type + " (the minimum required) should succeed",
246 GLSLConformanceTester.runTests(tests);
247 var successfullyParsed = true;
248 </script>
249 </body>
250 </html>