content/canvas/test/webgl-conformance/conformance/resources/glsl-generator.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 GLSLGenerator = (function() {
michael@0 2
michael@0 3 var vertexShaderTemplate = [
michael@0 4 "attribute vec4 aPosition;",
michael@0 5 "",
michael@0 6 "varying vec4 vColor;",
michael@0 7 "",
michael@0 8 "$(extra)",
michael@0 9 "$(emu)",
michael@0 10 "",
michael@0 11 "void main()",
michael@0 12 "{",
michael@0 13 " gl_Position = aPosition;",
michael@0 14 " vec2 texcoord = vec2(aPosition.xy * 0.5 + vec2(0.5, 0.5));",
michael@0 15 " vec4 color = vec4(",
michael@0 16 " texcoord,",
michael@0 17 " texcoord.x * texcoord.y,",
michael@0 18 " (1.0 - texcoord.x) * texcoord.y * 0.5 + 0.5);",
michael@0 19 " $(test)",
michael@0 20 "}"
michael@0 21 ].join("\n");
michael@0 22
michael@0 23 var fragmentShaderTemplate = [
michael@0 24 "#if defined(GL_ES)",
michael@0 25 "precision mediump float;",
michael@0 26 "#endif",
michael@0 27 "",
michael@0 28 "varying vec4 vColor;",
michael@0 29 "",
michael@0 30 "$(extra)",
michael@0 31 "$(emu)",
michael@0 32 "",
michael@0 33 "void main()",
michael@0 34 "{",
michael@0 35 " $(test)",
michael@0 36 "}"
michael@0 37 ].join("\n");
michael@0 38
michael@0 39 var baseVertexShader = [
michael@0 40 "attribute vec4 aPosition;",
michael@0 41 "",
michael@0 42 "varying vec4 vColor;",
michael@0 43 "",
michael@0 44 "void main()",
michael@0 45 "{",
michael@0 46 " gl_Position = aPosition;",
michael@0 47 " vec2 texcoord = vec2(aPosition.xy * 0.5 + vec2(0.5, 0.5));",
michael@0 48 " vColor = vec4(",
michael@0 49 " texcoord,",
michael@0 50 " texcoord.x * texcoord.y,",
michael@0 51 " (1.0 - texcoord.x) * texcoord.y * 0.5 + 0.5);",
michael@0 52 "}"
michael@0 53 ].join("\n");
michael@0 54
michael@0 55 var baseFragmentShader = [
michael@0 56 "#if defined(GL_ES)",
michael@0 57 "precision mediump float;",
michael@0 58 "#endif",
michael@0 59 "varying vec4 vColor;",
michael@0 60 "",
michael@0 61 "void main()",
michael@0 62 "{",
michael@0 63 " gl_FragColor = vColor;",
michael@0 64 "}"
michael@0 65 ].join("\n");
michael@0 66
michael@0 67 var types = [
michael@0 68 { type: "float",
michael@0 69 code: [
michael@0 70 "float $(func)_emu($(args)) {",
michael@0 71 " return $(func)_base($(baseArgs));",
michael@0 72 "}"].join("\n")
michael@0 73 },
michael@0 74 { type: "vec2",
michael@0 75 code: [
michael@0 76 "vec2 $(func)_emu($(args)) {",
michael@0 77 " return vec2(",
michael@0 78 " $(func)_base($(baseArgsX)),",
michael@0 79 " $(func)_base($(baseArgsY)));",
michael@0 80 "}"].join("\n")
michael@0 81 },
michael@0 82 { type: "vec3",
michael@0 83 code: [
michael@0 84 "vec3 $(func)_emu($(args)) {",
michael@0 85 " return vec3(",
michael@0 86 " $(func)_base($(baseArgsX)),",
michael@0 87 " $(func)_base($(baseArgsY)),",
michael@0 88 " $(func)_base($(baseArgsZ)));",
michael@0 89 "}"].join("\n")
michael@0 90 },
michael@0 91 { type: "vec4",
michael@0 92 code: [
michael@0 93 "vec4 $(func)_emu($(args)) {",
michael@0 94 " return vec4(",
michael@0 95 " $(func)_base($(baseArgsX)),",
michael@0 96 " $(func)_base($(baseArgsY)),",
michael@0 97 " $(func)_base($(baseArgsZ)),",
michael@0 98 " $(func)_base($(baseArgsW)));",
michael@0 99 "}"].join("\n")
michael@0 100 }
michael@0 101 ];
michael@0 102
michael@0 103 var bvecTypes = [
michael@0 104 { type: "bvec2",
michael@0 105 code: [
michael@0 106 "bvec2 $(func)_emu($(args)) {",
michael@0 107 " return bvec2(",
michael@0 108 " $(func)_base($(baseArgsX)),",
michael@0 109 " $(func)_base($(baseArgsY)));",
michael@0 110 "}"].join("\n")
michael@0 111 },
michael@0 112 { type: "bvec3",
michael@0 113 code: [
michael@0 114 "bvec3 $(func)_emu($(args)) {",
michael@0 115 " return bvec3(",
michael@0 116 " $(func)_base($(baseArgsX)),",
michael@0 117 " $(func)_base($(baseArgsY)),",
michael@0 118 " $(func)_base($(baseArgsZ)));",
michael@0 119 "}"].join("\n")
michael@0 120 },
michael@0 121 { type: "bvec4",
michael@0 122 code: [
michael@0 123 "vec4 $(func)_emu($(args)) {",
michael@0 124 " return bvec4(",
michael@0 125 " $(func)_base($(baseArgsX)),",
michael@0 126 " $(func)_base($(baseArgsY)),",
michael@0 127 " $(func)_base($(baseArgsZ)),",
michael@0 128 " $(func)_base($(baseArgsW)));",
michael@0 129 "}"].join("\n")
michael@0 130 }
michael@0 131 ];
michael@0 132
michael@0 133 var replaceRE = /\$\((\w+)\)/g;
michael@0 134
michael@0 135 var replaceParams = function(str) {
michael@0 136 var args = arguments;
michael@0 137 return str.replace(replaceRE, function(str, p1, offset, s) {
michael@0 138 for (var ii = 1; ii < args.length; ++ii) {
michael@0 139 if (args[ii][p1] !== undefined) {
michael@0 140 return args[ii][p1];
michael@0 141 }
michael@0 142 }
michael@0 143 throw "unknown string param '" + p1 + "'";
michael@0 144 });
michael@0 145 };
michael@0 146
michael@0 147 var generateReferenceShader = function(
michael@0 148 shaderInfo, template, params, typeInfo, test) {
michael@0 149 var input = shaderInfo.input;
michael@0 150 var output = shaderInfo.output;
michael@0 151 var feature = params.feature;
michael@0 152 var testFunc = params.testFunc;
michael@0 153 var emuFunc = params.emuFunc || "";
michael@0 154 var extra = params.extra || '';
michael@0 155 var args = params.args || "$(type) value";
michael@0 156 var type = typeInfo.type;
michael@0 157 var typeCode = typeInfo.code;
michael@0 158
michael@0 159 var baseArgs = params.baseArgs || "value$(field)";
michael@0 160 var baseArgsX = replaceParams(baseArgs, {field: ".x"});
michael@0 161 var baseArgsY = replaceParams(baseArgs, {field: ".y"});
michael@0 162 var baseArgsZ = replaceParams(baseArgs, {field: ".z"});
michael@0 163 var baseArgsW = replaceParams(baseArgs, {field: ".w"});
michael@0 164 var baseArgs = replaceParams(baseArgs, {field: ""});
michael@0 165
michael@0 166 test = replaceParams(test, {
michael@0 167 input: input,
michael@0 168 output: output,
michael@0 169 func: feature + "_emu"
michael@0 170 });
michael@0 171 emuFunc = replaceParams(emuFunc, {
michael@0 172 func: feature
michael@0 173 });
michael@0 174 args = replaceParams(args, {
michael@0 175 type: type
michael@0 176 });
michael@0 177 typeCode = replaceParams(typeCode, {
michael@0 178 func: feature,
michael@0 179 type: type,
michael@0 180 args: args,
michael@0 181 baseArgs: baseArgs,
michael@0 182 baseArgsX: baseArgsX,
michael@0 183 baseArgsY: baseArgsY,
michael@0 184 baseArgsZ: baseArgsZ,
michael@0 185 baseArgsW: baseArgsW
michael@0 186 });
michael@0 187 var shader = replaceParams(template, {
michael@0 188 extra: extra,
michael@0 189 emu: emuFunc + "\n\n" + typeCode,
michael@0 190 test: test
michael@0 191 });
michael@0 192 return shader;
michael@0 193 };
michael@0 194
michael@0 195 var generateTestShader = function(
michael@0 196 shaderInfo, template, params, test) {
michael@0 197 var input = shaderInfo.input;
michael@0 198 var output = shaderInfo.output;
michael@0 199 var feature = params.feature;
michael@0 200 var testFunc = params.testFunc;
michael@0 201 var extra = params.extra || '';
michael@0 202
michael@0 203 test = replaceParams(test, {
michael@0 204 input: input,
michael@0 205 output: output,
michael@0 206 func: feature
michael@0 207 });
michael@0 208 var shader = replaceParams(template, {
michael@0 209 extra: extra,
michael@0 210 emu: '',
michael@0 211 test: test
michael@0 212 });
michael@0 213 return shader;
michael@0 214 };
michael@0 215
michael@0 216 var runFeatureTest = function(params) {
michael@0 217 if (window.initNonKhronosFramework) {
michael@0 218 window.initNonKhronosFramework(false);
michael@0 219 }
michael@0 220
michael@0 221 var wtu = WebGLTestUtils;
michael@0 222 var gridRes = params.gridRes;
michael@0 223 var vertexTolerance = params.tolerance || 0;
michael@0 224 var fragmentTolerance = vertexTolerance;
michael@0 225 if ('fragmentTolerance' in params)
michael@0 226 fragmentTolerance = params.fragmentTolerance || 0;
michael@0 227
michael@0 228 description("Testing GLSL feature: " + params.feature);
michael@0 229
michael@0 230 var width = 32;
michael@0 231 var height = 32;
michael@0 232
michael@0 233 var console = document.getElementById("console");
michael@0 234 var canvas = document.createElement('canvas');
michael@0 235 canvas.width = width;
michael@0 236 canvas.height = height;
michael@0 237 var gl = wtu.create3DContext(canvas);
michael@0 238 if (!gl) {
michael@0 239 testFailed("context does not exist");
michael@0 240 finishTest();
michael@0 241 return;
michael@0 242 }
michael@0 243
michael@0 244 var canvas2d = document.createElement('canvas');
michael@0 245 canvas2d.width = width;
michael@0 246 canvas2d.height = height;
michael@0 247 var ctx = canvas2d.getContext("2d");
michael@0 248 var imgData = ctx.getImageData(0, 0, width, height);
michael@0 249
michael@0 250 var shaderInfos = [
michael@0 251 { type: "vertex",
michael@0 252 input: "color",
michael@0 253 output: "vColor",
michael@0 254 vertexShaderTemplate: vertexShaderTemplate,
michael@0 255 fragmentShaderTemplate: baseFragmentShader,
michael@0 256 tolerance: vertexTolerance
michael@0 257 },
michael@0 258 { type: "fragment",
michael@0 259 input: "vColor",
michael@0 260 output: "gl_FragColor",
michael@0 261 vertexShaderTemplate: baseVertexShader,
michael@0 262 fragmentShaderTemplate: fragmentShaderTemplate,
michael@0 263 tolerance: fragmentTolerance
michael@0 264 }
michael@0 265 ];
michael@0 266 for (var ss = 0; ss < shaderInfos.length; ++ss) {
michael@0 267 var shaderInfo = shaderInfos[ss];
michael@0 268 var tests = params.tests;
michael@0 269 var testTypes = params.emuFuncs || (params.bvecTest ? bvecTypes : types);
michael@0 270 // Test vertex shaders
michael@0 271 for (var ii = 0; ii < tests.length; ++ii) {
michael@0 272 var type = testTypes[ii];
michael@0 273 if (params.simpleEmu) {
michael@0 274 type = {
michael@0 275 type: type.type,
michael@0 276 code: params.simpleEmu
michael@0 277 };
michael@0 278 }
michael@0 279 debug("");
michael@0 280 var str = replaceParams(params.testFunc, {
michael@0 281 func: params.feature,
michael@0 282 type: type.type,
michael@0 283 arg0: type.type
michael@0 284 });
michael@0 285 debug("Testing: " + str + " in " + shaderInfo.type + " shader");
michael@0 286
michael@0 287 var referenceVertexShaderSource = generateReferenceShader(
michael@0 288 shaderInfo,
michael@0 289 shaderInfo.vertexShaderTemplate,
michael@0 290 params,
michael@0 291 type,
michael@0 292 tests[ii]);
michael@0 293 var referenceFragmentShaderSource = generateReferenceShader(
michael@0 294 shaderInfo,
michael@0 295 shaderInfo.fragmentShaderTemplate,
michael@0 296 params,
michael@0 297 type,
michael@0 298 tests[ii]);
michael@0 299 var testVertexShaderSource = generateTestShader(
michael@0 300 shaderInfo,
michael@0 301 shaderInfo.vertexShaderTemplate,
michael@0 302 params,
michael@0 303 tests[ii]);
michael@0 304 var testFragmentShaderSource = generateTestShader(
michael@0 305 shaderInfo,
michael@0 306 shaderInfo.fragmentShaderTemplate,
michael@0 307 params,
michael@0 308 tests[ii]);
michael@0 309
michael@0 310 debug("");
michael@0 311 wtu.addShaderSource(
michael@0 312 console, "reference vertex shader", referenceVertexShaderSource);
michael@0 313 wtu.addShaderSource(
michael@0 314 console, "reference fragment shader", referenceFragmentShaderSource);
michael@0 315 wtu.addShaderSource(
michael@0 316 console, "test vertex shader", testVertexShaderSource);
michael@0 317 wtu.addShaderSource(
michael@0 318 console, "test fragment shader", testFragmentShaderSource);
michael@0 319 debug("");
michael@0 320
michael@0 321 var refData = draw(
michael@0 322 canvas, referenceVertexShaderSource, referenceFragmentShaderSource);
michael@0 323 var refImg = wtu.makeImage(canvas);
michael@0 324 if (ss == 0) {
michael@0 325 var testData = draw(
michael@0 326 canvas, testVertexShaderSource, referenceFragmentShaderSource);
michael@0 327 } else {
michael@0 328 var testData = draw(
michael@0 329 canvas, referenceVertexShaderSource, testFragmentShaderSource);
michael@0 330 }
michael@0 331 var testImg = wtu.makeImage(canvas);
michael@0 332
michael@0 333 reportResults(refData, refImg, testData, testImg, shaderInfo.tolerance);
michael@0 334 }
michael@0 335 }
michael@0 336
michael@0 337 finishTest();
michael@0 338
michael@0 339 function reportResults(refData, refImage, testData, testImage, tolerance) {
michael@0 340 var same = true;
michael@0 341 for (var yy = 0; yy < height; ++yy) {
michael@0 342 for (var xx = 0; xx < width; ++xx) {
michael@0 343 var offset = (yy * width + xx) * 4;
michael@0 344 var imgOffset = ((height - yy - 1) * width + xx) * 4;
michael@0 345 imgData.data[imgOffset + 0] = 0;
michael@0 346 imgData.data[imgOffset + 1] = 0;
michael@0 347 imgData.data[imgOffset + 2] = 0;
michael@0 348 imgData.data[imgOffset + 3] = 255;
michael@0 349 if (Math.abs(refData[offset + 0] - testData[offset + 0]) > tolerance ||
michael@0 350 Math.abs(refData[offset + 1] - testData[offset + 1]) > tolerance ||
michael@0 351 Math.abs(refData[offset + 2] - testData[offset + 2]) > tolerance ||
michael@0 352 Math.abs(refData[offset + 3] - testData[offset + 3]) > tolerance) {
michael@0 353 imgData.data[imgOffset] = 255;
michael@0 354 same = false;
michael@0 355 }
michael@0 356 }
michael@0 357 }
michael@0 358
michael@0 359 var diffImg = null;
michael@0 360 if (!same) {
michael@0 361 ctx.putImageData(imgData, 0, 0);
michael@0 362 diffImg = wtu.makeImage(canvas2d);
michael@0 363 }
michael@0 364
michael@0 365 var div = document.createElement("div");
michael@0 366 div.className = "testimages";
michael@0 367 wtu.insertImage(div, "ref", refImg);
michael@0 368 wtu.insertImage(div, "test", testImg);
michael@0 369 if (diffImg) {
michael@0 370 wtu.insertImage(div, "diff", diffImg);
michael@0 371 }
michael@0 372 div.appendChild(document.createElement('br'));
michael@0 373
michael@0 374
michael@0 375 console.appendChild(div);
michael@0 376
michael@0 377 if (!same) {
michael@0 378 testFailed("images are different");
michael@0 379 } else {
michael@0 380 testPassed("images are the same");
michael@0 381 }
michael@0 382
michael@0 383 console.appendChild(document.createElement('hr'));
michael@0 384 }
michael@0 385
michael@0 386 function draw(canvas, vsSource, fsSource) {
michael@0 387 var program = wtu.loadProgram(gl, vsSource, fsSource, testFailed);
michael@0 388
michael@0 389 var posLoc = gl.getAttribLocation(program, "aPosition");
michael@0 390 WebGLTestUtils.setupQuad(gl, gridRes, posLoc);
michael@0 391
michael@0 392 gl.useProgram(program);
michael@0 393 gl.clearColor(0, 0, 1, 1);
michael@0 394 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
michael@0 395 gl.drawElements(gl.TRIANGLES, gridRes * gridRes * 6, gl.UNSIGNED_SHORT, 0);
michael@0 396 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no errors from draw");
michael@0 397
michael@0 398 var img = new Uint8Array(width * height * 4);
michael@0 399 gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, img);
michael@0 400 return img;
michael@0 401 }
michael@0 402
michael@0 403 };
michael@0 404
michael@0 405 var runBasicTest = function(params) {
michael@0 406 if (window.initNonKhronosFramework) {
michael@0 407 window.initNonKhronosFramework(false);
michael@0 408 }
michael@0 409
michael@0 410 var wtu = WebGLTestUtils;
michael@0 411 var gridRes = params.gridRes;
michael@0 412 var vertexTolerance = params.tolerance || 0;
michael@0 413 var fragmentTolerance = vertexTolerance;
michael@0 414 if ('fragmentTolerance' in params)
michael@0 415 fragmentTolerance = params.fragmentTolerance || 0;
michael@0 416
michael@0 417 description("Testing : " + document.getElementsByTagName("title")[0].innerText);
michael@0 418
michael@0 419 var width = 32;
michael@0 420 var height = 32;
michael@0 421
michael@0 422 var console = document.getElementById("console");
michael@0 423 var canvas = document.createElement('canvas');
michael@0 424 canvas.width = width;
michael@0 425 canvas.height = height;
michael@0 426 var gl = wtu.create3DContext(canvas);
michael@0 427 if (!gl) {
michael@0 428 testFailed("context does not exist");
michael@0 429 finishTest();
michael@0 430 return;
michael@0 431 }
michael@0 432
michael@0 433 var canvas2d = document.createElement('canvas');
michael@0 434 canvas2d.width = width;
michael@0 435 canvas2d.height = height;
michael@0 436 var ctx = canvas2d.getContext("2d");
michael@0 437 var imgData = ctx.getImageData(0, 0, width, height);
michael@0 438
michael@0 439 var shaderInfos = [
michael@0 440 { type: "vertex",
michael@0 441 input: "color",
michael@0 442 output: "vColor",
michael@0 443 vertexShaderTemplate: vertexShaderTemplate,
michael@0 444 fragmentShaderTemplate: baseFragmentShader,
michael@0 445 tolerance: vertexTolerance
michael@0 446 },
michael@0 447 { type: "fragment",
michael@0 448 input: "vColor",
michael@0 449 output: "gl_FragColor",
michael@0 450 vertexShaderTemplate: baseVertexShader,
michael@0 451 fragmentShaderTemplate: fragmentShaderTemplate,
michael@0 452 tolerance: fragmentTolerance
michael@0 453 }
michael@0 454 ];
michael@0 455 for (var ss = 0; ss < shaderInfos.length; ++ss) {
michael@0 456 var shaderInfo = shaderInfos[ss];
michael@0 457 var tests = params.tests;
michael@0 458 // var testTypes = params.emuFuncs || (params.bvecTest ? bvecTypes : types);
michael@0 459 // Test vertex shaders
michael@0 460 for (var ii = 0; ii < tests.length; ++ii) {
michael@0 461 var test = tests[ii];
michael@0 462 debug("");
michael@0 463 debug("Testing: " + test.name + " in " + shaderInfo.type + " shader");
michael@0 464
michael@0 465 function genShader(shaderInfo, template, shader, subs) {
michael@0 466 shader = replaceParams(shader, subs, {
michael@0 467 input: shaderInfo.input,
michael@0 468 output: shaderInfo.output
michael@0 469 });
michael@0 470 shader = replaceParams(template, subs, {
michael@0 471 test: shader,
michael@0 472 emu: "",
michael@0 473 extra: ""
michael@0 474 });
michael@0 475 return shader;
michael@0 476 }
michael@0 477
michael@0 478 var referenceVertexShaderSource = genShader(
michael@0 479 shaderInfo,
michael@0 480 shaderInfo.vertexShaderTemplate,
michael@0 481 test.reference.shader,
michael@0 482 test.reference.subs);
michael@0 483 var referenceFragmentShaderSource = genShader(
michael@0 484 shaderInfo,
michael@0 485 shaderInfo.fragmentShaderTemplate,
michael@0 486 test.reference.shader,
michael@0 487 test.reference.subs);
michael@0 488 var testVertexShaderSource = genShader(
michael@0 489 shaderInfo,
michael@0 490 shaderInfo.vertexShaderTemplate,
michael@0 491 test.test.shader,
michael@0 492 test.test.subs);
michael@0 493 var testFragmentShaderSource = genShader(
michael@0 494 shaderInfo,
michael@0 495 shaderInfo.fragmentShaderTemplate,
michael@0 496 test.test.shader,
michael@0 497 test.test.subs);
michael@0 498
michael@0 499 debug("");
michael@0 500 wtu.addShaderSource(
michael@0 501 console, "reference vertex shader", referenceVertexShaderSource);
michael@0 502 wtu.addShaderSource(
michael@0 503 console, "reference fragment shader", referenceFragmentShaderSource);
michael@0 504 wtu.addShaderSource(
michael@0 505 console, "test vertex shader", testVertexShaderSource);
michael@0 506 wtu.addShaderSource(
michael@0 507 console, "test fragment shader", testFragmentShaderSource);
michael@0 508 debug("");
michael@0 509
michael@0 510 var refData = draw(
michael@0 511 canvas, referenceVertexShaderSource, referenceFragmentShaderSource);
michael@0 512 var refImg = wtu.makeImage(canvas);
michael@0 513 if (ss == 0) {
michael@0 514 var testData = draw(
michael@0 515 canvas, testVertexShaderSource, referenceFragmentShaderSource);
michael@0 516 } else {
michael@0 517 var testData = draw(
michael@0 518 canvas, referenceVertexShaderSource, testFragmentShaderSource);
michael@0 519 }
michael@0 520 var testImg = wtu.makeImage(canvas);
michael@0 521
michael@0 522 reportResults(refData, refImg, testData, testImg, shaderInfo.tolerance);
michael@0 523 }
michael@0 524 }
michael@0 525
michael@0 526 finishTest();
michael@0 527
michael@0 528 function reportResults(refData, refImage, testData, testImage, tolerance) {
michael@0 529 var same = true;
michael@0 530 for (var yy = 0; yy < height; ++yy) {
michael@0 531 for (var xx = 0; xx < width; ++xx) {
michael@0 532 var offset = (yy * width + xx) * 4;
michael@0 533 var imgOffset = ((height - yy - 1) * width + xx) * 4;
michael@0 534 imgData.data[imgOffset + 0] = 0;
michael@0 535 imgData.data[imgOffset + 1] = 0;
michael@0 536 imgData.data[imgOffset + 2] = 0;
michael@0 537 imgData.data[imgOffset + 3] = 255;
michael@0 538 if (Math.abs(refData[offset + 0] - testData[offset + 0]) > tolerance ||
michael@0 539 Math.abs(refData[offset + 1] - testData[offset + 1]) > tolerance ||
michael@0 540 Math.abs(refData[offset + 2] - testData[offset + 2]) > tolerance ||
michael@0 541 Math.abs(refData[offset + 3] - testData[offset + 3]) > tolerance) {
michael@0 542 imgData.data[imgOffset] = 255;
michael@0 543 same = false;
michael@0 544 }
michael@0 545 }
michael@0 546 }
michael@0 547
michael@0 548 var diffImg = null;
michael@0 549 if (!same) {
michael@0 550 ctx.putImageData(imgData, 0, 0);
michael@0 551 diffImg = wtu.makeImage(canvas2d);
michael@0 552 }
michael@0 553
michael@0 554 var div = document.createElement("div");
michael@0 555 div.className = "testimages";
michael@0 556 wtu.insertImage(div, "ref", refImg);
michael@0 557 wtu.insertImage(div, "test", testImg);
michael@0 558 if (diffImg) {
michael@0 559 wtu.insertImage(div, "diff", diffImg);
michael@0 560 }
michael@0 561 div.appendChild(document.createElement('br'));
michael@0 562
michael@0 563 console.appendChild(div);
michael@0 564
michael@0 565 if (!same) {
michael@0 566 testFailed("images are different");
michael@0 567 } else {
michael@0 568 testPassed("images are the same");
michael@0 569 }
michael@0 570
michael@0 571 console.appendChild(document.createElement('hr'));
michael@0 572 }
michael@0 573
michael@0 574 function draw(canvas, vsSource, fsSource) {
michael@0 575 var program = wtu.loadProgram(gl, vsSource, fsSource, testFailed);
michael@0 576
michael@0 577 var posLoc = gl.getAttribLocation(program, "aPosition");
michael@0 578 WebGLTestUtils.setupQuad(gl, gridRes, posLoc);
michael@0 579
michael@0 580 gl.useProgram(program);
michael@0 581 gl.clearColor(0, 0, 1, 1);
michael@0 582 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
michael@0 583 gl.drawElements(gl.TRIANGLES, gridRes * gridRes * 6, gl.UNSIGNED_SHORT, 0);
michael@0 584 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no errors from draw");
michael@0 585
michael@0 586 var img = new Uint8Array(width * height * 4);
michael@0 587 gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, img);
michael@0 588 return img;
michael@0 589 }
michael@0 590
michael@0 591 };
michael@0 592
michael@0 593 var runReferenceImageTest = function(params) {
michael@0 594 if (window.initNonKhronosFramework) {
michael@0 595 window.initNonKhronosFramework(false);
michael@0 596 }
michael@0 597
michael@0 598 var wtu = WebGLTestUtils;
michael@0 599 var gridRes = params.gridRes;
michael@0 600 var vertexTolerance = params.tolerance || 0;
michael@0 601 var fragmentTolerance = vertexTolerance;
michael@0 602 if ('fragmentTolerance' in params)
michael@0 603 fragmentTolerance = params.fragmentTolerance || 0;
michael@0 604
michael@0 605 description("Testing GLSL feature: " + params.feature);
michael@0 606
michael@0 607 var width = 32;
michael@0 608 var height = 32;
michael@0 609
michael@0 610 var console = document.getElementById("console");
michael@0 611 var canvas = document.createElement('canvas');
michael@0 612 canvas.width = width;
michael@0 613 canvas.height = height;
michael@0 614 var gl = wtu.create3DContext(canvas, { antialias: false });
michael@0 615 if (!gl) {
michael@0 616 testFailed("context does not exist");
michael@0 617 finishTest();
michael@0 618 return;
michael@0 619 }
michael@0 620
michael@0 621 var canvas2d = document.createElement('canvas');
michael@0 622 canvas2d.width = width;
michael@0 623 canvas2d.height = height;
michael@0 624 var ctx = canvas2d.getContext("2d");
michael@0 625 var imgData = ctx.getImageData(0, 0, width, height);
michael@0 626
michael@0 627 var shaderInfos = [
michael@0 628 { type: "vertex",
michael@0 629 input: "color",
michael@0 630 output: "vColor",
michael@0 631 vertexShaderTemplate: vertexShaderTemplate,
michael@0 632 fragmentShaderTemplate: baseFragmentShader,
michael@0 633 tolerance: vertexTolerance
michael@0 634 },
michael@0 635 { type: "fragment",
michael@0 636 input: "vColor",
michael@0 637 output: "gl_FragColor",
michael@0 638 vertexShaderTemplate: baseVertexShader,
michael@0 639 fragmentShaderTemplate: fragmentShaderTemplate,
michael@0 640 tolerance: fragmentTolerance
michael@0 641 }
michael@0 642 ];
michael@0 643 for (var ss = 0; ss < shaderInfos.length; ++ss) {
michael@0 644 var shaderInfo = shaderInfos[ss];
michael@0 645 var tests = params.tests;
michael@0 646 var testTypes = params.emuFuncs || (params.bvecTest ? bvecTypes : types);
michael@0 647 // Test vertex shaders
michael@0 648 for (var ii = 0; ii < tests.length; ++ii) {
michael@0 649 var type = testTypes[ii];
michael@0 650 var isVertex = (ss == 0);
michael@0 651 debug("");
michael@0 652 var str = replaceParams(params.testFunc, {
michael@0 653 func: params.feature,
michael@0 654 type: type.type,
michael@0 655 arg0: type.type
michael@0 656 });
michael@0 657 debug("Testing: " + str + " in " + shaderInfo.type + " shader");
michael@0 658
michael@0 659 var referenceVertexShaderSource = generateReferenceShader(
michael@0 660 shaderInfo,
michael@0 661 shaderInfo.vertexShaderTemplate,
michael@0 662 params,
michael@0 663 type,
michael@0 664 tests[ii].source);
michael@0 665 var referenceFragmentShaderSource = generateReferenceShader(
michael@0 666 shaderInfo,
michael@0 667 shaderInfo.fragmentShaderTemplate,
michael@0 668 params,
michael@0 669 type,
michael@0 670 tests[ii].source);
michael@0 671 var testVertexShaderSource = generateTestShader(
michael@0 672 shaderInfo,
michael@0 673 shaderInfo.vertexShaderTemplate,
michael@0 674 params,
michael@0 675 tests[ii].source);
michael@0 676 var testFragmentShaderSource = generateTestShader(
michael@0 677 shaderInfo,
michael@0 678 shaderInfo.fragmentShaderTemplate,
michael@0 679 params,
michael@0 680 tests[ii].source);
michael@0 681 var referenceTexture = generateReferenceTexture(
michael@0 682 gl,
michael@0 683 tests[ii].generator,
michael@0 684 isVertex ? gridRes : width,
michael@0 685 isVertex ? gridRes : height,
michael@0 686 isVertex);
michael@0 687
michael@0 688 debug("");
michael@0 689 wtu.addShaderSource(
michael@0 690 console, "test vertex shader", testVertexShaderSource);
michael@0 691 wtu.addShaderSource(
michael@0 692 console, "test fragment shader", testFragmentShaderSource);
michael@0 693 debug("");
michael@0 694 var refData = drawReferenceImage(canvas, referenceTexture, isVertex);
michael@0 695 var refImg = wtu.makeImage(canvas);
michael@0 696 if (isVertex) {
michael@0 697 var testData = draw(
michael@0 698 canvas, testVertexShaderSource, referenceFragmentShaderSource);
michael@0 699 } else {
michael@0 700 var testData = draw(
michael@0 701 canvas, referenceVertexShaderSource, testFragmentShaderSource);
michael@0 702 }
michael@0 703 var testImg = wtu.makeImage(canvas);
michael@0 704 var testTolerance = shaderInfo.tolerance;
michael@0 705 // Provide per-test tolerance so that we can increase it only for those desired.
michael@0 706 if ('tolerance' in tests[ii])
michael@0 707 testTolerance = tests[ii].tolerance || 0;
michael@0 708 reportResults(refData, refImg, testData, testImg, testTolerance);
michael@0 709 }
michael@0 710 }
michael@0 711
michael@0 712 finishTest();
michael@0 713
michael@0 714 function reportResults(refData, refImage, testData, testImage, tolerance) {
michael@0 715 var same = true;
michael@0 716 for (var yy = 0; yy < height; ++yy) {
michael@0 717 for (var xx = 0; xx < width; ++xx) {
michael@0 718 var offset = (yy * width + xx) * 4;
michael@0 719 var imgOffset = ((height - yy - 1) * width + xx) * 4;
michael@0 720 imgData.data[imgOffset + 0] = 0;
michael@0 721 imgData.data[imgOffset + 1] = 0;
michael@0 722 imgData.data[imgOffset + 2] = 0;
michael@0 723 imgData.data[imgOffset + 3] = 255;
michael@0 724 if (Math.abs(refData[offset + 0] - testData[offset + 0]) > tolerance ||
michael@0 725 Math.abs(refData[offset + 1] - testData[offset + 1]) > tolerance ||
michael@0 726 Math.abs(refData[offset + 2] - testData[offset + 2]) > tolerance ||
michael@0 727 Math.abs(refData[offset + 3] - testData[offset + 3]) > tolerance) {
michael@0 728 console.appendChild(document.createTextNode('at (' + xx + ',' + yy + '): ref=(' +
michael@0 729 refData[offset + 0] + ',' +
michael@0 730 refData[offset + 1] + ',' +
michael@0 731 refData[offset + 2] + ',' +
michael@0 732 refData[offset + 3] + ') test=(' +
michael@0 733 testData[offset + 0] + ',' +
michael@0 734 testData[offset + 1] + ',' +
michael@0 735 testData[offset + 2] + ',' +
michael@0 736 testData[offset + 3] + ')'));
michael@0 737 console.appendChild(document.createElement('br'));
michael@0 738
michael@0 739
michael@0 740
michael@0 741 imgData.data[imgOffset] = 255;
michael@0 742 same = false;
michael@0 743 }
michael@0 744 }
michael@0 745 }
michael@0 746
michael@0 747 var diffImg = null;
michael@0 748 if (!same) {
michael@0 749 ctx.putImageData(imgData, 0, 0);
michael@0 750 diffImg = wtu.makeImage(canvas2d);
michael@0 751 }
michael@0 752
michael@0 753 var div = document.createElement("div");
michael@0 754 div.className = "testimages";
michael@0 755 wtu.insertImage(div, "ref", refImg);
michael@0 756 wtu.insertImage(div, "test", testImg);
michael@0 757 if (diffImg) {
michael@0 758 wtu.insertImage(div, "diff", diffImg);
michael@0 759 }
michael@0 760 div.appendChild(document.createElement('br'));
michael@0 761
michael@0 762 console.appendChild(div);
michael@0 763
michael@0 764 if (!same) {
michael@0 765 testFailed("images are different");
michael@0 766 } else {
michael@0 767 testPassed("images are the same");
michael@0 768 }
michael@0 769
michael@0 770 console.appendChild(document.createElement('hr'));
michael@0 771 }
michael@0 772
michael@0 773 function draw(canvas, vsSource, fsSource) {
michael@0 774 var program = wtu.loadProgram(gl, vsSource, fsSource, testFailed);
michael@0 775
michael@0 776 var posLoc = gl.getAttribLocation(program, "aPosition");
michael@0 777 WebGLTestUtils.setupQuad(gl, gridRes, posLoc);
michael@0 778
michael@0 779 gl.useProgram(program);
michael@0 780 gl.clearColor(0, 0, 1, 1);
michael@0 781 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
michael@0 782 gl.drawElements(gl.TRIANGLES, gridRes * gridRes * 6, gl.UNSIGNED_SHORT, 0);
michael@0 783 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no errors from draw");
michael@0 784
michael@0 785 var img = new Uint8Array(width * height * 4);
michael@0 786 gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, img);
michael@0 787 return img;
michael@0 788 }
michael@0 789
michael@0 790 function drawReferenceImage(canvas, texture, isVertex) {
michael@0 791 var program;
michael@0 792 if (isVertex) {
michael@0 793 var halfTexel = 0.5 / (1.0 + gridRes);
michael@0 794 program = WebGLTestUtils.setupTexturedQuadWithTexCoords(
michael@0 795 gl, [halfTexel, halfTexel], [1.0 - halfTexel, 1.0 - halfTexel]);
michael@0 796 } else {
michael@0 797 program = WebGLTestUtils.setupTexturedQuad(gl);
michael@0 798 }
michael@0 799
michael@0 800 gl.activeTexture(gl.TEXTURE0);
michael@0 801 gl.bindTexture(gl.TEXTURE_2D, texture);
michael@0 802 var texLoc = gl.getUniformLocation(program, "tex");
michael@0 803 gl.uniform1i(texLoc, 0);
michael@0 804 wtu.drawQuad(gl);
michael@0 805 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no errors from draw");
michael@0 806
michael@0 807 var img = new Uint8Array(width * height * 4);
michael@0 808 gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, img);
michael@0 809 return img;
michael@0 810 }
michael@0 811
michael@0 812 /**
michael@0 813 * Creates and returns a texture containing the reference image for
michael@0 814 * the function being tested. Exactly how the function is evaluated,
michael@0 815 * and the size of the returned texture, depends on whether we are
michael@0 816 * testing a vertex or fragment shader. If a fragment shader, the
michael@0 817 * function is evaluated at the pixel centers. If a vertex shader,
michael@0 818 * the function is evaluated at the triangle's vertices, and the
michael@0 819 * resulting texture must be offset by half a texel during
michael@0 820 * rendering.
michael@0 821 *
michael@0 822 * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use to generate texture objects.
michael@0 823 * @param {!function(number,number,number,number): !Array.<number>} generator The reference image generator function.
michael@0 824 * @param {number} width The width of the texture to generate if testing a fragment shader; the grid resolution if testing a vertex shader.
michael@0 825 * @param {number} height The height of the texture to generate if testing a fragment shader; the grid resolution if testing a vertex shader.
michael@0 826 * @param {boolean} isVertex True if generating a reference image for a vertex shader; false if for a fragment shader.
michael@0 827 * @return {!WebGLTexture} The texture object that was generated.
michael@0 828 */
michael@0 829 function generateReferenceTexture(
michael@0 830 gl,
michael@0 831 generator,
michael@0 832 width,
michael@0 833 height,
michael@0 834 isVertex) {
michael@0 835
michael@0 836 // Note: the math in this function must match that in the vertex and
michael@0 837 // fragment shader templates above.
michael@0 838 function computeTexCoord(x) {
michael@0 839 return x * 0.5 + 0.5;
michael@0 840 }
michael@0 841
michael@0 842 function computeColor(texCoordX, texCoordY) {
michael@0 843 return [ texCoordX,
michael@0 844 texCoordY,
michael@0 845 texCoordX * texCoordY,
michael@0 846 (1.0 - texCoordX) * texCoordY * 0.5 + 0.5 ];
michael@0 847 }
michael@0 848
michael@0 849 function clamp(value, minVal, maxVal) {
michael@0 850 return Math.max(minVal, Math.min(value, maxVal));
michael@0 851 }
michael@0 852
michael@0 853 // Evaluates the function at clip coordinates (px,py), storing the
michael@0 854 // result in the array "pixel". Each channel's result is clamped
michael@0 855 // between 0 and 255.
michael@0 856 function evaluateAtClipCoords(px, py, pixel) {
michael@0 857 var tcx = computeTexCoord(px);
michael@0 858 var tcy = computeTexCoord(py);
michael@0 859
michael@0 860 var color = computeColor(tcx, tcy);
michael@0 861
michael@0 862 var output = generator(color[0], color[1], color[2], color[3]);
michael@0 863
michael@0 864 // Multiply by 256 to get even distribution for all values between 0 and 1.
michael@0 865 // Use rounding rather than truncation to more closely match the GPU's behavior.
michael@0 866 pixel[0] = clamp(Math.round(256 * output[0]), 0, 255);
michael@0 867 pixel[1] = clamp(Math.round(256 * output[1]), 0, 255);
michael@0 868 pixel[2] = clamp(Math.round(256 * output[2]), 0, 255);
michael@0 869 pixel[3] = clamp(Math.round(256 * output[3]), 0, 255);
michael@0 870 }
michael@0 871
michael@0 872 function fillFragmentReference() {
michael@0 873 var data = new Uint8Array(4 * width * height);
michael@0 874
michael@0 875 var horizTexel = 1.0 / width;
michael@0 876 var vertTexel = 1.0 / height;
michael@0 877 var halfHorizTexel = 0.5 * horizTexel;
michael@0 878 var halfVertTexel = 0.5 * vertTexel;
michael@0 879
michael@0 880 var pixel = new Array(4);
michael@0 881
michael@0 882 for (var yi = 0; yi < height; ++yi) {
michael@0 883 for (var xi = 0; xi < width; ++xi) {
michael@0 884 // The function must be evaluated at pixel centers.
michael@0 885
michael@0 886 // Compute desired position in clip space
michael@0 887 var px = -1.0 + 2.0 * (halfHorizTexel + xi * horizTexel);
michael@0 888 var py = -1.0 + 2.0 * (halfVertTexel + yi * vertTexel);
michael@0 889
michael@0 890 evaluateAtClipCoords(px, py, pixel);
michael@0 891 var index = 4 * (width * yi + xi);
michael@0 892 data[index + 0] = pixel[0];
michael@0 893 data[index + 1] = pixel[1];
michael@0 894 data[index + 2] = pixel[2];
michael@0 895 data[index + 3] = pixel[3];
michael@0 896 }
michael@0 897 }
michael@0 898
michael@0 899 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0,
michael@0 900 gl.RGBA, gl.UNSIGNED_BYTE, data);
michael@0 901 }
michael@0 902
michael@0 903 function fillVertexReference() {
michael@0 904 // We generate a texture which contains the evaluation of the
michael@0 905 // function at the vertices of the triangle mesh. It is expected
michael@0 906 // that the width and the height are identical, and equivalent
michael@0 907 // to the grid resolution.
michael@0 908 if (width != height) {
michael@0 909 throw "width and height must be equal";
michael@0 910 }
michael@0 911
michael@0 912 var texSize = 1 + width;
michael@0 913 var data = new Uint8Array(4 * texSize * texSize);
michael@0 914
michael@0 915 var step = 2.0 / width;
michael@0 916
michael@0 917 var pixel = new Array(4);
michael@0 918
michael@0 919 for (var yi = 0; yi < texSize; ++yi) {
michael@0 920 for (var xi = 0; xi < texSize; ++xi) {
michael@0 921 // The function is evaluated at the triangles' vertices.
michael@0 922
michael@0 923 // Compute desired position in clip space
michael@0 924 var px = -1.0 + (xi * step);
michael@0 925 var py = -1.0 + (yi * step);
michael@0 926
michael@0 927 evaluateAtClipCoords(px, py, pixel);
michael@0 928 var index = 4 * (texSize * yi + xi);
michael@0 929 data[index + 0] = pixel[0];
michael@0 930 data[index + 1] = pixel[1];
michael@0 931 data[index + 2] = pixel[2];
michael@0 932 data[index + 3] = pixel[3];
michael@0 933 }
michael@0 934 }
michael@0 935
michael@0 936 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, texSize, texSize, 0,
michael@0 937 gl.RGBA, gl.UNSIGNED_BYTE, data);
michael@0 938 }
michael@0 939
michael@0 940 //----------------------------------------------------------------------
michael@0 941 // Body of generateReferenceTexture
michael@0 942 //
michael@0 943
michael@0 944 var texture = gl.createTexture();
michael@0 945 gl.bindTexture(gl.TEXTURE_2D, texture);
michael@0 946 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
michael@0 947 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
michael@0 948 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
michael@0 949 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
michael@0 950
michael@0 951 if (isVertex) {
michael@0 952 fillVertexReference();
michael@0 953 } else {
michael@0 954 fillFragmentReference();
michael@0 955 }
michael@0 956
michael@0 957 return texture;
michael@0 958 }
michael@0 959 };
michael@0 960
michael@0 961 return {
michael@0 962 /**
michael@0 963 * runs a bunch of GLSL tests using the passed in parameters
michael@0 964 * The parameters are:
michael@0 965 *
michael@0 966 * feature:
michael@0 967 * the name of the function being tested (eg, sin, dot,
michael@0 968 * normalize)
michael@0 969 *
michael@0 970 * testFunc:
michael@0 971 * The prototype of function to be tested not including the
michael@0 972 * return type.
michael@0 973 *
michael@0 974 * emuFunc:
michael@0 975 * A base function that can be used to generate emulation
michael@0 976 * functions. Example for 'ceil'
michael@0 977 *
michael@0 978 * float $(func)_base(float value) {
michael@0 979 * float m = mod(value, 1.0);
michael@0 980 * return m != 0.0 ? (value + 1.0 - m) : value;
michael@0 981 * }
michael@0 982 *
michael@0 983 * args:
michael@0 984 * The arguments to the function
michael@0 985 *
michael@0 986 * baseArgs: (optional)
michael@0 987 * The arguments when a base function is used to create an
michael@0 988 * emulation function. For example 'float sign_base(float v)'
michael@0 989 * is used to implemenent vec2 sign_emu(vec2 v).
michael@0 990 *
michael@0 991 * simpleEmu:
michael@0 992 * if supplied, the code that can be used to generate all
michael@0 993 * functions for all types.
michael@0 994 *
michael@0 995 * Example for 'normalize':
michael@0 996 *
michael@0 997 * $(type) $(func)_emu($(args)) {
michael@0 998 * return value / length(value);
michael@0 999 * }
michael@0 1000 *
michael@0 1001 * gridRes: (optional)
michael@0 1002 * The resolution of the mesh to generate. The default is a
michael@0 1003 * 1x1 grid but many vertex shaders need a higher resolution
michael@0 1004 * otherwise the only values passed in are the 4 corners
michael@0 1005 * which often have the same value.
michael@0 1006 *
michael@0 1007 * tests:
michael@0 1008 * The code for each test. It is assumed the tests are for
michael@0 1009 * float, vec2, vec3, vec4 in that order.
michael@0 1010 *
michael@0 1011 * tolerance: (optional)
michael@0 1012 * Allow some tolerance in the comparisons. The tolerance is applied to
michael@0 1013 * both vertex and fragment shaders. The default tolerance is 0, meaning
michael@0 1014 * the values have to be identical.
michael@0 1015 *
michael@0 1016 * fragmentTolerance: (optional)
michael@0 1017 * Specify a tolerance which only applies to fragment shaders. The
michael@0 1018 * fragment-only tolerance will override the shared tolerance for
michael@0 1019 * fragment shaders if both are specified. Fragment shaders usually
michael@0 1020 * use mediump float precision so they sometimes require higher tolerance
michael@0 1021 * than vertex shaders which use highp by default.
michael@0 1022 */
michael@0 1023 runFeatureTest: runFeatureTest,
michael@0 1024
michael@0 1025 /*
michael@0 1026 * Runs a bunch of GLSL tests using the passed in parameters
michael@0 1027 *
michael@0 1028 * The parameters are:
michael@0 1029 *
michael@0 1030 * tests:
michael@0 1031 * Array of tests. For each test the following parameters are expected
michael@0 1032 *
michael@0 1033 * name:
michael@0 1034 * some description of the test
michael@0 1035 * reference:
michael@0 1036 * parameters for the reference shader (see below)
michael@0 1037 * test:
michael@0 1038 * parameters for the test shader (see below)
michael@0 1039 *
michael@0 1040 * The parameter for the reference and test shaders are
michael@0 1041 *
michael@0 1042 * shader: the GLSL for the shader
michael@0 1043 * subs: any substitutions you wish to define for the shader.
michael@0 1044 *
michael@0 1045 * Each shader is created from a basic template that
michael@0 1046 * defines an input and an output. You can see the
michael@0 1047 * templates at the top of this file. The input and output
michael@0 1048 * change depending on whether or not we are generating
michael@0 1049 * a vertex or fragment shader.
michael@0 1050 *
michael@0 1051 * All this code function does is a bunch of string substitutions.
michael@0 1052 * A substitution is defined by $(name). If name is found in
michael@0 1053 * the 'subs' parameter it is replaced. 4 special names exist.
michael@0 1054 *
michael@0 1055 * 'input' the input to your GLSL. Always a vec4. All change
michael@0 1056 * from 0 to 1 over the quad to be drawn.
michael@0 1057 *
michael@0 1058 * 'output' the output color. Also a vec4
michael@0 1059 *
michael@0 1060 * 'emu' a place to insert extra stuff
michael@0 1061 * 'extra' a place to insert extra stuff.
michael@0 1062 *
michael@0 1063 * You can think of the templates like this
michael@0 1064 *
michael@0 1065 * $(extra)
michael@0 1066 * $(emu)
michael@0 1067 *
michael@0 1068 * void main() {
michael@0 1069 * // do math to calculate input
michael@0 1070 * ...
michael@0 1071 *
michael@0 1072 * $(shader)
michael@0 1073 * }
michael@0 1074 *
michael@0 1075 * Your shader first has any subs you provided applied as well
michael@0 1076 * as 'input' and 'output'
michael@0 1077 *
michael@0 1078 * It is then inserted into the template which is also provided
michael@0 1079 * with your subs.
michael@0 1080 *
michael@0 1081 * gridRes: (optional)
michael@0 1082 * The resolution of the mesh to generate. The default is a
michael@0 1083 * 1x1 grid but many vertex shaders need a higher resolution
michael@0 1084 * otherwise the only values passed in are the 4 corners
michael@0 1085 * which often have the same value.
michael@0 1086 *
michael@0 1087 * tolerance: (optional)
michael@0 1088 * Allow some tolerance in the comparisons. The tolerance is applied to
michael@0 1089 * both vertex and fragment shaders. The default tolerance is 0, meaning
michael@0 1090 * the values have to be identical.
michael@0 1091 *
michael@0 1092 * fragmentTolerance: (optional)
michael@0 1093 * Specify a tolerance which only applies to fragment shaders. The
michael@0 1094 * fragment-only tolerance will override the shared tolerance for
michael@0 1095 * fragment shaders if both are specified. Fragment shaders usually
michael@0 1096 * use mediump float precision so they sometimes require higher tolerance
michael@0 1097 * than vertex shaders which use highp.
michael@0 1098 */
michael@0 1099 runBasicTest: runBasicTest,
michael@0 1100
michael@0 1101 /**
michael@0 1102 * Runs a bunch of GLSL tests using the passed in parameters. The
michael@0 1103 * expected results are computed as a reference image in JavaScript
michael@0 1104 * instead of on the GPU. The parameters are:
michael@0 1105 *
michael@0 1106 * feature:
michael@0 1107 * the name of the function being tested (eg, sin, dot,
michael@0 1108 * normalize)
michael@0 1109 *
michael@0 1110 * testFunc:
michael@0 1111 * The prototype of function to be tested not including the
michael@0 1112 * return type.
michael@0 1113 *
michael@0 1114 * args:
michael@0 1115 * The arguments to the function
michael@0 1116 *
michael@0 1117 * gridRes: (optional)
michael@0 1118 * The resolution of the mesh to generate. The default is a
michael@0 1119 * 1x1 grid but many vertex shaders need a higher resolution
michael@0 1120 * otherwise the only values passed in are the 4 corners
michael@0 1121 * which often have the same value.
michael@0 1122 *
michael@0 1123 * tests:
michael@0 1124 * Array of tests. It is assumed the tests are for float, vec2,
michael@0 1125 * vec3, vec4 in that order. For each test the following
michael@0 1126 * parameters are expected:
michael@0 1127 *
michael@0 1128 * source: the GLSL source code for the tests
michael@0 1129 *
michael@0 1130 * generator: a JavaScript function taking four parameters
michael@0 1131 * which evaluates the same function as the GLSL source,
michael@0 1132 * returning its result as a newly allocated array.
michael@0 1133 *
michael@0 1134 * tolerance: (optional) a per-test tolerance.
michael@0 1135 *
michael@0 1136 * extra: (optional)
michael@0 1137 * Extra GLSL code inserted at the top of each test's shader.
michael@0 1138 *
michael@0 1139 * tolerance: (optional)
michael@0 1140 * Allow some tolerance in the comparisons. The tolerance is applied to
michael@0 1141 * both vertex and fragment shaders. The default tolerance is 0, meaning
michael@0 1142 * the values have to be identical.
michael@0 1143 *
michael@0 1144 * fragmentTolerance: (optional)
michael@0 1145 * Specify a tolerance which only applies to fragment shaders. The
michael@0 1146 * fragment-only tolerance will override the shared tolerance for
michael@0 1147 * fragment shaders if both are specified. Fragment shaders usually
michael@0 1148 * use mediump float precision so they sometimes require higher tolerance
michael@0 1149 * than vertex shaders which use highp.
michael@0 1150 */
michael@0 1151 runReferenceImageTest: runReferenceImageTest,
michael@0 1152
michael@0 1153 none: false
michael@0 1154 };
michael@0 1155
michael@0 1156 }());
michael@0 1157

mercurial