2 * Copyright (c) 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
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
25 * \file qbo-coherency.c
26 * Test coherency of ARB_query_buffer_object results with pre-shader pipeline
29 * Write the qbo result to the 'first' member of the indirect draw
30 * structure, and write the gl_VertexID to a transform feedback buffer.
31 * 2. Index buffer fetch
32 * Write the qbo result to the index buffer, and write the gl_VertexID to
33 * a transform feedback buffer.
34 * 3. Indirect draw count
35 * Write the qbo result to the 'drawcount' value for an
36 * GL_ARB_indirect_parameters multi-draw, and increment an atomic counter
37 * in the vertex shader.
38 * 4. Indirect dispatch
39 * Write the qbo result to the number of groups, and count the groups using
45 PIGLIT_GL_TEST_CONFIG_BEGIN
46 config
.supports_gl_compat_version
= 32;
47 config
.supports_gl_core_version
= 32;
48 config
.window_visual
= PIGLIT_GL_VISUAL_RGBA
| PIGLIT_GL_VISUAL_DOUBLE
|
49 PIGLIT_GL_VISUAL_DEPTH
;
50 PIGLIT_GL_TEST_CONFIG_END
52 #define BUFFER_OFFSET(i) ((void *)((char *)NULL + i))
54 #define DRAW_COUNT_CLAMP_MAX 50
56 static GLuint prog_compute
;
57 static GLuint prog_xfb
;
58 static GLuint prog_vs_atomic
;
59 static GLuint empty_vao
;
60 static GLuint indirect_draw_count_data_bo
;
62 static const char *arg_consumer_mode
;
63 static const char *arg_query_type
;
65 struct consumer_mode
{
67 unsigned (*run
)(unsigned query
);
68 const char *extensions
[2];
75 indirect_draw(unsigned query
)
77 static const GLuint indirect_data
[] = {
79 1, /* instanceCount */
86 glGenBuffers(1, &indirect_bo
);
87 glBindBuffer(GL_QUERY_BUFFER
, indirect_bo
);
88 glBufferData(GL_QUERY_BUFFER
, sizeof(indirect_data
), indirect_data
, GL_STATIC_DRAW
);
89 glGetQueryObjectuivARB(query
, GL_QUERY_RESULT
, BUFFER_OFFSET(2 * sizeof(GLuint
)));
91 glUseProgram(prog_xfb
);
92 glBindVertexArray(empty_vao
);
94 glGenBuffers(1, &xfb_bo
);
95 glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER
, 0, xfb_bo
, 0, sizeof(GLuint
));
96 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER
, sizeof(GLuint
), NULL
, GL_STREAM_READ
);
98 glEnable(GL_RASTERIZER_DISCARD
);
99 glBeginTransformFeedback(GL_POINTS
);
101 glBindBuffer(GL_DRAW_INDIRECT_BUFFER
, indirect_bo
);
102 glDrawArraysIndirect(GL_POINTS
, BUFFER_OFFSET(0));
104 glEndTransformFeedback();
105 glDisable(GL_RASTERIZER_DISCARD
);
108 glGetBufferSubData(GL_TRANSFORM_FEEDBACK_BUFFER
, 0, sizeof(result
), &result
);
110 glDeleteBuffers(1, &indirect_bo
);
111 glDeleteBuffers(1, &xfb_bo
);
112 piglit_check_gl_error(GL_NO_ERROR
);
118 index_buffer(unsigned query
)
120 static const GLuint index_data
[] = {
126 glGenBuffers(1, &index_bo
);
127 glBindBuffer(GL_QUERY_BUFFER
, index_bo
);
128 glBufferData(GL_QUERY_BUFFER
, sizeof(index_data
), index_data
, GL_STATIC_DRAW
);
129 glGetQueryObjectuivARB(query
, GL_QUERY_RESULT
, BUFFER_OFFSET(0));
131 glUseProgram(prog_xfb
);
132 glBindVertexArray(empty_vao
);
134 glGenBuffers(1, &xfb_bo
);
135 glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER
, 0, xfb_bo
, 0, sizeof(GLuint
));
136 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER
, sizeof(GLuint
), NULL
, GL_STREAM_READ
);
138 glEnable(GL_RASTERIZER_DISCARD
);
139 glBeginTransformFeedback(GL_POINTS
);
141 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, index_bo
);
142 glDrawElements(GL_POINTS
, 1, GL_UNSIGNED_INT
, BUFFER_OFFSET(0));
144 glEndTransformFeedback();
145 glDisable(GL_RASTERIZER_DISCARD
);
148 glGetBufferSubData(GL_TRANSFORM_FEEDBACK_BUFFER
, 0, sizeof(result
), &result
);
150 glDeleteBuffers(1, &index_bo
);
151 glDeleteBuffers(1, &xfb_bo
);
152 piglit_check_gl_error(GL_NO_ERROR
);
158 indirect_draw_count(unsigned query
)
160 static const unsigned zero
= 0;
161 static const unsigned count_default
= 999;
162 unsigned indirect_count_bo
;
165 glGenBuffers(1, &indirect_count_bo
);
166 glBindBuffer(GL_QUERY_BUFFER
, indirect_count_bo
);
167 glBufferData(GL_QUERY_BUFFER
, sizeof(count_default
), &count_default
, GL_STATIC_DRAW
);
168 glGetQueryObjectuivARB(query
, GL_QUERY_RESULT
, BUFFER_OFFSET(0));
170 glUseProgram(prog_vs_atomic
);
171 glBindVertexArray(empty_vao
);
173 glGenBuffers(1, &atomic_bo
);
174 glBindBufferRange(GL_ATOMIC_COUNTER_BUFFER
, 0, atomic_bo
, 0, 4);
175 glBufferData(GL_ATOMIC_COUNTER_BUFFER
, 4, &zero
, GL_STATIC_DRAW
);
177 glEnable(GL_RASTERIZER_DISCARD
);
179 glBindBuffer(GL_DRAW_INDIRECT_BUFFER
, indirect_draw_count_data_bo
);
180 glBindBuffer(GL_PARAMETER_BUFFER_ARB
, indirect_count_bo
);
181 glMultiDrawArraysIndirectCountARB(GL_POINTS
, BUFFER_OFFSET(0), 0,
182 DRAW_COUNT_CLAMP_MAX
, 0);
184 glDisable(GL_RASTERIZER_DISCARD
);
187 glGetBufferSubData(GL_ATOMIC_COUNTER_BUFFER
, 0, sizeof(result
), &result
);
189 glDeleteBuffers(1, &indirect_count_bo
);
190 glDeleteBuffers(1, &atomic_bo
);
191 piglit_check_gl_error(GL_NO_ERROR
);
197 indirect_dispatch(unsigned query
)
199 static const GLuint indirect_data
[] = {
200 999, /* num_groups_x */
201 1, /* num_groups_y */
202 1, /* num_groups_z */
204 static const unsigned zero
= 0;
205 unsigned indirect_bo
;
208 glGenBuffers(1, &indirect_bo
);
209 glBindBuffer(GL_QUERY_BUFFER
, indirect_bo
);
210 glBufferData(GL_QUERY_BUFFER
, sizeof(indirect_data
), indirect_data
, GL_STATIC_DRAW
);
211 glGetQueryObjectuivARB(query
, GL_QUERY_RESULT
, BUFFER_OFFSET(0));
213 glUseProgram(prog_compute
);
215 glGenBuffers(1, &atomic_bo
);
216 glBindBufferRange(GL_ATOMIC_COUNTER_BUFFER
, 0, atomic_bo
, 0, 4);
217 glBufferData(GL_ATOMIC_COUNTER_BUFFER
, 4, &zero
, GL_STATIC_DRAW
);
219 glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER
, indirect_bo
);
220 glDispatchComputeIndirect(0);
223 glGetBufferSubData(GL_ATOMIC_COUNTER_BUFFER
, 0, sizeof(result
), &result
);
225 glDeleteBuffers(1, &indirect_bo
);
226 glDeleteBuffers(1, &atomic_bo
);
227 piglit_check_gl_error(GL_NO_ERROR
);
232 static const struct consumer_mode consumer_modes
[] = {
233 { "indirect-draw", &indirect_draw
,
234 { "GL_ARB_draw_indirect", NULL
} },
235 { "index-buffer", &index_buffer
, { NULL
, } },
236 { "indirect-draw-count", &indirect_draw_count
,
237 { "GL_ARB_indirect_parameters", "GL_ARB_shader_atomic_counters" },
238 .clamped
= true, .clamp_max
= DRAW_COUNT_CLAMP_MAX
},
239 { "indirect-dispatch", &indirect_dispatch
,
240 { "GL_ARB_compute_shader", NULL
},
244 static enum piglit_result
245 run_subtest(const struct consumer_mode
*cm
, const struct query_type_desc
*qdesc
)
249 unsigned expected
, result
;
251 get_query_values(qdesc
, &exact
, &expected
);
253 glGenQueries(1, &query
);
255 run_query(query
, qdesc
);
256 result
= cm
->run(query
);
258 glDeleteQueries(1, &query
);
260 piglit_check_gl_error(GL_NO_ERROR
);
263 expected
= MIN2(expected
, cm
->clamp_max
);
265 if (result
!= expected
&& (exact
|| result
< expected
)) {
266 fprintf(stderr
, "Result: %u\nExpected: %u\n", result
, expected
);
276 enum piglit_result result
= PIGLIT_PASS
;
278 unsigned qnum_count
= num_query_types();
280 for (unsigned cnum
= 0; cnum
< ARRAY_SIZE(consumer_modes
); cnum
++) {
281 const struct consumer_mode
*cm
= &consumer_modes
[cnum
];
282 bool supported
= true;
284 if (arg_consumer_mode
&& strcmp(arg_consumer_mode
, cm
->name
))
287 for (unsigned i
= 0; i
< ARRAY_SIZE(cm
->extensions
); ++i
) {
288 if (cm
->extensions
[i
] &&
289 !piglit_is_extension_supported(cm
->extensions
[i
])) {
295 if (!strcmp(cm
->name
, "indirect-draw-count")) {
296 glGetIntegerv(GL_MAX_VERTEX_ATOMIC_COUNTERS
, &vertex_counters
);
298 if(vertex_counters
< 1)
302 for (unsigned qnum
= 0; qnum
< qnum_count
; qnum
++) {
303 enum piglit_result subtest_result
= PIGLIT_SKIP
;
304 const struct query_type_desc
*qdesc
= &query_types
[qnum
];
306 if (arg_query_type
&&
307 strcmp(arg_query_type
, piglit_get_gl_enum_name(qdesc
->type
)))
310 supported
= supported
&& is_query_supported(qdesc
);
313 if (qdesc
->type
== GL_TIMESTAMP
||
314 qdesc
->type
== GL_TIME_ELAPSED
)
319 subtest_result
= run_subtest(cm
, qdesc
);
320 if (subtest_result
!= PIGLIT_PASS
)
321 result
= subtest_result
;
324 piglit_report_subtest_result(
325 subtest_result
, "%s-%s",
327 piglit_get_gl_enum_name(qdesc
->type
));
337 static const char *tf_out
= "tf_out";
339 prog_xfb
= piglit_build_simple_program_unlinked(
345 " tf_out = gl_VertexID;\n"
346 " gl_Position = vec4(0);\n"
349 glTransformFeedbackVaryings(prog_xfb
, 1, &tf_out
, GL_INTERLEAVED_ATTRIBS
);
350 glLinkProgram(prog_xfb
);
351 if (!piglit_link_check_status(prog_xfb
))
352 piglit_report_result(PIGLIT_FAIL
);
353 piglit_check_gl_error(GL_NO_ERROR
);
357 prepare_indirect_draw_count()
359 prog_vs_atomic
= piglit_build_simple_program(
361 "#extension GL_ARB_shader_atomic_counters: require\n"
363 "layout(binding = 0, offset = 0) uniform atomic_uint counter;\n"
366 " atomicCounterIncrement(counter);\n"
367 " gl_Position = vec4(0);\n"
371 static const GLuint indirect_draw_template
[] = {
373 1, /* instanceCount */
375 0, /* baseInstance */
378 char *indirect_draw_count_data
= malloc(DRAW_COUNT_CLAMP_MAX
* sizeof(indirect_draw_template
));
379 char *dst
= indirect_draw_count_data
;
380 for (unsigned i
= 0; i
< DRAW_COUNT_CLAMP_MAX
; ++i
) {
381 memcpy(dst
, indirect_draw_template
, sizeof(indirect_draw_template
));
382 dst
+= sizeof(indirect_draw_template
);
385 glGenBuffers(1, &indirect_draw_count_data_bo
);
386 glBindBuffer(GL_DRAW_INDIRECT_BUFFER
, indirect_draw_count_data_bo
);
387 glBufferData(GL_DRAW_INDIRECT_BUFFER
,
388 DRAW_COUNT_CLAMP_MAX
* sizeof(indirect_draw_template
),
389 indirect_draw_count_data
, GL_STATIC_DRAW
);
391 free(indirect_draw_count_data
);
393 piglit_check_gl_error(GL_NO_ERROR
);
397 prepare_prog_compute()
399 GLuint shader
= piglit_compile_shader_text(GL_COMPUTE_SHADER
,
401 "#extension GL_ARB_compute_shader: require\n"
402 "#extension GL_ARB_shader_atomic_counters: require\n"
404 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
406 "layout(binding = 0, offset = 0) uniform atomic_uint counter;\n"
409 " atomicCounterIncrement(counter);\n"
412 prog_compute
= glCreateProgram();
413 glAttachShader(prog_compute
, shader
);
414 glLinkProgram(prog_compute
);
415 glDeleteShader(shader
);
417 if (!piglit_link_check_status(prog_compute
))
418 piglit_report_result(PIGLIT_FAIL
);
419 piglit_check_gl_error(GL_NO_ERROR
);
423 piglit_init(int argc
, char **argv
)
425 piglit_require_extension("GL_ARB_query_buffer_object");
429 fprintf(stderr
, "usage: %s <consumer> <query_type>\n", argv
[0]);
433 arg_consumer_mode
= argv
[1];
434 arg_query_type
= argv
[2];
441 if (piglit_is_extension_supported("GL_ARB_compute_shader"))
442 prepare_prog_compute();
444 if (piglit_is_extension_supported("GL_ARB_indirect_parameters") &&
445 piglit_is_extension_supported("GL_ARB_shader_atomic_counters"))
446 prepare_indirect_draw_count();
448 glGenVertexArrays(1, &empty_vao
);