perf/pixel-rate: new pixel throughput microbenchmark
[piglit.git] / tests / fast_color_clear / write-after-clear.c
blobb3814699cd3eb16d372d38475c65439911776058
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
12 * Software.
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
20 * IN THE SOFTWARE.
23 /**
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
37 enum piglit_result
38 piglit_display(void)
40 return PIGLIT_FAIL;
44 union color_value {
45 uint32_t uint[4];
46 float flt[4];
49 /* Returns the type of values used when specifying the clear color of a
50 * texture with a given format.
52 static GLenum
53 format_clear_value_type(GLuint format)
55 switch (format) {
56 case GL_RGBA8:
57 case GL_SRGB8_ALPHA8:
58 case GL_RGBA8_SNORM:
59 return GL_FLOAT;
60 case GL_RGBA8UI:
61 return GL_UNSIGNED_INT;
62 default:
63 abort();
67 /* Clears a subregion of a texture starting from the origin. */
68 static void
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.
75 GLuint fbo;
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);
85 } else {
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);
95 struct clear_list {
96 GLuint format;
97 uint32_t z;
98 uint32_t w;
99 uint32_t h;
100 uint32_t d;
101 union color_value color;
104 /* Clears a texture's data store according to the list then probes for a
105 * specific pixel.
107 static bool
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. */
114 GLuint tex;
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++) {
121 GLuint view;
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,
134 px, py, pz, 1, 1, 1,
135 probe_pix.flt);
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, \
144 .color = col }
146 static bool
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);
162 static void
163 color_value_linear_to_srgb(const union color_value *linear,
164 union color_value *srgb)
166 for (int i = 0; i < 3; i++) {
167 srgb->flt[i] =
168 piglit_linear_to_srgb(linear->flt[i]);
170 srgb->flt[3] = linear->flt[3];
173 void
174 piglit_init(int argc, char **argv)
176 bool pass = true;
178 const union color_value flt_zero = { .flt = {0.0, 0.0, 0.0, 0.0} };
179 const union color_value flt_one = { .flt = {1.0, 1.0, 1.0, 1.0} };
180 const union color_value flt_half = { .flt = {0.5, 0.5, 0.5, 0.5} };
181 union color_value half_linear_to_srgb;
182 color_value_linear_to_srgb(&flt_half, &half_linear_to_srgb);
184 /* Depending on the clear color and view format a resolve may be
185 * needed before reading a fast-cleared block. On gen7+, such a block
186 * is implicitly read when part of it is written to. On gen12, it may
187 * also be implicitly read when all of it is written to.
189 * These additional properties should be noted for test creation:
190 * * On gen7-8, the fast-clear channel values allowed are 0 for any
191 * format, 1.0 for floats, and 1 for ints.
192 * * On gen12, all compression is lost when a texture format's
193 * bits-per-channel changes.
196 puts("Testing implicit read of partial block "
197 "(linear storage) linear -> sRGB");
198 pass &= test_clear_after_clear(GL_RGBA8, 32, 32, flt_half,
199 GL_SRGB8_ALPHA8, 1, 1, flt_one,
200 0, 1, flt_half);
202 puts("Testing implicit read of partial block "
203 "(sRGB storage) linear -> sRGB");
205 const struct clear_list list[] = {
206 entry(GL_RGBA8, 0, 32, 32, 1, flt_half),
207 entry(GL_SRGB8_ALPHA8, 0, 1, 1, 1, flt_half),
209 pass &= test_clear_list(GL_SRGB8_ALPHA8, 32, 32, 1,
210 2, list, 0, 1, 0, flt_half);
213 puts("Testing implicit read of partial block sRGB -> linear");
214 pass &= test_clear_after_clear(GL_SRGB8_ALPHA8, 32, 32, flt_half,
215 GL_RGBA8, 1, 1, flt_one,
216 0, 1, half_linear_to_srgb);
218 puts("Testing implicit read of partial block sRGB -> sRGB");
219 pass &= test_clear_after_clear(GL_SRGB8_ALPHA8, 32, 32, flt_half,
220 GL_SRGB8_ALPHA8, 1, 1, flt_one,
221 0, 1, half_linear_to_srgb);
223 puts("Testing implicit read of partial block UNORM -> SNORM");
224 pass &= test_clear_after_clear(GL_RGBA8, 32, 32, flt_one,
225 GL_RGBA8_SNORM, 1, 1, flt_one,
226 0, 1, flt_one);
228 puts("Testing implicit read of full block UNORM -> SNORM");
229 pass &= test_clear_after_clear(GL_RGBA8, 32, 32, flt_one,
230 GL_RGBA8_SNORM, 8, 4, flt_one,
231 0, 0, flt_half);
233 puts("Testing fast-clear tracking on 128Bx32 "
234 "channels zero -> channels one");
235 pass &= test_clear_after_clear(GL_RGBA8, 32, 32, flt_zero,
236 GL_RGBA8, 32, 32, flt_one,
237 0, 0, flt_one);
239 puts("Testing fast-clear tracking on 16Bx4 "
240 "channels zero -> channels one");
241 pass &= test_clear_after_clear(GL_RGBA8, 4, 4, flt_zero,
242 GL_RGBA8, 4, 4, flt_one,
243 0, 0, flt_one);
245 puts("Testing fast-clear tracking across layers 1 -> 0 -> 1");
247 const struct clear_list list[] = {
248 entry(GL_RGBA8, 1, 32, 32, 1, flt_one),
249 entry(GL_RGBA8, 0, 32, 16, 1, flt_one),
250 entry(GL_RGBA8, 1, 32, 32, 1, flt_half),
252 pass &= test_clear_list(GL_RGBA8, 32, 32, 2,
253 3, list, 0, 0, 0, flt_one);
256 puts("Testing fast-clear tracking across layers 0 -> 1 -> (0-1)");
258 const struct clear_list list[] = {
259 entry(GL_RGBA8, 0, 32, 32, 1, flt_one),
260 entry(GL_RGBA8, 1, 32, 16, 1, flt_half),
261 entry(GL_RGBA8, 0, 32, 32, 2, flt_one),
263 pass &= test_clear_list(GL_RGBA8, 32, 32, 2,
264 3, list, 0, 0, 1, flt_one);
267 piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL);