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: return "#extension GL_EXT_tessellation_shader : require\n";
65 case GL_GEOMETRY_SHADER: return "#extension GL_EXT_geometry_shader : require\n";
66 default:
67 return "";
68 }
69 }
70
getGLUShaderType(glw::GLenum glShaderType)71 glu::ShaderType getGLUShaderType (glw::GLenum glShaderType)
72 {
73 switch (glShaderType)
74 {
75 case GL_VERTEX_SHADER: return glu::SHADERTYPE_VERTEX;
76 case GL_FRAGMENT_SHADER: return glu::SHADERTYPE_FRAGMENT;
77 case GL_TESS_CONTROL_SHADER: return glu::SHADERTYPE_TESSELLATION_CONTROL;
78 case GL_TESS_EVALUATION_SHADER: return glu::SHADERTYPE_TESSELLATION_EVALUATION;
79 case GL_GEOMETRY_SHADER: return glu::SHADERTYPE_GEOMETRY;
80 case GL_COMPUTE_SHADER: return glu::SHADERTYPE_COMPUTE;
81 default:
82 DE_FATAL("Unknown shader type");
83 return glu::SHADERTYPE_LAST;
84 }
85 }
86
getMaxSSBlockSizeEnum(glw::GLenum glShaderType)87 glw::GLenum getMaxSSBlockSizeEnum (glw::GLenum glShaderType)
88 {
89 switch (glShaderType)
90 {
91 case GL_VERTEX_SHADER: return GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS;
92 case GL_FRAGMENT_SHADER: return GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS;
93 case GL_TESS_CONTROL_SHADER: return GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS;
94 case GL_TESS_EVALUATION_SHADER: return GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS;
95 case GL_GEOMETRY_SHADER: return GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS;
96 case GL_COMPUTE_SHADER: return GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS;
97 default:
98 DE_FATAL("Unknown shader type");
99 return -1;
100 }
101 }
102
getMaxSSBlockSize(NegativeTestContext & ctx,glw::GLenum glShaderType)103 int getMaxSSBlockSize (NegativeTestContext& ctx, glw::GLenum glShaderType)
104 {
105 int maxSSBlocks = 0;
106 ctx.glGetIntegerv(getMaxSSBlockSizeEnum(glShaderType), &maxSSBlocks);
107
108 return maxSSBlocks;
109 }
110
genBlockSource(NegativeTestContext & ctx,deInt64 numSSBlocks,glw::GLenum shaderType)111 std::string genBlockSource (NegativeTestContext& ctx, deInt64 numSSBlocks, glw::GLenum shaderType)
112 {
113 const bool isES32 = contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
114 const glu::GLSLVersion version = isES32 ? glu::GLSL_VERSION_320_ES : glu::GLSL_VERSION_310_ES;
115 std::ostringstream source;
116
117 source << glu::getGLSLVersionDeclaration(version) << "\n"
118 << ((isES32) ? "" : getShaderExtensionDeclaration(shaderType));
119
120 switch (shaderType)
121 {
122 case GL_VERTEX_SHADER:
123 case GL_FRAGMENT_SHADER:
124 break;
125
126 case GL_COMPUTE_SHADER:
127 source << "layout (local_size_x = 1) in;\n";
128 break;
129
130 case GL_GEOMETRY_SHADER:
131 source << "layout(points) in;\n"
132 << "layout(line_strip, max_vertices = 3) out;\n";
133 break;
134
135 case GL_TESS_CONTROL_SHADER:
136 source << "layout(vertices = 10) out;\n";
137 break;
138
139 case GL_TESS_EVALUATION_SHADER:
140 source << "layout(triangles) in;\n";
141 break;
142
143 default:
144 DE_FATAL("Unknown shader type");
145 break;
146 }
147
148 source << "\n"
149 << "layout(std430, binding = 0) buffer Block {\n"
150 << " int value;\n"
151 << "} sb_in[" << numSSBlocks << "];\n"
152 << "void main(void) { sb_in[0].value = 1; }\n";
153
154 return source.str();
155 }
156
genCommonSource(NegativeTestContext & ctx,glw::GLenum shaderType)157 std::string genCommonSource (NegativeTestContext& ctx, glw::GLenum shaderType)
158 {
159 const bool isES32 = contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
160 const glu::GLSLVersion version = isES32 ? glu::GLSL_VERSION_320_ES : glu::GLSL_VERSION_310_ES;
161 std::ostringstream source;
162
163 source << glu::getGLSLVersionDeclaration(version) << "\n"
164 << ((isES32) ? "" : getShaderExtensionDeclaration(shaderType));
165
166 switch (shaderType)
167 {
168 case GL_TESS_CONTROL_SHADER:
169 source << "layout(vertices = 3) out;\n"
170 << "void main() {}\n";
171 break;
172
173 case GL_TESS_EVALUATION_SHADER:
174 source << "layout(triangles, equal_spacing, cw) in;\n"
175 << "void main() {}\n";
176 break;
177
178 default:
179 source << "void main() {}\n";
180 break;
181 }
182
183 return source.str();
184 }
185
genMaxSSBlocksSource(NegativeTestContext & ctx,glw::GLenum glShaderType,glu::ProgramSources & sources)186 int genMaxSSBlocksSource (NegativeTestContext& ctx, glw::GLenum glShaderType, glu::ProgramSources& sources)
187 {
188 int maxSSBlocks = getMaxSSBlockSize(ctx, glShaderType);
189 const std::string shaderSrc = genBlockSource(ctx, (maxSSBlocks), glShaderType);
190
191 sources.sources[getGLUShaderType(glShaderType)].push_back(shaderSrc);
192
193 return maxSSBlocks;
194 }
195
block_number_limits(NegativeTestContext & ctx)196 void block_number_limits (NegativeTestContext& ctx)
197 {
198 const glw::GLenum glShaderTypes[] =
199 {
200 GL_VERTEX_SHADER,
201 GL_FRAGMENT_SHADER,
202 GL_TESS_CONTROL_SHADER,
203 GL_TESS_EVALUATION_SHADER,
204 GL_GEOMETRY_SHADER,
205 GL_COMPUTE_SHADER,
206 };
207
208 const std::string vertSource = genCommonSource(ctx, GL_VERTEX_SHADER);
209 const std::string fragSource = genCommonSource(ctx, GL_FRAGMENT_SHADER);
210 const std::string tessControlSource = genCommonSource(ctx, GL_TESS_CONTROL_SHADER);
211 const std::string tessEvalSource = genCommonSource(ctx, GL_TESS_EVALUATION_SHADER);
212
213 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(glShaderTypes); ndx++)
214 {
215 ctx.beginSection("maxShaderStorageBlocks: Exceed limits");
216
217 if (!ctx.isShaderSupported(static_cast<glu::ShaderType>(getGLUShaderType(glShaderTypes[ndx]))))
218 {
219 ctx.endSection();
220 continue;
221 }
222
223 int maxSSBlocks = getMaxSSBlockSize(ctx, glShaderTypes[ndx]);
224 std::string source = genBlockSource(ctx, maxSSBlocks+1, glShaderTypes[ndx]);
225
226 glu::ProgramSources sources;
227
228 if (maxSSBlocks == 0)
229 {
230 ctx.endSection();
231 continue;
232 }
233
234 switch (glShaderTypes[ndx])
235 {
236 case GL_VERTEX_SHADER:
237 sources << glu::VertexSource(source)
238 << glu::FragmentSource(fragSource);
239 break;
240
241 case GL_FRAGMENT_SHADER:
242 sources << glu::VertexSource(vertSource)
243 << glu::FragmentSource(source);
244 break;
245
246 case GL_TESS_CONTROL_SHADER:
247 sources << glu::VertexSource(vertSource)
248 << glu::FragmentSource(fragSource)
249 << glu::TessellationControlSource(source)
250 << glu::TessellationEvaluationSource(tessEvalSource);
251 break;
252
253 case GL_TESS_EVALUATION_SHADER:
254 sources << glu::VertexSource(vertSource)
255 << glu::FragmentSource(fragSource)
256 << glu::TessellationControlSource(tessControlSource)
257 << glu::TessellationEvaluationSource(source);
258 break;
259
260 case GL_GEOMETRY_SHADER:
261 sources << glu::VertexSource(vertSource)
262 << glu::FragmentSource(fragSource)
263 << glu::GeometrySource(source);
264 break;
265
266 case GL_COMPUTE_SHADER:
267 sources << glu::ComputeSource(source);
268 break;
269
270 default:
271 DE_FATAL("Unknown shader type");
272 break;
273 }
274
275 verifyProgram(ctx, sources);
276 ctx.endSection();
277 }
278 }
279
max_combined_block_number_limit(NegativeTestContext & ctx)280 void max_combined_block_number_limit (NegativeTestContext& ctx)
281 {
282 ctx.beginSection("maxCombinedShaderStorageBlocks: Exceed limits");
283
284 glu::ProgramSources sources;
285
286 int combinedSSBlocks = 0;
287 int maxCombinedSSBlocks = 0;
288
289 combinedSSBlocks += genMaxSSBlocksSource(ctx, GL_VERTEX_SHADER, sources);
290 combinedSSBlocks += genMaxSSBlocksSource(ctx, GL_FRAGMENT_SHADER, sources);
291
292 if ((ctx.isShaderSupported(glu::SHADERTYPE_TESSELLATION_CONTROL)) && (ctx.isShaderSupported(glu::SHADERTYPE_TESSELLATION_EVALUATION)))
293 {
294 combinedSSBlocks += genMaxSSBlocksSource(ctx, GL_TESS_CONTROL_SHADER, sources);
295 combinedSSBlocks += genMaxSSBlocksSource(ctx, GL_TESS_EVALUATION_SHADER, sources);
296 }
297
298 if (ctx.isShaderSupported(glu::SHADERTYPE_GEOMETRY))
299 combinedSSBlocks += genMaxSSBlocksSource(ctx, GL_GEOMETRY_SHADER, sources);
300
301 ctx.glGetIntegerv(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &maxCombinedSSBlocks);
302
303 ctx.getLog() << tcu::TestLog::Message << "GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS: " << maxCombinedSSBlocks << tcu::TestLog::EndMessage;
304 ctx.getLog() << tcu::TestLog::Message << "Combined shader storage blocks: " << combinedSSBlocks << tcu::TestLog::EndMessage;
305
306 if (combinedSSBlocks > maxCombinedSSBlocks)
307 verifyProgram(ctx, sources);
308 else
309 ctx.getLog() << tcu::TestLog::Message << "Test skipped: Combined shader storage blocks < GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS: " << tcu::TestLog::EndMessage;
310
311 ctx.endSection();
312 }
313
314 } // anonymous
315
getNegativeShaderStorageTestFunctions()316 std::vector<FunctionContainer> getNegativeShaderStorageTestFunctions ()
317 {
318 const FunctionContainer funcs[] =
319 {
320 { block_number_limits, "block_number_limits", "Invalid shader linkage" },
321 { max_combined_block_number_limit, "max_combined_block_number_limit", "Invalid shader linkage" },
322 };
323
324 return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
325 }
326
327 } // NegativeTestShared
328 } // Functional
329 } // gles31
330 } // deqp
331