ext_gpu_shader4: add compiler tests for everything
[piglit.git] / tests / spec / ext_framebuffer_multisample / interpolation.cpp
blobe57113ea56a59a9e36fc168cc98d65bd0276ab65
1 /*
2 * Copyright © 2012 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 DEALINGS
21 * IN THE SOFTWARE.
24 /**
25 * \file interpolation.cpp
27 * Verify that the implementation interpolates varyings correctly when
28 * multisampling is in use, particularly that it properly implements
29 * the "centroid" keyword.
31 * From the GLSL 1.30 spec, section 4.3.7 (Interpolation):
33 * "This paragraph only applies if interpolation is being done: If
34 * single-sampling, the value is interpolated to the pixel's
35 * center, and the centroid qualifier, if present, is ignored. If
36 * multi-sampling and the variable is not qualified with centroid,
37 * then the value must be interpolated to the pixel's center, or
38 * anywhere within the pixel, or to one of the pixel's samples. If
39 * multi-sampling and the variable is qualified with centroid,
40 * then the value must be interpolated to a point that lies in
41 * both the pixel and in the primitive being rendered, or to one
42 * of the pixel's samples that falls within the primitive. Due to
43 * the less regular location of centroids, their derivatives may
44 * be less accurate than non-centroid interpolated variables."
47 * This test accepts two command-line parameters, a value for
48 * num_samples, and a test type. The test types are as follows:
50 * - non-centroid-disabled: verify that non-centroid interpolation
51 * produces the same results when applied to a non-multisampled
52 * buffer and a multisampled buffer with GL_MULTISAMPLE disabled.
53 * This effectively verifies that non-centroid varyings are
54 * interpolated at the pixel center when single-sampling. The test
55 * uses a fragment shader that sets the red, green, and blue
56 * channels to the barycentric coordinates within each triangle.
58 * - centroid-disabled: verify that centroid interpolation produces
59 * the same results as non-centroid interpolation when applied to a
60 * multisampled buffer with GL_MULTISAMPLE disabled. This
61 * effectively verifies that centroid varyings are interpolated at
62 * the pixel center when single-sampling. This test may also be run
63 * with num_samples=0 to verify that centroid varyings work properly
64 * in non-multisampled buffers. The test uses a fragment shader
65 * that sets the red, green, and blue channels to the barycentric
66 * coordinates within each triangle.
68 * - centroid-edges: verify that centroid interpolation occurs at
69 * points that lie within the extents of the triangle, even for
70 * pixels on triangle edges, where the center of the pixel might lie
71 * outside the extents of the triangle. The test uses a fragment
72 * shader that sets the blue channel to 1.0 (so that the triangles
73 * can be seen) and the red and green channels to 1.0 if any of the
74 * centroid-interpolated barycentric coordinates is outside the
75 * range [0, 1]; except when num_samples == 0, in which case
76 * it behaves like centroid-disabled.
78 * - non-centroid-deriv: verify that the numeric derivative of a
79 * varying using non-centroid interpolation is correct, even at
80 * triangle edges. This ensures that the implementation properly
81 * handles a subtle corner case: since numeric derivatives are
82 * usually computed using finite differences between adjacent
83 * pixels, it's possible that the value of a varying at a completely
84 * uncovered pixel might be used. In effect, this tests that the
85 * values of varyings are correct on completely uncovered pixels, if
86 * those values are needed for derivatives. This test may also be
87 * run with num_samples=0 to verify that non-centroid varyings
88 * exhibit proper derivative behaviour in non-multisampled buffers.
89 * The test uses a fragment shader that sets red=dFdx(interpolated x
90 * coordinate), green=dFdy(interpolated y coordinate), and blue=1.0,
91 * with appropriate scaling applied to the red and green outputs so
92 * that the expected output is red=0.5 and green=0.5.
94 * - non-centroid-deriv-disabled: Like non-centroid-deriv, but the
95 * test is done with GL_MULTISAMPLE disabled.
97 * - centroid-deriv: verify that the numeric derivative of a vaying
98 * using centroid interpolation is within reasonable bounds. Any
99 * derivative value between 0 and twice the expected derivative is
100 * considered passing, since this is the expected error bound for a
101 * typical implementation (where derivative is computed via a finite
102 * difference of adjacent pixels, and sample points are within the
103 * pixel boundary). As with non-centroid-deriv, this test may also
104 * be run with num_samples=0 to verify that centroid varyings
105 * exhibit proper derivative behaviour in non-multisampled buffers;
106 * in this case, the error bounds are as in non-centroid-deriv,
107 * since centroid-related derivative errors are not expected. When
108 * num_samples=0, the fragment shader generates outputs as in
109 * non-centroid-deriv. Otherwise it sets the blue channel to 1.0
110 * (so that the triangles can be seen) and the red nd green channels
111 * to 1.0 if either derivative is out of tolerance.
113 * - centroid-deriv-disabled: like centroid-deriv, but the test is
114 * done with GL_MULTISAMPLE disabled, and the error bounds are as in
115 * non-centroid-deriv. The fragment shader generates outputs as in
116 * non-centroid-deriv.
118 * All test types draw an array of small triangles at various
119 * rotations, so that pixels are covered in a wide variety of
120 * patterns. In each case the rendered result is displayed on the
121 * left, and the expected result is displayed on the right for
122 * comparison.
125 #include "piglit-test-pattern.h"
126 #include "piglit-fbo.h"
127 using namespace piglit_util_fbo;
128 using namespace piglit_util_test_pattern;
130 PIGLIT_GL_TEST_CONFIG_BEGIN
132 config.supports_gl_compat_version = 10;
134 config.window_width = 512;
135 config.window_height = 256;
136 config.window_visual = PIGLIT_GL_VISUAL_DOUBLE | PIGLIT_GL_VISUAL_RGBA;
137 config.khr_no_error_support = PIGLIT_NO_ERRORS;
139 PIGLIT_GL_TEST_CONFIG_END
141 namespace {
143 const int pattern_width = 256; const int pattern_height = 256;
145 Fbo singlesampled_fbo;
146 Fbo multisampled_fbo;
150 * Test pattern that we'll use to draw the test image.
152 TestPattern *test_pattern;
156 * Test pattern that we'll use to draw the reference image.
158 TestPattern *ref_pattern;
162 * If true, we will disable GL_MULTISAMPLE while drawing the test
163 * image, and we will draw the reference image into a single-sample
164 * buffer.
166 bool disable_msaa_during_test_image = false;
170 * Fragment shader source that sets the red, green, and blue channels
171 * to the non-centroid-interpolated barycentric coordinates within
172 * each triangle.
174 const char *frag_non_centroid_barycentric =
175 "#version 120\n"
176 "varying vec3 barycentric_coords;\n"
177 "\n"
178 "void main()\n"
179 "{\n"
180 " gl_FragColor = vec4(barycentric_coords, 1.0);\n"
181 "}\n";
185 * Fragment shader source that sets the red, green, and blue channels
186 * to the centroid-interpolated barycentric coordinates within each
187 * triangle.
189 const char *frag_centroid_barycentric =
190 "#version 120\n"
191 "centroid varying vec3 barycentric_coords_centroid;\n"
192 "\n"
193 "void main()\n"
194 "{\n"
195 " gl_FragColor = vec4(barycentric_coords_centroid, 1.0);\n"
196 "}\n";
200 * Fragment shader source that sets the blue channel to 1.0, and the
201 * red and green channels to 1.0 if any of the centroid-interpolated
202 * barycentric coordinates is outside the range [0, 1].
204 const char *frag_centroid_range_check =
205 "#version 120\n"
206 "centroid varying vec3 barycentric_coords_centroid;\n"
207 "\n"
208 "void main()\n"
209 "{\n"
210 " if (any(greaterThan(barycentric_coords_centroid, vec3(1.0))) ||\n"
211 " any(lessThan(barycentric_coords_centroid, vec3(0.0))))\n"
212 " gl_FragColor = vec4(1.0);\n"
213 " else\n"
214 " gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);\n"
215 "}\n";
219 * Fragment shader source that sets red=dFdx(interpolated x
220 * coordinate), green=dFdy(interpolated y coordinate), and blue=1.0,
221 * with appropriate scaling applied to the red and green outputs so
222 * that the expected output is red=0.5 and green=0.5. The coordinates
223 * are non-centroid interpolated.
225 const char *frag_non_centroid_deriv =
226 "#version 120\n"
227 "varying vec2 pixel_pos;\n"
228 "\n"
229 "void main()\n"
230 "{\n"
231 " gl_FragColor = vec4(0.5*dFdx(pixel_pos.x),\n"
232 " 0.5*dFdy(pixel_pos.y),\n"
233 " 1.0, 1.0);\n"
234 "}\n";
238 * Fragment shader source that sets red=dFdx(interpolated x
239 * coordinate), green=dFdy(interpolated y coordinate), and blue=1.0,
240 * with appropriate scaling applied to the red and green outputs so
241 * that the expected output is red=0.5 and green=0.5. The coordinates
242 * are non-centroid interpolated.
244 const char *frag_centroid_deriv =
245 "#version 120\n"
246 "centroid varying vec2 pixel_pos_centroid;\n"
247 "\n"
248 "void main()\n"
249 "{\n"
250 " gl_FragColor = vec4(0.5*dFdx(pixel_pos_centroid.x),\n"
251 " 0.5*dFdy(pixel_pos_centroid.y),\n"
252 " 1.0, 1.0);\n"
253 "}\n";
257 * Fragment shader source that sets the blue channel to 1.0, and the
258 * red and green channels to 1.0 if either derivative is out of
259 * tolerance.
261 const char *frag_centroid_deriv_range_check =
262 "#version 120\n"
263 "centroid varying vec2 pixel_pos_centroid;\n"
264 "\n"
265 "void main()\n"
266 "{\n"
267 " if (distance(1.0, dFdx(pixel_pos_centroid.x)) > 1.0 ||\n"
268 " distance(1.0, dFdy(pixel_pos_centroid.y)) > 1.0)\n"
269 " gl_FragColor = vec4(1.0);\n"
270 " else\n"
271 " gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);\n"
272 "}\n";
276 * Fragment shader source that outputs blue (the expected output of
277 * frag_centroid_range_check and frag_centroid_deriv_range_check).
279 const char *frag_blue =
280 "#version 120\n"
281 "\n"
282 "void main()\n"
283 "{\n"
284 " gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);\n"
285 "}\n";
289 * Fragment shader source that sets red=0.5, green=0.5, and blue=1.0
290 * (the expected output of frag_non_centroid_deriv and
291 * frag_centroid_deriv).
293 const char *frag_rg_0_5 =
294 "#version 120\n"
295 "\n"
296 "void main()\n"
297 "{\n"
298 " gl_FragColor = vec4(0.5, 0.5, 1.0, 1.0);\n"
299 "}\n";
302 void
303 print_usage_and_exit(char *prog_name)
305 printf("Usage: %s <num_samples> <test_type>\n"
306 " where <test_type> is one of:\n"
307 " non-centroid-disabled: non-centroid varying, MSAA off\n"
308 " centroid-disabled: centroid varying, MSAA off\n"
309 " centroid-edges: centroid behaviour at trinagle edges\n"
310 " non-centroid-deriv: dFdx/dFdy on non-centroid varying\n"
311 " non-centroid-deriv-disabled: As above, with MSAA off\n"
312 " centroid-deriv: dFdx/dFdy on centroid varying\n"
313 " centroid-deriv-disabled: As above, with MSAA off\n",
314 prog_name);
315 piglit_report_result(PIGLIT_FAIL);
318 extern "C" void
319 piglit_init(int argc, char **argv)
321 if (argc != 3)
322 print_usage_and_exit(argv[0]);
324 /* 1st arg: num_samples */
325 char *endptr = NULL;
326 int num_samples = strtol(argv[1], &endptr, 0);
327 if (endptr != argv[1] + strlen(argv[1]))
328 print_usage_and_exit(argv[0]);
330 /* 2nd arg: test_type */
331 const char *frag; /* Fragment shader for the test image */
332 const char *ref_frag; /* Fragment shader for the reference image */
333 if (strcmp(argv[2], "non-centroid-disabled") == 0) {
334 frag = frag_non_centroid_barycentric;
335 ref_frag = frag_non_centroid_barycentric;
336 disable_msaa_during_test_image = true;
337 } else if (strcmp(argv[2], "centroid-disabled") == 0) {
338 frag = frag_centroid_barycentric;
339 ref_frag = frag_non_centroid_barycentric;
340 disable_msaa_during_test_image = true;
341 } else if (strcmp(argv[2], "centroid-edges") == 0) {
342 if (num_samples == 0) {
343 frag = frag_centroid_barycentric;
344 ref_frag = frag_non_centroid_barycentric;
345 } else {
346 frag = frag_centroid_range_check;
347 ref_frag = frag_blue;
349 } else if (strcmp(argv[2], "non-centroid-deriv") == 0) {
350 frag = frag_non_centroid_deriv;
351 ref_frag = frag_rg_0_5;
352 } else if (strcmp(argv[2], "non-centroid-deriv-disabled") == 0) {
353 frag = frag_non_centroid_deriv;
354 ref_frag = frag_rg_0_5;
355 disable_msaa_during_test_image = true;
356 } else if (strcmp(argv[2], "centroid-deriv") == 0) {
357 if (num_samples == 0) {
358 frag = frag_centroid_deriv;
359 ref_frag = frag_rg_0_5;
360 } else {
361 frag = frag_centroid_deriv_range_check;
362 ref_frag = frag_blue;
364 } else if (strcmp(argv[2], "centroid-deriv-disabled") == 0) {
365 frag = frag_centroid_deriv;
366 ref_frag = frag_rg_0_5;
367 disable_msaa_during_test_image = true;
368 } else {
369 print_usage_and_exit(argv[0]);
372 piglit_require_gl_version(21);
373 piglit_require_extension("GL_ARB_framebuffer_object");
374 piglit_require_extension("GL_ARB_vertex_array_object");
375 piglit_require_extension("GL_EXT_framebuffer_multisample");
377 /* Skip the test if num_samples > GL_MAX_SAMPLES */
378 GLint max_samples;
379 glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
380 if (num_samples > max_samples)
381 piglit_report_result(PIGLIT_SKIP);
383 singlesampled_fbo.setup(FboConfig(0, pattern_width,
384 pattern_height));
385 multisampled_fbo.setup(FboConfig(num_samples, pattern_width,
386 pattern_height));
387 test_pattern = new InterpolationTestPattern(frag);
388 test_pattern->compile();
389 ref_pattern = new InterpolationTestPattern(ref_frag);
390 ref_pattern->compile();
392 if (!piglit_check_gl_error(GL_NO_ERROR))
393 piglit_report_result(PIGLIT_FAIL);
396 extern "C" enum piglit_result
397 piglit_display()
399 bool pass = true;
401 /* Draw the test pattern into the multisampled buffer,
402 * disabling MSAA if appropriate.
404 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, multisampled_fbo.handle);
405 multisampled_fbo.set_viewport();
406 if (disable_msaa_during_test_image)
407 glDisable(GL_MULTISAMPLE);
408 test_pattern->draw(TestPattern::no_projection);
409 if (disable_msaa_during_test_image)
410 glEnable(GL_MULTISAMPLE);
412 /* Blit the test pattern to the single-sampled buffer to force
413 * a resolve.
415 glBindFramebuffer(GL_READ_FRAMEBUFFER, multisampled_fbo.handle);
416 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, singlesampled_fbo.handle);
417 glBlitFramebuffer(0, 0, pattern_width, pattern_height,
418 0, 0, pattern_width, pattern_height,
419 GL_COLOR_BUFFER_BIT, GL_NEAREST);
421 /* Blit the test pattern to the left half of the piglit window. */
422 glBindFramebuffer(GL_READ_FRAMEBUFFER, singlesampled_fbo.handle);
423 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, piglit_winsys_fbo);
424 glBlitFramebuffer(0, 0, pattern_width, pattern_height,
425 0, 0, pattern_width, pattern_height,
426 GL_COLOR_BUFFER_BIT, GL_NEAREST);
428 /* Draw the reference pattern. If we disabled GL_MULTISAMPLE
429 * while drawing the test pattern, then draw the reference
430 * pattern into a single-sampled buffer so that multisampling
431 * won't take place; otherwise draw the reference pattern into
432 * the multisampled buffer.
434 Fbo *draw_fbo = disable_msaa_during_test_image ?
435 &singlesampled_fbo : &multisampled_fbo;
436 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, draw_fbo->handle);
437 draw_fbo->set_viewport();
438 ref_pattern->draw(TestPattern::no_projection);
440 /* If we drew the reference pattern into the multisampled
441 * buffer, blit to the single-sampled buffer to force a
442 * resolve.
444 if (!disable_msaa_during_test_image) {
445 glBindFramebuffer(GL_READ_FRAMEBUFFER,
446 multisampled_fbo.handle);
447 glBindFramebuffer(GL_DRAW_FRAMEBUFFER,
448 singlesampled_fbo.handle);
449 glBlitFramebuffer(0, 0, pattern_width, pattern_height,
450 0, 0, pattern_width, pattern_height,
451 GL_COLOR_BUFFER_BIT, GL_NEAREST);
454 /* Blit the reference image to the right half of the piglit window. */
455 glBindFramebuffer(GL_READ_FRAMEBUFFER, singlesampled_fbo.handle);
456 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, piglit_winsys_fbo);
457 glBlitFramebuffer(0, 0, pattern_width, pattern_height,
458 pattern_width, 0, 2*pattern_width, pattern_height,
459 GL_COLOR_BUFFER_BIT, GL_NEAREST);
461 /* Compare the test pattern to the reference image. */
462 glBindFramebuffer(GL_READ_FRAMEBUFFER, piglit_winsys_fbo);
463 pass = piglit_probe_rect_halves_equal_rgba(0, 0, 2*pattern_width,
464 pattern_height) && pass;
466 piglit_present_results();
468 return pass ? PIGLIT_PASS : PIGLIT_FAIL;
471 } /* Anonymous namespace */