2 * Copyright © 2015 Glenn Kennard
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
23 * Author: Glenn Kennard <glenn.kennard@gmail.com>
28 * Tests ARB_query_buffer_object
29 * - synchronous wait for result
30 * - asynchrounous result, default value is left intact if result unavailable
31 * - asynchrounous result, retrieve result to client memory before & after
36 PIGLIT_GL_TEST_CONFIG_BEGIN
37 config
.supports_gl_compat_version
= 32;
38 config
.supports_gl_core_version
= 32;
39 config
.window_visual
= PIGLIT_GL_VISUAL_RGBA
| PIGLIT_GL_VISUAL_DOUBLE
|
40 PIGLIT_GL_VISUAL_DEPTH
;
42 PIGLIT_GL_TEST_CONFIG_END
44 #define BUFFER_OFFSET(i) ((void *)((char *)NULL + i))
46 static const float green
[] = {0, 1, 0, 1};
48 static unsigned query
;
52 static int sync_mode_loc
;
53 static int expect_exact_loc
;
54 static int is_64bit_loc
;
55 static int expected_loc
;
56 static int expected_hi_loc
;
60 QBO_SYNC_CPU_READ_AFTER_CACHE_TEST
,
62 QBO_ASYNC_CPU_READ_BEFORE
,
63 QBO_ASYNC_CPU_READ_AFTER
,
67 static const char * const sync_mode_names
[] = {
69 "SYNC_CPU_READ_AFTER_CACHE_TEST",
71 "ASYNC_CPU_READ_BEFORE",
72 "ASYNC_CPU_READ_AFTER",
75 static const struct query_type_desc
*query_desc
;
76 static enum sync_mode sync_mode
;
77 static GLenum result_type
;
79 static enum piglit_result
80 cpu_gather_query(bool exact
, uint32_t expected
, uint64_t *cpu_result
)
84 glBindBuffer(GL_QUERY_BUFFER
, 0);
86 if (result_type
== GL_INT
)
87 glGetQueryObjectiv(query
, GL_QUERY_RESULT
, (GLint
*)cpu_result
);
88 else if (result_type
== GL_UNSIGNED_INT
)
89 glGetQueryObjectuiv(query
, GL_QUERY_RESULT
, (GLuint
*)cpu_result
);
91 glGetQueryObjectui64v(query
, GL_QUERY_RESULT
, cpu_result
);
93 glBindBuffer(GL_QUERY_BUFFER
, qbo
);
95 return (exact
? *cpu_result
== expected
: *cpu_result
>= expected
)
96 ? PIGLIT_PASS
: PIGLIT_FAIL
;
105 bool have_cpu_result
= false;
106 uint32_t default_value
[4] = { 0xccccccccu
, 0xccccccccu
, 0xccccccccu
, 0xccccccccu
};
108 sync_mode
== QBO_SYNC
||
109 sync_mode
== QBO_SYNC_CPU_READ_AFTER_CACHE_TEST
;
111 get_query_values(query_desc
, &exact
, &expected
);
113 glGenQueries(1, &query
);
114 run_query(query
, query_desc
);
116 /* Load default value into buffer */
117 glBindBuffer(GL_QUERY_BUFFER
, qbo
);
118 glBufferData(GL_QUERY_BUFFER
, 16, default_value
, GL_DYNAMIC_COPY
);
120 if (sync_mode
== QBO_ASYNC_CPU_READ_BEFORE
) {
121 if (cpu_gather_query(exact
, expected
, &cpu_result
))
123 have_cpu_result
= true;
126 glBindBuffer(GL_QUERY_BUFFER
, qbo
);
128 /* Special mode to test against a possible cache invalidation
129 * in case the wait-for-result is handled at a different place
130 * in the memory hierarchy than actually reading and
131 * summarizing the result.
133 if (sync_mode
== QBO_SYNC_CPU_READ_AFTER_CACHE_TEST
)
134 glGetQueryObjectivARB(query
, GL_QUERY_RESULT_NO_WAIT
, BUFFER_OFFSET(0));
136 if (result_type
== GL_INT
)
137 glGetQueryObjectivARB(query
, GL_QUERY_RESULT
, BUFFER_OFFSET(0));
138 else if (result_type
== GL_UNSIGNED_INT
)
139 glGetQueryObjectuivARB(query
, GL_QUERY_RESULT
, BUFFER_OFFSET(0));
141 glGetQueryObjectui64v(query
, GL_QUERY_RESULT
, BUFFER_OFFSET(0));
143 if (result_type
== GL_INT
) {
144 glGetQueryObjectivARB(query
, GL_QUERY_RESULT_AVAILABLE
, BUFFER_OFFSET(8));
145 glGetQueryObjectivARB(query
, GL_QUERY_RESULT_NO_WAIT
, BUFFER_OFFSET(0));
146 } else if (result_type
== GL_UNSIGNED_INT
) {
147 glGetQueryObjectuivARB(query
, GL_QUERY_RESULT_AVAILABLE
, BUFFER_OFFSET(8));
148 glGetQueryObjectuivARB(query
, GL_QUERY_RESULT_NO_WAIT
, BUFFER_OFFSET(0));
150 glGetQueryObjectui64v(query
, GL_QUERY_RESULT_AVAILABLE
, BUFFER_OFFSET(8));
151 glGetQueryObjectui64v(query
, GL_QUERY_RESULT_NO_WAIT
, BUFFER_OFFSET(0));
155 if (sync_mode
== QBO_SYNC_CPU_READ_AFTER_CACHE_TEST
||
156 sync_mode
== QBO_ASYNC_CPU_READ_AFTER
) {
157 if (cpu_gather_query(exact
, expected
, &cpu_result
))
159 have_cpu_result
= true;
162 /* Make it available to shader as uniform buffer 0 */
163 glBindBufferBase(GL_UNIFORM_BUFFER
, 0, qbo
);
165 glUseProgram(qbo_prog
);
167 /* Setup program uniforms */
168 glUniform1ui(sync_mode_loc
, is_sync
? GL_TRUE
: GL_FALSE
);
169 glUniform1ui(expect_exact_loc
, have_cpu_result
|| exact
);
170 glUniform1ui(is_64bit_loc
, result_type
== GL_UNSIGNED_INT64_ARB
);
171 glUniform1ui(expected_loc
, have_cpu_result
? cpu_result
: expected
);
172 glUniform1ui(expected_hi_loc
, have_cpu_result
? (cpu_result
>> 32) : 0);
174 glDisable(GL_DEPTH_TEST
);
175 /* Draw green if query successful */
176 piglit_draw_rect(-1, -1, 2, 2);
178 glDeleteQueries(1, &query
);
180 if (!piglit_probe_rect_rgba(0, 0, piglit_width
, piglit_height
, green
)) {
181 unsigned *ptr
= glMapBuffer(GL_QUERY_BUFFER
, GL_READ_ONLY
);
183 printf("Expected: %u\n", expected
);
185 printf("CPU result: %lu\n", cpu_result
);
186 printf("QBO: %u %u %u %u\n", ptr
[0], ptr
[1], ptr
[2], ptr
[3]);
187 glUnmapBuffer(GL_QUERY_BUFFER
);
198 static const GLenum result_types
[] = {
201 GL_UNSIGNED_INT64_ARB
203 enum piglit_result r
= PIGLIT_PASS
;
205 for (unsigned qnum
= 0; qnum
< num_query_types(); qnum
++) {
206 query_desc
= &query_types
[qnum
];
208 bool supported
= is_query_supported(query_desc
);
210 for (sync_mode
= QBO_SYNC
;
211 sync_mode
< NUM_QBO_SYNC_MODES
;
213 for (unsigned ridx
= 0; ridx
< ARRAY_SIZE(result_types
); ++ridx
) {
214 enum piglit_result subtest_result
= PIGLIT_SKIP
;
216 result_type
= result_types
[ridx
];
219 subtest_result
= run_subtest();
220 if (subtest_result
!= PIGLIT_PASS
)
224 piglit_report_subtest_result(subtest_result
, "query-%s-%s-%s",
225 piglit_get_gl_enum_name(query_desc
->type
),
226 sync_mode_names
[sync_mode
],
227 piglit_get_gl_enum_name(result_type
));
236 piglit_init(int argc
, char **argv
)
241 piglit_require_extension("GL_ARB_query_buffer_object");
242 piglit_require_extension("GL_ARB_uniform_buffer_object");
246 glGenBuffers(1, &qbo
);
247 glBindBuffer(GL_QUERY_BUFFER
, qbo
);
248 glBufferData(GL_QUERY_BUFFER
, 4, NULL
, GL_DYNAMIC_COPY
);
254 " gl_Position = pos_in;\n"
258 "#extension GL_ARB_uniform_buffer_object : require\n"
263 " uint available_hi;\n"
265 "uniform bool sync_mode;\n"
266 "uniform bool expect_exact;\n"
267 "uniform bool is_64bit;\n"
268 "uniform uint expected;\n"
269 "uniform uint expected_hi;\n"
272 " uint INIT = uint(0xcccccccc);\n"
273 " bool ready = sync_mode || available != 0u;\n"
274 " if (!is_64bit && (result_hi != INIT || available_hi != INIT)) {\n"
275 " color = vec4(1.0, 0.0, 0.25, 1.0);\n"
276 " } else if ((sync_mode && (available != INIT ||\n"
277 " available_hi != INIT)) ||\n"
278 " (!sync_mode && ((available != 0u && available != 1u) ||\n"
279 " (is_64bit && available_hi != 0u) ||\n"
280 " (!is_64bit && available_hi != INIT)))) {\n"
281 " color = vec4(1.0, 0.0, 0.5, 1.0);\n"
283 " bool result_ok = false;\n"
284 " if (result == expected &&\n"
285 " (!is_64bit || result_hi == expected_hi))\n"
286 " result_ok = true;\n"
287 " if (!expect_exact &&\n"
288 " ((!is_64bit && result >= expected) ||\n"
289 " (is_64bit && ((result_hi == expected_hi && result >= expected) ||\n"
290 " (result_hi > expected_hi)))))\n"
291 " result_ok = true;\n"
292 " if (!ready && result == INIT && result_hi == INIT)\n"
293 " result_ok = true;\n"
294 " if (result_ok) {\n"
295 " color = vec4(0.0, 1.0, 0.0, 1.0);\n"
296 " } else if (ready) {\n"
297 " color = vec4(1.0, 0.0, 0.0, 1.0);\n"
299 " color = vec4(1.0, 0.5, 0.0, 1.0);\n"
304 qbo_prog
= piglit_build_simple_program(vsCode
, qboFsCode
);
305 sync_mode_loc
= glGetUniformLocation(qbo_prog
, "sync_mode");
306 expect_exact_loc
= glGetUniformLocation(qbo_prog
, "expect_exact");
307 is_64bit_loc
= glGetUniformLocation(qbo_prog
, "is_64bit");
308 expected_loc
= glGetUniformLocation(qbo_prog
, "expected");
309 expected_hi_loc
= glGetUniformLocation(qbo_prog
, "expected_hi");