#include "tcuRGBA.hpp"
#include "tcuTexture.hpp"
#include "tcuTextureUtil.hpp"
-#include "tcuFloat.hpp"
#include <string.h>
}
/*--------------------------------------------------------------------*//*!
- * Returns the index of float in a float space without denormals
- * so that:
- * 1) f(0.0) = 0
- * 2) f(-0.0) = 0
- * 3) f(b) = f(a) + 1 <==> b = nextAfter(a)
- *
- * See computeFloatFlushRelaxedULPDiff for details
- *//*--------------------------------------------------------------------*/
-static deInt32 getPositionOfIEEEFloatWithoutDenormals (float x)
-{
- DE_ASSERT(!deIsNaN(x)); // not sane
-
- if (x == 0.0f)
- return 0;
- else if (x < 0.0f)
- return -getPositionOfIEEEFloatWithoutDenormals(-x);
- else
- {
- DE_ASSERT(x > 0.0f);
-
- const tcu::Float32 f(x);
-
- if (f.isDenorm())
- {
- // Denorms are flushed to zero
- return 0;
- }
- else
- {
- // sign is 0, and it's a normal number. Natural position is its bit
- // pattern but since we've collapsed the denorms, we must remove
- // the gap here too to keep the float enumeration continuous.
- //
- // Denormals occupy one exponent pattern. Removing one from
- // exponent should to the trick.
- return (deInt32)(f.bits() - (1u << 23u));
- }
- }
-}
-
-static deUint32 computeFloatFlushRelaxedULPDiff (float a, float b)
-{
- if (deIsNaN(a) && deIsNaN(b))
- return 0;
- else if (deIsNaN(a) || deIsNaN(b))
- {
- return 0xFFFFFFFFu;
- }
- else
- {
- // Using the "definition 5" in Muller, Jean-Michel. "On the definition of ulp (x)" (2005)
- // assuming a floating point space is IEEE single precision floating point space without
- // denormals (and signed zeros).
- const deInt32 aIndex = getPositionOfIEEEFloatWithoutDenormals(a);
- const deInt32 bIndex = getPositionOfIEEEFloatWithoutDenormals(b);
- return (deUint32)de::abs(aIndex - bIndex);
- }
-}
-
-static tcu::UVec4 computeFlushRelaxedULPDiff (const tcu::Vec4& a, const tcu::Vec4& b)
-{
- return tcu::UVec4(computeFloatFlushRelaxedULPDiff(a.x(), b.x()),
- computeFloatFlushRelaxedULPDiff(a.y(), b.y()),
- computeFloatFlushRelaxedULPDiff(a.z(), b.z()),
- computeFloatFlushRelaxedULPDiff(a.w(), b.w()));
-}
-
-/*--------------------------------------------------------------------*//*!
* \brief Per-pixel threshold-based comparison
*
* This compare computes per-pixel differences between result and reference
*
* This comparison uses ULP (units in last place) metric for computing the
* difference between floating-point values and thus this function can
- * be used only for comparing floating-point texture data. In ULP calculation
- * the denormal numbers are allowed to be flushed to zero.
+ * be used only for comparing floating-point texture data.
*
* On failure error image is generated that shows where the failing pixels
* are.
{
for (int x = 0; x < width; x++)
{
- const Vec4 refPix = reference.getPixel(x, y, z);
- const Vec4 cmpPix = result.getPixel(x, y, z);
- const UVec4 diff = computeFlushRelaxedULPDiff(refPix, cmpPix);
- const bool isOk = boolAll(lessThanEqual(diff, threshold));
+ Vec4 refPix = reference.getPixel(x, y, z);
+ Vec4 cmpPix = result.getPixel(x, y, z);
+ UVec4 refBits;
+ UVec4 cmpBits;
+
+ // memcpy() is the way to do float->uint32 reinterpretation.
+ memcpy(refBits.getPtr(), refPix.getPtr(), 4*sizeof(deUint32));
+ memcpy(cmpBits.getPtr(), cmpPix.getPtr(), 4*sizeof(deUint32));
+
+ UVec4 diff = abs(refBits.cast<int>() - cmpBits.cast<int>()).cast<deUint32>();
+ bool isOk = boolAll(lessThanEqual(diff, threshold));
maxDiff = max(maxDiff, diff);
static void fillWithRandomColorTiles (const PixelBufferAccess& dst, const Vec4& minVal, const Vec4& maxVal, deUint32 seed)
{
- const int numCols = dst.getWidth() >= 7 ? 7 : dst.getWidth();
- const int numRows = dst.getHeight() >= 5 ? 5 : dst.getHeight();
+ const int numCols = 7;
+ const int numRows = 5;
de::Random rnd (seed);
for (int slice = 0; slice < dst.getDepth(); slice++)
GATHERTYPE_LAST
};
-enum GatherCaseFlags
-{
- GATHERCASE_MIPMAP_INCOMPLETE = (1<<0), //!< Excercise special case of sampling mipmap-incomplete texture
- GATHERCASE_DONT_SAMPLE_CUBE_CORNERS = (1<<1) //!< For cube map cases: do not sample cube corners
-};
-
static inline const char* gatherTypeName (GatherType type)
{
switch (type)
tcu::Sampler::FilterMode minFilter,
tcu::Sampler::FilterMode magFilter,
int baseLevel,
- deUint32 flags);
+ bool mipmapIncomplete);
void init (void);
void deinit (void);
const tcu::Sampler::FilterMode m_minFilter;
const tcu::Sampler::FilterMode m_magFilter;
const int m_baseLevel;
- const deUint32 m_flags;
+ const bool m_mipmapIncomplete;
private:
enum
tcu::Sampler::FilterMode minFilter,
tcu::Sampler::FilterMode magFilter,
int baseLevel,
- deUint32 flags)
+ bool mipmapIncomplete)
: TestCase (context, name, description)
, m_gatherType (gatherType)
, m_offsetSize (offsetSize)
, m_minFilter (minFilter)
, m_magFilter (magFilter)
, m_baseLevel (baseLevel)
- , m_flags (flags)
+ , m_mipmapIncomplete (mipmapIncomplete)
, m_textureType (textureType)
, m_colorBufferFormat (tcu::TextureFormat(tcu::TextureFormat::RGBA,
isDepthFormat(textureFormat) ? tcu::TextureFormat::UNORM_INT8 : textureFormat.type))
m_colorBufferFormat.type == tcu::TextureFormat::SIGNED_INT16);
DE_ASSERT(glu::isGLInternalColorFormatFilterable(glu::getInternalFormat(m_colorBufferFormat)) ||
(m_magFilter == tcu::Sampler::NEAREST && (m_minFilter == tcu::Sampler::NEAREST || m_minFilter == tcu::Sampler::NEAREST_MIPMAP_NEAREST)));
- DE_ASSERT(isMipmapFilter(m_minFilter) || !(m_flags & GATHERCASE_MIPMAP_INCOMPLETE));
- DE_ASSERT(m_textureType == TEXTURETYPE_CUBE || !(m_flags & GATHERCASE_DONT_SAMPLE_CUBE_CORNERS));
- DE_ASSERT(!((m_flags & GATHERCASE_MIPMAP_INCOMPLETE) && isDepthFormat(m_textureFormat))); // It's not clear what shadow textures should return when incomplete.
+ DE_ASSERT(isMipmapFilter(m_minFilter) || !m_mipmapIncomplete);
+ DE_ASSERT(!(m_mipmapIncomplete && isDepthFormat(m_textureFormat))); // It's not clear what shadow textures should return when incomplete.
}
IVec2 TextureGatherCase::getOffsetRange (void) const
<< TestLog::Message << "Minification and magnification filter modes are "
<< glu::getTextureFilterName(glu::getGLFilterMode(m_minFilter)) << " and "
<< glu::getTextureFilterName(glu::getGLFilterMode(m_magFilter)) << ", respectively "
- << ((m_flags & GATHERCASE_MIPMAP_INCOMPLETE) ?
+ << (m_mipmapIncomplete ?
"(note that they cause the texture to be incomplete)" :
"(note that they should have no effect on gather result)")
<< TestLog::EndMessage
{
TestLog& log = m_testCtx.getLog();
- if (m_flags & GATHERCASE_MIPMAP_INCOMPLETE)
+ if (m_mipmapIncomplete)
{
const int componentNdx = de::max(0, gatherArgs.componentNdx);
const Vec4 incompleteColor (0.0f, 0.0f, 0.0f, 1.0f);
tcu::Sampler::FilterMode minFilter,
tcu::Sampler::FilterMode magFilter,
int baseLevel,
- deUint32 flags,
+ bool mipmapIncomplete,
const IVec2& textureSize)
- : TextureGatherCase (context, name, description, TEXTURETYPE_2D, gatherType, offsetSize, textureFormat, shadowCompareMode, wrapS, wrapT, texSwizzle, minFilter, magFilter, baseLevel, flags)
+ : TextureGatherCase (context, name, description, TEXTURETYPE_2D, gatherType, offsetSize, textureFormat, shadowCompareMode, wrapS, wrapT, texSwizzle, minFilter, magFilter, baseLevel, mipmapIncomplete)
, m_textureSize (textureSize)
, m_swizzledTexture (tcu::TextureFormat(), 1, 1)
{
{
tcu::Texture2D& refTexture = m_texture->getRefTexture();
const int levelBegin = m_baseLevel;
- const int levelEnd = isMipmapFilter(m_minFilter) && !(m_flags & GATHERCASE_MIPMAP_INCOMPLETE) ? refTexture.getNumLevels() : m_baseLevel+1;
+ const int levelEnd = isMipmapFilter(m_minFilter) && !m_mipmapIncomplete ? refTexture.getNumLevels() : m_baseLevel+1;
DE_ASSERT(m_baseLevel < refTexture.getNumLevels());
for (int levelNdx = levelBegin; levelNdx < levelEnd; levelNdx++)
tcu::Sampler::FilterMode minFilter,
tcu::Sampler::FilterMode magFilter,
int baseLevel,
- deUint32 flags,
+ bool mipmapIncomplete,
const IVec3& textureSize)
- : TextureGatherCase (context, name, description, TEXTURETYPE_2D_ARRAY, gatherType, offsetSize, textureFormat, shadowCompareMode, wrapS, wrapT, texSwizzle, minFilter, magFilter, baseLevel, flags)
+ : TextureGatherCase (context, name, description, TEXTURETYPE_2D_ARRAY, gatherType, offsetSize, textureFormat, shadowCompareMode, wrapS, wrapT, texSwizzle, minFilter, magFilter, baseLevel, mipmapIncomplete)
, m_textureSize (textureSize)
, m_swizzledTexture (tcu::TextureFormat(), 1, 1, 1)
{
{
tcu::Texture2DArray& refTexture = m_texture->getRefTexture();
const int levelBegin = m_baseLevel;
- const int levelEnd = isMipmapFilter(m_minFilter) && !(m_flags & GATHERCASE_MIPMAP_INCOMPLETE) ? refTexture.getNumLevels() : m_baseLevel+1;
+ const int levelEnd = isMipmapFilter(m_minFilter) && !m_mipmapIncomplete ? refTexture.getNumLevels() : m_baseLevel+1;
DE_ASSERT(m_baseLevel < refTexture.getNumLevels());
for (int levelNdx = levelBegin; levelNdx < levelEnd; levelNdx++)
tcu::Sampler::FilterMode minFilter,
tcu::Sampler::FilterMode magFilter,
int baseLevel,
- deUint32 flags,
+ bool mipmapIncomplete,
int textureSize)
- : TextureGatherCase (context, name, description, TEXTURETYPE_CUBE, GATHERTYPE_BASIC, OFFSETSIZE_NONE, textureFormat, shadowCompareMode, wrapS, wrapT, texSwizzle, minFilter, magFilter, baseLevel, flags)
+ : TextureGatherCase (context, name, description, TEXTURETYPE_CUBE, GATHERTYPE_BASIC, OFFSETSIZE_NONE, textureFormat, shadowCompareMode, wrapS, wrapT, texSwizzle, minFilter, magFilter, baseLevel, mipmapIncomplete)
, m_textureSize (textureSize)
, m_swizzledTexture (tcu::TextureFormat(), 1)
{
vector<float> TextureGatherCubeCase::computeQuadTexCoord (int iterationNdx) const
{
- const bool corners = (m_flags & GATHERCASE_DONT_SAMPLE_CUBE_CORNERS) == 0;
- const Vec2 minC = corners ? Vec2(-1.2f) : Vec2(-0.6f, -1.2f);
- const Vec2 maxC = corners ? Vec2( 1.2f) : Vec2( 0.6f, 1.2f);
- vector<float> res;
- gls::TextureTestUtil::computeQuadTexCoordCube(res, m_iterations[iterationNdx].face, minC, maxC);
+ vector<float> res;
+ gls::TextureTestUtil::computeQuadTexCoordCube(res, m_iterations[iterationNdx].face, Vec2(-1.2f), Vec2(1.2f));
return res;
}
{
tcu::TextureCube& refTexture = m_texture->getRefTexture();
const int levelBegin = m_baseLevel;
- const int levelEnd = isMipmapFilter(m_minFilter) && !(m_flags & GATHERCASE_MIPMAP_INCOMPLETE) ? refTexture.getNumLevels() : m_baseLevel+1;
+ const int levelEnd = isMipmapFilter(m_minFilter) && !m_mipmapIncomplete ? refTexture.getNumLevels() : m_baseLevel+1;
DE_ASSERT(m_baseLevel < refTexture.getNumLevels());
for (int levelNdx = levelBegin; levelNdx < levelEnd; levelNdx++)
tcu::Sampler::FilterMode magFilter,
int baseLevel,
const IVec3& textureSize,
- deUint32 flags = 0)
+ bool mipmapIncomplete = false)
{
switch (textureType)
{
case TEXTURETYPE_2D:
return new TextureGather2DCase(context, name, description, gatherType, offsetSize, textureFormat, shadowCompareMode,
- wrapS, wrapT, texSwizzle, minFilter, magFilter, baseLevel, flags, textureSize.swizzle(0, 1));
+ wrapS, wrapT, texSwizzle, minFilter, magFilter, baseLevel, mipmapIncomplete, textureSize.swizzle(0, 1));
case TEXTURETYPE_2D_ARRAY:
return new TextureGather2DArrayCase(context, name, description, gatherType, offsetSize, textureFormat, shadowCompareMode,
- wrapS, wrapT, texSwizzle, minFilter, magFilter, baseLevel, flags, textureSize);
+ wrapS, wrapT, texSwizzle, minFilter, magFilter, baseLevel, mipmapIncomplete, textureSize);
case TEXTURETYPE_CUBE:
DE_ASSERT(gatherType == GATHERTYPE_BASIC);
DE_ASSERT(offsetSize == OFFSETSIZE_NONE);
return new TextureGatherCubeCase(context, name, description, textureFormat, shadowCompareMode,
- wrapS, wrapT, texSwizzle, minFilter, magFilter, baseLevel, flags, textureSize.x());
+ wrapS, wrapT, texSwizzle, minFilter, magFilter, baseLevel, mipmapIncomplete, textureSize.x());
default:
DE_ASSERT(false);
TestCaseGroup* const formatGroup = new TestCaseGroup(m_context, formats[formatNdx].name, "");
textureTypeGroup->addChild(formatGroup);
- for (int noCornersI = 0; noCornersI <= (textureType == TEXTURETYPE_CUBE)?1:0; noCornersI++)
+ for (int textureSizeNdx = 0; textureSizeNdx < DE_LENGTH_OF_ARRAY(textureSizes); textureSizeNdx++)
{
- const bool noCorners = noCornersI!= 0;
- TestCaseGroup* const cornersGroup = noCorners
- ? new TestCaseGroup(m_context, "no_corners", "Test case variants that don't sample around cube map corners")
- : formatGroup;
-
- if (formatGroup != cornersGroup)
- formatGroup->addChild(cornersGroup);
+ const IVec3& textureSize = textureSizes[textureSizeNdx].size;
+ TestCaseGroup* const textureSizeGroup = new TestCaseGroup(m_context, textureSizes[textureSizeNdx].name, "");
+ formatGroup->addChild(textureSizeGroup);
- for (int textureSizeNdx = 0; textureSizeNdx < DE_LENGTH_OF_ARRAY(textureSizes); textureSizeNdx++)
+ for (int compareModeI = 0; compareModeI < tcu::Sampler::COMPAREMODE_LAST; compareModeI++)
{
- const IVec3& textureSize = textureSizes[textureSizeNdx].size;
- TestCaseGroup* const textureSizeGroup = new TestCaseGroup(m_context, textureSizes[textureSizeNdx].name, "");
- cornersGroup->addChild(textureSizeGroup);
-
- for (int compareModeI = 0; compareModeI < tcu::Sampler::COMPAREMODE_LAST; compareModeI++)
- {
- const tcu::Sampler::CompareMode compareMode = (tcu::Sampler::CompareMode)compareModeI;
+ const tcu::Sampler::CompareMode compareMode = (tcu::Sampler::CompareMode)compareModeI;
- if ((compareMode != tcu::Sampler::COMPAREMODE_NONE) != isDepthFormat(format))
- continue;
+ if ((compareMode != tcu::Sampler::COMPAREMODE_NONE) != isDepthFormat(format))
+ continue;
- if (compareMode != tcu::Sampler::COMPAREMODE_NONE &&
- compareMode != tcu::Sampler::COMPAREMODE_LESS &&
- compareMode != tcu::Sampler::COMPAREMODE_GREATER)
- continue;
+ if (compareMode != tcu::Sampler::COMPAREMODE_NONE &&
+ compareMode != tcu::Sampler::COMPAREMODE_LESS &&
+ compareMode != tcu::Sampler::COMPAREMODE_GREATER)
+ continue;
- TestCaseGroup* const compareModeGroup = compareMode == tcu::Sampler::COMPAREMODE_NONE ?
- textureSizeGroup :
- new TestCaseGroup(m_context,
- (string() + "compare_" + compareModeName(compareMode)).c_str(),
- "");
- if (compareModeGroup != textureSizeGroup)
- textureSizeGroup->addChild(compareModeGroup);
+ TestCaseGroup* const compareModeGroup = compareMode == tcu::Sampler::COMPAREMODE_NONE ?
+ textureSizeGroup :
+ new TestCaseGroup(m_context,
+ (string() + "compare_" + compareModeName(compareMode)).c_str(),
+ "");
+ if (compareModeGroup != textureSizeGroup)
+ textureSizeGroup->addChild(compareModeGroup);
- for (int wrapCaseNdx = 0; wrapCaseNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapCaseNdx++)
- {
- const int wrapSNdx = wrapCaseNdx;
- const int wrapTNdx = (wrapCaseNdx + 1) % DE_LENGTH_OF_ARRAY(wrapModes);
- const tcu::Sampler::WrapMode wrapS = wrapModes[wrapSNdx].mode;
- const tcu::Sampler::WrapMode wrapT = wrapModes[wrapTNdx].mode;
+ for (int wrapCaseNdx = 0; wrapCaseNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapCaseNdx++)
+ {
+ const int wrapSNdx = wrapCaseNdx;
+ const int wrapTNdx = (wrapCaseNdx + 1) % DE_LENGTH_OF_ARRAY(wrapModes);
+ const tcu::Sampler::WrapMode wrapS = wrapModes[wrapSNdx].mode;
+ const tcu::Sampler::WrapMode wrapT = wrapModes[wrapTNdx].mode;
- const string caseName = string() + wrapModes[wrapSNdx].name + "_" + wrapModes[wrapTNdx].name;
+ const string caseName = string() + wrapModes[wrapSNdx].name + "_" + wrapModes[wrapTNdx].name;
- compareModeGroup->addChild(makeTextureGatherCase(textureType, m_context, caseName.c_str(), "", gatherType, offsetSize, format, compareMode, wrapS, wrapT,
- MaybeTextureSwizzle::createNoneTextureSwizzle(), tcu::Sampler::NEAREST, tcu::Sampler::NEAREST, 0, textureSize,
- noCorners ? GATHERCASE_DONT_SAMPLE_CUBE_CORNERS : 0));
- }
+ compareModeGroup->addChild(makeTextureGatherCase(textureType, m_context, caseName.c_str(), "", gatherType, offsetSize, format, compareMode, wrapS, wrapT,
+ MaybeTextureSwizzle::createNoneTextureSwizzle(), tcu::Sampler::NEAREST, tcu::Sampler::NEAREST, 0, textureSize));
}
}
}
incompleteGroup->addChild(makeTextureGatherCase(textureType, m_context, "mipmap_incomplete", "", gatherType, offsetSize, format,
compareMode, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL,
MaybeTextureSwizzle::createNoneTextureSwizzle(), tcu::Sampler::NEAREST_MIPMAP_NEAREST, tcu::Sampler::NEAREST,
- 0, IVec3(64, 64, 3), GATHERCASE_MIPMAP_INCOMPLETE));
+ 0, IVec3(64, 64, 3), true /* Mipmap-incomplete */));
}
}
}