1 /*
2  * Copyright © 2015 Ilia Mirkin
3  *
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:
10  *
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.
14  *
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.
22  *
23  * Heavily based on textureSize.c
24  */
25 
26 /**
27  * \file textureSamples.c
28  *
29  * Tests the ARB_shader_texture_image_samples textureSamples() built-in.
30  *
31  * The test covers:
32  * - All pipeline stages (VS, GS, FS)
33  * - Sampler data types (floating point, signed integer, unsigned integer)
34  * - Sampler dimensionality (2DMS, 2DMSArray)
35  *
36  * The "textureSamples" binary takes three arguments:
37  *   shader stage
38  *   sampler type
39  *   number of samples
40  *
41  * For example:
42  * ./bin/textureSamples fs sampler2DMS 4
43  * ./bin/textureSamples vs usampler2DMSArray 2
44  */
45 #include "common.h"
46 
47 void
48 parse_args(int argc, char **argv);
49 static enum shader_target test_stage = UNKNOWN;
50 
51 PIGLIT_GL_TEST_CONFIG_BEGIN
52 
53 	config.window_visual = PIGLIT_GL_VISUAL_RGB | PIGLIT_GL_VISUAL_DOUBLE;
54 	config.khr_no_error_support = PIGLIT_NO_ERRORS;
55 
56 	piglit_gl_process_args(&argc, argv, &config);
57 
58 	parse_args(argc, argv);
59 	if (test_stage == GS) {
60 		config.supports_gl_compat_version = 32;
61 		config.supports_gl_core_version = 32;
62 	} else {
63 		config.supports_gl_compat_version = 30;
64 		config.supports_gl_core_version = 31;
65 	}
66 
67 PIGLIT_GL_TEST_CONFIG_END
68 
69 enum piglit_result
piglit_display()70 piglit_display()
71 {
72 	bool pass = true;
73 
74 	glClearColor(0.5, 0.5, 0.5, 1.0);
75 	glClear(GL_COLOR_BUFFER_BIT);
76 
77 	float expected_color[4] = {0, 1, 0};
78 	glViewport(0, 0, piglit_width, piglit_height);
79 	piglit_draw_rect(-1, -1, 2, 2);
80 
81 	pass &= piglit_probe_rect_rgb(0, 0, piglit_width, piglit_height,
82 				      expected_color);
83 
84 	piglit_present_results();
85 
86 	return pass ? PIGLIT_PASS : PIGLIT_FAIL;
87 }
88 
89 void
generate_texture()90 generate_texture()
91 {
92 	GLuint tex;
93 	GLint samples = 0;
94 	GLenum target = sampler.target;
95 
96 	glActiveTexture(GL_TEXTURE0);
97 	glGenTextures(1, &tex);
98 	glBindTexture(target, tex);
99 
100 	if (target == GL_TEXTURE_2D_MULTISAMPLE)
101 		glTexImage2DMultisample(target, sample_count, GL_RGBA8,
102 					32, 32, GL_TRUE);
103 	else
104 		glTexImage3DMultisample(target, sample_count, GL_RGBA8,
105 					32, 32, 32, GL_TRUE);
106 	glGetTexLevelParameteriv(
107 		target, 0, GL_TEXTURE_SAMPLES, &samples);
108 	if (samples != sample_count) {
109 		printf("Sample count of %d not supported, "
110 		       "got %d samples\n",
111 		       sample_count, samples);
112 		piglit_report_result(PIGLIT_SKIP);
113 	}
114 }
115 
116 int
generate_GLSL(enum shader_target test_stage)117 generate_GLSL(enum shader_target test_stage)
118 {
119 	int vs, gs = 0, fs;
120 	int prog;
121 
122 	static char *vs_code;
123 	static char *gs_code = NULL;
124 	static char *fs_code;
125 
126 	switch (test_stage) {
127 	case VS:
128 		(void)!asprintf(&vs_code,
129 			 "#version %d\n"
130 			 "#extension GL_ARB_texture_multisample: enable\n"
131 			 "#extension GL_ARB_shader_texture_image_samples: enable\n"
132 			 "uniform %s tex;\n"
133 			 "in vec4 piglit_vertex;\n"
134 			 "flat out int samples;\n"
135 			 "void main()\n"
136 			 "{\n"
137 			 "    samples = textureSamples(tex);\n"
138 			 "    gl_Position = piglit_vertex;\n"
139 			 "}\n",
140 			 shader_version, sampler.name);
141 		break;
142 	case GS:
143 		(void)!asprintf(&vs_code,
144 			 "#version %d\n"
145 			 "in vec4 piglit_vertex;\n"
146 			 "out vec4 pos_to_gs;\n"
147 			 "void main()\n"
148 			 "{\n"
149 			 "    pos_to_gs = piglit_vertex;\n"
150 			 "}\n",
151 			 shader_version);
152 		(void)!asprintf(&gs_code,
153 			 "#version %d\n"
154 			 "#extension GL_ARB_texture_multisample: enable\n"
155 			 "#extension GL_ARB_shader_texture_image_samples: enable\n"
156 			 "layout(triangles) in;\n"
157 			 "layout(triangle_strip, max_vertices = 3) out;\n"
158 			 "uniform %s tex;\n"
159 			 "in vec4 pos_to_gs[3];\n"
160 			 "flat out int samples;\n"
161 			 "void main()\n"
162 			 "{\n"
163 			 "    for (int i = 0; i < 3; i++) {\n"
164 			 "	  samples = textureSamples(tex);\n"
165 			 "	  gl_Position = pos_to_gs[i];\n"
166 			 "	  EmitVertex();\n"
167 			 "    }\n"
168 			 "}\n",
169 			 shader_version, sampler.name);
170 		break;
171 	case FS:
172 		(void)!asprintf(&vs_code,
173 			 "#version %d\n"
174 			 "in vec4 piglit_vertex;\n"
175 			 "void main()\n"
176 			 "{\n"
177 			 "    gl_Position = piglit_vertex;\n"
178 			 "}\n",
179 			 shader_version);
180 		(void)!asprintf(&fs_code,
181 			 "#version %d\n"
182 			 "#extension GL_ARB_texture_multisample: enable\n"
183 			 "#extension GL_ARB_shader_texture_image_samples: enable\n"
184 			 "uniform %s tex;\n"
185 			 "out vec4 color;\n"
186 			 "void main()\n"
187 			 "{\n"
188 			 "  if (textureSamples(tex) == %d) color = vec4(0,1,0,1);\n"
189 			 "  else color = vec4(1,0,0,1);\n"
190 			 "}\n",
191 			 shader_version, sampler.name, sample_count);
192 		break;
193 	default:
194 		assert(!"Should not get here.");
195 		break;
196 	}
197 
198 	switch (test_stage) {
199 	case VS:
200 	case GS:
201 		(void)!asprintf(&fs_code,
202 			 "#version %d\n"
203 			 "flat in int samples;\n"
204 			 "out vec4 color;\n"
205 			 "void main()\n"
206 			 "{\n"
207 			 "  if (samples == %d) color = vec4(0,1,0,1);\n"
208 			 "  else color = vec4(1,0,0,1);\n"
209 			 "}\n",
210 			 shader_version, sample_count);
211 		break;
212 	default:
213 		break;
214 	}
215 
216 	vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vs_code);
217 	if (gs_code) {
218 		gs = piglit_compile_shader_text(GL_GEOMETRY_SHADER, gs_code);
219 	}
220 	fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, fs_code);
221 
222 	if (!vs || (gs_code && !gs) || !fs)
223 		return 0;
224 
225 	prog = glCreateProgram();
226 	glAttachShader(prog, vs);
227 	if (gs_code)
228 		glAttachShader(prog, gs);
229 	glAttachShader(prog, fs);
230 	glLinkProgram(prog);
231 	if (!piglit_link_check_status(prog))
232 		piglit_report_result(PIGLIT_FAIL);
233 
234 	return prog;
235 }
236 
237 void
fail_and_show_usage()238 fail_and_show_usage()
239 {
240 	printf("Usage: textureSamples <vs|gs|fs> <sampler type> <sample_count> [piglit args...]\n");
241 	piglit_report_result(PIGLIT_SKIP);
242 }
243 
244 
245 void
parse_args(int argc,char ** argv)246 parse_args(int argc, char **argv)
247 {
248 	int i;
249 	bool sampler_found = false;
250 
251 	for (i = 1; i < argc; i++) {
252 		if (test_stage == UNKNOWN) {
253 			/* Maybe it's the shader stage? */
254 			if (strcmp(argv[i], "vs") == 0) {
255 				test_stage = VS;
256 				continue;
257 			} else if (strcmp(argv[i], "gs") == 0) {
258 				test_stage = GS;
259 				continue;
260 			} else if (strcmp(argv[i], "fs") == 0) {
261 				test_stage = FS;
262 				continue;
263 			}
264 		}
265 
266 		/* Maybe it's the sampler type? */
267 		if (!sampler_found && (sampler_found = select_sampler(argv[i])))
268 			continue;
269 
270 		/* Maybe it's the sample count? */
271 		if (sampler_found && !sample_count) {
272 			sample_count = atoi(argv[i]);
273 			continue;
274 		}
275 
276 		fail_and_show_usage();
277 	}
278 
279 	if (test_stage == UNKNOWN || !sampler_found)
280 		fail_and_show_usage();
281 
282 	if (test_stage == GS && shader_version < 150)
283 		shader_version = 150;
284 }
285 
286 
287 void
piglit_init(int argc,char ** argv)288 piglit_init(int argc, char **argv)
289 {
290 	int prog;
291 
292 	piglit_require_extension("GL_ARB_shader_texture_image_samples");
293 	require_GL_features(test_stage);
294 
295 	if (sample_count > 1) {
296 		/* check it */
297 		GLint max_samples;
298 
299 		if (sampler.data_type == GL_INT ||
300 		    sampler.data_type == GL_UNSIGNED_INT) {
301 			glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &max_samples);
302 			if (sample_count > max_samples) {
303 				printf("Sample count of %d not supported,"
304 				       " >MAX_INTEGER_SAMPLES\n",
305 				       sample_count);
306 				piglit_report_result(PIGLIT_SKIP);
307 			}
308 		} else {
309 			glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
310 			if (sample_count > max_samples) {
311 				printf("Sample count of %d not supported,"
312 				       " >MAX_SAMPLES\n",
313 				       sample_count);
314 				piglit_report_result(PIGLIT_SKIP);
315 			}
316 		}
317 	} else {
318 		sample_count = 1;
319 	}
320 
321 	prog = generate_GLSL(test_stage);
322 	if (!prog)
323 		piglit_report_result(PIGLIT_FAIL);
324 
325 	glUseProgram(prog);
326 
327 	generate_texture();
328 }
329