2 * Copyright © 2016 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
25 * \file compare-with-shader-subroutine
27 * Tests that the values returned by equivalent queries from
28 * ARB_shader_subroutine (glGetProgramStageiv) and
29 * ARB_program_interface_query (glGetProgramInterfaveiv) return the
32 * From the GL_ARB_program_interface_query spec:
35 * void GetProgramInterfaceiv(uint program, enum programInterface,
36 * enum pname, int *params);
38 * queries a property of the interface <programInterface> in program
39 * <program>, returning its value in <params>. The property to return is
40 * specified by <pname>.
42 * If <pname> is ACTIVE_RESOURCES, the value returned is the number of
43 * resources in the active resource list for <programInterface>. If the
44 * list of active resources for <programInterface> is empty, zero is
47 * "The supported values for <programInterface> are as follows:
49 * * VERTEX_SUBROUTINE_UNIFORM, TESS_CONTROL_SUBROUTINE_UNIFORM,
50 * TESS_EVALUATION_SUBROUTINE_UNIFORM, GEOMETRY_SUBROUTINE_UNIFORM,
51 * FRAGMENT_SUBROUTINE_UNIFORM, and COMPUTE_SUBROUTINE_UNIFORM correspond
52 * to the set of active subroutine uniform variables used by the vertex,
53 * tessellation control, tessellation evaluation, geometry, fragment, and
54 * compute shader stages of <program>, respectively (section 2.14.8)."
56 * From the GL_ARB_shader_subroutine spec:
60 * void GetProgramStageiv(uint program, enum shadertype,
61 * enum pname, int *values);
63 * returns properties of the program object <program> specific to the
64 * programmable stage corresponding to <shadertype> in <values>. The
65 * parameter value to return is specified by <pname>. If <pname> is
66 * ACTIVE_SUBROUTINE_UNIFORMS, the number of active subroutine variables in
67 * the stage is returned."
70 #include "piglit-util-gl.h"
73 PIGLIT_GL_TEST_CONFIG_BEGIN
75 config
.supports_gl_core_version
= 32;
76 config
.khr_no_error_support
= PIGLIT_NO_ERRORS
;
78 PIGLIT_GL_TEST_CONFIG_END
80 /* The shaders try to be as simple as possible for each stage, using
83 static const char *vs_text
= {
85 "#extension GL_ARB_shader_subroutine : require\n"
88 "out vec4 vs_output;\n"
90 "subroutine vec4 vs_subroutine();\n"
91 "subroutine uniform vs_subroutine vs[2];\n"
92 "subroutine(vs_subroutine) vec4 vs1() {\n"
93 " return vec4(1, 0, 0, 0);\n"
95 "subroutine(vs_subroutine) vec4 vs2() {\n"
96 " return vec4(1, 0, 0, 0);\n"
99 " gl_Position = vs_input;\n"
100 " vs_output = vs[0]() + vs[1]();\n"
104 static const char *tcs_text
= {
106 "#extension GL_ARB_shader_subroutine : require\n"
107 "#extension GL_ARB_tessellation_shader: require\n"
109 "layout(vertices = 3) out;\n"
111 "subroutine vec4 tcs_subroutine();\n"
112 "subroutine uniform tcs_subroutine tcs[2];\n"
113 "subroutine(tcs_subroutine) vec4 tcs1() {\n"
114 " return vec4(1, 0, 0, 0);\n"
116 "subroutine(tcs_subroutine) vec4 tcs2() {\n"
117 " return vec4(1, 0, 0, 0);\n"
120 " gl_out[gl_InvocationID].gl_Position = tcs[0]() + tcs[1]();\n"
121 " gl_TessLevelInner[0] = 1.0;\n"
122 " gl_TessLevelInner[1] = 1.0;\n"
123 " gl_TessLevelOuter[0] = 1.0;\n"
124 " gl_TessLevelOuter[1] = 1.0;\n"
125 " gl_TessLevelOuter[2] = 1.0;\n"
129 static const char *tes_text
= {
131 "#extension GL_ARB_shader_subroutine : require\n"
132 "#extension GL_ARB_tessellation_shader: require\n"
134 "layout(triangles, equal_spacing) in;\n"
136 "subroutine vec4 tes_subroutine();\n"
137 "subroutine uniform tes_subroutine tes[2];\n"
138 "subroutine(tes_subroutine) vec4 tes1() {\n"
139 " return vec4(1, 0, 0, 0);\n"
141 "subroutine(tes_subroutine) vec4 tes2() {\n"
142 " return vec4(1, 0, 0, 0);\n"
145 " gl_Position = tes[0]() + tes[1]();\n"
149 static const char *gs_text
= {
151 "#extension GL_ARB_shader_subroutine : require\n"
152 "layout(triangles) in;\n"
153 "layout(triangle_strip, max_vertices = 4) out;\n"
155 "subroutine vec4 gs_subroutine();\n"
156 "subroutine uniform gs_subroutine gs[4];\n"
157 "subroutine(gs_subroutine) vec4 gs1() {\n"
158 " return vec4(1, 0, 0, 0);\n"
160 "subroutine(gs_subroutine) vec4 gs2() {\n"
161 " return vec4(1, 0, 0, 0);\n"
164 " gl_Position = gs[0]();\n"
166 " gl_Position = gs[1]();\n"
168 " gl_Position = gs[2]();\n"
170 " gl_Position = gs[3]();\n"
176 static const char *fs_text
= {
178 "#extension GL_ARB_shader_subroutine : require\n"
180 "out vec4 fs_output;\n"
182 "subroutine vec4 fs_subroutine();\n"
183 "subroutine uniform fs_subroutine fs[3];\n"
184 "subroutine(fs_subroutine) vec4 fs1() {\n"
185 " return vec4(1, 0, 0, 0);\n"
187 "subroutine(fs_subroutine) vec4 fs2() {\n"
188 " return vec4(1, 0, 0, 0);\n"
191 " fs_output = fs[0]() + fs[1]() + fs[2]();\n"
195 /* We need SSBO in order to be able to use a buffer. And we need a
196 * buffer so the subroutine uniforms get active, in order to get a num
197 * of active uniforms different to 0.
199 static const char *cs_text
= {
201 "#extension GL_ARB_shader_subroutine : require\n"
202 "#extension GL_ARB_compute_shader : require\n"
203 "#extension GL_ARB_shader_storage_buffer_object : require\n"
205 "layout(local_size_x = 1) in;\n"
207 "buffer out_buffer {\n"
211 "subroutine vec4 cs_subroutine();\n"
212 "subroutine uniform cs_subroutine cs[4];\n"
213 "subroutine(cs_subroutine) vec4 cs1() {\n"
214 " return vec4(1, 0, 0, 0);\n"
216 "subroutine(cs_subroutine) vec4 cs2() {\n"
217 " return vec4(1, 0, 0, 0);\n"
220 " g_out.data = cs[0]() + cs[1]();\n"
224 static const GLenum subtests
[] = {
225 GL_VERTEX_SUBROUTINE_UNIFORM
,
226 GL_TESS_CONTROL_SUBROUTINE_UNIFORM
,
227 GL_TESS_EVALUATION_SUBROUTINE_UNIFORM
,
228 GL_GEOMETRY_SUBROUTINE_UNIFORM
,
229 GL_FRAGMENT_SUBROUTINE_UNIFORM
,
230 GL_COMPUTE_SUBROUTINE_UNIFORM
,
234 get_shadertype_from_program_interface(const GLenum programInterface
)
236 switch(programInterface
) {
237 case GL_VERTEX_SUBROUTINE_UNIFORM
:
238 return GL_VERTEX_SHADER
;
239 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM
:
240 return GL_TESS_CONTROL_SHADER
;
241 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM
:
242 return GL_TESS_EVALUATION_SHADER
;
243 case GL_GEOMETRY_SUBROUTINE_UNIFORM
:
244 return GL_GEOMETRY_SHADER
;
245 case GL_FRAGMENT_SUBROUTINE_UNIFORM
:
246 return GL_FRAGMENT_SHADER
;
247 case GL_COMPUTE_SUBROUTINE_UNIFORM
:
248 return GL_COMPUTE_SHADER
;
250 assert(!"unexpected programInterface value");
251 return GL_INVALID_ENUM
;
256 create_program(const GLenum programInterface
)
260 switch(programInterface
) {
261 case GL_VERTEX_SUBROUTINE_UNIFORM
:
262 case GL_GEOMETRY_SUBROUTINE_UNIFORM
:
263 case GL_FRAGMENT_SUBROUTINE_UNIFORM
:
264 program
= piglit_build_simple_program_unlinked_multiple_shaders(
265 GL_VERTEX_SHADER
, vs_text
,
266 GL_GEOMETRY_SHADER
, gs_text
,
267 GL_FRAGMENT_SHADER
, fs_text
, 0);
270 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM
:
271 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM
:
272 program
= piglit_build_simple_program_unlinked_multiple_shaders(
273 GL_VERTEX_SHADER
, vs_text
,
274 GL_TESS_CONTROL_SHADER
, tcs_text
,
275 GL_TESS_EVALUATION_SHADER
, tes_text
, 0);
278 case GL_COMPUTE_SUBROUTINE_UNIFORM
:
279 program
= piglit_build_simple_program_unlinked_multiple_shaders(
280 GL_COMPUTE_SHADER
, cs_text
, 0);
283 assert(!"unexpected programInterface value");
286 piglit_check_gl_error(GL_NO_ERROR
);
292 skip_subtest(const GLenum programInterface
)
294 switch(programInterface
) {
295 case GL_COMPUTE_SUBROUTINE_UNIFORM
:
296 return !piglit_is_extension_supported("GL_ARB_compute_shader") ||
297 !piglit_is_extension_supported("GL_ARB_shader_storage_buffer_object");
299 case GL_TESS_CONTROL_SUBROUTINE_UNIFORM
:
300 case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM
:
301 return !piglit_is_extension_supported("GL_ARB_tessellation_shader");
309 run_subtest(const GLenum programInterface
,
316 const char *linked_string
= link
? "linked" : "not linked";
318 if (skip_subtest(programInterface
))
321 program
= create_program(programInterface
);
323 glLinkProgram(program
);
324 if (!piglit_link_check_status(program
))
325 piglit_report_result(PIGLIT_FAIL
);
328 shader_type
= get_shadertype_from_program_interface(programInterface
);
330 glGetProgramStageiv(program
, shader_type
, GL_ACTIVE_SUBROUTINE_UNIFORMS
, &value
);
331 glGetProgramInterfaceiv(program
, programInterface
, GL_ACTIVE_RESOURCES
, &value2
);
333 if (value
== value2
) {
334 piglit_report_subtest_result(PIGLIT_PASS
, "%s (%s)",
335 piglit_get_gl_enum_name(programInterface
),
339 piglit_report_subtest_result(PIGLIT_FAIL
, "%s (%s): GetProgramStage returns %i, "
340 "GetProgramInterfaceiv returns %i",
341 piglit_get_gl_enum_name(programInterface
),
342 linked_string
, value
, value2
);
345 return value
== value2
;
349 piglit_init(int argc
, char **argv
)
351 piglit_require_extension("GL_ARB_program_interface_query");
352 piglit_require_extension("GL_ARB_shader_subroutine");
361 for (i
= 0; i
< ARRAY_SIZE(subtests
); i
++) {
362 pass
= run_subtest(subtests
[i
], false) && pass
;
365 for (i
= 0; i
< ARRAY_SIZE(subtests
); i
++) {
366 pass
= run_subtest(subtests
[i
], true) && pass
;
369 return pass
? PIGLIT_PASS
: PIGLIT_FAIL
;