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 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 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 155 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 168 CoreSamplerTypeCase::CoreSamplerTypeCase (Context& ctx, const char* name, const char* desc) 169 : BaseTypeCase(ctx, name, desc, DE_NULL) 170 { 171 } 172 173 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 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 203 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 228 TextureBufferSamplerTypeCase::TextureBufferSamplerTypeCase (Context& ctx, const char* name, const char* desc) 229 : BaseTypeCase(ctx, name, desc, "GL_EXT_texture_buffer") 230 { 231 } 232 233 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 259 TextureBufferImageTypeCase::TextureBufferImageTypeCase (Context& ctx, const char* name, const char* desc) 260 : BaseTypeCase(ctx, name, desc, "GL_EXT_texture_buffer") 261 { 262 } 263 264 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 280 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 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 300 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 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 332 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 348 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 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 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 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 433 ShaderStateQueryTests::ShaderStateQueryTests (Context& context) 434 : TestCaseGroup(context, "shader", "Shader state query tests") 435 { 436 } 437 438 ShaderStateQueryTests::~ShaderStateQueryTests (void) 439 { 440 } 441 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