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