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 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 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 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 163 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 176 CoreSamplerTypeCase::CoreSamplerTypeCase (Context& ctx, const char* name, const char* desc) 177 : BaseTypeCase(ctx, name, desc, DE_NULL) 178 { 179 } 180 181 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 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 211 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 236 TextureBufferSamplerTypeCase::TextureBufferSamplerTypeCase (Context& ctx, const char* name, const char* desc) 237 : BaseTypeCase(ctx, name, desc, "GL_EXT_texture_buffer") 238 { 239 } 240 241 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 267 TextureBufferImageTypeCase::TextureBufferImageTypeCase (Context& ctx, const char* name, const char* desc) 268 : BaseTypeCase(ctx, name, desc, "GL_EXT_texture_buffer") 269 { 270 } 271 272 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 288 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 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 308 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 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 340 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 356 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 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 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 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 445 ShaderStateQueryTests::ShaderStateQueryTests (Context& context) 446 : TestCaseGroup(context, "shader", "Shader state query tests") 447 { 448 } 449 450 ShaderStateQueryTests::~ShaderStateQueryTests (void) 451 { 452 } 453 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