1 /*
2 * Copyright (c) 2015 Intel Corporation
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 DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 /**
25 * @file interpolateAtSample-dynamically-nonuniform.c
26 *
27 * Test ARB_gpu_shader5 interpolateAtSample builtin using dynamically
28 * non-uniform sample IDs.
29 *
30 * A 2x2 multisample floating-point framebuffer is created with four
31 * samples. The buffer is then filled with a single triangle four
32 * times, once with interpolation at each different sample location.
33 * The interpolation values are written into the framebuffer and read
34 * back so that it will know the sample location of each sample for
35 * each pixel. This process is then repeated but with each pixel
36 * specifying the sample IDs in a different order so that the sample
37 * ID will be dynamically non-uniform. The results are checked to
38 * ensure that the sample locations are the same as the previous
39 * render.
40 */
41
42 #include "piglit-util-gl.h"
43
44 PIGLIT_GL_TEST_CONFIG_BEGIN
45
46 config.supports_gl_core_version = 32;
47
48 config.window_visual = PIGLIT_GL_VISUAL_DOUBLE | PIGLIT_GL_VISUAL_RGB;
49 config.khr_no_error_support = PIGLIT_NO_ERRORS;
50
51 PIGLIT_GL_TEST_CONFIG_END
52
53 #define N_SAMPLES 4
54 #define FBO_WIDTH 2
55 #define FBO_HEIGHT 2
56
57 static const char
58 vertex_shader[] =
59 "#version 150\n"
60 "in vec2 piglit_vertex;\n"
61 "out vec2 pos;\n"
62 "\n"
63 "void\n"
64 "main()\n"
65 "{\n"
66 " gl_Position = vec4(piglit_vertex, 0.0, 1.0);\n"
67 " pos = piglit_vertex;\n"
68 "}\n";
69
70 static const char
71 fragment_shader_dynamically_uniform[] =
72 "#version 150\n"
73 "#extension GL_ARB_gpu_shader5 : require\n"
74 "in vec2 pos;\n"
75 "uniform int sample_id;\n"
76 "\n"
77 "void\n"
78 "main()\n"
79 "{\n"
80 " gl_FragColor.rg = interpolateAtSample(pos, sample_id);\n"
81 " gl_FragColor.ba = vec2(0.0, 1.0);\n"
82 "}\n";
83
84 static const char
85 fragment_shader_dynamically_non_uniform[] =
86 "#version 150\n"
87 "#extension GL_ARB_gpu_shader5 : require\n"
88 "in vec2 pos;\n"
89 "uniform int sample_id;\n"
90 "\n"
91 "void\n"
92 "main()\n"
93 "{\n"
94 " int sid = sample_id ^ int(ceil(pos.x)) ^\n"
95 " (int(ceil(pos.y)) << 1);\n"
96 " gl_FragColor.rg = interpolateAtSample(pos, sid);\n"
97 " gl_FragColor.ba = vec2(0.0, 1.0);\n"
98 "}\n";
99
100 enum piglit_result
piglit_display(void)101 piglit_display(void)
102 {
103 /* not used */
104 return PIGLIT_FAIL;
105 }
106
107 static void
create_framebuffer(int sample_count,GLuint * fbo,GLuint * rb)108 create_framebuffer(int sample_count,
109 GLuint *fbo,
110 GLuint *rb)
111 {
112 GLenum status;
113
114 glGenFramebuffers(1, fbo);
115 glBindFramebuffer(GL_FRAMEBUFFER, *fbo);
116 glGenRenderbuffers(1, rb);
117 glBindRenderbuffer(GL_RENDERBUFFER, *rb);
118 if (sample_count > 1)
119 glRenderbufferStorageMultisample(GL_RENDERBUFFER,
120 sample_count, /* samples */
121 GL_RG32F,
122 FBO_WIDTH, FBO_HEIGHT);
123 else
124 glRenderbufferStorage(GL_RENDERBUFFER,
125 GL_RG32F,
126 FBO_WIDTH, FBO_HEIGHT);
127 glFramebufferRenderbuffer(GL_FRAMEBUFFER,
128 GL_COLOR_ATTACHMENT0,
129 GL_RENDERBUFFER,
130 *rb);
131
132 status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
133 if (status != GL_FRAMEBUFFER_COMPLETE) {
134 fprintf(stderr, "Multisample FBO incomplete\n");
135 piglit_report_result(PIGLIT_SKIP);
136 }
137 }
138
139 static void
get_samples(bool dynamically_uniform,GLuint ms_fbo,GLuint ss_fbo,GLfloat results[N_SAMPLES][FBO_WIDTH * FBO_HEIGHT * 2])140 get_samples(bool dynamically_uniform,
141 GLuint ms_fbo,
142 GLuint ss_fbo,
143 GLfloat results[N_SAMPLES][FBO_WIDTH * FBO_HEIGHT * 2])
144 {
145 static const float verts[] = {
146 -1.0f, -1.0f,
147 8.0f, -1.0f,
148 -1.0f, 8.0f
149 };
150 const char *fragment_source;
151 GLuint vbo, vao;
152 GLuint prog;
153 GLuint shader_id_location;
154 int attr;
155 int i;
156
157 if (dynamically_uniform)
158 fragment_source = fragment_shader_dynamically_uniform;
159 else
160 fragment_source = fragment_shader_dynamically_non_uniform;
161
162 prog = piglit_build_simple_program(vertex_shader, fragment_source);
163 glUseProgram(prog);
164 shader_id_location = glGetUniformLocation(prog, "sample_id");
165
166 glViewport(0, 0, FBO_WIDTH, FBO_HEIGHT);
167
168 glGenBuffers(1, &vbo);
169 glBindBuffer(GL_ARRAY_BUFFER, vbo);
170 glBufferData(GL_ARRAY_BUFFER, sizeof verts, verts, GL_STATIC_DRAW);
171
172 glGenVertexArrays(1, &vao);
173 glBindVertexArray(vao);
174
175 attr = glGetAttribLocation(prog, "piglit_vertex");
176 glEnableVertexAttribArray(attr);
177 glVertexAttribPointer(attr,
178 2, /* size */
179 GL_FLOAT,
180 GL_FALSE, /* normalized */
181 sizeof (GLfloat) * 2,
182 NULL /* pointer */);
183
184 for (i = 0; i < N_SAMPLES; i++) {
185 glUniform1i(shader_id_location, i);
186
187 glBindFramebuffer(GL_FRAMEBUFFER, ms_fbo);
188 glClear(GL_COLOR_BUFFER_BIT);
189
190 glDrawArrays(GL_TRIANGLES, 0, 3);
191
192 glBindFramebuffer(GL_READ_FRAMEBUFFER, ms_fbo);
193 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, ss_fbo);
194
195 glClear(GL_COLOR_BUFFER_BIT);
196 glBlitFramebuffer(0, 0, /* srcX/Y0 */
197 FBO_WIDTH, FBO_HEIGHT, /* srcX/Y1 */
198 0, 0, /* dstX/Y0 */
199 FBO_WIDTH, FBO_HEIGHT, /* dstX/Y1 */
200 GL_COLOR_BUFFER_BIT,
201 GL_NEAREST);
202
203 glBindFramebuffer(GL_FRAMEBUFFER, ss_fbo);
204
205 glReadPixels(0, 0, /* x/y */
206 FBO_WIDTH, FBO_HEIGHT,
207 GL_RG, GL_FLOAT,
208 results[i]);
209 }
210
211 glDeleteBuffers(1, &vbo);
212 glDeleteVertexArrays(1, &vao);
213
214 glDeleteProgram(prog);
215 }
216
217 static void
print_coords(int x,int y,const GLfloat * results)218 print_coords(int x, int y,
219 const GLfloat *results)
220 {
221 printf(" %f,%f",
222 results[(x + y * FBO_WIDTH) * 2] + 1.0f - x,
223 results[(x + y * FBO_WIDTH) * 2 + 1] + 1.0f - y);
224 }
225
226 void
piglit_init(int argc,char ** argv)227 piglit_init(int argc, char**argv)
228 {
229 GLuint ms_fbo, ms_rb;
230 GLuint ss_fbo, ss_rb;
231 GLfloat du_results[N_SAMPLES][FBO_WIDTH * FBO_HEIGHT * 2];
232 GLfloat dnu_results[N_SAMPLES][FBO_WIDTH * FBO_HEIGHT * 2];
233 bool pass = true;
234 int x, y, i, j;
235
236 piglit_require_extension("GL_ARB_gpu_shader5");
237 piglit_require_GLSL_version(150);
238
239 create_framebuffer(N_SAMPLES,
240 &ms_fbo, &ms_rb);
241 create_framebuffer(1, /* sample_count */
242 &ss_fbo, &ss_rb);
243
244 get_samples(true, ms_fbo, ss_fbo, du_results);
245 get_samples(false, ms_fbo, ss_fbo, dnu_results);
246
247 glDeleteFramebuffers(1, &ms_fbo);
248 glDeleteRenderbuffers(1, &ms_rb);
249 glDeleteFramebuffers(1, &ss_fbo);
250 glDeleteRenderbuffers(1, &ss_rb);
251
252 for (y = 0; y < FBO_HEIGHT; y++) {
253 for (x = 0; x < FBO_WIDTH; x++) {
254 printf("Dynamically uniform coords at (%i,%i):",
255 x, y);
256 for (i = 0; i < N_SAMPLES; i++)
257 print_coords(x, y, du_results[i]);
258 fputc('\n', stdout);
259 printf("Dynamically non-uniform coords at (%i,%i):",
260 x, y);
261 for (i = 0; i < N_SAMPLES; i++) {
262 j = i ^ x ^ (y << 1);
263 print_coords(x, y, dnu_results[j]);
264 if (memcmp(&du_results[i]
265 [(y * FBO_WIDTH + x) * 2],
266 &dnu_results[j]
267 [(y * FBO_WIDTH + x) * 2],
268 sizeof (GLfloat) * 2))
269 pass = false;
270
271 }
272 fputc('\n', stdout);
273 }
274 }
275
276 piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL);
277 }
278
279