perf/pixel-rate: new pixel throughput microbenchmark
[piglit.git] / tests / shaders / fp-long-alu.c
blob888a5778bfb0ccc44e88eac52b76cbfade5aedf4
1 /*
2 * Copyright (c) 2009 Nicolai Hähnle
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 * Nicolai Hähnle <nhaehnle@gmail.com>
28 /**
29 * \file
30 * Test certain type of very long fragment programs.
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
37 #include "piglit-util-gl.h"
39 PIGLIT_GL_TEST_CONFIG_BEGIN
41 config.supports_gl_compat_version = 10;
43 config.window_visual = PIGLIT_GL_VISUAL_RGBA;
45 PIGLIT_GL_TEST_CONFIG_END
47 int max_alu_instructions;
49 static const char program_Head[] =
50 "!!ARBfp1.0\n"
51 "TEMP r;\n"
52 "MOV r, 0;\n"
55 static const char program_Step[] = "ADD %s, r.wxyz, { %f, %f, %f, %f };\n";
57 static const char program_Tail[] =
58 "END\n";
60 static const char program_Output[] = "result.color";
62 static void step_add(unsigned int i, float * add)
64 unsigned int rotate = i % 4;
65 add[(0 + rotate) % 4] = ((i+1) % 16) ? 0.0625 : -1.0+0.0625;
66 add[(1 + rotate) % 4] = ((i+1) % 16) ? 0.0 : (((i+1) % 256) ? 0.0625 : -1.0+0.0625);
67 add[(2 + rotate) % 4] = ((i+1) % 256) ? 0.0 : (((i+1) % 4096) ? 0.0625 : -1.0+0.0625);
68 add[(3 + rotate) % 4] = ((i+1) % 4096) ? 0.0 : 0.0625;
71 static enum piglit_result test(unsigned int alu_depth)
73 char * program_text = malloc(sizeof(program_Head) +
74 2*alu_depth*sizeof(program_Step) +
75 sizeof(program_Tail) +
76 sizeof(program_Output));
77 char * buildp;
78 char buf[128];
79 GLuint program_object;
80 unsigned int i;
81 float expected[4] = { 0.0, 0.0, 0.0, 0.0 };
83 /* Note: This test makes sense up to alu_depth of 65536,
84 * but current drivers are not exactly efficient with such
85 * long programs, and if 16k works, then 64k will probably
86 * work, too ;-)
88 if (!alu_depth || alu_depth > 16384 || alu_depth + 1 > max_alu_instructions) {
89 free(program_text);
90 return PIGLIT_SKIP;
93 printf("Testing: alu_depth = %u\n", alu_depth);
95 memcpy(program_text, program_Head, sizeof(program_Head)-1);
96 buildp = program_text + sizeof(program_Head)-1;
98 for(i = 0; i < alu_depth; ++i) {
99 float add[4];
100 int length;
101 step_add(i, add);
102 length = snprintf(buf, sizeof(buf),
103 program_Step, i == (alu_depth-1) ? program_Output : "r",
104 add[0], add[1], add[2], add[3]);
105 memcpy(buildp, buf, length);
106 buildp += length;
108 memcpy(buildp, program_Tail, sizeof(program_Tail));
110 // printf(program_text);
112 program_object = piglit_compile_program(GL_FRAGMENT_PROGRAM_ARB, program_text);
113 free(program_text);
114 program_text = NULL;
116 glEnable(GL_FRAGMENT_PROGRAM_ARB);
117 glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, program_object);
119 piglit_draw_rect(0, 0, 32, 32);
121 glDisable(GL_FRAGMENT_PROGRAM_ARB);
122 glDeleteProgramsARB(1, &program_object);
124 expected[0] = (alu_depth % 16) * 0.0625;
125 expected[1] = ((alu_depth/16) % 16) * 0.0625;
126 expected[2] = ((alu_depth/256) % 16) * 0.0625;
127 expected[3] = (alu_depth/4096) * 0.0625;
128 for(i = 0; i < ((alu_depth+3) % 4); ++i) {
129 float tmp = expected[3];
130 expected[3] = expected[2];
131 expected[2] = expected[1];
132 expected[1] = expected[0];
133 expected[0] = tmp;
135 if (expected[0] > 1.0)
136 expected[0] = 1.0;
137 if (expected[1] > 1.0)
138 expected[1] = 1.0;
139 if (expected[2] > 1.0)
140 expected[2] = 1.0;
141 if (expected[3] > 1.0)
142 expected[3] = 1.0;
144 if (!piglit_probe_pixel_rgba(16, 16, expected)) {
145 fprintf(stderr, "Failure in alu_depth = %i\n", alu_depth);
146 return PIGLIT_FAIL;
149 return PIGLIT_PASS;
152 enum piglit_result piglit_display(void)
154 enum piglit_result result;
155 unsigned int alu_depth;
157 piglit_ortho_projection(piglit_width, piglit_height, GL_FALSE);
158 glClear(GL_COLOR_BUFFER_BIT);
160 alu_depth = 1;
161 for(;;) {
162 result = test(alu_depth);
163 if (result == PIGLIT_SKIP)
164 break;
165 if (result != PIGLIT_PASS)
166 return result;
168 if (alu_depth < 8) {
169 alu_depth++;
170 } else {
171 /* Not quite powers of two to avoid aliasing */
172 alu_depth = (alu_depth * 2) - 5;
176 return PIGLIT_PASS;
180 void piglit_init(int argc, char ** argv)
182 piglit_require_fragment_program();
184 glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,
185 GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB,
186 &max_alu_instructions);
188 printf("Max (native) ALU instructions: %i\n",
189 max_alu_instructions);