ARB_ubo/referenced-by-shader: pass if shader compiler moves UBOs between shaders
[piglit.git] / tests / spec / arb_uniform_buffer_object / maxuniformblocksize.c
blobce5dd1b10da50e899710aa0d0472ebd8acc9f545
1 /*
2 * Copyright © 2012 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 /** @file maxblocks.c
26 * Tests linking and drawing with uniform buffer objects of size
27 * MAX_UNIFORM_BLOCK_SIZE and MAX_UNIFORM_BLOCK_SIZE + 4.
29 * We test the max size + 4 because implementations are allowed to
30 * link and draw beyond the exposed limits, but at that point there
31 * are no guarantees it will link. Those tests are the "vsexceed" and
32 * "fsexceed" arguments.
35 #include "piglit-util-gl.h"
37 PIGLIT_GL_TEST_CONFIG_BEGIN
39 config.supports_gl_compat_version = 10;
41 config.window_visual = PIGLIT_GL_VISUAL_RGBA | PIGLIT_GL_VISUAL_DOUBLE;
42 config.khr_no_error_support = PIGLIT_NO_ERRORS;
44 PIGLIT_GL_TEST_CONFIG_END
46 static enum {
47 VS,
48 VS_EXCEED,
49 FS,
50 FS_EXCEED,
51 } mode;
53 static void
54 usage(const char *name)
56 fprintf(stderr, "usage: %s <vs | vsexceed | fs | fsexceed>\n",
57 name);
58 piglit_report_result(PIGLIT_FAIL);
61 enum piglit_result
62 piglit_display(void)
64 const char *vs_ubo_template =
65 "#extension GL_ARB_uniform_buffer_object : enable\n"
66 "\n"
67 "varying vec4 vary;"
68 "\n"
69 "layout(std140) uniform ubo {\n"
70 " vec4 v[%d];\n"
71 "};\n"
72 "uniform int i;\n"
73 "\n"
74 "void main() {\n"
75 " gl_Position = gl_Vertex;\n"
76 " vary = v[i];\n"
77 "}\n";
79 const char *fs_template =
80 "#extension GL_ARB_uniform_buffer_object : enable\n"
81 "\n"
82 "varying vec4 vary;"
83 "\n"
84 "void main() {\n"
85 " gl_FragColor = vary;\n"
86 "}\n";
88 const char *vs_template =
89 "#extension GL_ARB_uniform_buffer_object : enable\n"
90 "\n"
91 "void main() {\n"
92 " gl_Position = gl_Vertex;\n"
93 "}\n";
95 const char *fs_ubo_template =
96 "#extension GL_ARB_uniform_buffer_object : enable\n"
97 "\n"
98 "layout(std140) uniform ubo {\n"
99 " vec4 v[%d];\n"
100 "};\n"
101 "uniform int i;\n"
102 "\n"
103 "void main() {\n"
104 " gl_FragColor = v[i];\n"
105 "}\n";
107 GLint max_size, vec4s, i_location;
108 GLuint vs, fs, prog, bo;
109 GLenum target;
110 float *data;
111 size_t size;
112 bool pass = true;
113 bool may_link_fail;
114 const float green[4] = { 0, 1, 0, 0 };
115 int test_index;
117 piglit_require_extension("GL_ARB_uniform_buffer_object");
119 glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &max_size);
120 printf("Max uniform block size: %d\n", max_size);
121 vec4s = max_size / 4 / 4;
123 switch (mode) {
124 case VS:
125 target = GL_VERTEX_SHADER;
126 may_link_fail = false;
127 test_index = vec4s - 1;
128 break;
129 case VS_EXCEED:
130 target = GL_VERTEX_SHADER;
131 may_link_fail = true;
132 vec4s++;
133 test_index = vec4s - 2;
134 break;
135 case FS:
136 target = GL_FRAGMENT_SHADER;
137 may_link_fail = false;
138 test_index = vec4s - 1;
139 break;
140 case FS_EXCEED:
141 target = GL_FRAGMENT_SHADER;
142 may_link_fail = true;
143 vec4s++;
144 test_index = vec4s - 2;
145 break;
146 default:
147 assert(false);
148 target = GL_NONE;
149 may_link_fail = false;
152 switch (target) {
153 case GL_VERTEX_SHADER:
154 printf("Testing VS with uniform block vec4 v[%d]\n", vec4s);
155 vs = piglit_compile_shader_formatted(GL_VERTEX_SHADER,
156 vs_ubo_template, vec4s);
157 fs = piglit_compile_shader_formatted(GL_FRAGMENT_SHADER,
158 "%s", fs_template);
159 break;
160 case GL_FRAGMENT_SHADER:
161 printf("Testing FS with uniform block vec4 v[%d]\n", vec4s);
162 vs = piglit_compile_shader_formatted(GL_VERTEX_SHADER,
163 "%s", vs_template);
164 fs = piglit_compile_shader_formatted(GL_FRAGMENT_SHADER,
165 fs_ubo_template, vec4s);
166 break;
167 default:
168 piglit_report_result(PIGLIT_FAIL);
171 prog = glCreateProgram();
172 glAttachShader(prog, vs);
173 glAttachShader(prog, fs);
174 glLinkProgram(prog);
176 if (may_link_fail) {
177 if (!piglit_link_check_status_quiet(prog)) {
178 printf("Failed to link with uniform block vec4 "
179 "v[%d]\n", vec4s);
180 piglit_report_result(PIGLIT_PASS);
182 } else {
183 if (!piglit_link_check_status_quiet(prog)) {
184 fprintf(stderr,
185 "Failed to link with uniform block vec4 "
186 "v[%d]\n", vec4s);
187 return PIGLIT_FAIL;
191 size = vec4s * 4 * sizeof(float);
192 glGenBuffers(1, &bo);
193 glBindBuffer(GL_UNIFORM_BUFFER, bo);
194 glBufferData(GL_UNIFORM_BUFFER, size, NULL, GL_DYNAMIC_DRAW);
195 data = glMapBuffer(GL_UNIFORM_BUFFER, GL_READ_WRITE);
196 memset(data, 0, size);
198 /* The whole uniform buffer will be zeros, except for the
199 * entry at v[test_index] which will be green.
201 data[test_index * 4 + 0] = green[0];
202 data[test_index * 4 + 1] = green[1];
203 data[test_index * 4 + 2] = green[2];
204 data[test_index * 4 + 3] = green[3];
205 glUnmapBuffer(GL_UNIFORM_BUFFER);
207 glUseProgram(prog);
208 i_location = glGetUniformLocation(prog, "i");
209 glUniform1i(i_location, test_index);
211 glUniformBlockBinding(prog, 0, 0);
212 glBindBufferBase(GL_UNIFORM_BUFFER, 0, bo);
213 piglit_draw_rect(-1, -1, 2, 2);
215 pass = piglit_probe_rect_rgba(0, 0, piglit_width, piglit_height, green);
217 glDeleteProgram(prog);
219 piglit_present_results();
221 return pass ? PIGLIT_PASS : PIGLIT_FAIL;
225 void
226 piglit_init(int argc, char **argv)
228 if (argc < 2)
229 usage(argv[0]);
231 if (strcmp(argv[1], "vs") == 0)
232 mode = VS;
233 else if (strcmp(argv[1], "vsexceed") == 0)
234 mode = VS_EXCEED;
235 else if (strcmp(argv[1], "fs") == 0)
236 mode = FS;
237 else if (strcmp(argv[1], "fsexceed") == 0)
238 mode = FS_EXCEED;
239 else
240 usage(argv[0]);