perf/pixel-rate: new pixel throughput microbenchmark
[piglit.git] / tests / texturing / max-samplers.c
blob0fc5bd91b8a11a64a0b2d268805bce97aef249ca
1 /*
2 * Permission is hereby granted, free of charge, to any person obtaining a
3 * copy of this software and associated documentation files (the "Software"),
4 * to deal in the Software without restriction, including without limitation
5 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
6 * and/or sell copies of the Software, and to permit persons to whom the
7 * Software is furnished to do so, subject to the following conditions:
9 * The above copyright notice and this permission notice (including the next
10 * paragraph) shall be included in all copies or substantial portions of the
11 * Software.
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
16 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 * IN THE SOFTWARE.
21 * Authors:
22 * Marek Olšák <maraeo@gmail.com>
25 /**
26 * Tests that binding the maximum number of textures in both the vertex and
27 * fragment shader works.
30 #include <string.h>
31 #include "piglit-util-gl.h"
33 PIGLIT_GL_TEST_CONFIG_BEGIN
35 config.supports_gl_compat_version = 20;
37 config.window_width = 300;
38 config.window_height = 300;
39 config.window_visual = PIGLIT_GL_VISUAL_RGB | PIGLIT_GL_VISUAL_DOUBLE;
40 config.khr_no_error_support = PIGLIT_NO_ERRORS;
42 PIGLIT_GL_TEST_CONFIG_END
44 static const char *vs_source =
45 "#define NUM %i \n"
46 "uniform sampler2D vertex_tex[NUM]; \n"
47 "uniform int vertex_index;"
48 "varying vec3 vertex_tex_color; \n"
49 "void main() \n"
50 "{ \n"
51 " int i; \n"
52 " gl_Position = gl_Vertex; \n"
53 " vertex_tex_color = vec3(0.0); \n"
54 " for (i = 0; i < NUM; i++) \n"
55 " if (i == vertex_index) \n"
56 " vertex_tex_color = texture2DLod(vertex_tex[i], vec2(%f), 0.0).xyz; \n"
57 "} \n";
59 static const char *vs_source_no_textures =
60 "varying vec3 vertex_tex_color; \n"
61 "void main() \n"
62 "{ \n"
63 " gl_Position = gl_Vertex; \n"
64 " vertex_tex_color = vec3(0.0); \n"
65 "} \n";
67 static const char *fs_source =
68 "#define NUM %i \n"
69 "uniform sampler2D fragment_tex[NUM]; \n"
70 "uniform int fragment_index;"
71 "varying vec3 vertex_tex_color; \n"
72 "void main() \n"
73 "{ \n"
74 " int i; \n"
75 " vec3 fragment_tex_color = vec3(0.0); \n"
76 " for (i = 0; i < NUM; i++) \n"
77 " if (i == fragment_index) \n"
78 " fragment_tex_color = texture2D(fragment_tex[i], vec2(%f), 0.0).xyz; \n"
79 " gl_FragColor = vec4(fragment_tex_color + vertex_tex_color, 1.0); \n"
80 "} \n";
82 GLuint prog;
83 static int max_vs_textures, max_fs_textures;
85 static void
86 get_texture_color(int unit, float out[4])
88 out[0] = (unit % 16) / 15.0;
89 out[1] = (unit / 16) / 15.0;
90 out[2] = 0;
91 out[3] = 1;
94 static void
95 set_uniform(GLuint prog, const char *name, int value)
97 GLuint loc = glGetUniformLocation(prog, name);
98 if (loc != -1)
99 glUniform1i(loc, value);
102 static GLvoid
103 draw_rect_core(int ix, int iy, int iw, int ih)
105 float x = -1 + 2.0*ix/piglit_width;
106 float y = -1 + 2.0*iy/piglit_height;
107 float w = 2.0*iw/piglit_width;
108 float h = 2.0*ih/piglit_height;
109 float verts[4][4];
110 GLuint vbo;
112 verts[0][0] = x;
113 verts[0][1] = y;
114 verts[0][2] = 0.0;
115 verts[0][3] = 1.0;
116 verts[1][0] = x + w;
117 verts[1][1] = y;
118 verts[1][2] = 0.0;
119 verts[1][3] = 1.0;
120 verts[2][0] = x + w;
121 verts[2][1] = y + h;
122 verts[2][2] = 0.0;
123 verts[2][3] = 1.0;
124 verts[3][0] = x;
125 verts[3][1] = y + h;
126 verts[3][2] = 0.0;
127 verts[3][3] = 1.0;
129 glGenBuffers(1, &vbo);
130 glBindBuffer(GL_ARRAY_BUFFER, vbo);
131 glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
133 glEnableVertexAttribArray(0);
134 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
136 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
138 glDisableVertexAttribArray(0);
139 glDeleteBuffers(1, &vbo);
142 static GLboolean
143 probe_pixel(int unit, int x, int y)
145 float expected[4];
147 get_texture_color(unit, expected);
149 if (piglit_probe_pixel_rgb(x, y, expected))
150 return GL_TRUE;
152 printf(" When testing texture unit %i\n", unit);
153 return GL_FALSE;
156 enum piglit_result
157 piglit_display(void)
159 GLboolean pass = GL_TRUE;
160 int i, unit, x, y;
162 glClear(GL_COLOR_BUFFER_BIT);
164 x = 0;
165 y = 0;
166 unit = 0;
168 set_uniform(prog, "fragment_index", max_fs_textures);
169 for (i = 0; i < max_vs_textures; i++) {
170 set_uniform(prog, "vertex_index", i);
171 draw_rect_core(x, y, 20, 20);
172 pass = probe_pixel(unit, x+10, y+10) && pass;
174 unit++;
175 x += 20;
176 if (x+20 > piglit_width) {
177 x = 0;
178 y += 20;
182 set_uniform(prog, "vertex_index", max_vs_textures);
183 for (i = 0; i < max_fs_textures; i++) {
184 set_uniform(prog, "fragment_index", i);
185 draw_rect_core(x, y, 20, 20);
186 pass = probe_pixel(unit, x+10, y+10) && pass;
188 unit++;
189 x += 20;
190 if (x+20 > piglit_width) {
191 x = 0;
192 y += 20;
196 piglit_check_gl_error(GL_NO_ERROR);
197 piglit_present_results();
199 return pass ? PIGLIT_PASS : PIGLIT_FAIL;
202 static void
203 set_texture(int unit)
205 GLuint tex;
206 float color[4];
208 get_texture_color(unit, color);
210 glGenTextures(1, &tex);
211 glActiveTexture(GL_TEXTURE0 + unit);
212 glBindTexture(GL_TEXTURE_2D, tex);
213 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 1, 1, 0,
214 GL_RGB, GL_FLOAT, color);
215 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
216 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
217 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
218 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
219 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color);
221 piglit_check_gl_error(GL_NO_ERROR);
224 void
225 piglit_init(int argc, char **argv)
227 GLuint vs, fs, vao;
228 int max_combined_textures, i, unit;
229 char str[2048];
230 float texcoord = 0.5;
232 if (argc == 2 && strcmp(argv[1], "border") == 0) {
233 /* Sample outside of the texture, testing border color. */
234 texcoord = 5.0;
235 } else if (argc != 1) {
236 printf("Usage: max-samples [border]\n");
237 piglit_report_result(PIGLIT_SKIP);
240 /* get limits */
241 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_fs_textures);
242 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &max_vs_textures);
243 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_combined_textures);
244 printf("GL_MAX_TEXTURE_IMAGE_UNITS = %d\n", max_fs_textures);
245 printf("GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS = %d\n", max_vs_textures);
246 printf("GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS = %d\n", max_combined_textures);
248 assert(max_fs_textures <= max_combined_textures);
250 max_vs_textures = MIN2(max_vs_textures, max_combined_textures - max_fs_textures);
252 /* compile shaders */
253 if (max_vs_textures) {
254 sprintf(str, vs_source, max_vs_textures, texcoord);
255 vs = piglit_compile_shader_text(GL_VERTEX_SHADER, str);
257 else {
258 vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vs_source_no_textures);
261 sprintf(str, fs_source, max_fs_textures, texcoord);
262 fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, str);
264 prog = piglit_link_simple_program(vs, fs);
265 glUseProgram(prog);
267 piglit_check_gl_error(GL_NO_ERROR);
269 /* initialize textures */
270 unit = 0;
271 for (i = 0; i < max_vs_textures; i++) {
272 char name[64];
273 sprintf(name, "vertex_tex[%i]", i);
274 set_uniform(prog, name, unit);
275 set_texture(unit);
276 unit++;
279 for (i = 0; i < max_fs_textures; i++) {
280 char name[64];
281 sprintf(name, "fragment_tex[%i]", i);
282 set_uniform(prog, name, unit);
283 set_texture(unit);
284 unit++;
287 glClearColor(0.0, 0.0, 1.0, 1.0);
289 if (piglit_get_gl_version() >= 30) {
290 glGenVertexArrays(1, &vao);
291 glBindVertexArray(vao);
294 piglit_check_gl_error(GL_NO_ERROR);