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>Ensure sampling-feedback detection can allow certain immutable texture uses
</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>
17 <div id=
"description"></div>
18 <div id=
"console"></div>
22 const wtu
= WebGLTestUtils
;
25 const gl
= wtu
.create3DContext(undefined, undefined, 2);
27 function* range(a
, b
) {
29 if (b
=== undefined) {
33 for (let i
= a
; i
< b
; i
+= 1) {
45 uniform sampler2D u_tex0;
47 gl_FragColor = texture2D(u_tex0, vec2(0));
51 const prog
= wtu
.loadProgram(gl
, VS
, FS
);
58 const immutTex
= gl
.createTexture();
59 immutTex
.name
= "immutTex";
60 immutTex
.immutable
= true;
61 gl
.bindTexture(gl
.TEXTURE_2D
, immutTex
);
62 gl
.texStorage2D(gl
.TEXTURE_2D
, MIPS
, gl
.RGBA8
, SIZE
, SIZE
);
64 const mutTex
= gl
.createTexture();
65 mutTex
.name
= "mutTex";
66 mutTex
.immutable
= false;
67 gl
.bindTexture(gl
.TEXTURE_2D
, mutTex
);
68 for (const mip
of range(MIPS
)) {
69 const size
= SIZE
>> mip
;
70 gl
.texImage2D(gl
.TEXTURE_2D
, mip
, gl
.RGBA8
, size
, size
, 0,
71 gl
.RGBA
, gl
.UNSIGNED_BYTE
, null);
80 ['LINEAR_MIPMAP_LINEAR',true],
81 ['LINEAR_MIPMAP_NEAREST',true],
83 ['NEAREST_MIPMAP_LINEAR',true],
84 ['NEAREST_MIPMAP_NEAREST',true],
87 const fb
= gl
.createFramebuffer();
88 gl
.bindFramebuffer(gl
.FRAMEBUFFER
, fb
);
91 mips: ${MIPS}: [0,${MIPS-1}] (inclusive)
97 for (const tex
of texs
) {
100 immutable: ${tex.immutable}`);
101 gl
.bindTexture(gl
.TEXTURE_2D
, tex
);
103 for (const level_prime_base
of range(MIPS
+1)) { // `level_base` in GLES
105 let _level_base
= level_prime_base
;
107 _level_base
= Math
.min(_level_base
, MIPS
-1);
109 const level_base
= _level_base
;
111 for (let _level_prime_max
of range(level_prime_base
-1, MIPS
+2)) { // `q` in GLES
112 if (_level_prime_max
< 0) continue;
113 if (_level_prime_max
== MIPS
+1) {
114 _level_prime_max
= 10000; // This is the default, after all!
116 const level_prime_max
= _level_prime_max
;
119 let _level_max
= level_prime_max
;
121 _level_max
= Math
.min(Math
.max(level_base
, level_prime_max
), MIPS
-1);
123 const level_max
= _level_max
;
125 const p
= Math
.floor(Math
.log2(SIZE
)) + level_base
;
126 const q
= Math
.min(p
, level_max
);
130 level_prime_base/max: [${level_prime_base}, ${level_prime_max}] (inclusive)
131 level_base/max: [${level_base}, ${level_max}] (inclusive)
133 gl
.texParameteri(gl
.TEXTURE_2D
, gl
.TEXTURE_BASE_LEVEL
,
135 gl
.texParameteri(gl
.TEXTURE_2D
, gl
.TEXTURE_MAX_LEVEL
,
138 const mipComplete
= (q
<= MIPS
-1);
140 for (const [minFilter
,useMips
] of MIN_FILTERS
) {
141 gl
.texParameteri(gl
.TEXTURE_2D
, gl
.TEXTURE_MIN_FILTER
,
145 const srcMaxSampledMip
= (useMips
? q
: level_base
);
148 const textureComplete
= (srcMaxSampledMip
<= MIPS
-1) &&
149 (level_base
<= level_max
);
151 for (const magFilter
of MAG_FILTERS
) {
154 min: ${minFilter}, mag: ${magFilter}`);
155 gl
.texParameteri(gl
.TEXTURE_2D
, gl
.TEXTURE_MAG_FILTER
,
158 for (const dstMip
of range(0,MIPS
+1)) {
161 gl
.framebufferTexture2D(gl
.FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
,
162 gl
.TEXTURE_2D
, tex
, dstMip
);
167 let fbComplete
= true;
169 // * "The width and height of `image` are non-zero"
170 fbComplete
&= (0 <= dstMip
&& dstMip
<= MIPS
-1);
172 if (!tex
.immutable
) { // "...does not name an immutable-format texture..."
173 // * "...the value of [level] must be in the range `[level_base, q]`"
174 fbComplete
&= (level_base
<= dstMip
&& dstMip
<= q
);
176 // * "...the value of [level] is not `level_base`, then the texture must be mipmap complete"
177 if (dstMip
!= level_base
) {
178 fbComplete
&= mipComplete
;
185 let expectStatus
= gl
.FRAMEBUFFER_COMPLETE
;
188 let samplingFeedback
= (level_base
<= dstMip
&& dstMip
<= srcMaxSampledMip
);
189 if (!textureComplete
) {
190 // Incomplete textures are safe
191 samplingFeedback
= false;
193 if (samplingFeedback
) {
194 expectError
= gl
.INVALID_OPERATION
;
197 expectStatus
= gl
.FRAMEBUFFER_INCOMPLETE_ATTACHMENT
;
198 expectError
= gl
.INVALID_FRAMEBUFFER_OPERATION
;
203 wtu
.framebufferStatusShouldBe(gl
, gl
.FRAMEBUFFER
,
204 expectStatus
, `{immutable: ${tex.immutable}, level_prime_base/max: [${level_prime_base}, ${level_prime_max}], minFilter: ${minFilter}, dest: ${dstMip}}`);
206 gl
.drawArrays(gl
.POINTS
, 0, 1);
207 wtu
.glErrorShouldBe(gl
, expectError
, "after draw with texture");
216 var successfullyParsed
= true;
218 <script src=
"../../../js/js-test-post.js"></script>