1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.1 Module
3 * -------------------------------------------------
4 *
5 * Copyright 2014 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 Shader state query tests
22 *//*--------------------------------------------------------------------*/
23
24 #include "es31fShaderStateQueryTests.hpp"
25 #include "es31fInfoLogQueryShared.hpp"
26 #include "glsStateQueryUtil.hpp"
27 #include "tcuTestLog.hpp"
28 #include "tcuStringTemplate.hpp"
29 #include "gluShaderProgram.hpp"
30 #include "gluRenderContext.hpp"
31 #include "gluCallLogWrapper.hpp"
32 #include "gluContextInfo.hpp"
33 #include "gluStrUtil.hpp"
34 #include "glwFunctions.hpp"
35 #include "glwEnums.hpp"
36
37 namespace deqp
38 {
39 namespace gles31
40 {
41 namespace Functional
42 {
43 namespace
44 {
45
46 static const char* const s_brokenSource = "#version 310 es\n"
47 "broken, this should not compile,\n"
48 "{";
49
50 class BaseTypeCase : public TestCase
51 {
52 public:
53 struct TestTypeInfo
54 {
55 glw::GLenum glType;
56 const char* declarationStr;
57 const char* accessStr;
58 };
59
60 BaseTypeCase (Context& ctx, const char* name, const char* desc, const char* extension);
61
62 private:
63 IterateResult iterate (void);
64 virtual std::vector<TestTypeInfo> getInfos (void) const = 0;
65 virtual void checkRequirements (void) const;
66
67 const char* const m_extension;
68 };
69
BaseTypeCase(Context & ctx,const char * name,const char * desc,const char * extension)70 BaseTypeCase::BaseTypeCase (Context& ctx, const char* name, const char* desc, const char* extension)
71 : TestCase (ctx, name, desc)
72 , m_extension (extension)
73 {
74 }
75
iterate(void)76 BaseTypeCase::IterateResult BaseTypeCase::iterate (void)
77 {
78 static const char* const vertexSource = "#version 310 es\n"
79 "in highp vec4 a_position;\n"
80 "void main(void)\n"
81 "{\n"
82 " gl_Position = a_position;\n"
83 "}\n";
84 static const char* const fragmentSourceTemplate = "#version 310 es\n"
85 "${EXTENSIONSTATEMENT}"
86 "${DECLARATIONSTR};\n"
87 "layout(location = 0) out highp vec4 dEQP_FragColor;\n"
88 "void main(void)\n"
89 "{\n"
90 " dEQP_FragColor = vec4(${ACCESSSTR});\n"
91 "}\n";
92
93 tcu::ResultCollector result (m_testCtx.getLog());
94 std::vector<TestTypeInfo> samplerTypes = getInfos();
95
96 if (m_extension && !m_context.getContextInfo().isExtensionSupported(m_extension))
97 throw tcu::NotSupportedError("Test requires " + std::string(m_extension));
98 checkRequirements();
99
100 for (int typeNdx = 0; typeNdx < (int)samplerTypes.size(); ++typeNdx)
101 {
102 const tcu::ScopedLogSection section (m_testCtx.getLog(),
103 std::string(glu::getShaderVarTypeStr(samplerTypes[typeNdx].glType).toString()),
104 "Uniform type " + glu::getShaderVarTypeStr(samplerTypes[typeNdx].glType).toString());
105
106 std::map<std::string, std::string> shaderArgs;
107 shaderArgs["DECLARATIONSTR"] = samplerTypes[typeNdx].declarationStr;
108 shaderArgs["ACCESSSTR"] = samplerTypes[typeNdx].accessStr;
109 shaderArgs["EXTENSIONSTATEMENT"] = (m_extension) ? (std::string() + "#extension " + m_extension + " : require\n") : ("");
110
111 const std::string fragmentSource = tcu::StringTemplate(fragmentSourceTemplate).specialize(shaderArgs);
112 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
113 glu::ShaderProgram program (m_context.getRenderContext(), glu::ProgramSources() << glu::VertexSource(vertexSource) << glu::FragmentSource(fragmentSource));
114
115 m_testCtx.getLog() << tcu::TestLog::Message << "Building program with uniform sampler of type " << glu::getShaderVarTypeStr(samplerTypes[typeNdx].glType) << tcu::TestLog::EndMessage;
116
117 if (!program.isOk())
118 {
119 m_testCtx.getLog() << program;
120 result.fail("could not build shader");
121 }
122 else
123 {
124 // only one uniform -- uniform at index 0
125 int uniforms = 0;
126 gl.getProgramiv(program.getProgram(), GL_ACTIVE_UNIFORMS, &uniforms);
127
128 if (uniforms != 1)
129 result.fail("Unexpected GL_ACTIVE_UNIFORMS, expected 1");
130 else
131 {
132 // check type
133 const glw::GLuint uniformIndex = 0;
134 glw::GLint type = 0;
135
136 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying uniform type." << tcu::TestLog::EndMessage;
137 gl.getActiveUniformsiv(program.getProgram(), 1, &uniformIndex, GL_UNIFORM_TYPE, &type);
138
139 if (type != (glw::GLint)samplerTypes[typeNdx].glType)
140 {
141 std::ostringstream buf;
142 buf << "Invalid type, expected " << samplerTypes[typeNdx].glType << ", got " << type;
143 result.fail(buf.str());
144 }
145 }
146 }
147
148 GLU_EXPECT_NO_ERROR(gl.getError(), "");
149 }
150
151 result.setTestContextResult(m_testCtx);
152 return STOP;
153 }
154
checkRequirements(void) const155 void BaseTypeCase::checkRequirements (void) const
156 {
157 }
158
159 class CoreSamplerTypeCase : public BaseTypeCase
160 {
161 public:
162 CoreSamplerTypeCase (Context& ctx, const char* name, const char* desc);
163
164 private:
165 std::vector<TestTypeInfo> getInfos (void) const;
166 };
167
CoreSamplerTypeCase(Context & ctx,const char * name,const char * desc)168 CoreSamplerTypeCase::CoreSamplerTypeCase (Context& ctx, const char* name, const char* desc)
169 : BaseTypeCase(ctx, name, desc, DE_NULL)
170 {
171 }
172
getInfos(void) const173 std::vector<BaseTypeCase::TestTypeInfo> CoreSamplerTypeCase::getInfos (void) const
174 {
175 static const TestTypeInfo samplerTypes[] =
176 {
177 { GL_SAMPLER_2D_MULTISAMPLE, "uniform highp sampler2DMS u_sampler", "texelFetch(u_sampler, ivec2(gl_FragCoord.xy), 0)" },
178 { GL_INT_SAMPLER_2D_MULTISAMPLE, "uniform highp isampler2DMS u_sampler", "texelFetch(u_sampler, ivec2(gl_FragCoord.xy), 0)" },
179 { GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE, "uniform highp usampler2DMS u_sampler", "texelFetch(u_sampler, ivec2(gl_FragCoord.xy), 0)" },
180 };
181
182 std::vector<TestTypeInfo> infos;
183 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(samplerTypes); ++ndx)
184 infos.push_back(samplerTypes[ndx]);
185
186 return infos;
187 }
188
189 class MSArraySamplerTypeCase : public BaseTypeCase
190 {
191 public:
192 MSArraySamplerTypeCase (Context& ctx, const char* name, const char* desc);
193
194 private:
195 std::vector<TestTypeInfo> getInfos (void) const;
196 };
197
MSArraySamplerTypeCase(Context & ctx,const char * name,const char * desc)198 MSArraySamplerTypeCase::MSArraySamplerTypeCase (Context& ctx, const char* name, const char* desc)
199 : BaseTypeCase(ctx, name, desc, "GL_OES_texture_storage_multisample_2d_array")
200 {
201 }
202
getInfos(void) const203 std::vector<BaseTypeCase::TestTypeInfo> MSArraySamplerTypeCase::getInfos (void) const
204 {
205 static const TestTypeInfo samplerTypes[] =
206 {
207 { GL_SAMPLER_2D_MULTISAMPLE_ARRAY, "uniform highp sampler2DMSArray u_sampler", "texelFetch(u_sampler, ivec3(gl_FragCoord.xyz), 0)" },
208 { GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, "uniform highp isampler2DMSArray u_sampler", "texelFetch(u_sampler, ivec3(gl_FragCoord.xyz), 0)" },
209 { GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, "uniform highp usampler2DMSArray u_sampler", "texelFetch(u_sampler, ivec3(gl_FragCoord.xyz), 0)" },
210 };
211
212 std::vector<TestTypeInfo> infos;
213 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(samplerTypes); ++ndx)
214 infos.push_back(samplerTypes[ndx]);
215
216 return infos;
217 }
218
219 class TextureBufferSamplerTypeCase : public BaseTypeCase
220 {
221 public:
222 TextureBufferSamplerTypeCase (Context& ctx, const char* name, const char* desc);
223
224 private:
225 std::vector<TestTypeInfo> getInfos (void) const;
226 };
227
TextureBufferSamplerTypeCase(Context & ctx,const char * name,const char * desc)228 TextureBufferSamplerTypeCase::TextureBufferSamplerTypeCase (Context& ctx, const char* name, const char* desc)
229 : BaseTypeCase(ctx, name, desc, "GL_EXT_texture_buffer")
230 {
231 }
232
getInfos(void) const233 std::vector<BaseTypeCase::TestTypeInfo> TextureBufferSamplerTypeCase::getInfos (void) const
234 {
235 static const TestTypeInfo samplerTypes[] =
236 {
237 { GL_SAMPLER_BUFFER, "uniform highp samplerBuffer u_sampler", "texelFetch(u_sampler, int(gl_FragCoord.x))" },
238 { GL_INT_SAMPLER_BUFFER, "uniform highp isamplerBuffer u_sampler", "texelFetch(u_sampler, int(gl_FragCoord.x))" },
239 { GL_UNSIGNED_INT_SAMPLER_BUFFER, "uniform highp usamplerBuffer u_sampler", "texelFetch(u_sampler, int(gl_FragCoord.x))" },
240 };
241
242 std::vector<TestTypeInfo> infos;
243 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(samplerTypes); ++ndx)
244 infos.push_back(samplerTypes[ndx]);
245
246 return infos;
247 }
248
249 class TextureBufferImageTypeCase : public BaseTypeCase
250 {
251 public:
252 TextureBufferImageTypeCase (Context& ctx, const char* name, const char* desc);
253
254 private:
255 std::vector<TestTypeInfo> getInfos (void) const;
256 void checkRequirements (void) const;
257 };
258
TextureBufferImageTypeCase(Context & ctx,const char * name,const char * desc)259 TextureBufferImageTypeCase::TextureBufferImageTypeCase (Context& ctx, const char* name, const char* desc)
260 : BaseTypeCase(ctx, name, desc, "GL_EXT_texture_buffer")
261 {
262 }
263
getInfos(void) const264 std::vector<BaseTypeCase::TestTypeInfo> TextureBufferImageTypeCase::getInfos (void) const
265 {
266 static const TestTypeInfo samplerTypes[] =
267 {
268 { GL_IMAGE_BUFFER, "layout(binding=0, rgba8) readonly uniform highp imageBuffer u_image", "imageLoad(u_image, int(gl_FragCoord.x))" },
269 { GL_INT_IMAGE_BUFFER, "layout(binding=0, r32i) readonly uniform highp iimageBuffer u_image", "imageLoad(u_image, int(gl_FragCoord.x))" },
270 { GL_UNSIGNED_INT_IMAGE_BUFFER, "layout(binding=0, r32ui) readonly uniform highp uimageBuffer u_image", "imageLoad(u_image, int(gl_FragCoord.x))" },
271 };
272
273 std::vector<TestTypeInfo> infos;
274 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(samplerTypes); ++ndx)
275 infos.push_back(samplerTypes[ndx]);
276
277 return infos;
278 }
279
checkRequirements(void) const280 void TextureBufferImageTypeCase::checkRequirements (void) const
281 {
282 if (m_context.getContextInfo().getInt(GL_MAX_FRAGMENT_IMAGE_UNIFORMS) < 1)
283 throw tcu::NotSupportedError("Test requires fragment images");
284 }
285
286 class CubeArraySamplerTypeCase : public BaseTypeCase
287 {
288 public:
289 CubeArraySamplerTypeCase (Context& ctx, const char* name, const char* desc);
290
291 private:
292 std::vector<TestTypeInfo> getInfos (void) const;
293 };
294
CubeArraySamplerTypeCase(Context & ctx,const char * name,const char * desc)295 CubeArraySamplerTypeCase::CubeArraySamplerTypeCase (Context& ctx, const char* name, const char* desc)
296 : BaseTypeCase(ctx, name, desc, "GL_EXT_texture_cube_map_array")
297 {
298 }
299
getInfos(void) const300 std::vector<BaseTypeCase::TestTypeInfo> CubeArraySamplerTypeCase::getInfos (void) const
301 {
302 static const TestTypeInfo samplerTypes[] =
303 {
304 { GL_SAMPLER_CUBE_MAP_ARRAY, "uniform highp samplerCubeArray u_sampler", "texture(u_sampler, gl_FragCoord.xxyz)" },
305 { GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW, "uniform highp samplerCubeArrayShadow u_sampler", "texture(u_sampler, gl_FragCoord.xxyz, 0.5)" },
306 { GL_INT_SAMPLER_CUBE_MAP_ARRAY, "uniform highp isamplerCubeArray u_sampler", "texture(u_sampler, gl_FragCoord.xxyz)" },
307 { GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY, "uniform highp usamplerCubeArray u_sampler", "texture(u_sampler, gl_FragCoord.xxyz)" },
308 };
309
310 std::vector<TestTypeInfo> infos;
311 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(samplerTypes); ++ndx)
312 infos.push_back(samplerTypes[ndx]);
313
314 return infos;
315 }
316
317 class CubeArrayImageTypeCase : public BaseTypeCase
318 {
319 public:
320 CubeArrayImageTypeCase (Context& ctx, const char* name, const char* desc);
321
322 private:
323 std::vector<TestTypeInfo> getInfos (void) const;
324 void checkRequirements (void) const;
325 };
326
CubeArrayImageTypeCase(Context & ctx,const char * name,const char * desc)327 CubeArrayImageTypeCase::CubeArrayImageTypeCase (Context& ctx, const char* name, const char* desc)
328 : BaseTypeCase(ctx, name, desc, "GL_EXT_texture_cube_map_array")
329 {
330 }
331
getInfos(void) const332 std::vector<BaseTypeCase::TestTypeInfo> CubeArrayImageTypeCase::getInfos (void) const
333 {
334 static const TestTypeInfo samplerTypes[] =
335 {
336 { GL_IMAGE_CUBE_MAP_ARRAY, "layout(binding=0, rgba8) readonly uniform highp imageCubeArray u_image", "imageLoad(u_image, ivec3(gl_FragCoord.xyx))" },
337 { GL_INT_IMAGE_CUBE_MAP_ARRAY, "layout(binding=0, r32i) readonly uniform highp iimageCubeArray u_image", "imageLoad(u_image, ivec3(gl_FragCoord.xyx))" },
338 { GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY, "layout(binding=0, r32ui) readonly uniform highp uimageCubeArray u_image", "imageLoad(u_image, ivec3(gl_FragCoord.xyx))" },
339 };
340
341 std::vector<TestTypeInfo> infos;
342 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(samplerTypes); ++ndx)
343 infos.push_back(samplerTypes[ndx]);
344
345 return infos;
346 }
347
checkRequirements(void) const348 void CubeArrayImageTypeCase::checkRequirements (void) const
349 {
350 if (m_context.getContextInfo().getInt(GL_MAX_FRAGMENT_IMAGE_UNIFORMS) < 1)
351 throw tcu::NotSupportedError("Test requires fragment images");
352 }
353
354 class ShaderLogCase : public TestCase
355 {
356 public:
357 ShaderLogCase (Context& ctx, const char* name, const char* desc, glu::ShaderType shaderType);
358
359 private:
360 void init (void);
361 IterateResult iterate (void);
362
363 const glu::ShaderType m_shaderType;
364 };
365
ShaderLogCase(Context & ctx,const char * name,const char * desc,glu::ShaderType shaderType)366 ShaderLogCase::ShaderLogCase (Context& ctx, const char* name, const char* desc, glu::ShaderType shaderType)
367 : TestCase (ctx, name, desc)
368 , m_shaderType (shaderType)
369 {
370 }
371
init(void)372 void ShaderLogCase::init (void)
373 {
374 switch (m_shaderType)
375 {
376 case glu::SHADERTYPE_VERTEX:
377 case glu::SHADERTYPE_FRAGMENT:
378 case glu::SHADERTYPE_COMPUTE:
379 break;
380
381 case glu::SHADERTYPE_GEOMETRY:
382 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader"))
383 throw tcu::NotSupportedError("Test requires GL_EXT_geometry_shader extension");
384 break;
385
386 case glu::SHADERTYPE_TESSELLATION_CONTROL:
387 case glu::SHADERTYPE_TESSELLATION_EVALUATION:
388 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_tessellation_shader"))
389 throw tcu::NotSupportedError("Test requires GL_EXT_tessellation_shader extension");
390 break;
391
392 default:
393 DE_ASSERT(false);
394 break;
395 }
396 }
397
iterate(void)398 ShaderLogCase::IterateResult ShaderLogCase::iterate (void)
399 {
400 using gls::StateQueryUtil::StateQueryMemoryWriteGuard;
401
402 tcu::ResultCollector result (m_testCtx.getLog());
403 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
404 deUint32 shader = 0;
405 StateQueryMemoryWriteGuard<glw::GLint> logLen;
406
407 gl.enableLogging(true);
408
409 m_testCtx.getLog() << tcu::TestLog::Message << "Trying to compile broken shader source." << tcu::TestLog::EndMessage;
410
411 shader = gl.glCreateShader(glu::getGLShaderType(m_shaderType));
412 GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "create shader");
413
414 gl.glShaderSource(shader, 1, &s_brokenSource, DE_NULL);
415 gl.glCompileShader(shader);
416 GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "compile");
417
418 gl.glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLen);
419 logLen.verifyValidity(result);
420
421 if (!logLen.isUndefined())
422 verifyInfoLogQuery(result, gl, logLen, shader, &glu::CallLogWrapper::glGetShaderInfoLog, "glGetShaderInfoLog");
423
424 gl.glDeleteShader(shader);
425 GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "delete");
426
427 result.setTestContextResult(m_testCtx);
428 return STOP;
429 }
430
431 } // anonymous
432
ShaderStateQueryTests(Context & context)433 ShaderStateQueryTests::ShaderStateQueryTests (Context& context)
434 : TestCaseGroup(context, "shader", "Shader state query tests")
435 {
436 }
437
~ShaderStateQueryTests(void)438 ShaderStateQueryTests::~ShaderStateQueryTests (void)
439 {
440 }
441
init(void)442 void ShaderStateQueryTests::init (void)
443 {
444 addChild(new CoreSamplerTypeCase (m_context, "sampler_type", "Sampler type cases"));
445 addChild(new MSArraySamplerTypeCase (m_context, "sampler_type_multisample_array", "MSAA array sampler type cases"));
446 addChild(new TextureBufferSamplerTypeCase (m_context, "sampler_type_texture_buffer", "Texture buffer sampler type cases"));
447 addChild(new TextureBufferImageTypeCase (m_context, "image_type_texture_buffer", "Texture buffer image type cases"));
448 addChild(new CubeArraySamplerTypeCase (m_context, "sampler_type_cube_array", "Cube array sampler type cases"));
449 addChild(new CubeArrayImageTypeCase (m_context, "image_type_cube_array", "Cube array image type cases"));
450
451 // shader info log tests
452 // \note, there exists similar tests in gles3 module. However, the gles31 could use a different
453 // shader compiler with different INFO_LOG bugs.
454 {
455 static const struct
456 {
457 const char* caseName;
458 glu::ShaderType caseType;
459 } shaderTypes[] =
460 {
461 { "info_log_vertex", glu::SHADERTYPE_VERTEX },
462 { "info_log_fragment", glu::SHADERTYPE_FRAGMENT },
463 { "info_log_geometry", glu::SHADERTYPE_GEOMETRY },
464 { "info_log_tess_ctrl", glu::SHADERTYPE_TESSELLATION_CONTROL },
465 { "info_log_tess_eval", glu::SHADERTYPE_TESSELLATION_EVALUATION },
466 { "info_log_compute", glu::SHADERTYPE_COMPUTE },
467 };
468
469 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(shaderTypes); ++ndx)
470 addChild(new ShaderLogCase(m_context, shaderTypes[ndx].caseName, "", shaderTypes[ndx].caseType));
471 }
472 }
473
474 } // Functional
475 } // gles31
476 } // deqp
477