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 <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>
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;
26 gl_Position = a_position;
29 <script id=
"fshader" type=
"x-shader/x-vertex">
30 precision mediump float;
31 varying vec4 v_varying;
34 gl_FragColor = v_varying;
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)];
43 v_varying = $(result);
44 gl_Position = a_position;
47 <script id=
"fshaderArrayTest" type=
"x-shader/x-fragment">
48 precision mediump float;
49 uniform $(type) u_uniform[$(numTestType)];
52 gl_FragColor = $(result);
55 <script id=
"vshaderUniformTest" type=
"x-shader/x-fragment">
56 attribute vec4 a_position;
57 varying vec4 v_varying;
62 v_varying = $(result);
63 gl_Position = a_position;
66 <script id=
"fshaderUniformTest" type=
"x-shader/x-fragment">
67 precision mediump float;
72 gl_FragColor = $(result);
79 var wtu
= WebGLTestUtils
;
80 var gl
= wtu
.create3DContext("example");
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");
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.
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
});
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,
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
});
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,
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
});
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
,
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
});
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
,
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
) {
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
: ""}));
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.
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
,
232 passMsg
: shaderType
.type
+ " shader with " + (maxPacked
+ 1) + " uniforms of " + info
.type
+ " (one past maximum) should fail",
235 // Test required uniforms of type.
237 vShaderSource
: wtu
.replaceParams(shaderType
.vertUniformTest
, generateCode(minVars
), info
),
238 vShaderSuccess
: true,
239 fShaderSource
: wtu
.replaceParams(shaderType
.fragUniformTest
, generateCode(minVars
), info
),
240 fShaderSuccess
: 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;