2 * Copyright (c) 2013 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 DEALINGS
26 * Test 2D array texture rendering with gl_Layer (AMD_vertex_shader_layer)
28 * This test uses layered rendering (gl_Layer) within the vertex shader.
29 * Support for gl_Layer in VS is added by the AMD_vertex_shader_layer
32 * This test first draws to a color array texture which is attached to
33 * a framebuffer. The texture has 5 layers and 7 LODs.
35 * Once colors have been rendered to each array slice & LOD, the test
36 * then uses the texture to draw on the system framebuffer and verifies
37 * that the expected colors appear.
40 #include "piglit-util-gl.h"
47 PIGLIT_GL_TEST_CONFIG_BEGIN
49 config
.supports_gl_core_version
= 31;
50 config
.supports_gl_compat_version
= 31;
52 config
.window_width
= (((SIZE
+PAD
)*LAYERS
)+PAD
);
53 config
.window_height
= (((SIZE
+PAD
)*2)+PAD
);
54 config
.window_visual
= PIGLIT_GL_VISUAL_DOUBLE
| PIGLIT_GL_VISUAL_RGB
;
56 PIGLIT_GL_TEST_CONFIG_END
58 static GLuint rectangle_vertices_bo
;
60 /* VS and FS to fill the 2D array texture */
61 static const char *fill_tex_vs
=
63 "#extension GL_AMD_vertex_shader_layer: enable\n"
64 "uniform int color_bias;\n"
67 "vec3 get_color(int num)\n"
69 " vec3 result = vec3(0.0);\n"
70 " if ((num & 4) != 0) result.r = 1.0;"
71 " if ((num & 2) != 0) result.g = 1.0;"
72 " if ((num & 1) != 0) result.b = 1.0;"
77 " gl_Position = vec4(vertex, vec2(0.0, 1.0));\n"
78 " gl_Layer = gl_InstanceID;\n"
79 " color = get_color(color_bias + gl_InstanceID);\n"
82 static const char *fill_tex_fs
=
87 " gl_FragColor = vec4(color, 1.0);\n"
90 /* VS and FS to use and test the 2D array texture */
91 static const char *use_tex_vs
=
97 " gl_Position = vec4(vertex, vec2(0.0, 1.0));\n"
98 " coord = (vertex * 0.5) + 0.5;\n"
101 static const char *use_tex_fs
=
103 "uniform sampler2DArray tex; \n"
104 "uniform int layer;\n"
109 " gl_FragColor = textureLod(tex, vec3(coord, float(layer)), lod);\n"
112 static GLuint fill_tex_program
;
113 static GLuint use_tex_program
;
115 static int get_x(int layer
)
117 return ((SIZE
+ PAD
) * layer
) + PAD
;
120 static int get_y(int layer
, int lod
)
122 int size
= SIZE
>> lod
;
123 return PAD
+ (((1 << lod
) - 1) * 2 * size
);
126 static const GLfloat
*get_color(int num
)
130 static const GLfloat colors
[][3] = {
141 color_index
= num
% ARRAY_SIZE(colors
);
142 return colors
[color_index
];
146 render_tex_layers(GLuint tex
)
149 GLint color_bias_loc
;
155 glUseProgram(fill_tex_program
);
157 color_bias_loc
= glGetUniformLocation(fill_tex_program
, "color_bias");
159 glBindBuffer(GL_ARRAY_BUFFER
, rectangle_vertices_bo
);
160 vertex_loc
= glGetAttribLocation(fill_tex_program
, "vertex");
161 glVertexAttribPointer(vertex_loc
, 2, GL_FLOAT
, 0, 0, 0);
162 glEnableVertexAttribArray(vertex_loc
);
163 for (lod
= 0; lod
< LOD
; lod
++) {
165 glFramebufferTexture(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
, tex
, lod
);
166 status
= glCheckFramebufferStatus(GL_FRAMEBUFFER
);
167 if (status
!= GL_FRAMEBUFFER_COMPLETE
) {
168 fprintf(stderr
, "fbo incomplete (status = %s)\n",
169 piglit_get_gl_enum_name(status
));
172 glDrawBuffer(GL_COLOR_ATTACHMENT0
);
173 glViewport(0, 0, size
, size
);
174 glUniform1i(color_bias_loc
, color_index
);
175 glDrawArraysInstanced(GL_TRIANGLE_STRIP
, 0, 4, LAYERS
);
176 color_index
+= LAYERS
;
178 glFramebufferTexture(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
, 0, 0);
179 glBindFramebuffer(GL_FRAMEBUFFER
, piglit_winsys_fbo
);
180 glDisableVertexAttribArray(vertex_loc
);
192 glGenTextures(1, &tex
);
193 glBindTexture(GL_TEXTURE_2D_ARRAY
, tex
);
194 for (lod
= 0; lod
< LOD
; lod
++) {
196 glTexImage3D(GL_TEXTURE_2D_ARRAY
, lod
, GL_RGBA
,
197 size
, size
, LAYERS
, 0, GL_RGBA
, GL_FLOAT
, NULL
);
200 render_tex_layers(tex
);
206 draw_box(GLuint tex
, int layer
, int lod
)
208 GLint layer_loc
, lod_loc
, vertex_loc
;
209 int x
= get_x(layer
);
210 int y
= get_y(layer
, lod
);
211 int size
= SIZE
>> lod
;
213 layer_loc
= glGetUniformLocation(use_tex_program
, "layer");
214 lod_loc
= glGetUniformLocation(use_tex_program
, "lod");
216 glBindBuffer(GL_ARRAY_BUFFER
, rectangle_vertices_bo
);
218 vertex_loc
= glGetAttribLocation(use_tex_program
, "vertex");
219 glVertexAttribPointer(vertex_loc
, 2, GL_FLOAT
, 0, 0, 0);
220 glEnableVertexAttribArray(vertex_loc
);
222 glBindTexture(GL_TEXTURE_2D_ARRAY
, tex
);
224 glViewport(x
, y
, size
, size
);
225 glUniform1i(layer_loc
, layer
);
226 glUniform1i(lod_loc
, lod
);
227 glDrawArrays(GL_TRIANGLE_STRIP
, 0, 4);
229 glDisableVertexAttribArray(vertex_loc
);
233 test_results(int layer
, int lod
)
235 int x
= get_x(layer
);
236 int y
= get_y(layer
, lod
);
237 const GLfloat
*expected_color3f
= get_color((lod
* LAYERS
) + layer
);
239 int size
= SIZE
>> lod
;
241 pass
= piglit_probe_rect_rgb(x
, y
, size
, size
, expected_color3f
);
244 printf("2D array failed at size %d, layer %d\n",
252 test_texture(GLuint tex
)
256 GLboolean pass
= GL_TRUE
;
257 glUseProgram(use_tex_program
);
258 glActiveTexture(GL_TEXTURE0
);
259 tex_loc
= glGetUniformLocation(use_tex_program
, "tex");
260 glUniform1i(tex_loc
, 0);
262 glTexParameteri(GL_TEXTURE_2D_ARRAY
, GL_TEXTURE_MIN_FILTER
,
263 GL_NEAREST_MIPMAP_NEAREST
);
264 glTexParameteri(GL_TEXTURE_2D_ARRAY
, GL_TEXTURE_MAG_FILTER
,
267 for (lod
= 0; lod
< LOD
; lod
++) {
268 for (layer
= 0; layer
< LAYERS
; layer
++) {
269 draw_box(tex
, layer
, lod
);
273 for (lod
= 0; lod
< LOD
; lod
++) {
274 for (layer
= 0; layer
< LAYERS
; layer
++) {
275 pass
= test_results(layer
, lod
) && pass
;
289 static const GLfloat verts
[4][2] = {
296 /* Clear background to gray */
297 glClearColor(0.5, 0.5, 0.5, 1.0);
298 glClear(GL_COLOR_BUFFER_BIT
);
300 glGenFramebuffers(1, &fbo
);
301 glBindFramebuffer(GL_FRAMEBUFFER
, fbo
);
302 glGenVertexArrays(1, &vao
);
303 glBindVertexArray(vao
);
304 glGenBuffers(1, &rectangle_vertices_bo
);
305 glBindBuffer(GL_ARRAY_BUFFER
, rectangle_vertices_bo
);
306 glBufferData(GL_ARRAY_BUFFER
, sizeof(verts
), verts
, GL_STATIC_DRAW
);
308 tex
= build_texture();
309 pass
= test_texture(tex
);
310 glDeleteTextures(1, &tex
);
312 piglit_present_results();
314 glDeleteBuffers(1, &rectangle_vertices_bo
);
315 glDeleteFramebuffers(1, &fbo
);
316 glDeleteVertexArrays(1, &vao
);
318 return pass
? PIGLIT_PASS
: PIGLIT_FAIL
;
322 piglit_init(int argc
, char **argv
)
324 /* For glFramebufferTexture we need either GL 3.2 or
325 * GL_ARB_geometry_shader4.
327 if (piglit_get_gl_version() < 32) {
328 piglit_require_extension("GL_ARB_geometry_shader4");
331 piglit_require_extension("GL_AMD_vertex_shader_layer");
333 fill_tex_program
= piglit_build_simple_program(fill_tex_vs
, fill_tex_fs
);
334 piglit_check_gl_error(GL_NO_ERROR
);
336 use_tex_program
= piglit_build_simple_program(use_tex_vs
, use_tex_fs
);
337 piglit_check_gl_error(GL_NO_ERROR
);