ext_gpu_shader4: add compiler tests for everything
[piglit.git] / tests / spec / ext_framebuffer_multisample / fast-clear.c
blobc0b249fb933d4e84f354cdde396c97c43596535f
1 /*
2 * Copyright © 2015 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
24 /**
25 * \file fast-clear.c
27 * Clears a multisample texture with various formats to various
28 * different colors and then samples from it in a shader to ensure
29 * that the expected color is returned. This includes verifying that
30 * when there are components missing they are overriden to the right
31 * value (such as GL_RED should report 0 for green and blue and 1 for
32 * the alpha). The main reason to do this is that the i965 driver has
33 * various different code paths to implement a fast clear optimisation
34 * and the path taken depends on the color chosen to a certain
35 * degree.
37 * The test can take the following additional arguments:
39 * enable-fb-srgb: This will cause it to enable GL_FRAMEBUFFER_SRGB
40 * before clearing the buffer so that it can test that the color
41 * gets correctly converted to SRGB before being stored in the
42 * color buffer.
43 * single-sample: A single sample texture will be created instead.
46 #include "piglit-util-gl.h"
47 #include "../../fbo/fbo-formats.h"
49 PIGLIT_GL_TEST_CONFIG_BEGIN
51 config.supports_gl_compat_version = 21;
52 config.window_visual = PIGLIT_GL_VISUAL_RGBA | PIGLIT_GL_VISUAL_DOUBLE;
53 config.khr_no_error_support = PIGLIT_NO_ERRORS;
55 PIGLIT_GL_TEST_CONFIG_END
57 static const char
58 vertex_source[] =
59 "attribute vec4 piglit_vertex;\n"
60 "\n"
61 "void\n"
62 "main()\n"
63 "{\n"
64 " gl_Position = piglit_vertex;\n"
65 "}\n";
67 static const char
68 fragment_source_float[] =
69 "#version 130\n"
70 "%s\n"
71 "\n"
72 "uniform %s tex;\n"
73 "\n"
74 "void\n"
75 "main()\n"
76 "{\n"
77 " gl_FragColor = texelFetch(tex, ivec2(0), 0);\n"
78 "}\n";
80 static const char
81 fragment_source_int[] =
82 "#version 130\n"
83 "%s\n"
84 "\n"
85 "uniform i%s tex;\n"
86 "\n"
87 "void\n"
88 "main()\n"
89 "{\n"
90 " gl_FragColor = vec4(texelFetch(tex, ivec2(0), 0));\n"
91 "}\n";
93 static const char
94 fragment_source_uint[] =
95 "#version 130\n"
96 "%s\n"
97 "\n"
98 "uniform u%s tex;\n"
99 "\n"
100 "void\n"
101 "main()\n"
102 "{\n"
103 " gl_FragColor = vec4(texelFetch(tex, ivec2(0), 0));\n"
104 "}\n";
106 static const struct test_desc *
107 test_set = &test_sets[0];
109 static const float
110 clear_colors[][4] = {
111 { 0.0f, 0.0f, 0.0f, 0.0f },
112 { 1.0f, 1.0f, 1.0f, 1.0f },
113 { 0.0f, 0.0f, 1.0f, 0.0f },
114 { 1.0f, 0.0f, 0.0f, 1.0f },
116 { 0.25f, 0.5f, 0.75f, 1.0f },
117 { 0.75f, 0.5f, 0.25f, 0.0f },
118 { 0.5f, 0.25f, 0.75f, 0.5f },
120 { 2.0f, 3.0f, 0.5f, 1.0f },
121 { -2.0f, 0.0f, 0.25f, 1.0f },
122 { -0.5f, 0.0f, 0.25f, 1.0f },
125 struct component_sizes {
126 int r, g, b;
127 int a;
128 int l;
129 int i;
132 static GLuint prog_float, prog_int, prog_uint;
133 static GLuint result_fbo;
134 static bool enable_fb_srgb = false;
135 static bool single_sample = false;
136 static int num_samples = 2;
138 static void
139 convert_srgb_color(const struct format_desc *format,
140 float *color)
142 int i;
143 const char *format_name = get_format_name(format->internalformat);
145 /* If the texture is not an sRGB format then no conversion is
146 * needed regardless of the sRGB settings.
148 if (strstr(format_name, "SRGB") == NULL &&
149 strstr(format_name, "SLUMINANCE") == NULL)
150 return;
152 /* If GL_FRAMEBUFFER_SRGB was enabled when we did the clear
153 * then the clear color would have been converted to SRGB
154 * before being written. When it is sampled it will be
155 * converted back to linear. The two conversions cancel each
156 * other out so we don't need to do anything.
158 if (enable_fb_srgb)
159 return;
161 /* Otherwise we need to compensate for the color being
162 * converted to linear when sampled.
164 for (i = 0; i < 3; i++)
165 color[i] = piglit_srgb_to_linear(color[i]);
168 static int
169 clamp_signed(int value, int size)
171 return CLAMP(value,
172 -1 << (size - 1),
173 (int) (UINT32_MAX >> (33 - size)));
176 static unsigned int
177 clamp_unsigned(int value, int size)
179 if (value < 0)
180 return 0;
181 return CLAMP((unsigned int) value, 0, UINT32_MAX >> (32 - size));
184 static enum piglit_result
185 test_color(GLuint test_fbo,
186 int offset,
187 const struct format_desc *format,
188 GLenum clear_type,
189 const struct component_sizes *sizes,
190 const float *clear_color)
192 float expected_color[4];
193 int i;
195 glBindFramebuffer(GL_FRAMEBUFFER, test_fbo);
197 if (enable_fb_srgb)
198 glEnable(GL_FRAMEBUFFER_SRGB);
200 memcpy(expected_color, clear_color, sizeof expected_color);
202 switch (clear_type) {
203 case GL_INT: {
204 GLint clear_color_int[4];
205 for (i = 0; i < 4; i++) {
206 expected_color[i] *= 127;
207 clear_color_int[i] = expected_color[i];
209 if (prog_int == 0)
210 return PIGLIT_SKIP;
211 glUseProgram(prog_int);
212 glClearBufferiv(GL_COLOR,
213 0, /* draw buffer */
214 clear_color_int);
215 break;
217 case GL_UNSIGNED_INT: {
218 GLuint clear_color_uint[4];
219 for (i = 0; i < 4; i++) {
220 expected_color[i] *= 255;
221 clear_color_uint[i] = MAX2(expected_color[i], 0);
223 if (prog_uint == 0)
224 return PIGLIT_SKIP;
225 glUseProgram(prog_uint);
226 glClearBufferuiv(GL_COLOR,
227 0, /* draw buffer */
228 clear_color_uint);
229 break;
231 default:
232 glUseProgram(prog_float);
233 glClearColor(clear_color[0],
234 clear_color[1],
235 clear_color[2],
236 clear_color[3]);
237 glClear(GL_COLOR_BUFFER_BIT);
238 break;
241 if (enable_fb_srgb)
242 glDisable(GL_FRAMEBUFFER_SRGB);
244 switch (format->base_internal_format) {
245 case GL_ALPHA:
246 expected_color[0] = 0.0f;
247 expected_color[1] = 0.0f;
248 expected_color[2] = 0.0f;
249 break;
250 case GL_INTENSITY:
251 expected_color[1] = expected_color[0];
252 expected_color[2] = expected_color[0];
253 expected_color[3] = expected_color[0];
254 break;
255 case GL_LUMINANCE:
256 expected_color[1] = expected_color[0];
257 expected_color[2] = expected_color[0];
258 expected_color[3] = 1.0f;
259 break;
260 case GL_LUMINANCE_ALPHA:
261 expected_color[1] = expected_color[0];
262 expected_color[2] = expected_color[0];
263 break;
264 case GL_RED:
265 expected_color[1] = 0.0f;
266 expected_color[2] = 0.0f;
267 expected_color[3] = 1.0f;
268 break;
269 case GL_RG:
270 expected_color[2] = 0.0f;
271 expected_color[3] = 1.0f;
272 break;
273 case GL_RGB:
274 expected_color[3] = 1.0f;
275 break;
278 convert_srgb_color(format, expected_color);
280 if (clear_type == GL_UNSIGNED_NORMALIZED) {
281 for (i = 0; i < 4; i++) {
282 expected_color[i] =
283 CLAMP(expected_color[i], 0.0f, 1.0f);
285 } else if (clear_type == GL_SIGNED_NORMALIZED) {
286 for (i = 0; i < 4; i++) {
287 expected_color[i] =
288 CLAMP(expected_color[i], -1.0f, 1.0f);
290 } else if (clear_type == GL_INT) {
291 /* The clear colors are multiplied by 127 for integer
292 * formats so some of them will be large values. The
293 * GL spec states that out-of-range integer values
294 * written to the framebuffer will be clamped so we
295 * need to replicate this in the expected values. For
296 * example, the -2.0 color will be set to -254, and
297 * this will be clamped to -128 for an 8-bit integer
298 * surface.
300 expected_color[0] = clamp_signed(expected_color[0], sizes->r);
301 expected_color[1] = clamp_signed(expected_color[1], sizes->g);
302 expected_color[2] = clamp_signed(expected_color[2], sizes->b);
303 expected_color[3] = clamp_signed(expected_color[3], sizes->a);
304 } else if (clear_type == GL_UNSIGNED_INT) {
305 expected_color[0] = clamp_unsigned(expected_color[0], sizes->r);
306 expected_color[1] = clamp_unsigned(expected_color[1], sizes->g);
307 expected_color[2] = clamp_unsigned(expected_color[2], sizes->b);
308 expected_color[3] = clamp_unsigned(expected_color[3], sizes->a);
309 } else if (test_sets[test_index].format == ext_packed_float) {
310 /* These formats can't store negative values */
311 for (i = 0; i < 4; i++)
312 expected_color[i] = MAX2(expected_color[i], 0.0f);
315 /* Display something on the winsys FBO just so that something
316 * will be shown. This isn't used for the test results because
317 * the winsys buffer is a normalised format and some of the
318 * values we want to detect will be out of the range [0,1].
320 glBindFramebuffer(GL_FRAMEBUFFER, piglit_winsys_fbo);
321 piglit_draw_rect(offset * 16 * 2.0f / piglit_width - 1.0f,
322 -1.0f,
323 16 * 2.0f / piglit_width,
324 16 * 2.0f / piglit_height);
326 glBindFramebuffer(GL_FRAMEBUFFER, result_fbo);
327 piglit_draw_rect(-1, -1, 2, 2);
329 return piglit_probe_rect_rgba(0, 0, 1, 1, expected_color) ?
330 PIGLIT_PASS :
331 PIGLIT_FAIL;
334 static enum piglit_result
335 test_format(const struct format_desc *format)
337 enum piglit_result result = PIGLIT_PASS;
338 enum piglit_result color_result;
339 struct component_sizes sizes;
340 GLenum type_param;
341 GLenum tex_target;
342 GLenum tex_error;
343 GLint type;
344 GLuint tex;
345 GLuint fbo;
346 int i;
347 const char *name = get_format_name(format->internalformat);
349 if (format->internalformat == 3 || format->internalformat == 4)
350 return PIGLIT_SKIP;
352 /* Compressed formats aren't supported for multisampling */
353 if (strstr("COMPRESSED", name))
354 return PIGLIT_SKIP;
356 printf("Testing %s\n", name);
358 if (single_sample)
359 tex_target = GL_TEXTURE_2D;
360 else
361 tex_target = GL_TEXTURE_2D_MULTISAMPLE;
363 glGenTextures(1, &tex);
364 glBindTexture(tex_target, tex);
366 if (single_sample) {
367 glTexParameteri(tex_target,
368 GL_TEXTURE_MAG_FILTER,
369 GL_NEAREST);
370 glTexParameteri(tex_target,
371 GL_TEXTURE_MIN_FILTER,
372 GL_NEAREST);
373 glTexParameteri(tex_target,
374 GL_TEXTURE_MAX_LEVEL,
376 /* The pitch of the texture needs to at least as wide
377 * as a tile and taller than 1 pixel so that it will
378 * be y-tiled in the i965 driver. Otherwise fast
379 * clears will be disabled and the test will be
380 * pointless.
382 glTexImage2D(tex_target,
383 0, /* level */
384 format->internalformat,
385 128, 128, /* width/height */
386 0, /* border */
387 GL_RGBA, GL_UNSIGNED_BYTE,
388 NULL);
389 } else {
390 if (piglit_khr_no_error)
391 return PIGLIT_SKIP;
393 piglit_reset_gl_error();
395 /* The size doesn't matter on the i965 driver for
396 * multisample surfaces because it will always
397 * allocate an MCS buffer and so it will always do
398 * fast clears.
400 glTexImage2DMultisample(tex_target,
401 num_samples,
402 format->internalformat,
403 1, 1, /* width/height */
404 GL_FALSE /* fixed sample locations */);
405 tex_error = glGetError();
407 if (tex_error != GL_NO_ERROR) {
408 glDeleteTextures(1, &tex);
410 if (tex_error == GL_INVALID_ENUM) {
411 /* You're only supposed to pass color
412 * renderable formats to
413 * glTexImage2DMultisample.
415 printf("Format is not color renderable\n");
416 return PIGLIT_SKIP;
417 } else {
418 printf("Unexpected GL error: %s 0x%x\n",
419 piglit_get_gl_error_name(tex_error),
420 tex_error);
421 return PIGLIT_FAIL;
426 glGetTexLevelParameteriv(tex_target, 0,
427 GL_TEXTURE_LUMINANCE_SIZE, &sizes.l);
428 glGetTexLevelParameteriv(tex_target, 0,
429 GL_TEXTURE_ALPHA_SIZE, &sizes.a);
430 glGetTexLevelParameteriv(tex_target, 0,
431 GL_TEXTURE_INTENSITY_SIZE, &sizes.i);
432 glGetTexLevelParameteriv(tex_target, 0,
433 GL_TEXTURE_RED_SIZE, &sizes.r);
434 glGetTexLevelParameteriv(tex_target, 0,
435 GL_TEXTURE_GREEN_SIZE, &sizes.g);
436 glGetTexLevelParameteriv(tex_target, 0,
437 GL_TEXTURE_BLUE_SIZE, &sizes.b);
439 if (sizes.l > 0)
440 type_param = GL_TEXTURE_LUMINANCE_TYPE;
441 else if (sizes.i > 0)
442 type_param = GL_TEXTURE_INTENSITY_TYPE;
443 else if (sizes.r > 0)
444 type_param = GL_TEXTURE_RED_TYPE;
445 else if (sizes.a > 0)
446 type_param = GL_TEXTURE_ALPHA_TYPE;
447 else {
448 assert(0);
449 type_param = GL_NONE;
451 glGetTexLevelParameteriv(tex_target,
452 0, /* level */
453 type_param,
454 &type);
456 switch (format->base_internal_format) {
457 case GL_ALPHA:
458 sizes.r = sizes.g = sizes.b = 8;
459 break;
460 case GL_INTENSITY:
461 sizes.r = sizes.g = sizes.b = sizes.a = sizes.i;
462 break;
463 case GL_LUMINANCE:
464 sizes.r = sizes.g = sizes.b = sizes.l;
465 sizes.a = 8;
466 break;
467 case GL_LUMINANCE_ALPHA:
468 sizes.r = sizes.g = sizes.b = sizes.l;
469 break;
470 case GL_RED:
471 sizes.g = sizes.b = sizes.a = 8;
472 break;
473 case GL_RG:
474 sizes.b = sizes.a = 8;
475 break;
476 case GL_RGB:
477 sizes.a = 8;
478 break;
481 piglit_set_tolerance_for_bits(sizes.r, sizes.g, sizes.b, sizes.a);
483 glGenFramebuffers(1, &fbo);
484 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
485 glFramebufferTexture2D(GL_FRAMEBUFFER,
486 GL_COLOR_ATTACHMENT0,
487 tex_target,
488 tex,
490 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) ==
491 GL_FRAMEBUFFER_COMPLETE) {
492 for (i = 0; i < ARRAY_SIZE(clear_colors); i++) {
493 color_result = test_color(fbo, i, format, type, &sizes,
494 clear_colors[i]);
495 if (color_result == PIGLIT_SKIP) {
496 if (result == PIGLIT_PASS)
497 result = PIGLIT_SKIP;
498 break;
499 } else if (color_result == PIGLIT_FAIL) {
500 result = PIGLIT_FAIL;
503 } else {
504 printf("FBO not complete\n");
505 result = PIGLIT_SKIP;
508 glDeleteFramebuffers(1, &fbo);
509 glDeleteTextures(1, &tex);
511 return result;
514 enum piglit_result
515 piglit_display()
517 return fbo_formats_display(test_format);
520 static GLuint
521 build_program(const char *fragment_source)
523 GLint tex_location;
524 GLuint prog;
525 char *source;
527 (void)!asprintf(&source,
528 fragment_source,
529 single_sample ?
530 "" :
531 "#extension GL_ARB_texture_multisample : require\n",
532 single_sample ? "sampler2D" : "sampler2DMS");
534 prog = piglit_build_simple_program(vertex_source, source);
536 free(source);
538 glUseProgram(prog);
539 tex_location = glGetUniformLocation(prog, "tex");
540 glUniform1i(tex_location, 0);
542 return prog;
545 void
546 piglit_init(int argc, char **argv)
548 int test_set_index = 0;
549 GLuint rb;
550 int i;
552 for (i = 1; i < argc; i++) {
553 if (!strcmp(argv[i], "enable-fb-srgb")) {
554 enable_fb_srgb = true;
555 piglit_require_extension("GL_ARB_framebuffer_sRGB");
556 } else if (!strcmp(argv[i], "single-sample")) {
557 single_sample = true;
558 } else {
559 test_set_index = fbo_lookup_test_set(argv[i]);
563 if (!single_sample) {
564 piglit_require_extension("GL_ARB_texture_multisample");
565 /* Use the max number of samples for testing */
566 glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &num_samples);
567 printf("Testing %d samples\n", num_samples);
570 piglit_require_extension("GL_ARB_texture_float");
571 piglit_require_GLSL_version(130);
573 test_set = test_set + test_set_index;
575 fbo_formats_init_test_set(test_set_index,
576 GL_TRUE /* print_options */);
578 /* Create a floating point fbo to store the result of
579 * sampling. It is only used to store a single color sampled
580 * from the texture so it doesn't need to bigger than 1x1.
582 glGenFramebuffers(1, &result_fbo);
583 glBindFramebuffer(GL_FRAMEBUFFER, result_fbo);
584 glGenRenderbuffers(1, &rb);
585 glBindRenderbuffer(GL_RENDERBUFFER, rb);
586 glRenderbufferStorage(GL_RENDERBUFFER,
587 GL_RGBA32F,
588 1, 1 /* width/height */);
589 glFramebufferRenderbuffer(GL_FRAMEBUFFER,
590 GL_COLOR_ATTACHMENT0,
591 GL_RENDERBUFFER,
592 rb);
593 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) !=
594 GL_FRAMEBUFFER_COMPLETE) {
595 printf("Couldn't create RGBA32F FBO\n");
596 piglit_report_result(PIGLIT_SKIP);
598 glBindFramebuffer(GL_FRAMEBUFFER, piglit_winsys_fbo);
600 prog_float = build_program(fragment_source_float);
601 prog_int = build_program(fragment_source_int);
602 prog_uint = build_program(fragment_source_uint);