1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.1 Module
3 * -------------------------------------------------
4 *
5 * Copyright 2016 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Negative Shader Storage Tests
22 *//*--------------------------------------------------------------------*/
23
24 #include "es31fNegativeShaderStorageTests.hpp"
25
26 #include "gluShaderProgram.hpp"
27 #include "glwDefs.hpp"
28 #include "glwEnums.hpp"
29
30 namespace deqp
31 {
32 namespace gles31
33 {
34 namespace Functional
35 {
36 namespace NegativeTestShared
37 {
38 namespace
39 {
40
verifyProgram(NegativeTestContext & ctx,glu::ProgramSources sources)41 void verifyProgram(NegativeTestContext &ctx, glu::ProgramSources sources)
42 {
43 tcu::TestLog &log = ctx.getLog();
44 const glu::ShaderProgram program(ctx.getRenderContext(), sources);
45 bool testFailed = false;
46
47 log << program;
48
49 testFailed = program.getProgramInfo().linkOk;
50
51 if (testFailed)
52 {
53 const char *const message("Program was not expected to link.");
54 log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
55 ctx.fail(message);
56 }
57 }
58
getShaderExtensionDeclaration(glw::GLenum glShaderType)59 const char *getShaderExtensionDeclaration(glw::GLenum glShaderType)
60 {
61 switch (glShaderType)
62 {
63 case GL_TESS_CONTROL_SHADER:
64 case GL_TESS_EVALUATION_SHADER:
65 return "#extension GL_EXT_tessellation_shader : require\n";
66 case GL_GEOMETRY_SHADER:
67 return "#extension GL_EXT_geometry_shader : require\n";
68 default:
69 return "";
70 }
71 }
72
getGLUShaderType(glw::GLenum glShaderType)73 glu::ShaderType getGLUShaderType(glw::GLenum glShaderType)
74 {
75 switch (glShaderType)
76 {
77 case GL_VERTEX_SHADER:
78 return glu::SHADERTYPE_VERTEX;
79 case GL_FRAGMENT_SHADER:
80 return glu::SHADERTYPE_FRAGMENT;
81 case GL_TESS_CONTROL_SHADER:
82 return glu::SHADERTYPE_TESSELLATION_CONTROL;
83 case GL_TESS_EVALUATION_SHADER:
84 return glu::SHADERTYPE_TESSELLATION_EVALUATION;
85 case GL_GEOMETRY_SHADER:
86 return glu::SHADERTYPE_GEOMETRY;
87 case GL_COMPUTE_SHADER:
88 return glu::SHADERTYPE_COMPUTE;
89 default:
90 DE_FATAL("Unknown shader type");
91 return glu::SHADERTYPE_LAST;
92 }
93 }
94
getMaxSSBlockSizeEnum(glw::GLenum glShaderType)95 glw::GLenum getMaxSSBlockSizeEnum(glw::GLenum glShaderType)
96 {
97 switch (glShaderType)
98 {
99 case GL_VERTEX_SHADER:
100 return GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS;
101 case GL_FRAGMENT_SHADER:
102 return GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS;
103 case GL_TESS_CONTROL_SHADER:
104 return GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS;
105 case GL_TESS_EVALUATION_SHADER:
106 return GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS;
107 case GL_GEOMETRY_SHADER:
108 return GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS;
109 case GL_COMPUTE_SHADER:
110 return GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS;
111 default:
112 DE_FATAL("Unknown shader type");
113 return -1;
114 }
115 }
116
getMaxSSBlockSize(NegativeTestContext & ctx,glw::GLenum glShaderType)117 int getMaxSSBlockSize(NegativeTestContext &ctx, glw::GLenum glShaderType)
118 {
119 int maxSSBlocks = 0;
120 ctx.glGetIntegerv(getMaxSSBlockSizeEnum(glShaderType), &maxSSBlocks);
121
122 return maxSSBlocks;
123 }
124
genBlockSource(NegativeTestContext & ctx,int64_t numSSBlocks,glw::GLenum shaderType)125 std::string genBlockSource(NegativeTestContext &ctx, int64_t numSSBlocks, glw::GLenum shaderType)
126 {
127 const bool isES32 = contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
128 const glu::GLSLVersion version = isES32 ? glu::GLSL_VERSION_320_ES : glu::GLSL_VERSION_310_ES;
129 std::ostringstream source;
130
131 source << glu::getGLSLVersionDeclaration(version) << "\n"
132 << ((isES32) ? "" : getShaderExtensionDeclaration(shaderType));
133
134 switch (shaderType)
135 {
136 case GL_VERTEX_SHADER:
137 case GL_FRAGMENT_SHADER:
138 break;
139
140 case GL_COMPUTE_SHADER:
141 source << "layout (local_size_x = 1) in;\n";
142 break;
143
144 case GL_GEOMETRY_SHADER:
145 source << "layout(points) in;\n"
146 << "layout(line_strip, max_vertices = 3) out;\n";
147 break;
148
149 case GL_TESS_CONTROL_SHADER:
150 source << "layout(vertices = 10) out;\n";
151 break;
152
153 case GL_TESS_EVALUATION_SHADER:
154 source << "layout(triangles) in;\n";
155 break;
156
157 default:
158 DE_FATAL("Unknown shader type");
159 break;
160 }
161
162 source << "\n"
163 << "layout(std430, binding = 0) buffer Block {\n"
164 << " int value;\n"
165 << "} sb_in[" << numSSBlocks << "];\n"
166 << "void main(void) { sb_in[0].value = 1; }\n";
167
168 return source.str();
169 }
170
genCommonSource(NegativeTestContext & ctx,glw::GLenum shaderType)171 std::string genCommonSource(NegativeTestContext &ctx, glw::GLenum shaderType)
172 {
173 const bool isES32 = contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
174 const glu::GLSLVersion version = isES32 ? glu::GLSL_VERSION_320_ES : glu::GLSL_VERSION_310_ES;
175 std::ostringstream source;
176
177 source << glu::getGLSLVersionDeclaration(version) << "\n"
178 << ((isES32) ? "" : getShaderExtensionDeclaration(shaderType));
179
180 switch (shaderType)
181 {
182 case GL_TESS_CONTROL_SHADER:
183 source << "layout(vertices = 3) out;\n"
184 << "void main() {}\n";
185 break;
186
187 case GL_TESS_EVALUATION_SHADER:
188 source << "layout(triangles, equal_spacing, cw) in;\n"
189 << "void main() {}\n";
190 break;
191
192 default:
193 source << "void main() {}\n";
194 break;
195 }
196
197 return source.str();
198 }
199
genMaxSSBlocksSource(NegativeTestContext & ctx,glw::GLenum glShaderType,glu::ProgramSources & sources)200 int genMaxSSBlocksSource(NegativeTestContext &ctx, glw::GLenum glShaderType, glu::ProgramSources &sources)
201 {
202 int maxSSBlocks = getMaxSSBlockSize(ctx, glShaderType);
203 const std::string shaderSrc = genBlockSource(ctx, (maxSSBlocks), glShaderType);
204
205 sources.sources[getGLUShaderType(glShaderType)].push_back(shaderSrc);
206
207 return maxSSBlocks;
208 }
209
block_number_limits(NegativeTestContext & ctx)210 void block_number_limits(NegativeTestContext &ctx)
211 {
212 const glw::GLenum glShaderTypes[] = {
213 GL_VERTEX_SHADER, GL_FRAGMENT_SHADER, GL_TESS_CONTROL_SHADER,
214 GL_TESS_EVALUATION_SHADER, GL_GEOMETRY_SHADER, GL_COMPUTE_SHADER,
215 };
216
217 const std::string vertSource = genCommonSource(ctx, GL_VERTEX_SHADER);
218 const std::string fragSource = genCommonSource(ctx, GL_FRAGMENT_SHADER);
219 const std::string tessControlSource = genCommonSource(ctx, GL_TESS_CONTROL_SHADER);
220 const std::string tessEvalSource = genCommonSource(ctx, GL_TESS_EVALUATION_SHADER);
221
222 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(glShaderTypes); ndx++)
223 {
224 ctx.beginSection("maxShaderStorageBlocks: Exceed limits");
225
226 if (!ctx.isShaderSupported(static_cast<glu::ShaderType>(getGLUShaderType(glShaderTypes[ndx]))))
227 {
228 ctx.endSection();
229 continue;
230 }
231
232 int maxSSBlocks = getMaxSSBlockSize(ctx, glShaderTypes[ndx]);
233 std::string source = genBlockSource(ctx, maxSSBlocks + 1, glShaderTypes[ndx]);
234
235 glu::ProgramSources sources;
236
237 if (maxSSBlocks == 0)
238 {
239 ctx.endSection();
240 continue;
241 }
242
243 switch (glShaderTypes[ndx])
244 {
245 case GL_VERTEX_SHADER:
246 sources << glu::VertexSource(source) << glu::FragmentSource(fragSource);
247 break;
248
249 case GL_FRAGMENT_SHADER:
250 sources << glu::VertexSource(vertSource) << glu::FragmentSource(source);
251 break;
252
253 case GL_TESS_CONTROL_SHADER:
254 sources << glu::VertexSource(vertSource) << glu::FragmentSource(fragSource)
255 << glu::TessellationControlSource(source) << glu::TessellationEvaluationSource(tessEvalSource);
256 break;
257
258 case GL_TESS_EVALUATION_SHADER:
259 sources << glu::VertexSource(vertSource) << glu::FragmentSource(fragSource)
260 << glu::TessellationControlSource(tessControlSource) << glu::TessellationEvaluationSource(source);
261 break;
262
263 case GL_GEOMETRY_SHADER:
264 sources << glu::VertexSource(vertSource) << glu::FragmentSource(fragSource) << glu::GeometrySource(source);
265 break;
266
267 case GL_COMPUTE_SHADER:
268 sources << glu::ComputeSource(source);
269 break;
270
271 default:
272 DE_FATAL("Unknown shader type");
273 break;
274 }
275
276 verifyProgram(ctx, sources);
277 ctx.endSection();
278 }
279 }
280
max_combined_block_number_limit(NegativeTestContext & ctx)281 void max_combined_block_number_limit(NegativeTestContext &ctx)
282 {
283 ctx.beginSection("maxCombinedShaderStorageBlocks: Exceed limits");
284
285 glu::ProgramSources sources;
286
287 int combinedSSBlocks = 0;
288 int maxCombinedSSBlocks = 0;
289
290 combinedSSBlocks += genMaxSSBlocksSource(ctx, GL_VERTEX_SHADER, sources);
291 combinedSSBlocks += genMaxSSBlocksSource(ctx, GL_FRAGMENT_SHADER, sources);
292
293 if ((ctx.isShaderSupported(glu::SHADERTYPE_TESSELLATION_CONTROL)) &&
294 (ctx.isShaderSupported(glu::SHADERTYPE_TESSELLATION_EVALUATION)))
295 {
296 combinedSSBlocks += genMaxSSBlocksSource(ctx, GL_TESS_CONTROL_SHADER, sources);
297 combinedSSBlocks += genMaxSSBlocksSource(ctx, GL_TESS_EVALUATION_SHADER, sources);
298 }
299
300 if (ctx.isShaderSupported(glu::SHADERTYPE_GEOMETRY))
301 combinedSSBlocks += genMaxSSBlocksSource(ctx, GL_GEOMETRY_SHADER, sources);
302
303 ctx.glGetIntegerv(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &maxCombinedSSBlocks);
304
305 ctx.getLog() << tcu::TestLog::Message << "GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS: " << maxCombinedSSBlocks
306 << tcu::TestLog::EndMessage;
307 ctx.getLog() << tcu::TestLog::Message << "Combined shader storage blocks: " << combinedSSBlocks
308 << tcu::TestLog::EndMessage;
309
310 if (combinedSSBlocks > maxCombinedSSBlocks)
311 verifyProgram(ctx, sources);
312 else
313 ctx.getLog() << tcu::TestLog::Message
314 << "Test skipped: Combined shader storage blocks < GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS: "
315 << tcu::TestLog::EndMessage;
316
317 ctx.endSection();
318 }
319
320 } // namespace
321
getNegativeShaderStorageTestFunctions()322 std::vector<FunctionContainer> getNegativeShaderStorageTestFunctions()
323 {
324 const FunctionContainer funcs[] = {
325 {block_number_limits, "block_number_limits", "Invalid shader linkage"},
326 {max_combined_block_number_limit, "max_combined_block_number_limit", "Invalid shader linkage"},
327 };
328
329 return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
330 }
331
332 } // namespace NegativeTestShared
333 } // namespace Functional
334 } // namespace gles31
335 } // namespace deqp
336