cl: Don't use device_infos if num_device_infos == 0
[piglit.git] / tests / shaders / fp-indirections.c
blob584cff17bb1b0bc5e180c85ef14f8749f23f6b1d
1 /*
2 * Copyright © 2008 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.
23 * Authors:
24 * Eric Anholt <eric@anholt.net>
28 #include "piglit-util-gl.h"
30 PIGLIT_GL_TEST_CONFIG_BEGIN
32 config.supports_gl_compat_version = 10;
34 config.window_visual = PIGLIT_GL_VISUAL_RGB | PIGLIT_GL_VISUAL_DOUBLE;
36 PIGLIT_GL_TEST_CONFIG_END
38 static int get_program_i(GLenum pname)
40 GLint val;
42 glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, pname, &val);
44 return val;
47 /**
48 * Generate a program that samples the texture into the same temporary over
49 * and over..
51 * This should exercise case (2) of question (24) of the ARB_fragment_program
52 * spec.
54 * Note that the compiler could optimize out our inner TEX instructions
55 * since they've got the same coordinates. Assume the compiler isn't
56 * for now.
58 static char *gen_temporary_dest_indirections(int sample_count,
59 GLuint *progname)
61 char *prog;
62 char *pre =
63 "!!ARBfp1.0\n"
64 "TEMP val, sample;\n"
65 "MOV val, fragment.color;\n";
66 char *sample =
67 "TEX sample, fragment.color, texture[0], 2D;\n"
68 "MUL val, val, sample;\n";
69 char *post =
70 "MOV result.color, val;\n"
71 "END";
72 int i, instr_count;
74 prog = malloc(strlen(pre) + strlen(sample) * sample_count +
75 strlen(post) + 1);
77 if (prog == 0) {
78 printf("malloc failed.\n");
79 piglit_report_result(PIGLIT_FAIL);
80 exit(1);
83 sprintf(prog, "%s", pre);
84 for (i = 0; i < sample_count; i++)
85 strcat(prog, sample);
86 strcat(prog, post);
88 instr_count = 2 + 2 * (sample_count - 1) + 1;
89 if (get_program_i(GL_MAX_PROGRAM_INSTRUCTIONS_ARB) < instr_count) {
90 printf("indirection count %d too low to generate program with "
91 "%d indirections and %d instructions\n",
92 get_program_i(GL_MAX_PROGRAM_INSTRUCTIONS_ARB),
93 sample_count, instr_count);
94 free(prog);
95 return NULL;
98 *progname = piglit_compile_program(GL_FRAGMENT_PROGRAM_ARB, prog);
99 glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, *progname);
101 return prog;
105 * Generate a program that samples two textures into a pair of temporaries
106 * over and over.
108 * This should exercise case (1) of question (24) of the ARB_fragment_program
109 * spec without hitting case (2) at the same time.
111 * Note that the compiler could optimize out our inner TEX instructions
112 * since they've got the same coordinates. Assume the compiler isn't
113 * for now.
115 static char *gen_temporary_source_indirections(int sample_count,
116 GLuint *progname)
118 char *prog;
119 char *pre =
120 "!!ARBfp1.0\n"
121 "TEMP val, val2, sample, sample2;\n"
122 "MOV val, fragment.color;\n"
123 "MOV val2, fragment.color;\n";
124 char *sample =
125 "TEX sample, val, texture[0], 2D;\n"
126 "TEX sample2, val2, texture[1], 2D;\n"
127 "MUL val, sample, sample2;\n"
128 "MUL val2, val2, val;\n";
129 char *post =
130 "MOV result.color, val;\n"
131 "END";
132 int i, instr_count;
134 instr_count = 2 + 4 * (sample_count - 1) + 1;
135 if (get_program_i(GL_MAX_PROGRAM_INSTRUCTIONS_ARB) < instr_count) {
136 printf("indirection count %d too low to generate program with "
137 "%d indirections and %d instructions\n",
138 get_program_i(GL_MAX_PROGRAM_INSTRUCTIONS_ARB),
139 sample_count, instr_count);
140 return NULL;
143 prog = malloc(strlen(pre) + strlen(sample) * (sample_count - 1) +
144 strlen(post) + 1);
146 if (prog == 0) {
147 printf("malloc failed.\n");
148 piglit_report_result(PIGLIT_FAIL);
149 exit(1);
152 sprintf(prog, "%s", pre);
153 for (i = 0; i < sample_count - 1; i++)
154 strcat(prog, sample);
155 strcat(prog, post);
157 *progname = piglit_compile_program(GL_FRAGMENT_PROGRAM_ARB, prog);
158 glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, *progname);
160 return prog;
163 void
164 print_program_info(char *program)
166 printf("Program:\n");
167 printf("%s", program);
168 printf("\n");
170 printf("tex instructions: %d\n",
171 get_program_i(GL_PROGRAM_TEX_INSTRUCTIONS_ARB));
172 printf("native tex instructions: %d\n",
173 get_program_i(GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB));
174 printf("tex indirections: %d\n",
175 get_program_i(GL_PROGRAM_TEX_INDIRECTIONS_ARB));
176 printf("native tex indirections: %d\n",
177 get_program_i(GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB));
178 printf("\n");
182 * Test that we can emit a whole load of samples as long as the indirection
183 * count is low.
185 GLboolean test_temporary_dest_indirections(void)
187 GLboolean pass = GL_TRUE;
188 GLuint progname;
189 char *prog;
190 GLint indirections_limit, use_limit;
191 GLint count;
193 indirections_limit = get_program_i(GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB);
195 use_limit = MIN2(indirections_limit, 1024);
197 count = use_limit - 1;
198 printf("testing program with %d indirections from temporary dests\n",
199 count);
200 prog = gen_temporary_dest_indirections(count, &progname);
201 if (prog != NULL) {
202 if (!get_program_i(GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB)) {
203 printf("Program with %d indirections unexpectedly "
204 "exceeded native limits.\n", count);
205 print_program_info(prog);
206 pass = GL_FALSE;
208 free(prog);
211 count = use_limit + 1;
212 printf("testing program with %d indirections from temporary dests\n",
213 count);
214 prog = gen_temporary_dest_indirections(count, &progname);
215 if (prog != NULL && count > indirections_limit) {
216 if (get_program_i(GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB)) {
217 printf("Program with %d indirections unexpectedly "
218 "met native limits.\n", count);
219 print_program_info(prog);
221 free(prog);
224 return pass;
228 * Test that we can emit a whole load of samples as long as the indirection
229 * count is low.
231 GLboolean test_temporary_source_indirections(void)
233 GLboolean pass = GL_TRUE;
234 GLuint progname;
235 char *prog;
236 GLint indirections_limit, use_limit;
237 GLint count;
239 indirections_limit = get_program_i(GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB);
241 use_limit = MIN2(indirections_limit, 1024);
243 count = use_limit - 1;
244 printf("testing program with %d indirections from temporary sources\n",
245 count);
246 prog = gen_temporary_source_indirections(count, &progname);
247 if (prog != NULL) {
248 if (!get_program_i(GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB)) {
249 printf("Program with %d indirections unexpectedly "
250 "exceeded native limits.\n", count);
251 print_program_info(prog);
252 pass = GL_FALSE;
254 free(prog);
257 count = use_limit + 1;
258 printf("testing program with %d indirections from temporary sources\n",
259 count);
260 prog = gen_temporary_source_indirections(count, &progname);
261 if (prog != NULL && count > indirections_limit) {
262 if (get_program_i(GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB)) {
263 printf("Program with %d indirections unexpectedly "
264 "met native limits.\n", count);
265 print_program_info(prog);
267 free(prog);
270 return pass;
273 enum piglit_result
274 piglit_display(void)
276 GLboolean pass = GL_TRUE;
278 pass = test_temporary_dest_indirections() && pass;
279 pass = test_temporary_source_indirections() && pass;
281 return pass ? PIGLIT_PASS : PIGLIT_FAIL;
284 void
285 piglit_init(int argc, char **argv)
287 piglit_require_fragment_program();
289 glEnable(GL_FRAGMENT_PROGRAM_ARB);
291 printf("Maximum tex instructions: %d\n",
292 get_program_i(GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB));
293 printf("Maximum native tex instructions: %d\n",
294 get_program_i(GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB));
295 printf("Maximum tex indirections: %d\n",
296 get_program_i(GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB));
297 printf("Maximum native tex indirections: %d\n",
298 get_program_i(GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB));
300 /* If the GL reports more than 10000 texture indirections, then we're probably
301 * running on hardware with no limitations - the driver just picked some
302 * arbitrary large number to report back. The test isn't meaningful, and
303 * the run time explodes with huge limits, so just skip it.
305 * For reference, Mesa and NVIDIA report 16384; AMD reports 2147483647.
306 * Pineview hardware (where this test is relevant) has a limit of 4.
308 if (get_program_i(GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB) > 10000) {
309 printf("Skipping; the hardware doesn't appear to have real limits.\n");
310 piglit_report_result(PIGLIT_SKIP);