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