xref: /aosp_15_r20/external/deqp/modules/gles31/functional/es31fNegativeSampleVariablesTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.1 Module
3  * -------------------------------------------------
4  *
5  * Copyright 2017 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 Sample Variables Tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es31fNegativeSampleVariablesTests.hpp"
25 #include "gluShaderProgram.hpp"
26 
27 namespace deqp
28 {
29 namespace gles31
30 {
31 namespace Functional
32 {
33 namespace NegativeTestShared
34 {
35 namespace
36 {
37 
38 enum ExpectResult
39 {
40     EXPECT_RESULT_PASS = 0,
41     EXPECT_RESULT_FAIL,
42     EXPECT_RESULT_LAST
43 };
44 
verifyShader(NegativeTestContext & ctx,glu::ShaderType shaderType,std::string shaderSource,ExpectResult expect)45 void verifyShader(NegativeTestContext &ctx, glu::ShaderType shaderType, std::string shaderSource, ExpectResult expect)
46 {
47     DE_ASSERT(expect >= EXPECT_RESULT_PASS && expect < EXPECT_RESULT_LAST);
48 
49     tcu::TestLog &log        = ctx.getLog();
50     bool testFailed          = false;
51     const char *const source = shaderSource.c_str();
52     const int length         = (int)shaderSource.size();
53     glu::Shader shader(ctx.getRenderContext(), shaderType);
54     std::string message;
55 
56     shader.setSources(1, &source, &length);
57     shader.compile();
58 
59     log << shader;
60 
61     if (expect == EXPECT_RESULT_PASS)
62     {
63         testFailed = !shader.getCompileStatus();
64         message    = "Shader did not compile.";
65     }
66     else
67     {
68         testFailed = shader.getCompileStatus();
69         message    = "Shader was not expected to compile.";
70     }
71 
72     if (testFailed)
73     {
74         log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
75         ctx.fail(message);
76     }
77 }
78 
getVersionAndExtension(NegativeTestContext & ctx)79 std::string getVersionAndExtension(NegativeTestContext &ctx)
80 {
81     const bool isES32              = contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
82     const glu::GLSLVersion version = isES32 ? glu::GLSL_VERSION_320_ES : glu::GLSL_VERSION_310_ES;
83 
84     std::string versionAndExtension = glu::getGLSLVersionDeclaration(version);
85     versionAndExtension += " \n";
86 
87     if (!isES32)
88         versionAndExtension += "#extension GL_OES_sample_variables : require \n";
89 
90     return versionAndExtension;
91 }
92 
checkSupported(NegativeTestContext & ctx)93 void checkSupported(NegativeTestContext &ctx)
94 {
95     const bool isES32orGL45 = contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)) ||
96                               contextSupports(ctx.getRenderContext().getType(), glu::ApiType::core(4, 5));
97 
98     if (!isES32orGL45 && !ctx.isExtensionSupported("GL_OES_sample_variables"))
99         TCU_THROW(NotSupportedError, "GL_OES_sample_variables is not supported.");
100 }
101 
write_to_read_only_types(NegativeTestContext & ctx)102 void write_to_read_only_types(NegativeTestContext &ctx)
103 {
104     checkSupported(ctx);
105 
106     std::ostringstream shader;
107 
108     struct testConfig
109     {
110         std::string builtInType;
111         std::string varyingCheck;
112     } testConfigs[] = {{"gl_SampleID", "    lowp int writeValue = 1; \n    gl_SampleID = writeValue; \n"},
113                        {"gl_SamplePosition",
114                         "    mediump vec2 writeValue = vec2(1.0f, 1.0f); \n    gl_SamplePosition = writeValue; \n"},
115                        {"gl_SampleMaskIn", "    lowp int writeValue = 1; \n    gl_SampleMaskIn[0] = writeValue; \n"}};
116 
117     for (int idx = 0; idx < DE_LENGTH_OF_ARRAY(testConfigs); idx++)
118     {
119         shader.str("");
120         shader << getVersionAndExtension(ctx) << "layout (location = 0) out mediump vec4 fs_color; \n"
121                << "void main() \n"
122                << "{ \n"
123                << testConfigs[idx].varyingCheck << "    fs_color = vec4(1.0f, 0.0f, 0.0f, 1.0f); \n"
124                << "} \n";
125 
126         ctx.beginSection("OES_sample_variables: trying to write to built-in read-only variable" +
127                          testConfigs[idx].builtInType);
128         verifyShader(ctx, glu::SHADERTYPE_FRAGMENT, shader.str(), EXPECT_RESULT_FAIL);
129         ctx.endSection();
130     }
131 }
132 
access_built_in_types_inside_other_shaders(NegativeTestContext & ctx)133 void access_built_in_types_inside_other_shaders(NegativeTestContext &ctx)
134 {
135     checkSupported(ctx);
136 
137     if (glu::isContextTypeES(ctx.getRenderContext().getType()))
138     {
139         if ((!ctx.isExtensionSupported("GL_EXT_tessellation_shader") &&
140              !ctx.isExtensionSupported("GL_OES_tessellation_shader")) ||
141             (!ctx.isExtensionSupported("GL_EXT_geometry_shader") &&
142              !ctx.isExtensionSupported("GL_OES_geometry_shader")))
143             TCU_THROW(NotSupportedError, "tessellation and geometry shader extensions not supported");
144     }
145 
146     std::ostringstream shader;
147 
148     struct testConfig
149     {
150         std::string builtInType;
151         std::string varyingCheck;
152     } testConfigs[] = {
153         {"gl_SampleID", "    lowp int writeValue = 1; \n    gl_SampleID = writeValue; \n"},
154         {"gl_SamplePosition",
155          "    mediump vec2 writeValue = vec2(1.0f, 1.0f); \n    gl_SamplePosition = writeValue; \n"},
156         {"gl_SampleMaskIn", "    lowp int writeValue = 1; \n    gl_SampleMaskIn[0] = writeValue; \n"},
157         {"gl_SampleMask", "    highp int readValue = gl_SampleMask[0]; \n"},
158     };
159 
160     for (int idx = 0; idx < DE_LENGTH_OF_ARRAY(testConfigs); idx++)
161     {
162         shader.str("");
163         shader << getVersionAndExtension(ctx) << "void main () \n"
164                << "{ \n"
165                << testConfigs[idx].varyingCheck << "    gl_Position = vec4(1.0f, 0.0f, 0.0f , 1.0f); \n"
166                << "} \n";
167 
168         ctx.beginSection("OES_sample_variables: trying to use fragment shader built-in sampler variable " +
169                          testConfigs[idx].builtInType + " inside vertex shader");
170         verifyShader(ctx, glu::SHADERTYPE_VERTEX, shader.str(), EXPECT_RESULT_FAIL);
171         ctx.endSection();
172     }
173 
174     for (int idx = 0; idx < DE_LENGTH_OF_ARRAY(testConfigs); idx++)
175     {
176         shader.str("");
177         shader << getVersionAndExtension(ctx) << "layout (vertices = 3) out; \n"
178                << "void main () \n"
179                << "{ \n"
180                << testConfigs[idx].varyingCheck << "} \n";
181 
182         ctx.beginSection("OES_sample_variables: trying to use fragment shader built-in sampler variable " +
183                          testConfigs[idx].builtInType + " inside tessellation control shader");
184         verifyShader(ctx, glu::SHADERTYPE_TESSELLATION_CONTROL, shader.str(), EXPECT_RESULT_FAIL);
185         ctx.endSection();
186     }
187 
188     for (int idx = 0; idx < DE_LENGTH_OF_ARRAY(testConfigs); idx++)
189     {
190         shader.str("");
191         shader << getVersionAndExtension(ctx) << "layout (triangles, equal_spacing, ccw) in; \n"
192                << "void main () \n"
193                << "{ \n"
194                << testConfigs[idx].varyingCheck << "} \n";
195 
196         ctx.beginSection("OES_sample_variables: trying to use fragment shader built-in sampler variable " +
197                          testConfigs[idx].builtInType + " inside tessellation evaluation shader");
198         verifyShader(ctx, glu::SHADERTYPE_TESSELLATION_EVALUATION, shader.str(), EXPECT_RESULT_FAIL);
199         ctx.endSection();
200     }
201 
202     for (int idx = 0; idx < DE_LENGTH_OF_ARRAY(testConfigs); idx++)
203     {
204         shader.str("");
205         shader << getVersionAndExtension(ctx) << "layout (triangles) in; \n"
206                << "layout (triangle_strip, max_vertices = 32) out; \n"
207                << "void main () \n"
208                << "{ \n"
209                << testConfigs[idx].varyingCheck << "} \n";
210 
211         ctx.beginSection("OES_sample_variables: trying to use fragment shader built-in sampler variable " +
212                          testConfigs[idx].builtInType + " inside geometry shader");
213         verifyShader(ctx, glu::SHADERTYPE_GEOMETRY, shader.str(), EXPECT_RESULT_FAIL);
214         ctx.endSection();
215     }
216 }
217 
index_outside_sample_mask_range(NegativeTestContext & ctx)218 void index_outside_sample_mask_range(NegativeTestContext &ctx)
219 {
220     // Skip this test for GL4.5 - shader will compile
221     if (!glu::isContextTypeES(ctx.getRenderContext().getType()))
222         return;
223 
224     checkSupported(ctx);
225 
226     std::ostringstream shader;
227     const int MAX_TYPES   = 2;
228     const int MAX_INDEXES = 2;
229 
230     struct testConfig
231     {
232         std::string builtInType[MAX_TYPES];
233         std::string invalidIndex[MAX_INDEXES];
234     } testConfigs = {{"gl_SampleMask", "gl_SampleMaskIn"},
235                      {"    const highp int invalidIndex = (gl_MaxSamples + 31) / 32; \n",
236                       "    const highp int invalidIndex = -1; \n"}};
237 
238     for (int typeIdx = 0; typeIdx < MAX_TYPES; typeIdx++)
239     {
240         for (int invalidIdx = 0; invalidIdx < MAX_INDEXES; invalidIdx++)
241         {
242             shader.str("");
243             shader << getVersionAndExtension(ctx) << "layout (location = 0) out mediump vec4 fs_color; \n"
244                    << "void main() \n"
245                    << "{ \n"
246                    << testConfigs.invalidIndex[invalidIdx]
247                    << "    highp int invalidValue = " << testConfigs.builtInType[typeIdx] << "[invalidIndex]; \n"
248                    << "    fs_color = vec4(1.0f, 0.0f, 0.0f, 1.0f); \n"
249                    << "} \n";
250 
251             ctx.beginSection("OES_sample_variables: using constant integral expression outside of " +
252                              testConfigs.builtInType[typeIdx] + " bounds");
253             verifyShader(ctx, glu::SHADERTYPE_FRAGMENT, shader.str(), EXPECT_RESULT_FAIL);
254             ctx.endSection();
255         }
256     }
257 }
258 
access_built_in_types_without_extension(NegativeTestContext & ctx)259 void access_built_in_types_without_extension(NegativeTestContext &ctx)
260 {
261     checkSupported(ctx);
262 
263     std::ostringstream shader;
264 
265     struct testConfig
266     {
267         std::string builtInType;
268         std::string varyingCheck;
269     } testConfigs[] = {
270         {"gl_SampleID", "    lowp int writeValue = 1; \n    gl_SampleID = writeValue; \n"},
271         {"gl_SamplePosition",
272          "    mediump vec2 writeValue = vec2(1.0f, 1.0f); \n    gl_SamplePosition = writeValue; \n"},
273         {"gl_SampleMaskIn", "    lowp int writeValue = 1; \n    gl_SampleMaskIn[0] = writeValue; \n"},
274         {"gl_SampleMask", "    highp int readValue = gl_SampleMask[0]; \n"},
275     };
276 
277     for (int idx = 0; idx < DE_LENGTH_OF_ARRAY(testConfigs); idx++)
278     {
279         shader.str("");
280         shader << "#version 310 es \n"
281                << "layout (location = 0) out mediump vec4 fs_color; \n"
282                << "void main() \n"
283                << "{ \n"
284                << testConfigs[idx].varyingCheck << "    fs_color = vec4(1.0f, 0.0f, 0.0f, 1.0f); \n"
285                << "} \n";
286 
287         ctx.beginSection("OES_sample_variables: accessing built-in type " + testConfigs[idx].builtInType +
288                          " in shader version 310 ES without required extension");
289         verifyShader(ctx, glu::SHADERTYPE_FRAGMENT, shader.str(), EXPECT_RESULT_FAIL);
290         ctx.endSection();
291     }
292 }
293 
redeclare_built_in_types(NegativeTestContext & ctx)294 void redeclare_built_in_types(NegativeTestContext &ctx)
295 {
296     // skip this test for core GL
297     if (glu::isContextTypeGLCore(ctx.getRenderContext().getType()))
298         return;
299 
300     checkSupported(ctx);
301 
302     std::ostringstream shader;
303     std::ostringstream testName;
304 
305     const char *const testConfigs[] = {
306         "gl_SampleID",
307         "gl_SamplePosition",
308         "gl_SampleMaskIn",
309         "gl_SampleMask",
310     };
311 
312     for (int idx = 0; idx < DE_LENGTH_OF_ARRAY(testConfigs); idx++)
313     {
314         shader.str("");
315         shader << getVersionAndExtension(ctx) << "layout (location = 0) out mediump vec4 fs_color; \n"
316                << "uniform lowp int " << testConfigs[idx] << "; \n"
317                << "void main() \n"
318                << "{ \n"
319                << "    if (" << testConfigs[idx] << " == 0) \n"
320                << "        fs_color = vec4(1.0f, 0.0f, 0.0f, 1.0f); \n"
321                << "    else \n"
322                << "        fs_color = vec4(0.0f, 1.0f, 0.0f, 1.0f); \n"
323                << "} \n";
324 
325         testName.str("");
326         testName << "OES_sample_variables: redeclare built-in type " << testConfigs[idx];
327         ctx.beginSection(testName.str());
328         verifyShader(ctx, glu::SHADERTYPE_FRAGMENT, shader.str(), EXPECT_RESULT_FAIL);
329         ctx.endSection();
330     }
331 }
332 
333 } // namespace
334 
getNegativeSampleVariablesTestFunctions(void)335 std::vector<FunctionContainer> getNegativeSampleVariablesTestFunctions(void)
336 {
337     const FunctionContainer funcs[] = {
338         {write_to_read_only_types, "write_to_read_only_types",
339          "tests trying writing to read-only built-in sample variables"},
340         {access_built_in_types_inside_other_shaders, "access_built_in_types_inside_other_shaders",
341          "Tests try to access fragment shader sample variables in other shaders"},
342         {index_outside_sample_mask_range, "index_outside_sample_mask_range",
343          "tests try to index into built-in sample array types out of bounds"},
344         {access_built_in_types_without_extension, "access_built_in_types_without_extension",
345          "tests try to access built-in sample types without the correct extension using version 310 es"},
346         {redeclare_built_in_types, "redeclare_built_in_types", "Tests try to redeclare built-in sample types"},
347     };
348 
349     return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
350 }
351 
352 } // namespace NegativeTestShared
353 } // namespace Functional
354 } // namespace gles31
355 } // namespace deqp
356