ext_gpu_shader4: add compiler tests for everything
[piglit.git] / tests / spec / arb_shader_atomic_counters / active-counters.c
blob976b85886936a47e8baf2a375c369c193f19a7f6
1 /*
2 * Copyright © 2013 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 DEALINGS
21 * IN THE SOFTWARE.
24 /** @file active-counters.c
26 * Compile a shader with a bunch of atomic counters and check that the
27 * active atomic counter and buffer query functions return sane
28 * results.
31 #include "common.h"
33 PIGLIT_GL_TEST_CONFIG_BEGIN
35 config.supports_gl_core_version = 31;
37 config.window_width = 1;
38 config.window_height = 1;
39 config.window_visual = PIGLIT_GL_VISUAL_DOUBLE | PIGLIT_GL_VISUAL_RGBA;
40 config.khr_no_error_support = PIGLIT_NO_ERRORS;
42 PIGLIT_GL_TEST_CONFIG_END
44 const char *fs_source = "#version 140\n"
45 "#extension GL_ARB_shader_atomic_counters : enable\n"
46 "\n"
47 "out ivec4 fcolor;\n"
48 "\n"
49 "layout(binding=0) uniform atomic_uint x0[2];\n"
50 "layout(binding=0) uniform atomic_uint x1;\n"
51 "layout(binding=3, offset=8) uniform atomic_uint x2;\n"
52 "layout(binding=3, offset=12) uniform atomic_uint x3;\n"
53 "\n"
54 "layout(binding=7, binding=2, offset=4) uniform;\n"
55 "\n"
56 "layout(binding=2) uniform atomic_uint x4;\n"
57 "layout(binding=7, offset=8, offset=0) uniform atomic_uint x5;\n"
58 "layout(binding=3) uniform atomic_uint x6, x7;\n"
59 "\n"
60 "void main() {\n"
61 " fcolor.x = int(atomicCounter(x0[0]) + atomicCounter(x0[1])\n"
62 " + atomicCounter(x1) + atomicCounter(x2)\n"
63 " + atomicCounter(x3) + atomicCounter(x4)\n"
64 " + atomicCounter(x5) + atomicCounter(x6)\n"
65 " + atomicCounter(x7));\n"
66 "}\n";
68 struct buffer_info {
69 unsigned num_counters;
70 unsigned min_reasonable_size;
73 static const struct buffer_info *
74 expected_buffer_info(unsigned binding)
76 if (binding == 0) {
77 static const struct buffer_info info = { 2, 12 };
78 return &info;
79 } else if (binding == 2) {
80 static const struct buffer_info info = { 1, 4 };
81 return &info;
82 } else if (binding == 3) {
83 static const struct buffer_info info = { 4, 24 };
84 return &info;
85 } else if (binding == 7) {
86 static const struct buffer_info info = { 1, 4 };
87 return &info;
88 } else {
89 return NULL;
93 struct counter_info {
94 unsigned binding;
95 unsigned offset;
96 unsigned size;
99 static const struct counter_info *
100 expected_counter_info(const char *name)
102 static const struct {
103 const char *name;
104 const struct counter_info info;
105 } counters[] = {
106 { "x0[0]", { 0, 0, 2 } },
107 { "x1", { 0, 8, 1 }},
108 { "x2", { 3, 8, 1 }},
109 { "x3", { 3, 12, 1 }},
110 { "x4", { 2, 0, 1 }},
111 { "x5", { 7, 0, 1 }},
112 { "x6", { 3, 16, 1 }},
113 { "x7", { 3, 20, 1 }},
115 int i;
117 for (i = 0; i < ARRAY_SIZE(counters); i++) {
118 if (!strcmp(counters[i].name, name))
119 return &counters[i].info;
122 return NULL;
125 void
126 piglit_init(int argc, char **argv)
128 struct atomic_counters_limits ls = atomic_counters_get_limits();
129 bool visited_buffers[8] = { false };
130 bool visited_counters[8] = { false };
131 GLuint prog = glCreateProgram();
132 int i, j, n, ret;
134 piglit_require_gl_version(31);
135 piglit_require_extension("GL_ARB_shader_atomic_counters");
137 if (ls.fragment_counters < 9) {
138 fprintf(stderr, "Insufficient number of supported atomic "
139 "counters.\n");
140 piglit_report_result(PIGLIT_SKIP);
143 if (ls.fragment_buffers < 4) {
144 fprintf(stderr, "Insufficient number of supported atomic "
145 "counter buffers.\n");
146 piglit_report_result(PIGLIT_SKIP);
149 if (!atomic_counters_compile(prog, GL_FRAGMENT_SHADER, fs_source)) {
150 fprintf(stderr, "Program failed to compile.\n");
151 piglit_report_result(PIGLIT_FAIL);
154 if (!atomic_counters_link(prog)) {
155 fprintf(stderr, "Program failed to link.\n");
156 piglit_report_result(PIGLIT_FAIL);
159 glGetProgramiv(prog, GL_ACTIVE_ATOMIC_COUNTER_BUFFERS, &n);
160 if (n != 4) {
161 fprintf(stderr, "Unexpected number of active counter "
162 "buffers.\n");
163 piglit_report_result(PIGLIT_FAIL);
166 if (!piglit_khr_no_error) {
167 ret = 0xdeadbeef;
168 glGetActiveAtomicCounterBufferiv(
169 prog, n, GL_ATOMIC_COUNTER_BUFFER_BINDING, &ret);
171 if (!piglit_check_gl_error(GL_INVALID_VALUE)) {
172 fprintf(stderr, "glGetActiveAtomicCounterBufferiv "
173 "should have failed when trying to query a "
174 "non-existent buffer.\n");
175 piglit_report_result(PIGLIT_FAIL);
178 if (ret != 0xdeadbeef) {
179 fprintf(stderr, "Failed call to "
180 "glGetActiveAtomicCounterBufferiv didn't "
181 "preserve the output parameter contents.\n");
182 piglit_report_result(PIGLIT_FAIL);
186 for (i = 0; i < n; ++i) {
187 const struct buffer_info *binfo;
188 int binding, data_size, num_counters, ref;
189 GLuint counters[4];
191 glGetActiveAtomicCounterBufferiv(
192 prog, i, GL_ATOMIC_COUNTER_BUFFER_BINDING, &binding);
193 if (!piglit_check_gl_error(GL_NO_ERROR)) {
194 fprintf(stderr, "Couldn't obtain counter buffer binding"
195 " point.\n");
196 piglit_report_result(PIGLIT_FAIL);
199 binfo = expected_buffer_info(binding);
200 if (!binfo) {
201 fprintf(stderr, "Got unexpected buffer binding "
202 "point.\n");
203 piglit_report_result(PIGLIT_FAIL);
206 glGetActiveAtomicCounterBufferiv(
207 prog, i, GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE,
208 &data_size);
209 if (!piglit_check_gl_error(GL_NO_ERROR) ||
210 data_size < binfo->min_reasonable_size) {
211 fprintf(stderr, "Invalid buffer data size: %d,"
212 " expected at least: %d.\n", data_size,
213 binfo->min_reasonable_size);
214 piglit_report_result(PIGLIT_FAIL);
217 glGetActiveAtomicCounterBufferiv(
218 prog, i, GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS,
219 &num_counters);
220 if (!piglit_check_gl_error(GL_NO_ERROR) ||
221 num_counters != binfo->num_counters) {
222 fprintf(stderr, "Invalid number of atomic counters: %d,"
223 " expected: %d.\n", num_counters,
224 binfo->num_counters);
225 piglit_report_result(PIGLIT_FAIL);
228 if (visited_buffers[i]) {
229 fprintf(stderr, "Buffer at binding point %d seen twice."
230 "\n", binding);
231 piglit_report_result(PIGLIT_FAIL);
233 visited_buffers[i] = true;
235 glGetActiveAtomicCounterBufferiv(prog, i,
236 GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER,
237 &ref);
238 if (!piglit_check_gl_error(GL_NO_ERROR) || ref) {
239 fprintf(stderr, "Buffer incorrectly reported to be "
240 "referenced by vertex shader.\n");
241 piglit_report_result(PIGLIT_FAIL);
244 glGetActiveAtomicCounterBufferiv(prog, i,
245 GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER,
246 &ref);
247 if (!piglit_check_gl_error(GL_NO_ERROR) || ref) {
248 fprintf(stderr, "Buffer incorrectly reported to be "
249 "referenced by tessellation control shader.\n");
250 piglit_report_result(PIGLIT_FAIL);
253 glGetActiveAtomicCounterBufferiv(prog, i,
254 GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER,
255 &ref);
256 if (!piglit_check_gl_error(GL_NO_ERROR) || ref) {
257 fprintf(stderr, "Buffer incorrectly reported to be "
258 "referenced by tessellation evaluation shader."
259 "\n");
260 piglit_report_result(PIGLIT_FAIL);
263 glGetActiveAtomicCounterBufferiv(prog, i,
264 GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER,
265 &ref);
266 if (!piglit_check_gl_error(GL_NO_ERROR) || ref) {
267 fprintf(stderr, "Buffer incorrectly reported to be "
268 "referenced by geometry shader.\n");
269 piglit_report_result(PIGLIT_FAIL);
272 glGetActiveAtomicCounterBufferiv(prog, i,
273 GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER,
274 &ref);
275 if (!piglit_check_gl_error(GL_NO_ERROR) || !ref) {
276 fprintf(stderr, "Buffer incorrectly reported as "
277 "unreferenced from the fragment shader.\n");
278 piglit_report_result(PIGLIT_FAIL);
281 glGetActiveAtomicCounterBufferiv(prog, i,
282 GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES,
283 (GLint *)counters);
284 if (!piglit_check_gl_error(GL_NO_ERROR)) {
285 fprintf(stderr, "Couldn't obtain list of active atomic "
286 "counters for buffer at binding point %d.\n",
287 binding);
288 piglit_report_result(PIGLIT_FAIL);
291 for (j = 0; j < num_counters; ++j) {
292 const struct counter_info *cinfo;
293 int unif_type, unif_size, unif_name_len,
294 unif_block_idx, unif_offset, unif_stride,
295 unif_buffer_idx;
296 char unif_name[8];
298 glGetActiveUniformName(prog, counters[j],
299 sizeof(unif_name), NULL,
300 unif_name);
302 cinfo = expected_counter_info(unif_name);
303 if (!piglit_check_gl_error(GL_NO_ERROR) || !cinfo) {
304 fprintf(stderr, "Unknown atomic counter \"%s\"."
305 "\n", unif_name);
306 piglit_report_result(PIGLIT_FAIL);
309 glGetActiveUniformsiv(prog, 1, &counters[j],
310 GL_UNIFORM_TYPE, &unif_type);
311 if (!piglit_check_gl_error(GL_NO_ERROR) ||
312 unif_type != GL_UNSIGNED_INT_ATOMIC_COUNTER) {
313 fprintf(stderr, "Atomic counter \"%s\" has "
314 "invalid type 0x%x, expected 0x%x.\n",
315 unif_name, unif_type,
316 GL_UNSIGNED_INT_ATOMIC_COUNTER);
317 piglit_report_result(PIGLIT_FAIL);
320 glGetActiveUniformsiv(prog, 1, &counters[j],
321 GL_UNIFORM_SIZE, &unif_size);
322 if (!piglit_check_gl_error(GL_NO_ERROR) ||
323 unif_size != cinfo->size) {
324 fprintf(stderr, "Atomic counter \"%s\" has "
325 "invalid size %d, expected: %d.\n",
326 unif_name, unif_size, cinfo->size);
327 piglit_report_result(PIGLIT_FAIL);
330 glGetActiveUniformsiv(prog, 1, &counters[j],
331 GL_UNIFORM_NAME_LENGTH, &unif_name_len);
332 if (!piglit_check_gl_error(GL_NO_ERROR) ||
333 unif_name_len != strlen(unif_name) + 1) {
334 fprintf(stderr, "Atomic counter \"%s\" has "
335 "invalid name length %d, expected: %d."
336 "\n", unif_name, unif_name_len,
337 (int)strlen(unif_name) + 1);
338 piglit_report_result(PIGLIT_FAIL);
341 glGetActiveUniformsiv(prog, 1, &counters[j],
342 GL_UNIFORM_BLOCK_INDEX, &unif_block_idx);
343 if (!piglit_check_gl_error(GL_NO_ERROR) ||
344 unif_block_idx != -1) {
345 fprintf(stderr, "Atomic counter \"%s\" has "
346 "invalid block index %d, expected: -1."
347 "\n", unif_name, unif_block_idx);
348 piglit_report_result(PIGLIT_FAIL);
351 glGetActiveUniformsiv(prog, 1, &counters[j],
352 GL_UNIFORM_OFFSET, &unif_offset);
353 if (!piglit_check_gl_error(GL_NO_ERROR) ||
354 unif_offset != cinfo->offset) {
355 fprintf(stderr, "Atomic counter \"%s\" has "
356 "invalid offset %d, expected: %d.\n",
357 unif_name, unif_offset, cinfo->offset);
358 piglit_report_result(PIGLIT_FAIL);
361 glGetActiveUniformsiv(prog, 1, &counters[j],
362 GL_UNIFORM_ARRAY_STRIDE, &unif_stride);
363 if (!piglit_check_gl_error(GL_NO_ERROR) ||
364 (cinfo->size > 1 && unif_stride < 4) ||
365 (cinfo->size == 1 && unif_stride != 0)) {
366 fprintf(stderr, "Atomic counter \"%s\" has "
367 "invalid array stride %d.\n",
368 unif_name, unif_stride);
369 piglit_report_result(PIGLIT_FAIL);
372 glGetActiveUniformsiv(prog, 1, &counters[j],
373 GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX,
374 &unif_buffer_idx);
375 if (!piglit_check_gl_error(GL_NO_ERROR) ||
376 unif_buffer_idx != i) {
377 fprintf(stderr, "Atomic counter \"%s\" has "
378 "invalid buffer index %d, expected %d."
379 "\n", unif_name, unif_buffer_idx, i);
380 piglit_report_result(PIGLIT_FAIL);
383 if (cinfo->binding != binding) {
384 fprintf(stderr, "Atomic counter \"%s\" belongs "
385 "to the wrong binding point %d.\n",
386 unif_name, binding);
387 piglit_report_result(PIGLIT_FAIL);
390 if (visited_counters[counters[j]]) {
391 fprintf(stderr, "Atomic counter \"%s\" seen "
392 "twice.\n", unif_name);
393 piglit_report_result(PIGLIT_FAIL);
395 visited_counters[counters[j]] = true;
399 glDeleteProgram(prog);
401 piglit_report_result(PIGLIT_PASS);
404 enum piglit_result
405 piglit_display(void)
407 return PIGLIT_PASS;