1 /*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES 2.0 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 Texture access function tests. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "es2fShaderTextureFunctionTests.hpp" 25 #include "glsShaderRenderCase.hpp" 26 #include "glsShaderLibrary.hpp" 27 #include "glsTextureTestUtil.hpp" 28 #include "gluTexture.hpp" 29 #include "gluTextureUtil.hpp" 30 #include "tcuTextureUtil.hpp" 31 #include "tcuMatrix.hpp" 32 #include "tcuMatrixUtil.hpp" 33 34 #include <sstream> 35 36 #include "glwEnums.hpp" 37 #include "glwFunctions.hpp" 38 39 namespace deqp 40 { 41 namespace gles2 42 { 43 namespace Functional 44 { 45 46 namespace 47 { 48 49 enum Function 50 { 51 FUNCTION_TEXTURE = 0, //!< texture(), textureOffset() 52 FUNCTION_TEXTUREPROJ, //!< textureProj(), textureProjOffset() 53 FUNCTION_TEXTUREPROJ3, //!< textureProj(sampler2D, vec3) 54 FUNCTION_TEXTURELOD, // ... 55 FUNCTION_TEXTUREPROJLOD, 56 FUNCTION_TEXTUREPROJLOD3, //!< textureProjLod(sampler2D, vec3) 57 58 FUNCTION_LAST 59 }; 60 61 inline bool functionHasProj (Function function) 62 { 63 return function == FUNCTION_TEXTUREPROJ || 64 function == FUNCTION_TEXTUREPROJ3 || 65 function == FUNCTION_TEXTUREPROJLOD || 66 function == FUNCTION_TEXTUREPROJLOD3; 67 } 68 69 inline bool functionHasLod (Function function) 70 { 71 return function == FUNCTION_TEXTURELOD || 72 function == FUNCTION_TEXTUREPROJLOD || 73 function == FUNCTION_TEXTUREPROJLOD3; 74 } 75 76 struct TextureLookupSpec 77 { 78 Function function; 79 80 tcu::Vec4 minCoord; 81 tcu::Vec4 maxCoord; 82 83 // Bias 84 bool useBias; 85 86 // Bias or Lod for *Lod* functions 87 float minLodBias; 88 float maxLodBias; 89 90 TextureLookupSpec (void) 91 : function (FUNCTION_LAST) 92 , minCoord (0.0f) 93 , maxCoord (1.0f) 94 , useBias (false) 95 , minLodBias (0.0f) 96 , maxLodBias (0.0f) 97 { 98 } 99 100 TextureLookupSpec (Function function_, 101 const tcu::Vec4& minCoord_, 102 const tcu::Vec4& maxCoord_, 103 bool useBias_, 104 float minLodBias_, 105 float maxLodBias_) 106 : function (function_) 107 , minCoord (minCoord_) 108 , maxCoord (maxCoord_) 109 , useBias (useBias_) 110 , minLodBias (minLodBias_) 111 , maxLodBias (maxLodBias_) 112 { 113 } 114 }; 115 116 enum TextureType 117 { 118 TEXTURETYPE_2D, 119 TEXTURETYPE_CUBE_MAP, 120 121 TEXTURETYPE_LAST 122 }; 123 124 struct TextureSpec 125 { 126 TextureType type; //!< Texture type (2D, cubemap, ...) 127 deUint32 format; 128 deUint32 dataType; 129 int width; 130 int height; 131 int numLevels; 132 tcu::Sampler sampler; 133 134 TextureSpec (void) 135 : type (TEXTURETYPE_LAST) 136 , format (GL_NONE) 137 , dataType (GL_NONE) 138 , width (0) 139 , height (0) 140 , numLevels (0) 141 { 142 } 143 144 TextureSpec (TextureType type_, 145 deUint32 format_, 146 deUint32 dataType_, 147 int width_, 148 int height_, 149 int numLevels_, 150 const tcu::Sampler& sampler_) 151 : type (type_) 152 , format (format_) 153 , dataType (dataType_) 154 , width (width_) 155 , height (height_) 156 , numLevels (numLevels_) 157 , sampler (sampler_) 158 { 159 } 160 }; 161 162 struct TexLookupParams 163 { 164 float lod; 165 tcu::Vec4 scale; 166 tcu::Vec4 bias; 167 168 TexLookupParams (void) 169 : lod (0.0f) 170 , scale (1.0f) 171 , bias (0.0f) 172 { 173 } 174 }; 175 176 } // anonymous 177 178 using tcu::Vec2; 179 using tcu::Vec3; 180 using tcu::Vec4; 181 using tcu::IVec2; 182 using tcu::IVec3; 183 using tcu::IVec4; 184 185 typedef void (*TexEvalFunc) (gls::ShaderEvalContext& c, const TexLookupParams& lookupParams); 186 187 inline Vec4 texture2D (const gls::ShaderEvalContext& c, float s, float t, float lod) { return c.textures[0].tex2D->sample(c.textures[0].sampler, s, t, lod); } 188 inline Vec4 textureCube (const gls::ShaderEvalContext& c, float s, float t, float r, float lod) { return c.textures[0].texCube->sample(c.textures[0].sampler, s, t, r, lod); } 189 190 // Eval functions. 191 static void evalTexture2D (gls::ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2D(c, c.in[0].x(), c.in[0].y(), p.lod)*p.scale + p.bias; } 192 static void evalTextureCube (gls::ShaderEvalContext& c, const TexLookupParams& p) { c.color = textureCube(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), p.lod)*p.scale + p.bias; } 193 194 static void evalTexture2DBias (gls::ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2D(c, c.in[0].x(), c.in[0].y(), p.lod+c.in[1].x())*p.scale + p.bias; } 195 static void evalTextureCubeBias (gls::ShaderEvalContext& c, const TexLookupParams& p) { c.color = textureCube(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), p.lod+c.in[1].x())*p.scale + p.bias; } 196 197 static void evalTexture2DProj3 (gls::ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2D(c, c.in[0].x()/c.in[0].z(), c.in[0].y()/c.in[0].z(), p.lod)*p.scale + p.bias; } 198 static void evalTexture2DProj3Bias (gls::ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2D(c, c.in[0].x()/c.in[0].z(), c.in[0].y()/c.in[0].z(), p.lod+c.in[1].x())*p.scale + p.bias; } 199 static void evalTexture2DProj (gls::ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2D(c, c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), p.lod)*p.scale + p.bias; } 200 static void evalTexture2DProjBias (gls::ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2D(c, c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), p.lod+c.in[1].x())*p.scale + p.bias; } 201 202 static void evalTexture2DLod (gls::ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2D(c, c.in[0].x(), c.in[0].y(), c.in[1].x())*p.scale + p.bias; } 203 static void evalTextureCubeLod (gls::ShaderEvalContext& c, const TexLookupParams& p) { c.color = textureCube(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), c.in[1].x())*p.scale + p.bias; } 204 205 static void evalTexture2DProjLod3 (gls::ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2D(c, c.in[0].x()/c.in[0].z(), c.in[0].y()/c.in[0].z(), c.in[1].x())*p.scale + p.bias; } 206 static void evalTexture2DProjLod (gls::ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2D(c, c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), c.in[1].x())*p.scale + p.bias; } 207 208 class TexLookupEvaluator : public gls::ShaderEvaluator 209 { 210 public: 211 TexLookupEvaluator (TexEvalFunc evalFunc, const TexLookupParams& lookupParams) : m_evalFunc(evalFunc), m_lookupParams(lookupParams) {} 212 213 virtual void evaluate (gls::ShaderEvalContext& ctx) { m_evalFunc(ctx, m_lookupParams); } 214 215 private: 216 TexEvalFunc m_evalFunc; 217 const TexLookupParams& m_lookupParams; 218 }; 219 220 class ShaderTextureFunctionCase : public gls::ShaderRenderCase 221 { 222 public: 223 ShaderTextureFunctionCase (Context& context, const char* name, const char* desc, const TextureLookupSpec& lookup, const TextureSpec& texture, TexEvalFunc evalFunc, bool isVertexCase); 224 ~ShaderTextureFunctionCase (void); 225 226 void init (void); 227 void deinit (void); 228 229 protected: 230 void setupUniforms (int programID, const tcu::Vec4& constCoords); 231 232 private: 233 void initTexture (void); 234 void initShaderSources (void); 235 236 TextureLookupSpec m_lookupSpec; 237 TextureSpec m_textureSpec; 238 239 TexLookupParams m_lookupParams; 240 TexLookupEvaluator m_evaluator; 241 242 glu::Texture2D* m_texture2D; 243 glu::TextureCube* m_textureCube; 244 }; 245 246 ShaderTextureFunctionCase::ShaderTextureFunctionCase (Context& context, const char* name, const char* desc, const TextureLookupSpec& lookup, const TextureSpec& texture, TexEvalFunc evalFunc, bool isVertexCase) 247 : gls::ShaderRenderCase(context.getTestContext(), context.getRenderContext(), context.getContextInfo(), name, desc, isVertexCase, m_evaluator) 248 , m_lookupSpec (lookup) 249 , m_textureSpec (texture) 250 , m_evaluator (evalFunc, m_lookupParams) 251 , m_texture2D (DE_NULL) 252 , m_textureCube (DE_NULL) 253 { 254 } 255 256 ShaderTextureFunctionCase::~ShaderTextureFunctionCase (void) 257 { 258 delete m_texture2D; 259 delete m_textureCube; 260 } 261 262 void ShaderTextureFunctionCase::init (void) 263 { 264 if (m_isVertexCase) 265 { 266 const glw::Functions& gl = m_renderCtx.getFunctions(); 267 int numVertexUnits = 0; 268 gl.getIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &numVertexUnits); 269 if (numVertexUnits < 1) 270 throw tcu::NotSupportedError("Vertex shader texture access is not supported"); 271 } 272 273 { 274 // Base coord scale & bias 275 Vec4 s = m_lookupSpec.maxCoord-m_lookupSpec.minCoord; 276 Vec4 b = m_lookupSpec.minCoord; 277 278 float baseCoordTrans[] = 279 { 280 s.x(), 0.0f, 0.f, b.x(), 281 0.f, s.y(), 0.f, b.y(), 282 s.z()/2.f, -s.z()/2.f, 0.f, s.z()/2.f + b.z(), 283 -s.w()/2.f, s.w()/2.f, 0.f, s.w()/2.f + b.w() 284 }; 285 286 m_userAttribTransforms.push_back(tcu::Mat4(baseCoordTrans)); 287 } 288 289 if (functionHasLod(m_lookupSpec.function) || m_lookupSpec.useBias) 290 { 291 float s = m_lookupSpec.maxLodBias-m_lookupSpec.minLodBias; 292 float b = m_lookupSpec.minLodBias; 293 float lodCoordTrans[] = 294 { 295 s/2.0f, s/2.0f, 0.f, b, 296 0.0f, 0.0f, 0.0f, 0.0f, 297 0.0f, 0.0f, 0.0f, 0.0f, 298 0.0f, 0.0f, 0.0f, 0.0f 299 }; 300 301 m_userAttribTransforms.push_back(tcu::Mat4(lodCoordTrans)); 302 } 303 304 initShaderSources(); 305 initTexture(); 306 307 gls::ShaderRenderCase::init(); 308 } 309 310 void ShaderTextureFunctionCase::initTexture (void) 311 { 312 static const IVec4 texCubeSwz[] = 313 { 314 IVec4(0,0,1,1), 315 IVec4(1,1,0,0), 316 IVec4(0,1,0,1), 317 IVec4(1,0,1,0), 318 IVec4(0,1,1,0), 319 IVec4(1,0,0,1) 320 }; 321 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(texCubeSwz) == tcu::CUBEFACE_LAST); 322 323 tcu::TextureFormat texFmt = glu::mapGLTransferFormat(m_textureSpec.format, m_textureSpec.dataType); 324 tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt); 325 tcu::IVec2 viewportSize = getViewportSize(); 326 bool isProj = functionHasProj(m_lookupSpec.function); 327 float proj = isProj ? 1.0f/m_lookupSpec.minCoord[m_lookupSpec.function == FUNCTION_TEXTUREPROJ3 ? 2 : 3] : 1.0f; 328 329 switch (m_textureSpec.type) 330 { 331 case TEXTURETYPE_2D: 332 { 333 float cStep = 1.0f / (float)de::max(1, m_textureSpec.numLevels-1); 334 Vec4 cScale = fmtInfo.valueMax-fmtInfo.valueMin; 335 Vec4 cBias = fmtInfo.valueMin; 336 int baseCellSize = de::min(m_textureSpec.width/4, m_textureSpec.height/4); 337 338 m_texture2D = new glu::Texture2D(m_renderCtx, m_textureSpec.format, m_textureSpec.dataType, m_textureSpec.width, m_textureSpec.height); 339 for (int level = 0; level < m_textureSpec.numLevels; level++) 340 { 341 float fA = float(level)*cStep; 342 float fB = 1.0f-fA; 343 Vec4 colorA = cBias + cScale*Vec4(fA, fB, fA, fB); 344 Vec4 colorB = cBias + cScale*Vec4(fB, fA, fB, fA); 345 346 m_texture2D->getRefTexture().allocLevel(level); 347 tcu::fillWithGrid(m_texture2D->getRefTexture().getLevel(level), de::max(1, baseCellSize>>level), colorA, colorB); 348 } 349 m_texture2D->upload(); 350 351 // Compute LOD. 352 float dudx = (m_lookupSpec.maxCoord[0]-m_lookupSpec.minCoord[0])*proj*(float)m_textureSpec.width / (float)viewportSize[0]; 353 float dvdy = (m_lookupSpec.maxCoord[1]-m_lookupSpec.minCoord[1])*proj*(float)m_textureSpec.height / (float)viewportSize[1]; 354 m_lookupParams.lod = gls::TextureTestUtil::computeLodFromDerivates(gls::TextureTestUtil::LODMODE_EXACT, dudx, 0.0f, 0.0f, dvdy); 355 356 // Append to texture list. 357 m_textures.push_back(gls::TextureBinding(m_texture2D, m_textureSpec.sampler)); 358 break; 359 } 360 361 case TEXTURETYPE_CUBE_MAP: 362 { 363 float cStep = 1.0f / (float)de::max(1, m_textureSpec.numLevels-1); 364 Vec4 cScale = fmtInfo.valueMax-fmtInfo.valueMin; 365 Vec4 cBias = fmtInfo.valueMin; 366 int baseCellSize = de::min(m_textureSpec.width/4, m_textureSpec.height/4); 367 368 DE_ASSERT(m_textureSpec.width == m_textureSpec.height); 369 m_textureCube = new glu::TextureCube(m_renderCtx, m_textureSpec.format, m_textureSpec.dataType, m_textureSpec.width); 370 for (int level = 0; level < m_textureSpec.numLevels; level++) 371 { 372 float fA = float(level)*cStep; 373 float fB = 1.0f-fA; 374 Vec2 f (fA, fB); 375 376 for (int face = 0; face < tcu::CUBEFACE_LAST; face++) 377 { 378 const IVec4& swzA = texCubeSwz[face]; 379 IVec4 swzB = 1-swzA; 380 Vec4 colorA = cBias + cScale*f.swizzle(swzA[0], swzA[1], swzA[2], swzA[3]); 381 Vec4 colorB = cBias + cScale*f.swizzle(swzB[0], swzB[1], swzB[2], swzB[3]); 382 383 m_textureCube->getRefTexture().allocLevel((tcu::CubeFace)face, level); 384 tcu::fillWithGrid(m_textureCube->getRefTexture().getLevelFace(level, (tcu::CubeFace)face), de::max(1, baseCellSize>>level), colorA, colorB); 385 } 386 } 387 m_textureCube->upload(); 388 389 // Compute LOD \note Assumes that only single side is accessed and R is constant major axis. 390 DE_ASSERT(de::abs(m_lookupSpec.minCoord[2] - m_lookupSpec.maxCoord[2]) < 0.005); 391 DE_ASSERT(de::abs(m_lookupSpec.minCoord[0]) < de::abs(m_lookupSpec.minCoord[2]) && de::abs(m_lookupSpec.maxCoord[0]) < de::abs(m_lookupSpec.minCoord[2])); 392 DE_ASSERT(de::abs(m_lookupSpec.minCoord[1]) < de::abs(m_lookupSpec.minCoord[2]) && de::abs(m_lookupSpec.maxCoord[1]) < de::abs(m_lookupSpec.minCoord[2])); 393 394 tcu::CubeFaceFloatCoords c00 = tcu::getCubeFaceCoords(Vec3(m_lookupSpec.minCoord[0]*proj, m_lookupSpec.minCoord[1]*proj, m_lookupSpec.minCoord[2]*proj)); 395 tcu::CubeFaceFloatCoords c10 = tcu::getCubeFaceCoords(Vec3(m_lookupSpec.maxCoord[0]*proj, m_lookupSpec.minCoord[1]*proj, m_lookupSpec.minCoord[2]*proj)); 396 tcu::CubeFaceFloatCoords c01 = tcu::getCubeFaceCoords(Vec3(m_lookupSpec.minCoord[0]*proj, m_lookupSpec.maxCoord[1]*proj, m_lookupSpec.minCoord[2]*proj)); 397 float dudx = (c10.s - c00.s)*(float)m_textureSpec.width / (float)viewportSize[0]; 398 float dvdy = (c01.t - c00.t)*(float)m_textureSpec.height / (float)viewportSize[1]; 399 400 m_lookupParams.lod = gls::TextureTestUtil::computeLodFromDerivates(gls::TextureTestUtil::LODMODE_EXACT, dudx, 0.0f, 0.0f, dvdy); 401 402 m_textures.push_back(gls::TextureBinding(m_textureCube, m_textureSpec.sampler)); 403 break; 404 } 405 406 default: 407 DE_ASSERT(DE_FALSE); 408 } 409 410 // Set lookup scale & bias 411 m_lookupParams.scale = fmtInfo.lookupScale; 412 m_lookupParams.bias = fmtInfo.lookupBias; 413 } 414 415 void ShaderTextureFunctionCase::initShaderSources (void) 416 { 417 Function function = m_lookupSpec.function; 418 bool isVtxCase = m_isVertexCase; 419 bool isProj = functionHasProj(function); 420 bool is2DProj4 = m_textureSpec.type == TEXTURETYPE_2D && (function == FUNCTION_TEXTUREPROJ || function == FUNCTION_TEXTUREPROJLOD); 421 bool hasLodBias = functionHasLod(m_lookupSpec.function) || m_lookupSpec.useBias; 422 int texCoordComps = m_textureSpec.type == TEXTURETYPE_2D ? 2 : 3; 423 int extraCoordComps = isProj ? (is2DProj4 ? 2 : 1) : 0; 424 glu::DataType coordType = glu::getDataTypeFloatVec(texCoordComps+extraCoordComps); 425 glu::Precision coordPrec = glu::PRECISION_MEDIUMP; 426 const char* coordTypeName = glu::getDataTypeName(coordType); 427 const char* coordPrecName = glu::getPrecisionName(coordPrec); 428 tcu::TextureFormat texFmt = glu::mapGLTransferFormat(m_textureSpec.format, m_textureSpec.dataType); 429 glu::DataType samplerType = glu::TYPE_LAST; 430 const char* baseFuncName = m_textureSpec.type == TEXTURETYPE_2D ? "texture2D" : "textureCube"; 431 const char* funcExt = DE_NULL; 432 433 switch (m_textureSpec.type) 434 { 435 case TEXTURETYPE_2D: samplerType = glu::getSampler2DType(texFmt); break; 436 case TEXTURETYPE_CUBE_MAP: samplerType = glu::getSamplerCubeType(texFmt); break; 437 default: 438 DE_ASSERT(DE_FALSE); 439 } 440 441 switch (m_lookupSpec.function) 442 { 443 case FUNCTION_TEXTURE: funcExt = ""; break; 444 case FUNCTION_TEXTUREPROJ: funcExt = "Proj"; break; 445 case FUNCTION_TEXTUREPROJ3: funcExt = "Proj"; break; 446 case FUNCTION_TEXTURELOD: funcExt = "Lod"; break; 447 case FUNCTION_TEXTUREPROJLOD: funcExt = "ProjLod"; break; 448 case FUNCTION_TEXTUREPROJLOD3: funcExt = "ProjLod"; break; 449 default: 450 DE_ASSERT(DE_FALSE); 451 } 452 453 std::ostringstream vert; 454 std::ostringstream frag; 455 std::ostringstream& op = isVtxCase ? vert : frag; 456 457 vert << "attribute highp vec4 a_position;\n" 458 << "attribute " << coordPrecName << " " << coordTypeName << " a_in0;\n"; 459 460 if (hasLodBias) 461 vert << "attribute " << coordPrecName << " float a_in1;\n"; 462 463 if (isVtxCase) 464 { 465 vert << "varying mediump vec4 v_color;\n"; 466 frag << "varying mediump vec4 v_color;\n"; 467 } 468 else 469 { 470 vert << "varying " << coordPrecName << " " << coordTypeName << " v_texCoord;\n"; 471 frag << "varying " << coordPrecName << " " << coordTypeName << " v_texCoord;\n"; 472 473 if (hasLodBias) 474 { 475 vert << "varying " << coordPrecName << " float v_lodBias;\n"; 476 frag << "varying " << coordPrecName << " float v_lodBias;\n"; 477 } 478 } 479 480 // Uniforms 481 op << "uniform lowp " << glu::getDataTypeName(samplerType) << " u_sampler;\n"; 482 483 vert << "\nvoid main()\n{\n" 484 << "\tgl_Position = a_position;\n"; 485 frag << "\nvoid main()\n{\n"; 486 487 if (isVtxCase) 488 vert << "\tv_color = "; 489 else 490 frag << "\tgl_FragColor = "; 491 492 // Op. 493 { 494 const char* texCoord = isVtxCase ? "a_in0" : "v_texCoord"; 495 const char* lodBias = isVtxCase ? "a_in1" : "v_lodBias"; 496 497 op << baseFuncName << funcExt; 498 op << "(u_sampler, " << texCoord; 499 500 if (functionHasLod(function) || m_lookupSpec.useBias) 501 op << ", " << lodBias; 502 503 op << ");\n"; 504 } 505 506 if (isVtxCase) 507 frag << "\tgl_FragColor = v_color;\n"; 508 else 509 { 510 vert << "\tv_texCoord = a_in0;\n"; 511 512 if (hasLodBias) 513 vert << "\tv_lodBias = a_in1;\n"; 514 } 515 516 vert << "}\n"; 517 frag << "}\n"; 518 519 m_vertShaderSource = vert.str(); 520 m_fragShaderSource = frag.str(); 521 } 522 523 void ShaderTextureFunctionCase::deinit (void) 524 { 525 gls::ShaderRenderCase::deinit(); 526 527 delete m_texture2D; 528 delete m_textureCube; 529 530 m_texture2D = DE_NULL; 531 m_textureCube = DE_NULL; 532 } 533 534 void ShaderTextureFunctionCase::setupUniforms (int programID, const tcu::Vec4&) 535 { 536 const glw::Functions& gl = m_renderCtx.getFunctions(); 537 gl.uniform1i(gl.getUniformLocation(programID, "u_sampler"), 0); 538 } 539 540 ShaderTextureFunctionTests::ShaderTextureFunctionTests (Context& context) 541 : TestCaseGroup(context, "texture_functions", "Texture Access Function Tests") 542 { 543 } 544 545 ShaderTextureFunctionTests::~ShaderTextureFunctionTests (void) 546 { 547 } 548 549 struct TexFuncCaseSpec 550 { 551 const char* name; 552 TextureLookupSpec lookupSpec; 553 TextureSpec texSpec; 554 TexEvalFunc evalFunc; 555 }; 556 557 #define CASE_SPEC(NAME, FUNC, MINCOORD, MAXCOORD, USEBIAS, MINLOD, MAXLOD, TEXSPEC, EVALFUNC) \ 558 { #NAME, TextureLookupSpec(FUNC, MINCOORD, MAXCOORD, USEBIAS, MINLOD, MAXLOD), TEXSPEC, EVALFUNC } 559 560 static void createCaseGroup (TestCaseGroup* parent, const char* groupName, const char* groupDesc, const TexFuncCaseSpec* cases, int numCases, bool isVertex) 561 { 562 tcu::TestCaseGroup* group = new tcu::TestCaseGroup(parent->getTestContext(), groupName, groupDesc); 563 parent->addChild(group); 564 565 for (int ndx = 0; ndx < numCases; ndx++) 566 group->addChild(new ShaderTextureFunctionCase(parent->getContext(), cases[ndx].name, "", cases[ndx].lookupSpec, cases[ndx].texSpec, cases[ndx].evalFunc, isVertex)); 567 } 568 569 void ShaderTextureFunctionTests::init (void) 570 { 571 // Samplers 572 static const tcu::Sampler samplerLinearNoMipmap (tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, 573 tcu::Sampler::LINEAR, tcu::Sampler::LINEAR); 574 static const tcu::Sampler samplerLinearMipmap (tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, 575 tcu::Sampler::LINEAR_MIPMAP_NEAREST, tcu::Sampler::LINEAR); 576 577 // Default textures. 578 // Type Format DataType W H L Sampler 579 static const TextureSpec tex2D (TEXTURETYPE_2D, GL_RGBA, GL_UNSIGNED_BYTE, 256, 256, 1, samplerLinearNoMipmap); 580 static const TextureSpec tex2DMipmap (TEXTURETYPE_2D, GL_RGBA, GL_UNSIGNED_BYTE, 256, 256, 9, samplerLinearMipmap); 581 582 static const TextureSpec texCube (TEXTURETYPE_CUBE_MAP, GL_RGBA, GL_UNSIGNED_BYTE, 256, 256, 1, samplerLinearNoMipmap); 583 static const TextureSpec texCubeMipmap (TEXTURETYPE_CUBE_MAP, GL_RGBA, GL_UNSIGNED_BYTE, 256, 256, 9, samplerLinearMipmap); 584 585 // Vertex cases 586 static const TexFuncCaseSpec vertexCases[] = 587 { 588 // Name Function MinCoord MaxCoord Bias? MinLod MaxLod Texture EvalFunc 589 CASE_SPEC(texture2d, FUNCTION_TEXTURE, Vec4(-0.2f, -0.4f, 0.0f, 0.0f), Vec4( 1.5f, 2.3f, 0.0f, 0.0f), false, 0.0f, 0.0f, tex2D, evalTexture2D), 590 // CASE_SPEC(texture2d_bias, FUNCTION_TEXTURE, Vec4(-0.2f, -0.4f, 0.0f, 0.0f), Vec4( 1.5f, 2.3f, 0.0f, 0.0f), true, -2.0f, 2.0f, tex2D, evalTexture2DBias), 591 CASE_SPEC(texture2dproj_vec3, FUNCTION_TEXTUREPROJ3, Vec4(-0.3f, -0.6f, 1.5f, 0.0f), Vec4(2.25f, 3.45f, 1.5f, 0.0f), false, 0.0f, 0.0f, tex2D, evalTexture2DProj3), 592 CASE_SPEC(texture2dproj_vec4, FUNCTION_TEXTUREPROJ, Vec4(-0.3f, -0.6f, 0.0f, 1.5f), Vec4(2.25f, 3.45f, 0.0f, 1.5f), false, 0.0f, 0.0f, tex2D, evalTexture2DProj), 593 CASE_SPEC(texture2dlod, FUNCTION_TEXTURELOD, Vec4(-0.2f, -0.4f, 0.0f, 0.0f), Vec4( 1.5f, 2.3f, 0.0f, 0.0f), false, -1.0f, 9.0f, tex2DMipmap, evalTexture2DLod), 594 // CASE_SPEC(texture2dproj_vec3_bias, FUNCTION_TEXTUREPROJ3, Vec4(-0.3f, -0.6f, 1.5f, 0.0f), Vec4(2.25f, 3.45f, 1.5f, 0.0f), true, -2.0f, 2.0f, tex2D, evalTexture2DProj3Bias), 595 // CASE_SPEC(texture2dproj_vec4_bias, FUNCTION_TEXTUREPROJ, Vec4(-0.3f, -0.6f, 0.0f, 1.5f), Vec4(2.25f, 3.45f, 0.0f, 1.5f), true, -2.0f, 2.0f, tex2D, evalTexture2DProjBias), 596 CASE_SPEC(texture2dprojlod_vec3, FUNCTION_TEXTUREPROJLOD3, Vec4(-0.3f, -0.6f, 1.5f, 0.0f), Vec4(2.25f, 3.45f, 1.5f, 0.0f), false, -1.0f, 9.0f, tex2D, evalTexture2DProjLod3), 597 CASE_SPEC(texture2dprojlod_vec4, FUNCTION_TEXTUREPROJLOD, Vec4(-0.3f, -0.6f, 0.0f, 1.5f), Vec4(2.25f, 3.45f, 0.0f, 1.5f), false, -1.0f, 9.0f, tex2D, evalTexture2DProjLod), 598 CASE_SPEC(texturecube, FUNCTION_TEXTURE, Vec4(-1.0f, -1.0f, 1.01f, 0.0f), Vec4( 1.0f, 1.0f, 1.01f, 0.0f), false, 0.0f, 0.0f, texCube, evalTextureCube), 599 // CASE_SPEC(texturecube_bias, FUNCTION_TEXTURE, Vec4(-1.0f, -1.0f, -1.01f, 0.0f), Vec4( 1.0f, 1.0f, -1.01f, 0.0f), true, -2.0f, 2.0f, texCube, evalTextureCubeBias), 600 CASE_SPEC(texturecubelod, FUNCTION_TEXTURELOD, Vec4(-1.0f, -1.0f, 1.01f, 0.0f), Vec4( 1.0f, 1.0f, 1.01f, 0.0f), false, -1.0f, 9.0f, texCubeMipmap, evalTextureCubeLod), 601 }; 602 createCaseGroup(this, "vertex", "Vertex Shader Texture Lookups", &vertexCases[0], DE_LENGTH_OF_ARRAY(vertexCases), true); 603 604 // Fragment cases 605 static const TexFuncCaseSpec fragmentCases[] = 606 { 607 // Name Function MinCoord MaxCoord Bias? MinLod MaxLod Texture EvalFunc 608 CASE_SPEC(texture2d, FUNCTION_TEXTURE, Vec4(-0.2f, -0.4f, 0.0f, 0.0f), Vec4( 1.5f, 2.3f, 0.0f, 0.0f), false, 0.0f, 0.0f, tex2DMipmap, evalTexture2D), 609 CASE_SPEC(texture2d_bias, FUNCTION_TEXTURE, Vec4(-0.2f, -0.4f, 0.0f, 0.0f), Vec4( 1.5f, 2.3f, 0.0f, 0.0f), true, -2.0f, 2.0f, tex2DMipmap, evalTexture2DBias), 610 CASE_SPEC(texture2dproj_vec3, FUNCTION_TEXTUREPROJ3, Vec4(-0.3f, -0.6f, 1.5f, 0.0f), Vec4(2.25f, 3.45f, 1.5f, 0.0f), false, 0.0f, 0.0f, tex2DMipmap, evalTexture2DProj3), 611 CASE_SPEC(texture2dproj_vec4, FUNCTION_TEXTUREPROJ, Vec4(-0.3f, -0.6f, 0.0f, 1.5f), Vec4(2.25f, 3.45f, 0.0f, 1.5f), false, 0.0f, 0.0f, tex2DMipmap, evalTexture2DProj), 612 CASE_SPEC(texture2dproj_vec3_bias, FUNCTION_TEXTUREPROJ3, Vec4(-0.3f, -0.6f, 1.5f, 0.0f), Vec4(2.25f, 3.45f, 1.5f, 0.0f), true, -2.0f, 2.0f, tex2DMipmap, evalTexture2DProj3Bias), 613 CASE_SPEC(texture2dproj_vec4_bias, FUNCTION_TEXTUREPROJ, Vec4(-0.3f, -0.6f, 0.0f, 1.5f), Vec4(2.25f, 3.45f, 0.0f, 1.5f), true, -2.0f, 2.0f, tex2DMipmap, evalTexture2DProjBias), 614 CASE_SPEC(texturecube, FUNCTION_TEXTURE, Vec4(-1.0f, -1.0f, 1.01f, 0.0f), Vec4( 1.0f, 1.0f, 1.01f, 0.0f), false, 0.0f, 0.0f, texCubeMipmap, evalTextureCube), 615 CASE_SPEC(texturecube_bias, FUNCTION_TEXTURE, Vec4(-1.0f, -1.0f, -1.01f, 0.0f), Vec4( 1.0f, 1.0f, -1.01f, 0.0f), true, -2.0f, 2.0f, texCubeMipmap, evalTextureCubeBias) 616 }; 617 createCaseGroup(this, "fragment", "Fragment Shader Texture Lookups", &fragmentCases[0], DE_LENGTH_OF_ARRAY(fragmentCases), false); 618 619 // Negative cases. 620 { 621 gls::ShaderLibrary library(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo()); 622 std::vector<tcu::TestNode*> negativeCases = library.loadShaderFile("shaders/invalid_texture_functions.test"); 623 624 tcu::TestCaseGroup* group = new tcu::TestCaseGroup(m_testCtx, "invalid", "Invalid texture function usage", negativeCases); 625 addChild(group); 626 } 627 } 628 629 } // Functional 630 } // gles3 631 } // deqp 632