1 /*
2  * Copyright (c) 2013 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 /*
26  * Test 2D depth array texture rendering with gl_Layer (AMD_vertex_shader_layer)
27  *
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
30  * extension.
31  *
32  * This test first renders to a depth array texture which is attached to
33  * a framebuffer. The texture has 5 layers and 7 LODs.
34  *
35  * Once depths have been rendered to each array slice & LOD, the test
36  * then verifies the depth value in each array slice & LOD.
37  */
38 
39 #include "piglit-util-gl.h"
40 
41 #define PAD		5
42 #define SIZE		64
43 #define LAYERS		5
44 #define LOD		7
45 #define DRAW_COUNT	LAYERS * LOD
46 #define STRINGIFY(x)    #x
47 #define EXP_STRINGIFY(x) STRINGIFY(x)
48 
49 PIGLIT_GL_TEST_CONFIG_BEGIN
50 
51 	config.supports_gl_core_version = 31;
52 	config.supports_gl_compat_version = 31;
53 
54 	config.window_width = (((SIZE+PAD)*LAYERS)+PAD);
55 	config.window_height = (((SIZE+PAD)*2)+PAD);
56 	config.window_visual = PIGLIT_GL_VISUAL_DOUBLE | PIGLIT_GL_VISUAL_RGB;
57 
58 PIGLIT_GL_TEST_CONFIG_END
59 
60 static GLuint rectangle_vertices_bo;
61 
62 /* VS and FS to fill the 2D array texture */
63 static const char *fill_tex_vs =
64  "#version 140\n"
65  "#extension GL_AMD_vertex_shader_layer: enable\n"
66  "uniform int drawing_level;\n"
67  "in vec2 vertex;\n"
68  "out vec3 color;\n"
69  "int num_layers = " EXP_STRINGIFY(LAYERS) ";\n"
70  "int draw_count = " EXP_STRINGIFY(DRAW_COUNT) ";\n"
71  "float get_z()\n"
72  "{\n"
73  " return float((drawing_level * num_layers) + gl_InstanceID) / draw_count;\n"
74   "}\n"
75  "void main()\n"
76  "{\n"
77  " gl_Position = vec4(vertex, get_z(), 1.0);\n"
78  " gl_Layer = gl_InstanceID;\n"
79  "}\n";
80 
81 static GLuint fill_tex_program;
82 
83 static bool
render_tex_layers(GLuint tex)84 render_tex_layers(GLuint tex)
85 {
86 	int lod;
87 	GLint drawing_level_loc, vertex_loc;
88 	GLenum status;
89 	int color_index = 0;
90 	int size;
91 
92 	glUseProgram(fill_tex_program);
93 
94 	drawing_level_loc = glGetUniformLocation(fill_tex_program, "drawing_level");
95 
96 	glBindBuffer(GL_ARRAY_BUFFER, rectangle_vertices_bo);
97 	vertex_loc = glGetAttribLocation(fill_tex_program, "vertex");
98 	glVertexAttribPointer(vertex_loc, 2, GL_FLOAT, 0, 0, 0);
99 	glEnableVertexAttribArray(vertex_loc);
100 	for (lod = 0; lod < LOD; lod++) {
101 		size = SIZE >> lod;
102 		glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, tex, lod);
103 		status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
104 		if (status != GL_FRAMEBUFFER_COMPLETE) {
105 			fprintf(stderr, "fbo incomplete (status = %s)\n",
106 			        piglit_get_gl_enum_name(status));
107 			return false;
108 		}
109 
110 		/* Clear background to gray */
111 		glClearDepth(1.0);
112 		glClear(GL_DEPTH_BUFFER_BIT);
113 
114 		glViewport(0, 0, size, size);
115 		glUniform1i(drawing_level_loc, lod);
116 		glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, LAYERS);
117 		color_index += LAYERS;
118 	}
119 	glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, 0, 0);
120 	glDisableVertexAttribArray(vertex_loc);
121 
122 	return true;
123 }
124 
125 static GLuint
build_texture(void)126 build_texture(void)
127 {
128 	GLuint tex;
129 	int lod;
130 	int size;
131 
132 	glGenTextures(1, &tex);
133 	glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
134 	for (lod = 0; lod < LOD; lod++) {
135 		size = SIZE >> lod;
136 		glTexImage3D(GL_TEXTURE_2D_ARRAY, lod, GL_DEPTH_COMPONENT,
137 		             size, size, LAYERS, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
138 	}
139 
140 	render_tex_layers(tex);
141 
142 	return tex;
143 }
144 
145 /* Attach the texture layer/lod to the read framebuffer
146  */
147 static void
set_up_read_framebuffer(GLuint tex,int level,int layer)148 set_up_read_framebuffer(GLuint tex, int level, int layer)
149 {
150 	GLenum status;
151 
152 	glFramebufferTextureLayer(GL_READ_FRAMEBUFFER,
153 				  GL_DEPTH_ATTACHMENT,
154 				  tex, level, layer);
155 
156 	status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
157 	if (status == GL_FRAMEBUFFER_UNSUPPORTED && level == 0) {
158 		printf("This buffer combination is unsupported\n");
159 		piglit_report_result(PIGLIT_SKIP);
160 	} else if (status != GL_FRAMEBUFFER_COMPLETE) {
161 		printf("FBO incomplete at miplevel %d\n", level);
162 		piglit_report_result(PIGLIT_FAIL);
163 	}
164 }
165 
166 static GLboolean
test_texture(GLuint tex)167 test_texture(GLuint tex)
168 {
169 	int layer, lod;
170 	GLboolean retval = GL_TRUE;
171 	float expected;
172 	float draw_count = LAYERS * LOD;
173 	int dim = SIZE;
174 
175 	for (lod = 0; lod < LOD; lod++) {
176 		for (layer = 0; layer < LAYERS; layer++) {
177 			GLboolean pass;
178 			set_up_read_framebuffer(tex, lod, layer);
179 			expected = ((float)(lod * LAYERS) + layer) / draw_count;
180 			expected = (expected / 2.0) + 0.5;
181 			pass = piglit_probe_rect_depth(0, 0, dim, dim, expected);
182 			retval = retval && pass;
183 		}
184 		dim >>= 1;
185 	}
186 
187 	return retval;
188 }
189 
190 enum piglit_result
piglit_display(void)191 piglit_display(void)
192 {
193 	GLboolean pass;
194 	GLuint vao, fbo;
195 	GLuint tex;
196 	static const GLfloat verts[4][2] = {
197 		{ 1.0, -1.0},
198 		{-1.0, -1.0},
199 		{ 1.0,  1.0},
200 		{-1.0,  1.0},
201 	};
202 
203 	glEnable(GL_DEPTH_TEST);
204 
205 	glGenFramebuffers(1, &fbo);
206 	glBindFramebuffer(GL_FRAMEBUFFER, fbo);
207 	glGenVertexArrays(1, &vao);
208 	glBindVertexArray(vao);
209 	glGenBuffers(1, &rectangle_vertices_bo);
210 	glBindBuffer(GL_ARRAY_BUFFER, rectangle_vertices_bo);
211 	glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
212 
213 	tex = build_texture();
214 	pass = test_texture(tex);
215 	glDeleteTextures(1, &tex);
216 
217 	glDeleteBuffers(1, &rectangle_vertices_bo);
218 	glDeleteFramebuffers(1, &fbo);
219 	glDeleteVertexArrays(1, &vao);
220 
221 	return pass ? PIGLIT_PASS : PIGLIT_FAIL;
222 }
223 
224 void
piglit_init(int argc,char ** argv)225 piglit_init(int argc, char **argv)
226 {
227 	/* For glFramebufferTexture we need either GL 3.2 or
228 	 * GL_ARB_geometry_shader4.
229 	 */
230 	if (piglit_get_gl_version() < 32) {
231 		piglit_require_extension("GL_ARB_geometry_shader4");
232 	}
233 
234 	piglit_require_extension("GL_AMD_vertex_shader_layer");
235 
236 	fill_tex_program = piglit_build_simple_program(fill_tex_vs, NULL);
237 	piglit_check_gl_error(GL_NO_ERROR);
238 }
239