1 /* Copyright © 2020 Intel Corporation
3 * Permission is hereby granted, free of charge, to any person obtaining a
4 * copy of this software and associated documentation files (the "Software"),
5 * to deal in the Software without restriction, including without limitation
6 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
7 * and/or sell copies of the Software, and to permit persons to whom the
8 * Software is furnished to do so, subject to the following conditions:
10 * The above copyright notice and this permission notice (including the next
11 * paragraph) shall be included in all copies or substantial portions of the
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 * Check that drivers track the inputs to the fast-clear (clear color, format,
25 * etc.) to correctly write to a fast-cleared block.
28 #include "piglit-util-gl.h"
31 PIGLIT_GL_TEST_CONFIG_BEGIN
33 config
.supports_gl_core_version
= 43;
35 PIGLIT_GL_TEST_CONFIG_END
49 /* Returns the type of values used when specifying the clear color of a
50 * texture with a given format.
53 format_clear_value_type(GLuint format
)
61 return GL_UNSIGNED_INT
;
67 /* Clears a subregion of a texture starting from the origin. */
69 tex_sub_clear(GLuint tex
, GLuint format
, union color_value color
,
70 uint32_t w
, uint32_t h
)
72 /* Perform a scissored clear through an fbo, so that the clear color
73 * is interpreted through the texture format.
76 glGenFramebuffers(1, &fbo
);
77 glBindFramebuffer(GL_FRAMEBUFFER
, fbo
);
78 glFramebufferTexture(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
, tex
, 0);
79 glEnable(GL_FRAMEBUFFER_SRGB
);
80 glEnable(GL_SCISSOR_TEST
);
81 glScissor(0, 0, w
, h
);
83 if (format_clear_value_type(format
) == GL_UNSIGNED_INT
) {
84 glClearBufferuiv(GL_COLOR
, 0, color
.uint
);
86 assert(format_clear_value_type(format
) == GL_FLOAT
);
87 glClearBufferfv(GL_COLOR
, 0, color
.flt
);
90 glDisable(GL_SCISSOR_TEST
);
91 glDisable(GL_FRAMEBUFFER_SRGB
);
92 glDeleteFramebuffers(1, &fbo
);
101 union color_value color
;
104 /* Clears a texture's data store according to the list then probes for a
108 test_clear_list(GLuint tex_format
, uint32_t tw
, uint32_t th
, uint32_t td
,
109 uint32_t num_clears
, const struct clear_list
*list
,
110 uint32_t px
, uint32_t py
, uint32_t pz
,
111 union color_value probe_pix
)
113 /* Create the texture storage. */
115 glGenTextures(1, &tex
);
116 glBindTexture(GL_TEXTURE_2D_ARRAY
, tex
);
117 glTexStorage3D(GL_TEXTURE_2D_ARRAY
, 1, tex_format
, tw
, th
, td
);
119 /* Clear the views. */
120 for (int i
= 0; i
< num_clears
; i
++) {
122 glGenTextures(1, &view
);
123 glTextureView(view
, GL_TEXTURE_2D_ARRAY
, tex
, list
[i
].format
,
124 0, 1, list
[i
].z
, list
[i
].d
);
125 tex_sub_clear(view
, list
[i
].format
, list
[i
].color
,
126 list
[i
].w
, list
[i
].h
);
127 glDeleteTextures(1, &view
);
130 /* Inspect the texture. */
131 assert(format_clear_value_type(tex_format
) == GL_FLOAT
);
132 const bool matched_pixel
=
133 piglit_probe_texel_volume_rgba(GL_TEXTURE_2D_ARRAY
, 0,
137 /* Delete the texture. */
138 glDeleteTextures(1, &tex
);
139 return matched_pixel
;
142 #define entry(fmt, layer, width, height, depth, col) \
143 { .format = fmt, .z = layer, .w = width, . h = height, .d = depth, \
147 test_clear_after_clear(GLuint tex_format
, uint32_t tw
, uint32_t th
,
148 union color_value tex_color
,
149 GLuint view_format
, uint32_t vw
, uint32_t vh
,
150 union color_value view_color
,
151 uint32_t px
, uint32_t py
,
152 union color_value probe_pix
)
154 const struct clear_list list
[] = {
155 entry(tex_format
, 0, tw
, th
, 1, tex_color
),
156 entry(view_format
, 0, vw
, vh
, 1, view_color
)
158 return test_clear_list(tex_format
, tw
, th
, 1,
159 2, list
, px
, py
, 0, probe_pix
);
163 color_value_linear_to_srgb(const union color_value
*linear
,
164 union color_value
*srgb
)
166 for (int i
= 0; i
< 3; i
++) {
168 piglit_linear_to_srgb(linear
->flt
[i
]);
170 srgb
->flt
[3] = linear
->flt
[3];
174 piglit_init(int argc
, char **argv
)
178 const union color_value flt_one
= { .flt
= {1.0, 1.0, 1.0, 1.0} };
179 const union color_value flt_half
= { .flt
= {0.5, 0.5, 0.5, 0.5} };
180 union color_value half_linear_to_srgb
;
181 color_value_linear_to_srgb(&flt_half
, &half_linear_to_srgb
);
183 /* Depending on the clear color and view format a resolve may be
184 * needed before reading a fast-cleared block. On gen7+, such a block
185 * is implicitly read when part of it is written to. On gen12, it may
186 * also be implicitly read when all of it is written to.
188 * These additional properties should be noted for test creation:
189 * * On gen7-8, the fast-clear channel values allowed are 0 for any
190 * format, 1.0 for floats, and 1 for ints.
191 * * On gen12, all compression is lost when a texture format's
192 * bits-per-channel changes.
195 puts("Testing implicit read of partial block "
196 "(linear storage) linear -> sRGB");
197 pass
&= test_clear_after_clear(GL_RGBA8
, 32, 32, flt_half
,
198 GL_SRGB8_ALPHA8
, 1, 1, flt_one
,
201 puts("Testing implicit read of partial block "
202 "(sRGB storage) linear -> sRGB");
204 const struct clear_list list
[] = {
205 entry(GL_RGBA8
, 0, 32, 32, 1, flt_half
),
206 entry(GL_SRGB8_ALPHA8
, 0, 1, 1, 1, flt_half
),
208 pass
&= test_clear_list(GL_SRGB8_ALPHA8
, 32, 32, 1,
209 2, list
, 0, 1, 0, flt_half
);
212 puts("Testing implicit read of partial block sRGB -> linear");
213 pass
&= test_clear_after_clear(GL_SRGB8_ALPHA8
, 32, 32, flt_half
,
214 GL_RGBA8
, 1, 1, flt_one
,
215 0, 1, half_linear_to_srgb
);
217 puts("Testing implicit read of partial block sRGB -> sRGB");
218 pass
&= test_clear_after_clear(GL_SRGB8_ALPHA8
, 32, 32, flt_half
,
219 GL_SRGB8_ALPHA8
, 1, 1, flt_one
,
220 0, 1, half_linear_to_srgb
);
222 puts("Testing implicit read of partial block UNORM -> SNORM");
223 pass
&= test_clear_after_clear(GL_RGBA8
, 32, 32, flt_one
,
224 GL_RGBA8_SNORM
, 1, 1, flt_one
,
227 puts("Testing implicit read of full block UNORM -> SNORM");
228 pass
&= test_clear_after_clear(GL_RGBA8
, 32, 32, flt_one
,
229 GL_RGBA8_SNORM
, 8, 4, flt_one
,
232 puts("Testing fast-clear tracking across layers 1 -> 0 -> 1");
234 const struct clear_list list
[] = {
235 entry(GL_RGBA8
, 1, 32, 32, 1, flt_one
),
236 entry(GL_RGBA8
, 0, 32, 16, 1, flt_one
),
237 entry(GL_RGBA8
, 1, 32, 32, 1, flt_half
),
239 pass
&= test_clear_list(GL_RGBA8
, 32, 32, 2,
240 3, list
, 0, 0, 0, flt_one
);
243 puts("Testing fast-clear tracking across layers 0 -> 1 -> (0-1)");
245 const struct clear_list list
[] = {
246 entry(GL_RGBA8
, 0, 32, 32, 1, flt_one
),
247 entry(GL_RGBA8
, 1, 32, 16, 1, flt_half
),
248 entry(GL_RGBA8
, 0, 32, 32, 2, flt_one
),
250 pass
&= test_clear_list(GL_RGBA8
, 32, 32, 2,
251 3, list
, 0, 0, 1, flt_one
);
254 piglit_report_result(pass
? PIGLIT_PASS
: PIGLIT_FAIL
);