2 * Copyright © 2009 Intel Corporation
3 * Copyright (c) 2010 VMware, Inc.
4 * Copyright © 2011 Red Hat Inc.
5 * Copyright © 2014 Advanced Micro Devices, Inc.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
29 * Marek Olšák <maraeo@gmail.com>
32 /** @file fbo-depth-array.c
34 * Tests that drawing to or clearing each layer of a depth-stencil array
35 * texture FBO and then drawing views of those individual layers
36 * to the window system framebuffer succeeds.
37 * based on fbo-array.c
40 #include "piglit-util-gl.h"
42 /* GL3 requirement. */
44 #define MAX_MEM (2048*1024)
53 static bool test_stencil
;
54 static bool test_single_size
;
55 static unsigned width
= 32, height
= 32, layers
= 6;
58 static void parse_args(int argc
, char **argv
);
60 PIGLIT_GL_TEST_CONFIG_BEGIN
62 piglit_gl_process_args(&argc
, argv
, &config
);
63 parse_args(argc
, argv
);
65 config
.supports_gl_compat_version
= 33;
66 config
.supports_gl_core_version
= 33;
68 if (!piglit_use_fbo
|| test_single_size
) {
69 config
.window_width
= (width
+ 2) * MIN2(layers
, 4);
70 config
.window_height
= (height
+ 2) * ((layers
+ 2) / 3);
72 config
.window_visual
= PIGLIT_GL_VISUAL_DOUBLE
| PIGLIT_GL_VISUAL_RGB
;
73 config
.khr_no_error_support
= PIGLIT_NO_ERRORS
;
75 PIGLIT_GL_TEST_CONFIG_END
77 static const char *vs_text
=
79 "layout(location = 0) in vec4 piglit_vertex; \n"
80 "layout(location = 1) in vec4 piglit_texcoord; \n"
81 "out vec4 texcoord; \n"
83 " gl_Position = piglit_vertex; \n"
84 " texcoord = piglit_texcoord; \n"
87 static const char *frag_shader_empty_text
=
91 static const char *fs_depth_output_text
=
96 " gl_FragDepth = z; \n"
99 static const char *fs_stencil_output_text
=
101 "#extension GL_ARB_shader_stencil_export : require \n"
102 "uniform int ref; \n"
105 " gl_FragStencilRefARB = ref; \n"
109 static const char *fs_texdepth_text
=
111 "uniform sampler2DArray tex; \n"
112 "uniform float z; \n"
113 "in vec4 texcoord; \n"
116 " gl_FragColor = texture(tex, vec3(texcoord.xy, z)).xxxx; \n"
119 static const char *fs_texstencil_text
=
121 "uniform usampler2DArray tex; \n"
122 "uniform float z; \n"
123 "in vec4 texcoord; \n"
126 " gl_FragColor = vec4(float(texture(tex, vec3(texcoord.xy, z)))) / 255.0; \n"
129 static GLuint program_fs_empty
;
130 static GLuint program_depth_output
;
131 static GLuint program_stencil_output
;
132 static GLuint program_texdepth
;
133 static GLuint program_texstencil
;
137 get_depth_value(unsigned layer
)
139 if (test
== LAYERED_CLEAR
)
140 return 0.4; /* constant */
142 return (double)(layer
+1) / (layers
+1);
146 get_stencil_value(unsigned layer
) {
147 if (test
== LAYERED_CLEAR
)
150 return (layer
+1) * 255 / (layers
+1);
154 get_stencil_value_float(unsigned layer
)
156 return get_stencil_value(layer
) / 255.0;
160 parse_args(int argc
, char **argv
)
162 unsigned lwidth
, lheight
, llayers
;
165 for (i
= 1; i
< argc
; i
++) {
166 if (sscanf(argv
[i
], "%ux%ux%u", &lwidth
, &lheight
, &llayers
) == 3 &&
167 lwidth
&& lheight
&& llayers
) {
171 test_single_size
= true;
173 else if (!strcmp(argv
[i
], "depth-clear")) {
175 puts("Testing glClear");
177 else if (!strcmp(argv
[i
], "depth-layered-clear")) {
178 test
= LAYERED_CLEAR
;
179 puts("Testing layered glClear");
181 else if (!strcmp(argv
[i
], "depth-draw")) {
183 puts("Testing drawing");
185 else if (!strcmp(argv
[i
], "fs-writes-depth")) {
186 test
= FS_WRITES_VALUE
;
187 puts("Testing gl_FragDepth");
189 else if (!strcmp(argv
[i
], "stencil-clear")) {
192 puts("Testing stencil glClear");
194 else if (!strcmp(argv
[i
], "stencil-layered-clear")) {
195 test
= LAYERED_CLEAR
;
197 puts("Testing stencil layered glClear");
199 else if (!strcmp(argv
[i
], "stencil-draw")) {
202 puts("Testing stencil drawing");
204 else if (!strcmp(argv
[i
], "fs-writes-stencil")) {
205 test
= FS_WRITES_VALUE
;
207 puts("Testing gl_FragStencilRef");
210 puts("Invalid parameter.");
211 piglit_report_result(PIGLIT_FAIL
);
217 create_array_fbo(void)
219 GLuint tex
, fb
, z
, ref
;
223 glGenTextures(1, &tex
);
224 glBindTexture(GL_TEXTURE_2D_ARRAY
, tex
);
225 if (!piglit_check_gl_error(GL_NO_ERROR
))
226 piglit_report_result(PIGLIT_FAIL
);
228 /* allocate empty array texture */
229 glTexImage3D(GL_TEXTURE_2D_ARRAY
, 0, GL_DEPTH24_STENCIL8
,
230 width
, height
, layers
, 0,
231 GL_DEPTH_STENCIL
, GL_UNSIGNED_INT_24_8
, NULL
);
232 if (!piglit_check_gl_error(GL_NO_ERROR
))
233 piglit_report_result(PIGLIT_FAIL
);
235 glGenFramebuffers(1, &fb
);
236 glBindFramebuffer(GL_FRAMEBUFFER
, fb
);
238 glDrawBuffer(GL_NONE
);
239 glReadBuffer(GL_NONE
);
241 /* draw something into each layer of the array texture */
242 for (layer
= 0; layer
< layers
; layer
++) {
243 if (test
== LAYERED_CLEAR
) {
244 glFramebufferTexture(GL_FRAMEBUFFER
,
245 test_stencil
? GL_STENCIL_ATTACHMENT
:
249 status
= glCheckFramebufferStatus(GL_FRAMEBUFFER
);
250 if (status
!= GL_FRAMEBUFFER_COMPLETE
) {
251 fprintf(stderr
, "FBO incomplete\n");
255 glViewport(0, 0, width
, height
);
257 glClearStencil(get_stencil_value(0));
258 glClear(GL_STENCIL_BUFFER_BIT
);
261 glClearDepth(get_depth_value(0));
262 glClear(GL_DEPTH_BUFFER_BIT
);
266 glFramebufferTextureLayer(GL_FRAMEBUFFER
,
267 test_stencil
? GL_STENCIL_ATTACHMENT
:
273 if (!piglit_check_gl_error(GL_NO_ERROR
))
274 piglit_report_result(PIGLIT_FAIL
);
276 status
= glCheckFramebufferStatus(GL_FRAMEBUFFER
);
277 if (status
!= GL_FRAMEBUFFER_COMPLETE
) {
278 fprintf(stderr
, "FBO incomplete\n");
282 glViewport(0, 0, width
, height
);
287 glClearStencil(get_stencil_value(layer
));
288 glClear(GL_STENCIL_BUFFER_BIT
);
291 glClearDepth(get_depth_value(layer
));
292 glClear(GL_DEPTH_BUFFER_BIT
);
296 glUseProgram(program_fs_empty
);
298 glEnable(GL_STENCIL_TEST
);
299 glStencilOp(GL_KEEP
, GL_KEEP
, GL_REPLACE
);
300 glStencilFunc(GL_ALWAYS
, get_stencil_value(layer
), 0xff);
302 piglit_draw_rect(-1, -1, 2, 2);
304 glDisable(GL_STENCIL_TEST
);
307 glEnable(GL_DEPTH_TEST
);
308 glDepthFunc(GL_ALWAYS
);
310 piglit_draw_rect_z(get_depth_value(layer
) * 2 - 1,
313 glDisable(GL_DEPTH_TEST
);
317 case FS_WRITES_VALUE
:
319 glUseProgram(program_stencil_output
);
320 ref
= glGetUniformLocation(program_stencil_output
, "ref");
321 glUniform1i(ref
, get_stencil_value(layer
));
323 glEnable(GL_STENCIL_TEST
);
324 glStencilOp(GL_KEEP
, GL_KEEP
, GL_REPLACE
);
325 glStencilFunc(GL_ALWAYS
, 0, 0xff);
327 piglit_draw_rect(-1, -1, 2, 2);
329 glDisable(GL_STENCIL_TEST
);
332 glUseProgram(program_depth_output
);
333 z
= glGetUniformLocation(program_depth_output
, "z");
334 glUniform1f(z
, get_depth_value(layer
));
336 glEnable(GL_DEPTH_TEST
);
337 glDepthFunc(GL_ALWAYS
);
339 piglit_draw_rect(-1, -1, 2, 2);
341 glDisable(GL_DEPTH_TEST
);
349 glDeleteFramebuffers(1, &fb
);
350 if (!piglit_check_gl_error(GL_NO_ERROR
))
351 piglit_report_result(PIGLIT_FAIL
);
355 /* Draw a textured quad, sampling only the given layer of the
359 draw_layer(int x
, int y
,
364 GLfloat depth_coord
= (GLfloat
)depth
;
365 GLuint prog
= test_stencil
? program_texstencil
: program_texdepth
;
369 loc
= glGetUniformLocation(prog
, "tex");
370 z
= glGetUniformLocation(prog
, "z");
371 glUniform1i(loc
, 0); /* texture unit p */
372 glUniform1f(z
, depth_coord
);
374 glViewport(0, 0, piglit_width
, piglit_height
);
375 glBindFramebuffer(GL_FRAMEBUFFER
, piglit_winsys_fbo
);
377 glTexParameteri(GL_TEXTURE_2D_ARRAY
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
378 glTexParameteri(GL_TEXTURE_2D_ARRAY
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
379 glTexParameteri(GL_TEXTURE_2D_ARRAY
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_BORDER
);
380 glTexParameteri(GL_TEXTURE_2D_ARRAY
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_BORDER
);
381 glTexParameteri(GL_TEXTURE_2D_ARRAY
, GL_TEXTURE_WRAP_R
, GL_CLAMP_TO_BORDER
);
383 glTexParameteri(GL_TEXTURE_2D_ARRAY
, GL_DEPTH_STENCIL_TEXTURE_MODE
,
386 piglit_draw_rect_tex((double)x
/ piglit_width
* 2 - 1,
387 (double)y
/ piglit_height
* 2 - 1,
388 (double)tw
/ piglit_width
* 2,
389 (double)th
/ piglit_height
* 2,
390 tx
/ (float) width
, ty
/ (float) height
,
391 tw
/ (float) width
, th
/ (float) height
);
393 if (!piglit_check_gl_error(GL_NO_ERROR
))
394 piglit_report_result(PIGLIT_FAIL
);
397 static GLboolean
draw_and_test_layer(int start_x
, int start_y
,
400 float expected
= (test_stencil
?
401 get_stencil_value_float(layer
) :
402 get_depth_value(layer
));
404 GLboolean pass
= GL_TRUE
;
406 for (ty
= 0; ty
< height
; ty
+= piglit_height
- start_y
) {
407 for (tx
= 0; tx
< width
; tx
+= piglit_width
- start_x
) {
408 tw
= MIN2(piglit_width
- start_x
, width
- tx
);
409 th
= MIN2(piglit_height
- start_y
, height
- ty
);
410 draw_layer(start_x
, start_y
,
415 pass
= piglit_probe_rect_r_ubyte(start_x
, start_y
,
432 printf("Testing %ix%ix%i\n", width
, height
, layers
);
434 glClearColor(0.2, 0.1, 0.1, 1.0);
435 glClear(GL_COLOR_BUFFER_BIT
);
437 tex
= create_array_fbo();
439 for (layer
= 0; layer
< layers
; layer
++) {
442 if (piglit_use_fbo
&& !test_single_size
) {
447 x
= 1 + (layer
% 3) * (width
+ 1);
448 y
= 1 + (layer
/ 3) * (height
+ 1);
450 pass
= draw_and_test_layer(x
, y
, layer
) && pass
;
452 if (piglit_use_fbo
&& !test_single_size
&& layer
< layers
-1) {
453 glClearColor(0.2, 0.1, 0.1, 1.0);
454 glClear(GL_COLOR_BUFFER_BIT
);
458 glDeleteTextures(1, &tex
);
459 if (!piglit_check_gl_error(GL_NO_ERROR
))
460 piglit_report_result(PIGLIT_FAIL
);
470 if (piglit_use_fbo
&& !test_single_size
) {
471 static int dims
[] = {1, 4, 16, 64, 256, 1024, 4096, MAX_DIM
};
473 for (i
= 0; i
< ARRAY_SIZE(dims
); i
++) {
474 for (j
= 0; j
< ARRAY_SIZE(dims
); j
++) {
478 /* Don't allocate too much texture memory. */
479 if (width
*height
> MAX_MEM
) {
480 if (width
> height
&& height
/2 > dims
[j
-1])
482 else if (height
> width
&& width
/2 > dims
[i
-1])
485 if (width
*height
> MAX_MEM
)
489 pass
= test_once() && pass
;
494 pass
= test_once() && pass
;
497 piglit_present_results();
499 return pass
? PIGLIT_PASS
: PIGLIT_FAIL
;
502 void piglit_init(int argc
, char **argv
)
504 if (piglit_get_gl_version() < 33) {
505 piglit_report_result(PIGLIT_SKIP
);
509 piglit_require_extension("GL_ARB_stencil_texturing");
510 if (test
== FS_WRITES_VALUE
)
511 piglit_require_extension("GL_ARB_shader_stencil_export");
515 program_texstencil
= piglit_build_simple_program(vs_text
,
518 if (test
== FS_WRITES_VALUE
)
519 program_stencil_output
= piglit_build_simple_program(vs_text
,
520 fs_stencil_output_text
);
523 program_texdepth
= piglit_build_simple_program(vs_text
,
526 if (test
== FS_WRITES_VALUE
)
527 program_depth_output
= piglit_build_simple_program(vs_text
,
528 fs_depth_output_text
);
531 program_fs_empty
= piglit_build_simple_program(vs_text
,
532 frag_shader_empty_text
);
533 if (!piglit_check_gl_error(GL_NO_ERROR
))
534 piglit_report_result(PIGLIT_FAIL
);