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