arb_program_interface_query: set vs_input2[1][0] as valid name
[piglit.git] / tests / spec / arb_sample_shading / execution / samplemask.cpp
blob5f16d7f1a7c8cc1d190781aecbce1da4debfc71c
1 /*
2 * Copyright 2017 Advanced Micro Devices, Inc.
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 FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
24 /** \file samplemask.c
26 * Test two properties of gl_SampleMask and gl_SampleMaskIn for different
27 * sample rates, while rendering a slightly off-center triangle fan that
28 * covers the entire window, to thoroughly exercise cases where pixels are
29 * partially covered:
31 * 1. Setting all bits of gl_SampleMask in all fragment shader invocations will
32 * cause all samples to be written exactly once. I.e., setting
33 * bits outside the rasterization coverage has no effect.
34 * 2. The bits of gl_SampleMaskIn over all fragment shader invocations form a
35 * partition of the set of samples. This subtest requires
36 * ARB_shader_atomic_counters to disambiguate between fragment shader
37 * invocations. (Also verifies sampleID is 0 when msaa is disabled.)
38 * Additionally, there's a test to just verify gl_SampleMaskIn is 1 when
39 * msaa is disabled (regardless of per-sample frequency shader or sample
40 * shading). (Omitted from test 2 because it's difficult to track down
41 * what's going wrong if drivers fail too many parts of the test.)
43 * The sample rate is controlled in one of two ways: Either glMinSampleShading
44 * or a fragment shader variant that uses gl_SampleID is used.
47 #include "piglit-fbo.h"
49 using namespace piglit_util_fbo;
51 /* Produce lots of very narrow triangles, but some fully covered pixels as well. */
52 #define WINDOW_SIZE 256
53 #define VERTICES_PER_EDGE 80
55 PIGLIT_GL_TEST_CONFIG_BEGIN
57 config.supports_gl_core_version = 31;
59 config.window_width = WINDOW_SIZE;
60 config.window_height = WINDOW_SIZE;
61 config.window_visual = PIGLIT_GL_VISUAL_DOUBLE | PIGLIT_GL_VISUAL_RGBA;
62 config.khr_no_error_support = PIGLIT_NO_ERRORS;
64 PIGLIT_GL_TEST_CONFIG_END
66 #define STR(x) #x
67 #define STRINGIFY(x) STR(x)
69 enum rate_mode {
70 rate_mode_sampleshading,
71 rate_mode_sampleid,
72 rate_mode_sampleid_noms,
75 static int num_samples;
76 static int actual_num_samples;
77 static bool partition_check_supported;
78 static bool mask_in_one_supported;
79 static const char *procname;
80 static const char *testname;
81 static const char *sample_rate;
82 static unsigned prog_fix_sample_mask[2];
83 static unsigned prog_fix_check;
84 static unsigned prog_mask_in_one[2];
85 static unsigned prog_partition_write[2];
86 static unsigned prog_partition_check;
87 static unsigned prog_partition_check_have_sampleid;
88 static unsigned prog_partition_check_msaa_disabled;
89 static Fbo ms_fbo;
90 static Fbo ms_ifbo;
92 static void
93 print_usage_and_exit(const char *prog_name)
95 printf("Usage: %s <num_samples> <rate> {fix|partition|mask_in_one|all}\n"
96 "where <rate> is either a floating point MinSampleShading value\n"
97 " or 'sample', 'noms', or 'all'\n",
98 prog_name);
99 piglit_report_result(PIGLIT_FAIL);
102 static void
103 build_program_variants(unsigned prog[2], const char *vert, const char *frag_template)
105 char *frag;
107 if (asprintf(&frag, frag_template, "0") < 0)
108 piglit_report_result(PIGLIT_FAIL);
109 prog[0] = piglit_build_simple_program(vert, frag);
110 free(frag);
112 if (asprintf(&frag, frag_template, "gl_SampleID") < 0)
113 piglit_report_result(PIGLIT_FAIL);
114 prog[1] = piglit_build_simple_program(vert, frag);
115 free(frag);
118 static void
119 compile_shaders(void)
121 static const char vert_passthrough[] =
122 "#version 130\n"
123 "in vec4 piglit_vertex;\n"
124 "void main()\n"
125 "{\n"
126 " gl_Position = piglit_vertex;\n"
127 "}\n";
128 static const char vert_fan[] =
129 "#version 130\n"
130 "void main()\n"
131 "{\n"
132 /* Calculate vertices of the triangle fan based on gl_VertexID */
133 " if (gl_VertexID == 0) {\n"
134 " gl_Position = vec4(0.01, 0.011, 0, 1);\n"
135 " } else {\n"
136 " int edge = ((gl_VertexID - 1) / " STRINGIFY(VERTICES_PER_EDGE) ") % 4;\n"
137 " int vertex = (gl_VertexID - 1) % " STRINGIFY(VERTICES_PER_EDGE) ";\n"
138 " float t = 2.0 / " STRINGIFY(VERTICES_PER_EDGE) " * vertex;\n"
139 " if (edge == 0)\n"
140 " gl_Position = vec4(-1 + t, -1, 0, 1);\n"
141 " else if (edge == 1)\n"
142 " gl_Position = vec4(1, -1 + t, 0, 1);\n"
143 " else if (edge == 2)\n"
144 " gl_Position = vec4(1 - t, 1, 0, 1);\n"
145 " else\n"
146 " gl_Position = vec4(-1, 1 - t, 0, 1);\n"
147 " }\n"
148 "}\n";
150 static const char frag_fix_sample_mask[] =
151 "#version 130\n"
152 "#extension GL_ARB_sample_shading : enable\n"
153 "out vec4 out_color;\n"
154 "void main()\n"
155 "{\n"
156 " gl_SampleMask[0] = ~0;\n"
157 " out_color = vec4(0.1, 0.0, %s, 0.0);\n"
158 "}\n";
159 static const char frag_fix_check[] =
160 "#version 130\n"
161 "#extension GL_ARB_texture_multisample : require\n"
162 "uniform sampler2DMS tex;\n"
163 "uniform int num_samples;\n"
164 "out vec4 out_color;\n"
165 "void main()\n"
166 "{\n"
167 " out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
168 " for (int i = 0; i < num_samples; ++i) {\n"
169 " float v = texelFetch(tex, ivec2(gl_FragCoord.xy), i).x;\n"
170 " if (abs(v - 0.1) > 0.01)\n"
171 " out_color = vec4(1.0, float(i) / 255, v, 0.0);\n"
172 " }\n"
173 "}\n";
175 static const char frag_mask_in_one[] =
176 "#version 150\n"
177 "#extension GL_ARB_gpu_shader5 : enable\n"
178 "#extension GL_ARB_sample_shading : enable\n"
179 "out vec4 out_color;\n"
180 "void main()\n"
181 "{\n"
182 " out_color = vec4(float(gl_SampleMaskIn[0]) / 10.0, 0.0, %s, 0.0);\n"
183 "}\n";
185 static const char frag_partition_write[] =
186 "#version 150\n"
187 "#extension GL_ARB_gpu_shader5 : enable\n"
188 "#extension GL_ARB_sample_shading : enable\n"
189 "#extension GL_ARB_shader_atomic_counters : enable\n"
190 "layout(binding = 0, offset = 0) uniform atomic_uint counter;\n"
191 "out ivec4 out_color;\n"
192 "void main()\n"
193 "{\n"
194 " int invocation = int(atomicCounterIncrement(counter));\n"
195 " out_color = ivec4(gl_SampleMaskIn[0], invocation, %s, 0);\n"
196 "}\n";
197 static const char frag_partition_check[] =
198 "#version 130\n"
199 "#extension GL_ARB_texture_multisample : require\n"
200 "uniform isampler2DMS tex;\n"
201 "uniform int num_samples;\n"
202 "uniform bool have_sampleid;\n"
203 "uniform bool msaa_disabled;\n"
204 "out vec4 out_color;\n"
205 "void main()\n"
206 "{\n"
207 " out_color = vec4(0, 1, 0, 1);\n"
208 " for (int i = 0; i < num_samples; ++i) {\n"
209 " ivec4 di = texelFetch(tex, ivec2(gl_FragCoord.xy), i);\n"
210 " if (msaa_disabled) {\n"
211 " /* omit di.x == 1 test here, drivers fail multiple parts already... */\n"
212 " if (di.z != 0)\n"
213 " out_color = vec4(0.2, float(i) / 255, float(di.z) / 255, 0);\n"
214 " } else {\n"
215 " if ((di.x & (1 << i)) == 0)\n"
216 " out_color = vec4(0.1, float(i) / 255, float(di.x) / 255, 0);\n"
217 " if (have_sampleid && di.z != i)\n"
218 " out_color = vec4(0.2, float(i) / 255, float(di.z) / 255, 0);\n"
219 " };\n"
220 " for (int j = i + 1; j < num_samples; ++j) {\n"
221 " ivec2 dj = texelFetch(tex, ivec2(gl_FragCoord.xy), j).xy;\n"
222 " bool overlap = (di.x & dj.x) != 0;\n"
223 " bool equal = di.x == dj.x;\n"
224 " bool same_invoc = di.y == dj.y;\n"
225 " if (same_invoc && !equal)\n"
226 " out_color = vec4(0.5, float(i) / 255, float(j) / 255, 0);\n"
227 " if (!same_invoc && overlap)\n"
228 " out_color = vec4(0.6, float(i) / 255, float(j) / 255, 0);\n"
229 " }\n"
230 " }\n"
231 "}\n";
233 build_program_variants(prog_fix_sample_mask, vert_fan, frag_fix_sample_mask);
234 prog_fix_check = piglit_build_simple_program(vert_passthrough, frag_fix_check);
235 glUseProgram(prog_fix_check);
236 glUniform1i(glGetUniformLocation(prog_fix_check, "tex"), 0);
237 glUniform1i(glGetUniformLocation(prog_fix_check, "num_samples"), actual_num_samples);
239 if (mask_in_one_supported) {
240 build_program_variants(prog_mask_in_one, vert_fan, frag_mask_in_one);
243 if (partition_check_supported) {
244 build_program_variants(prog_partition_write, vert_fan, frag_partition_write);
245 prog_partition_check = piglit_build_simple_program(vert_passthrough, frag_partition_check);
246 glUseProgram(prog_partition_check);
247 glUniform1i(glGetUniformLocation(prog_partition_check, "tex"), 0);
248 glUniform1i(glGetUniformLocation(prog_partition_check, "num_samples"),
249 actual_num_samples);
250 prog_partition_check_have_sampleid =
251 glGetUniformLocation(prog_partition_check, "have_sampleid");
252 prog_partition_check_msaa_disabled =
253 glGetUniformLocation(prog_partition_check, "msaa_disabled");
257 static void
258 draw_fan(enum rate_mode mode, float sample_rate, bool msaa_force_disable)
260 if (mode == rate_mode_sampleid_noms || msaa_force_disable) {
261 glDisable(GL_MULTISAMPLE);
263 if (mode == rate_mode_sampleshading) {
264 glEnable(GL_SAMPLE_SHADING);
265 glMinSampleShading(sample_rate);
267 glDrawArrays(GL_TRIANGLE_FAN, 0, 2 + 4 * VERTICES_PER_EDGE);
268 glDisable(GL_SAMPLE_SHADING);
269 glEnable(GL_MULTISAMPLE);
272 static enum piglit_result
273 test_fix(enum rate_mode mode, float sample_rate)
275 glClearColor(0.0, 0.0, 0.0, 0.0);
277 /* 1. Draw everything with gl_SampleMask = ~0; */
278 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, ms_fbo.handle);
279 glClear(GL_COLOR_BUFFER_BIT);
281 glUseProgram(prog_fix_sample_mask[mode != rate_mode_sampleshading]);
283 glEnable(GL_BLEND);
284 glBlendFunc(GL_ONE, GL_ONE);
286 draw_fan(mode, sample_rate, false);
288 glDisable(GL_BLEND);
290 /* 2. Use the check shader to check correctness. */
291 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, piglit_winsys_fbo);
292 glClear(GL_COLOR_BUFFER_BIT);
294 glUseProgram(prog_fix_check);
295 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, ms_fbo.color_tex[0]);
297 piglit_draw_rect(-1, -1, 2, 2);
299 static const float expected[4] = { 0, 1, 0, 1 };
300 if (!piglit_probe_rect_rgba(0, 0, WINDOW_SIZE, WINDOW_SIZE, expected))
301 return PIGLIT_FAIL;
303 if (!piglit_check_gl_error(GL_NO_ERROR))
304 piglit_report_result(PIGLIT_FAIL);
306 return PIGLIT_PASS;
309 static enum piglit_result
310 test_mask_in_one(enum rate_mode mode, float sample_rate)
312 if (!mask_in_one_supported)
313 return PIGLIT_SKIP;
315 glClearColor(0.0, 0.0, 0.0, 0.0);
317 /* 1. Draw everything outputting gl_SampleMaskIn, with msaa disabled; */
318 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, ms_fbo.handle);
319 glClear(GL_COLOR_BUFFER_BIT);
322 * We'll abuse the sampleid_noms mode here and use the prog without
323 * sample id to so we still have 3 somewhat meaningful modes - of
324 * course with msaa always disabled it should always be the same.
326 glUseProgram(prog_mask_in_one[mode == rate_mode_sampleid]);
328 glEnable(GL_BLEND);
329 glBlendFunc(GL_ONE, GL_ONE);
331 draw_fan(mode, sample_rate, true);
333 glDisable(GL_BLEND);
335 /* 2. Use the check shader to check correctness. */
336 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, piglit_winsys_fbo);
337 glClear(GL_COLOR_BUFFER_BIT);
339 glUseProgram(prog_fix_check);
340 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, ms_fbo.color_tex[0]);
342 piglit_draw_rect(-1, -1, 2, 2);
344 static const float expected[4] = { 0, 1, 0, 1 };
345 if (!piglit_probe_rect_rgba(0, 0, WINDOW_SIZE, WINDOW_SIZE, expected))
346 return PIGLIT_FAIL;
348 if (!piglit_check_gl_error(GL_NO_ERROR))
349 piglit_report_result(PIGLIT_FAIL);
351 return PIGLIT_PASS;
354 static enum piglit_result
355 test_partition(enum rate_mode mode, float sample_rate)
357 if (!partition_check_supported)
358 return PIGLIT_SKIP;
360 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, ms_ifbo.handle);
362 glUseProgram(prog_partition_write[mode != rate_mode_sampleshading]);
364 draw_fan(mode, sample_rate, false);
366 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, piglit_winsys_fbo);
367 glClearColor(0.0, 0.0, 0.0, 0.0);
368 glClear(GL_COLOR_BUFFER_BIT);
370 glUseProgram(prog_partition_check);
371 glUniform1i(prog_partition_check_have_sampleid, mode == rate_mode_sampleid);
372 glUniform1i(prog_partition_check_msaa_disabled, mode == rate_mode_sampleid_noms);
373 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, ms_ifbo.color_tex[0]);
375 piglit_draw_rect(-1, -1, 2, 2);
377 static const float expected[4] = { 0, 1, 0, 1 };
378 if (!piglit_probe_rect_rgba(0, 0, WINDOW_SIZE, WINDOW_SIZE, expected))
379 return PIGLIT_FAIL;
381 if (!piglit_check_gl_error(GL_NO_ERROR))
382 piglit_report_result(PIGLIT_FAIL);
384 return PIGLIT_PASS;
387 static bool
388 iterate_sample_rates(const char *testname, enum piglit_result (*test)(enum rate_mode, float))
390 bool all = !strcmp(sample_rate, "all");
391 bool sample = all || !strcmp(sample_rate, "sample");
392 bool noms = all || !strcmp(sample_rate, "noms");
393 bool ok = true;
394 enum piglit_result result;
396 if (sample) {
397 result = test(rate_mode_sampleid, 0);
398 piglit_report_subtest_result(result, "sample %s", testname);
399 if (result == PIGLIT_FAIL)
400 ok = false;
403 if (noms) {
404 result = test(rate_mode_sampleid_noms, 0);
405 piglit_report_subtest_result(result, "noms %s", testname);
406 if (result == PIGLIT_FAIL)
407 ok = false;
410 if (all) {
411 float rate = 1.0;
412 for (;;) {
413 result = test(rate_mode_sampleshading, rate);
414 piglit_report_subtest_result(result, "%f %s", rate, testname);
415 if (result == PIGLIT_FAIL)
416 ok = false;
418 if (actual_num_samples * rate <= 1)
419 break;
421 rate *= 0.5;
425 if (!all && !sample && !noms) {
426 float rate = atof(sample_rate);
427 result = test(rate_mode_sampleshading, rate);
428 piglit_report_subtest_result(result, "%f %s", rate, testname);
429 if (result == PIGLIT_FAIL)
430 ok = false;
433 return ok;
436 enum piglit_result
437 piglit_display()
439 bool pass = true;
440 bool run = false;
441 bool all = !strcmp(testname, "all");
443 if (all || !strcmp(testname, "fix")) {
444 run = true;
445 pass = iterate_sample_rates("fix", test_fix) && pass;
448 if (all || !strcmp(testname, "mask_in_one")) {
449 run = true;
450 pass = iterate_sample_rates("mask_in_one", test_mask_in_one) && pass;
453 if (all || !strcmp(testname, "partition")) {
454 run = true;
455 pass = iterate_sample_rates("partition", test_partition) && pass;
458 if (!run)
459 print_usage_and_exit(procname);
461 piglit_present_results();
463 return pass ? PIGLIT_PASS : PIGLIT_FAIL;
466 void
467 piglit_init(int argc, char **argv)
469 if (argc != 4)
470 print_usage_and_exit(argv[0]);
472 procname = argv[0];
474 /* 1st arg: num_samples */
475 char *endptr = NULL;
476 num_samples = strtol(argv[1], &endptr, 0);
477 if (endptr != argv[1] + strlen(argv[1]))
478 print_usage_and_exit(argv[0]);
480 /* 2nd arg: sample rate */
481 sample_rate = argv[2];
483 /* 3rd arg: testname */
484 testname = argv[3];
486 piglit_require_extension("GL_ARB_texture_multisample");
487 piglit_require_extension("GL_ARB_sample_shading");
489 partition_check_supported =
490 piglit_is_extension_supported("GL_ARB_gpu_shader5") &&
491 piglit_is_extension_supported("GL_ARB_shader_atomic_counters");
493 mask_in_one_supported =
494 piglit_is_extension_supported("GL_ARB_gpu_shader5");
496 /* Skip the test if num_samples > GL_MAX_SAMPLES */
497 GLint max_samples;
498 glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
499 if (num_samples > max_samples)
500 piglit_report_result(PIGLIT_SKIP);
502 /* Dummy vertex array */
503 GLuint empty_vao;
504 glGenVertexArrays(1, &empty_vao);
505 glBindVertexArray(empty_vao);
507 /* Multi-sample framebuffer setup */
508 FboConfig fbo_config(num_samples, WINDOW_SIZE, WINDOW_SIZE);
509 fbo_config.num_tex_attachments = 1;
510 fbo_config.num_rb_attachments = 0;
511 fbo_config.depth_internalformat = GL_NONE;
512 fbo_config.stencil_internalformat = GL_NONE;
513 ms_fbo.setup(fbo_config);
515 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, ms_fbo.handle);
516 glGetFramebufferParameteriv(GL_DRAW_FRAMEBUFFER, GL_SAMPLES, &actual_num_samples);
517 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, piglit_winsys_fbo);
519 printf("Requested %d samples, got %d samples\n", num_samples, actual_num_samples);
521 /* Integer multi-sample framebuffer setup */
522 fbo_config.color_internalformat = GL_RGBA32I;
523 ms_ifbo.setup(fbo_config);
525 /* Shader setup */
526 compile_shaders();
528 if (partition_check_supported) {
529 GLuint atomic_bo;
530 glGenBuffers(1, &atomic_bo);
531 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomic_bo);
532 glBufferData(GL_ATOMIC_COUNTER_BUFFER, 4, NULL, GL_STATIC_DRAW);
535 if (!piglit_check_gl_error(GL_NO_ERROR))
536 piglit_report_result(PIGLIT_FAIL);