ext_gpu_shader4: add compiler tests for everything
[piglit.git] / tests / spec / arb_sample_locations / test.c
blob77bc0cc605db2528149aaa556d5595cec2ecba43
1 #include "piglit-util-gl.h"
3 /**
4 * @file test.c
6 * This test verifies that GL_ARB_sample_locations is implemented correctly.
7 * It does so by retrieving the sample positions using gl_SamplePosition,
8 * interpolateAtSample() and a method described in
9 * https://urldefense.proofpoint.com/v2/url?u=https-3A__mynameismjp.wordpress.com_2010_07_07_msaa-2Dsample-2Dpattern-2Ddetector_&d=DwIBAg&c=uilaK90D4TOVoH58JNXRgQ&r=Ie7_encNUsqxbSRbqbNgofw0ITcfE8JKfaUjIQhncGA&m=_I4YfQ6nzOyQ71BgwYmlUsP4O5-Pi2DfoZIGctuFnLs&s=RhpkXqf6twp4gawhoCbMx1cmqWZv4eRpX4d6JJ6_tmE&e=
10 * which draws a rectangle covering each possible sample location within a pixel.
11 * Each rectangle writes it's position within the pixel, which is then read
12 * through a shader.
14 * The retrieved sample locations are then tested against expectations. This is
15 * done with various MSAA levels and sample locations.
17 * The test can be rather slow by default, but it can be made less exhaustive by
18 * passing the argument --quick.
20 * Sample locations are typically represented in this test as 0.4 fixed point
21 * integers where 0 is the top.
24 /* new_locations in do_test_set() needs to be expanded when this is */
25 #define LOG2_MAX_SAMPLES 5
26 #define MAX_SAMPLES (1<<LOG2_MAX_SAMPLES)
28 #define WIDTH 4
29 /* the height is 7 pixels to test pixel grid flipping */
30 #define HEIGHT 7
32 PIGLIT_GL_TEST_CONFIG_BEGIN
34 config.supports_gl_core_version = 32;
36 config.window_width = 200;
37 config.window_height = 200;
38 config.window_visual = PIGLIT_GL_VISUAL_RGB;
40 PIGLIT_GL_TEST_CONFIG_END
42 static bool quick;
44 static GLuint draw_program;
45 static GLuint read_program;
46 static GLuint fb_textures[LOG2_MAX_SAMPLES+1];
47 static GLuint fbs[LOG2_MAX_SAMPLES+1];
49 static unsigned cur_fb;
50 static GLint grid_width, grid_height, samples;
52 static void
53 get_sample_locations(GLubyte *locations, unsigned count,
54 unsigned pixel_x, unsigned pixel_y)
56 glViewport(pixel_x, pixel_y, 1, 1);
57 glBindFramebuffer(GL_FRAMEBUFFER, fbs[cur_fb]);
58 glClearColor(1.0, 1.0, 1.0, 1.0);
59 glClear(GL_COLOR_BUFFER_BIT);
60 glUseProgram(draw_program);
61 for (int x = 0; x < 16; x++) {
62 for (int y = 0; y < 16; y++) {
63 float left = x/16.0 - (1.0/32.0);
64 float bottom = (16-y)/16.0 - (1.0/32.0);
65 float width = 1.0 / 16.0;
66 float height = 1.0 / 16.0;
67 glUniform2f(glGetUniformLocation(draw_program, "loc"), x/16.0, y/16.0);
68 piglit_draw_rect(left, bottom, width, height);
72 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, fb_textures[cur_fb]);
73 glViewport(0, 0, count, 1);
74 glBindFramebuffer(GL_FRAMEBUFFER, 0);
75 glClearColor(0.5, 0.5, 0.5, 1.0);
76 glClear(GL_COLOR_BUFFER_BIT);
77 glUseProgram(read_program);
78 glUniform1i(glGetUniformLocation(read_program, "input"), 0);
79 glUniform2i(glGetUniformLocation(read_program, "offset"), pixel_x, pixel_y);
80 piglit_draw_rect(0.0, 0.0, 1.0, 1.0);
82 glReadPixels(0, 0, count, 1, GL_RGBA, GL_UNSIGNED_BYTE, locations);
85 static enum piglit_result
86 test_pixel(const unsigned *expected, unsigned pixel_x, unsigned pixel_y)
88 GLubyte actual_locations[32*4];
89 get_sample_locations(actual_locations, samples, pixel_x, pixel_y);
91 unsigned grid_x = pixel_x % grid_width;
92 unsigned grid_y = pixel_y % grid_height;
94 for (unsigned i = 0; i < samples; i++) {
95 for (unsigned j = 0; j < 3; j++) {
96 const char* src =
97 (const char*[]){"Uniform", "gl_SamplePosition", "interpolateAtSample"}[j];
98 unsigned x = actual_locations[i*4+j] & 0xf;
99 unsigned y = actual_locations[i*4+j] >> 4;
100 unsigned expected_x = expected ? expected[i*2] : 8;
101 unsigned expected_y = expected ? expected[i*2+1] : 8;
103 if (x != expected_x) {
104 printf("Expected X coordinate of sample %u to be %u, got %u from %s (at pixel %u, %u and grid %u, %u)\n",
105 i, expected_x, x, src, pixel_x, pixel_y, grid_x, grid_y);
106 return PIGLIT_FAIL;
109 if (y != expected_y) {
110 printf("Expected Y coordinate of sample %u to be %u, got %u from %s (at pixel %u, %u and grid %u, %u)\n",
111 i, expected_y, y, src, pixel_x, pixel_y, grid_x, grid_y);
112 return PIGLIT_FAIL;
117 return PIGLIT_PASS;
120 static enum piglit_result
121 do_test(const unsigned *locations, unsigned pixel_x, unsigned pixel_y, bool grid)
123 if (!fbs[cur_fb]) return PIGLIT_SKIP;
125 glBindFramebuffer(GL_FRAMEBUFFER, fbs[cur_fb]);
127 GLint table_size;
128 glGetIntegerv(GL_SAMPLES, &samples);
129 glGetIntegerv(GL_SAMPLE_LOCATION_PIXEL_GRID_WIDTH_ARB, &grid_width);
130 glGetIntegerv(GL_SAMPLE_LOCATION_PIXEL_GRID_HEIGHT_ARB, &grid_height);
131 glGetIntegerv(GL_PROGRAMMABLE_SAMPLE_LOCATION_TABLE_SIZE_ARB, &table_size);
133 unsigned grid_x = pixel_x % grid_width;
134 unsigned grid_y = pixel_y % grid_height;
136 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB, grid);
137 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB, 1);
139 for (GLint i = 0; i < table_size; i++) {
140 GLfloat loc[2] = {0.5f, 0.5f};
141 glFramebufferSampleLocationsfvARB(GL_FRAMEBUFFER, i, 1, loc);
144 for (GLint i = 0; i < samples; i++) {
145 GLfloat loc[2] = {locations[i*2] / 16.0f, 1.0f - locations[i*2+1] / 16.0f};
146 unsigned index = i;
147 if (grid)
148 index += (grid_y*grid_width+grid_x) * samples;
149 glFramebufferSampleLocationsfvARB(GL_FRAMEBUFFER, index, 1, loc);
152 enum piglit_result result = PIGLIT_PASS;
153 if (quick) {
154 piglit_merge_result(&result, test_pixel(locations, grid_x, grid_y));
155 } else {
156 for (unsigned x = 0; x < WIDTH; x++) {
157 for (unsigned y = 0; y < HEIGHT; y++) {
158 const unsigned *expected = locations;
159 unsigned grid_x_2 = x % grid_width;
160 unsigned grid_y_2 = y % grid_height;
161 if ((grid_x_2 != grid_x || grid_y_2 != grid_y) && grid)
162 expected = NULL;
163 piglit_merge_result(&result, test_pixel(expected, x, y));
168 return result;
171 static enum piglit_result
172 do_test_set(unsigned x, unsigned y, bool grid)
174 static const unsigned new_locations[32][2] = {
175 {1, 3}, {4, 1}, {2, 5}, {5, 5}, {3, 5}, {5, 2}, {1, 6}, {2, 6},
176 {7, 2}, {5, 7}, {4, 8}, {2, 8}, {8, 1}, {8, 6}, {8, 3}, {9, 8},
177 {2, 9}, {9, 3}, {1, 10}, {9, 10}, {10, 1}, {1, 11}, {6, 11}, {11, 6},
178 {12, 5}, {10, 12}, {8, 13}, {13, 8}, {13, 12}, {6, 13}, {4, 14}, {14, 8}};
179 enum piglit_result result = do_test(&new_locations[0][0], x, y, grid);
181 piglit_report_subtest_result(result, "MSAA: %u, X: %u, Y: %u, Grid: %s",
182 1<<cur_fb, x, y, grid?"true":"false");
184 return result;
187 static void
188 create_shader_sources(char *vertex, char *fragment)
190 static const char *fragment_exts =
191 "#extension GL_ARB_gpu_shader5 : enable\n"
192 "#extension GL_ARB_sample_shading : enable\n";
193 static const char *fragment_main =
194 "uniform vec2 loc;\n"
195 "in vec2 pos;\n"
196 "out vec4 color;\n"
197 "float encode_location(in vec2 loc) { return (loc.x*16.0 + loc.y*256.0) / 255.0; }\n"
198 "void main() {\n"
199 " color.xyz = vec3(encode_location(loc));\n";
200 static const char *fragment_gl_sample_position =
201 "color.y = encode_location(vec2(gl_SamplePosition.x, 1.0-gl_SamplePosition.y));\n";
202 static const char *fragment_interpolate_at_sample =
203 "color.z = encode_location(vec2(interpolateAtSample(pos, gl_SampleID).x, 1.0-interpolateAtSample(pos, gl_SampleID).y));\n";
204 static const char *vertex_main =
205 "in vec2 piglit_vertex;\n"
206 "out vec2 pos;\n"
207 "void main() { gl_Position = vec4(piglit_vertex*2.0-1.0, 0.0, 1.0); pos = piglit_vertex; }\n";
209 int glsl_major, glsl_minor, glsl_ver;
210 bool use_gl_sample_position, use_interpolate_at_sample;
212 piglit_get_glsl_version(NULL, &glsl_major, &glsl_minor);
213 glsl_ver = glsl_major*100 + glsl_minor;
215 if (glsl_ver>=400)
216 use_gl_sample_position = use_interpolate_at_sample = true;
217 if (piglit_is_extension_supported("GL_ARB_gpu_shader5"))
218 use_interpolate_at_sample = true;
219 if (piglit_is_extension_supported("GL_ARB_sample_shading"))
220 use_gl_sample_position = true;
222 sprintf(fragment, "#version %u\n%s", glsl_ver, fragment_exts);
223 strcat(fragment, fragment_main);
224 if (use_gl_sample_position)
225 strcat(fragment, fragment_gl_sample_position);
226 if (use_interpolate_at_sample)
227 strcat(fragment, fragment_interpolate_at_sample);
228 strcat(fragment, "}");
230 sprintf(vertex, "#version %u\n%s", glsl_ver, fragment_exts);
231 strcat(vertex, vertex_main);
234 void
235 piglit_init(int argc, char **argv)
237 char vertex_source[1024];
238 char fragment_source[1024];
239 piglit_require_extension("GL_ARB_sample_locations");
241 if (argc > 1 && strcmp(argv[1], "--quick") == 0)
242 quick = true;
244 create_shader_sources(vertex_source, fragment_source);
246 draw_program = piglit_build_simple_program(vertex_source, fragment_source);
248 read_program = piglit_build_simple_program(
249 "#version 150\n"
250 "in vec2 piglit_vertex;\n"
251 "void main() { gl_Position = vec4(piglit_vertex*2.0-1.0, 0.0, 1.0); }\n",
252 "#version 150\n"
253 "uniform sampler2DMS tex;\n"
254 "uniform ivec2 offset;\n"
255 "out vec4 color;\n"
256 "void main() { color = texelFetch(tex, offset, int(gl_FragCoord.x)); }\n");
258 GLint count;
259 glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &count);
260 if (count > MAX_SAMPLES)
261 count = MAX_SAMPLES;
262 count = log2u(count) + 1;
264 glGenTextures(count, fb_textures);
265 glGenFramebuffers(count, fbs);
266 for (cur_fb = 0; cur_fb < count; cur_fb++) {
267 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, fb_textures[cur_fb]);
268 glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1<<cur_fb, GL_RGBA8, WIDTH, HEIGHT, GL_TRUE);
269 glBindFramebuffer(GL_FRAMEBUFFER, fbs[cur_fb]);
270 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, fb_textures[cur_fb], 0);
274 enum piglit_result
275 piglit_display(void)
277 enum piglit_result result = PIGLIT_PASS;
278 for (cur_fb = 0; cur_fb < sizeof(fb_textures)/sizeof(fb_textures[0]); cur_fb++) {
279 for (unsigned x = 0; x < WIDTH; x++) {
280 for (unsigned y = 0; y < HEIGHT; y++) {
281 piglit_merge_result(&result, do_test_set(x, y, false));
282 piglit_merge_result(&result, do_test_set(x, y, true));
287 piglit_present_results();
289 return result;