1 /*
2  * Copyright © 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
21  * DEALINGS IN THE SOFTWARE.
22  */
23 
24 /** @file program-interface-query.c
25  *
26  * Test that checks the proper implementation of GL_ARB_program_interface_query
27  * implementation for shader storage buffers
28  */
29 
30 #include "piglit-util-gl.h"
31 
32 PIGLIT_GL_TEST_CONFIG_BEGIN
33 	config.window_width = 100;
34 	config.window_height = 100;
35 	config.supports_gl_compat_version = 32;
36 	config.supports_gl_core_version = 32;
37 	config.window_visual = PIGLIT_GL_VISUAL_DOUBLE | PIGLIT_GL_VISUAL_RGBA;
38 	config.khr_no_error_support = PIGLIT_NO_ERRORS;
39 
40 PIGLIT_GL_TEST_CONFIG_END
41 
42 #define SSBO_SIZE 4
43 #define NUM_QUERIES 11
44 
45 static const char vs_pass_thru_text[] =
46 	"#version 330\n"
47 	"#extension GL_ARB_shader_storage_buffer_object : require\n"
48 	"\n"
49 	"struct B {mat2 b[3]; float c;};\n"
50 	"layout(row_major, std140, binding=2) buffer ssbo_std140 {\n"
51 	"       vec4 v;\n"
52 	"       B s[];\n"
53 	"} a_std140[2];\n"
54 	"\n"
55 	"in vec4 piglit_vertex;\n"
56 	"\n"
57 	"void main() {\n"
58 	"	gl_Position = piglit_vertex;\n"
59 	"       a_std140[0].s[0].b[0] = mat2(1.0, 2.0, 3.0, 4.0);\n"
60         "}\n";
61 
62 static const char vs_no_ssbo_text[] =
63 	"#version 330\n"
64 	"\n"
65 	"in vec4 piglit_vertex;\n"
66 	"\n"
67 	"void main() {\n"
68 	"	gl_Position = piglit_vertex;\n"
69         "}\n";
70 
71 static const char fs_source[] =
72 	"#version 330\n"
73 	"#extension GL_ARB_shader_storage_buffer_object : require\n"
74 	"\n"
75 	"out vec4 color;\n"
76 	"\n"
77 	"struct B {mat2 b[3]; float c;};\n"
78 	"\n"
79 	"layout(std430, column_major, binding=2) buffer ssbo_std430 {\n"
80 	"       vec4 v;\n"
81 	"       B s[2];\n"
82 	"} a_std430[2];\n"
83 	"\n"
84 	"void main() {\n"
85 	"       a_std430[0].s[0].b[0] = mat2(1.0, 2.0, 3.0, 4.0);\n"
86 	"       color = a_std430[0].v;\n"
87 	"}\n";
88 
89 GLuint prog;
90 
91 void
piglit_init(int argc,char ** argv)92 piglit_init(int argc, char **argv)
93 {
94 	bool pass = true;
95 	GLint index;
96 	const GLenum prop[NUM_QUERIES] = {GL_TOP_LEVEL_ARRAY_SIZE,
97 					  GL_TOP_LEVEL_ARRAY_STRIDE,
98 					  GL_TYPE,
99 					  GL_ARRAY_SIZE,
100 					  GL_BLOCK_INDEX,
101 					  GL_OFFSET,
102 					  GL_ARRAY_STRIDE,
103 					  GL_MATRIX_STRIDE,
104 					  GL_IS_ROW_MAJOR,
105 					  GL_REFERENCED_BY_VERTEX_SHADER,
106 					  GL_REFERENCED_BY_FRAGMENT_SHADER };
107 	int query_std140[NUM_QUERIES] = {0};
108 	int query_std430[NUM_QUERIES] = {0};
109 	int num_vertex_ssbo;
110 	const int expected_std140[NUM_QUERIES] =
111 		{ 0, 112, GL_FLOAT_MAT2, 3, 0, 16, 32, 16, 1, 1, 0 };
112 	int expected_std430[NUM_QUERIES] =
113 		{ 2, 56, GL_FLOAT_MAT2, 3, 2, 16, 16, 8, 0, 0, 1 };
114 	int i;
115 	bool has_vertex_ssbo = true;
116 
117 	piglit_require_extension("GL_ARB_shader_storage_buffer_object");
118 	piglit_require_extension("GL_ARB_program_interface_query");
119 
120 	glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &num_vertex_ssbo);
121 	if (num_vertex_ssbo == 0) {
122 		has_vertex_ssbo = false;
123 		/* modify GL_BLOCK_INDEX return */
124 		expected_std430[4] = 0;
125 	}
126 	prog = piglit_build_simple_program(has_vertex_ssbo ? vs_pass_thru_text : vs_no_ssbo_text, fs_source);
127 
128 	glUseProgram(prog);
129 
130 	if (has_vertex_ssbo) {
131 		/* First ssbo_std140 */
132 		index = glGetProgramResourceIndex(prog,
133 						  GL_BUFFER_VARIABLE,
134 						  "ssbo_std140.s[0].b[0]");
135 		glGetProgramResourceiv(prog, GL_BUFFER_VARIABLE, index,
136 				       NUM_QUERIES, prop, NUM_QUERIES, NULL,
137 				       query_std140);
138 		if (!piglit_check_gl_error(GL_NO_ERROR))
139 			pass = false;
140 	}
141 	/* Now ssbo_std430 */
142 	index = glGetProgramResourceIndex(prog,
143 					  GL_BUFFER_VARIABLE,
144                                           "ssbo_std430.s[0].b[0]");
145         glGetProgramResourceiv(prog, GL_BUFFER_VARIABLE, index,
146                                NUM_QUERIES, prop, NUM_QUERIES, NULL,
147 			       query_std430);
148 
149 	if (!piglit_check_gl_error(GL_NO_ERROR))
150 	   pass = false;
151 
152 	for (i = 0 ; i < NUM_QUERIES; i++) {
153 		const char *prop_name = piglit_get_gl_enum_name(prop[i]);
154 		if (has_vertex_ssbo) {
155 			if (query_std140[i] != expected_std140[i]) {
156 				printf("std140 %s expected = %d. Value = %d.\n",
157 				       prop_name, expected_std140[i],
158 				       query_std140[i]);
159 				pass = false;
160 			}
161 		}
162 		if (query_std430[i] != expected_std430[i]) {
163 			printf("std430 %s expected = %d. Value = %d.\n",
164 			       prop_name, expected_std430[i],
165 			       query_std430[i]);
166 			pass = false;
167 		}
168 	}
169 
170 	piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL);
171 }
172 
piglit_display(void)173 enum piglit_result piglit_display(void)
174 {
175 	/* UNREACHED */
176 	return PIGLIT_FAIL;
177 }
178