ext_gpu_shader4: add compiler tests for everything
[piglit.git] / tests / spec / ext_transform_feedback / intervening-read.c
blob7b8417f08256216ca15ab7f7537dccaaeed416e5
1 /*
2 * Copyright © 2011 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 intervening-read.c
27 * Verify that transform feedback continues to work correctly if
28 * glReadPixels is executed while it is in progress.
30 * This test accepts a single command-line argument which determines
31 * what aspect of transform feedback is tested:
33 * - output: Verifies that correct transform feedback output is generated.
35 * - prims_generated: Verifies that the PRIMITIVES_GENERATED counter
36 * is updated correctly.
38 * - prims_written: Verifies that the PRIMITIVES_WRITTEN counter is
39 * updated correctly.
41 * The test draws two triangles before executing glReadPixels, and two
42 * triangles after executing glReadPixels. It uses a transform
43 * feedback buffer that is large enough to accommodate 12 vertices,
44 * but it requests that no more than 9 vertices be written to it.
45 * This allows us to verify that the intervening glReadPixels call
46 * doesn't interfere with overflow checking.
48 * The optional argument "use_gs" causes the test to use a geometry
49 * shader. When this argument is given, the number of vertices output
50 * by the geometry shader is in general different from the number of
51 * vertices sent down the pipeline by the glDrawArrays() command.
52 * Thus, the test verifies that the implementation uses the
53 * post-geometry-shader vertex count to figure out where to resume
54 * transform feedback after the glReadPixels call.
57 #include "piglit-util-gl.h"
59 static bool use_gs;
61 PIGLIT_GL_TEST_CONFIG_BEGIN
63 use_gs = PIGLIT_STRIP_ARG("use_gs");
64 if (use_gs) {
65 config.supports_gl_compat_version = 32;
66 config.supports_gl_core_version = 32;
67 } else {
68 config.supports_gl_compat_version = 10;
69 config.supports_gl_core_version = 31;
72 config.window_visual = PIGLIT_GL_VISUAL_DOUBLE | PIGLIT_GL_VISUAL_RGB;
73 config.khr_no_error_support = PIGLIT_NO_ERRORS;
75 PIGLIT_GL_TEST_CONFIG_END
77 static enum test_mode {
78 TEST_MODE_OUTPUT,
79 TEST_MODE_PRIMS_GENERATED,
80 TEST_MODE_PRIMS_WRITTEN
81 } test_mode;
83 /**
84 * Vertex shader used when use_gs is false.
86 static const char *vstext_nogs =
87 "attribute vec4 in_position;\n"
88 "attribute vec4 in_color;\n"
89 "varying vec4 out_position;\n"
90 "varying vec4 out_color;\n"
91 "\n"
92 "void main()\n"
93 "{\n"
94 " gl_Position = in_position;\n"
95 " out_position = in_position;\n"
96 " out_color = in_color;\n"
97 "}\n";
99 /**
100 * Fragment shader used when use_gs is false.
102 static const char *fstext_nogs =
103 "varying vec4 out_color;\n"
104 "\n"
105 "void main()\n"
106 "{\n"
107 " gl_FragColor = out_color;\n"
108 "}\n";
111 * Vertex shader used when use_gs is true.
113 static const char *vstext_gs =
114 "#version 150\n"
115 "in vec4 in_color;\n"
116 "out vec4 color_to_gs;\n"
117 "\n"
118 "void main()\n"
119 "{\n"
120 " color_to_gs = in_color;\n"
121 "}\n";
124 * Geometry shader used when use_gs is true.
126 static const char *gstext_gs =
127 "#version 150\n"
128 "layout(points) in;\n"
129 "layout(triangle_strip, max_vertices=6) out;\n"
130 "uniform int start_index;\n"
131 "in vec4 color_to_gs[1];\n"
132 "out vec4 out_position;\n"
133 "out vec4 out_color;\n"
134 "\n"
135 "void main()\n"
136 "{\n"
137 " const vec2 positions[12] = vec2[12](\n"
138 " vec2(-1.0, -1.0),\n"
139 " vec2( 0.0, -1.0),\n"
140 " vec2(-1.0, 1.0),\n"
141 " vec2(-1.0, 1.0),\n"
142 " vec2( 0.0, -1.0),\n"
143 " vec2( 0.0, 1.0),\n"
144 " vec2( 0.0, -1.0),\n"
145 " vec2( 1.0, -1.0),\n"
146 " vec2( 0.0, 1.0),\n"
147 " vec2( 0.0, 1.0),\n"
148 " vec2( 1.0, -1.0),\n"
149 " vec2( 1.0, 1.0)\n"
150 " );\n"
151 " int index = start_index;\n"
152 " for (int i = 0; i < 2; i++) {\n"
153 " for (int j = 0; j < 3; j++) {\n"
154 " vec4 position = vec4(positions[index], 0.0, 1.0);\n"
155 " gl_Position = position;\n"
156 " out_position = position;\n"
157 " out_color = color_to_gs[0];\n"
158 " EmitVertex();\n"
159 " index++;\n"
160 " }\n"
161 " EndPrimitive();\n"
162 " }\n"
163 "}\n";
166 * Fragment shader used when use_gs is false.
168 static const char *fstext_gs =
169 "#version 150\n"
170 "in vec4 out_color;\n"
171 "\n"
172 "void main()\n"
173 "{\n"
174 " gl_FragColor = out_color;\n"
175 "}\n";
177 static const char *varyings[] = { "out_position", "out_color" };
179 static GLuint xfb_buf, vao, array_buf;
180 static GLuint prog;
181 static GLuint query;
183 static void
184 print_usage_and_exit(char *prog_name)
186 printf("Usage: %s <mode>\n"
187 " where <mode> is one of:\n"
188 " output\n"
189 " prims_generated\n"
190 " prims_written\n", prog_name);
191 exit(1);
194 void
195 piglit_init(int argc, char **argv)
197 GLuint vs, gs, fs;
199 /* Interpret command line args */
200 if (argc != 2)
201 print_usage_and_exit(argv[0]);
202 if (strcmp(argv[1], "output") == 0)
203 test_mode = TEST_MODE_OUTPUT;
204 else if (strcmp(argv[1], "prims_generated") == 0)
205 test_mode = TEST_MODE_PRIMS_GENERATED;
206 else if (strcmp(argv[1], "prims_written") == 0)
207 test_mode = TEST_MODE_PRIMS_WRITTEN;
208 else
209 print_usage_and_exit(argv[0]);
211 piglit_require_GLSL();
212 piglit_require_transform_feedback();
214 if (use_gs) {
215 vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vstext_gs);
216 gs = piglit_compile_shader_text(GL_GEOMETRY_SHADER, gstext_gs);
217 fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, fstext_gs);
218 } else {
219 vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vstext_nogs);
220 gs = 0;
221 fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER,
222 fstext_nogs);
224 prog = glCreateProgram();
225 glAttachShader(prog, vs);
226 if (use_gs)
227 glAttachShader(prog, gs);
228 glAttachShader(prog, fs);
229 if (!use_gs)
230 glBindAttribLocation(prog, 0, "in_position");
231 glBindAttribLocation(prog, 1, "in_color");
232 glTransformFeedbackVaryings(prog, 2, varyings, GL_INTERLEAVED_ATTRIBS);
233 glLinkProgram(prog);
234 if (!piglit_link_check_status(prog)) {
235 glDeleteProgram(prog);
236 piglit_report_result(PIGLIT_FAIL);
239 glGenBuffers(1, &xfb_buf);
240 glGenBuffers(1, &array_buf);
241 glGenQueries(1, &query);
242 if (piglit_is_extension_supported("GL_ARB_vertex_array_object") ||
243 piglit_get_gl_version() >= 30) {
244 glGenVertexArrays(1, &vao);
245 glBindVertexArray(vao);
249 struct vertex_data {
250 float position[4];
251 float color[4];
254 void
255 dump_vertex_data(const struct vertex_data *data)
257 printf("position=(%f, %f, %f, %f), color=(%f, %f, %f, %f)",
258 data->position[0], data->position[1], data->position[2], data->position[3],
259 data->color[0], data->color[1], data->color[2], data->color[3]);
262 enum piglit_result
263 piglit_display(void)
265 int i, j;
266 GLboolean pass = GL_TRUE;
267 static const struct vertex_data vertex_input[12] = {
268 /* position XYZW color RGBA */
269 { { -1.0, -1.0, 0.0, 1.0 }, { 1.0, 1.0, 0.0, 1.0 } },
270 { { 0.0, -1.0, 0.0, 1.0 }, { 1.0, 1.0, 0.0, 1.0 } },
271 { { -1.0, 1.0, 0.0, 1.0 }, { 1.0, 1.0, 0.0, 1.0 } },
272 { { -1.0, 1.0, 0.0, 1.0 }, { 1.0, 1.0, 0.0, 1.0 } },
273 { { 0.0, -1.0, 0.0, 1.0 }, { 1.0, 1.0, 0.0, 1.0 } },
274 { { 0.0, 1.0, 0.0, 1.0 }, { 1.0, 1.0, 0.0, 1.0 } },
275 { { 0.0, -1.0, 0.0, 1.0 }, { 0.0, 0.0, 1.0, 1.0 } },
276 { { 1.0, -1.0, 0.0, 1.0 }, { 0.0, 0.0, 1.0, 1.0 } },
277 { { 0.0, 1.0, 0.0, 1.0 }, { 0.0, 0.0, 1.0, 1.0 } },
278 { { 0.0, 1.0, 0.0, 1.0 }, { 0.0, 0.0, 1.0, 1.0 } },
279 { { 1.0, -1.0, 0.0, 1.0 }, { 0.0, 0.0, 1.0, 1.0 } },
280 { { 1.0, 1.0, 0.0, 1.0 }, { 0.0, 0.0, 1.0, 1.0 } }
282 static struct vertex_data initial_xfb_data[12];
283 const struct vertex_data *readback;
284 GLuint query_result;
286 glUseProgram(prog);
288 /* Setup inputs */
289 glBindBuffer(GL_ARRAY_BUFFER, array_buf);
290 glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_input), &vertex_input,
291 GL_STATIC_DRAW);
292 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE,
293 sizeof(struct vertex_data),
294 (void *) offsetof(struct vertex_data, position));
295 glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE,
296 sizeof(struct vertex_data),
297 (void *) offsetof(struct vertex_data, color));
298 glEnableVertexAttribArray(0);
299 glEnableVertexAttribArray(1);
301 /* Setup transform feedback */
302 for (i = 0; i < ARRAY_SIZE(initial_xfb_data); ++i) {
303 for (j = 0; j < 4; ++j) {
304 initial_xfb_data[i].position[j] = 12345.0;
305 initial_xfb_data[i].color[j] = 12345.0;
308 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_buf);
309 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(initial_xfb_data),
310 initial_xfb_data, GL_STREAM_READ);
311 glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, xfb_buf, 0,
312 sizeof(float[9][8]));
313 glBeginTransformFeedback(GL_TRIANGLES);
314 switch (test_mode) {
315 case TEST_MODE_PRIMS_GENERATED:
316 glBeginQuery(GL_PRIMITIVES_GENERATED, query);
317 break;
318 case TEST_MODE_PRIMS_WRITTEN:
319 glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, query);
320 break;
321 default:
322 break;
325 /* First draw call */
326 if (use_gs) {
327 glUniform1i(glGetUniformLocation(prog, "start_index"), 0);
328 glDrawArrays(GL_POINTS, 0, 1);
329 } else {
330 glDrawArrays(GL_TRIANGLES, 0, 6);
333 /* Read pixels */
334 pass = piglit_probe_rect_rgba(0, 0, piglit_width / 2, piglit_height,
335 vertex_input[0].color) && pass;
337 /* Second draw call */
338 if (use_gs) {
339 glUniform1i(glGetUniformLocation(prog, "start_index"), 6);
340 glDrawArrays(GL_POINTS, 6, 1);
341 } else {
342 glDrawArrays(GL_TRIANGLES, 6, 6);
345 /* Finish transform feedback and test correct behavior. */
346 glEndTransformFeedback();
347 switch (test_mode) {
348 case TEST_MODE_OUTPUT:
349 readback = glMapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER,
350 GL_READ_ONLY);
351 for (i = 0; i < 12; ++i) {
352 const struct vertex_data *expected = i < 9
353 ? &vertex_input[i] : &initial_xfb_data[i];
354 if (memcmp(&readback[i], expected,
355 sizeof(struct vertex_data)) != 0) {
356 printf("Read incorrect data for vertex %i.\n",
358 printf("Readback: ");
359 dump_vertex_data(&readback[i]);
360 printf("\nExpected: ");
361 dump_vertex_data(expected);
362 printf("\n");
363 pass = GL_FALSE;
366 glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
367 break;
368 case TEST_MODE_PRIMS_GENERATED:
369 glEndQuery(GL_PRIMITIVES_GENERATED);
370 glGetQueryObjectuiv(query, GL_QUERY_RESULT, &query_result);
371 if (query_result != 4) {
372 printf("Expected 4 primitives generated, got %u\n",
373 query_result);
374 pass = GL_FALSE;
376 break;
377 case TEST_MODE_PRIMS_WRITTEN:
378 glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
379 glGetQueryObjectuiv(query, GL_QUERY_RESULT, &query_result);
380 if (query_result != 3) {
381 printf("Expected 3 primitives written, got %u\n",
382 query_result);
383 pass = GL_FALSE;
385 break;
388 piglit_present_results();
390 return pass ? PIGLIT_PASS : PIGLIT_FAIL;