Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / webgl / src / sdk / tests / conformance / uniforms / gl-uniform-arrays.html
1 <!--
2
3 /*
4 ** Copyright (c) 2012 The Khronos Group Inc.
5 **
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:
13 **
14 ** The above copyright notice and this permission notice shall be included
15 ** in all copies or substantial portions of the Materials.
16 **
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.
24 */
25
26 -->
27
28 <!DOCTYPE html>
29 <html>
30 <head>
31 <meta charset="utf-8">
32 <title>WebGL uniform array Conformance Tests</title>
33 <link rel="stylesheet" href="../../resources/js-test-style.css"/>
34 <script src="../../resources/js-test-pre.js"></script>
35 <script src="../resources/webgl-test-utils.js"></script>
36 </head>
37 <body>
38 <div id="description"></div>
39 <div id="console"></div>
40 <canvas id="example" width="2" height="2"> </canvas>
41 <script id="vshader" type="x-shader/x-vertex">
42     attribute vec4 a_position;
43     void main()
44     {
45         gl_Position = a_position;
46     }
47 </script>
48
49 <script id="fshader" type="x-shader/x-fragment">
50     precision mediump float;
51     uniform $(type) color[3];
52     void main()
53     {
54         gl_FragColor = vec4(color[0]$(elem), color[1]$(elem), color[2]$(elem), 1);
55     }
56 </script>
57 <script id="fshader-max" type="x-shader/x-fragment">
58     precision mediump float;
59     uniform vec4 colora[$(maxUniformVectors)];
60     void main()
61     {
62         gl_FragColor = vec4(colora[$(usedUniformVector)]);
63     }
64 </script>
65 <script id="fshader-max-ab-ab" type="x-shader/x-fragment">
66     precision mediump float;
67     uniform vec4 $(decl1);
68     uniform vec4 $(decl2);
69     void main()
70     {
71         gl_FragColor = vec4($(usage1) + $(usage2));
72     }
73 </script>
74 <script>
75 "use strict";
76 description();
77 debug("");
78 var wtu = WebGLTestUtils;
79 var gl = wtu.create3DContext("example");
80
81 var vSrc = wtu.getScript("vshader");
82 var fTemplate = wtu.getScript("fshader");
83
84 var typeInfos = [
85   { type: 'float',
86     jsTypeOf: 'number',
87     setter: 'uniform1fv',
88     elem: '',
89     numSrcValues: 3,
90     invalidSet: function(loc) {
91       gl.uniform2fv(loc, [1, 2]);
92     },
93     srcValueAsString: function(index, srcValues) {
94       return srcValues[index].toString();
95     },
96     returnValueAsString: function(value) {
97       return value === null ? 'null' : value.toString();
98     },
99     checkType: function(value) {
100       return typeof value === 'number';
101     },
102     checkValue: function(typeInfo, index, value) {
103       return typeInfo.srcValues[index] == value;
104     },
105     srcValues: [16, 15, 14],
106     srcValuesLess: [],
107     srcValuesLessMultiple: [16],
108     srcValuesMoreMultiple: [16, 15, 14, 13],
109     srcValuesNonMultiple: null,
110   },
111   { type: 'vec2',
112     jsTypeOf: 'Float32Array',
113     setter: 'uniform2fv',
114     elem: '[1]',
115     numSrcValues: 3,
116     invalidSet: function(loc) {
117       gl.uniform1fv(loc, [2]);
118     },
119     illegalSet: function(loc) {
120       gl.uniform1fv(loc, 2);
121     },
122     srcValueAsString: function(index, srcValues) {
123       return "[" + srcValues[index * 2 + 0].toString() + ", " +
124                    srcValues[index * 2 + 1].toString() + "]";
125     },
126     returnValueAsString: function(value) {
127       return value === null ? 'null' : ("[" + value[0] + ", " + value[1] + "]");
128     },
129     checkType: function(value) {
130       return value &&
131              typeof value.length === 'number' &&
132              value.length == 2;
133     },
134     checkValue: function(typeInfo, index, value) {
135       return value !== null &&
136              typeInfo.srcValues[index * 2 + 0] == value[0] &&
137              typeInfo.srcValues[index * 2 + 1] == value[1];
138     },
139     srcValues: [16, 15, 14, 13, 12, 11],
140     srcValuesLess: [16],
141     srcValuesLessMultiple: [16, 15, 14, 13],
142     srcValuesMoreMultiple: [16, 15, 14, 13, 12, 11, 10, 9],
143     srcValuesNonMultiple: [16, 15, 14, 13, 12, 11, 10],
144   },
145   { type: 'vec3',
146     jsTypeOf: 'Float32Array',
147     setter: 'uniform3fv',
148     elem: '[2]',
149     numSrcValues: 3,
150     invalidSet: function(loc) {
151       gl.uniform1fv(loc, [2]);
152     },
153     illegalSet: function(loc) {
154       gl.uniform1fv(loc, 2);
155     },
156     srcValueAsString: function(index, srcValues) {
157       return "[" + srcValues[index * 3 + 0].toString() + ", " +
158                    srcValues[index * 3 + 1].toString() + ", " +
159                    srcValues[index * 3 + 2].toString() + "]";
160     },
161     returnValueAsString: function(value) {
162       return value === null ? 'null' :
163           ("[" + value[0] + ", " + value[1] + ", " + value[2] + "]");
164     },
165     checkType: function(value) {
166       return value &&
167              typeof value.length === 'number' &&
168              value.length == 3;
169     },
170     checkValue: function(typeInfo, index, value) {
171       return value !== null &&
172              typeInfo.srcValues[index * 3 + 0] == value[0] &&
173              typeInfo.srcValues[index * 3 + 1] == value[1] &&
174              typeInfo.srcValues[index * 3 + 2] == value[2];
175     },
176     srcValues: [16, 15, 14, 13, 12, 11, 10, 9, 8],
177     srcValuesLess: [16, 15],
178     srcValuesLessMultiple: [16, 15, 14, 13, 12, 11],
179     srcValuesMoreMultiple: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2],
180     srcValuesNonMultiple: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7],
181   },
182   { type: 'vec4',
183     jsTypeOf: 'Float32Array',
184     setter: 'uniform4fv',
185     elem: '[3]',
186     numSrcValues: 3,
187     invalidSet: function(loc) {
188       gl.uniform1fv(loc, [2]);
189     },
190     illegalSet: function(loc) {
191       gl.uniform1fv(loc, 2);
192     },
193     srcValueAsString: function(index, srcValues) {
194       return "[" + srcValues[index * 4 + 0].toString() + ", " +
195                    srcValues[index * 4 + 1].toString() + ", " +
196                    srcValues[index * 4 + 2].toString() + ", " +
197                    srcValues[index * 4 + 3].toString() + "]";
198     },
199     returnValueAsString: function(value) {
200       return value === null ? 'null' :
201           ("[" + value[0] + ", " + value[1] +
202            ", " + value[2] + ", " + value[3] + "]");
203     },
204     checkType: function(value) {
205       return value &&
206              typeof value.length === 'number' &&
207              value.length == 4;
208     },
209     checkValue: function(typeInfo, index, value) {
210       return value !== null &&
211              typeInfo.srcValues[index * 4 + 0] == value[0] &&
212              typeInfo.srcValues[index * 4 + 1] == value[1] &&
213              typeInfo.srcValues[index * 4 + 2] == value[2] &&
214              typeInfo.srcValues[index * 4 + 3] == value[3];
215     },
216     srcValues: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5],
217     srcValuesLess: [16, 15, 14],
218     srcValuesLessMultiple: [16, 15, 14, 13, 12, 11, 10, 9],
219     srcValuesMoreMultiple: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
220     srcValuesNonMultiple: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4],
221   }
222 ];
223
224 for (var tt = 0; tt < typeInfos.length; ++tt) {
225   var typeInfo = typeInfos[tt];
226   debug("");
227   debug("check " + typeInfo.type);
228   var fSrc = wtu.replaceParams(fTemplate, typeInfo);
229   //debug("fSrc: " + fSrc);
230   var program = wtu.loadProgram(gl, vSrc, fSrc);
231
232   var numUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
233   assertMsg(numUniforms == 1, "1 uniform found");
234   var info = gl.getActiveUniform(program, 0);
235   assertMsg(info.name == "color[0]",
236             "uniform name is 'color[0]' not 'color' as per OpenGL ES 2.0.24 section 2.10");
237   var loc = gl.getUniformLocation(program, "color[0]");
238   var srcValues = typeInfo.srcValues;
239   var srcValuesLess = typeInfo.srcValuesLess;
240   var srcValuesLessMultiple = typeInfo.srcValuesLessMultiple;
241   var srcValuesMoreMultiple = typeInfo.srcValuesMoreMultiple;
242   var srcValuesNonMultiple = typeInfo.srcValuesNonMultiple;
243
244   // Try setting the value before using the program
245   gl[typeInfo.setter](loc, srcValues);
246   wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
247                   "should fail if there is no current program");
248
249   gl.useProgram(program);
250   gl[typeInfo.setter](loc, srcValuesLess);
251   wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
252                   "should fail with insufficient array size with gl." + typeInfo.setter);
253   if (srcValuesNonMultiple) {
254     gl[typeInfo.setter](loc, srcValuesNonMultiple);
255     wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
256                     "should fail with non-multiple array size with gl." + typeInfo.setter);
257   }
258   gl[typeInfo.setter](loc, srcValues);
259   wtu.glErrorShouldBe(gl, gl.NO_ERROR,
260                   "can set an array of uniforms with gl." + typeInfo.setter);
261   gl[typeInfo.setter](loc, srcValuesLessMultiple);
262   wtu.glErrorShouldBe(gl, gl.NO_ERROR,
263                   "can partially set an array of uniforms with gl." + typeInfo.setter + " with a smaller array");
264   gl[typeInfo.setter](loc, srcValuesMoreMultiple);
265   wtu.glErrorShouldBe(gl, gl.NO_ERROR,
266                   "can set an array of uniforms with gl." + typeInfo.setter + " with a larger array");
267
268   var values = gl.getUniform(program, loc);
269   wtu.glErrorShouldBe(gl, gl.NO_ERROR,
270                   "can call gl.getUniform");
271   assertMsg(typeInfo.checkType(values),
272             "gl.getUniform returns the correct type.");
273   for (var ii = 0; ii < typeInfo.numSrcValues; ++ii) {
274     var elemLoc = gl.getUniformLocation(program, "color[" + ii + "]");
275     wtu.glErrorShouldBe(gl, gl.NO_ERROR,
276                     "can get location of element " + ii +
277                     " of array from gl.getUniformLocation");
278     var value = gl.getUniform(program, elemLoc);
279     wtu.glErrorShouldBe(gl, gl.NO_ERROR,
280                     "can get value of element " + ii + " of array from gl.getUniform");
281     assertMsg(typeInfo.checkValue(typeInfo, ii, value),
282               "value put in (" + typeInfo.srcValueAsString(ii, srcValues) +
283               ") matches value pulled out (" +
284               typeInfo.returnValueAsString(value) + ")");
285   }
286   typeInfo.invalidSet(loc);
287   wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
288                   "using the wrong size of gl.Uniform fails");
289   var exceptionCaught = false;
290   if (typeInfo.illegalSet) {
291     try {
292       typeInfo.illegalSet(loc);
293     } catch (e) {
294       exceptionCaught = true;
295     }
296     assertMsg(exceptionCaught, "passing non-array to glUniform*fv should throw TypeError");
297   }
298
299   gl.useProgram(null);
300   wtu.glErrorShouldBe(gl, gl.NO_ERROR,
301                   "can call gl.useProgram(null)");
302 }
303
304 // This test is to test drivers the have bugs related to optimizing
305 // an array of uniforms when only 1 of those uniforms is used.
306 debug("");
307 debug("Test drivers don't over optimize unused array elements");
308 var maxUniformVectors = gl.getParameter(gl.MAX_FRAGMENT_UNIFORM_VECTORS);
309 var tests = [
310  { desc: "using last element",
311    maxUniformVectors: maxUniformVectors,
312    usedUniformVector: maxUniformVectors - 1,
313    shader: "fshader-max",
314    color: [0, 1, 0, 1],
315    arrayName: "colora",
316    extraName: "colorb",
317  },
318  { desc: "using first element",
319    maxUniformVectors: maxUniformVectors,
320    usedUniformVector: 0,
321    shader: "fshader-max",
322    color: [0, 1, 0, 1],
323    arrayName: "colora",
324    extraName: "colorb",
325  },
326 ];
327
328 // Generate test shaders. We're trying to force the driver to
329 // overflow from 1 array into the next if it optimizes. So for example if it was C
330 //
331 //   int big[4];
332 //   int little[1];
333 //   big[5] = 124;
334 //
335 // Would end up setting little[0] instead of big. Some drivers optimize
336 // where if you only use say 'big[3]' it will actually only allocate just 1 element
337 // for big.
338 //
339 // But, some drivers have a bug where the fact that they optimized big to 1 element
340 // does not get passed down to glUniform so when setting the uniform 'big[3]' they
341 // overwrite memory.
342 //
343 // If the driver crashes, yea. We found a bug. We can blacklist the driver.
344 // Otherwise we try various combinations so that setting 'little[0]' first
345 // and then setting all elements of 'big' we hope it will overwrite 'little[0]'
346 // which will show the bug and again we can blacklist the driver.
347 //
348 // We don't know how the driver will order, in memory, the various uniforms
349 // or for that matter we don't even know if they will be contiguous in memory
350 // but to hopefully expose any bugs we try various combinations.
351 //
352 //    It could be the compiler orders uniforms alphabetically.
353 //    It could be it orders them in order of declaration.
354 //    It could be it orders them in order of usage.
355 //
356 // We also test using only first element of big or just the last element of big.
357 //
358 for (var nameOrder = 0; nameOrder < 2; ++nameOrder) {
359   var name1 = nameOrder ? "colora" : "colorb";
360   var name2 = nameOrder ? "colorb" : "colora";
361   for (var last = 0; last < 2; ++last) {
362     var usedUniformVector = last ? maxUniformVectors - 2 : 0;
363     for (var declOrder = 0; declOrder < 2; ++declOrder) {
364       var bigName    = declOrder ? name1 : name2;
365       var littleName = declOrder ? name2 : name1;
366       var decl1 = bigName + "[" + (maxUniformVectors - 1) + "]";
367       var decl2 = littleName + "[1]";
368       if (declOrder) {
369         var t = decl1;
370         decl1 = decl2;
371         decl2 = t;
372       }
373       for (var usageOrder = 0; usageOrder < 2; ++usageOrder) {
374         var usage1 = bigName + "[" + usedUniformVector + "]";
375         var usage2 = littleName + "[0]";
376         if (usageOrder) {
377           var t = usage1;
378           usage1 = usage2;
379           usage2 = t;
380         }
381         var fSrc = wtu.replaceParams(wtu.getScript("fshader-max-ab-ab"), {
382           decl1: decl1,
383           decl2: decl2,
384           usage1: usage1,
385           usage2: usage2,
386         });
387         var desc = "testing: " + name1 + ":" + name2 + " using " + (last ? "last" : "first") +
388             " creating uniforms " + decl1 + " " + decl2 + " and accessing " + usage1 + " " + usage2;
389         tests.push({
390           desc: desc,
391           maxUniformVectors: maxUniformVectors - 1,
392           usedUniformVector: usedUniformVector,
393           source: fSrc,
394           color: [0, 0, 0, 1],
395           arrayName: bigName,
396           extraName: littleName,
397         });
398       }
399     }
400   }
401 }
402
403 var allRequiredUniformLocationsQueryable = true;
404 function testUniformOptimizationIssues(testIndex) {
405   var test = tests[testIndex];
406   debug("");
407   debug(test.desc);
408   var fSrc = test.source;
409   if (!fSrc) {
410     fSrc = wtu.replaceParams(wtu.getScript(test.shader), test);
411   }
412
413   var consoleElem = document.getElementById("console");
414   wtu.addShaderSource(
415       consoleElem, "vertex shader", vSrc);
416   wtu.addShaderSource(
417       consoleElem, "fragment shader", fSrc);
418
419   var program = wtu.loadProgram(gl, vSrc, fSrc);
420   gl.useProgram(program);
421
422   var colorbLocation = gl.getUniformLocation(program, test.extraName + "[0]");
423   if (colorbLocation) {
424     gl.uniform4fv(colorbLocation, [0, 1, 0, 0]);
425   }
426
427   // Set just the used uniform
428   var name = test.arrayName + "[" + test.usedUniformVector + "]";
429   var uniformLocation = gl.getUniformLocation(program, name);
430   gl.uniform4fv(uniformLocation, test.color);
431   wtu.setupIndexedQuad(gl, 1, positionLoc);
432   wtu.clearAndDrawIndexedQuad(gl, 1);
433   wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green");
434
435   // Set all the unused uniforms
436   var locations = [];
437   allRequiredUniformLocationsQueryable = true;
438   for (var ii = 0; ii < test.maxUniformVectors; ++ii) {
439     var name = test.arrayName + "[" + ii + "]";
440     var uniformLocation = gl.getUniformLocation(program, name);
441     locations.push(uniformLocation);
442     if (ii == test.usedUniformVector) {
443       continue;
444     }
445     // Locations > usedUnformVector may not exist.
446     // Locations <= usedUniformVector MUST exist.
447     if (ii <= test.usedUniformVector && (uniformLocation === undefined || uniformLocation === null)) {
448       allRequiredUniformLocationsQueryable = false;
449     }
450     gl.uniform4fv(uniformLocation, [1, 0, 0, 1]);
451   }
452   shouldBeTrue("allRequiredUniformLocationsQueryable");
453   var positionLoc = gl.getAttribLocation(program, "a_position");
454   wtu.setupIndexedQuad(gl, 1, positionLoc);
455   wtu.clearAndDrawIndexedQuad(gl, 1);
456   wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green");
457
458   // Check we can read & write each uniform.
459   // Note: uniforms past test.usedUniformVector might not exist.
460   for (var ii = 0; ii < test.maxUniformVectors; ++ii) {
461     gl.uniform4fv(locations[ii], [ii + 4, ii + 2, ii + 3, ii + 1]);
462   }
463
464   var kEpsilon = 0.01;
465   var isSame = function(v1, v2) {
466     return Math.abs(v1 - v2) < kEpsilon;
467   };
468
469   for (var ii = 0; ii < test.maxUniformVectors; ++ii) {
470     var location = locations[ii];
471     if (location) {
472       var value = gl.getUniform(program, locations[ii]);
473       if (!isSame(value[0], ii + 4) ||
474           !isSame(value[1], ii + 2) ||
475           !isSame(value[2], ii + 3) ||
476           !isSame(value[3], ii + 1)) {
477         testFailed("location: " + ii + " was not correct value");
478         break;
479       }
480     }
481   }
482 }
483
484 var testIndex = 0;
485 function runNextTest() {
486   testUniformOptimizationIssues(testIndex++);
487   if (testIndex < tests.length) {
488     setTimeout(runNextTest, 0);
489   } else {
490     wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
491     debug("");
492     finishTest();
493   }
494 }
495 runNextTest();
496
497 var successfullyParsed = true;
498
499 </script>
500 </body>
501 </html>