2 Copyright (c) 2022 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>GLSL texture bias test
</title>
12 <link rel=
"stylesheet" href=
"../../resources/js-test-style.css"/>
13 <script src=
"../../js/js-test-pre.js"></script>
14 <script src=
"../../js/webgl-test-utils.js"></script>
15 <script src=
"../../js/glsl-conformance-test.js"></script>
18 <div id=
"description"></div>
19 <div id=
"console"></div>
22 description("Texture bias should both function and respect limits.");
24 function runTest(gl
) {
25 // no if idea any drivers have a giant limit like 2^32 so just in case.
26 const kMaxMaxTextureSize
= 256 * 1024 * 1024;
27 const maxTextureSize
= Math
.min(kMaxMaxTextureSize
, gl
.getParameter(gl
.MAX_TEXTURE_SIZE
));
28 const maxLODs
= (Math
.log2(maxTextureSize
) | 0) + 1;
29 const maxTextureLODBias
= gl
.getParameter(gl
.MAX_TEXTURE_LOD_BIAS
);
31 debug(`maxTextureSize: ${maxTextureSize}`);
32 debug(`maxLODs: ${maxLODs}`);
33 debug(`maxTextureLODBias: ${maxTextureLODBias}`);
35 const vs
= `#version 300 es
41 (gl_VertexID / 2 + gl_VertexID / 3) % 2);
43 gl_Position = vec4(xy * 2. - 1.0, 0, 1);
47 const fs
= `#version 300 es
48 precision highp float;
49 uniform sampler2D tex;
50 uniform float biasMult;
54 vec4 texColor = texture(tex, v_uv, (gl_FragCoord.x - 0.5) * biasMult); // the color we care about
55 vec4 texelColor = texelFetch(tex, ivec2(0), int(gl_FragCoord)); // just a sanity check
56 vec4 coordColor = vec4((100.0 + gl_FragCoord.x - 0.5) / 255.0); // another sanity check
57 fragColor = mix(texColor, coordColor, step(1.0, gl_FragCoord.y)); // line < 1 = texColor, line >= 1 = coordColor
58 fragColor = mix(fragColor, texelColor, step(2.0, gl_FragCoord.y)); // line < 2 = fragColor, line >= 2 = texelColor
61 const program
= wtu
.setupProgram(gl
, [vs
, fs
]);
62 const uvMultLoc
= gl
.getUniformLocation(program
, 'uvMult');
63 const biasLoc
= gl
.getUniformLocation(program
, 'biasMult');
65 gl
.canvas
.width
= maxLODs
;
67 gl
.viewport(0, 0, maxLODs
, 3);
69 // create a texture where each mip is a different color (1, 2, 3, ...)
70 const tex
= gl
.createTexture();
71 gl
.bindTexture(gl
.TEXTURE_2D
, tex
);
72 gl
.texParameteri(gl
.TEXTURE_2D
, gl
.TEXTURE_MAG_FILTER
, gl
.NEAREST
);
73 gl
.texParameteri(gl
.TEXTURE_2D
, gl
.TEXTURE_MIN_FILTER
, gl
.NEAREST_MIPMAP_NEAREST
);
74 gl
.texStorage2D(gl
.TEXTURE_2D
, maxLODs
, gl
.RGBA8
, maxTextureSize
, 1);
77 for (let width
= maxTextureSize
; width
> 0; width
= width
/ 2 | 0) {
78 const pixels
= new Uint8Array(width
* 1 * 4);
79 pixels
.fill(level
+ 1);
80 debug(`fill mip level: ${level}, width: ${width}`);
81 gl
.texSubImage2D(gl
.TEXTURE_2D
, level
, 0, 0, width
, 1, gl
.RGBA
, gl
.UNSIGNED_BYTE
, pixels
);
82 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
);
87 // Draw each mip. Result should be [mip0, mip1, mip2, ...]
89 debug("check positive bias");
90 // set the UVs so we'd get mip level 0 for every pixel
91 gl
.uniform1f(uvMultLoc
, maxLODs
/ maxTextureSize
);
92 gl
.uniform1f(biasLoc
, 1);
93 gl
.drawArrays(gl
.TRIANGLES
, 0, 6);
95 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
);
97 const clampPlusMinus
= (v
, limit
) => Math
.min(limit
, Math
.max(-limit
, v
));
99 const checkResults
= (gl
, biasMult
) => {
100 const base
= biasMult
> 0 ? 1 : maxLODs
;
101 for (let i
= 0; i
< maxLODs
; ++i
) {
103 const expected
= new Array(4).fill(clampPlusMinus(i
* biasMult
, maxTextureLODBias
) + base
);
104 wtu
.checkCanvasRect(gl
, i
, 0, 1, 1, expected
, `should be: ${expected}`);
107 const expected
= new Array(4).fill(100 + i
);
108 wtu
.checkCanvasRect(gl
, i
, 1, 1, 1, expected
, `should be: ${expected}`);
111 const expected
= new Array(4).fill(i
+ 1);
112 wtu
.checkCanvasRect(gl
, i
, 2, 1, 1, expected
, `should be: ${expected}`);
119 // Draw each mip. Result should be [mipMax, mipMax - 1, mipMax - 2, ...]
121 debug("check negative bias");
122 // set the UVs so we'd get highest mip level (the 1x1 level mip) for every pixel
123 gl
.uniform1f(uvMultLoc
, maxLODs
);
124 gl
.uniform1f(biasLoc
, -1);
125 gl
.drawArrays(gl
.TRIANGLES
, 0, 6);
127 checkResults(gl
, -1);
132 const wtu
= WebGLTestUtils
;
134 const gl
= wtu
.create3DContext(undefined, undefined, 2);
136 var successfullyParsed
= true;
139 testFailed("Unable to initialize WebGL 2.0 context.");