xref: /aosp_15_r20/external/deqp/modules/gles31/functional/es31fNegativeShaderStorageTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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