2 * Copyright (c) 2015 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
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.
24 #include "piglit-util-gl.h"
27 * A test to check whether GL_ARB_fragment_shader_interlock operates as
28 * expected. This test simulates blending behaviour by using image loads/stores
29 * to a 3D texture. The blending formula used is:
30 * result = current_alpha * current_color + (1 - current_alpha) * previous_color
31 * Multisampling is also enabled and tested at 2, 4, 8 and 16.
34 PIGLIT_GL_TEST_CONFIG_BEGIN
35 config
.supports_gl_compat_version
= 42;
36 config
.supports_gl_core_version
= 42;
37 config
.window_width
= 100;
38 config
.window_height
= 100;
39 config
.window_visual
= PIGLIT_GL_VISUAL_RGB
| PIGLIT_GL_VISUAL_DEPTH
|
40 PIGLIT_GL_VISUAL_DOUBLE
;
41 PIGLIT_GL_TEST_CONFIG_END
43 static GLuint prog
, vao
, tex_frame
, tex_blend
, fbo
;
49 glGenFramebuffers(1, &fbo
);
50 glBindFramebuffer(GL_FRAMEBUFFER
, fbo
);
51 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE
, tex_frame
);
52 glFramebufferTexture2D(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
53 GL_TEXTURE_2D_MULTISAMPLE
, tex_frame
, 0);
59 make_shader_program(void)
61 static const char *vs_text
=
63 "layout(location = 0) in vec4 pos_in;\n"
64 "layout(location = 1) in vec4 col_in;\n"
65 "smooth out vec4 col_vary;\n"
68 " gl_Position = pos_in;\n"
69 " col_vary = col_in;\n"
72 static const char *fs_text
=
74 "#extension GL_ARB_fragment_shader_interlock: require\n"
75 "layout(pixel_interlock_ordered) in;\n"
76 "layout(rgba32f, binding = 0) uniform image3D img_output;\n"
77 "layout(location = 1) uniform int sample_rate;\n"
78 "smooth in vec4 col_vary;\n"
82 " vec4 result = vec4(0.0, 0.0, 0.0, 1.0);\n"
83 " ivec3 current_sample_coord = ivec3(gl_FragCoord.x, gl_FragCoord.y, gl_SampleID);\n"
84 " ivec3 result_coord = ivec3(gl_FragCoord.x, gl_FragCoord.y, sample_rate);\n"
86 " beginInvocationInterlockARB();\n"
87 " vec4 current_sample_color = imageLoad(img_output, current_sample_coord);\n"
88 " result.rgb += col_vary.a * col_vary.rgb + (1 - col_vary.a) * current_sample_color.rgb;\n"
89 " imageStore(img_output, current_sample_coord, result);\n"
91 " for (i = 0; i < sample_rate; i++) {\n"
92 " if (i != gl_SampleID) {\n"
93 " ivec3 sample_coord = ivec3(gl_FragCoord.x, gl_FragCoord.y, i);\n"
94 " vec4 sample_color = imageLoad(img_output, sample_coord);\n"
95 " result.rgb += sample_color.rgb;\n"
98 " result.rgb /= sample_rate;\n"
99 " imageStore(img_output, result_coord, result);\n"
100 " endInvocationInterlockARB();\n"
101 " col_out = result;\n"
106 prog
= piglit_build_simple_program(vs_text
, fs_text
);
109 glBindAttribLocation(prog
, 0, "pos_in");
110 glBindAttribLocation(prog
, 1, "col_in");
114 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
115 piglit_report_result(PIGLIT_FAIL
);
122 make_texture_buffer(void)
126 glGenTextures(1, &tex
);
127 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE
, tex
);
128 glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE
, 2,
129 GL_RGBA32F
, piglit_width
, piglit_height
, false);
130 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE
, tex
);
136 make_texture_blend(void)
140 glGenTextures(1, &tex
);
141 glActiveTexture(GL_TEXTURE0
);
142 glBindTexture(GL_TEXTURE_3D
, tex
);
143 glTexParameteri(GL_TEXTURE_3D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
144 glTexParameteri(GL_TEXTURE_3D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
145 glTexParameteri(GL_TEXTURE_3D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
146 glTexParameteri(GL_TEXTURE_3D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
147 glBindImageTexture(0, tex
, 0, GL_TRUE
, 0, GL_READ_WRITE
, GL_RGBA32F
);
155 static const float pos_col
[18][6] = {
156 { -1.0, -1.0, 0.0, 1.0, 0.0, 0.25 },
157 { 0.0, -1.0, 0.0, 1.0, 0.0, 0.25 },
158 { 0.0, 1.0, 0.0, 1.0, 0.0, 0.25 },
159 { 0.0, 1.0, 0.0, 1.0, 0.0, 0.25 },
160 { -1.0, 1.0, 0.0, 1.0, 0.0, 0.25 },
161 { -1.0, -1.0, 0.0, 1.0, 0.0, 0.25 },
162 { -1.0, -1.0, 1.0, 0.0, 0.0, 0.25 },
163 { 1.0, -1.0, 1.0, 0.0, 0.0, 0.25 },
164 { 1.0, 1.0, 1.0, 0.0, 0.0, 0.25 },
165 { 1.0, 1.0, 1.0, 0.0, 0.0, 0.25 },
166 { -1.0, 1.0, 1.0, 0.0, 0.0, 0.25 },
167 { -1.0, -1.0, 1.0, 0.0, 0.0, 0.25 },
168 { -1.0, -1.0, 0.0, 0.0, 1.0, 0.25 },
169 { 1.0, -1.0, 0.0, 0.0, 1.0, 0.25 },
170 { 1.0, 1.0, 0.0, 0.0, 1.0, 0.25 },
171 { 1.0, 1.0, 0.0, 0.0, 1.0, 0.25 },
172 { -1.0, 1.0, 0.0, 0.0, 1.0, 0.25 },
173 { -1.0, -1.0, 0.0, 0.0, 1.0, 0.25 }
176 const int stride
= sizeof(pos_col
[0]);
179 glGenVertexArrays(1, &vao
);
180 glBindVertexArray(vao
);
182 glGenBuffers(1, &vbo
);
183 glBindBuffer(GL_ARRAY_BUFFER
, vbo
);
184 glBufferData(GL_ARRAY_BUFFER
, sizeof(pos_col
), pos_col
, GL_STATIC_DRAW
);
186 glVertexAttribPointer(0, 2, GL_FLOAT
, GL_FALSE
, stride
, (void *) 0);
187 glVertexAttribPointer(1, 4, GL_FLOAT
, GL_FALSE
, stride
,
188 (void *)(sizeof(float) * 2));
190 glEnableVertexAttribArray(0);
191 glEnableVertexAttribArray(1);
193 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
194 piglit_report_result(PIGLIT_FAIL
);
201 piglit_init(int argc
, char **argv
)
203 piglit_require_extension("GL_ARB_fragment_shader_interlock");
205 glEnable(GL_MULTISAMPLE
);
206 glDisable(GL_CULL_FACE
);
207 glClearColor(0.0, 0.0, 0.0, 1.0);
209 prog
= make_shader_program();
211 tex_frame
= make_texture_buffer();
213 tex_blend
= make_texture_blend();
219 int samples
[4] = { 2, 4, 8, 16 };
222 const unsigned result1
[4] = { 47, 35, 63, 255 };
223 const unsigned result2
[4] = { 47, 0, 63, 255 };
226 glViewport(0, 0, piglit_width
, piglit_height
);
227 glGetIntegerv(GL_MAX_SAMPLES
, &max_samples
);
229 for (i
= 0; i
< 4 && samples
[i
] <= max_samples
; i
++) {
230 GLfloat
*tex_data
= calloc(piglit_width
* piglit_height
*
231 (samples
[i
] + 1) * 4, sizeof(GLfloat
));
233 glTexImage3D(GL_TEXTURE_3D
, 0, GL_RGBA32F
, piglit_width
, piglit_height
,
234 samples
[i
] + 1, 0, GL_RGBA
, GL_FLOAT
, tex_data
);
236 glBindFramebuffer(GL_DRAW_FRAMEBUFFER
, fbo
);
237 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE
, tex_frame
);
238 glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE
, samples
[i
],
239 GL_RGBA8
, piglit_width
, piglit_height
, false);
240 glUniform1i(1, samples
[i
]);
242 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
|
243 GL_STENCIL_BUFFER_BIT
);
246 glDrawArrays(GL_TRIANGLES
, 0, 18);
248 glBindFramebuffer(GL_DRAW_FRAMEBUFFER
, 0);
249 glBindFramebuffer(GL_READ_FRAMEBUFFER
, fbo
);
250 glDrawBuffer(GL_BACK
);
251 glBlitFramebuffer(0, 0, piglit_width
, piglit_height
, 0, 0, piglit_width
,
252 piglit_height
, GL_COLOR_BUFFER_BIT
, GL_NEAREST
);
253 pass
= piglit_check_gl_error(GL_NO_ERROR
) && pass
;
254 piglit_present_results();
256 glGetTexImage(GL_TEXTURE_3D
, 0, GL_RGBA
, GL_FLOAT
, tex_data
);
257 for (j
= 0; j
< piglit_height
; j
++) {
258 for (k
= 0; k
< piglit_width
; k
++) {
259 unsigned l
= ((piglit_width
* piglit_height
* samples
[i
]) +
260 (j
* piglit_width
) + k
) * 4;
261 unsigned r
= fabs(tex_data
[l
]) * 255;
262 unsigned g
= fabs(tex_data
[l
+ 1]) * 255;
263 unsigned b
= fabs(tex_data
[l
+ 2]) * 255;
264 unsigned a
= fabs(tex_data
[l
+ 3]) * 255;
266 if ((k
< piglit_width
/ 2) && (r
!= result1
[0] ||
267 g
!= result1
[1] || b
!= result1
[2] || a
!= result1
[3])) {
268 printf("observed %u %u %u %u %u %u\n", j
, k
, r
,
270 printf("expected %u %u %u %u %u %u\n", j
, k
,
271 result1
[0], result1
[1], result1
[2], result1
[3]);
276 if ((k
> piglit_width
/ 2) && (r
!= result2
[0] ||
277 g
!= result2
[1] || b
!= result2
[2] || a
!= result2
[3])) {
278 printf("observed %u %u %u %u %u %u\n", j
, k
, r
,
280 printf("expected %u %u %u %u %u %u\n", j
, k
,
281 result1
[0], result1
[1], result1
[2], result1
[3]);
291 pass
= piglit_check_gl_error(GL_NO_ERROR
) && pass
;
296 return pass
? PIGLIT_PASS
: PIGLIT_FAIL
;