1e5c31af7Sopenharmony_ci/*------------------------------------------------------------------------- 2e5c31af7Sopenharmony_ci * drawElements Quality Program OpenGL ES 3.0 Module 3e5c31af7Sopenharmony_ci * ------------------------------------------------- 4e5c31af7Sopenharmony_ci * 5e5c31af7Sopenharmony_ci * Copyright 2014 The Android Open Source Project 6e5c31af7Sopenharmony_ci * 7e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 8e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License. 9e5c31af7Sopenharmony_ci * You may obtain a copy of the License at 10e5c31af7Sopenharmony_ci * 11e5c31af7Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 12e5c31af7Sopenharmony_ci * 13e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 14e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 15e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and 17e5c31af7Sopenharmony_ci * limitations under the License. 18e5c31af7Sopenharmony_ci * 19e5c31af7Sopenharmony_ci *//*! 20e5c31af7Sopenharmony_ci * \file 21e5c31af7Sopenharmony_ci * \brief Shadow texture lookup tests. 22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 23e5c31af7Sopenharmony_ci 24e5c31af7Sopenharmony_ci#include "es3fTextureShadowTests.hpp" 25e5c31af7Sopenharmony_ci#include "gluTexture.hpp" 26e5c31af7Sopenharmony_ci#include "gluPixelTransfer.hpp" 27e5c31af7Sopenharmony_ci#include "gluTextureUtil.hpp" 28e5c31af7Sopenharmony_ci#include "glsTextureTestUtil.hpp" 29e5c31af7Sopenharmony_ci#include "tcuTextureUtil.hpp" 30e5c31af7Sopenharmony_ci#include "tcuRenderTarget.hpp" 31e5c31af7Sopenharmony_ci#include "tcuTexCompareVerifier.hpp" 32e5c31af7Sopenharmony_ci#include "tcuVectorUtil.hpp" 33e5c31af7Sopenharmony_ci#include "deString.h" 34e5c31af7Sopenharmony_ci#include "deMath.h" 35e5c31af7Sopenharmony_ci#include "deStringUtil.hpp" 36e5c31af7Sopenharmony_ci#include "glwFunctions.hpp" 37e5c31af7Sopenharmony_ci#include "glwEnums.hpp" 38e5c31af7Sopenharmony_ci 39e5c31af7Sopenharmony_cinamespace deqp 40e5c31af7Sopenharmony_ci{ 41e5c31af7Sopenharmony_cinamespace gles3 42e5c31af7Sopenharmony_ci{ 43e5c31af7Sopenharmony_cinamespace Functional 44e5c31af7Sopenharmony_ci{ 45e5c31af7Sopenharmony_ci 46e5c31af7Sopenharmony_ciusing std::vector; 47e5c31af7Sopenharmony_ciusing std::string; 48e5c31af7Sopenharmony_ciusing tcu::TestLog; 49e5c31af7Sopenharmony_ciusing namespace deqp::gls::TextureTestUtil; 50e5c31af7Sopenharmony_ciusing namespace glu::TextureTestUtil; 51e5c31af7Sopenharmony_ci 52e5c31af7Sopenharmony_cienum 53e5c31af7Sopenharmony_ci{ 54e5c31af7Sopenharmony_ci TEX2D_VIEWPORT_WIDTH = 64, 55e5c31af7Sopenharmony_ci TEX2D_VIEWPORT_HEIGHT = 64, 56e5c31af7Sopenharmony_ci TEX2D_MIN_VIEWPORT_WIDTH = 64, 57e5c31af7Sopenharmony_ci TEX2D_MIN_VIEWPORT_HEIGHT = 64 58e5c31af7Sopenharmony_ci}; 59e5c31af7Sopenharmony_ci 60e5c31af7Sopenharmony_cistatic bool isFloatingPointDepthFormat (const tcu::TextureFormat& format) 61e5c31af7Sopenharmony_ci{ 62e5c31af7Sopenharmony_ci // Only two depth and depth-stencil formats are floating point 63e5c31af7Sopenharmony_ci return (format.order == tcu::TextureFormat::D && format.type == tcu::TextureFormat::FLOAT) || 64e5c31af7Sopenharmony_ci (format.order == tcu::TextureFormat::DS && format.type == tcu::TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV); 65e5c31af7Sopenharmony_ci} 66e5c31af7Sopenharmony_ci 67e5c31af7Sopenharmony_cistatic void clampFloatingPointTexture (const tcu::PixelBufferAccess& access) 68e5c31af7Sopenharmony_ci{ 69e5c31af7Sopenharmony_ci DE_ASSERT(isFloatingPointDepthFormat(access.getFormat())); 70e5c31af7Sopenharmony_ci 71e5c31af7Sopenharmony_ci for (int z = 0; z < access.getDepth(); ++z) 72e5c31af7Sopenharmony_ci for (int y = 0; y < access.getHeight(); ++y) 73e5c31af7Sopenharmony_ci for (int x = 0; x < access.getWidth(); ++x) 74e5c31af7Sopenharmony_ci access.setPixDepth( de::clamp(access.getPixDepth(x, y, z), 0.0f, 1.0f), x, y, z); 75e5c31af7Sopenharmony_ci} 76e5c31af7Sopenharmony_ci 77e5c31af7Sopenharmony_cistatic void clampFloatingPointTexture (tcu::Texture2D& target) 78e5c31af7Sopenharmony_ci{ 79e5c31af7Sopenharmony_ci for (int level = 0; level < target.getNumLevels(); ++level) 80e5c31af7Sopenharmony_ci if (!target.isLevelEmpty(level)) 81e5c31af7Sopenharmony_ci clampFloatingPointTexture(target.getLevel(level)); 82e5c31af7Sopenharmony_ci} 83e5c31af7Sopenharmony_ci 84e5c31af7Sopenharmony_cistatic void clampFloatingPointTexture (tcu::Texture2DArray& target) 85e5c31af7Sopenharmony_ci{ 86e5c31af7Sopenharmony_ci for (int level = 0; level < target.getNumLevels(); ++level) 87e5c31af7Sopenharmony_ci if (!target.isLevelEmpty(level)) 88e5c31af7Sopenharmony_ci clampFloatingPointTexture(target.getLevel(level)); 89e5c31af7Sopenharmony_ci} 90e5c31af7Sopenharmony_ci 91e5c31af7Sopenharmony_cistatic void clampFloatingPointTexture (tcu::TextureCube& target) 92e5c31af7Sopenharmony_ci{ 93e5c31af7Sopenharmony_ci for (int level = 0; level < target.getNumLevels(); ++level) 94e5c31af7Sopenharmony_ci for (int face = tcu::CUBEFACE_NEGATIVE_X; face < tcu::CUBEFACE_LAST; ++face) 95e5c31af7Sopenharmony_ci clampFloatingPointTexture(target.getLevelFace(level, (tcu::CubeFace)face)); 96e5c31af7Sopenharmony_ci} 97e5c31af7Sopenharmony_ci 98e5c31af7Sopenharmony_citemplate<typename TextureType> 99e5c31af7Sopenharmony_cibool verifyTexCompareResult (tcu::TestContext& testCtx, 100e5c31af7Sopenharmony_ci const tcu::ConstPixelBufferAccess& result, 101e5c31af7Sopenharmony_ci const TextureType& src, 102e5c31af7Sopenharmony_ci const float* texCoord, 103e5c31af7Sopenharmony_ci const ReferenceParams& sampleParams, 104e5c31af7Sopenharmony_ci const tcu::TexComparePrecision& comparePrec, 105e5c31af7Sopenharmony_ci const tcu::LodPrecision& lodPrec, 106e5c31af7Sopenharmony_ci const tcu::PixelFormat& pixelFormat) 107e5c31af7Sopenharmony_ci{ 108e5c31af7Sopenharmony_ci tcu::TestLog& log = testCtx.getLog(); 109e5c31af7Sopenharmony_ci tcu::Surface reference (result.getWidth(), result.getHeight()); 110e5c31af7Sopenharmony_ci tcu::Surface errorMask (result.getWidth(), result.getHeight()); 111e5c31af7Sopenharmony_ci const tcu::IVec4 nonShadowBits = tcu::max(getBitsVec(pixelFormat)-1, tcu::IVec4(0)); 112e5c31af7Sopenharmony_ci const tcu::Vec3 nonShadowThreshold = tcu::computeFixedPointThreshold(nonShadowBits).swizzle(1,2,3); 113e5c31af7Sopenharmony_ci int numFailedPixels; 114e5c31af7Sopenharmony_ci 115e5c31af7Sopenharmony_ci // sampleTexture() expects source image to be the same state as it would be in a GL implementation, that is 116e5c31af7Sopenharmony_ci // the floating point depth values should be in [0, 1] range as data is clamped during texture upload. Since 117e5c31af7Sopenharmony_ci // we don't have a separate "uploading" phase and just reuse the buffer we used for GL-upload, do the clamping 118e5c31af7Sopenharmony_ci // here if necessary. 119e5c31af7Sopenharmony_ci 120e5c31af7Sopenharmony_ci if (isFloatingPointDepthFormat(src.getFormat())) 121e5c31af7Sopenharmony_ci { 122e5c31af7Sopenharmony_ci TextureType clampedSource(src); 123e5c31af7Sopenharmony_ci 124e5c31af7Sopenharmony_ci clampFloatingPointTexture(clampedSource); 125e5c31af7Sopenharmony_ci 126e5c31af7Sopenharmony_ci // sample clamped values 127e5c31af7Sopenharmony_ci 128e5c31af7Sopenharmony_ci sampleTexture(tcu::SurfaceAccess(reference, pixelFormat), clampedSource, texCoord, sampleParams); 129e5c31af7Sopenharmony_ci numFailedPixels = computeTextureCompareDiff(result, reference.getAccess(), errorMask.getAccess(), clampedSource, texCoord, sampleParams, comparePrec, lodPrec, nonShadowThreshold); 130e5c31af7Sopenharmony_ci } 131e5c31af7Sopenharmony_ci else 132e5c31af7Sopenharmony_ci { 133e5c31af7Sopenharmony_ci // sample raw values (they are guaranteed to be in [0, 1] range as the format cannot represent any other values) 134e5c31af7Sopenharmony_ci 135e5c31af7Sopenharmony_ci sampleTexture(tcu::SurfaceAccess(reference, pixelFormat), src, texCoord, sampleParams); 136e5c31af7Sopenharmony_ci numFailedPixels = computeTextureCompareDiff(result, reference.getAccess(), errorMask.getAccess(), src, texCoord, sampleParams, comparePrec, lodPrec, nonShadowThreshold); 137e5c31af7Sopenharmony_ci } 138e5c31af7Sopenharmony_ci 139e5c31af7Sopenharmony_ci if (numFailedPixels > 0) 140e5c31af7Sopenharmony_ci log << TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage; 141e5c31af7Sopenharmony_ci 142e5c31af7Sopenharmony_ci log << TestLog::ImageSet("VerifyResult", "Verification result") 143e5c31af7Sopenharmony_ci << TestLog::Image("Rendered", "Rendered image", result); 144e5c31af7Sopenharmony_ci 145e5c31af7Sopenharmony_ci if (numFailedPixels > 0) 146e5c31af7Sopenharmony_ci { 147e5c31af7Sopenharmony_ci log << TestLog::Image("Reference", "Ideal reference image", reference) 148e5c31af7Sopenharmony_ci << TestLog::Image("ErrorMask", "Error mask", errorMask); 149e5c31af7Sopenharmony_ci } 150e5c31af7Sopenharmony_ci 151e5c31af7Sopenharmony_ci log << TestLog::EndImageSet; 152e5c31af7Sopenharmony_ci 153e5c31af7Sopenharmony_ci return numFailedPixels == 0; 154e5c31af7Sopenharmony_ci} 155e5c31af7Sopenharmony_ci 156e5c31af7Sopenharmony_ciclass Texture2DShadowCase : public TestCase 157e5c31af7Sopenharmony_ci{ 158e5c31af7Sopenharmony_cipublic: 159e5c31af7Sopenharmony_ci Texture2DShadowCase (Context& context, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, deUint32 format, int width, int height, deUint32 compareFunc); 160e5c31af7Sopenharmony_ci ~Texture2DShadowCase (void); 161e5c31af7Sopenharmony_ci 162e5c31af7Sopenharmony_ci void init (void); 163e5c31af7Sopenharmony_ci void deinit (void); 164e5c31af7Sopenharmony_ci IterateResult iterate (void); 165e5c31af7Sopenharmony_ci 166e5c31af7Sopenharmony_ciprivate: 167e5c31af7Sopenharmony_ci Texture2DShadowCase (const Texture2DShadowCase& other); 168e5c31af7Sopenharmony_ci Texture2DShadowCase& operator= (const Texture2DShadowCase& other); 169e5c31af7Sopenharmony_ci 170e5c31af7Sopenharmony_ci const deUint32 m_minFilter; 171e5c31af7Sopenharmony_ci const deUint32 m_magFilter; 172e5c31af7Sopenharmony_ci const deUint32 m_wrapS; 173e5c31af7Sopenharmony_ci const deUint32 m_wrapT; 174e5c31af7Sopenharmony_ci const deUint32 m_format; 175e5c31af7Sopenharmony_ci const int m_width; 176e5c31af7Sopenharmony_ci const int m_height; 177e5c31af7Sopenharmony_ci const deUint32 m_compareFunc; 178e5c31af7Sopenharmony_ci 179e5c31af7Sopenharmony_ci struct FilterCase 180e5c31af7Sopenharmony_ci { 181e5c31af7Sopenharmony_ci const glu::Texture2D* texture; 182e5c31af7Sopenharmony_ci tcu::Vec2 minCoord; 183e5c31af7Sopenharmony_ci tcu::Vec2 maxCoord; 184e5c31af7Sopenharmony_ci float ref; 185e5c31af7Sopenharmony_ci 186e5c31af7Sopenharmony_ci FilterCase (void) 187e5c31af7Sopenharmony_ci : texture (DE_NULL) 188e5c31af7Sopenharmony_ci , ref (0.0f) 189e5c31af7Sopenharmony_ci { 190e5c31af7Sopenharmony_ci } 191e5c31af7Sopenharmony_ci 192e5c31af7Sopenharmony_ci FilterCase (const glu::Texture2D* tex_, const float ref_, const tcu::Vec2& minCoord_, const tcu::Vec2& maxCoord_) 193e5c31af7Sopenharmony_ci : texture (tex_) 194e5c31af7Sopenharmony_ci , minCoord (minCoord_) 195e5c31af7Sopenharmony_ci , maxCoord (maxCoord_) 196e5c31af7Sopenharmony_ci , ref (ref_) 197e5c31af7Sopenharmony_ci { 198e5c31af7Sopenharmony_ci } 199e5c31af7Sopenharmony_ci }; 200e5c31af7Sopenharmony_ci 201e5c31af7Sopenharmony_ci std::vector<glu::Texture2D*> m_textures; 202e5c31af7Sopenharmony_ci std::vector<FilterCase> m_cases; 203e5c31af7Sopenharmony_ci 204e5c31af7Sopenharmony_ci TextureRenderer m_renderer; 205e5c31af7Sopenharmony_ci 206e5c31af7Sopenharmony_ci int m_caseNdx; 207e5c31af7Sopenharmony_ci}; 208e5c31af7Sopenharmony_ci 209e5c31af7Sopenharmony_ciTexture2DShadowCase::Texture2DShadowCase (Context& context, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, deUint32 format, int width, int height, deUint32 compareFunc) 210e5c31af7Sopenharmony_ci : TestCase (context, name, desc) 211e5c31af7Sopenharmony_ci , m_minFilter (minFilter) 212e5c31af7Sopenharmony_ci , m_magFilter (magFilter) 213e5c31af7Sopenharmony_ci , m_wrapS (wrapS) 214e5c31af7Sopenharmony_ci , m_wrapT (wrapT) 215e5c31af7Sopenharmony_ci , m_format (format) 216e5c31af7Sopenharmony_ci , m_width (width) 217e5c31af7Sopenharmony_ci , m_height (height) 218e5c31af7Sopenharmony_ci , m_compareFunc (compareFunc) 219e5c31af7Sopenharmony_ci , m_renderer (context.getRenderContext(), context.getTestContext().getLog(), glu::GLSL_VERSION_300_ES, glu::PRECISION_HIGHP) 220e5c31af7Sopenharmony_ci , m_caseNdx (0) 221e5c31af7Sopenharmony_ci{ 222e5c31af7Sopenharmony_ci} 223e5c31af7Sopenharmony_ci 224e5c31af7Sopenharmony_ciTexture2DShadowCase::~Texture2DShadowCase (void) 225e5c31af7Sopenharmony_ci{ 226e5c31af7Sopenharmony_ci deinit(); 227e5c31af7Sopenharmony_ci} 228e5c31af7Sopenharmony_ci 229e5c31af7Sopenharmony_civoid Texture2DShadowCase::init (void) 230e5c31af7Sopenharmony_ci{ 231e5c31af7Sopenharmony_ci try 232e5c31af7Sopenharmony_ci { 233e5c31af7Sopenharmony_ci // Create 2 textures. 234e5c31af7Sopenharmony_ci m_textures.reserve(2); 235e5c31af7Sopenharmony_ci m_textures.push_back(new glu::Texture2D(m_context.getRenderContext(), m_format, m_width, m_height)); 236e5c31af7Sopenharmony_ci m_textures.push_back(new glu::Texture2D(m_context.getRenderContext(), m_format, m_width, m_height)); 237e5c31af7Sopenharmony_ci 238e5c31af7Sopenharmony_ci int numLevels = m_textures[0]->getRefTexture().getNumLevels(); 239e5c31af7Sopenharmony_ci 240e5c31af7Sopenharmony_ci // Fill first gradient texture. 241e5c31af7Sopenharmony_ci for (int levelNdx = 0; levelNdx < numLevels; levelNdx++) 242e5c31af7Sopenharmony_ci { 243e5c31af7Sopenharmony_ci m_textures[0]->getRefTexture().allocLevel(levelNdx); 244e5c31af7Sopenharmony_ci tcu::fillWithComponentGradients(m_textures[0]->getRefTexture().getLevel(levelNdx), tcu::Vec4(-0.5f, -0.5f, -0.5f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f)); 245e5c31af7Sopenharmony_ci } 246e5c31af7Sopenharmony_ci 247e5c31af7Sopenharmony_ci // Fill second with grid texture. 248e5c31af7Sopenharmony_ci for (int levelNdx = 0; levelNdx < numLevels; levelNdx++) 249e5c31af7Sopenharmony_ci { 250e5c31af7Sopenharmony_ci deUint32 step = 0x00ffffff / numLevels; 251e5c31af7Sopenharmony_ci deUint32 rgb = step*levelNdx; 252e5c31af7Sopenharmony_ci deUint32 colorA = 0xff000000 | rgb; 253e5c31af7Sopenharmony_ci deUint32 colorB = 0xff000000 | ~rgb; 254e5c31af7Sopenharmony_ci 255e5c31af7Sopenharmony_ci m_textures[1]->getRefTexture().allocLevel(levelNdx); 256e5c31af7Sopenharmony_ci tcu::fillWithGrid(m_textures[1]->getRefTexture().getLevel(levelNdx), 4, tcu::RGBA(colorA).toVec(), tcu::RGBA(colorB).toVec()); 257e5c31af7Sopenharmony_ci } 258e5c31af7Sopenharmony_ci 259e5c31af7Sopenharmony_ci // Upload. 260e5c31af7Sopenharmony_ci for (std::vector<glu::Texture2D*>::iterator i = m_textures.begin(); i != m_textures.end(); i++) 261e5c31af7Sopenharmony_ci (*i)->upload(); 262e5c31af7Sopenharmony_ci } 263e5c31af7Sopenharmony_ci catch (const std::exception&) 264e5c31af7Sopenharmony_ci { 265e5c31af7Sopenharmony_ci // Clean up to save memory. 266e5c31af7Sopenharmony_ci Texture2DShadowCase::deinit(); 267e5c31af7Sopenharmony_ci throw; 268e5c31af7Sopenharmony_ci } 269e5c31af7Sopenharmony_ci 270e5c31af7Sopenharmony_ci // Compute cases. 271e5c31af7Sopenharmony_ci { 272e5c31af7Sopenharmony_ci const float refInRangeUpper = (m_compareFunc == GL_EQUAL || m_compareFunc == GL_NOTEQUAL) ? 1.0f : 0.5f; 273e5c31af7Sopenharmony_ci const float refInRangeLower = (m_compareFunc == GL_EQUAL || m_compareFunc == GL_NOTEQUAL) ? 0.0f : 0.5f; 274e5c31af7Sopenharmony_ci const float refOutOfBoundsUpper = 1.1f; // !< lookup function should clamp values to [0, 1] range 275e5c31af7Sopenharmony_ci const float refOutOfBoundsLower = -0.1f; 276e5c31af7Sopenharmony_ci 277e5c31af7Sopenharmony_ci const struct 278e5c31af7Sopenharmony_ci { 279e5c31af7Sopenharmony_ci int texNdx; 280e5c31af7Sopenharmony_ci float ref; 281e5c31af7Sopenharmony_ci float lodX; 282e5c31af7Sopenharmony_ci float lodY; 283e5c31af7Sopenharmony_ci float oX; 284e5c31af7Sopenharmony_ci float oY; 285e5c31af7Sopenharmony_ci } cases[] = 286e5c31af7Sopenharmony_ci { 287e5c31af7Sopenharmony_ci { 0, refInRangeUpper, 1.6f, 2.9f, -1.0f, -2.7f }, 288e5c31af7Sopenharmony_ci { 0, refInRangeLower, -2.0f, -1.35f, -0.2f, 0.7f }, 289e5c31af7Sopenharmony_ci { 1, refInRangeUpper, 0.14f, 0.275f, -1.5f, -1.1f }, 290e5c31af7Sopenharmony_ci { 1, refInRangeLower, -0.92f, -2.64f, 0.4f, -0.1f }, 291e5c31af7Sopenharmony_ci { 1, refOutOfBoundsUpper, -0.39f, -0.52f, 0.65f, 0.87f }, 292e5c31af7Sopenharmony_ci { 1, refOutOfBoundsLower, -1.55f, 0.65f, 0.35f, 0.91f }, 293e5c31af7Sopenharmony_ci }; 294e5c31af7Sopenharmony_ci 295e5c31af7Sopenharmony_ci const float viewportW = (float)de::min<int>(TEX2D_VIEWPORT_WIDTH, m_context.getRenderTarget().getWidth()); 296e5c31af7Sopenharmony_ci const float viewportH = (float)de::min<int>(TEX2D_VIEWPORT_HEIGHT, m_context.getRenderTarget().getHeight()); 297e5c31af7Sopenharmony_ci 298e5c31af7Sopenharmony_ci for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); caseNdx++) 299e5c31af7Sopenharmony_ci { 300e5c31af7Sopenharmony_ci const int texNdx = de::clamp(cases[caseNdx].texNdx, 0, (int)m_textures.size()-1); 301e5c31af7Sopenharmony_ci const float ref = cases[caseNdx].ref; 302e5c31af7Sopenharmony_ci const float lodX = cases[caseNdx].lodX; 303e5c31af7Sopenharmony_ci const float lodY = cases[caseNdx].lodY; 304e5c31af7Sopenharmony_ci const float oX = cases[caseNdx].oX; 305e5c31af7Sopenharmony_ci const float oY = cases[caseNdx].oY; 306e5c31af7Sopenharmony_ci const float sX = deFloatExp2(lodX)*viewportW / float(m_textures[texNdx]->getRefTexture().getWidth()); 307e5c31af7Sopenharmony_ci const float sY = deFloatExp2(lodY)*viewportH / float(m_textures[texNdx]->getRefTexture().getHeight()); 308e5c31af7Sopenharmony_ci 309e5c31af7Sopenharmony_ci m_cases.push_back(FilterCase(m_textures[texNdx], ref, tcu::Vec2(oX, oY), tcu::Vec2(oX+sX, oY+sY))); 310e5c31af7Sopenharmony_ci } 311e5c31af7Sopenharmony_ci } 312e5c31af7Sopenharmony_ci 313e5c31af7Sopenharmony_ci m_caseNdx = 0; 314e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 315e5c31af7Sopenharmony_ci} 316e5c31af7Sopenharmony_ci 317e5c31af7Sopenharmony_civoid Texture2DShadowCase::deinit (void) 318e5c31af7Sopenharmony_ci{ 319e5c31af7Sopenharmony_ci for (std::vector<glu::Texture2D*>::iterator i = m_textures.begin(); i != m_textures.end(); i++) 320e5c31af7Sopenharmony_ci delete *i; 321e5c31af7Sopenharmony_ci m_textures.clear(); 322e5c31af7Sopenharmony_ci 323e5c31af7Sopenharmony_ci m_renderer.clear(); 324e5c31af7Sopenharmony_ci m_cases.clear(); 325e5c31af7Sopenharmony_ci} 326e5c31af7Sopenharmony_ci 327e5c31af7Sopenharmony_ciTexture2DShadowCase::IterateResult Texture2DShadowCase::iterate (void) 328e5c31af7Sopenharmony_ci{ 329e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 330e5c31af7Sopenharmony_ci const RandomViewport viewport (m_context.getRenderTarget(), TEX2D_VIEWPORT_WIDTH, TEX2D_VIEWPORT_HEIGHT, deStringHash(getName()) ^ deInt32Hash(m_caseNdx)); 331e5c31af7Sopenharmony_ci const FilterCase& curCase = m_cases[m_caseNdx]; 332e5c31af7Sopenharmony_ci const tcu::ScopedLogSection section (m_testCtx.getLog(), string("Test") + de::toString(m_caseNdx), string("Test ") + de::toString(m_caseNdx)); 333e5c31af7Sopenharmony_ci ReferenceParams sampleParams (TEXTURETYPE_2D); 334e5c31af7Sopenharmony_ci tcu::Surface rendered (viewport.width, viewport.height); 335e5c31af7Sopenharmony_ci vector<float> texCoord; 336e5c31af7Sopenharmony_ci 337e5c31af7Sopenharmony_ci if (viewport.width < TEX2D_MIN_VIEWPORT_WIDTH || viewport.height < TEX2D_MIN_VIEWPORT_HEIGHT) 338e5c31af7Sopenharmony_ci throw tcu::NotSupportedError("Too small render target", "", __FILE__, __LINE__); 339e5c31af7Sopenharmony_ci 340e5c31af7Sopenharmony_ci // Setup params for reference. 341e5c31af7Sopenharmony_ci sampleParams.sampler = glu::mapGLSampler(m_wrapS, m_wrapT, m_minFilter, m_magFilter); 342e5c31af7Sopenharmony_ci sampleParams.sampler.compare = glu::mapGLCompareFunc(m_compareFunc); 343e5c31af7Sopenharmony_ci sampleParams.samplerType = SAMPLERTYPE_SHADOW; 344e5c31af7Sopenharmony_ci sampleParams.lodMode = LODMODE_EXACT; 345e5c31af7Sopenharmony_ci sampleParams.ref = curCase.ref; 346e5c31af7Sopenharmony_ci 347e5c31af7Sopenharmony_ci m_testCtx.getLog() << TestLog::Message << "Compare reference value = " << sampleParams.ref << TestLog::EndMessage; 348e5c31af7Sopenharmony_ci 349e5c31af7Sopenharmony_ci // Compute texture coordinates. 350e5c31af7Sopenharmony_ci m_testCtx.getLog() << TestLog::Message << "Texture coordinates: " << curCase.minCoord << " -> " << curCase.maxCoord << TestLog::EndMessage; 351e5c31af7Sopenharmony_ci computeQuadTexCoord2D(texCoord, curCase.minCoord, curCase.maxCoord); 352e5c31af7Sopenharmony_ci 353e5c31af7Sopenharmony_ci gl.bindTexture (GL_TEXTURE_2D, curCase.texture->getGLTexture()); 354e5c31af7Sopenharmony_ci gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_minFilter); 355e5c31af7Sopenharmony_ci gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, m_magFilter); 356e5c31af7Sopenharmony_ci gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_wrapS); 357e5c31af7Sopenharmony_ci gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_wrapT); 358e5c31af7Sopenharmony_ci gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); 359e5c31af7Sopenharmony_ci gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, m_compareFunc); 360e5c31af7Sopenharmony_ci 361e5c31af7Sopenharmony_ci gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height); 362e5c31af7Sopenharmony_ci m_renderer.renderQuad(0, &texCoord[0], sampleParams); 363e5c31af7Sopenharmony_ci glu::readPixels(m_context.getRenderContext(), viewport.x, viewport.y, rendered.getAccess()); 364e5c31af7Sopenharmony_ci 365e5c31af7Sopenharmony_ci { 366e5c31af7Sopenharmony_ci const tcu::PixelFormat pixelFormat = m_context.getRenderTarget().getPixelFormat(); 367e5c31af7Sopenharmony_ci tcu::LodPrecision lodPrecision; 368e5c31af7Sopenharmony_ci tcu::TexComparePrecision texComparePrecision; 369e5c31af7Sopenharmony_ci 370e5c31af7Sopenharmony_ci lodPrecision.derivateBits = 18; 371e5c31af7Sopenharmony_ci lodPrecision.lodBits = 6; 372e5c31af7Sopenharmony_ci texComparePrecision.coordBits = tcu::IVec3(20,20,0); 373e5c31af7Sopenharmony_ci texComparePrecision.uvwBits = tcu::IVec3(7,7,0); 374e5c31af7Sopenharmony_ci texComparePrecision.pcfBits = 5; 375e5c31af7Sopenharmony_ci texComparePrecision.referenceBits = 16; 376e5c31af7Sopenharmony_ci texComparePrecision.resultBits = pixelFormat.redBits-1; 377e5c31af7Sopenharmony_ci 378e5c31af7Sopenharmony_ci const bool isHighQuality = verifyTexCompareResult(m_testCtx, rendered.getAccess(), curCase.texture->getRefTexture(), 379e5c31af7Sopenharmony_ci &texCoord[0], sampleParams, texComparePrecision, lodPrecision, pixelFormat); 380e5c31af7Sopenharmony_ci 381e5c31af7Sopenharmony_ci if (!isHighQuality) 382e5c31af7Sopenharmony_ci { 383e5c31af7Sopenharmony_ci m_testCtx.getLog() << TestLog::Message << "Warning: Verification assuming high-quality PCF filtering failed." << TestLog::EndMessage; 384e5c31af7Sopenharmony_ci 385e5c31af7Sopenharmony_ci lodPrecision.lodBits = 4; 386e5c31af7Sopenharmony_ci texComparePrecision.uvwBits = tcu::IVec3(4,4,0); 387e5c31af7Sopenharmony_ci texComparePrecision.pcfBits = 0; 388e5c31af7Sopenharmony_ci 389e5c31af7Sopenharmony_ci const bool isOk = verifyTexCompareResult(m_testCtx, rendered.getAccess(), curCase.texture->getRefTexture(), 390e5c31af7Sopenharmony_ci &texCoord[0], sampleParams, texComparePrecision, lodPrecision, pixelFormat); 391e5c31af7Sopenharmony_ci 392e5c31af7Sopenharmony_ci if (!isOk) 393e5c31af7Sopenharmony_ci { 394e5c31af7Sopenharmony_ci m_testCtx.getLog() << TestLog::Message << "ERROR: Verification against low precision requirements failed, failing test case." << TestLog::EndMessage; 395e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed"); 396e5c31af7Sopenharmony_ci } 397e5c31af7Sopenharmony_ci else if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS) 398e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_QUALITY_WARNING, "Low-quality result"); 399e5c31af7Sopenharmony_ci } 400e5c31af7Sopenharmony_ci } 401e5c31af7Sopenharmony_ci 402e5c31af7Sopenharmony_ci m_caseNdx += 1; 403e5c31af7Sopenharmony_ci return m_caseNdx < (int)m_cases.size() ? CONTINUE : STOP; 404e5c31af7Sopenharmony_ci} 405e5c31af7Sopenharmony_ci 406e5c31af7Sopenharmony_ciclass TextureCubeShadowCase : public TestCase 407e5c31af7Sopenharmony_ci{ 408e5c31af7Sopenharmony_cipublic: 409e5c31af7Sopenharmony_ci TextureCubeShadowCase (Context& context, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, deUint32 format, int size, deUint32 compareFunc); 410e5c31af7Sopenharmony_ci ~TextureCubeShadowCase (void); 411e5c31af7Sopenharmony_ci 412e5c31af7Sopenharmony_ci void init (void); 413e5c31af7Sopenharmony_ci void deinit (void); 414e5c31af7Sopenharmony_ci IterateResult iterate (void); 415e5c31af7Sopenharmony_ci 416e5c31af7Sopenharmony_ciprivate: 417e5c31af7Sopenharmony_ci TextureCubeShadowCase (const TextureCubeShadowCase& other); 418e5c31af7Sopenharmony_ci TextureCubeShadowCase& operator= (const TextureCubeShadowCase& other); 419e5c31af7Sopenharmony_ci 420e5c31af7Sopenharmony_ci const deUint32 m_minFilter; 421e5c31af7Sopenharmony_ci const deUint32 m_magFilter; 422e5c31af7Sopenharmony_ci const deUint32 m_wrapS; 423e5c31af7Sopenharmony_ci const deUint32 m_wrapT; 424e5c31af7Sopenharmony_ci 425e5c31af7Sopenharmony_ci const deUint32 m_format; 426e5c31af7Sopenharmony_ci const int m_size; 427e5c31af7Sopenharmony_ci 428e5c31af7Sopenharmony_ci const deUint32 m_compareFunc; 429e5c31af7Sopenharmony_ci 430e5c31af7Sopenharmony_ci struct FilterCase 431e5c31af7Sopenharmony_ci { 432e5c31af7Sopenharmony_ci const glu::TextureCube* texture; 433e5c31af7Sopenharmony_ci tcu::Vec2 bottomLeft; 434e5c31af7Sopenharmony_ci tcu::Vec2 topRight; 435e5c31af7Sopenharmony_ci float ref; 436e5c31af7Sopenharmony_ci 437e5c31af7Sopenharmony_ci FilterCase (void) 438e5c31af7Sopenharmony_ci : texture (DE_NULL) 439e5c31af7Sopenharmony_ci , ref (0.0f) 440e5c31af7Sopenharmony_ci { 441e5c31af7Sopenharmony_ci } 442e5c31af7Sopenharmony_ci 443e5c31af7Sopenharmony_ci FilterCase (const glu::TextureCube* tex_, const float ref_, const tcu::Vec2& bottomLeft_, const tcu::Vec2& topRight_) 444e5c31af7Sopenharmony_ci : texture (tex_) 445e5c31af7Sopenharmony_ci , bottomLeft(bottomLeft_) 446e5c31af7Sopenharmony_ci , topRight (topRight_) 447e5c31af7Sopenharmony_ci , ref (ref_) 448e5c31af7Sopenharmony_ci { 449e5c31af7Sopenharmony_ci } 450e5c31af7Sopenharmony_ci }; 451e5c31af7Sopenharmony_ci 452e5c31af7Sopenharmony_ci glu::TextureCube* m_gradientTex; 453e5c31af7Sopenharmony_ci glu::TextureCube* m_gridTex; 454e5c31af7Sopenharmony_ci std::vector<FilterCase> m_cases; 455e5c31af7Sopenharmony_ci 456e5c31af7Sopenharmony_ci TextureRenderer m_renderer; 457e5c31af7Sopenharmony_ci 458e5c31af7Sopenharmony_ci int m_caseNdx; 459e5c31af7Sopenharmony_ci}; 460e5c31af7Sopenharmony_ci 461e5c31af7Sopenharmony_ciTextureCubeShadowCase::TextureCubeShadowCase (Context& context, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, deUint32 format, int size, deUint32 compareFunc) 462e5c31af7Sopenharmony_ci : TestCase (context, name, desc) 463e5c31af7Sopenharmony_ci , m_minFilter (minFilter) 464e5c31af7Sopenharmony_ci , m_magFilter (magFilter) 465e5c31af7Sopenharmony_ci , m_wrapS (wrapS) 466e5c31af7Sopenharmony_ci , m_wrapT (wrapT) 467e5c31af7Sopenharmony_ci , m_format (format) 468e5c31af7Sopenharmony_ci , m_size (size) 469e5c31af7Sopenharmony_ci , m_compareFunc (compareFunc) 470e5c31af7Sopenharmony_ci , m_gradientTex (DE_NULL) 471e5c31af7Sopenharmony_ci , m_gridTex (DE_NULL) 472e5c31af7Sopenharmony_ci , m_renderer (context.getRenderContext(), context.getTestContext().getLog(), glu::GLSL_VERSION_300_ES, glu::PRECISION_HIGHP) 473e5c31af7Sopenharmony_ci , m_caseNdx (0) 474e5c31af7Sopenharmony_ci{ 475e5c31af7Sopenharmony_ci} 476e5c31af7Sopenharmony_ci 477e5c31af7Sopenharmony_ciTextureCubeShadowCase::~TextureCubeShadowCase (void) 478e5c31af7Sopenharmony_ci{ 479e5c31af7Sopenharmony_ci TextureCubeShadowCase::deinit(); 480e5c31af7Sopenharmony_ci} 481e5c31af7Sopenharmony_ci 482e5c31af7Sopenharmony_civoid TextureCubeShadowCase::init (void) 483e5c31af7Sopenharmony_ci{ 484e5c31af7Sopenharmony_ci try 485e5c31af7Sopenharmony_ci { 486e5c31af7Sopenharmony_ci DE_ASSERT(!m_gradientTex && !m_gridTex); 487e5c31af7Sopenharmony_ci 488e5c31af7Sopenharmony_ci int numLevels = deLog2Floor32(m_size)+1; 489e5c31af7Sopenharmony_ci tcu::TextureFormat texFmt = glu::mapGLInternalFormat(m_format); 490e5c31af7Sopenharmony_ci tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt); 491e5c31af7Sopenharmony_ci tcu::Vec4 cBias = fmtInfo.valueMin; 492e5c31af7Sopenharmony_ci tcu::Vec4 cScale = fmtInfo.valueMax-fmtInfo.valueMin; 493e5c31af7Sopenharmony_ci 494e5c31af7Sopenharmony_ci // Create textures. 495e5c31af7Sopenharmony_ci m_gradientTex = new glu::TextureCube(m_context.getRenderContext(), m_format, m_size); 496e5c31af7Sopenharmony_ci m_gridTex = new glu::TextureCube(m_context.getRenderContext(), m_format, m_size); 497e5c31af7Sopenharmony_ci 498e5c31af7Sopenharmony_ci // Fill first with gradient texture. 499e5c31af7Sopenharmony_ci static const tcu::Vec4 gradients[tcu::CUBEFACE_LAST][2] = 500e5c31af7Sopenharmony_ci { 501e5c31af7Sopenharmony_ci { tcu::Vec4(-1.0f, -1.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative x 502e5c31af7Sopenharmony_ci { tcu::Vec4( 0.0f, -1.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive x 503e5c31af7Sopenharmony_ci { tcu::Vec4(-1.0f, 0.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative y 504e5c31af7Sopenharmony_ci { tcu::Vec4(-1.0f, -1.0f, 0.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive y 505e5c31af7Sopenharmony_ci { tcu::Vec4(-1.0f, -1.0f, -1.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f) }, // negative z 506e5c31af7Sopenharmony_ci { tcu::Vec4( 0.0f, 0.0f, 0.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) } // positive z 507e5c31af7Sopenharmony_ci }; 508e5c31af7Sopenharmony_ci for (int face = 0; face < tcu::CUBEFACE_LAST; face++) 509e5c31af7Sopenharmony_ci { 510e5c31af7Sopenharmony_ci for (int levelNdx = 0; levelNdx < numLevels; levelNdx++) 511e5c31af7Sopenharmony_ci { 512e5c31af7Sopenharmony_ci m_gradientTex->getRefTexture().allocLevel((tcu::CubeFace)face, levelNdx); 513e5c31af7Sopenharmony_ci tcu::fillWithComponentGradients(m_gradientTex->getRefTexture().getLevelFace(levelNdx, (tcu::CubeFace)face), gradients[face][0]*cScale + cBias, gradients[face][1]*cScale + cBias); 514e5c31af7Sopenharmony_ci } 515e5c31af7Sopenharmony_ci } 516e5c31af7Sopenharmony_ci 517e5c31af7Sopenharmony_ci // Fill second with grid texture. 518e5c31af7Sopenharmony_ci for (int face = 0; face < tcu::CUBEFACE_LAST; face++) 519e5c31af7Sopenharmony_ci { 520e5c31af7Sopenharmony_ci for (int levelNdx = 0; levelNdx < numLevels; levelNdx++) 521e5c31af7Sopenharmony_ci { 522e5c31af7Sopenharmony_ci deUint32 step = 0x00ffffff / (numLevels*tcu::CUBEFACE_LAST); 523e5c31af7Sopenharmony_ci deUint32 rgb = step*levelNdx*face; 524e5c31af7Sopenharmony_ci deUint32 colorA = 0xff000000 | rgb; 525e5c31af7Sopenharmony_ci deUint32 colorB = 0xff000000 | ~rgb; 526e5c31af7Sopenharmony_ci 527e5c31af7Sopenharmony_ci m_gridTex->getRefTexture().allocLevel((tcu::CubeFace)face, levelNdx); 528e5c31af7Sopenharmony_ci tcu::fillWithGrid(m_gridTex->getRefTexture().getLevelFace(levelNdx, (tcu::CubeFace)face), 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias); 529e5c31af7Sopenharmony_ci } 530e5c31af7Sopenharmony_ci } 531e5c31af7Sopenharmony_ci 532e5c31af7Sopenharmony_ci // Upload. 533e5c31af7Sopenharmony_ci m_gradientTex->upload(); 534e5c31af7Sopenharmony_ci m_gridTex->upload(); 535e5c31af7Sopenharmony_ci } 536e5c31af7Sopenharmony_ci catch (const std::exception&) 537e5c31af7Sopenharmony_ci { 538e5c31af7Sopenharmony_ci // Clean up to save memory. 539e5c31af7Sopenharmony_ci TextureCubeShadowCase::deinit(); 540e5c31af7Sopenharmony_ci throw; 541e5c31af7Sopenharmony_ci } 542e5c31af7Sopenharmony_ci 543e5c31af7Sopenharmony_ci // Compute cases 544e5c31af7Sopenharmony_ci { 545e5c31af7Sopenharmony_ci const float refInRangeUpper = (m_compareFunc == GL_EQUAL || m_compareFunc == GL_NOTEQUAL) ? 1.0f : 0.5f; 546e5c31af7Sopenharmony_ci const float refInRangeLower = (m_compareFunc == GL_EQUAL || m_compareFunc == GL_NOTEQUAL) ? 0.0f : 0.5f; 547e5c31af7Sopenharmony_ci const float refOutOfBoundsUpper = 1.1f; 548e5c31af7Sopenharmony_ci const float refOutOfBoundsLower = -0.1f; 549e5c31af7Sopenharmony_ci const bool singleSample = m_context.getRenderTarget().getNumSamples() == 0; 550e5c31af7Sopenharmony_ci 551e5c31af7Sopenharmony_ci if (singleSample) 552e5c31af7Sopenharmony_ci m_cases.push_back(FilterCase(m_gradientTex, refInRangeUpper, tcu::Vec2(-1.25f, -1.2f), tcu::Vec2(1.2f, 1.25f))); // minification 553e5c31af7Sopenharmony_ci else 554e5c31af7Sopenharmony_ci m_cases.push_back(FilterCase(m_gradientTex, refInRangeUpper, tcu::Vec2(-1.19f, -1.3f), tcu::Vec2(1.1f, 1.35f))); // minification - w/ tuned coordinates to avoid hitting triangle edges 555e5c31af7Sopenharmony_ci 556e5c31af7Sopenharmony_ci m_cases.push_back(FilterCase(m_gradientTex, refInRangeLower, tcu::Vec2(0.8f, 0.8f), tcu::Vec2(1.25f, 1.20f))); // magnification 557e5c31af7Sopenharmony_ci m_cases.push_back(FilterCase(m_gridTex, refInRangeUpper, tcu::Vec2(-1.19f, -1.3f), tcu::Vec2(1.1f, 1.35f))); // minification 558e5c31af7Sopenharmony_ci m_cases.push_back(FilterCase(m_gridTex, refInRangeLower, tcu::Vec2(-1.2f, -1.1f), tcu::Vec2(-0.8f, -0.8f))); // magnification 559e5c31af7Sopenharmony_ci m_cases.push_back(FilterCase(m_gridTex, refOutOfBoundsUpper, tcu::Vec2(-0.61f, -0.1f), tcu::Vec2(0.9f, 1.18f))); // reference value clamp, upper 560e5c31af7Sopenharmony_ci 561e5c31af7Sopenharmony_ci if (singleSample) 562e5c31af7Sopenharmony_ci m_cases.push_back(FilterCase(m_gridTex, refOutOfBoundsLower, tcu::Vec2(-0.75f, 1.0f), tcu::Vec2(0.05f, 0.75f))); // reference value clamp, lower 563e5c31af7Sopenharmony_ci else 564e5c31af7Sopenharmony_ci m_cases.push_back(FilterCase(m_gridTex, refOutOfBoundsLower, tcu::Vec2(-0.75f, 1.0f), tcu::Vec2(0.25f, 0.75f))); // reference value clamp, lower 565e5c31af7Sopenharmony_ci } 566e5c31af7Sopenharmony_ci 567e5c31af7Sopenharmony_ci m_caseNdx = 0; 568e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 569e5c31af7Sopenharmony_ci} 570e5c31af7Sopenharmony_ci 571e5c31af7Sopenharmony_civoid TextureCubeShadowCase::deinit (void) 572e5c31af7Sopenharmony_ci{ 573e5c31af7Sopenharmony_ci delete m_gradientTex; 574e5c31af7Sopenharmony_ci delete m_gridTex; 575e5c31af7Sopenharmony_ci 576e5c31af7Sopenharmony_ci m_gradientTex = DE_NULL; 577e5c31af7Sopenharmony_ci m_gridTex = DE_NULL; 578e5c31af7Sopenharmony_ci 579e5c31af7Sopenharmony_ci m_renderer.clear(); 580e5c31af7Sopenharmony_ci m_cases.clear(); 581e5c31af7Sopenharmony_ci} 582e5c31af7Sopenharmony_ci 583e5c31af7Sopenharmony_cistatic const char* getFaceDesc (const tcu::CubeFace face) 584e5c31af7Sopenharmony_ci{ 585e5c31af7Sopenharmony_ci switch (face) 586e5c31af7Sopenharmony_ci { 587e5c31af7Sopenharmony_ci case tcu::CUBEFACE_NEGATIVE_X: return "-X"; 588e5c31af7Sopenharmony_ci case tcu::CUBEFACE_POSITIVE_X: return "+X"; 589e5c31af7Sopenharmony_ci case tcu::CUBEFACE_NEGATIVE_Y: return "-Y"; 590e5c31af7Sopenharmony_ci case tcu::CUBEFACE_POSITIVE_Y: return "+Y"; 591e5c31af7Sopenharmony_ci case tcu::CUBEFACE_NEGATIVE_Z: return "-Z"; 592e5c31af7Sopenharmony_ci case tcu::CUBEFACE_POSITIVE_Z: return "+Z"; 593e5c31af7Sopenharmony_ci default: 594e5c31af7Sopenharmony_ci DE_ASSERT(false); 595e5c31af7Sopenharmony_ci return DE_NULL; 596e5c31af7Sopenharmony_ci } 597e5c31af7Sopenharmony_ci} 598e5c31af7Sopenharmony_ci 599e5c31af7Sopenharmony_ciTextureCubeShadowCase::IterateResult TextureCubeShadowCase::iterate (void) 600e5c31af7Sopenharmony_ci{ 601e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 602e5c31af7Sopenharmony_ci const int viewportSize = 28; 603e5c31af7Sopenharmony_ci const RandomViewport viewport (m_context.getRenderTarget(), viewportSize, viewportSize, deStringHash(getName()) ^ deInt32Hash(m_caseNdx)); 604e5c31af7Sopenharmony_ci const tcu::ScopedLogSection iterSection (m_testCtx.getLog(), string("Test") + de::toString(m_caseNdx), string("Test ") + de::toString(m_caseNdx)); 605e5c31af7Sopenharmony_ci const FilterCase& curCase = m_cases[m_caseNdx]; 606e5c31af7Sopenharmony_ci ReferenceParams sampleParams (TEXTURETYPE_CUBE); 607e5c31af7Sopenharmony_ci 608e5c31af7Sopenharmony_ci if (viewport.width < viewportSize || viewport.height < viewportSize) 609e5c31af7Sopenharmony_ci throw tcu::NotSupportedError("Too small render target", DE_NULL, __FILE__, __LINE__); 610e5c31af7Sopenharmony_ci 611e5c31af7Sopenharmony_ci // Setup texture 612e5c31af7Sopenharmony_ci gl.bindTexture (GL_TEXTURE_CUBE_MAP, curCase.texture->getGLTexture()); 613e5c31af7Sopenharmony_ci gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, m_minFilter); 614e5c31af7Sopenharmony_ci gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, m_magFilter); 615e5c31af7Sopenharmony_ci gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, m_wrapS); 616e5c31af7Sopenharmony_ci gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, m_wrapT); 617e5c31af7Sopenharmony_ci gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); 618e5c31af7Sopenharmony_ci gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_FUNC, m_compareFunc); 619e5c31af7Sopenharmony_ci 620e5c31af7Sopenharmony_ci // Other state 621e5c31af7Sopenharmony_ci gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height); 622e5c31af7Sopenharmony_ci 623e5c31af7Sopenharmony_ci // Params for reference computation. 624e5c31af7Sopenharmony_ci sampleParams.sampler = glu::mapGLSampler(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, m_minFilter, m_magFilter); 625e5c31af7Sopenharmony_ci sampleParams.sampler.seamlessCubeMap = true; 626e5c31af7Sopenharmony_ci sampleParams.sampler.compare = glu::mapGLCompareFunc(m_compareFunc); 627e5c31af7Sopenharmony_ci sampleParams.samplerType = SAMPLERTYPE_SHADOW; 628e5c31af7Sopenharmony_ci sampleParams.lodMode = LODMODE_EXACT; 629e5c31af7Sopenharmony_ci sampleParams.ref = curCase.ref; 630e5c31af7Sopenharmony_ci 631e5c31af7Sopenharmony_ci m_testCtx.getLog() 632e5c31af7Sopenharmony_ci << TestLog::Message 633e5c31af7Sopenharmony_ci << "Compare reference value = " << sampleParams.ref << "\n" 634e5c31af7Sopenharmony_ci << "Coordinates: " << curCase.bottomLeft << " -> " << curCase.topRight 635e5c31af7Sopenharmony_ci << TestLog::EndMessage; 636e5c31af7Sopenharmony_ci 637e5c31af7Sopenharmony_ci for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++) 638e5c31af7Sopenharmony_ci { 639e5c31af7Sopenharmony_ci const tcu::CubeFace face = tcu::CubeFace(faceNdx); 640e5c31af7Sopenharmony_ci tcu::Surface result (viewport.width, viewport.height); 641e5c31af7Sopenharmony_ci vector<float> texCoord; 642e5c31af7Sopenharmony_ci 643e5c31af7Sopenharmony_ci computeQuadTexCoordCube(texCoord, face, curCase.bottomLeft, curCase.topRight); 644e5c31af7Sopenharmony_ci 645e5c31af7Sopenharmony_ci m_testCtx.getLog() << TestLog::Message << "Face " << getFaceDesc(face) << TestLog::EndMessage; 646e5c31af7Sopenharmony_ci 647e5c31af7Sopenharmony_ci // \todo Log texture coordinates. 648e5c31af7Sopenharmony_ci 649e5c31af7Sopenharmony_ci m_renderer.renderQuad(0, &texCoord[0], sampleParams); 650e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "Draw"); 651e5c31af7Sopenharmony_ci 652e5c31af7Sopenharmony_ci glu::readPixels(m_context.getRenderContext(), viewport.x, viewport.y, result.getAccess()); 653e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "Read pixels"); 654e5c31af7Sopenharmony_ci 655e5c31af7Sopenharmony_ci { 656e5c31af7Sopenharmony_ci const tcu::PixelFormat pixelFormat = m_context.getRenderTarget().getPixelFormat(); 657e5c31af7Sopenharmony_ci tcu::LodPrecision lodPrecision; 658e5c31af7Sopenharmony_ci tcu::TexComparePrecision texComparePrecision; 659e5c31af7Sopenharmony_ci 660e5c31af7Sopenharmony_ci lodPrecision.derivateBits = 10; 661e5c31af7Sopenharmony_ci lodPrecision.lodBits = 5; 662e5c31af7Sopenharmony_ci texComparePrecision.coordBits = tcu::IVec3(10,10,10); 663e5c31af7Sopenharmony_ci texComparePrecision.uvwBits = tcu::IVec3(6,6,0); 664e5c31af7Sopenharmony_ci texComparePrecision.pcfBits = 5; 665e5c31af7Sopenharmony_ci texComparePrecision.referenceBits = 16; 666e5c31af7Sopenharmony_ci texComparePrecision.resultBits = pixelFormat.redBits-1; 667e5c31af7Sopenharmony_ci 668e5c31af7Sopenharmony_ci const bool isHighQuality = verifyTexCompareResult(m_testCtx, result.getAccess(), curCase.texture->getRefTexture(), 669e5c31af7Sopenharmony_ci &texCoord[0], sampleParams, texComparePrecision, lodPrecision, pixelFormat); 670e5c31af7Sopenharmony_ci 671e5c31af7Sopenharmony_ci if (!isHighQuality) 672e5c31af7Sopenharmony_ci { 673e5c31af7Sopenharmony_ci m_testCtx.getLog() << TestLog::Message << "Warning: Verification assuming high-quality PCF filtering failed." << TestLog::EndMessage; 674e5c31af7Sopenharmony_ci 675e5c31af7Sopenharmony_ci lodPrecision.lodBits = 4; 676e5c31af7Sopenharmony_ci texComparePrecision.uvwBits = tcu::IVec3(4,4,0); 677e5c31af7Sopenharmony_ci texComparePrecision.pcfBits = 0; 678e5c31af7Sopenharmony_ci 679e5c31af7Sopenharmony_ci const bool isOk = verifyTexCompareResult(m_testCtx, result.getAccess(), curCase.texture->getRefTexture(), 680e5c31af7Sopenharmony_ci &texCoord[0], sampleParams, texComparePrecision, lodPrecision, pixelFormat); 681e5c31af7Sopenharmony_ci 682e5c31af7Sopenharmony_ci if (!isOk) 683e5c31af7Sopenharmony_ci { 684e5c31af7Sopenharmony_ci m_testCtx.getLog() << TestLog::Message << "ERROR: Verification against low precision requirements failed, failing test case." << TestLog::EndMessage; 685e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed"); 686e5c31af7Sopenharmony_ci } 687e5c31af7Sopenharmony_ci else if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS) 688e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_QUALITY_WARNING, "Low-quality result"); 689e5c31af7Sopenharmony_ci } 690e5c31af7Sopenharmony_ci } 691e5c31af7Sopenharmony_ci } 692e5c31af7Sopenharmony_ci 693e5c31af7Sopenharmony_ci m_caseNdx += 1; 694e5c31af7Sopenharmony_ci return m_caseNdx < (int)m_cases.size() ? CONTINUE : STOP; 695e5c31af7Sopenharmony_ci} 696e5c31af7Sopenharmony_ci 697e5c31af7Sopenharmony_ciclass Texture2DArrayShadowCase : public TestCase 698e5c31af7Sopenharmony_ci{ 699e5c31af7Sopenharmony_cipublic: 700e5c31af7Sopenharmony_ci Texture2DArrayShadowCase (Context& context, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, deUint32 format, int width, int height, int numLayers, deUint32 compareFunc); 701e5c31af7Sopenharmony_ci ~Texture2DArrayShadowCase (void); 702e5c31af7Sopenharmony_ci 703e5c31af7Sopenharmony_ci void init (void); 704e5c31af7Sopenharmony_ci void deinit (void); 705e5c31af7Sopenharmony_ci IterateResult iterate (void); 706e5c31af7Sopenharmony_ci 707e5c31af7Sopenharmony_ciprivate: 708e5c31af7Sopenharmony_ci Texture2DArrayShadowCase (const Texture2DArrayShadowCase& other); 709e5c31af7Sopenharmony_ci Texture2DArrayShadowCase& operator= (const Texture2DArrayShadowCase& other); 710e5c31af7Sopenharmony_ci 711e5c31af7Sopenharmony_ci const deUint32 m_minFilter; 712e5c31af7Sopenharmony_ci const deUint32 m_magFilter; 713e5c31af7Sopenharmony_ci const deUint32 m_wrapS; 714e5c31af7Sopenharmony_ci const deUint32 m_wrapT; 715e5c31af7Sopenharmony_ci 716e5c31af7Sopenharmony_ci const deUint32 m_format; 717e5c31af7Sopenharmony_ci const int m_width; 718e5c31af7Sopenharmony_ci const int m_height; 719e5c31af7Sopenharmony_ci const int m_numLayers; 720e5c31af7Sopenharmony_ci 721e5c31af7Sopenharmony_ci const deUint32 m_compareFunc; 722e5c31af7Sopenharmony_ci 723e5c31af7Sopenharmony_ci struct FilterCase 724e5c31af7Sopenharmony_ci { 725e5c31af7Sopenharmony_ci const glu::Texture2DArray* texture; 726e5c31af7Sopenharmony_ci tcu::Vec3 minCoord; 727e5c31af7Sopenharmony_ci tcu::Vec3 maxCoord; 728e5c31af7Sopenharmony_ci float ref; 729e5c31af7Sopenharmony_ci 730e5c31af7Sopenharmony_ci FilterCase (void) 731e5c31af7Sopenharmony_ci : texture (DE_NULL) 732e5c31af7Sopenharmony_ci , ref (0.0f) 733e5c31af7Sopenharmony_ci { 734e5c31af7Sopenharmony_ci } 735e5c31af7Sopenharmony_ci 736e5c31af7Sopenharmony_ci FilterCase (const glu::Texture2DArray* tex_, float ref_, const tcu::Vec3& minCoord_, const tcu::Vec3& maxCoord_) 737e5c31af7Sopenharmony_ci : texture (tex_) 738e5c31af7Sopenharmony_ci , minCoord (minCoord_) 739e5c31af7Sopenharmony_ci , maxCoord (maxCoord_) 740e5c31af7Sopenharmony_ci , ref (ref_) 741e5c31af7Sopenharmony_ci { 742e5c31af7Sopenharmony_ci } 743e5c31af7Sopenharmony_ci }; 744e5c31af7Sopenharmony_ci 745e5c31af7Sopenharmony_ci glu::Texture2DArray* m_gradientTex; 746e5c31af7Sopenharmony_ci glu::Texture2DArray* m_gridTex; 747e5c31af7Sopenharmony_ci std::vector<FilterCase> m_cases; 748e5c31af7Sopenharmony_ci 749e5c31af7Sopenharmony_ci TextureRenderer m_renderer; 750e5c31af7Sopenharmony_ci 751e5c31af7Sopenharmony_ci int m_caseNdx; 752e5c31af7Sopenharmony_ci}; 753e5c31af7Sopenharmony_ci 754e5c31af7Sopenharmony_ciTexture2DArrayShadowCase::Texture2DArrayShadowCase (Context& context, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, deUint32 format, int width, int height, int numLayers, deUint32 compareFunc) 755e5c31af7Sopenharmony_ci : TestCase (context, name, desc) 756e5c31af7Sopenharmony_ci , m_minFilter (minFilter) 757e5c31af7Sopenharmony_ci , m_magFilter (magFilter) 758e5c31af7Sopenharmony_ci , m_wrapS (wrapS) 759e5c31af7Sopenharmony_ci , m_wrapT (wrapT) 760e5c31af7Sopenharmony_ci , m_format (format) 761e5c31af7Sopenharmony_ci , m_width (width) 762e5c31af7Sopenharmony_ci , m_height (height) 763e5c31af7Sopenharmony_ci , m_numLayers (numLayers) 764e5c31af7Sopenharmony_ci , m_compareFunc (compareFunc) 765e5c31af7Sopenharmony_ci , m_gradientTex (DE_NULL) 766e5c31af7Sopenharmony_ci , m_gridTex (DE_NULL) 767e5c31af7Sopenharmony_ci , m_renderer (context.getRenderContext(), context.getTestContext().getLog(), glu::GLSL_VERSION_300_ES, glu::PRECISION_HIGHP) 768e5c31af7Sopenharmony_ci , m_caseNdx (0) 769e5c31af7Sopenharmony_ci{ 770e5c31af7Sopenharmony_ci} 771e5c31af7Sopenharmony_ci 772e5c31af7Sopenharmony_ciTexture2DArrayShadowCase::~Texture2DArrayShadowCase (void) 773e5c31af7Sopenharmony_ci{ 774e5c31af7Sopenharmony_ci Texture2DArrayShadowCase::deinit(); 775e5c31af7Sopenharmony_ci} 776e5c31af7Sopenharmony_ci 777e5c31af7Sopenharmony_civoid Texture2DArrayShadowCase::init (void) 778e5c31af7Sopenharmony_ci{ 779e5c31af7Sopenharmony_ci try 780e5c31af7Sopenharmony_ci { 781e5c31af7Sopenharmony_ci tcu::TextureFormat texFmt = glu::mapGLInternalFormat(m_format); 782e5c31af7Sopenharmony_ci tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt); 783e5c31af7Sopenharmony_ci tcu::Vec4 cScale = fmtInfo.valueMax-fmtInfo.valueMin; 784e5c31af7Sopenharmony_ci tcu::Vec4 cBias = fmtInfo.valueMin; 785e5c31af7Sopenharmony_ci int numLevels = deLog2Floor32(de::max(m_width, m_height)) + 1; 786e5c31af7Sopenharmony_ci 787e5c31af7Sopenharmony_ci // Create textures. 788e5c31af7Sopenharmony_ci m_gradientTex = new glu::Texture2DArray(m_context.getRenderContext(), m_format, m_width, m_height, m_numLayers); 789e5c31af7Sopenharmony_ci m_gridTex = new glu::Texture2DArray(m_context.getRenderContext(), m_format, m_width, m_height, m_numLayers); 790e5c31af7Sopenharmony_ci 791e5c31af7Sopenharmony_ci // Fill first gradient texture. 792e5c31af7Sopenharmony_ci for (int levelNdx = 0; levelNdx < numLevels; levelNdx++) 793e5c31af7Sopenharmony_ci { 794e5c31af7Sopenharmony_ci tcu::Vec4 gMin = tcu::Vec4(-0.5f, -0.5f, -0.5f, 2.0f)*cScale + cBias; 795e5c31af7Sopenharmony_ci tcu::Vec4 gMax = tcu::Vec4( 1.0f, 1.0f, 1.0f, 0.0f)*cScale + cBias; 796e5c31af7Sopenharmony_ci 797e5c31af7Sopenharmony_ci m_gradientTex->getRefTexture().allocLevel(levelNdx); 798e5c31af7Sopenharmony_ci tcu::fillWithComponentGradients(m_gradientTex->getRefTexture().getLevel(levelNdx), gMin, gMax); 799e5c31af7Sopenharmony_ci } 800e5c31af7Sopenharmony_ci 801e5c31af7Sopenharmony_ci // Fill second with grid texture. 802e5c31af7Sopenharmony_ci for (int levelNdx = 0; levelNdx < numLevels; levelNdx++) 803e5c31af7Sopenharmony_ci { 804e5c31af7Sopenharmony_ci deUint32 step = 0x00ffffff / numLevels; 805e5c31af7Sopenharmony_ci deUint32 rgb = step*levelNdx; 806e5c31af7Sopenharmony_ci deUint32 colorA = 0xff000000 | rgb; 807e5c31af7Sopenharmony_ci deUint32 colorB = 0xff000000 | ~rgb; 808e5c31af7Sopenharmony_ci 809e5c31af7Sopenharmony_ci m_gridTex->getRefTexture().allocLevel(levelNdx); 810e5c31af7Sopenharmony_ci tcu::fillWithGrid(m_gridTex->getRefTexture().getLevel(levelNdx), 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias); 811e5c31af7Sopenharmony_ci } 812e5c31af7Sopenharmony_ci 813e5c31af7Sopenharmony_ci // Upload. 814e5c31af7Sopenharmony_ci m_gradientTex->upload(); 815e5c31af7Sopenharmony_ci m_gridTex->upload(); 816e5c31af7Sopenharmony_ci } 817e5c31af7Sopenharmony_ci catch (...) 818e5c31af7Sopenharmony_ci { 819e5c31af7Sopenharmony_ci // Clean up to save memory. 820e5c31af7Sopenharmony_ci Texture2DArrayShadowCase::deinit(); 821e5c31af7Sopenharmony_ci throw; 822e5c31af7Sopenharmony_ci } 823e5c31af7Sopenharmony_ci 824e5c31af7Sopenharmony_ci // Compute cases. 825e5c31af7Sopenharmony_ci { 826e5c31af7Sopenharmony_ci const float refInRangeUpper = (m_compareFunc == GL_EQUAL || m_compareFunc == GL_NOTEQUAL) ? 1.0f : 0.5f; 827e5c31af7Sopenharmony_ci const float refInRangeLower = (m_compareFunc == GL_EQUAL || m_compareFunc == GL_NOTEQUAL) ? 0.0f : 0.5f; 828e5c31af7Sopenharmony_ci const float refOutOfBoundsUpper = 1.1f; // !< lookup function should clamp values to [0, 1] range 829e5c31af7Sopenharmony_ci const float refOutOfBoundsLower = -0.1f; 830e5c31af7Sopenharmony_ci 831e5c31af7Sopenharmony_ci const struct 832e5c31af7Sopenharmony_ci { 833e5c31af7Sopenharmony_ci int texNdx; 834e5c31af7Sopenharmony_ci float ref; 835e5c31af7Sopenharmony_ci float lodX; 836e5c31af7Sopenharmony_ci float lodY; 837e5c31af7Sopenharmony_ci float oX; 838e5c31af7Sopenharmony_ci float oY; 839e5c31af7Sopenharmony_ci } cases[] = 840e5c31af7Sopenharmony_ci { 841e5c31af7Sopenharmony_ci { 0, refInRangeUpper, 1.6f, 2.9f, -1.0f, -2.7f }, 842e5c31af7Sopenharmony_ci { 0, refInRangeLower, -2.0f, -1.35f, -0.2f, 0.7f }, 843e5c31af7Sopenharmony_ci { 1, refInRangeUpper, 0.14f, 0.275f, -1.5f, -1.1f }, 844e5c31af7Sopenharmony_ci { 1, refInRangeLower, -0.92f, -2.64f, 0.4f, -0.1f }, 845e5c31af7Sopenharmony_ci { 1, refOutOfBoundsUpper, -0.49f, -0.22f, 0.45f, 0.97f }, 846e5c31af7Sopenharmony_ci { 1, refOutOfBoundsLower, -0.85f, 0.75f, 0.25f, 0.61f }, 847e5c31af7Sopenharmony_ci }; 848e5c31af7Sopenharmony_ci 849e5c31af7Sopenharmony_ci const float viewportW = (float)de::min<int>(TEX2D_VIEWPORT_WIDTH, m_context.getRenderTarget().getWidth()); 850e5c31af7Sopenharmony_ci const float viewportH = (float)de::min<int>(TEX2D_VIEWPORT_HEIGHT, m_context.getRenderTarget().getHeight()); 851e5c31af7Sopenharmony_ci 852e5c31af7Sopenharmony_ci const float minLayer = -0.5f; 853e5c31af7Sopenharmony_ci const float maxLayer = (float)m_numLayers; 854e5c31af7Sopenharmony_ci 855e5c31af7Sopenharmony_ci for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); caseNdx++) 856e5c31af7Sopenharmony_ci { 857e5c31af7Sopenharmony_ci const glu::Texture2DArray* tex = cases[caseNdx].texNdx > 0 ? m_gridTex : m_gradientTex; 858e5c31af7Sopenharmony_ci const float ref = cases[caseNdx].ref; 859e5c31af7Sopenharmony_ci const float lodX = cases[caseNdx].lodX; 860e5c31af7Sopenharmony_ci const float lodY = cases[caseNdx].lodY; 861e5c31af7Sopenharmony_ci const float oX = cases[caseNdx].oX; 862e5c31af7Sopenharmony_ci const float oY = cases[caseNdx].oY; 863e5c31af7Sopenharmony_ci const float sX = deFloatExp2(lodX)*viewportW / float(tex->getRefTexture().getWidth()); 864e5c31af7Sopenharmony_ci const float sY = deFloatExp2(lodY)*viewportH / float(tex->getRefTexture().getHeight()); 865e5c31af7Sopenharmony_ci 866e5c31af7Sopenharmony_ci m_cases.push_back(FilterCase(tex, ref, tcu::Vec3(oX, oY, minLayer), tcu::Vec3(oX+sX, oY+sY, maxLayer))); 867e5c31af7Sopenharmony_ci } 868e5c31af7Sopenharmony_ci } 869e5c31af7Sopenharmony_ci 870e5c31af7Sopenharmony_ci m_caseNdx = 0; 871e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 872e5c31af7Sopenharmony_ci} 873e5c31af7Sopenharmony_ci 874e5c31af7Sopenharmony_civoid Texture2DArrayShadowCase::deinit (void) 875e5c31af7Sopenharmony_ci{ 876e5c31af7Sopenharmony_ci delete m_gradientTex; 877e5c31af7Sopenharmony_ci delete m_gridTex; 878e5c31af7Sopenharmony_ci 879e5c31af7Sopenharmony_ci m_gradientTex = DE_NULL; 880e5c31af7Sopenharmony_ci m_gridTex = DE_NULL; 881e5c31af7Sopenharmony_ci 882e5c31af7Sopenharmony_ci m_renderer.clear(); 883e5c31af7Sopenharmony_ci m_cases.clear(); 884e5c31af7Sopenharmony_ci} 885e5c31af7Sopenharmony_ci 886e5c31af7Sopenharmony_ciTexture2DArrayShadowCase::IterateResult Texture2DArrayShadowCase::iterate (void) 887e5c31af7Sopenharmony_ci{ 888e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 889e5c31af7Sopenharmony_ci const RandomViewport viewport (m_context.getRenderTarget(), TEX2D_VIEWPORT_WIDTH, TEX2D_VIEWPORT_HEIGHT, deStringHash(getName()) ^ deInt32Hash(m_caseNdx)); 890e5c31af7Sopenharmony_ci const FilterCase& curCase = m_cases[m_caseNdx]; 891e5c31af7Sopenharmony_ci const tcu::ScopedLogSection section (m_testCtx.getLog(), string("Test") + de::toString(m_caseNdx), string("Test ") + de::toString(m_caseNdx)); 892e5c31af7Sopenharmony_ci ReferenceParams sampleParams (TEXTURETYPE_2D_ARRAY); 893e5c31af7Sopenharmony_ci tcu::Surface rendered (viewport.width, viewport.height); 894e5c31af7Sopenharmony_ci 895e5c31af7Sopenharmony_ci const float texCoord[] = 896e5c31af7Sopenharmony_ci { 897e5c31af7Sopenharmony_ci curCase.minCoord.x(), curCase.minCoord.y(), curCase.minCoord.z(), 898e5c31af7Sopenharmony_ci curCase.minCoord.x(), curCase.maxCoord.y(), (curCase.minCoord.z() + curCase.maxCoord.z()) / 2.0f, 899e5c31af7Sopenharmony_ci curCase.maxCoord.x(), curCase.minCoord.y(), (curCase.minCoord.z() + curCase.maxCoord.z()) / 2.0f, 900e5c31af7Sopenharmony_ci curCase.maxCoord.x(), curCase.maxCoord.y(), curCase.maxCoord.z() 901e5c31af7Sopenharmony_ci }; 902e5c31af7Sopenharmony_ci 903e5c31af7Sopenharmony_ci if (viewport.width < TEX2D_MIN_VIEWPORT_WIDTH || viewport.height < TEX2D_MIN_VIEWPORT_HEIGHT) 904e5c31af7Sopenharmony_ci throw tcu::NotSupportedError("Too small render target", "", __FILE__, __LINE__); 905e5c31af7Sopenharmony_ci 906e5c31af7Sopenharmony_ci // Setup params for reference. 907e5c31af7Sopenharmony_ci sampleParams.sampler = glu::mapGLSampler(m_wrapS, m_wrapT, m_minFilter, m_magFilter); 908e5c31af7Sopenharmony_ci sampleParams.sampler.compare = glu::mapGLCompareFunc(m_compareFunc); 909e5c31af7Sopenharmony_ci sampleParams.samplerType = SAMPLERTYPE_SHADOW; 910e5c31af7Sopenharmony_ci sampleParams.lodMode = LODMODE_EXACT; 911e5c31af7Sopenharmony_ci sampleParams.ref = curCase.ref; 912e5c31af7Sopenharmony_ci 913e5c31af7Sopenharmony_ci m_testCtx.getLog() 914e5c31af7Sopenharmony_ci << TestLog::Message 915e5c31af7Sopenharmony_ci << "Compare reference value = " << sampleParams.ref << "\n" 916e5c31af7Sopenharmony_ci << "Texture coordinates: " << curCase.minCoord << " -> " << curCase.maxCoord 917e5c31af7Sopenharmony_ci << TestLog::EndMessage; 918e5c31af7Sopenharmony_ci 919e5c31af7Sopenharmony_ci gl.bindTexture (GL_TEXTURE_2D_ARRAY, curCase.texture->getGLTexture()); 920e5c31af7Sopenharmony_ci gl.texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, m_minFilter); 921e5c31af7Sopenharmony_ci gl.texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, m_magFilter); 922e5c31af7Sopenharmony_ci gl.texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, m_wrapS); 923e5c31af7Sopenharmony_ci gl.texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, m_wrapT); 924e5c31af7Sopenharmony_ci gl.texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); 925e5c31af7Sopenharmony_ci gl.texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_COMPARE_FUNC, m_compareFunc); 926e5c31af7Sopenharmony_ci 927e5c31af7Sopenharmony_ci gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height); 928e5c31af7Sopenharmony_ci m_renderer.renderQuad(0, &texCoord[0], sampleParams); 929e5c31af7Sopenharmony_ci glu::readPixels(m_context.getRenderContext(), viewport.x, viewport.y, rendered.getAccess()); 930e5c31af7Sopenharmony_ci 931e5c31af7Sopenharmony_ci { 932e5c31af7Sopenharmony_ci const tcu::PixelFormat pixelFormat = m_context.getRenderTarget().getPixelFormat(); 933e5c31af7Sopenharmony_ci tcu::LodPrecision lodPrecision; 934e5c31af7Sopenharmony_ci tcu::TexComparePrecision texComparePrecision; 935e5c31af7Sopenharmony_ci 936e5c31af7Sopenharmony_ci lodPrecision.derivateBits = 18; 937e5c31af7Sopenharmony_ci lodPrecision.lodBits = 6; 938e5c31af7Sopenharmony_ci texComparePrecision.coordBits = tcu::IVec3(20,20,20); 939e5c31af7Sopenharmony_ci texComparePrecision.uvwBits = tcu::IVec3(7,7,7); 940e5c31af7Sopenharmony_ci texComparePrecision.pcfBits = 5; 941e5c31af7Sopenharmony_ci texComparePrecision.referenceBits = 16; 942e5c31af7Sopenharmony_ci texComparePrecision.resultBits = pixelFormat.redBits-1; 943e5c31af7Sopenharmony_ci 944e5c31af7Sopenharmony_ci const bool isHighQuality = verifyTexCompareResult(m_testCtx, rendered.getAccess(), curCase.texture->getRefTexture(), 945e5c31af7Sopenharmony_ci &texCoord[0], sampleParams, texComparePrecision, lodPrecision, pixelFormat); 946e5c31af7Sopenharmony_ci 947e5c31af7Sopenharmony_ci if (!isHighQuality) 948e5c31af7Sopenharmony_ci { 949e5c31af7Sopenharmony_ci m_testCtx.getLog() << TestLog::Message << "Warning: Verification assuming high-quality PCF filtering failed." << TestLog::EndMessage; 950e5c31af7Sopenharmony_ci 951e5c31af7Sopenharmony_ci lodPrecision.lodBits = 4; 952e5c31af7Sopenharmony_ci texComparePrecision.uvwBits = tcu::IVec3(4,4,4); 953e5c31af7Sopenharmony_ci texComparePrecision.pcfBits = 0; 954e5c31af7Sopenharmony_ci 955e5c31af7Sopenharmony_ci const bool isOk = verifyTexCompareResult(m_testCtx, rendered.getAccess(), curCase.texture->getRefTexture(), 956e5c31af7Sopenharmony_ci &texCoord[0], sampleParams, texComparePrecision, lodPrecision, pixelFormat); 957e5c31af7Sopenharmony_ci 958e5c31af7Sopenharmony_ci if (!isOk) 959e5c31af7Sopenharmony_ci { 960e5c31af7Sopenharmony_ci m_testCtx.getLog() << TestLog::Message << "ERROR: Verification against low precision requirements failed, failing test case." << TestLog::EndMessage; 961e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed"); 962e5c31af7Sopenharmony_ci } 963e5c31af7Sopenharmony_ci else if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS) 964e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_QUALITY_WARNING, "Low-quality result"); 965e5c31af7Sopenharmony_ci } 966e5c31af7Sopenharmony_ci } 967e5c31af7Sopenharmony_ci 968e5c31af7Sopenharmony_ci m_caseNdx += 1; 969e5c31af7Sopenharmony_ci return m_caseNdx < (int)m_cases.size() ? CONTINUE : STOP; 970e5c31af7Sopenharmony_ci} 971e5c31af7Sopenharmony_ci 972e5c31af7Sopenharmony_ciTextureShadowTests::TextureShadowTests (Context& context) 973e5c31af7Sopenharmony_ci : TestCaseGroup(context, "shadow", "Shadow texture lookup tests") 974e5c31af7Sopenharmony_ci{ 975e5c31af7Sopenharmony_ci} 976e5c31af7Sopenharmony_ci 977e5c31af7Sopenharmony_ciTextureShadowTests::~TextureShadowTests (void) 978e5c31af7Sopenharmony_ci{ 979e5c31af7Sopenharmony_ci} 980e5c31af7Sopenharmony_ci 981e5c31af7Sopenharmony_civoid TextureShadowTests::init (void) 982e5c31af7Sopenharmony_ci{ 983e5c31af7Sopenharmony_ci static const struct 984e5c31af7Sopenharmony_ci { 985e5c31af7Sopenharmony_ci const char* name; 986e5c31af7Sopenharmony_ci deUint32 format; 987e5c31af7Sopenharmony_ci } formats[] = 988e5c31af7Sopenharmony_ci { 989e5c31af7Sopenharmony_ci { "depth_component16", GL_DEPTH_COMPONENT16 }, 990e5c31af7Sopenharmony_ci { "depth_component32f", GL_DEPTH_COMPONENT32F }, 991e5c31af7Sopenharmony_ci { "depth24_stencil8", GL_DEPTH24_STENCIL8 } 992e5c31af7Sopenharmony_ci }; 993e5c31af7Sopenharmony_ci 994e5c31af7Sopenharmony_ci static const struct 995e5c31af7Sopenharmony_ci { 996e5c31af7Sopenharmony_ci const char* name; 997e5c31af7Sopenharmony_ci deUint32 minFilter; 998e5c31af7Sopenharmony_ci deUint32 magFilter; 999e5c31af7Sopenharmony_ci } filters[] = 1000e5c31af7Sopenharmony_ci { 1001e5c31af7Sopenharmony_ci { "nearest", GL_NEAREST, GL_NEAREST }, 1002e5c31af7Sopenharmony_ci { "linear", GL_LINEAR, GL_LINEAR }, 1003e5c31af7Sopenharmony_ci { "nearest_mipmap_nearest", GL_NEAREST_MIPMAP_NEAREST, GL_LINEAR }, 1004e5c31af7Sopenharmony_ci { "linear_mipmap_nearest", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR }, 1005e5c31af7Sopenharmony_ci { "nearest_mipmap_linear", GL_NEAREST_MIPMAP_LINEAR, GL_LINEAR }, 1006e5c31af7Sopenharmony_ci { "linear_mipmap_linear", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR } 1007e5c31af7Sopenharmony_ci }; 1008e5c31af7Sopenharmony_ci 1009e5c31af7Sopenharmony_ci static const struct 1010e5c31af7Sopenharmony_ci { 1011e5c31af7Sopenharmony_ci const char* name; 1012e5c31af7Sopenharmony_ci deUint32 func; 1013e5c31af7Sopenharmony_ci } compareFuncs[] = 1014e5c31af7Sopenharmony_ci { 1015e5c31af7Sopenharmony_ci { "less_or_equal", GL_LEQUAL }, 1016e5c31af7Sopenharmony_ci { "greater_or_equal", GL_GEQUAL }, 1017e5c31af7Sopenharmony_ci { "less", GL_LESS }, 1018e5c31af7Sopenharmony_ci { "greater", GL_GREATER }, 1019e5c31af7Sopenharmony_ci { "equal", GL_EQUAL }, 1020e5c31af7Sopenharmony_ci { "not_equal", GL_NOTEQUAL }, 1021e5c31af7Sopenharmony_ci { "always", GL_ALWAYS }, 1022e5c31af7Sopenharmony_ci { "never", GL_NEVER } 1023e5c31af7Sopenharmony_ci }; 1024e5c31af7Sopenharmony_ci 1025e5c31af7Sopenharmony_ci // 2D cases. 1026e5c31af7Sopenharmony_ci { 1027e5c31af7Sopenharmony_ci tcu::TestCaseGroup* group2D = new tcu::TestCaseGroup(m_testCtx, "2d", "2D texture shadow lookup tests"); 1028e5c31af7Sopenharmony_ci addChild(group2D); 1029e5c31af7Sopenharmony_ci 1030e5c31af7Sopenharmony_ci for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(filters); filterNdx++) 1031e5c31af7Sopenharmony_ci { 1032e5c31af7Sopenharmony_ci tcu::TestCaseGroup* filterGroup = new tcu::TestCaseGroup(m_testCtx, filters[filterNdx].name, ""); 1033e5c31af7Sopenharmony_ci group2D->addChild(filterGroup); 1034e5c31af7Sopenharmony_ci 1035e5c31af7Sopenharmony_ci for (int compareNdx = 0; compareNdx < DE_LENGTH_OF_ARRAY(compareFuncs); compareNdx++) 1036e5c31af7Sopenharmony_ci { 1037e5c31af7Sopenharmony_ci for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++) 1038e5c31af7Sopenharmony_ci { 1039e5c31af7Sopenharmony_ci deUint32 minFilter = filters[filterNdx].minFilter; 1040e5c31af7Sopenharmony_ci deUint32 magFilter = filters[filterNdx].magFilter; 1041e5c31af7Sopenharmony_ci deUint32 format = formats[formatNdx].format; 1042e5c31af7Sopenharmony_ci deUint32 compareFunc = compareFuncs[compareNdx].func; 1043e5c31af7Sopenharmony_ci const deUint32 wrapS = GL_REPEAT; 1044e5c31af7Sopenharmony_ci const deUint32 wrapT = GL_REPEAT; 1045e5c31af7Sopenharmony_ci const int width = 32; 1046e5c31af7Sopenharmony_ci const int height = 64; 1047e5c31af7Sopenharmony_ci string name = string(compareFuncs[compareNdx].name) + "_" + formats[formatNdx].name; 1048e5c31af7Sopenharmony_ci 1049e5c31af7Sopenharmony_ci filterGroup->addChild(new Texture2DShadowCase(m_context, name.c_str(), "", minFilter, magFilter, wrapS, wrapT, format, width, height, compareFunc)); 1050e5c31af7Sopenharmony_ci } 1051e5c31af7Sopenharmony_ci } 1052e5c31af7Sopenharmony_ci } 1053e5c31af7Sopenharmony_ci } 1054e5c31af7Sopenharmony_ci 1055e5c31af7Sopenharmony_ci // Cubemap cases. 1056e5c31af7Sopenharmony_ci { 1057e5c31af7Sopenharmony_ci tcu::TestCaseGroup* groupCube = new tcu::TestCaseGroup(m_testCtx, "cube", "Cube map texture shadow lookup tests"); 1058e5c31af7Sopenharmony_ci addChild(groupCube); 1059e5c31af7Sopenharmony_ci 1060e5c31af7Sopenharmony_ci for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(filters); filterNdx++) 1061e5c31af7Sopenharmony_ci { 1062e5c31af7Sopenharmony_ci tcu::TestCaseGroup* filterGroup = new tcu::TestCaseGroup(m_testCtx, filters[filterNdx].name, ""); 1063e5c31af7Sopenharmony_ci groupCube->addChild(filterGroup); 1064e5c31af7Sopenharmony_ci 1065e5c31af7Sopenharmony_ci for (int compareNdx = 0; compareNdx < DE_LENGTH_OF_ARRAY(compareFuncs); compareNdx++) 1066e5c31af7Sopenharmony_ci { 1067e5c31af7Sopenharmony_ci for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++) 1068e5c31af7Sopenharmony_ci { 1069e5c31af7Sopenharmony_ci deUint32 minFilter = filters[filterNdx].minFilter; 1070e5c31af7Sopenharmony_ci deUint32 magFilter = filters[filterNdx].magFilter; 1071e5c31af7Sopenharmony_ci deUint32 format = formats[formatNdx].format; 1072e5c31af7Sopenharmony_ci deUint32 compareFunc = compareFuncs[compareNdx].func; 1073e5c31af7Sopenharmony_ci const deUint32 wrapS = GL_REPEAT; 1074e5c31af7Sopenharmony_ci const deUint32 wrapT = GL_REPEAT; 1075e5c31af7Sopenharmony_ci const int size = 32; 1076e5c31af7Sopenharmony_ci string name = string(compareFuncs[compareNdx].name) + "_" + formats[formatNdx].name; 1077e5c31af7Sopenharmony_ci 1078e5c31af7Sopenharmony_ci filterGroup->addChild(new TextureCubeShadowCase(m_context, name.c_str(), "", minFilter, magFilter, wrapS, wrapT, format, size, compareFunc)); 1079e5c31af7Sopenharmony_ci } 1080e5c31af7Sopenharmony_ci } 1081e5c31af7Sopenharmony_ci } 1082e5c31af7Sopenharmony_ci } 1083e5c31af7Sopenharmony_ci 1084e5c31af7Sopenharmony_ci // 2D array cases. 1085e5c31af7Sopenharmony_ci { 1086e5c31af7Sopenharmony_ci tcu::TestCaseGroup* group2DArray = new tcu::TestCaseGroup(m_testCtx, "2d_array", "2D texture array shadow lookup tests"); 1087e5c31af7Sopenharmony_ci addChild(group2DArray); 1088e5c31af7Sopenharmony_ci 1089e5c31af7Sopenharmony_ci for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(filters); filterNdx++) 1090e5c31af7Sopenharmony_ci { 1091e5c31af7Sopenharmony_ci tcu::TestCaseGroup* filterGroup = new tcu::TestCaseGroup(m_testCtx, filters[filterNdx].name, ""); 1092e5c31af7Sopenharmony_ci group2DArray->addChild(filterGroup); 1093e5c31af7Sopenharmony_ci 1094e5c31af7Sopenharmony_ci for (int compareNdx = 0; compareNdx < DE_LENGTH_OF_ARRAY(compareFuncs); compareNdx++) 1095e5c31af7Sopenharmony_ci { 1096e5c31af7Sopenharmony_ci for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++) 1097e5c31af7Sopenharmony_ci { 1098e5c31af7Sopenharmony_ci deUint32 minFilter = filters[filterNdx].minFilter; 1099e5c31af7Sopenharmony_ci deUint32 magFilter = filters[filterNdx].magFilter; 1100e5c31af7Sopenharmony_ci deUint32 format = formats[formatNdx].format; 1101e5c31af7Sopenharmony_ci deUint32 compareFunc = compareFuncs[compareNdx].func; 1102e5c31af7Sopenharmony_ci const deUint32 wrapS = GL_REPEAT; 1103e5c31af7Sopenharmony_ci const deUint32 wrapT = GL_REPEAT; 1104e5c31af7Sopenharmony_ci const int width = 32; 1105e5c31af7Sopenharmony_ci const int height = 64; 1106e5c31af7Sopenharmony_ci const int numLayers = 8; 1107e5c31af7Sopenharmony_ci string name = string(compareFuncs[compareNdx].name) + "_" + formats[formatNdx].name; 1108e5c31af7Sopenharmony_ci 1109e5c31af7Sopenharmony_ci filterGroup->addChild(new Texture2DArrayShadowCase(m_context, name.c_str(), "", minFilter, magFilter, wrapS, wrapT, format, width, height, numLayers, compareFunc)); 1110e5c31af7Sopenharmony_ci } 1111e5c31af7Sopenharmony_ci } 1112e5c31af7Sopenharmony_ci } 1113e5c31af7Sopenharmony_ci } 1114e5c31af7Sopenharmony_ci} 1115e5c31af7Sopenharmony_ci 1116e5c31af7Sopenharmony_ci} // Functional 1117e5c31af7Sopenharmony_ci} // gles3 1118e5c31af7Sopenharmony_ci} // deqp 1119